2024-02-21 01:13:39 +00:00
|
|
|
import asyncio
|
2023-12-05 21:12:33 +00:00
|
|
|
import logging
|
2023-12-05 18:06:39 +00:00
|
|
|
import os
|
|
|
|
import signal
|
2023-02-23 10:29:30 +00:00
|
|
|
import sys
|
2023-12-03 22:42:16 +00:00
|
|
|
import textwrap
|
2023-11-04 17:18:39 +00:00
|
|
|
from datetime import datetime, timedelta, timezone
|
2023-02-22 15:17:53 +00:00
|
|
|
|
2022-09-13 14:00:27 +01:00
|
|
|
import discord
|
|
|
|
from discord.ext import commands
|
2023-12-05 21:12:33 +00:00
|
|
|
from rich.logging import RichHandler
|
2023-11-04 17:18:39 +00:00
|
|
|
|
2023-12-05 21:12:33 +00:00
|
|
|
import config
|
2023-11-04 17:18:39 +00:00
|
|
|
from utils import JimmyBanException, JimmyBans, console, get_or_none
|
2023-02-22 15:17:53 +00:00
|
|
|
from utils.client import bot
|
2022-09-13 14:00:27 +01:00
|
|
|
|
2023-11-13 20:38:33 +00:00
|
|
|
logging.basicConfig(
|
2023-12-05 18:06:39 +00:00
|
|
|
format="%(asctime)s:%(levelname)s:%(name)s: %(message)s",
|
2023-11-13 20:38:33 +00:00
|
|
|
datefmt="%Y-%m-%d:%H:%M",
|
2023-12-05 18:06:39 +00:00
|
|
|
level=logging.DEBUG,
|
|
|
|
force=True,
|
|
|
|
handlers=[
|
|
|
|
RichHandler(
|
|
|
|
getattr(config, "LOG_LEVEL", logging.INFO),
|
|
|
|
console=console,
|
|
|
|
markup=True,
|
|
|
|
rich_tracebacks=True,
|
|
|
|
show_path=False,
|
2023-12-05 21:12:33 +00:00
|
|
|
show_time=False,
|
2023-12-05 18:06:39 +00:00
|
|
|
),
|
2023-12-05 21:12:33 +00:00
|
|
|
logging.FileHandler("jimmy.log", "a"),
|
|
|
|
],
|
2023-11-13 20:38:33 +00:00
|
|
|
)
|
2023-12-05 18:06:39 +00:00
|
|
|
logging.getLogger("discord.gateway").setLevel(logging.WARNING)
|
|
|
|
for _ln in [
|
|
|
|
"discord.client",
|
|
|
|
"httpcore.connection",
|
|
|
|
"httpcore.http2",
|
|
|
|
"hpack.hpack",
|
|
|
|
"discord.http",
|
|
|
|
"discord.bot",
|
|
|
|
"httpcore.http11",
|
|
|
|
"aiosqlite",
|
2023-12-05 21:12:33 +00:00
|
|
|
"httpx",
|
2023-12-05 18:06:39 +00:00
|
|
|
]:
|
|
|
|
logging.getLogger(_ln).setLevel(logging.INFO)
|
|
|
|
|
|
|
|
|
|
|
|
if os.name != "nt":
|
|
|
|
signal.signal(signal.SIGTERM, lambda: bot.loop.run_until_complete(bot.close()))
|
2023-11-13 20:38:33 +00:00
|
|
|
|
2022-09-13 14:00:27 +01:00
|
|
|
|
2022-10-11 14:31:23 +01:00
|
|
|
@bot.listen()
|
2022-10-09 19:36:21 +01:00
|
|
|
async def on_connect():
|
2023-12-05 16:43:21 +00:00
|
|
|
bot.log.info("[green]Connected to discord!")
|
2022-10-09 19:36:21 +01:00
|
|
|
|
|
|
|
|
2022-10-15 15:30:27 +01:00
|
|
|
@bot.listen("on_application_command_error")
|
|
|
|
async def on_application_command_error(ctx: discord.ApplicationContext, error: Exception):
|
2023-01-23 15:22:38 +00:00
|
|
|
if isinstance(error, commands.CommandOnCooldown):
|
|
|
|
now = discord.utils.utcnow()
|
|
|
|
now += timedelta(seconds=error.retry_after)
|
|
|
|
return await ctx.respond(
|
|
|
|
f"\N{stopwatch} This command is on cooldown. You can use this command again "
|
|
|
|
f"{discord.utils.format_dt(now, 'R')}.",
|
|
|
|
delete_after=error.retry_after,
|
|
|
|
)
|
|
|
|
elif isinstance(error, commands.MaxConcurrencyReached):
|
|
|
|
return await ctx.respond(
|
|
|
|
f"\N{warning sign} This command is already running. Please wait for it to finish.",
|
|
|
|
ephemeral=True,
|
|
|
|
)
|
2023-03-17 09:25:26 +00:00
|
|
|
elif isinstance(error, JimmyBanException):
|
|
|
|
return await ctx.respond(str(error))
|
2023-05-01 19:40:11 +01:00
|
|
|
elif isinstance(error, commands.CommandError):
|
|
|
|
if error.args and error.args[0] == "User not connected to a voice channel.":
|
|
|
|
return
|
|
|
|
|
2023-06-01 01:14:39 +01:00
|
|
|
if ctx.user.id == 1019233057519177778:
|
2024-02-21 01:13:39 +00:00
|
|
|
await ctx.respond("Something happened!")
|
|
|
|
await asyncio.sleep(5)
|
|
|
|
await ctx.edit(
|
|
|
|
content="Command Error: `%s`" % repr(error)[:1950],
|
|
|
|
)
|
2023-06-01 01:14:39 +01:00
|
|
|
else:
|
2023-12-03 22:42:16 +00:00
|
|
|
text = "Application Command Error: `%r`" % error
|
|
|
|
await ctx.respond(textwrap.shorten(text, 2000))
|
2023-01-09 14:36:32 +00:00
|
|
|
raise error
|
2022-10-15 15:30:27 +01:00
|
|
|
|
|
|
|
|
2022-10-15 15:31:21 +01:00
|
|
|
@bot.listen("on_command_error")
|
2022-10-30 16:05:54 +00:00
|
|
|
async def on_command_error(ctx: commands.Context, error: Exception):
|
|
|
|
if isinstance(error, commands.CommandNotFound):
|
|
|
|
return
|
2023-03-17 09:25:26 +00:00
|
|
|
elif isinstance(error, JimmyBanException):
|
|
|
|
return await ctx.reply(str(error))
|
2023-12-05 14:07:49 +00:00
|
|
|
await ctx.reply(textwrap.shorten("Command Error: `%r`" % error, 2000))
|
2023-01-09 14:36:32 +00:00
|
|
|
raise error
|
2022-10-15 15:31:21 +01:00
|
|
|
|
|
|
|
|
2022-11-01 17:22:56 +00:00
|
|
|
@bot.listen("on_application_command")
|
|
|
|
async def on_application_command(ctx: discord.ApplicationContext):
|
2023-12-05 16:43:21 +00:00
|
|
|
bot.log.info(
|
2022-11-01 17:22:56 +00:00
|
|
|
"{0.author} ({0.author.id}) used application command /{0.command.qualified_name} in "
|
2023-05-01 19:40:11 +01:00
|
|
|
"[blue]#{0.channel}[/], {0.guild}".format(ctx)
|
2022-11-01 17:22:56 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2022-10-11 14:31:23 +01:00
|
|
|
@bot.event
|
2022-09-13 14:00:27 +01:00
|
|
|
async def on_ready():
|
2023-12-05 18:06:39 +00:00
|
|
|
bot.log.info("(READY) Logged in as %r", bot.user)
|
2023-02-22 15:17:53 +00:00
|
|
|
if getattr(config, "CONNECT_MODE", None) == 1:
|
2023-12-05 16:43:21 +00:00
|
|
|
bot.log.critical("Bot is now ready and exit target 1 is set, shutting down.")
|
2023-02-22 15:17:53 +00:00
|
|
|
await bot.close()
|
2023-02-23 10:29:30 +00:00
|
|
|
sys.exit(0)
|
2022-09-13 14:00:27 +01:00
|
|
|
|
|
|
|
|
|
|
|
@bot.slash_command()
|
|
|
|
async def ping(ctx: discord.ApplicationContext):
|
2022-10-12 17:40:02 +01:00
|
|
|
# noinspection SpellCheckingInspection
|
2022-09-13 14:00:27 +01:00
|
|
|
"""Checks the bot's response time"""
|
|
|
|
gateway = round(ctx.bot.latency * 1000, 2)
|
2022-09-13 21:27:14 +01:00
|
|
|
return await ctx.respond(f"\N{white heavy check mark} Pong! `{gateway}ms`.")
|
2022-09-13 14:00:27 +01:00
|
|
|
|
2024-02-21 01:13:39 +00:00
|
|
|
# @bot.check_once
|
|
|
|
# async def check_not_banned(ctx: discord.ApplicationContext | commands.Context):
|
|
|
|
# if await bot.is_owner(ctx.author) or ctx.command.name in ("block", "unblock", "timetable", "verify", "kys"):
|
|
|
|
# return True
|
|
|
|
# user = ctx.author
|
|
|
|
# ban: JimmyBans = await get_or_none(JimmyBans, user_id=user.id)
|
|
|
|
# if ban:
|
|
|
|
# dt = datetime.fromtimestamp(ban.until, timezone.utc)
|
|
|
|
# if dt < discord.utils.utcnow():
|
|
|
|
# await ban.delete()
|
|
|
|
# else:
|
|
|
|
# raise JimmyBanException(dt, ban.reason)
|
|
|
|
# return True
|
2023-01-19 14:04:28 +00:00
|
|
|
|
|
|
|
|
2022-10-09 19:27:02 +01:00
|
|
|
if __name__ == "__main__":
|
2023-12-05 16:43:21 +00:00
|
|
|
bot.log.info("Starting...")
|
2023-02-22 01:33:30 +00:00
|
|
|
bot.started_at = discord.utils.utcnow()
|
2023-02-22 15:17:53 +00:00
|
|
|
|
|
|
|
if getattr(config, "WEB_SERVER", True):
|
2023-12-05 16:43:21 +00:00
|
|
|
bot.log.info("Web server is enabled (WEB_SERVER=True in config.py), initialising.")
|
2023-02-22 15:17:53 +00:00
|
|
|
import uvicorn
|
2023-11-04 17:18:39 +00:00
|
|
|
|
|
|
|
from web.server import app
|
|
|
|
|
2023-02-23 10:29:30 +00:00
|
|
|
app.state.bot = bot
|
2023-02-22 15:17:53 +00:00
|
|
|
|
|
|
|
http_config = uvicorn.Config(
|
|
|
|
app,
|
|
|
|
host=getattr(config, "HTTP_HOST", "127.0.0.1"),
|
|
|
|
port=getattr(config, "HTTP_PORT", 3762),
|
2023-11-04 17:18:39 +00:00
|
|
|
**getattr(config, "UVICORN_CONFIG", {}),
|
2023-02-22 15:17:53 +00:00
|
|
|
)
|
2023-12-05 16:43:21 +00:00
|
|
|
bot.log.info("Web server will listen on %s:%s", http_config.host, http_config.port)
|
2023-02-22 15:17:53 +00:00
|
|
|
server = uvicorn.Server(http_config)
|
2023-12-05 16:43:21 +00:00
|
|
|
bot.log.info("Starting web server...")
|
2023-02-22 15:17:53 +00:00
|
|
|
loop = bot.loop
|
|
|
|
http_server_task = loop.create_task(server.serve())
|
|
|
|
bot.web = {
|
|
|
|
"server": server,
|
|
|
|
"config": http_config,
|
|
|
|
"task": http_server_task,
|
|
|
|
}
|
2023-12-05 16:43:21 +00:00
|
|
|
bot.log.info("Beginning main loop.")
|
2022-10-09 19:27:02 +01:00
|
|
|
bot.run(config.token)
|