134 lines
3.1 KiB
Go
134 lines
3.1 KiB
Go
package telegram
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/TelegramExchange/tgex-backend/tg_parser/internal/domain"
|
|
"github.com/gotd/td/telegram/deeplink"
|
|
"github.com/gotd/td/tg"
|
|
)
|
|
|
|
func (t *Telegram) ParseChannelMetaByInvite(ctx context.Context, inviteLink string) (domain.Channel, error) {
|
|
link, err := deeplink.Parse(inviteLink)
|
|
if err != nil {
|
|
return domain.Channel{}, fmt.Errorf("parse invite link: %w", err)
|
|
}
|
|
if link.Type != deeplink.Join {
|
|
return domain.Channel{}, fmt.Errorf("invite link is not a join link")
|
|
}
|
|
hash := link.Args.Get("invite")
|
|
if hash == "" {
|
|
return domain.Channel{}, fmt.Errorf("invite link missing hash")
|
|
}
|
|
|
|
info, err := t.API().MessagesCheckChatInvite(ctx, hash)
|
|
if err != nil {
|
|
return domain.Channel{}, fmt.Errorf("check invite: %w", err)
|
|
}
|
|
|
|
var channel *tg.Channel
|
|
|
|
switch v := info.(type) {
|
|
case *tg.ChatInviteAlready:
|
|
channel = extractChannelFromChat(v.Chat)
|
|
case *tg.ChatInvite:
|
|
updates, err := t.API().MessagesImportChatInvite(ctx, hash)
|
|
if err != nil {
|
|
return domain.Channel{}, fmt.Errorf("import invite: %w", err)
|
|
}
|
|
channel = extractChannelFromUpdates(updates)
|
|
case *tg.ChatInvitePeek:
|
|
// ChatInvitePeek means we can preview the channel without joining (public channels)
|
|
channel = extractChannelFromChat(v.Chat)
|
|
default:
|
|
return domain.Channel{}, fmt.Errorf("unexpected invite response: %T", v)
|
|
}
|
|
|
|
if channel == nil {
|
|
return domain.Channel{}, fmt.Errorf("no channel in invite response")
|
|
}
|
|
if channel.AccessHash == 0 {
|
|
return domain.Channel{}, fmt.Errorf("channel access hash missing")
|
|
}
|
|
|
|
pts, err := getChannelPTS(ctx, t.API(), channel)
|
|
if err != nil {
|
|
return domain.Channel{}, fmt.Errorf("get peer dialogs: %w", err)
|
|
}
|
|
|
|
username := ""
|
|
if usernameVal, ok := channel.GetUsername(); ok && usernameVal != "" {
|
|
username = usernameVal
|
|
}
|
|
|
|
return domain.Channel{
|
|
TelegramID: domain.ChatIDFromChannelID(channel.ID),
|
|
Username: username,
|
|
Title: channel.Title,
|
|
AccessHash: channel.AccessHash,
|
|
Pts: pts,
|
|
InviteLink: inviteLink,
|
|
IsAccessible: true,
|
|
}, nil
|
|
}
|
|
|
|
func extractChannelFromChat(chat tg.ChatClass) *tg.Channel {
|
|
switch v := chat.(type) {
|
|
case *tg.Channel:
|
|
return v
|
|
case *tg.ChannelForbidden:
|
|
return &tg.Channel{
|
|
ID: v.ID,
|
|
AccessHash: v.AccessHash,
|
|
Title: v.Title,
|
|
}
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func extractChannelFromUpdates(updates tg.UpdatesClass) *tg.Channel {
|
|
var chats []tg.ChatClass
|
|
switch v := updates.(type) {
|
|
case *tg.Updates:
|
|
chats = v.Chats
|
|
case *tg.UpdatesCombined:
|
|
chats = v.Chats
|
|
default:
|
|
return nil
|
|
}
|
|
|
|
for _, chat := range chats {
|
|
if channel := extractChannelFromChat(chat); channel != nil {
|
|
return channel
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func getChannelPTS(ctx context.Context, api *tg.Client, channel *tg.Channel) (int, error) {
|
|
req := []tg.InputDialogPeerClass{
|
|
&tg.InputDialogPeer{
|
|
Peer: &tg.InputPeerChannel{
|
|
ChannelID: channel.ID,
|
|
AccessHash: channel.AccessHash,
|
|
},
|
|
},
|
|
}
|
|
|
|
dialogs, err := api.MessagesGetPeerDialogs(ctx, req)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
if len(dialogs.Dialogs) > 0 {
|
|
if d, ok := dialogs.Dialogs[0].(*tg.Dialog); ok {
|
|
return d.Pts, nil
|
|
}
|
|
}
|
|
|
|
return 0, nil
|
|
}
|