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.setLevel(LEVEL)
|
||||||
logger.addHandler(handler)
|
logger.addHandler(handler)
|
||||||
|
|
||||||
class TestBot(yaboli.Bot):
|
class TestModule(yaboli.Module):
|
||||||
DEFAULT_NICK = "testbot"
|
PING_REPLY = "ModulePong!"
|
||||||
|
DESCRIPTION = "ModuleDescription"
|
||||||
|
HELP_GENERAL = "ModuleGeneralHelp"
|
||||||
|
HELP_SPECIFIC = ["ModuleGeneralHelp"]
|
||||||
|
|
||||||
def __init__(self):
|
class EchoModule(yaboli.Module):
|
||||||
super().__init__()
|
DEFAULT_NICK = "echo"
|
||||||
self.register_botrulez()
|
DESCRIPTION = "echoes back the input arguments"
|
||||||
self.register_general("test", self.cmd_test, args=False)
|
HELP_GENERAL = "/me " + DESCRIPTION
|
||||||
self.register_general("who", self.cmd_who, args=False)
|
HELP_SPECIFIC = [
|
||||||
self.register_general("err", self.cmd_err, args=False)
|
"!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):
|
async def started(self):
|
||||||
await self.join("test")
|
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():
|
async def main():
|
||||||
tc = TestBot()
|
tb = TestBot()
|
||||||
await tc.run()
|
tb.register_module("test", TestModule(standalone=False))
|
||||||
|
tb.register_module("echo", EchoModule(standalone=False))
|
||||||
|
await tb.run()
|
||||||
|
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ from .connection import *
|
||||||
from .events import *
|
from .events import *
|
||||||
from .exceptions import *
|
from .exceptions import *
|
||||||
from .message import *
|
from .message import *
|
||||||
|
from .module import *
|
||||||
from .room import *
|
from .room import *
|
||||||
from .session import *
|
from .session import *
|
||||||
from .util import *
|
from .util import *
|
||||||
|
|
@ -19,6 +20,7 @@ __all__ += connection.__all__
|
||||||
__all__ += events.__all__
|
__all__ += events.__all__
|
||||||
__all__ += exceptions.__all__
|
__all__ += exceptions.__all__
|
||||||
__all__ += message.__all__
|
__all__ += message.__all__
|
||||||
|
__all__ += module.__all__
|
||||||
__all__ += room.__all__
|
__all__ += room.__all__
|
||||||
__all__ += session.__all__
|
__all__ += session.__all__
|
||||||
__all__ += util.__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
|
import re
|
||||||
|
|
||||||
__all__ = ["mention", "atmention", "normalize", "similar"]
|
__all__ = ["mention", "atmention", "normalize", "similar", "plural"]
|
||||||
|
|
||||||
# Name/nick related functions
|
# Name/nick related functions
|
||||||
|
|
||||||
|
|
@ -16,3 +16,15 @@ def normalize(nick: str) -> str:
|
||||||
|
|
||||||
def similar(nick_a: str, nick_b: str) -> bool:
|
def similar(nick_a: str, nick_b: str) -> bool:
|
||||||
return normalize(nick_a) == normalize(nick_b)
|
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