all: fix inconsistent method receiver names
This commit is contained in:
+47
-47
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
+61
-61
@@ -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
|
||||
|
||||
+45
-45
@@ -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),
|
||||
|
||||
+103
-103
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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/",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+105
-105
@@ -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
|
||||
`<strong>%s: %s</strong><blockquote>%s</blockquote><p>Sponsored message%s - <a href="%s">%s</a></p>`,
|
||||
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,
|
||||
|
||||
+228
-228
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
|
||||
+27
-27
@@ -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 <telegram shortcode> <room ID> <state key>`")
|
||||
return
|
||||
@@ -94,7 +94,7 @@ func (t *TelegramClient) fnUploadEmojiPack(ce *commands.Event) {
|
||||
tgPackShortcode := ce.Args[0]
|
||||
roomID := id.RoomID(ce.Args[1])
|
||||
packStateKey := strings.Join(ce.Args[2:], " ")
|
||||
err := t.main.Bridge.Bot.EnsureJoined(ce.Ctx, roomID)
|
||||
err := tc.main.Bridge.Bot.EnsureJoined(ce.Ctx, roomID)
|
||||
if err != nil {
|
||||
ce.Reply("Failed to join room: %v", err)
|
||||
return
|
||||
@@ -111,7 +111,7 @@ func (t *TelegramClient) fnUploadEmojiPack(ce *commands.Event) {
|
||||
}
|
||||
evtID := ce.React("\u23f3\ufe0f")
|
||||
defer redactReaction(ce, evtID)
|
||||
link, err := t.synchronizeEmojiPack(ce.Ctx, ce, pack, tgPackShortcode)
|
||||
link, err := tc.synchronizeEmojiPack(ce.Ctx, ce, pack, tgPackShortcode)
|
||||
if err != nil {
|
||||
ce.Reply("Failed to synchronize emoji pack: %v", err)
|
||||
return
|
||||
@@ -216,10 +216,10 @@ func normalizeImage(ctx context.Context, data []byte, info *event.FileInfo, emoj
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) synchronizeEmoji(
|
||||
func (tc *TelegramClient) synchronizeEmoji(
|
||||
ctx context.Context, shortcode string, img *event.ImagePackImage, emoji bool,
|
||||
) (*tg.InputStickerSetItem, func(int64) error, error) {
|
||||
data, err := t.main.Bridge.Bot.DownloadMedia(ctx, img.URL, nil)
|
||||
data, err := tc.main.Bridge.Bot.DownloadMedia(ctx, img.URL, nil)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to download %s (%s): %w", shortcode, img.URL, err)
|
||||
}
|
||||
@@ -243,11 +243,11 @@ func (t *TelegramClient) synchronizeEmoji(
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to normalize image for %s: %w", shortcode, err)
|
||||
}
|
||||
up, err := uploader.NewUploader(t.client.API()).FromBytes(ctx, "", data)
|
||||
up, err := uploader.NewUploader(tc.client.API()).FromBytes(ctx, "", data)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to reupload %s: %w", shortcode, err)
|
||||
}
|
||||
uploaded, err := t.client.API().MessagesUploadMedia(ctx, &tg.MessagesUploadMediaRequest{
|
||||
uploaded, err := tc.client.API().MessagesUploadMedia(ctx, &tg.MessagesUploadMediaRequest{
|
||||
Media: &tg.InputMediaUploadedDocument{
|
||||
File: up,
|
||||
ForceFile: true,
|
||||
@@ -270,7 +270,7 @@ func (t *TelegramClient) synchronizeEmoji(
|
||||
if realDocID == 0 {
|
||||
return fmt.Errorf("failed to get real document ID for %s/%d", shortcode, fakeDoc.ID)
|
||||
}
|
||||
err = t.main.Store.TelegramFile.Insert(ctx, &store.TelegramFile{
|
||||
err = tc.main.Store.TelegramFile.Insert(ctx, &store.TelegramFile{
|
||||
LocationID: store.TelegramFileLocationID(strconv.FormatInt(realDocID, 10)),
|
||||
MXC: img.URL,
|
||||
MIMEType: img.Info.MimeType,
|
||||
@@ -315,8 +315,8 @@ func extractNewDocID(oldSet tg.MessagesStickerSetClass, newSetBox tg.MessagesSti
|
||||
return found
|
||||
}
|
||||
|
||||
func (t *TelegramClient) synchronizeEmojiPack(ctx context.Context, ce *commands.Event, pack *event.ImagePackEventContent, packShortcode string) (string, error) {
|
||||
resp, err := t.client.API().StickersCheckShortName(ctx, packShortcode)
|
||||
func (tc *TelegramClient) synchronizeEmojiPack(ctx context.Context, ce *commands.Event, pack *event.ImagePackEventContent, packShortcode string) (string, error) {
|
||||
resp, err := tc.client.API().StickersCheckShortName(ctx, packShortcode)
|
||||
if err != nil && !tgerr.Is(err, tg.ErrShortNameOccupied) {
|
||||
return "", fmt.Errorf("failed to check if shortcode is available: %w", err)
|
||||
}
|
||||
@@ -331,11 +331,11 @@ func (t *TelegramClient) synchronizeEmojiPack(ctx context.Context, ce *commands.
|
||||
if img == nil {
|
||||
return "", fmt.Errorf("pack must contain at least one image")
|
||||
}
|
||||
item, saveCache, err := t.synchronizeEmoji(ctx, shortcode, img, isEmojiPack)
|
||||
item, saveCache, err := tc.synchronizeEmoji(ctx, shortcode, img, isEmojiPack)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to synchronize emoji %s: %w", shortcode, err)
|
||||
}
|
||||
rawSet, err = t.client.API().StickersCreateStickerSet(ctx, &tg.StickersCreateStickerSetRequest{
|
||||
rawSet, err = tc.client.API().StickersCreateStickerSet(ctx, &tg.StickersCreateStickerSetRequest{
|
||||
Emojis: isEmojiPack,
|
||||
UserID: &tg.InputUserSelf{},
|
||||
Title: cmp.Or(pack.Metadata.DisplayName, packShortcode),
|
||||
@@ -350,7 +350,7 @@ func (t *TelegramClient) synchronizeEmojiPack(ctx context.Context, ce *commands.
|
||||
return "", fmt.Errorf("failed to cache document ID for new pack: %w", err)
|
||||
}
|
||||
} else {
|
||||
rawSet, err = t.client.API().MessagesGetStickerSet(ctx, &tg.MessagesGetStickerSetRequest{
|
||||
rawSet, err = tc.client.API().MessagesGetStickerSet(ctx, &tg.MessagesGetStickerSetRequest{
|
||||
Stickerset: &tg.InputStickerSetShortName{ShortName: packShortcode},
|
||||
})
|
||||
if err != nil {
|
||||
@@ -372,7 +372,7 @@ func (t *TelegramClient) synchronizeEmojiPack(ctx context.Context, ce *commands.
|
||||
deletedMXCs := make(map[id.ContentURIString]*tg.InputDocument, len(set.Documents))
|
||||
existingMXCs := make(exmaps.Set[id.ContentURIString], len(set.Documents))
|
||||
for _, doc := range set.Documents {
|
||||
file, err := t.main.Store.TelegramFile.GetByLocationID(ctx, store.TelegramFileLocationID(strconv.FormatInt(doc.GetID(), 10)))
|
||||
file, err := tc.main.Store.TelegramFile.GetByLocationID(ctx, store.TelegramFileLocationID(strconv.FormatInt(doc.GetID(), 10)))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get cached file for doc %d: %w", doc.GetID(), err)
|
||||
} else if file != nil {
|
||||
@@ -386,12 +386,12 @@ func (t *TelegramClient) synchronizeEmojiPack(ctx context.Context, ce *commands.
|
||||
continue
|
||||
}
|
||||
existingMXCs.Add(img.URL)
|
||||
item, saveCache, err := t.synchronizeEmoji(ctx, shortcode, img, isEmojiPack)
|
||||
item, saveCache, err := tc.synchronizeEmoji(ctx, shortcode, img, isEmojiPack)
|
||||
if err != nil {
|
||||
ce.Reply("Failed to reupload %s: %v", shortcode, err)
|
||||
continue
|
||||
}
|
||||
rawNewSet, err := t.client.API().StickersAddStickerToSet(ctx, &tg.StickersAddStickerToSetRequest{
|
||||
rawNewSet, err := tc.client.API().StickersAddStickerToSet(ctx, &tg.StickersAddStickerToSetRequest{
|
||||
Stickerset: inputSet,
|
||||
Sticker: *item,
|
||||
})
|
||||
@@ -409,7 +409,7 @@ func (t *TelegramClient) synchronizeEmojiPack(ctx context.Context, ce *commands.
|
||||
rawSet = rawNewSet
|
||||
}
|
||||
for mxc, inputDoc := range deletedMXCs {
|
||||
_, err = t.client.API().StickersRemoveStickerFromSet(ctx, inputDoc)
|
||||
_, err = tc.client.API().StickersRemoveStickerFromSet(ctx, inputDoc)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to remove %s/%d from set: %w", mxc, inputDoc.ID, err)
|
||||
}
|
||||
@@ -435,12 +435,12 @@ func redactReaction(ce *commands.Event, evtID id.EventID) {
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func (t *TelegramClient) fnDownloadEmojiPack(ce *commands.Event) {
|
||||
func (tc *TelegramClient) fnDownloadEmojiPack(ce *commands.Event) {
|
||||
if len(ce.Args) == 0 {
|
||||
ce.Reply("Usage: `$cmdprefix emoji-pack download <pack shortcode or link>`")
|
||||
return
|
||||
}
|
||||
spaceRoom, err := t.userLogin.GetSpaceRoom(ce.Ctx)
|
||||
spaceRoom, err := tc.userLogin.GetSpaceRoom(ce.Ctx)
|
||||
if err != nil {
|
||||
ce.Reply("Failed to get space room: %v", err)
|
||||
return
|
||||
@@ -457,7 +457,7 @@ func (t *TelegramClient) fnDownloadEmojiPack(ce *commands.Event) {
|
||||
ce.Reply("Invalid pack shortcode or link.")
|
||||
return
|
||||
}
|
||||
rawSet, err := t.client.API().MessagesGetStickerSet(ce.Ctx, &tg.MessagesGetStickerSetRequest{Stickerset: input})
|
||||
rawSet, err := tc.client.API().MessagesGetStickerSet(ce.Ctx, &tg.MessagesGetStickerSetRequest{Stickerset: input})
|
||||
if err != nil {
|
||||
ce.Reply("Failed to get sticker set: %v", err)
|
||||
return
|
||||
@@ -496,11 +496,11 @@ func (t *TelegramClient) fnDownloadEmojiPack(ce *commands.Event) {
|
||||
evtID := ce.React("\u23f3\ufe0f")
|
||||
defer redactReaction(ce, evtID)
|
||||
for i, rawDoc := range set.Documents {
|
||||
mxc, _, info, err := media.NewTransferer(t.client.API()).
|
||||
WithStickerConfig(t.main.Config.AnimatedSticker).
|
||||
mxc, _, info, err := media.NewTransferer(tc.client.API()).
|
||||
WithStickerConfig(tc.main.Config.AnimatedSticker).
|
||||
WithForceWebmStickerConvert(set.Set.Emojis).
|
||||
WithDocument(rawDoc, false).
|
||||
Transfer(ce.Ctx, t.main.Store, t.main.Bridge.Bot)
|
||||
Transfer(ce.Ctx, tc.main.Store, tc.main.Bridge.Bot)
|
||||
if err != nil {
|
||||
ce.Log.Err(err).Msg("Failed to transfer image in pack")
|
||||
ce.Reply("Failed to transfer document `%d`: %v", rawDoc.GetID(), err)
|
||||
@@ -530,13 +530,13 @@ func (t *TelegramClient) fnDownloadEmojiPack(ce *commands.Event) {
|
||||
Info: info,
|
||||
}
|
||||
}
|
||||
_, err = t.main.Bridge.Bot.SendState(ce.Ctx, spaceRoom, event.StateUnstableImagePack, set.Set.ShortName, &event.Content{Parsed: pack}, time.Now())
|
||||
_, err = tc.main.Bridge.Bot.SendState(ce.Ctx, spaceRoom, event.StateUnstableImagePack, set.Set.ShortName, &event.Content{Parsed: pack}, time.Now())
|
||||
if err != nil {
|
||||
ce.Reply("Failed to send image pack to space: %v", err)
|
||||
} else {
|
||||
ce.Reply(
|
||||
"Successfully bridged image pack to %s",
|
||||
format.MarkdownLink("your personal filtering space",
|
||||
spaceRoom.URI(t.main.Bridge.Matrix.ServerName()).MatrixToURL()))
|
||||
spaceRoom.URI(tc.main.Bridge.Matrix.ServerName()).MatrixToURL()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func (tg *TelegramConnector) GetLoginFlows() []bridgev2.LoginFlow {
|
||||
func (tc *TelegramConnector) GetLoginFlows() []bridgev2.LoginFlow {
|
||||
return []bridgev2.LoginFlow{
|
||||
{
|
||||
Name: "Phone Number",
|
||||
@@ -84,10 +84,10 @@ func (tg *TelegramConnector) GetLoginFlows() []bridgev2.LoginFlow {
|
||||
}
|
||||
}
|
||||
|
||||
func (tg *TelegramConnector) CreateLogin(ctx context.Context, user *bridgev2.User, flowID string) (bridgev2.LoginProcess, error) {
|
||||
func (tc *TelegramConnector) CreateLogin(ctx context.Context, user *bridgev2.User, flowID string) (bridgev2.LoginProcess, error) {
|
||||
bl := &baseLogin{
|
||||
user: user,
|
||||
main: tg,
|
||||
main: tc,
|
||||
flowID: flowID,
|
||||
}
|
||||
switch flowID {
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/session"
|
||||
)
|
||||
|
||||
func (tg *TelegramConnector) GetDBMetaTypes() database.MetaTypes {
|
||||
func (tc *TelegramConnector) GetDBMetaTypes() database.MetaTypes {
|
||||
return database.MetaTypes{
|
||||
Ghost: func() any { return &GhostMetadata{} },
|
||||
Portal: func() any { return &PortalMetadata{} },
|
||||
|
||||
+19
-19
@@ -256,13 +256,13 @@ var PushMessageFormats = map[string]string{
|
||||
|
||||
var FullSyncOnConnectBackground = false
|
||||
|
||||
func (t *TelegramClient) ConnectBackground(ctx context.Context, params *bridgev2.ConnectBackgroundParams) error {
|
||||
func (tc *TelegramClient) ConnectBackground(ctx context.Context, params *bridgev2.ConnectBackgroundParams) error {
|
||||
data, _ := params.ExtraData.(*PushNotificationData)
|
||||
var relatedPortal *bridgev2.Portal
|
||||
var sender *bridgev2.Ghost
|
||||
var messageID networkid.MessageID
|
||||
var messageText, notificationText, notificationTitle string
|
||||
if notifs, ok := t.main.Bridge.Matrix.(bridgev2.MatrixConnectorWithNotifications); ok && data != nil {
|
||||
if notifs, ok := tc.main.Bridge.Matrix.(bridgev2.MatrixConnectorWithNotifications); ok && data != nil {
|
||||
if data.Aps != nil {
|
||||
notificationTitle = data.Aps.Alert.Title
|
||||
notificationText = data.Aps.Alert.Body
|
||||
@@ -282,23 +282,23 @@ func (t *TelegramClient) ConnectBackground(ctx context.Context, params *bridgev2
|
||||
}
|
||||
var err error
|
||||
if data.Custom.ChannelID != 0 {
|
||||
relatedPortal, err = t.main.Bridge.GetPortalByKey(ctx, t.makePortalKeyFromID(ids.PeerTypeChannel, data.Custom.ChannelID, data.Custom.TopicID))
|
||||
relatedPortal, err = tc.main.Bridge.GetPortalByKey(ctx, tc.makePortalKeyFromID(ids.PeerTypeChannel, data.Custom.ChannelID, data.Custom.TopicID))
|
||||
} else if data.Custom.ChatID != 0 {
|
||||
relatedPortal, err = t.main.Bridge.GetPortalByKey(ctx, t.makePortalKeyFromID(ids.PeerTypeChat, data.Custom.ChatID, 0))
|
||||
relatedPortal, err = tc.main.Bridge.GetPortalByKey(ctx, tc.makePortalKeyFromID(ids.PeerTypeChat, data.Custom.ChatID, 0))
|
||||
} else if data.Custom.FromID != 0 {
|
||||
relatedPortal, err = t.main.Bridge.GetPortalByKey(ctx, t.makePortalKeyFromID(ids.PeerTypeUser, data.Custom.FromID, 0))
|
||||
relatedPortal, err = tc.main.Bridge.GetPortalByKey(ctx, tc.makePortalKeyFromID(ids.PeerTypeUser, data.Custom.FromID, 0))
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get related portal: %w", err)
|
||||
}
|
||||
if data.Custom.ChatFromBroadcastID != 0 {
|
||||
sender, err = t.main.Bridge.GetGhostByID(ctx, ids.MakeChannelUserID(data.Custom.FromID))
|
||||
sender, err = tc.main.Bridge.GetGhostByID(ctx, ids.MakeChannelUserID(data.Custom.FromID))
|
||||
} else if data.Custom.ChatFromGroupID != 0 {
|
||||
sender, err = t.main.Bridge.GetGhostByID(ctx, ids.MakeChannelUserID(data.Custom.ChatFromGroupID))
|
||||
sender, err = tc.main.Bridge.GetGhostByID(ctx, ids.MakeChannelUserID(data.Custom.ChatFromGroupID))
|
||||
} else if data.Custom.ChatFromID != 0 {
|
||||
sender, err = t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(data.Custom.ChatFromID))
|
||||
sender, err = tc.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(data.Custom.ChatFromID))
|
||||
} else if data.Custom.FromID != 0 {
|
||||
sender, err = t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(data.Custom.FromID))
|
||||
sender, err = tc.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(data.Custom.FromID))
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get sender: %w", err)
|
||||
@@ -317,8 +317,8 @@ func (t *TelegramClient) ConnectBackground(ctx context.Context, params *bridgev2
|
||||
})
|
||||
}
|
||||
if FullSyncOnConnectBackground {
|
||||
t.Connect(ctx)
|
||||
defer t.Disconnect()
|
||||
tc.Connect(ctx)
|
||||
defer tc.Disconnect()
|
||||
// TODO is it possible to safely only sync one chat?
|
||||
select {
|
||||
case <-time.After(20 * time.Second):
|
||||
@@ -328,7 +328,7 @@ func (t *TelegramClient) ConnectBackground(ctx context.Context, params *bridgev2
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tg *TelegramConnector) ParsePushNotification(ctx context.Context, data json.RawMessage) (networkid.UserLoginID, any, error) {
|
||||
func (tc *TelegramConnector) ParsePushNotification(ctx context.Context, data json.RawMessage) (networkid.UserLoginID, any, error) {
|
||||
val := gjson.GetBytes(data, "p")
|
||||
if val.Type != gjson.String {
|
||||
return "", nil, fmt.Errorf("missing or invalid p field")
|
||||
@@ -342,7 +342,7 @@ func (tg *TelegramConnector) ParsePushNotification(ctx context.Context, data jso
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to decode auth key and message ID: %w", err)
|
||||
}
|
||||
userIDs, err := tg.Bridge.DB.UserLogin.GetAllUserIDsWithLogins(ctx)
|
||||
userIDs, err := tc.Bridge.DB.UserLogin.GetAllUserIDsWithLogins(ctx)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to get users with logins: %w", err)
|
||||
}
|
||||
@@ -350,7 +350,7 @@ func (tg *TelegramConnector) ParsePushNotification(ctx context.Context, data jso
|
||||
var userLoginID networkid.UserLoginID
|
||||
UserLoop:
|
||||
for _, userID := range userIDs {
|
||||
user, err := tg.Bridge.GetExistingUserByMXID(ctx, userID)
|
||||
user, err := tc.Bridge.GetExistingUserByMXID(ctx, userID)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to get user %s: %w", userID, err)
|
||||
}
|
||||
@@ -398,11 +398,11 @@ UserLoop:
|
||||
return userLoginID, &pmd, nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) RegisterPushNotifications(ctx context.Context, pushType bridgev2.PushType, token string) error {
|
||||
meta := t.metadata
|
||||
func (tc *TelegramClient) RegisterPushNotifications(ctx context.Context, pushType bridgev2.PushType, token string) error {
|
||||
meta := tc.metadata
|
||||
if meta.PushEncryptionKey == nil {
|
||||
meta.PushEncryptionKey = random.Bytes(256)
|
||||
err := t.userLogin.Save(ctx)
|
||||
err := tc.userLogin.Save(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to save push encryption key: %w", err)
|
||||
}
|
||||
@@ -418,7 +418,7 @@ func (t *TelegramClient) RegisterPushNotifications(ctx context.Context, pushType
|
||||
default:
|
||||
return fmt.Errorf("unsupported push type %s", pushType)
|
||||
}
|
||||
_, err := t.client.API().AccountRegisterDevice(ctx, &tg.AccountRegisterDeviceRequest{
|
||||
_, err := tc.client.API().AccountRegisterDevice(ctx, &tg.AccountRegisterDeviceRequest{
|
||||
NoMuted: true,
|
||||
TokenType: tokenType,
|
||||
Token: token,
|
||||
@@ -429,6 +429,6 @@ func (t *TelegramClient) RegisterPushNotifications(ctx context.Context, pushType
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *TelegramClient) GetPushConfigs() *bridgev2.PushConfig {
|
||||
func (tc *TelegramClient) GetPushConfigs() *bridgev2.PushConfig {
|
||||
return &bridgev2.PushConfig{Native: true}
|
||||
}
|
||||
|
||||
+34
-34
@@ -32,7 +32,7 @@ import (
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
|
||||
)
|
||||
|
||||
func (t *TelegramClient) computeReactionsList(ctx context.Context, peer tg.PeerClass, msgID int, msgReactions tg.MessageReactions) (reactions []tg.MessagePeerReaction, isFull bool, customEmojis map[networkid.EmojiID]emojis.EmojiInfo, err error) {
|
||||
func (tc *TelegramClient) computeReactionsList(ctx context.Context, peer tg.PeerClass, msgID int, msgReactions tg.MessageReactions) (reactions []tg.MessagePeerReaction, isFull bool, customEmojis map[networkid.EmojiID]emojis.EmojiInfo, err error) {
|
||||
log := zerolog.Ctx(ctx).With().Str("fn", "computeReactionsList").Logger()
|
||||
var totalCount int
|
||||
for _, r := range msgReactions.Results {
|
||||
@@ -54,18 +54,18 @@ func (t *TelegramClient) computeReactionsList(ctx context.Context, peer tg.PeerC
|
||||
|
||||
if len(reactionsList) < totalCount {
|
||||
if user, ok := peer.(*tg.PeerUser); ok {
|
||||
reactionsList = splitDMReactionCounts(msgReactions.Results, user.UserID, t.telegramUserID)
|
||||
} else if t.metadata.IsBot {
|
||||
reactionsList = splitDMReactionCounts(msgReactions.Results, user.UserID, tc.telegramUserID)
|
||||
} else if tc.metadata.IsBot {
|
||||
// Can't fetch exact reaction senders as a bot
|
||||
return
|
||||
|
||||
// TODO remove redundant peer roundtrip, just add a peer -> input peer helper
|
||||
} else if peer, _, err := t.inputPeerForPortalID(ctx, t.makePortalKeyFromPeer(peer, 0).ID); err != nil {
|
||||
} else if peer, _, err := tc.inputPeerForPortalID(ctx, tc.makePortalKeyFromPeer(peer, 0).ID); err != nil {
|
||||
return nil, false, nil, fmt.Errorf("failed to get input peer: %w", err)
|
||||
} else {
|
||||
// TODO should calls to this be limited?
|
||||
reactions, err := APICallWithUpdates(ctx, t, func() (*tg.MessagesMessageReactionsList, error) {
|
||||
return t.client.API().MessagesGetMessageReactionsList(ctx, &tg.MessagesGetMessageReactionsListRequest{
|
||||
reactions, err := APICallWithUpdates(ctx, tc, func() (*tg.MessagesMessageReactionsList, error) {
|
||||
return tc.client.API().MessagesGetMessageReactionsList(ctx, &tg.MessagesGetMessageReactionsListRequest{
|
||||
Peer: peer, ID: msgID, Limit: 100,
|
||||
})
|
||||
})
|
||||
@@ -85,7 +85,7 @@ func (t *TelegramClient) computeReactionsList(ctx context.Context, peer tg.PeerC
|
||||
}
|
||||
}
|
||||
|
||||
customEmojis, err = t.transferEmojisToMatrix(ctx, customEmojiIDs)
|
||||
customEmojis, err = tc.transferEmojisToMatrix(ctx, customEmojiIDs)
|
||||
return reactionsList, len(reactionsList) == totalCount, customEmojis, err
|
||||
}
|
||||
|
||||
@@ -105,8 +105,8 @@ func computeEmojiAndID(reaction tg.ReactionClass, customEmojis map[networkid.Emo
|
||||
return
|
||||
}
|
||||
|
||||
func (t *TelegramClient) prepareReactionSync(ctx context.Context, peer tg.PeerClass, msgID int, reactions tg.MessageReactions) (*bridgev2.ReactionSyncData, error) {
|
||||
reactionsList, isFull, customEmojis, err := t.computeReactionsList(ctx, peer, msgID, reactions)
|
||||
func (tc *TelegramClient) prepareReactionSync(ctx context.Context, peer tg.PeerClass, msgID int, reactions tg.MessageReactions) (*bridgev2.ReactionSyncData, error) {
|
||||
reactionsList, isFull, customEmojis, err := tc.computeReactionsList(ctx, peer, msgID, reactions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to compute reactions: %w", err)
|
||||
}
|
||||
@@ -119,18 +119,18 @@ func (t *TelegramClient) prepareReactionSync(ctx context.Context, peer tg.PeerCl
|
||||
switch senderPeer := reaction.PeerID.(type) {
|
||||
case *tg.PeerUser:
|
||||
userID = ids.MakeUserID(senderPeer.UserID)
|
||||
eventSender = t.senderForUserID(senderPeer.UserID)
|
||||
eventSender = tc.senderForUserID(senderPeer.UserID)
|
||||
case *tg.PeerChannel:
|
||||
userID = ids.MakeChannelUserID(senderPeer.ChannelID)
|
||||
eventSender = bridgev2.EventSender{
|
||||
Sender: userID,
|
||||
IsFromMe: reaction.My && t.main.Bridge.Config.SplitPortals,
|
||||
IsFromMe: reaction.My && tc.main.Bridge.Config.SplitPortals,
|
||||
}
|
||||
default:
|
||||
log.Debug().Type("peer_type", reaction.PeerID).Msg("Ignoring reaction from non-user peer")
|
||||
continue
|
||||
}
|
||||
reactionLimit, err := t.getReactionLimit(ctx, userID)
|
||||
reactionLimit, err := tc.getReactionLimit(ctx, userID)
|
||||
if err != nil {
|
||||
reactionLimit = 1
|
||||
log.Err(err).Str("id", string(userID)).Msg("failed to get reaction limit")
|
||||
@@ -155,24 +155,24 @@ func (t *TelegramClient) prepareReactionSync(ctx context.Context, peer tg.PeerCl
|
||||
return &bridgev2.ReactionSyncData{Users: users, HasAllUsers: isFull}, nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) handleTelegramReactions(ctx context.Context, peer tg.PeerClass, topicID, msgID int, reactions tg.MessageReactions) error {
|
||||
func (tc *TelegramClient) handleTelegramReactions(ctx context.Context, peer tg.PeerClass, topicID, msgID int, reactions tg.MessageReactions) error {
|
||||
ctx = zerolog.Ctx(ctx).With().
|
||||
Str("handler", "handle_telegram_reactions").
|
||||
Int("message_id", msgID).
|
||||
Logger().WithContext(ctx)
|
||||
|
||||
data, err := t.prepareReactionSync(ctx, peer, msgID, reactions)
|
||||
data, err := tc.prepareReactionSync(ctx, peer, msgID, reactions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resultToError(t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ReactionSync{
|
||||
return resultToError(tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ReactionSync{
|
||||
EventMeta: simplevent.EventMeta{
|
||||
Type: bridgev2.RemoteEventReactionSync,
|
||||
LogContext: func(c zerolog.Context) zerolog.Context {
|
||||
return c.Int("message_id", msgID)
|
||||
},
|
||||
PortalKey: t.makePortalKeyFromPeer(peer, topicID),
|
||||
PortalKey: tc.makePortalKeyFromPeer(peer, topicID),
|
||||
},
|
||||
TargetMessage: ids.MakeMessageID(peer, msgID),
|
||||
Reactions: data,
|
||||
@@ -198,13 +198,13 @@ func splitDMReactionCounts(res []tg.ReactionCount, theirUserID, myUserID int64)
|
||||
return
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getReactionLimit(ctx context.Context, sender networkid.UserID) (limit int, err error) {
|
||||
config, err := t.getAppConfigCached(ctx)
|
||||
func (tc *TelegramClient) getReactionLimit(ctx context.Context, sender networkid.UserID) (limit int, err error) {
|
||||
config, err := tc.getAppConfigCached(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
ghost, err := t.main.Bridge.GetGhostByID(ctx, sender)
|
||||
ghost, err := tc.main.Bridge.GetGhostByID(ctx, sender)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -223,27 +223,27 @@ func (t *TelegramClient) getReactionLimit(ctx context.Context, sender networkid.
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) maybePollForReactions(ctx context.Context, portal *bridgev2.Portal) error {
|
||||
func (tc *TelegramClient) maybePollForReactions(ctx context.Context, portal *bridgev2.Portal) error {
|
||||
// Only poll for reactions in supergroups
|
||||
if t.metadata.IsBot || portal == nil || !portal.Metadata.(*PortalMetadata).IsSuperGroup || portal.RoomType == database.RoomTypeSpace {
|
||||
if tc.metadata.IsBot || portal == nil || !portal.Metadata.(*PortalMetadata).IsSuperGroup || portal.RoomType == database.RoomTypeSpace {
|
||||
return nil
|
||||
}
|
||||
|
||||
t.prevReactionPollLock.Lock()
|
||||
prev, ok := t.prevReactionPoll[portal.PortalKey]
|
||||
tc.prevReactionPollLock.Lock()
|
||||
prev, ok := tc.prevReactionPoll[portal.PortalKey]
|
||||
if ok && time.Since(prev) > 20*time.Second {
|
||||
ok = false
|
||||
t.prevReactionPoll[portal.PortalKey] = time.Now()
|
||||
tc.prevReactionPoll[portal.PortalKey] = time.Now()
|
||||
}
|
||||
t.prevReactionPollLock.Unlock()
|
||||
tc.prevReactionPollLock.Unlock()
|
||||
if ok {
|
||||
return nil
|
||||
}
|
||||
return t.pollForReactions(ctx, portal.PortalKey)
|
||||
return tc.pollForReactions(ctx, portal.PortalKey)
|
||||
}
|
||||
|
||||
func (t *TelegramClient) pollForReactions(ctx context.Context, portalKey networkid.PortalKey) error {
|
||||
inputPeer, _, parseErr := t.inputPeerForPortalID(ctx, portalKey.ID)
|
||||
func (tc *TelegramClient) pollForReactions(ctx context.Context, portalKey networkid.PortalKey) error {
|
||||
inputPeer, _, parseErr := tc.inputPeerForPortalID(ctx, portalKey.ID)
|
||||
if parseErr != nil {
|
||||
return parseErr
|
||||
}
|
||||
@@ -254,7 +254,7 @@ func (t *TelegramClient) pollForReactions(ctx context.Context, portalKey network
|
||||
|
||||
log.Debug().Msg("Polling reactions for recent messages")
|
||||
|
||||
messages, err := t.main.Bridge.DB.Message.GetLastNInPortal(ctx, portalKey, 20)
|
||||
messages, err := tc.main.Bridge.DB.Message.GetLastNInPortal(ctx, portalKey, 20)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -267,8 +267,8 @@ func (t *TelegramClient) pollForReactions(ctx context.Context, portalKey network
|
||||
}
|
||||
}
|
||||
|
||||
updates, err := APICallWithUpdates(ctx, t, func() (*tg.Updates, error) {
|
||||
u, err := t.client.API().MessagesGetMessagesReactions(ctx, &tg.MessagesGetMessagesReactionsRequest{
|
||||
updates, err := APICallWithUpdates(ctx, tc, func() (*tg.Updates, error) {
|
||||
u, err := tc.client.API().MessagesGetMessagesReactions(ctx, &tg.MessagesGetMessagesReactionsRequest{
|
||||
Peer: inputPeer,
|
||||
ID: messageIDs,
|
||||
})
|
||||
@@ -291,19 +291,19 @@ func (t *TelegramClient) pollForReactions(ctx context.Context, portalKey network
|
||||
log.Warn().Type("update_type", update).Msg("Unexpected update type in get reactions response")
|
||||
continue
|
||||
}
|
||||
dbMsg, err := t.main.Bridge.DB.Message.GetFirstPartByID(ctx, t.loginID, ids.MakeMessageID(portalKey, reaction.MsgID))
|
||||
dbMsg, err := tc.main.Bridge.DB.Message.GetFirstPartByID(ctx, tc.loginID, ids.MakeMessageID(portalKey, reaction.MsgID))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get message from database: %w", err)
|
||||
} else if dbMsg == nil {
|
||||
return fmt.Errorf("message not found in database: %w", err)
|
||||
}
|
||||
|
||||
data, err := t.prepareReactionSync(ctx, reaction.Peer, reaction.MsgID, reaction.Reactions)
|
||||
data, err := tc.prepareReactionSync(ctx, reaction.Peer, reaction.MsgID, reaction.Reactions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.ReactionSync{
|
||||
res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ReactionSync{
|
||||
EventMeta: simplevent.EventMeta{
|
||||
Type: bridgev2.RemoteEventReactionSync,
|
||||
LogContext: func(c zerolog.Context) zerolog.Context {
|
||||
|
||||
+51
-51
@@ -42,32 +42,32 @@ var (
|
||||
_ bridgev2.GroupCreatingNetworkAPI = (*TelegramClient)(nil)
|
||||
)
|
||||
|
||||
func (t *TelegramClient) resolveUser(ctx context.Context, user tg.UserClass) (*bridgev2.ResolveIdentifierResponse, error) {
|
||||
func (tc *TelegramClient) resolveUser(ctx context.Context, user tg.UserClass) (*bridgev2.ResolveIdentifierResponse, error) {
|
||||
networkUserID := ids.MakeUserID(user.GetID())
|
||||
if ghost, err := t.main.Bridge.GetGhostByID(ctx, networkUserID); err != nil {
|
||||
if ghost, err := tc.main.Bridge.GetGhostByID(ctx, networkUserID); err != nil {
|
||||
return nil, fmt.Errorf("failed to get ghost: %w", err)
|
||||
} else if userInfo, err := t.wrapUserInfo(ctx, user, ghost); err != nil {
|
||||
} else if userInfo, err := tc.wrapUserInfo(ctx, user, ghost); err != nil {
|
||||
return nil, fmt.Errorf("failed to get user info: %w", err)
|
||||
} else {
|
||||
return t.makeResolveIdentifierResponse(ghost, user, userInfo), nil
|
||||
return tc.makeResolveIdentifierResponse(ghost, user, userInfo), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) makeResolveIdentifierResponse(ghost *bridgev2.Ghost, user tg.UserClass, info *bridgev2.UserInfo) *bridgev2.ResolveIdentifierResponse {
|
||||
func (tc *TelegramClient) makeResolveIdentifierResponse(ghost *bridgev2.Ghost, user tg.UserClass, info *bridgev2.UserInfo) *bridgev2.ResolveIdentifierResponse {
|
||||
return &bridgev2.ResolveIdentifierResponse{
|
||||
Ghost: ghost,
|
||||
UserID: ids.MakeUserID(user.GetID()),
|
||||
UserInfo: info,
|
||||
Chat: &bridgev2.CreateChatResponse{
|
||||
PortalKey: t.makePortalKeyFromID(ids.PeerTypeUser, user.GetID(), 0),
|
||||
PortalKey: tc.makePortalKeyFromID(ids.PeerTypeUser, user.GetID(), 0),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) resolveUserID(ctx context.Context, userID int64) (resp *bridgev2.ResolveIdentifierResponse, err error) {
|
||||
_, err = t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeUser, userID)
|
||||
func (tc *TelegramClient) resolveUserID(ctx context.Context, userID int64) (resp *bridgev2.ResolveIdentifierResponse, err error) {
|
||||
_, err = tc.ScopedStore.GetAccessHash(ctx, ids.PeerTypeUser, userID)
|
||||
if errors.Is(err, store.ErrNoAccessHash) {
|
||||
username, usernameErr := t.main.Store.Username.Get(ctx, ids.PeerTypeUser, userID)
|
||||
username, usernameErr := tc.main.Store.Username.Get(ctx, ids.PeerTypeUser, userID)
|
||||
if usernameErr != nil {
|
||||
return nil, fmt.Errorf("failed to get username after missing access hash: %w", usernameErr)
|
||||
} else if username != "" {
|
||||
@@ -75,7 +75,7 @@ func (t *TelegramClient) resolveUserID(ctx context.Context, userID int64) (resp
|
||||
Str("target_username", username).
|
||||
Int64("target_user_id", userID).
|
||||
Msg("Access hash not found for user ID, trying to look up username")
|
||||
return t.resolveUsername(ctx, username, userID)
|
||||
return tc.resolveUsername(ctx, username, userID)
|
||||
}
|
||||
return nil, fmt.Errorf("%w: %w", bridgev2.ErrResolveIdentifierTryNext, err)
|
||||
} else if err != nil {
|
||||
@@ -85,39 +85,39 @@ func (t *TelegramClient) resolveUserID(ctx context.Context, userID int64) (resp
|
||||
resp = &bridgev2.ResolveIdentifierResponse{
|
||||
UserID: networkUserID,
|
||||
Chat: &bridgev2.CreateChatResponse{
|
||||
PortalKey: t.makePortalKeyFromID(ids.PeerTypeUser, userID, 0),
|
||||
PortalKey: tc.makePortalKeyFromID(ids.PeerTypeUser, userID, 0),
|
||||
},
|
||||
}
|
||||
resp.Ghost, err = t.main.Bridge.GetExistingGhostByID(ctx, networkUserID)
|
||||
resp.Ghost, err = tc.main.Bridge.GetExistingGhostByID(ctx, networkUserID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get ghost: %w", err)
|
||||
} else if resp.Ghost == nil || resp.Ghost.Name == "" {
|
||||
// Try to fetch the user from Telegram
|
||||
if user, err := t.getSingleUser(ctx, userID); err != nil {
|
||||
if user, err := tc.getSingleUser(ctx, userID); err != nil {
|
||||
return nil, fmt.Errorf("failed to get user with ID %d: %w", userID, err)
|
||||
} else if user.TypeID() != tg.UserTypeID {
|
||||
return nil, fmt.Errorf("unexpected user type: %T", user)
|
||||
} else if userInfo, err := t.updateGhost(ctx, userID, user.(*tg.User)); err != nil {
|
||||
} else if userInfo, err := tc.updateGhost(ctx, userID, user.(*tg.User)); err != nil {
|
||||
return nil, fmt.Errorf("failed to update ghost: %w", err)
|
||||
} else {
|
||||
if resp.Ghost == nil {
|
||||
resp.Ghost, _ = t.main.Bridge.GetExistingGhostByID(ctx, networkUserID)
|
||||
resp.Ghost, _ = tc.main.Bridge.GetExistingGhostByID(ctx, networkUserID)
|
||||
}
|
||||
return t.makeResolveIdentifierResponse(resp.Ghost, user, userInfo), nil
|
||||
return tc.makeResolveIdentifierResponse(resp.Ghost, user, userInfo), nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *TelegramClient) resolveUsername(ctx context.Context, username string, expectedID int64) (*bridgev2.ResolveIdentifierResponse, error) {
|
||||
resolved, err := APICallWithUpdates(ctx, t, func() (*tg.ContactsResolvedPeer, error) {
|
||||
return t.client.API().ContactsResolveUsername(ctx, &tg.ContactsResolveUsernameRequest{
|
||||
func (tc *TelegramClient) resolveUsername(ctx context.Context, username string, expectedID int64) (*bridgev2.ResolveIdentifierResponse, error) {
|
||||
resolved, err := APICallWithUpdates(ctx, tc, func() (*tg.ContactsResolvedPeer, error) {
|
||||
return tc.client.API().ContactsResolveUsername(ctx, &tg.ContactsResolveUsernameRequest{
|
||||
Username: username,
|
||||
})
|
||||
})
|
||||
if tg.IsUsernameNotOccupied(err) {
|
||||
if expectedID != 0 {
|
||||
err = t.main.Store.Username.Delete(ctx, username)
|
||||
err = tc.main.Store.Username.Delete(ctx, username)
|
||||
if err != nil {
|
||||
zerolog.Ctx(ctx).Warn().Err(err).Str("username", username).
|
||||
Msg("Failed to delete stale username mapping")
|
||||
@@ -137,7 +137,7 @@ func (t *TelegramClient) resolveUsername(ctx context.Context, username string, e
|
||||
}
|
||||
for _, user := range resolved.GetUsers() {
|
||||
if user.GetID() == peer.GetUserID() {
|
||||
return t.resolveUser(ctx, user)
|
||||
return tc.resolveUser(ctx, user)
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("peer user not found in contact resolved response")
|
||||
@@ -154,7 +154,7 @@ func (t *TelegramClient) resolveUsername(ctx context.Context, username string, e
|
||||
// (some bots like @pic and @gif have 3 characters, fragment might allow 4 characters)
|
||||
var usernameRe = regexp.MustCompile(`^(?:(?:https?://)?t(?:elegram)?\.(?:me|dog)/|tg:/{0,2}resolve\?domain=|@)?([a-zA-Z]\w{3,30}[a-zA-Z\d])$`)
|
||||
|
||||
func (t *TelegramClient) ResolveIdentifier(ctx context.Context, identifier string, createChat bool) (*bridgev2.ResolveIdentifierResponse, error) {
|
||||
func (tc *TelegramClient) ResolveIdentifier(ctx context.Context, identifier string, createChat bool) (*bridgev2.ResolveIdentifierResponse, error) {
|
||||
log := zerolog.Ctx(ctx).With().Str("identifier", identifier).Logger()
|
||||
log.Debug().Msg("Resolving identifier")
|
||||
|
||||
@@ -164,35 +164,35 @@ func (t *TelegramClient) ResolveIdentifier(ctx context.Context, identifier strin
|
||||
|
||||
if identifier[0] == '+' {
|
||||
normalized := strings.TrimPrefix(identifier, "+")
|
||||
if userID, err := t.main.Store.PhoneNumber.GetUserID(ctx, normalized); err != nil {
|
||||
if userID, err := tc.main.Store.PhoneNumber.GetUserID(ctx, normalized); err != nil {
|
||||
return nil, fmt.Errorf("failed to get user ID by phone number: %w", err)
|
||||
} else if userID == 0 {
|
||||
log.Info().Msg("Phone number not found in database")
|
||||
return nil, nil
|
||||
} else {
|
||||
return t.resolveUserID(ctx, userID)
|
||||
return tc.resolveUserID(ctx, userID)
|
||||
}
|
||||
} else if userID, err := strconv.ParseInt(identifier, 10, 64); err == nil && userID > 0 {
|
||||
// This is an integer, try and parse it as a Telegram User ID
|
||||
return t.resolveUserID(ctx, userID)
|
||||
return tc.resolveUserID(ctx, userID)
|
||||
} else if match := usernameRe.FindStringSubmatch(identifier); match != nil && !strings.Contains(identifier, "__") {
|
||||
// This is a username
|
||||
entityType, userID, err := t.main.Store.Username.GetEntityID(ctx, match[1])
|
||||
entityType, userID, err := tc.main.Store.Username.GetEntityID(ctx, match[1])
|
||||
if entityType == ids.PeerTypeUser && (err == nil || userID != 0) {
|
||||
// We know this username.
|
||||
resp, err := t.resolveUserID(ctx, userID)
|
||||
resp, err := tc.resolveUserID(ctx, userID)
|
||||
if err == nil || !errors.Is(err, store.ErrNoAccessHash) {
|
||||
return resp, err
|
||||
}
|
||||
}
|
||||
return t.resolveUsername(ctx, match[1], 0)
|
||||
return tc.resolveUsername(ctx, match[1], 0)
|
||||
}
|
||||
return nil, fmt.Errorf("invalid identifier: %q (must be a phone number, username, or Telegram user ID)", identifier)
|
||||
}
|
||||
|
||||
func (t *TelegramClient) SearchUsers(ctx context.Context, query string) (resp []*bridgev2.ResolveIdentifierResponse, err error) {
|
||||
contactsFound, err := APICallWithUpdates(ctx, t, func() (*tg.ContactsFound, error) {
|
||||
return t.client.API().ContactsSearch(ctx, &tg.ContactsSearchRequest{Q: query})
|
||||
func (tc *TelegramClient) SearchUsers(ctx context.Context, query string) (resp []*bridgev2.ResolveIdentifierResponse, err error) {
|
||||
contactsFound, err := APICallWithUpdates(ctx, tc, func() (*tg.ContactsFound, error) {
|
||||
return tc.client.API().ContactsSearch(ctx, &tg.ContactsSearchRequest{Q: query})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -206,7 +206,7 @@ func (t *TelegramClient) SearchUsers(ctx context.Context, query string) (resp []
|
||||
if peer, ok := p.(*tg.PeerUser); !ok {
|
||||
return nil
|
||||
} else if user, ok := users[peer.GetUserID()]; ok {
|
||||
if r, err := t.resolveUser(ctx, user); err != nil {
|
||||
if r, err := tc.resolveUser(ctx, user); err != nil {
|
||||
return err
|
||||
} else {
|
||||
resp = append(resp, r)
|
||||
@@ -230,37 +230,37 @@ func (t *TelegramClient) SearchUsers(ctx context.Context, query string) (resp []
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) GetContactList(ctx context.Context) (resp []*bridgev2.ResolveIdentifierResponse, err error) {
|
||||
t.contactsLock.Lock()
|
||||
defer t.contactsLock.Unlock()
|
||||
func (tc *TelegramClient) GetContactList(ctx context.Context) (resp []*bridgev2.ResolveIdentifierResponse, err error) {
|
||||
tc.contactsLock.Lock()
|
||||
defer tc.contactsLock.Unlock()
|
||||
var contacts *tg.ContactsContacts
|
||||
if time.Since(t.lastContactReq) > 10*time.Minute {
|
||||
contacts, err = APICallWithOnlyUserUpdates(ctx, t, func() (*tg.ContactsContacts, error) {
|
||||
c, err := t.client.API().ContactsGetContacts(ctx, t.cachedContactsHash)
|
||||
if time.Since(tc.lastContactReq) > 10*time.Minute {
|
||||
contacts, err = APICallWithOnlyUserUpdates(ctx, tc, func() (*tg.ContactsContacts, error) {
|
||||
c, err := tc.client.API().ContactsGetContacts(ctx, tc.cachedContactsHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch typedResp := c.(type) {
|
||||
case *tg.ContactsContacts:
|
||||
t.cachedContacts = typedResp
|
||||
tc.cachedContacts = typedResp
|
||||
var h hasher.Hasher
|
||||
for _, contact := range t.cachedContacts.Contacts {
|
||||
for _, contact := range tc.cachedContacts.Contacts {
|
||||
h.Update(uint32(contact.UserID))
|
||||
}
|
||||
t.cachedContactsHash = h.Sum()
|
||||
tc.cachedContactsHash = h.Sum()
|
||||
case *tg.ContactsContactsNotModified:
|
||||
// No changes
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected contacts type: %T", c)
|
||||
}
|
||||
return t.cachedContacts, nil
|
||||
return tc.cachedContacts, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.lastContactReq = time.Now()
|
||||
tc.lastContactReq = time.Now()
|
||||
} else {
|
||||
contacts = t.cachedContacts
|
||||
contacts = tc.cachedContacts
|
||||
}
|
||||
users := map[int64]tg.UserClass{}
|
||||
for _, user := range contacts.GetUsers() {
|
||||
@@ -269,7 +269,7 @@ func (t *TelegramClient) GetContactList(ctx context.Context) (resp []*bridgev2.R
|
||||
|
||||
for _, contact := range contacts.Contacts {
|
||||
if user, ok := users[contact.UserID]; ok {
|
||||
if r, err := t.resolveUser(ctx, user); err != nil {
|
||||
if r, err := tc.resolveUser(ctx, user); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
resp = append(resp, r)
|
||||
@@ -282,7 +282,7 @@ func (t *TelegramClient) GetContactList(ctx context.Context) (resp []*bridgev2.R
|
||||
}
|
||||
|
||||
// TODO support channels
|
||||
func (t *TelegramClient) CreateGroup(ctx context.Context, params *bridgev2.GroupCreateParams) (*bridgev2.CreateChatResponse, error) {
|
||||
func (tc *TelegramClient) CreateGroup(ctx context.Context, params *bridgev2.GroupCreateParams) (*bridgev2.CreateChatResponse, error) {
|
||||
req := tg.MessagesCreateChatRequest{
|
||||
Title: ptr.Val(params.Name).Name,
|
||||
}
|
||||
@@ -291,13 +291,13 @@ func (t *TelegramClient) CreateGroup(ctx context.Context, params *bridgev2.Group
|
||||
return nil, fmt.Errorf("failed to parse user ID: %w", err)
|
||||
} else if peerType != ids.PeerTypeUser {
|
||||
return nil, fmt.Errorf("unexpected peer type: %s", peerType)
|
||||
} else if inputUser, err := t.getInputUser(ctx, userID); err != nil {
|
||||
} else if inputUser, err := tc.getInputUser(ctx, userID); err != nil {
|
||||
return nil, fmt.Errorf("failed to get input user: %w", err)
|
||||
} else {
|
||||
req.Users = append(req.Users, inputUser)
|
||||
}
|
||||
}
|
||||
invitedUsers, err := t.client.API().MessagesCreateChat(ctx, &req)
|
||||
invitedUsers, err := tc.client.API().MessagesCreateChat(ctx, &req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create chat: %w", err)
|
||||
}
|
||||
@@ -315,9 +315,9 @@ func (t *TelegramClient) CreateGroup(ctx context.Context, params *bridgev2.Group
|
||||
} else if chat, ok := chats[0].(*tg.Chat); !ok {
|
||||
return nil, fmt.Errorf("unexpected chat type: %T", chats[0])
|
||||
} else {
|
||||
portalKey := t.makePortalKeyFromID(ids.PeerTypeChat, chat.ID, 0)
|
||||
portalKey := tc.makePortalKeyFromID(ids.PeerTypeChat, chat.ID, 0)
|
||||
if params.RoomID != "" {
|
||||
portal, err := t.main.Bridge.GetPortalByKey(ctx, portalKey)
|
||||
portal, err := tc.main.Bridge.GetPortalByKey(ctx, portalKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -329,7 +329,7 @@ func (t *TelegramClient) CreateGroup(ctx context.Context, params *bridgev2.Group
|
||||
OverwriteOldPortal: true,
|
||||
TombstoneOldRoom: true,
|
||||
DeleteOldRoom: true,
|
||||
ChatInfoSource: t.userLogin,
|
||||
ChatInfoSource: tc.userLogin,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
+65
-65
@@ -79,7 +79,7 @@ func mediaHashID(ctx context.Context, m tg.MessageMediaClass) []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *TelegramClient) mediaToMatrix(
|
||||
func (tc *TelegramClient) mediaToMatrix(
|
||||
ctx context.Context,
|
||||
portal *bridgev2.Portal,
|
||||
intent bridgev2.MatrixAPI,
|
||||
@@ -106,10 +106,10 @@ func (c *TelegramClient) mediaToMatrix(
|
||||
},
|
||||
}, nil, nil
|
||||
case tg.MessageMediaPhotoTypeID, tg.MessageMediaDocumentTypeID:
|
||||
converted, disappearingSetting := c.convertMediaRequiringUpload(ctx, portal, intent, msg.ID, media, true)
|
||||
converted, disappearingSetting := tc.convertMediaRequiringUpload(ctx, portal, intent, msg.ID, media, true)
|
||||
return converted, disappearingSetting, mediaHashID(ctx, media)
|
||||
case tg.MessageMediaContactTypeID:
|
||||
return c.convertContact(media), nil, nil
|
||||
return tc.convertContact(media), nil, nil
|
||||
case tg.MessageMediaGeoTypeID, tg.MessageMediaGeoLiveTypeID, tg.MessageMediaVenueTypeID:
|
||||
return convertLocation(media), nil, nil
|
||||
case tg.MessageMediaPollTypeID:
|
||||
@@ -134,7 +134,7 @@ func (c *TelegramClient) mediaToMatrix(
|
||||
}
|
||||
}
|
||||
|
||||
func (c *TelegramClient) convertToMatrix(
|
||||
func (tc *TelegramClient) convertToMatrix(
|
||||
ctx context.Context,
|
||||
portal *bridgev2.Portal,
|
||||
intent bridgev2.MatrixAPI,
|
||||
@@ -143,7 +143,7 @@ func (c *TelegramClient) convertToMatrix(
|
||||
log := zerolog.Ctx(ctx).With().Str("conversion_direction", "to_matrix").Logger()
|
||||
ctx = log.WithContext(ctx)
|
||||
|
||||
if c.client == nil {
|
||||
if tc.client == nil {
|
||||
return nil, fmt.Errorf("telegram client is nil, we are likely logged out")
|
||||
}
|
||||
|
||||
@@ -153,9 +153,9 @@ func (c *TelegramClient) convertToMatrix(
|
||||
} else if peerType == ids.PeerTypeChannel && !portal.Metadata.(*PortalMetadata).IsSuperGroup {
|
||||
var sender *networkid.UserID
|
||||
if msg.Out {
|
||||
sender = &c.userID
|
||||
sender = &tc.userID
|
||||
} else if fromID, ok := msg.GetFromID(); ok {
|
||||
sender = ptr.Ptr(c.getPeerSender(fromID).Sender)
|
||||
sender = ptr.Ptr(tc.getPeerSender(fromID).Sender)
|
||||
}
|
||||
if sender != nil {
|
||||
profile, err := portal.PerMessageProfileForSender(ctx, *sender)
|
||||
@@ -171,11 +171,11 @@ func (c *TelegramClient) convertToMatrix(
|
||||
if len(msg.Message) > 0 {
|
||||
hasher.Write([]byte(msg.Message))
|
||||
|
||||
content := c.parseBodyAndHTML(ctx, msg.Message, msg.Entities)
|
||||
content := tc.parseBodyAndHTML(ctx, msg.Message, msg.Entities)
|
||||
if media, ok := msg.GetMedia(); ok && media.TypeID() == tg.MessageMediaWebPageTypeID {
|
||||
webpageCtx, webpageCtxCancel := context.WithTimeout(ctx, time.Second*5)
|
||||
defer webpageCtxCancel()
|
||||
preview, err := c.webpageToBeeperLinkPreview(webpageCtx, portal, intent, msg, media)
|
||||
preview, err := tc.webpageToBeeperLinkPreview(webpageCtx, portal, intent, msg, media)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to convert webpage to link preview")
|
||||
} else if preview != nil {
|
||||
@@ -191,7 +191,7 @@ func (c *TelegramClient) convertToMatrix(
|
||||
}
|
||||
|
||||
var contentURI id.ContentURIString
|
||||
mediaPart, disappearingSetting, mediaHashID := c.mediaToMatrix(ctx, portal, intent, msg)
|
||||
mediaPart, disappearingSetting, mediaHashID := tc.mediaToMatrix(ctx, portal, intent, msg)
|
||||
if mediaPart != nil {
|
||||
hasher.Write(mediaHashID)
|
||||
cm.Parts = append(cm.Parts, mediaPart)
|
||||
@@ -213,7 +213,7 @@ func (c *TelegramClient) convertToMatrix(
|
||||
}
|
||||
|
||||
if fwd, isForwarded := msg.GetFwdFrom(); isForwarded {
|
||||
err = c.addForwardHeader(ctx, cm.Parts[0], fwd)
|
||||
err = tc.addForwardHeader(ctx, cm.Parts[0], fwd)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to add forward header: %w", err)
|
||||
}
|
||||
@@ -231,7 +231,7 @@ func (c *TelegramClient) convertToMatrix(
|
||||
}
|
||||
}
|
||||
if replyTo.Quote {
|
||||
parsedQuote := c.parseBodyAndHTML(ctx, replyTo.QuoteText, replyTo.QuoteEntities)
|
||||
parsedQuote := tc.parseBodyAndHTML(ctx, replyTo.QuoteText, replyTo.QuoteEntities)
|
||||
parsedQuote.EnsureHasHTML()
|
||||
existingPart := cm.Parts[0]
|
||||
existingPart.Content.EnsureHasHTML()
|
||||
@@ -256,20 +256,20 @@ func (c *TelegramClient) convertToMatrix(
|
||||
return
|
||||
}
|
||||
|
||||
func (t *TelegramClient) addForwardHeader(ctx context.Context, part *bridgev2.ConvertedMessagePart, fwd tg.MessageFwdHeader) error {
|
||||
func (tc *TelegramClient) addForwardHeader(ctx context.Context, part *bridgev2.ConvertedMessagePart, fwd tg.MessageFwdHeader) error {
|
||||
var fwdFromText, fwdFromHTML string
|
||||
switch from := fwd.FromID.(type) {
|
||||
case *tg.PeerUser:
|
||||
user := t.main.Bridge.GetCachedUserLoginByID(ids.MakeUserLoginID(from.UserID))
|
||||
user := tc.main.Bridge.GetCachedUserLoginByID(ids.MakeUserLoginID(from.UserID))
|
||||
var mxid id.UserID
|
||||
if user != nil {
|
||||
mxid = user.UserMXID
|
||||
fwdFromText = cmp.Or(user.RemoteName, user.UserMXID.String())
|
||||
} else if ghost, err := t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(from.UserID)); err != nil {
|
||||
} else if ghost, err := tc.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(from.UserID)); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if ghost.Name == "" {
|
||||
info, err := t.GetUserInfo(ctx, ghost)
|
||||
info, err := tc.GetUserInfo(ctx, ghost)
|
||||
if err != nil {
|
||||
zerolog.Ctx(ctx).Warn().Err(err).Msg("Failed to get user info to add forward header")
|
||||
} else if info != nil {
|
||||
@@ -291,7 +291,7 @@ func (t *TelegramClient) addForwardHeader(ctx context.Context, part *bridgev2.Co
|
||||
unknownType = "unknown channel"
|
||||
channelID = ch.ChannelID
|
||||
}
|
||||
portal, err := t.main.Bridge.GetExistingPortalByKey(ctx, t.makePortalKeyFromPeer(from, 0))
|
||||
portal, err := tc.main.Bridge.GetExistingPortalByKey(ctx, tc.makePortalKeyFromPeer(from, 0))
|
||||
if err != nil {
|
||||
return err
|
||||
} else if portal != nil && portal.MXID != "" {
|
||||
@@ -309,7 +309,7 @@ func (t *TelegramClient) addForwardHeader(ctx context.Context, part *bridgev2.Co
|
||||
fwdFromHTML = unknownType
|
||||
}
|
||||
if channelID != 0 && fwdFromText == unknownType {
|
||||
ghost, err := t.main.Bridge.GetExistingGhostByID(ctx, ids.MakeChannelUserID(channelID))
|
||||
ghost, err := tc.main.Bridge.GetExistingGhostByID(ctx, ids.MakeChannelUserID(channelID))
|
||||
if err != nil {
|
||||
return err
|
||||
} else if ghost != nil && ghost.Name != "" {
|
||||
@@ -364,7 +364,7 @@ func (t *TelegramClient) addForwardHeader(ctx context.Context, part *bridgev2.Co
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) parseBodyAndHTML(ctx context.Context, message string, entities []tg.MessageEntityClass) *event.MessageEventContent {
|
||||
func (tc *TelegramClient) parseBodyAndHTML(ctx context.Context, message string, entities []tg.MessageEntityClass) *event.MessageEventContent {
|
||||
if len(entities) == 0 {
|
||||
return &event.MessageEventContent{MsgType: event.MsgText, Body: message}
|
||||
}
|
||||
@@ -376,16 +376,16 @@ func (t *TelegramClient) parseBodyAndHTML(ctx context.Context, message string, e
|
||||
customEmojiIDs = append(customEmojiIDs, entity.DocumentID)
|
||||
}
|
||||
}
|
||||
customEmojis, err := t.transferEmojisToMatrix(ctx, customEmojiIDs)
|
||||
customEmojis, err := tc.transferEmojisToMatrix(ctx, customEmojiIDs)
|
||||
if err != nil {
|
||||
zerolog.Ctx(ctx).Err(err).
|
||||
Ints64("emoji_ids", customEmojiIDs).
|
||||
Msg("Failed to transfer custom emojis to Matrix")
|
||||
}
|
||||
return telegramfmt.Parse(ctx, message, entities, t.telegramFmtParams.WithCustomEmojis(customEmojis))
|
||||
return telegramfmt.Parse(ctx, message, entities, tc.telegramFmtParams.WithCustomEmojis(customEmojis))
|
||||
}
|
||||
|
||||
func (c *TelegramClient) webpageToBeeperLinkPreview(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, msg *tg.Message, msgMedia tg.MessageMediaClass) (preview *event.BeeperLinkPreview, err error) {
|
||||
func (tc *TelegramClient) webpageToBeeperLinkPreview(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, msg *tg.Message, msgMedia tg.MessageMediaClass) (preview *event.BeeperLinkPreview, err error) {
|
||||
webpage, ok := msgMedia.(*tg.MessageMediaWebPage).Webpage.(*tg.WebPage)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
@@ -401,11 +401,11 @@ func (c *TelegramClient) webpageToBeeperLinkPreview(ctx context.Context, portal
|
||||
|
||||
if photo, ok := webpage.Photo.(*tg.Photo); ok {
|
||||
var fileInfo *event.FileInfo
|
||||
transferer := media.NewTransferer(c.client.API()).WithPhoto(photo)
|
||||
if c.main.useDirectMedia {
|
||||
preview.ImageURL, fileInfo, err = transferer.DirectDownloadURL(ctx, c.telegramUserID, portal, msg.ID, true, 0)
|
||||
transferer := media.NewTransferer(tc.client.API()).WithPhoto(photo)
|
||||
if tc.main.useDirectMedia {
|
||||
preview.ImageURL, fileInfo, err = transferer.DirectDownloadURL(ctx, tc.telegramUserID, portal, msg.ID, true, 0)
|
||||
} else {
|
||||
preview.ImageURL, preview.ImageEncryption, fileInfo, err = transferer.Transfer(ctx, c.main.Store, intent)
|
||||
preview.ImageURL, preview.ImageEncryption, fileInfo, err = transferer.Transfer(ctx, tc.main.Store, intent)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -422,7 +422,7 @@ func (c *TelegramClient) webpageToBeeperLinkPreview(ctx context.Context, portal
|
||||
return preview, nil
|
||||
}
|
||||
|
||||
func (c *TelegramClient) convertMediaRequiringUpload(
|
||||
func (tc *TelegramClient) convertMediaRequiringUpload(
|
||||
ctx context.Context,
|
||||
portal *bridgev2.Portal,
|
||||
intent bridgev2.MatrixAPI,
|
||||
@@ -443,7 +443,7 @@ func (c *TelegramClient) convertMediaRequiringUpload(
|
||||
// FIXME don't use raw map for fields in the FileInfo struct
|
||||
extraInfo := map[string]any{}
|
||||
|
||||
transferer := media.NewTransferer(c.client.API()).WithRoomID(portal.MXID)
|
||||
transferer := media.NewTransferer(tc.client.API()).WithRoomID(portal.MXID)
|
||||
var mediaTransferer *media.ReadyTransferer
|
||||
|
||||
if t, ok := msgMedia.(ttlable); ok {
|
||||
@@ -457,7 +457,7 @@ func (c *TelegramClient) convertMediaRequiringUpload(
|
||||
// This is a view-once message, set a low TTL.
|
||||
ttl = 15
|
||||
|
||||
if c.main.Config.DisableViewOnce {
|
||||
if tc.main.Config.DisableViewOnce {
|
||||
converted = &bridgev2.ConvertedMessagePart{
|
||||
Type: event.EventMessage,
|
||||
Content: &event.MessageEventContent{
|
||||
@@ -509,17 +509,17 @@ func (c *TelegramClient) convertMediaRequiringUpload(
|
||||
var thumbnailInfo *event.FileInfo
|
||||
var err error
|
||||
|
||||
thumbnailTransferer := media.NewTransferer(c.client.API()).
|
||||
thumbnailTransferer := media.NewTransferer(tc.client.API()).
|
||||
WithRoomID(portal.MXID).
|
||||
WithPhoto(photo)
|
||||
if c.main.useDirectMedia {
|
||||
thumbnailURL, thumbnailInfo, err = thumbnailTransferer.DirectDownloadURL(ctx, c.telegramUserID, portal, msgID, false, photo.ID)
|
||||
if tc.main.useDirectMedia {
|
||||
thumbnailURL, thumbnailInfo, err = thumbnailTransferer.DirectDownloadURL(ctx, tc.telegramUserID, portal, msgID, false, photo.ID)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to create direct download URL for thumbnail")
|
||||
}
|
||||
}
|
||||
if thumbnailURL == "" {
|
||||
thumbnailURL, thumbnailFile, thumbnailInfo, err = thumbnailTransferer.Transfer(ctx, c.main.Store, intent)
|
||||
thumbnailURL, thumbnailFile, thumbnailInfo, err = thumbnailTransferer.Transfer(ctx, tc.main.Store, intent)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to transfer thumbnail")
|
||||
}
|
||||
@@ -603,7 +603,7 @@ func (c *TelegramClient) convertMediaRequiringUpload(
|
||||
}
|
||||
}
|
||||
extraInfo["fi.mau.telegram.sticker"] = stickerInfo
|
||||
transferer = transferer.WithStickerConfig(c.main.Config.AnimatedSticker)
|
||||
transferer = transferer.WithStickerConfig(tc.main.Config.AnimatedSticker)
|
||||
case *tg.DocumentAttributeAnimated:
|
||||
isVideoGif = true
|
||||
extraInfo["fi.mau.telegram.gif"] = true
|
||||
@@ -622,7 +622,7 @@ func (c *TelegramClient) convertMediaRequiringUpload(
|
||||
// Strip filename so that we never render the caption
|
||||
content.FileName = ""
|
||||
|
||||
if c.main.Config.AnimatedSticker.Target == "webm" || (isVideo && !c.main.Config.AnimatedSticker.ConvertFromWebm) {
|
||||
if tc.main.Config.AnimatedSticker.Target == "webm" || (isVideo && !tc.main.Config.AnimatedSticker.ConvertFromWebm) {
|
||||
isVideoGif = true
|
||||
extraInfo["fi.mau.telegram.animated_sticker"] = true
|
||||
transferer.WithMIMEType("video/webm")
|
||||
@@ -646,17 +646,17 @@ func (c *TelegramClient) convertMediaRequiringUpload(
|
||||
var thumbnailInfo *event.FileInfo
|
||||
var err error
|
||||
|
||||
thumbnailTransferer := media.NewTransferer(c.client.API()).
|
||||
thumbnailTransferer := media.NewTransferer(tc.client.API()).
|
||||
WithRoomID(portal.MXID).
|
||||
WithDocument(document, true)
|
||||
if c.main.useDirectMedia {
|
||||
thumbnailURL, thumbnailInfo, err = thumbnailTransferer.DirectDownloadURL(ctx, c.telegramUserID, portal, msgID, true, document.ID)
|
||||
if tc.main.useDirectMedia {
|
||||
thumbnailURL, thumbnailInfo, err = thumbnailTransferer.DirectDownloadURL(ctx, tc.telegramUserID, portal, msgID, true, document.ID)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to create direct download URL for thumbnail")
|
||||
}
|
||||
}
|
||||
if thumbnailURL == "" {
|
||||
thumbnailURL, thumbnailFile, thumbnailInfo, err = thumbnailTransferer.Transfer(ctx, c.main.Store, intent)
|
||||
thumbnailURL, thumbnailFile, thumbnailInfo, err = thumbnailTransferer.Transfer(ctx, tc.main.Store, intent)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to transfer thumbnail")
|
||||
}
|
||||
@@ -681,24 +681,24 @@ func (c *TelegramClient) convertMediaRequiringUpload(
|
||||
}
|
||||
|
||||
var err error
|
||||
if c.main.useDirectMedia && (!isSticker || c.main.Config.AnimatedSticker.Target == "disable") {
|
||||
content.URL, content.Info, err = mediaTransferer.DirectDownloadURL(ctx, c.telegramUserID, portal, msgID, false, telegramMediaID)
|
||||
if tc.main.useDirectMedia && (!isSticker || tc.main.Config.AnimatedSticker.Target == "disable") {
|
||||
content.URL, content.Info, err = mediaTransferer.DirectDownloadURL(ctx, tc.telegramUserID, portal, msgID, false, telegramMediaID)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to create direct download URL for media")
|
||||
}
|
||||
}
|
||||
if content.URL == "" {
|
||||
content.URL, content.File, content.Info, err = mediaTransferer.Transfer(ctx, c.main.Store, intent)
|
||||
content.URL, content.File, content.Info, err = mediaTransferer.Transfer(ctx, tc.main.Store, intent)
|
||||
if err != nil {
|
||||
if tgerr.Is(err, tg.ErrFileReferenceExpired) && allowRefetch {
|
||||
log.Warn().Err(err).Msg("Failed to transfer media, trying to refetch from message")
|
||||
peerType, peerID, _, err := ids.ParsePortalID(portal.ID)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to parse portal ID to refetch media")
|
||||
} else if msgMedia, err = c.refetchMedia(ctx, peerType, peerID, msgID); err != nil {
|
||||
} else if msgMedia, err = tc.refetchMedia(ctx, peerType, peerID, msgID); err != nil {
|
||||
log.Err(err).Msg("Failed to refetch media after file reference expired error")
|
||||
} else {
|
||||
return c.convertMediaRequiringUpload(ctx, portal, intent, msgID, msgMedia, false)
|
||||
return tc.convertMediaRequiringUpload(ctx, portal, intent, msgID, msgMedia, false)
|
||||
}
|
||||
} else {
|
||||
log.Err(err).Msg("Failed to transfer media")
|
||||
@@ -738,9 +738,9 @@ func (c *TelegramClient) convertMediaRequiringUpload(
|
||||
return
|
||||
}
|
||||
|
||||
func (c *TelegramClient) convertContact(media tg.MessageMediaClass) *bridgev2.ConvertedMessagePart {
|
||||
func (tc *TelegramClient) convertContact(media tg.MessageMediaClass) *bridgev2.ConvertedMessagePart {
|
||||
contact := media.(*tg.MessageMediaContact)
|
||||
name := c.main.Config.FormatDisplayname(contact.FirstName, contact.LastName, "", false, contact.UserID)
|
||||
name := tc.main.Config.FormatDisplayname(contact.FirstName, contact.LastName, "", false, contact.UserID)
|
||||
formattedPhone := fmt.Sprintf("+%s", strings.TrimPrefix(contact.PhoneNumber, "+"))
|
||||
|
||||
content := event.MessageEventContent{
|
||||
@@ -751,7 +751,7 @@ func (c *TelegramClient) convertContact(media tg.MessageMediaClass) *bridgev2.Co
|
||||
content.Format = event.FormatHTML
|
||||
content.FormattedBody = fmt.Sprintf(
|
||||
`Shared contact info for <a href="%s">%s</a>: %s`,
|
||||
c.main.Bridge.Matrix.GhostIntent(ids.MakeUserID(contact.UserID)).GetMXID().URI().MatrixToURL(),
|
||||
tc.main.Bridge.Matrix.GhostIntent(ids.MakeUserID(contact.UserID)).GetMXID().URI().MatrixToURL(),
|
||||
html.EscapeString(name),
|
||||
html.EscapeString(formattedPhone),
|
||||
)
|
||||
@@ -940,50 +940,50 @@ func convertGame(media tg.MessageMediaClass) *bridgev2.ConvertedMessagePart {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *TelegramClient) convertUserProfilePhoto(ctx context.Context, user *tg.User, photo *tg.UserProfilePhoto) (*bridgev2.Avatar, error) {
|
||||
func (tc *TelegramClient) convertUserProfilePhoto(ctx context.Context, user *tg.User, photo *tg.UserProfilePhoto) (*bridgev2.Avatar, error) {
|
||||
avatar := &bridgev2.Avatar{
|
||||
ID: ids.MakeAvatarID(photo.PhotoID),
|
||||
}
|
||||
|
||||
if c.main.useDirectMedia {
|
||||
if tc.main.useDirectMedia {
|
||||
mediaID, err := ids.DirectMediaInfo{
|
||||
PeerType: ids.PeerTypeUser,
|
||||
PeerID: user.ID,
|
||||
UserID: c.telegramUserID,
|
||||
UserID: tc.telegramUserID,
|
||||
ID: photo.PhotoID,
|
||||
}.AsMediaID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if avatar.MXC, err = c.main.Bridge.Matrix.GenerateContentURI(ctx, mediaID); err != nil {
|
||||
if avatar.MXC, err = tc.main.Bridge.Matrix.GenerateContentURI(ctx, mediaID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
avatar.Hash = ids.HashMediaID(mediaID)
|
||||
} else {
|
||||
avatar.Get = func(ctx context.Context) (data []byte, err error) {
|
||||
// TODO determine if it's safe to unconditionally use the access hash from the user object here
|
||||
peer, err := c.getInputPeerUser(ctx, user.ID)
|
||||
peer, err := tc.getInputPeerUser(ctx, user.ID)
|
||||
if errors.Is(err, store.ErrNoAccessHash) {
|
||||
peer = &tg.InputPeerUser{
|
||||
UserID: user.ID,
|
||||
AccessHash: user.AccessHash,
|
||||
}
|
||||
if user.Min && c.metadata.IsBot {
|
||||
if user.Min && tc.metadata.IsBot {
|
||||
// Bots should use a zero access hash when only a min hash is available
|
||||
peer.AccessHash = 0
|
||||
}
|
||||
} else if err != nil {
|
||||
return nil, fmt.Errorf("failed to get peer: %w", err)
|
||||
}
|
||||
return media.NewTransferer(c.client.API()).WithPeerPhoto(peer, photo.PhotoID).DownloadBytes(ctx)
|
||||
return media.NewTransferer(tc.client.API()).WithPeerPhoto(peer, photo.PhotoID).DownloadBytes(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
return avatar, nil
|
||||
}
|
||||
|
||||
func (c *TelegramClient) convertChatPhoto(chat tg.InputPeerClass, rawChatPhoto tg.ChatPhotoClass) (*bridgev2.Avatar, error) {
|
||||
func (tc *TelegramClient) convertChatPhoto(chat tg.InputPeerClass, rawChatPhoto tg.ChatPhotoClass) (*bridgev2.Avatar, error) {
|
||||
var chatPhoto *tg.ChatPhoto
|
||||
switch typedChatPhoto := rawChatPhoto.(type) {
|
||||
case *tg.ChatPhotoEmpty:
|
||||
@@ -997,7 +997,7 @@ func (c *TelegramClient) convertChatPhoto(chat tg.InputPeerClass, rawChatPhoto t
|
||||
ID: ids.MakeAvatarID(chatPhoto.PhotoID),
|
||||
}
|
||||
|
||||
if c.main.useDirectMedia {
|
||||
if tc.main.useDirectMedia {
|
||||
var peerID int64
|
||||
var peerType ids.PeerType
|
||||
switch typedChat := chat.(type) {
|
||||
@@ -1016,28 +1016,28 @@ func (c *TelegramClient) convertChatPhoto(chat tg.InputPeerClass, rawChatPhoto t
|
||||
mediaID, err := ids.DirectMediaInfo{
|
||||
PeerType: peerType,
|
||||
PeerID: peerID,
|
||||
UserID: c.telegramUserID,
|
||||
UserID: tc.telegramUserID,
|
||||
ID: chatPhoto.PhotoID,
|
||||
}.AsMediaID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
todoRemove := c.main.Bridge.BackgroundCtx // TODO remove context parameter from GenerateContentURI
|
||||
if avatar.MXC, err = c.main.Bridge.Matrix.GenerateContentURI(todoRemove, mediaID); err != nil {
|
||||
todoRemove := tc.main.Bridge.BackgroundCtx // TODO remove context parameter from GenerateContentURI
|
||||
if avatar.MXC, err = tc.main.Bridge.Matrix.GenerateContentURI(todoRemove, mediaID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
avatar.Hash = ids.HashMediaID(mediaID)
|
||||
} else {
|
||||
avatar.Get = func(ctx context.Context) (data []byte, err error) {
|
||||
return media.NewTransferer(c.client.API()).WithPeerPhoto(chat, chatPhoto.PhotoID).DownloadBytes(ctx)
|
||||
return media.NewTransferer(tc.client.API()).WithPeerPhoto(chat, chatPhoto.PhotoID).DownloadBytes(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
return avatar, nil
|
||||
}
|
||||
|
||||
func (c *TelegramClient) convertPhoto(ctx context.Context, peerType ids.PeerType, peerID int64, photoClass tg.PhotoClass) (*bridgev2.Avatar, error) {
|
||||
func (tc *TelegramClient) convertPhoto(ctx context.Context, peerType ids.PeerType, peerID int64, photoClass tg.PhotoClass) (*bridgev2.Avatar, error) {
|
||||
photo, ok := photoClass.(*tg.Photo)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not a photo: %T", photoClass)
|
||||
@@ -1047,25 +1047,25 @@ func (c *TelegramClient) convertPhoto(ctx context.Context, peerType ids.PeerType
|
||||
ID: ids.MakeAvatarID(photo.GetID()),
|
||||
}
|
||||
|
||||
if c.main.useDirectMedia {
|
||||
if tc.main.useDirectMedia {
|
||||
mediaID, err := ids.DirectMediaInfo{
|
||||
PeerType: peerType,
|
||||
PeerID: peerID,
|
||||
UserID: c.telegramUserID,
|
||||
UserID: tc.telegramUserID,
|
||||
ID: photo.GetID(),
|
||||
}.AsMediaID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if avatar.MXC, err = c.main.Bridge.Matrix.GenerateContentURI(ctx, mediaID); err != nil {
|
||||
if avatar.MXC, err = tc.main.Bridge.Matrix.GenerateContentURI(ctx, mediaID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
avatar.Hash = ids.HashMediaID(mediaID)
|
||||
} else {
|
||||
avatar.Get = func(ctx context.Context) (data []byte, err error) {
|
||||
return media.NewTransferer(c.client.API()).WithPhoto(photo).DownloadBytes(ctx)
|
||||
return media.NewTransferer(tc.client.API()).WithPhoto(photo).DownloadBytes(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+42
-42
@@ -16,37 +16,37 @@ import (
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
|
||||
)
|
||||
|
||||
func (t *TelegramClient) GetUserInfo(ctx context.Context, ghost *bridgev2.Ghost) (*bridgev2.UserInfo, error) {
|
||||
func (tc *TelegramClient) GetUserInfo(ctx context.Context, ghost *bridgev2.Ghost) (*bridgev2.UserInfo, error) {
|
||||
peerType, id, err := ids.ParseUserID(ghost.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch peerType {
|
||||
case ids.PeerTypeUser:
|
||||
if user, err := t.getSingleUser(ctx, id); err != nil {
|
||||
if user, err := tc.getSingleUser(ctx, id); err != nil {
|
||||
return nil, fmt.Errorf("failed to get user %d: %w", id, err)
|
||||
} else {
|
||||
return t.wrapUserInfo(ctx, user, ghost)
|
||||
return tc.wrapUserInfo(ctx, user, ghost)
|
||||
}
|
||||
case ids.PeerTypeChannel:
|
||||
if channel, err := t.getSingleChannel(ctx, id); err != nil {
|
||||
if channel, err := tc.getSingleChannel(ctx, id); err != nil {
|
||||
return nil, fmt.Errorf("failed to get channel %d: %w", id, err)
|
||||
} else {
|
||||
return t.wrapChannelGhostInfo(ctx, channel)
|
||||
return tc.wrapChannelGhostInfo(ctx, channel)
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected peer type: %s", peerType)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getChatPeerForInputFromMessage(ctx context.Context, id int64, peerID tg.PeerClass) (tg.InputPeerClass, error) {
|
||||
func (tc *TelegramClient) getChatPeerForInputFromMessage(ctx context.Context, id int64, peerID tg.PeerClass) (tg.InputPeerClass, error) {
|
||||
switch typedChat := peerID.(type) {
|
||||
case *tg.PeerUser:
|
||||
if id == typedChat.UserID {
|
||||
// We don't have the user's access hash
|
||||
return nil, nil
|
||||
}
|
||||
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeUser, typedChat.UserID)
|
||||
accessHash, err := tc.ScopedStore.GetAccessHash(ctx, ids.PeerTypeUser, typedChat.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func (t *TelegramClient) getChatPeerForInputFromMessage(ctx context.Context, id
|
||||
// We don't have the channel's access hash
|
||||
return nil, nil
|
||||
}
|
||||
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, typedChat.ChannelID)
|
||||
accessHash, err := tc.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, typedChat.ChannelID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -68,12 +68,12 @@ func (t *TelegramClient) getChatPeerForInputFromMessage(ctx context.Context, id
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getInputUserFromContext(ctx context.Context, id int64) (*tg.InputUserFromMessage, error) {
|
||||
func (tc *TelegramClient) getInputUserFromContext(ctx context.Context, id int64) (*tg.InputUserFromMessage, error) {
|
||||
msg, ok := bridgev2.GetRemoteEventFromContext(ctx).(*simplevent.Message[*tg.Message])
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
inputPeer, err := t.getChatPeerForInputFromMessage(ctx, id, msg.Data.PeerID)
|
||||
inputPeer, err := tc.getChatPeerForInputFromMessage(ctx, id, msg.Data.PeerID)
|
||||
if err != nil || inputPeer == nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -84,12 +84,12 @@ func (t *TelegramClient) getInputUserFromContext(ctx context.Context, id int64)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getInputChannelFromContext(ctx context.Context, id int64) (*tg.InputChannelFromMessage, error) {
|
||||
func (tc *TelegramClient) getInputChannelFromContext(ctx context.Context, id int64) (*tg.InputChannelFromMessage, error) {
|
||||
msg, ok := bridgev2.GetRemoteEventFromContext(ctx).(*simplevent.Message[*tg.Message])
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
inputPeer, err := t.getChatPeerForInputFromMessage(ctx, id, msg.Data.PeerID)
|
||||
inputPeer, err := tc.getChatPeerForInputFromMessage(ctx, id, msg.Data.PeerID)
|
||||
if err != nil || inputPeer == nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -100,10 +100,10 @@ func (t *TelegramClient) getInputChannelFromContext(ctx context.Context, id int6
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getInputUser(ctx context.Context, id int64) (tg.InputUserClass, error) {
|
||||
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeUser, id)
|
||||
func (tc *TelegramClient) getInputUser(ctx context.Context, id int64) (tg.InputUserClass, error) {
|
||||
accessHash, err := tc.ScopedStore.GetAccessHash(ctx, ids.PeerTypeUser, id)
|
||||
if errors.Is(err, store.ErrNoAccessHash) {
|
||||
fromMsg, fromMsgErr := t.getInputUserFromContext(ctx, id)
|
||||
fromMsg, fromMsgErr := tc.getInputUserFromContext(ctx, id)
|
||||
if fromMsgErr != nil {
|
||||
return nil, fmt.Errorf("%w, also failed to get from message: %w", err, fromMsgErr)
|
||||
} else if fromMsg == nil {
|
||||
@@ -119,8 +119,8 @@ func (t *TelegramClient) getInputUser(ctx context.Context, id int64) (tg.InputUs
|
||||
return &tg.InputUser{UserID: id, AccessHash: accessHash}, nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getInputPeerUser(ctx context.Context, id int64) (*tg.InputPeerUser, error) {
|
||||
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeUser, id)
|
||||
func (tc *TelegramClient) getInputPeerUser(ctx context.Context, id int64) (*tg.InputPeerUser, error) {
|
||||
accessHash, err := tc.ScopedStore.GetAccessHash(ctx, ids.PeerTypeUser, id)
|
||||
if errors.Is(err, store.ErrNoAccessHash) {
|
||||
return nil, err
|
||||
} else if err != nil {
|
||||
@@ -129,10 +129,10 @@ func (t *TelegramClient) getInputPeerUser(ctx context.Context, id int64) (*tg.In
|
||||
return &tg.InputPeerUser{UserID: id, AccessHash: accessHash}, nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getSingleUser(ctx context.Context, id int64) (tg.UserClass, error) {
|
||||
if inputUser, err := t.getInputUser(ctx, id); err != nil {
|
||||
func (tc *TelegramClient) getSingleUser(ctx context.Context, id int64) (tg.UserClass, error) {
|
||||
if inputUser, err := tc.getInputUser(ctx, id); err != nil {
|
||||
return nil, err
|
||||
} else if users, err := t.client.API().UsersGetUsers(ctx, []tg.InputUserClass{inputUser}); err != nil {
|
||||
} else if users, err := tc.client.API().UsersGetUsers(ctx, []tg.InputUserClass{inputUser}); err != nil {
|
||||
return nil, err
|
||||
} else if len(users) == 0 {
|
||||
// TODO does this mean the user is deleted? Need to handle this a bit better
|
||||
@@ -142,10 +142,10 @@ func (t *TelegramClient) getSingleUser(ctx context.Context, id int64) (tg.UserCl
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getInputChannel(ctx context.Context, id int64) (tg.InputChannelClass, error) {
|
||||
accessHash, err := t.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, id)
|
||||
func (tc *TelegramClient) getInputChannel(ctx context.Context, id int64) (tg.InputChannelClass, error) {
|
||||
accessHash, err := tc.ScopedStore.GetAccessHash(ctx, ids.PeerTypeChannel, id)
|
||||
if err != nil {
|
||||
fromMsg, fromMsgErr := t.getInputChannelFromContext(ctx, id)
|
||||
fromMsg, fromMsgErr := tc.getInputChannelFromContext(ctx, id)
|
||||
if fromMsgErr != nil {
|
||||
return nil, fmt.Errorf("%w, also failed to get from message: %w", err, fromMsgErr)
|
||||
} else if fromMsg == nil {
|
||||
@@ -159,13 +159,13 @@ func (t *TelegramClient) getInputChannel(ctx context.Context, id int64) (tg.Inpu
|
||||
return &tg.InputChannel{ChannelID: id, AccessHash: accessHash}, nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) getSingleChannel(ctx context.Context, id int64) (*tg.Channel, error) {
|
||||
inputChannel, err := t.getInputChannel(ctx, id)
|
||||
func (tc *TelegramClient) getSingleChannel(ctx context.Context, id int64) (*tg.Channel, error) {
|
||||
inputChannel, err := tc.getInputChannel(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chats, err := APICallWithOnlyChatUpdates(ctx, t, func() (tg.MessagesChatsClass, error) {
|
||||
return t.client.API().ChannelsGetChannels(ctx, []tg.InputChannelClass{inputChannel})
|
||||
chats, err := APICallWithOnlyChatUpdates(ctx, tc, func() (tg.MessagesChatsClass, error) {
|
||||
return tc.client.API().ChannelsGetChannels(ctx, []tg.InputChannelClass{inputChannel})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -178,23 +178,23 @@ func (t *TelegramClient) getSingleChannel(ctx context.Context, id int64) (*tg.Ch
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TelegramClient) wrapChannelGhostInfo(ctx context.Context, channel *tg.Channel) (*bridgev2.UserInfo, error) {
|
||||
func (tc *TelegramClient) wrapChannelGhostInfo(ctx context.Context, channel *tg.Channel) (*bridgev2.UserInfo, error) {
|
||||
var err error
|
||||
if accessHash, ok := channel.GetAccessHash(); ok && !channel.Min {
|
||||
if err = t.ScopedStore.SetAccessHash(ctx, ids.PeerTypeChannel, channel.ID, accessHash); err != nil {
|
||||
if err = tc.ScopedStore.SetAccessHash(ctx, ids.PeerTypeChannel, channel.ID, accessHash); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var avatar *bridgev2.Avatar
|
||||
avatar, err = t.convertChatPhoto(channel.AsInputPeer(), channel.GetPhoto())
|
||||
avatar, err = tc.convertChatPhoto(channel.AsInputPeer(), channel.GetPhoto())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var identifiers []string
|
||||
if username, set := channel.GetUsername(); set {
|
||||
err = t.main.Store.Username.Set(ctx, ids.PeerTypeChannel, channel.ID, username)
|
||||
err = tc.main.Store.Username.Set(ctx, ids.PeerTypeChannel, channel.ID, username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -208,7 +208,7 @@ func (t *TelegramClient) wrapChannelGhostInfo(ctx context.Context, channel *tg.C
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) wrapUserInfo(ctx context.Context, u tg.UserClass, ghost *bridgev2.Ghost) (*bridgev2.UserInfo, error) {
|
||||
func (tc *TelegramClient) wrapUserInfo(ctx context.Context, u tg.UserClass, ghost *bridgev2.Ghost) (*bridgev2.UserInfo, error) {
|
||||
oldMeta := ghost.Metadata.(*GhostMetadata)
|
||||
user, ok := u.(*tg.User)
|
||||
if !ok {
|
||||
@@ -217,12 +217,12 @@ func (t *TelegramClient) wrapUserInfo(ctx context.Context, u tg.UserClass, ghost
|
||||
var identifiers []string
|
||||
if !user.Min {
|
||||
if accessHash, ok := user.GetAccessHash(); ok {
|
||||
if err := t.ScopedStore.SetAccessHash(ctx, ids.PeerTypeUser, user.ID, accessHash); err != nil {
|
||||
if err := tc.ScopedStore.SetAccessHash(ctx, ids.PeerTypeUser, user.ID, accessHash); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := t.main.Store.Username.Set(ctx, ids.PeerTypeUser, user.ID, user.Username); err != nil {
|
||||
if err := tc.main.Store.Username.Set(ctx, ids.PeerTypeUser, user.ID, user.Username); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ func (t *TelegramClient) wrapUserInfo(ctx context.Context, u tg.UserClass, ghost
|
||||
if phone, ok := user.GetPhone(); ok {
|
||||
normalized := strings.TrimPrefix(phone, "+")
|
||||
identifiers = append(identifiers, fmt.Sprintf("tel:+%s", normalized))
|
||||
if err := t.main.Store.PhoneNumber.Set(ctx, user.ID, normalized); err != nil {
|
||||
if err := tc.main.Store.PhoneNumber.Set(ctx, user.ID, normalized); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -249,17 +249,17 @@ func (t *TelegramClient) wrapUserInfo(ctx context.Context, u tg.UserClass, ghost
|
||||
(!user.Min || user.ApplyMinPhoto || oldMeta.IsMin()) &&
|
||||
// Hack: check ApplyMinPhoto in addition to Personal, because some personalized avatars
|
||||
// only have the ApplyMinPhoto flag and not Personal.
|
||||
((!photo.Personal && user.ApplyMinPhoto) || t.main.Config.ContactAvatars) {
|
||||
((!photo.Personal && user.ApplyMinPhoto) || tc.main.Config.ContactAvatars) {
|
||||
var err error
|
||||
avatar, err = t.convertUserProfilePhoto(ctx, user, photo)
|
||||
avatar, err = tc.convertUserProfilePhoto(ctx, user, photo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
name := t.main.Config.FormatDisplayname(user.FirstName, user.LastName, user.Username, user.Deleted, user.ID)
|
||||
name := tc.main.Config.FormatDisplayname(user.FirstName, user.LastName, user.Username, user.Deleted, user.ID)
|
||||
namePtr := &name
|
||||
if user.Contact && ghost.Name != "" && oldMeta.ContactSource != t.telegramUserID && oldMeta.ContactSource != 0 && !t.main.Config.ContactNames {
|
||||
if user.Contact && ghost.Name != "" && oldMeta.ContactSource != tc.telegramUserID && oldMeta.ContactSource != 0 && !tc.main.Config.ContactNames {
|
||||
namePtr = nil
|
||||
}
|
||||
if user.Min && !oldMeta.IsMin() && ghost.Name != "" {
|
||||
@@ -277,9 +277,9 @@ func (t *TelegramClient) wrapUserInfo(ctx context.Context, u tg.UserClass, ghost
|
||||
meta.IsPremium = user.Premium
|
||||
meta.Deleted = user.Deleted
|
||||
meta.NotMin = true
|
||||
if meta.ContactSource == 0 || meta.ContactSource == t.telegramUserID || (!user.Contact && meta.SourceIsContact) {
|
||||
changed = changed || meta.ContactSource != t.telegramUserID || meta.SourceIsContact != user.Contact
|
||||
meta.ContactSource = t.telegramUserID
|
||||
if meta.ContactSource == 0 || meta.ContactSource == tc.telegramUserID || (!user.Contact && meta.SourceIsContact) {
|
||||
changed = changed || meta.ContactSource != tc.telegramUserID || meta.SourceIsContact != user.Contact
|
||||
meta.ContactSource = tc.telegramUserID
|
||||
meta.SourceIsContact = user.Contact
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user