connector: support messages sent by a channel
Signed-off-by: Sumner Evans <sumner.evans@automattic.com> Co-authored-by: Tulir Asokan <tulir@maunium.net>
This commit is contained in:
@@ -45,7 +45,7 @@ func APICallWithUpdates[U hasUpdates](ctx context.Context, t *TelegramClient, fn
|
|||||||
|
|
||||||
for _, c := range resp.GetChats() {
|
for _, c := range resp.GetChats() {
|
||||||
if channel, ok := c.(*tg.Channel); ok {
|
if channel, ok := c.(*tg.Channel); ok {
|
||||||
if err := t.ScopedStore.SetAccessHash(ctx, channel.ID, channel.AccessHash); err != nil {
|
if err := t.updateChannel(ctx, channel); err != nil {
|
||||||
return *new(U), err
|
return *new(U), err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,6 +216,15 @@ func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Porta
|
|||||||
// TODO save emojiset?
|
// TODO save emojiset?
|
||||||
|
|
||||||
chatInfo.Members.IsFull = false
|
chatInfo.Members.IsFull = false
|
||||||
|
if !portal.Metadata.(*PortalMetadata).IsSuperGroup {
|
||||||
|
// Add the channel user
|
||||||
|
chatInfo.Members.MemberMap[ids.MakeUserID(id)] = bridgev2.ChatMember{
|
||||||
|
EventSender: bridgev2.EventSender{
|
||||||
|
SenderLogin: ids.MakeUserLoginID(id),
|
||||||
|
Sender: ids.MakeUserID(id),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Just return the current user as a member if we can't view the
|
// Just return the current user as a member if we can't view the
|
||||||
// participants or the max initial sync is 0.
|
// participants or the max initial sync is 0.
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ func (tg *TelegramConnector) GetDBMetaTypes() database.MetaTypes {
|
|||||||
type GhostMetadata struct {
|
type GhostMetadata struct {
|
||||||
IsPremium bool `json:"is_premium,omitempty"`
|
IsPremium bool `json:"is_premium,omitempty"`
|
||||||
IsBot bool `json:"is_bot,omitempty"`
|
IsBot bool `json:"is_bot,omitempty"`
|
||||||
|
IsChannel bool `json:"is_channel,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PortalMetadata struct {
|
type PortalMetadata struct {
|
||||||
|
|||||||
@@ -209,6 +209,20 @@ func (t *Transferer) WithUserPhoto(ctx context.Context, store *store.ScopedStore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithChannelPhoto transforms a [Transferer] to a [ReadyTransferer] by setting
|
||||||
|
// the given chat photo as the location that will be downloaded by the
|
||||||
|
// [ReadyTransferer].
|
||||||
|
func (t *Transferer) WithChannelPhoto(channelID, accessHash, photoID int64) *ReadyTransferer {
|
||||||
|
return &ReadyTransferer{
|
||||||
|
inner: t,
|
||||||
|
loc: &tg.InputPeerPhotoFileLocation{
|
||||||
|
Peer: &tg.InputPeerChannel{ChannelID: channelID, AccessHash: accessHash},
|
||||||
|
PhotoID: photoID,
|
||||||
|
Big: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Transfer downloads the media from Telegram and uploads it to Matrix.
|
// Transfer downloads the media from Telegram and uploads it to Matrix.
|
||||||
//
|
//
|
||||||
// If the file is already in the database, the MXC URI will be reused. The
|
// If the file is already in the database, the MXC URI will be reused. The
|
||||||
|
|||||||
@@ -181,19 +181,25 @@ func (t *TelegramClient) getEventSender(msg interface {
|
|||||||
}) bridgev2.EventSender {
|
}) bridgev2.EventSender {
|
||||||
if msg.GetOut() {
|
if msg.GetOut() {
|
||||||
return t.mySender()
|
return t.mySender()
|
||||||
} else if f, ok := msg.GetFromID(); ok && f.TypeID() == tg.PeerUserTypeID {
|
}
|
||||||
from := f.(*tg.PeerUser)
|
|
||||||
|
peer, ok := msg.GetFromID()
|
||||||
|
if !ok {
|
||||||
|
peer = msg.GetPeerID()
|
||||||
|
}
|
||||||
|
switch from := peer.(type) {
|
||||||
|
case *tg.PeerUser:
|
||||||
return bridgev2.EventSender{
|
return bridgev2.EventSender{
|
||||||
SenderLogin: ids.MakeUserLoginID(from.UserID),
|
SenderLogin: ids.MakeUserLoginID(from.UserID),
|
||||||
Sender: ids.MakeUserID(from.UserID),
|
Sender: ids.MakeUserID(from.UserID),
|
||||||
}
|
}
|
||||||
} else if peer, ok := msg.GetPeerID().(*tg.PeerUser); ok {
|
case *tg.PeerChannel:
|
||||||
return bridgev2.EventSender{
|
return bridgev2.EventSender{
|
||||||
SenderLogin: ids.MakeUserLoginID(peer.UserID),
|
Sender: ids.MakeUserID(from.ChannelID),
|
||||||
Sender: ids.MakeUserID(peer.UserID),
|
|
||||||
}
|
}
|
||||||
} else {
|
default:
|
||||||
panic(fmt.Sprintf("couldn't determine sender (from: %+v) (peer: %+v)", f, msg.GetPeerID()))
|
fromID, _ := msg.GetFromID()
|
||||||
|
panic(fmt.Sprintf("couldn't determine sender (from: %+v) (peer: %+v)", fromID, msg.GetPeerID()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,14 +324,52 @@ func (t *TelegramClient) updateGhost(ctx context.Context, userID int64, user *tg
|
|||||||
return userInfo, t.maybeUpdateRemoteProfile(ctx, ghost, user)
|
return userInfo, t.maybeUpdateRemoteProfile(ctx, ghost, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TelegramClient) updateChannel(ctx context.Context, channel *tg.Channel) error {
|
||||||
|
if err := t.ScopedStore.SetAccessHash(ctx, channel.ID, channel.AccessHash); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !channel.Broadcast {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the channel ghost if this is a broadcast channel.
|
||||||
|
ghost, err := t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(channel.ID))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var avatar *bridgev2.Avatar
|
||||||
|
if photo, ok := channel.GetPhoto().(*tg.ChatPhoto); ok {
|
||||||
|
avatar = &bridgev2.Avatar{
|
||||||
|
ID: ids.MakeAvatarID(photo.PhotoID),
|
||||||
|
Get: func(ctx context.Context) (data []byte, err error) {
|
||||||
|
data, _, err = media.NewTransferer(t.client.API()).WithChannelPhoto(channel.ID, channel.AccessHash, photo.PhotoID).Download(ctx)
|
||||||
|
return
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ghost.UpdateInfo(ctx, &bridgev2.UserInfo{
|
||||||
|
Name: &channel.Title,
|
||||||
|
Avatar: avatar,
|
||||||
|
ExtraUpdates: func(ctx context.Context, g *bridgev2.Ghost) bool {
|
||||||
|
updated := !g.Metadata.(*GhostMetadata).IsChannel
|
||||||
|
g.Metadata.(*GhostMetadata).IsChannel = true
|
||||||
|
return updated
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *TelegramClient) onEntityUpdate(ctx context.Context, e tg.Entities) error {
|
func (t *TelegramClient) onEntityUpdate(ctx context.Context, e tg.Entities) error {
|
||||||
for userID, user := range e.Users {
|
for userID, user := range e.Users {
|
||||||
if _, err := t.updateGhost(ctx, userID, user); err != nil {
|
if _, err := t.updateGhost(ctx, userID, user); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for channelID, channel := range e.Channels {
|
for _, channel := range e.Channels {
|
||||||
if err := t.ScopedStore.SetAccessHash(ctx, channelID, channel.AccessHash); err != nil {
|
if err := t.updateChannel(ctx, channel); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user