# This Python file uses the following encoding: utf-8 #pylint: disable=too-many-lines #pylint: disable=line-too-long ''' Docstring ''' # *=========================================== Standard Library Imports import os import json import re import netrc import logging from logging import handlers from datetime import datetime import sys from sys import platform from platform import uname import io import random import asyncio from pathlib import PurePath from pathlib import Path import shutil # *==============Imported libraries import pdf2image import numpy as np import PyPDF2 import openai import requests import eyed3 import spotipy from spotipy.oauth2 import SpotifyClientCredentials import discord from discord.ext import commands from spotify_dl import spotify from spotify_dl import youtube as youtube_download import yt_dlp # *=========================================== Predefines formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") master_timeout = datetime.now() INITIAL_TIME_WAIT = 5 MUZYKA = {"playing": False, "ctx": None, "queue": [], "requestor": []} LOGFILE = "" NETRC_FILE = "" MUSIC_FOLDER = "" MEMORY_FIVE_SIARA = "" MEMORY_FIVE_MUZYKA = "" SETTINGS_FILE = "" ENCODING = "" GRAPHICS_PATH = "" # *=========================================== Platform Specific Predefines if platform in("linux","linux2"): if "microsoft-standard" in uname().release: 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/" ACCIDENT_LOG = "/home/pi/Conjurer/accident_log.json" ENCODING = "utf-8" GRAPHICS_PATH = "/home/pi/RetroPie/Conjurer_graphics/" else: 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/" ACCIDENT_LOG = "/home/pi/Conjurer/accident_log.json" ENCODING = "utf-8" GRAPHICS_PATH = "/home/pi/RetroPie/Conjurer_graphics/" elif platform == "win32": LOGFILE = "discord.log" MEMORY_FIVE_SIARA = "pamiec.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 = "cp1250" # *=========================================== Keys netrc = netrc.netrc(NETRC_FILE) REMOTE_HOST_NAME = "discord" authTokens = netrc.authenticators(REMOTE_HOST_NAME) TOKEN = authTokens[2] REMOTE_HOST_NAME = "openai" authTokens = netrc.authenticators(REMOTE_HOST_NAME) openai.api_key = authTokens[2] REMOTE_HOST_NAME = "spotipy" authTokens = netrc.authenticators(REMOTE_HOST_NAME) spotify_ctrl = spotipy.Spotify( client_credentials_manager=SpotifyClientCredentials( client_id=authTokens[0], client_secret=authTokens[2], ) ) # *=========================================== Initializations intents = discord.Intents.default() intents.message_content = True intents.typing = True intents.presences = True intents.members = True intents.messages = True intents.voice_states = True logger = logging.getLogger("discord") logger.setLevel(logging.DEBUG) handler = handlers.RotatingFileHandler( filename=LOGFILE, encoding=ENCODING, mode="a", maxBytes=6 * 1024 * 1024, backupCount=6, ) handler.setFormatter(formatter) logger.addHandler(handler) 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() if platform == "win32": temp_music_file = temp_music_file.replace("/", "\\") music_file_list.append(temp_music_file) with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as temp_memory_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) word_reactions = data["word_reactions"] 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(): """_summary_ """ logger.debug("%s has connected to Discord!", client.user) await client.change_presence(activity=discord.Game(name="Axe Throwing Darts")) await client.tree.sync() #await tree.sync(guild=discord.Object(id=Your guild id)) await check() @client.event async def on_message(message): """_summary_ Args: message (_type_): _description_ """ vykidailo = False channel = None if message.author == client.user: return if isinstance(message.author, discord.Member): for role in message.author.roles: if role.name == "Vykidailo": vykidailo = True if ("Conjurer Śpij Słodko Aniołku" in message.content) and vykidailo: sys.exit() # kanal bez bota 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) else: channel = message.channel await client.process_commands(message) # TODO: wpiac jego reakcje we framework chatu GPT message.content = message.content.lower() tdelta = datetime.now() - master_timeout tdelta = tdelta.total_seconds() if "opowiedz o fabryczce" in message.content: await message.reply(historia_fabryczki) if "opowiedz mi o fabryczce" in message.content: await message.reply(historia_fabryczki) if tdelta > INITIAL_TIME_WAIT: for word in word_reactions: if re.search(r"\b" + word + r"\b", 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 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: await message.reply(word_reactions[word][0]) word_reactions[word][2] = datetime.now() # TODO: drobne literówki, mentiony, spacja przed dwukropkiem. napraw. 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 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 ) 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 = openai.Image.create( prompt=message.content, n=1, size="1024x1024" ) image_url = response["data"][0]["url"] logger.debug("Wynikowy obrazek pod url: %s",image_url) response = requests.get(image_url, timeout=360) 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) logger.info("Koniec procedury obrazkowej.") fnord = discord.File(temp_file_name, spoiler=False, description=message.content) await message.reply(file=fnord) # *=========================================== Define Functions async def connect(ctx, arg=None): """_summary_ Args: ctx (_type_): _description_ arg (_type_, optional): _description_. Defaults to None. """ 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(): return voice_channel_connection = await voice_channel.connect() if not voice_channel_connection: logger.error("Not possible to connect to voice") logger.info("Connecting to voice") async def disconnect(ctx): """_summary_ Args: ctx (_type_): _description_ """ 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() async def play(ctx, zamawial=None, arg=None): """_summary_ Args: ctx (_type_): _description_ zamawial (_type_, optional): _description_. Defaults to None. arg (_type_, optional): _description_. Defaults to None. """ # 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. logger.info("Play procedure") if arg: logger.info("Arg defined for play") file_to_play = None voice_client = client.voice_clients[0] if not client.voice_clients: voice_client = client.voice_clients[0] await connect(ctx) if MUZYKA["queue"]: file_to_play = MUZYKA["queue"].pop() zamawial = MUZYKA["requestor"].pop() else: index = random.randint(0, len(music_file_list) - 1) file_to_play = music_file_list[index] logger.debug(file_to_play) metadata = eyed3.load(file_to_play) query = None separator = None if platform == "linux" or platform == "linux2": separator = "/" elif platform == "win32": separator = "\\" temp = file_to_play.split(separator)[-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: logger.debug("Zapytanie do openai") 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 # pylint: disable=global-statement result, MESSAGE_TABLE = await handle_response( query, vykidailo, bartender, message_table_muzyka, username, True ) logger.debug("Obecna historia czatu: %s",message_table_muzyka) await ctx.send(result) async def check(): """_summary_ """ 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: 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["requestor"]) await asyncio.sleep(0.1) 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 handle_response(prompt, vykidailo, bartender, history, username, music): """_summary_ Args: prompt (_type_): _description_ vykidailo (_type_): _description_ bartender (_type_): _description_ history (_type_): _description_ username (_type_): _description_ music (_type_): _description_ Returns: _type_: _description_ """ # TODO: Wykrywać "Pracuję nad odpowiedzią i tego typu rzeczy" logger.info("Wywolanie procedury openai z promptem: %s", 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: # First we load existing data into a dict. file_data = json.load(file_music_memory) # Join new_data with file_data inside emp_details file_data.append(temp) file_music_memory.seek(0) # convert back to json. json.dump(file_data, file_music_memory, indent=4) else: with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as file_memory: # First we load existing data into a dict. file_data = json.load(file_memory) # Join new_data with file_data inside emp_details file_data.append(temp) file_memory.seek(0) # convert back to json. json.dump(file_data, file_memory, indent=4) history = [] # * append bo pierwszy index # * extend bo 20 ostatnich if music: history.append(message_table_muzyka[0]) history.extend(message_table_muzyka[-20:]) else: history.append(MESSAGE_TABLE[0]) history.extend(MESSAGE_TABLE[-20:]) logger.info("Historia wysłana:") logger.debug(history) response = await openai.ChatCompletion.acreate( model="gpt-3.5-turbo", messages=history ) await asyncio.sleep(10) result = "" logger.debug("Odpowiedzi") logger.debug(response.choices) for choice in response.choices: result += choice.message.content logger.info("Sformatowane odpowiedzi") logger.info(result) temp = {"role": "assistant", "content": result} history.append(temp) if music: with open(MEMORY_FIVE_MUZYKA, "r+", encoding=ENCODING) as file: # First we load existing data into a dict. file_data = json.load(file) # Join new_data with file_data inside emp_details file_data.append(temp) # Sets file's current position at offset. file.seek(0) # convert back to json. json.dump(file_data, file, indent=4) else: with open(MEMORY_FIVE_SIARA, "r+",encoding=ENCODING) as file: # First we load existing data into a dict. file_data = json.load(file) # Join new_data with file_data inside emp_details file_data.append(temp) # Sets file's current position at offset. file.seek(0) # convert back to json. json.dump(file_data, file, indent=4) return result, MESSAGE_TABLE async def get_file(ctx, source, link): """_summary_ Args: ctx (_type_): _description_ source (_type_): _description_ link (_type_): _description_ Returns: _type_: _description_ """ item_id = None item_type = None file_list = {} if source == "Spotify": dir_path = None item_type, item_id = spotify.parse_spotify_url(link) if item_id: file_list = spotify.fetch_tracks(spotify_ctrl, item_type, link) directory_name = spotify.get_item_name(spotify_ctrl, item_type, item_id) url_data = {"urls": []} url_dict = {} url_dict["save_path"] = Path( PurePath.joinpath(Path(MUSIC_FOLDER), Path(directory_name)) ) url_dict["save_path"].mkdir(parents=True, exist_ok=True) url_dict["songs"] = file_list url_data["urls"].append(url_dict.copy()) file_name_f = youtube_download.default_filename youtube_download.download_songs( songs=url_data, output_dir=MUSIC_FOLDER, format_str="bestaudio/best", skip_mp3=False, keep_playlist_order=False, no_overwrites=True, remove_trailing_tracks="no", use_sponsorblock="yes", file_name_f=file_name_f, multi_core=0, proxy="", ) dir_path = (url_dict["save_path"].resolve()).as_posix() if platform == "win32": dir_path = dir_path.replace("/", "\\") return dir_path, file_list 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: %s",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()@:%_\+.~#?&\/=]*)$" if re.match(pat, link) and re.match(".*youtube.*", link): link_ok = True if link_ok: dir_path = "" file_list = [] query = link sponsorblock_postprocessor = [ { "key": "SponsorBlock", "categories": ["skip_non_music_sections"], }, { "key": "ModifyChapters", "remove_sponsor_segments": ["music_offtopic"], "force_keyframes": True, }, ] if platform == "win32": dir_path = "G:\\Muzyka\\Youtube" else: dir_path = "/home/pi/RetroPie/mp3/Youtube" ydl_opts = { "proxy": "", "default_search": "ytsearch", "format": "bestaudio/best", "postprocessors": sponsorblock_postprocessor, "noplaylist": True, "no_color": False, "paths": {"home": dir_path}, } mp3_postprocess_opts = { "key": "FFmpegExtractAudio", "preferredcodec": "mp3", "preferredquality": "192", } ydl_opts["postprocessors"].append(mp3_postprocess_opts.copy()) with yt_dlp.YoutubeDL(ydl_opts) as ydl: try: ydl.download([query]) except Exception as exce: #pylint: disable=broad-exception-caught logger.error(exce) logger.info( "Failed to download %s, make sure yt_dlp is up to date", link ) extract = re.search("v=(...........)[&,$]*", link) ident = 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): file_list.append(file) return dir_path, file_list 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: %s",link) return "", None # define an asynchronous generator async def async_iterator_generator(range_of_iterable): # pylint: disable=pointless-string-statement """_summary_ Args: range (_type_): _description_ Yields: _type_: _description_ """ # normal loop for i in range_of_iterable: # 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 wyszukaj(ctx, how_many=0): """_summary_ Args: ctx (_type_): _description_ how_many (int, optional): _description_. Defaults to 0. Returns: _type_: _description_ """ # 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") search_weight = [] for _ 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 for word in word_list[skip_start:]: token_weight = len(word) logger.info("Słowo kluczowe: %s",word) itr = 0 for file in music_file_list: if platform == "win32": file = file.split("\\") else: file = file.split("/") char_remove = [ ".", "^", "$", "*", "+", "?", "{", "}", "[", "]", "\\", "|", "(", ")", "!", ",", "-", ":", "mp3", ] all_words = [] for f_iter in file: for char in char_remove: f_iter = f_iter.replace(char, "") tmp = f_iter.split() all_words.extend(tmp) pingu = 1 pattern_len = len(all_words) if platform == "win32": skip = 2 else: skip = 4 matched_times = 1 for itm in all_words[skip:]: pingu += 1 pattern = ".*" + word + ".*" if re.match(pattern, itm, re.IGNORECASE): temp_weight = ( search_weight[itr][0] + (token_weight + (pingu**1.5) / pattern_len) / matched_times ) search_weight[itr] = temp_weight, music_file_list[itr] matched_times += 1 itr += 1 logger.info( "Stworzylem tablice wag zajęło mi to %s",datetime.now() - time_start) time_start = datetime.now() item_to_search = await max_weight(search_weight) itr = 0 if item_to_search == 0: return None not_found = True 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 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 async def max_weight(lista): """_summary_ Args: list (_type_): _description_ Returns: _type_: _description_ """ maximum_weight = 0 for iterator in lista: if iterator[0] > maximum_weight: maximum_weight = iterator[0] return maximum_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)) async def dej_co_ze_spotifaja(ctx): """_summary_ Args: ctx (_type_): _description_ """ 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 get_file(ctx, "Spotify", item) if platform == "win32": separator = "\\" else: separator = "/" for file in files: global MUZYKA #pylint: disable=global-variable-not-assigned MUZYKA["queue"].insert( 0, dir_path + separator + file["artist"] + " - " + file["name"] + ".mp3", ) 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" ) 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)) async def dej_co_z_jutuba(ctx): """_summary_ Args: ctx (_type_): _description_ """ 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) 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["requestor"].insert(0, ctx.author) await ctx.send(f"Dodałem do listy {file_iter}") 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): """_summary_ Args: ctx (_type_): _description_ """ async with ctx.channel.typing(): allowed = False for role in ctx.author.roles: if role.name == "Jarl": allowed = True if ctx.channel.id != 1102190666827702342: await ctx.send("Nie wydaje mnie sie") elif not allowed: await ctx.send("Idź bo Cię zdziele") else: tobancunter = 0 async with ctx.typing(): # 1. get list of users posted on channel for banning channel = ctx.channel messages = [message async for message in channel.history(limit=None)] ids_to_ban = [] for message in messages: lines = message.content.split("\n") for line in lines: match = re.search("\\d{18}", line) #poprawilem backslash na podwojny bo linter sie czepial if match: ids_to_ban.append(match.group()) tobancunter += 1 # 2. get list of already banned users for all servers Conjurer has rights to for guild in client.guilds: bancunter = 0 logger.info("Serwer: %s",guild) current_banlist = [] permission = True try: async for entry in guild.bans(limit=None): current_banlist.append(entry.user.id) bancunter += 1 except: #pylint: disable=bare-except permission = False if permission: # 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: try: tmp_user = await client.fetch_user(int(ident)) await guild.ban( tmp_user, reason="Automatyczna lista banów", delete_message_seconds=0, ) cunter_counter += 1 except discord.NotFound: logger.info( "Znaleziono uzyszkodnika ktory juz nie ma konta" ) 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" ) else: await ctx.send( f"Nie mam na serwerze {guild} uprawnień do banowania. :()" ) 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): """_summary_ Args: ctx (_type_): _description_ """ logger.info("Get sadox") channel = ctx.message.channel async with channel.typing(): dir_path_sadox = "" # select random file if platform == "linux" or platform == "linux2": dir_path_sadox = "/home/pi/RetroPie/Fansadox/" elif platform == "win32": dir_path_sadox = "C:\\Users\\mtusz\\OneDrive\\Dokumenty\\Fansadox\\" res = [] # Iterate directory for path in os.listdir(dir_path_sadox): # check if current path is a file if os.path.isfile(os.path.join(dir_path_sadox, path)): res.append(path) filename = res[random.randrange(0, len(res) - 1)] # select random page file = open(dir_path_sadox + 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 ) 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) 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): """_summary_ Args: ctx (_type_): _description_ """ logger.info("Press play on tape") async with ctx.typing(): global MUZYKA #pylint: disable = global-variable-not-assigned MUZYKA["playing"] = True MUZYKA["ctx"] = ctx await connect(ctx=ctx) await play(ctx=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): """_summary_ Args: ctx (_type_): _description_ """ logger.info("Stop") global MUZYKA #pylint: disable = global-variable-not-assigned MUZYKA["playing"] = False MUZYKA["ctx"] = None voice_client = client.voice_clients[0] if voice_client.is_connected(): await disconnect(ctx=ctx) while MUZYKA["queue"]: MUZYKA["queue"].pop() MUZYKA["requestor"].pop() logger.info("Stop completed") @client.hybrid_command(name = "dalej", description = "Przerzuca na następny kawałek",guild=discord.Object(id=664789470779932693)) async def dalej(ctx): """_summary_ Args: ctx (_type_): _description_ """ if ctx: logger.info("Ctx defined for dalej") logger.info("Next") voice_client = client.voice_clients[0] if voice_client.is_connected(): voice_client.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): """_summary_ Args: ctx (_type_): _description_ """ if ctx: logger.info("Ctx defined for pause") logger.info("Pause") voice_client = client.voice_clients[0] if voice_client.is_connected(): voice_client.pause() logger.info("Pause completed") @client.hybrid_command(name = "graj_dalej", description = "Odpauzowuje",guild=discord.Object(id=664789470779932693)) async def graj_dalej(ctx): """_summary_ Args: ctx (_type_): _description_ """ if ctx: logger.info("Ctx defined for graj_dalej") logger.info("Unpause") voice_client = client.voice_clients[0] if voice_client.is_paused(): voice_client.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): """_summary_ Args: ctx (_type_): _description_ """ async with ctx.typing(): search_time_glob = datetime.now() logger.info("Zaczynam szukać timestamp %s",datetime.now()) file = await wyszukaj(ctx=ctx) 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["requestor"].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" ) @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): """_summary_ Args: ctx (_type_): _description_ """ reply = "Wygenerowana plejlista:\n" async with ctx.typing(): logger.info("Zaczynam szukać timestamp %s",datetime.now()) search_time_glob = datetime.now() dlugosc_playlisty = ctx.message.content.split()[1] 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 ) index = 1 if file: for plik in file: global MUZYKA #pylint: disable=global-variable-not-assigned MUZYKA["queue"].insert(0, plik[1]) MUZYKA["requestor"].insert(0, ctx.author) metadata = eyed3.load(plik[1]) if metadata.tag.title: reply += f"{index} {metadata.tag.title}" else: reply += "{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" 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 = "przytul", description = "Przytul kogoś - daj mention po komendzie :)") async def przytul(ctx, arg:discord.Member=None): """_summary_ Args: ctx (_type_): _description_ arg (discord.Member, optional): _description_. Defaults to None. """ async with ctx.typing(): nieprzytulac = False for mention in ctx.message.mentions: for role in mention.roles: if role.name == "NIEPRZYTULAĆ!": nieprzytulac = True if arg and nieprzytulac: await ctx.send( f"Żebym ja Ciebie nie przytulił {ctx.message.author.mention}" ) elif arg: await ctx.send( 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*" ) else: 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): """_summary_ Args: ctx (_type_): _description_ """ await ctx.send(historia_fabryczki) @client.hybrid_command(name = "chata_hammera", description = "Czas od ostatniego incydentu w AbsinthHammerTimeSpaceContinuum") async def chata_hammera(ctx): """_summary_ Args: ctx (_type_): _description_ """ 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): """_summary_ Args: ctx (_type_): _description_ """ 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): """_summary_ Args: ctx (_type_): _description_ """ 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): """_summary_ Args: ctx (_type_): _description_ """ if ctx: pass #@client.hybrid_command() async def zagraj_muzyke_mego_ludu(ctx): """_summary_ Args: ctx (_type_): _description_ """ if ctx: pass # *================================== Run client.run(TOKEN)