@@ -27,8 +27,8 @@ from earwigbot import __version__ | |||||
from earwigbot.commands import BaseCommand | from earwigbot.commands import BaseCommand | ||||
class Command(BaseCommand): | class Command(BaseCommand): | ||||
"""Not an actual command, this module is used to respond to the CTCP | |||||
commands PING, TIME, and VERSION.""" | |||||
"""Not an actual command; this module implements responses to the CTCP | |||||
requests PING, TIME, and VERSION.""" | |||||
name = "ctcp" | name = "ctcp" | ||||
hooks = ["msg_private"] | hooks = ["msg_private"] | ||||
@@ -23,11 +23,12 @@ | |||||
from earwigbot.commands import BaseCommand | from earwigbot.commands import BaseCommand | ||||
class Command(BaseCommand): | class Command(BaseCommand): | ||||
"""Restart the bot. Only the owner can do this.""" | |||||
name = "restart" | |||||
"""Quit, restart, or reload components from the bot. Only the owners can | |||||
run this command.""" | |||||
name = "quit" | |||||
def check(self, data): | def check(self, data): | ||||
commands = ["restart", "reload"] | |||||
commands = ["quit", "restart", "reload"] | |||||
return data.is_command and data.command in commands | return data.is_command and data.command in commands | ||||
def process(self, data): | def process(self, data): | ||||
@@ -35,17 +36,34 @@ class Command(BaseCommand): | |||||
msg = "you must be a bot owner to use this command." | msg = "you must be a bot owner to use this command." | ||||
self.connection.reply(data, msg) | self.connection.reply(data, msg) | ||||
return | return | ||||
if data.command == "quit": | |||||
self.do_quit(data) | |||||
elif data.command == "restart": | |||||
self.do_restart(data) | |||||
else: | |||||
self.do_reload(data) | |||||
if data.command == "restart": | |||||
self.logger.info("Restarting bot per owner request") | |||||
if data.args: | |||||
self.bot.restart(" ".join(data.args)) | |||||
else: | |||||
self.bot.restart() | |||||
def do_quit(self, data): | |||||
nick = self.config.irc.frontend["nick"] | |||||
if not data.args or data.args[0].lower() != nick.lower(): | |||||
self.connection.reply(data, "to confirm this action, the first argument must be my nickname.") | |||||
return | |||||
if data.args[1:]: | |||||
msg = " ".join(data.args[1:]) | |||||
self.bot.stop("Stopped by {0}: {1}".format(data.nick, msg)) | |||||
else: | |||||
self.bot.stop("Stopped by {0}".format(data.nick)) | |||||
def do_restart(self, data): | |||||
self.logger.info("Restarting bot per owner request") | |||||
if data.args: | |||||
msg = " ".join(data.args) | |||||
self.bot.restart("Restarted by {0}: {1}".format(data.nick, msg)) | |||||
else: | |||||
self.bot.restart("Restarted by {0}".format(data.nick)) | |||||
elif data.command == "reload": | |||||
self.logger.info("Reloading IRC commands") | |||||
self.bot.commands.load() | |||||
self.logger.info("Reloading bot tasks") | |||||
self.bot.tasks.load() | |||||
self.connection.reply("IRC commands and bot tasks reloaded.") | |||||
def do_reload(self, data): | |||||
self.logger.info("Reloading IRC commands and bot tasks") | |||||
self.bot.commands.load() | |||||
self.bot.tasks.load() | |||||
self.connection.reply(data, "IRC commands and bot tasks reloaded.") |
@@ -117,9 +117,9 @@ class Command(BaseCommand): | |||||
t = "\x0302{0}\x0301 (\x02active\x0F as ids {1})" | t = "\x0302{0}\x0301 (\x02active\x0F as ids {1})" | ||||
tasklist.append(t.format(task, ', '.join(ids))) | tasklist.append(t.format(task, ', '.join(ids))) | ||||
tasklist = ", ".join(tasklist) | |||||
tasks = ", ".join(tasklist) | |||||
msg = "{0} tasks loaded: {1}.".format(len(all_tasks), tasklist) | |||||
msg = "{0} tasks loaded: {1}.".format(len(tasklist), tasks) | |||||
self.connection.reply(self.data, msg) | self.connection.reply(self.data, msg) | ||||
def do_start(self): | def do_start(self): | ||||
@@ -98,6 +98,7 @@ class BotConfig(object): | |||||
"""Configures the logging module so it works the way we want it to.""" | """Configures the logging module so it works the way we want it to.""" | ||||
log_dir = self._log_dir | log_dir = self._log_dir | ||||
logger = logging.getLogger("earwigbot") | logger = logging.getLogger("earwigbot") | ||||
logger.handlers = [] # Remove any handlers already attached to us | |||||
logger.setLevel(logging.DEBUG) | logger.setLevel(logging.DEBUG) | ||||
if self.metadata.get("enableLogging"): | if self.metadata.get("enableLogging"): | ||||
@@ -81,6 +81,13 @@ class IRCConnection(object): | |||||
self._sock.sendall(msg + "\r\n") | self._sock.sendall(msg + "\r\n") | ||||
self.logger.debug(msg) | self.logger.debug(msg) | ||||
def _quit(self, msg=None): | |||||
"""Issue a quit message to the server.""" | |||||
if msg: | |||||
self._send("QUIT :{0}".format(msg)) | |||||
else: | |||||
self._send("QUIT") | |||||
def say(self, target, msg): | def say(self, target, msg): | ||||
"""Send a private message to a target on the server.""" | """Send a private message to a target on the server.""" | ||||
msg = "PRIVMSG {0} :{1}".format(target, msg) | msg = "PRIVMSG {0} :{1}".format(target, msg) | ||||
@@ -121,13 +128,6 @@ class IRCConnection(object): | |||||
msg = "PONG {0}".format(target) | msg = "PONG {0}".format(target) | ||||
self._send(msg) | self._send(msg) | ||||
def quit(self, msg=None): | |||||
"""Issue a quit message to the server.""" | |||||
if msg: | |||||
self._send("QUIT :{0}".format(msg)) | |||||
else: | |||||
self._send("QUIT") | |||||
def loop(self): | def loop(self): | ||||
"""Main loop for the IRC connection.""" | """Main loop for the IRC connection.""" | ||||
self._is_running = True | self._is_running = True | ||||
@@ -150,7 +150,7 @@ class IRCConnection(object): | |||||
def stop(self, msg=None): | def stop(self, msg=None): | ||||
"""Request the IRC connection to close at earliest convenience.""" | """Request the IRC connection to close at earliest convenience.""" | ||||
if self._is_running: | if self._is_running: | ||||
self.quit(msg) | |||||
self._quit(msg) | |||||
self._is_running = False | self._is_running = False | ||||
def is_stopped(self): | def is_stopped(self): | ||||
@@ -67,8 +67,11 @@ def main(): | |||||
bot.tasks.start(args.task) | bot.tasks.start(args.task) | ||||
else: | else: | ||||
bot.run() | bot.run() | ||||
except KeyboardInterrupt: | |||||
pass | |||||
finally: | finally: | ||||
bot.stop() | |||||
if not bot._keep_looping: # Indicates bot has already been stopped | |||||
bot.stop() | |||||
if __name__ == "__main__": | if __name__ == "__main__": | ||||
main() | main() |