diff --git a/cmd/bot/main.go b/cmd/bot/main.go index 23c57c7..3551333 100644 --- a/cmd/bot/main.go +++ b/cmd/bot/main.go @@ -58,7 +58,8 @@ func main() { trackProcessor := processor.NewTrackProcessor(db, yandexClient, downloaderComponent, taggerComponent, telegramClient) - adminHandler := admin.NewHandler(db, telegramClient, yandexClient, startTime) + // Передаем taggerComponent в admin.NewHandler + adminHandler := admin.NewHandler(db, telegramClient, yandexClient, taggerComponent, startTime) inlineHandler := bot.NewInlineHandler(yandexClient, trackProcessor, telegramClient) // 5. Создание и запуск приложения diff --git a/internal/admin/handler.go b/internal/admin/handler.go index 54d004f..ecf9c97 100644 --- a/internal/admin/handler.go +++ b/internal/admin/handler.go @@ -18,15 +18,17 @@ type Handler struct { storage interfaces.TrackStorage telegram interfaces.TelegramClient yandex interfaces.YandexMusicClient + tagger interfaces.Tagger startTime time.Time } // NewHandler создает новый обработчик команд администратора. -func NewHandler(storage interfaces.TrackStorage, telegram interfaces.TelegramClient, yandex interfaces.YandexMusicClient, startTime time.Time) *Handler { +func NewHandler(storage interfaces.TrackStorage, telegram interfaces.TelegramClient, yandex interfaces.YandexMusicClient, tagger interfaces.Tagger, startTime time.Time) *Handler { return &Handler{ storage: storage, telegram: telegram, yandex: yandex, + tagger: tagger, startTime: startTime, } } @@ -165,17 +167,24 @@ func (h *Handler) handleWarmFromDir(ctx context.Context, chatID int64, dirPath s continue } - // 2. Загружаем в Telegram - // Поскольку метатеги уже вшиты, для отображения в кэш-канале можно использовать простые title/performer + // 2. Читаем метатеги из файла + title, artist, err := h.tagger.ReadMetadata(fullPath) + if err != nil { + slog.Warn("Failed to read metadata from file, using fallback", "path", fullPath, "error", err) + title = "" // Используем ID как заголовок + artist = "" // Используем заглушку как исполнителя + } + + // 3. Загружаем в Telegram с корректными метаданными slog.Debug("Uploading track to cache channel", "track_id", trackID, "path", fullPath) - fileID, err := h.telegram.SendAudioToCacheChannel(ctx, fullPath, trackID, "Pre-cached") + fileID, err := h.telegram.SendAudioToCacheChannel(ctx, fullPath, title, artist) if err != nil { slog.Error("Failed to upload pre-cached file", "track_id", trackID, "error", err) errorCount++ continue } - // 3. Сохраняем в БД + // 4. Сохраняем в БД err = h.storage.Set(ctx, trackID, fileID) if err != nil { slog.Error("Failed to save pre-cached file to storage", "track_id", trackID, "error", err) diff --git a/internal/interfaces/interfaces.go b/internal/interfaces/interfaces.go index 9751c92..e39da1e 100644 --- a/internal/interfaces/interfaces.go +++ b/internal/interfaces/interfaces.go @@ -34,6 +34,7 @@ type TelegramClient interface { // Tagger определяет методы для работы с метаданными аудиофайлов. type Tagger interface { WriteTags(filePath string, coverPath string, info *model.TrackInfo) error + ReadMetadata(filePath string) (title, artist string, err error) } // FileDownloader определяет метод для скачивания файла. diff --git a/pkg/tagger/id3.go b/pkg/tagger/id3.go index 695e5cd..326452a 100644 --- a/pkg/tagger/id3.go +++ b/pkg/tagger/id3.go @@ -17,6 +17,24 @@ func NewID3Tagger() *ID3Tagger { return &ID3Tagger{} } +// ReadMetadata читает основные метаданные (название, исполнитель) из аудиофайла. +func (t *ID3Tagger) ReadMetadata(filePath string) (string, string, error) { + tag, err := id3v2.Open(filePath, id3v2.Options{Parse: true}) + if err != nil { + return "", "", fmt.Errorf("failed to open mp3 file for reading tags: %w", err) + } + defer tag.Close() + + title := tag.Title() + artist := tag.Artist() + + if title == "" || artist == "" { + return "", "", fmt.Errorf("title or artist tag is empty") + } + + return title, artist, nil +} + // WriteTags записывает метаданные и обложку в указанный аудиофайл. func (t *ID3Tagger) WriteTags(filePath string, coverPath string, info *model.TrackInfo) error { tag, err := id3v2.Open(filePath, id3v2.Options{Parse: true})