mirror of
https://github.com/Ryujinx/ryuko-ng.git
synced 2024-12-23 06:15:31 +00:00
Handle various file related issues (#76)
* Create state files if they don't exist yet * Add notifications helper to message bot managers * Inform bot managers about errors if possible * Handle JSONDecodeErrors including empty files
This commit is contained in:
parent
31b9aeb436
commit
9669556a39
|
@ -8,6 +8,8 @@ import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord.ext.commands import CommandError, Context
|
from discord.ext.commands import CommandError, Context
|
||||||
|
|
||||||
|
from robocop_ng.helpers.notifications import report_critical_error
|
||||||
|
|
||||||
if len(sys.argv[1:]) != 1:
|
if len(sys.argv[1:]) != 1:
|
||||||
sys.stderr.write("usage: <state_dir>")
|
sys.stderr.write("usage: <state_dir>")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -63,6 +65,9 @@ for wanted_json_idx in range(len(wanted_jsons)):
|
||||||
wanted_jsons[wanted_json_idx] = os.path.join(
|
wanted_jsons[wanted_json_idx] = os.path.join(
|
||||||
state_dir, wanted_jsons[wanted_json_idx]
|
state_dir, wanted_jsons[wanted_json_idx]
|
||||||
)
|
)
|
||||||
|
if not os.path.isfile(wanted_jsons[wanted_json_idx]):
|
||||||
|
with open(wanted_jsons[wanted_json_idx], "w") as file:
|
||||||
|
file.write("{}")
|
||||||
|
|
||||||
intents = discord.Intents.all()
|
intents = discord.Intents.all()
|
||||||
intents.typing = False
|
intents.typing = False
|
||||||
|
@ -137,6 +142,25 @@ async def on_command(ctx):
|
||||||
async def on_error(event: str, *args, **kwargs):
|
async def on_error(event: str, *args, **kwargs):
|
||||||
log.exception(f"Error on {event}:")
|
log.exception(f"Error on {event}:")
|
||||||
|
|
||||||
|
exception = sys.exception()
|
||||||
|
is_report_allowed = any(
|
||||||
|
[
|
||||||
|
not isinstance(exception, x)
|
||||||
|
for x in [
|
||||||
|
discord.RateLimited,
|
||||||
|
discord.GatewayNotFound,
|
||||||
|
discord.InteractionResponded,
|
||||||
|
discord.LoginFailure,
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if exception is not None and is_report_allowed:
|
||||||
|
await report_critical_error(
|
||||||
|
bot,
|
||||||
|
exception,
|
||||||
|
additional_info={"Event": event, "args": args, "kwargs": kwargs},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_command_error(ctx: Context, error: CommandError):
|
async def on_command_error(ctx: Context, error: CommandError):
|
||||||
|
|
|
@ -2,6 +2,8 @@ import json
|
||||||
import os
|
import os
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
from robocop_ng.helpers.notifications import report_critical_error
|
||||||
|
|
||||||
|
|
||||||
def get_disabled_ids_path(bot) -> str:
|
def get_disabled_ids_path(bot) -> str:
|
||||||
return os.path.join(bot.state_dir, "data/disabled_ids.json")
|
return os.path.join(bot.state_dir, "data/disabled_ids.json")
|
||||||
|
@ -22,7 +24,19 @@ def is_ro_section_valid(ro_section: dict[str, str]) -> bool:
|
||||||
def get_disabled_ids(bot) -> dict[str, dict[str, Union[str, dict[str, str]]]]:
|
def get_disabled_ids(bot) -> dict[str, dict[str, Union[str, dict[str, str]]]]:
|
||||||
if os.path.isfile(get_disabled_ids_path(bot)):
|
if os.path.isfile(get_disabled_ids_path(bot)):
|
||||||
with open(get_disabled_ids_path(bot), "r") as f:
|
with open(get_disabled_ids_path(bot), "r") as f:
|
||||||
disabled_ids = json.load(f)
|
try:
|
||||||
|
disabled_ids = json.load(f)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
content = f.read()
|
||||||
|
report_critical_error(
|
||||||
|
bot,
|
||||||
|
e,
|
||||||
|
additional_info={
|
||||||
|
"file": {"length": len(content), "content": content}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return {}
|
||||||
|
|
||||||
# Migration code
|
# Migration code
|
||||||
if "app_id" in disabled_ids.keys():
|
if "app_id" in disabled_ids.keys():
|
||||||
old_disabled_ids = disabled_ids.copy()
|
old_disabled_ids = disabled_ids.copy()
|
||||||
|
|
|
@ -2,6 +2,8 @@ import json
|
||||||
import os
|
import os
|
||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
|
|
||||||
|
from robocop_ng.helpers.notifications import report_critical_error
|
||||||
|
|
||||||
|
|
||||||
def get_macros_path(bot):
|
def get_macros_path(bot):
|
||||||
return os.path.join(bot.state_dir, "data/macros.json")
|
return os.path.join(bot.state_dir, "data/macros.json")
|
||||||
|
@ -10,7 +12,18 @@ def get_macros_path(bot):
|
||||||
def get_macros_dict(bot) -> dict[str, dict[str, Union[list[str], str]]]:
|
def get_macros_dict(bot) -> dict[str, dict[str, Union[list[str], str]]]:
|
||||||
if os.path.isfile(get_macros_path(bot)):
|
if os.path.isfile(get_macros_path(bot)):
|
||||||
with open(get_macros_path(bot), "r") as f:
|
with open(get_macros_path(bot), "r") as f:
|
||||||
macros = json.load(f)
|
try:
|
||||||
|
macros = json.load(f)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
content = f.read()
|
||||||
|
report_critical_error(
|
||||||
|
bot,
|
||||||
|
e,
|
||||||
|
additional_info={
|
||||||
|
"file": {"length": len(content), "content": content}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return {}
|
||||||
|
|
||||||
# Migration code
|
# Migration code
|
||||||
if "aliases" not in macros.keys():
|
if "aliases" not in macros.keys():
|
||||||
|
|
53
robocop_ng/helpers/notifications.py
Normal file
53
robocop_ng/helpers/notifications.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import json
|
||||||
|
from typing import Optional, Union
|
||||||
|
|
||||||
|
from discord import Message, MessageReference, PartialMessage
|
||||||
|
|
||||||
|
|
||||||
|
MessageReferenceTypes = Union[Message, MessageReference, PartialMessage]
|
||||||
|
|
||||||
|
|
||||||
|
async def notify_management(
|
||||||
|
bot, message: str, reference_message: Optional[MessageReferenceTypes] = None
|
||||||
|
):
|
||||||
|
log_channel = await bot.get_channel_safe(bot.config.botlog_channel)
|
||||||
|
bot_manager_role = log_channel.guild.get_role(bot.config.bot_manager_role_id)
|
||||||
|
|
||||||
|
notification_message = f"{bot_manager_role.mention}:\n"
|
||||||
|
|
||||||
|
if reference_message is not None and reference_message.channel != log_channel:
|
||||||
|
notification_message += f"Message reference: {reference_message.jump_url}\n"
|
||||||
|
notification_message += message
|
||||||
|
|
||||||
|
return await log_channel.send(notification_message)
|
||||||
|
else:
|
||||||
|
notification_message += message
|
||||||
|
|
||||||
|
return await log_channel.send(
|
||||||
|
notification_message,
|
||||||
|
reference=reference_message,
|
||||||
|
mention_author=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def report_critical_error(
|
||||||
|
bot,
|
||||||
|
error: BaseException,
|
||||||
|
reference_message: Optional[MessageReferenceTypes] = None,
|
||||||
|
additional_info: Optional[dict] = None,
|
||||||
|
):
|
||||||
|
message = "⛔ A critical error occurred!"
|
||||||
|
|
||||||
|
if additional_info is not None:
|
||||||
|
message += f"""
|
||||||
|
```json
|
||||||
|
{json.dumps(additional_info)}
|
||||||
|
```"""
|
||||||
|
|
||||||
|
message += f"""
|
||||||
|
Exception:
|
||||||
|
```
|
||||||
|
{error}
|
||||||
|
```"""
|
||||||
|
|
||||||
|
return await notify_management(bot, message, reference_message)
|
|
@ -1,14 +1,28 @@
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from robocop_ng.helpers.notifications import report_critical_error
|
||||||
|
|
||||||
|
|
||||||
def get_restrictions_path(bot):
|
def get_restrictions_path(bot):
|
||||||
return os.path.join(bot.state_dir, "data/restrictions.json")
|
return os.path.join(bot.state_dir, "data/restrictions.json")
|
||||||
|
|
||||||
|
|
||||||
def get_restrictions(bot):
|
def get_restrictions(bot):
|
||||||
with open(get_restrictions_path(bot), "r") as f:
|
if os.path.isfile(get_restrictions_path(bot)):
|
||||||
return json.load(f)
|
with open(get_restrictions_path(bot), "r") as f:
|
||||||
|
try:
|
||||||
|
return json.load(f)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
content = f.read()
|
||||||
|
report_critical_error(
|
||||||
|
bot,
|
||||||
|
e,
|
||||||
|
additional_info={
|
||||||
|
"file": {"length": len(content), "content": content}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def set_restrictions(bot, contents):
|
def set_restrictions(bot, contents):
|
||||||
|
@ -18,11 +32,10 @@ def set_restrictions(bot, contents):
|
||||||
|
|
||||||
def get_user_restrictions(bot, uid):
|
def get_user_restrictions(bot, uid):
|
||||||
uid = str(uid)
|
uid = str(uid)
|
||||||
with open(get_restrictions_path(bot), "r") as f:
|
rsts = get_restrictions(bot)
|
||||||
rsts = json.load(f)
|
if uid in rsts:
|
||||||
if uid in rsts:
|
return rsts[uid]
|
||||||
return rsts[uid]
|
return []
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
def add_restriction(bot, uid, rst):
|
def add_restriction(bot, uid, rst):
|
||||||
|
|
|
@ -2,14 +2,28 @@ import json
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from robocop_ng.helpers.notifications import report_critical_error
|
||||||
|
|
||||||
|
|
||||||
def get_crontab_path(bot):
|
def get_crontab_path(bot):
|
||||||
return os.path.join(bot.state_dir, "data/robocronptab.json")
|
return os.path.join(bot.state_dir, "data/robocronptab.json")
|
||||||
|
|
||||||
|
|
||||||
def get_crontab(bot):
|
def get_crontab(bot):
|
||||||
with open(get_crontab_path(bot), "r") as f:
|
if os.path.isfile(get_crontab_path(bot)):
|
||||||
return json.load(f)
|
with open(get_crontab_path(bot), "r") as f:
|
||||||
|
try:
|
||||||
|
return json.load(f)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
content = f.read()
|
||||||
|
report_critical_error(
|
||||||
|
bot,
|
||||||
|
e,
|
||||||
|
additional_info={
|
||||||
|
"file": {"length": len(content), "content": content}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def set_crontab(bot, contents):
|
def set_crontab(bot, contents):
|
||||||
|
|
|
@ -2,6 +2,8 @@ import json
|
||||||
import os.path
|
import os.path
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from robocop_ng.helpers.notifications import report_critical_error
|
||||||
|
|
||||||
|
|
||||||
def get_persistent_roles_path(bot):
|
def get_persistent_roles_path(bot):
|
||||||
return os.path.join(bot.state_dir, "data/persistent_roles.json")
|
return os.path.join(bot.state_dir, "data/persistent_roles.json")
|
||||||
|
@ -10,7 +12,17 @@ def get_persistent_roles_path(bot):
|
||||||
def get_persistent_roles(bot) -> dict[str, list[str]]:
|
def get_persistent_roles(bot) -> dict[str, list[str]]:
|
||||||
if os.path.isfile(get_persistent_roles_path(bot)):
|
if os.path.isfile(get_persistent_roles_path(bot)):
|
||||||
with open(get_persistent_roles_path(bot), "r") as f:
|
with open(get_persistent_roles_path(bot), "r") as f:
|
||||||
return json.load(f)
|
try:
|
||||||
|
return json.load(f)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
content = f.read()
|
||||||
|
report_critical_error(
|
||||||
|
bot,
|
||||||
|
e,
|
||||||
|
additional_info={
|
||||||
|
"file": {"length": len(content), "content": content}
|
||||||
|
},
|
||||||
|
)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@ import json
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from robocop_ng.helpers.notifications import report_critical_error
|
||||||
|
|
||||||
userlog_event_types = {
|
userlog_event_types = {
|
||||||
"warns": "Warn",
|
"warns": "Warn",
|
||||||
"bans": "Ban",
|
"bans": "Ban",
|
||||||
|
@ -16,8 +18,20 @@ def get_userlog_path(bot):
|
||||||
|
|
||||||
|
|
||||||
def get_userlog(bot):
|
def get_userlog(bot):
|
||||||
with open(get_userlog_path(bot), "r") as f:
|
if os.path.isfile(get_userlog_path(bot)):
|
||||||
return json.load(f)
|
with open(get_userlog_path(bot), "r") as f:
|
||||||
|
try:
|
||||||
|
return json.load(f)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
content = f.read()
|
||||||
|
report_critical_error(
|
||||||
|
bot,
|
||||||
|
e,
|
||||||
|
additional_info={
|
||||||
|
"file": {"length": len(content), "content": content}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def set_userlog(bot, contents):
|
def set_userlog(bot, contents):
|
||||||
|
|
Loading…
Reference in a new issue