183 lines
5.4 KiB
Go
183 lines
5.4 KiB
Go
package handlers
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
|
|
"github.com/celestix/gotgproto/dispatcher"
|
|
"github.com/celestix/gotgproto/ext"
|
|
"github.com/charmbracelet/log"
|
|
"github.com/gotd/td/tg"
|
|
"github.com/krau/SaveAny-Bot/common/i18n"
|
|
"github.com/krau/SaveAny-Bot/common/i18n/i18nk"
|
|
"github.com/krau/SaveAny-Bot/common/utils/strutil"
|
|
"github.com/krau/SaveAny-Bot/common/utils/tgutil"
|
|
"github.com/krau/SaveAny-Bot/config"
|
|
storconfig "github.com/krau/SaveAny-Bot/config/storage"
|
|
"github.com/krau/SaveAny-Bot/core"
|
|
"github.com/krau/SaveAny-Bot/core/tasks/batchimport"
|
|
"github.com/krau/SaveAny-Bot/pkg/storagetypes"
|
|
"github.com/krau/SaveAny-Bot/storage"
|
|
"github.com/rs/xid"
|
|
)
|
|
|
|
func handleImportCmd(ctx *ext.Context, update *ext.Update) error {
|
|
logger := log.FromContext(ctx)
|
|
args := strutil.ParseArgsRespectQuotes(update.EffectiveMessage.Text)
|
|
|
|
if len(args) < 3 {
|
|
ctx.Reply(update, ext.ReplyTextString(i18n.T(i18nk.BotMsgImportUsage, nil)), nil)
|
|
return dispatcher.EndGroups
|
|
}
|
|
|
|
storageName := args[1]
|
|
dirPath := args[2]
|
|
|
|
userID := update.GetUserChat().GetID()
|
|
|
|
stor, err := storage.GetStorageByUserIDAndName(ctx, userID, storageName)
|
|
if err != nil {
|
|
logger.Errorf("Failed to get storage by user ID and name: %s", err)
|
|
ctx.Reply(update, ext.ReplyTextString(i18n.T(i18nk.BotMsgImportErrorStorageNotFound, map[string]any{
|
|
"StorageName": storageName,
|
|
"Error": err,
|
|
})), nil)
|
|
return dispatcher.EndGroups
|
|
}
|
|
|
|
listable, ok := stor.(storage.StorageListable)
|
|
if !ok {
|
|
ctx.Reply(update, ext.ReplyTextString(i18n.T(i18nk.BotMsgImportErrorStorageNotListable, map[string]any{
|
|
"StorageName": storageName,
|
|
})), nil)
|
|
return dispatcher.EndGroups
|
|
}
|
|
|
|
_, ok = stor.(storage.StorageReadable)
|
|
if !ok {
|
|
ctx.Reply(update, ext.ReplyTextString(i18n.T(i18nk.BotMsgImportErrorStorageNotReadable, map[string]any{
|
|
"StorageName": storageName,
|
|
})), nil)
|
|
return dispatcher.EndGroups
|
|
}
|
|
|
|
telegramStorage, err := storage.GetTelegramStorageByUserID(ctx, userID)
|
|
if err != nil {
|
|
ctx.Reply(update, ext.ReplyTextString(i18n.T(i18nk.BotMsgImportErrorNoTelegramStorage, map[string]any{
|
|
"Error": err,
|
|
})), nil)
|
|
return dispatcher.EndGroups
|
|
}
|
|
|
|
replied, err := ctx.Reply(update, ext.ReplyTextString(i18n.T(i18nk.BotMsgImportInfoFetchingFiles, nil)), nil)
|
|
if err != nil {
|
|
logger.Errorf("Failed to reply: %s", err)
|
|
return dispatcher.EndGroups
|
|
}
|
|
|
|
files, err := listable.ListFiles(ctx, dirPath)
|
|
if err != nil {
|
|
ctx.EditMessage(update.EffectiveChat().GetID(), &tg.MessagesEditMessageRequest{
|
|
ID: replied.ID,
|
|
Message: i18n.T(i18nk.BotMsgImportErrorListFilesFailed, map[string]any{"Error": err}),
|
|
})
|
|
return dispatcher.EndGroups
|
|
}
|
|
|
|
var filter *regexp.Regexp
|
|
if len(args) >= 5 {
|
|
filter, err = regexp.Compile(args[4])
|
|
if err != nil {
|
|
ctx.EditMessage(update.EffectiveChat().GetID(), &tg.MessagesEditMessageRequest{
|
|
ID: replied.ID,
|
|
Message: i18n.T(i18nk.BotMsgImportErrorInvalidRegex, map[string]any{"Error": err}),
|
|
})
|
|
return dispatcher.EndGroups
|
|
}
|
|
}
|
|
|
|
filteredFiles := make([]storagetypes.FileInfo, 0)
|
|
for _, file := range files {
|
|
if file.IsDir {
|
|
continue
|
|
}
|
|
if filter != nil && !filter.MatchString(file.Name) {
|
|
continue
|
|
}
|
|
filteredFiles = append(filteredFiles, file)
|
|
}
|
|
|
|
if len(filteredFiles) == 0 {
|
|
ctx.EditMessage(update.EffectiveChat().GetID(), &tg.MessagesEditMessageRequest{
|
|
ID: replied.ID,
|
|
Message: i18n.T(i18nk.BotMsgImportErrorNoFilesToImport, nil),
|
|
})
|
|
return dispatcher.EndGroups
|
|
}
|
|
|
|
// Get default chat_id from Telegram storage config
|
|
targetChatID := int64(0)
|
|
if telegramCfg := config.C().GetStorageByName(telegramStorage.Name()); telegramCfg != nil {
|
|
if tgCfg, ok := telegramCfg.(*storconfig.TelegramStorageConfig); ok {
|
|
targetChatID = tgCfg.ChatID
|
|
}
|
|
}
|
|
|
|
if len(args) >= 4 {
|
|
parsedChatID, err := tgutil.ParseChatID(ctx, args[3])
|
|
if err != nil {
|
|
ctx.EditMessage(update.EffectiveChat().GetID(), &tg.MessagesEditMessageRequest{
|
|
ID: replied.ID,
|
|
Message: i18n.T(i18nk.BotMsgImportErrorInvalidChatId, map[string]any{"Error": err}),
|
|
})
|
|
return dispatcher.EndGroups
|
|
}
|
|
targetChatID = parsedChatID
|
|
}
|
|
|
|
if targetChatID == 0 {
|
|
ctx.EditMessage(update.EffectiveChat().GetID(), &tg.MessagesEditMessageRequest{
|
|
ID: replied.ID,
|
|
Message: i18n.T(i18nk.BotMsgImportErrorNoTargetChatId, nil),
|
|
})
|
|
return dispatcher.EndGroups
|
|
}
|
|
|
|
elems := make([]batchimport.TaskElement, 0, len(filteredFiles))
|
|
var totalSize int64
|
|
for _, file := range filteredFiles {
|
|
elem := batchimport.NewTaskElement(stor, file, telegramStorage, targetChatID)
|
|
elems = append(elems, *elem)
|
|
totalSize += file.Size
|
|
}
|
|
|
|
taskID := xid.New().String()
|
|
injectCtx := tgutil.ExtWithContext(ctx.Context, ctx)
|
|
task := batchimport.NewBatchImportTask(
|
|
taskID,
|
|
injectCtx,
|
|
elems,
|
|
batchimport.NewProgressTracker(replied.ID, userID),
|
|
true, // IgnoreErrors
|
|
)
|
|
|
|
if err := core.AddTask(injectCtx, task); err != nil {
|
|
ctx.EditMessage(update.EffectiveChat().GetID(), &tg.MessagesEditMessageRequest{
|
|
ID: replied.ID,
|
|
Message: i18n.T(i18nk.BotMsgImportErrorAddTaskFailed, map[string]any{"Error": err}),
|
|
})
|
|
return dispatcher.EndGroups
|
|
}
|
|
|
|
ctx.EditMessage(update.EffectiveChat().GetID(), &tg.MessagesEditMessageRequest{
|
|
ID: replied.ID,
|
|
Message: i18n.T(i18nk.BotMsgImportInfoTaskAdded, map[string]any{
|
|
"Count": len(elems),
|
|
"SizeMB": fmt.Sprintf("%.2f", float64(totalSize)/(1024*1024)),
|
|
"TaskID": taskID,
|
|
}),
|
|
})
|
|
|
|
return dispatcher.EndGroups
|
|
}
|