package internal import ( "context" "fmt" "path/filepath" "exporter/config" "github.com/gotd/td/telegram" "github.com/gotd/td/telegram/auth" "github.com/gotd/td/telegram/downloader" "github.com/gotd/td/tg" "github.com/pkg/errors" "github.com/samber/lo" "go.uber.org/zap" ) type TClient struct { Config *config.Config Client *telegram.Client logger *zap.Logger api *tg.Client waitLogin chan error block chan struct{} } // func (t *TClient) Close() { // t.block <- struct{}{} // } func NewClient(config *config.Config) *TClient { c := &TClient{ Config: config, Client: telegram.NewClient(config.AppID, config.AppHash, telegram.Options{ Logger: logger, UpdateHandler: nil, SessionStorage: &telegram.FileSessionStorage{ Path: lo.Must(filepath.Abs(config.SessionFile)), }, }), } return c } // func (t *TClient) Run(ctx context.Context) { // err := t.Client.Run(ctx, func(ctx context.Context) error { // flow := auth.NewFlow(Terminal{PhoneNumber: t.Config.Phone}, auth.SendCodeOptions{}) // if err := t.Client.Auth().IfNecessary(ctx, flow); err != nil { // return errors.Wrap(err, "auth") // } // t.api = t.Client.API() // t.waitLogin <- nil // <-t.block // return nil // }) // if err != nil { // t.waitLogin <- err // } // } // func (t *TClient) Wait() <-chan error { // return t.waitLogin // } func (t *TClient) Login(ctx context.Context) error { flow := auth.NewFlow(Terminal{PhoneNumber: client.Config.Phone}, auth.SendCodeOptions{}) if err := t.Client.Auth().IfNecessary(context.Background(), flow); err != nil { return errors.Wrap(err, "auth") } self, err := t.Client.Self(ctx) if err != nil { return errors.Wrap(err, "call self") } logger.Info("Login", zap.String("first_name", self.FirstName), zap.String("last_name", self.LastName), zap.String("username", self.Username), zap.Int64("id", self.ID), ) return nil } // ChannelInfo func (t *TClient) ChannelInfoByAlias(ctx context.Context, channelAlias string) (*tg.Channel, error) { p, err := t.Client.API().ContactsResolveUsername(ctx, channelAlias) if err != nil { return nil, errors.Wrap(err, "contacts.resolveUsername") } chats := p.GetChats() if len(chats) == 0 { return nil, errors.New("chat not found") } channel := chats[0].(*tg.Channel) return channel, nil } func (t *TClient) ChannelInfoByID(ctx context.Context, channelID int64) (*tg.Channel, error) { p, err := t.Client.API().ChannelsGetChannels(ctx, []tg.InputChannelClass{ &tg.InputChannel{ChannelID: channelID}, }) if err != nil { return nil, errors.Wrap(err, "contacts.resolveUsername") } chats := p.GetChats() if len(chats) == 0 { return nil, errors.New("chat not found") } channel := chats[0].(*tg.Channel) return channel, nil } func (t *TClient) Channel(ctx context.Context, channel *tg.Channel, offset int) error { inputPeer := &tg.InputPeerChannel{ChannelID: channel.ID, AccessHash: channel.AccessHash} messages, err := t.api.MessagesGetHistory(ctx, &tg.MessagesGetHistoryRequest{ Peer: inputPeer, Limit: 10, OffsetID: offset, }) if err != nil { return errors.Wrap(err, "messages.getHistory") } downloader := downloader.NewDownloader() lo.ForEach(messages.(*tg.MessagesChannelMessages).GetMessages(), func(item tg.MessageClass, index int) { msg, ok := item.(*tg.Message) if !ok { fmt.Println("ID: get failed") return } if mediaClass, ok := msg.GetMedia(); ok { if photoClass, ok := mediaClass.(*tg.MessageMediaPhoto).GetPhoto(); ok { photo := photoClass.(*tg.Photo) thumbSize := "" if len(photo.Sizes) > 1 { thumbSize = photo.Sizes[len(photo.Sizes)-1].GetType() } location := &tg.InputPhotoFileLocation{ ID: photo.GetID(), AccessHash: photo.GetAccessHash(), FileReference: photo.GetFileReference(), ThumbSize: thumbSize, } saveTo := lo.Must(filepath.Abs(fmt.Sprintf("./photos/%d.jpg", photo.GetID()))) storage, err := downloader.Download(t.api, location).ToPath(ctx, saveTo) if err != nil { fmt.Println(err) } else { fmt.Println("Downloaded : ", storage) } } } fmt.Println("") fmt.Println("------------------------------------------------------------------------------------------------------") fmt.Println("") }) return nil }