""" Rocketbot Discord bot. Relies on a configured config.py (copy config.py.sample for a template). Author: Ian Albert (@rocketsoup) Date: 2021-11-11 """ import asyncio import traceback from discord import Intents from discord.ext import commands from config import CONFIG from rocketbot.cogs.autokickcog import AutoKickCog from rocketbot.cogs.configcog import ConfigCog from rocketbot.cogs.crosspostcog import CrossPostCog from rocketbot.cogs.generalcog import GeneralCog from rocketbot.cogs.joinagecog import JoinAgeCog from rocketbot.cogs.joinraidcog import JoinRaidCog from rocketbot.cogs.logcog import LoggingCog from rocketbot.cogs.patterncog import PatternCog from rocketbot.cogs.urlspamcog import URLSpamCog from rocketbot.cogs.usernamecog import UsernamePatternCog from rocketbot.utils import bot_log CURRENT_CONFIG_VERSION = 3 if (CONFIG.get('__config_version') or 0) < CURRENT_CONFIG_VERSION: # If you're getting this error, it means something changed in config.py's # format. Consult config.py.sample and compare it to your own config.py. # Rename/move any values as needed. When satisfied, update "__config_version" # to the value in config.py.sample. raise RuntimeError('config.py format may be outdated. Review ' + 'config.py.sample, update the "__config_version" field to ' + f'{CURRENT_CONFIG_VERSION}, and try again.') class Rocketbot(commands.Bot): """ Bot subclass """ def __init__(self, command_prefix, **kwargs): super().__init__(command_prefix, **kwargs) async def on_command_error(self, context: commands.Context, exception): bot_log(None, None, 'Command error:\n' + '\n'.join(traceback.format_stack())) if context.guild is None or \ context.message.channel is None or \ context.message.author.bot: return if not context.message.channel.permissions_for(context.message.author).ban_members: # Don't tell non-mods about errors return if isinstance(exception, (commands.errors.CommandError, )): # Reply with the error message for ordinary command errors await context.message.reply( f'{CONFIG["failure_emoji"]} {exception}', mention_author=False) return # Stack trace everything else # traceback.print_exception(type(exception), exception, exception.__traceback__) async def on_error(self, event_method, args=None, kwargs=None): bot_log(None, None, 'Event caused error\n' + \ f' event method: {event_method}' + \ f' event args: {args}' + \ f' event kwargs: {kwargs}' + \ traceback.format_exc()) async def start_bot(): intents = Intents.default() intents.messages = True # pylint: disable=assigning-non-slot intents.message_content = True # pylint: disable=assigning-non-slot intents.members = True # pylint: disable=assigning-non-slot intents.presences = True bot_log(None, None, 'Bot initializing...') bot_log(None, None, f"Type {CONFIG['command_prefix']}help in Discord for available commands.") bot = Rocketbot(command_prefix=CONFIG['command_prefix'], intents=intents) # Core await bot.add_cog(GeneralCog(bot)) await bot.add_cog(ConfigCog(bot)) # Optional await bot.add_cog(AutoKickCog(bot)) await bot.add_cog(CrossPostCog(bot)) await bot.add_cog(JoinAgeCog(bot)) await bot.add_cog(JoinRaidCog(bot)) await bot.add_cog(LoggingCog(bot)) await bot.add_cog(PatternCog(bot)) await bot.add_cog(URLSpamCog(bot)) await bot.add_cog(UsernamePatternCog(bot)) await bot.start(CONFIG['client_token'], reconnect=True) print('\nBot aborted') try: asyncio.run(start_bot()) except KeyboardInterrupt: bot_log(None, None, 'Stopping bot due to Ctrl+C key')