mirror of
https://github.com/migatu/conjurer.git
synced 2026-07-14 21:38:38 +00:00
5505022dbb
Hammertimespace Continuum
1055 lines
40 KiB
Python
1055 lines
40 KiB
Python
# This Python file uses the following encoding: utf-8
|
|
# *=========================================== Imports
|
|
import os
|
|
import discord
|
|
import json
|
|
import re
|
|
import netrc
|
|
from discord.ext import commands
|
|
import logging
|
|
import requests
|
|
from datetime import datetime
|
|
from sys import platform
|
|
import openai
|
|
import numpy as np
|
|
import pdf2image
|
|
import io
|
|
import PyPDF2
|
|
import random
|
|
import asyncio
|
|
from pathlib import PurePath
|
|
from pathlib import Path
|
|
import eyed3
|
|
import spotipy
|
|
from spotify_dl import spotify
|
|
from spotify_dl import youtube as youtube_download
|
|
import yt_dlp
|
|
from spotipy.oauth2 import SpotifyClientCredentials
|
|
import logging.handlers as handlers
|
|
import shutil
|
|
|
|
# *=========================================== Predefines
|
|
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
|
master_timeout = datetime.now()
|
|
INITIAL_TIME_WAIT = 5
|
|
MUZYKA = {"playing": False, "ctx": None, "queue": [], "requestor": []}
|
|
|
|
# *=========================================== Platform Specific Predefines
|
|
if platform == "linux" or platform == "linux2":
|
|
logfile = "/home/pi/Conjurer/discord.log"
|
|
memory_five_siara = "/home/pi/Conjurer/pamiec.json"
|
|
memory_five_muzyka = "/home/pi/Conjurer/pamiec_muzyki.json"
|
|
music_folder = "/home/pi/RetroPie/mp3/"
|
|
settings_file = "/home/pi/Conjurer/settings.json"
|
|
netrc_file = "/home/pi/.netrc"
|
|
logstore = "/home/pi/RetroPie/logs/"
|
|
accident_log = "/home/pi/accident_log.json"
|
|
|
|
elif platform == "win32":
|
|
logfile = "discord.log"
|
|
memory_five_siara = "pamiec.json"
|
|
memory_five_muzyka = "pamiec_muzyki.json"
|
|
# music_folder = 'G:\\Muzyka\\segars\\segars\\segars_&_friends_-_shanties_of_oldtime_sailing_ships\\'
|
|
music_folder = "G:\\Muzyka\\"
|
|
settings_file = "settings.json"
|
|
netrc_file = "C:\\Users\\mtusz\\.netrc"
|
|
logstore = "C:\\Users\\mtusz\\OneDrive\\Pulpit\\Conjurer\\logs\\"
|
|
accident_log = "accident_log.json"
|
|
|
|
|
|
# *=========================================== Keys
|
|
netrc = netrc.netrc(netrc_file)
|
|
remoteHostName = "discord"
|
|
authTokens = netrc.authenticators(remoteHostName)
|
|
TOKEN = authTokens[2]
|
|
|
|
remoteHostName = "openai"
|
|
authTokens = netrc.authenticators(remoteHostName)
|
|
openai.api_key = authTokens[2]
|
|
|
|
remoteHostName = "spotipy"
|
|
authTokens = netrc.authenticators(remoteHostName)
|
|
spotify_ctrl = spotipy.Spotify(
|
|
client_credentials_manager=SpotifyClientCredentials(
|
|
client_id=authTokens[0],
|
|
client_secret=authTokens[2],
|
|
)
|
|
)
|
|
|
|
# *=========================================== Initializations
|
|
intents = discord.Intents.default()
|
|
intents.message_content = True
|
|
intents.typing = True
|
|
intents.presences = True
|
|
intents.members = True
|
|
intents.messages = True
|
|
intents.voice_states = True
|
|
logger = logging.getLogger("discord")
|
|
logger.setLevel(logging.DEBUG)
|
|
handler = handlers.RotatingFileHandler(
|
|
filename=logfile,
|
|
encoding="utf-8",
|
|
mode="a",
|
|
maxBytes=6 * 1024 * 1024,
|
|
backupCount=6,
|
|
)
|
|
handler.setFormatter(formatter)
|
|
logger.addHandler(handler)
|
|
random.seed()
|
|
logger.debug(platform)
|
|
logger.info("Playlist generation")
|
|
|
|
|
|
# *=========================================== Load Data files
|
|
music_file_list = []
|
|
for item in Path.glob(Path(music_folder), "**/*.mp3"):
|
|
file = item.as_posix()
|
|
if platform == "win32":
|
|
file = file.replace("/", "\\")
|
|
music_file_list.append(file)
|
|
with open(memory_five_siara, "r+") as file:
|
|
# First we load existing data into a dict.
|
|
message_table = json.load(file)
|
|
with open(memory_five_muzyka, "r+") as file:
|
|
# First we load existing data into a dict.
|
|
message_table_muzyka = json.load(file)
|
|
f = open(settings_file)
|
|
data = json.load(f)
|
|
word_reactions = data["word_reactions"]
|
|
historia_fabryczki = data["fabryczka"]
|
|
for key in word_reactions:
|
|
word_reactions[key][2] = datetime.now()
|
|
|
|
# *=========================================== Create Client
|
|
client = commands.Bot(intents=intents, command_prefix="$")
|
|
# *=========================================== Define Events
|
|
|
|
|
|
@client.event
|
|
async def on_ready():
|
|
logger.debug(f"{client.user} has connected to Discrod!")
|
|
await client.change_presence(activity=discord.Game(name="Axe Throwing Darts"))
|
|
await check()
|
|
|
|
|
|
@client.event
|
|
async def on_message(message):
|
|
vykidailo = False
|
|
if message.author == client.user:
|
|
return
|
|
if isinstance(message.author, discord.Member):
|
|
for role in message.author.roles:
|
|
if role.name == "Vykidailo":
|
|
vykidailo = True
|
|
|
|
if ("Conjurer Śpij Słodko Aniołku" in message.content) and vykidailo:
|
|
exit()
|
|
#kanal bez bota
|
|
if message.channel.id == 1095985579147141202:
|
|
return
|
|
#wentylacja
|
|
if message.channel.id == 1083804024173764739:
|
|
return
|
|
#legendy
|
|
if message.channel.id == 1084448332841230388:
|
|
return
|
|
#interrogation booth
|
|
if message.channel.id == 1111625221171052595:
|
|
return
|
|
if isinstance(message.channel, discord.DMChannel):
|
|
channel = client.get_channel(1064888712565100614)
|
|
await channel.send("Słyszałem ja żem że: " + message.content)
|
|
else:
|
|
channel = message.channel
|
|
await client.process_commands(message)
|
|
|
|
#TODO: wpiac jego reakcje we framework chatu GPT
|
|
message.content = message.content.lower()
|
|
|
|
tdelta = datetime.now() - master_timeout
|
|
tdelta = tdelta.total_seconds()
|
|
if "opowiedz o fabryczce" in message.content:
|
|
await message.reply(historia_fabryczki)
|
|
if "opowiedz mi o fabryczce" in message.content:
|
|
await message.reply(historia_fabryczki)
|
|
|
|
if tdelta > INITIAL_TIME_WAIT:
|
|
for word in word_reactions:
|
|
if re.search(".*" + word + "[\s*,$]*", message.content):
|
|
|
|
tdelta = datetime.now() - word_reactions[word][2]
|
|
tdelta = tdelta.total_seconds()
|
|
reaction = word_reactions[word][3]
|
|
if tdelta > word_reactions[word][1]:
|
|
#TODO: to zrobic reactiony
|
|
logger.info("Ping z procedury reakcji")
|
|
if reaction:
|
|
emoji = client.get_emoji(word_reactions[word][0])
|
|
await message.add_reaction(emoji)
|
|
else:
|
|
await message.reply(word_reactions[word][0])
|
|
word_reactions[word][2] = datetime.now()
|
|
|
|
# TODO: drobne literówki, mentiony, spacja przed dwukropkiem. napraw.
|
|
|
|
if "conjurer:" in message.content:
|
|
async with channel.typing():
|
|
logger.debug("Procedura chatu")
|
|
message.content = message.content.replace("conjurer: ", "")
|
|
|
|
prompt = message.content
|
|
|
|
if message.author.nick:
|
|
username = message.author.nick
|
|
else:
|
|
username = message.author.name
|
|
vykidailo = False
|
|
bartender = False
|
|
for role in message.author.roles:
|
|
if role.name == "Vykidailo":
|
|
vykidailo = True
|
|
if role.name == "Bartender":
|
|
bartender = True
|
|
global message_table
|
|
result, message_table = await handle_response(
|
|
prompt, vykidailo, bartender, message_table, username, False
|
|
)
|
|
await message.reply(result)
|
|
if "imaginuje sobie:" in message.content:
|
|
async with channel.typing():
|
|
logger.info("Poczatek procedury obrazkowej")
|
|
message.content = message.content.replace("imaginuje sobie: ", "")
|
|
logger.debug("Wywolanie obrazka: {}".format(message.content))
|
|
response = openai.Image.create(
|
|
prompt=message.content, n=1, size="1024x1024"
|
|
)
|
|
image_url = response["data"][0]["url"]
|
|
logger.debug("Wynikowy obrazek pod url: {}".format(image_url))
|
|
response = requests.get(image_url)
|
|
file = response.content
|
|
|
|
file_name = message.content + ".png"
|
|
if platform == "linux" or platform == "linux2":
|
|
file_name = (
|
|
"/home/pi/RetroPie/Conjurer_graphics" + message.content + ".png"
|
|
)
|
|
elif platform == "win32":
|
|
file_name = message.content + ".png"
|
|
|
|
with open(file_name, "wb") as f:
|
|
f.write(response.content)
|
|
logger.info("Koniec procedury obrazkowej.")
|
|
fnord = discord.File(file_name, spoiler=False, description=message.content)
|
|
await message.reply(file=fnord)
|
|
|
|
|
|
# *=========================================== Define Functions
|
|
|
|
|
|
async def connect(ctx, arg=None):
|
|
voice_channel = client.get_channel(1060349757349974066)
|
|
if client.voice_clients:
|
|
voiceClient = client.voice_clients[0]
|
|
if voiceClient.is_connected():
|
|
return
|
|
vc = await voice_channel.connect()
|
|
logger.info("Connecting to voice")
|
|
|
|
|
|
async def disconnect(ctx):
|
|
if client.voice_clients:
|
|
voiceClient = client.voice_clients[0]
|
|
if voiceClient.is_connected():
|
|
await voiceClient.disconnect()
|
|
|
|
|
|
async def play(ctx, zamawial=None, arg=None):
|
|
# TODO: Uzupełnianie metadanych. Jeśli ich nie ma sprawdzamy nazwę (w sposób inteligentny - czyli jeśli składa się z samych cyfr i/lub słowa track to sprawdzić album w sensie folder)
|
|
# TODO: Jeśli w metadanych jest tylko "audiotrack" i "album" też po folderze. Jeśli są niekompletne uzupełnić dalej.
|
|
logger.info("Play procedure")
|
|
|
|
voiceClient = client.voice_clients[0]
|
|
file_to_play = None
|
|
if not client.voice_clients:
|
|
voiceClient = client.voice_clients[0]
|
|
if not voiceClient.is_connected():
|
|
await connect(ctx)
|
|
global MUZYKA
|
|
if MUZYKA["queue"]:
|
|
file_to_play = MUZYKA["queue"].pop()
|
|
zamawial = MUZYKA["requestor"].pop()
|
|
else:
|
|
index = random.randint(0, len(music_file_list) - 1)
|
|
file_to_play = music_file_list[index]
|
|
|
|
logger.debug(file_to_play)
|
|
metadata = eyed3.load(file_to_play)
|
|
query = None
|
|
if platform == "linux" or platform == "linux2":
|
|
separator = "/"
|
|
elif platform == "win32":
|
|
separator = "\\"
|
|
temp = file_to_play.split(separator)[-1]
|
|
kawalek = "Zagram teraz kawalek {} z prywatnej kolekcji Hammera.".format(temp)
|
|
if metadata:
|
|
if metadata.tag:
|
|
if metadata.tag.title:
|
|
query = "Opowiedz mi o kawałku {}".format(metadata.tag.title)
|
|
kawalek = "Zagram teraz kawalek {}".format(metadata.tag.title)
|
|
if metadata.tag.artist:
|
|
query += " wykonawcy {}".format(metadata.tag.artist)
|
|
kawalek += " wykonawcy {}".format(metadata.tag.artist)
|
|
if metadata.tag.album:
|
|
query += " z albumu {}".format(metadata.tag.album)
|
|
kawalek += " z albumu {}".format(metadata.tag.album)
|
|
kawalek += " z prywatnej kolekcji Hammera."
|
|
if zamawial:
|
|
kawalek += "Na specjalne życzenie <@{}>.".format(zamawial.id)
|
|
await ctx.send(kawalek)
|
|
|
|
voiceClient.play(
|
|
discord.PCMVolumeTransformer(
|
|
discord.FFmpegPCMAudio(source=file_to_play), volume=0.3
|
|
)
|
|
) # NIE DOTYKAC POKRĘTŁA GŁOŚNOŚCI!!!!
|
|
if query:
|
|
logger.debug("Zapytanie do openai")
|
|
logger.debug(query)
|
|
vykidailo = False
|
|
bartender = False
|
|
for role in ctx.message.author.roles:
|
|
if role.name == "Vykidailo":
|
|
vykidailo = True
|
|
if role.name == "Bartender":
|
|
bartender = True
|
|
if ctx.message.author.nick:
|
|
username = ctx.message.author.nick
|
|
else:
|
|
username = ctx.message.author.name
|
|
global message_table
|
|
result, message_table = await handle_response(
|
|
query, vykidailo, bartender, message_table_muzyka, username, True
|
|
)
|
|
logger.debug("Obecna historia czatu:{}".format(message_table_muzyka))
|
|
await ctx.send(result)
|
|
|
|
|
|
async def check():
|
|
while True:
|
|
# TODO: Tu dołożyć skanowanie rozmiaru pliku logowania oraz plików pamięci i przenoszenie ich na większy dysk.
|
|
# TODO: Dodać typing i dać znać że wykonuje operacje porządkowania Baru (zamiata, układa szklanki itp.)
|
|
# TODO: dlaczego sie tu wypierdala
|
|
if client.voice_clients:
|
|
voiceClient = client.voice_clients[0]
|
|
if voiceClient.is_connected():
|
|
global MUZYKA
|
|
while MUZYKA["playing"] and voiceClient.is_connected():
|
|
if voiceClient and not voiceClient.is_playing() and not voiceClient.is_paused():
|
|
await play(MUZYKA["ctx"], MUZYKA["requestor"])
|
|
await asyncio.sleep(0.1)
|
|
if os.path.getsize(logfile) > 600000:
|
|
shutil.copyfile(logfile,"{}discord{}.log".format(logstore, datetime.now()))
|
|
logger.info("Log rollover")
|
|
handler.doRollover()
|
|
|
|
if os.path.getsize(memory_five_muzyka) > 300000:
|
|
channel = client.get_channel(1062047571557744721)
|
|
await channel.send("*Conjurer porządkuje bar, wypala szklanki do czysta miotaczem płomieni ze swojej zbroi i ogólnie wygląda na zajętego....*")
|
|
with channel.typing():
|
|
path_newfile = "{}{}{}.json".format(logstore, memory_five_muzyka[:-4],datetime.now())
|
|
with open(memory_five_muzyka, "r+") as file:
|
|
with open(path_newfile, "x") as new_file:
|
|
# First we load existing data into a dict.
|
|
file_data = json.load(file)
|
|
new_data = []
|
|
new_data.append(file_data[0])
|
|
new_data.extend(file_data[:-20])
|
|
file.seek(0)
|
|
# convert back to json.
|
|
new_file.seek(0)
|
|
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* ...sać powieści o naszym wspaniałym barze SZEFIE!")
|
|
if os.path.getsize(memory_five_siara)> 300000:
|
|
path_newfile = "{}{}{}.json".format(logstore, memory_five_siara[:-4],datetime.now())
|
|
await channel.send("*Conjurer porządkuje bar, ścina lekkim laserem pulsacyjnym powierzchnie baru o grubości kilku mikronów i ogólnie wygląda na zajętego....*")
|
|
with open(memory_five_siara, "r+") as file:
|
|
with open(path_newfile, "x") as new_file:
|
|
# First we load existing data into a dict.
|
|
file_data = json.load(file)
|
|
new_data = []
|
|
new_data.append(file_data[0])
|
|
new_data.extend(file_data[:-20])
|
|
file.seek(0)
|
|
new_file.seek(0)
|
|
# convert back to json.
|
|
json.dump(new_data, file, indent=4)
|
|
json.dump(file_data, new_file, indent=4)
|
|
await channel.send("*Przeciąga się za barem* No dobra - porobione to można dalej pi... *Zauważa spojrzenie Hammera* eprzyć o głupotach z klientami... Szefie... *Bierze 'ukradkowy' łyk z piersiówki*")
|
|
await asyncio.sleep(60)
|
|
|
|
|
|
async def handle_response(prompt, vykidailo, bartender, history, username, music):
|
|
# TODO: Wykrywać "Pracuję nad odpowiedzią i tego typu rzeczy"
|
|
logger.info("Wywolanie procedury openai z promptem: {}".format(prompt))
|
|
temp = {"role": "user", "content": username + ":" + prompt}
|
|
|
|
history.append(temp)
|
|
if music:
|
|
with open(memory_five_muzyka, "r+") as file:
|
|
# First we load existing data into a dict.
|
|
file_data = json.load(file)
|
|
# Join new_data with file_data inside emp_details
|
|
file_data.append(temp)
|
|
file.seek(0)
|
|
# convert back to json.
|
|
json.dump(file_data, file, indent=4)
|
|
else:
|
|
with open(memory_five_siara, "r+") as file:
|
|
# First we load existing data into a dict.
|
|
file_data = json.load(file)
|
|
# Join new_data with file_data inside emp_details
|
|
file_data.append(temp)
|
|
file.seek(0)
|
|
# convert back to json.
|
|
json.dump(file_data, file, indent=4)
|
|
history = []
|
|
# * append bo pierwszy index
|
|
# * extend bo 20 ostatnich
|
|
if music:
|
|
history.append(message_table_muzyka[0])
|
|
history.extend(message_table_muzyka[-20:])
|
|
else:
|
|
history.append(message_table[0])
|
|
history.extend(message_table[-20:])
|
|
logger.info("Historia wysłana:")
|
|
logger.debug(history)
|
|
response = await openai.ChatCompletion.acreate(
|
|
model="gpt-3.5-turbo", messages=history
|
|
)
|
|
await asyncio.sleep(10)
|
|
result = ""
|
|
logger.debug("Odpowiedzi")
|
|
logger.debug(response.choices)
|
|
for choice in response.choices:
|
|
result += choice.message.content
|
|
logger.info("Sformatowane odpowiedzi")
|
|
logger.info(result)
|
|
temp = {"role": "assistant", "content": result}
|
|
history.append(temp)
|
|
if music:
|
|
with open(memory_five_muzyka, "r+") as file:
|
|
# First we load existing data into a dict.
|
|
file_data = json.load(file)
|
|
# Join new_data with file_data inside emp_details
|
|
file_data.append(temp)
|
|
# Sets file's current position at offset.
|
|
file.seek(0)
|
|
# convert back to json.
|
|
json.dump(file_data, file, indent=4)
|
|
else:
|
|
with open(memory_five_siara, "r+") as file:
|
|
# First we load existing data into a dict.
|
|
file_data = json.load(file)
|
|
# Join new_data with file_data inside emp_details
|
|
file_data.append(temp)
|
|
# Sets file's current position at offset.
|
|
file.seek(0)
|
|
# convert back to json.
|
|
json.dump(file_data, file, indent=4)
|
|
return result, message_table
|
|
|
|
|
|
async def get_file(ctx, source, link):
|
|
item_id = None
|
|
item_type = None
|
|
file_list = {}
|
|
if source == "Spotify":
|
|
dir_path = None
|
|
item_type, item_id = spotify.parse_spotify_url(link)
|
|
if item_id:
|
|
file_list = spotify.fetch_tracks(spotify_ctrl, item_type, link)
|
|
directory_name = spotify.get_item_name(spotify_ctrl, item_type, item_id)
|
|
url_data = {"urls": []}
|
|
url_dict = {}
|
|
url_dict["save_path"] = Path(
|
|
PurePath.joinpath(Path(music_folder), Path(directory_name))
|
|
)
|
|
url_dict["save_path"].mkdir(parents=True, exist_ok=True)
|
|
url_dict["songs"] = file_list
|
|
url_data["urls"].append(url_dict.copy())
|
|
file_name_f = youtube_download.default_filename
|
|
youtube_download.download_songs(
|
|
songs=url_data,
|
|
output_dir=music_folder,
|
|
format_str="bestaudio/best",
|
|
skip_mp3=False,
|
|
keep_playlist_order=False,
|
|
no_overwrites=True,
|
|
remove_trailing_tracks="no",
|
|
use_sponsorblock="yes",
|
|
file_name_f=file_name_f,
|
|
multi_core=0,
|
|
proxy="",
|
|
)
|
|
dir_path = (url_dict["save_path"].resolve()).as_posix()
|
|
if platform == "win32":
|
|
dir_path = dir_path.replace("/", "\\")
|
|
return dir_path, file_list
|
|
else:
|
|
await ctx.send(
|
|
"No se jaja chyba robisz, Ty byś spotifaja nie poznawszy jakby z krzaków wyskoczył i w dupę kopnął. Plejlista, kawałek albo album prosze."
|
|
)
|
|
logger.error("Wrong link provided spotify: {}".format(link))
|
|
elif source == "Youtube":
|
|
link_ok = False
|
|
pat = r"^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$"
|
|
if re.match(pat, link) and re.match(".*youtube.*", link):
|
|
link_ok = True
|
|
|
|
if link_ok:
|
|
dir_path = ""
|
|
file_list = []
|
|
query = link
|
|
sponsorblock_postprocessor = [
|
|
{
|
|
"key": "SponsorBlock",
|
|
"categories": ["skip_non_music_sections"],
|
|
},
|
|
{
|
|
"key": "ModifyChapters",
|
|
"remove_sponsor_segments": ["music_offtopic"],
|
|
"force_keyframes": True,
|
|
},
|
|
]
|
|
if platform == "win32":
|
|
dir_path = "G:\\Muzyka\Youtube"
|
|
else:
|
|
dir_path = "/home/pi/RetroPie/mp3/Youtube"
|
|
ydl_opts = {
|
|
"proxy": "",
|
|
"default_search": "ytsearch",
|
|
"format": "bestaudio/best",
|
|
"postprocessors": sponsorblock_postprocessor,
|
|
"noplaylist": True,
|
|
"no_color": False,
|
|
"paths": {"home": dir_path},
|
|
}
|
|
mp3_postprocess_opts = {
|
|
"key": "FFmpegExtractAudio",
|
|
"preferredcodec": "mp3",
|
|
"preferredquality": "192",
|
|
}
|
|
ydl_opts["postprocessors"].append(mp3_postprocess_opts.copy())
|
|
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
|
try:
|
|
ydl.download([query])
|
|
except Exception as e: # skipcq: PYL-W0703
|
|
logger.error(e)
|
|
logger.info(
|
|
f"Failed to download {link}, make sure yt_dlp is up to date"
|
|
)
|
|
extract = re.search("v=(...........)[&,$]*", link)
|
|
id = extract.group(1)
|
|
for item in Path.glob(Path(dir_path), "**/*.mp3"):
|
|
file = item.as_posix()
|
|
if platform == "win32":
|
|
file = file.replace("/", "\\")
|
|
if re.match(".*" + id + ".*", file):
|
|
file_list.append(file)
|
|
return dir_path, file_list
|
|
else:
|
|
await ctx.send(
|
|
"No se jaja chyba robisz, Ty byś jutuba nie poznawszy jakby z krzaków wyskoczył i w dupę kopnął. Jutuba to nie tuba którą sobie można gdzieś wsadzić."
|
|
)
|
|
logger.error("Wrong link provided youtube: {}".format(link))
|
|
return "", None
|
|
|
|
|
|
async def wyszukaj(ctx, how_many=0):
|
|
# TODO: Potem dorobić wyszukiwania po kawałkach słów i sieć neuronową z możliwością wyrażenia opinii o dopasowaniu.
|
|
word_list = ctx.message.content.split()
|
|
logger.info("Wyszukuje")
|
|
global music_file_list
|
|
search_weight = []
|
|
for i in range(len(music_file_list)):
|
|
search_weight.append((0, ""))
|
|
|
|
time_start = datetime.now()
|
|
if int(how_many) > 0:
|
|
skip_start = 2
|
|
else:
|
|
skip_start = 1
|
|
for word in word_list[skip_start:]:
|
|
token_weight = len(word)
|
|
logger.info("Słowo kluczowe: {}".format(word))
|
|
itr = 0
|
|
for file in music_file_list:
|
|
if platform == "win32":
|
|
file = file.split("\\")
|
|
else:
|
|
file = file.split("/")
|
|
char_remove = [
|
|
".",
|
|
"^",
|
|
"$",
|
|
"*",
|
|
"+",
|
|
"?",
|
|
"{",
|
|
"}",
|
|
"[",
|
|
"]",
|
|
"\\",
|
|
"|",
|
|
"(",
|
|
")",
|
|
"!",
|
|
",",
|
|
"-",
|
|
":",
|
|
"mp3",
|
|
]
|
|
all_words = []
|
|
for f in file:
|
|
for char in char_remove:
|
|
f = f.replace(char, "")
|
|
tmp = f.split()
|
|
all_words.extend(tmp)
|
|
pingu = 1
|
|
pattern_len = len(all_words)
|
|
if platform == "win32":
|
|
skip = 2
|
|
else:
|
|
skip = 4
|
|
matched_times = 1
|
|
for itm in all_words[skip:]:
|
|
pingu += 1
|
|
pattern = ".*" + word + ".*"
|
|
if re.match(pattern, itm, re.IGNORECASE):
|
|
temp_weight = (
|
|
search_weight[itr][0]
|
|
+ (token_weight + (pingu**1.5) / pattern_len) / matched_times
|
|
)
|
|
search_weight[itr] = temp_weight, music_file_list[itr]
|
|
matched_times += 1
|
|
itr += 1
|
|
|
|
logger.info(
|
|
"Stworzylem tablice wag zajęło mi to {}".format(datetime.now() - time_start)
|
|
)
|
|
time_start = datetime.now()
|
|
item_to_search = await max_weight(search_weight)
|
|
itr = 0
|
|
if item_to_search == 0:
|
|
return None
|
|
not_found = True
|
|
return_list = []
|
|
if int(how_many) <= 0:
|
|
logger.info("Jeden plik do zagrania")
|
|
while not_found:
|
|
if search_weight[itr][0] == item_to_search:
|
|
return_list.append(search_weight[itr])
|
|
return return_list
|
|
itr += 1
|
|
else:
|
|
logger.info("Wiele plików do zagrania")
|
|
search_weight.sort(key = lambda x: x[0],reverse=True)
|
|
return_list.extend(search_weight[:int(how_many)])
|
|
return return_list
|
|
|
|
|
|
|
|
async def max_weight(list):
|
|
max_weight = 0
|
|
for iter in list:
|
|
if iter[0] > max_weight:
|
|
max_weight = iter[0]
|
|
return max_weight
|
|
|
|
|
|
# *=========================================== Define Commands
|
|
|
|
|
|
@client.command()
|
|
async def dej_co_ze_spotifaja(ctx):
|
|
logger.info("Spotifaj")
|
|
await ctx.send("Dej mnie chwilkę")
|
|
async with ctx.typing():
|
|
# wyciagnij linka z kontekstu
|
|
content = ctx.message.content.split()
|
|
for item in content:
|
|
if re.match("http.*", item):
|
|
dir_path, files = await get_file(ctx, "Spotify", item)
|
|
if platform == "win32":
|
|
separator = "\\"
|
|
else:
|
|
separator = "/"
|
|
for file in files:
|
|
global MUZYKA
|
|
MUZYKA["queue"].insert(
|
|
0,
|
|
dir_path
|
|
+ separator
|
|
+ file["artist"]
|
|
+ " - "
|
|
+ file["name"]
|
|
+ ".mp3",
|
|
)
|
|
MUZYKA["requestor"].insert(0, ctx.author)
|
|
music_file_list.append(file)
|
|
await ctx.send(
|
|
"Dodałem do listy {}".format(
|
|
dir_path + file["artist"] + " - " + file["name"] + ".mp3"
|
|
)
|
|
)
|
|
logger.info("Spotifaj udany")
|
|
|
|
|
|
@client.command()
|
|
async def dej_co_z_jutuba(ctx):
|
|
await ctx.send("Dej mnie chwilkę")
|
|
logger.info("Jutub")
|
|
async with ctx.typing():
|
|
# wyciagnij linka z kontekstu
|
|
content = ctx.message.content.split()
|
|
for item in content:
|
|
if re.match("http.*", item):
|
|
dir_path, files = await get_file(ctx, "Youtube", item)
|
|
if platform == "win32":
|
|
separator = "\\"
|
|
else:
|
|
separator = "/"
|
|
if files:
|
|
for file in files:
|
|
global MUZYKA
|
|
MUZYKA["queue"].insert(0, file)
|
|
music_file_list.append(file)
|
|
MUZYKA["requestor"].insert(0, ctx.author)
|
|
await ctx.send("Dodałem do listy {}".format(file))
|
|
logger.info("Jutub udany")
|
|
|
|
|
|
@client.command()
|
|
async def update_banlist(ctx, arg=None):
|
|
async with channel.typing():
|
|
allowed = False
|
|
for role in ctx.author.roles:
|
|
if role.name == "Jarl":
|
|
allowed = True
|
|
|
|
if ctx.channel.id != 1102190666827702342:
|
|
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)
|
|
if match:
|
|
ids_to_ban.append(match.group())
|
|
tobancunter += 1
|
|
# 2. get list of already banned users for all servers Conjurer has rights to
|
|
for guild in client.guilds:
|
|
bancunter = 0
|
|
logger.info("Serwer:{}".format(guild))
|
|
current_banlist = []
|
|
permission = True
|
|
try:
|
|
async for entry in guild.bans(limit=None):
|
|
current_banlist.append(entry.user.id)
|
|
bancunter += 1
|
|
except:
|
|
permission = False
|
|
if permission:
|
|
# 3. compare lists ban only users on list 2 and not on list 1
|
|
cunter_counter = 0
|
|
bad_id_cunter_counter = 0
|
|
ban_list = np.setdiff1d(ids_to_ban, current_banlist)
|
|
for id in ban_list:
|
|
try:
|
|
tmp_user = await client.fetch_user(int(id))
|
|
await guild.ban(
|
|
tmp_user,
|
|
reason="Automatyczna lista banów",
|
|
delete_message_seconds=0,
|
|
)
|
|
cunter_counter += 1
|
|
except discord.NotFound:
|
|
logger.info(
|
|
"Znaleziono uzyszkodnika ktory juz nie ma konta"
|
|
)
|
|
bad_id_cunter_counter += 1
|
|
# 4. return message success/failure - how many banned
|
|
await ctx.send(
|
|
"Obecnie na serwerze {} jest {} zbanowanych użytkowników. Znaleziono na tym kanale {} id użytkowników do zbanowania. Zbanowano {} użytkowników. Na liście jest {} użytkowników którzy skasowali już konto".format(
|
|
guild,
|
|
bancunter,
|
|
tobancunter,
|
|
cunter_counter,
|
|
bad_id_cunter_counter,
|
|
)
|
|
)
|
|
else:
|
|
await ctx.send(
|
|
"Nie mam na serwerze {} uprawnień do banowania. :()".format(
|
|
guild
|
|
)
|
|
)
|
|
await ctx.send("Zrobione tak czy inaczej")
|
|
|
|
|
|
@client.command()
|
|
async def get_image_sadox(ctx, arg=None):
|
|
logger.info("Get sadox")
|
|
channel = ctx.message.channel
|
|
async with channel.typing():
|
|
# select random file
|
|
if platform == "linux" or platform == "linux2":
|
|
dir_path = "/home/pi/RetroPie/Fansadox/"
|
|
elif platform == "win32":
|
|
dir_path = "C:\\Users\\mtusz\\OneDrive\\Dokumenty\Fansadox\\"
|
|
res = []
|
|
# Iterate directory
|
|
for path in os.listdir(dir_path):
|
|
# check if current path is a file
|
|
if os.path.isfile(os.path.join(dir_path, path)):
|
|
res.append(path)
|
|
filename = res[random.randrange(0, len(res) - 1)]
|
|
# select random page
|
|
file = open(dir_path + filename, "rb")
|
|
readpdf = PyPDF2.PdfReader(file)
|
|
totalpages = len(readpdf.pages)
|
|
page = random.randrange(1, totalpages)
|
|
# convert page to image
|
|
image = pdf2image.convert_from_path(
|
|
dir_path + filename, first_page=page, last_page=page
|
|
)
|
|
b = io.BytesIO()
|
|
image[0].save(b, "JPEG")
|
|
b.seek(0)
|
|
b.name = "image.jpg"
|
|
file = discord.File(b)
|
|
await ctx.send(file=file)
|
|
logger.info("Get sadox completed")
|
|
|
|
|
|
@client.command()
|
|
async def graj_muzyko(ctx, arg=None):
|
|
logger.info("Press play on tape")
|
|
async with ctx.typing():
|
|
global MUZYKA
|
|
MUZYKA["playing"] = True
|
|
MUZYKA["ctx"] = ctx
|
|
await connect(ctx=ctx)
|
|
await play(ctx=ctx)
|
|
logger.info("Press play on tape completed")
|
|
|
|
|
|
@client.command()
|
|
async def cisza(ctx, arg=None):
|
|
logger.info("Stop")
|
|
global MUZYKA
|
|
MUZYKA["playing"] = False
|
|
MUZYKA["ctx"] = None
|
|
voiceClient = client.voice_clients[0]
|
|
if voiceClient.is_connected():
|
|
await disconnect(ctx=ctx)
|
|
while MUZYKA["queue"]:
|
|
MUZYKA["queue"].pop()
|
|
MUZYKA["requestor"].pop()
|
|
logger.info("Stop completed")
|
|
|
|
|
|
@client.command()
|
|
async def dalej(ctx, arg=None):
|
|
logger.info("Next")
|
|
voiceClient = client.voice_clients[0]
|
|
if voiceClient.is_connected():
|
|
voiceClient.stop()
|
|
await play(ctx=ctx)
|
|
logger.info("Next completed")
|
|
|
|
|
|
@client.command()
|
|
async def daj_mi_chwile(ctx, arg=None):
|
|
logger.info("Pause")
|
|
voiceClient = client.voice_clients[0]
|
|
if voiceClient.is_connected():
|
|
voiceClient.pause()
|
|
logger.info("Pause completed")
|
|
|
|
|
|
@client.command()
|
|
async def graj_dalej(ctx, arg=None):
|
|
logger.info("Unpause")
|
|
voiceClient = client.voice_clients[0]
|
|
if voiceClient.is_paused():
|
|
voiceClient.resume()
|
|
logger.info("Unpause completed")
|
|
|
|
|
|
@client.command()
|
|
async def zagraj_muzyke_mego_ludu(ctx, arg=None):
|
|
pass
|
|
|
|
|
|
@client.command()
|
|
async def zagraj_mi_kawalek(ctx, arg=None):
|
|
async with ctx.typing():
|
|
search_time_glob = datetime.now()
|
|
logger.info("Zaczynam szukać timestamp {}".format(datetime.now()))
|
|
file = await wyszukaj(ctx=ctx)
|
|
logger.info(
|
|
"Koniec szukania(timestamp {} zajęło {}".format(
|
|
datetime.now(), datetime.now() - search_time_glob
|
|
)
|
|
)
|
|
if file:
|
|
for plik in file:
|
|
global MUZYKA
|
|
MUZYKA["queue"].insert(0, plik[1])
|
|
MUZYKA["requestor"].insert(0, ctx.author)
|
|
metadata = eyed3.load(plik[1])
|
|
reply = "Dodałem do playlisty {} z prywatnej kolekcji Hammera.".format(
|
|
plik[1]
|
|
)
|
|
if metadata.tag.title:
|
|
reply = "Dodałem do playlisty kawalek {}".format(metadata.tag.title)
|
|
if metadata.tag.artist:
|
|
reply += " wykonawcy {}".format(metadata.tag.artist)
|
|
if metadata.tag.album:
|
|
reply += " z albumu {}".format(metadata.tag.album)
|
|
reply += " z prywatnej kolekcji Hammera i na Twoją specjalną rpośbę."
|
|
await ctx.reply(reply)
|
|
else:
|
|
await ctx.reply(
|
|
"Obawiam się że nie mogę nic znaleźć u siebie. Spróbuj komendy '$dej_co_ze_spotifaja' jeśli masz link"
|
|
)
|
|
|
|
|
|
@client.command()
|
|
async def zrob_mi_plejliste(ctx, *arg):
|
|
async with ctx.typing():
|
|
logger.info("Zaczynam szukać timestamp {}".format(datetime.now()))
|
|
search_time_glob = datetime.now()
|
|
|
|
dlugosc_playlisty = arg[0]
|
|
file = await wyszukaj(ctx=ctx, how_many=dlugosc_playlisty)
|
|
logger.info(
|
|
"Koniec szukania(timestamp {} zajęło {}".format(
|
|
datetime.now(), datetime.now() - search_time_glob
|
|
)
|
|
)
|
|
if file:
|
|
for plik in file:
|
|
global MUZYKA
|
|
MUZYKA["queue"].insert(0, plik[1])
|
|
MUZYKA["requestor"].insert(0, ctx.author)
|
|
metadata = eyed3.load(plik[1])
|
|
reply = "Dodałem do playlisty {} z prywatnej kolekcji Hammera.".format(
|
|
plik[1]
|
|
)
|
|
if metadata.tag.title:
|
|
reply = "Dodałem do playlisty kawalek {}".format(metadata.tag.title)
|
|
if metadata.tag.artist:
|
|
reply += " wykonawcy {}".format(metadata.tag.artist)
|
|
if metadata.tag.album:
|
|
reply += " z albumu {}".format(metadata.tag.album)
|
|
reply += " z prywatnej kolekcji Hammera i na Twoją specjalną rpośbę."
|
|
await ctx.reply(reply)
|
|
else:
|
|
await ctx.reply(
|
|
"Obawiam się że nie mogę nic znaleźć u siebie. Spróbuj komendy '$dej_co_ze_spotifaja' jeśli masz link"
|
|
)
|
|
|
|
|
|
@client.command()
|
|
async def przytul(ctx, arg=None):
|
|
async with ctx.typing():
|
|
nieprzytulac = False
|
|
for mention in ctx.message.mentions:
|
|
for role in mention.roles:
|
|
if role.name == "NIEPRZYTULAĆ!":
|
|
nieprzytulac = True
|
|
|
|
if arg and nieprzytulac:
|
|
await ctx.send(
|
|
"Żebym ja Ciebie nie przytulił {}".format(ctx.message.author.mention)
|
|
)
|
|
elif arg:
|
|
await ctx.send(
|
|
"Już dobrze.... Już dobrze... Ojej.. Biedactwo... :( *W ułamku sekundy {} znajduje sie w duszącym uścisku. Żebra trzeszczą - kilka pęka. Pacnięcia po plecach grożą odbiciem nerek, a głaskanie po głowie powoduje wstrząs mózgu*".format(
|
|
arg
|
|
)
|
|
)
|
|
else:
|
|
await ctx.message.add_reaction("\U0001fac2")
|
|
await ctx.send(
|
|
"Kogo mam przytulić? *Wyłamuje kostki i przeciąga się - jego 200 kilowa sylwetka złożona z samych mięśni świadczy o tym że jest gotowy*"
|
|
)
|
|
|
|
|
|
@client.command()
|
|
async def get_image_stable_diffusion(ctx, arg=None):
|
|
pass
|
|
|
|
@client.command()
|
|
async def fabryczka(ctx, arg=None):
|
|
await ctx.message.reply(historia_fabryczki)
|
|
|
|
@client.command()
|
|
async def chata_hammera(ctx, arg=None):
|
|
with open("accident_log.json", "r+") as new_file:
|
|
# First we load existing data into a dict.
|
|
file_data = json.load(new_file)
|
|
opis = file_data[-1][0]
|
|
czas = datetime.strptime(file_data[-1][1],'%Y-%m-%d %H:%M:%S.%f')
|
|
await ctx.send("Komenda mierząca Eldritch Absinht Horror Hammertimespacecontinuum. Od ostatniego incydentu w chacie Hammera minęło {}. Incydent to: {}".format(datetime.now()-czas,opis))
|
|
@client.command()
|
|
|
|
async def historia_incydentow_u_hammera(ctx, arg=None):
|
|
with open("accident_log.json", "r+") as new_file:
|
|
# First we load existing data into a dict.
|
|
file_data = json.load(new_file)
|
|
return_data = "Historia zarejestrownych incydentów u Hammera:\n"
|
|
index = 1
|
|
for data in file_data:
|
|
opis = data[0]
|
|
czas = datetime.strptime(data[1],'%Y-%m-%d %H:%M:%S.%f')
|
|
add_data = "{}. Opis: {} Data: {}".format(index,opis,czas)
|
|
return_data= return_data+ add_data + "\n"
|
|
index+=1
|
|
await ctx.send(return_data)
|
|
|
|
@client.command()
|
|
async def reset_the_clock(ctx, arg=None):
|
|
hammer = False
|
|
for role in ctx.message.author.roles:
|
|
if role.name == "Bartender":
|
|
hammer = True
|
|
if hammer:
|
|
with open("accident_log.json", "r+") as new_file:
|
|
# First we load existing data into a dict.
|
|
file_data = json.load(new_file)
|
|
czas = datetime.strptime(file_data[-1][1],'%Y-%m-%d %H:%M:%S.%f')
|
|
opis = ctx.message.content[16:]
|
|
accident= accident = [opis, "{}".format(datetime.now())]
|
|
file_data.append(accident)
|
|
new_file.seek(0)
|
|
# convert back to json.
|
|
json.dump(file_data, new_file, indent=4)
|
|
await ctx.send("RESET THE CLOCK. Od ostatniego incydentu w chacie Hammera minęło {}. No ale teraz odpierdolił: {}".format(czas, opis))
|
|
else:
|
|
await ctx.send("Gdzie z łapami do zegara? {} coś albo się komuś stało albo zaraz się stanie jak będzie zegar tykał....".format(client.get_user(346956223645614080)))
|
|
|
|
# *================================== Run
|
|
client.run(TOKEN)
|