fix: issues
This commit is contained in:
33
internal/channel_message.go
Normal file
33
internal/channel_message.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package internal
|
||||
|
||||
import "fmt"
|
||||
|
||||
type ChannelMessage struct {
|
||||
ID int
|
||||
Message string
|
||||
Medias []ChannelMessageMedia
|
||||
}
|
||||
|
||||
type ChannelMessageMedia struct {
|
||||
Photo string
|
||||
Video string
|
||||
}
|
||||
|
||||
func NewChannelMessage(id int) *ChannelMessage {
|
||||
return &ChannelMessage{ID: id}
|
||||
}
|
||||
|
||||
func (c *ChannelMessage) WithMessage(message string) *ChannelMessage {
|
||||
c.Message = message
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ChannelMessage) WithPhoto(assetID int64, ext string) *ChannelMessage {
|
||||
c.Medias = append(c.Medias, ChannelMessageMedia{Photo: fmt.Sprintf("%d.%s", assetID, ext)})
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ChannelMessage) WithVideo(video string) *ChannelMessage {
|
||||
c.Medias = append(c.Medias, ChannelMessageMedia{Video: video})
|
||||
return c
|
||||
}
|
||||
@@ -20,16 +20,10 @@ type TClient struct {
|
||||
logger *zap.Logger
|
||||
api *tg.Client
|
||||
|
||||
downloadMedia bool
|
||||
|
||||
waitLogin chan error
|
||||
block chan struct{}
|
||||
}
|
||||
|
||||
// func (t *TClient) Close() {
|
||||
// t.block <- struct{}{}
|
||||
// }
|
||||
|
||||
func NewClient(logger *zap.Logger, config *config.Config) *TClient {
|
||||
c := &TClient{
|
||||
Config: config,
|
||||
@@ -46,11 +40,6 @@ func NewClient(logger *zap.Logger, config *config.Config) *TClient {
|
||||
return c
|
||||
}
|
||||
|
||||
func (t *TClient) WithMedia() *TClient {
|
||||
t.downloadMedia = true
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *TClient) Login(ctx context.Context) error {
|
||||
t.logger.Info("login phone", zap.String("phone", t.Config.Phone))
|
||||
flow := auth.NewFlow(Terminal{PhoneNumber: client.Config.Phone}, auth.SendCodeOptions{})
|
||||
|
||||
@@ -2,24 +2,29 @@ package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gotd/td/telegram/downloader"
|
||||
"github.com/gotd/td/tg"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/samber/lo"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (t *TClient) Channel(ctx context.Context, channel *tg.Channel, offset int) error {
|
||||
func (t *TClient) Channel(ctx context.Context, channel *tg.Channel, cfg *ChannelConfig, modeHistory bool) error {
|
||||
inputPeer := &tg.InputPeerChannel{ChannelID: channel.ID, AccessHash: channel.AccessHash}
|
||||
messages, err := t.api.MessagesGetHistory(ctx, &tg.MessagesGetHistoryRequest{
|
||||
Peer: inputPeer,
|
||||
Limit: 10,
|
||||
OffsetID: offset,
|
||||
})
|
||||
|
||||
request := &tg.MessagesGetHistoryRequest{
|
||||
Peer: inputPeer,
|
||||
Limit: 1,
|
||||
}
|
||||
|
||||
if modeHistory { // 提供此ID供遍历历史消息
|
||||
request.OffsetID = cfg.Offset
|
||||
} else {
|
||||
request.MinID = cfg.MinID // 提供此ID供新增加的消息
|
||||
}
|
||||
|
||||
messages, err := t.Client.API().MessagesGetHistory(ctx, request)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "messages.getHistory")
|
||||
}
|
||||
@@ -28,13 +33,19 @@ func (t *TClient) Channel(ctx context.Context, channel *tg.Channel, offset int)
|
||||
lo.ForEach(messages.(*tg.MessagesChannelMessages).GetMessages(), func(item tg.MessageClass, index int) {
|
||||
msg, ok := item.(*tg.Message)
|
||||
if !ok {
|
||||
fmt.Println("ID: get failed")
|
||||
t.logger.Error("convert msg to *tg.Message failed")
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err := cfg.Update(ctx, msg.ID); err != nil {
|
||||
t.logger.Error("update config failed", zap.Error(err))
|
||||
}
|
||||
}()
|
||||
|
||||
if !t.downloadMedia {
|
||||
return
|
||||
}
|
||||
channelMessage := NewChannelMessage(msg.ID)
|
||||
defer cfg.SaveMessage(channelMessage)
|
||||
|
||||
channelMessage.WithMessage(msg.GetMessage())
|
||||
|
||||
if mediaClass, ok := msg.GetMedia(); ok {
|
||||
if photoClass, ok := mediaClass.(*tg.MessageMediaPhoto).GetPhoto(); ok {
|
||||
@@ -52,47 +63,17 @@ func (t *TClient) Channel(ctx context.Context, channel *tg.Channel, offset int)
|
||||
ThumbSize: thumbSize,
|
||||
}
|
||||
|
||||
saveTo := lo.Must(filepath.Abs(fmt.Sprintf("./photos/%d.jpg", photo.GetID())))
|
||||
storage, err := downloader.Download(t.api, location).ToPath(ctx, saveTo)
|
||||
|
||||
saveTo := cfg.Asset(photo.GetID(), "jpg")
|
||||
_, err := downloader.Download(t.Client.API(), location).ToPath(ctx, saveTo)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
fmt.Println("Downloaded : ", storage)
|
||||
t.logger.Error("download failed", zap.Error(err))
|
||||
return
|
||||
}
|
||||
channelMessage.WithPhoto(photo.GetID(), "jpg")
|
||||
t.logger.Info("download failed", zap.String("asset", saveTo))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ChannelConfig struct {
|
||||
ID int64 `json:"id"`
|
||||
Offset int `json:"offset"`
|
||||
}
|
||||
|
||||
func (t *TClient) SaveChannelConfig(ctx context.Context, channelID int64, offset int) (*ChannelConfig, error) {
|
||||
channelConfigFile := fmt.Sprintf("outputs/%d/config.json", channelID)
|
||||
// if file not exists then create it
|
||||
if _, err := os.Stat(channelConfigFile); os.IsNotExist(err) {
|
||||
// create config file
|
||||
data, _ := json.Marshal(&ChannelConfig{ID: channelID})
|
||||
if err := os.WriteFile(channelConfigFile, data, 0o644); err != nil {
|
||||
return nil, errors.Wrap(err, "write channel config")
|
||||
}
|
||||
}
|
||||
|
||||
// read config file
|
||||
data, err := os.ReadFile(channelConfigFile)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "read channel config")
|
||||
}
|
||||
|
||||
var config *ChannelConfig
|
||||
if err := json.Unmarshal(data, config); err != nil {
|
||||
return nil, errors.Wrap(err, "unmarshal channel config")
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
116
internal/client_channel_config.go
Normal file
116
internal/client_channel_config.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type ChannelConfig struct {
|
||||
ID int64 `json:"id"`
|
||||
Offset int `json:"offset"`
|
||||
MinID int `json:"min_id"`
|
||||
}
|
||||
|
||||
func NewChannelConfig(channelID int64) *ChannelConfig {
|
||||
return &ChannelConfig{ID: channelID}
|
||||
}
|
||||
|
||||
func (c *ChannelConfig) Asset(assetID int64, ext string) string {
|
||||
assetFile := fmt.Sprintf("outputs/%d/assets/%d.%s", c.ID, assetID, ext)
|
||||
|
||||
// if file dir not exists then create it
|
||||
if _, err := os.Stat(filepath.Dir(assetFile)); os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(filepath.Dir(assetFile), 0o755); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// if file exists then delete it
|
||||
if _, err := os.Stat(assetFile); err == nil {
|
||||
if err := os.Remove(assetFile); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
return assetFile
|
||||
}
|
||||
|
||||
func (c *ChannelConfig) file(_ context.Context) (string, error) {
|
||||
channelConfigFile := fmt.Sprintf("outputs/%d/config.json", c.ID)
|
||||
|
||||
// if file dir not exists then create it
|
||||
if _, err := os.Stat(filepath.Dir(channelConfigFile)); os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(filepath.Dir(channelConfigFile), 0o755); err != nil {
|
||||
return "", errors.Wrap(err, "create channel config dir")
|
||||
}
|
||||
}
|
||||
|
||||
// if file not exists then create it
|
||||
if _, err := os.Stat(channelConfigFile); os.IsNotExist(err) {
|
||||
// create config file
|
||||
data, _ := json.Marshal(&ChannelConfig{ID: channelID})
|
||||
if err := os.WriteFile(channelConfigFile, data, 0o644); err != nil {
|
||||
return "", errors.Wrap(err, "write channel config")
|
||||
}
|
||||
}
|
||||
return channelConfigFile, nil
|
||||
}
|
||||
|
||||
func (c *ChannelConfig) Read(ctx context.Context) error {
|
||||
channelConfigFile, err := c.file(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// read config file
|
||||
data, err := os.ReadFile(channelConfigFile)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "read channel config")
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &c); err != nil {
|
||||
return errors.Wrap(err, "unmarshal channel config")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ChannelConfig) Update(ctx context.Context, offsetID int) error {
|
||||
channelConfigFile, err := c.file(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Offset = offsetID
|
||||
|
||||
if c.MinID < offsetID {
|
||||
c.MinID = offsetID
|
||||
}
|
||||
|
||||
b, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshal channel config")
|
||||
}
|
||||
|
||||
if err := os.WriteFile(channelConfigFile, b, 0o644); err != nil {
|
||||
return errors.Wrap(err, "write channel config")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ChannelConfig) SaveMessage(msg *ChannelMessage) {
|
||||
// save message
|
||||
saveTo := fmt.Sprintf("outputs/%d/%d.json", c.ID, msg.ID)
|
||||
b, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := os.WriteFile(saveTo, b, 0o644); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
channelID int64
|
||||
offsetID int
|
||||
channelAlias string
|
||||
downloadMedia bool
|
||||
channelID int64
|
||||
modeHistory bool
|
||||
channelAlias string
|
||||
)
|
||||
|
||||
func ExportCmd() *cobra.Command {
|
||||
@@ -23,9 +22,8 @@ func ExportCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
cmd.Flags().Int64Var(&channelID, "channel", 0, "channel id")
|
||||
cmd.Flags().IntVar(&offsetID, "offset", 0, "offset id")
|
||||
cmd.Flags().BoolVar(&modeHistory, "history", false, "history mode")
|
||||
cmd.Flags().StringVar(&channelAlias, "alias", "", "channel alias")
|
||||
cmd.Flags().BoolVar(&downloadMedia, "media", false, "download media")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -49,15 +47,11 @@ func exportCmd(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
if downloadMedia {
|
||||
client.WithMedia()
|
||||
}
|
||||
|
||||
cfg, err := client.SaveChannelConfig(ctx, channel.ID, offsetID)
|
||||
if err != nil {
|
||||
cfg := NewChannelConfig(channel.ID)
|
||||
if err := cfg.Read(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
return client.Channel(ctx, channel, cfg.Offset)
|
||||
// https://t.me/yunpanshare/37426
|
||||
return client.Channel(ctx, channel, cfg, modeHistory)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user