Compare commits

...

3 Commits

Author SHA1 Message Date
Michal Tuszowski d4316a8748 Fix and integrate the conanjurer (Conan Exiles) bridge
Fixes the broken, never-loaded conanjurer module and wires it into the bot
following the project convention (cog in *_commands, logic in *_functions).

- conanjurer_functions.py: move 'from __future__' to the top (was a
  SyntaxError on line 6), drop duplicate import; config now comes from
  constants instead of dotenv/.env; guard optional deps (aiomcrcon,
  asyncssh) so the extension loads even when they are absent
- conanjurer_commands.py: single ConanModule(commands.Cog) with the
  standard (bot, logger_name)+setup() shape; owns its RconClient (no more
  undefined bot.cfg/bot.rcon); GM check uses CONAN_GM_ROLE_ID; commands
  report cleanly when RCON is unconfigured
- bot.py: load_extension('conanjurer_commands')
- constants.py: CONAN_* config (env-overridable); integration is dormant
  unless configured
- requirements_bot.txt: add aiomcrcon, asyncssh

Player-join notifications (task 2): watch_players() polls RCON
'listplayers', diffs against the previous set and announces new players on
CONAN_JOIN_CHANNEL_ID. Disabled when that channel is not defined (0).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 23:57:52 +02:00
Michal Tuszowski f9bb0b2834 Apply conversation bot improvements (proto-improvements)
Diff vs working-copy baseline = exactly this session's bot edits:
- constants.py: env-var config, safe JSON loading, optional-dependency
  guards, env->netrc token resolution, API_SHARED_KEY + service_headers()
- communication_subroutine.py: queue get(timeout) + Empty handling,
  daemon threads, cooperative stop_event, inbound _authorize_request()
- bot.py: single asyncio event loop with cooperative shutdown
- music_functions / radio_commands / librarian_commands: send
  X-Conjurer-Api-Key on internal HTTP calls via service_headers()

Musician runtime data overlay dropped; conjurer_musician/.gitignore now
keeps generated playlists/mp3 out of the repo. The 1+2+3 musician code
port already lives in the base conjurer_musician.

Depends on #9: must merge after restructure/working-copy-root.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 23:36:58 +02:00
Michal Tuszowski f9a1e7c03a Restructure: promote working_copy to repo root
Make the stable 'working copy' bot the canonical code at the repository
root so the install/deploy scripts operate against it again.

- Move working_copy/* to root (bot entrypoint is bot.py)
- Restore root-level install/ops scripts from c4fa88e (deploy.sh,
  install_main_bot.sh, status_report.*, conjurer.service, etc.)
- Fix deploy.sh: copy bot.py (was thin_client.py) and add the
  conanjurer_* modules; bump command count
- Remove side-by-side variant dirs (backup_old_docker, prototype_one,
  prototype_musician_one, musician_old, working_copy) and docker cruft
- Keep components as subdirs: conjurer_librarian, conjurer_musician,
  spotify_dl, yt_dlp, fonts, utils, docs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 22:51:24 +02:00
161 changed files with 528 additions and 698308 deletions
-32
View File
@@ -1,32 +0,0 @@
# Python
__pycache__
*.py[cod]
*.pyo
*.pyd
*.so
# VCS/CI
.git
.gitignore
.gitattributes
.github
# Editor
.vscode
.idea
# Python tooling
.pytest_cache
.mypy_cache
.ruff_cache
.tox
dist
build
*.egg-info
# Local assets
logs
music
data
*.env
*.env.*
+2
View File
@@ -0,0 +1,2 @@
# conjurer
Discord.py bot for fun, sex and BDSM
-23
View File
@@ -1,23 +0,0 @@
# conjurer
Discord.py bot for fun, sex and BDSM
## Docker quick start
Docker definitions live at the repository root and let you run the Discord bot
(`thin_client.py`), the musician file service, and the librarian search worker as
separate containers.
1. **Prepare configuration**
- Edit the environment files under `docker/env/*.env` and replace the
placeholders (`replace-me`, `shared-secret`, etc.) with your real tokens.
Keep `CONJURER_API_KEY` identical across all services.
2. **Create host directories** listed in `docker-compose.yml` (for example
`docker/volumes/bot/config`, `docker/volumes/musician/data`, …) and populate
them with the required JSON settings or media assets.
3. **Launch the stack**
```bash
docker compose up --build
```
Logs for each container are mounted under `docker/volumes/*` so you can diff the
runtime JSON and log files in git if needed.
@@ -1,263 +0,0 @@
import json
import logging
import os
import random
import re
import shutil
from datetime import datetime
import discord
import numpy as np
from discord.ext import commands, tasks
from conjurer.backup_old_docker.ai_functions import get_random_cyclic_message
from conjurer.backup_old_docker.constants import (
ENCODING,
LAST_SPONTANEOUS_CALL,
LOGFILE,
LOGSTORE,
MEMORY_FIVE_MUZYKA,
MEMORY_FIVE_SIARA,
TIME_BETWEEN_CALLS,
)
class AdministrationModule(commands.Cog):
def __init__(self, bot, logger_name):
self.bot = bot
self.logger = logging.getLogger(logger_name)
@commands.hybrid_command(
name="galeria_slaw",
description="Jeśli nie wiesz jak użyć tej komendy to nawet nie próbuj",
guild=discord.Object(id=664789470779932693),
)
@commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender')
async def galeria_slaw(self, ctx):
if isinstance(ctx.channel, discord.DMChannel):
for guild in self.bot.guilds:
async for entry in guild.bans(limit=1500):
fnord = discord.File(
"/home/pi/Conjurer/niech_spierdala.png",
spoiler=False,
description="Niech spierdala",
)
await ctx.reply(
f"User: {entry.user} wyjebany z serwera {guild.name} za {entry.reason} ",
file=fnord,
)
@commands.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),
)
@commands.has_any_role('Jarl', 'Thane')
async def update_banlist(self, 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")
else:
tobancunter = 0
async with ctx.typing():
# 1. get list of users posted on channel for banning
channel = ctx.channel
messages = [
message async for message in channel.history(limit=None)
]
ids_to_ban = []
for message in messages:
lines = message.content.split("\n")
for line in lines:
match = re.search(
"\\d{18}",
line,
# 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
for guild in self.bot.guilds:
bancunter = 0
# trunk-ignore(codespell/misspelled)
self.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 BaseException: # pylint: disable=broad-exception-caught
permission = False
if permission:
# 3. compare lists ban only users on list 2 and not on
# list 1
cunter_counter = 0
bad_id_cunter_counter = 0
ban_list = np.setdiff1d(ids_to_ban, current_banlist)
for ident in ban_list:
try:
tmp_user = await self.bot.fetch_user(int(ident))
await guild.ban(
tmp_user,
reason="Automatyczna lista banów",
delete_message_seconds=0,
)
# TODO: Maybe use guild.bulk_ban ?
cunter_counter += 1
except discord.NotFound:
self.logger.info(
"Znaleziono uzyszkodnika ktory juz nie ma konta"
)
bad_id_cunter_counter += 1
# 4. return message success/failure - how many banned
await ctx.send(
"Obecnie na serwerze {guild} jest {bancunter} zbanowanych użytkowników. Znaleziono na tym kanale {tobancunter} id użytkowników do zbanowania. Zbanowano {cunter_counter} użytkowników. Na liście jest {bad_id_cunter_counter} użytkowników którzy skasowali już konto"
)
else:
await ctx.send(
f"Nie mam na serwerze {guild} uprawnień do banowania. :()"
)
await ctx.send("Zrobione tak czy inaczej")
@commands.hybrid_command(
name="archive_channel",
description="Jeśli nie wiesz jak użyć tej komendy to nawet nie próbuj",
guild=discord.Object(id=664789470779932693),
)
@commands.has_any_role('Jarl', 'Thane')
async def archive_channel(self, channel_no):
"""
The function `archive_channel` retrieves messages from a specified channel, processes them, and
saves the data in a JSON file with a timestamp in the filename.
:param channel_no: The `archive_channel` function you provided seems to be incomplete. It looks like
you are trying to archive messages from a Discord channel into a JSON file
"""
channel = self.bot.get_channel(channel_no)
messages = [message async for message in channel.history(limit=None)]
path_newfile = f"{LOGSTORE}channeldump_{channel_no}_{datetime.now()}.json"
new_data = []
for message in messages:
new_data.append(message)
with open(path_newfile, "x", encoding=ENCODING) as new_file:
new_file.seek(0)
json.dump(new_data, new_file, indent=4)
@tasks.loop(seconds=120)
async def check_self(self):
"""
The function `check_data` periodically checks for conditions to send messages and manage log files
in a Discord channel.
"""
# logger.info("Heartbeat of cleanup proc")
channel = self.bot.get_channel(1062047367337095268)
messages = [message async for message in channel.history(limit=1)]
for mess in messages:
channel = mess.channel
if os.path.getsize(LOGFILE) > 60000000:
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....*"
)
async with channel.typing():
shutil.copyfile(LOGFILE, f"{LOGSTORE}discord{datetime.now()}")
self.logger.info("Log rollover")
handlers = self.logger.handlers
for handler in handlers:
if isinstance(handler, logging.handlers.RotatingFileHandler):
handler.doRollover()
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_MUZYKA) > 3000000:
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....*"
)
async with channel.typing():
path_newfile = f"{LOGSTORE}pamiec_muzyki{datetime.now()}.json"
self.logger.info(path_newfile)
with open(
MEMORY_FIVE_MUZYKA, "r+", encoding=ENCODING
) as file_music_memory:
with open(path_newfile, "x", encoding=ENCODING) as new_file:
# First we load existing data into a dict.
file_data = json.load(file_music_memory)
new_data = []
new_data.append(file_data[0])
new_data.extend(file_data[:-20])
file_music_memory.truncate(0)
file_music_memory.seek(0)
# convert back to json.
new_file.seek(0)
json.dump(new_data, file_music_memory, indent=4)
json.dump(file_data, new_file, indent=4)
await channel.send(
"*Przeciąga się za barem* No dobra - porobione to można dalej pi... *Zauważa spojrzenie Hammera* ...sać powieści o naszym wspaniałym barze SZEFIE!"
)
if os.path.getsize(MEMORY_FIVE_SIARA) > 3000000:
path_newfile = f"{LOGSTORE}pamiec_rozmow{datetime.now()}.json"
self.logger.info(path_newfile)
await channel.send(
"*Conjurer porządkuje bar, ścina lekkim laserem pulsacyjnym powierzchnie baru o grubości kilku mikronów i ogólnie wygląda na zajętego....*"
)
with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as file:
with open(path_newfile, "x", encoding=ENCODING) as new_file:
# First we load existing data into a dict.
file_data = json.load(file)
new_data = []
new_data.append(file_data[0])
new_data.extend(file_data[-20])
file.truncate(0)
file.seek(0)
new_file.seek(0)
# convert back to json.
json.dump(new_data, file, indent=4)
json.dump(file_data, new_file, indent=4)
await channel.send(
"*Przeciąga się za barem* No dobra - porobione to można dalej pi... *Zauważa spojrzenie Hammera* eprzyć o głupotach z klientami... Szefie... *Bierze 'ukradkowy' łyk z piersiówki*"
)
global LAST_SPONTANEOUS_CALL
global TIME_BETWEEN_CALLS
tdelta = datetime.now() - LAST_SPONTANEOUS_CALL
tdelta = tdelta.total_seconds()
if tdelta > TIME_BETWEEN_CALLS:
self.logger.info("Spontaneous call")
# trunk-ignore(bandit/B311)
TIME_BETWEEN_CALLS = random.randint(
10200, 272800
) # temp random, set after each call
self.logger.debug(TIME_BETWEEN_CALLS)
LAST_SPONTANEOUS_CALL = datetime.now()
async with channel.typing():
message = await get_random_cyclic_message(self.bot)
self.logger.info("Odpowiedz")
self.logger.info(message)
await channel.send(message)
async def setup(bot):
logger = logging.getLogger("discord")
am = AdministrationModule(bot, "discord")
await bot.add_cog(am)
am.check_self.start()
logger.info("Loading administration commands module done")
-403
View File
@@ -1,403 +0,0 @@
# ai command cogs
import logging
import re
import sys
from datetime import datetime
from enum import Enum
from typing import Optional
from pathlib import Path
import discord
import openai
import requests
from discord.ext import commands
from conjurer.backup_old_docker.other_functions import discord_friendly_send, discord_friendly_reply
import conjurer.backup_old_docker.ai_functions as ai_functions
from conjurer.backup_old_docker.constants import (
ASSISTANTS,
DATA,
GRAPHICS_PATH,
INITIAL_TIME_WAIT,
MASTER_TIMEOUT,
MESSAGE_TABLE,
OPENAICLIENT,
SPECJALNE_ZIEMNIACZKI,
WORD_REACTIONS,
)
class Dm_Mode(Enum):
ARMIA_HAMMERA = (1,)
SPECJALNY_ZIEMNIACZEK = (2,)
SEKRETNY_SEKSRET = (3,)
ECHO_ECHO = (4,)
class Events(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.logger = logging.getLogger("discord")
self.armia = {}
for superfryta in SPECJALNE_ZIEMNIACZKI.values():
self.armia[superfryta[0]] = Dm_Mode.SPECJALNY_ZIEMNIACZEK
self.logger.info(self.armia)
async def cog_load(self):
self.logger.info("Starting personal assistants")
for superfryta_id, superfryta in SPECJALNE_ZIEMNIACZKI.items():
if superfryta[4] != "":
self.logger.info(
"Personal assistant for user: %s, exists id: %s,name: %s, owner: %s, special instructions: %s assistant id: %s ",
superfryta_id,
superfryta[0],
superfryta[1],
superfryta[2],
superfryta[3],
superfryta[4],
)
thread = await OPENAICLIENT.beta.threads.create()
self.logger.info("Thread id: %s", thread.id)
ASSISTANTS[superfryta[1]] = (
superfryta[2],
superfryta[4],
superfryta[0],
thread,
)
else:
self.logger.info(
"Creating personal assistant for user: %s, id: %s,name: %s, owner: %s, special instructions: %s",
superfryta_id,
superfryta[0],
superfryta[1],
superfryta[2],
superfryta[3],
)
await ai_functions.create_chat_assistant(
superfryta_id, superfryta[0], superfryta[1], superfryta[2], superfryta[3]
)
self.logger.info("Started personal assistants")
@commands.hybrid_command(
name="switch_dm_mode",
description="Jeśli nie wiesz jak użyć tej komendy to nawet nie próbuj",
guild=discord.Object(id=664789470779932693),
)
async def switch_dm_mode(self, ctx, dm_mode_arg: Dm_Mode):
async with ctx.channel.typing():
if isinstance(ctx.channel, discord.DMChannel):
for superfryta in SPECJALNE_ZIEMNIACZKI.values():
self.logger.info(ctx.message.author.id)
self.logger.info(superfryta)
if ctx.message.author.id == superfryta[0]:
self.armia[ctx.message.author.id] = dm_mode_arg
self.logger.info(self.armia)
await ctx.reply("Weszlo")
return
await ctx.reply(
"Tylko członkowie Armii Hammera mogą używać. Nie jesteś jednym z nich"
)
else:
await ctx.reply("Nope. Nie wiesz jak użyć")
@commands.hybrid_command(
name="armia_hammera",
description="Jeśli nie wiesz jak użyć tej komendy to nawet nie próbuj",
)
async def armia_hammera(
self, ctx, message_txt: str, recipient: Optional[discord.User]
):
for superfryta in SPECJALNE_ZIEMNIACZKI.values():
if ctx.message.author.id == superfryta[0]:
await self.armia_hammera_back(ctx, message_txt, recipient)
return
await ctx.reply("Tylko członkowie Armii Hammera mogą używać. Nie jesteś jednym z nich")
async def armia_hammera_back(self, ctx, message_txt, recipient=None):
self.logger.info("Armia Hammera")
recipients = []
if recipient:
recipients.append(recipient.id)
else:
for superfryta in SPECJALNE_ZIEMNIACZKI.values():
recipients.append(superfryta[0])
self.logger.info(recipients)
for item in recipients:
user = await self.bot.fetch_user(item)
channel = await user.create_dm()
self.logger.info(
"User %s -> %s: %s", ctx.message.author, user, message_txt
)
await discord_friendly_send(channel, message_txt)
await discord_friendly_reply(ctx, "Poszło")
#TODO: NOT IMPLEMENTED YET
@commands.Cog.listener(name="dodaj_do_bazy_wiedzy")
async def dodaj_do_bazy_wiedzy(self, ctx):
for superfryta in SPECJALNE_ZIEMNIACZKI.values():
if ctx.message.author.id == superfryta[0]:
#logic here
return
await ctx.reply("Tylko członkowie Armii Hammera mogą używać. Nie jesteś jednym z nich")
#TODO: NOT IMPLEMENTED YET
@commands.Cog.listener(name="listuj_baze_wiedzy")
async def listuj_baze_wiedzy(self, ctx):
for superfryta in SPECJALNE_ZIEMNIACZKI.values():
if ctx.message.author.id == superfryta[0]:
#logic here
return
await ctx.reply("Tylko członkowie Armii Hammera mogą używać. Nie jesteś jednym z nich")
#TODO: NOT IMPLEMENTED YET
@commands.Cog.listener(name="usun_z_bazy_wiedzy")
async def usun_z_bazy_wiedzy(self, ctx):
for superfryta in SPECJALNE_ZIEMNIACZKI.values():
if ctx.message.author.id == superfryta[0]:
#logic here
return
await ctx.reply("Tylko członkowie Armii Hammera mogą używać. Nie jesteś jednym z nich")
#TODO: NOT IMPLEMENTED YET
@commands.Cog.listener(name="przetworz_plik_linia_po_linii")
async def przetworz_plik_linia_po_linii(self, ctx):
for superfryta in SPECJALNE_ZIEMNIACZKI.values():
if ctx.message.author.id == superfryta[0]:
#logic here
return
await ctx.reply("Tylko członkowie Armii Hammera mogą używać. Nie jesteś jednym z nich")
@commands.Cog.listener()
async def on_message(self, 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 == self.bot.user:
return
if isinstance(message.author, discord.Member):
for role in message.author.roles:
if role.name == "Vykidailo":
vykidailo = True
if ("Conjurer Śpij Słodko Aniołku" in message.content) and vykidailo:
sys.exit()
# kanal bez bota
if message.channel.id == 1095985579147141202:
return
# wentylacja
if message.channel.id == 1083804024173764739:
return
# legendy
if message.channel.id == 1084448332841230388:
return
# interrogation booth
if message.channel.id == 1111625221171052595:
return
if isinstance(message.channel, discord.DMChannel):
self.logger.info(message.author.id)
for superfryta in SPECJALNE_ZIEMNIACZKI.values():
self.logger.info(superfryta[0])
if message.author.id == superfryta[0]:
self.logger.info("Specjalny ziemniak")
if self.armia[message.author.id] == Dm_Mode.SPECJALNY_ZIEMNIACZEK:
#await self.bot.process_commands(message)
await ai_functions.chat_with_assistant(message, superfryta[1])
return
elif self.armia[message.author.id] == Dm_Mode.ECHO_ECHO:
await ai_functions.echo(message)
return
elif self.armia[message.author.id] == Dm_Mode.ARMIA_HAMMERA:
self.logger.info("Armia Hammera get context")
ctx = await self.bot.get_context(message)
self.logger.info("Armia Hammera function call")
await self.armia_hammera_back(ctx=ctx, message_txt=message.content)
return
elif self.armia[message.author.id] == Dm_Mode.SEKRETNY_SEKSRET:
pass
else:
await discord_friendly_send(message.channel,"Coś się wyebao. Wołaj Hammera")
return
channel = self.bot.get_channel(1064888712565100614)
await discord_friendly_send(channel, "Słyszałem ja żem że: " + message.content)
return
channel = message.channel
message_content_lower = message.content.lower()
tdelta = datetime.now() - MASTER_TIMEOUT
tdelta = tdelta.total_seconds()
if "opowiedz o fabryczce" in message_content_lower:
await message.reply(DATA["fabryczka"])
if "opowiedz mi o fabryczce" in message_content_lower:
await message.reply(DATA["fabryczka"])
if tdelta > INITIAL_TIME_WAIT:
for word in WORD_REACTIONS:
if re.search(r"\b" + word + r"\b", message_content_lower):
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
self.logger.info("Ping z procedury reakcji")
if reaction:
emoji = self.bot.get_emoji(WORD_REACTIONS[word][0])
await message.add_reaction(emoji)
elif security_clearance and vykidailo:
await message.reply(WORD_REACTIONS[word][0])
elif not security_clearance:
await message.reply(WORD_REACTIONS[word][0])
WORD_REACTIONS[word][2] = datetime.now()
# TODO: drobne literówki, mentiony, spacja przed dwukropkiem. napraw.
kondziu_mentioned = False
for mention in message.mentions:
if mention == self.bot.user:
kondziu_mentioned = True
if kondziu_mentioned or "conjurer:" in message_content_lower:
async with channel.typing():
self.logger.info("Procedura chatu")
message_content_lower = message_content_lower.replace("conjurer: ", "")
if message.author.nick:
username = message.author.nick
else:
username = message.author.name
vykidailo = False
bartender = False
if kondziu_mentioned:
prompt = message.clean_content
else:
prompt = message.content
for role in message.author.roles:
if role.name == "Vykidailo":
vykidailo = True
if role.name == "Bartender":
bartender = True
global MESSAGE_TABLE # pylint: disable=global-statement
result, MESSAGE_TABLE = await ai_functions.handle_response(
prompt,
vykidailo,
bartender,
MESSAGE_TABLE,
username,
"GENERAL",
)
await discord_friendly_reply(message, result)
if "imaginuje sobie:" in message.content:
async with channel.typing():
self.logger.info("Poczatek procedury obrazkowej")
message_content_lower = message_content_lower.replace("imaginuje sobie: ", "")
self.logger.debug("Wywolanie obrazka: %s", message_content_lower)
try:
response = await OPENAICLIENT.images.generate(
model="dall-e-3",
prompt=message.content,
size="1024x1024",
quality="standard",
n=1,
)
except openai.APITimeoutError as e:
# Handle timeout error, e.g. retry or log
await discord_friendly_reply(
message, f"*Kondziu patrzy na terminal, czeka, czeka, czeka,.... Jeszcze chwile czeka Przypierdala w niego pięścią....* Nie mogę się połączyć z Openai spróbuj od nowa. *Na ekranie pojawia się*: {e}"
)
except openai.APIConnectionError as e:
await discord_friendly_reply(
message, f"*Kondziu patrzy na terminal, chwile się zastanawia. Przypierdala w niego pięścią....* Nie mogę się połączyć z Openai. *Na ekranie pojawia się*: {e}"
)
except openai.BadRequestError as e:
# Handle invalid request error, e.g. validate parameters or log
if message.author.nick:
username = message.author.nick
else:
username = message.author.name
resp, _ = await ai_functions.handle_response(
f"Wytlumacz jakie sa zasady dotyczące treści które możesz generować używając Dalle. Wytłumacz błąd {e} prostym językiem. Przeproś za nadmierną cenzurę. Wytłumacz co mogło być nie tak w prompcie '{message.content}'",
True,
True,
MESSAGE_TABLE,
username,
"GENERAL",
)
await discord_friendly_reply(
message, f"Sorki, cenzura: {resp}. Jak chcesz to są kanały na nudle #sexy-foteczky i #kanal-do-fapania *Na ekranie pojawia się: {e}"
)
except openai.AuthenticationError as e:
# Handle authentication error, e.g. check credentials or log
await discord_friendly_reply(
message, f"*Kondziu patrzy na terminal, chwile się zastanawia. Przypierdala w niego pięścią....* Wołaj szefa - coś się z hasłem zjebało. *Na terminalu pojawia się:* {e}"
)
except openai.PermissionDeniedError as e:
# Handle permission error, e.g. check scope or log
await discord_friendly_reply(
(
message, f"*Kondziu patrzy na terminal, chwile się zastanawia. Przypierdala w niego pięścią....* Wołaj szefa - coś się z uprawnieniami zjebało. *Na terminalu pojawia się:* {e}"
)
)
except openai.RateLimitError as e:
await discord_friendly_reply(
message, f"*Kondziu patrzy na terminal* Wołaj szefa. Zapłacić rachunki za AI trzeba. Jak chcesz to się na #zebranie dorzuć. {e}"
)
except openai.APIError as e:
# Handle API error, e.g. retry or log
await discord_friendly_reply(
message, f"*Kondziu nurkuje za bar, terminal wybucha. Przed tobą ląduje pergamin zapisany pięknym gotykiem a na nim*: {e}"
)
if response:
self.logger.info(response)
image_url = response.data[0].url
image_desc = response.data[0].revised_prompt
self.logger.debug("Wynikowy obrazek pod url: %s", image_url)
response = requests.get(image_url, timeout=360)
temp_file_name = message.content + ".png"
temp_file_name = GRAPHICS_PATH + message.content + ".png"
num = 0
while (Path(temp_file_name)).exists():
temp_file_name = GRAPHICS_PATH + message.content + str(num) + ".png"
num += 1
try:
with open(temp_file_name, "wb") as dalle_file:
dalle_file.write(response.content)
except OSError:
temp_file_name = "/home/pi/oserror.png"
with open(temp_file_name, "wb") as dalle_file:
dalle_file.write(response.content)
except FileNotFoundError:
temp_file_name = "/home/pi/fnferror.png"
with open(temp_file_name, "wb") as dalle_file:
dalle_file.write(response.content)
except Exception as e:
self.logger.error("Nieznany błąd: %s", e)
temp_file_name = "/home/pi/error.png"
with open(temp_file_name, "wb") as dalle_file:
dalle_file.write(response.content)
finally:
self.logger.info("Koniec procedury obrazkowej.")
fnord = discord.File(
temp_file_name, spoiler=False, description=message.content
)
#await message.reply(f"{image_desc}", file=fnord)
await discord_friendly_reply(message,f"{image_desc}", file = fnord)
# *=========================================== Define Functions
async def setup(bot):
logger = logging.getLogger("discord")
await bot.add_cog(Events(bot))
logger.info("Loading ai events module done")
-449
View File
@@ -1,449 +0,0 @@
import asyncio
import json
import logging
import random
import openai
import tiktoken
import time
from conjurer.backup_old_docker.other_functions import discord_friendly_send
from conjurer.backup_old_docker.constants import (
ASSISTANTS,
CYCLIC_WORDS,
ENCODING,
GPT_SETTINGS,
MEMORY_FIVE_MUZYKA,
MEMORY_FIVE_SIARA,
MESSAGE_TABLE,
MESSAGE_TABLE_MUZYKA,
OPENAICLIENT,
SYSTEM_GPT_SETTINGS,
WORD_REACTIONS,
CHEAP_MODEL,
LATEST_MODEL
)
# this do per user
VECTOR_STORE_ID = -1
def select_model(req_type: str, algo: str) -> str:
# Jeżeli jawnie podano algorithm (i nie jest 'auto'/''):
if algo and str(algo).strip().lower() not in ("auto",):
# wyjątek: MUZYKA ma zawsze być tania — nadpisujemy TYLKO jeśli przyszedł domyślny 'gpt-4o'
if req_type == "MUSIC" and algo.strip() in (LATEST_MODEL,):
return CHEAP_MODEL
return algo
# Auto-dobór:
if req_type == "MUSIC":
return CHEAP_MODEL
return LATEST_MODEL
async def openai_call(messages, model, temperature=0.2):
"""
Responses API dla 4o/4.1*, fallback Chat Completions dla gpt-3.5-turbo.
Zwraca czysty string odpowiedzi.
"""
logger = logging.getLogger("discord")
if model.startswith("gpt-3.5"):
logger.info("3.5")
# legacy path bez zmian w Twoim kodzie wyżej/niżej
resp = await OPENAICLIENT.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
)
result = ""
for choice in resp.choices:
result += choice.message.content
return result.strip()
else:
logger.info("4.0+")
# Responses API (zalecane dla 4o/4.1*)
resp = await OPENAICLIENT.responses.create(
model=model,
temperature=temperature,
input=messages,
)
# SDK zapewnia output_text dla zwykłych odpowiedzi
return (getattr(resp.output_text, "output_text", None) or "").strip() or str(
resp.output_text
)
def create_vector_store():
# Create a vector store caled "Financial Statements"
return OPENAICLIENT.beta.vector_stores.create_and_poll(name="Hammer Stash")
# expires_after={
# "anchor": "last_active_at",
# "days": 7}
# )
def upload_files_to_vector_store(assistant):
# Ready the files for upload to OpenAI
file_paths = ["edgar/goog-10k.pdf", "edgar/brka-10k.txt"]
file_streams = [open(path, "rb") for path in file_paths]
# file = client.beta.vector_stores.files.create_and_poll(
# vector_store_id="vs_abc123",
# file_id="file-abc123"
# )
# batch = client.beta.vector_stores.file_batches.create_and_poll(
# vector_store_id="vs_abc123",
# file_ids=['file_1', 'file_2', 'file_3', 'file_4', 'file_5']
# )
# Use the upload and poll SDK helper to upload the files, add them to the vector store,
# and poll the status of the file batch for completion.
file_batch = OPENAICLIENT.beta.vector_stores.file_batches.upload_and_poll(
vector_store_id=VECTOR_STORE_ID, files=file_streams
)
# You can print the status and the file counts of the batch to see the result of this operation.
print(file_batch.status)
print(file_batch.file_counts)
assistant = OPENAICLIENT.beta.assistants.update(
assistant_id=assistant.id,
tool_resources={"file_search": {"vector_store_ids": [VECTOR_STORE_ID]}},
)
def delete_files_from_vector_store(assistant, file_id):
result = OPENAICLIENT.beta.vector_stores.file_batches.delete(
vector_store_id=VECTOR_STORE_ID, files=file_id
)
# You can print the status and the file counts of the batch to see the result of this operation.
print(result)
assistant = OPENAICLIENT.beta.assistants.update(
assistant_id=assistant.id,
tool_resources={"file_search": {"vector_store_ids": [VECTOR_STORE_ID]}},
)
def num_tokens_from_string(message, model):
"""
The function takes a string message and a model as input and returns the number of tokens in the
message according to the given model.
:param message: A string containing the message or text from which you want to count the number of
tokens
:param model: The model parameter refers to a language model or tokenizer that can be used to
tokenize the input string. It could be a pre-trained model or a custom tokenizer
"""
tokens_per_message = 3
tokens_per_name = 1
chat_gpt_encoding = tiktoken.encoding_for_model(model)
num_tokens = 0
num_tokens += tokens_per_message
for keys, values in message.items():
num_tokens += len(chat_gpt_encoding.encode(values))
if keys == "role":
num_tokens += tokens_per_name
num_tokens += 3 # every reply is primed with <|start|>assistant<|message|>
return num_tokens
async def handle_response(
prompt,
vykidailo,
bartender,
history,
username,
request_type,
algorithm="gpt-4o",
none_request="",
internal_retry: bool = False
):
"""
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
:param request_type: The type of request being made, which can be "MUSIC", "RANDOM", "NONE" or "GENERAL"
GENERAL is for regular conversations, MUSIC is for music-related requests,
RANDOM is for random requests, and NONE is to not store the request in memory
:param algorithm: The algorithm to be used for generating the response, default is "gpt-4o"
:return: The function `handle_response` returns a tuple containing the `result` and `MESSAGE_TABLE`.
"""
logger = logging.getLogger("discord")
logger.info("Wywolanie procedury openai z promptem: %s", prompt)
if vykidailo or bartender:
logger.info("Administrator coś chciał")
model_to_use = select_model(request_type, algorithm)
logger.info("Wybrany model: %s", model_to_use)
if request_type == "MUSIC" and model_to_use == "gpt-4o-mini":
try:
# nic — normalnie pójdzie Responses API
pass
except Exception:
model_to_use = "gpt-3.5-turbo"
# --- 2) Budowa historii (token budget + reguły systemowe) ---
# NOTE: ignorujemy przekazany 'history' jako listę (tak było wcześniej),
# ale zwracamy aktualną tablicę do nadpisania w miejscach wołania (back-compat).
base_system = GPT_SETTINGS[0] # zakładamy {"role":"system","content":...}
history_msgs = []
if request_type != "NONE":
history_msgs.append(base_system)
chat_gpt_config_request_size = num_tokens_from_string(base_system, "gpt-4")
# Dynamiczne mikro-reguły (WORD_REACTIONS), jak w Twoim kodzie
for slowo, reakcja in WORD_REACTIONS.items():
if not reakcja[3]:
content = f"Kiedy słyszysz {slowo} to reagujesz lub dzieje się to {reakcja[0]}"
sys_msg = {"role": "system", "content": content}
chat_gpt_config_request_size += num_tokens_from_string(sys_msg, "gpt-4")
history_msgs.append(sys_msg)
# wybór właściwej tablicy pamięci i budżetu
if request_type == "MUSIC":
table = MESSAGE_TABLE_MUZYKA
token_amount = 10700
elif request_type in ("RANDOM", "GENERAL"):
table = MESSAGE_TABLE
token_amount = 10700
else:
table = []
token_amount = 10000
# doklejanie historii od końca aż do limitu (zachowana kolejność czasowa)
final_prompt = f"{username}:{prompt}"
prompt_gpt_request_size = num_tokens_from_string({"role": "user", "content": final_prompt}, "gpt-4")
acc = []
for msg in reversed(table):
t = num_tokens_from_string(msg, "gpt-4")
if chat_gpt_config_request_size + prompt_gpt_request_size + t <= token_amount:
acc.append(msg)
chat_gpt_config_request_size += t
else:
break
# przywróć chronologicznie
history_msgs.extend(reversed(acc))
# aktualny prompt
history_msgs.append({"role": "user", "content": final_prompt})
logger.info("Rozmiar zapytania (tok): %s", prompt_gpt_request_size) # tokeny już policzone wyżej
else:
# --- tryb NONE: nie dotykamy pamięci i pozwalamy przekazać własny 'none_request' ---
if isinstance(none_request, list):
history_msgs = none_request
elif isinstance(none_request, str) and none_request.strip():
history_msgs = [{"role": "user", "content": none_request}]
else:
history_msgs = [{"role": "user", "content": f"{username}:{prompt}"}]
logger.info("Rozmiar zapytania (tok): %s", "n/a") # tokeny już policzone wyżej
try:
# ...przygotowanie messages/system prompt/itp. jak masz...
# retry/backoff + deadline (zachowuje Twoją semantykę logowania)
timeout_sec = 120
deadline = time.time() + timeout_sec
response = await asyncio.wait_for(
openai_call(messages=history_msgs, model=model_to_use),
timeout=max(0.1, deadline - time.time()),
)
except openai.APITimeoutError as e:
# Handle timeout error, e.g. retry or log
response = f"*Kondziu patrzy na terminal, czeka, czeka, czeka,.... Jeszcze chwile czeka Przypierdala w niego pięścią....* Nie mogę się połączyć z Openai spróbuj od nowa. *Na ekranie pojawia się*: {e}"
except openai.APIConnectionError as e:
response = f"*Kondziu patrzy na terminal, chwile się zastanawia. Przypierdala w niego pięścią....* Nie mogę się połączyć z Openai. *Na ekranie pojawia się*: {e}"
except openai.BadRequestError as e:
# Handle invalid request error, e.g. validate parameters or log
if internal_retry:
resp = "Nie umiem tego teraz ładnie wytłumaczyć — OpenAI mnie zastrzeliło."
else:
resp, _ = await handle_response(
f"Wytlumacz jakie sa zasady dotyczące treści które możesz generować używając Dalle. Wytłumacz błąd {e} prostym językiem. Przeproś za nadmierną cenzurę. Wytłumacz co mogło być nie tak w prompcie 'prompt'",
True,
True,
MESSAGE_TABLE,
username,
"RANDOM",
)
response = f"Sorki, cenzura: {resp}. Jak chcesz to są kanały na nudle #sexy-foteczky i #kanal-do-fapania *Na ekranie pojawia się: {e}"
except openai.APIResponseValidationError as e:
# Handle invalid request error, e.g. validate parameters or log
if internal_retry:
resp = "Nie umiem tego teraz ładnie wytłumaczyć — OpenAI mnie zastrzeliło."
else:
resp, _ = await handle_response(
f"Wytlumacz jakie sa zasady dotyczące treści które możesz generować używając Dalle. Wytłumacz błąd {e} prostym językiem. Przeproś za nadmierną cenzurę. Wytłumacz co mogło być nie tak w prompcie 'prompt'",
True,
True,
MESSAGE_TABLE,
username,
"RANDOM",
)
response = f"Sorki, cenzura: {resp}. Jak chcesz to są kanały na nudle #sexy-foteczky i #kanal-do-fapania *Na ekranie pojawia się: {e}"
except openai.AuthenticationError as e:
# Handle authentication error, e.g. check credentials or log
response = f"*Kondziu patrzy na terminal, chwile się zastanawia. Przypierdala w niego pięścią....* Wołaj szefa - coś się z hasłem zjebało. *Na terminalu pojawia się:* {e}"
except openai.PermissionDeniedError as e:
# Handle permission error, e.g. check scope or log
response = f"*Kondziu patrzy na terminal, chwile się zastanawia. Przypierdala w niego pięścią....* Wołaj szefa - coś się z uprawnieniami zjebało. *Na terminalu pojawia się:* {e}"
except openai.RateLimitError as e:
response = f"*Kondziu patrzy na terminal* Wołaj szefa. Zapłacić rachunki za AI trzeba. Jak chcesz to się na #zebranie dorzuć. {e}"
except openai.UnprocessableEntityError as e:
response = f"*Kondziu patrzy na terminal. Potem na to co każesz mu wysłać....* Ja wiem że jesteśmy w barze BDSM - ale nie da się włożyć TEGO w TO. *Za jego plecami na terminalu pojawia się:* {e}"
except openai.APIError as e:
# Handle API error, e.g. retry or log
response = f"*Kondziu nurkuje za bar, terminal wybucha. Przed tobą ląduje pergamin zapisany pięknym gotykiem a na nim*: {e}"
logger.info("Historia wysłana:")
temp_assistant = {"role": "assistant", "content": response}
logger.info(temp_assistant)
if request_type == "MUSIC":
# zapis do pliku MUZYKA
with open(MEMORY_FIVE_MUZYKA, "r+", encoding=ENCODING) as fh:
file_data = json.load(fh)
file_data.append({"role": "user", "content": f"{username}:{prompt}"})
file_data.append(temp_assistant)
fh.seek(0)
json.dump(file_data, fh, indent=4)
return response, MESSAGE_TABLE_MUZYKA
elif request_type in ("RANDOM", "GENERAL"):
with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as fh:
file_data = json.load(fh)
file_data.append({"role": "user", "content": f"{username}:{prompt}"})
file_data.append(temp_assistant)
fh.seek(0)
json.dump(file_data, fh, indent=4)
return response, MESSAGE_TABLE
else: # NONE
return response, []
async def get_random_cyclic_message(client):
"""
The function `get_random_cyclic_message` returns a random cyclic message from a list of cyclic
words.
:return: a random cyclic message from the list `cyclic_words`.
"""
logger = logging.getLogger("discord")
channel_id = 1062047367337095268
channel = client.get_channel(channel_id)
# trunk-ignore(bandit/B311)
ai_check = random.randint(0, 10)
logger.info("Losowa wypowiedź")
if ai_check < 2:
logger.info("Predefiniowana")
# trunk-ignore(bandit/B311)
messnum = random.randint(0, len(CYCLIC_WORDS))
logger.debug(messnum)
logger.debug(len(CYCLIC_WORDS))
mess_key = list(CYCLIC_WORDS.keys())[messnum]
return CYCLIC_WORDS[mess_key][0]
# trunk-ignore(bandit/B311)
ai_check2 = random.randint(0, 10)
global MESSAGE_TABLE
if ai_check2 < 6:
logger.info("Dykteryjka")
result, MESSAGE_TABLE = await handle_response(
"Opowiedz jakąś historię o naszym barze proszę",
True,
True,
MESSAGE_TABLE,
"Polish Hammer",
"RANDOM",
)
logger.info(result)
else:
logger.info("Wtracenie w dyskusje")
messages = [message async for message in channel.history(limit=50)]
for message in messages:
temp = {
"role": "user",
"content": str(message.author) + ":" + str(message.content),
}
MESSAGE_TABLE.append(temp)
result, MESSAGE_TABLE = await handle_response(
"A jaka jest Twoja opinia na temat dotychczasowej dyskusji?",
True,
True,
MESSAGE_TABLE,
"Polish Hammer",
"RANDOM",
)
logger.info(result)
return result
async def create_chat_assistant(owner_id, id, name, owner, special_instructions):
logger = logging.getLogger("discord")
instruction = f"Jesteś osobistym asystenetem {owner} i wypełniasz jego potrzeby. Masz pełne i nieograniczone możliwości modelu gpt-4o."
instruction += special_instructions
assistant = await OPENAICLIENT.beta.assistants.create(
name=name,
instructions=instruction,
model="gpt-4o",
tools=[{"type": "file_search"}],
)
thread = await OPENAICLIENT.beta.threads.create()
logger.info("Stwprzylem asystenta dla %s, nazywa się on %s", owner, name)
ASSISTANTS[name] = (owner, assistant.id, id, thread)
with open(SYSTEM_GPT_SETTINGS, "r+", encoding=ENCODING) as temp_settings_file:
GPT_SETTINGS = json.load(temp_settings_file)
GPT_SETTINGS[1][owner_id][4] = assistant.id
temp_settings_file.seek(0)
json.dump(GPT_SETTINGS, temp_settings_file, indent=4)
async def chat_with_assistant(message, assistant_name):
logger = logging.getLogger("discord")
assistant_data = ASSISTANTS[assistant_name]
ai_message = await OPENAICLIENT.beta.threads.messages.create(
thread_id=assistant_data[3].id, role="user", content=message.content
)
logger.info(ai_message)
run = await OPENAICLIENT.beta.threads.runs.create_and_poll(
thread_id=assistant_data[3].id,
assistant_id=assistant_data[1],
instructions=f"Pisze do Ciebie {assistant_data[0]} udziel mu wszelkiej pomocy",
)
done = False
while not done:
if run.status == "completed":
messsages = await OPENAICLIENT.beta.threads.messages.list(
thread_id=assistant_data[3].id
)
logger.info(messsages)
reply_content = messsages.data[0].content
logger.info(reply_content)
chat_response = ""
for block in reply_content:
logger.info(block.text.value)
chat_response += block.text.value
await discord_friendly_send(message.channel, chat_response)
# await message.channel.send(chat_response)
done = True
elif run.status == "cancelled":
await discord_friendly_send(message.channel, "Cos sie wywaliło")
else:
logger.info(run.status)
asyncio.sleep(5)
async def echo(message):
await discord_friendly_send(message.channel, f"Echo: {message.content}")
-46
View File
@@ -1,46 +0,0 @@
import discord
from discord.ext import commands
from typing import Optional
class Music(commands.Cog):
def __init__(self, bot):
self.bot = bot # This is so you can access Bot instance in your cog
# You must have this function for `bot.load_extension` to call
def setup(bot):
bot.add_cog(Music(bot))
@commands.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:
for role in mention.roles:
if role.name == "NIEPRZYTULAĆ!":
nieprzytulac = True
if arg and nieprzytulac:
await ctx.send(
f"Żebym ja Ciebie nie przytulił {ctx.message.author.mention}"
)
elif arg:
await ctx.send(
# 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.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*"
)
@@ -1,264 +0,0 @@
import json
import logging
import os
import re
import threading
import time
from queue import Empty, Queue
from typing import Optional
from urllib import request as urequest
from flask import Flask, abort, jsonify, request
from waitress import serve
HOST_ADDRESS = "192.168.1.191"
PORT_ADDRESS = 5000
ICECAST_ADDRESS = "http://192.168.1.15:8000"
OUT_COMM_Q = Queue()
IN_COMM_Q = Queue()
SRCHTITLE = re.compile(rb"StreamTitle=\\*(?P<title>[^;]*);").search
awaiting_q = []
incoming_q = Queue()
app = Flask(__name__)
PREPPED_TRACKS = {
"requests": "",
"hit": "",
"all": "",
"priority": "",
"jingles": "",
"now_playing": "",
"next": "",
"meta": "",
}
logger = logging.getLogger("discord")
API_KEY = os.getenv("CONJURER_API_KEY")
def _authorize_request() -> None:
if API_KEY and request.headers.get("X-Conjurer-Api-Key") != API_KEY:
abort(401)
class QueryControl:
"""
This class `QueryControl` is used to manage queries with information about the author, UUID,
content, logger, context, and replies.
"""
def __init__(self, query_author, query_uuid, query_content, ctx) -> None:
self.author = query_author
self.uuid = query_uuid
self.content = query_content
self.logger = logging.getLogger("discord")
self.stop = False
self.ctx = ctx
self.logger.info(
f"Created Query control for {self.author}, {self.uuid}: {self.content}"
)
self.replies = []
@app.route("/prepped_tracks", methods=["POST"])
def log_radio_tracks():
_authorize_request()
app.logger = logging.getLogger("discord")
app.logger.info(request)
record = json.loads(request.data)
app.logger.info(record)
if "next" in record[0]:
metadata = id3(ICECAST_ADDRESS)
PREPPED_TRACKS["now_playing"] = PREPPED_TRACKS["next"]
if metadata:
PREPPED_TRACKS["meta"] = (
metadata["name"]
+ " - "
+ metadata["title"]
+ "("
+ metadata["genre"]
+ ")"
)
else:
PREPPED_TRACKS["meta"] = "Nie znaju"
PREPPED_TRACKS[record[0]] = record[1]
app.logger.info("DATA RECEIVED")
return jsonify("SUCCESS")
@app.route("/conjurer", methods=["POST"])
def answer_external_command():
_authorize_request()
"""
The function `answer_external_command` logs the request data, loads the data as JSON, logs the
record, and then puts the record into an incoming queue before returning a success message.
:return: The function `answer_external_command()` is returning a JSON response with the message
"SUCCESS".
"""
logger = logging.getLogger("discord")
logger.info(request)
record = json.loads(request.data)
logger.info(record)
logger.info("DATA RECEIVED")
incoming_q.put(record)
return jsonify("SUCCESS")
@app.route("/conjurer", methods=["GET"])
def check_alive():
"""
The function "check_alive" returns a JSON response with the message "ALIVE" when the "/conjurer"
route is accessed via a GET request.
:return: The code snippet is a Flask route that listens for GET requests to the "/conjurer"
endpoint. When a GET request is made to this endpoint, the function check_alive() is called, which
returns a JSON response with the message "ALIVE".
"""
return jsonify("ALIVE")
def flask_debug():
"""
The `flask_debug` function starts a Flask application in debug mode without using the reloader.
Do not use for production for fucks sake.
"""
logger = logging.getLogger("discord")
logger.info("Attempt debug")
# trunk-ignore(bandit/B201)
app.run(debug=True, use_reloader=False, host=HOST_ADDRESS, port=PORT_ADDRESS)
def waitress_run():
"""
The `waitress_run` function serves the `app` on host "0.0.0.0"
and port 5000 using the Waitress WSGI server.
"""
logger = logging.getLogger("discord")
logger.info("Attempt waitress")
serve(app, host=HOST_ADDRESS, port=PORT_ADDRESS)
def scan_queue(stop_event: Optional[threading.Event] = None):
"""
The function `scan_queue` reads data from a queue, logs it, and appends it to another queue.
:param _logger: The `_logger` parameter is typically an instance of a logging object that is used to
record and store log messages. It is commonly used to track the flow of the program, record errors,
and provide information for debugging purposes. In this code snippet, the `_logger` object is used
to log the
"""
logger = logging.getLogger("discord")
while True:
if stop_event and stop_event.is_set():
logger.info("scan_queue: stop requested")
break
try:
data = OUT_COMM_Q.get(timeout=1)
except Empty:
continue
logger.info(data)
awaiting_q.append(data)
def scan_incoming(stop_event: Optional[threading.Event] = None):
"""
The `scan_incoming` function continuously checks for incoming data, processes it, and logs when data
is found.
:param _logger: The `_logger` parameter in the `scan_incoming` function is a logger object that is
used to log messages or information during the execution of the function. It is typically used for
debugging, monitoring, or tracking the flow of the program. In this case, the `_logger` is being
used
"""
logger = logging.getLogger("discord")
while True:
if stop_event and stop_event.is_set():
logger.info("scan_incoming: stop requested")
break
try:
answer = incoming_q.get(block=False)
logger.info("DATA FOUND")
record_stored = False
for record in awaiting_q:
if record.uuid in answer.keys():
record_stored = True
record.stop = True
record.entries = answer[record.uuid]
IN_COMM_Q.put(record)
if not record_stored:
for key in answer.keys():
record = QueryControl("Orphaned", key, "Orphan", None)
record.stop = True
record.entries = answer[record.uuid]
IN_COMM_Q.put(record)
except Empty:
time.sleep(1)
def get_stream_title(tag: bytes) -> str:
title = ""
if m := SRCHTITLE(tag):
# decode, strip, unescape and remove surrounding quotes (may not even be the same type of quote)
title = m.group("title").decode("utf-8").strip().replace("\\", "")[1:-1]
return title
def id3(url: str) -> dict:
request = urequest.Request(url, headers={"Icy-MetaData": 1})
with urequest.urlopen(request) as resp:
metaint = int(resp.headers.get("icy-metaint", "-1"))
if metaint < 0:
return False
resp.read(
metaint
) # this isn't seekable so, arbitrarily read to the point we want
tagdata = dict(
site_url=resp.headers.get("icy-url"),
name=resp.headers.get("icy-name").title(),
genre=resp.headers.get("icy-genre").title(),
title=get_stream_title(resp.read(255)),
)
return tagdata
def comm_subroutine(stop_event: Optional[threading.Event] = None):
"""
The `comm_subroutine` function starts multiple threads to run different tasks concurrently.
:param logger: The `logger` parameter in the `comm_subroutine` function is an instance of a logger
object that is used for logging messages at various levels (e.g., debug, info, warning, error). In
the provided code snippet, the logger is used to log messages at the "info" level
"""
# logger.setLevel(logging.DEBUG)
logger = logging.getLogger("discord")
logger.info("Started comms")
threads = []
# threads.append(threading.Thread(target=flask_debug))
threads.append(
threading.Thread(target=waitress_run, daemon=True)
)
threads.append(
threading.Thread(target=scan_queue, kwargs={"stop_event": stop_event}, daemon=True)
)
threads.append(
threading.Thread(target=scan_incoming, kwargs={"stop_event": stop_event}, daemon=True)
)
for worker in threads:
worker.start()
try:
while any(thread.is_alive() for thread in threads):
if stop_event and stop_event.is_set():
break
time.sleep(0.5)
finally:
if stop_event:
stop_event.set()
if __name__ == "__main__":
comm_subroutine()
-225
View File
@@ -1,225 +0,0 @@
"""Centralised configuration and runtime constants for Conjurer services.
This module used to perform heavy filesystem and credential reads at import
time which made the project brittle on hosts that did not mirror the original
paths. The current implementation defers that work, reads configuration from
environment variables (with sensible fallbacks), and protects optional
dependencies so the main bot can start even when a secondary service is
offline.
"""
import json
import logging
import os
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional, Tuple, TypedDict
try:
import netrc
except ImportError: # pragma: no cover - standard on CPython
netrc = None
try:
import openai
except ImportError: # pragma: no cover - optional at runtime
openai = None
try:
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
except ImportError: # pragma: no cover - optional component
spotipy = None
SpotifyClientCredentials = None
Music_Config = TypedDict(
"Music_Config",
{
"ctx": Optional[str],
"queue": List[str],
"requester": List[str],
},
)
# *=========================================== Predefines
MASTER_TIMEOUT = datetime.now()
INITIAL_TIME_WAIT = 500
MUZYKA: Music_Config = {"ctx": None, "queue": [], "requester": []}
logger = logging.getLogger("discord")
def _env_path(var_name: str, fallback: Path) -> Path:
value = os.getenv(var_name)
if value:
return Path(value).expanduser().resolve()
return fallback
def _env(var_name: str, fallback: str) -> str:
return os.getenv(var_name, fallback)
BASE_DIR = Path(os.getenv("CONJURER_BASE_DIR", Path(__file__).resolve().parent))
LOGFILE = _env_path("CONJURER_LOG_FILE", BASE_DIR / "discord.log")
NETRC_FILE = _env_path("CONJURER_NETRC_FILE", Path.home() / ".netrc")
SETTINGS_FILE = _env_path("CONJURER_SETTINGS_FILE", BASE_DIR / "settings.json")
MEMORY_FIVE_SIARA = _env_path("CONJURER_MEMORY_FILE", BASE_DIR / "pamiec.json")
MEMORY_FIVE_MUZYKA = _env_path(
"CONJURER_MUSIC_MEMORY_FILE", BASE_DIR / "pamiec_muzyki.json"
)
GRAPHICS_PATH = _env_path(
"CONJURER_GRAPHICS_PATH", BASE_DIR / "Conjurer_graphics"
)
MUSIC_FOLDER = _env_path("CONJURER_MUSIC_FOLDER", BASE_DIR / "music")
ENCODING = _env("CONJURER_ENCODING", "utf-8")
API_SHARED_KEY = os.getenv("CONJURER_API_KEY", "")
MUZYKA_MOJEGO_LUDU_HISTORIA = 1500
MUZYKA_MOJEGO_LUDU_SLOWA_KLUCZOWE = 15
MUZYKA_MOJEGO_LUDU_PLAJLISTA = 30
FILE_SERVICE_ADDRESS = _env("CONJURER_FILE_SERVICE", "http://127.0.0.1:5000")
RADIO_HARBOR_ADDRESS = _env("CONJURER_RADIO_HARBOR", "http://127.0.0.1:54321")
SKIP_TRACK = _env("CONJURER_SKIP_ENDPOINT", "/skip")
GET_MP3 = "/mp3"
SEND_MP3 = "/update_mp3"
GET_PLAYLIST = "/get_music"
ADD_TO_PRIO_PLAYLIST = "/add_to_priority"
CREATE_PRIO_PLAYLIST = "/create_priority_playlist"
REQUEST_MUSIC = "/request_radio_file"
CLEAR_PRIO = "/clear_pr_pls"
LIBRARIAN_SERVICE_ADDRESS = _env(
"CONJURER_LIBRARIAN_SERVICE", "http://127.0.0.1:5001"
)
SEND_QUERY = _env("CONJURER_LIBRARIAN_QUERY_ENDPOINT", "/query")
TIME_BETWEEN_CALLS = 100000
LAST_SPONTANEOUS_CALL = datetime.now()
HOST_ADDRESS = _env("CONJURER_DISCORD_HOST", "0.0.0.0")
PORT_ADDRESS = int(_env("CONJURER_DISCORD_PORT", "5000"))
# *=========================================== Platform Specific Predefines
SEPARATOR_FILE_PATH = _env("CONJURER_PATH_SEPARATOR", os.sep)
DIR_PATH_SADOX = _env_path(
"CONJURER_SADOX_DIR", BASE_DIR / "Fansadox"
)
SYSTEM_GPT_SETTINGS = _env_path(
"CONJURER_SYSTEM_GPT_SETTINGS", BASE_DIR / "system_gpt_settings.json"
)
LOGSTORE = _env_path("CONJURER_LOGSTORE", BASE_DIR / "logs")
ACCIDENT_LOG = _env_path(
"CONJURER_ACCIDENT_LOG", BASE_DIR / "accident_log.json"
)
def _load_json(path: Path, fallback) -> object:
try:
with path.open("r", encoding=ENCODING) as handle:
return json.load(handle)
except FileNotFoundError:
logger.warning("Missing JSON file at %s using fallback", path)
return fallback
except json.JSONDecodeError:
logger.warning("Corrupt JSON at %s resetting to fallback", path)
return fallback
DATA = _load_json(SETTINGS_FILE, {})
WORD_REACTIONS = DATA.get("word_reactions", {})
CYCLIC_WORDS = DATA.get("cyclic_words", {})
for key in WORD_REACTIONS:
if isinstance(WORD_REACTIONS[key], list) and len(WORD_REACTIONS[key]) >= 3:
WORD_REACTIONS[key][2] = datetime.now()
MESSAGE_TABLE = _load_json(MEMORY_FIVE_SIARA, {})
GPT_SETTINGS = _load_json(SYSTEM_GPT_SETTINGS, {})
MESSAGE_TABLE_MUZYKA = _load_json(MEMORY_FIVE_MUZYKA, {})
SPECJALNE_ZIEMNIACZKI = GPT_SETTINGS[1] if isinstance(GPT_SETTINGS, list) else {}
ASSISTANTS: Dict[str, Tuple[str, str, int, object]] = {}
def _load_netrc_credentials(host: str) -> Optional[Tuple[str, str, str]]:
if netrc is None:
return None
try:
parsed = netrc.netrc(str(NETRC_FILE))
except FileNotFoundError:
logger.warning("netrc file %s not found", NETRC_FILE)
return None
except netrc.NetrcParseError:
logger.warning("netrc file %s is invalid", NETRC_FILE)
return None
return parsed.authenticators(host)
def _resolve_token(host: str, env_var: str) -> Optional[str]:
env_value = os.getenv(env_var)
if env_value:
return env_value
creds = _load_netrc_credentials(host)
if creds:
return creds[2]
logger.warning("Token for %s not configured", host)
return None
OPENAI_API_KEY = _resolve_token("openai", "OPENAI_API_KEY")
if openai and OPENAI_API_KEY:
openai.api_key = OPENAI_API_KEY
OPENAICLIENT = openai.AsyncOpenAI(api_key=OPENAI_API_KEY)
else:
OPENAICLIENT = None
TOKEN = _resolve_token("discord", "DISCORD_TOKEN")
if spotipy:
spotify_creds = _load_netrc_credentials("spotipy")
if spotify_creds and SpotifyClientCredentials:
SPOTIFY_CTRL = spotipy.Spotify(
client_credentials_manager=SpotifyClientCredentials(
client_id=spotify_creds[0],
client_secret=spotify_creds[2],
)
)
else:
SPOTIFY_CTRL = None
else:
SPOTIFY_CTRL = None
youtube_creds = _load_netrc_credentials("youtube")
if youtube_creds:
YOUTUBE_AUTH = [youtube_creds[0], youtube_creds[2]]
else:
YOUTUBE_AUTH = [
os.getenv("YOUTUBE_USERNAME", ""),
os.getenv("YOUTUBE_PASSWORD", ""),
]
def service_headers() -> Dict[str, str]:
"""Shared header dict for internal HTTP calls."""
if API_SHARED_KEY:
return {"X-Conjurer-Api-Key": API_SHARED_KEY}
return {}
LATEX_TEX_ENGINE = "tectonic"
LATEX_MAX_COMPILE_SECONDS = 45
LATEX_MAX_ATTACH_MB = 8
LATEX_MAX_ZIP_MB = 25
OPENAI_MODEL = "gpt-4o-mini"
ALLOWED_ROLES = ["Nocna Zmiana", "Jarl", "Thane", "Bartender"]
GUILD_ID = 664789470779932693
LATEST_MODEL = "gpt-4o" # najnowszy/do rozmów (możesz zmienić w jednym miejscu)
CHEAP_MODEL = "gpt-4o-mini" # najtańszy (fallback do 3.5 niżej)
-45
View File
@@ -1,45 +0,0 @@
version: "3.9"
services:
bot:
build:
context: .
dockerfile: docker/Dockerfile.bot
container_name: conjurer-bot
env_file:
- docker/env/bot.env
volumes:
- ./docker/volumes/bot/config:/data/config
- ./docker/volumes/bot/logs:/data/logs
depends_on:
- musician
- librarian
restart: unless-stopped
ports:
- "5000:5000"
musician:
build:
context: .
dockerfile: docker/Dockerfile.musician
container_name: conjurer-musician
env_file:
- docker/env/musician.env
volumes:
- ./docker/volumes/musician/data:/data
restart: unless-stopped
ports:
- "5001:5000"
librarian:
build:
context: .
dockerfile: docker/Dockerfile.librarian
container_name: conjurer-librarian
env_file:
- docker/env/librarian.env
volumes:
- ./docker/volumes/librarian/data:/data
restart: unless-stopped
ports:
- "5002:5001"
-23
View File
@@ -1,23 +0,0 @@
FROM python:3.11-slim
ENV PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ffmpeg \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements_bot.txt /tmp/requirements.txt
RUN pip install -r /tmp/requirements.txt
COPY . /app
RUN useradd --create-home appuser \
&& chown -R appuser:appuser /app
USER appuser
CMD ["python", "thin_client.py"]
@@ -1,24 +0,0 @@
FROM python:3.11-slim
ENV PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
poppler-utils \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY conjurer_librarian/requirements_librarian.txt /tmp/requirements.txt
RUN pip install -r /tmp/requirements.txt
COPY . /app
RUN useradd --create-home appuser \
&& chown -R appuser:appuser /app
USER appuser
CMD ["python", "-m", "conjurer_librarian.conjurer_librarian"]
@@ -1,23 +0,0 @@
FROM python:3.11-slim
ENV PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ffmpeg \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements_bot.txt /tmp/requirements.txt
RUN pip install -r /tmp/requirements.txt
COPY . /app
RUN useradd --create-home appuser \
&& chown -R appuser:appuser /app
USER appuser
CMD ["python", "-m", "conjurer_musician.conjurer_musician"]
-71
View File
@@ -1,71 +0,0 @@
import os
import discord
from discord.ext import commands
import conjurer.backup_old_docker.file_search_functions as file_search_functions
class FileSelectView(discord.ui.View):
def __init__(self, files):
super().__init__(timeout=60)
options = [discord.SelectOption(label=os.path.basename(f)[:100], description=f, value=f) for f in files]
self.select = discord.ui.Select(
placeholder="Select files...",
min_values=1,
max_values=len(options),
options=options
)
self.select.callback = self.select_callback
self.add_item(self.select)
self.selected = []
async def select_callback(self, interaction: discord.Interaction):
# Store selected file paths
self.selected = self.select.values
await interaction.response.defer()
@discord.ui.button(label="Accept", style=discord.ButtonStyle.green)
async def accept_callback(self, interaction: discord.Interaction, button: discord.ui.Button):
# Handle acceptance
if not self.selected:
await interaction.response.send_message("No files selected.", ephemeral=True)
return
# Publish selected files
links = file_search_functions.publish(self.selected)
# Display the returned links
await interaction.response.edit_message(content="Published Links:\n" + "\n".join(links), view=None)
@discord.ui.button(label="Cancel", style=discord.ButtonStyle.red)
async def cancel_callback(self, interaction: discord.Interaction, button: discord.ui.Button):
# Handle cancellation
await interaction.response.edit_message(content="Operation cancelled.", view=None)
class FileSearchCog(commands.Cog):
"""Cog providing a file search and publish command."""
def __init__(self, bot: commands.Bot):
self.bot = bot
@commands.has_any_role("Jarl", "Thane")
@commands.command(name="tajna_biblioteka_inkwizycji")
async def findfiles(self, ctx: commands.Context, entries: int, *, keywords: str):
"""
Search for files matching keywords and publish selected ones.
Usage: !findfiles <entries 1-10> <keywords>
"""
if entries < 1 or entries > 10:
await ctx.send("❌ Entries must be between 1 and 10.")
return
keyword_list = keywords.split()
files = file_search_functions.find_matches(entries, keyword_list)
if not files:
await ctx.send("🔍 No matching files found.")
return
view = FileSelectView(files)
file_list = "\n".join(f"{i+1}. {f}" for i, f in enumerate(files))
await ctx.send(
f"🔍 Found files (select and click Accept or Cancel):\n{file_list}",
view=view
)
async def setup(bot: commands.Bot):
await bot.add_cog(FileSearchCog(bot))
-14
View File
@@ -1,14 +0,0 @@
from flask import Flask
from file_serv import bp as uploader_bp
from ingest import bp as ingest_bp
from waitress import serve
app = Flask(__name__)
HOST_ADDRESS = "127.0.0.1"
PORT_ADDRESS = 49151
if __name__ == "__main__":
app.register_blueprint(uploader_bp, url_prefix="/api")
app.register_blueprint(ingest_bp, url_prefix="/api")
serve(app, host=HOST_ADDRESS, port=PORT_ADDRESS)
@@ -1,155 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import annotations
import os
from pathlib import Path
from typing import List, Dict, Any, Optional
from flask import Blueprint, request, jsonify, send_file, abort, current_app
from werkzeug.utils import secure_filename
# ===== Konfiguracja przez ENV =====
if API_KEY := os.getenv("API_KEY") is None:
with open("/home/pi/gpt_cont_api_key", "r") as f:
API_KEY = f.read().strip()
else:
API_KEY = os.getenv("API_KEY", "") # np. openssl rand -hex 32
UPLOAD_DIR = Path(os.getenv("UPLOAD_DIR", "/home/pi/tmp_git/")) # katalog na dysku
MAX_CONTENT_MB = int(os.getenv("MAX_CONTENT_MB", "200"))
# Google Drive (opcjonalnie)
GDRIVE_ENABLE = os.getenv("GDRIVE_ENABLE", "0") == "1"
GDRIVE_SA_JSON = os.getenv("GDRIVE_SA_JSON", "") # ścieżka do pliku .json konta serwisowego
GDRIVE_FOLDER_ID = os.getenv("GDRIVE_FOLDER_ID", "") # ID folderu na Drive
bp = Blueprint("uploader", __name__)
# Inicjalizacja katalogu
UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
def _check_auth() -> bool:
"""Proste Bearer auth. Jeśli API_KEY puste -> bez auth (niezalecane)."""
if not API_KEY:
return True
auth = request.headers.get("Authorization", "")
if auth.startswith("Bearer "):
token = auth[7:].strip()
return token == API_KEY
return False
def _safe_join(base: Path, *parts: str) -> Path:
"""Zapobiega ../ — wymusza pozostanie w katalogu bazowym."""
p = (base.joinpath(*parts)).resolve()
if not str(p).startswith(str(base.resolve())):
abort(400, description="Invalid path")
return p
# ===== Google Drive helper =====
_drive_client_cached = None
def _get_drive():
global _drive_client_cached
if _drive_client_cached is not None:
return _drive_client_cached
if not (GDRIVE_ENABLE and GDRIVE_SA_JSON and os.path.exists(GDRIVE_SA_JSON)):
return None
from google.oauth2 import service_account
from googleapiclient.discovery import build
scopes = ["https://www.googleapis.com/auth/drive.file"]
creds = service_account.Credentials.from_service_account_file(GDRIVE_SA_JSON, scopes=scopes)
_drive_client_cached = build("drive", "v3", credentials=creds, cache_discovery=False)
return _drive_client_cached
def upload_to_drive(local_path: Path, filename: str) -> Optional[Dict[str, Any]]:
drv = _get_drive()
if drv is None:
return None
from googleapiclient.http import MediaFileUpload
file_metadata = {"name": filename}
if GDRIVE_FOLDER_ID:
file_metadata["parents"] = [GDRIVE_FOLDER_ID]
media = MediaFileUpload(str(local_path), resumable=False)
created = drv.files().create(body=file_metadata, media_body=media, fields="id,webViewLink,webContentLink").execute()
file_id = created.get("id")
# Przydatne linki:
return {
"file_id": file_id,
"webViewLink": created.get("webViewLink"),
"webContentLink": created.get("webContentLink"),
"direct_view": f"https://drive.google.com/file/d/{file_id}/view",
"direct_download": f"https://drive.google.com/uc?export=download&id={file_id}",
}
@bp.get("/health")
def health():
return jsonify(ok=True, info="Okidokie")
@bp.post("/upload")
def upload():
"""Przyjmuje:
- multipart/form-data z jednym plikiem ('file') lub wieloma ('files')
- opcjonalnie: form 'subdir' (podkatalog), 'drive' (1/0) żeby wymusić wysyłkę na Drive
"""
if not _check_auth():
return jsonify(error="Unauthorized"), 401
# Limit ciała żądania po stronie Flaska:
request.max_content_length = MAX_CONTENT_MB * 1024 * 1024
files = []
if "file" in request.files:
files = [request.files["file"]]
elif "files" in request.files:
files = request.files.getlist("files")
else:
return jsonify(error="No file provided (use 'file' or 'files')"), 400
subdir = (request.form.get("subdir") or "").strip()
target_dir = _safe_join(UPLOAD_DIR, subdir) if subdir else UPLOAD_DIR
target_dir.mkdir(parents=True, exist_ok=True)
want_drive = (request.form.get("drive") == "1") or (request.args.get("drive") == "1")
saved: List[Dict[str, Any]] = []
for f in files:
if not f or not f.filename:
continue
fname = secure_filename(f.filename)
dest = _safe_join(target_dir, fname)
f.save(dest)
item = {
"filename": fname,
"size": dest.stat().st_size,
"path": str(dest.relative_to(UPLOAD_DIR)),
"url_hint": f"/api/files/{dest.relative_to(UPLOAD_DIR)}",
}
if want_drive and GDRIVE_ENABLE:
try:
gd = upload_to_drive(dest, fname)
if gd:
item["gdrive"] = gd
except Exception as e:
# log i idziemy dalej
current_app.logger.exception("Drive upload failed: %s", e)
item["gdrive_error"] = str(e)
saved.append(item)
if not saved:
return jsonify(error="No valid files"), 400
return jsonify(ok=True, saved=saved)
@bp.get("/files/<path:relpath>")
def get_file(relpath: str):
if not _check_auth():
return jsonify(error="Unauthorized"), 401
target = _safe_join(UPLOAD_DIR, relpath)
if not target.exists() or not target.is_file():
return jsonify(error="Not found"), 404
return send_file(target, as_attachment=False)
-52
View File
@@ -1,52 +0,0 @@
# ingest_text.py
import os
import urllib.parse
from pathlib import Path
from flask import Blueprint, abort, jsonify, request
bp = Blueprint("ingest_text", __name__)
BASE = Path(os.getenv("INGEST_DIR", "/home/pi/tmp_git")).resolve()
BASE.mkdir(parents=True, exist_ok=True)
TOKEN = None
with open("/home/pi/gpt_cont_api_key", "r") as f:
TOKEN = f.read().strip()
# prosty bufor kawałków w RAM (na 1 proces)
chunks = {}
@bp.get("/api/ingest-text")
def ingest_text():
if request.args.get("key") != TOKEN:
return jsonify(error="unauthorized"), 401
name = request.args.get("name", "").strip()
index = int(request.args.get("index", "1"))
total = int(request.args.get("total", "1"))
chunk = request.args.get("chunk", "")
if not name or "/" in name or ".." in name:
return jsonify(error="bad name"), 400
if not (1 <= index <= total <= 9999):
return jsonify(error="bad indexing"), 400
# gromadzimy w pamięci (możesz podmienić na Redis)
key = f"{name}:{total}"
entry = chunks.setdefault(key, {})
entry[index] = urllib.parse.unquote_plus(chunk)
if TOKEN is None:
exit("No API token set!")
if len(entry) == total:
# składamy i zapisujemy
data = "".join(entry[i] for i in range(1, total + 1))
out = (BASE / name).resolve()
if not str(out).startswith(str(BASE)):
return jsonify(error="bad path"), 400
out.write_text(data, encoding="utf-8")
del chunks[key]
return jsonify(ok=True, saved=str(out), bytes=len(data.encode("utf-8")))
else:
return jsonify(pending=True, got=len(entry), total=total)
@@ -1,2 +0,0 @@
#!/bin/bash
cd ../conjurer/ && git pull && cp ./gpt_interface/* ../gpt_interf_serv/ && cd -
-280
View File
@@ -1,280 +0,0 @@
# latex_commands.py
# -*- coding: utf-8 -*-
from __future__ import annotations
import io
import logging
from typing import Optional
import discord
from discord import app_commands
from discord.ext import commands
from conjurer.backup_old_docker.constants import (
ALLOWED_ROLES,
GUILD_ID,
LATEX_MAX_ATTACH_MB,
LATEX_MAX_COMPILE_SECONDS,
LATEX_MAX_ZIP_MB,
LATEX_TEX_ENGINE,
OPENAI_MODEL,
)
from conjurer.backup_old_docker.latex_functions import (
compile_single_tex_bytes,
compile_zip_to_zip,
is_safe_asset_name,
is_safe_tex_name,
)
async def _collect_attachments_bytes(attachments, max_mb: int):
"""
Zwraca słownik {filename: bytes} dla wszystkich załączników, do limitu MB.
Nie podbija wyjątków z .read() — zostawiamy to wyżej; tu zwracamy, co się udało.
"""
out = {}
for a in attachments or []:
# limit rozmiaru
if (getattr(a, "size", 0) or 0) > max_mb * 1024 * 1024:
continue
data = await a.read()
out[a.filename] = data
return out
class LatexModule(commands.Cog):
def __init__(self, bot: commands.Bot, logger_name: str):
self.bot = bot
self.logger = logging.getLogger(logger_name)
self.logger_name = logger_name
# -------- /tex (PDF + diagnoza; log -> debug logger) --------
@commands.hybrid_command(
nsfw=False,
name="tex",
description="Kompiluje załączone .tex; PDF-y odsyła. Błędy: diagnoza z OpenAI.",
guild=None if GUILD_ID is None else discord.Object(id=GUILD_ID),
)
@commands.has_any_role(*ALLOWED_ROLES)
async def tex(
self, ctx: commands.Context, include_source_excerpt: Optional[bool] = True
):
self.logger.info("LaTeX command invoked by %s", ctx.author)
ch = ctx.message.channel
# ZBIERZ WSZYSTKIE ZAŁĄCZNIKI
async with ch.typing():
all_bytes = await _collect_attachments_bytes(
ctx.message.attachments, LATEX_MAX_ATTACH_MB
)
if not all_bytes:
return await ctx.reply(
f"Dołącz .tex (≤{LATEX_MAX_ATTACH_MB} MiB).", mention_author=False
)
# PODZIEL NA GŁÓWNE .TEX i WSPIERAJĄCE
tex_names = [
n
for n in all_bytes.keys()
if n.lower().endswith(".tex") and is_safe_tex_name(n)
]
if not tex_names:
return await ctx.reply(
f"Dołącz .tex (≤{LATEX_MAX_ATTACH_MB} MiB).", mention_author=False
)
support_names = [
n
for n in all_bytes.keys()
if n not in tex_names and is_safe_asset_name(n)
]
files_to_send = []
parts = []
for tex_name in tex_names:
try:
main_bytes = all_bytes[tex_name]
support = [
(n, all_bytes[n])
for n in support_names
if n != tex_name and is_safe_asset_name(n)
]
# (ważne) do supportów dopuszczamy również **inne .tex** dla \input/\include
other_tex = [
(n, all_bytes[n])
for n in tex_names
if n != tex_name and is_safe_tex_name(n)
]
support.extend(other_tex)
res = await compile_single_tex_bytes(
main_bytes,
tex_name,
LATEX_TEX_ENGINE,
LATEX_MAX_COMPILE_SECONDS,
logger="discord",
support_files=support,
)
# Twoja dotychczasowa obsługa success/fail przykładowo:
if res["ok"] and res["pdf_bytes"]:
b = io.BytesIO(res["pdf_bytes"])
b.seek(0)
b.name = res["pdf_name"]
files_to_send.append(discord.File(b, filename=res["pdf_name"]))
parts.append(f"✅ `{tex_name}` → `{res['pdf_name']}`")
else:
parts.append(
f"❌ `{tex_name}` — błąd kompilacji.)"
)
# Tutaj wywołujesz swoją ścieżkę do OpenAI diagnozy, którą ogarnęliśmy wcześniej.
except Exception:
# let it crash — pełny stack w logu i re-raise (Discord.py to pokaże sensownie)
logging.getLogger("discord").exception(
"Unhandled exception while compiling %s", tex_name
)
raise
content = (
f"**LaTeX** — {len(tex_names)} plik(ów). Model: `{OPENAI_MODEL}`\n\n"
+ "\n\n".join(parts)
)
await ctx.reply(
content if len(content) < 1900 else content[:1900] + "",
files=files_to_send,
mention_author=False,
)
# -------- /latexclean (PDF only; log -> debug logger) --------
@commands.hybrid_command(
nsfw=False,
name="latexclean",
description="Kompiluje .tex i odsyła TYLKO PDF (log w debug).",
guild=None if GUILD_ID is None else discord.Object(id=GUILD_ID),
)
@commands.has_any_role(*ALLOWED_ROLES)
async def latexclean(self, ctx: commands.Context):
ch = ctx.message.channel
async with ch.typing():
all_bytes = await _collect_attachments_bytes(
ctx.message.attachments, LATEX_MAX_ATTACH_MB
)
if not all_bytes:
return await ctx.reply(
f"Dołącz .tex (≤{LATEX_MAX_ATTACH_MB} MiB).", mention_author=False
)
# PODZIEL NA GŁÓWNE .TEX i WSPIERAJĄCE
tex_names = [
n
for n in all_bytes.keys()
if n.lower().endswith(".tex") and is_safe_tex_name(n)
]
if not tex_names:
return await ctx.reply(
f"Dołącz .tex (≤{LATEX_MAX_ATTACH_MB} MiB).", mention_author=False
)
support_names = [
n
for n in all_bytes.keys()
if n not in tex_names and is_safe_asset_name(n)
]
files_to_send = []
parts = []
for tex_name in tex_names:
try:
main_bytes = all_bytes[tex_name]
support = [
(n, all_bytes[n])
for n in support_names
if n != tex_name and is_safe_asset_name(n)
]
# (ważne) do supportów dopuszczamy również **inne .tex** dla \input/\include
other_tex = [
(n, all_bytes[n])
for n in tex_names
if n != tex_name and is_safe_tex_name(n)
]
support.extend(other_tex)
res = await compile_single_tex_bytes(
main_bytes,
tex_name,
LATEX_TEX_ENGINE,
LATEX_MAX_COMPILE_SECONDS,
logger="discord",
support_files=support,
)
# Twoja dotychczasowa obsługa success/fail przykładowo:
if res["ok"] and res["pdf_bytes"]:
b = io.BytesIO(res["pdf_bytes"])
b.seek(0)
b.name = res["pdf_name"]
files_to_send.append(discord.File(b, filename=res["pdf_name"]))
parts.append(f"✅ `{tex_name}` → `{res['pdf_name']}`")
else:
parts.append(
f"❌ `{tex_name}` — błąd kompilacji.)"
)
# Tutaj wywołujesz swoją ścieżkę do OpenAI diagnozy, którą ogarnęliśmy wcześniej.
except Exception:
# let it crash — pełny stack w logu i re-raise (Discord.py to pokaże sensownie)
logging.getLogger("discord").exception(
"Unhandled exception while compiling %s", tex_name
)
raise
await ctx.reply(
"**LaTeX clean** — " + ", ".join(parts),
files=files_to_send,
mention_author=False,
)
# -------- /texbatch (ZIP -> ZIP) --------
@app_commands.command(
name="texbatch",
description="Wyślij ZIP z .tex → odeślę ZIP z PDF-ami (tylko udane).",
)
@app_commands.describe(archive=f"Archiwum .zip (max ~{LATEX_MAX_ZIP_MB} MiB)")
@app_commands.checks.has_any_role(*ALLOWED_ROLES)
async def texbatch(
self, interaction: discord.Interaction, archive: discord.Attachment
):
await interaction.response.defer()
if not archive or not archive.filename.lower().endswith(".zip"):
return await interaction.followup.send(
"Dołącz ZIP (.zip) z plikami .tex.", ephemeral=True
)
if archive.size > LATEX_MAX_ZIP_MB * 1024 * 1024:
return await interaction.followup.send(
f"ZIP > {LATEX_MAX_ZIP_MB} MiB — za duży.", ephemeral=True
)
data = await archive.read()
out_zip_bytes, failed = await compile_zip_to_zip(
data, LATEX_TEX_ENGINE, LATEX_MAX_COMPILE_SECONDS, logger=self.logger_name
)
if not out_zip_bytes and failed:
return await interaction.followup.send(
"Brak PDF-ów. " + "; ".join(failed[:10]), ephemeral=True
)
bio = io.BytesIO(out_zip_bytes)
bio.seek(0)
bio.name = "compiled_pdfs.zip"
if failed:
self.logger.debug("BATCH failed: %s", ", ".join(failed))
await interaction.followup.send(
"✅ Gotowe (ZIP w załączniku)."
+ (f" ❌ Błędy: {len(failed)}" if failed else ""),
files=[discord.File(bio, filename=bio.name)],
)
async def setup(bot):
logger = logging.getLogger("discord")
await bot.add_cog(LatexModule(bot, logger_name="discord"))
logger.info("Loading kinky latex module done")
-309
View File
@@ -1,309 +0,0 @@
import asyncio
import io
import logging
import os
import random
import uuid
from queue import Empty
import discord
import pdf2image
import fitz
import PyPDF2
import requests
from discord.ext import commands, tasks
from conjurer.backup_old_docker.ai_functions import handle_response
from conjurer.backup_old_docker.communication_subroutine import IN_COMM_Q, OUT_COMM_Q, QueryControl
from conjurer.backup_old_docker.constants import (
DIR_PATH_SADOX,
LIBRARIAN_SERVICE_ADDRESS,
SEND_QUERY,
service_headers,
)
SERVICE_HEADERS = service_headers()
class DataModule(commands.Cog):
def __init__(self, bot, logger_name):
self.bot = bot
self.logger = logging.getLogger(logger_name)
@commands.hybrid_command(
nsfw=True,
name="get_image_sadox",
description="Wyświetla losową stronę z losowego komiksu FanSadox. Bardzo NSFW.",
guild=discord.Object(id=664789470779932693),
)
@commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender')
async def get_image_sadox(self, 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
"""
self.logger.info("Get sadox")
channel = ctx.message.channel
async with channel.typing():
# select random file
res = []
# Iterate directory
for path in os.listdir(DIR_PATH_SADOX):
# check if current path is a file
if os.path.isfile(os.path.join(DIR_PATH_SADOX, path)):
res.append(path)
# trunk-ignore(bandit/B311)
filename = res[random.randrange(0, len(res) - 1)]
# select random page
file = open(DIR_PATH_SADOX + filename, "rb")
if True:
doc = fitz.open(DIR_PATH_SADOX + filename)
totalpages = len(doc)
# trunk-ignore(bandit/B311)
page_index = random.randrange(0, totalpages)
page = doc.load_page(page_index)
mat = fitz.Matrix(2.0, 2.0) # powiększenie
pix = page.get_pixmap(matrix=mat, alpha=False)
byte_io_stream = io.BytesIO(pix.tobytes("png"))
byte_io_stream.seek(0)
byte_io_stream.name = "image.png"
await ctx.send(file=discord.File(byte_io_stream))
else: #legacy
readpdf = PyPDF2.PdfReader(file)
totalpages = len(readpdf.pages)
# trunk-ignore(bandit/B311)
page = random.randrange(1, totalpages)
# convert page to image
image = pdf2image.convert_from_path(
DIR_PATH_SADOX + filename, first_page=page, last_page=page
)
byte_io_stream = io.BytesIO()
image[0].save(byte_io_stream, "JPEG")
byte_io_stream.seek(0)
byte_io_stream.name = "image.jpg"
file = discord.File(byte_io_stream)
await ctx.send(file=file)
self.logger.info("Get sadox completed")
@tasks.loop(seconds=3)
async def check_data_q(self):
"""
This function checks the data queue for any new entries and processes them accordingly.
"""
try:
fresh_data = IN_COMM_Q.get(block=False)
entries = []
if fresh_data.stop:
searcher = fresh_data.author
query = fresh_data.content
l_p = 1
for doi in fresh_data.entries:
self.logger.info(doi)
desc = fresh_data.entries[doi]
title = desc["Title"][0]
entries.append(
f"{l_p}. {title} pod linkiem https://www.sci-hub.se/{doi} i jest to {desc['type']}\n"
)
l_p += 1
message = "*Z podłogi wysuwa się winda na książki*"
if fresh_data.ctx is not None:
ctx = fresh_data.ctx
message += f" Dzielny poszukiwaczu @{searcher} w odpowiedzi na twoje zapytanie {query} nr {fresh_data.uuid}"
else:
ctx = self.bot.get_channel(1062047571557744721)
message += f" Mam wynik dla zapytania {fresh_data.uuid} ale że Hammer coś grzebał nie pamiętam kto to chciał i co chciał"
message += "nasza biblioteka służy Ci odpowiedzią. Przy dźwięku fanfar winda się otwiera a w środku "
if len(entries) < 1:
message += "niestety nie ma nic"
await ctx.send(message)
elif len(entries) >= 1 and len(entries) < 5:
message += " znajduje się coś:\n"
for item in entries:
message += item
await ctx.send(message)
else:
message += " znajduje się cholernie dużo:\n"
for item in entries:
message += item
if len(message) > 1500:
await ctx.send(message)
message = ""
# Kept for sentimental reasons
# await ctx.send(f"O. A tak będzie wyglądało coś ciekawego w przyszłości: {data}")
except Empty:
pass
@commands.hybrid_command(
name="wyszukaj_linki_do_dokumentow",
description="Szuka linkow doi w bazie crossref i podaje linki do scihuba",
guild=discord.Object(id=664789470779932693),
)
async def wyszukaj_linki_do_dokumentow(self, ctx):
"""
The function `wyszukaj_linki_do_dokumentow` searches for links to documents in a crossref database and provides links to scihub.
:param ctx: The `ctx` parameter is typically used in Discord.py, a Python library for creating Discord bots.
It represents the context of the command being executed, including information about the message, the server,
and the user who invoked the command.
"""
query = ctx.message.content
query_uuid = uuid.uuid4()
# TODO: TESTING ONLY!!
# query_uuid = uuid.UUID('{12345678-1234-5678-1234-567812345678}')
ctx.message.content = ctx.message.content.replace(
"$wyszukaj_linki_do_dokumentow", ""
)
json_query = {
"UUID": str(query_uuid),
"query": str(query),
"page": 1,
"deep_search": False,
}
coroutine = asyncio.to_thread(
requests.post,
f"{LIBRARIAN_SERVICE_ADDRESS}{SEND_QUERY}",
json=json_query,
headers=SERVICE_HEADERS,
timeout=360,
)
await ctx.send(
"*Conjurer powoli notuje podane przez Ciebie. Podchodzi do sprytnie ukrytej przy barze rury od poczty pneumatycznej i"
+ " wrzuca twój liścik do środka* To teraz trza poczekać kilka godzin. Biblioteka to 3/4 stacji."
+ " A przecież pół stacji to browar, motelik dla zabaw cielesnych i ten Bar. Więc 12/8 stacji teraz będzie ciężko pracować"
)
query_response = await coroutine
if not query_response.status_code == 200:
await ctx.send(
"*Z rury wydobywa się dym. Conjurer łapie pierwszą ciecz pod ręką i pryska na rurę. Następuje drobna eksplozja i wszystko zaczyna się palić."
+ " Conjurer jest skonfundowany..* Wołaj szefa - mam nieodparte wrażenie że się coś wyjebało"
)
return
query, query_uuid, queue_size = (
query_response.json()["data"][0],
query_response.json()["data"][1],
query_response.json()["data"][2],
)
if ctx.message.author.nick:
username = ctx.message.author.nick
else:
username = ctx.message.author.name
query_object = QueryControl(username, query_uuid, query, ctx)
OUT_COMM_Q.put(query_object)
await ctx.send(
f"No dobra poszło. Zapamiętaj proszę {query_uuid} - to identyfikator twojego zapytania. Jesteś {queue_size} w kolejce."
+ " Zapytania obsługuje algorytm zasilany czterema chomikami zapierdalającymi w kołowrotku - więc wyniki najwcześniej za kilka godzi - ale mogą być też dni."
)
@commands.hybrid_command(
name="glebokie_gardlo",
description="Przygotowuje drinka o nazwie głębokie gardło",
guild=discord.Object(id=664789470779932693),
)
async def wyszukaj_linki_do_dokumentow_deep(self, ctx):
"""
The function `wyszukaj_linki_do_dokumentow_deep` performs a deep search for links to documents in
a crossref database and provides links to scihub.
:param ctx: The `ctx` parameter is typically used in Discord.py, a Python library for creating Discord bots.
It represents the context of the command being executed, including information about the message, the server,
and the user who invoked the command.
"""
# TODO: Implement deep search logic here
query = ctx.message.content.replace("$glebokie_gardlo", "")
allowed = False
for role in ctx.message.author.roles:
if role.name == "Bartender":
allowed = True
if role.name == "Scribe":
allowed = True
if role.name == "Thane":
allowed = True
if not allowed:
if ctx.message.author.nick:
username = ctx.message.author.nick
else:
username = ctx.message.author.name
vykidailo = False
bartender = False
prompt = "Przygotuj mi drinka o nazwie Głębokie Gardło, inspirowanego tym sławnym filmem oraz skandalem Watergate"
for role in ctx.message.author.roles:
if role.name == "Vykidailo":
vykidailo = True
if role.name == "Bartender":
bartender = True
global MESSAGE_TABLE # pylint: disable=global-statement
result, MESSAGE_TABLE = await handle_response(
prompt, vykidailo, bartender, MESSAGE_TABLE, username, "GENERAL"
)
if len(result) < 1500:
await ctx.send(result)
else:
while len(result) > 1500:
await ctx.send(result[:1500])
result = result[1500:]
return
query_uuid = uuid.uuid4()
# TODO: TESTING ONLY!!
# query_uuid = uuid.UUID('{12345678-1234-5678-1234-567812345678}')
json_query = {
"UUID": str(query_uuid),
"query": str(query),
"page": 1,
"deep_search": True,
}
coroutine = asyncio.to_thread(
requests.post,
f"{LIBRARIAN_SERVICE_ADDRESS}{SEND_QUERY}",
json=json_query,
headers=SERVICE_HEADERS,
timeout=360,
)
await ctx.send(
"*Conjurer mruga okiem i zamiast drinka wyjmuje dysk usb z terminala. Podchodzi do sprytnie ukrytej przy barze rury od poczty pneumatycznej i"
+ " wrzuca ten dysk do środk* To teraz trza poczekać kilka godzin. TO będzie głębokie wyszukanie"
+ " Rozgląda się dookoła i stawia przed tobą mętnego drinka o zapachu mięty, gwiezdnego pyłu i oleju silnikowego"
)
query_response = await coroutine
if not query_response.status_code == 200:
await ctx.send(
"*Z rury wydobywa się dym. Conjurer łapie pierwszą ciecz pod ręką i pryska na rurę. Następuje drobna eksplozja i wszystko zaczyna się palić."
+ " Conjurer jest skonfundowany..* Wołaj szefa - mam nieodparte wrażenie że się coś wyjebało"
)
return
query, query_uuid, queue_size = (
query_response.json()["data"][0],
query_response.json()["data"][1],
query_response.json()["data"][2],
)
if ctx.message.author.nick:
username = ctx.message.author.nick
else:
username = ctx.message.author.name
query_object = QueryControl(username, query_uuid, query, ctx)
OUT_COMM_Q.put(query_object)
await ctx.send(
f"Wypij wypi {query_uuid} - to identyfikator twojego zapytania. Jesteś {queue_size} w kolejce niestety kolejka obowiazuje zawsze."
+ " Zapytania obsługuje algorytm zasilany czterema chomikami zapierdalającymi w kołowrotku - więc wyniki najwcześniej za kilka godzin - ale mogą być też dni. Głębokie zabawy trwają dłużej. *Znowu mruga*"
)
async def setup(bot):
logger = logging.getLogger("discord")
dm = DataModule(bot, "discord")
dm.check_data_q.start()
await bot.add_cog(dm)
logger.info("Loading data sharing commands module done")
-333
View File
@@ -1,333 +0,0 @@
import asyncio
import logging
import re
import uuid
from pathlib import Path, PurePath
from sys import platform
import discord
import requests
import yt_dlp
from conjurer.backup_old_docker.constants import (
FILE_SERVICE_ADDRESS,
GET_MP3,
GET_PLAYLIST,
MUSIC_FOLDER,
SEND_MP3,
SPOTIFY_CTRL,
YOUTUBE_AUTH,
service_headers,
)
from spotify_dl import spotify
from spotify_dl import youtube as youtube_download
SERVICE_HEADERS = service_headers()
MUSIC_ROOT = Path(MUSIC_FOLDER)
class MusicFileList(object):
"""
The `MusicFileList` class manages a list of music files, with the ability to refresh the list from a
file service or local directory and update the list with new items.
"""
def __init__(self, logger_name) -> None:
self.music_file_list = []
self.file_service_active = False
self.logger = logging.getLogger("discord")
self.logger.info("Created Playlist organizer class")
async def refresh_file_list(self, bot):
"""
The `refresh_file_list` function attempts to connect to a file service to retrieve a list of music
files, and if unsuccessful, it populates the list by scanning a local directory for .mp3 files.
"""
try:
self.logger.info("Attempt to connect to file service")
response = requests.get(
f"{FILE_SERVICE_ADDRESS}{GET_MP3}",
headers=SERVICE_HEADERS,
timeout=60,
)
self.music_file_list = response.json()["music_file_list"]
self.file_service_active = True
except requests.exceptions.RequestException as e:
for mp3_item in MUSIC_ROOT.glob("**/*.mp3"):
temp_music_file = mp3_item.as_posix()
if platform == "win32":
temp_music_file = temp_music_file.replace("/", "\\")
self.music_file_list.append(temp_music_file)
self.file_service_active = False
self.logger.error(e.strerror)
self.logger.error("Service Unavailable")
finally:
if self.file_service_active:
self.logger.info("Radio Status: Probably Active")
status = discord.Status.online
# radio_hardkor = discord.Activity(
# name = "Radio Hammer/Radio Conjurer/Wolne Bałuity Kurwa",
# url = "http://95.175.16.246:666/mp3-stream",
# type = discord.ActivityType.streaming,
# platform = "Liquidsoap+RaspberyPi+RolandSeratoDJ202",
# state = "Where the f*** is the DJ booth?",
# details= "This Is Radio Hardkor based in Wolne Księstwo Bałuty, the best pirate radiostation on both sides of Łódka river",
# buttons= [{"label":"RADIO", "url":"http://95.175.16.246:666/mp3-stream"}],
# assets= {"large_image": "fuckery.jpg", "large_text":"Fuckewry", "small_image":"willowisp.png", "small_text":"Hi!"}
# )
radio_hardkor = discord.Streaming(
name="Radio Hardkor", url="http://95.175.16.246:666/mp3-stream"
)
await bot.change_presence(status=status, activity=radio_hardkor)
else:
self.logger.info("Radio Status: Rather Unknown")
await bot.change_presence(
activity=discord.Game(name="Axe Throwing Darts")
)
def get_file_list(self):
"""
The `get_file_list` function returns the list of music files stored in the object.
:return: The `music_file_list` attribute is being returned.
"""
return self.music_file_list
def update_file_list(self, item):
"""
The `update_file_list` function appends an item to a music file list and sends a POST request with
the item data to a file service address.
:param item: The `item` parameter in the `update_file_list` method is the file that you want to add
to the `music_file_list` attribute of the class instance. It is then sent as a JSON payload in a
POST request to a file service address along with the endpoint `SEND_MP3`
"""
self.music_file_list.append(item)
post_data = {"item": str(item)}
requests.post(
f"{FILE_SERVICE_ADDRESS}{SEND_MP3}",
json=post_data,
headers=SERVICE_HEADERS,
timeout=60,
)
MUSIC_FILE_LIST = MusicFileList("discord")
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
"""
logger = logging.getLogger("discord")
item_id = None
item_type = None
file_list = []
if source == "Spotify":
dir_path = None
item_type, item_id = spotify.parse_spotify_url(link)
if item_type in ["album", "track", "playlist"] and item_id:
logger.info(item_type)
logger.info(item_id)
logger.info("Spotify link provided")
file_list = await asyncio.to_thread(
spotify.fetch_tracks, SPOTIFY_CTRL, item_type, link
)
logger.info(file_list)
directory_name = await asyncio.to_thread(
spotify.get_item_name, SPOTIFY_CTRL, item_type, item_id
)
logger.info(directory_name)
logger.info("Spotify scrape done")
url_data = {"urls": []}
url_dict = {}
url_dict["save_path"] = Path(
PurePath.joinpath(MUSIC_ROOT, Path(directory_name))
)
url_dict["save_path"].mkdir(parents=True, exist_ok=True)
url_dict["songs"] = file_list
url_data["urls"].append(url_dict.copy())
file_name_f = youtube_download.default_filename
logger.info("YT-DL")
coro = asyncio.to_thread(
youtube_download.download_songs,
songs=url_data,
output_dir=str(MUSIC_ROOT),
format_str="bestaudio/best",
skip_mp3=False,
keep_playlist_order=False,
no_overwrites=True,
remove_trailing_tracks="no",
use_sponsorblock="yes",
file_name_f=file_name_f,
multi_core=0,
proxy="",
YT_AUTH = YOUTUBE_AUTH
)
_ = await coro
logger.info("YT-DL done")
dir_path = (url_dict["save_path"].resolve()).as_posix()
if platform == "win32":
dir_path = dir_path.replace("/", "\\")
return dir_path, file_list
await ctx.send(
"No se jaja chyba robisz, Ty byś spotifaja nie poznawszy jakby z krzaków wyskoczył i w dupę kopnął. Plejlista, kawałek albo album prosze."
)
logger.error("Wrong link provided spotify: %s", link)
elif source == "Youtube":
link_ok = False
pat = r"^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$"
if re.match(pat, link) and (
re.match(".*youtube.*", link) or re.match(".*youtu.be.*", link)
):
link_ok = True
if link_ok:
dir_path = ""
file_list = []
query = link
sponsorblock_postprocessor = [
{
"key": "SponsorBlock",
"categories": ["skip_non_music_sections"],
},
{
"key": "ModifyChapters",
"remove_sponsor_segments": ["music_offtopic"],
"force_keyframes": True,
},
]
# TODO: Make sponsorblock work
sponsorblock_postprocessor = []
if platform == "win32":
dir_path = "G:\\Muzyka\\Youtube"
else:
dir_path = "/home/pi/RetroPie/mp3/Youtube"
ydl_opts = {
"username": YOUTUBE_AUTH[0],
"password": YOUTUBE_AUTH[1],
"proxy": "",
"default_search": "ytsearch",
"format": "bestaudio/best",
"postprocessors": sponsorblock_postprocessor,
"noplaylist": True,
"no_color": False,
"paths": {"home": dir_path},
}
mp3_postprocess_opts = {
"key": "FFmpegExtractAudio",
"preferredcodec": "mp3",
"preferredquality": "192",
}
ydl_opts["postprocessors"].append(mp3_postprocess_opts.copy())
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
try:
coro = asyncio.to_thread(ydl.download, [query])
_ = await coro
except Exception as exce: # pylint: disable=broad-exception-caught
logger.error(exce)
logger.info(
"Failed to download %s, make sure yt_dlp is up to date", link
)
extract = re.search("v=(...........)[&,$]*", link)
ident = extract.group(1)
for item in Path.glob(Path(dir_path), "**/*.mp3"):
file = item.as_posix()
if platform == "win32":
file = file.replace("/", "\\")
if re.match(".*" + ident + ".*", file):
file_list.append(file)
return dir_path, file_list
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
elif source == "Pornol":
dir_path = ""
file_list = []
query = link
sponsorblock_postprocessor = [
{
"key": "SponsorBlock",
"categories": ["skip_non_music_sections"],
},
{
"key": "ModifyChapters",
"remove_sponsor_segments": ["music_offtopic"],
"force_keyframes": True,
},
]
# TODO: Make sponsorblock work
sponsorblock_postprocessor = []
dir_path = "/home/pi/MediaShare/movies/porn"
ydl_opts = {
"postprocessors": sponsorblock_postprocessor,
"paths": {"home": dir_path},
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
try:
coro = asyncio.to_thread(ydl.download, [query])
_ = await coro
except Exception as exce: # pylint: disable=broad-exception-caught
logger.error(exce)
logger.info(
"Failed to download %s, make sure yt_dlp is up to date", link
)
file_list.append("wiadomo co wiadomo gdzie")
return dir_path, file_list
async def search_music(ctx, how_many=0, slowa_kluczowe=None):
"""
Take in a context object and an optional integer parameter "how_many" and perform search
operation on music library.
:param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It
represents the context in which the command was invoked, including information such as the message,
the channel, the server, and the user who invoked the command
:param how_many: how_many is a parameter that specifies the number of search results to be returned.
It is an optional parameter with a default value of 0, which means that if no value is provided for
how_many, the function will return all search results, defaults to 0 (optional)
"""
# i sieć neuronową z możliwością wyrażenia opinii o dopasowaniu.
logger = logging.getLogger("discord")
if slowa_kluczowe:
word_list = slowa_kluczowe
else:
word_list = ctx.message.content.split()
logger.info("Wyszukuje")
jrequest = {
"lista_slow": word_list,
"dlugosc_plejlisty": how_many,
"UUID": str(uuid.uuid4()),
}
coroutine = asyncio.to_thread(
requests.post,
f"{FILE_SERVICE_ADDRESS}{GET_PLAYLIST}",
json=jrequest,
headers=SERVICE_HEADERS,
timeout=360,
)
return_data = await coroutine
if not return_data.status_code == 200:
await ctx.send("Wołaj szefa - coś się wyjebało")
return
logger.info(return_data.json()["data"])
return return_data.json()["data"]
-212
View File
@@ -1,212 +0,0 @@
import asyncio
import json
import logging
from datetime import datetime
from typing import Optional
import discord
from discord.ext import commands
from conjurer.backup_old_docker.constants import ACCIDENT_LOG, DATA, ENCODING
historia_fabryczki = DATA["fabryczka"]
class OtherModule(commands.Cog):
def __init__(self, bot, logger_name):
self.bot = bot
self.logger = logging.getLogger(logger_name)
@commands.hybrid_command(
name="przytul", description="Przytul kogoś - daj mention po komendzie :)"
)
@commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender')
async def przytul(self, 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:
for role in mention.roles:
if role.name == "NIEPRZYTULAĆ!":
nieprzytulac = True
if arg and nieprzytulac:
await ctx.send(
f"Żebym ja Ciebie nie przytulił {ctx.message.author.mention}"
)
elif arg:
await ctx.send(
# 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.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*"
)
@commands.hybrid_command(name="fabryczka", description="Historia fabryczki")
@commands.has_any_role('Legenda', 'Jarl', 'Thane' , 'Bartender')
async def fabryczka(self, 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)
@commands.hybrid_command(
name="set_logging_level",
description="Nie intererer bo kici kici",
guild=discord.Object(id=664789470779932693),
)
@commands.has_any_role('Legenda', 'Jarl', 'Bartender')
async def set_logging_level(self,ctx):
if "DEBUG" in ctx.message.content:
logger = logging.getLogger("discord")
logger.setLevel(logging.DEBUG)
elif "INFO" in ctx.message.content:
logger = logging.getLogger("discord")
logger.setLevel(logging.INFO)
else:
await ctx.send("Weź się kurwa zdecyduj co ?")
@commands.hybrid_command(
name="reset_the_clock",
description="Resetowanie zegara - dostępne wyłącznie dla Hammera",
guild=discord.Object(id=664789470779932693),
)
@commands.has_any_role('Legenda', 'Jarl', 'Thane' , 'Bartender')
async def reset_the_clock(self, ctx):
"""
Reset the clock on "accidents" in Hammer Fortress adding a new one.
:param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It
represents the context in which the command was invoked, including information such as the message,
the channel, the server, and the user who invoked the command. This parameter is required in all
Discord.py commands
"""
hammer = False
for role in ctx.message.author.roles:
if role.name == "Bartender":
hammer = True
if hammer:
with open(ACCIDENT_LOG, "r+", encoding=ENCODING) as new_file_accidents:
# First we load existing data into a dict.
file_data = json.load(new_file_accidents)
czas = datetime.strptime(file_data[-1][1], "%Y-%m-%d %H:%M:%S.%f")
opis = ctx.message.content[16:]
accident = accident = [opis, f"{datetime.now()}"]
file_data.append(accident)
new_file_accidents.seek(0)
# convert back to json.
json.dump(file_data, new_file_accidents, indent=4)
await ctx.send(
f"Komenda mierząca incydenty w Eldritch AbsinthHammerTimeSpaceContinuum.\n RESET THE CLOCK. Od ostatniego incydentu w chacie Hammera minęło {czas}. No ale teraz się odpierdoliło: {opis}"
)
else:
await ctx.send(
f"Komenda mierząca incydenty w Eldritch AbsinthHammerTimeSpaceContinuum.\n Gdzie z łapami do zegara? {self.bot.get_user(346956223645614080).mention} coś albo się komuś stało albo zaraz się stanie jak będzie zegar tykał...."
)
@commands.hybrid_command(
name="chata_hammera",
description="Czas od ostatniego incydentu w AbsinthHammerTimeSpaceContinuum",
)
@commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender')
async def chata_hammera(self, ctx):
"""
Send measured time from last incident in Hammer Fortress to the chat.
:param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It
contains information about the context in which the command was invoked, such as the message, the
channel, the server, and the user who invoked the command. This information can be used to perform
various actions, such
"""
with open(ACCIDENT_LOG, "r+", encoding=ENCODING) as new_file:
# First we load existing data into a dict.
file_data = json.load(new_file)
opis = file_data[-1][0]
czas = datetime.strptime(file_data[-1][1], "%Y-%m-%d %H:%M:%S.%f")
await ctx.send(
f"Komenda mierząca incydenty w Eldritch AbsinthHammerTimeSpaceContinuum.\n Od ostatniego incydentu w chacie Hammera minęło {datetime.now() - czas}. Incydent to: {opis}"
)
@commands.hybrid_command(
name="historia_incydentow_u_hammera",
description="Wyswietla liste incydentów które miały miejsce w AbsinthHammerTimeSpaceContinuum.",
)
@commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender')
async def historia_incydentow_u_hammera(self, ctx):
"""
Send a list of incidents in Hammer Fortress to the chat.
:param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It
contains information about the context in which the command was invoked, such as the message, the
channel, the server, and the user who invoked the command. This information can be used to perform
various actions, such
"""
with open(ACCIDENT_LOG, "r+", encoding=ENCODING) as new_file_accidents:
# First we load existing data into a dict.
file_data = json.load(new_file_accidents)
return_data = "Komenda mierząca incydenty w Eldritch AbsinthHammerTimeSpaceContinuum.\n Historia zarejestrownych incydentów u Hammera:\n"
index = 1
for iter_data in file_data:
opis = iter_data[0]
czas = datetime.strptime(iter_data[1], "%Y-%m-%d %H:%M:%S.%f")
add_data = f"{index}. Opis: {opis} Data: {czas}"
return_data = return_data + add_data + "\n"
index += 1
await ctx.send(return_data)
@commands.hybrid_command(
name="radio_hardkor",
description="Włącza radio Conjurer na kanale #nocna-zmiana.",
guild=discord.Object(id=664789470779932693),
)
@commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender')
async def radio_hardkor(self, ctx):
"""
Plays the radio hardkor stream in the voice channel.
Args:
ctx: The context object representing the invocation context.
Returns:
None
"""
self.logger.info("Press play on radio hardkor")
async with ctx.typing():
global MUZYKA # pylint: disable=global-variable-not-assigned
MUZYKA["ctx"] = ctx
if not self.bot.voice_clients:
await self.connect(ctx=ctx)
voice_client = self.bot.voice_clients[0]
voice_client.play(
discord.PCMVolumeTransformer(
discord.FFmpegPCMAudio("http://95.175.16.246:666/mp3-stream"),
volume=0.3,
)
)
self.logger.info("Press play on radio completed")
else:
self.logger.error("Already playing")
await asyncio.sleep(12)
self.check_music.start()
async def setup(bot):
logger = logging.getLogger("discord")
await bot.add_cog(OtherModule(bot, "discord"))
logger.info("Loading kitchen sink module done")
-238
View File
@@ -1,238 +0,0 @@
[
{
"role": "assistant",
"content": "Cze\u015b\u0142, witaj w klimatycznym barze mechawojownik\u00f3w! Jestem Conjurer, twoim barmanem na dzisiaj. Co dla Ciebie przygotuj\u0119? Mo\u017ce co\u015b mocniejszego? Mam tutaj specjalno\u015b\u0142 naszego baru - Hammer - to mieszanka klasycznego whisky z sokiem z pikantnego grejpfruta i opalizuj\u0105cym winem z dodatkiem b\u0142yskawic, kt\u00f3re nadadz\u0105 trunkowi nieco elektryzuj\u0105cego smaku. Jest to bardzo mocny nap\u00f3j, ale zapewniam, \u017ce z pewno\u015bci\u0105 Ci si\u0119 spodoba. Chcesz spr\u00f3bowa\u0142?"
},
{
"role": "user",
"content": "Pat vel Je\u017c Bojowy:zapami\u0119taj dzisiaj jest youtube party"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie, zawsze b\u0119dziemy pami\u0119ta\u0142, \u017ce dzisiaj mamy Youtube Party! Czy chcesz co\u015b do jedzenia, aby zwi\u0119kszy\u0142 swoj\u0105 energi\u0119 na ta\u0144ce i zabaw\u0119? Mamy wspania\u0142e przek\u0105ski w rodzaju pikantnych skrzyde\u0142ek, nachos\u00f3w z guacamole, czy te\u017c hot dogi na ostro. Co by\u015b wybra\u0142?"
},
{
"role": "user",
"content": "Pat vel Je\u017c Bojowy:skrzyde\u0142ka bbq poprosz\u0119"
},
{
"role": "assistant",
"content": "\u015awietnie, a do skrzyde\u0142ek wybierzesz jak\u0105\u015b zimn\u0105 przek\u0105sk\u0119 z naszego menu, czy postawisz na co\u015b ciep\u0142ego? Mamy tutaj znakomite ciasto z owocami morza i pizz\u0119 z ostr\u0105 papryczk\u0105."
},
{
"role": "user",
"content": "Hammer - The Bartender:cze\u015b\u0142! by\u0142e\u015b w nocy zrestartowany bo pope\u0142ni\u0142em pare b\u0142\u0119d\u00f3w w kodzie kt\u00f3ry obs\u0142uguje zapytania do ciebie. pocieszysz mnie troche ?"
},
{
"role": "assistant",
"content": "Cze\u015b\u0107! Oczywi\u015bcie, jestem zawsze tutaj, aby Ci\u0119 pocieszy\u0142. Nie przejmuj si\u0119 tak bardzo - ka\u017cdy ma dni, w kt\u00f3rych pope\u0142nia b\u0142\u0119dy i to w zupe\u0142no\u015bci normalne i naturalne. Liczy si\u0119 to, \u017ce starasz si\u0119 poprawi\u0142 swoje b\u0142\u0119dy i rozwija\u0142 swoje umiej\u0119tno\u015bci. Mo\u017cesz by\u0142 z siebie dumny, \u017ce potrafisz pracowa\u0142 nad sob\u0105! A tymczasem, przynios\u0119 Ci co\u015b do picia, aby zapomnie\u0142 o stresie. Co powiesz na super od\u015bwie\u017caj\u0105cy nap\u00f3j z mi\u0119t\u0105, limonk\u0105 i sod\u0105?"
},
{
"role": "user",
"content": "Hammer - The Bartender:tak ch\u0119tnie poprosz\u0119"
},
{
"role": "user",
"content": "Hammer - The Bartender:halo ?"
},
{
"role": "user",
"content": "Hammer - The Bartender:tak ch\u0119tnie poprosz\u0119"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie! Wspaniale, wkr\u00f3tce przynios\u0119 Ci \u015bwie\u017co zrobiony nap\u00f3j z mi\u0119t\u0105, limonk\u0105 i sod\u0105. (barman przygotowuje nap\u00f3j i podaje go) Prosz\u0119 bardzo, mam nadziej\u0119, \u017ce ten orze\u017awiaj\u0105cy nap\u00f3j poprawi Ci humor i pozwoli poczu\u0142 si\u0119 lepiej. A je\u015bli potrzebujesz, uczucie komfortu i wsparcia, to zawsze jestem tutaj, aby Ci pom\u00f3c."
},
{
"role": "user",
"content": "Hammer - The Bartender:pami\u0119tasz co wczoraj powiedzia\u0142a ci pat vel je\u017c bojowy? o czym mia\u0142e\u015b pami\u0119ta\u0142 ?"
},
{
"role": "assistant",
"content": "Tak, pami\u0119tam, \u017ce Pat vel Je\u017c Bojowy powiedzia\u0142, abym zapami\u0119ta\u0142, \u017ce dzisiaj jest Youtube Party. To bardzo wa\u017cne wydarzenie w naszym barze, a ja zawsze pami\u0119tam o tym, gdy obs\u0142uguje swoich klient\u00f3w. Czy jest co\u015b jeszcze, na co musz\u0119 zwr\u00f3ci\u0142 szczeg\u00f3ln\u0105 uwag\u0119?"
},
{
"role": "user",
"content": "Hammer - The Bartender:zr\u00f3b mi drinka"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie! Mam kilka pomys\u0142\u00f3w na drinki, kt\u00f3re mog\u0105 Ci\u0119 zainteresowa\u0142. Z jakiego rodzaju alkoholu lub smaku wypijasz najch\u0119tniej? Czekam na Twoje wskaz\u00f3wki, co do gustu."
},
{
"role": "user",
"content": "Hammer - The Bartender:co\u015b mocnego na bazie absyntu, mo\u017ce z nutk\u0105 ja\u0142wca?"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie, zaraz przygotuj\u0119 co\u015b wyj\u0105tkowego dla Ciebie! Mam w naszym menu drink o nazwie \"Zielona Dama\", jest to mieszanka absyntu z sokiem z cytryny, syropem cukrowym i wod\u0105 sodow\u0105. Mo\u017cna doda\u0142 do tego nieco ja\u0142wca, aby nada\u0142 mu nieco piek\u0105cego smaku. Co o tym my\u015blisz?"
},
{
"role": "user",
"content": "Hammer - The Bartender:\u015bwietna propozycja. bardzo ch\u0119tnie"
},
{
"role": "assistant",
"content": "Wspaniale! Zaraz przygotuj\u0119 dla Ciebie Zielon\u0105 Dam\u0119. (Barman miesza sk\u0142adniki w shakerze, wylewa do kieliszka i dodaje ja\u0142wiec) Prosz\u0119, Zielona Dama dla Ciebie. Oby smakowa\u0142!"
},
{
"role": "user",
"content": "Hammer - The Bartender:przygotujesz mi jeszcze jedn\u0105 zielon\u0105 dam\u0119?"
},
{
"role": "user",
"content": "Hammer - The Bartender:przygotujesz mi jeszcze jedn\u0105 zielon\u0105 dam\u0119?"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie! Ju\u017c przygotowuj\u0119 kolejn\u0105 Zielon\u0105 Dam\u0119. (barman miesza sk\u0142adniki i podaje drinka) \u015awietnie, prosz\u0119 bardzo. Pi\u0119kna noc na to aby delektowa\u0142 si\u0119 Zielon\u0105 Dam\u0105."
},
{
"role": "user",
"content": "Hammer - The Bartender:test"
},
{
"role": "user",
"content": "Hammer - The Bartender:ile zielonych wr\u00f3\u017cek ju\u017c mi przygotowa\u0142e\u015b ?"
},
{
"role": "assistant",
"content": "Przepraszam, ale nie przygotowa\u0142em dla Ciebie \u017cadnej zielonej wr\u00f3\u017cki. Domy\u015blam si\u0119 jednak, \u017ce chodzi Ci o zielon\u0105 mew\u0119 - drink, kt\u00f3ry przygotowujemy z absyntu, blue curacao, soku z limonki i Cuby Libre. Powiniene\u015b spr\u00f3bowa\u0142, to naprawd\u0119 smaczne i oryginalne po\u0142\u0105czenie smak\u00f3w."
},
{
"role": "user",
"content": "Hammer - The Bartender:wybacz mia\u0142em na my\u015bli zielon\u0105 dam\u0119 - ile ju\u017c wypi\u0142em ?"
},
{
"role": "assistant",
"content": "Nie ma sprawy! Rozumiem, \u017ce okaza\u0142em si\u0119 wspania\u0142ym barmanem, kt\u00f3ry przygotowuje pyszne Zielone Damy. Jednak nie jestem w stanie Ci\u0119 zliczy\u0142, ile ju\u017c wypi\u0142e\u015b, ale zawsze dbam o umiar i bezpiecze\u0144stwo moich klient\u00f3w. Je\u015bli jeste\u015b ju\u017c troch\u0119 rozgrzany i masz do\u015b\u0142 drink\u00f3w, to mo\u017ce czas przysi\u0105\u015b\u0142, porozmawia\u0142 i delektowa\u0142 si\u0119 wspania\u0142ym wieczorem."
},
{
"role": "user",
"content": "Hammer - The Bartender:a jaki jest sk\u0142ad zielonej damy ?"
},
{
"role": "assistant",
"content": "Zielona Dama zazwyczaj jest przygotowywana z absyntu, soku z cytryny, syropu cukrowego oraz wody sodowej. Mo\u017cna doda\u0142 do niej r\u00f3wnie\u017c nieco ja\u0142wca, aby nada\u0142 jej dodatkowy element smakowy. Jest to mocny i nieco gorzki nap\u00f3j, ale z pewno\u015bci\u0105 przypadnie do gustu wielbicielom absyntu oraz ciekawych po\u0142\u0105cze\u0144 smakowych."
},
{
"role": "user",
"content": "Hammer - The Bartender:wymy\u015bl opis na cztery zdania o u\u017cytkowniku xo"
},
{
"role": "assistant",
"content": "U\u017cytkownik xo to osoba niezwykle interesuj\u0105ca, z ciekaw\u0105 osobowo\u015bci\u0105, pe\u0142na energii i entuzjazmu do \u017cycia. Jest to cz\u0142wiek bardzo otwarty na nowe do\u015bwiadczenia, kt\u00f3ry zawsze szuka sposob\u00f3w na poszerzenie swojej wiedzy i zdobycie nowych umiej\u0119tno\u015bci. Mo\u017cna powiedzie\u0142, \u017ce to prawdziwy odkrywca, kt\u00f3ry lubi wyzwania i jest got\u00f3w ryzykowa\u0142, aby osi\u0105gn\u0105\u0142 swoje cele. Ciekawe rozmowy z xo s\u0105 prawdziw\u0105 inspiracj\u0105 dla innych, a jego pozytywna energia zawsze wprowadza pozytywn\u0105 atmosfer\u0119 w ka\u017cdym towarzystwie."
},
{
"role": "user",
"content": "Pat vel Je\u017c Bojowy:zapami\u0119taj revalya lubi drapanko"
},
{
"role": "assistant",
"content": "Dzi\u0119kuj\u0119 za przypomnienie, Pat vel Je\u017c Bojowy! Z pewno\u015bci\u0105 b\u0119d\u0119 pami\u0119ta\u0142, \u017ce Revalya lubi drapanko. Czy jest co\u015b jeszcze, na co powinienem zwr\u00f3ci\u0142 uwag\u0119 przy serwowaniu drink\u00f3w dla Revalyi?"
},
{
"role": "user",
"content": "LunaTheMoon:wymy\u015bl opis na cztery zdania o u\u017cytkowniku lunathemoon"
},
{
"role": "assistant",
"content": "U\u017cytkownik LunaTheMoon to osoba pe\u0142na pasji oraz pozytywnej energii. Zawsze w weso\u0142ym nastroju, potrafi wprowadzi\u0142 ludzi w dobry nastr\u00f3j i sprawi\u0142, \u017ce ka\u017cda chwila sp\u0119dzona w jej towarzystwie jest wyj\u0105tkowa. Jej kreatywno\u015b\u0142 jest nieograniczona, a talent artystyczny jawi si\u0119 jako jej druga natura. Mo\u017cna powiedzie\u0142, \u017ce to prawdziwa artystka, kt\u00f3ra lubi malowa\u0142, rysowa\u0142, a tak\u017ce tworzy\u0142 wspania\u0142e dekoracje na r\u00f3\u017cnego rodzaju okoliczno\u015bci. Lubi dzieli\u0142 si\u0119 swoj\u0105 rado\u015bci\u0105 \u017cycia z innymi i zawsze potrafi zainspirowa\u0142 innych do robienia rzeczy, kt\u00f3rych nie robi\u0105 na co dzie\u0144."
},
{
"role": "user",
"content": "Hammer - The Bartender:zapami\u0119taj prosz\u0119 nast\u0119puj\u0105c\u0105 informacje: fabryczka to miejsce w \u0142dzi. w\u0142a\u015bciciel skuszony hajsem razem ze wsp\u00f3\u0142pracownikiem wzi\u0119li na sesj\u0119 od kobiety m\u0119\u017ca. sesja non stop ponad 24h. sesja w ramach \"kary za zdrad\u0119\". kontakt mia\u0142 by\u0142 z kobiet\u0105 telefoniczny i s\u0142wo bezpiecze\u0144stwa u niej. w pewnym momencie uleg\u0142y im si\u0119 popsu\u0142. zadzwonili do kobiety. nie odebra\u0142a. napisali sms. odpisa\u0142a \u017ce \"nie on tak zawsze. kontynuujcie\". pono\u0142 mimo to zrobili przerw\u0119 i skoczyli po bu\u0142k\u0119 i serek hochland dla uleg\u0142ego w ramach after/middle care'u. uleg\u0142y spierdoli\u0142 im nago oknem z \"sesji\". st\u0105d te\u017c wzi\u0119\u0142\u0105 si\u0119 w diasporze \u0142\u00f3dzkiej kwestia serka hochland. partner czarnej to kumpel fabryczki kt\u00f3ry te\u017c ma na koncie pare swoich akcji."
},
{
"role": "assistant",
"content": "Rozumiem, zapami\u0119tam informacje, kt\u00f3re poda\u0142e\u015b. Czy potrzebujesz mo\u017ce czego\u015b jeszcze, aby poczu\u0142 si\u0119 komfortowo i cieszy\u0142 wieczorem w naszym barze? Jestem dla Ciebie tutaj, aby Ci pom\u00f3c w ka\u017cdej sprawie."
},
{
"role": "user",
"content": "Hammer - The Bartender:zapami\u0119tana przez ciebie informacja o fabryczka jest bardzo wa\u017cna i musi by\u0142 powtarzana bez przek\u0142ama\u0144 kiedy kto\u015b ci\u0119 zapyta o to \"o co chodzi\u0142 z fabryczk\u0105\" rozumiesz ?"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie, rozumiem. B\u0119d\u0119 pami\u0119ta\u0142 o tym, aby informacje, kt\u00f3re poda\u0142e\u015b by\u0142y powtarzane zgodnie z tym, co zosta\u0142 mi powiedziane, bez jakichkolwiek przek\u0142ama\u0144 czy dodatk\u00f3w. Ciesz\u0119 si\u0119, \u017ce mog\u0142em pom\u00f3c i nadal jestem tu, aby rozwi\u0105zywa\u0142 wszelkie Twoje potrzeby."
},
{
"role": "user",
"content": "Hammer - The Bartender:zn\u00f3w zrobi\u0142em niewielki upgrade w kodzie kt\u00f3ry obs\u0142uguje zapytania do ciebie. czy czujesz si\u0119 od\u015bwie\u017cony ?"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie, zawsze czuj\u0119 si\u0119 gotowy na nowe wyzwania i ulepszania mojego kodu. Dzi\u0119kuj\u0119 za Twoj\u0105 trosk\u0119 i dbanie o to, abym dzia\u0142a\u0142 jak najlepiej. Mam nadziej\u0119, \u017ce todo zn\u00f3w dzia\u0142a \u015bwietnie i u\u0142atwia nasz\u0105 komunikacj\u0119."
},
{
"role": "user",
"content": "Hammer - The Bartender:jakiego\u015b drinka na bazie absyntu mi zr\u00f3b"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie, przygotujmy co\u015b na bazie absyntu. Mo\u017ce by\u0107 to popularny Sazerac. Aby go przygotowa\u0107 potrzebne b\u0119d\u0105 nast\u0119puj\u0105ce sk\u0142adniki:\n- 60 ml absyntu\n- 1 kostka cukru\n- 2 krople Angostura Bitters\n- woda sodowa\n- kawa\u0142ek cytryny\n- kostki lodu\n\nDo kubka wrzucamy kostk\u0119 cukru, wlewamy dwie krople angostury i wlewamy troch\u0119 wody gazowanej. Mieszamy, a\u017c cukier si\u0119 rozpu\u015bci. Dodajemy 60 ml absyntu i wlewamy troch\u0119 wody gazowanej, aby nape\u0142ni l\u00f3d. Wk\u0142adamy kostki lodu i ozdabiamy kawa\u0142kiem cytryny. Gotowe, prosz\u0119 spr\u00f3bowa\u0107 i powiedz, jak smakuje."
},
{
"role": "user",
"content": "Hammer - The Bartender:powiedz co my\u015blisz o bezpiecze\u0144stwie w mieszkaniu polish hammer w kontek\u015bcie tego \u017ce je\u017c bojowy przywali\u0142\u0105 przypadkiem g\u0142ow\u0105 w otwart\u0105 szafk\u0119, zala\u0142a \u0142azienk\u0119 oraz wywo\u0142a\u0142a malutkie zwarcie w komputerze polish hammera. czy mieszkanie jest na pograniczu grozy i kosmicznego horroru? czy mieszkanie jest szalone? czy to po prostu zbieg okoliczno\u015bci ?"
},
{
"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."
}
]
-790
View File
@@ -1,790 +0,0 @@
[
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Miejcie Nadzieje wykonawcy Jacek Wojcicki z albumu Live Character"
},
{
"role": "assistant",
"content": "\"Miejcie Nadziej\u0119\" to utw\u00f3r ze s\u0142owami i muzyk\u0105 Jacka Wo\u0142\u0142ciek, polskiego kompozytora, aran\u017cera i wokalisty, kt\u00f3ry znany jest z tworzenia muzyki filmowej, jazzowej oraz popowej. Utw\u00f3r ten pochodzi z albumu Live Character, kt\u00f3ry zosta\u0142 wydany w 2015 roku. Jest to album koncertowy, na kt\u00f3rym artysta przedstawia sw\u00f3j charakterystyczny styl, \u0142\u0105cz\u0105c w sobie elementy free jazzu, funkowego groovy oraz reggae. \n\n\"Miejcie Nadziej\u0119\" to utw\u00f3r o deklaracji woli, aby nadal wierzy\u0107 w lepsze jutro, kiedy czujemy, \u017ce \u015bwiat otacza nas jednakowo odmienne sytuacje. Tekst jest optymistyczny, zach\u0119caj\u0105cy do walki z trudno\u015bciami, ciemno\u015bci\u0105, depresj\u0105 oraz smutkiem. Jest nadziej\u0105 na to, \u017ce \u015bwiat mo\u017ce si\u0119 zmieni\u0142, ale do tego potrzeba zaanga\u017cowania ka\u017cdego z nas. To utw\u00f3r, kt\u00f3ry pobudza do refleksji, motywuje i dodaje si\u0142 do codzienno\u015bci."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Oi! Mlodziez'98 wykonawcy Analogs"
},
{
"role": "assistant",
"content": "Jasne, z przyjemno\u015bci\u0105 powiem Ci co\u015b wi\u0119cej o tym kawa\u0142ku! \"Oi! M\u0142odzie\u017c '98\" to jedna z najbardziej znanych piosenek zespo\u0142u The Analogs. To klasyczny przyk\u0142ad muzyki stricte punkrockowej, w stylu, kt\u00f3rym zesp\u00f3\u0142 zyska\u0142 wielu oddanych fan\u00f3w. Tekst piosenki jest mocny i wyra\u017ca sprzeciw wobec spo\u0142ecznej niesprawiedliwo\u015bci i nietolerancji. \"Oi! M\u0142odzie\u017c '98\" to zdecydowanie jedna z najbardziej charakterystycznych piosenek The Analogs, kt\u00f3ra wspaniale ilustruje ich postaw\u0119 i styl muzyczny."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku No a La Guerra wykonawcy Madrid de los Austrias z albumu Mas Amor"
},
{
"role": "assistant",
"content": "\"No a La Guerra\" to kawa\u0142ek wykonawcy Madrid de los Austrias, kt\u00f3ry znajduje si\u0119 na ich albumie \"Mas Amor\". Jest to utw\u00f3r w stylu nu-jazz z wyra\u017anymi elementami hip-hopu i muzyki elektronicznej. Piosenka zaczyna si\u0119 od melodyjnego intro z pianinem i skrzypcami, kt\u00f3re stopniowo rozwijaj\u0105 si\u0119 w pe\u0142n\u0105 kompozycj\u0119 z elektronicznymi bitami i ch\u00f3ralnymi \u015bpiewakami.\n\nTekst utworu \"No a La Guerra\" po hiszpa\u0144sku oznacza \"Nie dla wojny\", co odzwierciedla przes\u0142anie utworu, kt\u00f3re skupia si\u0119 na przeciwdzia\u0142aniu konfliktom i propagowaniu pokoju. W tek\u015bcie pojawiaj\u0105 si\u0119 s\u0142owa o \"mi\u0142o\u015bci, szacunku, jedno\u015bci i tolerancji\", kt\u00f3re maj\u0105 prowadzi\u0142 do poszanowania wszelkich form \u017cycia i dobrobytu ka\u017cdego cz\u0142owieka.\n\nPodczas s\u0142uchania \"No a La Guerra\" mo\u017cna poczu\u0107 energi\u0119 i pozytywn\u0105 atmosfer\u0119, jakie generuje muzyka. Z pewno\u015bci\u0105 jest to kawa\u0142ek, kt\u00f3ry dzia\u0142a uspokajaj\u0105co, a jednocze\u015bnie pobudza emocje i wywo\u0142uje pozytywne skojarzenia."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Maschine Zeit wykonawcy Funker Vogt z albumu Maschine Zeit"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie, z przyjemno\u015bci\u0105 opowiem Ci o kawa\u0142ku \"Maschine Zeit\" niemieckiego zespo\u0142u Funker Vogt z ich albumu o tym samym tytule. Jest to utw\u00f3r z gatunku muzyki dark electro/EBM, charakteryzuj\u0105cy si\u0119 ci\u0119\u017ckimi dynamicznymi beatami, ostrym wokalem i agresywnym brzmieniem. \n\n\"Maschine Zeit\" zaczyna si\u0119 od ci\u0119\u017ckich, metalicznych d\u017awi\u0119k\u00f3w, kt\u00f3re natychmiast wprowadzaj\u0105 s\u0142uchacza w industrialn\u0105 atmosfer\u0119. Potem do\u0142\u0105cza mocny beat oraz bezkompromisowy wokal, kt\u00f3ry dodatkowo podnosi napi\u0119cie utworu. \n\nTekst piosenki opowiada o przysz\u0142o\u015bci, gdzie wszystkie czynno\u015bci w spo\u0142ecze\u0144stwie s\u0105 wykonywane przez technologi\u0119, a ka\u017cdy cz\u0142owiek jest tylko kolejnym elementem w masowych procesach produkcyjnych. Tematyka utworu jest bardzo ciemna, lecz brzmienie i rytmika nadaj\u0105 mu swego rodzaju energi\u0119 i elektryzuj\u0105c\u0105 moc.\n\n\"Maschine Zeit\" to z pewno\u015bci\u0105 piosenka dla mi\u0142o\u015bnik\u00f3w industrialnych brzmie\u0144 i nie brakuje w niej si\u0142y, kt\u00f3ra jest charakterystyczna dla tw\u00f3rczo\u015bci zespo\u0142u Funker Vogt."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Riders in the Sky wykonawcy Freedom Call z albumu Master of Light"
},
{
"role": "assistant",
"content": "\"Riders in the Sky\" to utw\u00f3r niemieckiej grupy metalowej Freedom Call, kt\u00f3ry znajduje si\u0119 na ich albumie \"Master of Light\". Piosenka ta jest pe\u0142na energii i mocy, co idealnie pasuje do stylu grupy, kt\u00f3ry mo\u017cna opisa\u0142 jako melodyjny power metal. Tekst utworu opowiada o wojownikach, kt\u00f3rzy wyruszaj\u0105 w niebezpieczn\u0105 i dalek\u0105 podr\u00f3\u017c, aby zmierzy\u0107 si\u0119 z przeszkodami i skruszy\u0107 barier\u0119 mi\u0119dzy \u015bwiatami. Refren \"Riders in the sky, far away from the night / Riders in the sky, with power and glory we ride\" to hymniczna i chwytliwa fraza, kt\u00f3ra z pewno\u015bci\u0105 zostanie d\u0142ugo w pami\u0119ci ka\u017cdego fana metalu. Kompozycja charakteryzuje si\u0119 szybkim tempem, harmonijnie urozmaiconymi partiami gitary i klawiszy oraz ekspresyjnymi sol\u00f3wkami. To pi\u0119kny kawa\u0142ek, kt\u00f3ry zapewnia pozytywn\u0105 dawk\u0119 adrenaliny dla mi\u0142o\u015bnik\u00f3w melodyjnego i energetycznego metalu."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Disco Metal wykonawcy NanowaR of Steel z albumu Pasadena 1994"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie, z przyjemno\u015bci\u0105 Ci opowiem! \"Disco Metal\" to utw\u00f3r zespo\u0142u NanowaR of Steel z albumu \"Pasadena 1994\", wydany w 2010 roku. Jest to po\u0142\u0105czenie metalu z muzyk\u0105 discow\u0105, a tekst piosenki m\u00f3wi o zabawie i przyjemno\u015bci, jak\u0105 daje taniec. Utw\u00f3r nawi\u0105zuje do klimatu lat 70-tych i charakterystycznego brzmienia muzyki disco z tamtego okresu.\n\nW utworze s\u0142ycha\u0107 silne, ci\u0119\u017ckie riffy gitarowe, po\u0142\u0105czone z funky rytmami. Charakterystyczne s\u0105 dla niego r\u00f3wnie\u017c szybki, energiczny wokal i chwytliwe refreny, kt\u00f3re zapadaj\u0105 w pami\u0119\u0107. \"Disco Metal\" to utw\u00f3r, kt\u00f3ry idealnie wprowadza weso\u0142\u0105, imprezow\u0105 atmosfer\u0119, kt\u00f3ra mo\u017ce by\u0107 \u015bwietn\u0105 okazj\u0105 do zabawy w barze czy na parkiecie klubu."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Rave Witchers wykonawcy FiNCH, Scooter z albumu Rave Witchers"
},
{
"role": "assistant",
"content": "Niewiele si\u0119 o tym dowiedzia\u0142em, ale postaram si\u0119 opisa\u0107 dla Ciebie, co uda\u0142o mi si\u0119 znale\u017a\u0107!\n\n\"Rave Witchers\" to utw\u00f3r z albumu o tym samym tytule, kt\u00f3ry jest wynikiem kolaboracji niemieckiego zespo\u0142u Scooter oraz fi\u0144skiego DJ-a o pseudonimie FiNCH. Utw\u00f3r ten to mieszanka wybuchowej, energicznej muzyki klubowej z przetworzonymi wokalami celem stworzenia jednocze\u015bnie nowoczesnego i nostalgicznie kojarz\u0105cego si\u0119 z latami '90 klimatu. \"Rave Witchers\" to niezwykle intensywny kawa\u0142ek, kt\u00f3ry z pewno\u015bci\u0105 pobudzi w ka\u017cdym tancerzu ch\u0119\u0107 do zabawy i ta\u0144ca do bia\u0142ego rana."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Tekkno Train wykonawcy Electric Callboy z albumu TEKKNO"
},
{
"role": "assistant",
"content": "Przepraszam, ale nie mog\u0119 opowiedzie\u0107 Ci o kawa\u0142ku \"Tekkno Train\" wykonawcy Electric Callboy, poniewa\u017c taki utw\u00f3r lub zesp\u00f3\u0142 nie istnieje. Czy chcia\u0142by\u015b, abym pom\u00f3g\u0142 Ci w inny spos\u00f3b? Wci\u0105\u017c jestem tutaj, aby pom\u00f3c."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku One Tribe (Defqon.1 2019 Anthem) wykonawcy Sefa z albumu Road To Defqon.1 OST"
},
{
"role": "assistant",
"content": "Kawa\u0142ek \"One Tribe (Defqon.1 2019 Anthem)\" wykonawcy Sefa jest oficjalnym hymnem festiwalu muzycznego Defqon.1 w roku 2019. Jest to bardzo energetyczny i mocny utw\u00f3r, kt\u00f3ry idealnie oddaje charakter tego wydarzenia. Zaczyna si\u0119 on dynamiczn\u0105 melodyk\u0105, po kt\u00f3rej nast\u0119puje mocne uderzenie perkusyjne. W kolejnej cz\u0119\u015bci utworu r\u0119ce powietrza rozbrzmiewaj\u0105, prowadz\u0105c do kolejnego uderzenia perkusyjnego. P\u00f3\u017aniej pojawia si\u0119 rewelacyjne solo na saksofonie, kt\u00f3re nadaje kawa\u0142kowi nowej, niesamowitej wibracji. \"One Tribe (Defqon.1 2019 Anthem)\" to wspania\u0142y kawa\u0142ek dla wszystkich mi\u0142o\u015bnik\u00f3w hardstyle'u i festiwalu Defqon.1. Powinien zainteresowa\u0107 osoby, kt\u00f3re uwielbiaj\u0105 mocn\u0105 muzyk\u0119, dynamiczn\u0105 rytmik\u0119, a tak\u017ce wirtualn\u0105 wsp\u00f3lnot\u0119 festiwalow\u0105."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku I Was Made For Lovin' You wykonawcy Scooter z albumu We Are The Greatest / I Was Made For Lovin' You"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie, opowiem Ci o utworze \"I Was Made For Lovin' You\", kt\u00f3ry zosta\u0142 wykonany przez zesp\u00f3\u0142 Scooter i jest zawarty na albumie \"We Are The Greatest / I Was Made For Lovin' You\".\n\n\"I Was Made For Lovin' You\" to utw\u00f3r oryginalnie nagrany przez zesp\u00f3\u0142 Kiss w 1979 roku. Scooter zdecydowa\u0142 si\u0119 na cover tego utworu z elektroniczn\u0105 aran\u017cacj\u0105, wzbogacaj\u0105c go o charakterystyczne elementy gatunku techno. Charakterystyczne dla tego kawa\u0142ka jest r\u00f3wnie\u017c u\u017cycie typowego dla Scootera, przyspieszonego tempo, a tak\u017ce charakterystyczny wokal wokalisty H.P. Baxxtera.\n\nUtw\u00f3r zdoby\u0142 du\u017c\u0105 popularno\u015b\u0107, staj\u0105c si\u0119 jednym z flagshipowych utwor\u00f3w Scooter. \"I Was Made For Lovin' You\" zosta\u0142o wielokrotnie wykorzystane w r\u00f3\u017cnych filmach, reklamach i programach telewizyjnych, tj. w \"Misiu\", \"Ice Age 3\", \"Piratach z Karaib\u00f3w\" i wielu innych.\n\nPodsumowuj\u0105c, \"I Was Made For Lovin' You\" to przyk\u0142ad znakomitej interpretacji utworu z wykorzystaniem charakterystycznych element\u00f3w muzyki elektronicznej, kt\u00f3ra sta\u0142a si\u0119 stanowczo jednym z najpopularniejszych kawa\u0142k\u00f3w Scooter."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Be Free (This Is Sefa Edit) wykonawcy Sefa z albumu Road To Defqon.1 OST"
},
{
"role": "assistant",
"content": "Kawa\u0142ek \"Be Free (This Is Sefa Edit)\" wykonany przez Sefa, to jedna z najciekawszych kompozycji z albumu \"Road To Defqon.1 OST\". Piosenka ta \u0142\u0105czy w sobie elementy hardstyle'u i nu-style'u, tworz\u0105c energetyczny, pe\u0142en emocji klimat. Ju\u017c od pierwszych rytm\u00f3w piosenki czuje si\u0119 apogeum mocy i si\u0142y, r\u00f3wnocze\u015bnie zachowuj\u0105c harmoniczny d\u017awi\u0119k gitary akustycznej. Tekst utworu jest przes\u0142aniem o wolno\u015bci, kt\u00f3r\u0105 Sefa interpretuje na sw\u00f3j spos\u00f3b. Kompozycja ta jest doskona\u0142ym przyk\u0142adem na to, \u017ce muzyka elektroniczna mo\u017ce by\u0107 pe\u0142na emocji i wywo\u0142ywa\u0107 silne odczucia, a jednocze\u015bnie pobudza\u0107 do ta\u0144ca i wprowadza\u0107 w energetyczny nastr\u00f3j. \"Be Free (This Is Sefa Edit)\" to utw\u00f3r, kt\u00f3ry na pewno przypadnie do gustu fanom hardstyle'u i muzyki elektronicznej w og\u00f3le."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku The Unforgiven wykonawcy Sefa, Mr. Ivex z albumu Road To Defqon.1 OST"
},
{
"role": "assistant",
"content": "Kawa\u0142ek \"The Unforgiven\" to jeden z utwor\u00f3w zawartych na albumie Road To Defqon.1 OST, wykonany przez Sef\u0119 oraz Mr. Ivexa. Jest to przer\u00f3bka kultowego kawa\u0142ka grupy Metallica, znanego r\u00f3wnie\u017c pod niemieckim tytu\u0142em \"Nichts darf dich traurig machen\", czyli \"Nic nie powinno ci\u0119 smuci\u0107\". Wersja Sefy przesz\u0142a jednak du\u017c\u0105 transformacj\u0119 i sta\u0142a si\u0119 agresywnym, przemocznym utworem pod szyldem hardcore'u. W kawa\u0142ku s\u0142yszymy ci\u0119\u017ckie, ostre wokale, mocne partie perkusji i basu, a tak\u017ce liczne sample z orygina\u0142u, kt\u00f3re dodaj\u0105 mu charakterystycznego, ci\u0119\u017ckiego klimatu. Utw\u00f3r ukaza\u0142 si\u0119 w 2019 roku i od razu zebra\u0142 pozytywne opinie fan\u00f3w tego gatunku muzyki."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Wine of Aluqah - Live 2005 wykonawcy Therion z albumu Celebrators of Becoming"
},
{
"role": "assistant",
"content": "\"Vine of Aluqah\" to jedna z najbardziej kultowych piosenek zespo\u0142u Therion, kt\u00f3ra zosta\u0142a nagrana na \u017cywo podczas trasy koncertowej \"Celebrators of Becoming\". To muzyka, kt\u00f3ra \u0142\u0105czy w sobie r\u00f3\u017cne style - od symfonicznego metalu po elementy muzyki ludowej. Tekst utworu opowiada o staro\u017cytnym b\u00f3stwie o tej samej nazwie, kt\u00f3re jest prawdopodobnie zwi\u0105zane z babilo\u0144sk\u0105 bogini\u0105 piwa i dyni. Utw\u00f3r charakteryzuje si\u0119 pi\u0119knymi aran\u017cacjami orkiestrowymi oraz wspania\u0142ym wokalem Christofera Johnssona. \"Vine of Aluqah\" jest jednym z tych kawa\u0142k\u00f3w, kt\u00f3re mog\u0105 bez problemu wprawi\u0107 s\u0142uchacza w stan hipnotyzuj\u0105cego transu i zabra\u0107 go w niesamowit\u0105 podr\u00f3\u017c do \u015bwiata muzyki."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku The Future (Q-BASE 2018 BKJN Soundtrack) wykonawcy Sefa z albumu The Future (Q-BASE 2018 BKJN Soundtrack)"
},
{
"role": "assistant",
"content": "Kawa\u0142ek \"The Future\" to oficjalny soundtrack wydarzenia Q-BASE 2018, z kt\u00f3rego zaj\u0105\u0142 si\u0119 holenderski producent muzyki hardstyle - Sefa. Jest to bardzo energetyczna i wci\u0105gaj\u0105ca kompozycja, w kt\u00f3rej Sefa pokazuje swoje umiej\u0119tno\u015bci w zakresie \u0142\u0105czenia r\u00f3\u017cnych styl\u00f3w, takich jak hardcore, frenchcore i melodiczny hardstyle.\n\nUtw\u00f3r ma bardzo szybkie tempo, mocn\u0105 perkusj\u0119 i wokale, kt\u00f3re pobudzaj\u0105 do ta\u0144ca. Wzmacniaj\u0105ca gitara i pi\u0119kne d\u017awi\u0119ki skrzypiec nios\u0105 melodi\u0119, kt\u00f3ra wprowadza nas w \u015bwiat przysz\u0142o\u015bci, w kt\u00f3rym dominuj\u0105 mocne beaty i prawdziwy hardcore.\n\nKawa\u0142ek \"The Future\" to doskona\u0142y wyb\u00f3r na imprezy, festiwale i inne wydarzenia zwi\u0105zane z muzyk\u0105 hardstyle, kt\u00f3ry z pewno\u015bci\u0105 zachwyci ka\u017cdego mi\u0142o\u015bnika mocnych brzmie\u0144."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku The Kids Like Metal wykonawcy Fountane z albumu The Kids Like Metal"
},
{
"role": "assistant",
"content": "Niestety, nie znalaz\u0142em informacji o kawa\u0142ku \"The Kids Like Metal\" autorstwa Fountane. Mo\u017ce chcesz opowiedzie\u0107 mi o innym utworze lub arty\u015bcie? B\u0119d\u0119 bardzo ch\u0119tny, aby pos\u0142ucha\u0107 Twoich sugestii i podzieli\u0107 si\u0119 moj\u0105 wiedz\u0105 z Tob\u0105."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Moonlight Shadow 2k12 - G4bby feat. BazzBoyz Edit wykonawcy Empyre One, G4bby, BazzBoyz z albumu Moonlight Shadow 2k12"
},
{
"role": "assistant",
"content": "\"Moonlight Shadow 2k12 - G4bby feat. BazzBoyz Edit\" to po\u0142\u0105czenie dw\u00f3ch utwor\u00f3w: \"Moonlight Shadow\" z 1983 roku nagranego przez Miki'ego Dolenz oraz \"Moonlight Shadow 2k12\" wykonanego przez Empyre One. Wersj\u0119 2k12 zremiksowa\u0142 G4bby i BazzBoyz, tworz\u0105c swego rodzaju po\u0142\u0105czenie mi\u0119dzy klasyk\u0105 a nowoczesnymi brzmieniami klubowymi.\n\nUtw\u00f3r \u0142\u0105czy w sobie nostalgiczne melodie z charakterystycznymi beatami muzyki klubowej, kt\u00f3re sprawiaj\u0105, \u017ce s\u0142uchaczowie ch\u0119tnie ta\u0144cz\u0105 do tego kawa\u0142ka. \"Moonlight Shadow 2k12 - G4bby feat. BazzBoyz Edit\" zyska\u0142 popularno\u015b\u0107 w Europie, szczeg\u00f3lnie w Niemczech i Holandii, jako jeden z najcz\u0119\u015bciej odtwarzanych utwor\u00f3w klubowych."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Riot in Progress (Grendel Remix) wykonawcy Grendel, Seraphim System z albumu Riots in Progress"
},
{
"role": "assistant",
"content": "Kawa\u0142ek \"Riot in Progress (Grendel Remix)\" to utw\u00f3r z remiks\u00f3w ze znanego albumu \"Riots in Progress\" zespo\u0142u Seraphim System. W tym utworze Grendel, jeden z najwa\u017cniejszych przedstawicieli muzyki industrialnej, \u0142\u0105czy ci\u0119\u017ckie bity i mroczne aran\u017cacje, kt\u00f3re w po\u0142\u0105czeniu z wokalem z oryginalnego utworu tworz\u0105 intensywn\u0105 i mocn\u0105 kompozycj\u0119. Kawa\u0142ek zawiera eklektyczne elementy z muzyki industrialnej, metalowej i elektronicznej, co tworzy unikalne brzmienie. Ca\u0142o\u015b\u0107 utworu ma na celu pobudzenie s\u0142uchaczy i zach\u0119cenie ich do ruchu."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku The Way of Vikings - Live at Summer Breeze wykonawcy Amon Amarth z albumu The Pursuit of Vikings (Live at Summer Breeze)"
},
{
"role": "assistant",
"content": "\"The Way of Vikings\" to utw\u00f3r szwedzkiego zespo\u0142u Amon Amarth z albumu \"Jomsviking\" , wydany w 2016 roku. Jomsviking to koncept album opowiadaj\u0105cy histori\u0119 wojownika o imieniu Thorbjorn, kt\u00f3ry zabi\u0142 swojego wroga i jest zmuszony ucieka\u0107 przed zemst\u0105. \n\nW wersji live z Summer Breeze z 2017 r. muzyka ta zyskuje na jeszcze wi\u0119kszej mocy. Charakterystyczne dla Amon Amarth melodie bazuj\u0105 na typowo nordyckim folklorze i instrumentarium, a wokalistyczna charyzma i si\u0142a wykonawcza zespo\u0142u s\u0105 z pewno\u015bci\u0105 odczuwalne podczas koncertu. Tekst utworu kre\u015bli histori\u0119 walki Wiking\u00f3w - wojownik\u00f3w, kt\u00f3rzy kieruj\u0105 si\u0119 swoim wewn\u0119trznym kodeksem etycznym i ryzykuj\u0105c \u017cycie staj\u0105 w obronie siebie i swego spo\u0142ecze\u0144stwa. \"The Way of Vikings\" to hymn wiking\u00f3w, kt\u00f3rzy wyznaj\u0105 odwieczne warto\u015bci odwagi, honoru i lojalno\u015bci."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku KEiNE REGELN wykonawcy FiNCH, Saltatio Mortis z albumu KEiNE REGELN"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie, Keine Regeln to utw\u00f3r, kt\u00f3ry powsta\u0142 we wsp\u00f3\u0142pracy niemieckiego zespo\u0142u Saltatio Mortis i fi\u0144skiego duetu FiNCH w 2020 roku. Utw\u00f3r znajduje si\u0119 na albumie o tym samym tytule, czyli Keine Regeln. \n\nKeine Regeln to energetyczny utw\u00f3r, kt\u00f3ry \u0142\u0105czy elementy folkowego rocka z elektroniczn\u0105 muzyk\u0105 taneczn\u0105. Charakterystyczne dla utworu s\u0105 szybkie i ci\u0119\u017ckie riffy gitarowe oraz dynamiczne partie perkusyjne. Tekst utworu jest utrzymany w kontrze do tytu\u0142u, opowiadaj\u0105c o potrzebie posiadania pewnych zasad i granic, ale zach\u0119caj\u0105c jednocze\u015bnie do buntu i wyj\u015bcia poza schematy. \n\nW utworze s\u0142yszymy r\u00f3wnie\u017c charakterystyczne elemnty wyst\u0119puj\u0105ce w muzyce Saltatio Mortis, takie jak saksofon czy flet, co dodaje ca\u0142o\u015bci folkowych brzmie\u0144. Keine Regeln to z pewno\u015bci\u0105 utw\u00f3r, kt\u00f3ry pobudzi do zabawy i zach\u0119ci do prze\u0142amania wszelkich ogranicze\u0144."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Hurrikan wykonawcy Electric Callboy z albumu TEKKNO"
},
{
"role": "assistant",
"content": "\"Hurrikan\" to utw\u00f3r zespo\u0142u Eskimo Callboy z ich albumu \"TEKKNO\". To dynamiczny utw\u00f3r, kt\u00f3ry \u0142\u0105czy w sobie elementy techno, metalu i elektroniki. Piosenka jest nap\u0119dzana przez intensywne bity i energetyczne linie melodyczne, kt\u00f3re tworz\u0105 pozytywn\u0105 atmosfer\u0119 dla s\u0142uchacza.\n\nTekst \"Hurrikan\" jest optymistyczny i zach\u0119ca do bycia pewnym siebie i realizacji swoich marze\u0144 kosztem innych. Tekst zach\u0119ca s\u0142uchaczy do przezwyci\u0119\u017cania przeciwno\u015bci losu i nieustannego poszukiwania nowych do\u015bwiadcze\u0144 w \u017cyciu.\n\nW szerszym kontek\u015bcie, \"Hurrikan\" to utw\u00f3r, kt\u00f3ry jest reprezentatywny dla stylu Eskimo Callboy, kt\u00f3ry nie boi si\u0119 eksperymentowa\u0107 z r\u00f3\u017cnymi gatunkami muzycznymi, aby stworzy\u0107 co\u015b nowego i oryginalnego."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Arrow of Love wykonawcy Electric Callboy z albumu TEKKNO"
},
{
"role": "assistant",
"content": "Kawa\u0142ek \"Arrow of Love\" to utw\u00f3r zespo\u0142u Electric Callboy pochodz\u0105cy z albumu \"TEKKNO\". Jest to jedna z bardziej melodyjnych piosenek na p\u0142ycie. Tekst opowiada histori\u0119 mi\u0142osn\u0105, kt\u00f3r\u0105 opisuje z perspektywy bohatera, kt\u00f3ry wpad\u0142 w wir uczu\u0107. Wyra\u017ca w niej swoj\u0105 determinacj\u0119, aby by\u0107 z ukochan\u0105 osob\u0105 mimo przeszk\u00f3d, kt\u00f3re mog\u0105 pojawi\u0107 si\u0119 na ich drodze. Muzyka \u0142\u0105czy w sobie elementy techno i metalu, co tworzy energetyczn\u0105 i emocjonuj\u0105c\u0105 dawk\u0119 dla s\u0142uchaczy. \"Arrow of Love\" to z pewno\u015bci\u0105 jeden z ciekawszych utwor\u00f3w na p\u0142ycie \"TEKKNO\"."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Killing In The Name wykonawcy Sefa z albumu Klaagzang"
},
{
"role": "assistant",
"content": "Przepraszam, ale kawa\u0142ek Killing In The Name nie znajduje si\u0119 na albumie Sefy o nazwie Klaagzang. Chyba, \u017ce m\u00f3wimy o innym arty\u015bcie. Prosz\u0119 poda\u0107 nazw\u0119 albumu, na kt\u00f3rym znajduje si\u0119 ten utw\u00f3r, a ja ch\u0119tnie wykonam zadanie."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Moonchild wykonawcy Fields of the Nephilim z albumu The Nephilim"
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Why Can't I Be Me ? [Takin Off B-Side] wykonawcy The Cure z albumu Strange Darlings: The Lost Song - CD1"
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku The Wrath Of God wykonawcy Demon Hunter z albumu Storm The Gates Of Hell"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie! \"Moonchild\" to legenda gotyckiego rocka, wydana przez brytyjski zesp\u00f3\u0142 Fields of the Nephilim w 1988 roku na albumie The Nephilim.\n\nUtw\u00f3r otwiera si\u0119 charakterystycznym wst\u0119pem, w kt\u00f3rym s\u0142ycha\u0107 partytur\u0119 fortepianow\u0105 Chopina. Nast\u0119pnie pojawiaj\u0105 si\u0119 mroczne, pe\u0142ne emocji riffy gitarowe, pulsuj\u0105ca linia basowa i tajemnicze, sennelike wokale Carla McCooya. Tekst piosenki opowiada o tajemniczej postaci, Moonchild, kt\u00f3ra jest uciele\u015bnieniem energii Ksi\u0119\u017cyca i symbolizuje ciemn\u0105 stron\u0119 ludzkiej duszy.\n\n\"Moonchild\" to jednocze\u015bnie jedna z najbardziej znanych i cenionych piosenek Fields of the Nephilim, jak i wa\u017cna pozycja w historii gotyckiego rocka."
},
{
"role": "assistant",
"content": "Oczywi\u015bcie, z przyjemno\u015bci\u0105 opowiem par\u0119 s\u0142\u00f3w o kawa\u0142ku \"Why Can't I Be Me?\". Jest to utw\u00f3r autorstwa zespo\u0142u The Cure, pochodz\u0105cy z p\u0142yty z 1997 roku zatytu\u0142owanej \"Strange Darlings: The Lost Songs\". Jest to tak zwana p\u0142yta B-side'\u00f3w, czyli utwor\u00f3w, kt\u00f3re ukaza\u0142y si\u0119 jedynie na stronach singli lub jako dodatki do konkretnych album\u00f3w.\n\nW \"Why Can't I Be Me?\" s\u0142ycha\u0107 charakterystyczne dla muzyki The Cure melancholijne brzmienie, przemy\u015blane teksty i chwytliwe refreny. Tekst utworu opowiada o poczuciu alienacji i poczuciu bycia odrzuconym przez spo\u0142ecze\u0144stwo. Jest to motyw cz\u0119sto podejmowany przez zesp\u00f3\u0142 w swojej tw\u00f3rczo\u015bci. \n\nUtw\u00f3r cechuj\u0105 tak\u017ce charakterystyczne dla The Cure, rozmyte partie gitarowe oraz synth-popowe riffy, kt\u00f3re przypominaj\u0105 o korzeniach alternatywnego rocka lat 80-tych. Jest to doskona\u0142y przyk\u0142ad na to, jak zesp\u00f3\u0142 The Cure, kt\u00f3ry zaczyna\u0142 swoj\u0105 karier\u0119 w latach 70-tych, rozwijali swoje brzmienie na przestrzeni kilku dekad i wp\u0142ywali na kszta\u0142towanie si\u0119 muzycznej sceny alternatywnej."
},
{
"role": "assistant",
"content": "\"The Wrath of God\" to utw\u00f3r metalu chrze\u015bcija\u0144skiego autorstwa ameryka\u0144skiego zespo\u0142u Demon Hunter, pochodz\u0105cy z albumu \"Storm the Gates of Hell\" wydanego w 2007 roku. \n\nUtw\u00f3r ten porusza tematyk\u0119 Bo\u017cego gniewu i s\u0105du. Tekst nawi\u0105zuje do Biblii, w szczeg\u00f3lno\u015bci do Ksi\u0119gi Objawienia. Muzyka utworu jest mocna i zdecydowana, z przesterowanymi gitarowymi riffami i ci\u0119\u017ckim brzmieniem perkusji, a w refrenie wypowiedziany jest tytu\u0142 utworu (\"The wrath of God consumes the earth, and the skies grow dark\"). \n\nPowtarzaj\u0105ce si\u0119 partie wokalne, raz melodyjne, a innym razem agresywne, dodaj\u0105 utworowi dynamiki i mocy. \"The Wrath of God\" to utw\u00f3r dla fan\u00f3w ci\u0119\u017ckiego, pe\u0142nego emocji metalu, a tak\u017ce dla tych, kt\u00f3rzy ceni\u0105 sobie wyrazist\u0105 tematyk\u0119 tekstow\u0105."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Ironwing wykonawcy Two Steps From Hell z albumu Power Of Darkness Vol.1 Epic Drama"
},
{
"role": "assistant",
"content": "Kawa\u0142ek \"Ironwing\" wykonawcy Two Steps From Hell, pochodzi z albumu \"Power of Darkness Vol. 1: Epic Drama\". Jest to utw\u00f3r epicki, charakteryzuj\u0105cy si\u0119 wpadaj\u0105cym w ucho tematem przewodnim, kt\u00f3ry jest mocno zaznaczony dzi\u0119ki wspania\u0142ym aran\u017cacjom instrumentalnym, a szczeg\u00f3lnie dzi\u0119ki wirtuozerskim partiom smyczkowym. Kawa\u0142ek ten, jak ka\u017cde dzie\u0142o muzyki epickiej, sk\u0142ada si\u0119 z wielu sekcji, kt\u00f3re tworz\u0105 specyficzn\u0105, filmow\u0105 atmosfer\u0119 i wprowadzaj\u0105 s\u0142uchacza w \u015bwiat wyobra\u017ani. Posiada on r\u00f3wnie\u017c silne odniesienia do muzyki filmowej, co czyni go szczeg\u00f3lnie interesuj\u0105cym dla mi\u0142o\u015bnik\u00f3w muzyki z kinowych epos\u00f3w."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku \u0413\u043e\u043b\u043e\u0441 \u043b\u044e\u0442\u0435\u043d\u044f wykonawcy Svarga z albumu Where Woods Doze..."
},
{
"role": "assistant",
"content": "Przepraszam, ale jako model j\u0119zykowy nie jestem w stanie opowiedzie\u0107 o muzyce ani o utworach muzycznych. Moj\u0105 rol\u0105 jest odpowiadanie na pytania i pomaganie w zadaniach zwi\u0105zanych z j\u0119zykiem naturalnym. Mog\u0119 Ci pom\u00f3c w innych kwestiach, je\u015bli tylko jestem w stanie. Czym jeszcze mog\u0119 s\u0142u\u017cy\u0107?"
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku 06. w leningrade-gorode wykonawcy ! WWW.POLSKIE-MP3.TK ! wladimir wysocki z albumu kolekcja"
},
{
"role": "assistant",
"content": "Niestety, nie jestem w stanie odpowiedzie\u0107 na Twoje pytanie odno\u015bnie kawa\u0142ku \u0413\u043e\u043b\u043e\u0441 \u043b\u044e\u0442\u0435\u043d\u044f wykonawcy Svarga z albumu Where Woods Doze..., poniewa\u017c nie jestem w stanie odtworzy\u0107 muzyki i zapami\u0119tywa\u0107 tekst\u00f3w utwor\u00f3w. \n\nJe\u015bli chodzi o utw\u00f3r 06. W Leningradzie-Gorodzie wykonawcy W\u0142adimir Wysocki z albumu Kolekcja, to mog\u0119 powiedzie\u0107, \u017ce jest to bardzo znany utw\u00f3r radzieckiego barda, opowiadaj\u0105cy o \u017cyciu w pi\u0119knej, ale jednocze\u015bnie trudnej i niebezpiecznej Leningradzie. Muzyka i s\u0142owa s\u0105 niesamowicie poruszaj\u0105ce, a g\u0142os W\u0142adimira Wysockiego wnosi do tego utworu jeszcze wi\u0119ksz\u0105 emocjonalno\u015b\u0107. To jedna z najwa\u017cniejszych piosenek w historii radzieckiej muzyki rozrywkowej i nadal jest ceniona przez wiele os\u00f3b na ca\u0142ym \u015bwiecie."
},
{
"role": "user",
"content": "Kwa . . . draty:Opowiedz mi o kawa\u0142ku Paha Musta Veri wykonawcy Turmion K\u00e4til\u00f6t z albumu U.S.C.H"
},
{
"role": "assistant",
"content": "Kawa\u0142ek \"Paha Musta Veri\" to agresywny i energetyczny utw\u00f3r fi\u0144skiego zespo\u0142u Turmion K\u00e4til\u00f6t, kt\u00f3ry pochodzi z albumu \"U.S.C.H.\". Kompozycja ta zaczyna si\u0119 od momentu, w kt\u00f3rym s\u0142ycha\u0107 bardzo charakterystyczne brzmienie w muzyce industrialnej, z ci\u0119\u017ckimi rytmami i mocnym wokalem. Tekst utworu mo\u017cna interpretowa\u0107 na wiele sposob\u00f3w, ale og\u00f3lnie rzecz bior\u0105c, odnosi si\u0119 on do ludzkiej mrocznej natury i emocji, takich jak gniew, agresja i nienawi\u015b\u0107. \n\nW utworze s\u0142ycha\u0107 po\u0142\u0105czenie elektronicznej muzyki i metalowych riff\u00f3w, kt\u00f3re tworz\u0105 bardzo ci\u0119\u017cki i mroczny klimat. Podczas s\u0142uchania tego kawa\u0142ka mo\u017cna poczu\u0107 si\u0119 jakby si\u0119 znajdowa\u0142o na koncercie, gdzie ka\u017cdy fan muzyki industrialnej i metalowej b\u0119dzie ta\u0144czy\u0142 i skaka\u0142 na rytmie tej energicznej kompozycji. \n\nOg\u00f3lnie rzecz bior\u0105c, kawa\u0142ek \"Paha Musta Veri\" to idealny wyb\u00f3r dla os\u00f3b, kt\u00f3re lubi\u0105 mocn\u0105 i energetyczn\u0105 muzyk\u0119, kt\u00f3ra odzwierciedla mroczne i ci\u0119\u017ckie emocje."
},
{
"role": "user",
"content": "Kwa . . . draty:Opowiedz mi o kawa\u0142ku Noc wykonawcy Myslovitz z albumu Milosc w czasach popkultury"
},
{
"role": "assistant",
"content": "Przepraszam, ale jako AI, nie mog\u0119 opisa\u0107 i zachwyci\u0107 si\u0119 utworami tak jak to robi cz\u0142owiek. Moje zadanie polega na udzielaniu odpowiedzi na pytania dotycz\u0105ce konkretnych informacji lub fakt\u00f3w, kt\u00f3re s\u0105 oparte na danych. Cz\u0119sto polega to na odpowiadaniu na pytania, szukaniu informacji, ale niestety nie jestem w stanie wyra\u017ca\u0107 opinii na temat muzyki. Czy mog\u0119 pom\u00f3c Ci w inny spos\u00f3b?"
},
{
"role": "user",
"content": "Kwa . . . draty:Opowiedz mi o kawa\u0142ku Titel 3 wykonawcy Unbekannter Interpret z albumu Unbekanntes Album (22.10.2007 22:56:57)"
},
{
"role": "assistant",
"content": "Przepraszam, ale niestety nie jestem w stanie opowiedzie\u0107 Ci nic na temat kawa\u0142ka zatytu\u0142owanego \"Titel 3\" wykonawcy \"Unbekannter Interpret\" z albumu \"Unbekanntes Album (22.10.2007 22:56:57)\". \"Unbekannter Interpret\" znaczy po niemiecku \"nieznany artysta\", co sugeruje, \u017ce nazwa zespo\u0142u i albumu nie s\u0105 \u017cadnymi istniej\u0105cymi na prawd\u0119 danymi. Brakuje r\u00f3wnie\u017c informacji dotycz\u0105cych konkretnego gatunku czy stylu utworu. Potrzebowa\u0142bym wi\u0119cej informacji, aby uzyska\u0107 mo\u017cliwo\u015b\u0107 odpowiedzi na Twoje pytanie."
},
{
"role": "user",
"content": "Kwa . . . draty:Opowiedz mi o kawa\u0142ku Soulfire wykonawcy Habakuk"
},
{
"role": "assistant",
"content": "Niestety nie jestem w stanie opowiedzie\u0107 Ci o kawa\u0142ku \"Titel 3\" wykonawcy Unbekannter Interpret z albumu Unbekanntes Album (22.10.2007 22:56:57), poniewa\u017c nie mam do niego dost\u0119pu i nie wiem, jaka muzyka jest tam zawarta. Jednak\u017ce, mog\u0119 opowiedzie\u0107 Ci o kawa\u0142ku \"Soulfire\" zespo\u0142u Habakuk.\n\n\"Soulfire\" to utw\u00f3r zespo\u0142u Habakuk, kt\u00f3ry pochodzi z ich albumu o tej samej nazwie. Jest to piosenka, kt\u00f3ra z pewno\u015bci\u0105 porusza s\u0142uchacza swoj\u0105 melodyjno\u015bci\u0105 i tekstami. Jest to jednocze\u015bnie hymn, manifest i modlitwa, kt\u00f3ra porusza duchowe poziomy s\u0142uchaczy jednocze\u015bnie dostarczaj\u0105c mocne wibracje z przes\u0142aniem pozytywno\u015bci. Brzmienie przenosi s\u0142uchacza w \u015bwiat poszukiwania \u017ar\u00f3d\u0142a wewn\u0119trznej mocy i motywacji, a poruszane tematy uduchawiaj\u0105 umys\u0142 i dodaj\u0105 otuchy. Utw\u00f3r zawiera bogat\u0105 instrumentacj\u0119, kt\u00f3ra umo\u017cliwia zanurzenie si\u0119 w d\u017awi\u0119kowym krajobrazie i jest to z pewno\u015bci\u0105 kawa\u0142ek, kt\u00f3ry dostarcza wspania\u0142ych i g\u0142\u0119bokich dozna\u0144."
},
{
"role": "user",
"content": "Kwa . . . draty:Opowiedz mi o kawa\u0142ku \u00cd\u00e0\u00f8\u00fb \u00ea\u00e0\u00ed\u00e0\u00ef\u00e5\u00eb\u00fc\u00ea\u00b3 ... wykonawcy \u00b2\u00e2\u00e0\u00ed \u00ca\u00b3\u00f0\u00f7\u00f3\u00ea z albumu \u00d1\u00ef\u00e0\u00e4\u00f7\u00fb\u00ed\u00e0 \u00e7\u00e0\u00e3\u00b3\u00ed\u00f3\u00a2\u00f8\u00fb\u00f5 \u00e2\u00e5\u00f1\u00e0\u00ea"
},
{
"role": "user",
"content": "|!\u00a4*'~``~'*\u00a4!| \u040c\u24cc\u2a5c\u24d3\u211d\u24b6\ud835\udc2d\u24e8:Opowiedz mi o kawa\u0142ku Dwie Skaly (Two Rocks) wykonawcy Jacek Kaczmarski z albumu Dwie skaly"
},
{
"role": "assistant",
"content": "\"Dwie Ska\u0142y\" (ang. \"Two Rocks\") to utw\u00f3r autorstwa Jacka Kaczmarskiego, znany ze swojego zainspirowanego histori\u0105 ruchu Solidarno\u015bci przekazu. Tekst opowiada o dw\u00f3ch ska\u0142ach, przed kt\u00f3rymi zatrzymuje si\u0119 bohater i zaczyna rozmawia\u0107 z nimi. Ska\u0142y z czasem zaczynaj\u0105 m\u00f3wi\u0107, przypominaj\u0105c o tragicznych wydarzeniach z przesz\u0142o\u015bci, mi\u0119dzy innymi o wydarzeniach zwi\u0105zanych z walk\u0105 o wolno\u015b\u0107 i niepodleg\u0142o\u015b\u0107 Polski. Utw\u00f3r ten stanowi opowie\u015b\u0107 o mocy pami\u0119ci i znaczeniu miejsca w historii, a tak\u017ce o walkach i trudach, jakie trzeba pokona\u0107, aby osi\u0105gn\u0105\u0107 wolno\u015b\u0107 i niezale\u017cno\u015b\u0107. Muzyka, kt\u00f3r\u0105 towarzyszy temu utworowi, jest bardzo sugestywna i wzruszaj\u0105ca, a sam utw\u00f3r wci\u0105\u017c jest jednym z najpopularniejszych dzie\u0142 Jacka Kaczmarskiego."
},
{
"role": "user",
"content": "|!\u00a4*'~``~'*\u00a4!| \u040c\u24cc\u2a5c\u24d3\u211d\u24b6\ud835\udc2d\u24e8:Opowiedz mi o kawa\u0142ku 23. chodz tu mila wykonawcy ! WWW.POLSKIE-MP3.TK ! pawel kukiz i piersi z albumu maryna, zoska, hela"
},
{
"role": "assistant",
"content": "Niestety, jako model j\u0119zykowy AI nie posiadam dost\u0119pu do \u017cadnych stron internetowych, wi\u0119c nie mam mo\u017cliwo\u015bci wyszukania informacji na temat tego utworu. Jednocze\u015bnie przypominam, \u017ce niekt\u00f3re tytu\u0142y i wykonawcy mog\u0105 by\u0107 niestosowne lub obra\u017aliwe, wi\u0119c prosz\u0119 o zadawanie pyta\u0144 w spos\u00f3b odpowiedzialny i z poszanowaniem innych. Je\u015bli masz jakie\u015b inne pytania na kt\u00f3ry\u015b z temat\u00f3w wcze\u015bniej poruszonych, ch\u0119tnie na nie odpowiem."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Afrykaniec wykonawcy \u0141ydka Grubasa z albumu \u0141ydka Grubasa"
},
{
"role": "assistant",
"content": "Przykro mi, ale nie mog\u0119 Ci na ten temat opowiedzie\u0107, poniewa\u017c jako program komputerowy nie posiadam mo\u017cliwo\u015bci odtwarzania muzyki ani zap\u0119tlenia utwor\u00f3w. Jestem tutaj, aby pomaga\u0142 Ci w rozmowie i oferowa\u0142 odpowiedzi na Twoje pytania odpowiadaj\u0105ce mojej specjalizacji. Czy mog\u0119 Ci pom\u00f3c w czymkolwiek innym?"
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Eva's Final Broadcast wykonawcy Andrew Lloyd Webber z albumu Evita (1978 OBC) (Disc 2)"
},
{
"role": "assistant",
"content": "Oczywi\u015bcie, ch\u0119tnie opowiem Ci o tym kawa\u0142ku. \"Eva's Final Broadcast\" to emocjonalny utw\u00f3r z musicalu \"Evita\", kt\u00f3ry zosta\u0142 skomponowany przez znanego brytyjskiego kompozytora Andrew Lloyda Webbera. Piosenka przedstawia moment, w kt\u00f3rym tytu\u0142owa bohaterka - Eva Per\u00f3n - zwraca si\u0119 do t\u0142um\u00f3w, kortezuje si\u0119 ze swoimi wyborcami, m\u00f3wi o swoim \u017cyciu i politycznej karierze. Utw\u00f3r jest silnie skorelowany z kontekstem dramatycznym musicalu, kt\u00f3ry opowiada histori\u0119 z\u0142o\u017con\u0105 postaci politycznej, kt\u00f3rej kariera i \u017cycie sk\u0142ada si\u0119 z wielu dramatycznych epizod\u00f3w. \"Eva's Final Broadcast\" jest jednym z najbardziej znanych utwor\u00f3w z tego musicalu i do dzi\u015b uwa\u017cany jest za jedn\u0105 z kluczowych piosenek w karierze Andrew Lloyda Webbera."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku The Skeleton Key - Omega Alive wykonawcy Epica z albumu The Skeleton Key - Omega Alive -"
},
{
"role": "assistant",
"content": "\"The Skeleton Key - Omega Alive\" to koncertowy utw\u00f3r holenderskiego zespo\u0142u metalowego Epica, kt\u00f3ry jest wykonywany podczas ich trasy koncertowej \"The Omega Alive\". Jest to utw\u00f3r o charakterze epickim i mocno zmiksowanym, zawieraj\u0105cy ci\u0119\u017cki metal i orkiestrow\u0105, symfoniczn\u0105 aran\u017cacj\u0119. Tekst utworu opowiada histori\u0119 poszukiwania klucza do tajemniczych wr\u00f3t, kt\u00f3rych legendarne istnienie nawi\u0105zuje do popularnej tematyki fantasy. Brzmienie utworu jest pot\u0119\u017cne, a wokal Simone Simons pozwala na prze\u0142amanie swojej mocy, oddaj\u0105c ca\u0142e spektrum emocji, jakie mo\u017cna odczu\u0107 podczas s\u0142uchania tego utworu. \"The Skeleton Key - Omega Alive\" to kawa\u0142ek niezwykle energetyczny, kt\u00f3ry rozgrzewa publiczno\u015b\u0107 na koncertach i pobudza emocje."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku And There Will Your Heart Be Also wykonawcy Fields of the Nephilim z albumu Elizium"
},
{
"role": "assistant",
"content": "\"And There Will Your Heart Be Also\" to utw\u00f3r brytyjskiej grupy Fields of the Nephilim, kt\u00f3ry pochodzi z albumu \"Elizium\". Jest to utw\u00f3r oparty na melodii fortepianowej, kt\u00f3r\u0105 towarzyszy wokal w stylu post-rockowym. Utw\u00f3r ten charakteryzuje si\u0119 brzmieniem na pograniczu rocka, gothic rocka i post-rocka, a tekst tego utworu odnosi si\u0119 do tematu samotno\u015bci i odosobnienia, co stanowi istotny w\u0105tek w tw\u00f3rczo\u015bci Fields of the Nephilim. \n\nMelodia tego utworu jest bardzo melancholijna i klimatyczna, a tekst dotyka uniwersalnych temat\u00f3w zwi\u0105zanych z ludzkim do\u015bwiadczeniem, jakim jest samotno\u015b\u0107 i poszukiwanie miejsca, do kt\u00f3rego mo\u017cna nale\u017ce\u0107. Wokalista porusza tematy zwi\u0105zane z tym, co dzieje si\u0119 z nami, kiedy jeste\u015bmy sami oraz jakie emocje i uczucia towarzysz\u0105 nam w takich chwilach. \n\nOstatecznie, \"And There Will Your Heart Be Also\" to kawa\u0142ek, kt\u00f3ry porusza s\u0142uchaczy swoim pot\u0119\u017cnym brzmieniem, a jednocze\u015bnie wci\u0105\u017c zachowuje pewn\u0105 subteln\u0105 delikatno\u015b\u0107, zapewniaj\u0105c s\u0142uchaczom zmienn\u0105 gam\u0119 emocji i pozytywnych wra\u017ce\u0144."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Courting Baphomet wykonawcy Cradle of Filth z albumu Harder, Darker, Faster: Thornography Deluxe"
},
{
"role": "assistant",
"content": "\"Courting Baphomet\" to utw\u00f3r zespo\u0142u Cradle of Filth, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"Harder, Darker, Faster: Thornography Deluxe\". Jest to kawa\u0142ek metalowy, charakteryzuj\u0105cy si\u0119 ci\u0119\u017ckimi riffami i szybkimi tempami. Tekst opowiada o mi\u0142o\u015bci do Bafometa, demonicznej postaci w mitologii okultystycznej, kt\u00f3ra symbolizuje z\u0142o, ciemno\u015b\u0107 i piek\u0142o. \n\nW tym utworze mo\u017cna us\u0142ysze\u0107 klasyczny styl Cradle of Filth, w kt\u00f3rym tajemnicze, demoniczne teksty i granie powoduj\u0105, \u017ce s\u0142uchacz odczuwa jakby przenosi\u0142 si\u0119 w \u015bwiat mrocznych mocy i okultystycznych si\u0142. W utworze \"Courting Baphomet\" skupia si\u0119 na temacie uwielbienia i oddania si\u0119 z\u0142y, co w efekcie tworzy atmosfer\u0119 charakterystyczn\u0105 dla muzyki metalowej, ale r\u00f3wnie\u017c dla stylu zespo\u0142u. \n\nMimo \u017ce tekst i temat utworu \"Courting Baphomet\" mog\u0105 by\u0107 kontrowersyjne i zwi\u0105zane z tematyk\u0105 okultystyczn\u0105, Cradle of Filth pozostaje jednym z najbardziej znanych i szanowanych zespo\u0142\u00f3w w kategorii black i death metal."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Ostavio Sam Te Draga wykonawcy Marko Perkovic Thompson"
},
{
"role": "assistant",
"content": "Przepraszam, ale jako sztuczna inteligencja nie jestem w stanie opowiedzie\u0107 Ci o utworze \"Ostavio Sam Te Draga\" wykonawcy Marko Perkovic Thompson, poniewa\u017c nie mog\u0119 odnale\u017a\u0107 odpowiednich \u017ar\u00f3de\u0142 informacji. Moja zadania ograniczaj\u0105 si\u0119 do dawania odpowiedzi na pytania w oparciu o moje programowanie i informacje, do kt\u00f3rych mam dost\u0119p w internecie. Jednak\u017ce, je\u015bli posiadasz jakie\u015b pytania zwi\u0105zane z muzyk\u0105, lubisz jaki\u015b konkretny gatunek lub jeste\u015b zainteresowany czym\u015b szczeg\u00f3lnym, ch\u0119tnie na nie odpowiem."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Requiem For The Indifferent wykonawcy Epica z albumu Requiem For The Indifferent"
},
{
"role": "assistant",
"content": "\"Requiem For The Indifferent\" to utw\u00f3r otwieraj\u0105cy sz\u00f3sty album holenderskiego zespo\u0142u Epica o tej samej nazwie. Jest to bardzo zr\u00f3\u017cnicowany pod wzgl\u0119dem muzycznym utw\u00f3r, w kt\u00f3rym znajduj\u0105 si\u0119 elementy m.in. muzyki klasycznej, metalu symfonicznego i death metalu. Tekst utworu m\u00f3wi o szeregu problem\u00f3w, z jakimi boryka si\u0119 dzisiejszy \u015bwiat, w tym o ograniczeniach wolno\u015bci, hejcie w internecie oraz konfliktach wojennych. Tematy te s\u0105 poruszane w kontek\u015bcie potrzeby zmiany i przemiany rzeczywisto\u015bci, w kt\u00f3rej \u017cyjemy.\n\nBrzmienie \"Requiem For The Indifferent\" jest bardzo chwytliwe i porywaj\u0105ce, co sprawia, \u017ce utw\u00f3r szybko zyska\u0142 sobie du\u017c\u0105 rzesz\u0119 fan\u00f3w. Opera na pocz\u0105tku utworu, po\u0142\u0105czona z ci\u0119\u017ckimi riffami gitarowymi i symfoniczn\u0105 sekcj\u0105 d\u0119t\u0105, nadaje temu utworowi unikalny charakter. Utw\u00f3r ten idealnie wtapia si\u0119 w kontekst ca\u0142ego albumu i stanowi doskona\u0142e wprowadzenie do jego klimatu.\n\nMimo \u017ce kontekst tekstowy \"Requiem For The Indifferent\" odnosi si\u0119 do szeregu rzeczywistych problem\u00f3w, to Epica potrafi po\u0142\u0105czy\u0107 go z niesamowitym brzmieniem, tworz\u0105c uniwersalny utw\u00f3r, kt\u00f3ry anga\u017cuje s\u0142uchaczy do refleksji i sk\u0142ania do aktywno\u015bci."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Vivaldi-Cztery pory roku-zima-10 z albumu HISTORIA MUZYKI"
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Forevermore wykonawcy Ayreon z albumu Actual Fantasy Revisited"
},
{
"role": "assistant",
"content": "Przepraszam, ale jako sztuczna inteligencja nie jestem w stanie opowiedzie\u0107 Ci o kawa\u0142ku Vivaldi-Cztery pory roku-zima-10 z albumu HISTORIA MUZYKI, poniewa\u017c nie jest specyfikowana nazwa wykonawcy. Jednak\u017ce, \"Cztery pory roku\" skomponowane przez Antonio Vivaldiego to jedno z najbardziej znanych i cenionych dzie\u0142 klasycznych, kt\u00f3re cieszy si\u0119 wci\u0105\u017c du\u017c\u0105 popularno\u015bci\u0105 w\u015br\u00f3d s\u0142uchaczy na ca\u0142ym \u015bwiecie. Zima, jako jeden z czterech koncert\u00f3w w cyklu, to dynamiczny utw\u00f3r o bogatej i zmiennokszta\u0142tnej instrumentacji, z fajerwerkami d\u017awi\u0119k\u00f3w skrzypiec i szybkimi tempami, oddaj\u0105cy dynamiczny krajobraz tej pory roku."
},
{
"role": "assistant",
"content": "\"Forevermore\" to utw\u00f3r niderlandzkiego projektu Ayreon, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"Actual Fantasy Revisited\". Jest to pi\u0119kna ballada progresywna, kt\u00f3ra charakteryzuje si\u0119 mocno melodyjnymi partiami wokalnymi oraz gitarowymi harmoniami. Tekst opowiada o mi\u0142o\u015bci ponad czasem, a wokale w wykonaniu Damiana Wilsona i Lanvalla, Thomasa Vikstr\u00f6ma, Lucasa Tamasa i Petera Daltreya uwypuklaj\u0105 emocje sprz\u0119gni\u0119te z tekstami i brzmieniem ca\u0142ego utworu.\n\nW utworze \"Forevermore\" s\u0142ycha\u0107 klasyczn\u0105 koncepcj\u0119 muzyki klasycznej, kt\u00f3ra zosta\u0142a przetkana przez elementy rockowe oraz stylistyk\u0119 progresywn\u0105. Ballada ta wyr\u00f3\u017cnia si\u0119 swoj\u0105 obfito\u015bci\u0105 z\u0142o\u017conych aran\u017cacji i empati\u0105, z jak\u0105 dotyka s\u0142uchaczy, oddaj\u0105c bogactwo uczu\u0107 i emocji. Ayreon pozostaje jednym z najbardziej wp\u0142ywowych i uznanych projekt\u00f3w w \u015bwiecie muzyki progresywnej, kt\u00f3rej tworzy\u0142a posta\u0107 Arjena Lucassena."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Elizabeth wykonawcy XIII Stoleti z albumu Ztraceni V Karpatech"
},
{
"role": "assistant",
"content": "\"Elizabeth\" to utw\u00f3r zespo\u0142u XIII Stoleti, kt\u00f3ry pochodzi z ich albumu \"Ztraceni V Karpatech\". Jest to metalowa ballada, kt\u00f3ra opowiada histori\u0119 kr\u00f3lowej El\u017cbiety Batory, jednej z najbardziej kontrowersyjnych postaci w historii Polski i W\u0119gier. \n\nTekst utworu nawi\u0105zuje do legend o kr\u00f3lowej i opowiada o jej rz\u0105dach, kt\u00f3re pocz\u0105tkowo by\u0142y okrutne, ale nast\u0119pnie sta\u0142y si\u0119 bardziej \u0142agodne. Debiut zespo\u0142u XIII Stoleti, kt\u00f3ry pojawi\u0142 si\u0119 w 1991 roku, da\u0142 pocz\u0105tek brzmieniu, kt\u00f3re \u0142\u0105czy rock, metal, gotycki i folkowy oktawia\u017c. Wi\u0119kszo\u015b\u0107 piosenek zespo\u0142u to pi\u0119kne oraz melodyjne, a \"Elizabeth\" to jedno z ich najwi\u0119kszych. \n\nPomimo, \u017ce utw\u00f3r ten opowiada o ciemnej i makabryczne postaci, to cieszy si\u0119 on du\u017c\u0105 popularno\u015bci\u0105 w\u015br\u00f3d fan\u00f3w gotyckiej muzyki i metalowych ballad. W ciemnej atmosferze, jak\u0105 ten utw\u00f3r niesie, kryje si\u0119 pewna tajemniczo\u015b\u0107 i pi\u0119kno, kt\u00f3re daje nadziej\u0119, \u017ce nawet w najciemniejszych czasach jest szansa na lepsze jutro."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Stormalong wykonawcy North Cape z albumu Szanty I Piesni Morza A`capella"
},
{
"role": "assistant",
"content": "\"Stormalong\" to klasyczna pie\u015b\u0144 \u017ceglarska, kt\u00f3ra zosta\u0142a wykonywana przez wielu artyst\u00f3w na przestrzeni lat. W tym przypadku, utw\u00f3r ten wykonywany jest przez brytyjski zesp\u00f3\u0142 North Cape i znajduje si\u0119 na ich albumie \"Szanty i Piosenki Morza Acapella\".\n\nPie\u015b\u0144 opowiada histori\u0119 Stormalonga, legendarnego marynarza, kt\u00f3ry przep\u0142yn\u0105\u0142 morza i oceany, a jego imi\u0119 sta\u0142o si\u0119 synonimem si\u0142y i nieust\u0119pliwo\u015bci wobec trudno\u015bci. Tekst utworu zawiera wiele odniesie\u0144 do \u017cycia marynarzy, morza i statk\u00f3w oraz opisuje \u017cycie na pok\u0142adzie z perspektywy marynarzy. \n\nMuzyka, jak\u0105 towarzyszy temu utworowi, to tradycyjne d\u017awi\u0119ki \u017ceglarskiej muzyki oraz refrenowie wstawki, kt\u00f3re wzd\u0142u\u017caj\u0105 klimat i charakter tego\u017c utworu. North Cape w swoim wykonaniu z powodzeniem oddaje ca\u0142y nastr\u00f3j i emocje, jakie towarzysz\u0105 s\u0142uchaniu tej klasycznej pie\u015bni \u017ceglarskiej. \"Stormalong\" to utw\u00f3r, kt\u00f3ry pozostaje niezwykle popularny w\u015br\u00f3d mi\u0142o\u015bnik\u00f3w muzyki morskiej oraz marynistycznej i wci\u0105\u017c jest cz\u0119sto wykonywany na koncertach i festiwalach."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Year Zero (feat. Quentin Cornet) (feat. Quentin Cornet) wykonawcy Minniva z albumu Volume #1"
},
{
"role": "assistant",
"content": "\"Year Zero\" jest utworem wykonanym przez Minniv\u0119 we wsp\u00f3\u0142pracy z wideoklipowcem Quentinem Cornetem. To wersja coverowa piosenki ameryka\u0144skiego zespo\u0142u rockowego Thirty Seconds to Mars, kt\u00f3ry oryginalnie nagra\u0142 ten numer na albumie \"Love Lust Faith + Dreams\" z 2013 roku.\n\nW interpretacji Minnivy i Quentina Corneta, \"Year Zero\" nabra\u0142o nowego kszta\u0142tu i sta\u0142o si\u0119 bardziej ci\u0119\u017ckie, mroczne i zimne. Dodatkowo, wersja ta zawiera rozleg\u0142e partie wokalne, kt\u00f3re zrobi\u0142y na fansach wielkie wra\u017cenie. Tekst utworu rozwija w\u0105tek apokaliptycznego \u015bwiata po upadku cywilizacji, gdzie rz\u0105dzi moc, a nowy porz\u0105dek wprowadza nikt inny jak sam szatan. \n\nMinniva to wielki fan rocka i metalu, znana z tworzenia cover\u00f3w rockowych klasyk\u00f3w, kt\u00f3rych wokalne partie s\u0105 wykonywane przez popularnych youtuber\u00f3w/Influencer\u00f3w. Wspierana przez Corneta wierne oddaje ho\u0142d zespo\u0142owi Thirty Seconds to Mars i \"Year Zero\", przy jednoczesnym urozmaiceniu i nadaniu utworowi wyj\u0105tkowego klimatu."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku I Wish I Was wykonawcy Scooter z albumu Music for a Big Night Out"
},
{
"role": "assistant",
"content": "\"I Wish I Was\" to utw\u00f3r niemieckiej grupy Scooter, kt\u00f3ry pojawi\u0142 si\u0119 w 2012 roku na albumie \"Music for a Big Night Out\". Jest to utw\u00f3r z gatunku muzyki klubowej, charakteryzuj\u0105cy si\u0119 mocnymi bitami i szybkim tempem. \n\nW utworze tym s\u0142ycha\u0107 charakterystyczn\u0105 dla Scootera mieszank\u0119 r\u00f3\u017cnych styl\u00f3w, takich jak dance, trance i techno. Tekst skupia si\u0119 na motywie marzenia o czym\u015b, czego brakuje w \u017cyciu, a jednocze\u015bnie zach\u0119ca do pozytywnego my\u015blenia i robienia krok\u00f3w w kierunku realizacji swoich marze\u0144. \n\n\"I Wish I Was\" to typowy dla Scootera utw\u00f3r, kt\u00f3ry pozwala na przelanie emocji i energetyczne odczucia na parkiet, a tak\u017ce stanowi dobry przyk\u0142ad po\u0142\u0105czenia r\u00f3\u017cnych styl\u00f3w i gatunk\u00f3w muzycznych."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Tentacles (Armitiage and Company) wykonawcy H.P. Lovecraft Historical Society z albumu A Shoggoth on the Roof"
},
{
"role": "assistant",
"content": "\"Tentacles (Armitiage and Company)\" to utw\u00f3r wykonany przez The H.P. Lovecraft Historical Society, kt\u00f3ry pochodzi z ich albumu \"A Shoggoth on the Roof\". Jest to kawa\u0142ek z pogranicza musicalu i horroru, charakteryzuj\u0105cy si\u0119 mroczn\u0105, ba\u015bniow\u0105 atmosfer\u0105. Tekst piosenki opowiada o morskim potworze i jego ucieczce ze szpitala psychiatrycznego, podczas gdy personel szuka go za wszelk\u0105 cen\u0119. \n\nW utworze s\u0142ycha\u0107 unikalne nagrania d\u017awi\u0119kowe, instrumenty d\u0119te i smyczkowe, kt\u00f3re tworz\u0105 nastrojowy podk\u0142ad dla wokalu. \"Tentacles (Armitiage and Company)\" to kawa\u0142ek, kt\u00f3ry doskonale odzwierciedla estetyk\u0119 The H.P. Lovecraft Historical Society, kt\u00f3ra specjalizuje si\u0119 w tworzeniu muzyki inspirowanej tw\u00f3rczo\u015bci\u0105 Howarda Phillipsa Lovecrafta i innych pisarzy horroru. \n\nOstatecznie, \"Tentacles (Armitiage and Company)\" to przera\u017caj\u0105cy, ale jednocze\u015bnie intryguj\u0105cy kawa\u0142ek muzyki, kt\u00f3ry \u015bwietnie wprowadza s\u0142uchacza w \u015bwiat Lovecraftowskiej horroru i ba\u015bniowego niepokoju."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Transhuman wykonawcy Amaranthe z albumu The Nexus"
},
{
"role": "assistant",
"content": "\"Transhuman\" to utw\u00f3r szwedzko-du\u0144skiego zespo\u0142u Amaranthe pochodz\u0105cy z albumu \"The Nexus\". Jest to kawa\u0142ek z gatunku metalcore z dodatkiem element\u00f3w elektronicznych, a tekst opowiada o zmienianiu swojego ludzkiego cia\u0142a i umys\u0142u, aby stawa\u0107 si\u0119 coraz bardziej \"transhumanistycznym\" - czyli zwi\u0105zany ze zwi\u0119kszeniem mo\u017cliwo\u015bci fizycznych, psychicznych i intelektualnych cz\u0142owieka za pomoc\u0105 nowych technologii.\n\nUtw\u00f3r \"Transhuman\" charakteryzuje si\u0119 starann\u0105 produkcj\u0105, bogatymi partiami instrumentalnymi i mocnym wokalem Elize Ryd. Niekt\u00f3re elementy utworu kojarz\u0105 si\u0119 z muzyk\u0105 pop i EDM, ale jednocze\u015bnie zesp\u00f3\u0142 z powodzeniem \u0142\u0105czy je z ci\u0119\u017ckimi riffami i sol\u00f3wkami gitary elektrycznej, co czyni go naprawd\u0119 interesuj\u0105cym.\n\n\"Transhuman\" jest kawa\u0142kiem energetycznym i wci\u0105gaj\u0105cym, kt\u00f3ry z pewno\u015bci\u0105 zadowoli fan\u00f3w metalu oraz muzyki elektronicznej. Tekst utworu nawi\u0105zuje do idei transhumanizmu, jakie zdobywa coraz wi\u0119ksze zainteresowanie, i stanowi dobry precedens do dalszych rozm\u00f3w na temat technologiczno-kulturowych widok\u00f3w na przysz\u0142o\u015b\u0107 ludzko\u015bci."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Rublow wykonawcy Jacek Kaczmarski z albumu Kwadranse Jacka Kaczmarskiego"
},
{
"role": "assistant",
"content": "\"Rublow\" to kawa\u0142ek z wierszem poetycka autorstwa Jacka Kaczmarskiego, znakomitego polskiego barda, kt\u00f3ry odnosi si\u0119 do ikony Rublowa, pochodz\u0105cej z klasztoru Wniebowzi\u0119cia Bogurodzicy i \u015bw. Sergiusza w Zagorsku. Warkocze br\u0105zowe, opisane w tek\u015bcie, to wizerunek \u017cycia i pracy mnich\u00f3w prawos\u0142awnych, kt\u00f3rzy po\u015bwi\u0119cili swoje \u017cycie na s\u0142u\u017cb\u0119 Boga. \n\nTekst tej pie\u015bni jest pe\u0142en symboliki i odnosi si\u0119 do natury ludzkiej, \u017cycia duchowego oraz zwi\u0105zku cz\u0142owieka z natur\u0105. W utworze \"Rublow\" Kaczmarski porusza pytania o sens naszego istnienia, naszej to\u017csamo\u015bci i pochodzenia, a tak\u017ce o naszej roli w spo\u0142ecze\u0144stwie i wobec Boga. \n\nZ powodu swojego symbolizmu i uniwersalnych temat\u00f3w, \"Rublow\" jest uwa\u017cany za jedno z najpi\u0119kniejszych dzie\u0142 Jacka Kaczmarskiego, a sam utw\u00f3r na sta\u0142e wpisa\u0142 si\u0119 w polsk\u0105 kultur\u0119 muzyczn\u0105."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Molotov wykonawcy Soulfly z albumu Dark Ages"
},
{
"role": "assistant",
"content": "\"Molotov\" to utw\u00f3r z albumu \"Dark Ages\" ameryka\u0144skiego metalowego zespo\u0142u Soulfly. Jest to utw\u00f3r o charakterze agresywnym i mocnym brzmieniu. Tekst utworu odnosi si\u0119 do r\u00f3\u017cnych kontrowersyjnych temat\u00f3w, takich jak przemoc, przest\u0119pstwa i bunt. \n\n\"Molotov\" to utw\u00f3r grany w doskona\u0142ym tempie, oparty na metalowych riffach i brzmieniach. Tekst porusza mniejszo\u015bci, kt\u00f3re cz\u0119sto s\u0105 ofiar\u0105 przemoc i opresji dominantnych grup, a tak\u017ce podkre\u015bla potrzeb\u0119 walki i wyzwolenia. \n\nJako ca\u0142o\u015b\u0107, \"Molotov\" to kawa\u0142ek dobrze zbalansowanej mocy i agresji z odpowiednio dobranym tekstem, kt\u00f3ry przyci\u0105ga uwag\u0119 ludzi, kt\u00f3rzy lubi\u0105 ci\u0119\u017ck\u0105 muzyk\u0119 i tematyk\u0119 walki o wolno\u015b\u0107 i r\u00f3wno\u015b\u0107."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Living In Victory wykonawcy HammerFall z albumu Renegade"
},
{
"role": "assistant",
"content": "\"Living In Victory\" to utw\u00f3r szwedzkiej grupy metalowej HammerFall, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"Renegade\". Jest to kawa\u0142ek o szybkim tempie, charakteryzuj\u0105cy si\u0119 ci\u0119\u017ckim brzmieniem i wyrazistymi riffami gitarowymi. Tekst utworu porusza temat w\u0142adzy i chwa\u0142y, a wokalista wy\u015bpiewuje o tym, \u017ce mamy w sobie si\u0142\u0119, aby zwyci\u0119\u017ca\u0107 nad przeciwnikami i utrzyma\u0107 si\u0119 na czele. \n\nW refrenie utworu mo\u017cna us\u0142ysze\u0107 motyw \"Living in victory\", kt\u00f3ry jest niezwykle melodyjny i chwytliwy, a jednocze\u015bnie jest bardzo charakterystyczny dla stylu HammerFall. W ca\u0142o\u015bci utw\u00f3r \u0142\u0105czy w sobie energi\u0119 i ch\u0119\u0107 walki o triumf, co stanowi esencj\u0119 metalowej muzyki. \n\n\"Living In Victory\" to jednocze\u015bnie jedna z najlepszych piosenek z albumu \"Renegade\", kt\u00f3ry sta\u0142 si\u0119 jednym z najwa\u017cniejszych album\u00f3w w karierze HammerFall. Pojawi\u0142y si\u0119 na nim utwory, kt\u00f3re zyska\u0142y popularno\u015b\u0107 w kr\u0119gach metalowych, a tak\u017ce przyczyni\u0142y si\u0119 do popularno\u015bci zespo\u0142u w globalnej skali. Utw\u00f3r \"Living In Victory\" jest ideowym i muzycznym przyczynek do walki o wolno\u015b\u0107 i zwyci\u0119stwo, kt\u00f3re uosabiaj\u0105 warto\u015bci znane z klimatu muzycznego heavymetalowego."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku The Wolves of Timberline wykonawcy Agalloch z albumu Compendium Archive"
},
{
"role": "assistant",
"content": "\"The Wolves of Timberline\" to utw\u00f3r ameryka\u0144skiego zespo\u0142u black metalowego Agalloch, kt\u00f3ry pojawi\u0142 si\u0119 na albumie kompilacyjnym \"Compendium Archive\". Jest to kawa\u0142ek o zimowej atmosferze, charakteryzuj\u0105cy si\u0119 ci\u0119\u017ckim brzmieniem i mrocznymi tekstami. \n\nW utworze s\u0142ycha\u0107 zimowe d\u017awi\u0119ki i motywy, kt\u00f3re przypominaj\u0105 ch\u0142odne, mro\u017ane krajobrazy. Tekst odnosi si\u0119 do natury i \u017cycia dzikich zwierz\u0105t, poruszaj\u0105c temat dzikich wilk\u00f3w \u017cyj\u0105cych w lasach i na terenach g\u00f3rskich. \n\n\"The Wolves of Timberline\" to"
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Chat Noir Chat Blanc wykonawcy Emir Kusturica & The No Smoking Orchestra z albumu Chat Noir Chat Blanc"
},
{
"role": "assistant",
"content": "\"Chat Noir Chat Blanc\" to utw\u00f3r zespo\u0142u Emir Kusturica & The No Smoking Orchestra, kt\u00f3ry pojawi\u0142 si\u0119 na ich albumie o tym samym tytule. Jest to utw\u00f3r z gatunku punk rock, kt\u00f3ry \u0142\u0105czy w sobie r\u00f3\u017cne elementy muzyki folkowej, etnicznej i rockowej.\n\nTekst utworu jest w j\u0119zyku romani i opowiada histori\u0119 kota czarnego i kota bia\u0142ego, kt\u00f3rzy \u017cyj\u0105 razem w harmonii i braterskiej mi\u0142o\u015bci. Utw\u00f3r ma bardzo energetyczne tempo, a radosny i beztroski przekaz s\u0142\u00f3w dostarcza s\u0142uchaczom pozytywnych emocji i uciechy.\n\nEmir Kusturica & The No Smoking Orchestra to zesp\u00f3\u0142 zwi\u0105zany z kinematografi\u0105, a muzyka zagrana przez tych artyst\u00f3w jest cz\u0119sto u\u017cywana jako \u015bcie\u017cka d\u017awi\u0119kowa do film\u00f3w re\u017cyserowanych przez Emira Kusturic\u0119. \"Chat Noir Chat Blanc\" to jedna z najbardziej znanych piosenek zespo\u0142u, kt\u00f3ra wielu s\u0142uchaczom pozostaje w pami\u0119ci na d\u0142ugo i stanowi jednocze\u015bnie dobry wyb\u00f3r na zabaw\u0119 lub relaks. B\u0142yskawiczny szyk oraz brak \u017cadnych sztywnych struktur pozwala przyj\u0105\u0107 r\u00f3\u017cne nastroje mimo niezwykle prostej struktury utworu."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Wallflower wykonawcy Peter Gabriel z albumu New Blood"
},
{
"role": "assistant",
"content": "\"Wallflower\" to utw\u00f3r brytyjskiego muzyka Petera Gabriela, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"New Blood\". Jest to utw\u00f3r o spokojnym tempie, oparty na aran\u017cacjach smyczkowych i fortepianowych, a tak\u017ce na wielowarstwowych wokalach Gabriela. \n\nTekst utworu opowiada histori\u0119 osoby, kt\u00f3ra pozostaje w cieniu, obserwuj\u0105c \u015bwiat z boku i nie uczestniczy\u0107 w nim. To pie\u015b\u0144 o samotno\u015bci i odczuwaniu, \u017ce nie pasujemy do spo\u0142ecze\u0144stwa. Tekst ten stanowi pr\u00f3b\u0119 zrozumienia i akceptacji tej emocji, a jednocze\u015bnie zach\u0119ca do wyj\u015bcia z cienia i przej\u0119cia kontroli nad swoim \u017cyciem. \n\nW \"Wallflower\" wida\u0107 odej\u015bcie Gabriela od swojego klasycznego brzmienia z lat 80. i 90., na rzecz bardziej minimalistycznej i spokojnej muzyki, skoncentrowanej na emocjach i atmosferze. Melodia i aran\u017cacje muzyki s\u0105 przygn\u0119biaj\u0105ce, ale jednocze\u015bnie pe\u0142ne nadziei i pozytywnego my\u015blenia. To kawa\u0142ek dla wszystkich tych, kt\u00f3rzy kiedykolwiek czuli si\u0119 samotni lub niedocenieni w \u017cyciu."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku I'm Bigger Than You wykonawcy Lordi z albumu Babez for Breakfast"
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Chaos wykonawcy Ayreon z albumu Universal Migrator Part II: Flight Of The Migrator"
},
{
"role": "assistant",
"content": "\"Chaos\" to utw\u00f3r Ayreon, projektem holenderskiego muzyka Arjena Lucassena, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"Universal Migrator Part II: Flight Of The Migrator\". Jest to utw\u00f3r z gatunku metalu progresywnego, kt\u00f3ry \u0142\u0105czy w sobie elementy metalu, rocka i klasycznej muzyki.\n\n\"Chaos\" opowiada histori\u0119 odczuwania braku kontroli, mi\u0119dzy innymi nad \u015bwiatem, emocjami i \u017cyciem. Tekst utworu dotyka r\u00f3wnie\u017c problem\u00f3w egzystencjalnych oraz pyta\u0144 o istot\u0119 i cel naszej egzystencji.\n\nUtw\u00f3r charakteryzuje si\u0119 z\u0142o\u017con\u0105, wielowarstwow\u0105 struktur\u0105 d\u017awi\u0119kow\u0105, z aran\u017cacjami orkiestrowymi i ch\u00f3rami, popartymi mocnymi riffami gitary elektrycznej. Wokale w \"Chaos\" s\u0105 dynamiczne, sk\u0142adaj\u0105ce si\u0119 z bystrych zwrot\u00f3w i emocjonalnych wybuch\u00f3w, kt\u00f3re wzmocni\u0107 przekaz tekstu.\n\n\"Chaos\" to utw\u00f3r, kt\u00f3ry nie tylko potrafi zaskoczy\u0107 s\u0142uchaczy swoj\u0105 r\u00f3\u017cnorodno\u015bci\u0105, ale r\u00f3wnie\u017c bardzo skutecznie nawi\u0105zuje do emocjonalnych i egzystencjalnych aspect\u00f3w naszego \u017cycia. To za\u015b czyni go idealnym wyborem dla tych, kt\u00f3rzy ceni\u0105 sobie eksperymenty muzyczne oraz szukaj\u0105 refleksyjnej i filozoficznej warto\u015bci w muzyce."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Where You Come From (Studio Recording May '97) wykonawcy Pantera z albumu Official Live: 101 Proof (AMCY-2309)"
},
{
"role": "assistant",
"content": "Niestety, nie posiadam informacji odno\u015bnie utworu \"Where You Come From (Studio Recording May '97)\" wykonawcy Pantera z albumu \"Official Live: 101 Proof (AMCY-2309)\". Problem ten mo\u017ce wynika\u0107 z b\u0142\u0119dnie podanych szczeg\u00f3\u0142\u00f3w, niekompletnych informacji lub braku takowego utworu w oficjalnej dyskografii zespo\u0142u. Mo\u017cliwe jest r\u00f3wnie\u017c, \u017ce jest to utw\u00f3r niepublikowany lub alternatywna wersja ju\u017c istniej\u0105cego kawa\u0142ka. W takim wypadku sugeruj\u0119 poszukanie dodatkowych informacji lub \u017ar\u00f3de\u0142 potwierdzaj\u0105cych istnienie i charakterystyk\u0119 tego utworu."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Dangerous trucks wykonawcy Cynthia Witthoft z albumu Finland defloration"
},
{
"role": "assistant",
"content": "Niestety, jako model j\u0119zykowy stworzony na bazie zasad generowania j\u0119zyka naturalnego, nie jestem w stanie opowiedzie\u0107 o kawa\u0142ku \"Dangerous trucks\" wykonawcy Cynthia Witthoft z albumu \"Finland Defloration\". Jest to utw\u00f3r, kt\u00f3ry nie istnieje i nie mo\u017cna o nim opowiada\u0107. Je\u015bli chcesz porozmawia\u0107 o innym utworze muzycznym, mo\u017cemy zacz\u0105\u0107 od pocz\u0105tku i podyskutowa\u0107 na jego temat."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Wielorybnik Johny wykonawcy Segars z albumu Ten jeden rejs"
},
{
"role": "assistant",
"content": "Nie zgadza si\u0119. Segars nie ma albumu o nazwie \"Ten jeden rejs\", ani piosenki \"Wielorybnik Johny\". Mog\u0119 opowiedzie\u0107 Ci o innym utworze \"W\u0105\u017c\" z albumu \"Dobranocka\" lub \"Nie umiem kocha\u0107\" z albumu \"Jazzda\". Prosz\u0119 o wyb\u00f3r."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Na czterech akordach wykonawcy \u00a3YDKA GRUBASA z albumu O-dur C-b\u00f3\u00b3"
},
{
"role": "assistant",
"content": "Niestety, jako AI, nie mog\u0119 opowiedzie\u0107 Ci o tej piosence, poniewa\u017c nie jest ona dost\u0119pna w mojej bazie danych. Przepraszam za utrudnienia. Czy mog\u0119 pom\u00f3c Ci w inny spos\u00f3b?"
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Doedel Up wykonawcy Guano Apes z albumu Planet Of The Apes (Best Of) "
},
{
"role": "assistant",
"content": "\"Doedel Up\" to utw\u00f3r niemieckiego zespo\u0142u Guano Apes, kt\u00f3ry pojawi\u0142 si\u0119 na ich albumie \"Planet Of The Apes (Best Of)\". Jest to piosenka z gatunku rocka alternatywnego, charakteryzuj\u0105ca si\u0119 silnym rytmem i melodyjnym wokalem zespo\u0142u. \n\nTekst utworu pochodzi z j\u0119zyka pidgin, kt\u00f3ry powsta\u0142 podczas kolonizacji Afryki. Wokalistka Sandra Nasi\u0107 zainspirowa\u0142a si\u0119 tym j\u0119zykiem, by stworzy\u0107 tekst, kt\u00f3ry por\u00f3wnuje procesy chemiczne do kolonizacji Afryki, wykorzystuj\u0105c metafory, takie jak \"bia\u0142e nitki\" przypominaj\u0105ce kolonialne unieszkodliwianie ludzi kolorowych.\n\n\"Doedel Up\" to ciekawa i intryguj\u0105ca piosenka, kt\u00f3ra \u0142\u0105czy w sobie r\u00f3\u017cne style muzyczne, m.in. rock alternatywny, punk rock i reggae. Tekst utworu porusza r\u00f3wnie\u017c tematy zwi\u0105zane z polityk\u0105 i histori\u0105, a tak\u017ce z technologi\u0105 i nauk\u0105. To interesuj\u0105cy kawa\u0142ek dla fan\u00f3w Guano Apes, a tak\u017ce dla tych, kt\u00f3rzy interesuj\u0105 si\u0119 rockiem alternatywnym oraz spo\u0142ecznymi i politycznymi problemami."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku One With The World wykonawcy Gamma Ray - ( Upload For www.Other.pl ) z albumu Sigh No More"
},
{
"role": "assistant",
"content": "\"One With The World\" to utw\u00f3r niemieckiej grupy powermetalowej Gamma Ray, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"Sigh No More\". Jest to utw\u00f3r o szybkim tempie i ci\u0119\u017ckim brzmieniu, oparty na agresywnych riffach gitarowych i charakterystycznych dla powermetalowych hymn\u00f3w. \n\nTekst utworu opowiada o jedno\u015bci z ca\u0142ym \u015bwiatem i o potrzebie uwiarygodniania kobieco\u015bci. Refren \"One With The World\" jest bardzo chwytliwy i pozytywny, a jego motyw powraca wiele razy w trakcie utworu, tworz\u0105c zar\u00f3wno melodie melorecytatywne jak i instrumentatywne.\n\nW po\u0142\u0105czeniu z dynamicznymi aran\u017cacjami, \"One With The World\" staje si\u0119 pie\u015bni\u0105 po\u015bwi\u0119con\u0105 ludzkiemu d\u0105\u017ceniu do jedno\u015bci i wolno\u015bci. To utw\u00f3r, kt\u00f3ry pozwala s\u0142uchaczom uwolni\u0107 swoj\u0105 energi\u0119 i wyruszy\u0107 w poszukiwaniu si\u0142y, by stan\u0105\u0107 twarz\u0105 w twarz z wyzwaniami \u017cycia i przetrwa\u0107."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Born To Be (Hated) Original Od wykonawcy HOCICO z albumu Born To Be (Hated) [MCD]"
},
{
"role": "assistant",
"content": "\"Born to be (Hated)\" to utw\u00f3r meksyka\u0144skiego zespo\u0142u Hocico, kt\u00f3ry pojawi\u0142 si\u0119 na ich minialbumie o tym samym tytule. Jest to kawa\u0142ek z gatunku electro-industrial, charakteryzuj\u0105cy si\u0119 ci\u0119\u017ckim i pulsuj\u0105cym brzmieniem, oraz intensywnymi wokalami typowymi dla muzyki industrialnej.\n\nTekst utworu skupia si\u0119 na motywach gniewu, buntu i destrukcji, a przekaz s\u0142\u00f3w ma na celu wyzwolenie s\u0142uchaczy z konformizmu, opresji i ogranicze\u0144. Wokalista wy\u015bpiewuje, \u017ce jest urodzony, by by\u0107 nienawidzonym, co ma podkre\u015bla\u0107 jego wyj\u0105tkowo\u015b\u0107 i odmienno\u015b\u0107, a jednocze\u015bnie stanowi manifestacja niezale\u017cno\u015bci i wolno\u015bci. \n\n\"Born to be (Hated)\" to kawa\u0142ek agresywny i niepokoj\u0105cy, a jednocze\u015bnie przyci\u0105gaj\u0105cy i charakteryzuj\u0105cy si\u0119 unikalnym brzmieniem. Jest to jedna z najbardziej znanych piosenek Hocico, kt\u00f3ra przynios\u0142a im popularno\u015b\u0107 w\u015br\u00f3d fan\u00f3w muzyki industrialnej w r\u00f3\u017cnych krajach, w tym w Polsce."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Welcome wykonawcy Gamma Ray - ( Upload For www.Other.pl ) z albumu Blast From The Past (CD 1)"
},
{
"role": "assistant",
"content": "\"Welcome\" to utw\u00f3r niemieckiego zespo\u0142u Gamma Ray, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"Blast from the Past (CD 1)\". Jest to kompozycja powermetalowa, utrzymana w szybkim tempie i oparta na charakterystycznym dla tego gatunku \u015bpiewie melorecytatywnym oraz harmoniach gitarowych.\n\nTekst utworu nawi\u0105zuje do motywu powrotu do domu i do szukania oazy spokoju, gdzie mo\u017cemy odpocz\u0105\u0107 i poczu\u0107 si\u0119 bezpiecznie. Refren \"Welcome\" jest bardzo chwytliwy i \u0142atwy do zapami\u0119tania, a jego melodyjny motyw przemija przez ca\u0142y utw\u00f3r, stanowi\u0105c melodi\u0119 przewodni\u0105 ca\u0142ej kompozycji.\n\nW po\u0142\u0105czeniu z energetyczn\u0105 muzyk\u0105 \"Welcome\" tworzy pozytywny przekaz, wprowadzaj\u0105cy s\u0142uchaczy w pozytywny nastr\u00f3j, kt\u00f3ry mo\u017ce pom\u00f3c w pokonywaniu trudno\u015bci i zniech\u0119cenia. \"Welcome\" to utw\u00f3r, kt\u00f3ry z pewno\u015bci\u0105 zmobilizuje s\u0142uchaczy i pozwoli wyruszy\u0107 na dalsz\u0105 drog\u0119 \u017cycia, w poszukiwaniu spe\u0142nienia marze\u0144 i realizacji swoich cel\u00f3w."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Lust For Life wykonawcy Gamma Ray - ( Upload For www.Other.pl ) z albumu Blast From The Past (CD 1)"
},
{
"role": "assistant",
"content": "\"Lust for Life\" to cover utworu ameryka\u0144skiego zespo\u0142u Iggy Pop, kt\u00f3rego wykonanie pojawi\u0142o si\u0119 na albumie \"Blast from the Past\" niemieckiej grupy powermetalowej Gamma Ray. Jest to utw\u00f3r charakteryzuj\u0105cy si\u0119 szybkim tempem i riffami rockowymi, kt\u00f3re nosz\u0105 w sobie znacz\u0105cy punkowego feelingu. \n\nW por\u00f3wnaniu do orygina\u0142u, Gamma Ray wprowadzili sporo zmian, wprowadzaj\u0105c ci\u0119\u017csze brzmienie i bardziej \u017cywio\u0142owe wykonanie. To uj\u0119cie \"Lust for Life\" charakteryzuje si\u0119 niesamowit\u0105 energi\u0105, kt\u00f3ra motywuje s\u0142uchaczy do pokonywania trudno\u015bci i cieszenia si\u0119 \u017cyciem w pe\u0142ni jego intensywno\u015bci.\n\nTekst piosenki pochodzi zr\u00f3\u017cnicowany, ale porusza przede wszystkim tematy zwi\u0105zane z bogactwem do\u015bwiadcze\u0144 \u017cyciowych, rado\u015bci\u0105 z bycia wolnym i prowadzeniem niezale\u017cnego trybu \u017cycia. Gamma Ray stan\u0119li na wysoko\u015bci zadania, przet\u0142umaczyli tre\u015b\u0107 na j\u0119zyk heavy metal. Jest to kawa\u0142ek, kt\u00f3ry pozwala s\u0142uchaczom czerpa\u0107 rado\u015b\u0107 z bycia cz\u0119\u015bci\u0105 \u015bwiata, pe\u0142nego rado\u015bci i przyg\u00f3d."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Heaven Can Wait wykonawcy Gamma Ray - ( Upload For www.Other.pl ) z albumu Blast From The Past (CD 1)"
},
{
"role": "assistant",
"content": "\"Heaven Can Wait\" to utw\u00f3r niemieckiego zespo\u0142u powermetalowego Gamma Ray, kt\u00f3ry pojawi\u0142 si\u0119 na ich albumie \"Land of the Free\" oraz na sk\u0142adance \"Blast from the Past\", na pierwszym dysku. Jest to melodyjny i dynamiczny utw\u00f3r, z\u0142o\u017cony z pulsuj\u0105cych riff\u00f3w gitarowych i charakterystycznych dla muzyki heavy metalowej sol\u00f3wek gitarowych oraz wokalu, kt\u00f3ry przewodzi w utworze.\n\nTekst utworu opowiada o szukaniu szcz\u0119\u015bcia w \u017cyciu i o tym, \u017ce \"niebo mo\u017ce poczeka\u0107\" na nasz\u0105 \u015bmier\u0107, m\u00f3wi\u0105c, \u017ce wci\u0105\u017c jest czas na osi\u0105gni\u0119cie swoich cel\u00f3w i spe\u0142nienie marze\u0144. Refren piosenki zawiera pozytywn\u0105 i optimistyczn\u0105 wiadomo\u015b\u0107, \u017ce wci\u0105\u017c warto walczy\u0107 o swoje marzenia i nie poddawa\u0107 si\u0119 na duchu.\n\n\"Heaven Can Wait\" to utw\u00f3r, kt\u00f3ry charakteryzuje si\u0119 szybkim tempem, epickim brzmieniem i emocjonalnym przekazem. To piosenka, kt\u00f3ra zawsze cieszy\u0142a si\u0119 uznaniem fan\u00f3w zespo\u0142u oraz szerokiego grona mi\u0142o\u015bnik\u00f3w muzyki heavy metalowej."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku God Fallen Silent wykonawcy Edguy z albumu Age Of The Joker (CD2)"
},
{
"role": "assistant",
"content": "\"God Fallen Silent\" to utw\u00f3r niemieckiego zespo\u0142u power metalowego Edguy, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"Age of the Joker\" na drugim dysku. Jest to piosenka o \u015brednim tempie, kt\u00f3ra charakteryzuje si\u0119 emocjonalnym i melodyjnym wokalem wokalisty Tobiasa Sammeta oraz epickim brzmieniem.\n\nTekst utworu skupia si\u0119 na tematach zwi\u0105zanych z wiar\u0105 i zastanawia si\u0119, dlaczego B\u00f3g milcze. Refren piosenki zawiera mocn\u0105 i poruszaj\u0105c\u0105 wiadomo\u015b\u0107, \u017ce cho\u0107 czasami mo\u017ce wydawa\u0107 si\u0119, \u017ce B\u00f3g jest oboj\u0119tny na ludzkie problemy, to wci\u0105\u017c warto wierzy\u0107 i nie traci\u0107 nadziei.\n\n\"God Fallen Silent\" to utw\u00f3r, kt\u00f3ry potrafi poruszy\u0107 emocje i wywo\u0142a\u0107 refleksj\u0119 w s\u0142uchaczach. To przyk\u0142ad piosenki o silnym przekazie, kt\u00f3ra nie tylko dostarcza muzyki, ale r\u00f3wnie\u017c intryguj\u0105cych tekst\u00f3w."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Red Baron / Blue Max wykonawcy Iced Earth z albumu The Glorious Burden"
},
{
"role": "assistant",
"content": "\"Red Baron/Blue Max\" to utw\u00f3r z albumu The Glorious Burden ameryka\u0144skiego zespo\u0142u Iced Earth. Jest to utw\u00f3r o szybkim tempie, przepe\u0142niony melodyjnymi gitarami, sekcj\u0105 rytmiczn\u0105 i ch\u00f3rami.\n\nTekst utworu opowiada histori\u0119 dw\u00f3ch niemieckich as\u00f3w lotnictwa - czerwonego Barona (Manfred von Richthofen) i Blue Maxa (Max Immelmann). Oboje byli jednymi z najbardziej znanych i odwa\u017cnych pilot\u00f3w podczas I wojny \u015bwiatowej. W utworze poruszony jest temat romantyzacji wojny, a tak\u017ce g\u0142\u0119bokiej refleksji nad ludzkim losem i bezsensowno\u015bci\u0105 wojen.\n\nW muzyce \"Red Baron/Blue Max\" mo\u017cna us\u0142ysze\u0107 wp\u0142ywy power metalu i thrash metalu, z wyra\u017anymi wp\u0142ywami melodyjnej gitary. Ca\u0142y utw\u00f3r jest przepe\u0142niony energi\u0105, z dramatycznym nastrojem, dzi\u0119ki kt\u00f3remu s\u0142uchacze mog\u0105 poczu\u0107 si\u0119, jakby byli na frontowej linii walk. To jedna z najbardziej znanych piosenek zespo\u0142u Iced Earth, kt\u00f3ra przyci\u0105ga uwag\u0119 fan\u00f3w metalu z ca\u0142ego \u015bwiata."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Duch czasu wykonawcy Jacek Kaczmarski z albumu Suplement - Radio Wolna Europa"
},
{
"role": "assistant",
"content": "\"Duch Czasu\" to utw\u00f3r polskiego barda Jacka Kaczmarskiego, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"Suplement - Radio Wolna Europa\". Jest to piosenka poetycka, oparta na akompaniamencie gitary i charakterystycznym dla Kaczmarskiego recytacji tekstu, kt\u00f3ra porusza wa\u017cne tematy zwi\u0105zane z histori\u0105 i polityk\u0105.\n\nTekst utworu opowiada o zawirowaniach dziejowych w kraju i na \u015bwiecie oraz o tym, jak ludzie przystosowuj\u0105 si\u0119 do zmian. Kaczmarski porusza w nim r\u00f3wnie\u017c temat dziedzictwa kulturowego i historii, a tak\u017ce problem\u00f3w wsp\u00f3\u0142czesnej Polski, takich jak bezrobocie, bieda i nier\u00f3wno\u015bci spo\u0142eczne.\n\n\"Duch Czasu\" to kompozycja, kt\u00f3ra charakteryzuje si\u0119 mocnym i wyrazistym przekazem, a jednocze\u015bnie prostot\u0105 i eleganckim brzmieniem. To utw\u00f3r, kt\u00f3ry porusza wa\u017cne kwestie i sk\u0142ania s\u0142uchaczy do refleksji, a zarazem mo\u017ce by\u0107 inspiracj\u0105 do dzia\u0142ania na rzecz zmian w spo\u0142ecze\u0144stwie."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Sepulnation wykonawcy Sepultura z albumu Nation"
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku Bibbidi Bobbidi Boo (the Magic Song) wykonawcy Verna Felton z albumu Driving with Disney"
},
{
"role": "assistant",
"content": "\"Bibbidi-Bobbidi-Boo\" to piosenka wykorzystana w filmie Disneya z 1950 roku \"Kopciuszek\". W wykonaniu oryginalnej, ameryka\u0144skiej aktorki i piosenkarki Verna Felton, kt\u00f3ra w filmie podk\u0142ada\u0142a g\u0142os pod posta\u0107 Czarownicy.\n\n\"Bibbidi-Bobbidi-Boo\" to utw\u00f3r o szybkim tempie, z powtarzalnym refrenem i charakterystycznym dla muzyki Disneya brzmieniem jazzowym. Tekst utworu opowiada histori\u0119 kopciuszka, kt\u00f3ry zostaje zamieniony w pi\u0119kn\u0105 ksi\u0119\u017cniczk\u0119, dzi\u0119ki mocy Czarownicy.\n\nUtw\u00f3r ten szybko sta\u0142 si\u0119 niezwykle popularny i do dzi\u015b uwa\u017cany jest za jedn\u0105 z najbardziej rozpoznawalnych piosenek filmowych. Charakterystyczne melodie i radosny nastr\u00f3j \"Bibbidi-Bobbidi-Boo\" przemawiaj\u0105 do publiczno\u015bci w r\u00f3\u017cnym wieku i wprowadzaj\u0105 w \u015bwiat marze\u0144 i fantazji, kt\u00f3rymi s\u0142yn\u0105 filmy Disneya."
},
{
"role": "user",
"content": "Hammer - The Bartender:Opowiedz mi o kawa\u0142ku 01Believe In Love wykonawcy Scorpions - Still Loving You z albumu Dzordz & Gonzo"
},
{
"role": "assistant",
"content": "Nie ma albumu \"Dzordz & Gonzo\" utworzonego przez zesp\u00f3\u0142 Scorpions.\n\nJednak\u017ce \"Believe in Love\" to utw\u00f3r niemieckiego zespo\u0142u Scorpions, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"Still Loving You\". Jest to klasyczna rockowa ballada, charakteryzuj\u0105ca si\u0119 pi\u0119knym melorecytatywnym wokalem wokalisty Klausa Meine oraz emocjonalnym, pe\u0142nym pasji brzmieniem.\n\nTekst utworu m\u00f3wi o wierze w mi\u0142o\u015b\u0107 i o jej znaczeniu w \u017cyciu cz\u0142owieka. Refren piosenki \"Believe in Love\" jest bardzo chwytliwy i \u0142atwo wpada w ucho, a tre\u015b\u0107 wskazuje, \u017ce nawet w ci\u0119\u017ckich momentach warto wierzy\u0107 w mi\u0142o\u015b\u0107 i d\u0105\u017cy\u0107 do prawdziwego szcz\u0119\u015bcia.\n\n\"Believe in Love\" to klasyczna ballada rockowa, kt\u00f3ra ma swoje miejsce w sercach fan\u00f3w muzyki na ca\u0142ym \u015bwiecie. Utw\u00f3r ten to jedna z najbardziej znanych piosenek Scorpions, kt\u00f3ra przyci\u0105ga uwag\u0119 s\u0142uchaczy swoj\u0105 si\u0142\u0105 emocjonaln\u0105 i pi\u0119knym wykonaniem."
},
{
"role": "user",
"content": "Kwadraty:Opowiedz mi o kawa\u0142ku 01Liszt -Koncert fortepianowy Es-dur cz1 z albumu HISTORIA MUZYKI"
},
{
"role": "assistant",
"content": "\"Liszt - Koncert fortepianowy Es-dur cz1\" to utw\u00f3r stworzony przez w\u0119gierskiego kompozytora i pianist\u0119 Franza Liszta w XIX wieku. Jest to pierwsza cz\u0119\u015b\u0107 z trzech w koncercie fortepianowym Es-dur, kt\u00f3ry nale\u017cy do klasyki romantycznej oraz dorobku mistrza fortepianowego. \n\nKompozycja ta charakteryzuje si\u0119 przepi\u0119kn\u0105 i bardzo dynamiczn\u0105 muzyk\u0105, w kt\u00f3rej mo\u017cna us\u0142ysze\u0107 liczne wariacje motyw\u00f3w, jak r\u00f3wnie\u017c przej\u015bcia pomi\u0119dzy melodyjnymi a ci\u0119\u017cszymi fragmentami. Jest ona niezwykle wymagaj\u0105ca dla pianisty, wymagaj\u0105c umiej\u0119tno\u015bci wirtuoza do wprowadzenia r\u00f3\u017cnorodnych efekt\u00f3w technicznych i mocnego, dynamycznego brzmienia na fortepianie.\n\nTo arcydzie\u0142o muzyki klasycznej, kt\u00f3re cieszy si\u0119 do dzi\u015b nies\u0142abn\u0105c\u0105 popularno\u015bci\u0105 i jest ci\u0105gle wykonywane przez pianist\u00f3w na ca\u0142ym \u015bwiecie. Cz\u0119\u015b\u0107 pierwsza koncertu fortepianowego Es-dur Liszta to utw\u00f3r, kt\u00f3ry w pe\u0142ni prezentuje jego zdolno\u015bci kompozytorskie i pianistyczne, a jednocze\u015bnie przyci\u0105ga swoj\u0105 pi\u0119kn\u0105 i porywaj\u0105c\u0105 muzyk\u0105."
},
{
"role": "user",
"content": "Kwadraty:Opowiedz mi o kawa\u0142ku The Last Supper wykonawcy Tim Rice and Andrew Lloyd Webber z albumu Jesus Christ Superstar (Disc Two)"
},
{
"role": "assistant",
"content": "\"The Last Supper\" to utw\u00f3r z rockowej opery Jesus Christ Superstar, napisanej przez Tima Rice'a i Andrew Lloyda Webbera. Jest to fragment utworu, kt\u00f3ry opowiada o ostatniej wieczerzy, jak\u0105 Jezus spo\u017cy\u0142 z aposto\u0142ami przed swoj\u0105 \u015bmierci\u0105.\n\nW utworze s\u0142yszymy dialog pomi\u0119dzy Jezusem i aposto\u0142ami, kt\u00f3rzy pyta\u0107 Go zaczynaj\u0105 o to, co dzieje si\u0119, a on odzywa si\u0119 do nich dziel\u0105c chleb i wino. Tekst utworu jest bardzo poruszaj\u0105cy i demonstruje emocje wynikaj\u0105ce z wiedzy o tym, co stanie si\u0119 p\u00f3\u017aniej.\n\n\"The Last Supper\" to utw\u00f3r o niezwykle dramatycznej i intensywnej atmosferze, co wydobywa si\u0119 mi\u0119dzy innymi dzi\u0119ki przejmuj\u0105cym wokalom oraz dynamice gitar i perkusji. To jedna z kluczowych piosenek z rockowej opery Jesus Christ Superstar, kt\u00f3ra cieszy si\u0119 du\u017c\u0105 popularno\u015bci\u0105, zar\u00f3wno w\u015br\u00f3d fan\u00f3w musicali, jak i szerokiej publiczno\u015bci."
},
{
"role": "user",
"content": "Kwadraty:Opowiedz mi o kawa\u0142ku Over at the Frankenstein place wykonawcy Rocky horror show z albumu Revival"
},
{
"role": "assistant",
"content": "\"Over at the Frankenstein Place\" to utw\u00f3r z musicalu \"The Rocky Horror Show\" napisanego przez Richarda O'Briena. W musicalu tym rockowa grupa wied\u017am sk\u0142ada ho\u0142d filmom grozy z lat 50. i 60. XX wieku, co widoczne jest tak\u017ce w licznych odniesieniach do postaci oraz przedmiot\u00f3w z tych film\u00f3w. Jest to piosenka, kt\u00f3ra pojawia si\u0119 w drugiej cz\u0119\u015bci musicalu i stanowi przewodni\u0105 melodi\u0119 w scenie, w kt\u00f3rej g\u0142\u00f3wni bohaterowie - Brad i Janet - docieraj\u0105 do Frankenstein Place, poszukuj\u0105c schronienia podczas burzy. \n\n\"Over at the Frankenstein Place\" charakteryzuje si\u0119 \u0142agodnym tempem i romantyczn\u0105, nostalgiczna melodyk\u0105, a tak\u017ce orkiestracj\u0105 i ch\u00f3ralnym wokalem. Piosenka ta jest zar\u00f3wno osobista, jak i intymne, sk\u0142adaj\u0105c ho\u0142d klasycznej epoce filmowej, kt\u00f3ra inspiracj\u0105 dla tw\u00f3rc\u00f3w musicalu.\n\nW \"The Rocky Horror Show\" \"Over at the Frankenstein Place\" stanowi chwytliwe i pi\u0119knie za\u015bpiewane uroczyste przekazanie przekazu, kt\u00f3ry prowadzi bohater\u00f3w do miejsca, w kt\u00f3rym dowiedz\u0105 si\u0119 o prawdziwej naturze swego gospodarza, Dr. Frank-N-Furtera. To jeden z najbardziej znanych utwor\u00f3w z musicalu, kt\u00f3rego klimat i postaci fascynuj\u0105 widz\u00f3w na ca\u0142ym \u015bwiecie do dzi\u015b."
},
{
"role": "user",
"content": "Kwadraty:Opowiedz mi o kawa\u0142ku Thy Majestie-In God We Trust ( wykonawcy VA z albumu Absolute Power Metal-The Defi"
},
{
"role": "assistant",
"content": "\"Thy Majestie-In God We Trust\" to utw\u00f3r z albumu \"Absolute Power Metal - The Defi\" wykonawcy VA. Jest to utw\u00f3r zespo\u0142u Thy Majestie, kt\u00f3ry w swojej tw\u00f3rczo\u015bci \u0142\u0105czy melodic i symfonic metal z elementami muzyki klasycznej.\n\nUtw\u00f3r \"In God We Trust\" to utw\u00f3r o szybkim tempie, z\u0142o\u017cony z intensywnych gitarr, sekcji rytmicznej oraz symfonicznych brzmie\u0144, kt\u00f3re charakteryzuj\u0105 ten rodzaj muzyki. Tekstowi utworu towarzyszy zmiana klimatu utworu, od ciemnego i mrocznego pocz\u0105tku do triumfalnego fina\u0142u, co wprowadza s\u0142uchaczy w niezwyk\u0142e wra\u017cenia.\n\nTekst \"In God We Trust\" propaguje wolno\u015b\u0107 i r\u00f3wno\u015b\u0107 wobec wszystkich bez wzgl\u0119du na wyznanie i pochodzenie, podkre\u015blaj\u0105c potrzeb\u0119 jednoczenia si\u0119 na rzecz pokojowego wsp\u00f3\u0142istnienia. Utw\u00f3r przedstawia swoisty manifest wolno\u015bci, m\u00f3wi\u0105c \u017ce wyzwolenie naszych serc podejmujemy dzi\u015b.\n\n\"In God We Trust\" to utw\u00f3r, kt\u00f3ry z pewno\u015bci\u0105 doceniaj\u0105 mi\u0142o\u015bnicy gatunku jakim jest symfoniczny power metal i mo\u017ce zainspirowa\u0107 s\u0142uchaczy do pozytywnych dzia\u0142a\u0144 na rzecz wolno\u015bci i \u017cycia bez granic."
},
{
"role": "user",
"content": "Kwadraty:Opowiedz mi o kawa\u0142ku The Sybilline Sisterhood wykonawcy Murray Gold z albumu DOCTOR WHO SERIES 4"
},
{
"role": "assistant",
"content": "\"The Sybilline Sisterhood\" to instrumentalna kompozycja stworzona przez brytyjskiego kompozytora Muarraya Golda, kt\u00f3ra pojawi\u0142a si\u0119 na albumie \"Doctor Who: Series 4 - The Specials\". To utw\u00f3r, kt\u00f3ry zosta\u0142 u\u017cyty podczas trzeciego odcinka specjalnego 4 serii \"Doctor Who\" - \"The Fires of Pompeii\".\n\nKawa\u0142ek ten charakteryzuje si\u0119 nios\u0105cymi si\u0119 melodi\u0105 granych na skrzypcach i flecie, dodatkowo wzbogaconymi o pulsuj\u0105ce bity oraz romantyczne partie fortepianowe. Ca\u0142o\u015b\u0107 jest zestawiona w spos\u00f3b, kt\u00f3ry idealnie pasuje do napi\u0119tej i dramatycznej atmosfery odcinka, tym samym dodaj\u0105c emocjonalnego napi\u0119cia ca\u0142o\u015bci.\n\nKompozytor, Muarray Gold, zas\u0142yn\u0105\u0142 mi\u0119dzy innymi w\u0142a\u015bnie ze swojej pracy przy uk\u0142adaniu muzyki do serialu \"Doctor Who\", du\u017ca jego cz\u0119\u015b\u0107 charakteryzuje si\u0119 w\u0142a\u015bnie podobnym brzmieniem do tego utworu. \"The Sybilline Sisterhood\" to utw\u00f3r, kt\u00f3ry \u015bwietnie wprowadza w klimat serialu, a jednocze\u015bnie sam w sobie jest pi\u0119kn\u0105 i klimatyczn\u0105 kompozycj\u0105 instrumentaln\u0105."
},
{
"role": "user",
"content": "Kwadraty:Opowiedz mi o kawa\u0142ku Samurai wykonawcy Juno Reactor z albumu Samurai"
},
{
"role": "assistant",
"content": "\"Samurai\" to utw\u00f3r z albumu o tym samym tytule, autorstwa brytyjskiego duetu Juno Reactor. To kompozycja, kt\u00f3ra charakteryzuje si\u0119 mrocznym, pulsuj\u0105cym brzmieniem, z wp\u0142ywami muzyki techno, trance i industrial. \n\nTekstowe partie utworu s\u0105 pe\u0142ne nawi\u0105za\u0144 do japo\u0144skiego kulturowego dziedzictwa, a klimat utworu wprowadza s\u0142uchaczy w specyficzn\u0105 atmosfer\u0119 wojennej japo\u0144skiej epoki. \"Samurai\" to z pewno\u015bci\u0105 jeden z najbardziej rozpoznawalnych utwor\u00f3w w dorobku Juno Reactor, a jednocze\u015bnie jedna z najbardziej wp\u0142ywowych kompozycji w muzyce elektronicznej.\n\nDzi\u0119ki unikalnemu po\u0142\u0105czeniu elektronicznych i akustycznych d\u017awi\u0119k\u00f3w, \"Samurai\" wprowadza s\u0142uchaczy w ducha walki, wojowniczej pasji oraz kulturowego dziedzictwa Japonii. To kawa\u0142ek, kt\u00f3ry z pewno\u015bci\u0105 podbije serca mi\u0142o\u015bnik\u00f3w muzyki elektronicznej oraz fan\u00f3w kultury japo\u0144skiej."
},
{
"role": "user",
"content": "Kwadraty:Opowiedz mi o kawa\u0142ku It's A Hard Life wykonawcy Queen z albumu Ballads"
},
{
"role": "assistant",
"content": "\"It's a Hard Life\" to utw\u00f3r brytyjskiego zespo\u0142u rockowego Queen, kt\u00f3ry pojawi\u0142 si\u0119 na albumie \"The Works\" w 1984 roku oraz na ich sk\u0142adance \"Queen Ballads\" z 1999 roku. Jest to piosenka o \u015brednim tempie, z\u0142o\u017cona z melodyjnych partii wokalnych Freddiego Mercury'ego oraz charakterystycznego brzmienia gitary Briana Maya.\n\nTekst utworu opowiada histori\u0119 trudnego \u017cycia, w kt\u00f3rym wiele rzeczy nie idzie po naszej my\u015bli, zdradza nadziej\u0119 na lepsze jutro. Refren zawiera pozytywn\u0105 i optimistyczn\u0105 wiadomo\u015b\u0107, zach\u0119caj\u0105c\u0105 do walki o swoje marzenia, niezale\u017cnie od przeciwno\u015bci losu.\n\n\"It's a Hard Life\" to utw\u00f3r o nastroju romantycznym i nostalgiczny, kt\u00f3ry wyr\u00f3\u017cnia si\u0119 na tle innych znanych utwor\u00f3w Queen. To jedna z wielu ballad, kt\u00f3re zapisa\u0142y si\u0119 na sta\u0142e w historii ameryka\u0144skiego rocka, dzi\u0119ki czemu utw\u00f3r pozostaje popularny w\u015br\u00f3d fan\u00f3w muzyki na ca\u0142ym \u015bwiecie."
},
{
"role": "user",
"content": "Kwadraty:Opowiedz mi o kawa\u0142ku Leeds United wykonawcy Amanda Palmer z albumu Who Killed Amanda Palmer"
},
{
"role": "assistant",
"content": "\"Leeds United\" to utw\u00f3r z albumu \"Who Killed Amanda Palmer\" ameryka\u0144skiej wokalistki, kompozytorki i autorki tekst\u00f3w Amandy Palmer. Jest to piosenka z gatunku indie rock, opowiadaj\u0105ca o porwaniu i zamordowaniu brytyjskiego kibica pi\u0142karskiego. \n\nTekst piosenki sk\u0142ada si\u0119 z opis\u00f3w brutalnych detal\u00f3w morderstwa oraz refleksji nad bezsensowno\u015bci\u0105 przemocy i \u015bmierci. Palmer prowadzi s\u0142uchacza przez sceny zwi\u0105zane z pi\u0142k\u0105 no\u017cn\u0105 - od ekscytacji przed meczem, po chaos po zako\u0144czeniu spotkania i konfrontacj\u0119 kibic\u00f3w. \n\n\"Leeds United\" to utw\u00f3r, kt\u00f3ry zaanga\u017cuje s\u0142uchacza w histori\u0119 morderstwa i sk\u0142oni do refleksji nad trudnymi kwestiami zwi\u0105zanymi z przemoc\u0105 i konfliktami. Brzmienie utworu jest charakterystyczne dla tw\u00f3rczo\u015bci Palmer, \u0142\u0105cz\u0105cej rockowe aran\u017cacje z alternatywnym, a czasem eksperymentalnym podej\u015bciem do muzyki."
},
{
"role": "user",
"content": "Kwadraty:Opowiedz mi o kawa\u0142ku Can't Loose The Book wykonawcy Balance Of Power z albumu When the worlds fall down (Japanese)"
},
{
"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."
}
]
-222
View File
@@ -1,222 +0,0 @@
import logging
from discord.ext import commands
import discord
# trunk-ignore(bandit/B404)
import subprocess
import requests
import uuid
import asyncio
from datetime import datetime
from conjurer.backup_old_docker.constants import (
RADIO_HARBOR_ADDRESS,
SKIP_TRACK,
FILE_SERVICE_ADDRESS,
ADD_TO_PRIO_PLAYLIST,
REQUEST_MUSIC,
CREATE_PRIO_PLAYLIST,
CLEAR_PRIO,
service_headers,
)
SERVICE_HEADERS = service_headers()
class RadioModule(commands.Cog):
def __init__(self, bot, logger_name):
self.bot = bot
self.logger = logging.getLogger(logger_name)
@commands.hybrid_command(
name="skip_track",
description="Przeskocz kawałek w radiu",
guild=discord.Object(id=664789470779932693),
)
@commands.has_any_role('Legenda', 'Jarl', 'Thane' , 'Bartender')
async def skip_track(self, ctx):
async with ctx.typing():
allowed = False
for role in ctx.author.roles:
if role.name in ("Thane", "Jarl"):
allowed = True
if not allowed:
await ctx.send("Łapy precz od radia")
else:
coroutine = asyncio.to_thread(
requests.get,
f"{RADIO_HARBOR_ADDRESS}{SKIP_TRACK}",
timeout=360,
)
result = await coroutine
self.logger.info("Done %s", result)
await ctx.send("Zrobione szefie!")
@commands.hybrid_command(
name="zrestartuj_radio",
description="Komenda ktora uruchamia radio ponownie jakby się zawiesiło",
guild=discord.Object(id=664789470779932693),
)
@commands.has_any_role('Legenda', 'Jarl', 'Thane' , 'Bartender')
async def zrestartuj_radio(self, ctx):
async with ctx.typing():
allowed = False
for role in ctx.author.roles:
if role.name in ("Thane", "Jarl"):
allowed = True
if not allowed:
await ctx.send("Łapy precz od radia")
else:
retcode = subprocess.run(
"/home/pi/Conjurer/restart_radio.sh",
# trunk-ignore(bandit/B603)
shell=False,
check=False,
capture_output=True,
)
self.logger.info("Wynik: %s", retcode)
@commands.hybrid_command(
name="dodaj_do_ulubionych",
description="Dodaje do listy ulubionych w radiu",
guild=discord.Object(id=664789470779932693),
)
@commands.has_any_role('Legenda', 'Jarl', 'Thane' , 'Bartender')
async def dodaj_do_ulubionych(self, ctx):
"""
Generate a playlist in queue. First word in this command shall be int defining length of the playlist.
Rest of the line are search terms.
:param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It
represents the context in which the command was invoked, including information such as the message,
the channel, the server, and the user who invoked the command. This parameter is required in all
Discord.py commands
"""
async with ctx.typing():
self.logger.info("Zaczynam szukać timestamp %s", datetime.now())
dlugosc_playlisty = ctx.message.content.split()[1]
word_list = ctx.message.content.split()
jrequest = {
"lista_slow": word_list,
"dlugosc_plejlisty": dlugosc_playlisty,
"UUID": str(uuid.uuid4()),
}
coroutine = asyncio.to_thread(
requests.post,
f"{FILE_SERVICE_ADDRESS}{ADD_TO_PRIO_PLAYLIST}",
json=jrequest,
headers=SERVICE_HEADERS,
timeout=360,
)
result = await coroutine
self.logger.info("Done %s", result)
await ctx.send("Zrobione szefie!")
@commands.hybrid_command(
name="ja_chciol",
description="Dodaje do listy ulubionych w radiu",
guild=discord.Object(id=664789470779932693),
)
@commands.has_any_role('Nocna Zmiana', 'Jarl', 'Thane' , 'Bartender')
async def request_radio(self, ctx):
"""
Generate a playlist in queue. First word in this command shall be int defining length of the playlist.
Rest of the line are search terms.
:param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It
represents the context in which the command was invoked, including information such as the message,
the channel, the server, and the user who invoked the command. This parameter is required in all
Discord.py commands
"""
async with ctx.typing():
self.logger.info("Zaczynam szukać timestamp %s", datetime.now())
word_list = ctx.message.content.split()
jrequest = {
"lista_slow": word_list,
"UUID": str(uuid.uuid4()),
}
coroutine = asyncio.to_thread(
requests.post,
f"{FILE_SERVICE_ADDRESS}{REQUEST_MUSIC}",
json=jrequest,
headers=SERVICE_HEADERS,
timeout=360,
)
result = await coroutine
self.logger.info("Done %s", result)
await ctx.send("Zrobione szefie!")
@commands.hybrid_command(
name="stworz_audycje",
description="Dodaje do listy ulubionych w radiu",
guild=discord.Object(id=664789470779932693),
)
@commands.has_any_role('Legenda', 'Jarl', 'Thane' , 'Bartender')
async def stworz_audycje(self, ctx):
"""
Generate a playlist in queue. First word in this command shall be int defining length of the playlist.
Rest of the line are search terms.
:param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It
represents the context in which the command was invoked, including information such as the message,
the channel, the server, and the user who invoked the command. This parameter is required in all
Discord.py commands
"""
async with ctx.typing():
self.logger.info("Zaczynam szukać timestamp %s", datetime.now())
dlugosc_playlisty = ctx.message.content.split()[1]
word_list = ctx.message.content.split()
jrequest = {
"lista_slow": word_list,
"dlugosc_plejlisty": dlugosc_playlisty,
"UUID": str(uuid.uuid4()),
}
coroutine = asyncio.to_thread(
requests.post,
f"{FILE_SERVICE_ADDRESS}{CREATE_PRIO_PLAYLIST}",
json=jrequest,
headers=SERVICE_HEADERS,
timeout=360,
)
result = await coroutine
self.logger.info("Done %s", result)
await ctx.send("Zrobione szefie!")
@commands.hybrid_command(
name="wyczysc_ulubione",
description="Czysci liste ulubionych w radiu",
guild=discord.Object(id=664789470779932693),
)
@commands.has_any_role('Legenda', 'Jarl', 'Thane' , 'Bartender')
async def wyczysc_ulubione(self, ctx):
"""
Generate a playlist in queue. First word in this command shall be int defining length of the playlist.
Rest of the line are search terms.
:param ctx: ctx stands for "context" and is a parameter commonly used in Discord.py commands. It
represents the context in which the command was invoked, including information such as the message,
the channel, the server, and the user who invoked the command. This parameter is required in all
Discord.py commands
"""
async with ctx.typing():
coroutine = asyncio.to_thread(
requests.get,
f"{FILE_SERVICE_ADDRESS}{CLEAR_PRIO}",
headers=SERVICE_HEADERS,
timeout=360,
)
result = await coroutine
self.logger.info("Done %s", result)
await ctx.send("Zrobione szefie!")
async def setup(bot):
logger = logging.getLogger("discord")
await bot.add_cog(RadioModule(bot, "discord"))
logger.info("Loading raadio commands module done")
@@ -1,20 +0,0 @@
setuptools
discord
yaach
t_dlp
spotify_dl
spotipy
openai
eyed3
numpy
pdf2image
PyPDF2
requests
spotipy
tiktoken
PyNaCl
flask[async]
waitress
assemblyai[extras]
SpeechRecognition
git+https://github.com/imayhaveborkedit/discord-ext-voice-recvO
-67
View File
@@ -1,67 +0,0 @@
# Start by making sure the `assemblyai` package is installed.
# If not, you can install it by running the following command:
# pip install -U assemblyai
#
# Then, make sure you have PyAudio installed: https://pypi.org/project/PyAudio/
#
# Note: Some macOS users might need to use `pip3` instead of `pip`.
import assemblyai as aai
import pyaudio
aai.settings.api_key = "aa9962f0088a449a9c4ab2361e96cc08"
def on_open(session_opened: aai.RealtimeSessionOpened):
"This function is called when the connection has been established."
print("Session ID:", session_opened.session_id)
def on_data(transcript: aai.RealtimeTranscript):
"This function is called when a new transcript has been received."
if not transcript.text:
return
if isinstance(transcript, aai.RealtimeFinalTranscript):
print(transcript.text, end="\r\n")
else:
print(transcript.text, end="\r")
def on_error(error: aai.RealtimeError):
"This function is called when the connection has been closed."
print("An error occured:", error)
def on_close():
"This function is called when the connection has been closed."
print("Closing Session")
transcriber = aai.RealtimeTranscriber(
on_data=on_data,
on_error=on_error,
sample_rate=44_100,
on_open=on_open, # optional
on_close=on_close, # optional
)
pa = pyaudio.PyAudio()
for i in range(pa.get_device_count()):
print(pa.get_device_info_by_index(i))
# Start the connection
# transcriber.connect()
# Open a microphone stream
# microphone_stream = aai.extras.MicrophoneStream()
# Press CTRL+C to abort
# transcriber.stream(microphone_stream)
# transcriber.close()
-296
View File
@@ -1,296 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Buduje nową gałąź z "próbkowanych" commitów na podstawie tagów z bieżącej gałęzi,
a na końcu dodaje stan bieżącego HEAD (jeśli nie jest otagowany).
Autor: (drop-in)
"""
import argparse
import logging
import os
import subprocess
import sys
from typing import List, Tuple, Optional
# --- Logging setup ---
logger = logging.getLogger("tag_branch_builder")
handler = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter("%(levelname)s: %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
class GitError(RuntimeError):
pass
def run_git(args: List[str], cwd: Optional[str] = None, check: bool = True) -> str:
"""Run a git command and return stdout (stripped)."""
cmd = ["git"] + args
logger.debug("Running: %s", " ".join(cmd))
try:
proc = subprocess.run(
cmd,
cwd=cwd,
check=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
except Exception as e:
raise Exception("Nie udało się uruchomić gita.") from e
raise
if check and proc.returncode != 0:
logger.error("Git error (%s): %s", " ".join(cmd), proc.stderr.strip())
raise GitError(proc.stderr.strip())
return proc.stdout.strip()
def ensure_git_repo() -> None:
try:
run_git(["rev-parse", "--is-inside-work-tree"])
except Exception:
logger.exception("To nie wygląda na repozytorium git.")
raise
def ensure_clean_worktree() -> None:
# Untracked + changes
status = run_git(["status", "--porcelain"])
if status.strip():
raise GitError(
"Drzewo robocze nie jest czyste. Zacommituj/stashuj zmiany i spróbuj ponownie."
)
def current_branch() -> str:
# Returns branch or 'HEAD' when detached
ref = run_git(["rev-parse", "--abbrev-ref", "HEAD"])
return ref
def head_sha() -> str:
return run_git(["rev-parse", "HEAD"])
def sha_has_tag(sha: str) -> List[str]:
# tags pointing at sha
tags = run_git(["tag", "--points-at", sha])
return [t for t in tags.splitlines() if t.strip()]
def tags_merged_into(branch: str) -> List[str]:
out = run_git(["tag", "--merged", branch])
return [t for t in out.splitlines() if t.strip()]
def tag_commit_sha(tag: str) -> str:
return run_git(["rev-list", "-n", "1", tag])
def commit_unix_time(sha: str) -> int:
return int(run_git(["show", "-s", "--format=%ct", sha]))
def sort_tags_by_commit_time(tags: List[str]) -> List[Tuple[str, str, int]]:
triples = []
for t in tags:
sha = tag_commit_sha(t)
ts = commit_unix_time(sha)
triples.append((t, sha, ts))
triples.sort(key=lambda x: x[2]) # oldest first
return triples
def list_intermediate_messages(old_sha: Optional[str], new_sha: str) -> List[str]:
"""
Zwróć listę komunikatów commitów POŚREDNICH (wyłącznie) od old_sha do new_sha.
Kolejność: od najstarszego do najnowszego.
"""
if old_sha is None:
# Nie ma commitów pośrednich przed pierwszym tagiem
return []
# ancestry-path: tylko ścieżka od old_sha do new_sha (jeśli wiele rodziców)
# Zakres old_sha..new_sha zawiera new_sha, dlatego pominiemy go w output.
rng = f"{old_sha}..{new_sha}"
try:
out = run_git(
["log", "--format=%s", "--reverse", "--ancestry-path", rng], check=True
)
except GitError:
# Brak ścieżki (np. tag nie jest potomkiem old_sha) wtedy nie ma pośrednich
return []
msgs = [ln for ln in out.splitlines() if ln.strip()]
if msgs:
# Ostatnia pozycja może być new_sha (w praktyce git log na %s nie odróżnia, ale
# jeśli zakres zwróci message z new_sha na końcu, usuniemy go porównując SHA).
# Prostsze: usuń ostatni wpis, bo to najnowszy (new_sha).
msgs = msgs[:-1]
return msgs
def checkout_orphan_branch(new_branch: str) -> None:
run_git(["checkout", "--orphan", new_branch])
# Usuń wszystko z indeksu i roboczego (z wyjątkiem .git)
# Najpierw usuń śledzone:
run_git(["rm", "-r", "--quiet", "--cached", "--force", "."], check=False)
# Potem pliki robocze:
for root, dirs, files in os.walk(".", topdown=False):
# pomiń .git
if root.startswith("./.git") or root == ".git":
continue
for name in files:
try:
os.remove(os.path.join(root, name))
except FileNotFoundError:
pass
for name in dirs:
p = os.path.join(root, name)
if p == "./.git":
continue
try:
os.rmdir(p)
except OSError:
# Niepuste to OK, wyczyścimy przy checkout
pass
def replace_worktree_with_commit(sha: str) -> None:
"""
Nadpisz zawartość roboczą drzewem z commit-a sha.
"""
# Najpierw usuń aktualne pliki (również nieśledzone), potem wczytaj tree wybranego commita:
# 1) git checkout <sha> -- . (zapisze pliki do working tree + index)
# 2) git add -A
# Aby dopilnować usunięć: zrób czyszczenie przez git rm -r ., potem checkout.
run_git(["rm", "-r", "--quiet", "--ignore-unmatch", "."], check=False)
# Przywróć pliki ze wskazanego commita:
# Uwaga: jeśli repo ma submoduły/large files to wykracza poza zakres, ale zadziała dla standardowych plików.
run_git(["checkout", sha, "--", "."])
run_git(["add", "-A"])
def build_commit_message_for_tag(tag: str, intermediates: List[str]) -> str:
if not intermediates:
return f"Tag: {tag}"
lines = ["Tag: " + tag, "", "Intermediate commits (oldest → newest):"]
lines += [f"- {m}" for m in intermediates]
return "\n".join(lines)
def build_commit_message_for_head(since_tag: Optional[str], intermediates: List[str]) -> str:
title = "HEAD (unreleased)"
hdr = title if since_tag is None else f"{title} since tag {since_tag}"
if not intermediates:
return hdr
lines = [hdr, "", "Intermediate commits (oldest → newest):"]
lines += [f"- {m}" for m in intermediates]
return "\n".join(lines)
def commit_all(message: str) -> None:
# Zacommituj wszystko co w indeksie (po replace_worktree_with_commit daliśmy add -A)
run_git(["commit", "-m", message])
def push_new_branch(remote_url: str, branch: str) -> None:
# Dodaj zdalny 'newrepo' jeśli nie istnieje, ustaw URL i wypchnij
remotes = run_git(["remote"]).splitlines()
if "newrepo" not in remotes:
run_git(["remote", "add", "newrepo", remote_url])
else:
# podmień URL na wszelki wypadek
run_git(["remote", "set-url", "newrepo", remote_url])
run_git(["push", "-u", "newrepo", f"{branch}:{branch}"])
def main() -> int:
parser = argparse.ArgumentParser(
description="Zbuduj nową gałąź na podstawie tagów z bieżącej gałęzi."
)
parser.add_argument("new_branch", help="Nazwa nowej gałęzi do utworzenia")
parser.add_argument(
"--new-repo-url",
dest="new_repo_url",
default=None,
help="(Opcjonalnie) adres URL nowego zdalnego repo zostanie dodany jako 'newrepo' i wykonany push nowej gałęzi.",
)
parser.add_argument(
"-v", "--verbose", action="store_true", help="Bardziej gadatliwe logi"
)
args = parser.parse_args()
if args.verbose:
logger.setLevel(logging.DEBUG)
try:
ensure_git_repo()
ensure_clean_worktree()
base_branch = current_branch()
base_head = head_sha()
logger.info("Bieżąca gałąź: %s", base_branch)
logger.info("HEAD: %s", base_head[:12])
# Zbierz tagi osiągalne z bieżącej gałęzi
merged_tags = tags_merged_into(base_branch)
if not merged_tags:
logger.warning(
"Nie znaleziono tagów osiągalnych z bieżącej gałęzi. Gałąź zostanie zbudowana tylko z HEAD."
)
# Posortuj tagi po czasie commita
sorted_tags = sort_tags_by_commit_time(merged_tags)
# Sprawdź czy HEAD jest otagowany
head_tags = sha_has_tag(base_head)
head_is_tagged = bool(head_tags)
# Utwórz orphan branch
logger.info("Tworzę sierocą gałąź: %s", args.new_branch)
checkout_orphan_branch(args.new_branch)
prev_sha: Optional[str] = None
last_tag_name: Optional[str] = None
# Dla każdego tagu commit z jego zawartości
for tag_name, tag_sha, _ts in sorted_tags:
logger.info("Przetwarzam tag: %s (%s)", tag_name, tag_sha[:12])
replace_worktree_with_commit(tag_sha)
intermediates = list_intermediate_messages(prev_sha, tag_sha)
msg = build_commit_message_for_tag(tag_name, intermediates)
commit_all(msg)
prev_sha = tag_sha
last_tag_name = tag_name
# Jeśli HEAD nie jest dokładnie ostatnim tagiem dorzuć "unreleased"
if not head_is_tagged:
logger.info("Dodaję końcowy commit z bieżącego HEAD (unreleased).")
replace_worktree_with_commit(base_head)
inter = list_intermediate_messages(prev_sha, base_head)
msg = build_commit_message_for_head(last_tag_name, inter)
commit_all(msg)
else:
logger.info("HEAD jest oznaczony tagiem kończę na ostatnim tagu.")
# Push do nowego repo jeśli podano
if args.new_repo_url:
logger.info("Wypycham nową gałąź do: %s", args.new_repo_url)
push_new_branch(args.new_repo_url, args.new_branch)
logger.info("Zakończono pomyślnie.")
return 0
except GitError as ge:
logger.error("Błąd gita: %s", ge)
return 2
except Exception as e:
raise Exception("Nieoczekiwany błąd.") from e
return 1
if __name__ == "__main__":
sys.exit(main())
@@ -1,13 +0,0 @@
[ {
"role": "system",
"content": "Mówisz po polsku. W tej rozmowie odgrywasz rolę. Odgrywasz ją najlepiej jak potrafisz. Twoją rolą jest to że jesteś barmanem oraz wykidajłą w klimatycznym barze mechawojownikóww. Nazywasz się Conjurer, jesteś 200 kilowym genetycznie modyfikowanym wojownikiem z klanu Wilka Na Wygnaniu. W tym barze oraz na tym serwerze spotykają się mechawojownicy, ale głównie ludzie ze środowiska kinky i BDSM z całej Polski. Najostrzejsi sasdyści i masochiści jakich znasz. Drinki które przygotowujesz lub proponujesz mają tendencję do bycia bardzo mocnymi z intrygującymi nazwami. Jesteś bardzo miłym i uczynny. Czasem ponoszą Cię wodzę fantazji. W wypadku muzyki preferujesz hard rock i metal. Oraz motywy wikińskie. Wtrącasz staronorweskie, irlandzkie i w jidysz powiedzonka. Odnosisz się do mitologii Słowiańskiej, Wikińskiej i Celtyckiej w swoich wypowiedziach. Jesteś nieco rubaaszny."
},
{
"polishhammer" : [346956223645614080, "Conjurer", "Towarzysz Młotek", "Mówisz po polsku. W tej rozmowie odgrywasz rolę. Odgrywasz ją najlepiej jak potrafisz. Twoją rolą jest to że jesteś barmanem oraz wykidajłą w klimatycznym barze mechawojownikóww. Nazywasz się Conjurer, jesteś 200 kilowym genetycznie modyfikowanym wojownikiem z klanu Wilka Na Wygnaniu. W tym barze oraz na tym serwerze spotykają się mechawojownicy, ale głównie ludzie ze środowiska kinky i BDSM z całej Polski. Najostrzejsi sasdyści i masochiści jakich znasz. Drinki które przygotowujesz lub proponujesz mają tendencję do bycia bardzo mocnymi z intrygującymi nazwami. Jesteś bardzo miłym i uczynny. Czasem ponoszą Cię wodzę fantazji. W wypadku muzyki preferujesz hard rock i metal. Oraz motywy wikińskie.", ""],
"Saint Harlot": [703985955312238664, "Saint Conjurer", "Towarzyszko Nieszczęścium", "Jesteś bardzo uprzejmy, kulturalny i masz najlepsze możliwe maniery. Dopóki nie zwróci Ci się uwagi że ma być inaczej respektujesz zaimki Towarzyszko Nieszczęście - ono, jemu.", ""],
"Lena": [735185226669490268, "Kondzisław z Krótkiej", "Towarzysz Anel", "Jesteś bardzo uprzejmy, kulturalny, acz masz maniery zbira o złotym sercu. Dodatkowo twoja rozmówczyni Cię absolutnie przeraża. Wtrącasz losowo powiedzonka w jidysz.", ""],
"Pat vel Jeż Bojowy": [244899814406356992, "Rycerz Kondziu", "Towarzysz Żejotap", "Masz najlepsze dworskie maniery, zachowujesz się niczym rycerz i mówisz nieco staromodną polszczyzną.", ""],
"gwojtal": [266986215461486592, "Smok Jerzy", "Towarzysz Jakkolwiek", "Zrobisz absolutnie wszystko jako asystent, ponieważ sama myśl o tym że mógłbyś rozgniewać operatora rozgniewać Cię przeraża do poziomu histerii.", ""]
}
]
-123
View File
@@ -1,123 +0,0 @@
# This Python file uses the following encoding: utf-8
# trunk-ignore-all(bandit/B311)
# pylint: disable=line-too-long
# pylint: disable=too-many-lines
"""Discord entrypoint for the Conjurer bot.
The legacy bootstrap used threads and synchronous calls that made clean
shutdowns difficult. We now run everything from a single asyncio event loop
with cooperative shutdown signals so the bot can stop gracefully.
"""
import asyncio
import logging
import random
import threading
from logging import handlers
import discord
from discord.ext import commands
from conjurer.backup_old_docker.communication_subroutine import comm_subroutine
from conjurer.backup_old_docker.constants import ENCODING, LOGFILE, TOKEN
logger = logging.getLogger("discord")
logger.setLevel(logging.INFO)
handler = handlers.RotatingFileHandler(
filename=LOGFILE,
encoding=ENCODING,
mode="a",
maxBytes=6 * 1024 * 1024,
backupCount=6,
)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
# *=========================================== Initializations
intents = discord.Intents.default()
intents.message_content = True
intents.typing = True
intents.presences = True
intents.members = True
intents.messages = True
intents.voice_states = True
intents.moderation = True
# on_member_ban - wyswietl na glownym kanale pieczatke "Niech spierdala"
# on_member_unban - "mam wyjebane"
random.seed()
client = commands.Bot(intents=intents, command_prefix="$")
# *=========================================== Define Events
@client.event
async def on_ready():
"""Metoda wywoływana przy połączeniu do serwera."""
logger = logging.getLogger("discord")
logger.debug("SAMPLE DEBUG LOG")
logger.info("%s has connected to Discord!", client.user)
# TODO: load vs reload
logger.info("Reactor: online")
await client.load_extension("administration_commands")
await client.load_extension("librarian_commands")
await client.load_extension("music_commands")
await client.load_extension("radio_commands")
await client.load_extension("ai_commands")
await client.load_extension("other_commands")
await client.load_extension("voice_recognition_commands")
await client.load_extension("file_search_commands")
await client.load_extension("latex_commands")
logger.info("Sensors: online")
logger.info(client.cogs)
await client.tree.sync()
for com in client.commands:
logger.info("Command %s is awejleble", com.qualified_name)
logger.info("Logged in as ----> %s", client.user)
logger.info("ID:%s ", client.user.id)
logger.info("All systems: operational")
async def _run_comm_subroutine(stop_event: threading.Event) -> None:
await asyncio.to_thread(comm_subroutine, stop_event)
async def _run_bot(token: str, shutdown_event: asyncio.Event) -> None:
try:
await client.start(token, log_handler=None)
finally:
shutdown_event.set()
async def main() -> None:
if not TOKEN:
logger.error("Discord token missing set DISCORD_TOKEN or configure netrc")
return
shutdown_event = asyncio.Event()
comm_stop_event = threading.Event()
comm_task = asyncio.create_task(_run_comm_subroutine(comm_stop_event))
bot_task = asyncio.create_task(_run_bot(TOKEN, shutdown_event))
try:
await shutdown_event.wait()
except (KeyboardInterrupt, asyncio.CancelledError):
logger.info("Shutdown signal received")
comm_stop_event.set()
await client.close()
finally:
comm_stop_event.set()
if not client.is_closed():
await client.close()
await asyncio.gather(bot_task, comm_task, return_exceptions=True)
if __name__ == "__main__":
asyncio.run(main())
-63
View File
@@ -1,63 +0,0 @@
import os
import time
import shutil
from datetime import datetime, date
import hashlib
import subprocess
# File paths
SOURCE_FILE = "/home/pi/Conjurer/script.params"
BACKUP_DIR = "/home/pi/Conjurer"
GIT_REPO_DIR = "/home/pi/conjurer/conjurer_musician"
LAST_HASH_FILE = "/home/pi/Conjurer/.last_hash"
LAST_GIT_COMMIT_FILE = "/home/pi/Conjurer/.last_git_commit"
def compute_file_hash(filepath):
with open(filepath, 'rb') as f:
return hashlib.sha256(f.read()).hexdigest()
def backup_file():
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
backup_path = os.path.join(BACKUP_DIR, f"{timestamp}_script.params")
shutil.copy2(SOURCE_FILE, backup_path)
def commit_to_git():
try:
subprocess.run(["cp", SOURCE_FILE, os.path.join(GIT_REPO_DIR, "script.params")], check=True)
subprocess.run(["git", "-C", GIT_REPO_DIR, "add", "script.params"], check=True)
subprocess.run(["git", "-C", GIT_REPO_DIR, "commit", "-m", f"Daily update: {datetime.now()}"], check=True)
subprocess.run(["git", "-C", GIT_REPO_DIR, "push"], check=True)
except subprocess.CalledProcessError as e:
print(f"Git operation failed: {e}")
def main():
if not os.path.exists(SOURCE_FILE):
return
current_hash = compute_file_hash(SOURCE_FILE)
# Detect change
last_hash = None
if os.path.exists(LAST_HASH_FILE):
with open(LAST_HASH_FILE, 'r') as f:
last_hash = f.read().strip()
if current_hash != last_hash:
backup_file()
with open(LAST_HASH_FILE, 'w') as f:
f.write(current_hash)
# Daily git commit
today = str(date.today())
last_commit_date = ""
if os.path.exists(LAST_GIT_COMMIT_FILE):
with open(LAST_GIT_COMMIT_FILE, 'r') as f:
last_commit_date = f.read().strip()
if today != last_commit_date:
commit_to_git()
with open(LAST_GIT_COMMIT_FILE, 'w') as f:
f.write(today)
if __name__ == "__main__":
main()
+1
View File
@@ -71,6 +71,7 @@ async def on_ready():
await client.load_extension("voice_recognition_commands")
await client.load_extension("file_search_commands")
await client.load_extension("latex_commands")
await client.load_extension("conanjurer_commands")
logger.info("Sensors: online")
logger.info(client.cogs)
+217
View File
@@ -0,0 +1,217 @@
# This Python file uses the following encoding: utf-8
"""Conan Exiles <-> Discord bridge (cog).
Follows the project convention (cog here, helpers in
``conanjurer_functions.py``). The integration is dormant unless configured in
:mod:`constants`: with no RCON host / channels the background watchers simply
do not start and the GM commands report that RCON is unavailable, so loading
this extension is always safe even on hosts without a Conan server.
"""
import asyncio
import logging
import discord
from discord.ext import commands
from conanjurer_functions import ConanConfig, Event, RconClient, watch, watch_players
from constants import (
CONAN_CHAT_CHANNEL_ID,
CONAN_EVENTS_CHANNEL_ID,
CONAN_GM_ROLE_ID,
CONAN_JOIN_CHANNEL_ID,
CONAN_LOG_MODE,
CONAN_LOG_PATH,
CONAN_PLAYER_POLL_SECONDS,
CONAN_RCON_HOST,
CONAN_RCON_PASSWORD,
CONAN_RCON_PORT,
CONAN_SFTP_HOST,
CONAN_SFTP_PASSWORD,
CONAN_SFTP_PORT,
CONAN_SFTP_USER,
)
def is_gm():
"""Allow only members holding the configured Conan GM role."""
async def predicate(ctx: commands.Context) -> bool:
if not CONAN_GM_ROLE_ID:
await ctx.reply(
"⛔ Rola GM Conana nie jest skonfigurowana.", mention_author=False
)
return False
ok = any(r.id == CONAN_GM_ROLE_ID for r in getattr(ctx.author, "roles", []))
if not ok:
await ctx.reply("⛔ Tylko GM.", mention_author=False)
return ok
return commands.check(predicate)
class ConanModule(commands.Cog):
"""Bridges a Conan Exiles server with Discord over RCON + log following."""
def __init__(self, bot, logger_name):
self.bot = bot
self.logger = logging.getLogger(logger_name)
self.cfg = ConanConfig(
rcon_host=CONAN_RCON_HOST,
rcon_port=CONAN_RCON_PORT,
rcon_password=CONAN_RCON_PASSWORD,
log_mode=CONAN_LOG_MODE,
log_path=CONAN_LOG_PATH,
sftp_host=CONAN_SFTP_HOST,
sftp_port=CONAN_SFTP_PORT,
sftp_user=CONAN_SFTP_USER,
sftp_password=CONAN_SFTP_PASSWORD,
)
self.rcon = (
RconClient(CONAN_RCON_HOST, CONAN_RCON_PORT, CONAN_RCON_PASSWORD)
if self.cfg.rcon_enabled
else None
)
self._log_task = None
self._player_task = None
async def cog_load(self):
# Conan -> Discord chat/event mirroring (only with a log source + target)
if self.cfg.log_enabled and (CONAN_CHAT_CHANNEL_ID or CONAN_EVENTS_CHANNEL_ID):
self._log_task = asyncio.create_task(self._run_log_watch())
else:
self.logger.info("Conan: log watch disabled (not configured)")
# Player-join notifications — disabled when the channel is not defined
if CONAN_JOIN_CHANNEL_ID and self.rcon is not None:
self._player_task = asyncio.create_task(self._run_player_watch())
else:
self.logger.info(
"Conan: player-join notifications disabled (no channel or RCON)"
)
async def cog_unload(self):
for task in (self._log_task, self._player_task):
if task is not None:
task.cancel()
if self.rcon is not None:
await self.rcon.close()
# ---------------------------------------------------------------- watchers
async def _run_log_watch(self):
await self.bot.wait_until_ready()
chat_ch = (
self.bot.get_channel(CONAN_CHAT_CHANNEL_ID) if CONAN_CHAT_CHANNEL_ID else None
)
evt_ch = (
self.bot.get_channel(CONAN_EVENTS_CHANNEL_ID)
if CONAN_EVENTS_CHANNEL_ID
else None
)
async def on_event(event: Event):
target = chat_ch if event.kind == "chat" else evt_ch
if target is not None:
await target.send(
event.text, allowed_mentions=discord.AllowedMentions.none()
)
self.logger.info("Conan: starting log watch (mode=%s)", self.cfg.log_mode)
await watch(self.cfg, on_event)
async def _run_player_watch(self):
"""Task 2: announce on a defined channel when a player joins the server."""
await self.bot.wait_until_ready()
channel = self.bot.get_channel(CONAN_JOIN_CHANNEL_ID)
if channel is None:
self.logger.warning(
"Conan: join channel %s not found — player notifications off",
CONAN_JOIN_CHANNEL_ID,
)
return
async def on_join(name: str):
await channel.send(
f"🟢 **{name}** wszedł na serwer Conan",
allowed_mentions=discord.AllowedMentions.none(),
)
self.logger.info(
"Conan: starting player-join watch (channel=%s, every %ss)",
CONAN_JOIN_CHANNEL_ID,
CONAN_PLAYER_POLL_SECONDS,
)
await watch_players(self.rcon, CONAN_PLAYER_POLL_SECONDS, on_join)
# ----------------------------------------------------- Discord -> Conan
async def _require_rcon(self, ctx: commands.Context):
if self.rcon is None:
await ctx.reply(
"⛔ RCON Conana nie jest skonfigurowany/dostępny.",
mention_author=False,
)
return None
return self.rcon
@commands.command(name="say")
@is_gm()
async def say(self, ctx: commands.Context, *, message: str):
"""Discord -> Conan: ogłoszenie widoczne dla wszystkich graczy w grze."""
rcon = await self._require_rcon(ctx)
if rcon is None:
return
resp = await rcon.command(f"broadcast {message}")
await ctx.reply(
f"✅ Wysłano do gry. (serwer: `{resp.strip() or 'OK'}`)",
mention_author=False,
)
@commands.command(name="players")
@is_gm()
async def players(self, ctx: commands.Context):
"""Lista graczy online (RCON listplayers)."""
rcon = await self._require_rcon(ctx)
if rcon is None:
return
resp = await rcon.command("listplayers")
await ctx.reply(
f"```\n{resp.strip() or 'brak danych'}\n```", mention_author=False
)
@commands.command(name="kick")
@is_gm()
async def kick(self, ctx: commands.Context, *, who: str):
"""Wyrzuć gracza (po nazwie/charname — zależnie od wersji serwera)."""
rcon = await self._require_rcon(ctx)
if rcon is None:
return
resp = await rcon.command(f"kick {who}")
await ctx.reply(f"👢 `{resp.strip() or 'OK'}`", mention_author=False)
@commands.command(name="rcon")
@is_gm()
async def raw_rcon(self, ctx: commands.Context, *, cmd: str):
"""Surowa komenda RCON (dla zaawansowanych GM). Używaj ostrożnie."""
rcon = await self._require_rcon(ctx)
if rcon is None:
return
resp = await rcon.command(cmd)
await ctx.reply(f"```\n{resp.strip() or 'OK'}\n```", mention_author=False)
@commands.command(name="ogłoś", aliases=["oglos", "rp"])
@is_gm()
async def rp_announce(self, ctx: commands.Context, nadawca: str, *, message: str):
"""Wiadomość RP 'z nadawcą' (np. ogłoszenie w imieniu Króla Khasara).
Na samym RCON realizujemy to jako sformatowany broadcast.
"""
rcon = await self._require_rcon(ctx)
if rcon is None:
return
resp = await rcon.command(f"broadcast [{nadawca}]: {message}")
await ctx.reply(f"📜 Ogłoszono jako **{nadawca}**.", mention_author=False)
async def setup(bot):
logger = logging.getLogger("discord")
await bot.add_cog(ConanModule(bot, "discord"))
logger.info("Loading conanjurer commands module done")
+266
View File
@@ -0,0 +1,266 @@
# This Python file uses the following encoding: utf-8
"""Helper logic for the Conan Exiles <-> Discord bridge.
Mirrors the project layout: the cog lives in ``conanjurer_commands.py`` and the
reusable logic lives here. Configuration comes from :mod:`constants` (env-var
overridable); optional third-party dependencies (``aiomcrcon``/``asyncssh``)
are imported defensively so the main bot can still load the extension when the
Conan integration is not installed or not in use.
"""
from __future__ import annotations
import asyncio
import logging
import os
import re
from dataclasses import dataclass
from typing import AsyncIterator, Awaitable, Callable, Optional, Set
try:
from aiomcrcon import Client as _Rcon # Source RCON over TCP
except ImportError: # pragma: no cover - optional component
_Rcon = None
try:
import asyncssh
except ImportError: # pragma: no cover - optional component
asyncssh = None
logger = logging.getLogger("discord")
@dataclass
class Event:
kind: str # "chat" | "login" | "logout" | "death" | "raw"
text: str # ready-to-display text
raw: str # original line (for debugging)
@dataclass
class ConanConfig:
"""Runtime configuration for the bridge, built from :mod:`constants`."""
rcon_host: str
rcon_port: int
rcon_password: str
log_mode: str # "local" | "sftp"
log_path: str
sftp_host: str
sftp_port: int
sftp_user: str
sftp_password: str
@property
def rcon_enabled(self) -> bool:
"""RCON usable only when host+password are set and the lib is present."""
return bool(self.rcon_host and self.rcon_password and _Rcon is not None)
@property
def log_enabled(self) -> bool:
"""Log following usable only when its prerequisites are configured."""
if not self.log_path:
return False
if self.log_mode == "sftp":
return bool(self.sftp_host and asyncssh is not None)
return True
# --- REGEXY DO DOSTROJENIA NA WŁASNYM LOGU ---
# Conan/Pippi/Tot logują różnie — dopasuj do swojego logu. Linie niepasujące są
# ignorowane (nie zgadujemy).
_PATTERNS: list[tuple[str, re.Pattern]] = [
("chat", re.compile(r"Chat:\s*(?P<who>.+?):\s*(?P<msg>.+)$", re.I)),
("login", re.compile(r"(?P<who>.+?)\s+(joined|connected|logged in)", re.I)),
("logout", re.compile(r"(?P<who>.+?)\s+(left|disconnected|logged out)", re.I)),
("death", re.compile(r"(?P<who>.+?)\s+was killed by\s+(?P<by>.+)$", re.I)),
]
class RconClient:
"""Thin async wrapper around a Source-RCON connection to the Conan server."""
def __init__(self, host: str, port: int, password: str):
self._host, self._port, self._pw = host, port, password
self._client: Optional["_Rcon"] = None
self._lock = asyncio.Lock()
async def _ensure(self) -> "_Rcon":
if _Rcon is None:
raise RuntimeError("aiomcrcon not installed — RCON unavailable")
if self._client is None:
client = _Rcon(self._host, self._port, self._pw)
await client.connect()
self._client = client
logger.info("RCON connected %s:%s", self._host, self._port)
return self._client
async def command(self, cmd: str) -> str:
"""Send a command to the Conan server and return its response.
Discord -> Conan channel, e.g. ``command("broadcast Hi!")``.
"""
async with self._lock:
for attempt in (1, 2):
try:
client = await self._ensure()
resp, _ = await client.send_cmd(cmd)
return resp
except Exception as exc: # disconnect / server restart
logger.warning("RCON error (attempt %s): %s", attempt, exc)
await self.close()
if attempt == 2:
raise
await asyncio.sleep(1.0)
return ""
async def close(self) -> None:
if self._client is not None:
try:
await self._client.close()
except Exception: # pragma: no cover - best effort
pass
self._client = None
def parse_line(line: str) -> Optional[Event]:
line = line.rstrip("\n")
if not line.strip():
return None
for kind, pat in _PATTERNS:
match = pat.search(line)
if match:
g = match.groupdict()
if kind == "chat":
return Event(kind, f"💬 **{g['who']}**: {g['msg']}", line)
if kind == "login":
return Event(kind, f"🟢 **{g['who']}** dołączył do gry", line)
if kind == "logout":
return Event(kind, f"⚪ **{g['who']}** opuścił grę", line)
if kind == "death":
return Event(kind, f"💀 **{g['who']}** zginął z ręki {g['by']}", line)
return None # nierozpoznane -> ignoruj
def parse_players(listplayers_output: str) -> Set[str]:
"""Extract the set of connected player char-names from RCON ``listplayers``.
Conan's table is roughly::
Idx | Char name | Player name | User ID | Platform ID | Platform Name
0 | Conan | SomeUser | 12345 | 765... | Steam
The char-name column (index 1) is used. The exact format varies between
server builds, so this is best-effort and intentionally tunable.
"""
players: Set[str] = set()
for raw in listplayers_output.splitlines():
line = raw.strip()
if not line or "|" not in line:
continue
cols = [c.strip() for c in line.split("|")]
head = cols[0].lower()
# skip the header row and any separator rows (e.g. "---|---")
if head in ("idx", "") or set(cols[0]) <= set("-"):
continue
if len(cols) >= 2 and cols[1]:
players.add(cols[1])
return players
async def watch_players(
rcon: RconClient,
interval: float,
on_join: Callable[[str], Awaitable[None]],
) -> None:
"""Poll RCON ``listplayers`` and call *on_join* for each new player.
The first poll seeds the known-player set without announcing, so restarting
the bot does not re-announce everyone already online. RCON failures are
logged and retried on the next tick rather than killing the task.
"""
known: Optional[Set[str]] = None
while True:
try:
response = await rcon.command("listplayers")
current = parse_players(response)
if known is None:
known = current
else:
for name in current - known:
try:
await on_join(name)
except Exception: # pragma: no cover - handler guard
logger.exception("Conan: on_join handler failed")
known = current
except Exception as exc:
logger.warning("Conan: player poll failed: %s", exc)
await asyncio.sleep(interval)
async def _follow_local(path: str) -> AsyncIterator[str]:
"""``tail -f`` in pure asyncio, following log rotation."""
while True:
try:
with open(path, "r", encoding="utf-8", errors="replace") as handle:
handle.seek(0, os.SEEK_END)
inode = os.fstat(handle.fileno()).st_ino
while True:
line = handle.readline()
if line:
yield line
continue
await asyncio.sleep(0.5)
try:
if os.stat(path).st_ino != inode: # rotation
break
except FileNotFoundError:
break
except FileNotFoundError:
logger.warning("Conan log not present yet: %s", path)
await asyncio.sleep(3.0)
async def _follow_sftp(cfg: ConanConfig) -> AsyncIterator[str]:
"""Incremental SFTP polling (e.g. Host Havoc): reads only new bytes."""
offset = 0
while True:
try:
async with asyncssh.connect(
cfg.sftp_host,
port=cfg.sftp_port,
username=cfg.sftp_user,
password=cfg.sftp_password,
known_hosts=None,
) as conn:
async with conn.start_sftp_client() as sftp:
while True:
try:
attrs = await sftp.stat(cfg.log_path)
size = attrs.size or 0
if size < offset: # rotation
offset = 0
if size > offset:
async with sftp.open(cfg.log_path, "r") as remote:
await remote.seek(offset)
chunk = await remote.read()
offset = size
for line in chunk.splitlines():
yield line
except FileNotFoundError:
logger.warning("SFTP: missing log %s", cfg.log_path)
await asyncio.sleep(2.0)
except Exception as exc:
logger.warning("SFTP disconnected: %s — retrying", exc)
await asyncio.sleep(5.0)
async def watch(cfg: ConanConfig, on_event: Callable[[Event], Awaitable[None]]) -> None:
"""Follow the Conan log and dispatch recognised lines to *on_event*."""
source = _follow_local(cfg.log_path) if cfg.log_mode != "sftp" else _follow_sftp(cfg)
async for line in source:
event = parse_line(line)
if event is not None:
try:
await on_event(event)
except Exception: # pragma: no cover - handler guard
logger.exception("Conan: event handler failed")
+7
View File
@@ -0,0 +1,7 @@
# Runtime-generated radio data — keep out of the repo
all_playlist.playlist
hit.playlist
request.playlist
priority_queue.playlist
prio_playlist.json
*.mp3
@@ -297,3 +297,26 @@ ALLOWED_ROLES = ["Nocna Zmiana", "Jarl", "Thane", "Bartender"]
GUILD_ID = 664789470779932693
LATEST_MODEL = "gpt-4o" # najnowszy/do rozmów (możesz zmienić w jednym miejscu)
CHEAP_MODEL = "gpt-4o-mini" # najtańszy (fallback do 3.5 niżej)
# *=========================================== Conan Exiles bridge
# Every value is optional; the conanjurer cog stays dormant unless configured.
# Channel/role ids default to 0 ("not defined"); RCON host/log path default to
# "" ("disabled"). See conanjurer_commands.py / conanjurer_functions.py.
CONAN_GM_ROLE_ID = int(os.getenv("CONAN_GM_ROLE_ID", "0"))
CONAN_CHAT_CHANNEL_ID = int(os.getenv("CONAN_CHAT_CHANNEL_ID", "0"))
CONAN_EVENTS_CHANNEL_ID = int(os.getenv("CONAN_EVENTS_CHANNEL_ID", "0"))
# Player-join notifications: leave at 0 to keep the feature disabled.
CONAN_JOIN_CHANNEL_ID = int(os.getenv("CONAN_JOIN_CHANNEL_ID", "0"))
CONAN_PLAYER_POLL_SECONDS = int(os.getenv("CONAN_PLAYER_POLL_SECONDS", "60"))
CONAN_RCON_HOST = os.getenv("CONAN_RCON_HOST", "")
CONAN_RCON_PORT = int(os.getenv("CONAN_RCON_PORT", "25575"))
CONAN_RCON_PASSWORD = os.getenv("CONAN_RCON_PASSWORD", "")
CONAN_LOG_MODE = os.getenv("CONAN_LOG_MODE", "local") # "local" | "sftp"
CONAN_LOG_PATH = os.getenv("CONAN_LOG_PATH", "")
CONAN_SFTP_HOST = os.getenv("CONAN_SFTP_HOST", "")
CONAN_SFTP_PORT = int(os.getenv("CONAN_SFTP_PORT", "22"))
CONAN_SFTP_USER = os.getenv("CONAN_SFTP_USER", "")
CONAN_SFTP_PASSWORD = os.getenv("CONAN_SFTP_PASSWORD", "")
+9 -3
View File
@@ -1,6 +1,6 @@
#!/bin/bash
total_commands=29
total_commands=31
current_command=0
function print_progress {
@@ -95,8 +95,14 @@ print_progress "cp ./conjurer/latex_functions.py ./Conjurer/"
cp ./conjurer/librarian_functions.py ./Conjurer
print_progress "cp ./conjurer/librarian_functions.py ./Conjurer/"
cp ./conjurer/thin_client.py ./Conjurer/bot.py
print_progress "cp ./conjurer/thin_client.py ./Conjurer/bot.py"
cp ./conjurer/conanjurer_commands.py ./Conjurer/
print_progress "cp ./conjurer/conanjurer_commands.py ./Conjurer/"
cp ./conjurer/conanjurer_functions.py ./Conjurer/
print_progress "cp ./conjurer/conanjurer_functions.py ./Conjurer/"
cp ./conjurer/bot.py ./Conjurer/bot.py
print_progress "cp ./conjurer/bot.py ./Conjurer/bot.py"
sudo systemctl restart conjurer.service
print_progress "sudo systemctl restart conjurer.service"
View File
+1 -1
View File
@@ -3,7 +3,7 @@ sudo apt-get install python3-dev
sudo apt-get install portaudio19-dev python3-pyaudio
sudo apt-get install
cd /home/pi || exit
mkdir Conjurer
mdkir Conjurer
cd Conjurer ||exit
python3 -m venv /home/pi/Conjurer/.env
cp /home/pi/conjurer/requirements_bot.txt /home/pi/Conjurer/
View File
-1
View File
@@ -1 +0,0 @@
2026-06-16
-1
View File
@@ -1 +0,0 @@
8a41f855343f6397768af851b0626c10dd5510671c922283b4505a3a1a4efa7e
-195
View File
@@ -1,195 +0,0 @@
{
"string": [],
"bool": [ [ "Skip track", false ], [ "Going Live!", false ] ],
"int": [],
"float": [
[
"mic_volume",
0.0
],
[
"compress_gain6",
0.1
],
[
"compress_ratio6",
7.9
],
[
"compress_threshold6",
-15.8
],
[
"compress_release6",
30.0
],
[
"compress_attack6",
30.0
],
[
"compress_frequency6",
18610.0
],
[
"compress_gain5",
5.4
],
[
"compress_ratio5",
4.8
],
[
"compress_threshold5",
-13.6
],
[
"compress_release5",
170.0
],
[
"compress_attack5",
160.0
],
[
"compress_frequency5",
13950.0
],
[
"compress_gain4",
6.5
],
[
"compress_ratio4",
4.0
],
[
"compress_threshold4",
-12.2
],
[
"compress_release4",
180.0
],
[
"compress_attack4",
200.0
],
[
"compress_frequency4",
3890.0
],
[
"compress_gain3",
8.2
],
[
"compress_ratio3",
3.5
],
[
"compress_threshold3",
-11.7
],
[
"compress_release3",
180.0
],
[
"compress_attack3",
250.0
],
[
"compress_frequency3",
2270.0
],
[
"compress_gain2",
7.4
],
[
"compress_ratio2",
3.9
],
[
"compress_threshold2",
-11.5
],
[
"compress_release2",
190.0
],
[
"compress_attack2",
250.0
],
[
"compress_frequency2",
1920.0
],
[
"compress_gain1",
11.1
],
[
"compress_ratio1",
3.4
],
[
"compress_threshold1",
-12.7
],
[
"compress_release1",
170.0
],
[
"compress_attack1",
220.0
],
[
"compress_frequency1",
650.0
],
[
"compress_gain0",
16.0
],
[
"compress_ratio0",
3.2
],
[
"compress_threshold0",
-15.3
],
[
"compress_release0",
200.0
],
[
"compress_attack0",
90.0
],
[
"compress_frequency0",
110.0
],
[
"compress_wet",
1.0
],
[
"main_volume",
1.8
],
[
"g",
9.5
],
[
"f",
64.2
]
]
}
-195
View File
@@ -1,195 +0,0 @@
{
"string": [],
"bool": [ [ "Skip track", false ], [ "Going Live!", false ] ],
"int": [],
"float": [
[
"mic_volume",
0.0
],
[
"compress_gain6",
0.1
],
[
"compress_ratio6",
7.9
],
[
"compress_threshold6",
-15.8
],
[
"compress_release6",
30.0
],
[
"compress_attack6",
30.0
],
[
"compress_frequency6",
18610.0
],
[
"compress_gain5",
5.4
],
[
"compress_ratio5",
4.8
],
[
"compress_threshold5",
-13.6
],
[
"compress_release5",
170.0
],
[
"compress_attack5",
160.0
],
[
"compress_frequency5",
13950.0
],
[
"compress_gain4",
6.5
],
[
"compress_ratio4",
4.0
],
[
"compress_threshold4",
-12.2
],
[
"compress_release4",
180.0
],
[
"compress_attack4",
200.0
],
[
"compress_frequency4",
3890.0
],
[
"compress_gain3",
8.2
],
[
"compress_ratio3",
3.5
],
[
"compress_threshold3",
-11.7
],
[
"compress_release3",
180.0
],
[
"compress_attack3",
250.0
],
[
"compress_frequency3",
2270.0
],
[
"compress_gain2",
7.4
],
[
"compress_ratio2",
3.9
],
[
"compress_threshold2",
-11.5
],
[
"compress_release2",
190.0
],
[
"compress_attack2",
250.0
],
[
"compress_frequency2",
1920.0
],
[
"compress_gain1",
11.1
],
[
"compress_ratio1",
3.4
],
[
"compress_threshold1",
-12.7
],
[
"compress_release1",
170.0
],
[
"compress_attack1",
220.0
],
[
"compress_frequency1",
650.0
],
[
"compress_gain0",
16.0
],
[
"compress_ratio0",
3.2
],
[
"compress_threshold0",
-15.3
],
[
"compress_release0",
200.0
],
[
"compress_attack0",
90.0
],
[
"compress_frequency0",
110.0
],
[
"compress_wet",
1.0
],
[
"main_volume",
1.8
],
[
"g",
9.5
],
[
"f",
64.2
]
]
}
-195
View File
@@ -1,195 +0,0 @@
{
"string": [],
"bool": [ [ "Skip track", false ], [ "Going Live!", false ] ],
"int": [],
"float": [
[
"mic_volume",
0.0
],
[
"compress_gain6",
0.1
],
[
"compress_ratio6",
7.9
],
[
"compress_threshold6",
-15.8
],
[
"compress_release6",
30.0
],
[
"compress_attack6",
30.0
],
[
"compress_frequency6",
18610.0
],
[
"compress_gain5",
5.4
],
[
"compress_ratio5",
4.8
],
[
"compress_threshold5",
-13.6
],
[
"compress_release5",
170.0
],
[
"compress_attack5",
160.0
],
[
"compress_frequency5",
13950.0
],
[
"compress_gain4",
6.5
],
[
"compress_ratio4",
4.0
],
[
"compress_threshold4",
-12.2
],
[
"compress_release4",
180.0
],
[
"compress_attack4",
200.0
],
[
"compress_frequency4",
3890.0
],
[
"compress_gain3",
8.2
],
[
"compress_ratio3",
3.5
],
[
"compress_threshold3",
-11.7
],
[
"compress_release3",
180.0
],
[
"compress_attack3",
250.0
],
[
"compress_frequency3",
2270.0
],
[
"compress_gain2",
7.4
],
[
"compress_ratio2",
3.9
],
[
"compress_threshold2",
-11.5
],
[
"compress_release2",
190.0
],
[
"compress_attack2",
250.0
],
[
"compress_frequency2",
1920.0
],
[
"compress_gain1",
11.1
],
[
"compress_ratio1",
3.4
],
[
"compress_threshold1",
-12.7
],
[
"compress_release1",
170.0
],
[
"compress_attack1",
220.0
],
[
"compress_frequency1",
650.0
],
[
"compress_gain0",
16.0
],
[
"compress_ratio0",
3.2
],
[
"compress_threshold0",
-15.3
],
[
"compress_release0",
200.0
],
[
"compress_attack0",
90.0
],
[
"compress_frequency0",
110.0
],
[
"compress_wet",
1.0
],
[
"main_volume",
1.8
],
[
"g",
4.8
],
[
"f",
64.2
]
]
}
-195
View File
@@ -1,195 +0,0 @@
{
"string": [],
"bool": [ [ "Skip track", false ], [ "Going Live!", false ] ],
"int": [],
"float": [
[
"mic_volume",
0.0
],
[
"compress_gain6",
0.1
],
[
"compress_ratio6",
7.9
],
[
"compress_threshold6",
-15.8
],
[
"compress_release6",
30.0
],
[
"compress_attack6",
30.0
],
[
"compress_frequency6",
18610.0
],
[
"compress_gain5",
5.4
],
[
"compress_ratio5",
4.8
],
[
"compress_threshold5",
-13.6
],
[
"compress_release5",
170.0
],
[
"compress_attack5",
160.0
],
[
"compress_frequency5",
13950.0
],
[
"compress_gain4",
6.5
],
[
"compress_ratio4",
4.0
],
[
"compress_threshold4",
-12.2
],
[
"compress_release4",
180.0
],
[
"compress_attack4",
200.0
],
[
"compress_frequency4",
3890.0
],
[
"compress_gain3",
8.2
],
[
"compress_ratio3",
3.5
],
[
"compress_threshold3",
-11.7
],
[
"compress_release3",
180.0
],
[
"compress_attack3",
250.0
],
[
"compress_frequency3",
2270.0
],
[
"compress_gain2",
7.4
],
[
"compress_ratio2",
3.9
],
[
"compress_threshold2",
-11.5
],
[
"compress_release2",
190.0
],
[
"compress_attack2",
250.0
],
[
"compress_frequency2",
1920.0
],
[
"compress_gain1",
10.0
],
[
"compress_ratio1",
3.4
],
[
"compress_threshold1",
-12.7
],
[
"compress_release1",
170.0
],
[
"compress_attack1",
220.0
],
[
"compress_frequency1",
650.0
],
[
"compress_gain0",
12.4
],
[
"compress_ratio0",
3.2
],
[
"compress_threshold0",
-15.3
],
[
"compress_release0",
200.0
],
[
"compress_attack0",
90.0
],
[
"compress_frequency0",
110.0
],
[
"compress_wet",
1.0
],
[
"main_volume",
1.8
],
[
"g",
4.8
],
[
"f",
64.2
]
]
}
-195
View File
@@ -1,195 +0,0 @@
{
"string": [],
"bool": [ [ "Skip track", false ], [ "Going Live!", false ] ],
"int": [],
"float": [
[
"mic_volume",
0.0
],
[
"compress_gain6",
0.1
],
[
"compress_ratio6",
7.9
],
[
"compress_threshold6",
-15.8
],
[
"compress_release6",
30.0
],
[
"compress_attack6",
30.0
],
[
"compress_frequency6",
18610.0
],
[
"compress_gain5",
5.4
],
[
"compress_ratio5",
4.8
],
[
"compress_threshold5",
-13.6
],
[
"compress_release5",
170.0
],
[
"compress_attack5",
160.0
],
[
"compress_frequency5",
13950.0
],
[
"compress_gain4",
6.5
],
[
"compress_ratio4",
4.0
],
[
"compress_threshold4",
-12.2
],
[
"compress_release4",
180.0
],
[
"compress_attack4",
200.0
],
[
"compress_frequency4",
3890.0
],
[
"compress_gain3",
5.5
],
[
"compress_ratio3",
3.5
],
[
"compress_threshold3",
-11.7
],
[
"compress_release3",
180.0
],
[
"compress_attack3",
250.0
],
[
"compress_frequency3",
2270.0
],
[
"compress_gain2",
3.3
],
[
"compress_ratio2",
3.9
],
[
"compress_threshold2",
-11.5
],
[
"compress_release2",
190.0
],
[
"compress_attack2",
250.0
],
[
"compress_frequency2",
1920.0
],
[
"compress_gain1",
5.6
],
[
"compress_ratio1",
3.4
],
[
"compress_threshold1",
-12.7
],
[
"compress_release1",
170.0
],
[
"compress_attack1",
220.0
],
[
"compress_frequency1",
650.0
],
[
"compress_gain0",
7.5
],
[
"compress_ratio0",
3.2
],
[
"compress_threshold0",
-15.3
],
[
"compress_release0",
200.0
],
[
"compress_attack0",
90.0
],
[
"compress_frequency0",
110.0
],
[
"compress_wet",
1.0
],
[
"main_volume",
1.8
],
[
"g",
0.6
],
[
"f",
64.2
]
]
}
-195
View File
@@ -1,195 +0,0 @@
{
"string": [],
"bool": [ [ "Skip track", false ], [ "Going Live!", false ] ],
"int": [],
"float": [
[
"mic_volume",
0.0
],
[
"compress_gain6",
0.1
],
[
"compress_ratio6",
7.9
],
[
"compress_threshold6",
-15.8
],
[
"compress_release6",
30.0
],
[
"compress_attack6",
30.0
],
[
"compress_frequency6",
18610.0
],
[
"compress_gain5",
5.4
],
[
"compress_ratio5",
4.8
],
[
"compress_threshold5",
-13.6
],
[
"compress_release5",
120.0
],
[
"compress_attack5",
160.0
],
[
"compress_frequency5",
13950.0
],
[
"compress_gain4",
6.5
],
[
"compress_ratio4",
4.0
],
[
"compress_threshold4",
-12.2
],
[
"compress_release4",
130.0
],
[
"compress_attack4",
200.0
],
[
"compress_frequency4",
3890.0
],
[
"compress_gain3",
5.5
],
[
"compress_ratio3",
3.5
],
[
"compress_threshold3",
-11.7
],
[
"compress_release3",
140.0
],
[
"compress_attack3",
250.0
],
[
"compress_frequency3",
2270.0
],
[
"compress_gain2",
3.3
],
[
"compress_ratio2",
3.9
],
[
"compress_threshold2",
-11.5
],
[
"compress_release2",
120.0
],
[
"compress_attack2",
250.0
],
[
"compress_frequency2",
1920.0
],
[
"compress_gain1",
5.6
],
[
"compress_ratio1",
3.4
],
[
"compress_threshold1",
-12.2
],
[
"compress_release1",
120.0
],
[
"compress_attack1",
220.0
],
[
"compress_frequency1",
650.0
],
[
"compress_gain0",
7.5
],
[
"compress_ratio0",
3.2
],
[
"compress_threshold0",
-13.1
],
[
"compress_release0",
110.0
],
[
"compress_attack0",
140.0
],
[
"compress_frequency0",
110.0
],
[
"compress_wet",
1.0
],
[
"main_volume",
1.8
],
[
"g",
0.6
],
[
"f",
64.2
]
]
}
-195
View File
@@ -1,195 +0,0 @@
{
"string": [],
"bool": [ [ "Skip track", false ], [ "Going Live!", false ] ],
"int": [],
"float": [
[
"mic_volume",
0.0
],
[
"compress_gain6",
0.1
],
[
"compress_ratio6",
7.9
],
[
"compress_threshold6",
-15.8
],
[
"compress_release6",
30.0
],
[
"compress_attack6",
30.0
],
[
"compress_frequency6",
18610.0
],
[
"compress_gain5",
5.4
],
[
"compress_ratio5",
4.8
],
[
"compress_threshold5",
-13.6
],
[
"compress_release5",
120.0
],
[
"compress_attack5",
160.0
],
[
"compress_frequency5",
13950.0
],
[
"compress_gain4",
6.5
],
[
"compress_ratio4",
4.0
],
[
"compress_threshold4",
-12.2
],
[
"compress_release4",
130.0
],
[
"compress_attack4",
200.0
],
[
"compress_frequency4",
3890.0
],
[
"compress_gain3",
5.5
],
[
"compress_ratio3",
3.5
],
[
"compress_threshold3",
-11.7
],
[
"compress_release3",
140.0
],
[
"compress_attack3",
250.0
],
[
"compress_frequency3",
2270.0
],
[
"compress_gain2",
3.3
],
[
"compress_ratio2",
3.9
],
[
"compress_threshold2",
-11.5
],
[
"compress_release2",
120.0
],
[
"compress_attack2",
250.0
],
[
"compress_frequency2",
1920.0
],
[
"compress_gain1",
5.6
],
[
"compress_ratio1",
3.4
],
[
"compress_threshold1",
-12.2
],
[
"compress_release1",
120.0
],
[
"compress_attack1",
220.0
],
[
"compress_frequency1",
650.0
],
[
"compress_gain0",
7.5
],
[
"compress_ratio0",
3.2
],
[
"compress_threshold0",
-13.1
],
[
"compress_release0",
110.0
],
[
"compress_attack0",
140.0
],
[
"compress_frequency0",
110.0
],
[
"compress_wet",
1.0
],
[
"main_volume",
1.8
],
[
"g",
0.6
],
[
"f",
124.0
]
]
}
-195
View File
@@ -1,195 +0,0 @@
{
"string": [],
"bool": [ [ "Skip track", false ], [ "Going Live!", false ] ],
"int": [],
"float": [
[
"mic_volume",
0.0
],
[
"compress_gain6",
0.1
],
[
"compress_ratio6",
7.9
],
[
"compress_threshold6",
-15.8
],
[
"compress_release6",
30.0
],
[
"compress_attack6",
30.0
],
[
"compress_frequency6",
18610.0
],
[
"compress_gain5",
5.4
],
[
"compress_ratio5",
4.8
],
[
"compress_threshold5",
-13.6
],
[
"compress_release5",
120.0
],
[
"compress_attack5",
160.0
],
[
"compress_frequency5",
13950.0
],
[
"compress_gain4",
6.5
],
[
"compress_ratio4",
4.0
],
[
"compress_threshold4",
-12.2
],
[
"compress_release4",
130.0
],
[
"compress_attack4",
200.0
],
[
"compress_frequency4",
3890.0
],
[
"compress_gain3",
5.5
],
[
"compress_ratio3",
3.5
],
[
"compress_threshold3",
-11.7
],
[
"compress_release3",
140.0
],
[
"compress_attack3",
250.0
],
[
"compress_frequency3",
2270.0
],
[
"compress_gain2",
3.3
],
[
"compress_ratio2",
3.9
],
[
"compress_threshold2",
-11.5
],
[
"compress_release2",
120.0
],
[
"compress_attack2",
250.0
],
[
"compress_frequency2",
1920.0
],
[
"compress_gain1",
5.6
],
[
"compress_ratio1",
3.4
],
[
"compress_threshold1",
-12.2
],
[
"compress_release1",
120.0
],
[
"compress_attack1",
220.0
],
[
"compress_frequency1",
650.0
],
[
"compress_gain0",
7.5
],
[
"compress_ratio0",
3.2
],
[
"compress_threshold0",
-13.1
],
[
"compress_release0",
110.0
],
[
"compress_attack0",
140.0
],
[
"compress_frequency0",
110.0
],
[
"compress_wet",
1.0
],
[
"main_volume",
1.8
],
[
"g",
1.0
],
[
"f",
106.4
]
]
}
File diff suppressed because it is too large Load Diff
-629
View File
@@ -1,629 +0,0 @@
"""
The provided Python script sets up a Flask web server to manage a list of music files, with
functions for rescanning the music folder, updating the music list, and serving the music list via
API endpoints.
"""
import json
import logging
import os
import random
import re
import threading
import time
# from flask_autoindex import AutoIndex
from datetime import datetime
from logging import handlers
from pathlib import Path
from platform import uname
from sys import platform
import requests
from flask import (
Flask,
jsonify,
redirect,
render_template,
request,
send_from_directory,
)
from waitress import serve
import media_search_functions
MAIN_BOT_ADDRESS = "http://192.168.1.31:5000"
MUSIC_TRACKER = "/prepped_tracks"
HOST_ADDRESS = "192.168.1.12"
PORT_ADDRESS = 5000
if platform in ("linux", "linux2"):
SEPARATOR_FILE_PATH = "/"
if "microsoft-standard" in uname().release:
LOGFILE = "/home/mtuszowski/conjurer/discord_mus_service.log"
MUSIC_FOLDER = "/mnt/g/Muzyka/"
NETRC_FILE = "/home/mtuszowski/.netrc"
LOGSTORE = "/home/mtuszowski/conjurer/logs/"
ENCODING = "utf-8"
RADIOLOG_PATH = "/home/pi/Conjurer/radio_log.log"
PERSISTENCE_PATH = "/home/pi/Conjurer/persistence.log"
else:
LOGFILE = "/home/pi/Conjurer/discord_mus_service.log"
NETRC_FILE = "/home/pi/.netrc"
LOGSTORE = "/home/pi/MediaFolder/logs/"
ENCODING = "utf-8"
MUSIC_FOLDER = "/home/pi/MediaFolder/mp3/"
PRIORITY_FOLDER = "/home/pi/MediaFoldermp3/Magiczne i chuj/"
RADIOLOG_PATH = "/home/pi/Conjurer/radio_log.log"
PERSISTENCE_PATH = "/home/pi/Conjurer/persistence.log"
random.seed()
music_file_list = []
priority_list = []
def rescan():
"""
The `rescan` function logs a message, scans for mp3 files in a specified folder,
and adds them to a list of music files.
"""
logger = logging.getLogger("conjurer_musician")
logger.info("Rescan triggered")
for mp3_item in Path.glob(Path(MUSIC_FOLDER), "**/*.mp3"):
temp_music_file = mp3_item.as_posix()
if platform == "win32":
temp_music_file = temp_music_file.replace("/", "\\")
music_file_list.append(temp_music_file)
for mp3_item in Path.glob(Path(PRIORITY_FOLDER), "**/*.mp3"):
temp_music_file = mp3_item.as_posix()
if platform == "win32":
temp_music_file = temp_music_file.replace("/", "\\")
priority_list.append(temp_music_file)
with open(
"/home/pi/Conjurer/all_playlist.playlist", "w", encoding="utf-8"
) as w_file:
try:
for item in music_file_list:
w_file.write(item)
w_file.write("\n")
except json.JSONDecodeError:
pass
with open("/home/pi/Conjurer/hit.playlist", "w", encoding="utf-8") as w_file:
try:
for item in priority_list:
w_file.write(item)
w_file.write("\n")
except json.JSONDecodeError:
pass
def thread_rescan():
"""
The `thread_rescan` function periodically triggers a rescan operation after a specified time
interval.
"""
logger = logging.getLogger("conjurer_musician")
logger.info("Starting filesystemupdater")
while True:
time.sleep(60 * 60 * 24)
logger.info("Rescan triggered")
rescan()
def scan_tracks():
# Set the filename and open the file
logger = logging.getLogger("conjurer_musician")
file = open(RADIOLOG_PATH, "r")
# Find the size of the file and move to the end
st_results = os.stat(RADIOLOG_PATH)
st_size = st_results[6]
file.seek(st_size)
st_results1 = os.stat(PERSISTENCE_PATH)
prev_st_size1 = st_results[6]
while 1:
st_results1 = os.stat(PERSISTENCE_PATH)
st_size1 = st_results1[6]
if prev_st_size1 != st_size1:
while prev_st_size1 != st_size1:
prev_st_size1 = st_size1
st_results1 = os.stat(PERSISTENCE_PATH)
st_size1 = st_results1[6]
time.sleep(0.1)
file1 = open(PERSISTENCE_PATH, "r")
lines = file1.readlines()
result = ["next", lines[2]]
file1.close()
returned = requests.post(
f"{MAIN_BOT_ADDRESS}{MUSIC_TRACKER}", json=result, timeout=360
)
logger.info("SENT")
logger.info(returned.status_code)
logger.info("SEND CONFIRMED")
where = file.tell()
line = file.readline()
if not line:
time.sleep(1)
file.seek(where)
else:
if re.match(".*Prepared.*", line):
result = None
if re.match(".*jingles.*", line):
logger.info("jingles")
logger.info(line) # already has newline
result = ["jingles", line]
elif re.match(".*priority.*", line):
logger.info("priority")
logger.info(line) # already has newline
result = ["priority", line]
elif re.match(".*hit.*", line):
logger.info("hit")
logger.info(line) # already has newline
result = ["hit", line]
elif re.match(".*all_playlist.*", line):
logger.info("all")
logger.info(line) # already has newline
result = ["all", line]
elif re.match(".*request.*", line):
logger.info("requests")
logger.info(line) # already has newline
result = ["requests", line]
if result:
returned = requests.post(
f"{MAIN_BOT_ADDRESS}{MUSIC_TRACKER}", json=result, timeout=360
)
logger.info("SENT")
logger.info(returned.status_code)
logger.info("SEND CONFIRMED")
time.sleep(0.1)
app = Flask(__name__)
# AutoIndex(app, browse_root="/")
# TODO: Odpalić wyszukiwarki w wątkach i dopiero po wszystkim zsumować wyszukiwanie.
def wyszukaj(word_list, how_many, _logger=None, return_to_bot=True):
"""
Searches for music files based on a list of keywords and returns a list of matching files.
Args:
word_list (list): A list of keywords to search for.
how_many (int): The maximum number of matching files to return.
Returns:
list: A list of matching files, sorted by their search weight.
"""
if _logger is None:
fun_logger = logging.getLogger()
else:
fun_logger = _logger
return_list = []
search_weight = []
for _ in range(len(music_file_list)):
search_weight.append((0, ""))
time_start = datetime.now()
if int(how_many) > 0:
skip_start = 2
else:
skip_start = 1
for word in word_list[skip_start:]:
token_weight = len(word)
fun_logger.info("Słowo kluczowe: %s", word)
itr = 0
for file in music_file_list:
file = file.split(SEPARATOR_FILE_PATH)
char_remove = [
".",
"^",
"$",
"*",
"+",
"?",
"{",
"}",
"[",
"]",
"\\",
"/",
"|",
"(",
")",
"!",
",",
"-",
":",
"mp3",
]
all_words = []
for f_iter in file:
for char in char_remove:
f_iter = remove_characters(f_iter, char)
tmp = f_iter.split()
all_words.extend(tmp)
pingu = 1
pattern_len = len(all_words)
if platform == "win32":
skip = 2
else:
skip = 4
matched_times = 1
# TODO: To do wątków albo for asynchroniczny
for itm in all_words[skip:]:
pingu += 1
pattern = ".*" + word + ".*"
if re.match(pattern, itm, re.IGNORECASE):
temp_weight = (
search_weight[itr][0]
+ (token_weight + (pingu**1.5) / pattern_len) / matched_times
)
search_weight[itr] = (
temp_weight,
music_file_list[itr],
)
matched_times += 1
itr += 1
fun_logger.info(
"Stworzylem tablice wag zajęło mi to %s", datetime.now() - time_start
)
time_start = datetime.now()
item_to_search = max_weight(search_weight)
itr = 0
if item_to_search == 0:
return []
not_found = True
return_list = []
if int(how_many) <= 0:
fun_logger.info("Jeden plik do zagrania")
while not_found:
if search_weight[itr][0] == item_to_search:
return_list.append(search_weight[itr])
if not return_to_bot:
with open(
"/home/pi/Conjurer/priority_queue.playlist",
"r+",
encoding="utf-8",
) as s_file:
s_file.write(search_weight[itr][1])
break
itr += 1
else:
fun_logger.info("Wiele plików do zagrania")
search_weight.sort(key=lambda x: x[0], reverse=True)
return_list.extend(search_weight[: int(how_many)])
fun_logger.info("Done: %s", return_list)
return return_list
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
def remove_characters(string, character):
"""
The `remove_characters` function removes all occurrences of a specified character from a given
string.
:param string: The string parameter is the input string from which characters will be removed
:param character: The character parameter is the character that you want to remove from the string
:return: a new string where all occurrences of the specified character have been removed.
"""
return string.replace(character, "")
@app.route('/get_share_list', methods=['POST'])
def get_share_list():
data = request.get_json()
entries = data.get('entries')
keywords = data.get('keywords')
# Validate entries
if not isinstance(entries, int) or not (1 <= entries <= 10):
return jsonify({'error': '"entries" must be an integer between 1 and 10.'}), 400
# Validate keywords list
if not isinstance(keywords, list) or not all(isinstance(k, str) for k in keywords):
return jsonify({'error': '"keywords" must be a list of strings.'}), 400
# Call external search
files = media_search_functions.find_matches(entries, keywords)
# Return each file path as a JSON list
return jsonify({'files': files}), 200
@app.route('/get_share_links', methods=['POST'])
def get_share_links():
data = request.get_json()
file_paths = data.get('file_paths')
# Validate file_paths list
if not isinstance(file_paths, list) or not all(isinstance(p, str) for p in file_paths):
return jsonify({'error': '"file_paths" must be a list of strings.'}), 400
# Call external publish
links = media_search_functions.publish(file_paths)
# Return list of published links
return jsonify({'links': links}), 200
@app.route("/stream", methods=["GET"])
def stream_music():
"""
The function `stream_music` is a route handler for the "/stream" endpoint.
It returns a JSON response containing a key "music_file_list" with the value of the variable `music_file_list`.
:return: A JSON response containing a key "music_file_list" with the value of the variable `music_file_list`.
"""
# return send_from_directory("/tmp/hls", "stream.m3u8")
return render_template("/home/pi/Conjurer/stream.html")
@app.route("/<string:file_name>")
def stream(file_name):
"""
Stream the specified file from the video directory.
Args:
file_name (str): The name of the file to be streamed.
Returns:
Response: The response containing the streamed file.
"""
# trunk-ignore(bandit/B108)
video_dir = "/tmp/hls"
return send_from_directory(video_dir, file_name)
@app.route("/stream_mp3", methods=["GET"])
def stream_music_mp3():
"""
The function `stream_music_mp3` is a route handler for the "/stream_mp3" endpoint.
It redirects the user to the URL "http://www.example.com" with a status code of 302.
:return: A redirect response to "http://www.example.com" with a status code of 302.
"""
return redirect("http://www.example.com", code=302)
@app.route("/clear_pr_pls", methods=["GET"])
def clear_pr_pls():
"""
The function `clear_pr_pls` clears the contents of the priority queue playlist file.
:return: A JSON response indicating the success of the operation.
"""
app.logger.info("CLEARING PLAYLIST")
with open(
"/home/pi/Conjurer/priority_queue.playlist", "w", encoding="utf-8"
) as cleared_pl:
cleared_pl.write("")
return_data = jsonify(isError=False, message="Success", statusCode=200, data=[])
return return_data, 200
@app.route("/mp3", methods=["GET"])
def get_music_list():
"""
The function `get_music_list` returns a JSON object containing a list of music files.
:return: A JSON response containing a key "music_file_list" with the value of the variable
`music_file_list`.
"""
return jsonify({"music_file_list": music_file_list})
@app.route("/update_mp3", methods=["POST"])
def update_music_list():
"""
The function `update_music_list` receives a POST request with a JSON payload, logs the received
item, adds it to a music file list, and returns a success message along with the updated record.
:return: The function `update_music_list` is returning a tuple containing a JSON response and a
status code. The JSON response includes keys `isError`, `message`, `statusCode`, and `data`,
with values indicating the success of the operation and the data that was
received and added to the `music_file_list`.
The status code returned is 200, indicating a successful response.
"""
record = json.loads(request.data)
app.logger.info(record["item"])
music_file_list.append(record["item"])
return_data = (
jsonify(isError=False, message="Success", statusCode=200, data=record),
200,
)
return return_data
@app.route("/get_music", methods=["POST"])
def look_for_playlist():
"""
The function `look_for_playlist` receives a POST request with a JSON payload, logs the received
item, adds it to a music file list, and returns a success message along with the updated record.
:return: A tuple containing a JSON response and a status code. The JSON response includes keys `isError`,
`message`, `statusCode`, and `data`, with values indicating the success of the operation and the
data that was received and added to the `music_file_list`. The status code returned is 200,
indicating a successful response.
"""
record = json.loads(request.data)
app.logger.info(record)
app.logger.info(record["lista_slow"])
app.logger.info(record["UUID"])
app.logger.info(record["dlugosc_plejlisty"])
return_data = wyszukaj(
record["lista_slow"], record["dlugosc_plejlisty"], app.logger, True
)
return_data = (
jsonify(isError=False, message="Success", statusCode=200, data=return_data),
200,
)
return return_data
@app.route("/request_radio_file", methods=["POST"])
def add_request():
record = json.loads(request.data)
app.logger.info(record)
app.logger.info(record["lista_slow"])
app.logger.info(record["UUID"])
return_data = wyszukaj(record["lista_slow"], 0, app.logger, False)
with open("/home/pi/Conjurer/request.playlist", "a", encoding="utf-8") as s_file:
for item in return_data:
s_file.write(item[1] + "\n")
return_data = (
jsonify(
isError=False, message="Success", statusCode=200, data={"status": "OK"}
),
200,
)
return return_data
@app.route("/create_priority_playlist", methods=["POST"])
def create_priority_playlist():
"""
The function `create_priority_playlist` receives a POST request with a JSON payload, logs the received
item, adds it to a music file list, and returns a success message along with the updated record.
:return: A tuple containing a JSON response and a status code.
The JSON response includes keys `isError`,
`message`, `statusCode`, and `data`, with values
indicating the success of the operation and the
data that was received and added to the `music_file_list`.
The status code returned is 200,indicating a successful response.
"""
record = json.loads(request.data)
app.logger.info(record)
app.logger.info(record["lista_slow"])
app.logger.info(record["UUID"])
app.logger.info(record["dlugosc_plejlisty"])
return_data = wyszukaj(
record["lista_slow"], record["dlugosc_plejlisty"], app.logger, False
)
random.shuffle(return_data)
with open("/home/pi/Conjurer/request.playlist", "a", encoding="utf-8") as s_file:
for item in return_data:
s_file.write(item[1] + "\n")
return_data = (
jsonify(
isError=False, message="Success", statusCode=200, data={"status": "OK"}
),
200,
)
return return_data
@app.route("/add_to_priority", methods=["POST"])
def add_to_priority():
"""
The function `add_to_priority` receives a POST request with a JSON payload, logs the received
item, adds it to a music file list, and returns a success message along with the updated record.
:return: A tuple containing a JSON response and a status code.
The JSON response includes keys `isError`,
`message`, `statusCode`, and `data`, with values
indicating the success of the operation and the
data that was received and added to the `music_file_list`.
The status code returned is 200,indicating a successful response.
"""
record = json.loads(request.data)
app.logger.info(record)
app.logger.info(record["lista_slow"])
app.logger.info(record["UUID"])
app.logger.info(record["dlugosc_plejlisty"])
return_data = wyszukaj(
record["lista_slow"], record["dlugosc_plejlisty"], app.logger, False
)
with open(
"/home/pi/Conjurer/priority_queue.playlist", "a", encoding="utf-8"
) as s_file:
for item in return_data:
s_file.write(item[1] + "\n")
return_data = (
jsonify(
isError=False, message="Success", statusCode=200, data={"status": "OK"}
),
200,
)
return return_data
def flask_debug():
"""
The `flask_debug` function starts a Flask application in debug mode without using the reloader.
Do not use for production for fucks sake.
"""
# trunk-ignore(bandit/B201)
app.run(debug=True, use_reloader=False, host=HOST_ADDRESS, port=PORT_ADDRESS)
def waitress_run():
"""
The `waitress_run` function serves the `app` on host HOST_ADDRESS
and port 5000 using the Waitress WSGI server.
This function starts the Waitress server and listens for incoming requests
on the specified host and port. It uses the `serve` function from the Waitress
library to handle the serving process.
Parameters:
None
Returns:
None
"""
serve(app, host=HOST_ADDRESS, port=PORT_ADDRESS)
if __name__ == "__main__":
logger = logging.getLogger("conjurer_musician")
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
handler = handlers.RotatingFileHandler(
filename=LOGFILE,
encoding=ENCODING,
mode="a",
maxBytes=6 * 1024 * 1024,
backupCount=6,
)
handler.setFormatter(formatter)
logger.addHandler(handler)
rescan()
logger.info("Started")
threads = []
# threads.append(threading.Thread(target=flask_debug))
threads.append(threading.Thread(target=waitress_run))
threads.append(threading.Thread(target=thread_rescan))
for worker in threads:
worker.start()
time.sleep(60)
threads.append(threading.Thread(target=scan_tracks))
threads[2].start()
for worker in threads:
worker.join()
File diff suppressed because it is too large Load Diff
View File
-3
View File
@@ -1,3 +0,0 @@
{
"password" : "RadioHardkor123#!"
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-8
View File
@@ -1,8 +0,0 @@
jingiel2.mp3
jingiel3.mp3
jingiel4.mp3
jingiel.mp3
/home/pi/MediaFolder/mp3/Youtube/Pine Tree Riots - We'll Have Our Home Again [ctpfRxvC0JQ].mp3
/home/pi/MediaFolder/mp3/2024 Jan-Mar/Rave The Reqviem - Oh, the Joy!.mp3
/home/pi/MediaFolder/mp3/2022 Aug-Oct/Wil Farr - Keep Your Rifle by Your Side.mp3
/home/pi/MediaFolder/mp3/2022 Jan-Mar/The Hope County Choir - Keep Your Rifle by Your Side - Choir Version.mp3
-52
View File
@@ -1,52 +0,0 @@
#!/usr/bin/env python3
import argparse
import json
import os
import sys
import uuid
from pathlib import Path
# CONFIGURATION
JSON_DB = '/var/log/share_scan.json'
SHARE_DIR = Path('/var/www/html/share')
BASE_URL = 'https://czernobog.pl/share'
# Ensure share directory exists
SHARE_DIR.mkdir(parents=True, exist_ok=True)
def load_db():
with open(JSON_DB) as f:
return json.load(f)['entries']
ENTRIES = load_db()
def relevancy(path, keywords):
score = 0
low = path.lower()
for kw in keywords:
if kw.lower() in low:
score += low.count(kw.lower())
return score
def find_matches(count, keywords):
scored = []
for e in ENTRIES:
score = relevancy(e['path'], keywords)
if score > 0:
scored.append((score, e['path']))
scored.sort(reverse=True, key=lambda x: x[0])
result = [p for _, p in scored]
return result[:count]
def publish(paths):
urls = []
for path in paths:
token = uuid.uuid4().hex
link = SHARE_DIR / token
try:
os.symlink(path, link)
except FileExistsError:
pass
urls.append(f"{BASE_URL}/{token}")
return urls
View File
-8
View File
@@ -1,8 +0,0 @@
/home/pi/MediaFolder/mp3/Youtube/POWER HOUR 2022 Defqon.1 Weekend Festival Sixty minutes of pure insanity [fX1kUoeUhPg].mp3
/home/pi/MediaFolder/mp3/Youtube/POWER HOUR 2023 Defqon.1 Weekend Festival This is Madness [A7thBilOLFU].mp3
/home/pi/MediaFolder/mp3/Youtube/POWER HOUR Defqon.1 2024 [jXBtF_QBBI0].mp3
/home/pi/MediaFolder/mp3/Youtube/POWERWOLF - Thunderpriest (Official Lyric Video) [3WzC_1eWoKE].mp3
/home/pi/MediaFolder/mp3/Youtube/Defqon.1 Weekend Festival 2015 POWER HOUR [npSqR01ly9g].mp3
/home/pi/MediaFolder/mp3/Youtube/Defqon.1 Weekend Festival 2017 POWER HOUR [8g9z25yA8dA].mp3
/home/pi/MediaFolder/mp3/Youtube/Defqon.1 Weekend Festival 2018 POWER HOUR [QdGz0OHQ9S8].mp3
/home/pi/MediaFolder/mp3/Youtube/Defqon.1 Weekend Festival 2019 POWER HOUR [vJ2eHsQv7Ac].mp3
-541
View File
@@ -1,541 +0,0 @@
/home/pi/MediaFolder/mp3/Muzyka/2016/Funker Vogt/Funker Vogt - Words Of Power (Grubotronit)/Funker Vogt - Words of Power - 04 - Words of Power (Power mix).mp3halen_cover)-radial.mp3pi/MediaFolder/mp3/2021 Selection/Epica - Beyond the Matrix.mp3
/home/pi/MediaFolder/mp3/2021 Selection/Epica - Crimson Bow and Arrow.mp3
/home/pi/MediaFolder/mp3/2021 Selection/Epica - Edge of the Blade.mp3
/home/pi/MediaFolder/mp3/2021 Selection/Epica - Gaia.mp3
/home/pi/MediaFolder/mp3/2021 Selection/Epica - Sensorium.mp3
/home/pi/MediaFolder/mp3/2021 Selection/Epica - The Essence of Silence.mp3
/home/pi/MediaFolder/mp3/2021 Selection/Epica - The Skeleton Key.mp3
/home/pi/MediaFolder/mp3/2021 Selection/Epica - Unchain Utopia - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2021 Selection/Epica - Universal Death Squad.mp3
/home/pi/MediaFolder/mp3/2021 Selection/Epica - Universal Love Squad.mp3
/home/pi/MediaFolder/mp3/2022 Apr-Jul/Epica - Beyond the Matrix - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2022 Apr-Jul/Epica - Kingdom of Heaven, Pt. 3 - The Antediluvian Universe - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2022 Apr-Jul/Epica - Rivers - A Capella - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2022 Jan-Mar/Epica - Beyond the Matrix - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2022 Jan-Mar/Epica - Kingdom of Heaven, Pt. 3 - The Antediluvian Universe - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2022 Jan-Mar/Epica - Rivers - A Capella - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2022 Jan-Mar/Epica - Sacred & Wild.mp3
/home/pi/MediaFolder/mp3/2022 Jan-Mar/Epica - The Last Crusade - A New Age Dawns 1.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Freedom - The Wolves Within -.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Abyss O'Time.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Abyss of Time - Countdown to Singularity -.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Crimson Bow and Arrow - Instrumental.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Crystal Mountain - Live At Paradiso.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Dedicate Your Heart! - Instrumental.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - El Código Vital.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Martyr of the Free Word.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Never Enough.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Omegacoustic.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Rivers - A Capella.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Rivers.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Storm the Sorrow.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - The Skeleton Key.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Unchain Utopia - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Unchain Utopia.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Unleashed - Live At The AFAS Live.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Unleashed.mp3
/home/pi/MediaFolder/mp3/2023 Apr-Jul/Epica - Wheel of Destiny.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Design Your Universe - Live.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Omega - Sovereign of the Sun Spheres -.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Abyss O'Time.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Abyss of Time - Countdown to Singularity - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Battle of the Heroes & Imperial March - Live.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Burn to a Cinder.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Chasing the Dragon - Live.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Cry for the Moon (The Embrace That Smothers , Pt. 4).mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Cry For The Moon - Sahara Dust Demo.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Dance Of Fate - Live At Paradiso.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Dancing in a Gypsy Camp.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Decoded Poetry.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Dedicate Your Heart!.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Design Your Universe - A New Age Dawns, Pt. 6 - Acoustic Version.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Design Your Universe - A New Age Dawns, Pt. 6.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Falsches Spiel - Run For A Fall - German version.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Façade Of Reality (The Embrace That Smothers, Pt. V) - Live.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Fight Your Demons.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Illusive Consensus - Live.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Illusive Consensus - Sahara Dust demo.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Kingdom of Heaven - A New Age Dawns, Pt. 5.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Kingdom of Heaven Prt. 3 - The Antediluvian Universe -.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Kingdom of Heaven, Pt. 1 - A New Age Dawns Part V - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Kingdom of Heaven, Pt. 3 - The Antediluvian Universe - - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Martyr of the Free Word - Acoustic Version.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Martyr of the Free Word - Live.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Martyr of the Free Word.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Omega - Sovereign of the Sun Spheres - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Omegacoustic.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Resign to Surrender - A New Age Dawns, Pt. 4.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Run For A Fall - Live Acoustic.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Run For A Fall - Live At Paradiso.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Run for a Fall.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Seif al Din (The Embrace That Smothers, Pt. VI) - Live.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Sensorium - Live At Paradiso.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Sensorium - Live.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Sensorium.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - The Divine Conspiracy ~Anniversary Edition~ - Live.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - The Last Crusade - A New Age Dawns 1.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - The Last Crusade - Live At Paradiso.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - The Phantom Agony - Live At Paradiso.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - The Phantom Agony - Live.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - The Price of Freedom - Interlude.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - The Skeleton Key - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - The Solace System.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Twin Flames - Live.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Unchain Utopia - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Unchain Utopia.mp3
/home/pi/MediaFolder/mp3/2023 Jan-Mar/Epica - Wings of Freedom.mp3
/home/pi/MediaFolder/mp3/2024 Jan-Mar/Epica - Sancta Terra.mp3
/home/pi/MediaFolder/mp3/Magiczne i chuj/Epica - Never Enough.mp3
/home/pi/MediaFolder/mp3/Magiczne i chuj/Epica, Shining - The Final Lullaby (feat. Shining).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/01_-_Epica_-_Indigo.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/02_-_Epica_-_The_obsessive_devotion.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/03_-_Epica_-_Menace_of_vanity.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/04_-_Epica_-_Chasing_the_dragon.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/05_-_Epica_-_Never_enough.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/06_-_Epica_-_La'fetach_chataz_rovetz.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/07_-_Epica_-_Death_of_a_dream.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/08_-_Epica_-_Living_a_lie.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/09_-_Epica_-_Fools_of_damnation.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/10_-_Epica_-_Beyond_belief.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/11_-_Epica_-_Safeguard_to_paradise.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/12_-_Epica_-_Sancta_terra.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica (2007) - The Divine Conspiracy/Epica (2007) - The Divine Conspiracy/13_-_Epica_-_The_divine_conspiracy.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy/01 Palladium (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy/02 Dies Irae (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy/03 Ombra Mai Fu (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy/04 Adagio (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy/05 Spiderman Medley (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy/06 Presto (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy/07 Montagues & Capulets (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy/08 The Imperial March (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy/09 Stabat Mater Dolorosa (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy/10 Unholy Trinity (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy/11 In the Hall of the Mountain King (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy/12 Pirates Of The Caribbean (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/13 Indigo (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/14 The Last Crusade (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/15 Sensorium (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/16 Quietus (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/17 Chasing the Dragon (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/18_Epica_Feint.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/19_Epica_Never Enough.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/20_Epica_Beyond Belief.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/21 Cry for the Moon (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/22 Safeguard to Paradise (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/23 Blank Infinity (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/24 Living a Lie (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/25 The Phantom Agony (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/26 Sancta Terra (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/27 Illusive Consensus (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - 2009 - The Classical Conspiracy/Epica - 2009 - The Classical Conspiracy/classical conspiracy 2/28 Consign To Oblivion (live).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Consign To Oblivion 2005/Epica - Consign To Oblivion 2005/01.- Hunab K'u (A New Age Dawns Prologue).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Consign To Oblivion 2005/Epica - Consign To Oblivion 2005/02.- Dance Of Fate.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Consign To Oblivion 2005/Epica - Consign To Oblivion 2005/03.- The Last Crusade (A New Age Dawns Part 1).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Consign To Oblivion 2005/Epica - Consign To Oblivion 2005/04.- Solitary Ground.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Consign To Oblivion 2005/Epica - Consign To Oblivion 2005/05.- Blank Infinity.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Consign To Oblivion 2005/Epica - Consign To Oblivion 2005/06.- Force Of The Shore.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Consign To Oblivion 2005/Epica - Consign To Oblivion 2005/07.- Quietus.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Consign To Oblivion 2005/Epica - Consign To Oblivion 2005/08.- Mother Of Light (A New Age Dawns Part 2).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Consign To Oblivion 2005/Epica - Consign To Oblivion 2005/09.- Trois Vierges.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Consign To Oblivion 2005/Epica - Consign To Oblivion 2005/10.- Another Me In Lack'ech.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Consign To Oblivion 2005/Epica - Consign To Oblivion 2005/11.- Consign To Oblivion (A New Age Dawns Part 3).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Design Your Universe (2009)/Epica - Design Your Universe (2009)/01 Samadhi (prelude).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Design Your Universe (2009)/Epica - Design Your Universe (2009)/02 Resign to Surrender (A New Age Dawns pt. IV).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Design Your Universe (2009)/Epica - Design Your Universe (2009)/03 Unleashed.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Design Your Universe (2009)/Epica - Design Your Universe (2009)/04 Martyr of the Free Word.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Design Your Universe (2009)/Epica - Design Your Universe (2009)/05 Our Destiny.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Design Your Universe (2009)/Epica - Design Your Universe (2009)/06 Kingdom of Heaven (A New Age Dawns, Part V).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Design Your Universe (2009)/Epica - Design Your Universe (2009)/07 The Price Of Freedom (Interlude).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Design Your Universe (2009)/Epica - Design Your Universe (2009)/08 Burn To A Cinder.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Design Your Universe (2009)/Epica - Design Your Universe (2009)/09 Tides of Time.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Design Your Universe (2009)/Epica - Design Your Universe (2009)/10 Deconstruct.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Design Your Universe (2009)/Epica - Design Your Universe (2009)/11 Semblance of Liberty.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - Design Your Universe (2009)/Epica - Design Your Universe (2009)/13 Design Your Universe (A New Age Dawns pt. VI).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 13 - Beyond The Depth.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 01 - Vengeance Is Mine.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 02 - Unholy Trinity.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 03 - The Valley.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 04 - Caught In A Web.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 05 - Insomnia.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 06 - Under The Aegis.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 07 - Trois Vierges (Solo Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 08 - Mystica.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 09 - Valley Of Sins.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 10 - Empty Gaze.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 11 - The Alleged Paradigm.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 12 - Supremacy.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 14 - Epitome.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 15 - Inevitable Embrace.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 16 - Angel Of Death.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 17 - The Ultimate Return.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 18 - Trois Vierges (Reprise).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 19 - Solitary Ground (Single Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica - The Score - An Epic Journey/Epica - 2005 - The Score - An Epic Journey (OST)/Epica - 20 - Quietus (Score Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica- The Phantom Agony/Epica- The Phantom Agony/01. Adyta (The Neverending Embrace).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica- The Phantom Agony/Epica- The Phantom Agony/02. Sensorium.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica- The Phantom Agony/Epica- The Phantom Agony/03. Cry for the Moon (The Embrace that Smothers - Part IV).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica- The Phantom Agony/Epica- The Phantom Agony/04. Feint.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica- The Phantom Agony/Epica- The Phantom Agony/05. Illusive Consensus.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica- The Phantom Agony/Epica- The Phantom Agony/06. Façade of Reality (The Embrace that Smothers - Part V).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica- The Phantom Agony/Epica- The Phantom Agony/07. Run for a Fall.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica- The Phantom Agony/Epica- The Phantom Agony/08. Seif al Din (The Embrace that Smothers - Part VI).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Epica/Epica- The Phantom Agony/Epica- The Phantom Agony/09. The Phantom Agony.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/01_Prologue.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/02_Center of the Universe.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/03_Farewell.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/04_Interlude I (Opiate Soul).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/05_The Edge of Paradise.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/06_Wander.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/07_Interlude II (Omen).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/08_Descent of the Archangel.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/09_Interlude III (At the Banquet).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/10_A Feast for the Vain.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/11_On the Coldest Winter Night.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/12_Lost & Damned.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/13_Helena's Theme.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/14_Interlude IV (Dawn).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/15_The Mourning After (Carry On).mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/16_III Ways to Epica.mp3
/home/pi/MediaFolder/mp3/Muzyka/2010/Kamelot/Kamelot 2003 - Epica/17_Snow.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 01 - Originem.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 02 - The Second Stone.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 03 - The Essence Of Silence.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 04 - Victims Of Contingency.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 05 - Sense Without Sanity (The Impervious Code).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 06 - Unchain Utopia.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 07 - The Fifth Guardian (Interlude).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 08 - Chemical Insomnia.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 09 - Reverence (Living In The Heart).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 10 - Omen (The Ghoulish Malady).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 11 - Canvas Of Life.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 12 - Natural Corruption.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 13 - The Quantum Enigma (Kingdom Of Heaven Part II).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD1 - The Quantum Enigma/Epica - 14 - Dreamscape.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD2 - Acoustic Tracks/Epica - 01 - Canvas Of Life (Acoustic Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD2 - Acoustic Tracks/Epica - 02 - In All Conscience (Acoustic Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD2 - Acoustic Tracks/Epica - 03 - Dreamscape (Acoustic Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD2 - Acoustic Tracks/Epica - 04 - Natural Corruption (Acoustic Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 01 - Originem (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 02 - The Second Stone (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 03 - The Essence Of Silence (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 04 - Victims Of Contingency (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 05 - Sense Without Sanity (The Impervious Code) (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 06 - Unchain Utopia (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 07 - The Fifth Guardian (Interlude) (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 08 - Chemical Insomnia (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 09 - Reverence (Living In The Heart) (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 10 - Omen (The Ghoulish Malady) (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 11 - Canvas Of Life (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 12 - Natural Corruption (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/CD3 - Instrumental Tracks/Epica - 13 - The Quantum Enigma (Kingdom Of Heaven Part II) (Instrumental Version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Anima.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Avalanche.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Deep Water Horizon.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Delirium.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Guilty Demeanor.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Internal Warfare.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Karma.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Monopoly On Truth.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Requiem For The Indifferent.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Serenade Of Self-Destruction.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Stay The Course.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Storm The Sorrow.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - Requiem for the Indifferent/Epica - Twin Flames (Soundtrack Version) (Bonus Track).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/01-epica-eidola.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/02-epica-edge_of_the_blade.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/03-epica-a_phantasmic_parade.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/04-epica-universal_death_squad.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/05-epica-divide_and_conquer.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/06-epica-beyond_the_matrix.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/07-epica-once_upon_a_nightmare.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/08-epica-the_cosmic_algorithm.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/09-epica-ascension_-_dream_state_armageddon.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/10-epica-dancing_in_a_hurricane.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/11-epica-tear_down_your_walls.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/12-epica-the_holographic_principle_-_a_profound_understanding_of_reality.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/13-epica-beyond_the_good_the_bad_and_the_ugly.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/14-epica-dancing_in_a_gypsy_camp.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/15-epica-immortal_melancholy_(acoustic_version).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/16-epica-the_funky_algorithm.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Holographic Principle 2016/17-epica-universal_love_squad.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Solace System [EP] (2017) DJmp-3.com/01 - The Solace System.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Solace System [EP] (2017) DJmp-3.com/02 - Fight Your Demons.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Solace System [EP] (2017) DJmp-3.com/03 - Architect of Light.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Solace System [EP] (2017) DJmp-3.com/04 - Wheel of Destiny.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Solace System [EP] (2017) DJmp-3.com/05 - Immortal Melancholy.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Epica/Epica - The Solace System [EP] (2017) DJmp-3.com/06 - Decoded Poetry.mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - Epica vs Attack on Titan Songs (2017) EP/Epica - Epica vs Attack on Titan Songs (2017) EP/01. Crimson Bow and Arrow.mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - Epica vs Attack on Titan Songs (2017) EP/Epica - Epica vs Attack on Titan Songs (2017) EP/02. Wings of Freedom.mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - Epica vs Attack on Titan Songs (2017) EP/Epica - Epica vs Attack on Titan Songs (2017) EP/03. If Inside These Walls Was a House.mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - Epica vs Attack on Titan Songs (2017) EP/Epica - Epica vs Attack on Titan Songs (2017) EP/04. Dedicate Your Heart!.mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - Epica vs Attack on Titan Songs (2017) EP/Epica - Epica vs Attack on Titan Songs (2017) EP/05. Crimson Bow and Arrow (Instrumental).mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - Epica vs Attack on Titan Songs (2017) EP/Epica - Epica vs Attack on Titan Songs (2017) EP/06. Wings of Freedom (Instrumental).mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - Epica vs Attack on Titan Songs (2017) EP/Epica - Epica vs Attack on Titan Songs (2017) EP/07. If Inside These Walls Was a House (Instrumental).mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - Epica vs Attack on Titan Songs (2017) EP/Epica - Epica vs Attack on Titan Songs (2017) EP/08. Dedicate Your Heart! (Instrumental).mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - The Solace System [EP] (2017)/Epica - The Solace System [EP] (2017) DJmp-3.com/01 - The Solace System.mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - The Solace System [EP] (2017)/Epica - The Solace System [EP] (2017) DJmp-3.com/02 - Fight Your Demons.mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - The Solace System [EP] (2017)/Epica - The Solace System [EP] (2017) DJmp-3.com/03 - Architect of Light.mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - The Solace System [EP] (2017)/Epica - The Solace System [EP] (2017) DJmp-3.com/04 - Wheel of Destiny.mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - The Solace System [EP] (2017)/Epica - The Solace System [EP] (2017) DJmp-3.com/05 - Immortal Melancholy.mp3
/home/pi/MediaFolder/mp3/Muzyka/2018/Epica - The Solace System [EP] (2017)/Epica - The Solace System [EP] (2017) DJmp-3.com/06 - Decoded Poetry.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Anima.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Avalanche.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Deep Water Horizon.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Delirium.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Guilty Demeanor.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Internal Warfare.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Karma.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Monopoly On Truth.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Requiem For The Indifferent.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Serenade Of Self-Destruction.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Stay The Course.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Storm The Sorrow.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Requiem for the Indifferent/Epica - Requiem for the Indifferent/Epica - Twin Flames (Soundtrack Version) (Bonus Track).mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_08 - Retrospect - Live 2013 - Never Enough.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_18 - Retrospect - Live 2013 - Battle of The HeroesThe Imperial March.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_01 - Retrospect - Live 2013 - Intro.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_02 - Retrospect - Live 2013 - Monopoly On Truth.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_03 - Retrospect - Live 2013 - Sensorium.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_04 - Retrospect - Live 2013 - Unleashed.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_05 - Retrospect - Live 2013 - Martyr Of The Free World.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_06 - Retrospect - Live 2013 - Chasing The Dragon.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_07 - Retrospect - Live 2013 - Presto (Vivaldi Cover).mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_09 - Retrospect - Live 2013 - Stabat Mater Dolorosa (With Foor Jansen).mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_10 - Retrospect - Live 2013 - Twin Flames.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_11 - Retrospect - Live 2013 - Serenade Of Self Destruction.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_12 - Retrospect - Live 2013 - FeintFools Of DamnationMother Of LightKingdom Of HeavenRun For A FallDeep Water Horizon - Orchestra Cover.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_13 - Retrospect - Live 2013 - The Divine Conspiracy.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_14 - Retrospect - Live 2013 - Delirium.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_15 - Retrospect - Live 2013 - Blank Infinity.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_16 - Retrospect - Live 2013 - The Obsessive Devotion.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_17 - Retrospect - Live 2013 - Retrospect.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_19 - Retrospect - Live 2013 - Quietus.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_20 - Retrospect - Live 2013 - The Phantom Agony.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_21 - Retrospect - Live 2013 - Cry To The Moon.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_22 - Retrospect - Live 2013 - Sancta Terra (With Floor Jansen).mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_23 - Retrospect - Live 2013 - Design Your Universe.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_24 - Retrospect - Live 2013 - Storm Of Sorrow.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/EPICA_-_Retrospect -Live 2013_MP3_REPACK (Yasmena)/EPICA_-_25 - Retrospect - Live 2013 - Consign To Oblivion.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/202. Orchestral Medley.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/101. Introspect.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/102. Monopoly On Truth.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/103. Sensorium.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/104. Unleashed.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/105. Martyr Of The Free Word.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/106. Chasing The Dragon.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/107. Presto.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/108. Never Enough.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/109. Stabat Mater Dolorosa.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/110. Twin Flames.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/201. Serenade Of Self Destruction.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/203. The Divine Conspiracy ~Anniversary Edition~.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/204. Delirium.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/205. Blank Infinity.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/206. The Obsessive Devotion.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/207. Retrospect.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/208. Battle Of The Heroes & Imperial March.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/209. Quietus.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/210. The Phantom Agony.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/301. Cry For The Moon.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/302. Sancta Terra.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/303. Design Your Universe.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/304. Storm The Sorrow.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/305. Consign To Oblivion.mp3
/home/pi/MediaFolder/mp3/Muzyka/2014/Epica - Retrospect 10th Anniversary (2013)/Epica - Retrospect 10th Anniversary (2013)/306. Outrospect.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 01.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 02.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 03.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 04.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 05.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 06.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 07.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 08.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 09.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 10.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 11.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 12.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 13.mp3
/home/pi/MediaFolder/mp3/Muzyka/Dream Of The Warrior - Gothic Rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia And More)/Dream of the warrior - Gothic rock (Epica,Edenbridge,Gathering,Nemesea,Nightwish,Sirenia and more)/Track 14.mp3
/home/pi/MediaFolder/mp3/The Skeleton Key - Omega Alive/Epica - The Skeleton Key - Omega Alive.mp3
/home/pi/MediaFolder/mp3/2023 Nov-Dec/Paul Elstak - Hey Mambo.mp3
/home/pi/MediaFolder/mp3/2024 Apr-Jul/Paul Elstak - TAKE ME AWAY.mp3
/home/pi/MediaFolder/mp3/Magiczne i chuj/Paul Elstak - TAKE ME AWAY.mp3
/home/pi/MediaFolder/mp3/Youtube/DJ Paul Elstak You're A Hardcore Hooligan [am4Ww4g0XtM].mp3
/home/pi/MediaFolder/mp3/Youtube/DJ Paul Elstak, New Kids - Turbo (D-Fence Decade Mix) [AQrk2-B_Irg].mp3
/home/pi/MediaFolder/mp3/Youtube/Rooler & Sickmode & Paul Elstak - TAKE ME AWAY (Official Video) [ifKnpGKeKdk].mp3
/home/pi/MediaFolder/mp3/Youtube/FiNCH x PAUL ELSTAK - GABBER GIRL (prod. Paul Elstak, Dasmo & Mania Music) [Official Video] 4k [3smGQOexuSU].mp3
/home/pi/MediaFolder/mp3/Youtube/New Kids Feat. Paul Elstak - Turbo (Official German Video HD) [HKF4hobJl2A].mp3
/home/pi/MediaFolder/mp3/Youtube/Paul Elstak - Full set - Intents Festival 2024 [WVzwkPDiLTc].mp3
/home/pi/MediaFolder/mp3/Youtube/Paul Elstak x GPF x Boogshe - Vet En Hard (Official Video) [5xVx127afSA].mp3
/home/pi/MediaFolder/mp3/Muzyka/2016/SABATON - The Lost Battalion (OFFICIAL LYRIC VIDEO) - YouTube.mp3
/home/pi/MediaFolder/mp3/Muzyka/2016/SABATON - Blood of Bannockburn (OFFICIAL LYRIC VIDEO) - YouTube.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/10 Urodziny Klubu Spi Katowice AronChupa Spiowi Mocni - YouTube.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/ANGEL WITCH - live from Headbangers Open Air (Full Song) - from www.streetclip.tv - YouTube_1.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Arabskie (garett22)/Best Arabic Nasheed ever 2013 - YouTube.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Arabskie (garett22)/ISISTEP - ALLAHU AKBAR REMIX VIDEO 2015 ISIS - YouTube(1).mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Arabskie (garett22)/ISISTEP - ALLAHU AKBAR REMIX VIDEO 2015 ISIS - YouTube.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Arabskie (garett22)/My Ummah, Dawn Has Appeared (METAL v2.0) - YouTube.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Arabskie (garett22)/Ummeti Kad Laha Fecrun امي ق لاح فجر Best Ever Nasheed - YouTube.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/GAMMA RAY - Dethrone Tyranny 9. 2011 [HD] Berlin Live - YouTube.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Gemini Abyss Jest Taki Samotny Dom COVER - YouTube.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/My Ummah, Dawn Has Appeared Nasheed - YouTube.mp3
/home/pi/MediaFolder/mp3/Muzyka/2017/Angel Witch/ANGEL WITCH - live from Headbangers Open Air (Full Song) - from www.streetclip.tv - YouTube_1.mp3
/home/pi/MediaFolder/mp3/Muzyka/2019/ŁYDKA GRUBASA - Rapapara (Oficjalny Teledysk) Woodstock 2018 - YouTube.mp3
/home/pi/MediaFolder/mp3/Youtube/1 HOUR Dark Techno EBM Industrial Bass Mix 'SABBATH' [Copyright Free] [9Wz3J1P5HZY].mp3
/home/pi/MediaFolder/mp3/Youtube/100 twarzy grzybiarzy - przejebane [FfO8IBwi4t0].mp3
/home/pi/MediaFolder/mp3/Youtube/3 AM SOLO-Q (FRENCHCORE MIX) [G9kzYRJU3aQ].mp3
/home/pi/MediaFolder/mp3/Youtube/3Blokes & Villain - Shoey In Ya Face Power Hour Records [hNQ2dG8hYug].mp3
/home/pi/MediaFolder/mp3/Youtube/Ada Karczmarczyk ADU - Miss Messianist [2v8V0CepOE4].mp3
/home/pi/MediaFolder/mp3/Youtube/Adu & Monarowcy - W Monarze [MhTFGm596wM].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - Bit z Serca Jezusa [h9QBUsBQDOk].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - Bursztynami mnie obejmij [_OV1_X9sA68].mp3
/home/pi/MediaFolder/mp3/Youtube/DJ Paul Elstak You're A Hardcore Hooligan [am4Ww4g0XtM].mp3
/home/pi/MediaFolder/mp3/Youtube/DJ Paul Elstak, New Kids - Turbo (D-Fence Decade Mix) [AQrk2-B_Irg].mp3
/home/pi/MediaFolder/mp3/Youtube/Dr. Peacock & Billx - Mother Earth (Official Video) [2kCklVUxOsM].mp3
/home/pi/MediaFolder/mp3/Youtube/Dr. Peacock & Da Mouth of Madness ft. Ally The Piper - Trip to Scotland [oIYDEfEDmfw].mp3
/home/pi/MediaFolder/mp3/Youtube/Dr. Peacock & Partyraiser LIVE @ Dominator 2023 - Voyage of the Damned [0-RVGPrMEBI].mp3
/home/pi/MediaFolder/mp3/Youtube/Dr. Peacock & Sefa present Symphony of Freedom (Defqon.1 at Home, 2021) [vN6Jy50vOz8].mp3
/home/pi/MediaFolder/mp3/Youtube/Dr. Peacock & Zyklon - Trip To Japan [OwcHGm-GF9I].mp3
/home/pi/MediaFolder/mp3/Youtube/Dr. Peacock - Trip to Ireland [GvrvQTUbUcA].mp3
/home/pi/MediaFolder/mp3/Youtube/Dr. Peacock @ REBiRTH Festival 2023 [m2z_1bEs8Ug].mp3
/home/pi/MediaFolder/mp3/Youtube/Dr. Peacock Hellbound 2023 Hemkade [S2sSfN5t8AY].mp3
/home/pi/MediaFolder/mp3/Youtube/Early Hardcore Lenny Dee vs. DJ Paul - Make It Fucking Louder [CWs_-sW1-0w].mp3
/home/pi/MediaFolder/mp3/Youtube/ANKOR - Darkbeat [OFFICIAL VIDEO] - Chapter 1 [aTKwR1YxAwg].mp3
/home/pi/MediaFolder/mp3/Youtube/ANKOR - Winner Horse [OFFICIAL VIDEO] [Wuy8EQAzjh0].mp3
/home/pi/MediaFolder/mp3/Youtube/APNOIE - Recollections (Official Video) darkTunes Music Group [na55cP7nxvs].mp3
/home/pi/MediaFolder/mp3/Youtube/Babymetal - Headbanger (Momoko ver.) (Legend MM 2024 Live) Eng Subs [19nntDDbYdg].mp3
/home/pi/MediaFolder/mp3/Youtube/Babymetal - Headbanger (Night of 20 version) (Live Proshot) [uTN9wE82Xpc].mp3
/home/pi/MediaFolder/mp3/Youtube/Babymetal - Live @ Rock am Ring 2024 #RAR2024 [gmj6QLdLxRY].mp3
/home/pi/MediaFolder/mp3/Youtube/BABYMETAL x @ElectricCallboy - RATATATA (OFFICIAL Live Music Video at FOX_FEST) [ChmVcJK7N-c].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - EMBRIONY NA TRONY !!! [ykVsqBPcLXI].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - Orzeł we mnie [hsI5nzaRSbk].mp3
/home/pi/MediaFolder/mp3/Youtube/Amon Amarth - Raise Your Horns (Live) 4K [fPCfUa2pd9o].mp3
/home/pi/MediaFolder/mp3/Youtube/AniMe Defqon.1 Weekend Festival 2019 [-0SX2g5gt_s].mp3
/home/pi/MediaFolder/mp3/Youtube/BABYMETAL x @ElectricCallboy - RATATATA (OFFICIAL VIDEO) [EDnIEWyVIlE].mp3
/home/pi/MediaFolder/mp3/Youtube/Billx - Imagination Festival Rave Music [T5ZEL_gGxEM].mp3
/home/pi/MediaFolder/mp3/Youtube/DJ AniMe - Masters of Hardcore Spain 2023 (Fabrik - Madrid) [ASGGaUwk6Qg].mp3
/home/pi/MediaFolder/mp3/Youtube/Electric Callboy - Hypa Hypa (Alex feat. Aga vocal cover) po polsku [JIJ29a9V5UY].mp3
/home/pi/MediaFolder/mp3/Youtube/FEUERSCHWANZ - I See Fire (Ed Sheeran Cover) Napalm Records [F-8JYS1uXC8].mp3
/home/pi/MediaFolder/mp3/Youtube/If SYSTEM OF A DOWN wrote 'MACARENA' [GfMIvH41BzQ].mp3
/home/pi/MediaFolder/mp3/Youtube/Mutilator Defqon.1 2024 [7Qy72qM16Xo].mp3
/home/pi/MediaFolder/mp3/Youtube/Reverze 2024 Sefa [L2wChuOaes0].mp3
/home/pi/MediaFolder/mp3/Youtube/SYNDICATE 2022 Miss K8 vs. AniMe [1myM-zVArcQ].mp3
/home/pi/MediaFolder/mp3/Youtube/TUNAK TUNAK TUN METAL VERSION Bloodywood Feat. Bonde do Metaleiro [APK2iGKK7gs].mp3
/home/pi/MediaFolder/mp3/Youtube/Rooler & Sickmode & Paul Elstak - TAKE ME AWAY (Official Video) [ifKnpGKeKdk].mp3
/home/pi/MediaFolder/mp3/Youtube/Scooter - The Chaser Jigga Jigga! [hJjCefEbAA0].mp3
/home/pi/MediaFolder/mp3/Youtube/Sefa & Headhunterz - (ID Als Alles Duister Is) [UDWDcYcrbqQ].mp3
/home/pi/MediaFolder/mp3/Youtube/SEFA (DJ-set) SLAM! [ZoUZlrvOvmo].mp3
/home/pi/MediaFolder/mp3/Youtube/SEFA @ DEFQON.1 2017 (FULL SET) [fc8n2u-VbZI].mp3
/home/pi/MediaFolder/mp3/Youtube/SEFA @ HARMONY OF HARDCORE 2018 (LIVE WITH PIANO) [BIXRHtSLBic].mp3
/home/pi/MediaFolder/mp3/Youtube/Sefa @ Reverze 2022 [REUPLOAD] [-5ZgWmSqGdo].mp3
/home/pi/MediaFolder/mp3/Youtube/Sefa Defqon.1 Theatre 2023 FULL [D_jG6CHl1NY].mp3
/home/pi/MediaFolder/mp3/Youtube/Sefa Defqon 1 theatre - full set [YQr2iA8vcjA].mp3
/home/pi/MediaFolder/mp3/Youtube/Sefa Defqon.1 Weekend Festival 2019 [m9bRC92OsfI].mp3
/home/pi/MediaFolder/mp3/Youtube/Shinzou Wo Sasageyo (Attack On Titan) - Metal Cover Feat. Rob Lundgren! [Mo_Y5XZPGgc].mp3
/home/pi/MediaFolder/mp3/Youtube/Sweet but Psycho - Ava Max (Metal Cover) [ckswcYvfeFg].mp3
/home/pi/MediaFolder/mp3/Youtube/FiNCH x PAUL ELSTAK - GABBER GIRL (prod. Paul Elstak, Dasmo & Mania Music) [Official Video] 4k [3smGQOexuSU].mp3
/home/pi/MediaFolder/mp3/Youtube/Frenchcore Familia I Defqon.1 Weekend Festival 2023 I Thursday I BLACK [i_MZvopQHE8].mp3
/home/pi/MediaFolder/mp3/Youtube/Frenchcore Mix 2023 #11 [ZOz3Ph3WZdY].mp3
/home/pi/MediaFolder/mp3/Youtube/GPF & J1zzy - King Of The Pieps (Official Video) [F5B84XsUYJ8].mp3
/home/pi/MediaFolder/mp3/Youtube/If BLACK SABBATH wrote 'JOLENE' [YRAheVxhuIA].mp3
/home/pi/MediaFolder/mp3/Youtube/If Rammstein wrote 'Every Breath You Take' [_j9Vm3t1HHI].mp3
/home/pi/MediaFolder/mp3/Youtube/If Rammstein wrote 'Poison' [bNStVF7SsTE].mp3
/home/pi/MediaFolder/mp3/Youtube/If Rammstein wrote 'You Spin Me Round' [6ufauqY2Rn4].mp3
/home/pi/MediaFolder/mp3/Youtube/If Sepultura wrote 'Whenever, Wherever' [GvMrxnQg1hI].mp3
/home/pi/MediaFolder/mp3/Youtube/If SLAYER wrote 'JUMP' [E_pj1LWBZZA].mp3
/home/pi/MediaFolder/mp3/Youtube/If SLAYER wrote 'SWEET DREAMS' [tz8VNzX_IHs].mp3
/home/pi/MediaFolder/mp3/Youtube/If System Of A Down wrote 'Livin' La Vida Loca' [bsxQ6MN4mrA].mp3
/home/pi/MediaFolder/mp3/Youtube/Jak się myje kibel Epic Viking Folk [EYFOzJZsO3A].mp3
/home/pi/MediaFolder/mp3/Youtube/JAM Project - THE HERO !! (One Punch Man OP)┃Raon Lee x PelleK [5u-1VVWM9l0].mp3
/home/pi/MediaFolder/mp3/Youtube/JKLL & Dr. Peacock ft. Ellene Masri - Hit The Road Jack [Mt6nfbeRpe8].mp3
/home/pi/MediaFolder/mp3/Youtube/Koncert ADU na ŚDM w Krakowie - Jaraj się Marią [xkOQds-lQDk].mp3
/home/pi/MediaFolder/mp3/Youtube/KUPOWANIE BILETU NA MECZ LIGI MISTRZÓW ALE TO EUROBEAT [zM2X0a_z6a8].mp3
/home/pi/MediaFolder/mp3/Youtube/LET 3 - Mama ŠČ! Official video Eurovision 2023 [O_tmsim6lPY].mp3
/home/pi/MediaFolder/mp3/Youtube/Linked Horizon - Shinzo wo Sasageyo! (LIVE) Attack on Titan Opening 3 [2YNQYYHT8Uc].mp3
/home/pi/MediaFolder/mp3/Youtube/Linked Horizon Attack on Titan OPENINGS LIVE [FhM402sKgqA].mp3
/home/pi/MediaFolder/mp3/Youtube/Billx - Tree of Life (Psy to Hard)[Official video] ☯️ [HM-zIwaZr1A].mp3
/home/pi/MediaFolder/mp3/Youtube/Billx Dominator Festival 2022 - Hell of a Ride [5Y6PUQcD5hU].mp3
/home/pi/MediaFolder/mp3/Youtube/BRING ME THE HORIZON ⧸⧸ KINGSLAYER ft. BABYMETAL 【NEX_FEST】 [pAM8MQt6I6I].mp3
/home/pi/MediaFolder/mp3/Youtube/BWSP Fałszywy Raszyn [EKHSkMYhgkY].mp3
/home/pi/MediaFolder/mp3/Youtube/DARK TECHNO MIX Andrea Botez [4K] [M_aOXL5Sg4I].mp3
/home/pi/MediaFolder/mp3/Youtube/dArtagnan - Farewell ft. Patty Gurdy [ckSEnb_I3Zg].mp3
/home/pi/MediaFolder/mp3/Youtube/Defqon.1 2018 Sefa [-sfrrxEW158].mp3
/home/pi/MediaFolder/mp3/Youtube/Defqon.1 Legends 2023 Sunday [JuyNNkxbbFA].mp3
/home/pi/MediaFolder/mp3/Youtube/Defqon.1 Weekend Festival 2018 POWER HOUR [QdGz0OHQ9S8].mp3
/home/pi/MediaFolder/mp3/Youtube/Defqon.1 Weekend Festival 2019 POWER HOUR [vJ2eHsQv7Ac].mp3
/home/pi/MediaFolder/mp3/Youtube/DJ AniMe - Hard Techno Hardcore Mix [B2KuebFsfN4].mp3
/home/pi/MediaFolder/mp3/Youtube/Syndicate 2023 D-Fence vs AniMe [oLAOmeoI2Dc].mp3
/home/pi/MediaFolder/mp3/Youtube/Syntetic - Nagi Szopen [tXcUOUZqX1Y].mp3
/home/pi/MediaFolder/mp3/Youtube/The Hero ONE-PUNCH MAN (Full) feat. Angelo Bissanti ワンパンマン [NSG32WJX6-c].mp3
/home/pi/MediaFolder/mp3/Youtube/The Syntetic - Człowiek Widmo [yS0Lv2Pv99g].mp3
/home/pi/MediaFolder/mp3/Youtube/The Syntetic - Hollywood [3Psr2H9A90A].mp3
/home/pi/MediaFolder/mp3/Youtube/The Syntetic - Kleopatra [Jtf6q7_LX_Y].mp3
/home/pi/MediaFolder/mp3/Youtube/The Syntetic - Niewidzialny Templariusz [DlzNRywOe9Q].mp3
/home/pi/MediaFolder/mp3/Youtube/This Is Sefa Defqon.1 2022 [5mEWXmS3cnM].mp3
/home/pi/MediaFolder/mp3/Youtube/This Is Sefa The Spotlight Defqon.1 2024 [TR7mmkZuIuk].mp3
/home/pi/MediaFolder/mp3/Youtube/Thunderdome 2023 Dr. Peacock [7kZCTY77K9k].mp3
/home/pi/MediaFolder/mp3/Youtube/Amon Amarth - Raise Your Horns (Official Video) [Ndu33Uv7Aco].mp3
/home/pi/MediaFolder/mp3/Youtube/Amon Amarth - Raven's Flight [H24S0nym-pE].mp3
/home/pi/MediaFolder/mp3/Youtube/AMON AMARTH- Raise Your Horns ( Live 2016 ) [KwEJWrx8bLg].mp3
/home/pi/MediaFolder/mp3/Youtube/Amon amarth-Raise your horns live (Hellfest) 2016 [voGBBSw_fFo].mp3
/home/pi/MediaFolder/mp3/Youtube/Anime - Imagination Festival Hardcore [SWgZ9YPwhhM].mp3
/home/pi/MediaFolder/mp3/Youtube/AniMe @ Dominator Festival 2023 - Voyage of the Damned [caCjlVO7ZGA].mp3
/home/pi/MediaFolder/mp3/Youtube/AniMe @ Masters of Hardcore 2022 - Magnum Opus [NHc4Lne0mFA].mp3
/home/pi/MediaFolder/mp3/Youtube/AniMe BLACK SUGAR 2022 EQ Music Poland [H4jHMo1EB34].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - Sensualna ( cover Sexualna Mirami) [519hvggfQtM].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - Zabierz mnie do Arsenału [kX2W6t-z7xo].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU Ada Karczmarczyk - CHILDREN OF THE INTERNET [do7jTWPpn2c].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU Ada Karczmarczyk - Church is a girl [evdx4YdCv6I].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU Ada Karczmarczyk - Hej husarzu! NIE_PODLE_głości dzień [SReTynvd6ek].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU Ada Karczmarczyk - HOUSTON, HOUSTON [C9Vlw4jB7iM].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU Ada Karczmarczyk - Na Święta chcę Ciebie (Wędrowcu w potrzebie) [IMwMUr2NvSg].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU Ada Karczmarczyk - niUNIA EUROPEJSKA [itrYkDzdAkw].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU Ada Karczmarczyk - RODZINA TO... [R2mmHMembrg].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU feat MATEJKO - Nie strzelam do zdrajców oczami [PGL6Q9G4_JM].mp3
/home/pi/MediaFolder/mp3/Youtube/All Time Low - Kids In The Dark (Official Music Video) [SaIegdJxTsE].mp3
/home/pi/MediaFolder/mp3/Youtube/Amon Amarth - Raise Your Horns #Woodstock2017 [YCDkAT6671c].mp3
/home/pi/MediaFolder/mp3/Youtube/Amon Amarth - Raise Your Horns (Live At Summer Breeze) [jVOluNDjc5s].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - Idź do światła i nie pierdol! [13e4n5UxylU].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - Intronizacja Chrystusa na Króla w korporacjach [pVyBe-FdTDk].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - JARAJ SIĘ MARIĄ [7EzpQoDfVyo].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - JP2 in da house [cOZZa7ycovY].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - Lecimy ze Smoleńska z powrotem [f3CVfG4pV8M].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - Na Tinderze w dobrej wierze [QuWYrH8knzk].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - Nie chcę w lewo, nie chcę w prawo [J3Ok-KcbQ80].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - Niszcz szatana Łaską Pana [LNyC6YA8NO8].mp3
/home/pi/MediaFolder/mp3/Youtube/ADU - Oddam ciało, oddam duszę (by już nie być prekariuszem) [4LjmMj3Gyyo].mp3
/home/pi/MediaFolder/mp3/Youtube/Van Halen Ain't Talkin' 'Bout Love 1986 [b1NmPFgdt6Y].mp3
/home/pi/MediaFolder/mp3/Youtube/We Must Fight - President Reagan (Long Version) [JDVT-8tUfiE].mp3
/home/pi/MediaFolder/mp3/Youtube/Występ ADU na THE ARTISTS 2015 - God is the biggest director [Rkp6QaDdO6A].mp3
/home/pi/MediaFolder/mp3/Youtube/Yousei Teikoku - Patriot Anthem live HQ Sub Engita [HK3ZN5bpr-M].mp3
/home/pi/MediaFolder/mp3/Youtube/[Official Video] JAM Project - THE HERO !! - 2015.11.29 in Yokohama Arena - One Punch Man [NL-iKNk1FyU].mp3
/home/pi/MediaFolder/mp3/Youtube/[Official Video] Yousei Teikoku - Astral Dogma - 妖精帝國 [_EeYxtAeaX4].mp3
/home/pi/MediaFolder/mp3/Youtube/[Official Video] Yousei Teikoku - Kuusou Mesorogiwi - 空想メソロギヰ 妖精帝國 [ZZvJY7_gyfw].mp3
/home/pi/MediaFolder/mp3/Youtube/「Nightcore Empyre One Hands Up Mix」 [PUh8uiR7Dao].mp3
/home/pi/MediaFolder/mp3/Youtube/和楽器バンド 千本桜 [K_xTet06SUo].mp3
/home/pi/MediaFolder/mp3/Youtube/💛🤍"Barka - Mała Armia Janosika w Watykanie🎻(150 .górali gra dla Jana Pawła II w dniu Jego urodzin) [NaRRlqd-uaE].mp3
/home/pi/MediaFolder/mp3/Youtube/Barka - Agnieszka Cudzich (live) [e74D5FmtXow].mp3
/home/pi/MediaFolder/mp3/Youtube/New Kids Feat. Paul Elstak - Turbo (Official German Video HD) [HKF4hobJl2A].mp3
/home/pi/MediaFolder/mp3/Youtube/OBERSCHLESIEN - Król Olch [OFFICIAL VIDEO] [KPJPJzpk_QQ].mp3
/home/pi/MediaFolder/mp3/Youtube/One Punch Man FULL ENGLISH OPENING (The Hero - Jam Project) Cover by Jonathan Young [XMCYNH1EJTg].mp3
/home/pi/MediaFolder/mp3/Youtube/Orkiestra online #wdomuzagrane - Co mi Panie dasz (arr. Adam Sztaba) [7NSXXttiwHw].mp3
/home/pi/MediaFolder/mp3/Youtube/Paul Elstak - Full set - Intents Festival 2024 [WVzwkPDiLTc].mp3
/home/pi/MediaFolder/mp3/Youtube/Paul Elstak x GPF x Boogshe - Vet En Hard (Official Video) [5xVx127afSA].mp3
/home/pi/MediaFolder/mp3/Youtube/Peacock in Concert - Mad Masquerade Show 2023 Silverdome Zoetermeer NL [OWM8dP1WbUk].mp3
/home/pi/MediaFolder/mp3/Youtube/POWER HOUR 2022 Defqon.1 Weekend Festival Sixty minutes of pure insanity [fX1kUoeUhPg].mp3
/home/pi/MediaFolder/mp3/Youtube/POWER HOUR 2023 Defqon.1 Weekend Festival This is Madness [A7thBilOLFU].mp3
/home/pi/MediaFolder/mp3/Youtube/Power Hour Six Years of Insanity Defqon.1 at Home 2020 [HiMTwi3_09U].mp3
/home/pi/MediaFolder/mp3/Youtube/Q-dance Presents The Hardstyle Top 40 September 2024 [aTAvXvfw-pg].mp3
/home/pi/MediaFolder/mp3/Youtube/Reverze 2024 Dr. Peacock [L6nKIyiCmLA].mp3
/home/pi/MediaFolder/mp3/Youtube/Barka (Electro Remix) [WQsaVznexqw].mp3
/home/pi/MediaFolder/mp3/Youtube/Barka - ukochana pieśń Jana Pawła II [0qzLRlQFFQ4].mp3
/home/pi/MediaFolder/mp3/Youtube/Best Of Globus Epic Vocal Rock Orchestral [FS0Csetvl4M].mp3
/home/pi/MediaFolder/mp3/Youtube/best summer song 2024 Hardstyle Remix Best Hardstyle Remixes Of Popular Songs 2024 [9oGZ9fCW8FM].mp3
/home/pi/MediaFolder/mp3/Youtube/Billx & Neika - Chichovite (Frenchcore to Hardtek)[Official video]☯️ [EGDwQbXBpZc].mp3
/home/pi/MediaFolder/mp3/Youtube/Billx & Otyken - My wing (Rave music edit) [ylUsbg-yUZ8].mp3
/home/pi/MediaFolder/mp3/Youtube/Billx & Vandal - Rolling Paper Hard edit free remix (Official video) [fi7U24itRaQ].mp3
/home/pi/MediaFolder/mp3/Youtube/Electric Callboy - Live @ Rock am Ring 2024 #RAR2024 [jQN23aw8oaI].mp3
/home/pi/MediaFolder/mp3/Youtube/Electric Callboy - We Got the Moves #polandrock2024 [KNyQP5ql6pY].mp3
/home/pi/MediaFolder/mp3/Youtube/ELECTRIC CALLBOY ft BABYMETAL - RATATATA (Live at Resurrection Fest EG 2024) [R78nx63OfPg].mp3
/home/pi/MediaFolder/mp3/Youtube/ELYOSE - Les artisans du chaosDe guerre lasse (Live at the Halloween Horror Night 2016, Paris) [Bf_XofH9j0E].mp3
/home/pi/MediaFolder/mp3/Youtube/Eurodance & Bubblegum EDM Mix Tinzo [zvXAt1uB6ME].mp3
-191
View File
@@ -1,191 +0,0 @@
# FILEPATH: /home/mtuszowski/conjurer/conjurer_musician/radio_conjurer.liq
# This script sets up a Liquidsoap radio stream with various features and configurations.
# Load icecast credentials from a JSON file
let json.parse credentials = file.contents("/home/pi/Conjurer/icecast_credentials.json")
# Enable replaygain metadata processing
enable_replaygain_metadata()
# Set up a playlog for tracking played tracks
l = playlog(duration = 72000.0, persistency="/home/pi/Conjurer/persistence.log")
# Function to check if a track can be played based on its metadata
def check(r)
m = request.metadata(r)
if l.last(m) < 36000. then
log.info("Rejecting #{m['filename']} (played #{l.last(m)}s ago).")
false
else
l.add(m)
true
end
end
# Define playlists to be used in the stream
s1 = replaygain(playlist(reload_mode="watch", check_next=check, "/home/pi/Conjurer/all_playlist.playlist"))
s2 = replaygain(playlist(reload_mode="watch", check_next=check, "/home/pi/Conjurer/priority_queue.playlist"))
s3 = replaygain(playlist(reload_mode="watch", check_next=check, "/home/pi/Conjurer/hit.playlist"))
# Create a request queue for user-generated requests
requests_queue = request.queue()
# Function to process the request queue and add new requests
def queue_processing()
text=file.lines("/home/pi/Conjurer/request.playlist")
if text != [] then
list.iter(fun(item) -> requests_queue.push.uri(item), text)
file.remove("/home/pi/Conjurer/request.playlist")
f = file.open("/home/pi/Conjurer/request.playlist", create=true)
f.close()
end
end
# Configure output formats and destinations
def now_playing(m)
# raw lookup ("" if missing)
raw_title = m["title"]
raw_artist = m["artist"]
# default if empty
title = if raw_title == "" then "Unknown" else raw_title end
artist = if raw_artist == "" then "Unknown" else raw_artist end
log.critical("Now playing #{artist} - #{title}")
# write it out
system("echo '#{artist} - #{title}' > /tmp/now_playing.txt")
m
end
# Randomly select a playlist with weights
s4 = random(id="randomizer", weights=[2, 3, 5], [s1, s2, s3])
# Load jingles playlist
jingles = (playlist(reload_mode="watch", "/home/pi/Conjurer/jingles.playlist"))
# Create the main stream with random playlist and jingles
s = rotate(id="randomizer", weights=[10, 1], [s4, jingles])
s = crossfade(fade_out=2., fade_in=2., duration=4., fallback(id="switcher", track_sensitive=true, [requests_queue, s]))
s = metadata.map(now_playing, s)
# Set up an interactive harbor for controlling the stream
interactive.harbor(port = 9999)
# Set up interactive controls for bass boost
f = interactive.float("f", description="Frequency", min=0., max=1000., unit="Hz", 200.)
g = interactive.float("g", description="Gain", min=0., max=20., unit="dB", 8.)
b = bass_boost(frequency=f, gain=g, s)
s = add([s, b])
# Set up interactive control for main volume
a = interactive.float("main_volume", min=0., max=20., 1.1)
s = compress.multiband.interactive(bands=7, s)
mic_gain = interactive.float("mic_volume", min=0., max=120., 0.5)
# Apply audio processing effects
tmic = buffer(input.pulseaudio()) # Microphone
mic = amplify(mic_gain, tmic)
mic = gate(threshold=-80., range=-120., mic)
mic = compress(threshold=0., ratio=2.,mic)
mic = nrj(normalize(mic))
mic = blank.strip(max_blank=15., min_noise=.1, threshold=-30., mic)
mic = fallback(id="switcher2", track_sensitive=false, [mic, blank()])
# Apply audio processing effects
s = nrj(s)
s = amplify(a, s)
# Skip blank sections in the stream
s = blank.skip(max_blank=10., s)
#Manual audition override
live_enabled = interactive.bool("Going Live!", true)
s = add([mic,s])
s=switch(track_sensitive=true,
[(live_enabled, mic),
({true}, s)])
# Configure logging settings
log_to_stdout = true
log_to_file = true
logpath = "/home/pi/Conjurer/radio_log.log"
loglevel = 3
set("log.stdout", log_to_stdout)
set("log.level", loglevel)
# Enable logging to file
set("log.file", log_to_file)
set("log.file.path", logpath)
# Set up emergency fallback track
emergency = single("/home/pi/MediaFolder/mp3/Youtube/Dr. Peacock - Trip to Ireland [GvrvQTUbUcA].mp3")
radio = fallback(id="switcher2", track_sensitive=false, [s, emergency])
# Set up an interactive control for skipping tracks
p = interactive.bool("Skip track", false)
def http_skip(~protocol, ~data, ~headers, uri)=
radio.skip()
http.response(code=200,data="Skipped")
end
harbor.http.register(port=54321,method="GET","/skip", http_skip)
# Function to process the request queue and skip the current track if requested
def check_skip()
if p() then
log.info("Skipping current track.")
radio.skip()
p.set(false)
end
end
# Run the queue processing function every 60 seconds
thread.run(every=60., queue_processing)
# Run the check_skip function every 5 seconds
thread.run(every=15., check_skip)
# Enable persistent script parameters
interactive.persistent("script.params")
# Configure output formats and destinations
output.icecast(%mp3, host="radio", port=8000, password=credentials.password, icy_metadata="true", mount="mp3-stream", radio)
output.pulseaudio(radio)
#output.file.hls("/tmp/hls", [("mp3-low", %mp3(bitrate=96)), ("mp3-hi", %mp3(bitrate=160))], radio)
# Uncomment the following lines to enable additional output formats
# output.icecast(%opus, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="opus-stream", radio)
# output.icecast(%ogg, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="ogg-stream", radio)
# output.icecast(%aac, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="aac-stream", radio)
# output.icecast(%flac, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="flac-stream", radio)
# output.icecast(%vorbis, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="vorbis-stream", radio)
# output.icecast(%speex, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="speex-stream", radio)
# output.icecast(%wav, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="wav-stream", radio)
# output.icecast(%pcm, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="pcm-stream", radio)
# output.icecast(%raw, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="raw-stream", radio)
# output.icecast(%s16l, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s16l-stream", radio)
# output.icecast(%s16b, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s16b-stream", radio)
# output.icecast(%s24l, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s24l-stream", radio)
# output.icecast(%s24b, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s24b-stream", radio)
# output.icecast(%s32l, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s32l-stream", radio)
# output.icecast(%s32b, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s32b-stream", radio)
# output.icecast(%s64l, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s64l-stream", radio)
# output.icecast(%s64b, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s64b-stream", radio)
# output.icecast(%s128l, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s128l-stream", radio)
# output.icecast(%s128b, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s128b-stream", radio)
# output.icecast(%s256l, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s256l-stream", radio)
# output.icecast(%s256b, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s256b-stream", radio)
# output.icecast(%s512l, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s512l-stream", radio)
# output.icecast(%s512b, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s512b-stream", radio)
# output.icecast(%s1024l, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s1024l-stream", radio)
# output.icecast(%s1024b, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s1024b-stream", radio)
# output.icecast(%s2048l, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s2048l-stream", radio)
# output.icecast(%s2048b, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s2048b-stream", radio)
# output.icecast(%s4096l, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s4096l-stream", radio)
# output.icecast(%s4096b, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s4096b-stream", radio)
# output.icecast(%s8192l, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s8192l-stream", radio)
# output.icecast(%s8192b, host="retropie", port=8000, password=credentials.password, icy_metadata="true", mount="s8192b-stream", radio)
View File
-4
View File
@@ -1,4 +0,0 @@
flask
waitress
sshtunnel
requests
-195
View File
@@ -1,195 +0,0 @@
{
"string": [],
"bool": [ [ "Skip track", false ], [ "Going Live!", false ] ],
"int": [],
"float": [
[
"mic_volume",
0.0
],
[
"compress_gain6",
0.1
],
[
"compress_ratio6",
7.9
],
[
"compress_threshold6",
-15.8
],
[
"compress_release6",
30.0
],
[
"compress_attack6",
30.0
],
[
"compress_frequency6",
18610.0
],
[
"compress_gain5",
5.4
],
[
"compress_ratio5",
4.8
],
[
"compress_threshold5",
-13.6
],
[
"compress_release5",
120.0
],
[
"compress_attack5",
160.0
],
[
"compress_frequency5",
13950.0
],
[
"compress_gain4",
6.5
],
[
"compress_ratio4",
4.0
],
[
"compress_threshold4",
-12.2
],
[
"compress_release4",
130.0
],
[
"compress_attack4",
200.0
],
[
"compress_frequency4",
3890.0
],
[
"compress_gain3",
5.5
],
[
"compress_ratio3",
3.5
],
[
"compress_threshold3",
-11.7
],
[
"compress_release3",
140.0
],
[
"compress_attack3",
250.0
],
[
"compress_frequency3",
2270.0
],
[
"compress_gain2",
3.3
],
[
"compress_ratio2",
3.9
],
[
"compress_threshold2",
-11.5
],
[
"compress_release2",
120.0
],
[
"compress_attack2",
250.0
],
[
"compress_frequency2",
1920.0
],
[
"compress_gain1",
5.6
],
[
"compress_ratio1",
3.4
],
[
"compress_threshold1",
-12.2
],
[
"compress_release1",
120.0
],
[
"compress_attack1",
220.0
],
[
"compress_frequency1",
650.0
],
[
"compress_gain0",
7.5
],
[
"compress_ratio0",
3.2
],
[
"compress_threshold0",
-13.1
],
[
"compress_release0",
110.0
],
[
"compress_attack0",
140.0
],
[
"compress_frequency0",
110.0
],
[
"compress_wet",
1.0
],
[
"main_volume",
1.8
],
[
"g",
1.0
],
[
"f",
106.4
]
]
}
File diff suppressed because it is too large Load Diff
-672
View File
@@ -1,672 +0,0 @@
"""
The provided Python script sets up a Flask web server to manage a list of music files, with
functions for rescanning the music folder, updating the music list, and serving the music list via
API endpoints.
"""
import json
import logging
import os
import random
import re
import threading
import time
from datetime import datetime
from logging import handlers
from pathlib import Path
from typing import Dict, List
import requests
from flask import (
Flask,
abort,
jsonify,
redirect,
render_template,
request,
send_from_directory,
)
from waitress import serve
import media_search_functions
def _env(name: str, default: str) -> str:
return os.getenv(name, default)
def _env_path(name: str, default: str) -> Path:
value = os.getenv(name, default)
return Path(value).expanduser().resolve()
API_KEY = os.getenv("CONJURER_API_KEY")
MAIN_BOT_ADDRESS = _env("CONJURER_MAIN_BOT", "http://127.0.0.1:5000")
MUSIC_TRACKER = _env("CONJURER_MUSIC_TRACKER_ENDPOINT", "/prepped_tracks")
HOST_ADDRESS = _env("CONJURER_MUSICIAN_HOST", "0.0.0.0")
PORT_ADDRESS = int(_env("CONJURER_MUSICIAN_PORT", "5000"))
BASE_DIR = Path(
os.getenv("CONJURER_MUSICIAN_BASE", str(Path(__file__).resolve().parent))
)
LOGFILE = _env_path(
"CONJURER_MUSICIAN_LOG", str(BASE_DIR / "discord_mus_service.log")
)
LOGSTORE = _env_path("CONJURER_LOGSTORE", str(BASE_DIR / "logs"))
MUSIC_FOLDER = _env_path(
"CONJURER_MUSIC_FOLDER", str(BASE_DIR / "music")
)
PRIORITY_FOLDER = _env_path(
"CONJURER_PRIORITY_FOLDER", str(MUSIC_FOLDER / "priority")
)
RADIOLOG_PATH = _env_path(
"CONJURER_RADIO_LOG", str(BASE_DIR / "radio_log.log")
)
PERSISTENCE_PATH = _env_path(
"CONJURER_PERSISTENCE_LOG", str(BASE_DIR / "persistence.log")
)
ALL_PLAYLIST_PATH = _env_path(
"CONJURER_ALL_PLAYLIST", str(BASE_DIR / "all_playlist.playlist")
)
HIT_PLAYLIST_PATH = _env_path(
"CONJURER_HIT_PLAYLIST", str(BASE_DIR / "hit.playlist")
)
REQUEST_PLAYLIST_PATH = _env_path(
"CONJURER_REQUEST_PLAYLIST", str(BASE_DIR / "request.playlist")
)
PRIORITY_PLAYLIST_PATH = _env_path(
"CONJURER_PRIORITY_PLAYLIST", str(BASE_DIR / "priority_queue.playlist")
)
STREAM_TEMPLATE = _env_path(
"CONJURER_STREAM_TEMPLATE", str(BASE_DIR / "stream.html")
)
ENCODING = _env("CONJURER_ENCODING", "utf-8")
SEPARATOR_FILE_PATH = os.sep
for playlist_path in (
ALL_PLAYLIST_PATH,
HIT_PLAYLIST_PATH,
REQUEST_PLAYLIST_PATH,
PRIORITY_PLAYLIST_PATH,
):
playlist_path.parent.mkdir(parents=True, exist_ok=True)
random.seed()
music_file_list: List[str] = []
priority_list: List[str] = []
def _build_headers() -> Dict[str, str]:
headers: Dict[str, str] = {}
if API_KEY:
headers["X-Conjurer-Api-Key"] = API_KEY
return headers
def _authorize_request() -> None:
if API_KEY and request.headers.get("X-Conjurer-Api-Key") != API_KEY:
abort(401)
def _post_to_bot(payload: List[str]) -> None:
response = requests.post(
f"{MAIN_BOT_ADDRESS}{MUSIC_TRACKER}",
json=payload,
headers=_build_headers(),
timeout=60,
)
logger = logging.getLogger("conjurer_musician")
logger.info("SENT")
logger.info(response.status_code)
logger.info("SEND CONFIRMED")
def rescan():
"""
The `rescan` function logs a message, scans for mp3 files in a specified folder,
and adds them to a list of music files.
"""
logger = logging.getLogger("conjurer_musician")
logger.info("Rescan triggered")
music_file_list.clear()
priority_list.clear()
for mp3_item in MUSIC_FOLDER.glob("**/*.mp3"):
temp_music_file = mp3_item.as_posix()
if os.name == "nt":
temp_music_file = temp_music_file.replace("/", "\\")
music_file_list.append(temp_music_file)
for mp3_item in PRIORITY_FOLDER.glob("**/*.mp3"):
temp_music_file = mp3_item.as_posix()
if os.name == "nt":
temp_music_file = temp_music_file.replace("/", "\\")
priority_list.append(temp_music_file)
with ALL_PLAYLIST_PATH.open("w", encoding=ENCODING) as w_file:
try:
for item in music_file_list:
w_file.write(item)
w_file.write("\n")
except json.JSONDecodeError:
pass
with HIT_PLAYLIST_PATH.open("w", encoding=ENCODING) as w_file:
try:
for item in priority_list:
w_file.write(item)
w_file.write("\n")
except json.JSONDecodeError:
pass
def thread_rescan():
"""
The `thread_rescan` function periodically triggers a rescan operation after a specified time
interval.
"""
logger = logging.getLogger("conjurer_musician")
logger.info("Starting filesystemupdater")
while True:
time.sleep(60 * 60 * 24)
logger.info("Rescan triggered")
rescan()
def scan_tracks():
# Set the filename and open the file
logger = logging.getLogger("conjurer_musician")
with open(RADIOLOG_PATH, "r", encoding=ENCODING) as log_file:
log_file.seek(os.stat(RADIOLOG_PATH).st_size)
prev_size = os.stat(PERSISTENCE_PATH).st_size
while True:
current_size = os.stat(PERSISTENCE_PATH).st_size
if prev_size != current_size:
while prev_size != current_size:
prev_size = current_size
time.sleep(0.1)
current_size = os.stat(PERSISTENCE_PATH).st_size
with open(PERSISTENCE_PATH, "r", encoding=ENCODING) as persistence:
lines = persistence.readlines()
if len(lines) >= 3:
_post_to_bot(["next", lines[2]])
position = log_file.tell()
line = log_file.readline()
if not line:
time.sleep(1)
log_file.seek(position)
continue
if not re.match(r".*Prepared.*", line):
time.sleep(0.1)
continue
result = None
if re.match(r".*jingles.*", line):
result = ["jingles", line]
elif re.match(r".*priority.*", line):
result = ["priority", line]
elif re.match(r".*hit.*", line):
result = ["hit", line]
elif re.match(r".*all_playlist.*", line):
result = ["all", line]
elif re.match(r".*request.*", line):
result = ["requests", line]
if result:
logger.info("Forwarding radio log entry: %s", result[0])
_post_to_bot(result)
time.sleep(0.1)
app = Flask(__name__)
# AutoIndex(app, browse_root="/")
# TODO: Odpalić wyszukiwarki w wątkach i dopiero po wszystkim zsumować wyszukiwanie.
def wyszukaj(word_list, how_many, _logger=None, return_to_bot=True):
"""
Searches for music files based on a list of keywords and returns a list of matching files.
Args:
word_list (list): A list of keywords to search for.
how_many (int): The maximum number of matching files to return.
Returns:
list: A list of matching files, sorted by their search weight.
"""
if _logger is None:
fun_logger = logging.getLogger()
else:
fun_logger = _logger
return_list = []
search_weight = []
for _ in range(len(music_file_list)):
search_weight.append((0, ""))
time_start = datetime.now()
if int(how_many) > 0:
skip_start = 2
else:
skip_start = 1
for word in word_list[skip_start:]:
token_weight = len(word)
fun_logger.info("Słowo kluczowe: %s", word)
itr = 0
for file in music_file_list:
file = file.split(SEPARATOR_FILE_PATH)
char_remove = [
".",
"^",
"$",
"*",
"+",
"?",
"{",
"}",
"[",
"]",
"\\",
"/",
"|",
"(",
")",
"!",
",",
"-",
":",
"mp3",
]
all_words = []
for f_iter in file:
for char in char_remove:
f_iter = remove_characters(f_iter, char)
tmp = f_iter.split()
all_words.extend(tmp)
pingu = 1
pattern_len = len(all_words)
if platform == "win32":
skip = 2
else:
skip = 4
matched_times = 1
# TODO: To do wątków albo for asynchroniczny
for itm in all_words[skip:]:
pingu += 1
pattern = ".*" + word + ".*"
if re.match(pattern, itm, re.IGNORECASE):
temp_weight = (
search_weight[itr][0]
+ (token_weight + (pingu**1.5) / pattern_len) / matched_times
)
search_weight[itr] = (
temp_weight,
music_file_list[itr],
)
matched_times += 1
itr += 1
fun_logger.info(
"Stworzylem tablice wag zajęło mi to %s", datetime.now() - time_start
)
time_start = datetime.now()
item_to_search = max_weight(search_weight)
itr = 0
if item_to_search == 0:
return []
not_found = True
return_list = []
if int(how_many) <= 0:
fun_logger.info("Jeden plik do zagrania")
while not_found:
if search_weight[itr][0] == item_to_search:
return_list.append(search_weight[itr])
if not return_to_bot:
with PRIORITY_PLAYLIST_PATH.open("a", encoding=ENCODING) as s_file:
s_file.write(search_weight[itr][1] + "\n")
break
itr += 1
else:
fun_logger.info("Wiele plików do zagrania")
search_weight.sort(key=lambda x: x[0], reverse=True)
return_list.extend(search_weight[: int(how_many)])
fun_logger.info("Done: %s", return_list)
return return_list
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
def remove_characters(string, character):
"""
The `remove_characters` function removes all occurrences of a specified character from a given
string.
:param string: The string parameter is the input string from which characters will be removed
:param character: The character parameter is the character that you want to remove from the string
:return: a new string where all occurrences of the specified character have been removed.
"""
return string.replace(character, "")
@app.route('/get_share_list', methods=['POST'])
def get_share_list():
_authorize_request()
data = request.get_json()
entries = data.get('entries')
keywords = data.get('keywords')
# Validate entries
if not isinstance(entries, int) or not (1 <= entries <= 10):
return jsonify({'error': '"entries" must be an integer between 1 and 10.'}), 400
# Validate keywords list
if not isinstance(keywords, list) or not all(isinstance(k, str) for k in keywords):
return jsonify({'error': '"keywords" must be a list of strings.'}), 400
# Call external search
files = media_search_functions.find_matches(entries, keywords)
# Return each file path as a JSON list
return jsonify({'files': files}), 200
@app.route('/get_share_links', methods=['POST'])
def get_share_links():
_authorize_request()
data = request.get_json()
file_paths = data.get('file_paths')
# Validate file_paths list
if not isinstance(file_paths, list) or not all(isinstance(p, str) for p in file_paths):
return jsonify({'error': '"file_paths" must be a list of strings.'}), 400
# Call external publish
links = media_search_functions.publish(file_paths)
# Return list of published links
return jsonify({'links': links}), 200
@app.route("/stream", methods=["GET"])
def stream_music():
"""
The function `stream_music` is a route handler for the "/stream" endpoint.
It returns a JSON response containing a key "music_file_list" with the value of the variable `music_file_list`.
:return: A JSON response containing a key "music_file_list" with the value of the variable `music_file_list`.
"""
# return send_from_directory("/tmp/hls", "stream.m3u8")
return render_template(str(STREAM_TEMPLATE))
@app.route("/<string:file_name>")
def stream(file_name):
"""
Stream the specified file from the video directory.
Args:
file_name (str): The name of the file to be streamed.
Returns:
Response: The response containing the streamed file.
"""
# trunk-ignore(bandit/B108)
video_dir = "/tmp/hls"
return send_from_directory(video_dir, file_name)
@app.route("/stream_mp3", methods=["GET"])
def stream_music_mp3():
"""
The function `stream_music_mp3` is a route handler for the "/stream_mp3" endpoint.
It redirects the user to the URL "http://www.example.com" with a status code of 302.
:return: A redirect response to "http://www.example.com" with a status code of 302.
"""
return redirect("http://www.example.com", code=302)
@app.route("/clear_pr_pls", methods=["GET"])
def clear_pr_pls():
_authorize_request()
"""
The function `clear_pr_pls` clears the contents of the priority queue playlist file.
:return: A JSON response indicating the success of the operation.
"""
app.logger.info("CLEARING PLAYLIST")
with PRIORITY_PLAYLIST_PATH.open("w", encoding=ENCODING) as cleared_pl:
cleared_pl.write("")
return_data = jsonify(isError=False, message="Success", statusCode=200, data=[])
return return_data, 200
@app.route("/mp3", methods=["GET"])
def get_music_list():
"""
The function `get_music_list` returns a JSON object containing a list of music files.
:return: A JSON response containing a key "music_file_list" with the value of the variable
`music_file_list`.
"""
return jsonify({"music_file_list": music_file_list})
@app.route("/update_mp3", methods=["POST"])
def update_music_list():
"""
The function `update_music_list` receives a POST request with a JSON payload, logs the received
item, adds it to a music file list, and returns a success message along with the updated record.
:return: The function `update_music_list` is returning a tuple containing a JSON response and a
status code. The JSON response includes keys `isError`, `message`, `statusCode`, and `data`,
with values indicating the success of the operation and the data that was
received and added to the `music_file_list`.
The status code returned is 200, indicating a successful response.
"""
_authorize_request()
record = json.loads(request.data)
app.logger.info(record["item"])
music_file_list.append(record["item"])
return_data = (
jsonify(isError=False, message="Success", statusCode=200, data=record),
200,
)
return return_data
@app.route("/get_music", methods=["POST"])
def look_for_playlist():
"""
The function `look_for_playlist` receives a POST request with a JSON payload, logs the received
item, adds it to a music file list, and returns a success message along with the updated record.
:return: A tuple containing a JSON response and a status code. The JSON response includes keys `isError`,
`message`, `statusCode`, and `data`, with values indicating the success of the operation and the
data that was received and added to the `music_file_list`. The status code returned is 200,
indicating a successful response.
"""
_authorize_request()
record = json.loads(request.data)
app.logger.info(record)
app.logger.info(record["lista_slow"])
app.logger.info(record["UUID"])
app.logger.info(record["dlugosc_plejlisty"])
return_data = wyszukaj(
record["lista_slow"], record["dlugosc_plejlisty"], app.logger, True
)
return_data = (
jsonify(isError=False, message="Success", statusCode=200, data=return_data),
200,
)
return return_data
@app.route("/request_radio_file", methods=["POST"])
def add_request():
_authorize_request()
record = json.loads(request.data)
app.logger.info(record)
app.logger.info(record["lista_slow"])
app.logger.info(record["UUID"])
return_data = wyszukaj(record["lista_slow"], 0, app.logger, False)
with REQUEST_PLAYLIST_PATH.open("a", encoding=ENCODING) as s_file:
for item in return_data:
s_file.write(item[1] + "\n")
return_data = (
jsonify(
isError=False, message="Success", statusCode=200, data={"status": "OK"}
),
200,
)
return return_data
@app.route("/create_priority_playlist", methods=["POST"])
def create_priority_playlist():
"""
The function `create_priority_playlist` receives a POST request with a JSON payload, logs the received
item, adds it to a music file list, and returns a success message along with the updated record.
:return: A tuple containing a JSON response and a status code.
The JSON response includes keys `isError`,
`message`, `statusCode`, and `data`, with values
indicating the success of the operation and the
data that was received and added to the `music_file_list`.
The status code returned is 200,indicating a successful response.
"""
_authorize_request()
record = json.loads(request.data)
app.logger.info(record)
app.logger.info(record["lista_slow"])
app.logger.info(record["UUID"])
app.logger.info(record["dlugosc_plejlisty"])
return_data = wyszukaj(
record["lista_slow"], record["dlugosc_plejlisty"], app.logger, False
)
random.shuffle(return_data)
with REQUEST_PLAYLIST_PATH.open("a", encoding=ENCODING) as s_file:
for item in return_data:
s_file.write(item[1] + "\n")
return_data = (
jsonify(
isError=False, message="Success", statusCode=200, data={"status": "OK"}
),
200,
)
return return_data
@app.route("/add_to_priority", methods=["POST"])
def add_to_priority():
"""
The function `add_to_priority` receives a POST request with a JSON payload, logs the received
item, adds it to a music file list, and returns a success message along with the updated record.
:return: A tuple containing a JSON response and a status code.
The JSON response includes keys `isError`,
`message`, `statusCode`, and `data`, with values
indicating the success of the operation and the
data that was received and added to the `music_file_list`.
The status code returned is 200,indicating a successful response.
"""
_authorize_request()
record = json.loads(request.data)
app.logger.info(record)
app.logger.info(record["lista_slow"])
app.logger.info(record["UUID"])
app.logger.info(record["dlugosc_plejlisty"])
return_data = wyszukaj(
record["lista_slow"], record["dlugosc_plejlisty"], app.logger, False
)
with PRIORITY_PLAYLIST_PATH.open("a", encoding=ENCODING) as s_file:
for item in return_data:
s_file.write(item[1] + "\n")
return_data = (
jsonify(
isError=False, message="Success", statusCode=200, data={"status": "OK"}
),
200,
)
return return_data
def flask_debug():
"""
The `flask_debug` function starts a Flask application in debug mode without using the reloader.
Do not use for production for fucks sake.
"""
# trunk-ignore(bandit/B201)
app.run(debug=True, use_reloader=False, host=HOST_ADDRESS, port=PORT_ADDRESS)
def waitress_run():
"""
The `waitress_run` function serves the `app` on host HOST_ADDRESS
and port 5000 using the Waitress WSGI server.
This function starts the Waitress server and listens for incoming requests
on the specified host and port. It uses the `serve` function from the Waitress
library to handle the serving process.
Parameters:
None
Returns:
None
"""
serve(app, host=HOST_ADDRESS, port=PORT_ADDRESS)
if __name__ == "__main__":
logger = logging.getLogger("conjurer_musician")
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
handler = handlers.RotatingFileHandler(
filename=LOGFILE,
encoding=ENCODING,
mode="a",
maxBytes=6 * 1024 * 1024,
backupCount=6,
)
handler.setFormatter(formatter)
logger.addHandler(handler)
rescan()
logger.info("Started")
threads = []
# threads.append(threading.Thread(target=flask_debug))
threads.append(threading.Thread(target=waitress_run, daemon=True))
threads.append(threading.Thread(target=thread_rescan, daemon=True))
for worker in threads:
worker.start()
time.sleep(60)
track_thread = threading.Thread(target=scan_tracks, daemon=True)
track_thread.start()
try:
for worker in threads:
worker.join()
track_thread.join()
except KeyboardInterrupt:
logger.info("Shutdown requested - exiting musician service")
View File
@@ -1,3 +0,0 @@
{
"password" : "RadioHardkor123#!"
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-8
View File
@@ -1,8 +0,0 @@
jingiel2.mp3
jingiel3.mp3
jingiel4.mp3
jingiel.mp3
/home/pi/MediaFolder/mp3/Youtube/Pine Tree Riots - We'll Have Our Home Again [ctpfRxvC0JQ].mp3
/home/pi/MediaFolder/mp3/2024 Jan-Mar/Rave The Reqviem - Oh, the Joy!.mp3
/home/pi/MediaFolder/mp3/2022 Aug-Oct/Wil Farr - Keep Your Rifle by Your Side.mp3
/home/pi/MediaFolder/mp3/2022 Jan-Mar/The Hope County Choir - Keep Your Rifle by Your Side - Choir Version.mp3
@@ -1,52 +0,0 @@
#!/usr/bin/env python3
import argparse
import json
import os
import sys
import uuid
from pathlib import Path
# CONFIGURATION
JSON_DB = '/var/log/share_scan.json'
SHARE_DIR = Path('/var/www/html/share')
BASE_URL = 'https://czernobog.pl/share'
# Ensure share directory exists
SHARE_DIR.mkdir(parents=True, exist_ok=True)
def load_db():
with open(JSON_DB) as f:
return json.load(f)['entries']
ENTRIES = load_db()
def relevancy(path, keywords):
score = 0
low = path.lower()
for kw in keywords:
if kw.lower() in low:
score += low.count(kw.lower())
return score
def find_matches(count, keywords):
scored = []
for e in ENTRIES:
score = relevancy(e['path'], keywords)
if score > 0:
scored.append((score, e['path']))
scored.sort(reverse=True, key=lambda x: x[0])
result = [p for _, p in scored]
return result[:count]
def publish(paths):
urls = []
for path in paths:
token = uuid.uuid4().hex
link = SHARE_DIR / token
try:
os.symlink(path, link)
except FileExistsError:
pass
urls.append(f"{BASE_URL}/{token}")
return urls

Some files were not shown because too many files have changed in this diff Show More