feat: Add vote functionality.

This commit is contained in:
Lemon4ksan
2025-01-22 19:30:37 +03:00
parent 18ff925236
commit 859d60de35
8 changed files with 278 additions and 152 deletions

View File

@@ -12,9 +12,9 @@ from yandex_music import Track, Album, Artist, Playlist
from MusicBot.database import BaseUsersDatabase, BaseGuildsDatabase
from MusicBot.cogs.utils.find import (
process_album, process_track, process_artist, process_playlist,
ListenAlbum, ListenTrack, ListenArtist, ListenPlaylist
ListenAlbum, ListenTrack, ListenArtist, ListenPlaylist, ListenLikesPlaylist
)
from MusicBot.cogs.utils.misc import MyPlalists, ListenLikesPlaylist, generate_playlist_embed, generate_likes_embed
from MusicBot.cogs.utils.misc import MyPlaylists, generate_playlist_embed, generate_likes_embed
def setup(bot):
bot.add_cog(General(bot))
@@ -161,7 +161,7 @@ class General(Cog):
]
self.users_db.update(ctx.user.id, {'playlists': playlists, 'playlists_page': 0})
embed = generate_playlist_embed(0, playlists)
await ctx.respond(embed=embed, view=MyPlalists(ctx), ephemeral=True)
await ctx.respond(embed=embed, view=MyPlaylists(ctx), ephemeral=True)
@discord.slash_command(description="Найти контент и отправить информацию о нём. Возвращается лучшее совпадение.")
@discord.option(

View File

@@ -23,7 +23,7 @@ class Settings(Cog):
embed = discord.Embed(title="Настройки бота", color=0xfed42b)
explicit = "✅ - Разрешены" if guild['allow_explicit'] else "❌ - Запрещены"
menu = "✅ - Всегда доступно" if guild['always_allow_menu'] else "❌ - Если в канале 1 пользователь."
menu = "✅ - Всегда доступно" if guild['always_allow_menu'] else "❌ - Если в канале 1 человек."
vote = "✅ - Переключение" if guild['vote_next_track'] else "❌ - Переключение"
vote += "\n✅ - Добавление треков" if guild['vote_add_track'] else "\n❌ - Добавление треков"
@@ -32,7 +32,7 @@ class Settings(Cog):
vote += "\n✅ - Добавление плейлистов" if guild['vote_add_playlist'] else "\n❌ - Добавление плейлистов"
embed.add_field(name="__Explicit треки__", value=explicit, inline=False)
embed.add_field(name="__Проигрыватель__", value=menu, inline=False)
embed.add_field(name="__Меню проигрывателя__", value=menu, inline=False)
embed.add_field(name="__Голосование__", value=vote, inline=False)
await ctx.respond(embed=embed, ephemeral=True)
@@ -64,8 +64,8 @@ class Settings(Cog):
"vote_type",
description="Тип голосования.",
type=discord.SlashCommandOptionType.string,
choices=['+Всё', '-Всё', 'Переключение', '+Трек', '+Альбом', '+Плейлист'],
default='Всё'
choices=['+Всё', '-Всё', 'Переключение', 'Трек', 'Альбом', 'Плейлист'],
default='+Всё'
)
async def vote(self, ctx: discord.ApplicationContext, vote_type: Literal['+Всё', '-Всё', 'Переключение', 'Трек', 'Альбом', 'Плейлист']) -> None:
member = cast(discord.Member, ctx.author)
@@ -97,18 +97,18 @@ class Settings(Cog):
response_message = "Голосование включено."
elif vote_type == 'Переключение':
self.db.update(ctx.guild.id, {'vote_next_track': not guild['vote_next_track']})
response_message = "Голосование за переключение трека " + ("включено." if guild['vote_next_track'] else "выключено.")
response_message = "Голосование за переключение трека " + ("выключено." if guild['vote_next_track'] else "включено.")
elif vote_type == 'Трек':
self.db.update(ctx.guild.id, {'vote_add_track': not guild['vote_add_track']})
response_message = "Голосование за добавление трека " + ("включено." if guild['vote_add_track'] else "выключено.")
response_message = "Голосование за добавление трека " + ("выключено." if guild['vote_add_track'] else "включено.")
elif vote_type == 'Альбом':
self.db.update(ctx.guild.id, {'vote_add_album': not guild['vote_add_album']})
response_message = "Голосование за добавление альбома " + ("включено." if guild['vote_add_album'] else "выключено.")
response_message = "Голосование за добавление альбома " + ("выключено." if guild['vote_add_album'] else "включено.")
elif vote_type == 'Артист':
self.db.update(ctx.guild.id, {'vote_add_artist': not guild['vote_add_artist']})
response_message = "Голосование за добавление артиста " + ("включено." if guild['vote_add_artist'] else "выключено.")
response_message = "Голосование за добавление артиста " + ("выключено." if guild['vote_add_artist'] else "включено.")
elif vote_type == 'Плейлист':
self.db.update(ctx.guild.id, {'vote_add_playlist': not guild['vote_add_playlist']})
response_message = "Голосование за добавление плейлиста " + ("включено." if guild['vote_add_playlist'] else "выключено.")
response_message = "Голосование за добавление плейлиста " + ("выключено." if guild['vote_add_playlist'] else "включено.")
await ctx.respond(response_message, delete_after=15, ephemeral=True)

