// 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.") }