From d47a6fd1bfbc1b000c4cd4c997b4421101620397 Mon Sep 17 00:00:00 2001 From: Ev-1 <33662061+Ev-1@users.noreply.github.com> Date: Sat, 19 Sep 2020 18:31:33 +0200 Subject: [PATCH] Added votable force play commands Added better handling of livestreams. --- cogs/music/__init__.py | 24 ++++++++++++++------ cogs/music/basic_commands.py | 38 ++++++++++++++++++++++++++++++++ cogs/music/decorators.py | 2 +- localization/en_en/commands.yaml | 4 ++++ localization/nb_no/commands.yaml | 4 ++++ 5 files changed, 64 insertions(+), 8 deletions(-) diff --git a/cogs/music/__init__.py b/cogs/music/__init__.py index edb6675..7e3bf7f 100644 --- a/cogs/music/__init__.py +++ b/cogs/music/__init__.py @@ -36,14 +36,18 @@ class Music(commands.Cog): ws = self.bot._connection._get_websocket(guild_id) await ws.voice_state(str(guild_id), channel_id) - async def enqueue(self, ctx, track, embed, silent=False): + async def enqueue(self, ctx, track, embed, silent=False, check_max_length=True): player = self.bot.lavalink.player_manager.get(ctx.guild.id) # Only add tracks that don't exceed the max track length if maxlength := self.max_track_length(ctx.guild, player): - if track['info']['length'] > maxlength: + if track['info']['length'] > maxlength and check_max_length: + if track['info']['isStream']: + length = '{live}' + else: + length = timeformatter.format_ms(track['info']['length']) embed.description = ctx.localizer.format_str("{enqueue.toolong}", - _length=timeformatter.format_ms(track['info']['length']), + _length=length, _max=timeformatter.format_ms(maxlength)) return embed, False @@ -55,7 +59,10 @@ class Music(commands.Cog): track, pos_global, pos_local = player.add(requester=ctx.author.id, track=track) if player.current is not None and not silent: - until_play = player.queue_duration(include_current=True, end_pos=pos_global) + if player.current.stream: + until_play = '--:--' + else: + until_play = player.queue_duration(include_current=True, end_pos=pos_global) embed.add_field(name="{enqueue.position}", value=f"`{pos_local + 1}({pos_global + 1})`", inline=True) embed.add_field(name="{enqueue.playing_in}", value=f"`{until_play} ({{enqueue.estimated}})`", inline=True) @@ -66,7 +73,10 @@ class Music(commands.Cog): if thumbnail_url: embed.set_thumbnail(url=thumbnail_url) - duration = timeformatter.format_ms(int(track.duration)) + if track.stream: + duration = '{live}' + else: + duration = timeformatter.format_ms(int(track.duration)) embed.description = f'[{track.title}]({track.uri})\n**{duration}**' return embed, True @@ -110,8 +120,8 @@ class Music(commands.Cog): # commands from .basic_commands import ( - _disconnect, _djremove, _move, _myqueue, _now, _pause, _play, _queue, _reconnect, _remove, _search, _seek, - _shuffle, _skip, _skip_to, _stop, _user_queue_remove, _volume) + _disconnect, _djremove, _forceplay, _move, _myqueue, _now, _pause, _play, _queue, _reconnect, _remove, _search, + _seek, _shuffle, _skip, _skip_to, _stop, _user_queue_remove, _volume) # events from .events import check_leave_voice, cog_unload, leave_check, leave_timer, on_voice_state_update, track_hook # commands diff --git a/cogs/music/basic_commands.py b/cogs/music/basic_commands.py index 77a919a..dda711f 100644 --- a/cogs/music/basic_commands.py +++ b/cogs/music/basic_commands.py @@ -390,3 +390,41 @@ async def _volume(self, ctx, volume: int = None): embed = discord.Embed(description="{volume.set_to}", color=ctx.me.color) embed = ctx.localizer.format_embed(embed, _volume=player.volume) await ctx.send(embed=embed) + + +@commands.command(name='forceplay') +@require_voice_connection(should_connect=True) +@voteable(DJ_override=True, react_to_vote=True) +async def _forceplay(self, ctx, *, query: str): + """ Searches and plays a song from a given query. """ + player = self.bot.lavalink.player_manager.get(ctx.guild.id) + query = query.strip('<>') + + if not url_rx.match(query): + query = f'ytsearch:{query}' + + results = await player.node.get_tracks(query) + + if not results or not results['tracks']: + return await ctx.send(ctx.localizer.format_str("{nothing_found}")) + + embed = discord.Embed(color=ctx.me.color) + + if results['loadType'] == 'PLAYLIST_LOADED': + numtracks = 0 + for track in results['tracks']: + _, track_added = await self.enqueue(ctx, track, embed, silent=True, check_max_length=False) + if track_added: + numtracks += 1 + + embed.title = '{playlist_enqued}' + embed.description = f'{results["playlistInfo"]["name"]} - {numtracks} {{tracks}}' + else: + track = results['tracks'][0] + await self.enqueue(ctx, track, embed, check_max_length=False) + + embed = ctx.localizer.format_embed(embed) + await ctx.send(embed=embed) + + if not player.is_playing: + await player.play() diff --git a/cogs/music/decorators.py b/cogs/music/decorators.py index 6475d74..6db999d 100644 --- a/cogs/music/decorators.py +++ b/cogs/music/decorators.py @@ -141,7 +141,7 @@ def voteable(requester_override=False, DJ_override=False, react_to_vote=False): enough_votes = votes/total >= threshold/100 DJ = DJ_override and is_dj(ctx) - requester = player.current.requester == ctx.author.id and requester_override + requester = player.current is None or (player.current.requester == ctx.author.id and requester_override) if enough_votes or requester or DJ: await func(self, ctx, *command_args, **kwargs) diff --git a/localization/en_en/commands.yaml b/localization/en_en/commands.yaml index b6d980a..03341f4 100644 --- a/localization/en_en/commands.yaml +++ b/localization/en_en/commands.yaml @@ -91,6 +91,10 @@ scrub: reconnect: aliases: [rc] description: 'disconnects then reconnects the bot in case of bugged songs' +forceplay: + aliases: [forceplay, fp] + args: '' # This is just a cosmetic representation of the arguments. + description: 'Searches and plays a song from a given query.' loop: aliases: [loop, looping] description: 'Loops the queue' diff --git a/localization/nb_no/commands.yaml b/localization/nb_no/commands.yaml index e3ef188..2f75945 100644 --- a/localization/nb_no/commands.yaml +++ b/localization/nb_no/commands.yaml @@ -88,6 +88,10 @@ lyrics: scrub: aliases: [kontroller] description: 'Gir deg en kontroller som du kan styre musikken med.' +forceplay: + aliases: [tvingspill, ts] + args: '' # This is just a cosmetic representation of the arguments. + description: 'Søker opp og spiller av en sang.' loop: aliases: [gjenta, repeter] description: 'Styr om køen skal gjenta seg'