View File

@@ -23,18 +23,37 @@ class PlayTrackButton(Button, VoiceExtension):
gid = interaction.guild.id
guild = self.db.get_guild(gid)
if guild['current_track']:
self.db.modify_track(gid, self.track, 'next', 'append')
response_message = f"Трек **{self.track.title}** был добавлен в очередь."
channel = cast(discord.VoiceChannel, interaction.channel)
member = cast(discord.Member, interaction.user)
if guild['vote_add_track'] and len(channel.members) > 2 and not member.guild_permissions.manage_channels:
message = cast(discord.Interaction, await interaction.respond(f"{member.mention} хочет добавить трек **{self.track.title}** в очередь.\n\n Голосуйте за добавление.", delete_after=30))
response = await message.original_response()
await response.add_reaction('')
await response.add_reaction('')
self.db.update_vote(
gid,
response.id,
{
'positive_votes': list(),
'negative_votes': list(),
'total_members': len(channel.members),
'action': 'add_track',
'vote_content': self.track.to_dict()
}
)
else:
await self.play_track(interaction, self.track)
response_message = f"Сейчас играет: **{self.track.title}**!"
if guild['current_track']:
self.db.modify_track(gid, self.track, 'next', 'append')
response_message = f"Трек **{self.track.title}** был добавлен в очередь."
else:
await self.play_track(interaction, self.track)
response_message = f"Сейчас играет: **{self.track.title}**!"
if guild['current_player'] is not None and interaction.message:
await interaction.message.delete()
if guild['current_player'] is not None and interaction.message:
await interaction.message.delete()
await interaction.respond(response_message, delete_after=15)
await interaction.respond(response_message, delete_after=15)
class PlayAlbumButton(Button, VoiceExtension):
@@ -53,22 +72,41 @@ class PlayAlbumButton(Button, VoiceExtension):
gid = interaction.guild.id
guild = self.db.get_guild(gid)
channel = cast(discord.VoiceChannel, interaction.channel)
member = cast(discord.Member, interaction.user)
tracks: list[Track] = [track for volume in album.volumes for track in volume]
if guild['current_track'] is not None:
self.db.modify_track(gid, tracks, 'next', 'extend')
response_message = f"Альбом **{album.title}** был добавлен в очередь."
if guild['vote_add_album'] and len(channel.members) > 2 and not member.guild_permissions.manage_channels:
message = cast(discord.Interaction, await interaction.respond(f"{member.mention} хочет добавить альбом **{self.album.title}** в очередь.\n\n Голосуйте за добавление.", delete_after=30))
response = await message.original_response()
await response.add_reaction('')
await response.add_reaction('')
self.db.update_vote(
gid,
response.id,
{
'positive_votes': list(),
'negative_votes': list(),
'total_members': len(channel.members),
'action': 'add_album',
'vote_content': [track.to_dict() for track in tracks]
}
)
else:
track = tracks.pop(0)
self.db.modify_track(gid, tracks, 'next', 'extend')
await self.play_track(interaction, track)
response_message = f"Сейчас играет: **{track.title}**!"
if guild['current_track'] is not None:
self.db.modify_track(gid, tracks, 'next', 'extend')
response_message = f"Альбом **{album.title}** был добавлен в очередь."
else:
track = tracks.pop(0)
self.db.modify_track(gid, tracks, 'next', 'extend')
await self.play_track(interaction, track)
response_message = f"Сейчас играет: **{track.title}**!"
if guild['current_player'] is not None and interaction.message:
await interaction.message.delete()
else:
await interaction.respond(response_message, delete_after=15)
if guild['current_player'] is not None and interaction.message:
await interaction.message.delete()
else:
await interaction.respond(response_message, delete_after=15)
class PlayArtistButton(Button, VoiceExtension):
def __init__(self, artist: Artist, **kwargs):
@@ -86,24 +124,44 @@ class PlayArtistButton(Button, VoiceExtension):
gid = interaction.guild.id
guild = self.db.get_guild(gid)
channel = cast(discord.VoiceChannel, interaction.channel)
member = cast(discord.Member, interaction.user)
tracks: list[Track] = artist_tracks.tracks.copy()
if guild['current_track'] is not None:
self.db.modify_track(gid, tracks, 'next', 'extend')
response_message = f"Песни артиста **{self.artist.name}** были добавлены в очередь."
if guild['vote_add_artist'] and len(channel.members) > 2 and not member.guild_permissions.manage_channels:
message = cast(discord.Interaction, await interaction.respond(f"{member.mention} хочет добавить треки от **{self.artist.name}** в очередь.\n\n Голосуйте за добавление.", delete_after=30))
response = await message.original_response()
await response.add_reaction('')
await response.add_reaction('')
self.db.update_vote(
gid,
response.id,
{
'positive_votes': list(),
'negative_votes': list(),
'total_members': len(channel.members),
'action': 'add_album',
'vote_content': [track.to_dict() for track in tracks]
}
)
else:
track = tracks.pop(0)
self.db.modify_track(gid, tracks, 'next', 'extend')
await self.play_track(interaction, track)
response_message = f"Сейчас играет: **{track.title}**!"
if guild['current_track'] is not None:
self.db.modify_track(gid, tracks, 'next', 'extend')
response_message = f"Песни артиста **{self.artist.name}** были добавлены в очередь."
else:
track = tracks.pop(0)
self.db.modify_track(gid, tracks, 'next', 'extend')
await self.play_track(interaction, track)
response_message = f"Сейчас играет: **{track.title}**!"
if guild['current_player'] is not None and interaction.message:
await interaction.message.delete()
if guild['current_player'] is not None and interaction.message:
await interaction.message.delete()
await interaction.respond(response_message, delete_after=15)
await interaction.respond(response_message, delete_after=15)
class PlayPlaylistButton(Button, VoiceExtension):
def __init__(self, playlist: Playlist, **kwargs):
Button.__init__(self, **kwargs)
VoiceExtension.__init__(self, None)
@@ -120,22 +178,93 @@ class PlayPlaylistButton(Button, VoiceExtension):
gid = interaction.guild.id
guild = self.db.get_guild(gid)
channel = cast(discord.VoiceChannel, interaction.channel)
member = cast(discord.Member, interaction.user)
tracks: list[Track] = [cast(Track, short_track.track) for short_track in short_tracks]
if guild['current_track'] is not None:
self.db.modify_track(gid, tracks, 'next', 'extend')
response_message = f"Плейлист **{self.playlist.title}** был добавлен в очередь."
if guild['vote_add_playlist'] and len(channel.members) > 2 and not member.guild_permissions.manage_channels:
message = cast(discord.Interaction, await interaction.respond(f"{member.mention} хочет добавить плейлист **{self.playlist.title}** в очередь.\n\n Голосуйте за добавление.", delete_after=30))
response = await message.original_response()
await response.add_reaction('')
await response.add_reaction('')
self.db.update_vote(
gid,
response.id,
{
'positive_votes': list(),
'negative_votes': list(),
'total_members': len(channel.members),
'action': 'add_playlist',
'vote_content': [track.to_dict() for track in tracks]
}
)
else:
track = tracks.pop(0)
self.db.modify_track(gid, tracks, 'next', 'extend')
await self.play_track(interaction, track)
response_message = f"Сейчас играет: **{self.playlist.title}**!"
if guild['current_track'] is not None:
self.db.modify_track(gid, tracks, 'next', 'extend')
response_message = f"Плейлист **{self.playlist.title}** был добавлен в очередь."
else:
track = tracks.pop(0)
self.db.modify_track(gid, tracks, 'next', 'extend')
await self.play_track(interaction, track)
response_message = f"Сейчас играет: **{self.playlist.title}**!"
if guild['current_player'] is not None and interaction.message:
await interaction.message.delete()
if guild['current_player'] is not None and interaction.message:
await interaction.message.delete()
await interaction.respond(response_message, delete_after=15)
await interaction.respond(response_message, delete_after=15)
class PlayLikesButton(Button, VoiceExtension):
def __init__(self, playlist: list[Track], **kwargs):
Button.__init__(self, **kwargs)
VoiceExtension.__init__(self, None)
self.playlist = playlist
async def callback(self, interaction: Interaction):
if not interaction.guild or not await self.voice_check(interaction):
return
playlist = self.playlist.copy()
gid = interaction.guild.id
guild = self.db.get_guild(gid)
channel = cast(discord.VoiceChannel, interaction.channel)
member = cast(discord.Member, interaction.user)
if guild['vote_add_playlist'] and len(channel.members) > 2 and not member.guild_permissions.manage_channels:
message = cast(discord.Interaction, await interaction.respond(f"{member.mention} хочет добавить плейлист **«Мне нравится»** в очередь.\n\n Голосуйте за добавление.", delete_after=30))
response = await message.original_response()
await response.add_reaction('')
await response.add_reaction('')
self.db.update_vote(
gid,
response.id,
{
'positive_votes': list(),
'negative_votes': list(),
'total_members': len(channel.members),
'action': 'add_playlist',
'vote_content': [track.to_dict() for track in playlist]
}
)
else:
if guild['current_track'] is not None:
self.db.modify_track(gid, playlist, 'next', 'extend')
response_message = f"Плейлист **«Мне нравится»** был добавлен в очередь."
else:
track = playlist.pop(0)
self.db.modify_track(gid, playlist, 'next', 'extend')
await self.play_track(interaction, track)
response_message = f"Сейчас играет: **{track.title}**!"
if guild['current_player'] is not None and interaction.message:
await interaction.message.delete()
await interaction.respond(response_message, delete_after=15)
class ListenLikesPlaylist(View):
def __init__(self, playlist: list[Track], *items: Item, timeout: float | None = None, disable_on_timeout: bool = False):
super().__init__(*items, timeout=timeout, disable_on_timeout=disable_on_timeout)
self.add_item(PlayLikesButton(playlist, label="Слушать в голосовом канале", style=ButtonStyle.gray))
class ListenTrack(View):

