diff --git a/cogs/basecog.py b/cogs/basecog.py index 865e13c..585664a 100644 --- a/cogs/basecog.py +++ b/cogs/basecog.py @@ -10,7 +10,6 @@ General Public License, version 2. import discord import discord.ext.commands as commands -import os class BaseCog(commands.Cog): def __init__(self, bot): @@ -26,30 +25,6 @@ class BaseCog(commands.Cog): embed = embed.add_field(name="License", value=self.gs.info.license) await ctx.send(embed=embed) - @commands.command(name="restart") - async def _restart_bot(self, ctx): - """Restarts the bot.""" - if ctx.author.id in self.gs.opt.owners_uids: - await ctx.message.add_reaction("✅") - await self.bot.logout() - else: - try: - await ctx.message.add_reaction("❌") - except: - return - - @commands.command(name="shutdown") - async def _shutdown_bot(self, ctx): - """Shuts down the bot.""" - if ctx.author.id in self.gs.opt.owners_uids: - await ctx.message.add_reaction("✅") - os._exit(42) - else: - try: - await ctx.message.add_reaction("❌") - except: - return - @commands.command(name="ping") async def _ping(self, ctx): await ctx.send(f'**Pong!** Current ping is {self.bot.latency*1000:.1f} ms') diff --git a/main.py b/main.py index 6cd2ac7..b2d0606 100644 --- a/main.py +++ b/main.py @@ -19,7 +19,9 @@ import options as opt import keys -# --- Global settings --- +# --- Settings --- + +exit_code = 1 # The default exit code. ?shutdown and ?restart will change it accordingly (fail-safe) debug_mode = opt.debug # Separate assignement in-case we define an override (ternary operator goes here) @@ -43,6 +45,34 @@ bot = commands.Bot(command_prefix=opt.prefix, description=info.description, help # --- Commands --- +@bot.command(name="restart") +async def _restart_bot(ctx): + """Restarts the bot.""" + global exit_code + if ctx.author.id in opt.owners_uids: + await ctx.message.add_reaction("✅") + exit_code = 42 # Signals to the wrapper script that the bot needs to be restarted. + await bot.logout() + else: + try: + await ctx.message.add_reaction("❌") + except: + return + +@bot.command(name="shutdown") +async def _shutdown_bot(ctx): + """Shuts down the bot.""" + global exit_code + if ctx.author.id in opt.owners_uids: + await ctx.message.add_reaction("✅") + exit_code = 0 # Signals to the wrapper script that the bot should not be restarted. + await bot.logout() + else: + try: + await ctx.message.add_reaction("❌") + except: + return + # --- Events --- @@ -93,3 +123,12 @@ except ConnectionResetError as ex: # More generic connection reset error if debug_mode: raise raise SystemExit("ConnectionResetError: {}".format(ex)) + + +# --- Exit --- +# Codes for the wrapper shell script: +# 0 - Clean exit, don't restart +# 1 - Error exit, [restarting is up to the shell script] +# 42 - Clean exit, do restart + +raise SystemExit(exit_code) diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..a48c23e --- /dev/null +++ b/run.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# A wrapper script for painless discord bots. +# v1.0.0 +# Copyright (c) 2019 0x5c +# Released under the terms of the MIT license. +# Part of: +# https://github.com/0x5c/quick-bot-no-pain + + +# If $BOTENV is not defined, default to 'botenv' +if [[ -z ${BOTENV+x} ]]; then + BOTENV='botenv' +fi + +# Argument handling # ? TODO: Argument passing ? +if [[ $1 == '--pass-errors' ]]; then + _PASS_ERRORS=1 +fi + + +# A function called when the bot exits to decide what to do +code_handling() { + case $err in + 0) + echo "$_message: exiting" + exit 0 # The bot whishes to stay alone. + ;; + 42) + echo "$_message: restarting" + return # The bot whishes to be restarted (returns to the loop). + ;; + *) + if [[ $_PASS_ERRORS -eq 0 ]]; then # The bot crashed and: + echo "$_message: restarting" + return # ...we should return to the loop to restart it. + else + echo "$_message: exiting (--pass-errors)" + exit $err # ...we should just exit and pass the code to our parent (probably a daemon/service manager). + fi + ;; + esac +} + + +echo "$0: Starting bot..." + +# The loop +while true; do + ./$BOTENV/bin/python3 main.py + err=$? + _message="$0: The bot exited with [$err]" + code_handling +done