|
17 | 17 | package connector |
18 | 18 |
|
19 | 19 | import ( |
| 20 | + "cmp" |
20 | 21 | "context" |
21 | 22 | "crypto/sha256" |
22 | 23 | "encoding/binary" |
@@ -209,6 +210,12 @@ func (c *TelegramClient) convertToMatrix( |
209 | 210 | ContentHash: hasher.Sum(nil), |
210 | 211 | ContentURI: contentURI, |
211 | 212 | } |
| 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 | + } |
212 | 219 |
|
213 | 220 | if replyTo, ok := msg.GetReplyTo(); ok { |
214 | 221 | switch replyTo := replyTo.(type) { |
@@ -236,6 +243,99 @@ func (c *TelegramClient) convertToMatrix( |
236 | 243 | return |
237 | 244 | } |
238 | 245 |
|
| 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 | + |
239 | 339 | func (t *TelegramClient) parseBodyAndHTML(ctx context.Context, message string, entities []tg.MessageEntityClass) *event.MessageEventContent { |
240 | 340 | if len(entities) == 0 { |
241 | 341 | return &event.MessageEventContent{MsgType: event.MsgText, Body: message} |
|
0 commit comments