Add modules

This commit is contained in:
Joscha 2019-04-11 23:35:44 +00:00
parent 40cb7917c8
commit 9cb38c4ca8
4 changed files with 208 additions and 29 deletions

61
test.py
View file

@ -23,39 +23,44 @@ logger = logging.getLogger('yaboli')
logger.setLevel(LEVEL)
logger.addHandler(handler)
class TestBot(yaboli.Bot):
DEFAULT_NICK = "testbot"
class TestModule(yaboli.Module):
PING_REPLY = "ModulePong!"
DESCRIPTION = "ModuleDescription"
HELP_GENERAL = "ModuleGeneralHelp"
HELP_SPECIFIC = ["ModuleGeneralHelp"]
def __init__(self):
super().__init__()
self.register_botrulez()
self.register_general("test", self.cmd_test, args=False)
self.register_general("who", self.cmd_who, args=False)
self.register_general("err", self.cmd_err, args=False)
class EchoModule(yaboli.Module):
DEFAULT_NICK = "echo"
DESCRIPTION = "echoes back the input arguments"
HELP_GENERAL = "/me " + DESCRIPTION
HELP_SPECIFIC = [
"!echo <args> output the arguments, each in its own line"
#"!fancyecho <args> same as !echo, but different parser"
]
def __init__(self, standalone: bool) -> None:
super().__init__(standalone)
self.register_general("echo", self.cmd_echo)
#self.register_general("fancyecho", self.cmd_fancyecho)
async def cmd_echo(self, room, message, args):
if args.has_args():
lines = [repr(arg) for arg in args.basic()]
await message.reply("\n".join(lines))
else:
await message.reply("No arguments")
class TestBot(yaboli.ModuleBot):
DEFAULT_NICK = "testbot"
async def started(self):
await self.join("test")
async def on_send(self, room, message):
await self.process_commands(room, message,
aliases=["testalias", "aliastest"])
async def cmd_test(self, room, message, args):
await message.reply(f"You said {message.content!r}.")
msg1 = await room.send(f"{message.sender.atmention} said something.")
await msg1.reply("Yes, they really did.")
async def cmd_who(self, room, message, args):
lines = []
for user in await room.who():
lines.append(repr(user.nick))
await message.reply("\n".join(lines))
async def cmd_err(self, room, message, args):
await message.reply(str(1/0))
async def main():
tc = TestBot()
await tc.run()
tb = TestBot()
tb.register_module("test", TestModule(standalone=False))
tb.register_module("echo", EchoModule(standalone=False))
await tb.run()
asyncio.run(main())

View file

@ -7,6 +7,7 @@ from .connection import *
from .events import *
from .exceptions import *
from .message import *
from .module import *
from .room import *
from .session import *
from .util import *
@ -19,6 +20,7 @@ __all__ += connection.__all__
__all__ += events.__all__
__all__ += exceptions.__all__
__all__ += message.__all__
__all__ += module.__all__
__all__ += room.__all__
__all__ += session.__all__
__all__ += util.__all__

160
yaboli/module.py Normal file
View file

