Skip to content

Commit b695e0b

Browse files
committed
tomatrix: add forward headers
1 parent 3269066 commit b695e0b

File tree

3 files changed

+183
-37
lines changed

3 files changed

+183
-37
lines changed

pkg/connector/client.go

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -549,27 +549,6 @@ func (t *TelegramClient) Disconnect() {
549549
t.userLogin.Log.Info().Msg("Disconnect complete")
550550
}
551551

552-
func (t *TelegramClient) getSingleChannel(ctx context.Context, id int64) (*tg.Channel, error) {
553-
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, id)
554-
if err != nil {
555-
return nil, err
556-
}
557-
chats, err := APICallWithOnlyChatUpdates(ctx, t, func() (tg.MessagesChatsClass, error) {
558-
return t.client.API().ChannelsGetChannels(ctx, []tg.InputChannelClass{
559-
&tg.InputChannel{ChannelID: id, AccessHash: accessHash},
560-
})
561-
})
562-
if err != nil {
563-
return nil, err
564-
} else if len(chats.GetChats()) == 0 {
565-
return nil, fmt.Errorf("failed to get channel info for channel %d", id)
566-
} else if channel, ok := chats.GetChats()[0].(*tg.Channel); !ok {
567-
return nil, fmt.Errorf("unexpected channel type %T", chats.GetChats()[id])
568-
} else {
569-
return channel, nil
570-
}
571-
}
572-
573552
func (t *TelegramClient) IsLoggedIn() bool {
574553
// TODO use less hacky check than context cancellation
575554
return t != nil && t.client != nil &&

pkg/connector/tomatrix.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package connector
1818

1919
import (
20+
"cmp"
2021
"context"
2122
"crypto/sha256"
2223
"encoding/binary"
@@ -209,6 +210,12 @@ func (c *TelegramClient) convertToMatrix(
209210
ContentHash: hasher.Sum(nil),
210211
ContentURI: contentURI,
211212
}
213+
if fwd, isForwarded := msg.GetFwdFrom(); isForwarded {
214+
err = c.addForwardHeader(ctx, cm.Parts[0], fwd)
215+
if err != nil {
216+
return nil, fmt.Errorf("failed to add forward header: %w", err)
217+
}
218+
}
212219

213220
if replyTo, ok := msg.GetReplyTo(); ok {
214221
switch replyTo := replyTo.(type) {
@@ -236,6 +243,99 @@ func (c *TelegramClient) convertToMatrix(
236243
return
237244
}
238245

246+
func (t *TelegramClient) addForwardHeader(ctx context.Context, part *bridgev2.ConvertedMessagePart, fwd tg.MessageFwdHeader) error {
247+
var fwdFromText, fwdFromHTML string
248+
switch from := fwd.FromID.(type) {
249+
case *tg.PeerUser:
250+
user := t.main.Bridge.GetCachedUserLoginByID(ids.MakeUserLoginID(from.UserID))
251+
var mxid id.UserID
252+
if user != nil {
253+
mxid = user.UserMXID
254+
fwdFromText = cmp.Or(user.RemoteName, user.UserMXID.String())
255+
} else if ghost, err := t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(from.UserID)); err != nil {
256+
return err
257+
} else {
258+
if ghost.Name == "" {
259+
info, err := t.GetUserInfo(ctx, ghost)
260+
if err != nil {
261+
zerolog.Ctx(ctx).Warn().Err(err).Msg("Failed to get user info to add forward header")
262+
} else if info != nil {
263+
ghost.UpdateInfo(ctx, info)
264+
}
265+
}
266+
mxid = ghost.Intent.GetMXID()
267+
fwdFromText = cmp.Or(ghost.Name, fwd.FromName, "unknown user")
268+
}
269+
fwdFromHTML = fmt.Sprintf(
270+
`<a href="%s">%s</a>`,
271+
mxid.URI().MatrixToURL(),
272+
html.EscapeString(fwdFromText),
273+
)
274+
case *tg.PeerChannel, *tg.PeerChat:
275+
unknownType := "unknown chat"
276+
if _, ok := from.(*tg.PeerChannel); ok {
277+
unknownType = "unknown channel"
278+
}
279+
portal, err := t.main.Bridge.GetExistingPortalByKey(ctx, t.makePortalKeyFromPeer(from, 0))
280+
if err != nil {
281+
return err
282+
} else if portal != nil && portal.MXID != "" {
283+
fwdFromText = cmp.Or(portal.Name, fwd.FromName, unknownType)
284+
fwdFromHTML = fmt.Sprintf(
285+
`<a href="%s">%s</a>`,
286+
portal.MXID.URI().MatrixToURL(),
287+
html.EscapeString(fwdFromText),
288+
)
289+
} else if fwd.FromName != "" {
290+
fwdFromText = fwd.FromName
291+
fwdFromHTML = fmt.Sprintf("<strong>%s</strong>", html.EscapeString(fwd.FromName))
292+
} else {
293+
fwdFromText = unknownType
294+
fwdFromHTML = unknownType
295+
}
296+
// TODO fetch channel if not found
297+
}
298+
if fwdFromText == "" && fwd.FromName != "" {
299+
fwdFromText = fwd.FromName
300+
fwdFromHTML = fmt.Sprintf("<strong>%s</strong>", html.EscapeString(fwd.FromName))
301+
}
302+
if fwdFromText == "" {
303+
fwdFromText = "unknown source"
304+
fwdFromHTML = fwdFromText
305+
}
306+
307+
if part.Content.MsgType.IsMedia() {
308+
if part.Content.FileName == "" {
309+
part.Content.FileName = part.Content.Body
310+
}
311+
if part.Content.Body == part.Content.FileName {
312+
part.Content.Body = ""
313+
}
314+
}
315+
316+
part.Content.EnsureHasHTML()
317+
existingBodyLines := strings.Split(part.Content.Body, "\n")
318+
for i, line := range existingBodyLines {
319+
existingBodyLines[i] = fmt.Sprintf("> %s", line)
320+
}
321+
if len(existingBodyLines) > 0 {
322+
existingBodyLines = append([]string{"\n"}, existingBodyLines...)
323+
}
324+
part.Content.Body = fmt.Sprintf(
325+
"Forwarded message from %s%s",
326+
fwdFromText, strings.Join(existingBodyLines, "\n"),
327+
)
328+
existingFormattedBody := part.Content.FormattedBody
329+
if existingFormattedBody != "" {
330+
existingFormattedBody = fmt.Sprintf("<br><tg-forward><blockquote>%s</blockquote></tg-forward>", existingFormattedBody)
331+
}
332+
part.Content.FormattedBody = fmt.Sprintf(
333+
"Forwarded message from %s%s",
334+
fwdFromHTML, existingFormattedBody,
335+
)
336+
return nil
337+
}
338+
239339
func (t *TelegramClient) parseBodyAndHTML(ctx context.Context, message string, entities []tg.MessageEntityClass) *event.MessageEventContent {
240340
if len(entities) == 0 {
241341
return &event.MessageEventContent{MsgType: event.MsgText, Body: message}

pkg/connector/userinfo.go

Lines changed: 83 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,33 +40,64 @@ func (t *TelegramClient) GetUserInfo(ctx context.Context, ghost *bridgev2.Ghost)
4040
}
4141
}
4242

43-
func (t *TelegramClient) getInputUserFromContext(ctx context.Context, id int64) (*tg.InputUserFromMessage, error) {
44-
msg, ok := bridgev2.GetRemoteEventFromContext(ctx).(*simplevent.Message[*tg.Message])
45-
if !ok {
46-
return nil, nil
47-
}
48-
fromUser, ok := msg.Data.FromID.(*tg.PeerUser)
49-
if !ok || fromUser.UserID != id {
50-
return nil, nil
51-
}
52-
var inputPeer tg.InputPeerClass
53-
switch typedChat := msg.Data.PeerID.(type) {
43+
func (t *TelegramClient) getChatPeerForInputFromMessage(ctx context.Context, id int64, peerID tg.PeerClass) (tg.InputPeerClass, error) {
44+
switch typedChat := peerID.(type) {
5445
case *tg.PeerUser:
55-
// We don't have the user's access hash
56-
return nil, nil
46+
if id == typedChat.UserID {
47+
// We don't have the user's access hash
48+
return nil, nil
49+
}
50+
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeUser, typedChat.UserID)
51+
if err != nil {
52+
return nil, err
53+
}
54+
return &tg.InputPeerUser{UserID: typedChat.UserID, AccessHash: accessHash}, nil
5755
case *tg.PeerChat:
58-
inputPeer = &tg.InputPeerChat{ChatID: typedChat.ChatID}
56+
return &tg.InputPeerChat{ChatID: typedChat.ChatID}, nil
5957
case *tg.PeerChannel:
58+
if id == typedChat.ChannelID {
59+
// We don't have the channel's access hash
60+
return nil, nil
61+
}
6062
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, typedChat.ChannelID)
6163
if err != nil {
6264
return nil, err
6365
}
64-
inputPeer = &tg.InputPeerChannel{ChannelID: typedChat.ChannelID, AccessHash: accessHash}
66+
return &tg.InputPeerChannel{ChannelID: typedChat.ChannelID, AccessHash: accessHash}, nil
67+
default:
68+
return nil, nil
69+
}
70+
}
71+
72+
func (t *TelegramClient) getInputUserFromContext(ctx context.Context, id int64) (*tg.InputUserFromMessage, error) {
73+
msg, ok := bridgev2.GetRemoteEventFromContext(ctx).(*simplevent.Message[*tg.Message])
74+
if !ok {
75+
return nil, nil
76+
}
77+
inputPeer, err := t.getChatPeerForInputFromMessage(ctx, id, msg.Data.PeerID)
78+
if err != nil || inputPeer == nil {
79+
return nil, err
6580
}
6681
return &tg.InputUserFromMessage{
6782
Peer: inputPeer,
6883
MsgID: msg.Data.ID,
69-
UserID: fromUser.UserID,
84+
UserID: id,
85+
}, nil
86+
}
87+
88+
func (t *TelegramClient) getInputChannelFromContext(ctx context.Context, id int64) (*tg.InputChannelFromMessage, error) {
89+
msg, ok := bridgev2.GetRemoteEventFromContext(ctx).(*simplevent.Message[*tg.Message])
90+
if !ok {
91+
return nil, nil
92+
}
93+
inputPeer, err := t.getChatPeerForInputFromMessage(ctx, id, msg.Data.PeerID)
94+
if err != nil || inputPeer == nil {
95+
return nil, err
96+
}
97+
return &tg.InputChannelFromMessage{
98+
Peer: inputPeer,
99+
MsgID: msg.Data.ID,
100+
ChannelID: id,
70101
}, nil
71102
}
72103

@@ -112,6 +143,42 @@ func (t *TelegramClient) getSingleUser(ctx context.Context, id int64) (tg.UserCl
112143
}
113144
}
114145

146+
func (t *TelegramClient) getInputChannel(ctx context.Context, id int64) (tg.InputChannelClass, error) {
147+
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, id)
148+
if err != nil {
149+
fromMsg, fromMsgErr := t.getInputChannelFromContext(ctx, id)
150+
if fromMsgErr != nil {
151+
return nil, fmt.Errorf("%w, also failed to get from message: %w", err, fromMsgErr)
152+
} else if fromMsg == nil {
153+
return nil, err
154+
}
155+
zerolog.Ctx(ctx).Trace().
156+
Any("input_peer", fromMsg).
157+
Msg("Using InputChannelFromMessage as access hash wasn't found")
158+
return fromMsg, nil
159+
}
160+
return &tg.InputChannel{ChannelID: id, AccessHash: accessHash}, nil
161+
}
162+
163+
func (t *TelegramClient) getSingleChannel(ctx context.Context, id int64) (*tg.Channel, error) {
164+
inputChannel, err := t.getInputChannel(ctx, id)
165+
if err != nil {
166+
return nil, err
167+
}
168+
chats, err := APICallWithOnlyChatUpdates(ctx, t, func() (tg.MessagesChatsClass, error) {
169+
return t.client.API().ChannelsGetChannels(ctx, []tg.InputChannelClass{inputChannel})
170+
})
171+
if err != nil {
172+
return nil, err
173+
} else if len(chats.GetChats()) == 0 {
174+
return nil, fmt.Errorf("failed to get channel info for channel %d", id)
175+
} else if channel, ok := chats.GetChats()[0].(*tg.Channel); !ok {
176+
return nil, fmt.Errorf("unexpected channel type %T", chats.GetChats()[id])
177+
} else {
178+
return channel, nil
179+
}
180+
}
181+
115182
func (t *TelegramClient) wrapChannelGhostInfo(ctx context.Context, channel *tg.Channel) (*bridgev2.UserInfo, error) {
116183
var err error
117184
if accessHash, ok := channel.GetAccessHash(); ok && !channel.Min {

0 commit comments

Comments
 (0)