handlematrix: implement group chat deletes (#126)
This commit is contained in:
@@ -28,6 +28,8 @@ import (
|
|||||||
"maunium.net/go/mautrix/bridgev2"
|
"maunium.net/go/mautrix/bridgev2"
|
||||||
"maunium.net/go/mautrix/bridgev2/database"
|
"maunium.net/go/mautrix/bridgev2/database"
|
||||||
"maunium.net/go/mautrix/event"
|
"maunium.net/go/mautrix/event"
|
||||||
|
|
||||||
|
"go.mau.fi/mautrix-telegram/pkg/connector/ids"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (tg *TelegramConnector) GetCapabilities() *bridgev2.NetworkGeneralCapabilities {
|
func (tg *TelegramConnector) GetCapabilities() *bridgev2.NetworkGeneralCapabilities {
|
||||||
@@ -58,7 +60,7 @@ func (tg *TelegramConnector) GetCapabilities() *bridgev2.NetworkGeneralCapabilit
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tg *TelegramConnector) GetBridgeInfoVersion() (info, capabilities int) {
|
func (tg *TelegramConnector) GetBridgeInfoVersion() (info, capabilities int) {
|
||||||
return 1, 6
|
return 1, 7
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO get these from getConfig instead of hardcoding?
|
// TODO get these from getConfig instead of hardcoding?
|
||||||
@@ -208,7 +210,7 @@ func makeTimerList() []jsontime.Milliseconds {
|
|||||||
var telegramTimers = makeTimerList()
|
var telegramTimers = makeTimerList()
|
||||||
|
|
||||||
func (t *TelegramClient) GetCapabilities(ctx context.Context, portal *bridgev2.Portal) *event.RoomFeatures {
|
func (t *TelegramClient) GetCapabilities(ctx context.Context, portal *bridgev2.Portal) *event.RoomFeatures {
|
||||||
baseID := "fi.mau.telegram.capabilities.2025_09_27"
|
baseID := "fi.mau.telegram.capabilities.2025_11_12"
|
||||||
feat := &event.RoomFeatures{
|
feat := &event.RoomFeatures{
|
||||||
Formatting: formattingCaps,
|
Formatting: formattingCaps,
|
||||||
File: fileCaps,
|
File: fileCaps,
|
||||||
@@ -251,11 +253,22 @@ func (t *TelegramClient) GetCapabilities(ctx context.Context, portal *bridgev2.P
|
|||||||
feat.File = premiumFileCaps
|
feat.File = premiumFileCaps
|
||||||
feat.ReactionCount = 3
|
feat.ReactionCount = 3
|
||||||
}
|
}
|
||||||
if portal.RoomType == database.RoomTypeDM {
|
portalMetadata := portal.Metadata.(*PortalMetadata)
|
||||||
|
peerType, _, _ := ids.ParsePortalID(portal.ID)
|
||||||
|
|
||||||
|
switch portal.RoomType {
|
||||||
|
case database.RoomTypeDM:
|
||||||
baseID += "+dm"
|
baseID += "+dm"
|
||||||
feat.DeleteChat = true
|
feat.DeleteChat = true
|
||||||
feat.DeleteChatForEveryone = true
|
feat.DeleteChatForEveryone = true
|
||||||
|
default:
|
||||||
|
// Group creators can delete the chat for everyone, unless it's a large channel
|
||||||
|
if peerType == ids.PeerTypeChat || portalMetadata.ParticipantsCount < 1000 {
|
||||||
|
baseID += "+deletablegroup"
|
||||||
|
feat.DeleteChatForEveryone = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
feat.ID = baseID
|
feat.ID = baseID
|
||||||
return feat
|
return feat
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ func (t *TelegramClient) getDMChatInfo(ctx context.Context, userID int64) (*brid
|
|||||||
func (t *TelegramClient) getGroupChatInfo(fullChat *tg.MessagesChatFull, chatID int64) (*bridgev2.ChatInfo, bool, error) {
|
func (t *TelegramClient) getGroupChatInfo(fullChat *tg.MessagesChatFull, chatID int64) (*bridgev2.ChatInfo, bool, error) {
|
||||||
var name *string
|
var name *string
|
||||||
var isBroadcastChannel, isMegagroup bool
|
var isBroadcastChannel, isMegagroup bool
|
||||||
|
var participantsCount int
|
||||||
for _, c := range fullChat.GetChats() {
|
for _, c := range fullChat.GetChats() {
|
||||||
if c.GetID() == chatID {
|
if c.GetID() == chatID {
|
||||||
switch chat := c.(type) {
|
switch chat := c.(type) {
|
||||||
@@ -134,6 +135,10 @@ func (t *TelegramClient) getGroupChatInfo(fullChat *tg.MessagesChatFull, chatID
|
|||||||
name = &chat.Title
|
name = &chat.Title
|
||||||
isBroadcastChannel = chat.Broadcast
|
isBroadcastChannel = chat.Broadcast
|
||||||
isMegagroup = chat.Megagroup
|
isMegagroup = chat.Megagroup
|
||||||
|
|
||||||
|
if value, ok := chat.GetParticipantsCount(); ok {
|
||||||
|
participantsCount = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -154,6 +159,7 @@ func (t *TelegramClient) getGroupChatInfo(fullChat *tg.MessagesChatFull, chatID
|
|||||||
meta := p.Metadata.(*PortalMetadata)
|
meta := p.Metadata.(*PortalMetadata)
|
||||||
_ = updatePortalLastSyncAt(ctx, p)
|
_ = updatePortalLastSyncAt(ctx, p)
|
||||||
_ = meta.SetIsSuperGroup(isMegagroup)
|
_ = meta.SetIsSuperGroup(isMegagroup)
|
||||||
|
meta.ParticipantsCount = participantsCount
|
||||||
|
|
||||||
if reactions, ok := fullChat.FullChat.GetAvailableReactions(); ok {
|
if reactions, ok := fullChat.FullChat.GetAvailableReactions(); ok {
|
||||||
switch typedReactions := reactions.(type) {
|
switch typedReactions := reactions.(type) {
|
||||||
@@ -444,6 +450,7 @@ func (t *TelegramClient) getDMPowerLevels(ghost *bridgev2.Ghost) *bridgev2.Power
|
|||||||
event.StateRoomAvatar: 0,
|
event.StateRoomAvatar: 0,
|
||||||
event.StateTopic: 0,
|
event.StateTopic: 0,
|
||||||
event.StateBeeperDisappearingTimer: 0,
|
event.StateBeeperDisappearingTimer: 0,
|
||||||
|
event.BeeperDeleteChat: 0,
|
||||||
}
|
}
|
||||||
return &plo
|
return &plo
|
||||||
}
|
}
|
||||||
@@ -500,6 +507,7 @@ func (t *TelegramClient) getPowerLevelOverridesFromBannedRights(entity tg.ChatCl
|
|||||||
event.StatePowerLevels: 85,
|
event.StatePowerLevels: 85,
|
||||||
event.StateHistoryVisibility: 85,
|
event.StateHistoryVisibility: 85,
|
||||||
event.StateBeeperDisappearingTimer: 85,
|
event.StateBeeperDisappearingTimer: 85,
|
||||||
|
event.BeeperDeleteChat: *creatorPowerLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
if dbr.ChangeInfo {
|
if dbr.ChangeInfo {
|
||||||
|
|||||||
@@ -805,22 +805,53 @@ func (t *TelegramClient) HandleMatrixDeleteChat(ctx context.Context, chat *bridg
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if chat.Portal.RoomType == database.RoomTypeDM {
|
switch peerType {
|
||||||
if chat.Content.DeleteForEveryone {
|
case ids.PeerTypeUser:
|
||||||
_, err := t.client.API().MessagesDeleteHistory(ctx, &tg.MessagesDeleteHistoryRequest{
|
accessHash, err := t.ScopedStore.GetAccessHash(ctx, peerType, id)
|
||||||
Peer: &tg.InputPeerUser{UserID: id},
|
|
||||||
Revoke: true,
|
|
||||||
MaxID: 0,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, err = t.client.API().MessagesDeleteChat(ctx, id)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
_, err = t.client.API().MessagesDeleteHistory(ctx, &tg.MessagesDeleteHistoryRequest{
|
||||||
|
Peer: &tg.InputPeerUser{UserID: id, AccessHash: accessHash},
|
||||||
|
JustClear: !chat.Content.DeleteForEveryone,
|
||||||
|
Revoke: chat.Content.DeleteForEveryone,
|
||||||
|
MaxID: 0,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case ids.PeerTypeChat:
|
||||||
|
if chat.Content.DeleteForEveryone {
|
||||||
|
result, err := t.client.API().MessagesDeleteChat(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !result {
|
||||||
|
return fmt.Errorf("failed to delete chat %d", id)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("deleting chat only supported for group creators")
|
||||||
|
}
|
||||||
|
case ids.PeerTypeChannel:
|
||||||
|
accessHash, err := t.ScopedStore.GetAccessHash(ctx, peerType, id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
channel := &tg.InputChannel{
|
||||||
|
ChannelID: id,
|
||||||
|
AccessHash: accessHash,
|
||||||
|
}
|
||||||
|
if chat.Content.DeleteForEveryone {
|
||||||
|
_, err := t.client.API().ChannelsDeleteChannel(ctx, channel)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("deleting chat only supported for channel creators")
|
||||||
|
}
|
||||||
|
default:
|
||||||
return fmt.Errorf("deleting chat not supported for peer type %s", peerType)
|
return fmt.Errorf("deleting chat not supported for peer type %s", peerType)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -50,10 +50,11 @@ type GhostMetadata struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PortalMetadata struct {
|
type PortalMetadata struct {
|
||||||
IsSuperGroup bool `json:"is_supergroup,omitempty"`
|
IsSuperGroup bool `json:"is_supergroup,omitempty"`
|
||||||
ReadUpTo int `json:"read_up_to,omitempty"`
|
ReadUpTo int `json:"read_up_to,omitempty"`
|
||||||
AllowedReactions []string `json:"allowed_reactions"`
|
AllowedReactions []string `json:"allowed_reactions"`
|
||||||
LastSync jsontime.Unix `json:"last_sync,omitempty"`
|
LastSync jsontime.Unix `json:"last_sync,omitempty"`
|
||||||
|
ParticipantsCount int `json:"member_count,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *PortalMetadata) SetIsSuperGroup(isSupergroup bool) (changed bool) {
|
func (pm *PortalMetadata) SetIsSuperGroup(isSupergroup bool) (changed bool) {
|
||||||
|
|||||||
Reference in New Issue
Block a user