122 lines
4.1 KiB
Go
122 lines
4.1 KiB
Go
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)
|
||
}
|
||
}
|