Files
yamusic-bot/internal/bot/handler.go
Vladimir Zagainov 4005371767
Some checks failed
continuous-integration/drone/push Build is failing
fixed gitignore
2025-06-23 16:29:45 +03:00

122 lines
4.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package bot
import (
"context"
"log/slog"
"strconv"
"sync"
"gitea.mrixs.me/Mrixs/yamusic-bot/internal/interfaces"
"gitea.mrixs.me/Mrixs/yamusic-bot/internal/model"
"gitea.mrixs.me/Mrixs/yamusic-bot/internal/processor"
"gitea.mrixs.me/Mrixs/yamusic-bot/pkg/yamusic"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)
// InlineHandler обрабатывает inline-запросы.
type InlineHandler struct {
yandex interfaces.YandexMusicClient
processor *processor.TrackProcessor
telegram interfaces.TelegramClient
}
// NewInlineHandler создает новый обработчик inline-запросов.
func NewInlineHandler(yandex interfaces.YandexMusicClient, processor *processor.TrackProcessor, telegram interfaces.TelegramClient) *InlineHandler {
return &InlineHandler{
yandex: yandex,
processor: processor,
telegram: telegram,
}
}
// HandleInlineQuery обрабатывает входящий inline-запрос.
func (h *InlineHandler) HandleInlineQuery(ctx context.Context, query *tgbotapi.InlineQuery) {
slog.Info("Handling inline query", "user_id", query.From.ID, "query", query.Query)
urlInfo, err := yamusic.ParseYandexURL(query.Query)
if err != nil {
h.answerWithError(ctx, query.ID, "Неверный формат ссылки. Поддерживаются ссылки на треки, альбомы и исполнителей Yandex.Music.")
return
}
var trackInfos []*model.TrackInfo
switch urlInfo.Type {
case "track":
info, err := h.yandex.GetTrackInfo(ctx, urlInfo.TrackID)
if err != nil {
slog.Error("Failed to get track info", "track_id", urlInfo.TrackID, "error", err)
h.answerWithError(ctx, query.ID, "Не удалось получить информацию о треке.")
return
}
trackInfos = append(trackInfos, info)
case "album":
infos, err := h.yandex.GetAlbumTrackInfos(ctx, urlInfo.AlbumID)
if err != nil {
slog.Error("Failed to get album info", "album_id", urlInfo.AlbumID, "error", err)
h.answerWithError(ctx, query.ID, "Не удалось получить информацию об альбоме.")
return
}
trackInfos = infos
case "artist":
infos, err := h.yandex.GetArtistTrackInfos(ctx, urlInfo.ArtistID)
if err != nil {
slog.Error("Failed to get artist info", "artist_id", urlInfo.ArtistID, "error", err)
h.answerWithError(ctx, query.ID, "Не удалось получить информацию об исполнителе.")
return
}
trackInfos = infos
}
if len(trackInfos) == 0 {
h.answerWithError(ctx, query.ID, "По этой ссылке ничего не найдено.")
return
}
h.processAndAnswer(ctx, query.ID, trackInfos)
}
func (h *InlineHandler) processAndAnswer(ctx context.Context, queryID string, trackInfos []*model.TrackInfo) {
var wg sync.WaitGroup
resultsChan := make(chan interface{}, len(trackInfos))
for i, info := range trackInfos {
wg.Add(1)
go func(trackInfo *model.TrackInfo, resultID int) {
defer wg.Done()
fileID, err := h.processor.Process(ctx, trackInfo)
if err != nil {
slog.Error("Failed to process track", "track_id", trackInfo.YandexTrackID, "error", err)
return
}
result := tgbotapi.NewInlineQueryResultAudio(strconv.Itoa(resultID), fileID, trackInfo.Title)
result.Performer = trackInfo.Artist
resultsChan <- result
}(info, i)
}
wg.Wait()
close(resultsChan)
var finalResults []interface{}
for result := range resultsChan {
finalResults = append(finalResults, result)
}
if len(finalResults) == 0 {
slog.Warn("No results to send after processing", "query_id", queryID)
h.answerWithError(ctx, queryID, "Не удалось обработать ни один трек.")
return
}
if err := h.telegram.AnswerInlineQuery(ctx, queryID, finalResults); err != nil {
slog.Error("Failed to send final answer to inline query", "error", err)
}
}
func (h *InlineHandler) answerWithError(ctx context.Context, queryID, message string) {
article := tgbotapi.NewInlineQueryResultArticle(queryID, "Ошибка", message)
if err := h.telegram.AnswerInlineQuery(ctx, queryID, []interface{}{article}); err != nil {
slog.Error("Failed to answer with error", "error", err)
}
}