mirror of
https://github.com/deadcxap/YandexMusicDiscordBot.git
synced 2026-01-10 12:31:46 +03:00
impr: Async database and code optimization.
This commit is contained in:
@@ -16,18 +16,18 @@ class PlayButton(Button, VoiceExtension):
|
||||
self.item = item
|
||||
|
||||
async def callback(self, interaction: Interaction) -> None:
|
||||
logging.debug(f"Callback triggered for type: '{type(self.item).__name__}'")
|
||||
logging.debug(f"[FIND] Callback triggered for type: '{type(self.item).__name__}'")
|
||||
|
||||
if not interaction.guild:
|
||||
logging.warning("No guild found in PlayButton callback")
|
||||
logging.warning("[FIND] No guild found in PlayButton callback")
|
||||
return
|
||||
|
||||
if not await self.voice_check(interaction):
|
||||
logging.debug("Voice check failed in PlayButton callback")
|
||||
logging.debug("[FIND] Voice check failed in PlayButton callback")
|
||||
return
|
||||
|
||||
gid = interaction.guild.id
|
||||
guild = self.db.get_guild(gid)
|
||||
guild = await self.db.get_guild(gid, projection={'current_track': 1, 'current_menu': 1, 'vote_add_track': 1, 'vote_add_album': 1, 'vote_add_artist': 1, 'vote_add_playlist': 1})
|
||||
channel = cast(discord.VoiceChannel, interaction.channel)
|
||||
member = cast(discord.Member, interaction.user)
|
||||
action: Literal['add_track', 'add_album', 'add_artist', 'add_playlist']
|
||||
@@ -41,7 +41,7 @@ class PlayButton(Button, VoiceExtension):
|
||||
elif isinstance(self.item, Album):
|
||||
album = await self.item.with_tracks_async()
|
||||
if not album or not album.volumes:
|
||||
logging.debug("Failed to fetch album tracks in PlayButton callback")
|
||||
logging.debug("[FIND] Failed to fetch album tracks in PlayButton callback")
|
||||
await interaction.respond("Не удалось получить треки альбома.", ephemeral=True)
|
||||
return
|
||||
|
||||
@@ -53,7 +53,7 @@ class PlayButton(Button, VoiceExtension):
|
||||
elif isinstance(self.item, Artist):
|
||||
artist_tracks = await self.item.get_tracks_async()
|
||||
if not artist_tracks:
|
||||
logging.debug("Failed to fetch artist tracks in PlayButton callback")
|
||||
logging.debug("[FIND] Failed to fetch artist tracks in PlayButton callback")
|
||||
await interaction.respond("Не удалось получить треки артиста.", ephemeral=True)
|
||||
return
|
||||
|
||||
@@ -65,7 +65,7 @@ class PlayButton(Button, VoiceExtension):
|
||||
elif isinstance(self.item, Playlist):
|
||||
short_tracks = await self.item.fetch_tracks_async()
|
||||
if not short_tracks:
|
||||
logging.debug("Failed to fetch playlist tracks in PlayButton callback")
|
||||
logging.debug("[FIND] Failed to fetch playlist tracks in PlayButton callback")
|
||||
await interaction.respond("❌ Не удалось получить треки из плейлиста.", delete_after=15)
|
||||
return
|
||||
|
||||
@@ -77,12 +77,12 @@ class PlayButton(Button, VoiceExtension):
|
||||
elif isinstance(self.item, list):
|
||||
tracks = self.item.copy()
|
||||
if not tracks:
|
||||
logging.debug("Empty tracks list in PlayButton callback")
|
||||
logging.debug("[FIND] Empty tracks list in PlayButton callback")
|
||||
await interaction.respond("❌ Не удалось получить треки.", delete_after=15)
|
||||
return
|
||||
|
||||
action = 'add_playlist'
|
||||
vote_message = f"{member.mention} хочет добавить плейлист **** в очередь.\n\n Голосуйте за добавление."
|
||||
vote_message = f"{member.mention} хочет добавить плейлист **Мне Нравится** в очередь.\n\n Голосуйте за добавление."
|
||||
response_message = f"Плейлист **«Мне нравится»** был добавлен в очередь."
|
||||
|
||||
else:
|
||||
@@ -97,7 +97,7 @@ class PlayButton(Button, VoiceExtension):
|
||||
await response.add_reaction('✅')
|
||||
await response.add_reaction('❌')
|
||||
|
||||
self.db.update_vote(
|
||||
await self.db.update_vote(
|
||||
gid,
|
||||
response.id,
|
||||
{
|
||||
@@ -109,22 +109,22 @@ class PlayButton(Button, VoiceExtension):
|
||||
}
|
||||
)
|
||||
else:
|
||||
logging.debug(f"Skipping vote for '{action}' (from PlayButton callback)")
|
||||
logging.debug(f"[FIND] Skipping vote for '{action}' (from PlayButton callback)")
|
||||
|
||||
current_menu = await self.get_menu_message(interaction, guild['current_menu']) if guild['current_menu'] else None
|
||||
|
||||
if guild['current_track'] is not None:
|
||||
self.db.modify_track(gid, tracks, 'next', 'extend')
|
||||
logging.debug(f"[FIND] Adding tracks to queue (from PlayButton callback)")
|
||||
await self.db.modify_track(gid, tracks, 'next', 'extend')
|
||||
else:
|
||||
logging.debug(f"[FIND] Playing track (from PlayButton callback)")
|
||||
track = tracks.pop(0)
|
||||
self.db.modify_track(gid, tracks, 'next', 'extend')
|
||||
await self.db.modify_track(gid, tracks, 'next', 'extend')
|
||||
await self.play_track(interaction, track)
|
||||
response_message = f"Сейчас играет: **{track.title}**!"
|
||||
|
||||
current_menu = None
|
||||
if guild['current_menu']:
|
||||
current_menu = await self.get_menu_message(interaction, guild['current_menu'])
|
||||
|
||||
if current_menu and interaction.message:
|
||||
logging.debug(f"Deleting interaction message {interaction.message.id}: current player {current_menu.id} found")
|
||||
logging.debug(f"[FIND] Deleting interaction message {interaction.message.id}: current player {current_menu.id} found")
|
||||
await interaction.message.delete()
|
||||
else:
|
||||
await interaction.respond(response_message, delete_after=15)
|
||||
@@ -145,7 +145,7 @@ class MyVibeButton(Button, VoiceExtension):
|
||||
logging.warning(f"[VIBE] Guild ID is None in button callback")
|
||||
return
|
||||
|
||||
guild = self.db.get_guild(gid)
|
||||
guild = await self.db.get_guild(gid)
|
||||
channel = cast(discord.VoiceChannel, interaction.channel)
|
||||
|
||||
if len(channel.members) > 2 and not guild['always_allow_menu']:
|
||||
@@ -167,7 +167,7 @@ class MyVibeButton(Button, VoiceExtension):
|
||||
class ListenView(View):
|
||||
def __init__(self, item: Track | Album | Artist | Playlist | list[Track], *items: Item, timeout: float | None = 360, disable_on_timeout: bool = True):
|
||||
super().__init__(*items, timeout=timeout, disable_on_timeout=disable_on_timeout)
|
||||
logging.debug(f"Creating view for type: '{type(item).__name__}'")
|
||||
logging.debug(f"[FIND] Creating view for type: '{type(item).__name__}'")
|
||||
|
||||
if isinstance(item, Track):
|
||||
link_app = f"yandexmusic://album/{item.albums[0].id}/track/{item.id}"
|
||||
@@ -195,3 +195,9 @@ class ListenView(View):
|
||||
self.add_item(self.button2)
|
||||
self.add_item(self.button3)
|
||||
self.add_item(self.button4)
|
||||
|
||||
async def on_timeout(self) -> None:
|
||||
try:
|
||||
return await super().on_timeout()
|
||||
except discord.NotFound:
|
||||
pass
|
||||
|
||||
@@ -18,8 +18,8 @@ class ToggleRepeatButton(Button, VoiceExtension):
|
||||
if not await self.voice_check(interaction) or not interaction.guild:
|
||||
return
|
||||
gid = interaction.guild.id
|
||||
guild = self.db.get_guild(gid)
|
||||
self.db.update(gid, {'repeat': not guild['repeat']})
|
||||
guild = await self.db.get_guild(gid)
|
||||
await self.db.update(gid, {'repeat': not guild['repeat']})
|
||||
|
||||
if gid in menu_views:
|
||||
menu_views[gid].stop()
|
||||
@@ -36,8 +36,8 @@ class ToggleShuffleButton(Button, VoiceExtension):
|
||||
if not await self.voice_check(interaction) or not interaction.guild:
|
||||
return
|
||||
gid = interaction.guild.id
|
||||
guild = self.db.get_guild(gid)
|
||||
self.db.update(gid, {'shuffle': not guild['shuffle']})
|
||||
guild = await self.db.get_guild(gid)
|
||||
await self.db.update(gid, {'shuffle': not guild['shuffle']})
|
||||
|
||||
if gid in menu_views:
|
||||
menu_views[gid].stop()
|
||||
@@ -155,8 +155,8 @@ class LyricsButton(Button, VoiceExtension):
|
||||
if not await self.voice_check(interaction, check_vibe_privilage=False) or not interaction.guild_id or not interaction.user:
|
||||
return
|
||||
|
||||
ym_token = self.users_db.get_ym_token(interaction.user.id)
|
||||
current_track = self.db.get_track(interaction.guild_id, 'current')
|
||||
ym_token = await self.users_db.get_ym_token(interaction.user.id)
|
||||
current_track = await self.db.get_track(interaction.guild_id, 'current')
|
||||
if not current_track or not ym_token:
|
||||
return
|
||||
|
||||
@@ -199,7 +199,7 @@ class MyVibeButton(Button, VoiceExtension):
|
||||
logging.warning('[VIBE] No guild id in button callback')
|
||||
return
|
||||
|
||||
track = self.db.get_track(interaction.guild_id, 'current')
|
||||
track = await self.db.get_track(interaction.guild_id, 'current')
|
||||
if track:
|
||||
logging.info(f"[MENU] Playing vibe for track '{track["id"]}'")
|
||||
await self.update_vibe(
|
||||
@@ -248,7 +248,7 @@ class MyVibeSelect(Select, VoiceExtension):
|
||||
return
|
||||
|
||||
logging.info(f"[VIBE] Settings option '{custom_id}' updated to {data_value}")
|
||||
self.users_db.update(interaction.user.id, {f'vibe_settings.{custom_id}': data_value})
|
||||
await self.users_db.update(interaction.user.id, {f'vibe_settings.{custom_id}': data_value})
|
||||
|
||||
view = MyVibeSettingsView(interaction)
|
||||
view.disable_all_items()
|
||||
@@ -263,11 +263,14 @@ class MyVibeSettingsView(View, VoiceExtension):
|
||||
View.__init__(self, *items, timeout=timeout, disable_on_timeout=disable_on_timeout)
|
||||
VoiceExtension.__init__(self, None)
|
||||
|
||||
if not interaction.user:
|
||||
self.interaction = interaction
|
||||
|
||||
async def init(self) -> None:
|
||||
if not self.interaction.user:
|
||||
logging.warning('[VIBE] No user in settings view')
|
||||
return
|
||||
|
||||
settings = self.users_db.get_user(interaction.user.id)['vibe_settings']
|
||||
settings = (await self.users_db.get_user(self.interaction.user.id, projection={'vibe_settings'}))['vibe_settings']
|
||||
|
||||
diversity_settings = settings['diversity']
|
||||
diversity = [
|
||||
@@ -347,7 +350,7 @@ class AddToPlaylistSelect(Select, VoiceExtension):
|
||||
logging.debug(f"[MENU] Add to playlist select callback: {data}")
|
||||
|
||||
playlist = cast(Playlist, await self.ym_client.users_playlists(kind=data[0], user_id=data[1]))
|
||||
current_track = self.db.get_track(interaction.guild_id, 'current')
|
||||
current_track = await self.db.get_track(interaction.guild_id, 'current')
|
||||
if not current_track:
|
||||
return
|
||||
|
||||
@@ -407,13 +410,10 @@ class MenuView(View, VoiceExtension):
|
||||
def __init__(self, ctx: ApplicationContext | Interaction | RawReactionActionEvent, *items: Item, timeout: float | None = 3600, disable_on_timeout: bool = False):
|
||||
View.__init__(self, *items, timeout=timeout, disable_on_timeout=disable_on_timeout)
|
||||
VoiceExtension.__init__(self, None)
|
||||
if not ctx.guild_id:
|
||||
return
|
||||
self.ctx = ctx
|
||||
self.guild = self.db.get_guild(ctx.guild_id)
|
||||
|
||||
self.repeat_button = ToggleRepeatButton(style=ButtonStyle.success if self.guild['repeat'] else ButtonStyle.secondary, emoji='🔂', row=0)
|
||||
self.shuffle_button = ToggleShuffleButton(style=ButtonStyle.success if self.guild['shuffle'] else ButtonStyle.secondary, emoji='🔀', row=0)
|
||||
self.repeat_button = ToggleRepeatButton(style=ButtonStyle.secondary, emoji='🔂', row=0)
|
||||
self.shuffle_button = ToggleShuffleButton(style=ButtonStyle.secondary, emoji='🔀', row=0)
|
||||
self.play_pause_button = PlayPauseButton(style=ButtonStyle.primary, emoji='⏯', row=0)
|
||||
self.next_button = NextTrackButton(style=ButtonStyle.primary, emoji='⏭', row=0)
|
||||
self.prev_button = PrevTrackButton(style=ButtonStyle.primary, emoji='⏮', row=0)
|
||||
@@ -426,6 +426,16 @@ class MenuView(View, VoiceExtension):
|
||||
self.vibe_settings_button = MyVibeSettingsButton(style=ButtonStyle.success, emoji='🛠', row=1)
|
||||
|
||||
async def init(self, *, disable: bool = False) -> Self:
|
||||
if not self.ctx.guild_id:
|
||||
return self
|
||||
|
||||
self.guild = await self.db.get_guild(self.ctx.guild_id)
|
||||
|
||||
if self.guild['repeat']:
|
||||
self.repeat_button.style = ButtonStyle.success
|
||||
if self.guild['shuffle']:
|
||||
self.shuffle_button.style = ButtonStyle.success
|
||||
|
||||
current_track = self.guild['current_track']
|
||||
likes = await self.get_likes(self.ctx)
|
||||
|
||||
@@ -470,7 +480,7 @@ class MenuView(View, VoiceExtension):
|
||||
|
||||
if self.guild['current_menu']:
|
||||
await self.stop_playing(self.ctx)
|
||||
self.db.update(self.ctx.guild_id, {'current_menu': None, 'previous_tracks': [], 'vibing': False})
|
||||
await self.db.update(self.ctx.guild_id, {'current_menu': None, 'previous_tracks': [], 'vibing': False})
|
||||
message = await self.get_menu_message(self.ctx, self.guild['current_menu'])
|
||||
if message:
|
||||
await message.delete()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from math import ceil
|
||||
from typing import Any
|
||||
from typing import Self, Any
|
||||
|
||||
from discord.ui import View, Button, Item
|
||||
from discord import ApplicationContext, ButtonStyle, Interaction, Embed
|
||||
@@ -45,11 +45,11 @@ class MPNextButton(Button, VoiceExtension):
|
||||
async def callback(self, interaction: Interaction) -> None:
|
||||
if not interaction.user:
|
||||
return
|
||||
user = self.users_db.get_user(interaction.user.id)
|
||||
user = await self.users_db.get_user(interaction.user.id)
|
||||
page = user['playlists_page'] + 1
|
||||
self.users_db.update(interaction.user.id, {'playlists_page': page})
|
||||
await self.users_db.update(interaction.user.id, {'playlists_page': page})
|
||||
embed = generate_playlists_embed(page, user['playlists'])
|
||||
await interaction.edit(embed=embed, view=MyPlaylists(interaction))
|
||||
await interaction.edit(embed=embed, view=await MyPlaylists(interaction).init())
|
||||
|
||||
class MPPrevButton(Button, VoiceExtension):
|
||||
def __init__(self, **kwargs):
|
||||
@@ -59,31 +59,37 @@ class MPPrevButton(Button, VoiceExtension):
|
||||
async def callback(self, interaction: Interaction) -> None:
|
||||
if not interaction.user:
|
||||
return
|
||||
user = self.users_db.get_user(interaction.user.id)
|
||||
user = await self.users_db.get_user(interaction.user.id)
|
||||
page = user['playlists_page'] - 1
|
||||
self.users_db.update(interaction.user.id, {'playlists_page': page})
|
||||
await self.users_db.update(interaction.user.id, {'playlists_page': page})
|
||||
embed = generate_playlists_embed(page, user['playlists'])
|
||||
await interaction.edit(embed=embed, view=MyPlaylists(interaction))
|
||||
await interaction.edit(embed=embed, view=await MyPlaylists(interaction).init())
|
||||
|
||||
class MyPlaylists(View, VoiceExtension):
|
||||
def __init__(self, ctx: ApplicationContext | Interaction, *items: Item, timeout: float | None = 360, disable_on_timeout: bool = True):
|
||||
View.__init__(self, *items, timeout=timeout, disable_on_timeout=disable_on_timeout)
|
||||
VoiceExtension.__init__(self, None)
|
||||
if not ctx.user:
|
||||
return
|
||||
user = self.users_db.get_user(ctx.user.id)
|
||||
|
||||
self.ctx = ctx
|
||||
self.next_button = MPNextButton(style=ButtonStyle.primary, emoji='▶️')
|
||||
self.prev_button = MPPrevButton(style=ButtonStyle.primary, emoji='◀️')
|
||||
|
||||
async def init(self) -> Self:
|
||||
if not self.ctx.user:
|
||||
return self
|
||||
|
||||
user = await self.users_db.get_user(self.ctx.user.id)
|
||||
count = 10 * user['playlists_page']
|
||||
|
||||
next_button = MPNextButton(style=ButtonStyle.primary, emoji='▶️')
|
||||
prev_button = MPPrevButton(style=ButtonStyle.primary, emoji='◀️')
|
||||
|
||||
|
||||
if not user['playlists'][count + 10:]:
|
||||
next_button.disabled = True
|
||||
self.next_button.disabled = True
|
||||
if not user['playlists'][:count]:
|
||||
prev_button.disabled = True
|
||||
self.prev_button.disabled = True
|
||||
|
||||
self.add_item(self.prev_button)
|
||||
self.add_item(self.next_button)
|
||||
|
||||
self.add_item(prev_button)
|
||||
self.add_item(next_button)
|
||||
return self
|
||||
|
||||
class QueueNextButton(Button, VoiceExtension):
|
||||
def __init__(self, **kwargs):
|
||||
@@ -93,12 +99,12 @@ class QueueNextButton(Button, VoiceExtension):
|
||||
async def callback(self, interaction: Interaction) -> None:
|
||||
if not interaction.user or not interaction.guild:
|
||||
return
|
||||
user = self.users_db.get_user(interaction.user.id)
|
||||
user = await self.users_db.get_user(interaction.user.id)
|
||||
page = user['queue_page'] + 1
|
||||
self.users_db.update(interaction.user.id, {'queue_page': page})
|
||||
tracks = self.db.get_tracks_list(interaction.guild.id, 'next')
|
||||
await self.users_db.update(interaction.user.id, {'queue_page': page})
|
||||
tracks = await self.db.get_tracks_list(interaction.guild.id, 'next')
|
||||
embed = generate_queue_embed(page, tracks)
|
||||
await interaction.edit(embed=embed, view=QueueView(interaction))
|
||||
await interaction.edit(embed=embed, view=await QueueView(interaction).init())
|
||||
|
||||
class QueuePrevButton(Button, VoiceExtension):
|
||||
def __init__(self, **kwargs):
|
||||
@@ -108,31 +114,38 @@ class QueuePrevButton(Button, VoiceExtension):
|
||||
async def callback(self, interaction: Interaction) -> None:
|
||||
if not interaction.user or not interaction.guild:
|
||||
return
|
||||
user = self.users_db.get_user(interaction.user.id)
|
||||
user = await self.users_db.get_user(interaction.user.id)
|
||||
page = user['queue_page'] - 1
|
||||
self.users_db.update(interaction.user.id, {'queue_page': page})
|
||||
tracks = self.db.get_tracks_list(interaction.guild.id, 'next')
|
||||
await self.users_db.update(interaction.user.id, {'queue_page': page})
|
||||
tracks = await self.db.get_tracks_list(interaction.guild.id, 'next')
|
||||
embed = generate_queue_embed(page, tracks)
|
||||
await interaction.edit(embed=embed, view=QueueView(interaction))
|
||||
await interaction.edit(embed=embed, view=await QueueView(interaction).init())
|
||||
|
||||
class QueueView(View, VoiceExtension):
|
||||
def __init__(self, ctx: ApplicationContext | Interaction, *items: Item, timeout: float | None = 360, disable_on_timeout: bool = True):
|
||||
View.__init__(self, *items, timeout=timeout, disable_on_timeout=disable_on_timeout)
|
||||
VoiceExtension.__init__(self, None)
|
||||
if not ctx.user or not ctx.guild:
|
||||
return
|
||||
|
||||
tracks = self.db.get_tracks_list(ctx.guild.id, 'next')
|
||||
user = self.users_db.get_user(ctx.user.id)
|
||||
self.ctx = ctx
|
||||
self.next_button = QueueNextButton(style=ButtonStyle.primary, emoji='▶️')
|
||||
self.prev_button = QueuePrevButton(style=ButtonStyle.primary, emoji='◀️')
|
||||
|
||||
async def init(self) -> Self:
|
||||
if not self.ctx.user or not self.ctx.guild:
|
||||
return self
|
||||
|
||||
tracks = await self.db.get_tracks_list(self.ctx.guild.id, 'next')
|
||||
user = await self.users_db.get_user(self.ctx.user.id)
|
||||
|
||||
count = 15 * user['queue_page']
|
||||
|
||||
next_button = QueueNextButton(style=ButtonStyle.primary, emoji='▶️')
|
||||
prev_button = QueuePrevButton(style=ButtonStyle.primary, emoji='◀️')
|
||||
|
||||
|
||||
if not tracks[count + 15:]:
|
||||
next_button.disabled = True
|
||||
self.next_button.disabled = True
|
||||
if not tracks[:count]:
|
||||
prev_button.disabled = True
|
||||
|
||||
self.add_item(prev_button)
|
||||
self.add_item(next_button)
|
||||
self.prev_button.disabled = True
|
||||
|
||||
self.add_item(self.prev_button)
|
||||
self.add_item(self.next_button)
|
||||
|
||||
return self
|
||||
|
||||
Reference in New Issue
Block a user