All checks were successful
continuous-integration/drone/push Build is passing
86 lines
3.2 KiB
Go
86 lines
3.2 KiB
Go
// yamusic-bot/cmd/bot/main.go
|
||
|
||
package main
|
||
|
||
import (
|
||
"context"
|
||
"log/slog"
|
||
"time"
|
||
|
||
"gitea.mrixs.me/Mrixs/yamusic-bot/internal/admin"
|
||
"gitea.mrixs.me/Mrixs/yamusic-bot/internal/bot"
|
||
"gitea.mrixs.me/Mrixs/yamusic-bot/internal/config"
|
||
"gitea.mrixs.me/Mrixs/yamusic-bot/internal/processor"
|
||
"gitea.mrixs.me/Mrixs/yamusic-bot/internal/storage"
|
||
"gitea.mrixs.me/Mrixs/yamusic-bot/pkg/downloader"
|
||
"gitea.mrixs.me/Mrixs/yamusic-bot/pkg/logging"
|
||
"gitea.mrixs.me/Mrixs/yamusic-bot/pkg/tagger"
|
||
"gitea.mrixs.me/Mrixs/yamusic-bot/pkg/yamusic"
|
||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||
"golang.org/x/time/rate"
|
||
)
|
||
|
||
func main() {
|
||
startTime := time.Now()
|
||
ctx := context.Background()
|
||
|
||
// 1. Инициализация конфигурации
|
||
cfg := config.New()
|
||
|
||
// 2. Инициализация логгера
|
||
logger := logging.NewLogger(cfg.LogLevel)
|
||
slog.SetDefault(logger)
|
||
|
||
slog.Info("Starting Yandex.Music Downloader Bot...", "version", "1.0")
|
||
|
||
// 3. Инициализация зависимостей
|
||
db, err := storage.NewSQLiteStorage(ctx, cfg.DatabasePath)
|
||
if err != nil {
|
||
slog.Error("Failed to initialize storage", "error", err)
|
||
return
|
||
}
|
||
|
||
yandexClient, err := yamusic.NewApiClient(cfg.YandexMusicToken)
|
||
if err != nil {
|
||
slog.Error("Failed to initialize yandex client", "error", err)
|
||
return
|
||
}
|
||
|
||
tgAPI, err := tgbotapi.NewBotAPI(cfg.TelegramBotToken)
|
||
if err != nil {
|
||
slog.Error("Failed to initialize telegram bot api", "error", err)
|
||
return
|
||
}
|
||
tgAPI.Debug = cfg.LogLevel == "debug"
|
||
slog.Info("Authorized on account", "username", tgAPI.Self.UserName)
|
||
|
||
// 4. Инициализация компонентов
|
||
downloaderComponent := downloader.NewHTTPDownloader()
|
||
taggerComponent := tagger.NewID3Tagger()
|
||
|
||
// Создаем БЫСТРЫЙ лимитер для общих вызовов API (в секунду)
|
||
fastLimiter := rate.NewLimiter(rate.Limit(cfg.TelegramAPIRateLimit), cfg.TelegramAPIRateLimit)
|
||
slog.Info("General Telegram API rate limit set", "requests_per_second", cfg.TelegramAPIRateLimit)
|
||
|
||
// Создаем МЕДЛЕННЫЙ лимитер для кэш-канала (в минуту)
|
||
// rate.Limit измеряется в событиях/секунду, поэтому конвертируем
|
||
// Burst size = 1, чтобы избежать отправки пачки сообщений и долгого ожидания
|
||
cacheRPS := float64(cfg.TelegramCacheRateLimitPerMinute) / 60.0
|
||
cacheLimiter := rate.NewLimiter(rate.Limit(cacheRPS), 1)
|
||
slog.Info("Cache channel Telegram API rate limit set", "requests_per_minute", cfg.TelegramCacheRateLimitPerMinute)
|
||
|
||
// Передаем оба лимитера в адаптер
|
||
telegramClient := bot.NewTelegramClientAdapter(tgAPI, cfg.TelegramCacheChatID, fastLimiter, cacheLimiter)
|
||
|
||
trackProcessor := processor.NewTrackProcessor(db, yandexClient, downloaderComponent, taggerComponent, telegramClient)
|
||
|
||
adminHandler := admin.NewHandler(db, telegramClient, yandexClient, taggerComponent, startTime)
|
||
inlineHandler := bot.NewInlineHandler(yandexClient, trackProcessor, telegramClient)
|
||
|
||
// 5. Создание и запуск приложения
|
||
app := bot.NewApp(cfg, tgAPI, db, adminHandler, inlineHandler)
|
||
app.Run(ctx)
|
||
|
||
slog.Info("Bot stopped.")
|
||
}
|