diff --git a/yaboli/bot.py b/yaboli/bot.py index 4b787ef..a274d77 100644 --- a/yaboli/bot.py +++ b/yaboli/bot.py @@ -1,8 +1,10 @@ import asyncio import logging import re +import time from .callbacks import * from .controller import * +from .utils import * logger = logging.getLogger(__name__) __all__ = ["Bot"] @@ -17,8 +19,15 @@ class Bot(Controller): def __init__(self, nick): super().__init__(nick) + self.start_time = time.time() + self._callbacks = Callbacks() self.register_default_callbacks() + + # settings (modify in your bot's __init__) + self.general_help = None # None -> does not respond to general help + self.killable = True + self.kill_message = "/me *poof*" # how to respond to !kill, whether killable or not def register_callback(self, event, callback, specific=True): self._callbacks.add((event, specific), callback) @@ -88,9 +97,10 @@ class Bot(Controller): arg += character elif character in "'\"": quote = character - elif character.isspace() and len(arg) > 0: - args.append(arg) - arg = "" + elif character.isspace(): + if len(arg) > 0: + args.append(arg) + arg = "" else: arg += character @@ -133,6 +143,34 @@ class Bot(Controller): def register_default_callbacks(self): self.register_callback("ping", self.command_ping) self.register_callback("ping", self.command_ping, specific=False) + self.register_callback("help", self.command_help) + self.register_callback("help", self.command_help_general, specific=False) + self.register_callback("uptime", self.command_uptime) + self.register_callback("kill", self.command_kill) + # TODO: maybe !restart command async def command_ping(self, message, args): await self.room.send("Pong!", message.message_id) + + async def command_help(self, message, args): + await self.room.send("", message.message_id) + + async def command_help_general(self, message, args): + if self.general_help is not None: + await self.room.send(self.general_help, message.message_id) + + async def command_uptime(self, message, args): + now = time.time() + startformat = format_time(self.start_time) + deltaformat = format_time_delta(now - self.start_time) + text = f"/me has been up since {startformat} ({deltaformat})" + await self.room.send(text, message.message_id) + + async def command_kill(self, message, args): + logging.warn(f"Kill attempt in &{self.room.roomname}: {message.content!r}") + + if self.kill_message is not None: + await self.room.send(self.kill_message, message.message_id) + + if self.killable: + await self.stop() diff --git a/yaboli/utils.py b/yaboli/utils.py index eaf8d16..0f619ed 100644 --- a/yaboli/utils.py +++ b/yaboli/utils.py @@ -1,8 +1,10 @@ import asyncio +import time __all__ = [ "run_controller", "mention", "mention_reduced", "similar", + "format_time", "format_time_delta", "Session", "Listing", "Message", "Log", "ResponseError" @@ -31,6 +33,41 @@ def mention_reduced(nick): def similar(nick1, nick2): return mention_reduced(nick1) == mention_reduced(nick2) +def format_time(timestamp): + return time.strftime( + "%Y-%m-%d %H:%M:%S UTC", + time.gmtime(timestamp) + ) + +def format_time_delta(delta): + if delta < 0: + result = "-" + else: + result = "" + + delta = int(delta) + + second = 1 + minute = second*60 + hour = minute*60 + day = hour*24 + + if delta >= day: + result += f"{delta//day}d " + delta = delta%day + + if delta >= hour: + result += f"{delta//hour}h " + delta = delta%day + + if delta >= minute: + result += f"{delta//minute}m " + delta = delta%minute + + result += f"{delta}s" + + return result + class Session: def __init__(self, user_id, nick, server_id, server_era, session_id, is_staff=None, is_manager=None, client_address=None, real_address=None):