connector: handle supergroup upgrades (#118)
Co-authored-by: Tulir Asokan <tulir@maunium.net>
This commit is contained in:
@@ -82,6 +82,8 @@ type TelegramConfig struct {
|
|||||||
AlwaysCustomEmojiReaction bool `yaml:"always_custom_emoji_reaction"`
|
AlwaysCustomEmojiReaction bool `yaml:"always_custom_emoji_reaction"`
|
||||||
|
|
||||||
SavedMessagesAvatar id.ContentURIString `yaml:"saved_message_avatar"`
|
SavedMessagesAvatar id.ContentURIString `yaml:"saved_message_avatar"`
|
||||||
|
|
||||||
|
AlwaysTombstoneOnSupergroupMigration bool `yaml:"always_tombstone_on_supergroup_migration"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c TelegramConfig) ShouldBridge(participantCount int) bool {
|
func (c TelegramConfig) ShouldBridge(participantCount int) bool {
|
||||||
@@ -120,6 +122,7 @@ func upgradeConfig(helper up.Helper) {
|
|||||||
helper.Copy(up.Bool, "sync", "direct_chats")
|
helper.Copy(up.Bool, "sync", "direct_chats")
|
||||||
helper.Copy(up.Bool, "always_custom_emoji_reaction")
|
helper.Copy(up.Bool, "always_custom_emoji_reaction")
|
||||||
helper.Copy(up.Str, "saved_message_avatar")
|
helper.Copy(up.Str, "saved_message_avatar")
|
||||||
|
helper.Copy(up.Bool, "always_tombstone_on_supergroup_migration")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tg *TelegramConnector) GetConfig() (example string, data any, upgrader up.Upgrader) {
|
func (tg *TelegramConnector) GetConfig() (example string, data any, upgrader up.Upgrader) {
|
||||||
|
|||||||
@@ -88,3 +88,6 @@ always_custom_emoji_reaction: false
|
|||||||
|
|
||||||
# The avatar to use for the Telegram Saved Messages chat
|
# The avatar to use for the Telegram Saved Messages chat
|
||||||
saved_message_avatar: mxc://nevarro.space/ZzzyOSDZfyGjKRRbyDPTweAA
|
saved_message_avatar: mxc://nevarro.space/ZzzyOSDZfyGjKRRbyDPTweAA
|
||||||
|
|
||||||
|
# Create a new room and tombstone the old one when upgrading rooms
|
||||||
|
always_tombstone_on_supergroup_migration: false
|
||||||
|
|||||||
@@ -534,8 +534,39 @@ func (t *TelegramClient) onUpdateNewMessage(ctx context.Context, entities tg.Ent
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// case *tg.MessageActionChatMigrateTo:
|
case *tg.MessageActionChatMigrateTo:
|
||||||
|
log.Debug().Int64("channel_id", action.ChannelID).Msg("MessageActionChatMigrateTo")
|
||||||
|
newPortalKey := t.makePortalKeyFromID(ids.PeerTypeChannel, action.ChannelID)
|
||||||
|
if err := t.migrateChat(ctx, eventMeta.PortalKey, newPortalKey); err != nil {
|
||||||
|
log.Err(err).Msg("Failed to migrate chat to channel")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
res := t.main.Bridge.QueueRemoteEvent(t.userLogin, &simplevent.Message[any]{
|
||||||
|
EventMeta: eventMeta.
|
||||||
|
WithPortalKey(newPortalKey).
|
||||||
|
WithStreamOrder(0).
|
||||||
|
WithType(bridgev2.RemoteEventMessage),
|
||||||
|
ID: ids.GetMessageIDFromMessage(msg),
|
||||||
|
ConvertMessageFunc: func(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, data any) (*bridgev2.ConvertedMessage, error) {
|
||||||
|
return &bridgev2.ConvertedMessage{
|
||||||
|
Parts: []*bridgev2.ConvertedMessagePart{
|
||||||
|
{
|
||||||
|
Type: event.EventMessage,
|
||||||
|
Content: &event.MessageEventContent{
|
||||||
|
MsgType: event.MsgNotice,
|
||||||
|
Body: "Upgraded this group to a supergroup",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err := resultToError(res); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// case *tg.MessageActionChannelMigrateFrom:
|
// case *tg.MessageActionChannelMigrateFrom:
|
||||||
|
|
||||||
// case *tg.MessageActionPinMessage:
|
// case *tg.MessageActionPinMessage:
|
||||||
// case *tg.MessageActionHistoryClear:
|
// case *tg.MessageActionHistoryClear:
|
||||||
// case *tg.MessageActionGameScore:
|
// case *tg.MessageActionGameScore:
|
||||||
@@ -579,6 +610,37 @@ func (t *TelegramClient) onUpdateNewMessage(ctx context.Context, entities tg.Ent
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TelegramClient) migrateChat(ctx context.Context, oldPortalKey, newPortalKey networkid.PortalKey) error {
|
||||||
|
if t.main.Config.AlwaysTombstoneOnSupergroupMigration {
|
||||||
|
newPortal, err := t.main.Bridge.GetPortalByKey(ctx, newPortalKey)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get new portal for chat migration: %w", err)
|
||||||
|
}
|
||||||
|
info, err := t.GetChatInfo(ctx, newPortal)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get chat info for new portal: %w", err)
|
||||||
|
}
|
||||||
|
err = newPortal.CreateMatrixRoom(ctx, t.userLogin, info)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create Matrix room for new portal: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result, portal, err := t.main.Bridge.ReIDPortal(ctx, oldPortalKey, newPortalKey)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to re-ID portal: %w", err)
|
||||||
|
} else if result == bridgev2.ReIDResultSourceReIDd || result == bridgev2.ReIDResultTargetDeletedAndSourceReIDd {
|
||||||
|
// If the source portal is re-ID'd, we need to sync metadata and participants.
|
||||||
|
// If the source is deleted, then it doesn't matter, any existing target will already be correct
|
||||||
|
info, err := t.GetChatInfo(ctx, portal)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get chat info for new portal: %w", err)
|
||||||
|
}
|
||||||
|
portal.UpdateInfo(ctx, info, t.userLogin, nil, time.Time{})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *TelegramClient) getEventSender(msg interface {
|
func (t *TelegramClient) getEventSender(msg interface {
|
||||||
GetOut() bool
|
GetOut() bool
|
||||||
GetFromID() (tg.PeerClass, bool)
|
GetFromID() (tg.PeerClass, bool)
|
||||||
|
|||||||
Reference in New Issue
Block a user