YusarinBot/functions.py

364 lines
15 KiB
Python
Raw Normal View History

2023-01-17 16:05:39 +02:00
from gzip import open as gzipopen
2022-02-05 02:31:32 +02:00
from datetime import datetime
2023-01-17 16:05:39 +02:00
from os import listdir, makedirs, remove, stat, path
from shutil import copyfileobj
from typing import Any, Literal, Union
from discord import utils, Embed, TextChannel, VoiceChannel, PermissionOverwrite, Guild, CategoryChannel, Member, Client, ApplicationContext, Message
2022-02-05 02:31:32 +02:00
2023-01-17 16:06:51 +02:00
try:
from ujson import loads, dumps
except ImportError:
from json import loads, dumps
2023-01-17 16:05:39 +02:00
# path = Path(__file__).resolve().parent
2022-02-05 02:31:32 +02:00
log_size = 512
2022-02-08 23:37:24 +02:00
# This is the default option for "debug" key in
# file config.json, so if cebug is not set in it
# bot will use this value instead.
debug = False
try:
2022-02-10 21:26:16 +02:00
with open("config.json", 'r', encoding="utf-8") as json_file:
2023-01-17 16:05:39 +02:00
output = loads(json_file.read())
2022-02-08 23:37:24 +02:00
json_file.close()
debug = output["debug"]
except:
debug = debug
2022-02-05 02:31:32 +02:00
# Check latest log size
def checkSize():
try:
2023-01-17 16:05:39 +02:00
if not path.isdir("logs"):
makedirs("logs", exist_ok=True)
2022-02-05 02:31:32 +02:00
2023-01-17 16:05:39 +02:00
log = stat("logs/latest.log")
2022-02-05 02:31:32 +02:00
global log_size
if (log.st_size / 1024) > log_size:
2023-01-17 16:05:39 +02:00
with open("logs/latest.log", "rb") as f_in:
with gzipopen(f'logs/{datetime.now().strftime("%d.%m.%Y_%H:%M:%S")}.log.gz', 'wb') as f_out:
copyfileobj(f_in, f_out)
print(f'Copied logs/{datetime.now().strftime("%d.%m.%Y_%H:%M:%S")}.log.gz')
open("logs/latest.log", "w").close()
2022-02-05 02:31:32 +02:00
except FileNotFoundError:
print('Not found')
pass
# Append string to log
2023-01-17 16:05:39 +02:00
def appendLog(message: str, guild: Union[Guild, None] = None, announce=True) -> None:
2022-02-08 23:37:24 +02:00
global debug
2023-01-17 16:05:39 +02:00
2022-02-05 02:31:32 +02:00
2022-02-08 23:37:24 +02:00
if guild == None:
message_formatted = f'[{datetime.now().strftime("%d.%m.%Y")}] [{datetime.now().strftime("%H:%M:%S")}] {message}'
else:
if debug:
message_formatted = f'[{datetime.now().strftime("%d.%m.%Y")}] [{datetime.now().strftime("%H:%M:%S")}] [{guild} | {str(guild.id)}] {message}'
else:
message_formatted = f'[{datetime.now().strftime("%d.%m.%Y")}] [{datetime.now().strftime("%H:%M:%S")}] [{guild}] {message}'
2022-02-05 02:31:32 +02:00
2022-02-08 23:37:24 +02:00
if announce:
2022-08-03 11:11:04 +03:00
print(message_formatted, flush=True)
2022-02-05 02:31:32 +02:00
checkSize()
2023-01-17 16:05:39 +02:00
log = open('logs/latest.log', 'a') # type: ignore
2022-02-05 02:31:32 +02:00
log.write(f'{message_formatted}\n')
log.close()
2023-01-17 16:05:39 +02:00
def saveJson(value: Any, filename: str) -> None:
2022-02-05 02:31:32 +02:00
with open(filename, 'w', encoding="utf-8") as f:
2023-01-17 16:05:39 +02:00
f.write(dumps(value, indent=4, ensure_ascii=False))
2022-02-05 02:31:32 +02:00
f.close()
2023-01-17 16:05:39 +02:00
def loadJson(filename: str) -> Any:
2022-02-08 23:37:24 +02:00
global debug
2022-02-05 02:31:32 +02:00
try:
with open(filename, 'r', encoding="utf-8") as json_file:
2023-01-17 16:05:39 +02:00
output = loads(json_file.read())
2022-02-05 02:31:32 +02:00
json_file.close()
except Exception as exp:
2022-02-08 23:37:24 +02:00
if debug:
appendLog(f"Could not load json file {filename} due to exception {exp}")
2022-02-05 02:31:32 +02:00
output = {}
return output
2022-02-14 19:07:31 +02:00
def colorToStr():
pass
2023-01-17 16:05:39 +02:00
def strToColor(string: str) -> int:
2022-02-14 19:07:31 +02:00
return int(hex(int(string.replace("#", ""), 16)), 0)
2023-01-17 16:05:39 +02:00
def gotCommand(message: Message) -> None:
2022-02-08 23:37:24 +02:00
global debug
if debug:
appendLog(f"Command '{message.content}' from {message.author} ({str(message.author.id)})", message.guild)
else:
appendLog(f"Command '{message.content}' from {message.author}", message.guild)
2023-01-17 16:05:39 +02:00
def guildConfGet(guild: Guild, variable: str) -> Any:
2022-02-08 23:37:24 +02:00
global debug
2022-02-05 02:31:32 +02:00
try:
2023-01-17 16:05:39 +02:00
config = loadJson(f"guilds/{str(guild.id)}/config.json")
2022-02-05 02:31:32 +02:00
return config[variable]
2022-02-08 23:37:24 +02:00
except Exception as exp:
if debug:
appendLog(f"Could not get guild config key '{variable}' due to {exp}", guild)
2022-02-05 02:31:32 +02:00
return None
2023-01-17 16:05:39 +02:00
def guildConfSet(guild: Guild, variable: str, value: Any) -> None:
config = loadJson(f"guilds/{str(guild.id)}/config.json")
2022-02-05 02:31:32 +02:00
config[variable] = value
try:
2023-01-17 16:05:39 +02:00
saveJson(config, f"guilds/{str(guild.id)}/config.json")
2022-02-05 02:31:32 +02:00
except:
2023-01-17 16:05:39 +02:00
makedirs(f"guilds/{str(guild.id)}", exist_ok=True)
makedirs(f"guilds/{str(guild.id)}/channels", exist_ok=True)
saveJson(config, f"guilds/{str(guild.id)}/config.json")
2022-02-08 23:37:24 +02:00
appendLog(f"Guild config key '{variable}' is now set to '{value}'", guild)
2022-02-05 02:31:32 +02:00
2023-01-17 16:05:39 +02:00
def guildConfReset(guild: Guild, variable: str) -> None:
2022-02-05 02:31:32 +02:00
try:
2023-01-17 16:05:39 +02:00
config = loadJson(f"guilds/{str(guild.id)}/config.json")
2022-02-08 23:37:24 +02:00
del config[variable]
try:
2023-01-17 16:05:39 +02:00
saveJson(config, f"guilds/{str(guild.id)}/config.json")
2022-02-08 23:37:24 +02:00
except:
2023-01-17 16:05:39 +02:00
makedirs(f"guilds/{str(guild.id)}", exist_ok=True)
makedirs(f"guilds/{str(guild.id)}/channels", exist_ok=True)
saveJson(config, f"guilds/{str(guild.id)}/config.json")
2022-02-08 23:37:24 +02:00
appendLog(f"Guild config key '{variable}' has been reset", guild)
except Exception as exp:
appendLog(f"Could not reset guild config key '{variable}' due to {exp}", guild)
2022-02-05 02:31:32 +02:00
2023-01-17 16:05:39 +02:00
def guildLocaleGet(guild: Guild) -> str:
config = loadJson(f"config.json")
2022-02-07 03:06:01 +02:00
try:
2022-02-08 23:37:24 +02:00
locale = guildConfGet(guild, "locale")
2022-02-07 03:06:01 +02:00
except:
return config["bot_locale"]
if locale is None:
return config["bot_locale"]
else:
return locale
2023-01-17 16:05:39 +02:00
def getMsg(string: str, guild: Union[Guild, None] = None) -> str:
2022-02-07 03:06:01 +02:00
try:
2023-01-17 16:05:39 +02:00
locale = loadJson(f'locale/{guildLocaleGet(guild)}.json')
2022-02-07 03:06:01 +02:00
return locale["messages"][string]
except Exception as exp:
2022-02-08 23:37:24 +02:00
appendLog(f"Could not get locale string named {string} due to exception {exp}", guild)
2022-02-14 19:07:31 +02:00
return string
2022-02-07 03:06:01 +02:00
2023-01-17 16:05:39 +02:00
def makeEmbed(title="", description="", footer="", color=0xffffff) -> Embed:
embed=Embed(title=title, description=description, color=color)
2022-02-14 19:07:31 +02:00
if footer is not None:
embed.set_footer(text=footer)
return embed
2023-01-17 16:05:39 +02:00
def channelExists(number: int, guild: Guild, type: Literal["Any", "Text", "Voice"] = "Any") -> bool:
2022-02-14 19:07:31 +02:00
global debug
if number == None:
return False
try:
if type == "Voice":
2023-01-17 16:05:39 +02:00
selected_channel = utils.get(guild.channels, id=number)
if isinstance(selected_channel, VoiceChannel):
2022-02-14 19:07:31 +02:00
return True
elif type == "Text":
2023-01-17 16:05:39 +02:00
selected_channel = utils.get(guild.channels, id=number)
if isinstance(selected_channel, TextChannel):
2022-02-14 19:07:31 +02:00
return True
elif type == "Any":
2023-01-17 16:05:39 +02:00
selected_channel = utils.get(guild.channels, id=number)
2022-02-14 19:07:31 +02:00
return True
except Exception as exp:
if debug:
appendLog(f"Channel ID {str(number)} is not a channel due to {exp}")
return False
2023-01-17 16:05:39 +02:00
def channelGetName(number: int, guild: Guild):
2022-02-14 19:07:31 +02:00
global debug
try:
2023-01-17 16:05:39 +02:00
selected_channel = utils.get(guild.channels, id=number)
2022-02-14 19:07:31 +02:00
return selected_channel.name
except Exception as exp:
if debug:
appendLog(f"Channel ID {str(number)} is not a channel due to {exp}")
return "Channel doesn't exist"
2022-02-10 21:26:16 +02:00
2023-01-17 16:05:39 +02:00
def isUserVoice(vc: VoiceChannel) -> bool:
2022-02-05 02:31:32 +02:00
try:
2023-01-17 16:05:39 +02:00
channels_list = listdir(f"guilds/{str(vc.guild.id)}/channels/")
2022-02-05 02:31:32 +02:00
if f"{str(vc.id)}.json" in channels_list:
return True
else:
return False
except:
return False
2023-01-17 16:05:39 +02:00
async def removeUserVoice(vc: VoiceChannel) -> None:
2022-02-08 23:37:24 +02:00
global debug
2023-01-17 16:05:39 +02:00
channels_list = listdir(f"guilds/{str(vc.guild.id)}/channels/")
2022-02-05 02:31:32 +02:00
if f"{vc.id}.json" in channels_list:
2023-01-17 16:05:39 +02:00
vc_file = f"guilds/{str(vc.guild.id)}/channels/{str(vc.id)}.json"
2022-02-05 02:31:32 +02:00
vc_conf = loadJson(vc_file)
2023-01-17 16:05:39 +02:00
needed_channel = utils.get(vc.guild.channels, id=vc.id)
2022-08-03 11:11:04 +03:00
if loadJson("config.json")["enable_nomic"]:
2023-01-17 16:05:39 +02:00
nomic_channel = utils.get(vc.guild.channels, id=vc_conf["nomic"])
2022-02-05 02:31:32 +02:00
2023-01-17 16:05:39 +02:00
remove(vc_file)
2022-02-05 02:31:32 +02:00
await needed_channel.delete()
2022-02-08 23:37:24 +02:00
if debug:
appendLog(f"Removed voice channel '{needed_channel}' ({str(needed_channel.id)}) of user with id {str(vc_conf['ownerid'])}", guild=vc.guild)
else:
appendLog(f"Removed voice channel '{needed_channel}' of user with id {str(vc_conf['ownerid'])}", guild=vc.guild)
2022-08-03 11:11:04 +03:00
if loadJson("config.json")["enable_nomic"]:
await nomic_channel.delete()
if debug:
appendLog(f"Removed nomic channel {nomic_channel} ({str(nomic_channel.id)}) of channel with id {str(needed_channel.id)}", guild=vc.guild)
else:
appendLog(f"Removed nomic channel '{nomic_channel}' of channel with id {str(needed_channel.id)}", guild=vc.guild)
2022-02-05 02:31:32 +02:00
else:
return
2023-01-17 16:05:39 +02:00
async def createUserVoice(vc: VoiceChannel, category: CategoryChannel, member: Member) -> VoiceChannel:
2022-02-08 23:37:24 +02:00
global debug
2022-02-05 02:31:32 +02:00
chan = {}
overwrites_channel = {
2023-01-17 16:05:39 +02:00
vc.guild.default_role: PermissionOverwrite(view_channel=True),
vc.guild.me: PermissionOverwrite(read_messages=True, view_channel=True, manage_channels=True),
member: PermissionOverwrite(read_messages=True, view_channel=True, manage_channels=True)
2022-02-05 02:31:32 +02:00
}
overwrites_nomic = {
2023-01-17 16:05:39 +02:00
vc.guild.default_role: PermissionOverwrite(view_channel=False, read_messages=False),
vc.guild.me: PermissionOverwrite(read_messages=True, view_channel=True, manage_channels=True),
member: PermissionOverwrite(read_messages=True, view_channel=True, manage_channels=True)
2022-02-05 02:31:32 +02:00
}
2022-02-07 03:06:01 +02:00
created_channel = await vc.guild.create_voice_channel(getMsg("name_voice", vc.guild).format(member.name), category=category, overwrites=overwrites_channel)
2022-02-08 23:37:24 +02:00
if debug:
appendLog(f"Created voice channel '{created_channel}' ({str(created_channel.id)}) for user {member} ({str(member.id)})", guild=vc.guild)
else:
appendLog(f"Created voice channel '{created_channel}' for user {member}", guild=vc.guild)
2023-01-17 16:05:39 +02:00
if not path.isdir(f"guilds/{str(created_channel.guild.id)}/channels"):
makedirs(f"guilds/{str(created_channel.guild.id)}/channels", exist_ok=True)
vc_file = f"guilds/{str(created_channel.guild.id)}/channels/{str(created_channel.id)}.json"
2022-02-05 02:31:32 +02:00
chan["ownerid"] = member.id
saveJson(chan, vc_file)
2022-08-03 11:11:04 +03:00
if loadJson("config.json")["enable_nomic"]:
nomic_channel = await vc.guild.create_text_channel(getMsg("name_nomic", vc.guild).format(created_channel.id), category=category, overwrites=overwrites_nomic, topic=getMsg("description_nomic", vc.guild).format(str(created_channel.id)))
if debug:
appendLog(f"Created nomic channel '{nomic_channel}' ({str(nomic_channel.id)}) for channel '{created_channel}' ({str(created_channel.id)})", guild=vc.guild)
else:
appendLog(f"Created nomic channel '{nomic_channel}' for channel '{created_channel}'", guild=vc.guild)
chan["nomic"] = nomic_channel.id
saveJson(chan, vc_file)
2022-02-05 02:31:32 +02:00
return created_channel
2023-01-17 16:05:39 +02:00
def isVoiceOfUser(vc: VoiceChannel, member: Member) -> bool:
vc_file = f"guilds/{str(vc.guild.id)}/channels/{str(vc.id)}.json"
2022-02-05 02:31:32 +02:00
vc_conf = loadJson(vc_file)
if vc_conf["ownerid"] == member.id:
return True
else:
return False
2023-01-17 16:05:39 +02:00
async def changeNomicPerms(mode: Literal["deny", "allow"], vc: VoiceChannel, member: Member) -> None:
vc_file = f"guilds/{str(vc.guild.id)}/channels/{str(vc.id)}.json"
2022-02-05 02:31:32 +02:00
vc_conf = loadJson(vc_file)
2022-08-03 11:11:04 +03:00
if loadJson("config.json")["enable_nomic"]:
2023-01-17 16:05:39 +02:00
nomic_channel = utils.get(vc.guild.channels, id=vc_conf["nomic"])
2022-08-03 11:11:04 +03:00
if mode == "deny":
await nomic_channel.set_permissions(member, view_channel=False)
else:
await nomic_channel.set_permissions(member, view_channel=True)
2022-02-07 03:06:01 +02:00
2023-01-17 16:05:39 +02:00
async def clearTrash(client: Client):
if not path.isdir(f"guilds/"):
makedirs(f"guilds", exist_ok=True)
guilds_list = listdir(f"guilds/")
2022-02-07 03:06:01 +02:00
for guild in guilds_list:
guild_object = client.get_guild(int(guild))
2023-01-17 16:05:39 +02:00
if path.isdir(f"guilds/{guild}/channels"):
channels_list = listdir(f"guilds/{guild}/channels/")
2022-02-07 03:06:01 +02:00
for channel in channels_list:
channel_id = channel[:-5]
try:
2023-01-17 16:05:39 +02:00
selected_channel = utils.get(guild_object.voice_channels, id=int(channel_id))
channel_owner = loadJson(f"guilds/{guild}/channels/{channel}")["ownerid"]
2022-02-07 03:06:01 +02:00
remove_channel = True
for member in selected_channel.members:
if member.id == channel_owner:
remove_channel = False
if remove_channel:
await removeUserVoice(selected_channel)
except:
2023-01-17 16:05:39 +02:00
remove(f"guilds/{guild}/channels/{channel_id}.json")
2022-02-07 03:06:01 +02:00
#async def autoClearTrash(client):
# execute clearTrash every 120 seconds
2023-01-17 16:05:39 +02:00
def getHelpMessage(ctx: ApplicationContext, version: float) -> Embed:
2022-02-14 19:07:31 +02:00
#channelExists(number, guild, type="Voice")
config = loadJson("config.json")
2022-05-09 00:09:19 +03:00
if ctx.guild is not None:
if channelExists(guildConfGet(ctx.guild, 'channel'), ctx.guild, type="Voice"):
desc_channel = getMsg("help_channel_set", guild=ctx.guild).format(channelGetName(guildConfGet(ctx.guild, 'channel'), ctx.guild))
2022-02-14 19:07:31 +02:00
else:
2022-05-09 00:09:19 +03:00
desc_channel = getMsg("help_channel_none", guild=ctx.guild)
2022-02-14 19:07:31 +02:00
2022-05-09 00:09:19 +03:00
if channelExists(guildConfGet(ctx.guild, 'category'), ctx.guild, type="Any"):
desc_category = getMsg("help_category_set", guild=ctx.guild).format(channelGetName(guildConfGet(ctx.guild, 'category'), ctx.guild))
2022-02-14 19:07:31 +02:00
else:
2022-05-09 00:09:19 +03:00
desc_category = getMsg("help_category_none", guild=ctx.guild)
2022-02-14 19:07:31 +02:00
2022-05-09 00:09:19 +03:00
desc_locale = getMsg("help_locale", guild=ctx.guild).format(getMsg("locale_name", ctx.guild))
2022-02-14 19:07:31 +02:00
2022-05-09 00:09:19 +03:00
description = "\n".join([desc_locale, desc_channel, desc_category])
2022-02-14 19:07:31 +02:00
2023-01-17 16:05:39 +02:00
embed=Embed(title=getMsg("help_title", ctx.guild), description=description, color=strToColor(config["color_default"]))
2022-02-14 19:07:31 +02:00
else:
2023-01-17 16:05:39 +02:00
embed=Embed(title=getMsg("help_title_dm", ctx.guild), color=strToColor(config["color_default"]))
2022-02-14 19:07:31 +02:00
embed.set_author(name=f'{config["bot_name"]} v{str(version)}', url=config["bot_site"], icon_url=config["bot_icon"])
2022-05-09 00:09:19 +03:00
if ctx.author.id == config["owner"]:
embed.add_field(name=f"/shutdown", value=getMsg("help_cmd_shutdown", ctx.guild), inline=False)
2022-02-14 19:07:31 +02:00
2022-05-09 00:09:19 +03:00
embed.add_field(name=f"/channel set", value=getMsg("help_cmd_channel", ctx.guild), inline=False)
embed.add_field(name=f"/category set", value=getMsg("help_cmd_category", ctx.guild), inline=False)
embed.add_field(name=f"/locale set", value=getMsg("help_cmd_locale", ctx.guild), inline=False)
2022-02-14 19:07:31 +02:00
2022-05-09 00:09:19 +03:00
if ctx.guild is None:
embed.set_footer(text=getMsg("help_server", ctx.guild))
2022-02-14 19:07:31 +02:00
else:
2022-05-09 00:09:19 +03:00
embed.set_footer(text=getMsg("help_notice_id", ctx.guild))
2022-02-14 19:07:31 +02:00
return embed
2023-01-17 16:05:39 +02:00
async def guildConfigured(guild: Guild) -> str:
2022-02-05 02:31:32 +02:00
output = {}
config = loadJson("config.json")
2022-05-09 00:09:19 +03:00
for kind in ["channel", "category"]:
2022-02-08 23:37:24 +02:00
if guildConfGet(guild, kind) is not None:
2022-02-05 02:31:32 +02:00
try:
2023-01-17 16:05:39 +02:00
guild_object = utils.get(guild.categories, id=guildConfGet(guild, kind))
2022-05-09 00:09:19 +03:00
output[kind] = getMsg("configured_"+kind, guild).format(guild_object.name)
2022-02-05 02:31:32 +02:00
except Exception as exp:
2022-02-07 03:06:01 +02:00
output[kind] = getMsg("unconfigured_"+kind, guild)
2022-05-09 00:09:19 +03:00
else:
output[kind] = getMsg("unconfigured_"+kind, guild)
2022-02-05 02:31:32 +02:00
2022-05-09 00:09:19 +03:00
return getMsg("server_config", guild).format(getMsg("info_locale", guild).format(getMsg("locale_name", guild)), output["channel"], output["category"])