diff --git a/cogs/music/basic_commands.py b/cogs/music/basic_commands.py index f433166..77a919a 100644 --- a/cogs/music/basic_commands.py +++ b/cogs/music/basic_commands.py @@ -77,7 +77,7 @@ async def _seek(self, ctx, *, time: str): @commands.command(name='skip') @require_voice_connection() @require_playing() -@voteable(requester_override=True) +@voteable(requester_override=True, react_to_vote=True) async def _skip(self, ctx): """ Skips the current track. """ player = self.bot.lavalink.player_manager.get(ctx.guild.id) @@ -112,7 +112,7 @@ async def _skip_to(self, ctx, pos: int = 1): @commands.command(name='stop') @require_voice_connection() @require_playing(require_user_listening=True) -@voteable(DJ_override=True) +@voteable(DJ_override=True, react_to_vote=True) async def _stop(self, ctx): """ Stops the player and clears its queue. """ player = self.bot.lavalink.player_manager.get(ctx.guild.id) @@ -333,7 +333,7 @@ async def _search(self, ctx, *, query): @commands.command(name='disconnect') @require_voice_connection() -@voteable(DJ_override=True) +@voteable(DJ_override=True, react_to_vote=True) async def _disconnect(self, ctx): """ Disconnects the player from the voice channel and clears its queue. """ player = self.bot.lavalink.player_manager.get(ctx.guild.id) @@ -348,7 +348,7 @@ async def _disconnect(self, ctx): @commands.command(name='reconnect') @require_voice_connection() -@voteable(DJ_override=True) +@voteable(DJ_override=True, react_to_vote=True) async def _reconnect(self, ctx): """ Tries to disconnect then reconnect the player in case the bot gets stuck on a song """ player = self.bot.lavalink.player_manager.get(ctx.guild.id) diff --git a/cogs/music/decorators.py b/cogs/music/decorators.py index 997ba4b..e1339fe 100644 --- a/cogs/music/decorators.py +++ b/cogs/music/decorators.py @@ -2,6 +2,7 @@ import discord from discord.ext import commands +import asyncio import functools import inspect import math @@ -127,7 +128,7 @@ def require_queue(require_member_queue=False, require_author_queue=False): return ensure_queue -def voteable(requester_override=False, DJ_override=False): +def voteable(requester_override=False, DJ_override=False, react_to_vote=False): def make_voteable(func): @functools.wraps(func) async def voteable_inner(self, ctx, *command_args, **kwargs): @@ -145,6 +146,48 @@ def voteable(requester_override=False, DJ_override=False): if enough_votes or requester or DJ: await func(self, ctx, *command_args, **kwargs) player.clear_votes() + + elif react_to_vote: + embed = discord.Embed(title="Votes", description=f"{votes} out of {total} required votes.", + color=ctx.me.color) + embed.set_footer(text=f'{{requested_by}} {ctx.author.name}', icon_url=ctx.author.avatar_url) + msg = await ctx.send(embed=ctx.localizer.format_embed(embed)) + await msg.add_reaction('👍') + + def check(reaction, user): + if not reaction.message.id == msg.id: + return False + + if user is None or user not in player.listeners: + return False + + if reaction.emoji == '👍' and user.id not in player.get_voters(func.__name__): + player.add_vote(func.__name__, user) + return True + return False + + while True: + try: + reaction, user = await self.bot.wait_for('reaction_add', timeout=15.0, check=check) + except asyncio.TimeoutError: + await msg.clear_reactions() + embed.title = '' + embed.set_footer(text='{time_expired}') + await msg.edit(embed=ctx.localizer.format_embed(embed)) + break + + total = len(player.listeners) + votes = len(player.get_voters(func.__name__)) + + embed.description = f"{votes} out of {total} required votes." + await msg.edit(embed=ctx.localizer.format_embed(embed)) + + if votes/total >= threshold/100: + player.clear_votes() + await msg.delete() + await func(self, ctx, *command_args, **kwargs) + break + else: if votes != 0: needed = math.ceil(total*threshold/100) diff --git a/cogs/music/extra_commands.py b/cogs/music/extra_commands.py index f97c1e2..3c2a63c 100644 --- a/cogs/music/extra_commands.py +++ b/cogs/music/extra_commands.py @@ -228,7 +228,7 @@ async def _loop(self, ctx): @_loop.command(name='start') @require_playing(require_user_listening=True) -@voteable(DJ_override=True) +@voteable(DJ_override=True, react_to_vote=True) async def _loop_start(self, ctx): """ Set the equalizer to bass boost the music """ player = self.bot.lavalink.player_manager.get(ctx.guild.id) @@ -241,7 +241,7 @@ async def _loop_start(self, ctx): @_loop.command(name='stop') @require_playing(require_user_listening=True) -@voteable(DJ_override=True) +@voteable(DJ_override=True, react_to_vote=True) async def _loop_stop(self, ctx): """ Set the equalizer to bass boost the music """ player = self.bot.lavalink.player_manager.get(ctx.guild.id) diff --git a/cogs/utils/mixplayer.py b/cogs/utils/mixplayer.py index 9e22484..49e1587 100644 --- a/cogs/utils/mixplayer.py +++ b/cogs/utils/mixplayer.py @@ -189,7 +189,6 @@ class MixQueue: self.queues = OrderedDict() self.priority_queue = [] self._history = deque(maxlen=11) # 10 + current - self.looped_queue = [] self.looping = False self.loop_offset = 0 @@ -206,8 +205,7 @@ class MixQueue: def __iter__(self): global_queue = roundrobin(*[x for x in self.queues.values()]) priority_queue = self.priority_queue - looped_queue = self.looped_queue - out = chain(priority_queue, looped_queue, global_queue) + out = chain(priority_queue, global_queue) return out def __len__(self): @@ -243,10 +241,6 @@ class MixQueue: next_track = self.priority_queue.pop(0) self._history.append(next_track) return next_track - if self.looped_queue: - next_track = self.looped_queue.pop(0) - self._history.append(next_track) - return next_track try: if self.looping: queue = list(self) @@ -254,6 +248,7 @@ class MixQueue: self.loop_offset += 1 if self.loop_offset == len(self): self.loop_offset = 0 + self._history.append(next_track) return next_track else: next_track = self.queues[self.first_queue].pop(0) @@ -343,7 +338,7 @@ class MixQueue: self.queues.pop(i) def _loc_to_glob(self, requester, pos): - globpos = len(self.priority_queue) + len(self.looped_queue) + globpos = len(self.priority_queue) passed = False for key, queue in self.queues.items(): if len(queue) <= pos: