college-bot-v1/main.py

169 lines
5.2 KiB
Python
Raw Permalink Normal View History

2023-12-05 18:06:39 +00:00
import os
import signal
2023-02-23 10:29:30 +00:00
import sys
2023-11-13 20:38:33 +00:00
import logging
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-12-05 16:43:21 +00:00
from rich.logging import RichHandler
2023-02-22 15:17:53 +00:00
2023-11-04 17:18:39 +00:00
import config
2022-09-13 14:00:27 +01:00
import discord
from discord.ext import commands
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,
show_time=False
),
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",
"httpx"
]:
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
@bot.listen("on_application_command_error")
async def on_application_command_error(ctx: discord.ApplicationContext, error: Exception):
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:
await ctx.respond("Uh oh! I did a fucky wucky >.< I'll make sure to let important peoplez know straight away!!")
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: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
2023-01-19 14:04:28 +00:00
@bot.check_once
async def check_not_banned(ctx: discord.ApplicationContext | commands.Context):
2023-03-17 09:25:26 +00:00
if await bot.is_owner(ctx.author) or ctx.command.name in ("block", "unblock", "timetable", "verify", "kys"):
2023-01-19 14:04:28 +00:00
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:
2023-03-17 09:25:26 +00:00
raise JimmyBanException(dt, ban.reason)
2023-01-19 14:04:28 +00:00
return True
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)