diff --git a/.idea/dictionaries/romain.xml b/.idea/dictionaries/romain.xml index d6f5b03..b11d467 100644 --- a/.idea/dictionaries/romain.xml +++ b/.idea/dictionaries/romain.xml @@ -38,6 +38,7 @@ tuxbot's tuxvenv venv + webhook webhooks écrite diff --git a/.pylintrc b/.pylintrc index bb75e4a..b978cd6 100644 --- a/.pylintrc +++ b/.pylintrc @@ -4,6 +4,7 @@ good-names= f, # (file) as f k, # for k, v in v, # for k, v in + dt, # datetime [MASTER] disable= @@ -11,5 +12,6 @@ disable= C0115, # missing-class-docstring C0116, # missing-function-docstring W0703, # broad-except + R0801, # duplicate-code R0902, # too-many-instance-attributes R0903, # too-few-public-methods diff --git a/tuxbot/__main__.py b/tuxbot/__main__.py index 880a6d4..fdf4ebe 100644 --- a/tuxbot/__main__.py +++ b/tuxbot/__main__.py @@ -1,5 +1,3 @@ -from typing import NoReturn - from rich.console import Console from rich.traceback import install from tuxbot import ExitCodes @@ -8,7 +6,7 @@ console = Console() install(console=console) -def main() -> NoReturn: +def main() -> None: try: from .__run__ import run # pylint: disable=import-outside-toplevel diff --git a/tuxbot/__run__.py b/tuxbot/__run__.py index 2876b4a..9039a54 100644 --- a/tuxbot/__run__.py +++ b/tuxbot/__run__.py @@ -6,7 +6,6 @@ import sys import os import tracemalloc from argparse import Namespace -from typing import NoReturn from datetime import datetime import discord @@ -35,7 +34,7 @@ tracemalloc.start() BORDER_STYLE = "not dim" -def list_instances() -> NoReturn: +def list_instances() -> None: """List all available instances""" app_config = config.ConfigFile( data_manager.config_dir / "config.yaml", config.AppConfig @@ -70,7 +69,7 @@ def list_instances() -> NoReturn: sys.exit(os.EX_OK) -def debug_info() -> NoReturn: +def debug_info() -> None: """Show debug info relatives to the bot""" python_version = sys.version.replace("\n", "") pip_version = pip.__version__ @@ -172,7 +171,7 @@ def parse_cli_flags(args: list) -> Namespace: return args -async def shutdown_handler(tux: Tux, signal_type, exit_code=None) -> NoReturn: +async def shutdown_handler(tux: Tux, signal_type, exit_code=None) -> None: """Handler when the bot shutdown It cancels all running task. @@ -247,7 +246,7 @@ async def run_bot(tux: Tux, cli_flags: Namespace) -> None: return None -def run() -> NoReturn: +def run() -> None: """Main function""" tux = None cli_flags = parse_cli_flags(sys.argv[1:]) diff --git a/tuxbot/cogs/admin/config.py b/tuxbot/cogs/admin/config.py index 23e3984..ff6762b 100644 --- a/tuxbot/cogs/admin/config.py +++ b/tuxbot/cogs/admin/config.py @@ -1,36 +1,8 @@ -from structured_config import Structure, StrField +from structured_config import Structure class AdminConfig(Structure): - dm: str = StrField("") - mentions: str = StrField("") - guilds: str = StrField("") - errors: str = StrField("") - gateway: str = StrField("") + pass -extra = { - "dm": { - "type": str, - "description": "URL of the webhook used for send DMs " - "received and sent by the bot", - }, - "mentions": { - "type": str, - "description": "URL of the webhook used for send Mentions " - "received by the bot", - }, - "guilds": { - "type": str, - "description": "URL of the webhook used for send guilds where the " - "bot is added or removed", - }, - "errors": { - "type": str, - "description": "URL of the webhook used for send errors in the bot", - }, - "gateway": { - "type": str, - "description": "URL of the webhook used for send gateway information", - }, -} +extra = {} diff --git a/tuxbot/cogs/admin/locales/messages.pot b/tuxbot/cogs/admin/locales/messages.pot index c522501..5bf0f40 100644 --- a/tuxbot/cogs/admin/locales/messages.pot +++ b/tuxbot/cogs/admin/locales/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Tuxbot-bot\n" "Report-Msgid-Bugs-To: rick@gnous.eu\n" -"POT-Creation-Date: 2020-06-11 19:07+0200\n" +"POT-Creation-Date: 2020-10-21 01:13+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,11 +17,11 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: tuxbot/cogs/admin/admin.py:33 +#: tuxbot/cogs/admin/admin.py:47 #, python-brace-format msgid "Locale changed to {lang} successfully" msgstr "" -#: tuxbot/cogs/admin/admin.py:43 +#: tuxbot/cogs/admin/admin.py:62 msgid "List of available locales: " msgstr "" diff --git a/tuxbot/cogs/logs/__init__.py b/tuxbot/cogs/logs/__init__.py new file mode 100644 index 0000000..85eaf19 --- /dev/null +++ b/tuxbot/cogs/logs/__init__.py @@ -0,0 +1,27 @@ +import logging +from collections import namedtuple + +from discord.ext import commands + +from .logs import Logs, on_error, GatewayHandler +from .config import LogsConfig +from ...core.bot import Tux + +VersionInfo = namedtuple("VersionInfo", "major minor micro release_level") +version_info = VersionInfo(major=1, minor=0, micro=0, release_level="alpha") + +__version__ = "v{}.{}.{}-{}".format( + version_info.major, + version_info.minor, + version_info.micro, + version_info.release_level, +).replace("\n", "") + + +def setup(bot: Tux): + cog = Logs(bot) + bot.add_cog(cog) + + handler = GatewayHandler(cog) + logging.getLogger().addHandler(handler) + commands.AutoShardedBot.on_error = on_error diff --git a/tuxbot/cogs/logs/config.py b/tuxbot/cogs/logs/config.py new file mode 100644 index 0000000..e1f7802 --- /dev/null +++ b/tuxbot/cogs/logs/config.py @@ -0,0 +1,36 @@ +from structured_config import Structure, StrField + + +class LogsConfig(Structure): + dm: str = StrField("") + mentions: str = StrField("") + guilds: str = StrField("") + errors: str = StrField("") + gateway: str = StrField("") + + +extra = { + "dm": { + "type": str, + "description": "URL of the webhook used for send DMs " + "received and sent by the bot", + }, + "mentions": { + "type": str, + "description": "URL of the webhook used for send Mentions " + "received by the bot", + }, + "guilds": { + "type": str, + "description": "URL of the webhook used for send guilds where the " + "bot is added or removed", + }, + "errors": { + "type": str, + "description": "URL of the webhook used for send errors in the bot", + }, + "gateway": { + "type": str, + "description": "URL of the webhook used for send gateway information", + }, +} diff --git a/tuxbot/cogs/logs/locales/en-US.po b/tuxbot/cogs/logs/locales/en-US.po new file mode 100644 index 0000000..d7bc028 --- /dev/null +++ b/tuxbot/cogs/logs/locales/en-US.po @@ -0,0 +1,18 @@ +# English translations for Tuxbot-bot package. +# Copyright (C) 2020 THE Tuxbot-bot'S COPYRIGHT HOLDER +# This file is distributed under the same license as the Tuxbot-bot package. +# Automatically generated, 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: Tuxbot-bot\n" +"Report-Msgid-Bugs-To: rick@gnous.eu\n" +"POT-Creation-Date: 2020-10-21 01:15+0200\n" +"PO-Revision-Date: 2020-10-21 01:15+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" diff --git a/tuxbot/cogs/logs/locales/fr-FR.po b/tuxbot/cogs/logs/locales/fr-FR.po new file mode 100644 index 0000000..3562511 --- /dev/null +++ b/tuxbot/cogs/logs/locales/fr-FR.po @@ -0,0 +1,19 @@ +# French translations for Tuxbot-bot package +# Traductions françaises du paquet Tuxbot-bot. +# Copyright (C) 2020 THE Tuxbot-bot'S COPYRIGHT HOLDER +# This file is distributed under the same license as the Tuxbot-bot package. +# Automatically generated, 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: Tuxbot-bot\n" +"Report-Msgid-Bugs-To: rick@gnous.eu\n" +"POT-Creation-Date: 2020-10-21 01:15+0200\n" +"PO-Revision-Date: 2020-10-21 01:15+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" diff --git a/tuxbot/cogs/logs/locales/messages.pot b/tuxbot/cogs/logs/locales/messages.pot new file mode 100644 index 0000000..9c11528 --- /dev/null +++ b/tuxbot/cogs/logs/locales/messages.pot @@ -0,0 +1,18 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the Tuxbot-bot package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Tuxbot-bot\n" +"Report-Msgid-Bugs-To: rick@gnous.eu\n" +"POT-Creation-Date: 2020-10-21 01:15+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" diff --git a/tuxbot/cogs/logs/logs.py b/tuxbot/cogs/logs/logs.py new file mode 100644 index 0000000..9f53163 --- /dev/null +++ b/tuxbot/cogs/logs/logs.py @@ -0,0 +1,332 @@ +import asyncio +import datetime +import json +import logging +import textwrap +import traceback +from collections import defaultdict +from logging import LogRecord + +import discord +import humanize +import psutil +from discord.ext import commands, tasks +from structured_config import ConfigFile + +from tuxbot.core.bot import Tux +from tuxbot.core.i18n import ( + Translator, +) +from tuxbot.core.utils.functions.extra import ( + command_extra, + ContextPlus, +) +from .config import LogsConfig +from ...core.data_manager import cogs_data_path + +log = logging.getLogger("tuxbot.cogs.logs") +_ = Translator("Logs", __file__) + + +class GatewayHandler(logging.Handler): + def __init__(self, cog): + self.cog = cog + super().__init__(logging.INFO) + + def filter(self, record: LogRecord): + return ( + record.name == "discord.gateway" + or "Shard ID" in record.msg + or "Websocket closed " in record.msg + ) + + def emit(self, record: LogRecord): + self.cog.add_record(record) + + +class Logs(commands.Cog, name="Logs"): + def __init__(self, bot: Tux): + self.bot = bot + self.process = psutil.Process() + self._batch_lock = asyncio.Lock(loop=bot.loop) + self._data_batch = [] + self._gateway_queue = asyncio.Queue(loop=bot.loop) + self.gateway_worker.start() # pylint: disable=no-member + + self.config: LogsConfig = ConfigFile( + str( + cogs_data_path(self.bot.instance_name, "logs") / "config.yaml" + ), + LogsConfig, + ).config + + self._resumes = [] + self._identifies = defaultdict(list) + + def _clear_gateway_data(self): + one_week_ago = datetime.datetime.utcnow() - datetime.timedelta(days=7) + to_remove = [ + index + for index, dt in enumerate(self._resumes) + if dt < one_week_ago + ] + for index in reversed(to_remove): + del self._resumes[index] + + for _, dates in self._identifies.items(): + to_remove = [ + index for index, dt in enumerate(dates) if dt < one_week_ago + ] + for index in reversed(to_remove): + del dates[index] + + @tasks.loop(seconds=0.0) + async def gateway_worker(self): + record = await self._gateway_queue.get() + await self.notify_gateway_status(record) + + async def register_command(self, ctx: ContextPlus): + if ctx.command is None: + return + + command = ctx.command.qualified_name + self.bot.stats["commands"][command] += 1 + message = ctx.message + if ctx.guild is None: + destination = "Private Message" + guild_id = None + else: + destination = f"#{message.channel} ({message.guild})" + guild_id = ctx.guild.id + + log.info( + "%s: %s in %s > %s", + message.created_at, + message.author, + destination, + message.content, + ) + async with self._batch_lock: + self._data_batch.append( + { + "guild": guild_id, + "channel": ctx.channel.id, + "author": ctx.author.id, + "used": message.created_at.isoformat(), + "prefix": ctx.prefix, + "command": command, + "failed": ctx.command_failed, + } + ) + + @commands.Cog.listener() + async def on_command_completion(self, ctx: ContextPlus): + await self.register_command(ctx) + + @commands.Cog.listener() + async def on_socket_response(self, msg): + self.bot.stats["socket"][msg.get("t")] += 1 + + def webhook(self, log_type): + webhook = discord.Webhook.from_url( + getattr(self.config, log_type), + adapter=discord.AsyncWebhookAdapter(self.bot.session), + ) + return webhook + + async def log_error(self, *, ctx: ContextPlus = None, extra=None): + e = discord.Embed(title="Error", colour=0xDD5F53) + e.description = f"```py\n{traceback.format_exc()}\n```" + e.add_field(name="Extra", value=extra, inline=False) + e.timestamp = datetime.datetime.utcnow() + + if ctx is not None: + fmt = "{0} (ID: {0.id})" + author = fmt.format(ctx.author) + channel = fmt.format(ctx.channel) + guild = "None" if ctx.guild is None else fmt.format(ctx.guild) + + e.add_field(name="Author", value=author) + e.add_field(name="Channel", value=channel) + e.add_field(name="Guild", value=guild) + + await self.webhook("errors").send(embed=e) + + async def send_guild_stats(self, e, guild): + e.add_field(name="Name", value=guild.name) + e.add_field(name="ID", value=guild.id) + e.add_field(name="Shard ID", value=guild.shard_id or "N/A") + e.add_field( + name="Owner", value=f"{guild.owner} (ID: {guild.owner.id})" + ) + + bots = sum(member.bot for member in guild.members) + total = guild.member_count + online = sum( + member.status is discord.Status.online for member in guild.members + ) + + e.add_field(name="Members", value=str(total)) + e.add_field(name="Bots", value=f"{bots} ({bots / total:.2%})") + e.add_field(name="Online", value=f"{online} ({online / total:.2%})") + + if guild.icon: + e.set_thumbnail(url=guild.icon_url) + + if guild.me: + e.timestamp = guild.me.joined_at + + await self.webhook("guilds").send(embed=e) + + @commands.Cog.listener() + async def on_guild_join(self, guild: discord.guild): + e = discord.Embed(colour=0x53DDA4, title="New Guild") # green colour + await self.send_guild_stats(e, guild) + + @commands.Cog.listener() + async def on_guild_remove(self, guild: discord.guild): + e = discord.Embed(colour=0xDD5F53, title="Left Guild") # red colour + await self.send_guild_stats(e, guild) + + @commands.Cog.listener() + async def on_message(self, message: discord.message): + if message.guild is None: + e = discord.Embed(colour=0x0A97F5, title="New DM") # blue colour + e.set_author( + name=message.author, + icon_url=message.author.avatar_url_as(format="png"), + ) + e.description = message.content + if len(message.attachments) > 0: + e.set_image(url=message.attachments[0].url) + e.set_footer(text=f"User ID: {message.author.id}") + await self.webhook("dm").send(embed=e) + + @commands.Cog.listener() + async def on_command_error(self, ctx: ContextPlus, error): + await self.register_command(ctx) + if not isinstance( + error, (commands.CommandInvokeError, commands.ConversionError) + ): + return + + error = error.original + if isinstance(error, (discord.Forbidden, discord.NotFound)): + return + + e = discord.Embed(title="Command Error", colour=0xCC3366) + e.add_field(name="Name", value=ctx.command.qualified_name) + e.add_field(name="Author", value=f"{ctx.author} (ID: {ctx.author.id})") + + fmt = f"Channel: {ctx.channel} (ID: {ctx.channel.id})" + if ctx.guild: + fmt = f"{fmt}\nGuild: {ctx.guild} (ID: {ctx.guild.id})" + + e.add_field(name="Location", value=fmt, inline=False) + e.add_field( + name="Content", + value=textwrap.shorten(ctx.message.content, width=512), + ) + + exc = "".join( + traceback.format_exception( + type(error), error, error.__traceback__, chain=False + ) + ) + e.description = f"```py\n{exc}\n```" + e.timestamp = datetime.datetime.utcnow() + await self.webhook("errors").send(embed=e) + + @commands.Cog.listener() + async def on_socket_raw_send(self, data): + if '"op":2' not in data and '"op":6' not in data: + return + + back_to_json = json.loads(data) + if back_to_json["op"] == 2: + payload = back_to_json["d"] + inner_shard = payload.get("shard", [0]) + self._identifies[inner_shard[0]].append(datetime.datetime.utcnow()) + else: + self._resumes.append(datetime.datetime.utcnow()) + + self._clear_gateway_data() + + def add_record(self, record: LogRecord): + self._gateway_queue.put_nowait(record) + + async def notify_gateway_status(self, record: LogRecord): + types = {"INFO": ":information_source:", "WARNING": ":warning:"} + + emoji = types.get(record.levelname, ":heavy_multiplication_x:") + dt = datetime.datetime.utcfromtimestamp(record.created) + msg = f"{emoji} `[{dt:%Y-%m-%d %H:%M:%S}] {record.message}`" + await self.webhook("gateway").send(msg) + + @command_extra(name="commandstats", hidden=True, deletable=True) + @commands.is_owner() + async def _commandstats(self, ctx: ContextPlus, limit=20): + counter = self.bot.stats["commands"] + width = len(max(counter, key=len)) + 1 + + if limit > 0: + common = counter.most_common(limit) + else: + common = counter.most_common()[limit:] + + output = "\n".join(f"{k:<{width}}: {c}" for k, c in common) + + await ctx.send(f"```\n{output}\n```") + + @command_extra(name="socketstats", hidden=True, deletable=True) + @commands.is_owner() + async def _socketstats(self, ctx: ContextPlus): + delta = datetime.datetime.now() - self.bot.uptime + minutes = delta.total_seconds() / 60 + + counter = self.bot.stats["socket"] + if None in counter: + counter.pop(None) + width = len(max(counter, key=len)) + 1 + common = counter.most_common() + + total = sum(self.bot.stats["socket"].values()) + cpm = total / minutes + + output = "\n".join(f"{k:<{width}}: {c}" for k, c in common) + + await ctx.send( + f"{total} socket events observed ({cpm:.2f}/minute):" + f"```\n{output}\n```" + ) + + @command_extra(name="uptime") + async def _uptime(self, ctx: ContextPlus): + uptime = humanize.naturaltime( + datetime.datetime.now() - self.bot.uptime + ) + await ctx.send(f"Uptime: **{uptime}**") + + +async def on_error(self, event, *args): + e = discord.Embed(title="Event Error", colour=0xA32952) + e.add_field(name="Event", value=event) + e.description = f"```py\n{traceback.format_exc()}\n```" + e.timestamp = datetime.datetime.utcnow() + + args_str = ["```py"] + for index, arg in enumerate(args): + args_str.append(f"[{index}]: {arg!r}") + args_str.append("```") + e.add_field(name="Args", value="\n".join(args_str), inline=False) + + hook = self.get_cog("Logs").webhook("errors") + try: + await hook.send(embed=e) + except ( + discord.HTTPException, + discord.NotFound, + discord.Forbidden, + discord.InvalidArgument, + ): + pass diff --git a/tuxbot/core/bot.py b/tuxbot/core/bot.py index 1897a19..9541075 100644 --- a/tuxbot/core/bot.py +++ b/tuxbot/core/bot.py @@ -1,8 +1,10 @@ import asyncio import datetime import logging +from collections import Counter from typing import List, Union +import aiohttp import discord from discord.ext import commands from rich import box @@ -33,7 +35,7 @@ log = logging.getLogger("tuxbot") console = Console() install(console=console) -packages: List[str] = ["jishaku", "tuxbot.cogs.admin"] +packages: List[str] = ["jishaku", "tuxbot.cogs.admin", "tuxbot.cogs.logs"] class Tux(commands.AutoShardedBot): @@ -55,6 +57,10 @@ class Tux(commands.AutoShardedBot): self.last_exception = None self.logs = logs_data_path(self.instance_name) + self.console = console + + self.stats = {"commands": Counter(), "socket": Counter()} + self.config: Config = ConfigFile( str(data_path(self.instance_name) / "config.yaml"), Config ).config @@ -84,6 +90,7 @@ class Tux(commands.AutoShardedBot): self._app_owners_fetched = False # to prevent abusive API calls super().__init__(*args, help_command=None, **kwargs) + self.session = aiohttp.ClientSession(loop=self.loop) async def load_packages(self): if packages: diff --git a/tuxbot/core/config.py b/tuxbot/core/config.py index 6d8a13e..9ea992c 100644 --- a/tuxbot/core/config.py +++ b/tuxbot/core/config.py @@ -1,5 +1,5 @@ import logging -from typing import List, Dict, Any, NoReturn +from typing import List, Dict, Any from structured_config import ( Structure, IntField, @@ -80,7 +80,7 @@ def search_for(config, key, value, default=False) -> Any: return default -def set_for_key(config, key, ctype, **values) -> NoReturn: +def set_for_key(config, key, ctype, **values) -> None: # pylint: disable=anomalous-backslash-in-string """ La fonction suivante \`*-. @@ -105,6 +105,6 @@ def set_for_key(config, key, ctype, **values) -> NoReturn: setattr(config[key], k, v) -def set_for(config, **values) -> NoReturn: +def set_for(config, **values) -> None: for k, v in values.items(): setattr(config, k, v) diff --git a/tuxbot/core/utils/functions/extra.py b/tuxbot/core/utils/functions/extra.py index 44897db..0fe7915 100644 --- a/tuxbot/core/utils/functions/extra.py +++ b/tuxbot/core/utils/functions/extra.py @@ -12,24 +12,45 @@ TOKEN_REPLACEMENT = "whoops, leaked token" class ContextPlus(commands.Context): - async def send(self, *args, content=None, **kwargs): - if content is not None: + async def send( + self, + content=None, + *, + tts=False, + embed=None, + file=None, + files=None, + delete_after=None, + nonce=None, + allowed_mentions=None, + deletable=False + ): # i know *args and **kwargs but, i prefer work with same values + if content: content = content.replace( self.bot.config.Core.token, TOKEN_REPLACEMENT ) - if kwargs.get("embed"): - embed = kwargs["embed"].to_dict() - for key, value in embed.items(): + if embed: + e = embed.to_dict() + for key, value in e.items(): if isinstance(value, (str, bytes)): - embed[key] = value.replace( + e[key] = value.replace( self.bot.config.Core.token, TOKEN_REPLACEMENT ) - kwargs["embed"] = Embed.from_dict(embed) + embed = Embed.from_dict(e) if ( hasattr(self.command, "deletable") and self.command.deletable - ) or kwargs.pop("deletable", False): - message = await super().send(content, *args, **kwargs) + ) or deletable: + message = await super().send( + content=content, + tts=tts, + embed=embed, + file=file, + files=files, + delete_after=delete_after, + nonce=nonce, + allowed_mentions=allowed_mentions, + ) await message.add_reaction("🗑") def check(reaction: discord.Reaction, user: discord.User): @@ -49,7 +70,16 @@ class ContextPlus(commands.Context): await message.delete() return message - return await super().send(content, *args, **kwargs) + return await super().send( + content=content, + tts=tts, + embed=embed, + file=file, + files=files, + delete_after=delete_after, + nonce=nonce, + allowed_mentions=allowed_mentions, + ) class CommandPLus(flags.FlagCommand): diff --git a/tuxbot/logging.py b/tuxbot/logging.py index 44cabb5..3b99329 100644 --- a/tuxbot/logging.py +++ b/tuxbot/logging.py @@ -24,19 +24,19 @@ def init_logging(level: int, location: pathlib.Path) -> None: Where to store logs. """ - dpy_logger = logging.getLogger("discord") - dpy_logger.setLevel(logging.WARN) - dpy_logger_file = location / "discord.log" + # dpy_logger = logging.getLogger("discord") + # dpy_logger.setLevel(logging.WARN) + # dpy_logger_file = location / "discord.log" base_logger = logging.getLogger("tuxbot") base_logger.setLevel(level) base_logger_file = location / "tuxbot.log" - dpy_handler = logging.handlers.RotatingFileHandler( - str(dpy_logger_file.resolve()), - maxBytes=MAX_BYTES, - backupCount=MAX_OLD_LOGS, - ) + # dpy_handler = logging.handlers.RotatingFileHandler( + # str(dpy_logger_file.resolve()), + # maxBytes=MAX_BYTES, + # backupCount=MAX_OLD_LOGS, + # ) base_handler = logging.handlers.RotatingFileHandler( str(base_logger_file.resolve()), maxBytes=MAX_BYTES, @@ -46,8 +46,8 @@ def init_logging(level: int, location: pathlib.Path) -> None: stdout_handler = logging.StreamHandler(sys.stdout) stdout_handler.setFormatter(formatter) - dpy_handler.setFormatter(formatter) + # dpy_handler.setFormatter(formatter) base_handler.setFormatter(formatter) - dpy_logger.addHandler(dpy_handler) + # dpy_logger.addHandler(dpy_handler) base_logger.addHandler(base_handler) diff --git a/tuxbot/setup.py b/tuxbot/setup.py index da7270b..0dd3801 100644 --- a/tuxbot/setup.py +++ b/tuxbot/setup.py @@ -5,7 +5,7 @@ import re import sys from argparse import Namespace from pathlib import Path -from typing import NoReturn, Union, List +from typing import Union, List from rich.prompt import Prompt, IntPrompt from rich.console import Console @@ -263,7 +263,7 @@ def additional_config(instance: str, cogs: str = "**"): ) -def finish_setup(data_dir: Path) -> NoReturn: +def finish_setup(data_dir: Path) -> None: """Configs who directly refer to the bot. Parameters @@ -311,7 +311,7 @@ def finish_setup(data_dir: Path) -> NoReturn: instance_config.config.Core.locale = "en-US" -def basic_setup() -> NoReturn: +def basic_setup() -> None: """Configs who refer to instances.""" console.print( Rule( @@ -395,7 +395,7 @@ def parse_cli_flags(args: list) -> Namespace: return args -def setup() -> NoReturn: +def setup() -> None: cli_flags = parse_cli_flags(sys.argv[1:]) try: