✨ reworking a bunch of stuff
This commit is contained in:
12
gwendolyn_old/utils/__init__.py
Normal file
12
gwendolyn_old/utils/__init__.py
Normal file
@ -0,0 +1,12 @@
|
||||
"""A collections of utilities used by Gwendolyn and her functions."""
|
||||
|
||||
__all__ = ["get_options", "get_credentials", "DatabaseFuncs", "EventHandler",
|
||||
"ErrorHandler", "get_params", "log_this", "cap", "make_files",
|
||||
"replace_multiple", "emoji_to_command"]
|
||||
|
||||
from .helper_classes import DatabaseFuncs
|
||||
from .event_handlers import EventHandler, ErrorHandler
|
||||
from .util_functions import (get_params, log_this, cap, make_files,
|
||||
replace_multiple, emoji_to_command, long_strings,
|
||||
sanitize, get_options, get_credentials, encode_id,
|
||||
decode_id)
|
165
gwendolyn_old/utils/event_handlers.py
Normal file
165
gwendolyn_old/utils/event_handlers.py
Normal file
@ -0,0 +1,165 @@
|
||||
"""
|
||||
Classes used to handle bot events and errors.
|
||||
|
||||
*Classes*
|
||||
---------
|
||||
EventHandler
|
||||
ErrorHandler
|
||||
"""
|
||||
import traceback # Used to get the traceback of errors
|
||||
|
||||
import discord # Used to init discord.Game and discord.Status, as well
|
||||
# as compare errors to discord errors and as typehints
|
||||
from discord.ext import commands # Used to compare errors with command
|
||||
# errors
|
||||
|
||||
from interactions import SlashContext, ComponentContext
|
||||
from gwendolyn_old.utils.util_functions import decode_id
|
||||
from gwendolyn_old.exceptions import InvalidInteraction
|
||||
|
||||
|
||||
class EventHandler():
|
||||
"""
|
||||
Handles bot events.
|
||||
|
||||
*Methods*
|
||||
---------
|
||||
on_ready()
|
||||
on_slash_command(ctx: interactions.SlashContext)
|
||||
on_reaction_add(ctx: interactions.SlashContext)
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
"""Initialize the handler."""
|
||||
self.bot = bot
|
||||
|
||||
async def on_ready(self):
|
||||
"""Log and sets status when it logs in."""
|
||||
await self.bot.database_funcs.imdb_commands()
|
||||
name = self.bot.user.name
|
||||
userid = str(self.bot.user.id)
|
||||
logged_in_message = f"Logged in as {name}, {userid}"
|
||||
self.bot.log(logged_in_message, level=25)
|
||||
game = discord.Game("Use /help for commands")
|
||||
|
||||
online_status = discord.Status.online
|
||||
await self.bot.change_presence(activity=game, status=online_status)
|
||||
|
||||
async def on_slash_command(self, ctx: SlashContext):
|
||||
"""Log when a slash command is given."""
|
||||
if ctx.subcommand_name is not None:
|
||||
subcommand = f" {ctx.subcommand_name} "
|
||||
else:
|
||||
subcommand = " "
|
||||
|
||||
if ctx.subcommand_group is not None:
|
||||
sub_command_group = f"{ctx.subcommand_group} "
|
||||
else:
|
||||
sub_command_group = ""
|
||||
|
||||
args = " ".join([str(i) for i in ctx.args])
|
||||
full_command = f"/{ctx.command}{subcommand}{sub_command_group}{args}"
|
||||
log_message = f"{ctx.author.display_name} ran {full_command}"
|
||||
self.bot.log(log_message, str(ctx.channel_id), level=25)
|
||||
|
||||
async def on_component(self, ctx: ComponentContext):
|
||||
"""Handle component interaction."""
|
||||
info = decode_id(ctx.custom_id)
|
||||
self.bot.log(f"Component action with info {info}")
|
||||
channel = ctx.channel
|
||||
author = str(ctx.author_id)
|
||||
|
||||
if info[0].lower() == "plex":
|
||||
if info[1].lower() == "movie":
|
||||
await self.bot.other.plex.add_movie(
|
||||
ctx.origin_message,
|
||||
info[2],
|
||||
not isinstance(channel, discord.DMChannel)
|
||||
)
|
||||
return
|
||||
|
||||
elif info[1].lower() == "show":
|
||||
await self.bot.other.plex.add_show(
|
||||
ctx.origin_message,
|
||||
info[2],
|
||||
not isinstance(channel, discord.DMChannel)
|
||||
)
|
||||
else:
|
||||
raise InvalidInteraction(ctx.custom_id, info)
|
||||
|
||||
elif info[0].lower() == "hangman" and author == info[2]:
|
||||
if info[1].lower() == "guess":
|
||||
await self.bot.games.hangman.guess(ctx, *info[3:])
|
||||
elif info[1].lower() == "end":
|
||||
await self.bot.games.hangman.stop(ctx, *info[3:])
|
||||
else:
|
||||
raise InvalidInteraction(ctx.custom_id, info)
|
||||
elif info[0].lower() == "connectfour":
|
||||
connect_four = self.bot.games.connect_four
|
||||
if info[1].lower() == "place" and author == info[2]:
|
||||
await connect_four.place_piece(
|
||||
ctx,
|
||||
info[3],
|
||||
int(info[4]),
|
||||
[int(info[5]), int(info[6])],
|
||||
int(info[7]),
|
||||
ctx.author_id,
|
||||
int(info[8])
|
||||
)
|
||||
elif info[1].lower() == "end" and author in [info[2], info[3]]:
|
||||
await connect_four.surrender(
|
||||
ctx, [int(info[2]), int(info[3])], info[4], info[5]
|
||||
)
|
||||
else:
|
||||
raise InvalidInteraction(ctx.custom_id, info)
|
||||
elif info[0].lower() == "blackjack":
|
||||
await self.bot.games.blackjack.decode_interaction(ctx, info[1:])
|
||||
else:
|
||||
raise InvalidInteraction(ctx.custom_id, info)
|
||||
|
||||
|
||||
|
||||
class ErrorHandler():
|
||||
"""
|
||||
Handles errors.
|
||||
|
||||
*Methods*
|
||||
---------
|
||||
on_slash_command_error(ctx: interactions.SlashContext,
|
||||
error: Exception)
|
||||
on_error(method: str)
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
"""Initialize the handler."""
|
||||
self.bot = bot
|
||||
|
||||
async def on_slash_command_error(self, ctx: SlashContext,
|
||||
error: Exception):
|
||||
"""Log when there's a slash command."""
|
||||
if isinstance(error, commands.CommandNotFound):
|
||||
await ctx.send("That's not a command")
|
||||
elif isinstance(error, discord.errors.NotFound):
|
||||
self.bot.log("Deleted message before I could add all reactions")
|
||||
elif isinstance(error, commands.errors.MissingRequiredArgument):
|
||||
self.bot.log(f"{error}", str(ctx.channel_id))
|
||||
await ctx.send(self.bot.long_strings["missing parameters"])
|
||||
else:
|
||||
params = [type(error), error, error.__traceback__]
|
||||
exception = traceback.format_exception(*params)
|
||||
|
||||
exception_string = "".join(exception)
|
||||
log_messages = [f"exception in /{ctx.name}", f"{exception_string}"]
|
||||
self.bot.log(log_messages, str(ctx.channel_id), 40)
|
||||
if isinstance(error, discord.errors.NotFound):
|
||||
self.bot.log("Context is non-existant", level=40)
|
||||
else:
|
||||
await ctx.send("Something went wrong")
|
||||
|
||||
async def on_error(self, method: str):
|
||||
"""Log when there's an error."""
|
||||
exception = traceback.format_exc()
|
||||
|
||||
exception_string = "".join(exception)
|
||||
log_messages = [f"exception in {method}", f"{exception_string}"]
|
||||
self.bot.log(log_messages, level=40)
|
173
gwendolyn_old/utils/helper_classes.py
Normal file
173
gwendolyn_old/utils/helper_classes.py
Normal file
@ -0,0 +1,173 @@
|
||||
"""
|
||||
Contains classes used for utilities.
|
||||
|
||||
*Classes*
|
||||
---------
|
||||
DatabaseFuncs()
|
||||
"""
|
||||
import os # Used to test if files exist
|
||||
import time # Used to test how long it's been since commands were synced
|
||||
|
||||
import re # Used in get_id
|
||||
import discord # Used for type hints
|
||||
|
||||
|
||||
class DatabaseFuncs():
|
||||
"""
|
||||
Manages database functions.
|
||||
|
||||
*Methods*
|
||||
---------
|
||||
get_name(user_id: str) -> str
|
||||
get_id(user_name: str) -> str
|
||||
delete_game(game_type: str, channel: str)
|
||||
wipe_games()
|
||||
connect_four_reaction_test(message: discord.Message,
|
||||
user: discord.User) -> bool
|
||||
imdb_commands()
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
"""Initialize the class."""
|
||||
self.bot = bot
|
||||
|
||||
def get_name(self, user_id: str):
|
||||
"""
|
||||
Get the name of a user you have the # id of.
|
||||
|
||||
*Parameters:
|
||||
------------
|
||||
user_id: str
|
||||
The id of the user you want the name of. The format is
|
||||
"#" + str(discord.User.id)
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
user_name: str
|
||||
The name of the user. If the user couldn't be found,
|
||||
returns the user_id.
|
||||
"""
|
||||
user = self.bot.database["users"].find_one({"_id": user_id})
|
||||
|
||||
if user_id == f"#{self.bot.user.id}":
|
||||
return_name = "Gwendolyn"
|
||||
elif user is not None:
|
||||
return_name = user["user name"]
|
||||
else:
|
||||
self.bot.log(f"Couldn't find user {user_id}")
|
||||
return_name = user_id
|
||||
|
||||
return return_name
|
||||
|
||||
def get_id(self, user_name: str):
|
||||
"""
|
||||
Get the id of a user you have the username of.
|
||||
|
||||
*Parameters:
|
||||
------------
|
||||
user_name: str
|
||||
The name of the user you want the id of.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
user_id: str
|
||||
The id of the user in the format "#" +
|
||||
str(discord.User.id). If the user couldn't be found,
|
||||
returns the user_name.
|
||||
"""
|
||||
user_search = {"user name": re.compile(user_name, re.IGNORECASE)}
|
||||
user = self.bot.database["users"].find_one(user_search)
|
||||
|
||||
if user is not None:
|
||||
return_id = user["_id"]
|
||||
else:
|
||||
self.bot.log("Couldn't find user "+user_name)
|
||||
return_id = None
|
||||
|
||||
return return_id
|
||||
|
||||
def delete_game(self, game_type: str, channel: str):
|
||||
"""
|
||||
Remove a game from the database.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
game_type: str
|
||||
The name of the collection the game is in, like
|
||||
"hangman games", "blackjack games" etc.
|
||||
channel: str
|
||||
The channel id of the channel the game is on as a
|
||||
string.
|
||||
"""
|
||||
self.bot.database[game_type].delete_one({"_id": channel})
|
||||
|
||||
def wipe_games(self):
|
||||
"""Delete all running games and pull from git."""
|
||||
game_types = [
|
||||
"trivia questions",
|
||||
"blackjack games",
|
||||
"connect 4 games"
|
||||
"hex games",
|
||||
"wordle games"
|
||||
]
|
||||
for game_type in game_types:
|
||||
self.bot.database[game_type].delete_many({})
|
||||
|
||||
def connect_four_reaction_test(self, message: discord.Message,
|
||||
user: discord.User):
|
||||
"""
|
||||
Test if the given message is the current connect four game.
|
||||
|
||||
Also tests if the given user is the one who's turn it is.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
message: discord.Message
|
||||
The message to test.
|
||||
user: discord.User
|
||||
The user to test.
|
||||
*Returns*
|
||||
---------
|
||||
: bool
|
||||
Whether the given message is the current connect four
|
||||
game and if the user who reacted is the user who's turn
|
||||
it is.
|
||||
"""
|
||||
channel = message.channel
|
||||
channel_search = {"_id": str(channel.id)}
|
||||
game = self.bot.database["connect 4 games"].find_one(channel_search)
|
||||
|
||||
old_images_path = "gwendolyn/resources/games/old_images/"
|
||||
file_path = old_images_path + f"connect_four{channel.id}"
|
||||
if os.path.isfile(file_path):
|
||||
with open(file_path, "r", encoding="utf-8") as file_pointer:
|
||||
old_image = int(file_pointer.read())
|
||||
else:
|
||||
old_image = 0
|
||||
|
||||
if message.id == old_image:
|
||||
self.bot.log("They reacted to the connect_four game")
|
||||
turn = game["turn"]
|
||||
if user == game["players"][turn]:
|
||||
valid_reaction = True
|
||||
else:
|
||||
self.bot.log("It wasn't their turn")
|
||||
valid_reaction = False
|
||||
else:
|
||||
valid_reaction = False
|
||||
|
||||
return valid_reaction
|
||||
|
||||
async def imdb_commands(self):
|
||||
"""Sync the slash commands with the discord API."""
|
||||
collection = self.bot.database["last synced"]
|
||||
last_synced = collection.find_one()
|
||||
now = time.time()
|
||||
if last_synced["last synced"] < now - 86400:
|
||||
slash_command_list = await self.bot.slash.to_dict()
|
||||
self.bot.log(f"Updating commands: {slash_command_list}")
|
||||
await self.bot.slash.sync_all_commands()
|
||||
id_number = last_synced["_id"]
|
||||
query_filter = {"_id": id_number}
|
||||
update = {"$set": {"last synced": now}}
|
||||
collection.update_one(query_filter, update)
|
391
gwendolyn_old/utils/util_functions.py
Normal file
391
gwendolyn_old/utils/util_functions.py
Normal file
@ -0,0 +1,391 @@
|
||||
"""
|
||||
Contains utility functions used by parts of the bot.
|
||||
|
||||
*Functions*
|
||||
-----------
|
||||
sanitize(data: str, lower_case_value: bool = false) -> dict
|
||||
get_options() -> dict
|
||||
get_credentials() -> dict
|
||||
long_strings() -> dict
|
||||
get_params() -> dict
|
||||
log_this(messages: Union[str, list], channel: str = "",
|
||||
level: int = 20)
|
||||
cap(s: str) -> str
|
||||
make_files()
|
||||
replace_multiple(main_string: str, to_be_replaced: list,
|
||||
new_string: str) -> str
|
||||
emoji_to_command(emoji: str) -> str
|
||||
"""
|
||||
import string
|
||||
import json # Used by long_strings(), get_params() and make_files()
|
||||
import logging # Used for logging
|
||||
import os # Used by make_files() to check if files exist
|
||||
import sys # Used to specify printing for logging
|
||||
import imdb # Used to disable logging for the module
|
||||
|
||||
|
||||
BASE_37 = ":" + string.digits + string.ascii_uppercase
|
||||
BASE_128 = list(
|
||||
string.digits +
|
||||
string.ascii_letters +
|
||||
"!#$€£¢¥¤&%()*+,-./;:<=>?@[]_{|}~ `¦§©®«»±µ·¿əʒ" +
|
||||
"ÆØÅÐÉÈÊÇÑÖ" +
|
||||
"æøåðéèêçñö"
|
||||
)
|
||||
|
||||
# All of this is logging configuration
|
||||
FORMAT = " %(asctime)s | %(name)-16s | %(levelname)-8s | %(message)s"
|
||||
PRINTFORMAT = "%(asctime)s - %(message)s"
|
||||
DATEFORMAT = "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
logging.addLevelName(25, "PRINT")
|
||||
loggingConfigParams = {
|
||||
"format": FORMAT,
|
||||
"datefmt": DATEFORMAT,
|
||||
"level": logging.INFO,
|
||||
"filename": "gwendolyn.log"
|
||||
}
|
||||
logging.basicConfig(**loggingConfigParams)
|
||||
logger = logging.getLogger("Gwendolyn")
|
||||
printer = logging.getLogger("printer")
|
||||
handler = logging.StreamHandler(sys.stdout)
|
||||
handler.setFormatter(logging.Formatter(fmt=PRINTFORMAT, datefmt=DATEFORMAT))
|
||||
printer.addHandler(handler)
|
||||
printer.propagate = False
|
||||
|
||||
imdb._logging.setLevel("CRITICAL") # pylint: disable=protected-access
|
||||
# Basically disables imdbpy logging, since it's being printed to the
|
||||
# terminal.
|
||||
|
||||
def sanitize(data: str, lower_case_value: bool = False):
|
||||
"""
|
||||
Sanitize and create a dictionary from a string.
|
||||
|
||||
Each element is created from a line with a : in it. The key is left
|
||||
of the :, the value is right of it.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
data: str
|
||||
The string to create a dict from.
|
||||
lower_case_value: bool = False
|
||||
Whether the value of each element should be lowercase.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
dct: dict
|
||||
The sanitized dictionary of elements.
|
||||
|
||||
"""
|
||||
data = data.splitlines()
|
||||
dct = {}
|
||||
for line in data:
|
||||
if line[0] != "#" and ":" in line:
|
||||
line_values = line.split(":")
|
||||
line_values[0] = line_values[0].lower()
|
||||
line_values[1] = line_values[1].replace(" ", "")
|
||||
if lower_case_value:
|
||||
line_values[1] = line_values[1].lower()
|
||||
|
||||
if line_values[0] in ["testing guild ids", "admins"]:
|
||||
line_values[1] = line_values[1].split(",")
|
||||
if all(i.isnumeric() for i in line_values[1]):
|
||||
line_values[1] = [int(i) for i in line_values[1]]
|
||||
|
||||
if any(i == line_values[1] for i in ["true", "false"]):
|
||||
line_values[1] = (line_values[1] == "true")
|
||||
|
||||
dct[line_values[0]] = line_values[1]
|
||||
|
||||
return dct
|
||||
|
||||
|
||||
def get_options():
|
||||
"""
|
||||
Get the bot options as dict.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
options: dict
|
||||
The options of the bot.
|
||||
"""
|
||||
with open("options.txt", "r", encoding="utf-8") as file_pointer:
|
||||
data = sanitize(file_pointer.read(), True)
|
||||
|
||||
options = {}
|
||||
|
||||
options["testing"] = data["testing"]
|
||||
options["guild_ids"] = data["testing guild ids"]
|
||||
options["admins"] = data["admins"]
|
||||
return options
|
||||
|
||||
def get_credentials():
|
||||
"""
|
||||
Returns the credentials used by the bot as a dict.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
credentials: dict
|
||||
The credentials used by the bot.
|
||||
"""
|
||||
with open("credentials.txt", "r", encoding="utf-8") as file_pointer:
|
||||
data = sanitize(file_pointer.read())
|
||||
|
||||
credentials = {}
|
||||
|
||||
credentials["token"] = data["bot token"]
|
||||
credentials["wordnik_key"] = data["wordnik api key"]
|
||||
credentials["mongo_db_user"] = data["mongodb user"]
|
||||
credentials["mongo_db_password"] = data["mongodb password"]
|
||||
credentials["wolfram_alpha_key"] = data["wolframalpha appid"]
|
||||
credentials["radarr_key"] = data["radarr api key"]
|
||||
credentials["sonarr_key"] = data["sonarr api key"]
|
||||
credentials["qbittorrent_username"] = data["qbittorrent username"]
|
||||
credentials["qbittorrent_password"] = data["qbittorrent password"]
|
||||
|
||||
return credentials
|
||||
|
||||
def long_strings():
|
||||
"""
|
||||
Get the data from gwendolyn/resources/long_strings.json.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
data: dict
|
||||
The long strings and their keys.
|
||||
"""
|
||||
long_strings_path = "gwendolyn/resources/long_strings.json"
|
||||
with open(long_strings_path, "r", encoding="utf-8") as file_pointer:
|
||||
data = json.load(file_pointer)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_params():
|
||||
"""
|
||||
Get the slash command parameters.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
params: dict
|
||||
The parameters for every slash command.
|
||||
"""
|
||||
path = "gwendolyn/resources/slash_parameters.json"
|
||||
with open(path, "r", encoding="utf-8") as file_pointer:
|
||||
slash_parameters = json.load(file_pointer)
|
||||
|
||||
options = get_options()
|
||||
|
||||
if options["testing"]:
|
||||
for parameter in slash_parameters:
|
||||
slash_parameters[parameter]["guild_ids"] = options["guild_ids"]
|
||||
|
||||
return slash_parameters
|
||||
|
||||
|
||||
def log_this(messages, channel: str = "", level: int = 20):
|
||||
"""
|
||||
Log something in Gwendolyn's logs.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
messages: Union[str, list]
|
||||
A string or list of strings to be logged. If there are
|
||||
multiple strings and the level is PRINT (25) or higher,
|
||||
only the first string will be printed.
|
||||
channel: str = ""
|
||||
The channel the event to be logged occurred in. Will be
|
||||
logged along with the message(s).
|
||||
level: int = 20
|
||||
The level to log the message(s) at. If PRINT (25) or
|
||||
higher, the first message will be printed to the console.
|
||||
"""
|
||||
channel = channel.replace("Direct Message with ", "")
|
||||
if isinstance(messages, str):
|
||||
messages = [messages]
|
||||
|
||||
print_message = messages[0]
|
||||
|
||||
for i, message in enumerate(messages):
|
||||
if channel != "":
|
||||
messages[i] = f"{message} - ({channel})" # Adds channel ID
|
||||
# to log messages
|
||||
|
||||
if len(messages) > 1: # Tells user to check the log if there are
|
||||
# more messages there
|
||||
print_message += " (details in log)"
|
||||
|
||||
if level >= 25:
|
||||
printer.log(level, print_message)
|
||||
|
||||
for log_message in messages:
|
||||
logger.log(level, log_message)
|
||||
|
||||
|
||||
def cap(input_string: str):
|
||||
"""
|
||||
Capitalize a string like a movie title.
|
||||
|
||||
That means "of" and "the" are not capitalized.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
input_string: str
|
||||
The string to capitalized.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
return_string: str
|
||||
The capitalized string.
|
||||
"""
|
||||
no_caps_list = ["of", "the"]
|
||||
word_number = 0
|
||||
string_list = input_string.split()
|
||||
return_string = ''
|
||||
for word in string_list:
|
||||
word_number += 1
|
||||
if word not in no_caps_list or word_number == 1:
|
||||
word = word.capitalize()
|
||||
return_string += word+" "
|
||||
return_string = return_string[:-1]
|
||||
return return_string
|
||||
|
||||
|
||||
def make_files():
|
||||
"""Create all the files and directories needed by Gwendolyn."""
|
||||
def make_json_file(path, content):
|
||||
"""Create json file if it doesn't exist."""
|
||||
if not os.path.isfile(path):
|
||||
log_this(path.split("/")[-1]+" didn't exist. Making it now.")
|
||||
with open(path, "w", encoding="utf-8") as file_pointer:
|
||||
json.dump(content, file_pointer, indent=4)
|
||||
|
||||
def make_txt_file(path, content):
|
||||
"""Create txt file if it doesn't exist."""
|
||||
if not os.path.isfile(path):
|
||||
log_this(path.split("/")[-1]+" didn't exist. Making it now.")
|
||||
with open(path, "w", encoding="utf-8") as file_pointer:
|
||||
file_pointer.write(content)
|
||||
|
||||
def directory(path):
|
||||
"""Create directory if it doesn't exist."""
|
||||
if not os.path.isdir(path):
|
||||
os.makedirs(path)
|
||||
log_this("The "+path.split("/")[-1]+" directory didn't exist")
|
||||
|
||||
file_path = "gwendolyn/resources/starting_files.json"
|
||||
with open(file_path, "r", encoding="utf-8") as file_pointer:
|
||||
data = json.load(file_pointer)
|
||||
|
||||
for path, content in data["json"].items():
|
||||
make_json_file(path, content)
|
||||
|
||||
for path, content in data["txt"].items():
|
||||
make_txt_file(path, content)
|
||||
|
||||
for path in data["folder"]:
|
||||
directory(path)
|
||||
|
||||
|
||||
def replace_multiple(main_string: str, to_be_replaced: list, new_string: str):
|
||||
"""
|
||||
Replace multiple substrings in a string with the same substring.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
main_string: str
|
||||
The string to replace substrings in.
|
||||
to_be_replaced: list
|
||||
The substrings to replace.
|
||||
new_string: str
|
||||
The string to replace the substrings with.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
main_string: str
|
||||
The string with the substrings replaced.
|
||||
"""
|
||||
# Iterate over the strings to be replaced
|
||||
for elem in to_be_replaced:
|
||||
# Check if string is in the main string
|
||||
if elem in main_string:
|
||||
# Replace the string
|
||||
main_string = main_string.replace(elem, new_string)
|
||||
|
||||
return main_string
|
||||
|
||||
|
||||
def emoji_to_command(emoji: str):
|
||||
"""
|
||||
Convert emoji to text.
|
||||
|
||||
*Parameters*
|
||||
------------
|
||||
emoji: str
|
||||
The emoji to decipher.
|
||||
|
||||
*Returns*
|
||||
---------
|
||||
: str
|
||||
The deciphered string.
|
||||
"""
|
||||
if emoji == "1️⃣":
|
||||
return_value = 1
|
||||
elif emoji == "2️⃣":
|
||||
return_value = 2
|
||||
elif emoji == "3️⃣":
|
||||
return_value = 3
|
||||
elif emoji == "4️⃣":
|
||||
return_value = 4
|
||||
elif emoji == "5️⃣":
|
||||
return_value = 5
|
||||
elif emoji == "6️⃣":
|
||||
return_value = 6
|
||||
elif emoji == "7️⃣":
|
||||
return_value = 7
|
||||
elif emoji == "🎲":
|
||||
return_value = "roll"
|
||||
elif emoji == "❌":
|
||||
return_value = "none"
|
||||
elif emoji == "✔️":
|
||||
return_value = 1
|
||||
else:
|
||||
return_value = ""
|
||||
|
||||
return return_value
|
||||
|
||||
def encode_id(info: list):
|
||||
letters = list(":".join(info))
|
||||
dec = 0
|
||||
for i, letter in enumerate(letters):
|
||||
try:
|
||||
dec += (37**i) * BASE_37.index(letter.upper())
|
||||
except ValueError:
|
||||
log_this(f"Could not encode letter {letter}", level=30)
|
||||
|
||||
custom_id = []
|
||||
|
||||
while dec:
|
||||
custom_id.append(BASE_128[dec % 128])
|
||||
dec = dec // 128
|
||||
|
||||
custom_id = ''.join(custom_id)
|
||||
log_this(f"Encoded {info} to {custom_id}")
|
||||
return custom_id
|
||||
|
||||
|
||||
def decode_id(custom_id: str):
|
||||
letters = list(custom_id)
|
||||
dec = 0
|
||||
for i, letter in enumerate(letters):
|
||||
dec += (128**i) * BASE_128.index(letter)
|
||||
|
||||
info_string = []
|
||||
|
||||
while dec:
|
||||
info_string.append(BASE_37[dec % 37])
|
||||
dec = dec // 37
|
||||
|
||||
info = ''.join(info_string).split(':')
|
||||
log_this(f"Decoded {custom_id} to be {info}")
|
||||
return ''.join(info_string).split(':')
|
Reference in New Issue
Block a user