tomatrix: add forward headers
This commit is contained in:
@@ -549,27 +549,6 @@ func (t *TelegramClient) Disconnect() {
|
||||
t.userLogin.Log.Info().Msg("Disconnect complete")
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getSingleChannel(ctx context.Context, id int64) (*tg.Channel, error) {
|
||||
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chats, err := APICallWithOnlyChatUpdates(ctx, t, func() (tg.MessagesChatsClass, error) {
|
||||
return t.client.API().ChannelsGetChannels(ctx, []tg.InputChannelClass{
|
||||
&tg.InputChannel{ChannelID: id, AccessHash: accessHash},
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(chats.GetChats()) == 0 {
|
||||
return nil, fmt.Errorf("failed to get channel info for channel %d", id)
|
||||
} else if channel, ok := chats.GetChats()[0].(*tg.Channel); !ok {
|
||||
return nil, fmt.Errorf("unexpected channel type %T", chats.GetChats()[id])
|
||||
} else {
|
||||
return channel, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) IsLoggedIn() bool {
|
||||
// TODO use less hacky check than context cancellation
|
||||
return t != nil && t.client != nil &&
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package connector
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
@@ -209,6 +210,12 @@ func (c *TelegramClient) convertToMatrix(
|
||||
ContentHash: hasher.Sum(nil),
|
||||
ContentURI: contentURI,
|
||||
}
|
||||
if fwd, isForwarded := msg.GetFwdFrom(); isForwarded {
|
||||
err = c.addForwardHeader(ctx, cm.Parts[0], fwd)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to add forward header: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if replyTo, ok := msg.GetReplyTo(); ok {
|
||||
switch replyTo := replyTo.(type) {
|
||||
@@ -236,6 +243,99 @@ func (c *TelegramClient) convertToMatrix(
|
||||
return
|
||||
}
|
||||
|
||||
func (t *TelegramClient) addForwardHeader(ctx context.Context, part *bridgev2.ConvertedMessagePart, fwd tg.MessageFwdHeader) error {
|
||||
var fwdFromText, fwdFromHTML string
|
||||
switch from := fwd.FromID.(type) {
|
||||
case *tg.PeerUser:
|
||||
user := t.main.Bridge.GetCachedUserLoginByID(ids.MakeUserLoginID(from.UserID))
|
||||
var mxid id.UserID
|
||||
if user != nil {
|
||||
mxid = user.UserMXID
|
||||
fwdFromText = cmp.Or(user.RemoteName, user.UserMXID.String())
|
||||
} else if ghost, err := t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(from.UserID)); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if ghost.Name == "" {
|
||||
info, err := t.GetUserInfo(ctx, ghost)
|
||||
if err != nil {
|
||||
zerolog.Ctx(ctx).Warn().Err(err).Msg("Failed to get user info to add forward header")
|
||||
} else if info != nil {
|
||||
ghost.UpdateInfo(ctx, info)
|
||||
}
|
||||
}
|
||||
mxid = ghost.Intent.GetMXID()
|
||||
fwdFromText = cmp.Or(ghost.Name, fwd.FromName, "unknown user")
|
||||
}
|
||||
fwdFromHTML = fmt.Sprintf(
|
||||
`<a href="%s">%s</a>`,
|
||||
mxid.URI().MatrixToURL(),
|
||||
html.EscapeString(fwdFromText),
|
||||
)
|
||||
case *tg.PeerChannel, *tg.PeerChat:
|
||||
unknownType := "unknown chat"
|
||||
if _, ok := from.(*tg.PeerChannel); ok {
|
||||
unknownType = "unknown channel"
|
||||
}
|
||||
portal, err := t.main.Bridge.GetExistingPortalByKey(ctx, t.makePortalKeyFromPeer(from, 0))
|
||||
if err != nil {
|
||||
return err
|
||||
} else if portal != nil && portal.MXID != "" {
|
||||
fwdFromText = cmp.Or(portal.Name, fwd.FromName, unknownType)
|
||||
fwdFromHTML = fmt.Sprintf(
|
||||
`<a href="%s">%s</a>`,
|
||||
portal.MXID.URI().MatrixToURL(),
|
||||
html.EscapeString(fwdFromText),
|
||||
)
|
||||
} else if fwd.FromName != "" {
|
||||
fwdFromText = fwd.FromName
|
||||
fwdFromHTML = fmt.Sprintf("<strong>%s</strong>", html.EscapeString(fwd.FromName))
|
||||
} else {
|
||||
fwdFromText = unknownType
|
||||
fwdFromHTML = unknownType
|
||||
}
|
||||
// TODO fetch channel if not found
|
||||
}
|
||||
if fwdFromText == "" && fwd.FromName != "" {
|
||||
fwdFromText = fwd.FromName
|
||||
fwdFromHTML = fmt.Sprintf("<strong>%s</strong>", html.EscapeString(fwd.FromName))
|
||||
}
|
||||
if fwdFromText == "" {
|
||||
fwdFromText = "unknown source"
|
||||
fwdFromHTML = fwdFromText
|
||||
}
|
||||
|
||||
if part.Content.MsgType.IsMedia() {
|
||||
if part.Content.FileName == "" {
|
||||
part.Content.FileName = part.Content.Body
|
||||
}
|
||||
if part.Content.Body == part.Content.FileName {
|
||||
part.Content.Body = ""
|
||||
}
|
||||
}
|
||||
|
||||
part.Content.EnsureHasHTML()
|
||||
existingBodyLines := strings.Split(part.Content.Body, "\n")
|
||||
for i, line := range existingBodyLines {
|
||||
existingBodyLines[i] = fmt.Sprintf("> %s", line)
|
||||
}
|
||||
if len(existingBodyLines) > 0 {
|
||||
existingBodyLines = append([]string{"\n"}, existingBodyLines...)
|
||||
}
|
||||
part.Content.Body = fmt.Sprintf(
|
||||
"Forwarded message from %s%s",
|
||||
fwdFromText, strings.Join(existingBodyLines, "\n"),
|
||||
)
|
||||
existingFormattedBody := part.Content.FormattedBody
|
||||
if existingFormattedBody != "" {
|
||||
existingFormattedBody = fmt.Sprintf("<br><tg-forward><blockquote>%s</blockquote></tg-forward>", existingFormattedBody)
|
||||
}
|
||||
part.Content.FormattedBody = fmt.Sprintf(
|
||||
"Forwarded message from %s%s",
|
||||
fwdFromHTML, existingFormattedBody,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) parseBodyAndHTML(ctx context.Context, message string, entities []tg.MessageEntityClass) *event.MessageEventContent {
|
||||
if len(entities) == 0 {
|
||||
return &event.MessageEventContent{MsgType: event.MsgText, Body: message}
|
||||
|
||||
+85
-18
@@ -40,33 +40,64 @@ func (t *TelegramClient) GetUserInfo(ctx context.Context, ghost *bridgev2.Ghost)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getChatPeerForInputFromMessage(ctx context.Context, id int64, peerID tg.PeerClass) (tg.InputPeerClass, error) {
|
||||
switch typedChat := peerID.(type) {
|
||||
case *tg.PeerUser:
|
||||
if id == typedChat.UserID {
|
||||
// We don't have the user's access hash
|
||||
return nil, nil
|
||||
}
|
||||
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeUser, typedChat.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tg.InputPeerUser{UserID: typedChat.UserID, AccessHash: accessHash}, nil
|
||||
case *tg.PeerChat:
|
||||
return &tg.InputPeerChat{ChatID: typedChat.ChatID}, nil
|
||||
case *tg.PeerChannel:
|
||||
if id == typedChat.ChannelID {
|
||||
// We don't have the channel's access hash
|
||||
return nil, nil
|
||||
}
|
||||
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, typedChat.ChannelID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tg.InputPeerChannel{ChannelID: typedChat.ChannelID, AccessHash: accessHash}, nil
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getInputUserFromContext(ctx context.Context, id int64) (*tg.InputUserFromMessage, error) {
|
||||
msg, ok := bridgev2.GetRemoteEventFromContext(ctx).(*simplevent.Message[*tg.Message])
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
fromUser, ok := msg.Data.FromID.(*tg.PeerUser)
|
||||
if !ok || fromUser.UserID != id {
|
||||
return nil, nil
|
||||
}
|
||||
var inputPeer tg.InputPeerClass
|
||||
switch typedChat := msg.Data.PeerID.(type) {
|
||||
case *tg.PeerUser:
|
||||
// We don't have the user's access hash
|
||||
return nil, nil
|
||||
case *tg.PeerChat:
|
||||
inputPeer = &tg.InputPeerChat{ChatID: typedChat.ChatID}
|
||||
case *tg.PeerChannel:
|
||||
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, typedChat.ChannelID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inputPeer = &tg.InputPeerChannel{ChannelID: typedChat.ChannelID, AccessHash: accessHash}
|
||||
inputPeer, err := t.getChatPeerForInputFromMessage(ctx, id, msg.Data.PeerID)
|
||||
if err != nil || inputPeer == nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tg.InputUserFromMessage{
|
||||
Peer: inputPeer,
|
||||
MsgID: msg.Data.ID,
|
||||
UserID: fromUser.UserID,
|
||||
UserID: id,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getInputChannelFromContext(ctx context.Context, id int64) (*tg.InputChannelFromMessage, error) {
|
||||
msg, ok := bridgev2.GetRemoteEventFromContext(ctx).(*simplevent.Message[*tg.Message])
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
inputPeer, err := t.getChatPeerForInputFromMessage(ctx, id, msg.Data.PeerID)
|
||||
if err != nil || inputPeer == nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tg.InputChannelFromMessage{
|
||||
Peer: inputPeer,
|
||||
MsgID: msg.Data.ID,
|
||||
ChannelID: id,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -112,6 +143,42 @@ func (t *TelegramClient) getSingleUser(ctx context.Context, id int64) (tg.UserCl
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getInputChannel(ctx context.Context, id int64) (tg.InputChannelClass, error) {
|
||||
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, id)
|
||||
if err != nil {
|
||||
fromMsg, fromMsgErr := t.getInputChannelFromContext(ctx, id)
|
||||
if fromMsgErr != nil {
|
||||
return nil, fmt.Errorf("%w, also failed to get from message: %w", err, fromMsgErr)
|
||||
} else if fromMsg == nil {
|
||||
return nil, err
|
||||
}
|
||||
zerolog.Ctx(ctx).Trace().
|
||||
Any("input_peer", fromMsg).
|
||||
Msg("Using InputChannelFromMessage as access hash wasn't found")
|
||||
return fromMsg, nil
|
||||
}
|
||||
return &tg.InputChannel{ChannelID: id, AccessHash: accessHash}, nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getSingleChannel(ctx context.Context, id int64) (*tg.Channel, error) {
|
||||
inputChannel, err := t.getInputChannel(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chats, err := APICallWithOnlyChatUpdates(ctx, t, func() (tg.MessagesChatsClass, error) {
|
||||
return t.client.API().ChannelsGetChannels(ctx, []tg.InputChannelClass{inputChannel})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(chats.GetChats()) == 0 {
|
||||
return nil, fmt.Errorf("failed to get channel info for channel %d", id)
|
||||
} else if channel, ok := chats.GetChats()[0].(*tg.Channel); !ok {
|
||||
return nil, fmt.Errorf("unexpected channel type %T", chats.GetChats()[id])
|
||||
} else {
|
||||
return channel, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) wrapChannelGhostInfo(ctx context.Context, channel *tg.Channel) (*bridgev2.UserInfo, error) {
|
||||
var err error
|
||||
if accessHash, ok := channel.GetAccessHash(); ok && !channel.Min {
|
||||
|
||||
Reference in New Issue
Block a user