Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion bot/handlers/get_track.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from aiogram.types import BufferedInputFile
from aiogram.utils.i18n import gettext

from bot.utils import load_tracks_from_db
from bot.utils import get_user_pic, load_tracks_from_db
from service import Music, Track

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -41,6 +41,7 @@ async def send_track(
title=track.title,
performer=track.performer,
caption=gettext("promo_caption").format(username=me.username),
thumbnail=await get_user_pic(bot, me),
)
except Exception:
if callback.message is not None:
Expand Down
26 changes: 26 additions & 0 deletions bot/utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
"""Utils for the bot."""

from __future__ import annotations

from typing import TYPE_CHECKING

from aiogram.types import InputFile, URLInputFile

from database.crud import CRUD
from database.models import SearchHistory
from service.data import Track

if TYPE_CHECKING:
from aiogram import Bot
from aiogram.types import User


async def load_tracks_from_db(search_id: int) -> list[Track]:
"""Get tracks from the database."""
Expand All @@ -16,3 +26,19 @@ async def load_tracks_from_db(search_id: int) -> list[Track]:
return []

return [Track.from_dict(track) for track in search.tracks]


async def get_user_pic(bot: Bot, user: User) -> InputFile | None:
"""Get user pic."""
url = f"https://api.telegram.org/file/bot{bot.token}/"

photos = await user.get_profile_photos(limit=1)

if photos.total_count:
best = photos.photos[0][-1]
bot_pic = await bot.get_file(best.file_id)

if bot_pic.file_path:
return URLInputFile(url + bot_pic.file_path)

return None
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ aiogram[i18n]==3.17.0
sqlalchemy==2.0.36
beautifulsoup4==4.12.3
asyncpg==0.30.0
tenacity==9.1.2
9 changes: 9 additions & 0 deletions service/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import aiohttp
from aiohttp import ClientTimeout
from bs4 import BeautifulSoup, Tag
from tenacity import retry, stop_after_attempt, wait_exponential
from typing_extensions import Self

from .data import ServiceConfig, Track
Expand Down Expand Up @@ -69,6 +70,10 @@ async def get_top_hits(self) -> list[Track]:
"""Get top tracks."""
return await self._parse_tracks(f"https://{self.BASE_URL}")

@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=1, max=5),
)
async def _parse_tracks(self, url: str) -> list[Track]:
"""Parse tracks from the given URL."""
try:
Expand Down Expand Up @@ -140,6 +145,10 @@ async def _download_data(
msg = f"Failed to download {resource_type}"
raise MusicServiceError(msg) from e

@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=1, max=5),
)
async def get_audio_bytes(self, track: Track) -> bytes:
"""Download music file."""
return await self._download_data(track.audio_url, "audio", track.name)
Expand Down