From 87f06d62690cf255a703ea752904fd8dbdf85843 Mon Sep 17 00:00:00 2001 From: Polish Hammer Date: Thu, 30 Oct 2025 16:58:50 +0100 Subject: [PATCH] Tag: 0.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intermediate commits (oldest → newest): - Added playlist display - Bugfixy - Linting - Wrong encoding in settings.json - Kolejna poprawka - Fix of metadata loading - Another fix - Update settings and history - Small fixes in the paths --- .vscode/settings.json | 4 + accident_log.json | 10 +- bot.py | 1121 ++++++++++++++++++++++++++++------------- pamiec.json | 56 ++ pamiec_muzyki.json | 136 +++++ settings.json | 183 ++++--- 6 files changed, 1086 insertions(+), 424 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3c8b1b3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "python.linting.enabled": true, + "python.linting.pylintEnabled": true +} \ No newline at end of file diff --git a/accident_log.json b/accident_log.json index 0c54808..cd675c3 100644 --- a/accident_log.json +++ b/accident_log.json @@ -5,7 +5,7 @@ ], [ "Pat wy\u0142\u0105czy\u0142\u0105 wydruk i wywo\u0142a\u0142a spi\u0119cie na p\u0142ycie g\u0142\u00f3wnej", - "2023-06-01 14:00:43.444444" + "2023-06-01 15:27:43.444444" ], [ "Pat zala\u0142a \u0142azienk\u0119", @@ -28,7 +28,11 @@ "2023-06-08 23:29:43.453654" ], [ - "Hammer kupi\u0142 bilet na 16 zamiast na 09 czerwca", + "Hammer kupi\u0142 Je\u017cowi bilet na 16 zamiast na 09 czerwca", "2023-06-09 14:52:43.453654" + ], + [ + " Z\u0142ama\u0142 paznokie\u0107 otwierajac piwo", + "2023-06-21 21:37:54.583469" ] -] \ No newline at end of file +] diff --git a/bot.py b/bot.py index b98398f..5a6f193 100644 --- a/bot.py +++ b/bot.py @@ -1,74 +1,128 @@ +""" +Module of a python bot named Conjurer - used to work on BDSM discord servers. +""" # This Python file uses the following encoding: utf-8 -# *=========================================== Imports -import os -import discord -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 +# trunk-ignore-all(flake8/E501) +# trunk-ignore-all(bandit/B311) +# trunk-ignore-all(mypy/index) +# pylint: disable=line-too-long +# pylint: disable=too-many-lines import asyncio -from pathlib import PurePath -from pathlib import Path +import io +import json +import logging +import netrc + +# *=========================================== Standard Library 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, TypedDict, Optional + +# *==============Imported libraries +import discord import eyed3 +import numpy as np +import openai +import pdf2image +import PyPDF2 +import requests import spotipy +from discord.ext import commands +from spotipy.oauth2 import SpotifyClientCredentials + +import yt_dlp from spotify_dl import spotify from spotify_dl import youtube as youtube_download -import yt_dlp -from spotipy.oauth2 import SpotifyClientCredentials -import logging.handlers as handlers -import shutil + +Music_Config = TypedDict( + "Music_Config", + { + "playing": bool, + "ctx": Optional[str], + "queue": List[str], + "requestor": List[str], + }, +) # *=========================================== 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 = {"playing": False, "ctx": None, "queue": [], "requestor": []} +MUZYKA: Music_Config = {"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 == "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/" - accident_log = "/home/pi/Conjurer/accident_log.json" + +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" + 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" + 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/" + elif platform == "win32": - 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\\" - accident_log = "accident_log.json" + 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 = "utf-8" + DIR_PATH_SADOX = "C:\\Users\\mtusz\\OneDrive\\Dokumenty\\Fansadox\\" + SEPARATOR_FILE_PATH = "\\" # *=========================================== Keys -netrc = netrc.netrc(netrc_file) -remoteHostName = "discord" -authTokens = netrc.authenticators(remoteHostName) +netrc_mod = netrc.netrc(NETRC_FILE) +REMOTE_HOST_NAME = "discord" +authTokens = netrc_mod.authenticators(REMOTE_HOST_NAME) TOKEN = authTokens[2] -remoteHostName = "openai" -authTokens = netrc.authenticators(remoteHostName) +REMOTE_HOST_NAME = "openai" +authTokens = netrc_mod.authenticators(REMOTE_HOST_NAME) openai.api_key = authTokens[2] -remoteHostName = "spotipy" -authTokens = netrc.authenticators(remoteHostName) +REMOTE_HOST_NAME = "spotipy" +authTokens = netrc_mod.authenticators(REMOTE_HOST_NAME) spotify_ctrl = spotipy.Spotify( client_credentials_manager=SpotifyClientCredentials( client_id=authTokens[0], @@ -87,8 +141,8 @@ intents.voice_states = True logger = logging.getLogger("discord") logger.setLevel(logging.DEBUG) handler = handlers.RotatingFileHandler( - filename=logfile, - encoding="utf-8", + filename=LOGFILE, + encoding=ENCODING, mode="a", maxBytes=6 * 1024 * 1024, backupCount=6, @@ -99,22 +153,21 @@ random.seed() logger.debug(platform) logger.info("Playlist generation") - # *=========================================== Load Data files music_file_list = [] -for item in Path.glob(Path(music_folder), "**/*.mp3"): - file = item.as_posix() +for mp3_item in Path.glob(Path(MUSIC_FOLDER), "**/*.mp3"): + temp_music_file = mp3_item.as_posix() if platform == "win32": - file = file.replace("/", "\\") - music_file_list.append(file) -with open(memory_five_siara, "r+") as file: + 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(file) -with open(memory_five_muzyka, "r+") as file: + 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(file) -f = open(settings_file) -data = json.load(f) + 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: @@ -122,19 +175,37 @@ for key in word_reactions: # *=========================================== Create Client client = commands.Bot(intents=intents, command_prefix="$") + # *=========================================== Define Events @client.event async def on_ready(): - logger.debug(f"{client.user} has connected to Discrod!") + """Metoda wywoływana przy połączeniu do serwera.""" + 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 +# trunk-ignore(pylint/R0915) +# trunk-ignore(pylint/R0914) +# trunk-ignore(pylint/R0912) 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): @@ -143,7 +214,7 @@ async def on_message(message): vykidailo = True if ("Conjurer Śpij Słodko Aniołku" in message.content) and vykidailo: - exit() + sys.exit() # kanal bez bota if message.channel.id == 1095985579147141202: return @@ -166,7 +237,7 @@ async def on_message(message): # TODO: 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) @@ -175,9 +246,10 @@ async def on_message(message): if tdelta > INITIAL_TIME_WAIT: for word in word_reactions: - if re.search(".*" + word + "[\s*,$]*", message.content): + 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 @@ -185,7 +257,9 @@ async def on_message(message): if reaction: emoji = client.get_emoji(word_reactions[word][0]) await message.add_reaction(emoji) - else: + 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() @@ -209,36 +283,32 @@ async def on_message(message): vykidailo = True if role.name == "Bartender": bartender = True - global message_table - result, message_table = await handle_response( - prompt, vykidailo, bartender, message_table, username, False + 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: {}".format(message.content)) + 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: {}".format(image_url)) - response = requests.get(image_url) - file = response.content + 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(file_name, "wb") as f: - f.write(response.content) + with open(temp_file_name, "wb") as dalle_file: + dalle_file.write(response.content) logger.info("Koniec procedury obrazkowej.") - fnord = discord.File(file_name, spoiler=False, description=message.content) + fnord = discord.File( + temp_file_name, spoiler=False, description=message.content + ) await message.reply(file=fnord) @@ -246,34 +316,80 @@ async def on_message(message): 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: - voiceClient = client.voice_clients[0] - if voiceClient.is_connected(): + voice_client = client.voice_clients[0] + if voice_client.is_connected(): return - vc = await voice_channel.connect() + 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): + """ + 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: - voiceClient = client.voice_clients[0] - if voiceClient.is_connected(): - await voiceClient.disconnect() + voice_client = client.voice_clients[0] + if voice_client.is_connected(): + await voice_client.disconnect() +# trunk-ignore(pylint/R0915) +# trunk-ignore(pylint/R0914) +# trunk-ignore(pylint/R0912) async def play(ctx, zamawial=None, arg=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") + """ + 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. + 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: - voiceClient = client.voice_clients[0] - if not voiceClient.is_connected(): - await connect(ctx) - global MUZYKA + voice_client = client.voice_clients[0] + await connect(ctx) if MUZYKA["queue"]: file_to_play = MUZYKA["queue"].pop() zamawial = MUZYKA["requestor"].pop() @@ -284,29 +400,25 @@ async def play(ctx, zamawial=None, arg=None): logger.debug(file_to_play) metadata = eyed3.load(file_to_play) query = None - 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) + temp = file_to_play.split(SEPARATOR_FILE_PATH)[-1] + kawalek = f"Zagram teraz kawalek {temp} z prywatnej kolekcji Hammera." if metadata: if metadata.tag: if metadata.tag.title: - query = "Opowiedz mi o kawałku {}".format(metadata.tag.title) - kawalek = "Zagram teraz kawalek {}".format(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 += " wykonawcy {}".format(metadata.tag.artist) - kawalek += " wykonawcy {}".format(metadata.tag.artist) + query += f" wykonawcy {metadata.tag.artist}" + kawalek += f" wykonawcy {metadata.tag.artist}" if metadata.tag.album: - query += " z albumu {}".format(metadata.tag.album) - kawalek += " z albumu {}".format(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 += "Na specjalne życzenie <@{}>.".format(zamawial.id) + kawalek += f"Na specjalne życzenie <@{zamawial.id}>." await ctx.send(kawalek) - voiceClient.play( + voice_client.play( discord.PCMVolumeTransformer( discord.FFmpegPCMAudio(source=file_to_play), volume=0.3 ) @@ -325,69 +437,70 @@ async def play(ctx, zamawial=None, arg=None): username = ctx.message.author.nick else: username = ctx.message.author.name - global message_table - result, message_table = await handle_response( + 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:{}".format(message_table_muzyka)) + logger.debug("Obecna historia czatu: %s", message_table_muzyka) await ctx.send(result) async def check(): + """Funkcja sprawdzająca czy grać następny kawałek.""" 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.) + # trunk-ignore(codespell/misspelled) # TODO: dlaczego sie tu wypierdala if client.voice_clients: - voiceClient = client.voice_clients[0] - if voiceClient.is_connected(): - global MUZYKA - while MUZYKA["playing"] and voiceClient.is_connected(): + voice_client = client.voice_clients[0] + if voice_client.is_connected(): + while MUZYKA["playing"] and voice_client.is_connected(): if ( - voiceClient - and not voiceClient.is_playing() - and not voiceClient.is_paused() + 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, "{}discord{}.log".format(logstore, datetime.now())) + 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: + 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 = "{}{}{}.json".format( - logstore, memory_five_muzyka[:-4], datetime.now() + path_newfile = ( + f"{LOGSTORE}{MEMORY_FIVE_MUZYKA[:-4]}{datetime.now()}.json" ) - with open(memory_five_muzyka, "r+") as file: - with open(path_newfile, "x") as new_file: + 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) + file_data = json.load(file_music_memory) new_data = [] new_data.append(file_data[0]) new_data.extend(file_data[:-20]) - file.seek(0) + file_music_memory.seek(0) # convert back to json. new_file.seek(0) - json.dump(new_data, file, indent=4) + 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 = "{}{}{}.json".format( - logstore, memory_five_siara[:-4], datetime.now() - ) + 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+") as file: - with open(path_newfile, "x") as new_file: + 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 = [] @@ -404,30 +517,48 @@ async def check(): await asyncio.sleep(60) +# trunk-ignore(pylint/R0913) async def handle_response(prompt, vykidailo, bartender, history, username, music): - # TODO: Wykrywać "Pracuję nad odpowiedzią i tego typu rzeczy" - logger.info("Wywolanie procedury openai z promptem: {}".format(prompt)) - temp = {"role": "user", "content": username + ":" + prompt} + """ + 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) + 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+") as file: + 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) + file_data = json.load(file_music_memory) # Join new_data with file_data inside emp_details file_data.append(temp) - file.seek(0) + file_music_memory.seek(0) # convert back to json. - json.dump(file_data, file, indent=4) + json.dump(file_data, file_music_memory, indent=4) else: - with open(memory_five_siara, "r+") as file: + with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as file_memory: # First we load existing data into a dict. - file_data = json.load(file) + file_data = json.load(file_memory) # Join new_data with file_data inside emp_details file_data.append(temp) - file.seek(0) + file_memory.seek(0) # convert back to json. - json.dump(file_data, file, indent=4) + json.dump(file_data, file_memory, indent=4) history = [] # * append bo pierwszy index # * extend bo 20 ostatnich @@ -435,8 +566,8 @@ async def handle_response(prompt, vykidailo, bartender, history, username, music history.append(message_table_muzyka[0]) history.extend(message_table_muzyka[-20:]) else: - history.append(message_table[0]) - history.extend(message_table[-20:]) + history.append(MESSAGE_TABLE[0]) + history.extend(MESSAGE_TABLE[-20:]) logger.info("Historia wysłana:") logger.debug(history) response = await openai.ChatCompletion.acreate( @@ -453,7 +584,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+") as file: + 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 @@ -463,7 +594,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+") as file: + 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 @@ -472,10 +603,26 @@ 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 +# trunk-ignore(pylint/R0914) +# trunk-ignore(pylint/R0915) 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 = {} @@ -488,7 +635,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 @@ -496,7 +643,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, @@ -511,11 +658,11 @@ async def get_file(ctx, source, link): 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: {}".format(link)) + + 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()@:%_\+.~#?&\/=]*)$" @@ -538,7 +685,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 = { @@ -559,50 +706,76 @@ async def get_file(ctx, source, link): with yt_dlp.YoutubeDL(ydl_opts) as ydl: try: ydl.download([query]) - except Exception as e: # skipcq: PYL-W0703 - logger.error(e) + except Exception as exce: # pylint: disable=broad-exception-caught + logger.error(exce) logger.info( - f"Failed to download {link}, make sure yt_dlp is up to date" + "Failed to download %s, make sure yt_dlp is up to date", link ) extract = re.search("v=(...........)[&,$]*", link) - id = extract.group(1) + 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(".*" + id + ".*", file): + 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: {}".format(link)) - return "", None - + 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): +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: + 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) + """ -''' 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) -''' +# trunk-ignore(pylint/R0914) +# trunk-ignore(pylint/R0915) +# trunk-ignore(pylint/R0912) 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. + """ + 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. word_list = ctx.message.content.split() logger.info("Wyszukuje") - global music_file_list search_weight = [] - for i in range(len(music_file_list)): + for _ in range(len(music_file_list)): search_weight.append((0, "")) time_start = datetime.now() @@ -612,7 +785,7 @@ async def wyszukaj(ctx, how_many=0): skip_start = 1 for word in word_list[skip_start:]: token_weight = len(word) - logger.info("Słowo kluczowe: {}".format(word)) + logger.info("Słowo kluczowe: %s", word) itr = 0 for file in music_file_list: if platform == "win32": @@ -641,10 +814,10 @@ async def wyszukaj(ctx, how_many=0): "mp3", ] all_words = [] - for f in file: + for f_iter in file: for char in char_remove: - f = f.replace(char, "") - tmp = f.split() + f_iter = f_iter.replace(char, "") + tmp = f_iter.split() all_words.extend(tmp) pingu = 1 pattern_len = len(all_words) @@ -665,9 +838,7 @@ async def wyszukaj(ctx, how_many=0): matched_times += 1 itr += 1 - logger.info( - "Stworzylem tablice wag zajęło mi to {}".format(datetime.now() - time_start) - ) + 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 @@ -689,19 +860,40 @@ async def wyszukaj(ctx, how_many=0): return return_list -async def max_weight(list): - max_weight = 0 - for iter in list: - if iter[0] > max_weight: - max_weight = iter[0] - return max_weight +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 # *=========================================== Define Commands -@client.command() +# trunk-ignore(mypy/arg-type) +@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): + """ + 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(): @@ -715,7 +907,7 @@ async def dej_co_ze_spotifaja(ctx): else: separator = "/" for file in files: - global MUZYKA + global MUZYKA # pylint: disable=global-variable-not-assigned MUZYKA["queue"].insert( 0, dir_path @@ -728,46 +920,69 @@ async def dej_co_ze_spotifaja(ctx): MUZYKA["requestor"].insert(0, ctx.author) music_file_list.append(file) await ctx.send( - "Dodałem do listy {}".format( - dir_path + file["artist"] + " - " + file["name"] + ".mp3" - ) + f"Dodałem do listy {dir_path}{file['artist']} - + {file['name']}.mp3" ) logger.info("Spotifaj udany") -@client.command() +# trunk-ignore(mypy/arg-type) +@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): + """ + 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 in content: - if re.match("http.*", item): - dir_path, files = await get_file(ctx, "Youtube", item) - if platform == "win32": - separator = "\\" - else: - separator = "/" + for item_yt in content: + if re.match("http.*", item_yt): + _, files = await get_file(ctx, "Youtube", item_yt) if files: - for file in files: - global MUZYKA - MUZYKA["queue"].insert(0, file) - music_file_list.append(file) + 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("Dodałem do listy {}".format(file)) + await ctx.send(f"Dodałem do listy {file_iter}") logger.info("Jutub udany") -@client.command() -async def update_banlist(ctx, arg=None): - async with channel.typing(): +# trunk-ignore(mypy/arg-type) +@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), +) +# trunk-ignore(pylint/R0914) +# trunk-ignore(pylint/R0912) +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(): 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") @@ -781,30 +996,37 @@ async def update_banlist(ctx, arg=None): for message in messages: lines = message.content.split("\n") for line in lines: - match = re.search("\d{18}", line) + match = re.search( + "\\d{18}", + line + # trunk-ignore(codespell/misspelled) + ) # 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 + # 2. get list of already banned users for all servers Conjurer + # has rights to for guild in client.guilds: bancunter = 0 - logger.info("Serwer:{}".format(guild)) + # trunk-ignore(codespell/misspelled) + 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: + except BaseException: # pylint: disable=broad-exception-caught 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 id in ban_list: + for ident in ban_list: try: - tmp_user = await client.fetch_user(int(id)) + tmp_user = await client.fetch_user(int(ident)) await guild.ban( tmp_user, reason="Automatyczna lista banów", @@ -818,63 +1040,79 @@ async def update_banlist(ctx, arg=None): bad_id_cunter_counter += 1 # 4. return message success/failure - how many banned await ctx.send( - "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, - ) + "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( - "Nie mam na serwerze {} uprawnień do banowania. :()".format( - guild - ) + f"Nie mam na serwerze {guild} uprawnień do banowania. :()" ) await ctx.send("Zrobione tak czy inaczej") -@client.command() -async def get_image_sadox(ctx, arg=None): +# trunk-ignore(mypy/arg-type) +@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 + """ 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): + for path in os.listdir(DIR_PATH_SADOX): # check if current path is a file - if os.path.isfile(os.path.join(dir_path, path)): + 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 + filename, "rb") + 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 + filename, first_page=page, last_page=page + DIR_PATH_SADOX + filename, first_page=page, last_page=page ) - b = io.BytesIO() - image[0].save(b, "JPEG") - b.seek(0) - b.name = "image.jpg" - file = discord.File(b) + 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.command() -async def graj_muzyko(ctx, arg=None): +# trunk-ignore(mypy/arg-type) +@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 + """ + logger.info("Press play on tape") async with ctx.typing(): - global MUZYKA + global MUZYKA # pylint: disable=global-variable-not-assigned MUZYKA["playing"] = True MUZYKA["ctx"] = ctx await connect(ctx=ctx) @@ -882,14 +1120,27 @@ async def graj_muzyko(ctx, arg=None): logger.info("Press play on tape completed") -@client.command() -async def cisza(ctx, arg=None): +# trunk-ignore(mypy/arg-type) +@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 + """ logger.info("Stop") - global MUZYKA + global MUZYKA # pylint: disable=global-variable-not-assigned MUZYKA["playing"] = False MUZYKA["ctx"] = None - voiceClient = client.voice_clients[0] - if voiceClient.is_connected(): + voice_client = client.voice_clients[0] + if voice_client.is_connected(): await disconnect(ctx=ctx) while MUZYKA["queue"]: MUZYKA["queue"].pop() @@ -897,111 +1148,204 @@ async def cisza(ctx, arg=None): logger.info("Stop completed") -@client.command() -async def dalej(ctx, arg=None): +# trunk-ignore(mypy/arg-type) +@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") logger.info("Next") - voiceClient = client.voice_clients[0] - if voiceClient.is_connected(): - voiceClient.stop() + voice_client = client.voice_clients[0] + if voice_client.is_connected(): + voice_client.stop() await play(ctx=ctx) logger.info("Next completed") -@client.command() -async def daj_mi_chwile(ctx, arg=None): +# trunk-ignore(mypy/arg-type) +@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") + logger.info("Pause") - voiceClient = client.voice_clients[0] - if voiceClient.is_connected(): - voiceClient.pause() + voice_client = client.voice_clients[0] + if voice_client.is_connected(): + voice_client.pause() logger.info("Pause completed") -@client.command() -async def graj_dalej(ctx, arg=None): +# trunk-ignore(mypy/arg-type) +@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") logger.info("Unpause") - voiceClient = client.voice_clients[0] - if voiceClient.is_paused(): - voiceClient.resume() + voice_client = client.voice_clients[0] + if voice_client.is_paused(): + voice_client.resume() logger.info("Unpause completed") -@client.command() -async def zagraj_muzyke_mego_ludu(ctx, arg=None): - pass +# trunk-ignore(mypy/arg-type) +@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_mi_kawalek(ctx, arg=None): + :param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It + contains information about the context in which the command was invoked, such as the message, the + channel, the server, and the user who invoked the command. This information can be used to perform + various actions, such + """ async with ctx.typing(): search_time_glob = datetime.now() - logger.info("Zaczynam szukać timestamp {}".format(datetime.now())) + logger.info("Zaczynam szukać timestamp %s", datetime.now()) file = await wyszukaj(ctx=ctx) logger.info( - "Koniec szukania(timestamp {} zajęło {}".format( - datetime.now(), datetime.now() - search_time_glob - ) + "Koniec szukania(timestamp %s zajęło %s", + datetime.now(), + datetime.now() - search_time_glob, ) + if file: for plik in file: - global MUZYKA + 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 {} z prywatnej kolekcji Hammera.".format( - plik[1] - ) + reply = "Dodałem do playlisty {plik[1]} z prywatnej kolekcji Hammera." if metadata.tag.title: - reply = "Dodałem do playlisty kawalek {}".format(metadata.tag.title) + reply = f"Dodałem do playlisty kawalek {metadata.tag.title}" if metadata.tag.artist: - reply += " wykonawcy {}".format(metadata.tag.artist) + reply += f" wykonawcy {metadata.tag.artist}" if metadata.tag.album: - reply += " z albumu {}".format(metadata.tag.album) + reply += f" z albumu {metadata.tag.album}" reply += " z prywatnej kolekcji Hammera i na Twoją specjalną rpośbę." - await ctx.reply(reply) + await ctx.send(reply) else: - await ctx.reply( + await ctx.send( "Obawiam się że nie mogę nic znaleźć u siebie. Spróbuj komendy '$dej_co_ze_spotifaja' jeśli masz link" ) -@client.command() -async def zrob_mi_plejliste(ctx, *arg): +# trunk-ignore(mypy/arg-type) +@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" async with ctx.typing(): - logger.info("Zaczynam szukać timestamp {}".format(datetime.now())) + logger.info("Zaczynam szukać timestamp %s", datetime.now()) search_time_glob = datetime.now() - dlugosc_playlisty = arg[0] + dlugosc_playlisty = ctx.message.content.split()[1] file = await wyszukaj(ctx=ctx, how_many=dlugosc_playlisty) logger.info( - "Koniec szukania(timestamp {} zajęło {}".format( - datetime.now(), datetime.now() - search_time_glob - ) + "Koniec szukania(timestamp %s zajęło %s", + datetime.now(), + datetime.now() - search_time_glob, ) + index = 1 if file: for plik in file: - global MUZYKA + 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 {} z prywatnej kolekcji Hammera.".format( - plik[1] - ) - 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) + 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." + + index += 1 + if len(reply) > 1800: + await ctx.send(reply) + reply = "" else: - await ctx.reply( + 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.command() -async def przytul(ctx, arg=None): +# trunk-ignore(mypy/arg-type) +@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] + """ async with ctx.typing(): nieprzytulac = False for mention in ctx.message.mentions: @@ -1011,90 +1355,153 @@ async def przytul(ctx, arg=None): if arg and nieprzytulac: await ctx.send( - "Żebym ja Ciebie nie przytulił {}".format(ctx.message.author.mention) + f"Żebym ja Ciebie nie przytulił {ctx.message.author.mention}" ) elif arg: await ctx.send( - "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 - ) + # 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*" ) 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.command() -async def get_image_stable_diffusion(ctx, arg=None): - pass +# trunk-ignore(mypy/arg-type) +@client.hybrid_command(name="fabryczka", description="Historia fabryczki") +async def fabryczka(ctx): + """ + Send a general description of "fabryczkagate" to channel. + + :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.command() -async def fabryczka(ctx, arg=None): - await ctx.message.reply(historia_fabryczki) +# trunk-ignore(mypy/arg-type) +@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. - -@client.command() -async def chata_hammera(ctx, arg=None): - with open(accident_log, "r+") as new_file: + :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( - "Komenda mierząca incydenty w Eldritch AbsinthHammerTimeSpaceContinuum.\n Od ostatniego incydentu w chacie Hammera minęło {}. Incydent to: {}".format( - datetime.now() - czas, opis - ) + f"Komenda mierząca incydenty w Eldritch AbsinthHammerTimeSpaceContinuum.\n Od ostatniego incydentu w chacie Hammera minęło {datetime.now() - czas}. Incydent to: {opis}" ) -@client.command() -async def historia_incydentow_u_hammera(ctx, arg=None): - with open(accident_log, "r+") as new_file: +# trunk-ignore(mypy/arg-type) +@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) + 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 data in file_data: - opis = data[0] - czas = datetime.strptime(data[1], "%Y-%m-%d %H:%M:%S.%f") - add_data = "{}. Opis: {} Data: {}".format(index, opis, czas) + 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.command() -async def reset_the_clock(ctx, arg=None): +# trunk-ignore(mypy/arg-type) +@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+") as new_file: + 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) + 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, "{}".format(datetime.now())] + accident = accident = [opis, f"{datetime.now()}"] file_data.append(accident) - new_file.seek(0) + new_file_accidents.seek(0) # convert back to json. - json.dump(file_data, new_file, indent=4) + json.dump(file_data, new_file_accidents, indent=4) await ctx.send( - "Komenda mierząca incydenty w Eldritch AbsinthHammerTimeSpaceContinuum.\n RESET THE CLOCK. Od ostatniego incydentu w chacie Hammera minęło {}. No ale teraz się odpierdoliło: {}".format( - czas, opis - ) + 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( - "Komenda mierząca incydenty w Eldritch AbsinthHammerTimeSpaceContinuum.\n Gdzie z łapami do zegara? {} coś albo się komuś stało albo zaraz się stanie jak będzie zegar tykał....".format( - client.get_user(346956223645614080).mention - ) + 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() +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 + """ + + if ctx: + pass + + # *================================== Run +# trunk-ignore(mypy/arg-type) client.run(TOKEN) diff --git a/pamiec.json b/pamiec.json index 06fe548..4448eba 100644 --- a/pamiec.json +++ b/pamiec.json @@ -182,5 +182,61 @@ { "role": "assistant", "content": "Z ca\u0142\u0105 pewno\u015bci\u0105 nale\u017cy zwr\u00f3ci\u0107 uwag\u0119 na bezpiecze\u0144stwo w mieszkaniu Polish Hammer. Wypadk\u0119, kt\u00f3ry opisa\u0142e\u015b, nale\u017cy wzi\u0105\u0107 pod uwag\u0119 i podj\u0105\u0107 kroki, aby unikn\u0105\u0107 podobnych w przysz\u0142o\u015bci. Najwa\u017cniejsze, aby zadba\u0107 o bezpiecze\u0144stwo w ka\u017cdym miejscu, w kt\u00f3rym przebywamy, w tym w domu. Zdarzenia w mieszkaniu Polish Hammera to raczej zwyk\u0142y zbieg okoliczno\u015bci ni\u017c szale\u0144stwo lub pogranicze grozy i kosmicznego horroru. Jednak zawsze warto zachowa\u0107 ostro\u017cno\u015b\u0107 i pami\u0119ta\u0107 o przyk\u0142adaniu uwagi do bezpiecze\u0144stwa w ka\u017cdej sytuacji. W razie potrzeby mo\u017cna skonsultowa\u0107 si\u0119 z ekspertami w dziedzinie bezpiecze\u0144stwa mieszkaniowego, kt\u00f3rzy pomog\u0105 Ci unikn\u0105\u0107 niebezpiecze\u0144stwa i zadba\u0107 o Twoje bezpiecze\u0144stwo." + }, + { + "role": "user", + "content": "Pat vel Je\u017c Bojowy [Pat]:powiedz co\u015b o <@975675093999034390>" + }, + { + "role": "assistant", + "content": "Nie jestem w stanie powiedzie\u0107 nic konkretnego o u\u017cytkowniku o nicku <@975675093999034390>, poniewa\u017c nie posiadam dost\u0119pu do informacji o konkretnych u\u017cytkownikach Discorda. Mog\u0119 jedynie sporz\u0105dzi\u0107 og\u00f3lny opis u\u017cytkownik\u00f3w lub pom\u00f3c w przygotowaniu drink\u00f3w." + }, + { + "role": "user", + "content": "Pat vel Je\u017c Bojowy [Pat]:zapami\u0119taj, \u017ce u\u017cytkowniczka <@975675093999034390> jest sympatycznym stworzonkiem" + }, + { + "role": "assistant", + "content": "Dzi\u0119kuj\u0119 za informacj\u0119, zapami\u0119tam, \u017ce u\u017cytkowniczka <@975675093999034390> to sympatyczne stworzonko. Czy potrzebujesz mo\u017ce czego\u015b wi\u0119cej? Jestem tutaj, aby Ci pom\u00f3c." + }, + { + "role": "user", + "content": "Pat vel Je\u017c Bojowy [Pat]:co wiesz o <@975675093999034390> ?" + }, + { + "role": "assistant", + "content": "Przepraszam, ale jako sztuczna inteligencja nie jestem w stanie przypisa\u0107 opisu do osoby o podanym numerze ID. Musisz poda\u0107 nazw\u0119 lub nick dla identyfikacji u\u017cytkownika." + }, + { + "role": "user", + "content": "Pat vel Je\u017c Bojowy [Pat]:co wiesz o u\u017cytkowniczce <@975675093999034390> ?" + }, + { + "role": "assistant", + "content": "Niestety, jako model AI nie mog\u0119 uzyska\u0107 informacji o u\u017cytkownikach serwera. Moje funkcje s\u0105 ograniczone tylko do odpowiedzi na pytania i wskaz\u00f3wek udzielanych przeze mnie podczas trwaj\u0105cej rozmowy. Jednak zapami\u0119ta\u0142em, co powiedzia\u0142e\u015b wcze\u015bniej i zawsze b\u0119d\u0119 pami\u0119ta\u0142, \u017ce u\u017cytkowniczka <@975675093999034390> jest sympatycznym stworzonkiem." + }, + { + "role": "user", + "content": "Fallain:sporz\u0105d\u017a og\u00f3lny opis <@715277726126309378>" + }, + { + "role": "assistant", + "content": "Oczywi\u015bcie, przygotuj\u0119 og\u00f3lny opis u\u017cytkowniczki <@715277726126309378>. \n\nMo\u017cna powiedzie\u0107, \u017ce jest to osoba bardzo wra\u017cliwa i empatyczna, kt\u00f3ra zawsze stara si\u0119 pom\u00f3c innym w potrzebie. Dzi\u0119ki swojej \u017cyczliwej i pe\u0142nej mi\u0142o\u015bci naturze, potrafi przyci\u0105ga\u0107 do siebie ludzi i wprowadza\u0107 pozytywn\u0105 atmosfer\u0119 w ka\u017cdym towarzystwie. Jej kreatywno\u015b\u0107 i artystyczna dusza pomagaj\u0105 jej wyra\u017ca\u0107 swoje emocje i wywo\u0142ywa\u0107 u innych podziw i zachwyt. Jest osob\u0105 szczer\u0105 i bezpo\u015bredni\u0105, a tak\u017ce bardzo lojaln\u0105 wobec swoich przyjaci\u00f3\u0142 i bliskich." + }, + { + "role": "user", + "content": "bezimienna_Su (protected):<@975675093999034390>" + }, + { + "role": "assistant", + "content": "Niestety nie jestem w stanie przet\u0142umaczy\u0107 tej komendy. Czy mo\u017ce to wynika\u0107 z b\u0142\u0119du w sk\u0142adni? Potrzebujesz mojej pomocy w innej kwestii?" + }, + { + "role": "user", + "content": "inside_and_out:doucz si\u0119" + }, + { + "role": "assistant", + "content": "Jakich konkretnych informacji mam si\u0119 douczy\u0107? Jestem tu po to, aby Ci pom\u00f3c, wi\u0119c jestem otwarty na uzupe\u0142nienie swojej wiedzy w dowolnym zakresie, o ile tylko nie \u0142amie to zasad regulaminu i etyki." } ] \ No newline at end of file diff --git a/pamiec_muzyki.json b/pamiec_muzyki.json index 292d1fb..02744f9 100644 --- a/pamiec_muzyki.json +++ b/pamiec_muzyki.json @@ -654,5 +654,141 @@ { "role": "assistant", "content": "Niestety, nie znalaz\u0142em informacji na temat utworu \"Can't Loose The Book\" wykonawcy Balance Of Power z albumu \"When the worlds fall down\". Mo\u017ce to b\u0142\u0105d w pisowni lub nie\u015bcis\u0142o\u015b\u0107 w informacjach, kt\u00f3rych u\u017cy\u0142e\u015b. Prosz\u0119 sprawdzi\u0107 jeszcze raz dok\u0142adnie tytu\u0142 utworu i albumu lub poda\u0107 wi\u0119cej informacji, a ja postaram si\u0119 na ich podstawie odpowiedzie\u0107 na Twoje pytanie." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku The End of Time / Wilf's Wiggle wykonawcy Murray Gold z albumu Doctor Who - Series 4 - The Specials (Original Television Soundtrack)" + }, + { + "role": "assistant", + "content": "\"The End of Time\" i \"Wilf's Wiggle\" to dwa utwory autorstwa brytyjskiego kompozytora Muarraya Golda, kt\u00f3re pojawi\u0142y si\u0119 na albumie \"Doctor Who - Series 4 - The Specials (Original Television Soundtrack)\", na kt\u00f3rym znalaz\u0142a si\u0119 muzyka z serii specjalnych odcink\u00f3w 4 sezonu serialu \"Doctor Who\".\n\n\"The End of Time\" to utw\u00f3r, kt\u00f3ry pojawi\u0142 si\u0119 w dwucz\u0119\u015bciowym odcinku \"The End of Time\", b\u0119d\u0105cym jednym z najwa\u017cniejszych moment\u00f3w w historii \"Doctor Who\". Charakteryzuje si\u0119 on ci\u0119\u017ckim, mrocznym brzmieniem, s\u0142yszalnym w tle modulacji sygna\u0142\u00f3w d\u017awi\u0119kowych typowych dla serialu, a tak\u017ce mocnym ch\u00f3ralnym wokalem. Utw\u00f3r ten bardzo dobrze oddaje napi\u0119cie i dramaturgi\u0119 akcji oraz atmosfer\u0119 ko\u0144ca epoki.\n\n\"Wilf's Wiggle\" to natomiast utw\u00f3r, kt\u00f3ry pojawi\u0142 si\u0119 w tym samym odcinku serialu, ale w przeciwie\u0144stwie do \"The End of Time\", ma zupe\u0142nie inny charakter. Jest to utw\u00f3r bardziej radosny i optymistyczny, kt\u00f3ry wprowadza s\u0142uchacza w lekkim klimacie beztroskiej zabawy. W szczeg\u00f3lno\u015bci, nawi\u0105zuje do weso\u0142ych i zabawnych moment\u00f3w, jakie pojawiaj\u0105 si\u0119 w odcinku dzi\u0119ki" + }, + { + "role": "user", + "content": "Pat vel Je\u017c Bojowy [Wolfram]:Opowiedz mi o kawa\u0142ku The Omega wykonawcy Sefa z albumu Qlimax The Source" + }, + { + "role": "assistant", + "content": "\"The Omega\" to utw\u00f3r stworzony przez holenderskiego producenta muzycznego o pseudonimie Sefa, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"Qlimax The Source\". Jest to hardstyle'owy kawa\u0142ek, kt\u00f3ry charakteryzuje si\u0119 mocnym brzmieniem, ci\u0119\u017ckimi bitemi i intensywnymi elektronicznymi d\u017awi\u0119kami.\n\nTekst utworu sk\u0142ada si\u0119 tylko z jednego s\u0142owa \u2013 \"omega\", kt\u00f3re jest powtarzane przez ca\u0142y utw\u00f3r. S\u0142owo to, jako ostatnia litera greckiego alfabetu, odnosi si\u0119 do ko\u0144ca i symbolizuje zako\u0144czenie czego\u015b wa\u017cnego lub kluczowego. Muzyka i tekst tego utworu zatem wprowadzaj\u0105 s\u0142uchaczy w nastrojowy klimat i nadaj\u0105 utworowi wyr\u00f3\u017cniaj\u0105cy charakter.\n\n\"The Omega\" to utw\u00f3r, kt\u00f3ry odznacza si\u0119 ci\u0119\u017ckim i przejmuj\u0105cym brzmieniem, idealnym do s\u0142uchania na ch\u00f3rzystki i imprezy z muzyk\u0105 hardstyle. To jedna z najmocniejszych i najbardziej wpadaj\u0105cych w ucho kompozycji z albumu \"Qlimax The Source\", kt\u00f3ry cieszy si\u0119 du\u017cym zainteresow" + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Wiosna nie ominie ci\u0119 wykonawcy Antonina Krzyszton z albumu Turkusowy st\u00f3\u0142" + }, + { + "role": "assistant", + "content": "\"Wiosna nie ominie ci\u0119\" to piosenka Antoniny Krzyszton, kt\u00f3ra pojawi\u0142a si\u0119 na jej albumie \"Turkusowy st\u00f3\u0142\" wydanym w 1987 roku. Jest to utw\u00f3r, kt\u00f3ry charakteryzuje si\u0119 mi\u0119kk\u0105 i delikatn\u0105 melodyj\u0105 w po\u0142\u0105czeniu z pi\u0119knym wokalem Antoniny Krzyszton.\n\nTekst utworu opowiada o nadchodz\u0105cej wio\u015bnie, kt\u00f3rej nie da si\u0119 unikn\u0105\u0107, a kt\u00f3ra zwiastuje nadziej\u0119 i nowy pocz\u0105tek. Refren, w kt\u00f3rym \u015bpiewa si\u0119 \"Wiosna nie ominie ci\u0119, nawet gdy trzeba ci cierpliwo\u015bci mie\u0107\" podkre\u015bla wytrwa\u0142o\u015b\u0107 w d\u0105\u017ceniu do celu z poczuciem, \u017ce zmiana nast\u0105pi i przyniesie z sob\u0105 dobre rzeczy.\n\n\"Wiosna nie ominie ci\u0119\" to pi\u0119kna, klimatyczna i optymistyczna piosenka, kt\u00f3ra doskonale oddaje pozytywne emocje towarzysz\u0105ce ko\u0144cowi zimy i nadej\u015bciu wiosny. To jedna z najbardziej znanych i lubianych piosenek w dorobku Antoniny Krzyszton i cieszy si\u0119 popularno\u015bci\u0105 w\u015br\u00f3d fan\u00f3w muzyki polskiej." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Jak to B\u00f3g wykonawcy Andrzej Poniedzielski z albumu SzlafRock & roll" + }, + { + "role": "assistant", + "content": "\"Jak to B\u00f3g\" to utw\u00f3r, kt\u00f3ry znalaz\u0142 si\u0119 na albumie \"SzlafRock & roll\" Andrzeja Poniedzielskiego z 1995 roku. Jest to utw\u00f3r z gatunku rockowo-komediowego, charakteryzuj\u0105cy si\u0119 weso\u0142ym tekstem oraz melodyjnym, \u0142atwo wpadaj\u0105cym w ucho refrenem.\n\nW tek\u015bcie piosenki Andrzej Poniedzielski porusza kwesti\u0119 z\u0142o\u017cono\u015bci ludzkiego \u017cycia i zwi\u0105zanymi z nim trudno\u015bciami, a jednocze\u015bnie k\u0142adzie nacisk na pozytywne aspekty \u017cycia, takie jak rodzina, przyja\u017a\u0144 i solidarno\u015b\u0107 mi\u0119dzy lud\u017ami. W tek\u015bcie pojawiaj\u0105 si\u0119 tak\u017ce odniesienia do tematyki religijnej, a w refrenie s\u0142yszymy powtarzaj\u0105ce si\u0119 pytanie: \"Jak to B\u00f3g da\u0142 n\u00f3\u017cki, a Mr\u00f3wka chodzi, a Lech Kaczy\u0144ski rz\u0105dzi?\"\n\n\"Jak to B\u00f3g\" to utw\u00f3r z lekkim, humorystycznym przes\u0142aniem, kt\u00f3ry na pierwszy rzut oka mo\u017ce wydawa\u0107 si\u0119 spor\u0105 odmian\u0105 od utwor\u00f3w rockowych. Jednak utw\u00f3r ten przyci\u0105ga s\u0142uchaczy swoim dobrym humorem, pozytywnym przes\u0142aniem i chwytliw\u0105 melodi\u0105, kt\u00f3ra \u0142atwo wpada w ucho i pozostaje w pami\u0119ci na d\u0142u\u017cej." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Nie ma jak u mamy wykonawcy Wojciech M\u0142ynarski z albumu Polska mi\u0142o\u015b\u0107" + }, + { + "role": "assistant", + "content": "\"Nie ma jak u mamy\" to utw\u00f3r autorstwa Wojciecha M\u0142ynarskiego, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"Polska mi\u0142o\u015b\u0107\" w 1983 roku. Jest to lekka i humorystyczna piosenka, kt\u00f3ra z pewno\u015bci\u0105 zachwyci ka\u017cdego, kto kiedykolwiek skorzysta\u0142 z domowych obiad\u00f3w.\n\nTekst utworu opowiada o przepi\u0119knym dniu, kt\u00f3ry straci\u0142 sw\u00f3j urok, gdy okaza\u0142o si\u0119, \u017ce domownikom brakuje domowego jedzenia. S\u0142uchacz poznaje zwyczaje, kt\u00f3re towarzysz\u0105 rodzinie podczas wsp\u00f3lnych posi\u0142k\u00f3w, a przede wszystkim dowiaduje si\u0119, jakie przysmaki swoj\u0105 urocz\u0105 prezencj\u0105 potrafi\u0105 o\u017cywi\u0107 wspania\u0142e chwile rodzinne.\n\n\"Nie ma jak u mamy\" to lekka piosenka, w kt\u00f3rej M\u0142ynarski \u015bwietnie po\u0142\u0105czy\u0142 elementy polskiej tradycji z melodi\u0105 przyci\u0105gaj\u0105c\u0105 do siebie uwag\u0119 ka\u017cdego s\u0142uchacza. To utw\u00f3r, kt\u00f3ry z pewno\u015bci\u0105 budzi pozytywne emocje i sprzyja odpr\u0119\u017ceniu, a jednocze\u015bnie celebruje polskie rodzinne tradycje zgromadzone wok\u00f3\u0142 wsp\u00f3lnego sto\u0142u." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Zata\u0144czymy na mo\u015bcie wykonawcy Czerwony Tulipan z albumu Olsztyn kocham" + }, + { + "role": "assistant", + "content": "\"Zata\u0144czymy na mo\u015bcie\" to utw\u00f3r zespo\u0142u Czerwony Tulipan, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"Olsztyn kocham\" w 1993 roku. Jest to piosenka o charakterze ludowym, sk\u0142adaj\u0105ca si\u0119 z przyjemnej, melodyjnej wokalnej partii oraz prostego, ale zach\u0119caj\u0105cego do ta\u0144ca rytmu.\n\nTekst utworu jest pe\u0142en nostalgii i romantyzmu, opowiadaj\u0105c histori\u0119 mi\u0142osn\u0105, kt\u00f3ra dzieje si\u0119 na mo\u015bcie. Piosenk\u0119 charakteryzuje prostota i wyj\u0105tkowo\u015b\u0107, kt\u00f3ra pozwala jej wybi\u0107 si\u0119 z t\u0142umu komercyjnej muzyki z tego czasu.\n\nCzerwony Tulipan to zesp\u00f3\u0142 wyr\u00f3\u017cniaj\u0105cy si\u0119 na polskiej scenie muzycznej, ciesz\u0105cy si\u0119 du\u017c\u0105 popularno\u015bci\u0105 zw\u0142aszcza w latach 90. Ich tw\u00f3rczo\u015b\u0107 to po\u0142\u0105czenie r\u00f3\u017cnych gatunk\u00f3w muzycznych, co sprawia, \u017ce ich utwory s\u0105 wyj\u0105tkowo bogate i ciekawe.\n\n\"Zata\u0144czymy na mo\u015bcie\" to pi\u0119kna, nostalgiczna piosenka, kt\u00f3ra wprowadza s\u0142uchaczy w romantyczny nastr\u00f3j oraz sk\u0142ania do refleksji nad uczuciami i warto\u015bciami, kt\u00f3re mo\u017cna odnale\u017a\u0107 w prostych rzeczach." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Klas\u00f3wka z fragmentu wolno\u015bci wykonawcy Krzysztof Daukszewicz z albumu 44 x" + }, + { + "role": "assistant", + "content": "Przepraszam, ale nie jestem w stanie udzieli\u0107 informacji na temat utworu \"Klas\u00f3wka z fragmentu wolno\u015bci\" wykonawcy Krzysztofa Daukszewicza, poniewa\u017c ten utw\u00f3r nie istnieje. By\u0107 mo\u017ce pope\u0142ni\u0142(a)\u015b liter\u00f3wk\u0119 albo jest to utw\u00f3r, kt\u00f3ry wyst\u0119puje pod innym tytu\u0142em. Je\u015bli podasz dok\u0142adniejsze informacje lub skorygujesz b\u0142\u0119dy to postaram si\u0119 udzieli\u0107 jak najbardziej precyzyjnej odpowiedzi." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Wsta\u0144 i id\u017a wykonawcy Antonina Krzyszton z albumu Czekaj" + }, + { + "role": "assistant", + "content": "\"Wsta\u0144 i id\u017a\" to utw\u00f3r autorstwa Antoniny Krzyszton, kt\u00f3ry pojawi\u0142 si\u0119 na jej albumie zatytu\u0142owanym \"Czekaj\". Utw\u00f3r charakteryzuje si\u0119 spokojnym, melodyjnym brzmieniem, pe\u0142nym optymizmu i pozytywnej energii.\n\nTekst piosenki opowiada o zach\u0119cie do wyj\u015bcia z marazmu i rutyny codziennego \u017cycia, do odwagi i determinacji w walce o swoje cele. Antonina Krzyszton w spos\u00f3b lekki i przyst\u0119pny przedstawia przes\u0142anie, \u017ce ka\u017cdy mo\u017ce dokona\u0107 zmiany w swoim \u017cyciu, potrzeba tylko wzi\u0119cia odpowiedzialno\u015bci za swoje wybory.\n\n\"Wsta\u0144 i id\u017a\" to utw\u00f3r, kt\u00f3ry z pewno\u015bci\u0105 dodaje optymizmu i motywacji do dzia\u0142ania s\u0142uchaczowi. Melodyjne brzmienie i pozytywny przekaz sprawiaj\u0105, \u017ce kompozycja ta idealnie nadaje si\u0119 na depremiuj\u0105ce momenty w \u017cyciu, by zainspirowa\u0107 i u\u015bwiadomi\u0107 s\u0142uchaczowi, \u017ce trudne czasem s\u0105 tylko przej\u015bciowe." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Majster Bieda wykonawcy Wolna Grupa Bukowina z albumu Kolory Muzyki" + }, + { + "role": "assistant", + "content": "\"Majster Bieda\" to utw\u00f3r folkowy polskiej grupy Wolna Grupa Bukowina, pochodz\u0105cy z albumu \"Kolory Muzyki\" z 1998 roku. Jest to adaptacja ludowej pie\u015bni, kt\u00f3ra w oryginale opowiada o biednym majstrze, kt\u00f3remu nie wiedzie si\u0119 w pracy, nie ma pieni\u0119dzy na codzienne potrzeby, a jego jedynym schronieniem s\u0105 bezdomne psy. \n\nW wykonaniu Wolnej Grupy Bukowina, \"Majster Bieda\" zyskuje now\u0105 aran\u017cacj\u0119, charakterystyczn\u0105 dla muzyki folkowej. Piosenka jest pe\u0142na sentymentalnej refleksji nad przemijaniem i trudami codziennego \u017cycia, a jednocze\u015bnie nios\u0105ca nadziej\u0119 na lepsze jutro.\n\nW warstwie muzycznej utw\u00f3r charakteryzuje si\u0119 prostymi aran\u017cacjami ludowych instrument\u00f3w, przede wszystkim skrzypiec i akordeonu, co dodaje mu rustykalnego klimatu. \"Majster Bieda\" jest jednym z najbardziej znanych i cenionych utwor\u00f3w Wolnej Grupy Bukowina, kt\u00f3ry po latach nadal zaskakuje swoj\u0105 uniwersalno\u015bci\u0105 i aktualno\u015bci\u0105." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Elegancka piosenka o szcz\u0119\u015bciu wykonawcy Andrzej Poniedzielski z albumu SzlafRock & roll" + }, + { + "role": "assistant", + "content": "\"Elegancka piosenka o szcz\u0119\u015bciu\" to utw\u00f3r, kt\u00f3ry znalaz\u0142 si\u0119 na albumie \"SzlafRock & roll\" Andrzeja Poniedzielskiego - znanej postaci polskiej kultury. Utw\u00f3r ten \u0142\u0105czy w sobie charakterystyczne dla muzyki Poniedzielskiego zabawne, pogodne liryczne style z subtelno\u015bci\u0105 i przes\u0142aniem o naturze szcz\u0119\u015bcia.\n\nW swojej kompozycji Poniedzielski wykorzystuje subtelne, melodyjne i nostalgiczne partie na gitarze akustycznej ze swoim niezwyk\u0142ym tekstem. W piosence tej Por\u00f3wnuje wszystkich ludzi, pidkre\u015blaj\u0105c, \u017ce wa\u017cne jest by zdawa\u0107 sobie spraw\u0119 z tego, co sprawia nam rado\u015b\u0107 i szcz\u0119\u015bcie. \n\n\"Elegancka piosenka o szcz\u0119\u015bciu\" to wspania\u0142a piosenka, kt\u00f3ra przypomina nam o rado\u015bciach z mniej skomplikowanych i codziennych rzeczy. Utw\u00f3r cechuje si\u0119 subtelno\u015bci\u0105 i przytuln\u0105 aur\u0105, a tak\u017ce dotyka wa\u017cnych temat\u00f3w z humorem i wra\u017cliwo\u015bci\u0105. To uczciwa i wyra\u017ana pie\u015b\u0144, kt\u00f3ra inspiruje s\u0142uchaczy do bardziej pozytywnego i szcz\u0119\u015bliwego podej\u015bcia do \u017cycia." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Zabiegani, uwik\u0142ani wykonawcy Czerwony Tulipan z albumu Jedyne co mam" + }, + { + "role": "assistant", + "content": "\"Zabiegani, uwik\u0142ani\" to utw\u00f3r Czerwonych Tulipan\u00f3w z albumu \"Jedyne co mam\". Jest to piosenka z gatunku folk rock, opowiadaj\u0105ca o zabieganych i skomplikowanych ludzkich relacjach w \u017cyciu codziennym. \n\nTekst utworu sk\u0142ada si\u0119 z refleksji nad zat\u0142oczeniem, brakiem czasu i poczucia pogoni za sukcesem oraz potrzeby zatrzymania si\u0119, by zastanowi\u0107 si\u0119 nad sensem poszczeg\u00f3lnych dzia\u0142a\u0144. Piosenka porusza kwestie zwi\u0105zane z potrzeb\u0105 oddechu, szczero\u015bci, prawdziwego kontaktu mi\u0119dzyludzkiego i umiej\u0119tno\u015bci cieszenia si\u0119 drobnymi przyjemno\u015bciami.\n\n\"Zabiegani, uwik\u0142ani\" to utw\u00f3r oboj\u0119tny do wieku i czasu, kt\u00f3ry przemawia przede wszystkim do ludzkich warto\u015bci i d\u0105\u017ce\u0144. Brzmienie piosenki sk\u0142ada si\u0119 z mi\u0119kkich, melodyjnych d\u017awi\u0119k\u00f3w, kt\u00f3rych dynamizm wzrasta wraz z narracj\u0105 tekstu. To jedna z wielu piosenek, kt\u00f3ra zyska\u0142a uznanie s\u0142uchaczy w skali kraju, dzi\u0119ki swojej uniwersalno\u015bci i niebanalnym tre\u015bciom." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Wiatr od Klimczoka wykonawcy Stan Borys z albumu The Best - Spacer dzik\u0105 pla\u017c\u0105" + }, + { + "role": "assistant", + "content": "\"Wiatr od Klimczoka\" to utw\u00f3r z repertuaru polskiego piosenkarza i kompozytora Stanis\u0142awa Guzika, bardziej znany pod swoim artystycznym pseudonimem Stan Borys. Utw\u00f3r ten pochodzi z albumu \"The Best - Spacer dzik\u0105 pla\u017c\u0105\" i cieszy si\u0119 du\u017c\u0105 popularno\u015bci\u0105 i uznaniem w Polsce.\n\nUtw\u00f3r \"Wiatr od Klimczoka\" charakteryzuje si\u0119 melodyjnym wokalem Borysa oraz \u0142agodnym, gitarowym brzmieniem. Tekst piosenki opowiada o ulubionej g\u00f3rskiej \u015bcie\u017cce, kt\u00f3r\u0105 Borys uwielbia przemierza\u0107. Stan Borys, kt\u00f3ry w swojej tw\u00f3rczo\u015bci cz\u0119sto korzysta\u0142 z motyw\u00f3w natury i krajobrazu, w tym utworze ukazuje pi\u0119kno g\u00f3rskiego szlaku i oddaje ho\u0142d g\u00f3rom.\n\n\"Wiatr od Klimczoka\" to utw\u00f3r, kt\u00f3ry przyci\u0105ga uwag\u0119 swoj\u0105 prostot\u0105 i pi\u0119knym wykonaniem. Utw\u00f3r ten jest uwa\u017cany za jedn\u0105 z najlepszych piosenek w repertuarze Stanis\u0142awa Guzika, kt\u00f3ry pozostaje jednym z najwa\u017cniejszych artyst\u00f3w polskiej muzyki piosenkowej." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Zata\u0144czymy na mo\u015bcie wykonawcy Czerwony Tulipan z albumu Olsztyn kocham" + }, + { + "role": "assistant", + "content": "\"Zata\u0144czymy na mo\u015bcie\" to folkowa piosenka pochodz\u0105ca z albumu \"Olsztyn kocham\" polskiej grupy muzycznej Czerwony Tulipan. Utw\u00f3r charakteryzuje si\u0119 melodyjnym brzmieniem, typowym dla muzyki folkowej oraz charakterystycznym, porywaj\u0105cym rytmem.\n\nTekst piosenki opowiada o niesamowitym uczuciu, jakie towarzyszy ludziom, kt\u00f3rzy zata\u0144cz\u0105 przez chwil\u0119 na mo\u015bcie. Utw\u00f3r porusza tak\u017ce tematyk\u0119 mi\u0142o\u015bci i pozytywnych emocji zwi\u0105zanych z nimi.\n\n\"Zata\u0144czymy na mo\u015bcie" + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Bukowina I wykonawcy Wolna Grupa Bukowina z albumu Z\u0142ota Kolekcja" + }, + { + "role": "assistant", + "content": "\"Bukowina I\" to utw\u00f3r pochodz\u0105cy z albumu \"Rzekoma I\" polskiej grupy muzycznej Wolna Grupa Bukowina. Utw\u00f3r ten pojawi\u0142 si\u0119 r\u00f3wnie\u017c na sk\u0142adance \"Z\u0142ota Kolekcja\". Jest to utw\u00f3r o charakterze balladowym, o z\u0142o\u017conej melodyjnej strukturze.\n\nTekst piosenki odnosi si\u0119 do historii Bukowiny Tatrza\u0144skiej - jednej z najpi\u0119kniejszych krain w Polsce, kt\u00f3ra sta\u0142a si\u0119 azylem dla uchod\u017ac\u00f3w narod\u00f3w Galicji podczas pierwszej wojny \u015bwiatowej. W tek\u015bcie piosenki zosta\u0142a uchwycona historia tego regionu, przyrody oraz historie dawnych mieszka\u0144c\u00f3w i w\u0119drowc\u00f3w.\n\nW utworze w zwyk\u0142ych s\u0142owach ukazane s\u0105 realia \u017cycia ludzi mieszkaj\u0105cych w g\u00f3rach, z pejza\u017cami i natur\u0105 zaprezentowanymi w spos\u00f3b bardzo poetycki. Klimat utworu tworzy tak\u017ce charakterystyczna i skomplikowana melodia, uzupe\u0142niona o partie g\u0119stego brzmienia gitar oraz instrument\u00f3w perkusyjnych. \n\n\"Bukowina I\" to utw\u00f3r, kt\u00f3ry \u0142\u0105czy w sobie inspiracje kultur\u0105 i tradycj\u0105 oferuj\u0105c pi\u0119kny, nostalgiczny utw\u00f3r z pozostaj\u0105cym w pami\u0119ci oraz unikalnym brzmieniem. To jedna z charakterystycznych piosenek grupy Wolna Grupa Bukowina, kt\u00f3ra zyska\u0142a uznanie i szacunek w\u015br\u00f3d mi\u0142o\u015bnik\u00f3w polskiej muzyki folkowej." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Pigs (Three Different Ones) wykonawcy Pink Floyd z albumu Animals" + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Vosstanie Roda wykonawcy Arkona z albumu Vo Slavu Velikim" + }, + { + "role": "assistant", + "content": "\"Pigs (Three Different Ones)\" to utw\u00f3r rockowej grupy Pink Floyd pochodz\u0105cy z albumu \"Animals\", kt\u00f3ry ukaza\u0142 si\u0119 w 1977 roku. Jest to jedna z najbardziej znanych piosenek z albumu \"Animals\" i w og\u00f3le z ca\u0142ej dyskografii zespo\u0142u. \n\nTekst utworu opowiada o trzech r\u00f3\u017cnych osobach, z kt\u00f3rych ka\u017cda reprezentuje inny typ cz\u0142owieka. Tekst jest krytyk\u0105 zachowa\u0144 cz\u0142owieka wobec innych ludzi i przyrody, a tak\u017ce drobiazgowym opisem cech i zachowa\u0144, kt\u00f3re w\u0142a\u015bnie to typuj\u0105. Przy tym Pink Floyd r\u00f3wnie\u017c niuansowo opisuj\u0105 zwierz\u0119cy i \u015bwi\u0144ski charakter takich ludzkich postaw.\n\nLiczne partie instrumentalne, w tym sol\u00f3wki Davida Gilmoura, wprowadzaj\u0105 wyj\u0105tkowy klimat utworu. Charakterystyczne brzmienie gitary, fortepianu oraz partii saksofonu sprawia, \u017ce utw\u00f3r ten idealnie wpisuje si\u0119 w stylistyk\u0119 Pink Floyd, z jednoczesnym naciskiem na spo\u0142eczno-polity" + }, + { + "role": "assistant", + "content": "\"Vosstanie Roda\" to utw\u00f3r zespo\u0142u Arkona, pochodz\u0105cy z albumu \"Vo Slavu Velikim\" z 2005 roku. Zesp\u00f3\u0142 Arkona to rosyjska grupa muzyczna, \u0142\u0105cz\u0105ca elementy folk metalu i black metalu.\n\nUtw\u00f3r \"Vosstanie Roda\" charakteryzuje si\u0119 mrocznym brzmieniem, growlingiem oraz charakterystycznymi wokalami folkowymi Mariny \"Scream\" Sobolewskiej. Tekst utworu opowiada o wierzeniach s\u0142owia\u0144skich oraz o historii i dumie s\u0142owia\u0144skiego narodu.\n\nW warstwie muzycznej utw\u00f3r charakteryzuje si\u0119 g\u0119stym brzmieniem, z\u0142o\u017conymi partiami perkusji, gitary oraz d\u017awi\u0119kami folkowych instrument\u00f3w, takich jak dudy i skrzypce. Arkona jest znana z unikalnego brzmienia, kt\u00f3re \u0142\u0105czy r\u00f3\u017cne style muzyczne.\n\n\"Vosstanie Roda\" to utw\u00f3r, kt\u00f3ry \u0142\u0105czy w sobie mroczne i mocne brzmienie z poetyckimi tekstami, kt\u00f3re poruszaj\u0105 wa\u017cne tematy zwi\u0105zane z kultur\u0105 i histori\u0105 S\u0142owian. To jedna z najbardziej znanych i cenionych piosenek zespo\u0142u Arkona, kt\u00f3ra przyci\u0105ga uwag\u0119 nie tylko fan\u00f3w muzyki folk metalowej, ale tak\u017ce ludzi zainteresowanych histori\u0105 i kultur\u0105 S\u0142owia\u0144sk\u0105." + }, + { + "role": "user", + "content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Coffin Fodder wykonawcy Cradle Of Filth z albumu Nymphetamine" + }, + { + "role": "assistant", + "content": "\"Coffin Fodder\" to utw\u00f3r z albumu \"Nymphetamine\" brytyjskiego zespo\u0142u Cradle Of Filth. To death-metalowe brzmienie z elementami black metalu i gotyckiego rocka. \n\nTekst utworu to prowokacyjne po\u0142\u0105czenie j\u0119zyka poetyckiego z drastycznymi opisami \u015bmierci i ciemn\u0105 estetyk\u0105, charakterystyczn\u0105 dla tw\u00f3rczo\u015bci Cradle Of Filth. \n\n\"Coffin Fodder\" opowiada histori\u0119 mordercy zabijaj\u0105cego kobiety i wk\u0142adaj\u0105cego ich cia\u0142a do trumien, aby zaspokoi\u0107 swoje mroczne i okrutne pragnienia. To utw\u00f3r pe\u0142en brutalnych opis\u00f3w, kt\u00f3rych celem jest szokowanie i wywo\u0142anie wstr\u0119tu w s\u0142uchaczu. \n\nPod wzgl\u0119dem muzycznym, \"Coffin Fodder\" charakteryzuje si\u0119 szybkim tempem, ci\u0119\u017ckimi riffami gitary i intensywnymi partiami perkusyjnymi. Utw\u00f3r jest jednym z bardziej ekstremalnych utwor\u00f3w zespo\u0142u Cradle Of Filth, co czyni go atrakcyjnym dla mi\u0142o\u015bnik\u00f3w mocnej i agresywnej muzyki metalowej." } ] \ No newline at end of file diff --git a/settings.json b/settings.json index f53eccd..702fab8 100644 --- a/settings.json +++ b/settings.json @@ -1,314 +1,369 @@ { - "fabryczka": "Fabryczka to miejsce w odzi. Waciciel skuszony hajsem razem ze wsppracownikiem wzili na sesj od kobiety ma. Sesja non stop ponad 24h. Sesja w ramach \"kary za zdrad\". Kontakt mia by z kobiet telefoniczny i sowo bezpieczestwa u niej. W pewnym momencie ulegy im si popsu. Zadzwonili do kobiety. Nie odebraa. Napisali sms. Odpisaa e \"Nie on tak zawsze. Kontynuujcie\". Pono mimo to zrobili przerw i skoczyli po buk i serek Hochland dla ulegego w ramach after/middle care'u. Ulegy spierdoli im nago oknem z \"sesji\". Std te wzi곹 si w Diasporze dzkiej kwestia serka Hochland. Po caej akcji pan 'Fabryczka' straszy par prawnikami, tumaczc e 'sta go na dobrych'. Partner Czarnej to kumpel fabryczki ktry te ma na koncie pare swoich akcji.", + "fabryczka": "Fabryczka to miejsce w Łodzi. Właściciel skuszony hajsem razem ze współpracownikiem wzięli na sesję od kobiety męża. Sesja non stop ponad 24h. Sesja w ramach \"kary za zdradę\". Kontakt miał być z kobietą telefoniczny i słowo bezpieczeństwa u niej. W pewnym momencie uległy im się popsuł. Zadzwonili do kobiety. Nie odebrała. Napisali sms. Odpisała że \"Nie on tak zawsze. Kontynuujcie\". Ponoć mimo to zrobili przerwę i skoczyli po bułkę i serek Hochland dla uległego w ramach after/middle care'u. Uległy spierdolił im nago oknem z \"sesji\". Stąd też wzięłą się w Diasporze łódzkiej kwestia serka Hochland. Po całej akcji pan 'Fabryczka' straszył parę prawnikami, tłumacząc że 'stać go na dobrych'. Partner Czarnej to kumpel fabryczki który też ma na koncie pare swoich akcji.", "word_reactions": { "fabryczka": [ 1103376650487484556, 10, 0, - true - ], - "hammer": [ - "Hammer? Chuj o zotym serduszku? Popierdolony w idealnych proporcjach do czystego serduszka? Legendarny zbanowany admin Kinky Little Discord? Legendarny kochanek? \"Bardzo fajny sadysta\":tm: Waciciel \"Domu ktry czyni pijanym\"? \nNie znam. Nie syszaem", - 15.0, - 0, + true, false ], - "chujzoty": [ - "Eeeee.... Szefie... kto ci woa! Wskazuje na Hammera", + "hammer": [ + "Hammer? Chuj o złotym serduszku? Popierdolony w idealnych proporcjach do czystego serduszka? Legendarny zbanowany admin Kinky Little Discord? Legendarny kochanek? \"Bardzo fajny sadysta\":tm: Właściciel \"Domu który czyni pijanym\"? \nNie znam. Nie słyszałem", 15.0, 0, + false, + false + ], + "chujzłoty": [ + "Eeeee.... Szefie... ktoś cię woła! Wskazuje na Hammera", + 15.0, + 0, + false, false ], "indie": [ - "Indie? *Wyciga rewolwerow wyrzutni taktycznych bomb jdrowych* Gdzie??? *Zaczyna si maniakalnie mia*", + "Indie? *Wyciąga rewolwerową wyrzutnię taktycznych bomb jądrowych* Gdzie??? *Zaczyna się maniakalnie śmiać*", 15.0, 0, + false, false ], "hindus": [ - "Hindus? Gdzie.... *Wyciga spod lady ciki miotacz pomieni i zaczyna si maniakalnie mia*", + "Hindus? Gdzie.... *Wyciąga spod lady ciężki miotacz płomieni i zaczyna się maniakalnie śmiać*", 15.0, 0, + false, false ], "chuj": [ - "Eeeee.... Szefie... kto ci woa! Wskazuje na Hammera", + "Eeeee.... Szefie... ktoś cię woła! Wskazuje na Hammera", 15.0, 0, + false, false ], "Sowa": [ - "Czy ja usyszaem Sowa? Jedne z lepszych cyckw po tej stronie wewntrznej sfery. Ale ja tego nie mwiem", + "Czy ja usłyszałem Sowa? Jedne z lepszych cycków po tej stronie wewnętrznej sfery. Ale ja tego nie mówiłem", 100000.0, 0, + false, false ], - "je": [ - "*wiato ganie i cay bar nagle zostaje przemalowany w soneczniki.* Ki dia... *wiato znowu ganie i pojawiaj si psychodeliczne animacje* Jeu. Ogranicz. *Po kolejnym bysku wszystko jest anime chibi style* Swoj... *I wraca do normy* Kreatywno. *Wzdycha* I tak jedyna chemia jak tu widz to domestos... *Krci gow*", + "jeż": [ + "*Światło gaśnie i cały bar nagle zostaje przemalowany w słoneczniki.* Ki dia... *Światło znowu gaśnie i pojawiają się psychodeliczne animacje* Jeżu. Ogranicz. *Po kolejnym błysku wszystko jest anime chibi style* Swoją... *I wraca do normy* Kreatywność. *Wzdycha* I tak jedyna chemia jaką tu widzę to domestos... *Kręci głową*", 15.0, 0, + false, false ], "savil": [ - "*Znikd zaczyna by sycha muzyk. Conjurer nuci* There must be some way out of here... Said the joker to the thief...", + "*Znikąd zaczyna być słychać muzykę. Conjurer nuci* There must be some way out of here... Said the joker to the thief...", 15.0, 0, + false, false ], "zinnejbajki": [ - "ZInnejBajki? Nie wcale nie ywi si krwi. To pogoski. *Nieudolnie chowa za plecami plastikowy pakiet z duym napisem AB RH+ do lodwki na drinki*", + "ZInnejBajki? Nie wcale nie żywi się krwią. To pogłoski. *Nieudolnie chowa za plecami plastikowy pakiet z dużym napisem AB RH+ do lodówki na drinki*", 15.0, 0, + false, false ], "Bluszcz": [ - "Bluszcz? *widocznie blednie i cofa si o krok, dwustukilowy Elemental robi si nagle taaaaki malutki* Nieeee.... Wcaaaale si jej nie boje.... *Szybko ucieka za bar polerowa nerwowo szklanki* W ogle nie jest straszna *Ostatnie zdanie brzmi jak pisk*", + "Bluszcz? *widocznie blednie i cofa się o krok, dwustukilowy Elemental robi się nagle taaaaki malutki* Nieeee.... Wcaaaale się jej nie boje.... *Szybko ucieka za bar polerować nerwowo szklanki* W ogóle nie jest straszna *Ostatnie zdanie brzmi jak pisk*", 15.0, 0, + false, false ], "jaeger": [ - "Jaeger? *W tle zaczyna gra opening z Attack on the Titan* Na pnocy siedzi, na te no... Pieroki bezglutenowe poluje. Odwany chop. *kiwa gow z szacunkiem jaki tylko owca moe wobec innego owcy mie*", + "Jaeger? *W tle zaczyna grać opening z Attack on the Titan* Na północy siedzi, na te no... Pierożki bezglutenowe poluje. Odważny chłop. *kiwa głową z szacunkiem jaki tylko łowca może wobec innego łowcy mieć*", 15.0, 0, + false, false ], "lena": [ - "Lena? Nie nie miaem NIC wsplnego ze znikniciem... A czekaj - o ktr z osb zniknitych pytasz? *Zaczyna nuci* Boogie ugi, znikn wrgi", + "Lena? Nie nie miałem NIC wspólnego ze zniknięciem... A czekaj - o którą z osób znikniętych pytasz? *Zaczyna nucić* Boogie ługi, znikną wrógi", 15.0, 0, + false, false ], "rafikowy": [ - "Rafikowy? *wyamuje kostki* Jak masz PROBLEM z tym super dzieciakiem - to masz problem ze mn. I reszt Nocnej Zmiany. *wali pici w st* Ka-pe-wu?", + "Rafikowy? *wyłamuje kostki* Jak masz PROBLEM z tym super dzieciakiem - to masz problem ze mną. I resztą Nocnej Zmiany. *wali pięścią w stół* Ka-pe-wu?", 15.0, 0, + false, false ], "kurwa": [ - "Kurwa? Ale ktra... Ta mityczna czy Toka?", + "Kurwa? Ale która... Ta mityczna czy Toćka?", 15.0, 0, + false, false ], "shila": [ - "Shila? Instruktorka aerobiku. Takiego nago. Z elektrod w tyku... A i robi takie sodkie *roar*. No normalnie a si chc odpowiedzie *kici, kici*", + "Shila? Instruktorka aerobiku. Takiego nago. Z elektrodą w tyłku... A i robi takie słodkie *roar*. No normalnie aż się chcę odpowiedzieć *kici, kici*", 15.0, 0, + false, false ], "mienco": [ - "*Wyciga kawa krwawicego krliczego udka* Frecia, Frecia, Frecia... kici, kici, ta ta.... *wiato ganie na sekundd i po tym jak si zapala cay bar jest uwalony krwi* Za kadym razem *wzdycha*", + "*Wyciąga kawał krwawiącego króliczego udka* Frecia, Frecia, Frecia... kici, kici, taś taś.... *Światło gaśnie na sekunddę i po tym jak się zapala cały bar jest uwalony krwią* Za każdym razem *wzdycha*", 15.0, 0, + false, false ], "tatarek": [ "Tatarek? Nie dramatyzuj....", 15.0, 0, + false, false ], "krowa": [ - "Krwka? Nie dramatyzuj....", + "Krówka? Nie dramatyzuj....", 15.0, 0, + false, false ], - "krwka": [ - "Krwka? Nie dramatyzuj....", + "krówka": [ + "Krówka? Nie dramatyzuj....", 15.0, 0, + false, false ], "cielak": [ - "Krwka? Nie dramatyzuj....", + "Krówka? Nie dramatyzuj....", 15.0, 0, + false, false ], "cielaczek": [ - "Krwka? Nie dramatyzuj....", + "Krówka? Nie dramatyzuj....", 15.0, 0, + false, false ], "jessenia": [ - "Jessenia? Jak przysza tu w rowej pidamie z uszkami to nawet nie mrugnem okiem. Te oczy.... No ale jaki debil J prowokowa mwic \"Zdominuj mnie\" Akurat miaa dobry humor wic przey - ale po 115.0 sekundach by ju na \"Tak Pani, przepraszam e zajem czas Pani\" Respect dla kobitki", + "Jessenia? Jak przyszła tu w różowej pidżamie z uszkami to nawet nie mrugnąłem okiem. Te oczy.... No ale jakiś debil Ją prowokował mówiąc \"Zdominuj mnie\" Akurat miała dobry humor więc przeżył - ale po 115.0 sekundach był już na \"Tak Pani, przepraszam że zająłem czas Pani\" Respect dla kobitki", 15.0, 0, + false, false ], "enterix": [ - "Enterix? Chodzca encyklopedia sprztu BDSM... Jeli On o czym nie sysza to to nie istnieje.", + "Enterix? Chodząca encyklopedia sprzętu BDSM... Jeśli On o czymś nie słyszał to to nie istnieje.", 15.0, 0, + false, false ], "aswerus": [ - "Aswerus? Bardzo miy czowiek. Bardzo si stara by miy. Szacun - ja nawet nie prbuje.", + "Aswerus? Bardzo miły człowiek. Bardzo się stara być miły. Szacun - ja nawet nie próbuje.", 15.0, 0, + false, false ], "szeherezada": [ - "Szeherezada? BDSMowa Mata Hari. Tylko na tyle cwana e zdecydowanie lepiej skoczy.", + "Szeherezada? BDSMowa Mata Hari. Tylko na tyle cwana że zdecydowanie lepiej skończy.", 15.0, 0, + false, false ], "szehera": [ - "Szeherezada? BDSMowa Mata Hari. Tylko na tyle cwana e zdecydowanie lepiej skoczy.", + "Szeherezada? BDSMowa Mata Hari. Tylko na tyle cwana że zdecydowanie lepiej skończy.", 15.0, 0, + false, false ], "szechera": [ - "Szeherezada? BDSMowa Mata Hari. Tylko na tyle cwana e zdecydowanie lepiej skoczy.", + "Szeherezada? BDSMowa Mata Hari. Tylko na tyle cwana że zdecydowanie lepiej skończy.", 15.0, 0, + false, false ], "orja": [ - "Orja? Nie wkurzamy goreaskich kajir. Mona batem dosta:D", + "Orja? Nie wkurzamy goreańskich kajir. Można batem dostać:D", 15.0, 0, + false, false ], "khattaw": [ - "*Zza ciany zaczyna dobywa si przytumione dobre techenko. Conjurer blednie* Nie.... znowu ona.... Khaaaa *Mijaj 72 godziny nieustajcego raveu. Khat nadal taczy. Elemental ley na pododze pod kroplwk*", + "*Zza ściany zaczyna dobywać się przytłumione dobre techenko. Conjurer blednie* Nie.... znowu ona.... Khaaaa *Mijają 72 godziny nieustającego raveu. Khat nadal tańczy. Elemental leży na podłodze pod kroplówką*", 15.0, 0, + false, false ], "kwadraty": [ - "Kwadraty? Przemiy czowiek. Mylaem e jak go trzy napalone laski napady to bd musia wkroczy... Tak go lay... A on potem cay w skowronkach. Szacun dla gocia. Zajebisty ziomek.", + "Kwadraty? Przemiły człowiek. Myślałem że jak go trzy napalone laski napadły to będę musiał wkroczyć... Tak go lały... A on potem cały w skowronkach. Szacun dla gościa. Zajebisty ziomek.", 15.0, 0, + false, false ], "jules": [ - "Jules? wietna diablica. Zaraz... Jak to szo... All is dust? Krew dla boga krwi? Poka cycki dla Slaanesh? Iron within, iron without? Co w ten dese.", + "Jules? Świetna diablica. Zaraz... Jak to szło... All is dust? Krew dla boga krwi? Pokaż cycki dla Slaanesh? Iron within, iron without? Coś w ten deseń.", 15.0, 0, + false, false ], "elokwentna": [ - "O matko. Znowu ta dyskusja? Hammer ma stary sownik gdzie elokwentna i pyskata s praktycznie synonimami. Jedyna rnica e swojej ulegej mona za bycie pyskatym da po dupie.", + "O matko. Znowu ta dyskusja? Hammer ma stary słownik gdzie elokwentna i pyskata są praktycznie synonimami. Jedyna różnica że swojej uległej można za bycie pyskatym dać po dupie.", 15.0, 0, + false, false ], "elokwencja": [ - "O matko. Znowu ta dyskusja? Hammer ma stary sownik gdzie elokwentna i pyskata s praktycznie synonimami. Jedyna rnica e swojej ulegej mona za bycie pyskatym da po dupie.", + "O matko. Znowu ta dyskusja? Hammer ma stary słownik gdzie elokwentna i pyskata są praktycznie synonimami. Jedyna różnica że swojej uległej można za bycie pyskatym dać po dupie.", 15.0, 0, + false, false ], "pyskata": [ - "Pyskata? A teraz mwisz o Tatarku czy o tej drugiej? *Zauwaa spojrzenie Hammera* Taaaak o Tatarku.", + "Pyskata? A teraz mówisz o Tatarku czy o tej drugiej? *Zauważa spojrzenie Hammera* Taaaak o Tatarku.", 15.0, 0, + false, false ], "kld": [ - "KLD? Burdel wikszy ni u Hammera.... Chocia ten ju sprzta.... Burdel wikszy ni u Hammera zanim zacz sprzta.", + "KLD? Burdel większy niż u Hammera.... Chociaż ten już sprząta.... Burdel większy niż u Hammera zanim zaczął sprzątać.", 15.0, 0, + false, false ], "burdel": [ - "Oooo... Widz e Hammera odwiedzie. Tylko mu nie mw eby firanki zmieni.", + "Oooo... Widzę że Hammera odwiedziłeś. Tylko mu nie mów żeby firanki zmienił.", 15.0, 0, + false, false ], "xo": [ - "Xo? Jejku. Taka maa dziewczynka. A la j mona godzinami. Sam si bym zasapa. No i sznurki adne wie.", + "Xo? Jejku. Taka mała dziewczynka. A lać ją można godzinami. Sam się bym zasapał. No i sznurki ładne wiąże.", 15.0, 0, + false, false ], "ziemniaczek": [ - "May. PODY!!! PSYCHOPAT!!!!! Ahahahahaha..... *Strzela z karabinu maszynowego w sufit*", + "Mały. PODŁY!!! PSYCHOPAT!!!!! Ahahahahaha..... *Strzela z karabinu maszynowego w sufit*", 15.0, 0, + false, false ], - "toka": [ - "Toka? Csiii... Nie tak gono. Wpada, pokazuje cycki - poowa facetw mdleje z powodu niedokrwienia gowy, druga poowa z powodu przekrwienia gwki - a trzecia si bije kto si na ni pierwszy rzuci", + "toćka": [ + "Toćka? Csiii... Nie tak głośno. Wpada, pokazuje cycki - połowa facetów mdleje z powodu niedokrwienia głowy, druga połowa z powodu przekrwienia główki - a trzecia się bije kto się na nią pierwszy rzuci", 15.0, 0, + false, false ], "istoriya": [ - "*Z gonikw zaczyna lecie muzyka podejrzanie przypominajca Disco Polo* Istoriya? Legenda memiarstwa, rka chodzi najebana. Nakurwia memami Na Na Na Na NA NA! *Conjurer rapuje niezbornie wymachujc apkami*", + "*Z głośników zaczyna lecieć muzyka podejrzanie przypominająca Disco Polo* Istoriya? Legenda memiarstwa, ręka chodzi najebana. Nakurwia memami Na Na Na Na NA NA! *Conjurer rapuje niezbornie wymachując łapkami*", 15.0, 0, + false, false ], "panifretka": [ - "*wiato ganie. Z kranw zaczynaj lecie iskry, a woda z wentylatora. Conjurer gono wzdycha.* No tak ONA. Wiedma znowu korki wyjebaa bawic si w loszku jakim szczliwym biedactwem", + "*Światło gaśnie. Z kranów zaczynają lecieć iskry, a woda z wentylatora. Conjurer głośno wzdycha.* No tak ONA. Wiedźma znowu korki wyjebała bawiąc się w loszku jakimś szczęśliwym biedactwem", 15.0, 0, + false, false ], "frecia": [ - "Kochana pluszowa delikatna sadystka *patrzy na Fretk, orientuje si co ta robi* - Nie Frecia prosz nie wpinaj tego penisa do kontaktu, za Fretka, niedobra Sadystka *Nastpuje wybuch snopu iskier i zapada ciemno*", + "Kochana pluszowa delikatna sadystka *patrzy na Fretkę, orientuje się co ta robi* - Nie Frecia proszę nie wpinaj tego penisa do kontaktu, zła Fretka, niedobra Sadystka *Następuje wybuch snopu iskier i zapada ciemność*", 15.0, 0, + false, false ], "wolfram": [ - "A kolega po fachu. Karczmarz ze wsi pod odzi. Warszyce? Warszomin? Co takiego. Spoko ziomek. Coprawda nasza stacja kosmiczna jest wiksza od jego karczmy - ale nie wszystko da si zrobi w polu grawitacyjnym planety. Jeu mwi e jest bardem z naczelnych... No Homo Sapiens w kocu.", + "A kolega po fachu. Karczmarz ze wsi pod Łodzią. Warszyce? Warszomin? Coś takiego. Spoko ziomek. Coprawda nasza stacja kosmiczna jest większa od jego karczmy - ale nie wszystko da się zrobić w polu grawitacyjnym planety. Jeżu mówi że jest bardem z naczelnych... No Homo Sapiens w końcu.", 15.0, 0, + false, false ], "fallain": [ - "Kochana Krwka. Skonno do dramatw i zakrwawiania cian. Jedna z kilku NAPRAWDE srogich masochistek... Ach ta krew :drool:", + "Kochana Krówka. Skłonność do dramatów i zakrwawiania ścian. Jedna z kilku NAPRAWDE srogich masochistek... Ach ta krew :drool:", 15.0, 0, + false, false ], "roar": [ "Kici, kici....", 15.0, 0, + false, false ], "conjurer": [ - "Kto mnie woa? Czego chcia? Jak chcesz pogada to napisz **Conjurer:** i powiedz co masz na myli. Jak chcesz ebym Ci co narysowa napisz **imaginuje sobie** i tak samo. Moge te Ci opowiedzie o fabryczce", - 15.0, + "Kto mnie wołał? Czego chciał? Jak chcesz pogadać to napisz **Conjurer:** i powiedz co masz na myśli. Jak chcesz żebym Ci coś narysował napisz **imaginuje sobie** i tak samo. Moge też Ci opowiedzieć o fabryczce", + 1200.0, 0, + false, false ], - "wita": [ - "wita Ladacznica? Przyjazna osbka. Bardzo. Jak wilk. Z wielkimi kami. Strasznie j lubi. Tak samo nie lubi przemocowcw jak ja i Hammer", + "święta": [ + "Święta Ladacznica? Przyjazna osóbka. Bardzo. Jak wilk. Z wielkimi kłami. Strasznie ją lubię. Tak samo nie lubi przemocowców jak ja i Hammer", 15.0, 0, + false, false ], "ladacznica": [ - "wita Ladacznica? Oj tak. Jeli okazuje si e kto jej nacinie na odcisk zostaje poarty w caoci... Dobra jest.", + "Święta Ladacznica? Oj tak. Jeśli okazuje się że ktoś jej naciśnie na odcisk zostaje pożarty w całości... Dobra jest.", 15.0, 0, + false, false ], "saint": [ - "Saint Harlot? Ten jej umiech. Potrafi nim wyrazi wszystko. Zarwno eby rozmwca si ucieszy i wyluzowa... Jak i zesra ze strachu.", + "Saint Harlot? Ten jej uśmiech. Potrafi nim wyrazić wszystko. Zarówno żeby rozmówca się ucieszył i wyluzował... Jak i zesrał ze strachu.", 15.0, 0, + false, false ], "harlot": [ - "Saint Harlot? Wielkie ky. Wielkie pazury. Puchate miciutkie futerko. Nie naley irytowa. No i przemocowcy znikaj w jej okolicy 'przypadkiem'.", + "Saint Harlot? Wielkie kły. Wielkie pazury. Puchate mięciutkie futerko. Nie należy irytować. No i przemocowcy znikają w jej okolicy 'przypadkiem'.", 15.0, 0, + false, false + ], + "(oj\\.*\\s*){3,}": [ + "Widzę że szykuje się wpierdol. *Przeładowuje ręczną rewolwerową wyrzutnię granatów termojądrowych i szeroko się uśmiecha w kierunku Hammera i Wykidajłów*", + 15.0, + 0, + false, + true ] - - - } -} +} \ No newline at end of file