View File

@@ -62,39 +62,6 @@ def generate_queue_embed(page: int, tracks_list: list[dict[str, Any]]) -> Embed:
embed.add_field(name=f"{i} - {track['title']} - {duration_m}:{duration_s:02d}", value="", inline=False)
return embed
class PlayLikesButton(Button, VoiceExtension):
def __init__(self, playlist: list[Track], **kwargs):
Button.__init__(self, **kwargs)
VoiceExtension.__init__(self, None)
self.playlist = playlist
async def callback(self, interaction: Interaction):
if not interaction.guild or not await self.voice_check(interaction):
return
playlist = self.playlist.copy()
gid = interaction.guild.id
guild = self.db.get_guild(gid)
if guild['current_track'] is not None:
self.db.modify_track(gid, playlist, 'next', 'extend')
response_message = f"Плейлист **«Мне нравится»** был добавлен в очередь."
else:
track = playlist.pop(0)
self.db.modify_track(gid, playlist, 'next', 'extend')
await self.play_track(interaction, track)
response_message = f"Сейчас играет плейлист **{track.title}**!"
if guild['current_player'] is not None and interaction.message:
await interaction.message.delete()
await interaction.respond(response_message, delete_after=15)
class ListenLikesPlaylist(View):
def __init__(self, playlist: list[Track], *items: Item, timeout: float | None = None, disable_on_timeout: bool = False):
super().__init__(*items, timeout=timeout, disable_on_timeout=disable_on_timeout)
self.add_item(PlayLikesButton(playlist, label="Слушать в голосовом канале", style=ButtonStyle.gray))
class MPNextButton(Button, VoiceExtension):
def __init__(self, **kwargs):
Button.__init__(self, **kwargs)
@@ -107,7 +74,7 @@ class MPNextButton(Button, VoiceExtension):
page = user['playlists_page'] + 1
self.users_db.update(interaction.user.id, {'playlists_page': page})
embed = generate_playlist_embed(page, user['playlists'])
await interaction.edit(embed=embed, view=MyPlalists(interaction))
await interaction.edit(embed=embed, view=MyPlaylists(interaction))
class MPPrevButton(Button, VoiceExtension):
def __init__(self, **kwargs):
@@ -121,9 +88,9 @@ class MPPrevButton(Button, VoiceExtension):
page = user['playlists_page'] - 1
self.users_db.update(interaction.user.id, {'playlists_page': page})
embed = generate_playlist_embed(page, user['playlists'])
await interaction.edit(embed=embed, view=MyPlalists(interaction))
await interaction.edit(embed=embed, view=MyPlaylists(interaction))
class MyPlalists(View, VoiceExtension):
class MyPlaylists(View, VoiceExtension):
def __init__(self, ctx: ApplicationContext | Interaction, *items: Item, timeout: float | None = 3600, disable_on_timeout: bool = True):
View.__init__(self, *items, timeout=timeout, disable_on_timeout=disable_on_timeout)
VoiceExtension.__init__(self, None)

