impr: Remove restricted access to the Vibe.

This commit is contained in:
Lemon4ksan
2025-03-15 21:43:41 +03:00
parent 7fe9d699b1
commit 1f63a4c50d
3 changed files with 106 additions and 83 deletions

View File

@@ -35,10 +35,10 @@ class BaseBot:
Returns: Returns:
(YMClient | None): Client or None. (YMClient | None): Client or None.
""" """
logging.debug("[VC_EXT] Initializing Yandex Music client") logging.debug("[BASE_BOT] Initializing Yandex Music client")
if not (token := await self.get_ym_token(ctx)): if not (token := await self.get_ym_token(ctx)):
logging.debug("[VC_EXT] No token found") logging.debug("[BASE_BOT] No token found")
await self.send_response_message(ctx, "❌ Укажите токен через /account login.", delete_after=15, ephemeral=True) await self.send_response_message(ctx, "❌ Укажите токен через /account login.", delete_after=15, ephemeral=True)
return None return None
@@ -138,6 +138,31 @@ class BaseBot:
logging.debug(f"[BASE_BOT] Failed to get message: {e}") logging.debug(f"[BASE_BOT] Failed to get message: {e}")
raise raise
async def get_discord_user_by_id(self, ctx: ApplicationContext | Interaction | RawReactionActionEvent, user_id: int) -> discord.User | None:
if isinstance(ctx, ApplicationContext) and ctx.user:
logging.debug(f"[BASE_BOT] Getting user {user_id} from ApplicationContext")
return await ctx.bot.fetch_user(user_id)
elif isinstance(ctx, Interaction):
logging.debug(f"[BASE_BOT] Getting user {user_id} from Interaction")
return await ctx.client.fetch_user(user_id)
elif not self.bot:
raise ValueError("Bot instance is not available")
else:
logging.debug(f"[BASE_BOT] Getting user {user_id} from bot instance")
return await self.bot.fetch_user(user_id)
async def get_viber_id_from_ctx(self, ctx: ApplicationContext | Interaction | RawReactionActionEvent) -> int | None:
if not ctx.guild_id:
logging.warning("[BASE_BOT] Guild not found")
return None
guild = await self.db.get_guild(ctx.guild_id, projection={'current_viber_id': 1})
if guild['current_viber_id']:
return guild['current_viber_id']
return ctx.user_id if isinstance(ctx, discord.RawReactionActionEvent) else ctx.user.id if ctx.user else None
async def update_menu_views_dict( async def update_menu_views_dict(
self, self,
ctx: ApplicationContext | Interaction | RawReactionActionEvent, ctx: ApplicationContext | Interaction | RawReactionActionEvent,
@@ -152,31 +177,17 @@ class BaseBot:
guild (ExplicitGuild): Guild. guild (ExplicitGuild): Guild.
disable (bool, optional): Disable menu. Defaults to False. disable (bool, optional): Disable menu. Defaults to False.
""" """
logging.debug(f"[VC_EXT] Updating menu views dict for guild {ctx.guild_id}") logging.debug(f"[BASE_BOT] Updating menu views dict for guild {ctx.guild_id}")
from MusicBot.ui import MenuView from MusicBot.ui import MenuView
if not ctx.guild_id: if not ctx.guild_id:
logging.warning("[VC_EXT] Guild not found") logging.warning("[BASE_BOT] Guild not found")
return return
if ctx.guild_id in self.menu_views: if ctx.guild_id in self.menu_views:
self.menu_views[ctx.guild_id].stop() self.menu_views[ctx.guild_id].stop()
self.menu_views[ctx.guild_id] = await MenuView(ctx).init(disable=disable) self.menu_views[ctx.guild_id] = await MenuView(ctx).init(disable=disable)
async def get_discord_user_by_id(self, ctx: ApplicationContext | Interaction | RawReactionActionEvent, user_id: int) -> discord.User | None:
if isinstance(ctx, ApplicationContext) and ctx.user:
logging.debug(f"[BASE_BOT] Getting user {user_id} from ApplicationContext")
return await ctx.bot.fetch_user(user_id)
elif isinstance(ctx, Interaction):
logging.debug(f"[BASE_BOT] Getting user {user_id} from Interaction")
return await ctx.client.fetch_user(user_id)
elif not self.bot:
raise ValueError("Bot instance is not available")
else:
logging.debug(f"[BASE_BOT] Getting user {user_id} from bot instance")
return await self.bot.fetch_user(user_id)
def get_current_event_loop(self, ctx: ApplicationContext | Interaction | RawReactionActionEvent) -> asyncio.AbstractEventLoop: def get_current_event_loop(self, ctx: ApplicationContext | Interaction | RawReactionActionEvent) -> asyncio.AbstractEventLoop:
"""Get the current event loop. If the context is a RawReactionActionEvent, get the loop from the self.bot instance. """Get the current event loop. If the context is a RawReactionActionEvent, get the loop from the self.bot instance.
@@ -200,4 +211,4 @@ class BaseBot:
raise ValueError("Bot is not set.") raise ValueError("Bot is not set.")
return self.bot.loop return self.bot.loop
else: else:
raise TypeError(f"Invalid context type: '{type(ctx).__name__}'.") raise TypeError(f"Invalid context type: '{type(ctx).__name__}'.")

View File

@@ -264,21 +264,19 @@ class VoiceExtension(BaseBot):
""" """
logging.info(f"[VC_EXT] Updating vibe for guild {ctx.guild_id} with type '{vibe_type}' and id '{item_id}'") logging.info(f"[VC_EXT] Updating vibe for guild {ctx.guild_id} with type '{vibe_type}' and id '{item_id}'")
uid = viber_id if viber_id else ctx.user_id if isinstance(ctx, discord.RawReactionActionEvent) else ctx.user.id if ctx.user else None uid = viber_id if viber_id else await self.get_viber_id_from_ctx(ctx)
if not uid or not ctx.guild_id: if not uid or not ctx.guild_id:
logging.warning("[VC_EXT] Guild ID or User ID not found in context") logging.warning("[VC_EXT] Guild ID or User ID not found in context")
return False return False
user = await self.users_db.get_user(uid, projection={'vibe_settings': 1})
guild = await self.db.get_guild(ctx.guild_id, projection={'vibing': 1, 'current_track': 1})
if not (client := await self.init_ym_client(ctx)): if not (client := await self.init_ym_client(ctx)):
return False return False
if update_settings: if update_settings:
logging.debug("[VIBE] Updating vibe settings") logging.debug("[VIBE] Updating vibe settings")
user = await self.users_db.get_user(uid, projection={'vibe_settings': 1})
settings = user['vibe_settings'] settings = user['vibe_settings']
await client.rotor_station_settings2( await client.rotor_station_settings2(
f"{vibe_type}:{item_id}", f"{vibe_type}:{item_id}",
@@ -287,6 +285,8 @@ class VoiceExtension(BaseBot):
language=settings['lang'] language=settings['lang']
) )
guild = await self.db.get_guild(ctx.guild_id, projection={'vibing': 1, 'current_track': 1})
if not guild['vibing']: if not guild['vibing']:
try: try:
feedback = await client.rotor_station_feedback_radio_started( feedback = await client.rotor_station_feedback_radio_started(
@@ -371,7 +371,7 @@ class VoiceExtension(BaseBot):
guild = await self.db.get_guild(ctx.guild_id, projection={'current_viber_id': 1, 'vibing': 1}) guild = await self.db.get_guild(ctx.guild_id, projection={'current_viber_id': 1, 'vibing': 1})
if guild['vibing'] and ctx.user.id != guild['current_viber_id']: if guild['vibing'] and ctx.user.id != guild['current_viber_id']:
logging.debug("[VIBE] Context user is not the current viber") logging.debug("[VIBE] Context user is not the current viber")
await ctx.respond("❌ Вы не можете взаимодействовать с чужой волной!", delete_after=15, ephemeral=True) await ctx.respond("❌ Вы не можете изменять чужую волну!", delete_after=15, ephemeral=True)
return False return False
logging.debug("[VC_EXT] Voice requirements met") logging.debug("[VC_EXT] Voice requirements met")
@@ -504,7 +504,8 @@ class VoiceExtension(BaseBot):
menu_message: discord.Message | None = None, menu_message: discord.Message | None = None,
button_callback: bool = False button_callback: bool = False
) -> str | None: ) -> str | None:
"""Switch to the next track in the queue. Return track title on success. Performs all additional actions like updating menu and sending vibe feedback. """Switch to the next track in the queue. Return track title on success.
Performs all additional actions like updating menu and sending vibe feedback.
Doesn't change track if stopped. Stop playing if tracks list is empty. Doesn't change track if stopped. Stop playing if tracks list is empty.
Args: Args:
@@ -519,14 +520,11 @@ class VoiceExtension(BaseBot):
""" """
logging.debug("[VC_EXT] Switching to next track") logging.debug("[VC_EXT] Switching to next track")
uid = ctx.user_id if isinstance(ctx, discord.RawReactionActionEvent) else ctx.user.id if ctx.user else None if not (uid := await self.get_viber_id_from_ctx(ctx)) or not ctx.guild_id:
if not ctx.guild_id or not uid:
logging.warning("[VC_EXT] Guild ID or User ID not found in context inside 'next_track'") logging.warning("[VC_EXT] Guild ID or User ID not found in context inside 'next_track'")
return None return None
guild = await self.db.get_guild(ctx.guild_id, projection={'shuffle': 1, 'repeat': 1, 'is_stopped': 1, 'current_menu': 1, 'vibing': 1, 'current_track': 1}) guild = await self.db.get_guild(ctx.guild_id, projection={'shuffle': 1, 'repeat': 1, 'is_stopped': 1, 'current_menu': 1, 'vibing': 1, 'current_track': 1})
user = await self.users_db.get_user(uid)
if guild['is_stopped'] and after: if guild['is_stopped'] and after:
logging.debug("[VC_EXT] Playback is stopped, skipping after callback.") logging.debug("[VC_EXT] Playback is stopped, skipping after callback.")
@@ -553,7 +551,12 @@ class VoiceExtension(BaseBot):
next_track = await self.db.get_track(ctx.guild_id, 'next') next_track = await self.db.get_track(ctx.guild_id, 'next')
if not next_track and guild['vibing']: if not next_track and guild['vibing']:
# NOTE: Real vibe gets next tracks after each skip. For smoother experience
# we get next tracks only after all the other tracks are finished
logging.debug("[VC_EXT] No next track found, generating new vibe") logging.debug("[VC_EXT] No next track found, generating new vibe")
user = await self.users_db.get_user(uid)
if not user['vibe_type'] or not user['vibe_id']: if not user['vibe_type'] or not user['vibe_id']:
logging.warning("[VC_EXT] No vibe type or vibe id found in user data") logging.warning("[VC_EXT] No vibe type or vibe id found in user data")
return None return None
@@ -701,9 +704,6 @@ class VoiceExtension(BaseBot):
bool: Success status. bool: Success status.
""" """
logging.info(f"[VOICE] Performing '{vote_data['action']}' action for message {ctx.message_id}") logging.info(f"[VOICE] Performing '{vote_data['action']}' action for message {ctx.message_id}")
if guild['current_viber_id']:
ctx.user_id = guild['current_viber_id']
if not ctx.guild_id: if not ctx.guild_id:
logging.warning("[VOICE] Guild not found") logging.warning("[VOICE] Guild not found")
@@ -818,20 +818,11 @@ class VoiceExtension(BaseBot):
""" """
logging.debug(f"[VC_EXT] Sending vibe feedback, type: {feedback_type}") logging.debug(f"[VC_EXT] Sending vibe feedback, type: {feedback_type}")
uid = ctx.user_id if isinstance(ctx, discord.RawReactionActionEvent) else ctx.user.id if ctx.user else None if not (uid := await self.get_viber_id_from_ctx(ctx)) or not ctx.guild_id:
if not uid or not ctx.guild_id:
logging.warning("[VC_EXT] User id or guild id not found") logging.warning("[VC_EXT] User id or guild id not found")
return False return False
guild = await self.db.get_guild(ctx.guild_id, projection={'current_viber_id': 1}) user = await self.users_db.get_user(uid, projection={'vibe_batch_id': 1, 'vibe_type': 1, 'vibe_id': 1})
if guild['current_viber_id']:
viber_id = guild['current_viber_id']
else:
viber_id = uid
user = await self.users_db.get_user(viber_id, projection={'vibe_batch_id': 1, 'vibe_type': 1, 'vibe_id': 1})
if not (client := await self.init_ym_client(ctx)): if not (client := await self.init_ym_client(ctx)):
logging.info(f"[VC_EXT] Failed to init YM client for user {user['_id']}") logging.info(f"[VC_EXT] Failed to init YM client for user {user['_id']}")
@@ -871,12 +862,18 @@ class VoiceExtension(BaseBot):
logging.warning(f"[VC_EXT] Timed out while downloading track '{track.title}'") logging.warning(f"[VC_EXT] Timed out while downloading track '{track.title}'")
raise raise
async def _delete_menu_message(self, ctx: ApplicationContext | Interaction | RawReactionActionEvent, current_menu: int, gid: int) -> Literal[True]: async def _delete_menu_message(
self,
ctx: ApplicationContext | Interaction | RawReactionActionEvent,
current_menu: int,
gid: int
) -> Literal[True]:
"""Delete current menu message and stop menu view. Return True on success. """Delete current menu message and stop menu view. Return True on success.
Args: Args:
ctx (ApplicationContext | Interaction | RawReactionActionEvent): Context. ctx (ApplicationContext | Interaction | RawReactionActionEvent): Context.
guild (ExplicitGuild): Guild. current_menu (int): Current menu message ID.
gid (int): Guild ID.
Returns: Returns:
Literal[True]: Always returns True. Literal[True]: Always returns True.
@@ -916,34 +913,32 @@ class VoiceExtension(BaseBot):
Returns: Returns:
(str | None): Song title or None. (str | None): Song title or None.
""" """
gid = ctx.guild_id
uid = ctx.user_id if isinstance(ctx, discord.RawReactionActionEvent) else ctx.user.id if ctx.user else None
if not gid or not uid: if not ctx.guild_id:
logging.warning("Guild ID or User ID not found in context") logging.warning("Guild ID or User ID not found in context")
return None return None
guild = await self.db.get_guild(gid, projection={'current_menu': 1, 'vibing': 1, 'current_track': 1}) guild = await self.db.get_guild(ctx.guild_id, projection={'current_menu': 1, 'vibing': 1, 'current_track': 1})
if not (vc := await self.get_voice_client(ctx) if not vc else vc): if not (vc := await self.get_voice_client(ctx) if not vc else vc):
return None return None
try: try:
if not guild['current_track'] or track.id != guild['current_track']['id']: if not guild['current_track'] or track.id != guild['current_track']['id']:
await self._download_track(gid, track) await self._download_track(ctx.guild_id, track)
except yandex_music.exceptions.TimedOutError: except yandex_music.exceptions.TimedOutError:
if not retry: if not retry:
return await self._play_track(ctx, track, vc=vc, menu_message=menu_message, button_callback=button_callback, retry=True) return await self._play_track(ctx, track, vc=vc, menu_message=menu_message, button_callback=button_callback, retry=True)
else:
await self.send_response_message(ctx, f"😔 Не удалось загрузить трек. Попробуйте сбросить меню.", delete_after=15) await self.send_response_message(ctx, f"😔 Не удалось загрузить трек. Попробуйте сбросить меню.", delete_after=15)
logging.error(f"[VC_EXT] Failed to download track '{track.title}'") logging.error(f"[VC_EXT] Failed to download track '{track.title}'")
return None return None
async with aiofiles.open(f'music/{gid}.mp3', "rb") as f: async with aiofiles.open(f'music/{ctx.guild_id}.mp3', "rb") as f:
track_bytes = io.BytesIO(await f.read()) track_bytes = io.BytesIO(await f.read())
song = discord.FFmpegPCMAudio(track_bytes, pipe=True, options='-vn -b:a 64k -filter:a "volume=0.15"') song = discord.FFmpegPCMAudio(track_bytes, pipe=True, options='-vn -b:a 64k -filter:a "volume=0.15"')
await self.db.set_current_track(gid, track) await self.db.set_current_track(ctx.guild_id, track)
if menu_message or guild['current_menu']: if menu_message or guild['current_menu']:
# Updating menu message before playing to prevent delay and avoid FFMPEG lags. # Updating menu message before playing to prevent delay and avoid FFMPEG lags.
@@ -966,7 +961,7 @@ class VoiceExtension(BaseBot):
return None return None
logging.info(f"[VC_EXT] Playing track '{track.title}'") logging.info(f"[VC_EXT] Playing track '{track.title}'")
await self.db.update(gid, {'is_stopped': False}) await self.db.update(ctx.guild_id, {'is_stopped': False})
if guild['vibing']: if guild['vibing']:
await self.send_vibe_feedback(ctx, 'trackStarted', track) await self.send_vibe_feedback(ctx, 'trackStarted', track)

View File

@@ -29,7 +29,7 @@ class ToggleButton(Button, VoiceExtension):
await interaction.respond("❌ Что-то пошло не так. Попробуйте снова.", delete_after=15, ephemeral=True) await interaction.respond("❌ Что-то пошло не так. Попробуйте снова.", delete_after=15, ephemeral=True)
return return
if not await self.voice_check(interaction, check_vibe_privilage=True): if not await self.voice_check(interaction):
return return
guild = await self.db.get_guild(gid) guild = await self.db.get_guild(gid)
@@ -72,7 +72,8 @@ class PlayPauseButton(Button, VoiceExtension):
async def callback(self, interaction: Interaction) -> None: async def callback(self, interaction: Interaction) -> None:
logging.info('[MENU] Play/Pause button callback...') logging.info('[MENU] Play/Pause button callback...')
if not await self.voice_check(interaction, check_vibe_privilage=True):
if not await self.voice_check(interaction):
return return
if not (gid := interaction.guild_id) or not interaction.user: if not (gid := interaction.guild_id) or not interaction.user:
@@ -114,11 +115,15 @@ class PlayPauseButton(Button, VoiceExtension):
await interaction.respond("❌ Нет воспроизводимого трека.", delete_after=15, ephemeral=True) await interaction.respond("❌ Нет воспроизводимого трека.", delete_after=15, ephemeral=True)
return return
guild = await self.db.get_guild(interaction.guild_id, projection={'single_token_uid': 1})
if vc.is_paused(): if vc.is_paused():
vc.resume() vc.resume()
embed.remove_footer() if guild['single_token_uid'] and (user := await self.get_discord_user_by_id(interaction, guild['single_token_uid'])):
embed.set_footer(text=f"Используется токен {user.display_name}", icon_url=user.display_avatar.url)
else:
embed.remove_footer()
else: else:
vc.pause()
embed.set_footer(text='Приостановлено') embed.set_footer(text='Приостановлено')
await interaction.edit(embed=embed) await interaction.edit(embed=embed)
@@ -139,7 +144,7 @@ class SwitchTrackButton(Button, VoiceExtension):
logging.info(f'[MENU] {callback_type.capitalize()} track button callback') logging.info(f'[MENU] {callback_type.capitalize()} track button callback')
if not await self.voice_check(interaction, check_vibe_privilage=True): if not await self.voice_check(interaction):
return return
tracks_type = callback_type + '_tracks' tracks_type = callback_type + '_tracks'
@@ -240,8 +245,7 @@ class LyricsButton(Button, VoiceExtension):
if not await self.voice_check(interaction) or not interaction.guild_id or not interaction.user: if not await self.voice_check(interaction) or not interaction.guild_id or not interaction.user:
return return
client = await self.init_ym_client(interaction) if not (client := await self.init_ym_client(interaction)):
if not client:
return return
current_track = await self.db.get_track(interaction.guild_id, 'current') current_track = await self.db.get_track(interaction.guild_id, 'current')
@@ -286,18 +290,18 @@ class MyVibeButton(Button, VoiceExtension):
member = cast(Member, interaction.user) member = cast(Member, interaction.user)
channel = cast(VoiceChannel, interaction.channel) channel = cast(VoiceChannel, interaction.channel)
track = await self.db.get_track(interaction.guild_id, 'current') track = await self.db.get_track(interaction.guild_id, 'current')
if len(channel.members) > 2 and not member.guild_permissions.manage_channels: if len(channel.members) > 2 and not member.guild_permissions.manage_channels:
logging.info(f"Starting vote for starting vibe in guild {interaction.guild_id}") logging.info(f"Starting vote for starting vibe in guild {interaction.guild_id}")
if track: if track:
response_message = f"{member.mention} хочет запустить волну по треку **{track['title']}**.\n\n Выполнить действие?" response_message = f"{member.mention} хочет запустить волну по треку **{track['title']}**.\n\n Выполнить действие?"
_type = 'track' vibe_type = 'track'
_id = track['id'] vibe_id = track['id']
else: else:
response_message = f"{member.mention} хочет запустить станцию **Моя Волна**.\n\n Выполнить действие?" response_message = f"{member.mention} хочет запустить станцию **Моя Волна**.\n\n Выполнить действие?"
_type = 'user' vibe_type = 'user'
_id = 'onyourwave' vibe_id = 'onyourwave'
message = cast(Interaction, await interaction.respond(response_message)) message = cast(Interaction, await interaction.respond(response_message))
response = await message.original_response() response = await message.original_response()
@@ -313,7 +317,7 @@ class MyVibeButton(Button, VoiceExtension):
'negative_votes': list(), 'negative_votes': list(),
'total_members': len(channel.members), 'total_members': len(channel.members),
'action': 'vibe_station', 'action': 'vibe_station',
'vote_content': [_type, _id, interaction.user.id] 'vote_content': [vibe_type, vibe_id, interaction.user.id]
} }
) )
return return
@@ -337,8 +341,7 @@ class MyVibeButton(Button, VoiceExtension):
logging.info('[MENU] Failed to start the vibe') logging.info('[MENU] Failed to start the vibe')
await interaction.respond('Не удалось запустить "Мою Волну". Возможно, у вас нет подписки на Яндекс Музыку.', ephemeral=True) await interaction.respond('Не удалось запустить "Мою Волну". Возможно, у вас нет подписки на Яндекс Музыку.', ephemeral=True)
next_track = await self.db.get_track(interaction.guild_id, 'next') if (next_track := await self.db.get_track(interaction.guild_id, 'next')):
if next_track:
await self.play_track(interaction, next_track, button_callback=True) await self.play_track(interaction, next_track, button_callback=True)
class MyVibeSelect(Select, VoiceExtension): class MyVibeSelect(Select, VoiceExtension):
@@ -539,8 +542,7 @@ class AddToPlaylistButton(Button, VoiceExtension):
await interaction.respond('❌ Нет воспроизводимого трека.', delete_after=15, ephemeral=True) await interaction.respond('❌ Нет воспроизводимого трека.', delete_after=15, ephemeral=True)
return return
client = await self.init_ym_client(interaction) if not (client := await self.init_ym_client(interaction)):
if not client:
await interaction.respond('❌ Что-то пошло не так. Попробуйте позже.', delete_after=15, ephemeral=True) await interaction.respond('❌ Что-то пошло не так. Попробуйте позже.', delete_after=15, ephemeral=True)
return return
@@ -582,7 +584,7 @@ class MenuView(View, VoiceExtension):
self.play_pause_button = PlayPauseButton(style=ButtonStyle.primary, emoji='', row=0) self.play_pause_button = PlayPauseButton(style=ButtonStyle.primary, emoji='', row=0)
self.next_button = SwitchTrackButton(style=ButtonStyle.primary, emoji='', row=0, custom_id='next') self.next_button = SwitchTrackButton(style=ButtonStyle.primary, emoji='', row=0, custom_id='next')
self.prev_button = SwitchTrackButton(style=ButtonStyle.primary, emoji='', row=0, custom_id='previous') self.prev_button = SwitchTrackButton(style=ButtonStyle.primary, emoji='', row=0, custom_id='previous')
self.like_button = ReactionButton(style=ButtonStyle.secondary, emoji='❤️', row=1, custom_id='like') self.like_button = ReactionButton(style=ButtonStyle.secondary, emoji='❤️', row=1, custom_id='like')
self.dislike_button = ReactionButton(style=ButtonStyle.secondary, emoji='💔', row=1, custom_id='dislike') self.dislike_button = ReactionButton(style=ButtonStyle.secondary, emoji='💔', row=1, custom_id='dislike')
self.lyrics_button = LyricsButton(style=ButtonStyle.secondary, emoji='📋', row=1) self.lyrics_button = LyricsButton(style=ButtonStyle.secondary, emoji='📋', row=1)
@@ -594,26 +596,33 @@ class MenuView(View, VoiceExtension):
if not self.ctx.guild_id: if not self.ctx.guild_id:
return self return self
self.guild = await self.db.get_guild(self.ctx.guild_id, projection={'repeat': 1, 'shuffle': 1, 'current_track': 1, 'current_menu': 1, 'vibing': 1}) self.guild = await self.db.get_guild(self.ctx.guild_id, projection={
'repeat': 1, 'shuffle': 1, 'current_track': 1, 'current_menu': 1, 'vibing': 1, 'single_token_uid': 1
})
if self.guild['repeat']: if self.guild['repeat']:
self.repeat_button.style = ButtonStyle.success self.repeat_button.style = ButtonStyle.success
if self.guild['shuffle']: if self.guild['shuffle']:
self.shuffle_button.style = ButtonStyle.success self.shuffle_button.style = ButtonStyle.success
current_track = self.guild['current_track'] current_track = self.guild['current_track']
likes = await self.get_liked_tracks(self.ctx)
self.add_item(self.repeat_button) self.add_item(self.repeat_button)
self.add_item(self.prev_button) self.add_item(self.prev_button)
self.add_item(self.play_pause_button) self.add_item(self.play_pause_button)
self.add_item(self.next_button) self.add_item(self.next_button)
self.add_item(self.shuffle_button) self.add_item(self.shuffle_button)
if not isinstance(self.ctx, RawReactionActionEvent) and len(cast(VoiceChannel, self.ctx.channel).members) == 2: if not isinstance(self.ctx, RawReactionActionEvent) \
if current_track and str(current_track['id']) in [str(like.id) for like in likes]: and len(cast(VoiceChannel, self.ctx.channel).members) == 2 \
and not self.guild['single_token_uid']:
if current_track and str(current_track['id']) in [str(like.id) for like in await self.get_reacted_tracks(self.ctx, 'like')]:
self.like_button.style = ButtonStyle.success self.like_button.style = ButtonStyle.success
if current_track and str(current_track['id']) in [str(dislike.id) for dislike in await self.get_reacted_tracks(self.ctx, 'dislike')]:
self.dislike_button.style = ButtonStyle.success
if not current_track: if not current_track:
self.lyrics_button.disabled = True self.lyrics_button.disabled = True
self.like_button.disabled = True self.like_button.disabled = True
@@ -621,6 +630,11 @@ class MenuView(View, VoiceExtension):
self.add_to_playlist_button.disabled = True self.add_to_playlist_button.disabled = True
elif not current_track['lyrics_available']: elif not current_track['lyrics_available']:
self.lyrics_button.disabled = True self.lyrics_button.disabled = True
if self.guild['single_token_uid']:
self.like_button.disabled = True
self.dislike_button.disabled = True
self.add_to_playlist_button.disabled = True
self.add_item(self.like_button) self.add_item(self.like_button)
self.add_item(self.dislike_button) self.add_item(self.dislike_button)
@@ -643,8 +657,11 @@ class MenuView(View, VoiceExtension):
return return
if self.guild['current_menu']: if self.guild['current_menu']:
await self.stop_playing(self.ctx) await self.db.update(self.ctx.guild_id, {
await self.db.update(self.ctx.guild_id, {'current_menu': None, 'previous_tracks': [], 'vibing': False}) 'current_menu': None, 'repeat': False, 'shuffle': False,
'previous_tracks': [], 'next_tracks': [], 'votes': {},
'vibing': False, 'current_viber_id': None
})
if (message := await self.get_menu_message(self.ctx, self.guild['current_menu'])): if (message := await self.get_menu_message(self.ctx, self.guild['current_menu'])):
await message.delete() await message.delete()