Files
mautrix-telegram/pkg/gotd/telegram/peers/join.go
T
2025-06-27 20:03:37 -07:00

100 lines
2.4 KiB
Go

package peers
import (
"context"
"github.com/go-faster/errors"
"go.mau.fi/mautrix-telegram/pkg/gotd/telegram/internal/deeplink"
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
)
type updateWithChats interface {
tg.UpdatesClass
GetChats() []tg.ChatClass
}
var _ = []updateWithChats{
(*tg.Updates)(nil),
(*tg.UpdatesCombined)(nil),
}
// JoinLink joins to private chat using given link or hash.
// Input examples:
//
// t.me/+AAAAAAAAAAAAAAAA
// https://t.me/+AAAAAAAAAAAAAAAA
// t.me/joinchat/AAAAAAAAAAAAAAAA
// https://t.me/joinchat/AAAAAAAAAAAAAAAA
// tg:join?invite=AAAAAAAAAAAAAAAA
// tg://join?invite=AAAAAAAAAAAAAAAA
func (m *Manager) JoinLink(ctx context.Context, link string) (Peer, error) {
l, err := deeplink.Expect(link, deeplink.Join)
if err != nil {
return nil, err
}
return m.ImportInvite(ctx, l.Args.Get("invite"))
}
// ImportInvite imports given hash invite.
func (m *Manager) ImportInvite(ctx context.Context, hash string) (Peer, error) {
inviteInfo, err := m.api.MessagesCheckChatInvite(ctx, hash)
if err != nil {
return Chat{}, errors.Wrap(err, "check invite")
}
switch inviteInfo := inviteInfo.(type) {
case *tg.ChatInviteAlready:
return m.extractChat(inviteInfo.GetChat())
case *tg.ChatInvite:
if err := m.applyUsers(ctx, inviteInfo.Participants...); err != nil {
return nil, errors.Wrap(err, "update users")
}
case *tg.ChatInvitePeek:
if err := m.applyChats(ctx, inviteInfo.GetChat()); err != nil {
return Chat{}, errors.Wrap(err, "update chats")
}
default:
return nil, errors.Errorf("unexpected type %T", inviteInfo)
}
ch, err := m.importInvite(ctx, hash)
if err != nil {
return nil, err
}
return m.extractChat(ch)
}
func (m *Manager) importInvite(ctx context.Context, hash string) (tg.ChatClass, error) {
u, err := m.api.MessagesImportChatInvite(ctx, hash)
if err != nil {
return nil, errors.Wrap(err, "import invite")
}
updates, ok := u.(updateWithChats)
if !ok {
return nil, errors.Errorf("bad result %T type", u)
}
// Do not apply it, update hook already did it.
chats := updates.GetChats()
if len(chats) < 1 {
return nil, errors.New("empty result")
}
return chats[0], nil
}
func (m *Manager) extractChat(p tg.ChatClass) (Peer, error) {
// TODO: handle forbidden.
switch p := p.(type) {
case *tg.Chat:
return m.Chat(p), nil
case *tg.Channel:
return m.Channel(p), nil
default:
return nil, errors.Errorf("unexpected type %T", p)
}
}