Compare commits

..

41 Commits

Author SHA1 Message Date
gitea 0297527965 install manual 2025-04-19 17:16:28 +02:00
gitea f56935e48b How to setup radio 2025-04-19 17:15:11 +02:00
gitea b9e0f73534 Fix in default config 2025-04-18 13:45:33 +02:00
gitea 7f560decd3 Add musician fixes 2025-04-17 22:59:47 +02:00
gitea 88fdf35dc5 fixx 2025-04-17 21:51:30 +02:00
gitea b4fe6270a9 Fixes after reinstall 2025-04-17 20:44:39 +02:00
gitea c103b6b22e Modified spotipy for auth 2025-04-09 18:21:37 +01:00
gitea 0e860fe6a9 Add auth to ytdlp 2025-04-09 18:55:52 +02:00
gitea fdccde6137 refactor: comment out unused AutoIndex import and related code 2025-02-08 13:25:46 +01:00
gitea 043b1d3628 Fix 2025-01-31 20:16:43 +01:00
gitea afc5c42e30 of course fix needed 2025-01-31 20:15:21 +01:00
gitea 74b7c22b6c New command added that sets logging level dymnamically 2025-01-31 20:13:47 +01:00
gitea cf27b2f3f9 Finally fixed this bug. The AI can now play perfectly. 2025-01-31 20:08:38 +01:00
gitea 4aa442a802 Maybe fix 2025-01-31 20:00:05 +01:00
gitea 3964336370 Maybe this is the fix ? 2025-01-31 19:53:15 +01:00
gitea 625579ebbb another attempt to fix the bug 2025-01-31 19:49:01 +01:00
gitea ed71f7871d test 2025-01-31 19:44:49 +01:00
gitea ff8d1abf8a test 2025-01-31 19:42:21 +01:00
gitea a74b18f62a Maybe this will fix 2025-01-31 19:38:09 +01:00
gitea 323a1ac021 Fixing logging issues in music_functions.py and other_functions.py 2025-01-31 19:30:48 +01:00
gitea 993b303e2f Inside joke very boomer much wow 2025-01-21 21:51:26 +01:00
gitea 3b7248cb00 Fixit 2025-01-21 21:47:13 +01:00
gitea e35e028001 Fixc
Fixc
2025-01-21 21:36:07 +01:00
gitea 2c19e4565e Add comment 2025-01-21 16:53:09 +01:00
gitea 853e952128 Hej hoppsan! 2025-01-21 16:51:33 +01:00
gitea 041544917c Literowka 2025-01-21 15:44:43 +00:00
gitea 3ed4dcfbb4 add exception handling 2025-01-13 20:34:26 +00:00
gitea 276e814515 Fix old bug 2025-01-10 21:34:56 +01:00
gitea 5dd2aadd7c Arguments added to the utility. 2025-01-08 12:01:01 +01:00
gitea 19fbd27f3a FIXED! 2025-01-08 11:45:41 +01:00
gitea 8deea0584c LGFIX 2025-01-08 11:42:08 +01:00
gitea 9f0fadf908 Logs additional 2025-01-08 11:41:14 +01:00
gitea d176b762f7 Merge branch 'main' of https://github.com/migatu/conjurer 2025-01-08 11:35:01 +01:00
gitea 85d276f2d4 Function for idv3 and bugfix 2025-01-08 11:34:40 +01:00
gitea b031bd9fdc BGFX 2025-01-07 14:59:59 +00:00
gitea b3722deef2 Merge branch 'main' of https://github.com/migatu/conjurer 2025-01-07 14:54:47 +00:00
gitea 961ca74c14 BGFX 2025-01-07 14:54:38 +00:00
gitea 0f596cbdba Merge branch 'main' of https://github.com/migatu/conjurer 2025-01-05 22:09:53 +01:00
gitea 85be1ce9fc Small fix 2025-01-05 22:09:43 +01:00
gitea 5983439a5d Services 2025-01-05 20:40:42 +00:00
gitea fd4c066008 Status report script 2025-01-05 20:30:05 +00:00
26 changed files with 446 additions and 98 deletions
+1
View File
@@ -201,3 +201,4 @@ cr_results.json
not_in_db.json
rr_results.json
s_results.json
*.bak
+28 -15
View File
@@ -132,6 +132,7 @@ class Events(commands.Cog):
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():
@@ -140,6 +141,7 @@ class Events(commands.Cog):
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():
@@ -148,6 +150,7 @@ class Events(commands.Cog):
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():
@@ -156,6 +159,7 @@ class Events(commands.Cog):
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():
@@ -264,7 +268,7 @@ class Events(commands.Cog):
if kondziu_mentioned or "conjurer:" in message_content_lower:
async with channel.typing():
self.logger.debug("Procedura chatu")
self.logger.info("Procedura chatu")
message_content_lower = message_content_lower.replace("conjurer: ", "")
if message.author.nick:
@@ -293,12 +297,7 @@ class Events(commands.Cog):
"CONVERSATION",
)
if len(result) < 999:
await message.reply(result)
else:
while len(result) > 999:
await message.reply(result[:999])
result = result[999:]
await discord_friendly_reply(message, result)
if "imaginuje sobie:" in message.content:
async with channel.typing():
self.logger.info("Poczatek procedury obrazkowej")
@@ -365,20 +364,34 @@ class Events(commands.Cog):
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
with open(temp_file_name, "wb") as dalle_file:
dalle_file.write(response.content)
self.logger.info("Koniec procedury obrazkowej.")
fnord = discord.File(
temp_file_name, spoiler=False, description=message.content
)
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
+1 -1
View File
@@ -39,7 +39,7 @@ MAIN_BOT_ADDRESS = "http://192.168.1.191:5000"
SEND_RESULTS = "/conjurer"
BDSM_UUID_TEST = "96b7f85a-1142-4908-8986-62a2ea25a147"
MAX_CR_RESULTS = 1000
MAX_CR_RESULTS = 500
#TEST PURPOSES ONLY!
#MAX_CR_RESULTS = 5
+1 -2
View File
@@ -104,9 +104,8 @@ def check_if_exists_brute_force(logger):
pass
if blocked:
logger.info(item)
logger.info(text)
logger.error("Got blocked. Fuck.")
time.sleep(60 * 60 * 72)
time.sleep(60 * 60)
# trunk-ignore(bandit/B311)
rand = random.randint(1, 60)
logger.info(f"Sleeping for {2*rand} minutes")
+9 -7
View File
@@ -1,9 +1,9 @@
# This Python file uses the following encoding: utf-8
"""
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
@@ -11,7 +11,8 @@ import random
import re
import threading
import time
from flask_autoindex import AutoIndex
# from flask_autoindex import AutoIndex
from datetime import datetime
from logging import handlers
from pathlib import Path
@@ -47,10 +48,10 @@ if platform in ("linux", "linux2"):
else:
LOGFILE = "/home/pi/Conjurer/discord_mus_service.log"
NETRC_FILE = "/home/pi/.netrc"
LOGSTORE = "/home/pi/RetroPie/logs/"
LOGSTORE = "/home/pi/MediaShare/logs/"
ENCODING = "utf-8"
MUSIC_FOLDER = "/home/pi/RetroPie/mp3/"
PRIORITY_FOLDER = "/home/pi/RetroPie/mp3/Magiczne i chuj/"
MUSIC_FOLDER = "/home/pi/MediaShare/mp3/"
PRIORITY_FOLDER = "/home/pi/MediaShare/mp3/Magiczne i chuj/"
RADIOLOG_PATH = "/home/pi/Conjurer/radio_log.log"
PERSISTENCE_PATH = "/home/pi/Conjurer/persistence.log"
@@ -182,7 +183,8 @@ def scan_tracks():
app = Flask(__name__)
#AutoIndex(app, browse_root="/")
# 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):
@@ -486,7 +488,7 @@ def create_priority_playlist():
return_data = wyszukaj(
record["lista_slow"], record["dlugosc_plejlisty"], app.logger, False
)
return_data = random.shuffle(return_data)
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")
+74 -2
View File
@@ -2,9 +2,47 @@
"""This module contains utility scripts used by musi radiostation Conjurer"""
import time
import re
import os
import argparse
from mutagen.easyid3 import EasyID3
from mutagen.mp3 import MP3
def update_metadata(folder_path):
for root, _, files in os.walk(folder_path):
for file in files:
if file.endswith(".mp3"):
file_path = os.path.join(root, file)
# Sample logic for guessing metadata from filename
# Assuming the filename format is "Artist - Title.mp3"
try:
artist, title = file.rsplit(" - ", 1)
title = title.replace(".mp3", "")
except ValueError:
# If file name doesn't fit the expected pattern, skip
print(f"Skipping file due to unexpected format: {file}")
continue
try:
# Load the mp3 file
audio = MP3(file_path, ID3=EasyID3)
# Update metadata
audio["artist"] = artist.strip()
audio["title"] = title.strip()
# Save changes
audio.save()
print(f"Updated metadata for: {file}")
except Exception as e:
print(f"Failed to update metadata for {file}: {e}")
NAME = "/home/pi/Conjurer/persistence.log"
def print_top():
"""
Prints the top 65 lines from a file specified by the NAME variable.
@@ -13,7 +51,7 @@ def print_top():
line = ""
buffer = ""
with open(NAME, "r", encoding="utf-8") as f:
for _ in range (45):
for _ in range(45):
line = f.readline()
if re.match(".*mp3", line):
buffer += line
@@ -22,5 +60,39 @@ def print_top():
print("=====================================")
time.sleep(180)
def main():
parser = argparse.ArgumentParser(
description="Perform operations on a directory of .mp3 files."
)
# Positional argument for choosing the function to execute
parser.add_argument(
"operation",
type=str,
choices=["update_metadata", "print_top"],
help="Operation to perform: update_metadata or print_top.",
default="print_top",
)
# Positional argument for folder path
parser.add_argument("folder", type=str, help="Path to the folder to operate on.")
args = parser.parse_args()
if args.operation == "update_metadata":
if args.folder:
folder_to_scan = args.folder
else:
print("Please provide a folder path to scan.")
raise ValueError("No folder path provided.")
if args.operation == "update_metadata" and os.path.isdir(folder_to_scan):
update_metadata(folder_to_scan)
elif args.operation == "print_top":
print_top()
else:
print(f"The specified path is not a directory: {folder_to_scan}")
if __name__ == "__main__":
print_top()
main()
+2 -1
View File
@@ -1,3 +1,4 @@
flask
waitress
sshtunnel
sshtunnel
requests
+7 -4
View File
@@ -78,14 +78,14 @@ if platform in ("linux", "linux2"):
MEMORY_FIVE_SIARA = "/home/pi/Conjurer/pamiec.json"
SYSTEM_GPT_SETTINGS = "/home/pi/Conjurer/system_gpt_settings.json"
MEMORY_FIVE_MUZYKA = "/home/pi/Conjurer/pamiec_muzyki.json"
MUSIC_FOLDER = "/home/pi/RetroPie/mp3/"
MUSIC_FOLDER = "/home/pi/MediaShare/mp3/"
SETTINGS_FILE = "/home/pi/Conjurer/settings.json"
NETRC_FILE = "/home/pi/.netrc"
LOGSTORE = "/home/pi/RetroPie/logs/"
LOGSTORE = "/home/pi/MediaShara/logs/"
ACCIDENT_LOG = "/home/pi/Conjurer/accident_log.json"
ENCODING = "utf-8"
GRAPHICS_PATH = "/home/pi/RetroPie/Conjurer_graphics/"
DIR_PATH_SADOX = "/home/pi/RetroPie/Fansadox/"
GRAPHICS_PATH = "/home/pi/MediaShare/Conjurer_graphics/"
DIR_PATH_SADOX = "/home/pi/MediaShare/Fansadox/"
elif platform == "win32":
@@ -120,6 +120,9 @@ SPOTIFY_CTRL = spotipy.Spotify(
client_secret=authTokens[2],
)
)
REMOTE_HOST_NAME = "youtube"
authTokens = netrc_mod.authenticators(REMOTE_HOST_NAME)
YOUTUBE_AUTH = [authTokens[0],authTokens[2]]
WORD_REACTIONS = DATA["word_reactions"]
CYCLIC_WORDS = DATA["cyclic_words"]
+3
View File
@@ -0,0 +1,3 @@
Package: ffmpeg libavcodec-dev libavcodec59 libavdevice59 libavfilter8 libavformat-dev libavformat59 libavutil-dev libavutil57 libpostproc56 libswresample-dev libswresample4 libswscale-dev libswscale6 libavdevice-dev libavfilter-dev libpostproc-dev
Pin: origin deb.debian.org
Pin-Priority: 1001
+11 -9
View File
@@ -1,20 +1,22 @@
#!/bin/bash
sudo apt-get install python3-dev
sudo apt-get install portaudio19-dev python3-pyaudio
sudo apt-get install
cd /home/pi || exit
mdkir Conjurer
cd Conjurer ||exit
python3 -m venv /home/pi/Conjurer/.venv
python3 -m venv /home/pi/Conjurer/.env
cp /home/pi/conjurer/requirements_bot.txt /home/pi/Conjurer/
# trunk-ignore(shellcheck/SC1091)
source /home/pi/Conjurer/.venv/bin/activate
./env/bin/python3 -m pip install --upgrade pip
./env/bin/python3 -m pip install -r requirements_bot.txt
sed -i -e 's/os.rename/shutil.copy/g' ./env/lib/python3.11/site-packages/spotify_dl/youtube.py
sed -i '1i\import shutil' ./env/lib/python3.11/site-packages/spotify_dl/youtube.py
sed -i '1i\import logging' ./env/lib/python3.11/site-packages/spotify_dl/spotify.py
source /home/pi/Conjurer/.env/bin/activate
./.env/bin/python3 -m pip install --upgrade pip
./.env/bin/python3 -m pip install -r requirements_bot.txt
sed -i -e 's/os.rename/shutil.copy/g' ./.env/lib/python3.11/site-packages/spotify_dl/youtube.py
sed -i '1i\import shutil' ./.env/lib/python3.11/site-packages/spotify_dl/youtube.py
sed -i '1i\import logging' ./.env/lib/python3.11/site-packages/spotify_dl/spotify.py
sed -i '21i\ logger = logging.getLogger("discord")' ./env/lib/python3.11/site-packages/spotify_dl/spotify.py
sed -i '22i\ logger.info("Playlist")' ./env/lib/python3.11/site-packages/spotify_dl/spotify.py
sed -i '21i\ logger = logging.getLogger("discord")' ./.env/lib/python3.11/site-packages/spotify_dl/spotify.py
sed -i '22i\ logger.info("Playlist")' ./.env/lib/python3.11/site-packages/spotify_dl/spotify.py
#add sed changing signal registration to catch exception in spotify dl init
deactivate
sudo cp ./conjurer.service /etc/systemd/system/
+6 -2
View File
@@ -25,8 +25,12 @@ sudo usermod -aG pulse-access root
sudo usermod -aG audio pi
sudo usermod -aG audio root
echo "Add exception suppresion to signal handler in spotify __ini__.py"
echo "Add password to youtube opts in spotify_dl youtube.py"
echo "Downgrade ffmpeg by copying ffmpeg.pref from repository to /etc/apt/preferences.d"
echo "Install opam from installation link"
echo "Initialize opam"
echo "Install liquidsoap and its dependencies"
touch /home/pi/Conjurer/radio_log.log
./env/bin/python3 -m pip install --upgrade pip
+101
View File
@@ -0,0 +1,101 @@
# === SYSTEM SETUP ===
sudo apt update && sudo apt install -y \
pulseaudio pulseaudio-utils pavucontrol \
libgtk-3-dev gtk-3-examples \
xauth dbus-x11 \
samba
# === SAMBA CONFIGURATION ===
sudo nano /etc/samba/smb.conf
# Add at the end of the file:
# [RaspberryPiNAS]
# path = /home/pi/Public
# comment = Pi Share
# browseable = yes
# writeable = yes
# guest ok = no
# valid users = pi
# Set permissions
chmod 755 /home/pi
mkdir -p /home/pi/Public
chmod 777 /home/pi/Public
chown -R pi:pi /home/pi/Public
# Set Samba password for pi
sudo smbpasswd -a pi
# Restart Samba
sudo systemctl restart smbd
# === PULSEAUDIO SYSTEM-WIDE SERVICE ===
sudo nano /etc/systemd/system/pulseaudio.service
# Paste this content:
# [Unit]
# Description=PulseAudio System-wide Daemon
# After=sound.target network.target
#
# [Service]
# Type=simple
# ExecStart=/usr/bin/pulseaudio --system --disallow-exit --disallow-module-loading=0 --daemonize=no
# Restart=always
#
# [Install]
# WantedBy=multi-user.target
# === PULSEAUDIO MODULES FOR LEXICON LAMBDA USB ===
sudo nano /etc/pulse/system.pa
# Comment out:
# load-module module-udev-detect
# load-module module-detect
# Add this at the bottom:
# load-module module-alsa-sink device=hw:1,0 sink_name=LambdaOutput sink_properties=device.description="Lexicon_Lambda_USB_Output"
# load-module module-alsa-source device=hw:1,0 source_name=LambdaInput source_properties=device.description="Lexicon_Lambda_USB_Input"
# load-module module-native-protocol-unix auth-anonymous=1 socket=/tmp/pulseaudio.socket
# Set client default socket
sudo nano /etc/pulse/client.conf
# Add this line:
# default-server = unix:/tmp/pulseaudio.socket
# Enable and start PulseAudio system-wide
sudo systemctl daemon-reload
sudo systemctl enable pulseaudio.service
sudo systemctl restart pulseaudio.service
# === X11 & GUI FIXES FOR SSH/MOBAXTERM ===
sudo nano /etc/ssh/sshd_config
# Ensure these lines are present:
# X11Forwarding yes
# X11UseLocalhost no
# XAuthLocation /usr/bin/xauth
# Restart SSH
sudo systemctl restart ssh
# Ensure xauth is installed
sudo apt install -y xauth
# === BASHRC: MAKE GUI EXPORTS PERSISTENT ===
nano ~/.bashrc
# Add this at the end:
# export GDK_BACKEND=x11
# export LIBGL_ALWAYS_INDIRECT=1
# export NO_AT_BRIDGE=1
# export $(dbus-launch)
# Reload bashrc immediately
source ~/.bashrc
# === TESTING GUI ===
# (Reconnect via MobaXterm SSH with X11 forwarding enabled before running below)
# Run pavucontrol GUI
pavucontrol &
# Optional: Test GTK GUI rendering
gtk3-demo &
# Check audio devices
pactl list sinks short
pactl list sources short
+11 -5
View File
@@ -16,11 +16,11 @@ from constants import (
MUSIC_FOLDER,
SEND_MP3,
SPOTIFY_CTRL,
YOUTUBE_AUTH,
)
from spotify_dl import spotify
from spotify_dl import youtube as youtube_download
logger = logging.getLogger("discord")
class MusicFileList(object):
@@ -29,10 +29,11 @@ class MusicFileList(object):
file service or local directory and update the list with new items.
"""
def __init__(self, uplogger,) -> None:
def __init__(self, logger_name) -> None:
self.music_file_list = []
self.file_service_active = False
self.logger = uplogger
self.logger = logging.getLogger("discord")
self.logger.info("Created Playlist organizer class")
async def refresh_file_list(self, bot):
@@ -100,7 +101,7 @@ class MusicFileList(object):
requests.post(f"{FILE_SERVICE_ADDRESS}{SEND_MP3}", json=post_data, timeout=360)
MUSIC_FILE_LIST = MusicFileList(logger)
MUSIC_FILE_LIST = MusicFileList("discord")
async def get_file(ctx, source, link):
@@ -118,6 +119,7 @@ async def get_file(ctx, source, link):
: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 = []
@@ -160,6 +162,7 @@ async def get_file(ctx, source, link):
file_name_f=file_name_f,
multi_core=0,
proxy="",
YT_AUTH = YOUTUBE_AUTH
)
_ = await coro
logger.info("YT-DL done")
@@ -202,6 +205,8 @@ async def get_file(ctx, source, link):
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",
@@ -257,7 +262,7 @@ async def get_file(ctx, source, link):
]
# TODO: Make sponsorblock work
sponsorblock_postprocessor = []
dir_path = "/home/pi/RetroPie/movies/porn"
dir_path = "/home/pi/MediaShare/movies/porn"
ydl_opts = {
"postprocessors": sponsorblock_postprocessor,
"paths": {"home": dir_path},
@@ -288,6 +293,7 @@ async def search_music(ctx, how_many=0, slowa_kluczowe=None):
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:
+16
View File
@@ -66,6 +66,22 @@ class OtherModule(commands.Cog):
"""
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",
+14 -2
View File
@@ -1,4 +1,6 @@
import logging
# define an asynchronous generator
async def async_iterator_generator(range_of_iterable):
"""
Generate asynchronouse iterator.
@@ -86,20 +88,30 @@ async def get_stats(client, ctx, history_limit):
yield name, how_many
async def discord_friendly_reply(ctx, message_content, file=None):
logger = logging.getLogger("discord")
if len(message_content) < 999:
logger.info("Answer reply - message below 999")
await ctx.reply(message_content)
else:
while len(message_content) > 999:
logger.info("Answer reply - message above 999")
while len(message_content) > 0:
logger.info("Mesaage content: %s", message_content[:999])
await ctx.reply(message_content[:999])
message_content = message_content[999:]
if file:
await ctx.reply("Attachment:", file=file)
async def discord_friendly_send(ctx, message_content, file=None):
logger = logging.getLogger("discord")
if len(message_content) < 999:
logger.info("Answer send - message below 999")
await ctx.send(message_content)
else:
while len(message_content) > 999:
logger.info("Answer send - message above 999")
while len(message_content) > 0:
logger.info("Mesaage content: %s", message_content[:999])
await ctx.send(message_content[:999])
message_content = message_content[999:]
if file:
+11
View File
@@ -0,0 +1,11 @@
[Unit]
Description=PulseAudio System-wide Daemon
After=sound.target network.target
[Service]
Type=simple
ExecStart=/usr/bin/pulseaudio --system --disallow-exit --disallow-module-loading=0 --daemonize=no
Restart=always
[Install]
WantedBy=multi-user.target
+1 -1
View File
@@ -17,4 +17,4 @@ waitress
clickupython
assemblyai[extras]
SpeechRecognition
git+https://github.com/imayhaveborkedit/discord-ext-voice-recvO
git+https://github.com/imayhaveborkedit/discord-ext-voice-recv
+4 -2
View File
@@ -8,5 +8,7 @@ def signal_handler(sig, frame):
print("\nCaught interrupt(did you press Ctrl+C?), stopping spotify_dl")
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
try:
signal.signal(signal.SIGINT, signal_handler)
except ValueError:
print("Exception in signal handler")
+1 -1
View File
@@ -3,7 +3,7 @@ from pathlib import Path
__all__ = ["VERSION"]
VERSION = "8.8.1"
VERSION = "8.9.0"
if os.getenv("XDG_CACHE_HOME") is not None:
SAVE_PATH = os.getenv("XDG_CACHE_HOME") + "/spotifydl"
+52 -16
View File
@@ -1,15 +1,17 @@
import sys
import logging
from spotify_dl.scaffold import log
from spotify_dl.utils import sanitize
from rich.progress import Progress
def fetch_tracks(sp, item_type, url):
def fetch_tracks(sp, item_type, item_id):
"""
Fetches tracks from the provided URL.
Fetches tracks from the provided item_id.
:param sp: Spotify client
:param item_type: Type of item being requested for: album/playlist/track
:param url: URL of the item
:param item_id: id of the item
:return Dictionary of song and artist
"""
songs_list = []
@@ -17,11 +19,14 @@ def fetch_tracks(sp, item_type, url):
songs_fetched = 0
if item_type == "playlist":
logger = logging.getLogger("discord")
logger.info("Playlist")
with Progress() as progress:
songs_task = progress.add_task(description="Fetching songs from playlist..")
while True:
items = sp.playlist_items(
playlist_id=url,
playlist_id=item_id,
fields="items.track.name,items.track.artists(name, uri),"
"items.track.album(name, release_date, total_tracks, images),"
"items.track.track_number,total, next,offset,"
@@ -30,6 +35,7 @@ def fetch_tracks(sp, item_type, url):
offset=offset,
)
total_songs = items.get("total")
logger.info(total_songs)
track_info_task = progress.add_task(
description="Fetching track info", total=len(items["items"])
)
@@ -37,16 +43,32 @@ def fetch_tracks(sp, item_type, url):
track_info = item.get("track")
# If the user has a podcast in their playlist, there will be no track
# Without this conditional, the program will fail later on when the metadata is fetched
logger.info(item)
if track_info is None:
offset += 1
continue
if not track_info.get("artists")[0]["name"]:
offset +=1
continue
track_album_info = track_info.get("album")
track_num = track_info.get("track_number")
spotify_id = track_info.get("id")
track_name = track_info.get("name")
track_artist = ", ".join(
[artist["name"] for artist in track_info.get("artists")]
)
spotify_id = track_info.get("id")
track_audio_data = "No audio data"
try:
track_audio_data = sp.audio_analysis(spotify_id)
tempo = track_audio_data.get("track").get("tempo")
except:
log.error("Couldn't fetch audio analysis for %s", track_name)
tempo = None
print(track_info.get("artists"))
print(track_audio_data)
track_artist = ""
for artist in track_info.get("artists"):
if artist["name"]:
track_artist = ", ".join(
[artist["name"]]
)
if track_album_info:
track_album = track_album_info.get("name")
track_year = (
@@ -86,6 +108,7 @@ def fetch_tracks(sp, item_type, url):
"genre": genre,
"spotify_id": spotify_id,
"track_url": None,
"tempo": tempo,
}
)
offset += 1
@@ -111,8 +134,8 @@ def fetch_tracks(sp, item_type, url):
description="Fetching songs from the album.."
)
while True:
album_info = sp.album(album_id=url)
items = sp.album_tracks(album_id=url, offset=offset)
album_info = sp.album(album_id=item_id)
items = sp.album_tracks(album_id=item_id, offset=offset)
total_songs = items.get("total")
track_album = album_info.get("name")
track_year = (
@@ -141,6 +164,12 @@ def fetch_tracks(sp, item_type, url):
)
track_num = item["track_number"]
spotify_id = item.get("id")
try:
track_audio_data = sp.audio_analysis(spotify_id)
tempo = track_audio_data.get("track").get("tempo")
except:
log.error("Couldn't fetch audio analysis for %s", track_name)
tempo = None
songs_list.append(
{
"name": track_name,
@@ -154,6 +183,7 @@ def fetch_tracks(sp, item_type, url):
"cover": cover,
"genre": genre,
"spotify_id": spotify_id,
"tempo": tempo,
}
)
offset += 1
@@ -168,7 +198,7 @@ def fetch_tracks(sp, item_type, url):
break
elif item_type == "track":
items = sp.track(track_id=url)
items = sp.track(track_id=item_id)
track_name = items.get("name")
album_info = items.get("album")
track_artist = ", ".join([artist["name"] for artist in items["artists"]])
@@ -182,6 +212,12 @@ def fetch_tracks(sp, item_type, url):
album_total = album_info.get("total_tracks")
track_num = items["track_number"]
spotify_id = items["id"]
try:
track_audio_data = sp.audio_analysis(spotify_id)
tempo = track_audio_data.get("track").get("tempo")
except:
log.error("Couldn't fetch audio analysis for %s", track_name)
tempo = None
if len(items["album"]["images"]) > 0:
cover = items["album"]["images"][0]["url"]
else:
@@ -203,6 +239,7 @@ def fetch_tracks(sp, item_type, url):
"genre": genre,
"track_url": None,
"spotify_id": spotify_id,
"tempo": tempo,
}
)
@@ -219,9 +256,10 @@ def parse_spotify_url(url):
if url.startswith("spotify:"):
log.error("Spotify URI was provided instead of a playlist/album/track URL.")
sys.exit(1)
parsed_url = url.replace("https://open.spotify.com/", "").split("?")[0]
item_type = parsed_url.split("/")[0]
item_id = parsed_url.split("/")[1]
parsed_url = url.replace("https://open.spotify.com/", "").split("?")[0].split("/")
index_adjustment = 1 if parsed_url[0].startswith("intl") else 0
item_type = parsed_url[0+index_adjustment]
item_id = parsed_url[1+index_adjustment]
return item_type, item_id
@@ -239,8 +277,6 @@ def get_item_name(sp, item_type, item_id):
name = sp.album(album_id=item_id).get("name")
elif item_type == "track":
name = sp.track(track_id=item_id).get("name")
elif item_type == "artist_top_tracks":
name = sp.artist_top_tracks(artist_id=item_id).get("name")
return sanitize(name)
+1 -1
View File
@@ -198,7 +198,7 @@ def spotify_dl():
)
url_dict["save_path"].mkdir(parents=True, exist_ok=True)
log.info("Saving songs to %s directory", directory_name)
url_dict["songs"] = fetch_tracks(sp, item_type, url)
url_dict["songs"] = fetch_tracks(sp, item_type, item_id)
url_data["urls"].append(url_dict.copy())
if args.dump_json is True:
dump_json(url_dict["songs"])
+11 -11
View File
@@ -1,9 +1,9 @@
import shutil
import urllib.request
from os import path
import os
import multiprocessing
import shutil
import json
import mutagen
import csv
@@ -65,13 +65,13 @@ def write_tracks(tracks_file, song_dict):
i = 0
writer = csv.writer(file_out, delimiter=";")
for url_dict in song_dict["urls"]:
# for track in url_dict['songs']:
for track in url_dict["songs"]:
track_url = track["track_url"] # here
track_name = track["name"]
track_artist = track["artist"]
track_num = track["num"]
track_album = track["album"]
track_tempo = track["tempo"]
track["save_path"] = url_dict["save_path"]
track_db.append(track)
track_index = i
@@ -82,6 +82,7 @@ def write_tracks(tracks_file, song_dict):
track_url,
str(track_num),
track_album,
str(track_tempo),
str(track_index),
]
try:
@@ -97,8 +98,8 @@ def write_tracks(tracks_file, song_dict):
def set_tags(temp, filename, kwargs):
"""
sets song tags after they are downloaded
:param temp: contains index used to obtain more info about song being edited
:param filename: location of song whose tags are to be edited
:param temp: contains index used to obtain more info about song being editted
:param filename: location of song whose tags are to be editted
:param kwargs: a dictionary of extra arguments to be used in tag editing
"""
song = kwargs["track_db"][int(temp[-1])]
@@ -120,6 +121,8 @@ def set_tags(temp, filename, kwargs):
)
song_file["genre"] = song.get("genre")
if song.get("tempo") is not None:
song_file["bpm"] = str(song.get("tempo"))
song_file.save()
song_file = MP3(filename, ID3=ID3)
cover = song.get("cover")
@@ -162,7 +165,7 @@ def find_and_download_songs(kwargs):
print(f"Initiating download for {query}.")
file_name = kwargs["file_name_f"](
name=name, artist=artist, track_num=kwargs["track_db"][i].get("num")
name=name, artist=artist, track_num=kwargs["track_db"][i].get("playlist_num")
)
if kwargs["use_sponsorblock"][0].lower() == "y":
@@ -197,9 +200,10 @@ def find_and_download_songs(kwargs):
):
print(f"File {mp3file_path} already exists, we do not overwrite it ")
continue
outtmpl = f"{file_path}.%(ext)s"
ydl_opts = {
"username":kwargs["YT_AUTH"][0],
"password":kwargs["YT_AUTH"][1],
"proxy": kwargs.get("proxy"),
"default_search": "ytsearch",
"format": "bestaudio/best",
@@ -312,11 +316,7 @@ def download_songs(**kwargs):
log.debug("Downloading to %s", url["save_path"])
reference_file = DOWNLOAD_LIST
track_db = write_tracks(reference_file, kwargs["songs"])
try:
shutil.copy(reference_file, kwargs["output_dir"] + "/" + reference_file)
os.remove(reference_file)
except:
os.rename(reference_file, kwargs["output_dir"] + "/" + reference_file)
shutil.copy(reference_file, kwargs["output_dir"] + "/" + reference_file)
reference_file = str(kwargs["output_dir"]) + "/" + reference_file
kwargs["reference_file"] = reference_file
kwargs["track_db"] = track_db
+10
View File
@@ -0,0 +1,10 @@
[Unit]
Description=Check Raspberry Pi Parameters
After=network.target
[Service]
Type=oneshot
ExecStart=/bin/bash -c '/home/pi/conjurer/status_report.sh >> /home/pi/Conjurer/discord.log'
[Install]
WantedBy=multi-user.target
+38
View File
@@ -0,0 +1,38 @@
#!/bin/bash
# Script to check and display Raspberry Pi parameters using libgpiod
echo "=== Raspberry Pi System Information ==="
# General system information
echo "Hostname: $(hostname)"
echo "Model: $(cat /proc/device-tree/model | tr -d '\0')"
echo "CPU Temperature: $(vcgencmd measure_temp | cut -d '=' -f2)"
echo "CPU Frequency: $(vcgencmd measure_clock arm | awk -F= '{print $2}') Hz"
echo "GPU Frequency: $(vcgencmd measure_clock core | awk -F= '{print $2}') Hz"
echo "Voltage: $(vcgencmd measure_volts | cut -d '=' -f2)"
# Memory and disk usage
echo "Total Memory: $(free -h | grep Mem | awk '{print $2}')"
echo "Used Memory: $(free -h | grep Mem | awk '{print $3}')"
echo "Free Memory: $(free -h | grep Mem | awk '{print $4}')"
echo "Disk Usage:"
df -h | grep '^/dev/root'
# Network information
echo "IP Address: $(hostname -I | awk '{print $1}')"
echo "MAC Address: $(cat /sys/class/net/eth0/address 2>/dev/null || echo 'No Ethernet')"
# Uptime
echo "Uptime: $(uptime -p)"
echo "Last Boot: $(who -b | awk '{print $3, $4}')"
# GPIO Information using libgpiod
echo "GPIO Chip Info:"
if command -v gpioinfo &>/dev/null; then
gpioinfo
else
echo "gpiod tools not installed. Please install libgpiod using 'sudo apt install gpiod'."
fi
echo "=== End of Raspberry Pi System Information ==="
+9
View File
@@ -0,0 +1,9 @@
[Unit]
Description=Run Check Raspberry Pi Parameters Script Hourly
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
Regular → Executable
+23 -16
View File
@@ -18,6 +18,18 @@ from discord.ext import commands
from communication_subroutine import comm_subroutine
from 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()
@@ -32,18 +44,6 @@ intents.moderation = True
# on_member_ban - wyswietl na glownym kanale pieczatke "Niech spierdala"
# on_member_unban - "mam wyjebane"
logger = logging.getLogger("discord")
logger.setLevel(logging.DEBUG)
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)
random.seed()
client = commands.Bot(intents=intents, command_prefix="$")
@@ -52,8 +52,12 @@ client = commands.Bot(intents=intents, command_prefix="$")
@client.event
async def on_ready():
"""Metoda wywoływana przy połączeniu do serwera."""
logger.debug("%s has connected to Discord!", client.user)
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")
@@ -64,13 +68,16 @@ async def on_ready():
await client.load_extension("other_commands")
await client.load_extension("voice_recognition_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 ---->", client.user)
logger.info("ID:", client.user.id)
logger.info("Logged in as ----> %s", client.user)
logger.info("ID:%s ", client.user.id)
logger.info("All systems: operational")
# *================================== Run
@@ -78,7 +85,7 @@ if __name__ == "__main__":
logger.info("Starting discord bot")
threads = []
logger.info("Starting discord bot: Creating threads")
threads.append(threading.Thread(target=client.run, args=(TOKEN,)))
threads.append(threading.Thread(target=client.run, args=(TOKEN,),kwargs={"log_handler":None}))
threads.append(threading.Thread(target=comm_subroutine))
logger.info("Starting discord bot: Starting threads")
WRK_CNT = 0