diff --git a/pkg/connector/backfill.go b/pkg/connector/backfill.go index a0b8fc06..11bed9f6 100644 --- a/pkg/connector/backfill.go +++ b/pkg/connector/backfill.go @@ -40,74 +40,74 @@ var ( ) // getTakeoutID blocks until the takeout ID is available. -func (t *TelegramClient) getTakeoutID(ctx context.Context) (takeoutID int64, err error) { +func (tc *TelegramClient) getTakeoutID(ctx context.Context) (takeoutID int64, err error) { // Always stop the takeout timeout timer - if t.stopTakeoutTimer != nil { - t.stopTakeoutTimer.Stop() + if tc.stopTakeoutTimer != nil { + tc.stopTakeoutTimer.Stop() } log := zerolog.Ctx(ctx).With().Str("function", "getTakeoutID").Logger() - if t.metadata.TakeoutID != 0 { + if tc.metadata.TakeoutID != 0 { // Resume fetching dialogs using takeout and enqueueing them for // backfill. - go t.takeoutDialogsOnce.Do(func() { - if err = t.syncChats(ctx, takeoutID, false, false); err != nil { + go tc.takeoutDialogsOnce.Do(func() { + if err = tc.syncChats(ctx, takeoutID, false, false); err != nil { log.Err(err).Msg("Failed to takeout dialogs") } }) - return t.metadata.TakeoutID, nil + return tc.metadata.TakeoutID, nil } - t.stopTakeoutTimer = time.AfterFunc(max(time.Hour, time.Duration(t.main.Bridge.Config.Backfill.Queue.BatchDelay*2)), sync.OnceFunc(func() { t.stopTakeout(ctx) })) + tc.stopTakeoutTimer = time.AfterFunc(max(time.Hour, time.Duration(tc.main.Bridge.Config.Backfill.Queue.BatchDelay*2)), sync.OnceFunc(func() { tc.stopTakeout(ctx) })) for { - t.takeoutAccepted.Clear() + tc.takeoutAccepted.Clear() - accountTakeout, err := t.client.API().AccountInitTakeoutSession(ctx, &tg.AccountInitTakeoutSessionRequest{ + accountTakeout, err := tc.client.API().AccountInitTakeoutSession(ctx, &tg.AccountInitTakeoutSessionRequest{ MessageUsers: true, MessageChats: true, MessageMegagroups: true, MessageChannels: true, Files: true, - FileMaxSize: min(t.main.maxFileSize, 2000*1024*1024), + FileMaxSize: min(tc.main.maxFileSize, 2000*1024*1024), }) if rpcErr, ok := tgerr.As(err); ok && rpcErr.IsOneOf(tg.ErrTakeoutInitDelay) { log.Warn(). Err(err). Int("delay", rpcErr.Argument). Msg("Takeout requested, will wait for retry request or delay") - t.takeoutAccepted.WaitTimeout(time.Duration(rpcErr.Argument) * time.Second) + tc.takeoutAccepted.WaitTimeout(time.Duration(rpcErr.Argument) * time.Second) continue } else if err != nil { return 0, err } // Fetch all dialogs using takeout and enqueue them for backfill. - go t.takeoutDialogsOnce.Do(func() { - if err = t.syncChats(ctx, takeoutID, false, false); err != nil { + go tc.takeoutDialogsOnce.Do(func() { + if err = tc.syncChats(ctx, takeoutID, false, false); err != nil { log.Err(err).Msg("Failed to takeout dialogs") } }) - t.metadata.TakeoutID = accountTakeout.ID - return accountTakeout.ID, t.userLogin.Save(ctx) + tc.metadata.TakeoutID = accountTakeout.ID + return accountTakeout.ID, tc.userLogin.Save(ctx) } } -func (t *TelegramClient) stopTakeout(ctx context.Context) error { - t.takeoutLock.Lock() - defer t.takeoutLock.Unlock() +func (tc *TelegramClient) stopTakeout(ctx context.Context) error { + tc.takeoutLock.Lock() + defer tc.takeoutLock.Unlock() - _, err := t.client.API().AccountFinishTakeoutSession(ctx, &tg.AccountFinishTakeoutSessionRequest{Success: true}) + _, err := tc.client.API().AccountFinishTakeoutSession(ctx, &tg.AccountFinishTakeoutSessionRequest{Success: true}) if err != nil { return err } - t.metadata.TakeoutID = 0 - return t.userLogin.Save(ctx) + tc.metadata.TakeoutID = 0 + return tc.userLogin.Save(ctx) } -func (t *TelegramClient) FetchMessages(ctx context.Context, fetchParams bridgev2.FetchMessagesParams) (*bridgev2.FetchMessagesResponse, error) { - if t.metadata.IsBot { +func (tc *TelegramClient) FetchMessages(ctx context.Context, fetchParams bridgev2.FetchMessagesParams) (*bridgev2.FetchMessagesResponse, error) { + if tc.metadata.IsBot { return nil, fmt.Errorf("bots cannot backfill messages") } log := zerolog.Ctx(ctx).With().Str("method", "FetchMessages").Logger() @@ -115,26 +115,26 @@ func (t *TelegramClient) FetchMessages(ctx context.Context, fetchParams bridgev2 var takeoutID int64 var err error - if (t.main.Config.Takeout.ForwardBackfill && fetchParams.Forward) || (t.main.Config.Takeout.BackwardBackfill && !fetchParams.Forward) { - t.takeoutLock.Lock() - defer t.takeoutLock.Unlock() - takeoutID, err = t.getTakeoutID(ctx) + if (tc.main.Config.Takeout.ForwardBackfill && fetchParams.Forward) || (tc.main.Config.Takeout.BackwardBackfill && !fetchParams.Forward) { + tc.takeoutLock.Lock() + defer tc.takeoutLock.Unlock() + takeoutID, err = tc.getTakeoutID(ctx) if err != nil { return nil, err } if takeoutID != 0 { defer func() { - if t.stopTakeoutTimer == nil { - t.stopTakeoutTimer = time.AfterFunc(max(time.Hour, time.Duration(t.main.Bridge.Config.Backfill.Queue.BatchDelay*2)), sync.OnceFunc(func() { t.stopTakeout(ctx) })) + if tc.stopTakeoutTimer == nil { + tc.stopTakeoutTimer = time.AfterFunc(max(time.Hour, time.Duration(tc.main.Bridge.Config.Backfill.Queue.BatchDelay*2)), sync.OnceFunc(func() { tc.stopTakeout(ctx) })) } else { - t.stopTakeoutTimer.Reset(max(time.Hour, time.Duration(t.main.Bridge.Config.Backfill.Queue.BatchDelay*2))) + tc.stopTakeoutTimer.Reset(max(time.Hour, time.Duration(tc.main.Bridge.Config.Backfill.Queue.BatchDelay*2))) } }() } } - peer, topicID, err := t.inputPeerForPortalID(ctx, fetchParams.Portal.ID) + peer, topicID, err := tc.inputPeerForPortalID(ctx, fetchParams.Portal.ID) if err != nil { return nil, err } @@ -176,10 +176,10 @@ func (t *TelegramClient) FetchMessages(ctx context.Context, fetchParams bridgev2 req = &tg.InvokeWithTakeoutRequest{TakeoutID: takeoutID, Query: req} } log.Info().Any("req", req).Msg("Fetching messages") - msgs, err := APICallWithUpdates(ctx, t, func() (tg.ModifiedMessagesMessages, error) { + msgs, err := APICallWithUpdates(ctx, tc, func() (tg.ModifiedMessagesMessages, error) { var box tg.MessagesMessagesBox // TODO a single request can only fetch 100 messages, use multiple requests if the requested count is higher - err = t.client.Invoke(ctx, req, &box) + err = tc.client.Invoke(ctx, req, &box) if err != nil { return nil, err } @@ -191,8 +191,8 @@ func (t *TelegramClient) FetchMessages(ctx context.Context, fetchParams bridgev2 }) if err != nil { if tgerr.Is(err, tg.ErrTakeoutInvalid) { - t.metadata.TakeoutID = 0 - err := t.userLogin.Save(ctx) + tc.metadata.TakeoutID = 0 + err := tc.userLogin.Save(ctx) if err != nil { log.Err(err).Msg("Failed to save user login after clearing takeout ID") } else { @@ -248,12 +248,12 @@ func (t *TelegramClient) FetchMessages(ctx context.Context, fetchParams bridgev2 continue } - sender := t.getEventSender(message, !portal.Metadata.(*PortalMetadata).IsSuperGroup) - intent, ok := portal.GetIntentFor(ctx, sender, t.userLogin, bridgev2.RemoteEventBackfill) + sender := tc.getEventSender(message, !portal.Metadata.(*PortalMetadata).IsSuperGroup) + intent, ok := portal.GetIntentFor(ctx, sender, tc.userLogin, bridgev2.RemoteEventBackfill) if !ok { continue } - converted, err := t.convertToMatrix(ctx, portal, intent, message) + converted, err := tc.convertToMatrix(ctx, portal, intent, message) if err != nil { return nil, err } @@ -267,7 +267,7 @@ func (t *TelegramClient) FetchMessages(ctx context.Context, fetchParams bridgev2 } if reactions, ok := message.GetReactions(); ok { - reactionsList, _, customEmojis, err := t.computeReactionsList(ctx, message.PeerID, message.ID, reactions) + reactionsList, _, customEmojis, err := tc.computeReactionsList(ctx, message.PeerID, message.ID, reactions) if err != nil { return nil, err } @@ -285,7 +285,7 @@ func (t *TelegramClient) FetchMessages(ctx context.Context, fetchParams bridgev2 backfillMessage.Reactions = append(backfillMessage.Reactions, &bridgev2.BackfillReaction{ Timestamp: time.Unix(int64(reaction.Date), 0), - Sender: t.senderForUserID(peer.UserID), + Sender: tc.senderForUserID(peer.UserID), EmojiID: emojiID, Emoji: emoji, }) @@ -307,7 +307,7 @@ func (t *TelegramClient) FetchMessages(ctx context.Context, fetchParams bridgev2 }, nil } -func (c *TelegramClient) GetBackfillMaxBatchCount(ctx context.Context, portal *bridgev2.Portal, task *database.BackfillTask) int { +func (tc *TelegramClient) GetBackfillMaxBatchCount(ctx context.Context, portal *bridgev2.Portal, task *database.BackfillTask) int { log := zerolog.Ctx(ctx).With(). Str("method", "GetBackfillMaxBatchCount"). Logger() @@ -318,18 +318,18 @@ func (c *TelegramClient) GetBackfillMaxBatchCount(ctx context.Context, portal *b } switch peerType { case ids.PeerTypeUser: - return c.main.Bridge.Config.Backfill.Queue.GetOverride("user") + return tc.main.Bridge.Config.Backfill.Queue.GetOverride("user") case ids.PeerTypeChat: - return c.main.Bridge.Config.Backfill.Queue.GetOverride("normal_group") + return tc.main.Bridge.Config.Backfill.Queue.GetOverride("normal_group") case ids.PeerTypeChannel: if topicID == ids.TopicIDSpaceRoom { return 0 } else if topicID > 0 { - return c.main.Bridge.Config.Backfill.Queue.GetOverride("topic", "supergroup") + return tc.main.Bridge.Config.Backfill.Queue.GetOverride("topic", "supergroup") } else if portal.Metadata.(*PortalMetadata).IsSuperGroup { - return c.main.Bridge.Config.Backfill.Queue.GetOverride("supergroup") + return tc.main.Bridge.Config.Backfill.Queue.GetOverride("supergroup") } else { - return c.main.Bridge.Config.Backfill.Queue.GetOverride("channel") + return tc.main.Bridge.Config.Backfill.Queue.GetOverride("channel") } default: log.Error().Str("peer_type", string(peerType)).Msg("unknown peer type") diff --git a/pkg/connector/capabilities.go b/pkg/connector/capabilities.go index 52f623c4..b306f504 100644 --- a/pkg/connector/capabilities.go +++ b/pkg/connector/capabilities.go @@ -32,7 +32,7 @@ import ( "go.mau.fi/mautrix-telegram/pkg/connector/ids" ) -func (tg *TelegramConnector) GetCapabilities() *bridgev2.NetworkGeneralCapabilities { +func (tc *TelegramConnector) GetCapabilities() *bridgev2.NetworkGeneralCapabilities { return &bridgev2.NetworkGeneralCapabilities{ DisappearingMessages: true, Provisioning: bridgev2.ProvisioningCapabilities{ @@ -59,7 +59,7 @@ func (tg *TelegramConnector) GetCapabilities() *bridgev2.NetworkGeneralCapabilit } } -func (tg *TelegramConnector) GetBridgeInfoVersion() (info, capabilities int) { +func (tc *TelegramConnector) GetBridgeInfoVersion() (info, capabilities int) { return 1, 8 } @@ -210,7 +210,7 @@ func makeTimerList() []jsontime.Milliseconds { var telegramTimers = makeTimerList() -func (t *TelegramClient) GetCapabilities(ctx context.Context, portal *bridgev2.Portal) *event.RoomFeatures { +func (tc *TelegramClient) GetCapabilities(ctx context.Context, portal *bridgev2.Portal) *event.RoomFeatures { baseID := "fi.mau.telegram.capabilities.2025_11_24" feat := &event.RoomFeatures{ Formatting: formattingCaps, @@ -240,7 +240,7 @@ func (t *TelegramClient) GetCapabilities(ctx context.Context, portal *bridgev2.P reactions := portal.Metadata.(*PortalMetadata).AllowedReactions if reactions == nil { baseID += "+reactions_any" - feat.AllowedReactions, feat.CustomEmojiReactions = t.getAvailableReactionsForCapability(ctx) + feat.AllowedReactions, feat.CustomEmojiReactions = tc.getAvailableReactionsForCapability(ctx) if len(feat.AllowedReactions) > 0 { baseID += "+any_list_" + hashEmojiList(feat.AllowedReactions) } @@ -254,7 +254,7 @@ func (t *TelegramClient) GetCapabilities(ctx context.Context, portal *bridgev2.P for i, react := range feat.AllowedReactions { feat.AllowedReactions[i] = variationselector.Add(react) } - if t.isPremiumCache.Load() { + if tc.isPremiumCache.Load() { baseID += "+premium" feat.File = premiumFileCaps feat.ReactionCount = 3 diff --git a/pkg/connector/chatinfo.go b/pkg/connector/chatinfo.go index 1016e367..2c19526c 100644 --- a/pkg/connector/chatinfo.go +++ b/pkg/connector/chatinfo.go @@ -93,8 +93,8 @@ func adminRightsToPowerLevel(rights tg.ChatAdminRights) *int { return otherPowerLevel } -func (t *TelegramClient) getDMChatInfo(ctx context.Context, userID int64) (*bridgev2.ChatInfo, error) { - ghost, err := t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(userID)) +func (tc *TelegramClient) getDMChatInfo(ctx context.Context, userID int64) (*bridgev2.ChatInfo, error) { + ghost, err := tc.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(userID)) if err != nil { return nil, err } @@ -104,19 +104,19 @@ func (t *TelegramClient) getDMChatInfo(ctx context.Context, userID int64) (*brid Members: &bridgev2.ChatMemberList{ IsFull: true, MemberMap: map[networkid.UserID]bridgev2.ChatMember{}, - PowerLevels: t.getDMPowerLevels(ghost), + PowerLevels: tc.getDMPowerLevels(ghost), }, - CanBackfill: !t.metadata.IsBot, + CanBackfill: !tc.metadata.IsBot, ExtraUpdates: updatePortalLastSyncAt, } - chatInfo.Members.MemberMap.Add(bridgev2.ChatMember{EventSender: t.mySender()}) - chatInfo.Members.MemberMap.Add(bridgev2.ChatMember{EventSender: t.senderForUserID(userID)}) - if userID == t.telegramUserID { + chatInfo.Members.MemberMap.Add(bridgev2.ChatMember{EventSender: tc.mySender()}) + chatInfo.Members.MemberMap.Add(bridgev2.ChatMember{EventSender: tc.senderForUserID(userID)}) + if userID == tc.telegramUserID { chatInfo.Avatar = &bridgev2.Avatar{ - ID: networkid.AvatarID(t.main.Config.SavedMessagesAvatar), - Remove: len(t.main.Config.SavedMessagesAvatar) == 0, - MXC: t.main.Config.SavedMessagesAvatar, - Hash: sha256.Sum256([]byte(t.main.Config.SavedMessagesAvatar)), + ID: networkid.AvatarID(tc.main.Config.SavedMessagesAvatar), + Remove: len(tc.main.Config.SavedMessagesAvatar) == 0, + MXC: tc.main.Config.SavedMessagesAvatar, + Hash: sha256.Sum256([]byte(tc.main.Config.SavedMessagesAvatar)), } chatInfo.Name = ptr.Ptr("Telegram Saved Messages") chatInfo.Topic = ptr.Ptr("Your Telegram cloud storage chat") @@ -140,10 +140,10 @@ type memberFetchMeta struct { IsForum bool } -func (t *TelegramClient) wrapChatInfo(portalID networkid.PortalID, rawChat tg.ChatClass) (*bridgev2.ChatInfo, *memberFetchMeta, error) { +func (tc *TelegramClient) wrapChatInfo(portalID networkid.PortalID, rawChat tg.ChatClass) (*bridgev2.ChatInfo, *memberFetchMeta, error) { info := bridgev2.ChatInfo{ Type: ptr.Ptr(database.RoomTypeDefault), - CanBackfill: !t.metadata.IsBot, + CanBackfill: !tc.metadata.IsBot, Members: &bridgev2.ChatMemberList{ ExcludeChangesFromTimeline: true, MemberMap: bridgev2.ChatMemberMap{}, @@ -158,8 +158,8 @@ func (t *TelegramClient) wrapChatInfo(portalID networkid.PortalID, rawChat tg.Ch case *tg.Chat: info.Name = &chat.Title info.Members.TotalMemberCount = chat.ParticipantsCount - info.Avatar, avatarErr = t.convertChatPhoto(chat.AsInputPeer(), chat.Photo) - info.Members.PowerLevels = t.getPowerLevelOverridesFromBannedRights(chat, chat.DefaultBannedRights) + info.Avatar, avatarErr = tc.convertChatPhoto(chat.AsInputPeer(), chat.Photo) + info.Members.PowerLevels = tc.getPowerLevelOverridesFromBannedRights(chat, chat.DefaultBannedRights) left = chat.Left if chat.Creator { ownPL = creatorPowerLevel @@ -174,8 +174,8 @@ func (t *TelegramClient) wrapChatInfo(portalID networkid.PortalID, rawChat tg.Ch info.Name = &chat.Title info.Members.TotalMemberCount = chat.ParticipantsCount isMegagroup = chat.Megagroup - info.Avatar, avatarErr = t.convertChatPhoto(chat.AsInputPeer(), chat.Photo) - info.Members.PowerLevels = t.getPowerLevelOverridesFromBannedRights(chat, chat.DefaultBannedRights) + info.Avatar, avatarErr = tc.convertChatPhoto(chat.AsInputPeer(), chat.Photo) + info.Members.PowerLevels = tc.getPowerLevelOverridesFromBannedRights(chat, chat.DefaultBannedRights) if chat.Creator { ownPL = creatorPowerLevel } else if rights, isAdmin := chat.GetAdminRights(); isAdmin { @@ -204,7 +204,7 @@ func (t *TelegramClient) wrapChatInfo(portalID networkid.PortalID, rawChat tg.Ch EventSender: bridgev2.EventSender{Sender: ids.MakeChannelUserID(chat.GetID())}, PowerLevel: superadminPowerLevel, }) - } else if chat.Megagroup && !t.main.Config.ShouldBridge(chat.ParticipantsCount) { + } else if chat.Megagroup && !tc.main.Config.ShouldBridge(chat.ParticipantsCount) { // TODO change this to a better error whenever that is implemented in mautrix-go return nil, nil, fmt.Errorf("too many participants (%d) in chat %d", chat.ParticipantsCount, chat.GetID()) } @@ -215,7 +215,7 @@ func (t *TelegramClient) wrapChatInfo(portalID networkid.PortalID, rawChat tg.Ch return nil, nil, fmt.Errorf("failed to wrap chat avatar: %w", avatarErr) } if !left { - info.Members.MemberMap.Add(bridgev2.ChatMember{EventSender: t.mySender(), PowerLevel: ownPL}) + info.Members.MemberMap.Add(bridgev2.ChatMember{EventSender: tc.mySender(), PowerLevel: ownPL}) } info.ExtraUpdates = func(ctx context.Context, portal *bridgev2.Portal) bool { meta := portal.Metadata.(*PortalMetadata) @@ -231,16 +231,16 @@ func (t *TelegramClient) wrapChatInfo(portalID networkid.PortalID, rawChat tg.Ch return &info, &mfm, nil } -func (t *TelegramClient) overrideChatInfoWithTopic(info *bridgev2.ChatInfo, topic *tg.ForumTopic) { +func (tc *TelegramClient) overrideChatInfoWithTopic(info *bridgev2.ChatInfo, topic *tg.ForumTopic) { info.Name = ptr.Ptr(topic.Title + " - " + *info.Name) if topic.Closed { info.Members.PowerLevels.EventsDefault = nobodyPowerLevel } } -func (t *TelegramClient) getChannelParticipants(ctx context.Context, req *tg.ChannelsGetParticipantsRequest) (*tg.ChannelsChannelParticipants, error) { - return APICallWithUpdates(ctx, t, func() (*tg.ChannelsChannelParticipants, error) { - p, err := t.client.API().ChannelsGetParticipants(ctx, req) +func (tc *TelegramClient) getChannelParticipants(ctx context.Context, req *tg.ChannelsGetParticipantsRequest) (*tg.ChannelsChannelParticipants, error) { + return APICallWithUpdates(ctx, tc, func() (*tg.ChannelsChannelParticipants, error) { + p, err := tc.client.API().ChannelsGetParticipants(ctx, req) if err != nil { return nil, err } @@ -249,14 +249,14 @@ func (t *TelegramClient) getChannelParticipants(ctx context.Context, req *tg.Cha }) } -func (t *TelegramClient) fillChannelMembers(ctx context.Context, mfm *memberFetchMeta, info *bridgev2.ChatMemberList) error { - if mfm.Input == nil || mfm.ParticipantsHidden || (mfm.IsBroadcast && !t.main.Config.MemberList.SyncBroadcastChannels) { +func (tc *TelegramClient) fillChannelMembers(ctx context.Context, mfm *memberFetchMeta, info *bridgev2.ChatMemberList) error { + if mfm.Input == nil || mfm.ParticipantsHidden || (mfm.IsBroadcast && !tc.main.Config.MemberList.SyncBroadcastChannels) { return nil } - memberSyncLimit := t.main.Config.MemberList.NormalizedMaxInitialSync() + memberSyncLimit := tc.main.Config.MemberList.NormalizedMaxInitialSync() if memberSyncLimit <= 200 { - participants, err := t.getChannelParticipants(ctx, &tg.ChannelsGetParticipantsRequest{ + participants, err := tc.getChannelParticipants(ctx, &tg.ChannelsGetParticipantsRequest{ Channel: mfm.Input, Filter: &tg.ChannelParticipantsRecent{}, Limit: memberSyncLimit, @@ -267,14 +267,14 @@ func (t *TelegramClient) fillChannelMembers(ctx context.Context, mfm *memberFetc info.IsFull = len(participants.Participants) < memberSyncLimit && len(participants.Participants) >= info.TotalMemberCount && info.TotalMemberCount > 0 - for participant := range t.filterChannelParticipants(participants.Participants, memberSyncLimit) { + for participant := range tc.filterChannelParticipants(participants.Participants, memberSyncLimit) { info.MemberMap.Set(participant) } } else { remaining := memberSyncLimit var offset int for remaining > 0 { - participants, err := t.getChannelParticipants(ctx, &tg.ChannelsGetParticipantsRequest{ + participants, err := tc.getChannelParticipants(ctx, &tg.ChannelsGetParticipantsRequest{ Channel: mfm.Input, Filter: &tg.ChannelParticipantsSearch{}, Limit: min(remaining, 200), @@ -289,7 +289,7 @@ func (t *TelegramClient) fillChannelMembers(ctx context.Context, mfm *memberFetc break } - for participant := range t.filterChannelParticipants(participants.Participants, remaining) { + for participant := range tc.filterChannelParticipants(participants.Participants, remaining) { info.MemberMap.Set(participant) } @@ -300,7 +300,7 @@ func (t *TelegramClient) fillChannelMembers(ctx context.Context, mfm *memberFetc return nil } -func (t *TelegramClient) fillUserLocalMeta(info *bridgev2.ChatInfo, dialog *tg.Dialog) { +func (tc *TelegramClient) fillUserLocalMeta(info *bridgev2.ChatInfo, dialog *tg.Dialog) { info.UserLocal = &bridgev2.UserLocalPortalInfo{} if mu, ok := dialog.NotifySettings.GetMuteUntil(); ok { info.UserLocal.MutedUntil = ptr.Ptr(time.Unix(int64(mu), 0)) @@ -312,7 +312,7 @@ func (t *TelegramClient) fillUserLocalMeta(info *bridgev2.ChatInfo, dialog *tg.D } } -func (t *TelegramClient) wrapFullChatInfo(portalID networkid.PortalID, fullChat *tg.MessagesChatFull) (*bridgev2.ChatInfo, *memberFetchMeta, error) { +func (tc *TelegramClient) wrapFullChatInfo(portalID networkid.PortalID, fullChat *tg.MessagesChatFull) (*bridgev2.ChatInfo, *memberFetchMeta, error) { var chat tg.ChatClass for _, c := range fullChat.GetChats() { if c.GetID() == fullChat.FullChat.GetID() { @@ -324,7 +324,7 @@ func (t *TelegramClient) wrapFullChatInfo(portalID networkid.PortalID, fullChat return nil, nil, fmt.Errorf("chat ID %d not found in full chat", fullChat.FullChat.GetID()) } - info, mfm, err := t.wrapChatInfo(portalID, chat) + info, mfm, err := tc.wrapChatInfo(portalID, chat) if err != nil { return nil, nil, err } @@ -365,7 +365,7 @@ func (t *TelegramClient) wrapFullChatInfo(portalID networkid.PortalID, fullChat switch typedFullChat := fullChat.FullChat.(type) { case *tg.ChatFull: participants, _ := typedFullChat.GetParticipants().(*tg.ChatParticipants) - memberSyncLimit := t.main.Config.MemberList.NormalizedMaxInitialSync() + memberSyncLimit := tc.main.Config.MemberList.NormalizedMaxInitialSync() info.Members.IsFull = true for i, user := range participants.GetParticipants() { var powerLevel *int @@ -379,7 +379,7 @@ func (t *TelegramClient) wrapFullChatInfo(portalID networkid.PortalID, fullChat } info.Members.MemberMap.Set(bridgev2.ChatMember{ - EventSender: t.senderForUserID(user.GetUserID()), + EventSender: tc.senderForUserID(user.GetUserID()), PowerLevel: powerLevel, }) @@ -422,7 +422,7 @@ func markFullSynced(ctx context.Context, portal *bridgev2.Portal) bool { return false } -func (t *TelegramClient) avatarFromPhoto(ctx context.Context, peerType ids.PeerType, peerID int64, photo tg.PhotoClass) *bridgev2.Avatar { +func (tc *TelegramClient) avatarFromPhoto(ctx context.Context, peerType ids.PeerType, peerID int64, photo tg.PhotoClass) *bridgev2.Avatar { if photo == nil { zerolog.Ctx(ctx).Trace().Msg("Chat photo is nil, returning no avatar") return nil @@ -430,7 +430,7 @@ func (t *TelegramClient) avatarFromPhoto(ctx context.Context, peerType ids.PeerT zerolog.Ctx(ctx).Debug().Str("type_name", photo.TypeName()).Msg("Chat photo type unknown, returning no avatar") return nil } - avatar, err := t.convertPhoto(ctx, peerType, peerID, photo) + avatar, err := tc.convertPhoto(ctx, peerType, peerID, photo) if err != nil { zerolog.Ctx(ctx).Err(err).Int64("id", photo.GetID()).Msg("Failed to convert avatar") return nil @@ -438,22 +438,22 @@ func (t *TelegramClient) avatarFromPhoto(ctx context.Context, peerType ids.PeerT return avatar } -func (t *TelegramClient) filterChannelParticipants(participants []tg.ChannelParticipantClass, limit int) iter.Seq[bridgev2.ChatMember] { +func (tc *TelegramClient) filterChannelParticipants(participants []tg.ChannelParticipantClass, limit int) iter.Seq[bridgev2.ChatMember] { return func(yield func(bridgev2.ChatMember) bool) { for i, u := range participants { var member bridgev2.ChatMember switch participant := u.(type) { case *tg.ChannelParticipant: - member.EventSender = t.senderForUserID(participant.GetUserID()) + member.EventSender = tc.senderForUserID(participant.GetUserID()) member.PowerLevel = anyonePowerLevel case *tg.ChannelParticipantSelf: - member.EventSender = t.senderForUserID(participant.GetUserID()) + member.EventSender = tc.senderForUserID(participant.GetUserID()) member.PowerLevel = anyonePowerLevel case *tg.ChannelParticipantCreator: - member.EventSender = t.senderForUserID(participant.GetUserID()) + member.EventSender = tc.senderForUserID(participant.GetUserID()) member.PowerLevel = creatorPowerLevel case *tg.ChannelParticipantAdmin: - member.EventSender = t.senderForUserID(participant.GetUserID()) + member.EventSender = tc.senderForUserID(participant.GetUserID()) member.PowerLevel = adminRightsToPowerLevel(participant.AdminRights) case *tg.ChannelParticipantBanned: if participant.BannedRights.ViewMessages { @@ -466,12 +466,12 @@ func (t *TelegramClient) filterChannelParticipants(participants []tg.ChannelPart } else { member.PowerLevel = anyonePowerLevel } - member.EventSender = t.getPeerSender(participant.GetPeer()) - member.MemberSender = t.senderForUserID(participant.GetKickedBy()) + member.EventSender = tc.getPeerSender(participant.GetPeer()) + member.MemberSender = tc.senderForUserID(participant.GetKickedBy()) case *tg.ChannelParticipantLeft: member.Membership = event.MembershipLeave member.PrevMembership = event.MembershipJoin - member.EventSender = t.getPeerSender(participant.GetPeer()) + member.EventSender = tc.getPeerSender(participant.GetPeer()) default: // TODO warning log? continue @@ -487,7 +487,7 @@ func (t *TelegramClient) filterChannelParticipants(participants []tg.ChannelPart } } -func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Portal) (*bridgev2.ChatInfo, error) { +func (tc *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Portal) (*bridgev2.ChatInfo, error) { peerType, id, topicID, err := ids.ParsePortalID(portal.ID) if err != nil { return nil, err @@ -495,24 +495,24 @@ func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Porta switch peerType { case ids.PeerTypeUser: - return t.getDMChatInfo(ctx, id) + return tc.getDMChatInfo(ctx, id) case ids.PeerTypeChat: - fullChat, err := APICallWithUpdates(ctx, t, func() (*tg.MessagesChatFull, error) { - return t.client.API().MessagesGetFullChat(ctx, id) + fullChat, err := APICallWithUpdates(ctx, tc, func() (*tg.MessagesChatFull, error) { + return tc.client.API().MessagesGetFullChat(ctx, id) }) if err != nil { return nil, err } - info, _, err := t.wrapFullChatInfo(portal.ID, fullChat) + info, _, err := tc.wrapFullChatInfo(portal.ID, fullChat) return info, err case ids.PeerTypeChannel: - accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, id) + accessHash, err := tc.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, id) if err != nil { return nil, fmt.Errorf("failed to get channel access hash: %w", err) } if topicID > 0 { - resp, err := APICallWithUpdates(ctx, t, func() (*tg.MessagesForumTopics, error) { - return t.client.API().MessagesGetForumTopicsByID(ctx, &tg.MessagesGetForumTopicsByIDRequest{ + resp, err := APICallWithUpdates(ctx, tc, func() (*tg.MessagesForumTopics, error) { + return tc.client.API().MessagesGetForumTopicsByID(ctx, &tg.MessagesGetForumTopicsByIDRequest{ Peer: &tg.InputPeerChannel{ChannelID: id, AccessHash: accessHash}, Topics: []int{topicID}, }) @@ -524,24 +524,24 @@ func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Porta if err != nil { return nil, err } - info, _, err := t.wrapChatInfo(portal.ID, channel) + info, _, err := tc.wrapChatInfo(portal.ID, channel) if err != nil { return nil, err } - t.overrideChatInfoWithTopic(info, topic) + tc.overrideChatInfoWithTopic(info, topic) return info, nil } - fullChat, err := APICallWithUpdates(ctx, t, func() (*tg.MessagesChatFull, error) { - return t.client.API().ChannelsGetFullChannel(ctx, &tg.InputChannel{ChannelID: id, AccessHash: accessHash}) + fullChat, err := APICallWithUpdates(ctx, tc, func() (*tg.MessagesChatFull, error) { + return tc.client.API().ChannelsGetFullChannel(ctx, &tg.InputChannel{ChannelID: id, AccessHash: accessHash}) }) if err != nil { return nil, err } - info, mfm, err := t.wrapFullChatInfo(portal.ID, fullChat) + info, mfm, err := tc.wrapFullChatInfo(portal.ID, fullChat) if err != nil { return nil, err } - err = t.fillChannelMembers(ctx, mfm, info.Members) + err = tc.fillChannelMembers(ctx, mfm, info.Members) if err != nil { zerolog.Ctx(ctx).Err(err).Msg("Failed to get channel members") } @@ -580,7 +580,7 @@ func getTopicInfoFromResponse(resp *tg.MessagesForumTopics, channelID int64, top return } -func (t *TelegramClient) getDMPowerLevels(ghost *bridgev2.Ghost) *bridgev2.PowerLevelOverrides { +func (tc *TelegramClient) getDMPowerLevels(ghost *bridgev2.Ghost) *bridgev2.PowerLevelOverrides { var plo bridgev2.PowerLevelOverrides // TODO use per-login metadata for blocked status if /*ghost.Metadata.(*GhostMetadata).Blocked*/ false { @@ -599,7 +599,7 @@ func (t *TelegramClient) getDMPowerLevels(ghost *bridgev2.Ghost) *bridgev2.Power return &plo } -func (t *TelegramClient) getPowerLevelOverridesFromBannedRights(entity tg.ChatClass, dbr tg.ChatBannedRights) *bridgev2.PowerLevelOverrides { +func (tc *TelegramClient) getPowerLevelOverridesFromBannedRights(entity tg.ChatClass, dbr tg.ChatBannedRights) *bridgev2.PowerLevelOverrides { var plo bridgev2.PowerLevelOverrides plo.Ban = banUsersPowerLevel plo.Kick = banUsersPowerLevel diff --git a/pkg/connector/chatsync.go b/pkg/connector/chatsync.go index 3752f163..b74fdd39 100644 --- a/pkg/connector/chatsync.go +++ b/pkg/connector/chatsync.go @@ -33,8 +33,8 @@ import ( "go.mau.fi/mautrix-telegram/pkg/gotd/tgerr" ) -func (t *TelegramClient) syncChats(ctx context.Context, takeoutID int64, onLogin, restart bool) error { - if takeoutID != 0 && !t.main.Config.Takeout.DialogSync { +func (tc *TelegramClient) syncChats(ctx context.Context, takeoutID int64, onLogin, restart bool) error { + if takeoutID != 0 && !tc.main.Config.Takeout.DialogSync { return nil } logWith := zerolog.Ctx(ctx).With().Str("loop", "chat sync") @@ -46,36 +46,36 @@ func (t *TelegramClient) syncChats(ctx context.Context, takeoutID int64, onLogin } log := logWith.Logger() - if !t.syncChatsLock.TryLock() { + if !tc.syncChatsLock.TryLock() { log.Warn().Msg("Waiting for chat sync lock") - t.syncChatsLock.Lock() + tc.syncChatsLock.Lock() log.Debug().Msg("Acquired chat sync lock after waiting") } - defer t.syncChatsLock.Unlock() + defer tc.syncChatsLock.Unlock() if restart { - t.metadata.DialogSyncCount = 0 - t.metadata.DialogSyncComplete = false - t.metadata.DialogSyncCursor = "" - } else if t.metadata.DialogSyncComplete { + tc.metadata.DialogSyncCount = 0 + tc.metadata.DialogSyncComplete = false + tc.metadata.DialogSyncCursor = "" + } else if tc.metadata.DialogSyncComplete { log.Debug().Msg("Dialogs already synced") return nil } isFullSync := true - updateLimit := subtractLimit(t.main.Config.Sync.UpdateLimit, t.metadata.DialogSyncCount) - if onLogin && t.main.Config.Takeout.DialogSync { - updateLimit = t.main.Config.Sync.LoginLimit + updateLimit := subtractLimit(tc.main.Config.Sync.UpdateLimit, tc.metadata.DialogSyncCount) + if onLogin && tc.main.Config.Takeout.DialogSync { + updateLimit = tc.main.Config.Sync.LoginLimit isFullSync = false } - createLimit := subtractLimit(t.main.Config.Sync.CreateLimit, t.metadata.DialogSyncCount) + createLimit := subtractLimit(tc.main.Config.Sync.CreateLimit, tc.metadata.DialogSyncCount) var req tg.MessagesGetDialogsRequest isFirst := true - if t.metadata.DialogSyncCursor != "" { + if tc.metadata.DialogSyncCursor != "" { isFirst = false var err error - req.OffsetPeer, _, err = t.inputPeerForPortalID(ctx, t.metadata.DialogSyncCursor) + req.OffsetPeer, _, err = tc.inputPeerForPortalID(ctx, tc.metadata.DialogSyncCursor) if err != nil { return fmt.Errorf("failed to get input peer for pagination: %w", err) } @@ -99,12 +99,12 @@ func (t *TelegramClient) syncChats(ctx context.Context, takeoutID int64, onLogin Int("update_limit", updateLimit). Int("create_limit", createLimit). Msg("Fetching dialogs") - dialogs, err := APICallWithUpdates(ctx, t, func() (tg.ModifiedMessagesDialogs, error) { + dialogs, err := APICallWithUpdates(ctx, tc, func() (tg.ModifiedMessagesDialogs, error) { var dialogs tg.MessagesDialogsBox retry := true var err error for retry { - retry, err = tgerr.FloodWait(ctx, t.client.Invoke(ctx, wrappedReq, &dialogs)) + retry, err = tgerr.FloodWait(ctx, tc.client.Invoke(ctx, wrappedReq, &dialogs)) } if err != nil { return nil, err @@ -123,7 +123,7 @@ func (t *TelegramClient) syncChats(ctx context.Context, takeoutID int64, onLogin if isFirst { // This is the first fetch of dialogs, reset the pinned dialogs based on the list. - if err = t.resetPinnedDialogs(ctx, dialogs.GetDialogs()); err != nil { + if err = tc.resetPinnedDialogs(ctx, dialogs.GetDialogs()); err != nil { return fmt.Errorf("failed to save pinned dialogs: %w", err) } } @@ -133,34 +133,34 @@ func (t *TelegramClient) syncChats(ctx context.Context, takeoutID int64, onLogin if updateLimit > 0 && len(dialogList) > updateLimit { dialogList = dialogList[:updateLimit] } - err = t.handleDialogs(ctx, dialogList, dialogs, createLimit) + err = tc.handleDialogs(ctx, dialogList, dialogs, createLimit) if err != nil { return fmt.Errorf("failed to handle dialogs: %w", err) } updateLimit = subtractLimit(updateLimit, len(dialogList)) createLimit = subtractLimit(createLimit, len(dialogList)) - cursorPortalKey := t.makePortalKeyFromPeer(dialogList[len(dialogList)-1].GetPeer(), 0) - if t.metadata.DialogSyncCursor == cursorPortalKey.ID { + cursorPortalKey := tc.makePortalKeyFromPeer(dialogList[len(dialogList)-1].GetPeer(), 0) + if tc.metadata.DialogSyncCursor == cursorPortalKey.ID { log.Debug().Msg("No more dialogs found (last dialog is same as old cursor)") break } - t.metadata.DialogSyncCursor = cursorPortalKey.ID - t.metadata.DialogSyncCount += len(dialogList) - if err = t.userLogin.Save(ctx); err != nil { + tc.metadata.DialogSyncCursor = cursorPortalKey.ID + tc.metadata.DialogSyncCount += len(dialogList) + if err = tc.userLogin.Save(ctx); err != nil { return fmt.Errorf("failed to save user login to update cursor: %w", err) } - req.OffsetPeer, _, err = t.inputPeerForPortalID(ctx, cursorPortalKey.ID) + req.OffsetPeer, _, err = tc.inputPeerForPortalID(ctx, cursorPortalKey.ID) if err != nil { return fmt.Errorf("failed to get input peer for pagination: %w", err) } } if isFullSync { - t.metadata.DialogSyncComplete = true - t.metadata.DialogSyncCursor = "" - t.metadata.DialogSyncCount = 0 - if err := t.userLogin.Save(ctx); err != nil { + tc.metadata.DialogSyncComplete = true + tc.metadata.DialogSyncCursor = "" + tc.metadata.DialogSyncCount = 0 + if err := tc.userLogin.Save(ctx); err != nil { return fmt.Errorf("failed to save user login after successful sync: %w", err) } } @@ -179,18 +179,18 @@ func subtractLimit(limit, count int) int { return limit } -func (t *TelegramClient) resetPinnedDialogs(ctx context.Context, dialogs []tg.DialogClass) error { - t.metadata.PinnedDialogs = nil +func (tc *TelegramClient) resetPinnedDialogs(ctx context.Context, dialogs []tg.DialogClass) error { + tc.metadata.PinnedDialogs = nil for _, dialog := range dialogs { if dialog.GetPinned() { - portalKey := t.makePortalKeyFromPeer(dialog.GetPeer(), 0) - t.metadata.PinnedDialogs = append(t.metadata.PinnedDialogs, portalKey.ID) + portalKey := tc.makePortalKeyFromPeer(dialog.GetPeer(), 0) + tc.metadata.PinnedDialogs = append(tc.metadata.PinnedDialogs, portalKey.ID) } } - return t.userLogin.Save(ctx) + return tc.userLogin.Save(ctx) } -func (t *TelegramClient) handleDialogs(ctx context.Context, dialogList []tg.DialogClass, meta tg.ModifiedMessagesDialogs, createLimit int) error { +func (tc *TelegramClient) handleDialogs(ctx context.Context, dialogList []tg.DialogClass, meta tg.ModifiedMessagesDialogs, createLimit int) error { log := zerolog.Ctx(ctx) users := map[int64]tg.UserClass{} @@ -218,8 +218,8 @@ func (t *TelegramClient) handleDialogs(ctx context.Context, dialogList []tg.Dial Logger() log.Debug().Msg("Syncing dialog") - portalKey := t.makePortalKeyFromPeer(dialog.GetPeer(), 0) - portal, err := t.main.Bridge.GetPortalByKey(ctx, portalKey) + portalKey := tc.makePortalKeyFromPeer(dialog.GetPeer(), 0) + portal, err := tc.main.Bridge.GetPortalByKey(ctx, portalKey) if err != nil { return err } @@ -236,7 +236,7 @@ func (t *TelegramClient) handleDialogs(ctx context.Context, dialogList []tg.Dial log.Debug().Int64("user_id", peer.UserID).Msg("Not syncing portal because user is deleted") continue } - chatInfo, err = t.getDMChatInfo(ctx, peer.UserID) + chatInfo, err = tc.getDMChatInfo(ctx, peer.UserID) if err != nil { return fmt.Errorf("failed to get dm info for %d: %w", peer.UserID, err) } @@ -251,7 +251,7 @@ func (t *TelegramClient) handleDialogs(ctx context.Context, dialogList []tg.Dial switch chat := chats[peer.ChatID].(type) { case *tg.Chat: // Need to get full chat info to get the member list - chatInfo, err = t.GetChatInfo(ctx, portal) + chatInfo, err = tc.GetChatInfo(ctx, portal) if err != nil { return fmt.Errorf("failed to get chat info for %s: %w", portalKey, err) } @@ -271,11 +271,11 @@ func (t *TelegramClient) handleDialogs(ctx context.Context, dialogList []tg.Dial switch channel := chats[peer.ChannelID].(type) { case *tg.Channel: var mfm *memberFetchMeta - chatInfo, mfm, err = t.wrapChatInfo(portal.ID, channel) + chatInfo, mfm, err = tc.wrapChatInfo(portal.ID, channel) if err != nil { return fmt.Errorf("failed to get chat info for %s: %w", portalKey, err) } - err = t.fillChannelMembers(ctx, mfm, chatInfo.Members) + err = tc.fillChannelMembers(ctx, mfm, chatInfo.Members) if err != nil { log.Err(err).Msg("Failed to get channel members") } @@ -315,9 +315,9 @@ func (t *TelegramClient) handleDialogs(ctx context.Context, dialogList []tg.Dial } } - t.fillUserLocalMeta(chatInfo, dialog) + tc.fillUserLocalMeta(chatInfo, dialog) - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatResync{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatResync{ ChatInfo: chatInfo, EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventChatResync, @@ -343,11 +343,11 @@ func (t *TelegramClient) handleDialogs(ctx context.Context, dialogList []tg.Dial } // Generate a read receipt from the last known read message id - res = t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Receipt{ + res = tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Receipt{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventReadReceipt, PortalKey: portalKey, - Sender: t.mySender(), + Sender: tc.mySender(), }, LastTarget: ids.MakeMessageID(portalKey, dialog.ReadInboxMaxID), ReadUpToStreamOrder: int64(dialog.ReadInboxMaxID), diff --git a/pkg/connector/client.go b/pkg/connector/client.go index 8932781a..9a13df34 100644 --- a/pkg/connector/client.go +++ b/pkg/connector/client.go @@ -123,13 +123,13 @@ var _ bridgev2.NetworkAPI = (*TelegramClient)(nil) var messageLinkRegex = regexp.MustCompile(`^https?://t(?:elegram)?\.(?:me|dog)/([A-Za-z][A-Za-z0-9_]{3,31}[A-Za-z0-9]|[Cc]/[0-9]{1,20})/([0-9]{1,20})(?:/([0-9]{1,20}))?$`) -func (tg *TelegramConnector) deviceConfig() telegram.DeviceConfig { +func (tc *TelegramConnector) deviceConfig() telegram.DeviceConfig { return telegram.DeviceConfig{ - DeviceModel: tg.Config.DeviceInfo.DeviceModel, - SystemVersion: tg.Config.DeviceInfo.SystemVersion, - AppVersion: tg.Config.DeviceInfo.AppVersion, - SystemLangCode: tg.Config.DeviceInfo.SystemLangCode, - LangCode: tg.Config.DeviceInfo.LangCode, + DeviceModel: tc.Config.DeviceInfo.DeviceModel, + SystemVersion: tc.Config.DeviceInfo.SystemVersion, + AppVersion: tc.Config.DeviceInfo.AppVersion, + SystemLangCode: tc.Config.DeviceInfo.SystemLangCode, + LangCode: tc.Config.DeviceInfo.LangCode, } } @@ -365,34 +365,34 @@ func NewTelegramClient(ctx context.Context, tc *TelegramConnector, login *bridge return &client, err } -func (t *TelegramClient) onDead() { - prevState := t.userLogin.BridgeState.GetPrev().StateEvent +func (tc *TelegramClient) onDead() { + prevState := tc.userLogin.BridgeState.GetPrev().StateEvent if slices.Contains([]status.BridgeStateEvent{ status.StateTransientDisconnect, status.StateBadCredentials, status.StateLoggedOut, status.StateUnknownError, }, prevState) { - t.userLogin.Log.Warn(). + tc.userLogin.Log.Warn(). Str("prev_state", string(prevState)). Msg("client is dead, not sending transient disconnect, because already in an error state") return } - t.userLogin.BridgeState.Send(status.BridgeState{ + tc.userLogin.BridgeState.Send(status.BridgeState{ StateEvent: status.StateTransientDisconnect, Message: "Telegram client disconnected", }) } -func (t *TelegramClient) sendBadCredentialsOrUnknownError(err error) { +func (tc *TelegramClient) sendBadCredentialsOrUnknownError(err error) { if auth.IsUnauthorized(err) || errors.Is(err, ErrNoAuthKey) { - t.userLogin.BridgeState.Send(status.BridgeState{ + tc.userLogin.BridgeState.Send(status.BridgeState{ StateEvent: status.StateBadCredentials, Error: "tg-no-auth", Message: humanise.Error(err), }) } else { - t.userLogin.BridgeState.Send(status.BridgeState{ + tc.userLogin.BridgeState.Send(status.BridgeState{ StateEvent: status.StateUnknownError, Error: "tg-unknown-error", Message: humanise.Error(err), @@ -403,38 +403,38 @@ func (t *TelegramClient) sendBadCredentialsOrUnknownError(err error) { } } -func (t *TelegramClient) onPing() { - prev := t.userLogin.BridgeState.GetPrev() +func (tc *TelegramClient) onPing() { + prev := tc.userLogin.BridgeState.GetPrev() if prev.StateEvent == status.StateConnected || prev.Error == updateHandlerStuck { return } - ctx := t.userLogin.Log.WithContext(t.main.Bridge.BackgroundCtx) - t.userLogin.Log.Debug().Msg("Got ping while not connected, checking auth") + ctx := tc.userLogin.Log.WithContext(tc.main.Bridge.BackgroundCtx) + tc.userLogin.Log.Debug().Msg("Got ping while not connected, checking auth") - me, err := t.client.Self(ctx) + me, err := tc.client.Self(ctx) if auth.IsUnauthorized(err) { - t.onAuthError(err) + tc.onAuthError(err) } else if errors.Is(err, syscall.EPIPE) { // This is a pipe error, try disconnecting which will force the // updatesManager to fail and cause the client to reconnect. - t.userLogin.BridgeState.Send(status.BridgeState{ + tc.userLogin.BridgeState.Send(status.BridgeState{ StateEvent: status.StateTransientDisconnect, Error: "pipe-error", Message: humanise.Error(err), }) } else if err != nil { - t.sendBadCredentialsOrUnknownError(err) + tc.sendBadCredentialsOrUnknownError(err) } else { - t.onConnected(me) + tc.onConnected(me) } } -func (t *TelegramConnector) userToRemoteProfile( +func (tc *TelegramConnector) userToRemoteProfile( self *tg.User, ghost *bridgev2.Ghost, prevState *status.RemoteProfile, ) (profile status.RemoteProfile, name string) { - profile.Name = t.Config.FormatDisplayname(self.FirstName, self.LastName, self.Username, self.Deleted, self.ID) + profile.Name = tc.Config.FormatDisplayname(self.FirstName, self.LastName, self.Username, self.Deleted, self.ID) if self.Phone != "" { profile.Phone = "+" + strings.TrimPrefix(self.Phone, "+") } else if prevState != nil { @@ -453,99 +453,99 @@ func (t *TelegramConnector) userToRemoteProfile( return } -func (t *TelegramClient) updateRemoteProfile(ctx context.Context, self *tg.User, ghost *bridgev2.Ghost) bool { - newProfile, newName := t.main.userToRemoteProfile(self, ghost, &t.userLogin.RemoteProfile) - if t.userLogin.RemoteProfile != newProfile || t.userLogin.RemoteName != newName { - t.userLogin.RemoteProfile = newProfile - t.userLogin.RemoteName = newName - err := t.userLogin.Save(ctx) +func (tc *TelegramClient) updateRemoteProfile(ctx context.Context, self *tg.User, ghost *bridgev2.Ghost) bool { + newProfile, newName := tc.main.userToRemoteProfile(self, ghost, &tc.userLogin.RemoteProfile) + if tc.userLogin.RemoteProfile != newProfile || tc.userLogin.RemoteName != newName { + tc.userLogin.RemoteProfile = newProfile + tc.userLogin.RemoteName = newName + err := tc.userLogin.Save(ctx) if err != nil { - t.userLogin.Log.Err(err).Msg("Failed to save user login after profile update") + tc.userLogin.Log.Err(err).Msg("Failed to save user login after profile update") } return true } return false } -func (t *TelegramClient) onConnected(self *tg.User) { - log := t.userLogin.Log - ctx := log.WithContext(t.main.Bridge.BackgroundCtx) - ghost, err := t.main.Bridge.GetGhostByID(ctx, t.userID) +func (tc *TelegramClient) onConnected(self *tg.User) { + log := tc.userLogin.Log + ctx := log.WithContext(tc.main.Bridge.BackgroundCtx) + ghost, err := tc.main.Bridge.GetGhostByID(ctx, tc.userID) if err != nil { log.Err(err).Msg("Failed to get own ghost") - } else if wrapped, err := t.wrapUserInfo(ctx, self, ghost); err != nil { + } else if wrapped, err := tc.wrapUserInfo(ctx, self, ghost); err != nil { log.Err(err).Msg("Failed to wrap own user info") } else { ghost.UpdateInfo(ctx, wrapped) } - t.updateRemoteProfile(ctx, self, ghost) - t.userLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) + tc.updateRemoteProfile(ctx, self, ghost) + tc.userLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) } -func (t *TelegramClient) onTransfer(ctx context.Context, _ *telegram.Client, fn func(context.Context) error) error { - t.userLogin.Log.Trace().Msg("Doing DC auth transfer") - t.dcTransferLock.Lock() - defer t.dcTransferLock.Unlock() +func (tc *TelegramClient) onTransfer(ctx context.Context, _ *telegram.Client, fn func(context.Context) error) error { + tc.userLogin.Log.Trace().Msg("Doing DC auth transfer") + tc.dcTransferLock.Lock() + defer tc.dcTransferLock.Unlock() return fn(ctx) } -func (t *TelegramClient) onSession() { - t.userLogin.Log.Debug().Msg("Got session created event") +func (tc *TelegramClient) onSession() { + tc.userLogin.Log.Debug().Msg("Got session created event") } -func (t *TelegramClient) onAuthError(err error) { - t.sendBadCredentialsOrUnknownError(err) - t.metadata.ResetOnLogout() +func (tc *TelegramClient) onAuthError(err error) { + tc.sendBadCredentialsOrUnknownError(err) + tc.metadata.ResetOnLogout() go func() { - t.Disconnect() - if err := t.userLogin.Save(context.Background()); err != nil { - t.main.Bridge.Log.Err(err).Msg("failed to save user login") + tc.Disconnect() + if err := tc.userLogin.Save(context.Background()); err != nil { + tc.main.Bridge.Log.Err(err).Msg("failed to save user login") } }() } -func (t *TelegramClient) Connect(ctx context.Context) { - t.mu.Lock() - defer t.mu.Unlock() +func (tc *TelegramClient) Connect(ctx context.Context) { + tc.mu.Lock() + defer tc.mu.Unlock() log := zerolog.Ctx(ctx) - if !t.metadata.Session.HasAuthKey() { + if !tc.metadata.Session.HasAuthKey() { log.Warn().Msg("user does not have an auth key, sending bad credentials state") - t.sendBadCredentialsOrUnknownError(ErrNoAuthKey) + tc.sendBadCredentialsOrUnknownError(ErrNoAuthKey) return } - t.userLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnecting}) + tc.userLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnecting}) log.Info().Msg("Connecting client") // Add a cancellation layer we can use for explicit Disconnect ctx, cancel := context.WithCancel(ctx) - t.clientCtx = ctx - t.clientCancel = cancel - t.clientDone.Clear() - t.clientInitialized.Clear() - go t.runInBackground(ctx) + tc.clientCtx = ctx + tc.clientCancel = cancel + tc.clientDone.Clear() + tc.clientInitialized.Clear() + go tc.runInBackground(ctx) } -func (t *TelegramClient) runInBackground(ctx context.Context) { +func (tc *TelegramClient) runInBackground(ctx context.Context) { log := zerolog.Ctx(ctx) - err := t.client.Run(ctx, func(ctx context.Context) error { - t.clientInitialized.Set() + err := tc.client.Run(ctx, func(ctx context.Context) error { + tc.clientInitialized.Set() // If takeout dialog sync is enabled, we assume it'll resume from a getTakeoutID call. // If not, resume dialog sync manually here. - if !t.isNewLogin && !t.main.Config.Takeout.DialogSync { + if !tc.isNewLogin && !tc.main.Config.Takeout.DialogSync { go func() { - if err := t.syncChats(log.WithContext(t.clientCtx), 0, false, false); err != nil { + if err := tc.syncChats(log.WithContext(tc.clientCtx), 0, false, false); err != nil { log.Err(err).Msg("Failed to resume chat sync") } }() } log.Info().Msg("Client running, starting updates") - err := t.updatesManager.Run(ctx, t.client.API(), t.telegramUserID, updates.AuthOptions{ - IsBot: t.metadata.IsBot, + err := tc.updatesManager.Run(ctx, tc.client.API(), tc.telegramUserID, updates.AuthOptions{ + IsBot: tc.metadata.IsBot, }) if err != nil && !errors.Is(err, ctx.Err()) { log.Warn().Err(err).AnErr("ctx_err", ctx.Err()).Msg("Update manager exited with error") @@ -554,77 +554,77 @@ func (t *TelegramClient) runInBackground(ctx context.Context) { } return err }) - t.clientDone.Set() - t.clientInitialized.Set() + tc.clientDone.Set() + tc.clientInitialized.Set() if err != nil { log.Err(err).AnErr("ctx_err", ctx.Err()).Msg("Client exited with error") - t.sendBadCredentialsOrUnknownError(err) + tc.sendBadCredentialsOrUnknownError(err) } else if ctx.Err() == nil { log.Warn().Msg("Client exited unexpectedly") - t.sendBadCredentialsOrUnknownError(fmt.Errorf("unexpectedly disconnected from Telegram")) + tc.sendBadCredentialsOrUnknownError(fmt.Errorf("unexpectedly disconnected from Telegram")) } else { log.Debug().AnErr("ctx_err", ctx.Err()).Msg("Client exited without error") } } -func (t *TelegramClient) Disconnect() { - t.mu.Lock() - defer t.mu.Unlock() +func (tc *TelegramClient) Disconnect() { + tc.mu.Lock() + defer tc.mu.Unlock() - t.userLogin.Log.Debug().Msg("Disconnecting client") + tc.userLogin.Log.Debug().Msg("Disconnecting client") - if t.clientCancel != nil { - t.clientCancel() - t.userLogin.Log.Debug().Msg("Waiting for client disconnection") - <-t.clientDone.GetChan() + if tc.clientCancel != nil { + tc.clientCancel() + tc.userLogin.Log.Debug().Msg("Waiting for client disconnection") + <-tc.clientDone.GetChan() } - t.userLogin.Log.Info().Msg("Disconnect complete") + tc.userLogin.Log.Info().Msg("Disconnect complete") } -func (t *TelegramClient) IsLoggedIn() bool { +func (tc *TelegramClient) IsLoggedIn() bool { // TODO use less hacky check than context cancellation - return t != nil && t.client != nil && - t.clientInitialized.IsSet() && !t.clientDone.IsSet() && - t.metadata.Session.HasAuthKey() + return tc != nil && tc.client != nil && + tc.clientInitialized.IsSet() && !tc.clientDone.IsSet() && + tc.metadata.Session.HasAuthKey() } -func (t *TelegramClient) LogoutRemote(ctx context.Context) { +func (tc *TelegramClient) LogoutRemote(ctx context.Context) { log := zerolog.Ctx(ctx).With(). Str("action", "logout_remote"). - Int64("user_id", t.telegramUserID). + Int64("user_id", tc.telegramUserID). Logger() log.Info().Msg("Logging out and disconnecting") - if t.metadata.Session.HasAuthKey() { + if tc.metadata.Session.HasAuthKey() { log.Info().Msg("User has an auth key, logging out") // logging out is best effort, we want to logout even if we can't call the endpoint ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() - _, err := t.client.API().AuthLogOut(ctx) + _, err := tc.client.API().AuthLogOut(ctx) if err != nil { log.Err(err).Msg("failed to logout on Telegram") } } - t.Disconnect() + tc.Disconnect() log.Info().Msg("Deleting user state") - err := t.ScopedStore.DeleteUserState(ctx) + err := tc.ScopedStore.DeleteUserState(ctx) if err != nil { log.Err(err).Msg("failed to delete user state") } - err = t.ScopedStore.DeleteChannelStateForUser(ctx) + err = tc.ScopedStore.DeleteChannelStateForUser(ctx) if err != nil { log.Err(err).Msg("failed to delete channel state for user") } - err = t.ScopedStore.DeleteAccessHashesForUser(ctx) + err = tc.ScopedStore.DeleteAccessHashesForUser(ctx) if err != nil { log.Err(err).Msg("failed to delete access hashes for user") } @@ -632,31 +632,31 @@ func (t *TelegramClient) LogoutRemote(ctx context.Context) { log.Info().Msg("Logged out and deleted user state") } -func (t *TelegramClient) IsThisUser(ctx context.Context, userID networkid.UserID) bool { - return userID == networkid.UserID(t.userLogin.ID) +func (tc *TelegramClient) IsThisUser(ctx context.Context, userID networkid.UserID) bool { + return userID == networkid.UserID(tc.userLogin.ID) } -func (t *TelegramClient) mySender() bridgev2.EventSender { +func (tc *TelegramClient) mySender() bridgev2.EventSender { return bridgev2.EventSender{ IsFromMe: true, - SenderLogin: t.loginID, - Sender: t.userID, + SenderLogin: tc.loginID, + Sender: tc.userID, } } -func (t *TelegramClient) senderForUserID(userID int64) bridgev2.EventSender { +func (tc *TelegramClient) senderForUserID(userID int64) bridgev2.EventSender { return bridgev2.EventSender{ - IsFromMe: userID == t.telegramUserID, + IsFromMe: userID == tc.telegramUserID, SenderLogin: ids.MakeUserLoginID(userID), Sender: ids.MakeUserID(userID), } } -func (t *TelegramClient) FillBridgeState(state status.BridgeState) status.BridgeState { +func (tc *TelegramClient) FillBridgeState(state status.BridgeState) status.BridgeState { if state.Info == nil { state.Info = make(map[string]any) } - state.Info["is_bot"] = t.metadata.IsBot - state.Info["login_method"] = t.metadata.LoginMethod + state.Info["is_bot"] = tc.metadata.IsBot + state.Info["login_method"] = tc.metadata.LoginMethod return state } diff --git a/pkg/connector/config.go b/pkg/connector/config.go index 569ce4e3..f290888e 100644 --- a/pkg/connector/config.go +++ b/pkg/connector/config.go @@ -179,8 +179,8 @@ func upgradeConfig(helper up.Helper) { helper.Copy(up.Str, "displayname_template") } -func (tg *TelegramConnector) GetConfig() (example string, data any, upgrader up.Upgrader) { - return ExampleConfig, &tg.Config, &up.StructUpgrader{ +func (tc *TelegramConnector) GetConfig() (example string, data any, upgrader up.Upgrader) { + return ExampleConfig, &tc.Config, &up.StructUpgrader{ SimpleUpgrader: up.SimpleUpgrader(upgradeConfig), Blocks: [][]string{ {"device_info"}, @@ -195,15 +195,15 @@ func (tg *TelegramConnector) GetConfig() (example string, data any, upgrader up. } } -func (tg *TelegramConnector) ValidateConfig() error { - if tg.Config.APIID == 0 { +func (tc *TelegramConnector) ValidateConfig() error { + if tc.Config.APIID == 0 { return fmt.Errorf("api_id is required") } - if tg.Config.APIHash == "" || tg.Config.APIHash == "tjyd5yge35lbodk1xwzw2jstp90k55qz" { + if tc.Config.APIHash == "" || tc.Config.APIHash == "tjyd5yge35lbodk1xwzw2jstp90k55qz" { return fmt.Errorf("api_hash is required") } - if !slices.Contains([]string{"disable", "gif", "png", "webp", "webm"}, tg.Config.AnimatedSticker.Target) { - return fmt.Errorf("unsupported animated sticker target: %s", tg.Config.AnimatedSticker.Target) + if !slices.Contains([]string{"disable", "gif", "png", "webp", "webm"}, tc.Config.AnimatedSticker.Target) { + return fmt.Errorf("unsupported animated sticker target: %s", tc.Config.AnimatedSticker.Target) } return nil } diff --git a/pkg/connector/connector.go b/pkg/connector/connector.go index e829dad1..81367a40 100644 --- a/pkg/connector/connector.go +++ b/pkg/connector/connector.go @@ -38,14 +38,14 @@ type TelegramConnector struct { var _ bridgev2.NetworkConnector = (*TelegramConnector)(nil) var _ bridgev2.MaxFileSizeingNetwork = (*TelegramConnector)(nil) -func (tg *TelegramConnector) Init(bridge *bridgev2.Bridge) { - tg.Store = store.NewStore(bridge.DB.Database, dbutil.ZeroLogger(bridge.Log.With().Str("db_section", "telegram").Logger())) - tg.Bridge = bridge - tg.Bridge.Commands.(*commands.Processor).AddHandlers(cmdSyncChats, cmdEmojiPack, cmdUpgrade, cmdJoin) +func (tc *TelegramConnector) Init(bridge *bridgev2.Bridge) { + tc.Store = store.NewStore(bridge.DB.Database, dbutil.ZeroLogger(bridge.Log.With().Str("db_section", "telegram").Logger())) + tc.Bridge = bridge + tc.Bridge.Commands.(*commands.Processor).AddHandlers(cmdSyncChats, cmdEmojiPack, cmdUpgrade, cmdJoin) } -func (tg *TelegramConnector) Start(ctx context.Context) error { - return tg.Store.Upgrade(ctx) +func (tc *TelegramConnector) Start(ctx context.Context) error { + return tc.Store.Upgrade(ctx) } func (tc *TelegramConnector) LoadUserLogin(ctx context.Context, login *bridgev2.UserLogin) (err error) { @@ -53,11 +53,11 @@ func (tc *TelegramConnector) LoadUserLogin(ctx context.Context, login *bridgev2. return } -func (tg *TelegramConnector) SetMaxFileSize(maxSize int64) { - tg.maxFileSize = maxSize +func (tc *TelegramConnector) SetMaxFileSize(maxSize int64) { + tc.maxFileSize = maxSize } -func (tg *TelegramConnector) GetName() bridgev2.BridgeName { +func (tc *TelegramConnector) GetName() bridgev2.BridgeName { return bridgev2.BridgeName{ DisplayName: "Telegram", NetworkURL: "https://telegram.org/", diff --git a/pkg/connector/directdownload.go b/pkg/connector/directdownload.go index 878ab6e0..9fc070d1 100644 --- a/pkg/connector/directdownload.go +++ b/pkg/connector/directdownload.go @@ -218,6 +218,6 @@ func (tc *TelegramConnector) Download(ctx context.Context, mediaID networkid.Med return readyTransferer.ToDirectMediaResponse(ctx) } -func (tg *TelegramConnector) SetUseDirectMedia() { - tg.useDirectMedia = true +func (tc *TelegramConnector) SetUseDirectMedia() { + tc.useDirectMedia = true } diff --git a/pkg/connector/handlematrix.go b/pkg/connector/handlematrix.go index de96a1d8..9cc4e014 100644 --- a/pkg/connector/handlematrix.go +++ b/pkg/connector/handlematrix.go @@ -97,7 +97,7 @@ func getMediaFilename(content *event.MessageEventContent) (filename string) { return filename } -func (t *TelegramClient) HandleMatrixViewingChat(ctx context.Context, msg *bridgev2.MatrixViewingChat) error { +func (tc *TelegramClient) HandleMatrixViewingChat(ctx context.Context, msg *bridgev2.MatrixViewingChat) error { if msg.Portal == nil { return nil } @@ -105,27 +105,27 @@ func (t *TelegramClient) HandleMatrixViewingChat(ctx context.Context, msg *bridg // TODO sync topic parent space meta := msg.Portal.Metadata.(*PortalMetadata) if (topicID == 0 && !meta.FullSynced) || meta.LastSync.Add(24*time.Hour).Before(time.Now()) { - t.userLogin.QueueRemoteEvent(&simplevent.ChatResync{ + tc.userLogin.QueueRemoteEvent(&simplevent.ChatResync{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventChatResync, PortalKey: msg.Portal.PortalKey, }, - GetChatInfoFunc: t.GetChatInfo, + GetChatInfoFunc: tc.GetChatInfo, }) } - err := t.maybePollForReactions(ctx, msg.Portal) + err := tc.maybePollForReactions(ctx, msg.Portal) if err != nil { return err } - err = t.pollSponsoredMessage(ctx, msg.Portal) + err = tc.pollSponsoredMessage(ctx, msg.Portal) if err != nil { return err } return nil } -func (t *TelegramClient) pollSponsoredMessage(ctx context.Context, portal *bridgev2.Portal) error { - if t.metadata.IsBot { +func (tc *TelegramClient) pollSponsoredMessage(ctx context.Context, portal *bridgev2.Portal) error { + if tc.metadata.IsBot { return nil } meta := portal.Metadata.(*PortalMetadata) @@ -140,18 +140,18 @@ func (t *TelegramClient) pollSponsoredMessage(ctx context.Context, portal *bridg if time.Since(meta.SponsoredMessagePollTS.Time) < 5*time.Minute { return nil } - latestMessage, err := t.main.Bridge.DB.Message.GetLastNonFakePartAtOrBeforeTime(ctx, portal.PortalKey, time.Now()) + latestMessage, err := tc.main.Bridge.DB.Message.GetLastNonFakePartAtOrBeforeTime(ctx, portal.PortalKey, time.Now()) if err != nil { return fmt.Errorf("failed to get latest message for portal: %w", err) } else if latestMessage != nil && latestMessage.ID == meta.LastMessageOnSponsorFetch { meta.SponsoredMessagePollTS = jsontime.UnixNow() return nil } - accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, id) + accessHash, err := tc.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, id) if err != nil { return err } - resp, err := t.client.API().MessagesGetSponsoredMessages(ctx, &tg.MessagesGetSponsoredMessagesRequest{ + resp, err := tc.client.API().MessagesGetSponsoredMessages(ctx, &tg.MessagesGetSponsoredMessagesRequest{ Peer: &tg.InputPeerChannel{ChannelID: id, AccessHash: accessHash}, }) if err != nil { @@ -179,7 +179,7 @@ func (t *TelegramClient) pollSponsoredMessage(ctx context.Context, portal *bridg msg = msgs.Messages[1] } meta.SponsoredMessageRandomID = msg.RandomID - content := t.parseBodyAndHTML(ctx, msg.Message, msg.Entities) + content := tc.parseBodyAndHTML(ctx, msg.Message, msg.Entities) content.MsgType = event.MsgNotice content.EnsureHasHTML() extra := map[string]any{ @@ -207,7 +207,7 @@ func (t *TelegramClient) pollSponsoredMessage(ctx context.Context, portal *bridg `%s: %s
%s
Sponsored message%s - %s
`, prefix, html.EscapeString(msg.Title), content.FormattedBody, fromStr, msg.URL, msg.ButtonText, ) - sendResp, err := t.main.Bridge.Bot.SendMessage(ctx, portal.MXID, event.EventMessage, &event.Content{ + sendResp, err := tc.main.Bridge.Bot.SendMessage(ctx, portal.MXID, event.EventMessage, &event.Content{ Raw: extra, Parsed: content, }, &bridgev2.MatrixSendExtra{Timestamp: time.Now()}) @@ -226,11 +226,11 @@ func (t *TelegramClient) pollSponsoredMessage(ctx context.Context, portal *bridg return nil } -func (t *TelegramClient) transferMediaToTelegram(ctx context.Context, content *event.MessageEventContent, sticker bool) (tg.InputMediaClass, error) { +func (tc *TelegramClient) transferMediaToTelegram(ctx context.Context, content *event.MessageEventContent, sticker bool) (tg.InputMediaClass, error) { var upload tg.InputFileClass var forceDocument bool filename := getMediaFilename(content) - err := t.main.Bridge.Bot.DownloadMediaToFile(ctx, content.URL, content.File, false, func(f *os.File) (err error) { + err := tc.main.Bridge.Bot.DownloadMediaToFile(ctx, content.URL, content.File, false, func(f *os.File) (err error) { uploadFilename := f.Name() if sticker && content.Info != nil && (content.Info.MimeType == "image/png" || content.Info.MimeType == "image/jpeg") { tempFile, err := os.CreateTemp("", "telegram-sticker-*.webp") @@ -270,7 +270,7 @@ func (t *TelegramClient) transferMediaToTelegram(ctx context.Context, content *e // We also have the image_as_file_pixels configuration threshold to // prevent Telegram from compressing the file. aspectRatio := float64(max(cfg.Height, cfg.Width)) / float64(min(cfg.Height, cfg.Width)) - forceDocument = cfg.Height*cfg.Width > t.main.Config.ImageAsFilePixels || + forceDocument = cfg.Height*cfg.Width > tc.main.Config.ImageAsFilePixels || info.Size() > int64(10*1024*1024) || aspectRatio > 20 || cfg.Height+cfg.Width > 10000 @@ -298,7 +298,7 @@ func (t *TelegramClient) transferMediaToTelegram(ctx context.Context, content *e content.Info.MimeType = "image/jpeg" } - upload, err = uploader.NewUploader(t.client.API()).FromPath(ctx, uploadFilename, filename) + upload, err = uploader.NewUploader(tc.client.API()).FromPath(ctx, uploadFilename, filename) return }) if err != nil { @@ -349,7 +349,7 @@ func (t *TelegramClient) transferMediaToTelegram(ctx context.Context, content *e }, nil } -func (t *TelegramClient) humaniseSendError(err error) bridgev2.MessageStatus { +func (tc *TelegramClient) humaniseSendError(err error) bridgev2.MessageStatus { status := bridgev2.WrapErrorInStatus(err). WithErrorReason(event.MessageStatusNetworkError). WithMessage(humanise.Error(err)) @@ -381,7 +381,7 @@ func (t *TelegramClient) humaniseSendError(err error) bridgev2.MessageStatus { WithStatus(event.MessageStatusFail) } -func (tg *TelegramConnector) GenerateTransactionID(userID id.UserID, roomID id.RoomID, eventType event.Type) networkid.RawTransactionID { +func (tc *TelegramConnector) GenerateTransactionID(userID id.UserID, roomID id.RoomID, eventType event.Type) networkid.RawTransactionID { return networkid.RawTransactionID(strconv.FormatInt(rand.Int64(), 10)) } @@ -394,17 +394,17 @@ func parseRandomID(txnID networkid.RawTransactionID) int64 { return rand.Int64() } -func (t *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2.MatrixMessage) (resp *bridgev2.MatrixMessageResponse, err error) { +func (tc *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2.MatrixMessage) (resp *bridgev2.MatrixMessageResponse, err error) { if msg.Portal.RoomType == database.RoomTypeSpace { return nil, fmt.Errorf("can't send messages to space portals") } // Handle Matrix events only after initial connection has been established to avoid deadlocking gotd - err = t.clientInitialized.Wait(ctx) + err = tc.clientInitialized.Wait(ctx) if err != nil { return nil, err } - peer, topicID, err := t.inputPeerForPortalID(ctx, msg.Portal.ID) + peer, topicID, err := tc.inputPeerForPortalID(ctx, msg.Portal.ID) if err != nil { return nil, err } @@ -418,7 +418,7 @@ func (t *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2. noWebpage := msg.Content.BeeperLinkPreviews != nil && len(msg.Content.BeeperLinkPreviews) == 0 - message, entities := matrixfmt.Parse(ctx, t.matrixParser, msg.Content, msg.Portal) + message, entities := matrixfmt.Parse(ctx, tc.matrixParser, msg.Content, msg.Portal) var replyTo tg.InputReplyToClass if msg.ReplyTo != nil { @@ -442,11 +442,11 @@ func (t *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2. var updates tg.UpdatesClass if msg.Event.Type == event.EventSticker { var media tg.InputMediaClass - media, err = t.transferMediaToTelegram(ctx, msg.Content, true) + media, err = tc.transferMediaToTelegram(ctx, msg.Content, true) if err != nil { return nil, err } - updates, err = t.client.API().MessagesSendMedia(ctx, &tg.MessagesSendMediaRequest{ + updates, err = tc.client.API().MessagesSendMedia(ctx, &tg.MessagesSendMediaRequest{ Peer: peer, Message: message, Entities: entities, @@ -457,7 +457,7 @@ func (t *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2. } else { switch msg.Content.MsgType { case event.MsgText, event.MsgNotice, event.MsgEmote: - updates, err = t.client.API().MessagesSendMessage(ctx, &tg.MessagesSendMessageRequest{ + updates, err = tc.client.API().MessagesSendMessage(ctx, &tg.MessagesSendMessageRequest{ Peer: peer, NoWebpage: noWebpage, Message: message, @@ -467,11 +467,11 @@ func (t *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2. }) case event.MsgImage, event.MsgFile, event.MsgAudio, event.MsgVideo: var media tg.InputMediaClass - media, err = t.transferMediaToTelegram(ctx, msg.Content, false) + media, err = tc.transferMediaToTelegram(ctx, msg.Content, false) if err != nil { return nil, err } - updates, err = t.client.API().MessagesSendMedia(ctx, &tg.MessagesSendMediaRequest{ + updates, err = tc.client.API().MessagesSendMedia(ctx, &tg.MessagesSendMediaRequest{ Peer: peer, Message: message, Entities: entities, @@ -491,7 +491,7 @@ func (t *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2. message = desc } } - updates, err = t.client.API().MessagesSendMedia(ctx, &tg.MessagesSendMediaRequest{ + updates, err = tc.client.API().MessagesSendMedia(ctx, &tg.MessagesSendMediaRequest{ Peer: peer, Message: message, Media: &tg.InputMediaGeoPoint{ @@ -506,7 +506,7 @@ func (t *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2. } if err != nil { log.Err(err).Msg("failed to send message to Telegram") - return nil, t.humaniseSendError(err) + return nil, tc.humaniseSendError(err) } hasher := sha256.New() @@ -581,7 +581,7 @@ func (t *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2. resp = &bridgev2.MatrixMessageResponse{ DB: &database.Message{ ID: messageID, - SenderID: t.userID, + SenderID: tc.userID, Timestamp: timestamp, Metadata: &MessageMetadata{ ContentHash: hash, @@ -593,7 +593,7 @@ func (t *TelegramClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2. return } -func (t *TelegramClient) HandleMatrixEdit(ctx context.Context, msg *bridgev2.MatrixEdit) error { +func (tc *TelegramClient) HandleMatrixEdit(ctx context.Context, msg *bridgev2.MatrixEdit) error { if msg.Portal.RoomType == database.RoomTypeSpace { return fmt.Errorf("can't send messages to space portals") } @@ -602,7 +602,7 @@ func (t *TelegramClient) HandleMatrixEdit(ctx context.Context, msg *bridgev2.Mat Str("handler", "matrix_edit"). Logger() - peer, _, err := t.inputPeerForPortalID(ctx, msg.Portal.ID) + peer, _, err := tc.inputPeerForPortalID(ctx, msg.Portal.ID) if err != nil { return err } @@ -612,7 +612,7 @@ func (t *TelegramClient) HandleMatrixEdit(ctx context.Context, msg *bridgev2.Mat return err } - message, entities := matrixfmt.Parse(ctx, t.matrixParser, msg.Content, msg.Portal) + message, entities := matrixfmt.Parse(ctx, tc.matrixParser, msg.Content, msg.Portal) var newContentURI id.ContentURIString req := tg.MessagesEditMessageRequest{ @@ -631,7 +631,7 @@ func (t *TelegramClient) HandleMatrixEdit(ctx context.Context, msg *bridgev2.Mat log.Info().Msg("media URI unchanged, skipping re-upload, just editing text") } else { log.Info().Msg("media URI changed, re-uploading media") - req.Media, err = t.transferMediaToTelegram(ctx, msg.Content, false) + req.Media, err = tc.transferMediaToTelegram(ctx, msg.Content, false) if err != nil { return err } @@ -639,9 +639,9 @@ func (t *TelegramClient) HandleMatrixEdit(ctx context.Context, msg *bridgev2.Mat } else if !msg.Content.MsgType.IsText() { return fmt.Errorf("editing message type %s is unsupported", msg.Content.MsgType) } - updates, err := t.client.API().MessagesEditMessage(ctx, &req) + updates, err := tc.client.API().MessagesEditMessage(ctx, &req) if err != nil { - return t.humaniseSendError(err) + return tc.humaniseSendError(err) } hasher := sha256.New() @@ -690,17 +690,17 @@ func (t *TelegramClient) HandleMatrixEdit(ctx context.Context, msg *bridgev2.Mat return nil } -func (t *TelegramClient) HandleMatrixMessageRemove(ctx context.Context, msg *bridgev2.MatrixMessageRemove) error { +func (tc *TelegramClient) HandleMatrixMessageRemove(ctx context.Context, msg *bridgev2.MatrixMessageRemove) error { if msg.Portal.RoomType == database.RoomTypeSpace { return fmt.Errorf("can't send messages to space portals") - } else if dbMsg, err := t.main.Bridge.DB.Message.GetPartByMXID(ctx, msg.TargetMessage.MXID); err != nil { + } else if dbMsg, err := tc.main.Bridge.DB.Message.GetPartByMXID(ctx, msg.TargetMessage.MXID); err != nil { return err } else if _, messageID, err := ids.ParseMessageID(dbMsg.ID); err != nil { return err - } else if peer, _, err := t.inputPeerForPortalID(ctx, msg.Portal.ID); err != nil { + } else if peer, _, err := tc.inputPeerForPortalID(ctx, msg.Portal.ID); err != nil { return err } else { - _, err := message.NewSender(t.client.API()). + _, err := message.NewSender(tc.client.API()). To(peer). Revoke(). Messages(ctx, messageID) @@ -708,7 +708,7 @@ func (t *TelegramClient) HandleMatrixMessageRemove(ctx context.Context, msg *bri } } -func (t *TelegramClient) PreHandleMatrixReaction(ctx context.Context, msg *bridgev2.MatrixReaction) (bridgev2.MatrixReactionPreResponse, error) { +func (tc *TelegramClient) PreHandleMatrixReaction(ctx context.Context, msg *bridgev2.MatrixReaction) (bridgev2.MatrixReactionPreResponse, error) { if msg.Portal.RoomType == database.RoomTypeSpace { return bridgev2.MatrixReactionPreResponse{}, fmt.Errorf("can't send messages to space portals") } @@ -720,7 +720,7 @@ func (t *TelegramClient) PreHandleMatrixReaction(ctx context.Context, msg *bridg var resp bridgev2.MatrixReactionPreResponse var maxReactions int - maxReactions, err := t.getReactionLimit(ctx, t.userID) + maxReactions, err := tc.getReactionLimit(ctx, tc.userID) if err != nil { return resp, err } @@ -728,7 +728,7 @@ func (t *TelegramClient) PreHandleMatrixReaction(ctx context.Context, msg *bridg keyNoVariation := variationselector.Remove(msg.Content.RelatesTo.Key) emojiID := ids.MakeEmojiIDFromEmoticon(msg.Content.RelatesTo.Key) if strings.HasPrefix(msg.Content.RelatesTo.Key, "mxc://") { - if file, err := t.main.Store.TelegramFile.GetByMXC(ctx, id.ContentURIString(msg.Content.RelatesTo.Key)); err != nil { + if file, err := tc.main.Store.TelegramFile.GetByMXC(ctx, id.ContentURIString(msg.Content.RelatesTo.Key)); err != nil { return resp, err } else if file == nil { return resp, fmt.Errorf("reaction MXC URI %s does not correspond with any known Telegram files", msg.Content.RelatesTo.Key) @@ -737,17 +737,17 @@ func (t *TelegramClient) PreHandleMatrixReaction(ctx context.Context, msg *bridg } else { emojiID = ids.MakeEmojiIDFromDocumentID(documentID) } - } else if t.main.Config.AlwaysCustomEmojiReaction { + } else if tc.main.Config.AlwaysCustomEmojiReaction { // Always use the unicodemoji reaction if available if documentID, ok := emojis.GetEmojiDocumentID(keyNoVariation); ok { log.Debug().Msg("Using custom emoji reaction") emojiID = ids.MakeEmojiIDFromDocumentID(documentID) } - } else if availableReactions, err := t.getAvailableReactions(ctx); err != nil { + } else if availableReactions, err := tc.getAvailableReactions(ctx); err != nil { return resp, fmt.Errorf("failed to get available reactions: %w", err) } else if _, ok := availableReactions[keyNoVariation]; ok { log.Debug().Msg("Not using custom emoji reaction since the emoji is available") - } else if documentID, ok := emojis.GetEmojiDocumentID(keyNoVariation); ok && !t.metadata.IsBot { + } else if documentID, ok := emojis.GetEmojiDocumentID(keyNoVariation); ok && !tc.metadata.IsBot { log.Debug().Msg("Using custom emoji reaction") emojiID = ids.MakeEmojiIDFromDocumentID(documentID) } @@ -755,14 +755,14 @@ func (t *TelegramClient) PreHandleMatrixReaction(ctx context.Context, msg *bridg log.Debug().Str("emoji_id", string(emojiID)).Msg("Pre-handled reaction") return bridgev2.MatrixReactionPreResponse{ - SenderID: t.userID, + SenderID: tc.userID, EmojiID: emojiID, Emoji: variationselector.FullyQualify(msg.Content.RelatesTo.Key), MaxReactions: maxReactions, }, nil } -func (t *TelegramClient) appendEmojiID(reactionList []tg.ReactionClass, emojiID networkid.EmojiID) ([]tg.ReactionClass, error) { +func (tc *TelegramClient) appendEmojiID(reactionList []tg.ReactionClass, emojiID networkid.EmojiID) ([]tg.ReactionClass, error) { if documentID, emoticon, err := ids.ParseEmojiID(emojiID); err != nil { return nil, err } else if documentID > 0 { @@ -772,8 +772,8 @@ func (t *TelegramClient) appendEmojiID(reactionList []tg.ReactionClass, emojiID } } -func (t *TelegramClient) HandleMatrixReaction(ctx context.Context, msg *bridgev2.MatrixReaction) (reaction *database.Reaction, err error) { - peer, _, err := t.inputPeerForPortalID(ctx, msg.Portal.ID) +func (tc *TelegramClient) HandleMatrixReaction(ctx context.Context, msg *bridgev2.MatrixReaction) (reaction *database.Reaction, err error) { + peer, _, err := tc.inputPeerForPortalID(ctx, msg.Portal.ID) if err != nil { return nil, err } @@ -784,17 +784,17 @@ func (t *TelegramClient) HandleMatrixReaction(ctx context.Context, msg *bridgev2 var newReactions []tg.ReactionClass for _, existing := range msg.ExistingReactionsToKeep { - newReactions, err = t.appendEmojiID(newReactions, existing.EmojiID) + newReactions, err = tc.appendEmojiID(newReactions, existing.EmojiID) if err != nil { return nil, err } } - newReactions, err = t.appendEmojiID(newReactions, msg.PreHandleResp.EmojiID) + newReactions, err = tc.appendEmojiID(newReactions, msg.PreHandleResp.EmojiID) if err != nil { return nil, err } - _, err = t.client.API().MessagesSendReaction(ctx, &tg.MessagesSendReactionRequest{ + _, err = tc.client.API().MessagesSendReaction(ctx, &tg.MessagesSendReactionRequest{ Peer: peer, AddToRecent: true, MsgID: targetMessageID, @@ -809,27 +809,27 @@ func (t *TelegramClient) HandleMatrixReaction(ctx context.Context, msg *bridgev2 return &database.Reaction{}, err } -func (t *TelegramClient) HandleMatrixReactionRemove(ctx context.Context, msg *bridgev2.MatrixReactionRemove) error { +func (tc *TelegramClient) HandleMatrixReactionRemove(ctx context.Context, msg *bridgev2.MatrixReactionRemove) error { if msg.Portal.RoomType == database.RoomTypeSpace { return fmt.Errorf("can't send messages to space portals") } - peer, _, err := t.inputPeerForPortalID(ctx, msg.Portal.ID) + peer, _, err := tc.inputPeerForPortalID(ctx, msg.Portal.ID) if err != nil { return err } var newReactions []tg.ReactionClass - if maxReactions, err := t.getReactionLimit(ctx, t.userID); err != nil { + if maxReactions, err := tc.getReactionLimit(ctx, tc.userID); err != nil { return err } else if maxReactions > 1 { - existing, err := t.main.Bridge.DB.Reaction.GetAllToMessageBySender(ctx, msg.Portal.Receiver, msg.TargetReaction.MessageID, msg.TargetReaction.SenderID) + existing, err := tc.main.Bridge.DB.Reaction.GetAllToMessageBySender(ctx, msg.Portal.Receiver, msg.TargetReaction.MessageID, msg.TargetReaction.SenderID) if err != nil { return err } for _, existing := range existing { if msg.TargetReaction.EmojiID != existing.EmojiID { - newReactions, err = t.appendEmojiID(newReactions, existing.EmojiID) + newReactions, err = tc.appendEmojiID(newReactions, existing.EmojiID) if err != nil { return err } @@ -841,7 +841,7 @@ func (t *TelegramClient) HandleMatrixReactionRemove(ctx context.Context, msg *br if err != nil { return err } - _, err = t.client.API().MessagesSendReaction(ctx, &tg.MessagesSendReactionRequest{ + _, err = tc.client.API().MessagesSendReaction(ctx, &tg.MessagesSendReactionRequest{ Peer: peer, AddToRecent: true, MsgID: messageID, @@ -850,7 +850,7 @@ func (t *TelegramClient) HandleMatrixReactionRemove(ctx context.Context, msg *br return err } -func (t *TelegramClient) HandleMatrixReadReceipt(ctx context.Context, msg *bridgev2.MatrixReadReceipt) error { +func (tc *TelegramClient) HandleMatrixReadReceipt(ctx context.Context, msg *bridgev2.MatrixReadReceipt) error { if msg.Portal.RoomType == database.RoomTypeSpace { return nil } @@ -866,7 +866,7 @@ func (t *TelegramClient) HandleMatrixReadReceipt(ctx context.Context, msg *bridg if msg.Portal.Metadata.(*PortalMetadata).IsForumGeneral { topicID = 1 } - inputPeer, _, parseErr := t.inputPeerForPortalID(ctx, msg.Portal.ID) + inputPeer, _, parseErr := tc.inputPeerForPortalID(ctx, msg.Portal.ID) if parseErr != nil { return parseErr } @@ -874,7 +874,7 @@ func (t *TelegramClient) HandleMatrixReadReceipt(ctx context.Context, msg *bridg var readMentionsErr, readReactionsErr, readMessagesErr error var wg sync.WaitGroup - isBot := t.metadata.IsBot + isBot := tc.metadata.IsBot // Read mentions wg.Add(1) @@ -883,7 +883,7 @@ func (t *TelegramClient) HandleMatrixReadReceipt(ctx context.Context, msg *bridg if isBot { return } - _, readMentionsErr = t.client.API().MessagesReadMentions(ctx, &tg.MessagesReadMentionsRequest{ + _, readMentionsErr = tc.client.API().MessagesReadMentions(ctx, &tg.MessagesReadMentionsRequest{ Peer: inputPeer, TopMsgID: topicID, }) @@ -896,7 +896,7 @@ func (t *TelegramClient) HandleMatrixReadReceipt(ctx context.Context, msg *bridg if isBot { return } - _, readMentionsErr = t.client.API().MessagesReadReactions(ctx, &tg.MessagesReadReactionsRequest{ + _, readMentionsErr = tc.client.API().MessagesReadReactions(ctx, &tg.MessagesReadReactionsRequest{ Peer: inputPeer, TopMsgID: topicID, }) @@ -913,7 +913,7 @@ func (t *TelegramClient) HandleMatrixReadReceipt(ctx context.Context, msg *bridg message := msg.ExactMessage if message == nil { - message, readMessagesErr = t.main.Bridge.DB.Message.GetLastPartAtOrBeforeTime(ctx, msg.Portal.PortalKey, time.Now()) + message, readMessagesErr = tc.main.Bridge.DB.Message.GetLastPartAtOrBeforeTime(ctx, msg.Portal.PortalKey, time.Now()) if readMessagesErr != nil { return } else if message == nil { @@ -929,29 +929,29 @@ func (t *TelegramClient) HandleMatrixReadReceipt(ctx context.Context, msg *bridg switch peerType { case ids.PeerTypeUser, ids.PeerTypeChat: - _, readMessagesErr = t.client.API().MessagesReadHistory(ctx, &tg.MessagesReadHistoryRequest{ + _, readMessagesErr = tc.client.API().MessagesReadHistory(ctx, &tg.MessagesReadHistoryRequest{ Peer: inputPeer, MaxID: maxID, }) case ids.PeerTypeChannel: var accessHash int64 - accessHash, readMessagesErr = t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, portalID) + accessHash, readMessagesErr = tc.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, portalID) if readMessagesErr != nil { return } - _, readMessagesErr = t.client.API().ChannelsReadHistory(ctx, &tg.ChannelsReadHistoryRequest{ + _, readMessagesErr = tc.client.API().ChannelsReadHistory(ctx, &tg.ChannelsReadHistoryRequest{ Channel: &tg.InputChannel{ChannelID: portalID, AccessHash: accessHash}, MaxID: maxID, }) meta := msg.Portal.Metadata.(*PortalMetadata) randomID := meta.SponsoredMessageRandomID - if !t.metadata.IsBot && + if !tc.metadata.IsBot && randomID != nil && time.Since(meta.SponsoredMessagePollTS.Time) < 15*time.Minute && (meta.SponsoredMessageEventID == msg.EventID || msg.Receipt.Timestamp.After(meta.SponsoredMessagePollTS.Time)) && - meta.sponsoredMessageSeen.Add(t.telegramUserID) { - _, viewSponsoredErr := t.client.API().MessagesViewSponsoredMessage(ctx, randomID) + meta.sponsoredMessageSeen.Add(tc.telegramUserID) { + _, viewSponsoredErr := tc.client.API().MessagesViewSponsoredMessage(ctx, randomID) if viewSponsoredErr != nil { log.Err(viewSponsoredErr).Msg("Failed to mark sponsored message as viewed after read receipt") } else { @@ -967,11 +967,11 @@ func (t *TelegramClient) HandleMatrixReadReceipt(ctx context.Context, msg *bridg // Poll for reactions (non-blocking to avoid deadlock when portal event buffer is disabled) go func() { - err := t.maybePollForReactions(ctx, msg.Portal) + err := tc.maybePollForReactions(ctx, msg.Portal) if err != nil { log.Err(err).Msg("failed to poll for reactions after read receipt") } - err = t.pollSponsoredMessage(ctx, msg.Portal) + err = tc.pollSponsoredMessage(ctx, msg.Portal) if err != nil { log.Err(err).Msg("failed to poll for sponsored message after read receipt") } @@ -979,12 +979,12 @@ func (t *TelegramClient) HandleMatrixReadReceipt(ctx context.Context, msg *bridg if peerType == ids.PeerTypeChannel && !msg.Portal.Metadata.(*PortalMetadata).FullSynced { log.Debug().Msg("Scheduling chat resync on read receipt because channel has never got a full sync") - go t.userLogin.QueueRemoteEvent(&simplevent.ChatResync{ + go tc.userLogin.QueueRemoteEvent(&simplevent.ChatResync{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventChatResync, PortalKey: msg.Portal.PortalKey, }, - GetChatInfoFunc: t.GetChatInfo, + GetChatInfoFunc: tc.GetChatInfo, }) } @@ -992,11 +992,11 @@ func (t *TelegramClient) HandleMatrixReadReceipt(ctx context.Context, msg *bridg return errors.Join(readMentionsErr, readReactionsErr, readMessagesErr) } -func (t *TelegramClient) HandleMatrixTyping(ctx context.Context, msg *bridgev2.MatrixTyping) error { +func (tc *TelegramClient) HandleMatrixTyping(ctx context.Context, msg *bridgev2.MatrixTyping) error { if msg.Portal.RoomType == database.RoomTypeSpace { return nil } - inputPeer, topicID, err := t.inputPeerForPortalID(ctx, msg.Portal.ID) + inputPeer, topicID, err := tc.inputPeerForPortalID(ctx, msg.Portal.ID) if err != nil { return err } @@ -1016,7 +1016,7 @@ func (t *TelegramClient) HandleMatrixTyping(ctx context.Context, msg *bridgev2.M if !msg.IsTyping { action = &tg.SendMessageCancelAction{} } - _, err = t.client.API().MessagesSetTyping(ctx, &tg.MessagesSetTypingRequest{ + _, err = tc.client.API().MessagesSetTyping(ctx, &tg.MessagesSetTypingRequest{ Peer: inputPeer, TopMsgID: topicID, Action: action, @@ -1024,14 +1024,14 @@ func (t *TelegramClient) HandleMatrixTyping(ctx context.Context, msg *bridgev2.M return err } -func (t *TelegramClient) HandleMatrixDisappearingTimer(ctx context.Context, msg *bridgev2.MatrixDisappearingTimer) (bool, error) { - inputPeer, topicID, err := t.inputPeerForPortalID(ctx, msg.Portal.ID) +func (tc *TelegramClient) HandleMatrixDisappearingTimer(ctx context.Context, msg *bridgev2.MatrixDisappearingTimer) (bool, error) { + inputPeer, topicID, err := tc.inputPeerForPortalID(ctx, msg.Portal.ID) if err != nil { return false, err } else if topicID > 0 { return false, fmt.Errorf("topics can't have their own disappearing timer") } - _, err = t.client.API().MessagesSetHistoryTTL(ctx, &tg.MessagesSetHistoryTTLRequest{ + _, err = tc.client.API().MessagesSetHistoryTTL(ctx, &tg.MessagesSetHistoryTTLRequest{ Peer: inputPeer, Period: int(msg.Content.Timer.Seconds()), }) @@ -1044,8 +1044,8 @@ func (t *TelegramClient) HandleMatrixDisappearingTimer(ctx context.Context, msg return err == nil, err } -func (t *TelegramClient) HandleMute(ctx context.Context, msg *bridgev2.MatrixMute) error { - inputPeer, topicID, err := t.inputPeerForPortalID(ctx, msg.Portal.ID) +func (tc *TelegramClient) HandleMute(ctx context.Context, msg *bridgev2.MatrixMute) error { + inputPeer, topicID, err := tc.inputPeerForPortalID(ctx, msg.Portal.ID) if err != nil { return err } @@ -1061,40 +1061,40 @@ func (t *TelegramClient) HandleMute(ctx context.Context, msg *bridgev2.MatrixMut peer = &tg.InputNotifyPeer{Peer: inputPeer} } - _, err = t.client.API().AccountUpdateNotifySettings(ctx, &tg.AccountUpdateNotifySettingsRequest{ + _, err = tc.client.API().AccountUpdateNotifySettings(ctx, &tg.AccountUpdateNotifySettingsRequest{ Peer: peer, Settings: settings, }) return err } -func (t *TelegramClient) HandleRoomTag(ctx context.Context, msg *bridgev2.MatrixRoomTag) error { - inputPeer, topicID, err := t.inputPeerForPortalID(ctx, msg.Portal.ID) +func (tc *TelegramClient) HandleRoomTag(ctx context.Context, msg *bridgev2.MatrixRoomTag) error { + inputPeer, topicID, err := tc.inputPeerForPortalID(ctx, msg.Portal.ID) if err != nil { return err } else if topicID > 0 { return fmt.Errorf("topics can't be pinned for yourself") } - _, err = t.client.API().MessagesToggleDialogPin(ctx, &tg.MessagesToggleDialogPinRequest{ + _, err = tc.client.API().MessagesToggleDialogPin(ctx, &tg.MessagesToggleDialogPinRequest{ Pinned: slices.Contains(maps.Keys(msg.Content.Tags), event.RoomTagFavourite), Peer: &tg.InputDialogPeer{Peer: inputPeer}, }) return err } -func (t *TelegramClient) HandleMatrixDeleteChat(ctx context.Context, chat *bridgev2.MatrixDeleteChat) error { +func (tc *TelegramClient) HandleMatrixDeleteChat(ctx context.Context, chat *bridgev2.MatrixDeleteChat) error { peerType, id, topicID, err := ids.ParsePortalID(chat.Portal.ID) if err != nil { return err } switch peerType { case ids.PeerTypeUser: - accessHash, err := t.ScopedStore.GetAccessHash(ctx, peerType, id) + accessHash, err := tc.ScopedStore.GetAccessHash(ctx, peerType, id) if err != nil { return err } - _, err = t.client.API().MessagesDeleteHistory(ctx, &tg.MessagesDeleteHistoryRequest{ + _, err = tc.client.API().MessagesDeleteHistory(ctx, &tg.MessagesDeleteHistoryRequest{ Peer: &tg.InputPeerUser{UserID: id, AccessHash: accessHash}, JustClear: !chat.Content.DeleteForEveryone, Revoke: chat.Content.DeleteForEveryone, @@ -1107,7 +1107,7 @@ func (t *TelegramClient) HandleMatrixDeleteChat(ctx context.Context, chat *bridg if !chat.Content.DeleteForEveryone { return fmt.Errorf("chats can only be deleted for everyone or left") } - result, err := t.client.API().MessagesDeleteChat(ctx, id) + result, err := tc.client.API().MessagesDeleteChat(ctx, id) if err != nil { return err } @@ -1119,12 +1119,12 @@ func (t *TelegramClient) HandleMatrixDeleteChat(ctx context.Context, chat *bridg if !chat.Content.DeleteForEveryone { return fmt.Errorf("channels can only be deleted for everyone or left") } - accessHash, err := t.ScopedStore.GetAccessHash(ctx, peerType, id) + accessHash, err := tc.ScopedStore.GetAccessHash(ctx, peerType, id) if err != nil { return err } if topicID > 0 { - _, err = t.client.API().MessagesDeleteTopicHistory(ctx, &tg.MessagesDeleteTopicHistoryRequest{ + _, err = tc.client.API().MessagesDeleteTopicHistory(ctx, &tg.MessagesDeleteTopicHistoryRequest{ Peer: &tg.InputPeerChannel{ ChannelID: id, AccessHash: accessHash, @@ -1132,7 +1132,7 @@ func (t *TelegramClient) HandleMatrixDeleteChat(ctx context.Context, chat *bridg TopMsgID: topicID, }) } else { - _, err = t.client.API().ChannelsDeleteChannel(ctx, &tg.InputChannel{ + _, err = tc.client.API().ChannelsDeleteChannel(ctx, &tg.InputChannel{ ChannelID: id, AccessHash: accessHash, }) @@ -1147,7 +1147,7 @@ func (t *TelegramClient) HandleMatrixDeleteChat(ctx context.Context, chat *bridg return nil } -func (t *TelegramClient) HandleMatrixRoomName(ctx context.Context, msg *bridgev2.MatrixRoomName) (bool, error) { +func (tc *TelegramClient) HandleMatrixRoomName(ctx context.Context, msg *bridgev2.MatrixRoomName) (bool, error) { peerType, id, topicID, err := ids.ParsePortalID(msg.Portal.ID) if err != nil { return false, err @@ -1155,7 +1155,7 @@ func (t *TelegramClient) HandleMatrixRoomName(ctx context.Context, msg *bridgev2 switch peerType { case ids.PeerTypeChat: - _, err = t.client.API().MessagesEditChatTitle(ctx, &tg.MessagesEditChatTitleRequest{ + _, err = tc.client.API().MessagesEditChatTitle(ctx, &tg.MessagesEditChatTitleRequest{ ChatID: id, Title: msg.Content.Name, }) @@ -1164,12 +1164,12 @@ func (t *TelegramClient) HandleMatrixRoomName(ctx context.Context, msg *bridgev2 } return true, nil case ids.PeerTypeChannel: - accessHash, err := t.ScopedStore.GetAccessHash(ctx, peerType, id) + accessHash, err := tc.ScopedStore.GetAccessHash(ctx, peerType, id) if err != nil { return false, err } if topicID > 0 { - _, err = t.client.API().MessagesEditForumTopic(ctx, &tg.MessagesEditForumTopicRequest{ + _, err = tc.client.API().MessagesEditForumTopic(ctx, &tg.MessagesEditForumTopicRequest{ Peer: &tg.InputPeerChannel{ ChannelID: id, AccessHash: accessHash, @@ -1178,7 +1178,7 @@ func (t *TelegramClient) HandleMatrixRoomName(ctx context.Context, msg *bridgev2 Title: msg.Content.Name, }) } else { - _, err = t.client.API().ChannelsEditTitle(ctx, &tg.ChannelsEditTitleRequest{ + _, err = tc.client.API().ChannelsEditTitle(ctx, &tg.ChannelsEditTitleRequest{ Channel: &tg.InputChannel{ ChannelID: id, AccessHash: accessHash, @@ -1195,7 +1195,7 @@ func (t *TelegramClient) HandleMatrixRoomName(ctx context.Context, msg *bridgev2 } } -func (t *TelegramClient) HandleMatrixRoomAvatar(ctx context.Context, msg *bridgev2.MatrixRoomAvatar) (bool, error) { +func (tc *TelegramClient) HandleMatrixRoomAvatar(ctx context.Context, msg *bridgev2.MatrixRoomAvatar) (bool, error) { peerType, id, topicID, err := ids.ParsePortalID(msg.Portal.ID) if err != nil { return false, err @@ -1211,11 +1211,11 @@ func (t *TelegramClient) HandleMatrixRoomAvatar(ctx context.Context, msg *bridge if msg.Content.URL == "" { photo = &tg.InputChatPhotoEmpty{} } else { - data, err := t.main.Bridge.Bot.DownloadMedia(ctx, msg.Content.URL, nil) + data, err := tc.main.Bridge.Bot.DownloadMedia(ctx, msg.Content.URL, nil) if err != nil { return false, fmt.Errorf("failed to download avatar: %w", err) } - upload, err := uploader.NewUploader(t.client.API()).FromBytes(ctx, "avatar.jpg", data) + upload, err := uploader.NewUploader(tc.client.API()).FromBytes(ctx, "avatar.jpg", data) if err != nil { return false, fmt.Errorf("failed to upload avatar: %w", err) } @@ -1224,7 +1224,7 @@ func (t *TelegramClient) HandleMatrixRoomAvatar(ctx context.Context, msg *bridge switch peerType { case ids.PeerTypeChat: - _, err = t.client.API().MessagesEditChatPhoto(ctx, &tg.MessagesEditChatPhotoRequest{ + _, err = tc.client.API().MessagesEditChatPhoto(ctx, &tg.MessagesEditChatPhotoRequest{ ChatID: id, Photo: photo, }) @@ -1234,11 +1234,11 @@ func (t *TelegramClient) HandleMatrixRoomAvatar(ctx context.Context, msg *bridge // TODO update portal metadata return true, nil case ids.PeerTypeChannel: - accessHash, err := t.ScopedStore.GetAccessHash(ctx, peerType, id) + accessHash, err := tc.ScopedStore.GetAccessHash(ctx, peerType, id) if err != nil { return false, err } - _, err = t.client.API().ChannelsEditPhoto(ctx, &tg.ChannelsEditPhotoRequest{ + _, err = tc.client.API().ChannelsEditPhoto(ctx, &tg.ChannelsEditPhotoRequest{ Channel: &tg.InputChannel{ ChannelID: id, AccessHash: accessHash, diff --git a/pkg/connector/handletelegram.go b/pkg/connector/handletelegram.go index 95800b60..62e71f2b 100644 --- a/pkg/connector/handletelegram.go +++ b/pkg/connector/handletelegram.go @@ -54,23 +54,23 @@ type IGetMessages interface { GetMessages() []int } -func (t *TelegramClient) selfLeaveChat(ctx context.Context, portalKey networkid.PortalKey, reason error) error { +func (tc *TelegramClient) selfLeaveChat(ctx context.Context, portalKey networkid.PortalKey, reason error) error { peerType, id, _, err := ids.ParsePortalID(portalKey.ID) if err != nil { return err } if peerType == ids.PeerTypeChannel { - t.updatesManager.RemoveChannel(id, reason) - topics, err := t.main.Store.Topic.GetAll(ctx, id) + tc.updatesManager.RemoveChannel(id, reason) + topics, err := tc.main.Store.Topic.GetAll(ctx, id) if err != nil { return err } for _, topicID := range topics { - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatDelete{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatDelete{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventChatDelete, - PortalKey: t.makePortalKeyFromID(peerType, id, topicID), - Sender: t.mySender(), + PortalKey: tc.makePortalKeyFromID(peerType, id, topicID), + Sender: tc.mySender(), LogContext: func(c zerolog.Context) zerolog.Context { return c.AnErr("self_leave_reason", reason) }, @@ -82,11 +82,11 @@ func (t *TelegramClient) selfLeaveChat(ctx context.Context, portalKey networkid. } } } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatDelete{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatDelete{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventChatDelete, PortalKey: portalKey, - Sender: t.mySender(), + Sender: tc.mySender(), LogContext: func(c zerolog.Context) zerolog.Context { return c.AnErr("self_leave_reason", reason) }, @@ -98,11 +98,11 @@ func (t *TelegramClient) selfLeaveChat(ctx context.Context, portalKey networkid. } if peerType == ids.PeerTypeChannel { // This is a no-op if there's no space portal - res = t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatDelete{ + res = tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatDelete{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventChatDelete, - PortalKey: t.makePortalKeyFromID(peerType, id, ids.TopicIDSpaceRoom), - Sender: t.mySender(), + PortalKey: tc.makePortalKeyFromID(peerType, id, ids.TopicIDSpaceRoom), + Sender: tc.mySender(), LogContext: func(c zerolog.Context) zerolog.Context { return c.AnErr("self_leave_reason", reason) }, @@ -116,35 +116,35 @@ func (t *TelegramClient) selfLeaveChat(ctx context.Context, portalKey networkid. return nil } -func (t *TelegramClient) onNotChannelMember(ctx context.Context, channelID int64) error { - return t.selfLeaveChat(ctx, t.makePortalKeyFromID(ids.PeerTypeChannel, channelID, 0), fmt.Errorf("startup channel member check failed")) +func (tc *TelegramClient) onNotChannelMember(ctx context.Context, channelID int64) error { + return tc.selfLeaveChat(ctx, tc.makePortalKeyFromID(ids.PeerTypeChannel, channelID, 0), fmt.Errorf("startup channel member check failed")) } -func (t *TelegramClient) onUpdateChannel(ctx context.Context, e tg.Entities, update *tg.UpdateChannel) error { +func (tc *TelegramClient) onUpdateChannel(ctx context.Context, e tg.Entities, update *tg.UpdateChannel) error { log := zerolog.Ctx(ctx).With(). Str("handler", "on_update_channel"). Int64("channel_id", update.ChannelID). Logger() // TODO resync topic portals? - portalKey := t.makePortalKeyFromID(ids.PeerTypeChannel, update.ChannelID, 0) + portalKey := tc.makePortalKeyFromID(ids.PeerTypeChannel, update.ChannelID, 0) // TODO is using the info in entities safe? channel, ok := e.Channels[update.ChannelID] if !ok { log.Debug().Msg("Fetching channel due to UpdateChannel event") - chats, err := APICallWithOnlyChatUpdates(ctx, t, func() (tg.MessagesChatsClass, error) { - if accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, update.ChannelID); err != nil { + chats, err := APICallWithOnlyChatUpdates(ctx, tc, func() (tg.MessagesChatsClass, error) { + if accessHash, err := tc.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, update.ChannelID); err != nil { return nil, err } else { - return t.client.API().ChannelsGetChannels(ctx, []tg.InputChannelClass{ + return tc.client.API().ChannelsGetChannels(ctx, []tg.InputChannelClass{ &tg.InputChannel{ChannelID: update.ChannelID, AccessHash: accessHash}, }) } }) if err != nil { if tgerr.Is(err, tg.ErrChannelInvalid, tg.ErrChannelPrivate) { - return t.selfLeaveChat(ctx, portalKey, fmt.Errorf("error fetching after UpdateChannel: %w", err)) + return tc.selfLeaveChat(ctx, portalKey, fmt.Errorf("error fetching after UpdateChannel: %w", err)) } log.Err(err).Msg("Failed to get channel info after UpdateChannel event") return nil @@ -153,14 +153,14 @@ func (t *TelegramClient) onUpdateChannel(ctx context.Context, e tg.Entities, upd return nil } else if channel, ok = chats.GetChats()[0].(*tg.Channel); !ok { log.Error().Type("chat_type", chats.GetChats()[0]).Msg("Expected channel, got something else. Leaving the channel.") - return t.selfLeaveChat(ctx, portalKey, fmt.Errorf("channel not returned in getChannels after UpdateChannel")) + return tc.selfLeaveChat(ctx, portalKey, fmt.Errorf("channel not returned in getChannels after UpdateChannel")) } } if channel.Left { log.Debug().Msg("Update was for a left channel. Leaving the channel.") - return t.selfLeaveChat(ctx, portalKey, fmt.Errorf("channel has left=true after UpdateChannel")) + return tc.selfLeaveChat(ctx, portalKey, fmt.Errorf("channel has left=true after UpdateChannel")) } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatResync{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatResync{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventChatResync, PortalKey: portalKey, @@ -170,12 +170,12 @@ func (t *TelegramClient) onUpdateChannel(ctx context.Context, e tg.Entities, upd }, }, GetChatInfoFunc: func(ctx context.Context, portal *bridgev2.Portal) (*bridgev2.ChatInfo, error) { - chatInfo, mfm, err := t.wrapChatInfo(portal.ID, channel) + chatInfo, mfm, err := tc.wrapChatInfo(portal.ID, channel) if err != nil { return nil, err } if portal.MXID == "" { - err = t.fillChannelMembers(ctx, mfm, chatInfo.Members) + err = tc.fillChannelMembers(ctx, mfm, chatInfo.Members) if err != nil { return nil, err } @@ -186,7 +186,7 @@ func (t *TelegramClient) onUpdateChannel(ctx context.Context, e tg.Entities, upd return resultToError(res) } -func (t *TelegramClient) onUpdateNewMessage(ctx context.Context, entities tg.Entities, update IGetMessage) error { +func (tc *TelegramClient) onUpdateNewMessage(ctx context.Context, entities tg.Entities, update IGetMessage) error { log := *zerolog.Ctx(ctx) switch msg := update.GetMessage().(type) { case *tg.Message: @@ -208,7 +208,7 @@ func (t *TelegramClient) onUpdateNewMessage(ctx context.Context, entities tg.Ent } } - sender := t.getEventSender(msg, isBroadcastChannel) + sender := tc.getEventSender(msg, isBroadcastChannel) if media, ok := msg.GetMedia(); ok && media.TypeID() == tg.MessageMediaContactTypeID { contact := media.(*tg.MessageMediaContact) @@ -216,8 +216,8 @@ func (t *TelegramClient) onUpdateNewMessage(ctx context.Context, entities tg.Ent log.Info().Int64("user_id", contact.UserID).Msg("received contact") } - topicID := t.getTopicID(ctx, msg.PeerID, msg.ReplyTo) - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Message[*tg.Message]{ + topicID := tc.getTopicID(ctx, msg.PeerID, msg.ReplyTo) + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Message[*tg.Message]{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventMessage, LogContext: func(c zerolog.Context) zerolog.Context { @@ -229,23 +229,23 @@ func (t *TelegramClient) onUpdateNewMessage(ctx context.Context, entities tg.Ent Stringer("peer_id", msg.PeerID) }, Sender: sender, - PortalKey: t.makePortalKeyFromPeer(msg.PeerID, topicID), + PortalKey: tc.makePortalKeyFromPeer(msg.PeerID, topicID), CreatePortal: true, Timestamp: time.Unix(int64(msg.Date), 0), StreamOrder: int64(msg.GetID()), }, ID: ids.GetMessageIDFromMessage(msg), Data: msg, - ConvertMessageFunc: t.convertToMatrix, + ConvertMessageFunc: tc.convertToMatrix, }) if err := resultToError(res); err != nil { return err } - return t.handleTelegramReactions(ctx, msg.PeerID, topicID, msg.ID, msg.Reactions) + return tc.handleTelegramReactions(ctx, msg.PeerID, topicID, msg.ID, msg.Reactions) case *tg.MessageService: - return t.handleServiceMessage(ctx, msg) + return tc.handleServiceMessage(ctx, msg) default: log.Warn(). @@ -255,11 +255,11 @@ func (t *TelegramClient) onUpdateNewMessage(ctx context.Context, entities tg.Ent } } -func (t *TelegramClient) getTopicID(ctx context.Context, peerID tg.PeerClass, rawReplyTo tg.MessageReplyHeaderClass) int { +func (tc *TelegramClient) getTopicID(ctx context.Context, peerID tg.PeerClass, rawReplyTo tg.MessageReplyHeaderClass) int { topicID := rawGetTopicID(rawReplyTo) if topicID != 0 { channelPeer, _ := peerID.(*tg.PeerChannel) - err := t.main.Store.Topic.Add(ctx, channelPeer.GetChannelID(), topicID) + err := tc.main.Store.Topic.Add(ctx, channelPeer.GetChannelID(), topicID) if err != nil { zerolog.Ctx(ctx).Err(err).Msg("Failed to save topic ID") } @@ -280,12 +280,12 @@ func rawGetTopicID(rawReplyTo tg.MessageReplyHeaderClass) int { return 0 } -func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.MessageService) error { +func (tc *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.MessageService) error { log := zerolog.Ctx(ctx) - sender := t.getEventSender(msg, false) + sender := tc.getEventSender(msg, false) eventMeta := simplevent.EventMeta{ - PortalKey: t.makePortalKeyFromPeer(msg.PeerID, t.getTopicID(ctx, msg.PeerID, msg.ReplyTo)), + PortalKey: tc.makePortalKeyFromPeer(msg.PeerID, tc.getTopicID(ctx, msg.PeerID, msg.ReplyTo)), Sender: sender, Timestamp: time.Unix(int64(msg.Date), 0), LogContext: func(c zerolog.Context) zerolog.Context { @@ -301,7 +301,7 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa } switch action := msg.Action.(type) { case *tg.MessageActionChatEditTitle: - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatInfoChange{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventChatInfoChange), ChatInfoChange: &bridgev2.ChatInfoChange{ChatInfo: &bridgev2.ChatInfo{Name: &action.Title}}, }) @@ -309,18 +309,18 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa case *tg.MessageActionChatEditPhoto: switch peer := msg.PeerID.(type) { case *tg.PeerChat: - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatInfoChange{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventChatInfoChange), ChatInfoChange: &bridgev2.ChatInfoChange{ChatInfo: &bridgev2.ChatInfo{ - Avatar: t.avatarFromPhoto(ctx, ids.PeerTypeChat, peer.ChatID, action.Photo), + Avatar: tc.avatarFromPhoto(ctx, ids.PeerTypeChat, peer.ChatID, action.Photo), }}, }) return resultToError(res) case *tg.PeerChannel: - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatInfoChange{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventChatInfoChange), ChatInfoChange: &bridgev2.ChatInfoChange{ChatInfo: &bridgev2.ChatInfo{ - Avatar: t.avatarFromPhoto(ctx, ids.PeerTypeChannel, peer.ChannelID, action.Photo), + Avatar: tc.avatarFromPhoto(ctx, ids.PeerTypeChannel, peer.ChannelID, action.Photo), }}, }) return resultToError(res) @@ -329,7 +329,7 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa } case *tg.MessageActionChatDeletePhoto: - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatInfoChange{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventChatInfoChange), ChatInfoChange: &bridgev2.ChatInfoChange{ChatInfo: &bridgev2.ChatInfo{Avatar: &bridgev2.Avatar{Remove: true}}}, }) @@ -340,17 +340,17 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa } for _, userID := range action.Users { memberChanges.MemberMap.Set(bridgev2.ChatMember{ - EventSender: t.senderForUserID(userID), + EventSender: tc.senderForUserID(userID), Membership: event.MembershipJoin, }) } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatInfoChange{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventChatInfoChange), ChatInfoChange: &bridgev2.ChatInfoChange{MemberChanges: memberChanges}, }) return resultToError(res) case *tg.MessageActionChatJoinedByLink: - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatInfoChange{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventChatInfoChange), ChatInfoChange: &bridgev2.ChatInfoChange{ MemberChanges: &bridgev2.ChatMemberList{ @@ -363,15 +363,15 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa }) return resultToError(res) case *tg.MessageActionChatDeleteUser: - if action.UserID == t.telegramUserID { - return t.selfLeaveChat(ctx, eventMeta.PortalKey, fmt.Errorf("delete user event for chat")) + if action.UserID == tc.telegramUserID { + return tc.selfLeaveChat(ctx, eventMeta.PortalKey, fmt.Errorf("delete user event for chat")) } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatInfoChange{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventChatInfoChange), ChatInfoChange: &bridgev2.ChatInfoChange{ MemberChanges: &bridgev2.ChatMemberList{ MemberMap: bridgev2.ChatMemberMap{}.Set(bridgev2.ChatMember{ - EventSender: t.senderForUserID(action.UserID), + EventSender: tc.senderForUserID(action.UserID), Membership: event.MembershipLeave, }), }, @@ -379,7 +379,7 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa }) return resultToError(res) case *tg.MessageActionChatCreate: - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Message[any]{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Message[any]{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventMessage).WithCreatePortal(true), ID: ids.GetMessageIDFromMessage(msg), ConvertMessageFunc: func(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, data any) (*bridgev2.ConvertedMessage, error) { @@ -397,16 +397,16 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa return resultToError(res) case *tg.MessageActionChannelCreate: - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatResync{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatResync{ EventMeta: eventMeta. WithType(bridgev2.RemoteEventChatResync). WithCreatePortal(true), - GetChatInfoFunc: t.GetChatInfo, + GetChatInfoFunc: tc.GetChatInfo, }) if err := resultToError(res); err != nil { return err } - res = t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Message[any]{ + res = tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Message[any]{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventMessage), ID: ids.GetMessageIDFromMessage(msg), ConvertMessageFunc: func(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, data any) (*bridgev2.ConvertedMessage, error) { @@ -426,7 +426,7 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa Type: event.DisappearingTypeAfterSend, Timer: time.Duration(action.Period) * time.Second, }.Normalize() - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatInfoChange{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventChatInfoChange), ChatInfoChange: &bridgev2.ChatInfoChange{ ChatInfo: &bridgev2.ChatInfo{ @@ -462,7 +462,7 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa body.WriteString(")") } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Message[any]{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Message[any]{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventMessage), ID: ids.GetMessageIDFromMessage(msg), ConvertMessageFunc: func(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, data any) (*bridgev2.ConvertedMessage, error) { @@ -485,7 +485,7 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa body = fmt.Sprintf("Ended the video chat (%s)", exfmt.Duration(time.Duration(action.Duration)*time.Second)) } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Message[any]{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Message[any]{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventMessage), ID: ids.GetMessageIDFromMessage(msg), ConvertMessageFunc: func(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, data any) (*bridgev2.ConvertedMessage, error) { @@ -515,11 +515,11 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa body.WriteString(", ") } - if ghost, err := t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(userID)); err != nil { + if ghost, err := tc.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(userID)); err != nil { return err } else { var name string - if username, err := t.main.Store.Username.Get(ctx, ids.PeerTypeUser, userID); err != nil { + if username, err := tc.main.Store.Username.Get(ctx, ids.PeerTypeUser, userID); err != nil { name = "@" + username } else { name = ghost.Name @@ -532,7 +532,7 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa } body.WriteString(" to the video chat") html.WriteString(" to the video chat") - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Message[any]{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Message[any]{ EventMeta: eventMeta.WithType(bridgev2.RemoteEventMessage), ID: ids.GetMessageIDFromMessage(msg), ConvertMessageFunc: func(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, data any) (*bridgev2.ConvertedMessage, error) { @@ -553,7 +553,7 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa return resultToError(res) case *tg.MessageActionGroupCallScheduled: start := time.Unix(int64(action.ScheduleDate), 0) - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Message[any]{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Message[any]{ EventMeta: eventMeta. WithType(bridgev2.RemoteEventMessage). WithSender(bridgev2.EventSender{}), // Telegram shows it as not coming from a specific user @@ -577,12 +577,12 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa Str("old_portal_id", string(eventMeta.PortalKey.ID)). Int64("channel_id", action.ChannelID). Msg("MessageActionChatMigrateTo") - newPortalKey := t.makePortalKeyFromID(ids.PeerTypeChannel, action.ChannelID, 0) - if err := t.migrateChat(ctx, eventMeta.PortalKey, newPortalKey); err != nil { + newPortalKey := tc.makePortalKeyFromID(ids.PeerTypeChannel, action.ChannelID, 0) + if err := tc.migrateChat(ctx, eventMeta.PortalKey, newPortalKey); err != nil { log.Err(err).Msg("Failed to migrate chat to channel") return err } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Message[any]{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Message[any]{ EventMeta: eventMeta. WithPortalKey(newPortalKey). WithStreamOrder(0). @@ -604,26 +604,26 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa case *tg.MessageActionTopicCreate: channelPeer, _ := msg.PeerID.(*tg.PeerChannel) - err := t.main.Store.Topic.Add(ctx, channelPeer.GetChannelID(), msg.ID) + err := tc.main.Store.Topic.Add(ctx, channelPeer.GetChannelID(), msg.ID) if err != nil { return fmt.Errorf("failed to store new topic: %w", err) } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatResync{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatResync{ EventMeta: eventMeta. - WithPortalKey(t.makePortalKeyFromPeer(msg.PeerID, msg.ID)). + WithPortalKey(tc.makePortalKeyFromPeer(msg.PeerID, msg.ID)). WithType(bridgev2.RemoteEventChatResync). WithCreatePortal(true), - GetChatInfoFunc: t.GetChatInfo, + GetChatInfoFunc: tc.GetChatInfo, }) return resultToError(res) case *tg.MessageActionTopicEdit: // TODO specific changes? - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatResync{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatResync{ EventMeta: eventMeta. - WithPortalKey(t.makePortalKeyFromPeer(msg.PeerID, msg.ID)). + WithPortalKey(tc.makePortalKeyFromPeer(msg.PeerID, msg.ID)). WithType(bridgev2.RemoteEventChatResync). WithCreatePortal(true), - GetChatInfoFunc: t.GetChatInfo, + GetChatInfoFunc: tc.GetChatInfo, }) return resultToError(res) @@ -635,29 +635,29 @@ func (t *TelegramClient) handleServiceMessage(ctx context.Context, msg *tg.Messa } } -func (t *TelegramClient) migrateChat(ctx context.Context, oldPortalKey, newPortalKey networkid.PortalKey) error { - if t.main.Config.AlwaysTombstoneOnSupergroupMigration { - newPortal, err := t.main.Bridge.GetPortalByKey(ctx, newPortalKey) +func (tc *TelegramClient) migrateChat(ctx context.Context, oldPortalKey, newPortalKey networkid.PortalKey) error { + if tc.main.Config.AlwaysTombstoneOnSupergroupMigration { + newPortal, err := tc.main.Bridge.GetPortalByKey(ctx, newPortalKey) if err != nil { return fmt.Errorf("failed to get new portal for chat migration: %w", err) } - info, err := t.GetChatInfo(ctx, newPortal) + info, err := tc.GetChatInfo(ctx, newPortal) if err != nil { return fmt.Errorf("failed to get chat info for new portal: %w", err) } - err = newPortal.CreateMatrixRoom(ctx, t.userLogin, info) + err = newPortal.CreateMatrixRoom(ctx, tc.userLogin, info) if err != nil { return fmt.Errorf("failed to create Matrix room for new portal: %w", err) } } - result, portal, err := t.main.Bridge.ReIDPortal(ctx, oldPortalKey, newPortalKey) + result, portal, err := tc.main.Bridge.ReIDPortal(ctx, oldPortalKey, newPortalKey) if err != nil { return fmt.Errorf("failed to re-ID portal: %w", err) } else if result == bridgev2.ReIDResultSourceReIDd || result == bridgev2.ReIDResultTargetDeletedAndSourceReIDd { // If the source portal is re-ID'd, we need to sync metadata and participants. // If the source is deleted, then it doesn't matter, any existing target will already be correct - info, err := t.GetChatInfo(ctx, portal) + info, err := tc.GetChatInfo(ctx, portal) if err != nil { zerolog.Ctx(ctx).Err(err).Msg("Failed to get chat info after re-ID") if tgerr.Is(err, tg.ErrChannelPrivate) { @@ -668,22 +668,22 @@ func (t *TelegramClient) migrateChat(ctx context.Context, oldPortalKey, newPorta return } zerolog.Ctx(ctx).Debug().Msg("Retrying GetChatInfo after re-ID") - info, err := t.GetChatInfo(ctx, portal) + info, err := tc.GetChatInfo(ctx, portal) if err != nil { zerolog.Ctx(ctx).Err(err).Msg("Failed to get chat info after re-ID retry") } else { - portal.UpdateInfo(ctx, info, t.userLogin, nil, time.Time{}) + portal.UpdateInfo(ctx, info, tc.userLogin, nil, time.Time{}) } }() } } else { - portal.UpdateInfo(ctx, info, t.userLogin, nil, time.Time{}) + portal.UpdateInfo(ctx, info, tc.userLogin, nil, time.Time{}) } } return nil } -func (t *TelegramClient) getEventSender(msg interface { +func (tc *TelegramClient) getEventSender(msg interface { GetOut() bool GetFromID() (tg.PeerClass, bool) GetPeerID() tg.PeerClass @@ -691,24 +691,24 @@ func (t *TelegramClient) getEventSender(msg interface { if isBroadcastChannel && msg.GetPeerID().TypeID() == tg.PeerChannelTypeID { // Always send as the channel in broadcast channels. We set a // per-message profile to indicate the actual user it was from. - return t.getPeerSender(msg.GetPeerID()) + return tc.getPeerSender(msg.GetPeerID()) } if msg.GetOut() { - return t.mySender() + return tc.mySender() } peer, ok := msg.GetFromID() if !ok { peer = msg.GetPeerID() } - return t.getPeerSender(peer) + return tc.getPeerSender(peer) } -func (t *TelegramClient) getPeerSender(peer tg.PeerClass) bridgev2.EventSender { +func (tc *TelegramClient) getPeerSender(peer tg.PeerClass) bridgev2.EventSender { switch from := peer.(type) { case *tg.PeerUser: - return t.senderForUserID(from.UserID) + return tc.senderForUserID(from.UserID) case *tg.PeerChannel: return bridgev2.EventSender{ Sender: ids.MakeChannelUserID(from.ChannelID), @@ -718,8 +718,8 @@ func (t *TelegramClient) getPeerSender(peer tg.PeerClass) bridgev2.EventSender { } } -func (t *TelegramClient) onUserName(ctx context.Context, e tg.Entities, update *tg.UpdateUserName) error { - ghost, err := t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(update.UserID)) +func (tc *TelegramClient) onUserName(ctx context.Context, e tg.Entities, update *tg.UpdateUserName) error { + ghost, err := tc.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(update.UserID)) if err != nil { return err } @@ -746,20 +746,20 @@ func (t *TelegramClient) onUserName(ctx context.Context, e tg.Entities, update * userInfo.Identifiers = slices.Compact(userInfo.Identifiers) } - name := t.main.Config.FormatDisplayname(update.FirstName, update.LastName, firstUsername, false, update.UserID) + name := tc.main.Config.FormatDisplayname(update.FirstName, update.LastName, firstUsername, false, update.UserID) userInfo.Name = &name - if meta.ContactSource != 0 && meta.ContactSource != t.telegramUserID && !t.main.Config.ContactNames { + if meta.ContactSource != 0 && meta.ContactSource != tc.telegramUserID && !tc.main.Config.ContactNames { // TODO fetch full info to accurately detect if the user is a contact or not userInfo.Name = nil } ghost.UpdateInfo(ctx, &userInfo) - if ghost.ID == t.userID { + if ghost.ID == tc.userID { var firstUsername string if len(update.Usernames) > 0 { firstUsername = update.Usernames[0].Username } - t.updateRemoteProfile(ctx, &tg.User{ + tc.updateRemoteProfile(ctx, &tg.User{ Self: true, ID: update.UserID, FirstName: update.FirstName, @@ -772,27 +772,27 @@ func (t *TelegramClient) onUserName(ctx context.Context, e tg.Entities, update * return nil } -func (t *TelegramClient) onDeleteMessages(ctx context.Context, channelID int64, update IGetMessages) error { +func (tc *TelegramClient) onDeleteMessages(ctx context.Context, channelID int64, update IGetMessages) error { for _, messageID := range update.GetMessages() { wrappedMessageID := ids.MakeMessageID(channelID, messageID) var portalKey networkid.PortalKey var ok bool - if portalKey, ok = t.recentMessageRooms.Get(wrappedMessageID); ok { + if portalKey, ok = tc.recentMessageRooms.Get(wrappedMessageID); ok { // key found in cache - } else if parts, err := t.main.Bridge.DB.Message.GetAllPartsByID(ctx, t.loginID, wrappedMessageID); err != nil { + } else if parts, err := tc.main.Bridge.DB.Message.GetAllPartsByID(ctx, tc.loginID, wrappedMessageID); err != nil { return err } else if len(parts) > 0 { portalKey = parts[0].Room } else if channelID != 0 { // This won't work for topics, but should work for any other channels - portalKey = t.makePortalKeyFromPeer(&tg.PeerChannel{ChannelID: channelID}, 0) + portalKey = tc.makePortalKeyFromPeer(&tg.PeerChannel{ChannelID: channelID}, 0) } else { zerolog.Ctx(ctx).Debug(). Int("message_id", messageID). Msg("Ignoring delete of unknown message") continue } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.MessageRemove{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.MessageRemove{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventMessageRemove, PortalKey: portalKey, @@ -806,31 +806,31 @@ func (t *TelegramClient) onDeleteMessages(ctx context.Context, channelID int64, return nil } -func (t *TelegramClient) updateGhost(ctx context.Context, userID int64, user *tg.User) (*bridgev2.UserInfo, error) { - ghost, err := t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(userID)) +func (tc *TelegramClient) updateGhost(ctx context.Context, userID int64, user *tg.User) (*bridgev2.UserInfo, error) { + ghost, err := tc.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(userID)) if err != nil { return nil, err } - userInfo, err := t.wrapUserInfo(ctx, user, ghost) + userInfo, err := tc.wrapUserInfo(ctx, user, ghost) if err != nil { return nil, err } ghost.UpdateInfo(ctx, userInfo) - if !user.Min && ghost.ID == t.userID && t.updateRemoteProfile(ctx, user, ghost) { - t.userLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) + if !user.Min && ghost.ID == tc.userID && tc.updateRemoteProfile(ctx, user, ghost) { + tc.userLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) } return userInfo, nil } -func (t *TelegramClient) updateChannel(ctx context.Context, channel *tg.Channel) (*bridgev2.UserInfo, error) { +func (tc *TelegramClient) updateChannel(ctx context.Context, channel *tg.Channel) (*bridgev2.UserInfo, error) { // TODO resync portal metadata? - userInfo, err := t.wrapChannelGhostInfo(ctx, channel) + userInfo, err := tc.wrapChannelGhostInfo(ctx, channel) if err != nil { return nil, err } - ghost, err := t.main.Bridge.GetGhostByID(ctx, ids.MakeChannelUserID(channel.ID)) + ghost, err := tc.main.Bridge.GetGhostByID(ctx, ids.MakeChannelUserID(channel.ID)) if err != nil { return nil, err } @@ -840,10 +840,10 @@ func (t *TelegramClient) updateChannel(ctx context.Context, channel *tg.Channel) const updateHandlerStuck status.BridgeStateErrorCode = "tg-update-handler-stuck" -func (t *TelegramClient) onUpdateWrapper(ctx context.Context, e tg.Entities, upd tg.UpdateClass) error { +func (tc *TelegramClient) onUpdateWrapper(ctx context.Context, e tg.Entities, upd tg.UpdateClass) error { doneChan := make(chan error, 1) go func() { - doneChan <- t.onUpdate(ctx, e, upd) + doneChan <- tc.onUpdate(ctx, e, upd) }() ticker := time.NewTicker(10 * time.Second) defer ticker.Stop() @@ -857,15 +857,15 @@ func (t *TelegramClient) onUpdateWrapper(ctx context.Context, e tg.Entities, upd Msg("Telegram update handling is taking long") if time.Since(startedAt) > 3*time.Minute && !bridgeStateUpdated { bridgeStateUpdated = true - t.userLogin.BridgeState.Send(status.BridgeState{ + tc.userLogin.BridgeState.Send(status.BridgeState{ StateEvent: status.StateUnknownError, Error: updateHandlerStuck, Message: "Processing messages from Telegram is stuck", }) } case err := <-doneChan: - if bridgeStateUpdated && t.userLogin.BridgeState.GetPrevUnsent().Error == updateHandlerStuck { - t.userLogin.BridgeState.Send(status.BridgeState{ + if bridgeStateUpdated && tc.userLogin.BridgeState.GetPrevUnsent().Error == updateHandlerStuck { + tc.userLogin.BridgeState.Send(status.BridgeState{ StateEvent: status.StateConnected, Info: map[string]any{ "update_reason": "finished processing slow update", @@ -877,11 +877,11 @@ func (t *TelegramClient) onUpdateWrapper(ctx context.Context, e tg.Entities, upd } } -func (t *TelegramClient) onUpdate(ctx context.Context, e tg.Entities, upd tg.UpdateClass) error { +func (tc *TelegramClient) onUpdate(ctx context.Context, e tg.Entities, upd tg.UpdateClass) error { zerolog.Ctx(ctx).Trace().Stringer("update", upd).Msg("Raw update") for userID, user := range e.Users { zerolog.Ctx(ctx).Trace().Stringer("user", user).Msg("Raw user info in update") - if _, err := t.updateGhost(ctx, userID, user); err != nil { + if _, err := tc.updateGhost(ctx, userID, user); err != nil { return err } } @@ -889,65 +889,65 @@ func (t *TelegramClient) onUpdate(ctx context.Context, e tg.Entities, upd tg.Upd zerolog.Ctx(ctx).Trace().Stringer("chat", chat).Msg("Raw chat info in update") if chat.GetLeft() { // TODO don't ignore errors - t.selfLeaveChat(ctx, t.makePortalKeyFromID(ids.PeerTypeChat, chatID, 0), fmt.Errorf("left flag in entity update")) + tc.selfLeaveChat(ctx, tc.makePortalKeyFromID(ids.PeerTypeChat, chatID, 0), fmt.Errorf("left flag in entity update")) } } for _, channel := range e.Channels { zerolog.Ctx(ctx).Trace().Stringer("channel", channel).Msg("Raw channel info in update") if channel.GetLeft() { - t.selfLeaveChat(ctx, t.makePortalKeyFromID(ids.PeerTypeChannel, channel.ID, 0), fmt.Errorf("left flag in entity update")) + tc.selfLeaveChat(ctx, tc.makePortalKeyFromID(ids.PeerTypeChannel, channel.ID, 0), fmt.Errorf("left flag in entity update")) } - if _, err := t.updateChannel(ctx, channel); err != nil { + if _, err := tc.updateChannel(ctx, channel); err != nil { return err } } switch update := upd.(type) { case *tg.UpdateNewMessage: - return t.onUpdateNewMessage(ctx, e, update) + return tc.onUpdateNewMessage(ctx, e, update) case *tg.UpdateNewChannelMessage: - return t.onUpdateNewMessage(ctx, e, update) + return tc.onUpdateNewMessage(ctx, e, update) case *tg.UpdateChannel: - return t.onUpdateChannel(ctx, e, update) + return tc.onUpdateChannel(ctx, e, update) case *tg.UpdateUserName: - return t.onUserName(ctx, e, update) + return tc.onUserName(ctx, e, update) case *tg.UpdateDeleteMessages: - return t.onDeleteMessages(ctx, 0, update) + return tc.onDeleteMessages(ctx, 0, update) case *tg.UpdateDeleteChannelMessages: - return t.onDeleteMessages(ctx, update.ChannelID, update) + return tc.onDeleteMessages(ctx, update.ChannelID, update) case *tg.UpdateEditMessage: - return t.onMessageEdit(ctx, update) + return tc.onMessageEdit(ctx, update) case *tg.UpdateEditChannelMessage: - return t.onMessageEdit(ctx, update) + return tc.onMessageEdit(ctx, update) case *tg.UpdateMessageReactions: - return t.onMessageReactions(ctx, update) + return tc.onMessageReactions(ctx, update) case *tg.UpdateUserTyping: - return t.handleTyping(t.makePortalKeyFromID(ids.PeerTypeUser, update.UserID, 0), t.senderForUserID(update.UserID), update.Action) + return tc.handleTyping(tc.makePortalKeyFromID(ids.PeerTypeUser, update.UserID, 0), tc.senderForUserID(update.UserID), update.Action) case *tg.UpdateChatUserTyping: if update.FromID.TypeID() != tg.PeerUserTypeID { zerolog.Ctx(ctx).Warn().Str("from_id_type", update.FromID.TypeName()).Msg("unsupported from_id type") return nil } - return t.handleTyping(t.makePortalKeyFromID(ids.PeerTypeChat, update.ChatID, 0), t.getPeerSender(update.FromID), update.Action) + return tc.handleTyping(tc.makePortalKeyFromID(ids.PeerTypeChat, update.ChatID, 0), tc.getPeerSender(update.FromID), update.Action) case *tg.UpdateChannelUserTyping: - return t.handleTyping(t.makePortalKeyFromID(ids.PeerTypeChannel, update.ChannelID, update.TopMsgID), t.getPeerSender(update.FromID), update.Action) + return tc.handleTyping(tc.makePortalKeyFromID(ids.PeerTypeChannel, update.ChannelID, update.TopMsgID), tc.getPeerSender(update.FromID), update.Action) case *tg.UpdateReadHistoryOutbox: - return t.updateReadReceipt(ctx, e, update) + return tc.updateReadReceipt(ctx, e, update) case *tg.UpdateReadHistoryInbox: - return t.onOwnReadReceipt(t.makePortalKeyFromPeer(update.Peer, update.TopMsgID), update.MaxID) + return tc.onOwnReadReceipt(tc.makePortalKeyFromPeer(update.Peer, update.TopMsgID), update.MaxID) case *tg.UpdateReadChannelInbox: - return t.onOwnReadReceipt(t.makePortalKeyFromID(ids.PeerTypeChannel, update.ChannelID, 0), update.MaxID) + return tc.onOwnReadReceipt(tc.makePortalKeyFromID(ids.PeerTypeChannel, update.ChannelID, 0), update.MaxID) case *tg.UpdateNotifySettings: - return t.onNotifySettings(ctx, e, update) + return tc.onNotifySettings(ctx, e, update) case *tg.UpdatePinnedDialogs: - return t.onPinnedDialogs(ctx, e, update) + return tc.onPinnedDialogs(ctx, e, update) case *tg.UpdateChatDefaultBannedRights: - return t.onChatDefaultBannedRights(ctx, e, update) + return tc.onChatDefaultBannedRights(ctx, e, update) case *tg.UpdatePeerBlocked: - return t.onPeerBlocked(ctx, e, update) + return tc.onPeerBlocked(ctx, e, update) case *tg.UpdateChat: - return t.onChat(ctx, e, update) + return tc.onChat(ctx, e, update) case *tg.UpdatePhoneCall: - return t.onPhoneCall(ctx, e, update) + return tc.onPhoneCall(ctx, e, update) case *tg.UpdateUserStatus: // ignored return nil @@ -957,11 +957,11 @@ func (t *TelegramClient) onUpdate(ctx context.Context, e tg.Entities, upd tg.Upd } } -func (t *TelegramClient) onMessageReactions(ctx context.Context, update *tg.UpdateMessageReactions) error { - return t.handleTelegramReactions(ctx, update.Peer, update.TopMsgID, update.MsgID, update.Reactions) +func (tc *TelegramClient) onMessageReactions(ctx context.Context, update *tg.UpdateMessageReactions) error { + return tc.handleTelegramReactions(ctx, update.Peer, update.TopMsgID, update.MsgID, update.Reactions) } -func (t *TelegramClient) onMessageEdit(ctx context.Context, update IGetMessage) error { +func (tc *TelegramClient) onMessageEdit(ctx context.Context, update IGetMessage) error { msg, ok := update.GetMessage().(*tg.Message) if !ok { zerolog.Ctx(ctx).Warn(). @@ -970,23 +970,23 @@ func (t *TelegramClient) onMessageEdit(ctx context.Context, update IGetMessage) return nil } - topicID := t.getTopicID(ctx, msg.PeerID, msg.ReplyTo) + topicID := tc.getTopicID(ctx, msg.PeerID, msg.ReplyTo) // Channels don't use edits to signal reactions, and when sending the first reaction they send a no-op edit // with an empty reactions list, which would confuse the handle method. Therefore, just don't sync reactions // on channel message edits. if _, isChannel := msg.PeerID.(*tg.PeerChannel); !isChannel { - err := t.handleTelegramReactions(ctx, msg.PeerID, topicID, msg.ID, msg.Reactions) + err := tc.handleTelegramReactions(ctx, msg.PeerID, topicID, msg.ID, msg.Reactions) if err != nil { zerolog.Ctx(ctx).Err(err).Msg("Failed to handle reactions on edited message") } } - portalKey := t.makePortalKeyFromPeer(msg.PeerID, topicID) - portal, err := t.main.Bridge.GetPortalByKey(ctx, portalKey) + portalKey := tc.makePortalKeyFromPeer(msg.PeerID, topicID) + portal, err := tc.main.Bridge.GetPortalByKey(ctx, portalKey) if err != nil { return err } - sender := t.getEventSender(msg, !portal.Metadata.(*PortalMetadata).IsSuperGroup) + sender := tc.getEventSender(msg, !portal.Metadata.(*PortalMetadata).IsSuperGroup) // Check if this edit was a data export request acceptance message if sender.Sender == networkid.UserID("777000") { @@ -994,12 +994,12 @@ func (t *TelegramClient) onMessageEdit(ctx context.Context, update IGetMessage) zerolog.Ctx(ctx).Info(). Int("message_id", msg.ID). Msg("Received an edit to message that looks like the data export was accepted, marking takeout as retriable") - t.takeoutAccepted.Set() + tc.takeoutAccepted.Set() } // TODO detect takeout being rejected too } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Message[*tg.Message]{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Message[*tg.Message]{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventEdit, LogContext: func(c zerolog.Context) zerolog.Context { @@ -1017,7 +1017,7 @@ func (t *TelegramClient) onMessageEdit(ctx context.Context, update IGetMessage) Data: msg, ConvertEditFunc: func(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, existing []*database.Message, data *tg.Message) (*bridgev2.ConvertedEdit, error) { log := zerolog.Ctx(ctx) - converted, err := t.convertToMatrix(ctx, portal, intent, msg) + converted, err := tc.convertToMatrix(ctx, portal, intent, msg) if err != nil { return nil, err } @@ -1052,8 +1052,8 @@ func (t *TelegramClient) onMessageEdit(ctx context.Context, update IGetMessage) return resultToError(res) } -func (t *TelegramClient) handleTyping(portal networkid.PortalKey, sender bridgev2.EventSender, action tg.SendMessageActionClass) error { - if sender.IsFromMe || (sender.Sender == t.userID && sender.SenderLogin == t.userLogin.ID) { +func (tc *TelegramClient) handleTyping(portal networkid.PortalKey, sender bridgev2.EventSender, action tg.SendMessageActionClass) error { + if sender.IsFromMe || (sender.Sender == tc.userID && sender.SenderLogin == tc.userLogin.ID) { return nil } timeout := time.Duration(6) * time.Second @@ -1070,7 +1070,7 @@ func (t *TelegramClient) handleTyping(portal networkid.PortalKey, sender bridgev default: timeout = 0 } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Typing{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Typing{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventTyping, PortalKey: portal, @@ -1085,17 +1085,17 @@ func (t *TelegramClient) handleTyping(portal networkid.PortalKey, sender bridgev return resultToError(res) } -func (t *TelegramClient) updateReadReceipt(ctx context.Context, e tg.Entities, update *tg.UpdateReadHistoryOutbox) error { +func (tc *TelegramClient) updateReadReceipt(ctx context.Context, e tg.Entities, update *tg.UpdateReadHistoryOutbox) error { user, ok := update.Peer.(*tg.PeerUser) if !ok { // Read receipts from other users are meaningless in chats/channels // (they only say "someone read the message" and not who) return nil } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Receipt{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Receipt{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventReadReceipt, - PortalKey: t.makePortalKeyFromPeer(update.Peer, 0), + PortalKey: tc.makePortalKeyFromPeer(update.Peer, 0), Sender: bridgev2.EventSender{ SenderLogin: ids.MakeUserLoginID(user.UserID), Sender: ids.MakeUserID(user.UserID), @@ -1110,12 +1110,12 @@ func (t *TelegramClient) updateReadReceipt(ctx context.Context, e tg.Entities, u return resultToError(res) } -func (t *TelegramClient) onOwnReadReceipt(portalKey networkid.PortalKey, maxID int) error { - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Receipt{ +func (tc *TelegramClient) onOwnReadReceipt(portalKey networkid.PortalKey, maxID int) error { + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Receipt{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventReadReceipt, PortalKey: portalKey, - Sender: t.mySender(), + Sender: tc.mySender(), LogContext: func(c zerolog.Context) zerolog.Context { return c.Str("tg_event", "updateRead*Inbox") }, @@ -1126,14 +1126,14 @@ func (t *TelegramClient) onOwnReadReceipt(portalKey networkid.PortalKey, maxID i return resultToError(res) } -func (t *TelegramClient) inputPeerForPortalID(ctx context.Context, portalID networkid.PortalID) (tg.InputPeerClass, int, error) { +func (tc *TelegramClient) inputPeerForPortalID(ctx context.Context, portalID networkid.PortalID) (tg.InputPeerClass, int, error) { peerType, id, topicID, err := ids.ParsePortalID(portalID) if err != nil { return nil, 0, err } switch peerType { case ids.PeerTypeUser: - if accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeUser, id); err != nil { + if accessHash, err := tc.ScopedStore.GetAccessHash(ctx, ids.PeerTypeUser, id); err != nil { return nil, 0, fmt.Errorf("failed to get user access hash for %d: %w", id, err) } else { return &tg.InputPeerUser{UserID: id, AccessHash: accessHash}, 0, nil @@ -1141,7 +1141,7 @@ func (t *TelegramClient) inputPeerForPortalID(ctx context.Context, portalID netw case ids.PeerTypeChat: return &tg.InputPeerChat{ChatID: id}, 0, nil case ids.PeerTypeChannel: - if accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, id); err != nil { + if accessHash, err := tc.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, id); err != nil { return nil, 0, err } else { return &tg.InputPeerChannel{ChannelID: id, AccessHash: accessHash}, topicID, nil @@ -1151,14 +1151,14 @@ func (t *TelegramClient) inputPeerForPortalID(ctx context.Context, portalID netw } } -func (t *TelegramClient) getAppConfigCached(ctx context.Context) (map[string]any, error) { - if t.metadata.IsBot { +func (tc *TelegramClient) getAppConfigCached(ctx context.Context) (map[string]any, error) { + if tc.metadata.IsBot { return nil, nil } - t.appConfigLock.Lock() - defer t.appConfigLock.Unlock() - if t.appConfig == nil { - cfg, err := t.client.API().HelpGetAppConfig(ctx, t.appConfigHash) + tc.appConfigLock.Lock() + defer tc.appConfigLock.Unlock() + if tc.appConfig == nil { + cfg, err := tc.client.API().HelpGetAppConfig(ctx, tc.appConfigHash) if err != nil { return nil, err } @@ -1170,39 +1170,39 @@ func (t *TelegramClient) getAppConfigCached(ctx context.Context) (map[string]any if err != nil { return nil, err } - t.appConfig, ok = parsedConfig.(map[string]any) + tc.appConfig, ok = parsedConfig.(map[string]any) if !ok { - return nil, fmt.Errorf("failed to parse app config: unexpected type %T", t.appConfig) + return nil, fmt.Errorf("failed to parse app config: unexpected type %T", tc.appConfig) } - t.appConfigHash = appConfig.Hash + tc.appConfigHash = appConfig.Hash } - return t.appConfig, nil + return tc.appConfig, nil } -func (t *TelegramClient) getAvailableReactionsForCapability(ctx context.Context) ([]string, bool) { - _, err := t.getAvailableReactions(ctx) +func (tc *TelegramClient) getAvailableReactionsForCapability(ctx context.Context) ([]string, bool) { + _, err := tc.getAvailableReactions(ctx) if err != nil { zerolog.Ctx(ctx).Warn().Err(err).Msg("Failed to get available reactions for capability listing") } - return t.availableReactionsList, t.isPremiumCache.Load() + return tc.availableReactionsList, tc.isPremiumCache.Load() } -func (t *TelegramClient) getAvailableReactions(ctx context.Context) (map[string]struct{}, error) { - if t.metadata.IsBot { +func (tc *TelegramClient) getAvailableReactions(ctx context.Context) (map[string]struct{}, error) { + if tc.metadata.IsBot { return nil, nil - } else if !t.IsLoggedIn() { + } else if !tc.IsLoggedIn() { return nil, errors.New("you must be logged in to get available reactions") } log := zerolog.Ctx(ctx).With().Str("handler", "get_available_reactions").Logger() - t.availableReactionsLock.Lock() - defer t.availableReactionsLock.Unlock() - if t.availableReactions == nil || time.Since(t.availableReactionsFetched) > 12*time.Hour { - cfg, err := t.client.API().MessagesGetAvailableReactions(ctx, t.availableReactionsHash) + tc.availableReactionsLock.Lock() + defer tc.availableReactionsLock.Unlock() + if tc.availableReactions == nil || time.Since(tc.availableReactionsFetched) > 12*time.Hour { + cfg, err := tc.client.API().MessagesGetAvailableReactions(ctx, tc.availableReactionsHash) if err != nil { return nil, err } - t.availableReactionsFetched = time.Now() + tc.availableReactionsFetched = time.Now() switch v := cfg.(type) { case *tg.MessagesAvailableReactions: availableReactions, ok := cfg.(*tg.MessagesAvailableReactions) @@ -1212,26 +1212,26 @@ func (t *TelegramClient) getAvailableReactions(ctx context.Context) (map[string] log.Debug().Msg("Fetched new available reactions") - myGhost, err := t.main.Bridge.GetGhostByID(ctx, t.userID) + myGhost, err := tc.main.Bridge.GetGhostByID(ctx, tc.userID) if err != nil { log.Err(err).Msg("failed to get own ghost") } - t.availableReactions = make(map[string]struct{}, len(availableReactions.Reactions)) + tc.availableReactions = make(map[string]struct{}, len(availableReactions.Reactions)) for _, reaction := range availableReactions.Reactions { if !reaction.Inactive && (myGhost.Metadata.(*GhostMetadata).IsPremium || !reaction.Premium) { - t.availableReactions[reaction.Reaction] = struct{}{} + tc.availableReactions[reaction.Reaction] = struct{}{} } } - t.availableReactionsHash = availableReactions.Hash + tc.availableReactionsHash = availableReactions.Hash if myGhost.Metadata.(*GhostMetadata).IsPremium { // All reactions are allowed via the unicodemojipack feature - t.availableReactionsList = nil - t.isPremiumCache.Store(true) + tc.availableReactionsList = nil + tc.isPremiumCache.Store(true) } else { - t.availableReactionsList = maps.Keys(t.availableReactions) - t.isPremiumCache.Store(false) - slices.Sort(t.availableReactionsList) + tc.availableReactionsList = maps.Keys(tc.availableReactions) + tc.isPremiumCache.Store(false) + slices.Sort(tc.availableReactionsList) } case *tg.MessagesAvailableReactionsNotModified: log.Debug().Msg("Available reactions not modified") @@ -1239,27 +1239,27 @@ func (t *TelegramClient) getAvailableReactions(ctx context.Context) (map[string] log.Error().Type("reaction_type", v).Msg("failed to get available reactions: unexpected type") } } - return t.availableReactions, nil + return tc.availableReactions, nil } -func (t *TelegramClient) transferEmojisToMatrix(ctx context.Context, customEmojiIDs []int64) (result map[networkid.EmojiID]emojis.EmojiInfo, err error) { +func (tc *TelegramClient) transferEmojisToMatrix(ctx context.Context, customEmojiIDs []int64) (result map[networkid.EmojiID]emojis.EmojiInfo, err error) { result, customEmojiIDs = emojis.ConvertKnownEmojis(customEmojiIDs) if len(customEmojiIDs) == 0 { return } - if t.main.useDirectMedia { + if tc.main.useDirectMedia { for _, emojiID := range customEmojiIDs { mediaID, err := ids.DirectMediaInfo{ PeerType: ids.FakePeerTypeEmoji, - UserID: t.telegramUserID, + UserID: tc.telegramUserID, ID: emojiID, }.AsMediaID() if err != nil { return nil, err } - if mxcURI, err := t.main.Bridge.Matrix.GenerateContentURI(ctx, mediaID); err != nil { + if mxcURI, err := tc.main.Bridge.Matrix.GenerateContentURI(ctx, mediaID); err != nil { return nil, err } else { result[ids.MakeEmojiIDFromDocumentID(emojiID)] = emojis.EmojiInfo{EmojiURI: mxcURI, DocumentID: emojiID} @@ -1271,7 +1271,7 @@ func (t *TelegramClient) transferEmojisToMatrix(ctx context.Context, customEmoji missingCustomEmojiIDs := customEmojiIDs[:0] for _, emojiID := range customEmojiIDs { - file, err := t.main.Store.TelegramFile.GetByLocationID(ctx, store.TelegramFileLocationID(strconv.FormatInt(emojiID, 10))) + file, err := tc.main.Store.TelegramFile.GetByLocationID(ctx, store.TelegramFileLocationID(strconv.FormatInt(emojiID, 10))) if err != nil { return nil, fmt.Errorf("failed to get file for custom emoji %d: %w", emojiID, err) } else if file != nil { @@ -1284,17 +1284,17 @@ func (t *TelegramClient) transferEmojisToMatrix(ctx context.Context, customEmoji return } - customEmojiDocuments, err := t.client.API().MessagesGetCustomEmojiDocuments(ctx, missingCustomEmojiIDs) + customEmojiDocuments, err := tc.client.API().MessagesGetCustomEmojiDocuments(ctx, missingCustomEmojiIDs) if err != nil { return nil, err } for _, customEmojiDocument := range customEmojiDocuments { - mxcURI, _, _, err := media.NewTransferer(t.client.API()). - WithStickerConfig(t.main.Config.AnimatedSticker). + mxcURI, _, _, err := media.NewTransferer(tc.client.API()). + WithStickerConfig(tc.main.Config.AnimatedSticker). WithForceWebmStickerConvert(true). WithDocument(customEmojiDocument, false). - Transfer(ctx, t.main.Store, t.main.Bridge.Bot) + Transfer(ctx, tc.main.Store, tc.main.Bridge.Bot) if err != nil { return nil, err } @@ -1303,13 +1303,13 @@ func (t *TelegramClient) transferEmojisToMatrix(ctx context.Context, customEmoji return } -func (t *TelegramClient) onNotifySettings(ctx context.Context, e tg.Entities, update *tg.UpdateNotifySettings) error { +func (tc *TelegramClient) onNotifySettings(ctx context.Context, e tg.Entities, update *tg.UpdateNotifySettings) error { var portalKey networkid.PortalKey switch typedPeer := update.Peer.(type) { case *tg.NotifyPeer: - portalKey = t.makePortalKeyFromPeer(typedPeer.Peer, 0) + portalKey = tc.makePortalKeyFromPeer(typedPeer.Peer, 0) case *tg.NotifyForumTopic: - portalKey = t.makePortalKeyFromPeer(typedPeer.Peer, typedPeer.TopMsgID) + portalKey = tc.makePortalKeyFromPeer(typedPeer.Peer, typedPeer.TopMsgID) default: zerolog.Ctx(ctx).Debug(). Type("peer_type", update.Peer). @@ -1325,7 +1325,7 @@ func (t *TelegramClient) onNotifySettings(ctx context.Context, e tg.Entities, up mutedUntil = &bridgev2.Unmuted } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatInfoChange{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ ChatInfoChange: &bridgev2.ChatInfoChange{ ChatInfo: &bridgev2.ChatInfo{ UserLocal: &bridgev2.UserLocalPortalInfo{ @@ -1346,27 +1346,27 @@ func (t *TelegramClient) onNotifySettings(ctx context.Context, e tg.Entities, up return resultToError(res) } -func (t *TelegramClient) onPinnedDialogs(ctx context.Context, e tg.Entities, msg *tg.UpdatePinnedDialogs) error { +func (tc *TelegramClient) onPinnedDialogs(ctx context.Context, e tg.Entities, msg *tg.UpdatePinnedDialogs) error { needsUnpinning := map[networkid.PortalKey]struct{}{} - for _, portalID := range t.metadata.PinnedDialogs { + for _, portalID := range tc.metadata.PinnedDialogs { pt, id, _, err := ids.ParsePortalID(portalID) if err != nil { return err } - needsUnpinning[t.makePortalKeyFromID(pt, id, 0)] = struct{}{} + needsUnpinning[tc.makePortalKeyFromID(pt, id, 0)] = struct{}{} } - t.metadata.PinnedDialogs = nil + tc.metadata.PinnedDialogs = nil for _, d := range msg.Order { dialog, ok := d.(*tg.DialogPeer) if !ok { continue } - portalKey := t.makePortalKeyFromPeer(dialog.Peer, 0) + portalKey := tc.makePortalKeyFromPeer(dialog.Peer, 0) delete(needsUnpinning, portalKey) - t.metadata.PinnedDialogs = append(t.metadata.PinnedDialogs, portalKey.ID) + tc.metadata.PinnedDialogs = append(tc.metadata.PinnedDialogs, portalKey.ID) - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatInfoChange{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ ChatInfoChange: &bridgev2.ChatInfoChange{ ChatInfo: &bridgev2.ChatInfo{ UserLocal: &bridgev2.UserLocalPortalInfo{ @@ -1391,7 +1391,7 @@ func (t *TelegramClient) onPinnedDialogs(ctx context.Context, e tg.Entities, msg var empty event.RoomTag for portalKey := range needsUnpinning { - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatInfoChange{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ ChatInfoChange: &bridgev2.ChatInfoChange{ ChatInfo: &bridgev2.ChatInfo{ UserLocal: &bridgev2.UserLocalPortalInfo{ @@ -1414,22 +1414,22 @@ func (t *TelegramClient) onPinnedDialogs(ctx context.Context, e tg.Entities, msg } } - return t.userLogin.Save(ctx) + return tc.userLogin.Save(ctx) } -func (t *TelegramClient) onChatDefaultBannedRights(ctx context.Context, entities tg.Entities, update *tg.UpdateChatDefaultBannedRights) error { +func (tc *TelegramClient) onChatDefaultBannedRights(ctx context.Context, entities tg.Entities, update *tg.UpdateChatDefaultBannedRights) error { // TODO update all topic portals - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatInfoChange{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ ChatInfoChange: &bridgev2.ChatInfoChange{ ChatInfo: &bridgev2.ChatInfo{ Members: &bridgev2.ChatMemberList{ - PowerLevels: t.getPowerLevelOverridesFromBannedRights(entities.Chats[0], update.DefaultBannedRights), + PowerLevels: tc.getPowerLevelOverridesFromBannedRights(entities.Chats[0], update.DefaultBannedRights), }, }, }, EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventChatInfoChange, - PortalKey: t.makePortalKeyFromPeer(update.Peer, 0), + PortalKey: tc.makePortalKeyFromPeer(update.Peer, 0), LogContext: func(c zerolog.Context) zerolog.Context { return c.Str("tg_event", "updateChatDefaultBannedRights") }, @@ -1438,7 +1438,7 @@ func (t *TelegramClient) onChatDefaultBannedRights(ctx context.Context, entities return resultToError(res) } -func (t *TelegramClient) onPeerBlocked(ctx context.Context, e tg.Entities, update *tg.UpdatePeerBlocked) error { +func (tc *TelegramClient) onPeerBlocked(ctx context.Context, e tg.Entities, update *tg.UpdatePeerBlocked) error { // TODO fix this after adding storage for block status (getDMPowerLevels also needs updating) if true { return nil @@ -1452,22 +1452,22 @@ func (t *TelegramClient) onPeerBlocked(ctx context.Context, e tg.Entities, updat } // Update the ghost - ghost, err := t.main.Bridge.GetGhostByID(ctx, userID) + ghost, err := tc.main.Bridge.GetGhostByID(ctx, userID) if err != nil { return err } // Find portals that are DMs with the user - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ChatResync{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatResync{ ChatInfo: &bridgev2.ChatInfo{ Members: &bridgev2.ChatMemberList{ - PowerLevels: t.getDMPowerLevels(ghost), + PowerLevels: tc.getDMPowerLevels(ghost), }, CanBackfill: true, }, EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventChatResync, - PortalKey: t.makePortalKeyFromPeer(update.PeerID, 0), + PortalKey: tc.makePortalKeyFromPeer(update.PeerID, 0), LogContext: func(c zerolog.Context) zerolog.Context { return c.Str("tg_event", "updatePeerBlocked") }, @@ -1476,17 +1476,17 @@ func (t *TelegramClient) onPeerBlocked(ctx context.Context, e tg.Entities, updat return resultToError(res) } -func (t *TelegramClient) onChat(ctx context.Context, e tg.Entities, update *tg.UpdateChat) error { +func (tc *TelegramClient) onChat(ctx context.Context, e tg.Entities, update *tg.UpdateChat) error { return nil } -func (t *TelegramClient) onPhoneCall(ctx context.Context, e tg.Entities, update *tg.UpdatePhoneCall) error { +func (tc *TelegramClient) onPhoneCall(ctx context.Context, e tg.Entities, update *tg.UpdatePhoneCall) error { log := zerolog.Ctx(ctx).With().Str("action", "on_phone_call").Logger() call, ok := update.PhoneCall.(*tg.PhoneCallRequested) if !ok { log.Info().Type("type", update.PhoneCall).Msg("Unhandled phone call update class") return nil - } else if call.ParticipantID != t.telegramUserID { + } else if call.ParticipantID != tc.telegramUserID { log.Warn().Msg("Received phone call for user that is not us") return nil } @@ -1501,12 +1501,12 @@ func (t *TelegramClient) onPhoneCall(ctx context.Context, e tg.Entities, update callType = event.BeeperActionMessageCallTypeVoice body.WriteString("call") } - res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Message[any]{ + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.Message[any]{ EventMeta: simplevent.EventMeta{ Type: bridgev2.RemoteEventMessage, - PortalKey: t.makePortalKeyFromID(ids.PeerTypeUser, call.AdminID, 0), + PortalKey: tc.makePortalKeyFromID(ids.PeerTypeUser, call.AdminID, 0), CreatePortal: true, - Sender: t.senderForUserID(call.AdminID), + Sender: tc.senderForUserID(call.AdminID), LogContext: func(c zerolog.Context) zerolog.Context { return c.Str("tg_event", "updatePhoneCall") }, diff --git a/pkg/connector/ids.go b/pkg/connector/ids.go index 150bcaa5..b414c68c 100644 --- a/pkg/connector/ids.go +++ b/pkg/connector/ids.go @@ -23,18 +23,18 @@ import ( "go.mau.fi/mautrix-telegram/pkg/gotd/tg" ) -func (t *TelegramClient) makePortalKeyFromPeer(peer tg.PeerClass, topicID int) networkid.PortalKey { - key := ids.InternalPeerToPortalKey(peer, topicID, t.loginID) - if t.main.Bridge.Config.SplitPortals { - key.Receiver = t.userLogin.ID +func (tc *TelegramClient) makePortalKeyFromPeer(peer tg.PeerClass, topicID int) networkid.PortalKey { + key := ids.InternalPeerToPortalKey(peer, topicID, tc.loginID) + if tc.main.Bridge.Config.SplitPortals { + key.Receiver = tc.userLogin.ID } return key } -func (t *TelegramClient) makePortalKeyFromID(peerType ids.PeerType, chatID int64, topicID int) networkid.PortalKey { - key := ids.InternalMakePortalKey(peerType, chatID, topicID, t.loginID) - if t.main.Bridge.Config.SplitPortals { - key.Receiver = t.userLogin.ID +func (tc *TelegramClient) makePortalKeyFromID(peerType ids.PeerType, chatID int64, topicID int) networkid.PortalKey { + key := ids.InternalMakePortalKey(peerType, chatID, topicID, tc.loginID) + if tc.main.Bridge.Config.SplitPortals { + key.Receiver = tc.userLogin.ID } return key } diff --git a/pkg/connector/imagepack.go b/pkg/connector/imagepack.go index 95b70cc2..8640576e 100644 --- a/pkg/connector/imagepack.go +++ b/pkg/connector/imagepack.go @@ -49,8 +49,8 @@ import ( "go.mau.fi/mautrix-telegram/pkg/gotd/tgerr" ) -func (t *TelegramClient) fnListEmojiPacks(ce *commands.Event) { - resp, err := t.client.API().MessagesGetAllStickers(ce.Ctx, 0) +func (tc *TelegramClient) fnListEmojiPacks(ce *commands.Event) { + resp, err := tc.client.API().MessagesGetAllStickers(ce.Ctx, 0) if err != nil { ce.Reply("Failed to list image packs: %v", err) return @@ -76,7 +76,7 @@ func (t *TelegramClient) fnListEmojiPacks(ce *commands.Event) { ce.Reply("Your packs:\n\n%s", strings.Join(lines, "\n")) } -func (t *TelegramClient) fnUploadEmojiPack(ce *commands.Event) { +func (tc *TelegramClient) fnUploadEmojiPack(ce *commands.Event) { if len(ce.Args) < 3 || !strings.HasPrefix(ce.Args[1], "!") { ce.Reply("Usage: `$cmdprefix emoji-pack upload