1
Fork 0
mirror of https://github.com/RGBCube/minearchy-bot synced 2025-07-27 08:57:46 +00:00
This commit is contained in:
RGBCube 2022-12-17 20:41:40 +03:00
parent 5b7fb2deba
commit 5ab80712d0
6 changed files with 45 additions and 36 deletions

View file

@ -2,12 +2,12 @@ from __future__ import annotations
__all__ = ("MinearchyBot",) __all__ = ("MinearchyBot",)
from asyncio import run as run_coro import asyncio
from inspect import cleandoc as strip_doc from inspect import cleandoc as strip
from itertools import chain as chain_iter from itertools import chain
from pathlib import Path from pathlib import Path
from time import time as current_time from time import time as get_time
from traceback import format_exc as format_exit from traceback import format_exc as format_exception
from aiohttp import ClientSession as AIOHTTPSession from aiohttp import ClientSession as AIOHTTPSession
from discord import AllowedMentions, Game, Intents, Webhook from discord import AllowedMentions, Game, Intents, Webhook
@ -58,7 +58,7 @@ class MinearchyBot(CommandsBot):
@override @override
async def on_ready(self) -> None: async def on_ready(self) -> None:
print( print(
strip_doc( strip(
f""" f"""
Connected to Discord! Connected to Discord!
User: {self.user} User: {self.user}
@ -67,12 +67,12 @@ class MinearchyBot(CommandsBot):
) )
) )
self.ready_timestamp = current_time() self.ready_timestamp = get_time()
await self.log_webhook.send("Bot is now online!") await self.log_webhook.send("Bot is now online!")
async def load_extensions(self) -> None: async def load_extensions(self) -> None:
cogs = Path(__file__).parent / "cogs" cogs = Path(__file__).parent / "cogs"
for file_name in chain_iter( for file_name in chain(
map( map(
lambda file_path: ".".join(file_path.relative_to(cogs.parent.parent).parts)[:-3], lambda file_path: ".".join(file_path.relative_to(cogs.parent.parent).parts)[:-3],
cogs.rglob("*.py"), cogs.rglob("*.py"),
@ -83,7 +83,7 @@ class MinearchyBot(CommandsBot):
await self.load_extension(file_name) await self.load_extension(file_name)
print(f"Loaded {file_name}") print(f"Loaded {file_name}")
except (ExtensionFailed, NoEntryPointError): except (ExtensionFailed, NoEntryPointError):
print(f"Couldn't load {file_name}:\n{format_exit()}") print(f"Couldn't load {file_name}:\n{format_exception()}")
@override @override
def run(self) -> None: def run(self) -> None:
@ -96,6 +96,6 @@ class MinearchyBot(CommandsBot):
await self.start(self.token, reconnect=True) await self.start(self.token, reconnect=True)
try: try:
run_coro(runner()) asyncio.run(runner())
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass

View file

@ -1,23 +1,29 @@
from __future__ import annotations from __future__ import annotations
from json import load as parse_json import json
from os import environ as env from os import environ as env
from pathlib import Path from pathlib import Path
from uvloop import install as install_uvloop import uvloop
from . import MinearchyBot from . import MinearchyBot
def main() -> None: def main() -> None:
install_uvloop() uvloop.install()
with (Path(__file__).parent / "config.json").open() as f: config = json.loads(
config = parse_json(f) (
Path(__file__).parent / "config.json"
).read_text()
)
for key in ("HIDE", "NO_UNDERSCORE"): env[f"JISHAKU_HIDE"] = "True"
env[f"JISHAKU_{key}"] = "True" env[f"JISHAKU_NO_UNDERSCORE"] = "True"
bot = MinearchyBot(token=config["BOT_TOKEN"], webhook_url=config["WEBHOOK_URL"]) bot = MinearchyBot(
token=config["BOT_TOKEN"],
webhook_url=config["WEBHOOK_URL"]
)
bot.run() bot.run()

View file

@ -1,8 +1,8 @@
from __future__ import annotations from __future__ import annotations
from asyncio import gather as await_parallel import asyncio
from contextlib import suppress as suppress_error from contextlib import suppress as suppress_error
from traceback import format_exception as format_exit from traceback import format_exception
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from discord import HTTPException from discord import HTTPException
@ -61,10 +61,10 @@ class ErrorHandler(Cog):
await ctx.reply("Invalid channel.") await ctx.reply("Invalid channel.")
else: else:
trace = "".join(format_exit(type(error), error, error.__traceback__)) trace = "".join(format_exception(type(error), error, error.__traceback__))
print(f"Ignoring exception in command {ctx.command}:\n{trace}") print(f"Ignoring exception in command {ctx.command}:\n{trace}")
await await_parallel( await asyncio.gather(
self.bot.log_webhook.send(f"<@512640455834337290>```{trace}```"), self.bot.log_webhook.send(f"<@512640455834337290>```{trace}```"),
ctx.reply( ctx.reply(
"An error occurred while executing the command. The error has been reported." "An error occurred while executing the command. The error has been reported."

View file

@ -2,7 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from discord.ext.commands import Cog, command, group from discord.ext import commands
from discord.ext.commands import Cog, command
from discord.ui import Button, View from discord.ui import Button, View
if TYPE_CHECKING: if TYPE_CHECKING:
@ -19,7 +20,7 @@ class MinecraftServer(
def __init__(self, bot: MinearchyBot) -> None: def __init__(self, bot: MinearchyBot) -> None:
self.bot = bot self.bot = bot
@group( @commands.group(
invoke_without_command=True, invoke_without_command=True,
brief="Sends the server IP.", brief="Sends the server IP.",
help="Sends the server IP.", help="Sends the server IP.",

View file

@ -2,14 +2,15 @@ from __future__ import annotations
from collections import defaultdict as DefaultDict, deque as Deque from collections import defaultdict as DefaultDict, deque as Deque
from datetime import timedelta as TimeDelta from datetime import timedelta as TimeDelta
from inspect import cleandoc as strip_doc from inspect import cleandoc as strip
from io import BytesIO from io import BytesIO
from platform import python_version from platform import python_version
from time import monotonic as ping_time, time as current_time from time import monotonic as get_monotonic, time as get_time
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from discord import CategoryChannel, Color, Embed, File, TextChannel from discord import CategoryChannel, Color, Embed, File, TextChannel
from discord.ext.commands import Cog, command, has_permissions from discord.ext import commands
from discord.ext.commands import Cog, command
from discord.utils import escape_markdown from discord.utils import escape_markdown
from ..utils import override from ..utils import override
@ -52,9 +53,9 @@ class Miscellaneous(
help="Sends the bots ping." help="Sends the bots ping."
) )
async def ping(self, ctx: Context) -> None: async def ping(self, ctx: Context) -> None:
ts = ping_time() ts = get_monotonic()
message = await ctx.reply("Pong!") message = await ctx.reply("Pong!")
ts = ping_time() - ts ts = get_monotonic() - ts
await message.edit(content=f"Pong! `{int(ts * 1000)}ms`") await message.edit(content=f"Pong! `{int(ts * 1000)}ms`")
@command( @command(
@ -63,11 +64,11 @@ class Miscellaneous(
) )
async def info(self, ctx: Context) -> None: async def info(self, ctx: Context) -> None:
await ctx.reply( await ctx.reply(
strip_doc( strip(
f""" f"""
__**Bot Info**__ __**Bot Info**__
**Python Version:** v{python_version()} **Python Version:** v{python_version()}
**Uptime:** `{TimeDelta(seconds=int(current_time() - self.bot.ready_timestamp))}` **Uptime:** `{TimeDelta(seconds=int(get_time() - self.bot.ready_timestamp))}`
""" """
) )
) )
@ -155,7 +156,7 @@ class Miscellaneous(
" isn't specified, it uses the current channel." " isn't specified, it uses the current channel."
), ),
) )
@has_permissions(manage_messages=True) # needs to be able to delete messages to run the command @commands.has_permissions(manage_messages=True) # needs to be able to delete messages to run the command
async def snipe(self, ctx: Context, channel: TextChannel | None = None) -> None: async def snipe(self, ctx: Context, channel: TextChannel | None = None) -> None:
if channel is None: if channel is None:
channel = ctx.channel channel = ctx.channel
@ -185,7 +186,7 @@ class Miscellaneous(
embed.add_field( embed.add_field(
name=str(i) + ("" if i else " (latest)"), name=str(i) + ("" if i else " (latest)"),
value=strip_doc( value=strip(
f""" f"""
Author: {message.author.mention} (ID: {message.author.id}, Plain: {escape_markdown(str(message.author))}) Author: {message.author.mention} (ID: {message.author.id}, Plain: {escape_markdown(str(message.author))})
Deleted at: <t:{ts}:F> (Relative: <t:{ts}:R>) Deleted at: <t:{ts}:F> (Relative: <t:{ts}:R>)
@ -205,7 +206,7 @@ class Miscellaneous(
if not message.guild: if not message.guild:
return return
self.sniped[message.channel.id].appendleft((message, int(current_time()))) self.sniped[message.channel.id].appendleft((message, int(get_time())))
while len(self.sniped[message.channel.id]) > 5: while len(self.sniped[message.channel.id]) > 5:
self.sniped[message.channel.id].pop() self.sniped[message.channel.id].pop()

View file

@ -3,7 +3,8 @@ from __future__ import annotations
from datetime import timedelta as TimeDelta from datetime import timedelta as TimeDelta
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from discord.ext.commands import Cog, command, has_permissions from discord.ext import commands
from discord.ext.commands import Cog, command
if TYPE_CHECKING: if TYPE_CHECKING:
from discord import Member from discord import Member
@ -27,7 +28,7 @@ class Moderation(Cog):
brief="Times out a user.", brief="Times out a user.",
help="Times out a user." help="Times out a user."
) )
@has_permissions(manage_messages=True) @commands.has_permissions(manage_messages=True)
async def timeout(self, ctx: Context, member: Member, duration: str = "1d") -> None: async def timeout(self, ctx: Context, member: Member, duration: str = "1d") -> None:
if duration[-1] not in self.time_values or len(duration) < 2: if duration[-1] not in self.time_values or len(duration) < 2:
await ctx.reply("Invalid duration. Valid durations are: d, h, m, s.") await ctx.reply("Invalid duration. Valid durations are: d, h, m, s.")