import asyncio import logging import random import re from datetime import datetime from sys import platform import discord import eyed3 from discord.ext import commands, tasks import music_functions from ai_functions import handle_response from communication_subroutine import PREPPED_TRACKS from constants import MESSAGE_TABLE_MUZYKA, MUZYKA, SEPARATOR_FILE_PATH from other_functions import get_stats class MusicModule(commands.Cog): def __init__(self, bot, logger_name): self.bot = bot self.logger = logging.getLogger(logger_name) @commands.hybrid_command( name="krecimy_pornola", description="Wiadomo co, dla kogo i po co", ) @commands.has_any_role('Legenda', 'Jarl', 'Thane' , 'Bartender') async def krecimy_pornola(self, ctx): """ Download a music number from youtube. :param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It represents the context in which the command was invoked, including information such as the message, the channel, the server, and the user who invoked the command. It allows the command to interact with the Discord API and """ await ctx.send("Dej mnie chwilkę") self.logger.info("Pornol") async with ctx.typing(): # wyciagnij linka z kontekstu content = ctx.message.content.split() for item_yt in content: if re.match("http.*", item_yt): sciezka, files = await music_functions.get_file( ctx, "Pornol", item_yt ) if files: self.logger.info("Pornol udany") await ctx.send( f"Jest w tajnym archiwum pod adresem{sciezka})" ) @commands.hybrid_command( name="co_na_plejliscie_wariacie", description="Wyswietl kawalki ktore sa na pocztku list radia", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender') async def co_na_plejliscie_wariacie(self, ctx): """ Download a music number from youtube. :param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It represents the context in which the command was invoked, including information such as the message, the channel, the server, and the user who invoked the command. It allows the command to interact with the Discord API and """ await ctx.send("Dej mnie chwilkę") async with ctx.typing(): self.logger.info("plejlista") self.logger.info(PREPPED_TRACKS) await ctx.send( f"Didżej Hammer i jego sztuczna inteligencja (||he he||) prezentują: \n- obecnie grany jest {(PREPPED_TRACKS['now_playing']).rstrip()} (wg metadanych: {PREPPED_TRACKS['meta']}) \n- następny będzie{(PREPPED_TRACKS['next']).rstrip()} \n- na liście priorytetowej {(PREPPED_TRACKS['priority']).rstrip()} \n- na liście hitów obecnie czeka kawałek {(PREPPED_TRACKS['hit']).rstrip()} \n- na liście wszystkich kawałków {(PREPPED_TRACKS['all']).rstrip()} \n- najświeższym zamówieniem od słuchaczy jest {(PREPPED_TRACKS['requests']).rstrip()} \nZ kolei jingiel to: {(PREPPED_TRACKS['jingles']).rstrip()}" ) @tasks.loop(seconds=1) async def check_music(self): """ This Python function continuously checks for music playback in a voice client and plays music if conditions are met. """ if self.bot.voice_clients: voice_client = self.bot.voice_clients[0] if ( voice_client and voice_client.is_connected() and not voice_client.is_playing() and not voice_client.is_paused() ): await self.play(MUZYKA["ctx"], MUZYKA["requester"]) await asyncio.sleep(2) @commands.hybrid_command( name="dej_co_z_jutuba", description="Podaj link do youtube - sciagnie i doda muzyke", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender') async def dej_co_z_jutuba(self, ctx): """ Download a music number from youtube. :param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It represents the context in which the command was invoked, including information such as the message, the channel, the server, and the user who invoked the command. It allows the command to interact with the Discord API and """ await ctx.send("Dej mnie chwilkę") self.logger.info("Jutub") async with ctx.typing(): # wyciagnij linka z kontekstu content = ctx.message.content.split() for item_yt in content: if re.match("http.*", item_yt): _, files = await music_functions.get_file(ctx, "Youtube", item_yt) if files: for file_iter in files: global MUZYKA # pylint: disable=global-variable-not-assigned MUZYKA["queue"].insert(0, file_iter) music_functions.MUSIC_FILE_LIST.update_file_list(file_iter) MUZYKA["requester"].insert(0, ctx.author) await ctx.send(f"Dodałem do listy {file_iter}") self.logger.info("Jutub udany") @commands.hybrid_command( name="dej_co_ze_spotifaja", description="Podaj link do spotify - sciagnie i doda muzyke", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender') async def dej_co_ze_spotifaja(self, ctx): """ Get a playlist or a music number from Spotify. :param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It represents the context in which the command was invoked, including information such as the message, the channel, the server, and the user who invoked the command. This parameter is required in all Discord.py commands """ self.logger.info("Spotifaj") await ctx.send("Dej mnie chwilkę") async with ctx.typing(): # wyciagnij linka z kontekstu content = ctx.message.content.split() for item in content: if re.match("http.*", item): dir_path, files = await music_functions.get_file( ctx, "Spotify", item ) if platform == "win32": separator = "\\" else: separator = "/" for file in files: file_path = ( dir_path + separator + file["artist"] + " - " + file["name"] + ".mp3" ) global MUZYKA # pylint: disable=global-variable-not-assigned MUZYKA["queue"].insert( 0, dir_path + separator + file["artist"] + " - " + file["name"] + ".mp3", ) MUZYKA["requester"].insert(0, ctx.author) music_functions.MUSIC_FILE_LIST.update_file_list(file_path) await ctx.send( f"Dodałem do listy {dir_path}{file['artist']} - + {file['name']}.mp3" ) self.logger.info("Spotifaj udany") # MUSIC BOT PART @commands.hybrid_command( name="cisza", description="Wyłącza muzykę i czyści plejliste.", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender') async def cisza(self, ctx): """ Stop playback of the music and clear the queue. :param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It represents the context in which the command was invoked, including information such as the message, the channel, the server, and the user who invoked the command. This parameter is required in all Discord.py commands """ self.logger.info("Stop") global MUZYKA # pylint: disable=global-variable-not-assigned MUZYKA["ctx"] = None voice_client = self.bot.voice_clients[0] self.check_music.stop() if voice_client.is_connected(): await self.disconnect(ctx=ctx) while MUZYKA["queue"]: MUZYKA["queue"].pop() MUZYKA["requester"].pop() self.logger.info("Stop completed") @commands.hybrid_command( name="dalej", description="Przerzuca na następny kawałek", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender') async def dalej(self, ctx): """ Play next track in queue. :param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It represents the context in which a command is being executed, including information such as the message, the channel, the server, and the user who invoked the command. The context object is used to access and manipulate this """ if ctx: self.logger.info("Ctx defined for dalej") self.logger.info("Next") voice_client = self.bot.voice_clients[0] if voice_client.is_connected(): voice_client.stop() self.logger.info("Next completed") @commands.hybrid_command( name="daj_mi_chwile", description="Pauzuje", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender') async def daj_mi_chwile(self, ctx): """ Pause music playback. :param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It represents the context in which the command was invoked, including information such as the message, the channel, the server, and the user who invoked the command. This parameter is required in most Discord.py commands and is """ if ctx: self.logger.info("Ctx defined for pause") self.logger.info("Pause") voice_client = self.bot.voice_clients[0] if voice_client.is_connected(): voice_client.pause() self.logger.info("Pause completed") @commands.hybrid_command( name="graj_dalej", description="Odpauzowuje", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender') async def graj_dalej(self, ctx): """ Unpause music and continue playback. :param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It represents the context in which the command was invoked, including information such as the message, the channel, the server, and the user who invoked the command. This parameter is required in all Discord.py commands """ if ctx: self.logger.info("Ctx defined for graj_dalej") self.logger.info("Unpause") voice_client = self.bot.voice_clients[0] if voice_client.is_paused(): voice_client.resume() self.logger.info("Unpause completed") @commands.hybrid_command( name="zagraj_mi_kawalek", description="Wyszukuje w bibliotece muzycznej Hammera kawałek który ma zostać zagrany", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender') async def zagraj_mi_kawalek(self, ctx): """ Play a song or music piece in response to a command triggered by a user in a Discord chat context. :param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It contains information about the context in which the command was invoked, such as the message, the channel, the server, and the user who invoked the command. This information can be used to perform various actions, such """ async with ctx.typing(): search_time_glob = datetime.now() self.logger.info("Zaczynam szukać timestamp %s", datetime.now()) file = await self.wyszukaj(ctx=ctx) self.logger.info( "Koniec szukania(timestamp %s zajęło %s", datetime.now(), datetime.now() - search_time_glob, ) if file: for plik in file: global MUZYKA # pylint: disable=global-variable-not-assigned MUZYKA["queue"].insert(0, plik[1]) MUZYKA["requester"].insert(0, ctx.author) metadata = eyed3.load(plik[1]) reply = ( "Dodałem do playlisty {plik[1]} z prywatnej kolekcji Hammera." ) if metadata.tag.title: reply = f"Dodałem do playlisty kawalek {metadata.tag.title}" if metadata.tag.artist: reply += f" wykonawcy {metadata.tag.artist}" if metadata.tag.album: reply += f" z albumu {metadata.tag.album}" reply += ( " z prywatnej kolekcji Hammera i na Twoją specjalną rpośbę." ) await ctx.send(reply) else: await ctx.send( "Obawiam się że nie mogę nic znaleźć u siebie. Spróbuj komendy '$dej_co_ze_spotifaja' jeśli masz link" ) @commands.hybrid_command( name="zrob_mi_plejliste", description="Generuje playliste - param1 - dlugosc, potem slowa wyszukiwania", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender') async def zrob_mi_plejliste(self, ctx): """ Generate a playlist in queue. First word in this command shall be int defining length of the playlist. Rest of the line are search terms. :param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It represents the context in which the command was invoked, including information such as the message, the channel, the server, and the user who invoked the command. This parameter is required in all Discord.py commands """ reply = "Wygenerowana plejlista:\n" async with ctx.typing(): self.logger.info("Zaczynam szukać timestamp %s", datetime.now()) search_time_glob = datetime.now() dlugosc_playlisty = ctx.message.content.split()[1] file = await music_functions.wyszukaj(ctx=ctx, how_many=dlugosc_playlisty) self.logger.info( "Koniec szukania(timestamp %s zajęło %s", datetime.now(), datetime.now() - search_time_glob, ) index = 1 if file: for plik in file: if plik[1]: self.logger.info(plik) global MUZYKA # pylint: disable=global-variable-not-assigned MUZYKA["queue"].insert(0, plik[1]) MUZYKA["requester"].insert(0, ctx.author) metadata = eyed3.load(plik[1]) if metadata and metadata.tag: if metadata.tag.title: reply += f"{index} {metadata.tag.title}" else: reply += ( f"{index}. {plik[1]} z prywatnej kolekcji Hammera." ) if metadata.tag.artist: reply += f" wykonawcy {metadata.tag.artist}" if metadata.tag.album: reply += f" z albumu {metadata.tag.album}" if metadata.tag.title: reply += " z prywatnej kolekcji Hammera i na Twoją specjalną rpośbę.\n" else: reply += ( f"{index}. {plik[1]} z prywatnej kolekcji Hammera.\n" ) index += 1 if len(reply) > 1800: await ctx.send(reply) reply = "" else: await ctx.send( "Obawiam się że nie mogę nic znaleźć u siebie. Spróbuj komendy '$dej_co_ze_spotifaja' jeśli masz link" ) await ctx.send(reply) self.logger.info("Plejlista zrobiona") @commands.hybrid_command( name="zagraj_muzyke_mego_ludu", description="Gra muzyke wyszukana na bazie tematow konwersacji na kanale NZ", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender') async def zagraj_muzyke_mego_ludu(self, ctx): """ Play completeley random playlist based on messaging history. :param ctx: ctx stands for "context" and is typically used in Discord.py commands to represent the context in which the command was invoked. This includes information such as the message, the channel, the author, and other relevant details. In this case, it is being passed as a parameter to the `get_image """ stats = {} if ctx: self.logger.info("Zagraj muzyke mego ludu: wywolane") stat_iter = get_stats(self.bot, ctx, MUZYKA_MOJEGO_LUDU_HISTORIA) async for name, how_many in stat_iter: if len(name) > 3: stats[name] = how_many sorted_stats = sorted(stats.items(), key=lambda x: x[1]) self.logger.info("Zagraj muzyke mego ludu:zebrano statystyki") key_words = [] for stat in sorted_stats: key_words.append(stat[0]) self.logger.info(sorted_stats[:MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE]) self.logger.info(key_words[:MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE]) self.logger.info(sorted_stats[-MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE:]) self.logger.info(key_words[-MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE:]) final_key_words = key_words[:MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE] final_key_words.extend(key_words[-MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE:]) reply = "Wygenerowana plejlista:\n" async with ctx.typing(): self.logger.info( "Zagraj muzyke mego ludu:Zaczynam szukać timestamp %s", datetime.now() ) search_time_glob = datetime.now() file = await music_functions.wyszukaj( ctx=ctx, how_many=MUZYKA_MOJEGO_LUDU_PLAJLISTA, slowa_kluczowe=final_key_words, ) self.logger.info("Zagraj muzyke mego ludu:wygenerowano plejliste") self.logger.info(file) self.logger.info( "Zagraj muzyke mego ludu: Koniec szukania(timestamp %s zajęło %s", datetime.now(), datetime.now() - search_time_glob, ) index = 1 if file: for plik in file: global MUZYKA # pylint: disable=global-variable-not-assigned MUZYKA["queue"].insert(0, plik[1]) MUZYKA["requester"].insert(0, ctx.author) metadata = eyed3.load(plik[1]) if metadata and metadata.tag: if metadata.tag.title: reply += f"{index} {metadata.tag.title}" else: reply += f"{index}. {plik[1]} z prywatnej kolekcji Hammera." if metadata.tag.artist: reply += f" wykonawcy {metadata.tag.artist}" if metadata.tag.album: reply += f" z albumu {metadata.tag.album}" if metadata.tag.title: reply += " z prywatnej kolekcji Hammera i na Twoją specjalną rpośbę.\n" else: reply += f"{index}. {plik[1]} z prywatnej kolekcji Hammera.\n" index += 1 if len(reply) > 1800: await ctx.send(reply) reply = "" else: await ctx.send( "Obawiam się że nie mogę nic znaleźć u siebie. Spróbuj komendy '$dej_co_ze_spotifaja' jeśli masz link" ) await ctx.send(reply) self.logger.info("Plejlista zrobiona") @commands.hybrid_command( name="parametry_muzyki_mego_ludu", description="Konfiguruje komende zagraj muzyke mojego ludu", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender') async def parametry_muzyki_mego_ludu( self, ctx, ile_historii=1500, ile_slow_kluczowych=15, jak_dluga_plejlista=30 ): """ The function `parametry_muzyki_mego_ludu` sets global variables for the number of history entries, number of keywords, and length of playlist for a music application. :param ctx: The `ctx` parameter is typically used in Discord.py, a Python library for creating Discord bots. It represents the context of the command being executed, including information about the message, the server, and the user who invoked the command :param ile_historii: The parameter "ile_historii" represents the number of history items for the music playlist, defaults to 1500 (optional) :param ile_slow_kluczowych: The parameter "ile_slow_kluczowych" represents the number of keywords or key phrases related to music that you want to include in your analysis or search, defaults to 30 (optional) :param jak_dluga_plejlista: The parameter "jak_dluga_plejlista" determines the length of the playlist. It specifies how many songs should be included in the playlist, defaults to 30 (optional) """ if ctx: async with ctx.typing(): # if ':' in ile_historii: # _, _, ile_historii = ile_historii.partition(':') # if ':' in ile_slow_kluczowych: # _, _, ile_slow_kluczowych = ile_slow_kluczowych.partition(':') # if ':' in jak_dluga_plejlista: # _, _, jak_dluga_plejlista = jak_dluga_plejlista.partition(':') try: global MUZYKA_MOJEGO_LUDU_HISTORIA # pylint: disable=global-statement global MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE # pylint: disable=global-statement global MUZYKA_MOJEGO_LUDU_PLAJLISTA # pylint: disable=global-statement self.logger.info( "Długość historii wyszukiwania: %s\n Ilość słów kluczowych: %s\n Długość plejlisty do wygenerowanie: %s", MUZYKA_MOJEGO_LUDU_HISTORIA, MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE, MUZYKA_MOJEGO_LUDU_PLAJLISTA, ) ctx.send( f"Dotychczasowe wartośći:\n Długość historii wyszukiwania: {MUZYKA_MOJEGO_LUDU_HISTORIA}\n Ilość słów kluczowych: {MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE}\n Długość plejlisty do wygenerowanie:{MUZYKA_MOJEGO_LUDU_PLAJLISTA}" ) MUZYKA_MOJEGO_LUDU_HISTORIA = ile_historii MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE = ile_slow_kluczowych MUZYKA_MOJEGO_LUDU_PLAJLISTA = jak_dluga_plejlista self.logger.info( "Długość historii wyszukiwania: %s\n Ilość słów kluczowych: %s\n Długość plejlisty do wygenerowanie: %s", MUZYKA_MOJEGO_LUDU_HISTORIA, MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE, MUZYKA_MOJEGO_LUDU_PLAJLISTA, ) self.ctx.send( f"Zmienione wartośći:\n Długość historii wyszukiwania: {MUZYKA_MOJEGO_LUDU_HISTORIA}\n Ilość słów kluczowych: {MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE}\n Długość plejlisty do wygenerowanie:{MUZYKA_MOJEGO_LUDU_PLAJLISTA}" ) except discord.ext.commands.errors.BadArgument as exce: ctx.send("Spierdalaj") self.logger.info(exce) @commands.hybrid_command( name="graj_muzyko", description="Włącza muzykę na kanale #nocna-zmiana.", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender') async def graj_muzyko(self, ctx): """ Async function named "graj_muzyko" starts music playback on channel "Nocna Zmiana". :param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It represents the context in which the command was invoked, including information such as the message, the channel, the server, and the user who invoked the command. This parameter is required in all Discord.py commands """ self.logger.info("Press play on tape") async with ctx.typing(): global MUZYKA # pylint: disable=global-variable-not-assigned MUZYKA["ctx"] = ctx await self.connect(ctx=ctx) await self.play(ctx=ctx) self.logger.info("Press play on tape completed") self.check_music.start() async def connect(self, ctx, arg=None): """ Connect the bot to a voice channel if it is not already connected. :param ctx: ctx is short for context and refers to the context in which the command was invoked. It contains information about the message, the channel, the server, and the user who invoked the command :param arg: The `arg` parameter is an optional argument that can be passed to the `connect` function. It is not used in the code snippet provided, but it could potentially be used to specify a specific voice channel to connect to :return: If the voice client is already connected, the function will return without doing anything. If the function successfully connects to the voice channel, it will return a voice channel connection object. If it is not possible to connect to the voice channel, the function will log an error message and return nothing. """ if ctx and arg: self.logger.info("Ctx and arg defined for connect") if self.bot.voice_clients: self.logger.info("Already connected with other client") else: vc = None if ctx.author.voice.channel: vc = await ctx.author.voice.channel.connect() else: voice_channel = self.bot.get_channel(1060349757349974066) vc = await voice_channel.connect() if not vc: self.logger.error("Not possible to connect to voice") return self.logger.info("Connected to voice") @commands.hybrid_command( name="batch_download", description="Zaciąga obiekty z pliku", guild=discord.Object(id=664789470779932693), ) @commands.has_any_role('Legenda', 'Jarl', 'Thane' , 'Bartender') async def batch_download(self, ctx): content_type = ctx.message.attachments[0].content_type check = re.search("text\/plain; *charset=(.*)", content_type, re.IGNORECASE) await ctx.reply("Kurwa. Aleś mi roboty narobił... No nic. Ku radości. Skal!") async with ctx.typing(): if check: global MUZYKA # pylint: disable=global-variable-not-assigned file_bytes = await ctx.message.attachments[0].read() text = file_bytes.decode(encoding=check.group(1)) self.logger.info(text) lines = text.split("\n") for link in lines: link = link.strip() self.logger.info(link) pat = r"^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$" self.logger.info("Verification") if re.match(pat, link) and ( re.match(".*youtube.*", link) or re.match(".*youtu.be.*", link) ): self.logger.info("%s to link do jutuba", link) dir_path, files = await music_functions.get_file( ctx, "Youtube", link ) if files: for file_iter in files: global MUZYKA # pylint: disable=global-variable-not-assigned MUZYKA["queue"].insert(0, file_iter) music_functions.MUSIC_FILE_LIST.update_file_list( file_iter ) MUZYKA["requester"].insert(0, ctx.author) await ctx.send(f"Dodałem do listy {file_iter}") self.logger.info("Jutub udany") elif re.match(pat, link) and re.match(".*spotify.*", link): self.logger.info("%s to link do spotify", link) dir_path, files = await music_functions.get_file( ctx, "Spotify", link ) if platform == "win32": separator = "\\" else: separator = "/" for file in files: file_path = ( dir_path + separator + file["artist"] + " - " + file["name"] + ".mp3" ) MUZYKA["queue"].insert( 0, dir_path + separator + file["artist"] + " - " + file["name"] + ".mp3", ) MUZYKA["requester"].insert(0, ctx.author) music_functions.MUSIC_FILE_LIST.update_file_list(file_path) await ctx.send( f"Dodałem do listy {dir_path}{file['artist']} - + {file['name']}.mp3" ) self.logger.info("Spotifaj udany") elif re.match(pat, link): self.logger.info("%s to link do czegos", link) sciezka, files = await music_functions.get_file( ctx, "Pornol", link ) if files: self.logger.info("Pornol udany") await ctx.send( f"Jest w tajnym archiwum pod adresem{sciezka})" ) else: self.logger.info("Spierdalaj") self.logger.info(link) await ctx.message.reply("Spierdalaj") else: self.logger.info(content_type) self.logger.info("Spierdalaj") await ctx.message.reply("Spierdalaj") async def disconnect(self, ctx): """ Asynchronous Python function that disconnects the voice client if it is connected and logs a message if the context is defined. :param ctx: ctx is short for context and refers to the context in which a command is being executed. It contains information about the message, the user who sent the message, the channel the message was sent in, and more. In this case, the `disconnect` function is likely being called as a command in """ if ctx: self.logger.info("Ctx defined for disconnect") if self.bot.voice_clients: voice_client = self.bot.voice_clients[0] if voice_client.is_connected(): await voice_client.disconnect() async def play(self, ctx, zamawial=None, arg=None): """ Play a music file, retrieve metadata about the file, and send a message to a Discord channel with information about the song being played. :param ctx: The "ctx" parameter is a context object that contains information about the current Discord command invocation, such as the message, the channel, and the user who invoked the command. It is passed to the function automatically by the Discord.py library :param zamawial: The parameter `zamawial` is a variable that stores the user who requested the song to be played. It is an optional parameter and can be None if no user requested the song :param arg: The `arg` parameter is an optional argument that can be passed to the `play` function. It is not used in the code provided, so its purpose is unclear without additional context """ # TODO: Uzupełnianie metadanych. Jeśli ich nie ma sprawdzamy nazwę (w sposób inteligentny - czyli jeśli składa się z samych cyfr i/lub słowa track to sprawdzić album w sensie folder) # TODO: Jeśli w metadanych jest tylko "audiotrack" i "album" też po # folderze. Jeśli są niekompletne uzupełnić dalej. self.logger.info("Play procedure") if arg: self.logger.info("Arg defined for play") file_to_play = None voice_client = self.bot.voice_clients[0] if not self.bot.voice_clients: voice_client = self.bot.voice_clients[0] await self.connect(ctx) if MUZYKA["queue"]: file_to_play = MUZYKA["queue"].pop() zamawial = MUZYKA["requester"].pop() self.logger.info("Muzyka z listy zamówień") else: # trunk-ignore(bandit/B311) index = random.randint( 0, len(music_functions.MUSIC_FILE_LIST.get_file_list()) - 1 ) file_to_play = music_functions.MUSIC_FILE_LIST.get_file_list()[index] self.logger.info("Muzyka losowo") self.logger.info(file_to_play) metadata = eyed3.load(file_to_play) query = None temp = file_to_play.split(SEPARATOR_FILE_PATH)[-1] kawalek = f"Zagram teraz kawalek {temp} z prywatnej kolekcji Hammera." if metadata: if metadata.tag: if metadata.tag.title: query = f"Opowiedz mi o kawałku {metadata.tag.title}" kawalek = f"Zagram teraz kawalek {metadata.tag.title}" if metadata.tag.artist: query += f" wykonawcy {metadata.tag.artist}" kawalek += f" wykonawcy {metadata.tag.artist}" if metadata.tag.album: query += f" z albumu {metadata.tag.album}" kawalek += f" z albumu {metadata.tag.album}" kawalek += " z prywatnej kolekcji Hammera." if zamawial: kawalek += f"Na specjalne życzenie <@{zamawial.id}>." await ctx.send(kawalek) voice_client.play( discord.PCMVolumeTransformer( discord.FFmpegPCMAudio(source=file_to_play), volume=0.3 ) ) # NIE DOTYKAC POKRĘTŁA GŁOŚNOŚCI!!!! if query: self.logger.debug("Zapytanie do openai") self.logger.debug(query) vykidailo = False bartender = False for role in ctx.message.author.roles: if role.name == "Vykidailo": vykidailo = True if role.name == "Bartender": bartender = True if ctx.message.author.nick: username = ctx.message.author.nick else: username = ctx.message.author.name global MESSAGE_TABLE_MUZYKA # pylint: disable=global-statement result, MESSAGE_TABLE_MUZYKA = await handle_response( query, vykidailo, bartender, MESSAGE_TABLE_MUZYKA, username, "MUSIC" ) self.logger.debug("Obecna historia czatu: %s", MESSAGE_TABLE_MUZYKA) if len(result) < 1500: await ctx.send(result) else: while len(result) > 1500: await ctx.send(result[:1500]) result = result[1500:] async def setup(bot): logger = logging.getLogger("discord") await music_functions.MUSIC_FILE_LIST.refresh_file_list(bot) logger.info("Playlist generation") await bot.add_cog(MusicModule(bot, "discord")) logger.info("Loading music commands module done")