View File

@@ -1,4 +1,4 @@
from typing import cast, TypedDict, Literal
from typing import cast
import discord
from discord.ext.commands import Cog
@@ -21,32 +21,26 @@ class Voice(Cog, VoiceExtension):
def __init__(self, bot: discord.Bot):
VoiceExtension.__init__(self, bot)
self.bot = bot
MessageVotes = TypedDict('MessageVotes', {'positive_votes': set[int], 'negative_votes': set[int], 'total_members': int, 'action': Literal['next']})
self.vote_messages: dict[int, dict[int, MessageVotes]] = {}
@Cog.listener()
async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState) -> None:
gid = member.guild.id
guild = self.db.get_guild(gid)
if after.channel:
channel = cast(discord.VoiceChannel, after.channel)
else:
channel = cast(discord.VoiceChannel, before.channel)
channel = after.channel or before.channel
if not channel:
return
discord_guild = await self.bot.fetch_guild(gid)
vc = cast((discord.VoiceClient | None), discord.utils.get(self.bot.voice_clients, guild=discord_guild))
vc = cast(discord.VoiceClient | None, discord.utils.get(self.bot.voice_clients, guild=discord_guild))
if len(channel.members) == 1 and vc:
self.db.clear_history(gid)
self.db.update(gid, {'current_track': None, 'is_stopped': True})
vc.stop()
if len(channel.members) > 2 and not guild['always_allow_menu']:
elif len(channel.members) > 2 and not guild['always_allow_menu']:
current_player = self.db.get_current_player(gid)
if current_player is not None:
if current_player:
self.db.update(gid, {'current_player': None, 'repeat': False, 'shuffle': False})
try:
message = await channel.fetch_message(current_player)
@@ -78,42 +72,58 @@ class Voice(Cog, VoiceExtension):
return
guild_id = payload.guild_id
if guild_id not in self.vote_messages:
if not guild_id:
return
guild = self.db.get_guild(guild_id)
votes = guild['votes']
if payload.message_id not in self.vote_messages[guild_id]:
return
vote_data = self.vote_messages[guild_id][payload.message_id]
vote_data = votes[str(payload.message_id)]
if payload.emoji.name == '':
vote_data['positive_votes'].add(payload.user_id)
vote_data['positive_votes'].append(payload.user_id)
elif payload.emoji.name == '':
vote_data['negative_votes'].add(payload.user_id)
vote_data['negative_votes'].append(payload.user_id)
total_members = len(channel.members)
if total_members <= 5:
required_votes = 2
elif total_members <= 10:
required_votes = 4
elif total_members <= 15:
required_votes = 6
else:
required_votes = 9
required_votes = 2 if total_members <= 5 else 4 if total_members <= 10 else 6 if total_members <= 15 else 9
if len(vote_data['positive_votes']) >= required_votes:
if vote_data['action'] == 'next':
self.db.update(guild_id, {'is_stopped': False})
title = await self.next_track(payload)
await message.clear_reactions()
if title is not None:
await message.edit(content=f"Сейчас играет: **{title}**!", delete_after=15)
del votes[str(payload.message_id)]
elif vote_data['action'] == 'add_track':
await message.clear_reactions()
track = vote_data['vote_content']
if not track:
return
self.db.update(guild_id, {'is_stopped': False})
self.db.modify_track(guild_id, track, 'next', 'append')
if guild['current_track']:
await message.edit(content=f"Трек был добавлен в очередь!", delete_after=15)
else:
title = await self.next_track(payload)
await message.edit(content=f"Сейчас играет: **{title}**!", delete_after=15)
del self.vote_messages[guild_id][payload.message_id]
del votes[str(payload.message_id)]
elif vote_data['action'] in ('add_album', 'add_artist', 'add_playlist'):
tracks = vote_data['vote_content']
await message.clear_reactions()
if not tracks:
return
self.db.update(guild_id, {'is_stopped': False})
self.db.modify_track(guild_id, tracks, 'next', 'extend')
if guild['current_track']:
await message.edit(content=f"Контент был добавлен в очередь!", delete_after=15)
else:
title = await self.next_track(payload)
await message.edit(content=f"Сейчас играет: **{title}**!", delete_after=15)
del votes[str(payload.message_id)]
elif len(vote_data['negative_votes']) >= required_votes:
channel = cast(discord.VoiceChannel, self.bot.get_channel(payload.channel_id))
message = await channel.fetch_message(payload.message_id)
await message.clear_reactions()
await message.edit(content='Запрос был отклонён.', delete_after=15)
del self.vote_messages[guild_id][payload.message_id]
del votes[str(payload.message_id)]
self.db.update(guild_id, {'votes': votes})
@Cog.listener()
async def on_raw_reaction_remove(self, payload: discord.RawReactionActionEvent) -> None:
@@ -121,11 +131,10 @@ class Voice(Cog, VoiceExtension):
return
guild_id = payload.guild_id
if guild_id not in self.vote_messages:
return
if payload.message_id not in self.vote_messages[guild_id]:
if not guild_id:
return
guild = self.db.get_guild(guild_id)
votes = guild['votes']
channel = cast(discord.VoiceChannel, self.bot.get_channel(payload.channel_id))
if not channel:
@@ -135,11 +144,13 @@ class Voice(Cog, VoiceExtension):
if not message or message.author.id != self.bot.user.id:
return
vote_data = self.vote_messages[guild_id][payload.message_id]
vote_data = votes[str(payload.message_id)]
if payload.emoji.name == '✔️':
vote_data['positive_votes'].discard(payload.user_id)
del vote_data['positive_votes'][payload.user_id]
elif payload.emoji.name == '':
vote_data['negative_votes'].discard(payload.user_id)
del vote_data['negative_votes'][payload.user_id]
self.db.update(guild_id, {'votes': votes})
@voice.command(name="menu", description="Создать меню проигрывателя. Доступно только если вы единственный в голосовом канале.")
async def menu(self, ctx: discord.ApplicationContext) -> None:
@@ -280,33 +291,33 @@ class Voice(Cog, VoiceExtension):
if not await self.voice_check(ctx):
return
gid = ctx.guild.id
tracks_list = self.db.get_tracks_list(gid, 'next')
if not tracks_list:
guild = self.db.get_guild(gid)
if not guild['next_tracks']:
await ctx.respond("❌ Нет песенен в очереди.", delete_after=15, ephemeral=True)
return
member = cast(discord.Member, ctx.author)
channel = cast(discord.VoiceChannel, ctx.channel)
if self.db.get_track(gid, 'current') and len(channel.members) > 2 and not member.guild_permissions.manage_channels:
message = cast(discord.Interaction, await ctx.respond(f"{ctx.user.mention} хочет пропустить текущий трек.\n\nВыполнить переход?", delete_after=30))
if guild['vote_next_track'] and len(channel.members) > 2 and not member.guild_permissions.manage_channels:
message = cast(discord.Interaction, await ctx.respond(f"{member.mention} хочет пропустить текущий трек.\n\nВыполнить переход?", delete_after=30))
response = await message.original_response()
await response.add_reaction('')
await response.add_reaction('')
self.vote_messages[ctx.guild.id] = {
response.id: {
'positive_votes': set(),
'negative_votes': set(),
self.db.update_vote(
gid,
response.id,
{
'positive_votes': list(),
'negative_votes': list(),
'total_members': len(channel.members),
'action': 'next'
'action': 'next',
'vote_content': None
}
}
)
else:
self.db.update(gid, {'is_stopped': False})
title = await self.next_track(ctx)
if title is not None:
await ctx.respond(f"Сейчас играет: **{title}**!", delete_after=15)
else:
await ctx.respond(f"Нет треков в очереди.", delete_after=15, ephemeral=True)
await ctx.respond(f"Сейчас играет: **{title}**!", delete_after=15)
@track.command(description="Добавить трек в избранное или убрать, если он уже там.")
async def like(self, ctx: discord.ApplicationContext) -> None:

View File

@@ -2,7 +2,7 @@ from .base import BaseGuildsDatabase, BaseUsersDatabase
from .extensions import VoiceGuildsDatabase
from .user import User, ExplicitUser
from .guild import Guild, ExplicitGuild
from .guild import Guild, ExplicitGuild, MessageVotes
__all__ = [
'BaseGuildsDatabase',
@@ -12,4 +12,5 @@ __all__ = [
'ExplicitUser',
'Guild',
'ExplicitGuild',
'MessageVotes'
]

View File

@@ -5,8 +5,8 @@ from typing import cast
from pymongo import MongoClient
from pymongo.collection import Collection
from MusicBot.database.user import User, ExplicitUser
from MusicBot.database.guild import Guild, ExplicitGuild
from .user import User, ExplicitUser
from .guild import Guild, ExplicitGuild, MessageVotes
client: MongoClient = MongoClient("mongodb://localhost:27017/")
users: Collection[ExplicitUser] = client.YandexMusicBot.users
@@ -91,14 +91,14 @@ class BaseGuildsDatabase:
is_stopped=True,
allow_explicit=True,
always_allow_menu=False,
vote_add=True,
vote_next_track=True,
vote_add_track=True,
vote_add_album=True,
vote_add_artist=True,
vote_add_playlist=True,
shuffle=False,
repeat=False
repeat=False,
votes={}
))
def update(self, gid: int, data: Guild) -> None:
@@ -135,14 +135,14 @@ class BaseGuildsDatabase:
is_stopped=True,
allow_explicit=True,
always_allow_menu=False,
vote_add=True,
vote_next_track=True,
vote_add_track=True,
vote_add_album=True,
vote_add_artist=True,
vote_add_playlist=True,
shuffle=False,
repeat=False
repeat=False,
votes={}
)
for field, default_value in fields.items():
if field not in existing_fields and field != '_id':
@@ -151,3 +151,14 @@ class BaseGuildsDatabase:
return guild
def update_vote(self, gid: int, mid: int, data: MessageVotes) -> None:
"""Update vote for a message in a guild.
Args:
gid (int): Guild id.
mid (int): Message id.
vote (bool): Vote value.
"""
guild = self.get_guild(gid)
guild['votes'][str(mid)] = data
guilds.update_one({'_id': gid}, {"$set": {'votes': guild['votes']}})

View File

@@ -1,4 +1,11 @@
from typing import TypedDict, Any
from typing import TypedDict, Literal, Any
class MessageVotes(TypedDict):
positive_votes: list[int]
negative_votes: list[int]
total_members: int
action: Literal['next', 'add_track', 'add_album', 'add_artist', 'add_playlist']
vote_content: dict[str, Any] | list[dict[str, Any]] | None
class Guild(TypedDict, total=False):
next_tracks: list[dict[str, Any]]
@@ -8,7 +15,6 @@ class Guild(TypedDict, total=False):
is_stopped: bool
allow_explicit: bool
always_allow_menu: bool
vote_add: bool
vote_next_track: bool
vote_add_track: bool
vote_add_album: bool
@@ -16,6 +22,7 @@ class Guild(TypedDict, total=False):
vote_add_playlist: bool
shuffle: bool
repeat: bool
votes: dict[str, MessageVotes]
class ExplicitGuild(TypedDict):
_id: int
@@ -26,11 +33,11 @@ class ExplicitGuild(TypedDict):
is_stopped: bool # Prevents the `after` callback of play_track
allow_explicit: bool
always_allow_menu: bool
vote_add: bool
vote_next_track: bool
vote_add_track: bool
vote_add_album: bool
vote_add_artist: bool
vote_add_playlist: bool
shuffle: bool
repeat: bool
repeat: bool
votes: dict[str, MessageVotes]