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) } }