Advertisement
Wonkiest29

Untitled

Sep 3rd, 2024
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.41 KB | None | 0 0
  1. import re
  2. import disnake
  3. from disnake import ApplicationCommandInteraction as Interaction
  4. from disnake.ext import commands
  5. import lavalink
  6. import logging
  7.  
  8. # Configure logging
  9. logging.basicConfig(level=logging.DEBUG)
  10. url_rx = re.compile(r'https?://(?:www\.)?.+')
  11. CHOICE = commands.option_enum(["Youtube", "Spotify", "Soundcloud"])
  12.  
  13.  
  14. class LavalinkVoiceClient(disnake.VoiceProtocol):
  15.     def __init__(self, client: disnake.Client, channel: disnake.abc.Connectable):
  16.         self.client = client
  17.         self.channel = channel
  18.         self.guild_id = channel.guild.id
  19.         self._destroyed = False
  20.  
  21.         if not hasattr(self.client, 'lavalink'):
  22.             self.client.lavalink = lavalink.Client(client.user.id)
  23.             self.client.lavalink.add_node(
  24.                 host='localhost',
  25.                 port=2333,
  26.                 password='youshallnotpass',
  27.                 region='us',
  28.                 name='default-node'
  29.             )
  30.  
  31.         self.lavalink = self.client.lavalink
  32.  
  33.     async def on_voice_server_update(self, data):
  34.         lavalink_data = {'t': 'VOICE_SERVER_UPDATE', 'd': data}
  35.         await self.lavalink.voice_update_handler(lavalink_data)
  36.  
  37.     async def on_voice_state_update(self, data):
  38.         channel_id = data['channel_id']
  39.  
  40.         if not channel_id:
  41.             await self._destroy()
  42.             return
  43.  
  44.         self.channel = self.client.get_channel(int(channel_id))
  45.         lavalink_data = {'t': 'VOICE_STATE_UPDATE', 'd': data}
  46.         await self.lavalink.voice_update_handler(lavalink_data)
  47.  
  48.     async def connect(self, *, timeout: float, reconnect: bool, self_deaf: bool = False, self_mute: bool = False) -> None:
  49.         self.lavalink.player_manager.create(guild_id=self.channel.guild.id)
  50.         await self.channel.guild.change_voice_state(
  51.             channel=self.channel,
  52.             self_mute=self_mute,
  53.             self_deaf=self_deaf
  54.         )
  55.  
  56.     async def disconnect(self, *, force: bool = False) -> None:
  57.         player = self.lavalink.player_manager.get(self.channel.guild.id)
  58.  
  59.         if not force and not player.is_connected:
  60.             return
  61.  
  62.         await self.channel.guild.change_voice_state(channel=None)
  63.         player.channel_id = None
  64.         await self._destroy()
  65.  
  66.     async def _destroy(self):
  67.         if self._destroyed:
  68.             return
  69.  
  70.         self._destroyed = True
  71.  
  72.         try:
  73.             await self.lavalink.player_manager.destroy(self.guild_id)
  74.         except lavalink.ClientError as e:
  75.             logger.error(f'Error destroying Lavalink player: {e}')
  76.  
  77. class Music(commands.Cog):
  78.     def __init__(self, bot):
  79.         self.bot = bot
  80.  
  81.     @commands.Cog.listener()
  82.     async def on_ready(self):
  83.         if not hasattr(self.bot, 'lavalink'):
  84.             self.bot.lavalink = lavalink.Client(self.bot.user.id)
  85.             self.bot.lavalink.add_node(
  86.                 host='localhost',
  87.                 port=2333,
  88.                 password='youshallnotpass',
  89.                 region='us',
  90.                 name='default-node'
  91.             )
  92.  
  93.     async def create_player(self, inter):
  94.         if inter.guild is None:
  95.             await inter.response.send_message("This command can only be used in a server.")
  96.             return
  97.  
  98.         player = self.bot.lavalink.player_manager.create(inter.guild.id)
  99.         should_connect = inter.data['name'] in ('play',)
  100.  
  101.         voice_client = inter.guild.voice_client
  102.  
  103.         if not inter.author.voice or not inter.author.voice.channel:
  104.             await inter.response.send_message('You need to join a voice channel first.')
  105.             return
  106.  
  107.         voice_channel = inter.author.voice.channel
  108.  
  109.         if voice_client is None:
  110.             if not should_connect:
  111.                 await inter.response.send_message("I'm not playing music.")
  112.                 return
  113.  
  114.             permissions = voice_channel.permissions_for(inter.guild.me)
  115.  
  116.             if not permissions.connect or not permissions.speak:
  117.                 await inter.response.send_message('I need the `CONNECT` and `SPEAK` permissions.')
  118.                 return
  119.  
  120.             if voice_channel.user_limit > 0:
  121.                 if len(voice_channel.members) >= voice_channel.user_limit and not inter.guild.me.guild_permissions.move_members:
  122.                     raise commands.CommandInvokeError('Your voice channel is full!')
  123.  
  124.             player.store('channel', inter.channel.id)
  125.  
  126.             # Automatically join the voice channel if the bot is not already connected
  127.            
  128.             await voice_channel.connect(cls=LavalinkVoiceClient)
  129.         elif voice_client.channel.id != voice_channel.id:
  130.             # If the bot is connected to another channel, raise an error
  131.             raise commands.CommandInvokeError('You need to be in the same voice channel as the bot.')
  132.  
  133.         return True
  134.  
  135.  
  136.     @commands.slash_command(name='play', description='Searches and plays a song from a given query.')
  137.     async def play(self, inter, query: str, source: CHOICE = None):
  138.         await self.create_player(inter)
  139.         player = self.bot.lavalink.player_manager.get(inter.guild.id)
  140.         # print(player)
  141.         query = query.strip('<>')
  142.         # print(source)
  143.         if not url_rx.match(query):
  144.             if source == 'Spotify':
  145.                 query = f'sprec:{query}'
  146.             elif source == 'Soundcloud':
  147.                 query = f'scsearch:{query}'
  148.             elif source == 'Youtube':
  149.                 query = f'ytsearch:{query}'
  150.             else:
  151.                 query = f'ytsearch:{query}'
  152.         # print(query)
  153.         results = await player.node.get_tracks(query)
  154.  
  155.         embed = disnake.Embed(color=disnake.Color.blurple())
  156.  
  157.         if results.load_type == lavalink.LoadType.EMPTY:
  158.             return await inter.response.send_message("I couldn't find any tracks for that query.")
  159.         elif results.load_type == lavalink.LoadType.PLAYLIST:
  160.             tracks = results.tracks
  161.  
  162.             for track in tracks:
  163.                 player.add(track=track, requester=inter.author.id)
  164.  
  165.             embed.title = 'Playlist Enqueued!'
  166.             embed.description = f'{results.playlist_info.name} - {len(tracks)} tracks'
  167.         else:
  168.             track = results.tracks[0]
  169.             embed.title = 'Track Enqueued'
  170.             embed.description = f'[{track.title}]({track.uri})'
  171.  
  172.             player.add(track=track, requester=inter.author.id)
  173.  
  174.         await inter.response.send_message(embed=embed)
  175.  
  176.         if not player.is_playing:
  177.             await player.play()
  178.  
  179.     @commands.slash_command(name='stop', description='Stops the player and clears the queue.')
  180.     async def stop(self, inter):
  181.         player = self.bot.lavalink.player_manager.get(inter.guild.id)
  182.  
  183.         if not player.is_connected:
  184.             return await inter.response.send_message("I'm not connected to a voice channel.")
  185.  
  186.         player.queue.clear()
  187.         # Stop the current track so Lavalink consumes less resources.
  188.         await player.stop()
  189.         # Disconnect from the voice channel.
  190.         await inter.guild.voice_client.disconnect(force=True)
  191.         # await inter.guild.voice_client.disconnect(force=True)
  192.         await inter.response.send_message("Stopped the player and cleared the queue.")
  193.  
  194.     @commands.slash_command(name='skip', description='Skips the current track.')
  195.     async def skip(self, inter: Interaction):
  196.         player = self.bot.lavalink.player_manager.get(inter.guild.id)
  197.  
  198.         if not player.is_connected:
  199.             return await inter.response.send_message("I'm not connected to a voice channel.")
  200.  
  201.         if not player.is_playing:
  202.             return await inter.response.send_message("There's no track playing right now.")
  203.  
  204.         await player.skip()
  205.         await inter.response.send_message("Skipped the current track.")
  206.  
  207.     @commands.slash_command(name='join', description='Joins the voice channel you are in.')
  208.     async def join(self, inter):
  209.         await self.create_player(inter)
  210.         await inter.response.send_message("Joined the voice channel.")
  211.  
  212.  
  213.     @commands.slash_command(name='volume', description='Sets the player volume.')
  214.     async def volume(self, inter: Interaction, volume: int):
  215.         player = self.bot.lavalink.player_manager.get(inter.guild.id)
  216.  
  217.         if not player.is_connected:
  218.             return await inter.response.send_message("I'm not connected to a voice channel.")
  219.  
  220.         if volume < 0 or volume > 1000:
  221.             return await inter.response.send_message("Volume must be between 0 and 100.")
  222.  
  223.         await player.set_volume(volume)
  224.         await inter.response.send_message(f"Set the player volume to {volume}%.")
  225.  
  226.     @commands.slash_command(name='pause', description='Pauses the current track.')
  227.     async def pause(self, inter: Interaction):
  228.         player = self.bot.lavalink.player_manager.get(inter.guild.id)
  229.  
  230.         if not player.is_connected:
  231.             return await inter.response.send_message("I'm not connected to a voice channel.")
  232.  
  233.         if not player.is_playing:
  234.             return await inter.response.send_message("There's no track playing right now.")
  235.  
  236.         await player.set_pause(True)
  237.         await inter.response.send_message("Paused the current track.")
  238.  
  239.     @commands.slash_command(name='resume', description='Resumes the current track.')
  240.     async def continue_(self, inter: Interaction):
  241.         player = self.bot.lavalink.player_manager.get(inter.guild.id)
  242.  
  243.         if not player.is_connected:
  244.             return await inter.response.send_message("I'm not connected to a voice channel.")
  245.  
  246.         if not player.is_playing:
  247.             return await inter.response.send_message("There's no track playing right now.")
  248.  
  249.         await player.set_pause(False)
  250.         await inter.response.send_message("Resumed the current track.")
  251.  
  252.     @commands.slash_command(name='loop', description='Toggles looping the current track.')
  253.     async def loop(self, inter: Interaction):
  254.         player = self.bot.lavalink.player_manager.get(inter.guild.id)
  255.  
  256.         if not player.is_connected:
  257.             return await inter.response.send_message("I'm not connected to a voice channel.")
  258.  
  259.         if not player.is_playing:
  260.             return await inter.response.send_message("There's no track playing right now.")
  261.  
  262.         player.set_loop(not player.loop)
  263.         loop_state = "enabled" if player.loop else "disabled"
  264.         await inter.response.send_message(f"Looping is now {loop_state}.")
  265.  
  266. def setup(bot):
  267.     bot.add_cog(Music(bot))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement