Files
yamusic-bot/cmd/bot/main.go
Vladimir Zagainov 1852c5025e
All checks were successful
continuous-integration/drone/push Build is passing
add rate limiter to telegram
2025-06-24 12:40:42 +03:00

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