@ -0,0 +1,160 @@
import logging
from typing import Dict, List, Optional
from .bot import Bot
from .command import *
from .message import LiveMessage
from .room import Room
from .session import LiveSession
from .util import *
logger = logging.getLogger(__name__)
__all__ = ["Module", "ModuleBot"]
class Module(Bot):
DESCRIPTION: Optional[str] = None
def __init__(self, standalone: bool) -> None:
super().__init__()
self.standalone = standalone
class ModuleBot(Bot):
HELP_PRE: Optional[List[str]] = [
"This bot contains the following modules:"
]
HELP_POST: Optional[List[str]] = [
""
"Use \"!help {atmention} <module>\" to get more information on a"
" specific module."
]
MODULE_HELP_LIMIT = 5
def __init__(self) -> None:
super().__init__()
self.modules: Dict[str, Module] = {}
self.register_botrulez(help_=False)
self.register_general("help", self.cmd_help_general, args=False)
self.register_specific("help", self.cmd_help_specific, args=True)
def register_module(self, name: str, module: Module) -> None:
if name in self.modules:
logger.warn(f"Module {name!r} is already registered, overwriting...")
self.modules[name] = module
def compile_module_overview(self) -> List[str]:
lines = []
if self.HELP_PRE is not None:
lines.extend(self.HELP_PRE)
modules_without_desc: List[str] = []
for module_name in sorted(self.modules):
module = self.modules[module_name]
if module.DESCRIPTION is None:
modules_without_desc.append(module_name)
else:
line = f"\t{module_name}{module.DESCRIPTION}"
lines.append(line)
if modules_without_desc:
lines.append(", ".join(modules_without_desc))
if self.HELP_POST is not None:
lines.extend(self.HELP_POST)
return lines
def compile_module_help(self, module_name: str) -> List[str]:
module = self.modules.get(module_name)
if module is None:
return [f"Module {module_name!r} not found."]
elif module.HELP_SPECIFIC is None:
return [f"Module {module_name!r} has no detailed help message."]
return module.HELP_SPECIFIC
# Overwriting the botrulez help function
async def cmd_help_specific(self,
room: Room,
message: LiveMessage,
args: SpecificArgumentData
) -> None:
if args.has_args():
if len(args.basic()) > self.MODULE_HELP_LIMIT:
limit = self.MODULE_HELP_LIMIT
text = f"A maximum of {limit} module{plural(limit)} is allowed."
await message.reply(text)
else:
for module_name in args.basic():
help_lines = self.compile_module_help(module_name)
await message.reply(self.format_help(room, help_lines))
else:
help_lines = self.compile_module_overview()
await message.reply(self.format_help(room, help_lines))
# Sending along all kinds of events
async def on_snapshot(self, room: Room, messages: List[LiveMessage]) -> None:
await super().on_snapshot(room, messages)
for module in self.modules.values():
await module.on_snapshot(room, messages)
async def on_send(self, room: Room, message: LiveMessage) -> None:
await super().on_send(room, message)
for module in self.modules.values():
await module.on_send(room, message)
async def on_join(self, room: Room, user: LiveSession) -> None:
await super().on_join(room, user)
for module in self.modules.values():
await module.on_join(room, user)
async def on_part(self, room: Room, user: LiveSession) -> None:
await super().on_part(room, user)
for module in self.modules.values():
await module.on_part(room, user)
async def on_nick(self,
room: Room,
user: LiveSession,
from_nick: str,
to_nick: str
) -> None:
await super().on_nick(room, user, from_nick, to_nick)
for module in self.modules.values():
await module.on_nick(room, user, from_nick, to_nick)
async def on_edit(self, room: Room, message: LiveMessage) -> None:
await super().on_edit(room, message)
for module in self.modules.values():
await module.on_edit(room, message)
async def on_pm(self,
room: Room,
from_id: str,
from_nick: str,
from_room: str,
pm_id: str
) -> None:
await super().on_pm(room, from_id, from_nick, from_room, pm_id)
for module in self.modules.values():
await module.on_pm(room, from_id, from_nick, from_room, pm_id)
async def on_disconnect(self, room: Room, reason: str) -> None:
await super().on_disconnect(room, reason)
for module in self.modules.values():
await module.on_disconnect(room, reason)

View file

@ -1,6 +1,6 @@
import re
__all__ = ["mention", "atmention", "normalize", "similar"]
__all__ = ["mention", "atmention", "normalize", "similar", "plural"]
# Name/nick related functions
@ -16,3 +16,15 @@ def normalize(nick: str) -> str:
def similar(nick_a: str, nick_b: str) -> bool:
return normalize(nick_a) == normalize(nick_b)
# Other formatting
def plural(
number: int,
if_plural: str = "s",
if_singular: str = ""
) -> str:
if number in [1, -1]:
return if_singular
else:
return if_plural