From 7f3de2ea13ad9281ee3b544a5c380048fc511753 Mon Sep 17 00:00:00 2001 From: Polish Hammer Date: Tue, 6 Jun 2023 12:54:35 +0200 Subject: [PATCH] Kurwa bugfix pod windowsa --- bot.py | 1561 ++++++++++++++------------------------------------------ 1 file changed, 373 insertions(+), 1188 deletions(-) diff --git a/bot.py b/bot.py index d2bb2cd..dd222fd 100644 --- a/bot.py +++ b/bot.py @@ -1,135 +1,71 @@ # This Python file uses the following encoding: utf-8 -# trunk-ignore-all(bandit/B311) -# pylint: disable=line-too-long -# pylint: disable=too-many-lines -""" -Module of a python bot named Conjurer - used to work on BDSM discord servers. -""" -import asyncio -import io -import json -import logging -import netrc - -# *=========================================== Standard Library Imports +# *=========================================== Imports import os -import random -import re -import shutil -import sys -from datetime import datetime -from logging import handlers -from pathlib import Path, PurePath -from platform import uname -from sys import platform -from typing import List, Optional, TypedDict - -# *==============Imported libraries import discord -import eyed3 -import numpy as np -import openai -import pdf2image -import PyPDF2 +import json +import re +import netrc +from discord.ext import commands +import logging import requests +from datetime import datetime +from sys import platform +import openai +import numpy as np +import pdf2image +import io +import PyPDF2 +import random +import asyncio +from pathlib import PurePath +from pathlib import Path +import eyed3 import spotipy -import tiktoken -from discord.ext import commands, tasks -from spotipy.oauth2 import SpotifyClientCredentials - -import yt_dlp from spotify_dl import spotify from spotify_dl import youtube as youtube_download - -Music_Config = TypedDict( - "Music_Config", - { - "playing": bool, - "ctx": Optional[str], - "queue": List[str], - "requester": List[str], - }, -) +import yt_dlp +from spotipy.oauth2 import SpotifyClientCredentials +import logging.handlers as handlers +import shutil # *=========================================== Predefines formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") -MASTER_TIMEOUT = datetime.now() +master_timeout = datetime.now() INITIAL_TIME_WAIT = 5 -MUZYKA: Music_Config = {"playing": False, "ctx": None, "queue": [], "requester": []} - -LOGFILE = "" -NETRC_FILE = "" -MUSIC_FOLDER = "" -MEMORY_FIVE_SIARA = "" -MEMORY_FIVE_MUZYKA = "" -SETTINGS_FILE = "" -ENCODING = "" -GRAPHICS_PATH = "" -MUZYKA_MOJEGO_LUDU_HISTORIA = 1500 -MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE = 15 -MUZYKA_MOJEGO_LUDU_PLAJLISTA = 30 +MUZYKA = {"playing": False, "ctx": None, "queue": [], "requestor": []} # *=========================================== Platform Specific Predefines - -if platform in ("linux", "linux2"): - SEPARATOR_FILE_PATH = "/" - if "microsoft-standard" in uname().release: - LOGFILE = "/home/mtuszowski/conjurer/discord.log" - MEMORY_FIVE_SIARA = "/home/mtuszowski/conjurer/pamiec.json" - SYSTEM_GPT_SETTINGS = "/home/mtuszowski/conjurer/system_gpt_settings.json" - MEMORY_FIVE_MUZYKA = "/home/mtuszowski/conjurer/pamiec_muzyki.json" - MUSIC_FOLDER = "/mnt/g/Muzyka/" - SETTINGS_FILE = "/home/mtuszowski/conjurer/settings.json" - NETRC_FILE = "/home/mtuszowski/.netrc" - LOGSTORE = "/home/mtuszowski/conjurer/logs/" - ACCIDENT_LOG = "/home/mtuszowski/conjurer/accident_log.json" - ENCODING = "utf-8" - GRAPHICS_PATH = "/home/mtuszowski/conjurer/Conjurer_graphics/" - DIR_PATH_SADOX = "/mnt/c/Users/mtusz/OneDrive/Dokumenty/Fansadox" - - else: - LOGFILE = "/home/pi/Conjurer/discord.log" - MEMORY_FIVE_SIARA = "/home/pi/Conjurer/pamiec.json" - SYSTEM_GPT_SETTINGS = "/home/pi/Conjurer/system_gpt_settings.json" - MEMORY_FIVE_MUZYKA = "/home/pi/Conjurer/pamiec_muzyki.json" - MUSIC_FOLDER = "/home/pi/RetroPie/mp3/" - SETTINGS_FILE = "/home/pi/Conjurer/settings.json" - NETRC_FILE = "/home/pi/.netrc" - LOGSTORE = "/home/pi/RetroPie/logs/" - ACCIDENT_LOG = "/home/pi/Conjurer/accident_log.json" - ENCODING = "utf-8" - GRAPHICS_PATH = "/home/pi/RetroPie/Conjurer_graphics/" - DIR_PATH_SADOX = "/home/pi/RetroPie/Fansadox/" - +if platform == "linux" or platform == "linux2": + logfile = "/home/pi/Conjurer/discord.log" + memory_five_siara = "/home/pi/Conjurer/pamiec.json" + memory_five_muzyka = "/home/pi/Conjurer/pamiec_muzyki.json" + music_folder = "/home/pi/RetroPie/mp3/" + settings_file = "/home/pi/Conjurer/settings.json" + netrc_file = "/home/pi/.netrc" + logstore = "/home/pi/RetroPie/logs/" elif platform == "win32": - LOGFILE = "discord.log" - MEMORY_FIVE_SIARA = "pamiec.json" - SYSTEM_GPT_SETTINGS = "system_gpt_settings.json" - MEMORY_FIVE_MUZYKA = "pamiec_muzyki.json" - MUSIC_FOLDER = "G:\\Muzyka\\" - SETTINGS_FILE = "settings.json" - NETRC_FILE = "C:\\Users\\mtusz\\.netrc" - LOGSTORE = "C:\\Users\\mtusz\\OneDrive\\Pulpit\\Conjurer\\logs\\" - ACCIDENT_LOG = "accident_log.json" - ENCODING = "utf-8" - DIR_PATH_SADOX = "C:\\Users\\mtusz\\OneDrive\\Dokumenty\\Fansadox\\" - SEPARATOR_FILE_PATH = "\\" - + logfile = "discord.log" + memory_five_siara = "pamiec.json" + memory_five_muzyka = "pamiec_muzyki.json" + # music_folder = 'G:\\Muzyka\\segars\\segars\\segars_&_friends_-_shanties_of_oldtime_sailing_ships\\' + music_folder = "G:\\Muzyka\\" + settings_file = "settings.json" + netrc_file = "C:\\Users\\mtusz\\.netrc" + logstore = "C:\\users\\mtusz\\OneDrive\\Pulpit\\Conjurer\\logs\\" # *=========================================== Keys -netrc_mod = netrc.netrc(NETRC_FILE) -REMOTE_HOST_NAME = "discord" -authTokens = netrc_mod.authenticators(REMOTE_HOST_NAME) +netrc = netrc.netrc(netrc_file) +remoteHostName = "discord" +authTokens = netrc.authenticators(remoteHostName) TOKEN = authTokens[2] -REMOTE_HOST_NAME = "openai" -authTokens = netrc_mod.authenticators(REMOTE_HOST_NAME) +remoteHostName = "openai" +authTokens = netrc.authenticators(remoteHostName) openai.api_key = authTokens[2] -openAIClient = openai.AsyncOpenAI(api_key=openai.api_key) -REMOTE_HOST_NAME = "spotipy" -authTokens = netrc_mod.authenticators(REMOTE_HOST_NAME) +remoteHostName = "spotipy" +authTokens = netrc.authenticators(remoteHostName) spotify_ctrl = spotipy.Spotify( client_credentials_manager=SpotifyClientCredentials( client_id=authTokens[0], @@ -148,8 +84,8 @@ intents.voice_states = True logger = logging.getLogger("discord") logger.setLevel(logging.DEBUG) handler = handlers.RotatingFileHandler( - filename=LOGFILE, - encoding=ENCODING, + filename=logfile, + encoding="utf-8", mode="a", maxBytes=6 * 1024 * 1024, backupCount=6, @@ -160,59 +96,42 @@ random.seed() logger.debug(platform) logger.info("Playlist generation") + # *=========================================== Load Data files music_file_list = [] -for mp3_item in Path.glob(Path(MUSIC_FOLDER), "**/*.mp3"): - temp_music_file = mp3_item.as_posix() +for item in Path.glob(Path(music_folder), "**/*.mp3"): + file = item.as_posix() if platform == "win32": - temp_music_file = temp_music_file.replace("/", "\\") - music_file_list.append(temp_music_file) -with open(SYSTEM_GPT_SETTINGS, "r+", encoding=ENCODING) as temp_settings_file: + file = file.replace("/", "\\") + music_file_list.append(file) +with open(memory_five_siara, "r+") as file: # First we load existing data into a dict. - GPT_SETTINGS = json.load(temp_settings_file) - -with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as temp_memory_file: + message_table = json.load(file) +with open(memory_five_muzyka, "r+") as file: # First we load existing data into a dict. - MESSAGE_TABLE = json.load(temp_memory_file) -with open(MEMORY_FIVE_MUZYKA, "r+", encoding=ENCODING) as temp_music_memory_file: - # First we load existing data into a dict. - message_table_muzyka = json.load(temp_music_memory_file) -with open(SETTINGS_FILE, "r", encoding=ENCODING) as f_settings_file: - data = json.load(f_settings_file) + message_table_muzyka = json.load(file) +f = open(settings_file) +data = json.load(f) word_reactions = data["word_reactions"] -cyclic_words = data["cyclic_words"] historia_fabryczki = data["fabryczka"] for key in word_reactions: word_reactions[key][2] = datetime.now() # *=========================================== Create Client client = commands.Bot(intents=intents, command_prefix="$") - # *=========================================== Define Events @client.event async def on_ready(): - """Metoda wywoływana przy połączeniu do serwera.""" - logger.debug("%s has connected to Discord!", client.user) + logger.debug(f"{client.user} has connected to Discrod!") await client.change_presence(activity=discord.Game(name="Axe Throwing Darts")) - await client.tree.sync() - check_data.start() + await check() @client.event async def on_message(message): - """ - Handle incoming messages in a Discord server, perform various - checks and actions based on the content and context of the message, and respond accordingly. - - :param message: The message object that is received when a user sends a message in a Discord server - or DM. The code is checking various conditions and performing actions based on the content of the - message and the context in which it was sent. It also includes TODOs for future improvements - :return: The function `on_message` is being returned. - """ vykidailo = False - channel = None if message.author == client.user: return if isinstance(message.author, discord.Member): @@ -221,19 +140,11 @@ async def on_message(message): vykidailo = True if ("Conjurer Śpij Słodko Aniołku" in message.content) and vykidailo: - sys.exit() - # kanal bez bota + exit() + if message.channel.id == 1095985579147141202: return - # wentylacja - if message.channel.id == 1083804024173764739: - return - # legendy - if message.channel.id == 1084448332841230388: - return - # interrogation booth - if message.channel.id == 1111625221171052595: - return + if isinstance(message.channel, discord.DMChannel): channel = client.get_channel(1064888712565100614) await channel.send("Słyszałem ja żem że: " + message.content) @@ -241,10 +152,10 @@ async def on_message(message): channel = message.channel await client.process_commands(message) - # TODO: wpiac jego reakcje we framework chatu GPT + # wpiac jego reakcje we framework chatu GPT message.content = message.content.lower() - tdelta = datetime.now() - MASTER_TIMEOUT + tdelta = datetime.now() - master_timeout tdelta = tdelta.total_seconds() if "opowiedz o fabryczce" in message.content: await message.reply(historia_fabryczki) @@ -253,217 +164,142 @@ async def on_message(message): if tdelta > INITIAL_TIME_WAIT: for word in word_reactions: - if re.search(r"\b" + word + r"\b", message.content): + if re.search(".*" + word + "[\s*,$]*", message.content): + # if word in message.content: + tdelta = datetime.now() - word_reactions[word][2] tdelta = tdelta.total_seconds() - security_clearance = word_reactions[word][4] reaction = word_reactions[word][3] if tdelta > word_reactions[word][1]: - # TODO: to zrobic reactiony + # to zrobic reactiony logger.info("Ping z procedury reakcji") if reaction: emoji = client.get_emoji(word_reactions[word][0]) await message.add_reaction(emoji) - elif security_clearance and vykidailo: - await message.reply(word_reactions[word][0]) - elif not security_clearance: + else: await message.reply(word_reactions[word][0]) word_reactions[word][2] = datetime.now() # TODO: drobne literówki, mentiony, spacja przed dwukropkiem. napraw. - kondziu_mentioned = False - for mention in message.mentions: - if mention == client.user: - kondziu_mentioned = True - if kondziu_mentioned or "conjurer:" in message.content: + if "conjurer:" in message.content: async with channel.typing(): logger.debug("Procedura chatu") - message.content = message.content.replace("conjurer: ", "") + + prompt = message.content + if message.author.nick: username = message.author.nick else: username = message.author.name vykidailo = False bartender = False - if kondziu_mentioned: - prompt = message.clean_content - else: - prompt = message.content for role in message.author.roles: if role.name == "Vykidailo": vykidailo = True if role.name == "Bartender": bartender = True - global MESSAGE_TABLE # pylint: disable=global-statement - - result, MESSAGE_TABLE = await handle_response( - prompt, vykidailo, bartender, MESSAGE_TABLE, username, False + global message_table + result, message_table = await handle_response( + prompt, vykidailo, bartender, message_table, username, False ) await message.reply(result) if "imaginuje sobie:" in message.content: async with channel.typing(): logger.info("Poczatek procedury obrazkowej") message.content = message.content.replace("imaginuje sobie: ", "") - logger.debug("Wywolanie obrazka: %s", message.content) - response = await openAIClient.images.generate( - model="dall-e-3", - prompt=message.content, - size="1024x1024", - quality="standard", - n=1, + logger.debug("Wywolanie obrazka: {}".format(message.content)) + response = openai.Image.create( + prompt=message.content, n=1, size="1024x1024" ) + image_url = response["data"][0]["url"] + logger.debug("Wynikowy obrazek pod url: {}".format(image_url)) + response = requests.get(image_url) + file = response.content - logger.info(response) - image_url = response.data[0].url - logger.debug("Wynikowy obrazek pod url: %s", image_url) - response = requests.get(image_url, timeout=360) + file_name = message.content + ".png" + if platform == "linux" or platform == "linux2": + file_name = ( + "/home/pi/RetroPie/Conjurer_graphics" + message.content + ".png" + ) + elif platform == "win32": + file_name = message.content + ".png" - temp_file_name = message.content + ".png" - temp_file_name = GRAPHICS_PATH + message.content + ".png" - - with open(temp_file_name, "wb") as dalle_file: - dalle_file.write(response.content) + with open(file_name, "wb") as f: + f.write(response.content) logger.info("Koniec procedury obrazkowej.") - fnord = discord.File( - temp_file_name, spoiler=False, description=message.content - ) + fnord = discord.File(file_name, spoiler=False, description=message.content) await message.reply(file=fnord) # *=========================================== Define Functions -def num_tokens_from_string(message, model): - """ - The function takes a string message and a model as input and returns the number of tokens in the - message according to the given model. - - :param message: A string containing the message or text from which you want to count the number of - tokens - :param model: The model parameter refers to a language model or tokenizer that can be used to - tokenize the input string. It could be a pre-trained model or a custom tokenizer - """ - tokens_per_message = 3 - tokens_per_name = 1 - chat_gpt_encoding = tiktoken.encoding_for_model(model) - - num_tokens = 0 - num_tokens += tokens_per_message - for keys, values in message.items(): - num_tokens += len(chat_gpt_encoding.encode(values)) - if keys == "role": - num_tokens += tokens_per_name - num_tokens += 3 # every reply is primed with <|start|>assistant<|message|> - return num_tokens - - async def connect(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: - logger.info("Ctx and arg defined for connect") voice_channel = client.get_channel(1060349757349974066) - if client.voice_clients: - voice_client = client.voice_clients[0] - if voice_client.is_connected(): + voiceClient = client.voice_clients[0] + if voiceClient.is_connected(): return - voice_channel_connection = await voice_channel.connect() - if not voice_channel_connection: - logger.error("Not possible to connect to voice") + vc = await voice_channel.connect() logger.info("Connecting to voice") async def disconnect(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: - logger.info("Ctx defined for disconnect") if client.voice_clients: - voice_client = client.voice_clients[0] - if voice_client.is_connected(): - await voice_client.disconnect() + voiceClient = client.voice_clients[0] + if voiceClient.is_connected(): + await voiceClient.disconnect() async def play(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. + # TODO: Jeśli w metadanych jest tylko "audiotrack" i "album" też po folderze. Jeśli są niekompletne uzupełnić dalej. logger.info("Play procedure") - if arg: - logger.info("Arg defined for play") + voiceClient = client.voice_clients[0] file_to_play = None - voice_client = client.voice_clients[0] if not client.voice_clients: - voice_client = client.voice_clients[0] - await connect(ctx) + voiceClient = client.voice_clients[0] + if not voiceClient.is_connected(): + await connect(ctx) + global MUZYKA if MUZYKA["queue"]: file_to_play = MUZYKA["queue"].pop() - zamawial = MUZYKA["requester"].pop() - logger.info("Muzyka z listy zamówień") + zamawial = MUZYKA["requestor"].pop() else: index = random.randint(0, len(music_file_list) - 1) file_to_play = music_file_list[index] - logger.info("Muzyka losowo") - logger.info(file_to_play) + logger.debug(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 platform == "linux" or platform == "linux2": + separator = "/" + elif platform == "win32": + separator = "\\" + temp = file_to_play.split(separator)[-1] + kawalek = "Zagram teraz kawalek {} z prywatnej kolekcji Hammera.".format(temp) 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}" + query = "Opowiedz mi o kawałku {}".format(metadata.tag.title) + kawalek = "Zagram teraz kawalek {}".format(metadata.tag.title) if metadata.tag.artist: - query += f" wykonawcy {metadata.tag.artist}" - kawalek += f" wykonawcy {metadata.tag.artist}" + query += " wykonawcy {}".format(metadata.tag.artist) + kawalek += " wykonawcy {}".format(metadata.tag.artist) if metadata.tag.album: - query += f" z albumu {metadata.tag.album}" - kawalek += f" z albumu {metadata.tag.album}" + query += " z albumu {}".format(metadata.tag.album) + kawalek += " z albumu {}".format(metadata.tag.album) kawalek += " z prywatnej kolekcji Hammera." if zamawial: - kawalek += f"Na specjalne życzenie <@{zamawial.id}>." + kawalek += "Na specjalne życzenie <@{}>.".format(zamawial.id) await ctx.send(kawalek) - voice_client.play( + voiceClient.play( discord.PCMVolumeTransformer( - discord.FFmpegPCMAudio(source=file_to_play), volume=0.3 + discord.FFmpegPCMAudio(source=file_to_play), volume=0.15 ) ) # NIE DOTYKAC POKRĘTŁA GŁOŚNOŚCI!!!! if query: @@ -480,231 +316,75 @@ async def play(ctx, zamawial=None, arg=None): username = ctx.message.author.nick else: username = ctx.message.author.name - global MESSAGE_TABLE # pylint: disable=global-statement - result, MESSAGE_TABLE = await handle_response( + global message_table + result, message_table = await handle_response( query, vykidailo, bartender, message_table_muzyka, username, True ) - logger.debug("Obecna historia czatu: %s", message_table_muzyka) + logger.debug("Obecna historia czatu:{}".format(message_table_muzyka)) await ctx.send(result) -async def archive_channel(channel_no): - """ - The function `archive_channel` retrieves messages from a specified channel, processes them, and - saves the data in a JSON file with a timestamp in the filename. - - :param channel_no: The `archive_channel` function you provided seems to be incomplete. It looks like - you are trying to archive messages from a Discord channel into a JSON file - """ - channel = client.get_channel(channel_no) - messages = [message async for message in channel.history(limit=None)] - path_newfile = f"{LOGSTORE}channeldump_{channel_no}_{datetime.now()}.json" - new_data = [] - for message in messages: - new_data.append(message) - with open(path_newfile, "x", encoding=ENCODING) as new_file: - new_file.seek(0) - json.dump(new_data, new_file, indent=4) - - -@tasks.loop(seconds=1) -async def check_music(): - """ - This Python function continuously checks for music playback in a voice client and plays music if - conditions are met. - """ - if client.voice_clients: - voice_client = client.voice_clients[0] - if voice_client.is_connected(): - while MUZYKA["playing"] and voice_client.is_connected(): - if ( - voice_client - and not voice_client.is_playing() - and not voice_client.is_paused() - ): - await play(MUZYKA["ctx"], MUZYKA["requester"]) - await asyncio.sleep(1) - - -@tasks.loop(minutes=2) -async def check_data(): - """ - The function `check_data` periodically checks for conditions to send messages and manage log files - in a Discord channel. - """ - last_spontaneous_call = datetime.now() - tdelta = datetime.now() - last_spontaneous_call - tdelta = tdelta.total_seconds() - if tdelta > 34000: - channel = client.get_channel(1062047571557744721) - last_spontaneous_call = datetime.now() - with channel.typing(): - message = get_random_cyclic_message() - await channel.send(message) - # trunk-ignore(codespell/misspelled) - # TODO: dlaczego sie tu wypierdala - if os.path.getsize(LOGFILE) > 600000: - shutil.copyfile(LOGFILE, f"{LOGSTORE}discord{datetime.now()}") - logger.info("Log rollover") - handler.doRollover() - - if os.path.getsize(MEMORY_FIVE_MUZYKA) > 300000: - channel = client.get_channel(1062047571557744721) - await channel.send( - "*Conjurer porządkuje bar, wypala szklanki do czysta miotaczem płomieni ze swojej zbroi i ogólnie wygląda na zajętego....*" - ) - with channel.typing(): - path_newfile = f"{LOGSTORE}{MEMORY_FIVE_MUZYKA[:-4]}{datetime.now()}.json" - with open(MEMORY_FIVE_MUZYKA, "r+", encoding=ENCODING) as file_music_memory: - with open(path_newfile, "x", encoding=ENCODING) as new_file: - # First we load existing data into a dict. - file_data = json.load(file_music_memory) - new_data = [] - new_data.append(file_data[0]) - new_data.extend(file_data[:-20]) - file_music_memory.seek(0) - # convert back to json. - new_file.seek(0) - json.dump(new_data, file_music_memory, indent=4) - json.dump(file_data, new_file, indent=4) - await channel.send( - "*Przeciąga się za barem* No dobra - porobione to można dalej pi... *Zauważa spojrzenie Hammera* ...sać powieści o naszym wspaniałym barze SZEFIE!" - ) - if os.path.getsize(MEMORY_FIVE_SIARA) > 300000: - path_newfile = "{LOGSTORE}{MEMORY_FIVE_SIARA[:-4]}{datetime.now()}.json" - await channel.send( - "*Conjurer porządkuje bar, ścina lekkim laserem pulsacyjnym powierzchnie baru o grubości kilku mikronów i ogólnie wygląda na zajętego....*" - ) - with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as file: - with open(path_newfile, "x", encoding=ENCODING) as new_file: - # First we load existing data into a dict. - file_data = json.load(file) - new_data = [] - new_data.append(file_data[0]) - new_data.extend(file_data[:-20]) - file.seek(0) - new_file.seek(0) - # convert back to json. - json.dump(new_data, file, indent=4) - json.dump(file_data, new_file, indent=4) - await channel.send( - "*Przeciąga się za barem* No dobra - porobione to można dalej pi... *Zauważa spojrzenie Hammera* eprzyć o głupotach z klientami... Szefie... *Bierze 'ukradkowy' łyk z piersiówki*" - ) - await asyncio.sleep(60) - - -async def get_random_cyclic_message(): - """ - The function `get_random_cyclic_message` returns a random cyclic message from a list of cyclic - words. - :return: a random cyclic message from the list `cyclic_words`. - """ - messnum = random.randint(0, len(cyclic_words) - 1) - return cyclic_words[messnum][0] +async def check(): + while True: + # TODO: Tu dołożyć skanowanie rozmiaru pliku logowania oraz plików pamięci i przenoszenie ich na większy dysk. + # TODO: Dodać typing i dać znać że wykonuje operacje porządkowania Baru (zamiata, układa szklanki itp.) + # TODO: dlaczego sie tu wypierdala + if client.voice_clients: + voiceClient = client.voice_clients[0] + if voiceClient.is_connected(): + global MUZYKA + while MUZYKA["playing"]: + await asyncio.sleep(10) + if not voiceClient.is_playing() and not voiceClient.is_paused(): + await play(MUZYKA["ctx"], MUZYKA["requestor"]) + if os.path.getsize(logfile) > 600000: + shutil.copyfile(logfile,"{}discord{}.log".format(logstore, datetime.now())) + logger.info("Log rollover") + handler.doRollover() + await asyncio.sleep(60) async def handle_response(prompt, vykidailo, bartender, history, username, music): - """ - Handle responses by appending them to a history, use OpenAI to - generate a response, and then append the generated response to the history. - - :param prompt: The prompt for the OpenAI chatbot to generate a response to - :param vykidailo: It is a boolean variable that indicates whether the user invoking the function is - an administrator or not - :param bartender: The bartender parameter is a boolean value indicating whether the user making the - request is a bartender or not - :param history: A list containing the conversation history between the user and the assistant - :param username: The username of the user who initiated the conversation - :param music: The "music" parameter is a boolean value that indicates whether the conversation is - related to music or not. If it is True, the conversation history will be stored in a different file - and the response will be generated using a different model - :return: The function `handle_response` returns a tuple containing the `result` and `MESSAGE_TABLE`. - """ # TODO: Wykrywać "Pracuję nad odpowiedzią i tego typu rzeczy" - logger.info("Wywolanie procedury openai z promptem: %s", prompt) + logger.info("Wywolanie procedury openai z promptem: {}".format(prompt)) temp = {"role": "user", "content": username + ":" + prompt} - if vykidailo or bartender: - logger.info("Administrator coś chciał") + history.append(temp) if music: - with open(MEMORY_FIVE_MUZYKA, "r+", encoding=ENCODING) as file_music_memory: + with open(memory_five_muzyka, "r+") as file: # First we load existing data into a dict. - file_data = json.load(file_music_memory) + file_data = json.load(file) # Join new_data with file_data inside emp_details file_data.append(temp) - file_music_memory.seek(0) + file.seek(0) # convert back to json. - json.dump(file_data, file_music_memory, indent=4) + json.dump(file_data, file, indent=4) else: - with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as file_memory: + with open(memory_five_siara, "r+") as file: # First we load existing data into a dict. - file_data = json.load(file_memory) + file_data = json.load(file) # Join new_data with file_data inside emp_details file_data.append(temp) - file_memory.seek(0) + file.seek(0) # convert back to json. - json.dump(file_data, file_memory, indent=4) + json.dump(file_data, file, indent=4) history = [] - history.append(GPT_SETTINGS[0]) - chat_gpt_config_request_size = num_tokens_from_string(GPT_SETTINGS[0], "gpt-4") - - for slowo, reakcja in word_reactions.items(): - if not reakcja[3]: - content = ( - "Kiedy słyszysz " - + slowo - + " to reagujesz lub dzieje się to " - + reakcja[0] - ) - temp = {"role": "system", "content": content} - chat_gpt_config_request_size += num_tokens_from_string(temp, "gpt-4") - history.append(temp) - - final_prompt = username + ":" + prompt - logger.info( - "Rozmiar zapytania przed dodaniem historii %s", chat_gpt_config_request_size - ) + # * append bo pierwszy index + # * extend bo 20 ostatnich if music: - algorithm = "gpt-3.5-turbo-0125" - table = message_table_muzyka - token_amount = 10700 + history.append(message_table_muzyka[0]) + history.extend(message_table_muzyka[-20:]) else: - table = MESSAGE_TABLE - algorithm = "gpt-4" - token_amount = 7000 - - prompt_gpt_request_size = num_tokens_from_string( - {"role": "user", "content": final_prompt}, "gpt-4" - ) - temptable = [] - for i in reversed(table): - temp_token = num_tokens_from_string(i, "gpt-4") - logger.info( - "Rozmiar zapytania %s prompt %s temp %s", - chat_gpt_config_request_size, - prompt_gpt_request_size, - temp_token, - ) - if ( - chat_gpt_config_request_size - < token_amount + prompt_gpt_request_size + temp_token - ): - temptable.insert(1, i) - chat_gpt_config_request_size += temp_token - history.extend(temptable) - temp = {"role": "user", "content": final_prompt} - history.append(temp) - logger.info("Rozmiar zapytania po wyslaniu %s", chat_gpt_config_request_size) - response = await openAIClient.chat.completions.create( - model=algorithm, messages=history - ) - + history.append(message_table[0]) + history.extend(message_table[-20:]) logger.info("Historia wysłana:") - logger.info(history) - await asyncio.sleep(15) + logger.debug(history) + response = await openai.ChatCompletion.acreate( + model="gpt-3.5-turbo", messages=history + ) + await asyncio.sleep(10) result = "" logger.debug("Odpowiedzi") - logger.info(response) logger.debug(response.choices) for choice in response.choices: result += choice.message.content @@ -713,7 +393,7 @@ async def handle_response(prompt, vykidailo, bartender, history, username, music temp = {"role": "assistant", "content": result} history.append(temp) if music: - with open(MEMORY_FIVE_MUZYKA, "r+", encoding=ENCODING) as file: + with open(memory_five_muzyka, "r+") as file: # First we load existing data into a dict. file_data = json.load(file) # Join new_data with file_data inside emp_details @@ -723,7 +403,7 @@ async def handle_response(prompt, vykidailo, bartender, history, username, music # convert back to json. json.dump(file_data, file, indent=4) else: - with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as file: + with open(memory_five_siara, "r+") as file: # First we load existing data into a dict. file_data = json.load(file) # Join new_data with file_data inside emp_details @@ -732,27 +412,13 @@ async def handle_response(prompt, vykidailo, bartender, history, username, music file.seek(0) # convert back to json. json.dump(file_data, file, indent=4) - return result, MESSAGE_TABLE + return result, message_table async def get_file(ctx, source, link): - """ - Take in three parameters: "ctx" (context), - "source" (a string representing the source of the file), and "link" (a string representing the link - to the file). Execute it in asynchronouse way. And get file from spotify or youtube. - - :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 - :param source: The source parameter is likely a string that represents the source of the file that - the user wants to retrieve. This could be a website, a cloud storage service, or any other location - where the file is stored - :param link: The "link" parameter is likely a string that represents a URL or file path to the - location of the file that the function is trying to retrieve - """ item_id = None item_type = None - file_list = [] + file_list = {} if source == "Spotify": dir_path = None item_type, item_id = spotify.parse_spotify_url(link) @@ -762,7 +428,7 @@ async def get_file(ctx, source, link): url_data = {"urls": []} url_dict = {} url_dict["save_path"] = Path( - PurePath.joinpath(Path(MUSIC_FOLDER), Path(directory_name)) + PurePath.joinpath(Path(music_folder), Path(directory_name)) ) url_dict["save_path"].mkdir(parents=True, exist_ok=True) url_dict["songs"] = file_list @@ -770,7 +436,7 @@ async def get_file(ctx, source, link): file_name_f = youtube_download.default_filename youtube_download.download_songs( songs=url_data, - output_dir=MUSIC_FOLDER, + output_dir=music_folder, format_str="bestaudio/best", skip_mp3=False, keep_playlist_order=False, @@ -785,11 +451,11 @@ async def get_file(ctx, source, link): if platform == "win32": dir_path = dir_path.replace("/", "\\") return dir_path, file_list - - await ctx.send( - "No se jaja chyba robisz, Ty byś spotifaja nie poznawszy jakby z krzaków wyskoczył i w dupę kopnął. Plejlista, kawałek albo album prosze." - ) - logger.error("Wrong link provided spotify: %s", link) + else: + await ctx.send( + "No se jaja chyba robisz, Ty byś spotifaja nie poznawszy jakby z krzaków wyskoczył i w dupę kopnął. Plejlista, kawałek albo album prosze." + ) + logger.error("Wrong link provided spotify: {}".format(link)) elif source == "Youtube": link_ok = False pat = r"^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$" @@ -812,7 +478,7 @@ async def get_file(ctx, source, link): }, ] if platform == "win32": - dir_path = "G:\\Muzyka\\Youtube" + dir_path = "G:\\Muzyka\Youtube" else: dir_path = "/home/pi/RetroPie/mp3/Youtube" ydl_opts = { @@ -833,122 +499,46 @@ async def get_file(ctx, source, link): with yt_dlp.YoutubeDL(ydl_opts) as ydl: try: ydl.download([query]) - except Exception as exce: # pylint: disable=broad-exception-caught - logger.error(exce) + except Exception as e: # skipcq: PYL-W0703 + logger.error(e) logger.info( - "Failed to download %s, make sure yt_dlp is up to date", link + f"Failed to download {link}, make sure yt_dlp is up to date" ) extract = re.search("v=(...........)[&,$]*", link) - ident = extract.group(1) + id = extract.group(1) for item in Path.glob(Path(dir_path), "**/*.mp3"): file = item.as_posix() if platform == "win32": file = file.replace("/", "\\") - if re.match(".*" + ident + ".*", file): + if re.match(".*" + id + ".*", file): file_list.append(file) return dir_path, file_list - await ctx.send( - "No se jaja chyba robisz, Ty byś jutuba nie poznawszy jakby z krzaków wyskoczył i w dupę kopnął. Jutuba to nie tuba którą sobie można gdzieś wsadzić." - ) - logger.error("Wrong link provided youtube: %s", link) - return "", None + else: + await ctx.send( + "No se jaja chyba robisz, Ty byś jutuba nie poznawszy jakby z krzaków wyskoczył i w dupę kopnął. Jutuba to nie tuba którą sobie można gdzieś wsadzić." + ) + logger.error("Wrong link provided youtube: {}".format(link)) + return "", None -# define an asynchronous generator -async def async_iterator_generator(range_of_iterable): - """ - Generate asynchronouse iterator. - This is an incomplete function definition for an asynchronous iterator generator that takes a range - of iterable as input. - - :param range_of_iterable: The parameter `range_of_iterable` is likely a range or iterable object - that the async iterator generator will iterate over asynchronously. It could be a list, tuple, set, - or any other iterable object. The generator will yield each item in the iterable object - asynchronously, allowing other code to run in between - """ - # normal loop - for i in range_of_iterable: - # pylint: disable=pointless-string-statement - # yield the result - yield i - """ - Alternatywna wersja przerobienia fora na asynchroniczny. - # traverse the iterable of awaitables - for item in coros: - # await and get the result from the awaitable - result = await item - # report the results - print(result) - """ - - -async def get_stats(ctx, history_limit): - """ - The `get_stats` function retrieves the message history of a specific channel and counts the - frequency of each word in the messages. - - :param ctx: The `ctx` parameter is an object that represents the context of the command being - executed. It contains information such as the message, the author, the server, and other relevant - details - :param history_limit: The `history_limit` parameter is the maximum number of messages to retrieve - from the channel history. It determines how far back in time the statistics will be calculated - :return: The function `get_stats` returns a dictionary `stats` that contains the frequency count of - words found in the messages from the specified channel. - """ - channel_id = 1062047367337095268 - async with ctx.typing(): - stats = {} - channel = client.get_channel(channel_id) - messages = [message async for message in channel.history(limit=history_limit)] - # traverse the iterable of awaitables - for message in messages: - # await and get the result from the awaitable - result = message.content - words = result.split() - for word in words: - if word in stats: - stats[word] += 1 - else: - stats[word] = 1 - for name, how_many in stats.items(): - yield name, how_many - - -async def wyszukaj(ctx, how_many=0, slowa_kluczowe=None): - """ - Take in a context object and an optional integer parameter "how_many" and perform search - operation on music library. - - :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 - :param how_many: how_many is a parameter that specifies the number of search results to be returned. - It is an optional parameter with a default value of 0, which means that if no value is provided for - how_many, the function will return all search results, defaults to 0 (optional) - """ - # TODO: Potem dorobić wyszukiwania po kawałkach słów - # i sieć neuronową z możliwością wyrażenia opinii o dopasowaniu. - if slowa_kluczowe: - word_list = slowa_kluczowe - else: - word_list = ctx.message.content.split() +async def wyszukaj(ctx, how_many=0): + # TODO: Potem dorobić wyszukiwania po kawałkach słów i sieć neuronową z możliwością wyrażenia opinii o dopasowaniu. + word_list = ctx.message.content.split() logger.info("Wyszukuje") + global music_file_list search_weight = [] - for _ in range(len(music_file_list)): + for i in range(len(music_file_list)): search_weight.append((0, "")) time_start = datetime.now() - if int(how_many) > 0: - skip_start = 2 - else: - skip_start = 1 - async for word in async_iterator_generator(word_list[skip_start:]): + for word in word_list[1:]: token_weight = len(word) - logger.info("Słowo kluczowe: %s", word) itr = 0 - async for file in async_iterator_generator(music_file_list): - file = file.split(SEPARATOR_FILE_PATH) - + for file in music_file_list: + if platform == "win32": + file = file.split("\\") + else: + file = file.split("/") char_remove = [ ".", "^", @@ -961,7 +551,6 @@ async def wyszukaj(ctx, how_many=0, slowa_kluczowe=None): "[", "]", "\\", - "/", "|", "(", ")", @@ -972,19 +561,20 @@ async def wyszukaj(ctx, how_many=0, slowa_kluczowe=None): "mp3", ] all_words = [] - async for f_iter in async_iterator_generator(file): - async for char in async_iterator_generator(char_remove): - f_iter = await remove_characters(f_iter, char) - tmp = f_iter.split() + for f in file: + for char in char_remove: + f = f.replace(char, "") + tmp = f.split() all_words.extend(tmp) pingu = 1 pattern_len = len(all_words) + plapka = False if platform == "win32": skip = 2 else: skip = 4 matched_times = 1 - async for itm in async_iterator_generator(all_words[skip:]): + for itm in all_words[skip:]: pingu += 1 pattern = ".*" + word + ".*" if re.match(pattern, itm, re.IGNORECASE): @@ -993,10 +583,14 @@ async def wyszukaj(ctx, how_many=0, slowa_kluczowe=None): + (token_weight + (pingu**1.5) / pattern_len) / matched_times ) search_weight[itr] = temp_weight, music_file_list[itr] + matched_times += 1 itr += 1 + await asyncio.sleep(1e-3) - logger.info("Stworzylem tablice wag zajęło mi to %s", datetime.now() - time_start) + logger.info( + "Stworzylem tablice wag zajęło mi to {}".format(datetime.now() - time_start) + ) time_start = datetime.now() item_to_search = await max_weight(search_weight) itr = 0 @@ -1006,63 +600,45 @@ async def wyszukaj(ctx, how_many=0, slowa_kluczowe=None): return_list = [] if int(how_many) <= 0: logger.info("Jeden plik do zagrania") + while not_found: if search_weight[itr][0] == item_to_search: - return_list.append(search_weight[itr]) + return_list.append(search_weight[itr][1]) return return_list itr += 1 else: logger.info("Wiele plików do zagrania") - search_weight.sort(key=lambda x: x[0], reverse=True) - return_list.extend(search_weight[: int(how_many)]) - return return_list + for i in range(int(how_many)): + item_to_search = await max_weight(search_weight) + while not_found: + if search_weight[itr][0] == item_to_search: + return_list.append(search_weight[itr][1]) + search_weight.remove(search_weight[itr]) + itr = 0 + logger.info("Zajęło mi to {}".format(datetime.now() - time_start)) + item_to_search = await max_weight(search_weight) + else: + itr += 1 + if await max_weight(search_weight) < 5: + return return_list + if len(return_list) >= int(how_many): + logger.info("Zajęło mi to {}".format(datetime.now() - time_start)) + return return_list -async def remove_characters(string, character): - """ - The `remove_characters` function removes all occurrences of a specified character from a given - string. - - :param string: The string parameter is the input string from which characters will be removed - :param character: The character parameter is the character that you want to remove from the string - :return: a new string where all occurrences of the specified character have been removed. - """ - return string.replace(character, "") - - -async def max_weight(lista): - """ - Take a list of weights and return the maximum weight. - - :param lista: It seems like the parameter `lista` is a list of items, possibly representing weights. - The function name `max_weight` suggests that the function is intended to find the maximum weight - from the list. However, without more context or information about the problem, it's difficult to say - for sure what the - """ - maximum_weight = 0 - for iterator in lista: - if iterator[0] > maximum_weight: - maximum_weight = iterator[0] - return maximum_weight +async def max_weight(list): + max_weight = 0 + for iter in list: + if iter[0] > max_weight: + max_weight = iter[0] + return max_weight # *=========================================== Define Commands -@client.hybrid_command( - name="dej_co_ze_spotifaja", - description="Podaj link do spotify - sciagnie i doda muzyke", - guild=discord.Object(id=664789470779932693), -) +@client.command() async def dej_co_ze_spotifaja(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 - """ logger.info("Spotifaj") await ctx.send("Dej mnie chwilkę") async with ctx.typing(): @@ -1076,7 +652,7 @@ async def dej_co_ze_spotifaja(ctx): else: separator = "/" for file in files: - global MUZYKA # pylint: disable=global-variable-not-assigned + global MUZYKA MUZYKA["queue"].insert( 0, dir_path @@ -1086,68 +662,49 @@ async def dej_co_ze_spotifaja(ctx): + file["name"] + ".mp3", ) - MUZYKA["requester"].insert(0, ctx.author) + MUZYKA["requestor"].insert(0, ctx.author) music_file_list.append(file) await ctx.send( - f"Dodałem do listy {dir_path}{file['artist']} - + {file['name']}.mp3" + "Dodałem do listy {}".format( + dir_path + file["artist"] + " - " + file["name"] + ".mp3" + ) ) logger.info("Spotifaj udany") -@client.hybrid_command( - name="dej_co_z_jutuba", - description="Podaj link do youtube - sciagnie i doda muzyke", - guild=discord.Object(id=664789470779932693), -) +@client.command() async def dej_co_z_jutuba(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ę") 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 get_file(ctx, "Youtube", item_yt) + for item in content: + if re.match("http.*", item): + dir_path, files = await get_file(ctx, "Youtube", item) + if platform == "win32": + separator = "\\" + else: + separator = "/" if files: - for file_iter in files: - global MUZYKA # pylint: disable=global-variable-not-assigned - MUZYKA["queue"].insert(0, file_iter) - music_file_list.append(file_iter) - MUZYKA["requester"].insert(0, ctx.author) - await ctx.send(f"Dodałem do listy {file_iter}") + for file in files: + global MUZYKA + MUZYKA["queue"].insert(0, file) + music_file_list.append(file) + MUZYKA["requestor"].insert(0, ctx.author) + await ctx.send("Dodałem do listy {}".format(file)) logger.info("Jutub udany") -@client.hybrid_command( - name="update_banlist", - description="Jeśli nie wiesz jak użyć tej komendy to nawet nie próbuj", - guild=discord.Object(id=664789470779932693), -) -async def update_banlist(ctx): - """ - Update a banlist in a Discord guild from preprovided list in channel. - - :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.channel.typing(): +@client.command() +async def update_banlist(ctx, arg=None): + async with channel.typing(): allowed = False for role in ctx.author.roles: if role.name == "Jarl": allowed = True if ctx.channel.id != 1102190666827702342: - # trunk-ignore(codespell/misspelled) await ctx.send("Nie wydaje mnie sie") elif not allowed: await ctx.send("Idź bo Cię zdziele") @@ -1161,37 +718,30 @@ async def update_banlist(ctx): for message in messages: lines = message.content.split("\n") for line in lines: - match = re.search( - "\\d{18}", - line, - # trunk-ignore(codespell/misspelled) - ) # poprawilem backslash na podwojny bo linter sie czepial + match = re.search("\d{18}", line) if match: ids_to_ban.append(match.group()) tobancunter += 1 - # 2. get list of already banned users for all servers Conjurer - # has rights to + # 2. get list of already banned users for all servers Conjurer has rights to for guild in client.guilds: bancunter = 0 - # trunk-ignore(codespell/misspelled) - logger.info("Serwer: %s", guild) + logger.info("Serwer:{}".format(guild)) current_banlist = [] permission = True try: async for entry in guild.bans(limit=None): current_banlist.append(entry.user.id) bancunter += 1 - except BaseException: # pylint: disable=broad-exception-caught + except: permission = False if permission: - # 3. compare lists ban only users on list 2 and not on - # list 1 + # 3. compare lists ban only users on list 2 and not on list 1 cunter_counter = 0 bad_id_cunter_counter = 0 ban_list = np.setdiff1d(ids_to_ban, current_banlist) - for ident in ban_list: + for id in ban_list: try: - tmp_user = await client.fetch_user(int(ident)) + tmp_user = await client.fetch_user(int(id)) await guild.ban( tmp_user, reason="Automatyczna lista banów", @@ -1205,78 +755,63 @@ async def update_banlist(ctx): bad_id_cunter_counter += 1 # 4. return message success/failure - how many banned await ctx.send( - "Obecnie na serwerze {guild} jest {bancunter} zbanowanych użytkowników. Znaleziono na tym kanale {tobancunter} id użytkowników do zbanowania. Zbanowano {cunter_counter} użytkowników. Na liście jest {bad_id_cunter_counter} użytkowników którzy skasowali już konto" + "Obecnie na serwerze {} jest {} zbanowanych użytkowników. Znaleziono na tym kanale {} id użytkowników do zbanowania. Zbanowano {} użytkowników. Na liście jest {} użytkowników którzy skasowali już konto".format( + guild, + bancunter, + tobancunter, + cunter_counter, + bad_id_cunter_counter, + ) ) else: await ctx.send( - f"Nie mam na serwerze {guild} uprawnień do banowania. :()" + "Nie mam na serwerze {} uprawnień do banowania. :()".format( + guild + ) ) await ctx.send("Zrobione tak czy inaczej") -@client.hybrid_command( - nsfw=True, - name="get_image_sadox", - description="Wyświetla losową stronę z losowego komiksu FanSadox. Bardzo NSFW.", - guild=discord.Object(id=664789470779932693), -) -async def get_image_sadox(ctx): - """ - Take in a context parameter and retrieve an image related from fansadox collection. - - :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. In this case, it is likely being used - to determine - """ +@client.command() +async def get_image_sadox(ctx, arg=None): logger.info("Get sadox") channel = ctx.message.channel async with channel.typing(): # select random file + if platform == "linux" or platform == "linux2": + dir_path = "/home/pi/RetroPie/Fansadox/" + elif platform == "win32": + dir_path = "C:\\Users\\mtusz\\OneDrive\\Dokumenty\Fansadox\\" res = [] # Iterate directory - for path in os.listdir(DIR_PATH_SADOX): + for path in os.listdir(dir_path): # check if current path is a file - if os.path.isfile(os.path.join(DIR_PATH_SADOX, path)): + if os.path.isfile(os.path.join(dir_path, path)): res.append(path) filename = res[random.randrange(0, len(res) - 1)] # select random page - file = open(DIR_PATH_SADOX + filename, "rb") + file = open(dir_path + filename, "rb") readpdf = PyPDF2.PdfReader(file) totalpages = len(readpdf.pages) page = random.randrange(1, totalpages) # convert page to image image = pdf2image.convert_from_path( - DIR_PATH_SADOX + filename, first_page=page, last_page=page + dir_path + filename, first_page=page, last_page=page ) - byte_io_stream = io.BytesIO() - image[0].save(byte_io_stream, "JPEG") - byte_io_stream.seek(0) - byte_io_stream.name = "image.jpg" - file = discord.File(byte_io_stream) + b = io.BytesIO() + image[0].save(b, "JPEG") + b.seek(0) + b.name = "image.jpg" + file = discord.File(b) await ctx.send(file=file) logger.info("Get sadox completed") -@client.hybrid_command( - name="graj_muzyko", - description="Włącza muzykę na kanale #nocna-zmiana.", - guild=discord.Object(id=664789470779932693), -) -async def graj_muzyko(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 - """ - +@client.command() +async def graj_muzyko(ctx, arg=None): logger.info("Press play on tape") - check_music.start() async with ctx.typing(): - global MUZYKA # pylint: disable=global-variable-not-assigned + global MUZYKA MUZYKA["playing"] = True MUZYKA["ctx"] = ctx await connect(ctx=ctx) @@ -1284,226 +819,126 @@ async def graj_muzyko(ctx): logger.info("Press play on tape completed") -@client.hybrid_command( - name="cisza", - description="Wyłącza muzykę i czyści plejliste.", - guild=discord.Object(id=664789470779932693), -) -async def cisza(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 - """ +@client.command() +async def cisza(ctx, arg=None): logger.info("Stop") - global MUZYKA # pylint: disable=global-variable-not-assigned + global MUZYKA MUZYKA["playing"] = False MUZYKA["ctx"] = None - voice_client = client.voice_clients[0] - if voice_client.is_connected(): + voiceClient = client.voice_clients[0] + if voiceClient.is_connected(): await disconnect(ctx=ctx) while MUZYKA["queue"]: MUZYKA["queue"].pop() - MUZYKA["requester"].pop() + MUZYKA["requestor"].pop() logger.info("Stop completed") - check_music.stop() -@client.hybrid_command( - name="dalej", - description="Przerzuca na następny kawałek", - guild=discord.Object(id=664789470779932693), -) -async def dalej(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: - logger.info("Ctx defined for dalej") +@client.command() +async def dalej(ctx, arg=None): logger.info("Next") - voice_client = client.voice_clients[0] - if voice_client.is_connected(): - voice_client.stop() + voiceClient = client.voice_clients[0] + if voiceClient.is_connected(): + voiceClient.stop() await play(ctx=ctx) logger.info("Next completed") -@client.hybrid_command( - name="daj_mi_chwile", - description="Pauzuje", - guild=discord.Object(id=664789470779932693), -) -async def daj_mi_chwile(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: - logger.info("Ctx defined for pause") - +@client.command() +async def daj_mi_chwile(ctx, arg=None): logger.info("Pause") - voice_client = client.voice_clients[0] - if voice_client.is_connected(): - voice_client.pause() + voiceClient = client.voice_clients[0] + if voiceClient.is_connected(): + voiceClient.pause() logger.info("Pause completed") -@client.hybrid_command( - name="graj_dalej", - description="Odpauzowuje", - guild=discord.Object(id=664789470779932693), -) -async def graj_dalej(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: - logger.info("Ctx defined for graj_dalej") +@client.command() +async def graj_dalej(ctx, arg=None): logger.info("Unpause") - voice_client = client.voice_clients[0] - if voice_client.is_paused(): - voice_client.resume() + voiceClient = client.voice_clients[0] + if voiceClient.is_paused(): + voiceClient.resume() logger.info("Unpause completed") -@client.hybrid_command( - name="zagraj_mi_kawalek", - description="Wyszukuje w bibliotece muzycznej Hammera kawałek który ma zostać zagrany", - guild=discord.Object(id=664789470779932693), -) -async def zagraj_mi_kawalek(ctx): - """ - Play a song or music piece in response to a command - triggered by a user in a Discord chat context. +@client.command() +async def zagraj_muzyke_mego_ludu(ctx, arg=None): + pass - :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 - """ + +@client.command() +async def zagraj_mi_kawalek(ctx, arg=None): async with ctx.typing(): search_time_glob = datetime.now() - logger.info("Zaczynam szukać timestamp %s", datetime.now()) + logger.info("Zaczynam szukać timestamp {}".format(datetime.now())) file = await wyszukaj(ctx=ctx) logger.info( - "Koniec szukania(timestamp %s zajęło %s", - datetime.now(), - datetime.now() - search_time_glob, + "Koniec szukania(timestamp {} zajęło {}".format( + 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." + global MUZYKA + MUZYKA["queue"].insert(0, plik) + MUZYKA["requestor"].insert(0, ctx.author) + metadata = eyed3.load(plik) + reply = "Dodałem do playlisty {} z prywatnej kolekcji Hammera.".format( + plik + ) if metadata.tag.title: - reply = f"Dodałem do playlisty kawalek {metadata.tag.title}" + reply = "Dodałem do playlisty kawalek {}".format(metadata.tag.title) if metadata.tag.artist: - reply += f" wykonawcy {metadata.tag.artist}" + reply += " wykonawcy {}".format(metadata.tag.artist) if metadata.tag.album: - reply += f" z albumu {metadata.tag.album}" + reply += " z albumu {}".format(metadata.tag.album) reply += " z prywatnej kolekcji Hammera i na Twoją specjalną rpośbę." - await ctx.send(reply) + await ctx.reply(reply) else: - await ctx.send( + await ctx.reply( "Obawiam się że nie mogę nic znaleźć u siebie. Spróbuj komendy '$dej_co_ze_spotifaja' jeśli masz link" ) -@client.hybrid_command( - name="zrob_mi_plejliste", - description="Generuje playliste - param1 - dlugosc, potem slowa wyszukiwania", - guild=discord.Object(id=664789470779932693), -) -async def zrob_mi_plejliste(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" +@client.command() +async def zrob_mi_plejliste(ctx, *arg): async with ctx.typing(): - logger.info("Zaczynam szukać timestamp %s", datetime.now()) + logger.info("Zaczynam szukać timestamp {}".format(datetime.now())) search_time_glob = datetime.now() - dlugosc_playlisty = ctx.message.content.split()[1] + dlugosc_playlisty = arg[0] file = await wyszukaj(ctx=ctx, how_many=dlugosc_playlisty) logger.info( - "Koniec szukania(timestamp %s zajęło %s", - datetime.now(), - datetime.now() - search_time_glob, + "Koniec szukania(timestamp {} zajęło {}".format( + 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 = "" + global MUZYKA + MUZYKA["queue"].insert(0, plik) + MUZYKA["requestor"].insert(0, ctx.author) + metadata = eyed3.load(plik) + reply = "Dodałem do playlisty {} z prywatnej kolekcji Hammera.".format( + plik + ) + if metadata.tag.title: + reply = "Dodałem do playlisty kawalek {}".format(metadata.tag.title) + if metadata.tag.artist: + reply += " wykonawcy {}".format(metadata.tag.artist) + if metadata.tag.album: + reply += " z albumu {}".format(metadata.tag.album) + reply += " z prywatnej kolekcji Hammera i na Twoją specjalną rpośbę." + await ctx.reply(reply) else: - await ctx.send( + await ctx.reply( "Obawiam się że nie mogę nic znaleźć u siebie. Spróbuj komendy '$dej_co_ze_spotifaja' jeśli masz link" ) - await ctx.send(reply) - logger.info("Plejlista zrobiona") -@client.hybrid_command( - name="przytul", description="Przytul kogoś - daj mention po komendzie :)" -) -async def przytul(ctx, arg: Optional[discord.Member] = None): - """ - Generate a text about hugging mentioned user. - - :param ctx: ctx stands for "context" and is a required parameter 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 - :param arg: arg is a parameter of the function "przytul" that expects a Discord member object. The - parameter is optional, meaning that if no member object is provided, it will default to None - :type arg: Optional[discord.Member] - """ +@client.command() +async def przytul(ctx, arg=None): async with ctx.typing(): nieprzytulac = False for mention in ctx.message.mentions: @@ -1513,278 +948,28 @@ async def przytul(ctx, arg: Optional[discord.Member] = None): if arg and nieprzytulac: await ctx.send( - f"Żebym ja Ciebie nie przytulił {ctx.message.author.mention}" + "Żebym ja Ciebie nie przytulił {}".format(ctx.message.author.mention) ) elif arg: await ctx.send( - # trunk-ignore(codespell/misspelled) - f"Już dobrze.... Już dobrze... Ojej.. Biedactwo... :( *W ułamku sekundy {arg.mention} znajduje sie w duszącym uścisku. Żebra trzeszczą - kilka pęka. Pacnięcia po plecach grożą odbiciem nerek, a głaskanie po głowie powoduje wstrząs mózgu*" + "Już dobrze.... Już dobrze... Ojej.. Biedactwo... :( *W ułamku sekundy {} znajduje sie w duszącym uścisku. Żebra trzeszczą - kilka pęka. Pacnięcia po plecach grożą odbiciem nerek, a głaskanie po głowie powoduje wstrząs mózgu*".format( + arg + ) ) else: + await ctx.message.add_reaction("\U0001fac2") await ctx.send( "Kogo mam przytulić? *Wyłamuje kostki i przeciąga się - jego 200 kilowa sylwetka złożona z samych mięśni świadczy o tym że jest gotowy*" ) -@client.hybrid_command(name="fabryczka", description="Historia fabryczki") -async def fabryczka(ctx): - """ - Send a general description of "fabryczkagate" to channel. +@client.command() +async def get_image_stable_diffusion(ctx, arg=None): + pass - :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. The context object provides a way to - interact with the Discord - """ - await ctx.send(historia_fabryczki) - - -@client.hybrid_command( - name="chata_hammera", - description="Czas od ostatniego incydentu w AbsinthHammerTimeSpaceContinuum", -) -async def chata_hammera(ctx): - """ - Send measured time from last incident in Hammer Fortress to the chat. - - :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 - """ - with open(ACCIDENT_LOG, "r+", encoding=ENCODING) as new_file: - # First we load existing data into a dict. - file_data = json.load(new_file) - opis = file_data[-1][0] - czas = datetime.strptime(file_data[-1][1], "%Y-%m-%d %H:%M:%S.%f") - await ctx.send( - f"Komenda mierząca incydenty w Eldritch AbsinthHammerTimeSpaceContinuum.\n Od ostatniego incydentu w chacie Hammera minęło {datetime.now() - czas}. Incydent to: {opis}" - ) - - -@client.hybrid_command( - name="historia_incydentow_u_hammera", - description="Wyswietla liste incydentów które miały miejsce w AbsinthHammerTimeSpaceContinuum.", -) -async def historia_incydentow_u_hammera(ctx): - """ - Send a list of incidents in Hammer Fortress to the chat. - - :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 - """ - with open(ACCIDENT_LOG, "r+", encoding=ENCODING) as new_file_accidents: - # First we load existing data into a dict. - file_data = json.load(new_file_accidents) - return_data = "Komenda mierząca incydenty w Eldritch AbsinthHammerTimeSpaceContinuum.\n Historia zarejestrownych incydentów u Hammera:\n" - index = 1 - for iter_data in file_data: - opis = iter_data[0] - czas = datetime.strptime(iter_data[1], "%Y-%m-%d %H:%M:%S.%f") - add_data = f"{index}. Opis: {opis} Data: {czas}" - return_data = return_data + add_data + "\n" - index += 1 - await ctx.send(return_data) - - -@client.hybrid_command( - name="reset_the_clock", - description="Resetowanie zegara - dostępne wyłącznie dla Hammera", - guild=discord.Object(id=664789470779932693), -) -async def reset_the_clock(ctx): - """ - Reset the clock on "accidents" in Hammer Fortress adding a new one. - - :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 - """ - hammer = False - for role in ctx.message.author.roles: - if role.name == "Bartender": - hammer = True - if hammer: - with open(ACCIDENT_LOG, "r+", encoding=ENCODING) as new_file_accidents: - # First we load existing data into a dict. - file_data = json.load(new_file_accidents) - czas = datetime.strptime(file_data[-1][1], "%Y-%m-%d %H:%M:%S.%f") - opis = ctx.message.content[16:] - accident = accident = [opis, f"{datetime.now()}"] - file_data.append(accident) - new_file_accidents.seek(0) - # convert back to json. - json.dump(file_data, new_file_accidents, indent=4) - await ctx.send( - f"Komenda mierząca incydenty w Eldritch AbsinthHammerTimeSpaceContinuum.\n RESET THE CLOCK. Od ostatniego incydentu w chacie Hammera minęło {czas}. No ale teraz się odpierdoliło: {opis}" - ) - else: - await ctx.send( - f"Komenda mierząca incydenty w Eldritch AbsinthHammerTimeSpaceContinuum.\n Gdzie z łapami do zegara? {client.get_user(346956223645614080).mention} coś albo się komuś stało albo zaraz się stanie jak będzie zegar tykał...." - ) - - -# @client.hybrid_command() -async def get_image_stable_diffusion(ctx): - """ - Connect to remote stable diffusion and generate an image. Retrieve the image. - - :param ctx: ctx is short for context and is typically used in Discord.py to represent the context in - which a command is being executed. It contains information such as the message, the channel, the - author, and other relevant data that can be used to perform actions or respond to the user. In this - case, it - """ - if ctx: - pass - - -@client.hybrid_command( - name="zagraj_muzyke_mego_ludu", - description="Gra muzyke wyszukana na bazie tematow konwersacji na kanale NZ", - guild=discord.Object(id=664789470779932693), -) -async def zagraj_muzyke_mego_ludu(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: - logger.info("Zagraj muzyke mego ludu: wywolane") - stat_iter = get_stats(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]) - logger.info("Zagraj muzyke mego ludu:zebrano statystyki") - key_words = [] - for stat in sorted_stats: - key_words.append(stat[0]) - logger.info(sorted_stats[:MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE]) - logger.info(key_words[:MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE]) - logger.info(sorted_stats[-MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE:]) - 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(): - logger.info("Zaczynam szukać timestamp %s", datetime.now()) - search_time_glob = datetime.now() - file = await wyszukaj( - ctx=ctx, - how_many=MUZYKA_MOJEGO_LUDU_PLAJLISTA, - slowa_kluczowe=final_key_words, - ) - logger.info("Zagraj muzyke mego ludu:wygenerowano plejliste") - logger.info(file) - logger.info( - "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) - logger.info("Plejlista zrobiona") - - -@client.hybrid_command( - name="parametry_muzyki_mego_ludu", - description="Konfiguruje komende zagraj muzyke mojego ludu", - guild=discord.Object(id=664789470779932693), -) -async def parametry_muzyki_mego_ludu( - 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 - 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 - 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"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") - logger.info(exce) +@client.command() +async def fabryczka(ctx, arg=None): + await ctx.message.reply(historia_fabryczki) # *================================== Run