umi/app.py
a 4ac878fecb Modern packaging
- add pyproject.toml, README, and recommend using pdm
- cleanup dependencies and switch to better ones
- remove mumble stub

fix missing env var call
fix null env var
2022-12-12 06:59:21 -06:00

123 lines
3.7 KiB
Python

import discord
""" Declare intents that the bot will use """
intents = discord.Intents.default()
intents.emojis_and_stickers = True
intents.guilds = True
intents.integrations = True
intents.message_content = True
intents.messages = True
intents.members = True
intents.presences = True
intents.reactions = True
intents.voice_states = True
""" Load the bot token """
from decouple import config
DISCORD_TOKEN: str = config("DISCORD_BOT_TOKEN")
DISCORD_GUILD: int = config("DISCORD_GUILD_ID", cast=int)
""" Initialize the Discord bot """
from discord.ext.commands import Bot, when_mentioned_or
bot: Bot = Bot(
command_prefix=when_mentioned_or('..', '>', '.'),
description="A list of commands available",
intents=intents,
# debug_guilds=[GUILD],
max_messages=100_000
)
@bot.event
async def on_ready():
print(f"Logged in as {bot.user} (ID: {bot.user.id})")
print("------")
""" Load cogs """
from os import listdir
def list_all_cogs() -> list[str]:
return [file[:-3] for file in listdir("cogs") if file.endswith(".py")]
for cog in list_all_cogs():
bot.load_extension(f"cogs.{cog}")
# TODO: web server for jukebox and/or soundboard?
# TODO: cog to announce when someone joins vc (maybe delete messages after some time?)
# TODO: purge messages from a user / etc? links, number, bot or human, idk
# TODO: automod? blocklist certain words or urls or whatever
# TODO: warn or kick or ban a user?
# TODO: filter the audit logs for a user? maybe?
# TODO: keep stats or levels? ehhhh
# ================================= ADMIN ======================================
from discord.commands import Option
from discord.ext.commands import Context
from discord import AutocompleteContext, ApplicationContext
async def cog_autocomplete(ctx: AutocompleteContext) -> list[str]:
return [cog for cog in list_all_cogs() if cog.lower().startswith( ctx.value.lower() )]
ADMIN_ROLE: int = config("DISCORD_BOT_ADMIN_ROLE_ID", cast=int, default=0)
ADMIN_USER: int = config("DISCORD_BOT_ADMIN_USER_ID", cast=int)
def allowed_to_reload(ctx: Context | ApplicationContext) -> bool:
roles: set[int] = set([role.id for role in ctx.author.roles])
admin: bool = ADMIN_ROLE in roles
owner: bool = ctx.author.id == ADMIN_USER
return any([admin, owner])
from cogs.music import Music
def reload_music(ctx):
music: Music = bot.get_cog("Music")
q = music.q
track = music.track
repeat_mode = music.repeat_mode
search_results = music.search_results
bot.reload_extension(f"cogs.music")
music = bot.get_cog("Music")
music.q = q
music.track = track
music.repeat_mode = repeat_mode
music.search_results = search_results
@bot.command(name='reload')
async def reload_prefix(ctx: Context, cog: str = "") -> None:
"""Reload an extension (admin command)"""
if not allowed_to_reload(ctx):
return await ctx.send("You must be an admin or bot owner to use this command")
if not cog:
return await ctx.send("Please specify a cog to reload")
elif cog.lower() == "music":
reload_music(ctx)
else:
bot.reload_extension(f"cogs.{cog}")
return await ctx.send(f"Reloaded `{cog}` extension")
@bot.slash_command(
name='reload',
guild_ids=[DISCORD_GUILD],
)
async def reload_slash(
ctx: ApplicationContext,
cog: Option(str, "The cog to be reloaded", autocomplete=cog_autocomplete)
):
"""Reload an extension (admin command)"""
if not allowed_to_reload(ctx):
return await ctx.respond(
"You must be an admin or bot owner to use this command",
ephemeral=True
)
if cog == "music":
reload_music(ctx)
else:
bot.reload_extension(f"cogs.{cog}")
return await ctx.respond(f"Reloaded `{cog}` extension", ephemeral=True)
# ================================== END =======================================
""" Run the bot """
bot.run(DISCORD_TOKEN)