Add modules
This commit is contained in:
parent
40cb7917c8
commit
9cb38c4ca8
4 changed files with 208 additions and 29 deletions
61
test.py
61
test.py
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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
160
yaboli/module.py
Normal 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)
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue