Pass along ConfigParsers instead of file names
This commit is contained in:
parent
2f7502723b
commit
86472afb3f
4 changed files with 109 additions and 27 deletions
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
## Next version
|
||||
|
||||
- change how config files are passed along
|
||||
- change module system to support config file changes
|
||||
|
||||
# 1.0.0 (2019-04-13)
|
||||
|
||||
- add fancy argument parsing
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import asyncio
|
||||
import configparser
|
||||
import logging
|
||||
from typing import Callable
|
||||
from typing import Callable, Dict
|
||||
|
||||
from .bot import *
|
||||
from .client import *
|
||||
|
|
@ -48,12 +49,33 @@ def enable_logging(name: str = "yaboli", level: int = logging.INFO) -> None:
|
|||
logger.addHandler(handler)
|
||||
|
||||
def run(
|
||||
client: Callable[[str], Client],
|
||||
config_file: str = "bot.conf"
|
||||
bot_constructor: BotConstructor,
|
||||
config_file: str = "bot.conf",
|
||||
) -> None:
|
||||
# Load the config file
|
||||
config = configparser.ConfigParser(allow_no_value=True)
|
||||
config.read(config_file)
|
||||
|
||||
async def _run() -> None:
|
||||
while True:
|
||||
client_ = client(config_file)
|
||||
await client_.run()
|
||||
bot = bot_constructor(config, config_file)
|
||||
await bot.run()
|
||||
|
||||
asyncio.run(_run())
|
||||
|
||||
def run_modulebot(
|
||||
modulebot_constructor: ModuleBotConstructor,
|
||||
module_constructors: Dict[str, ModuleConstructor],
|
||||
config_file: str = "bot.conf",
|
||||
) -> None:
|
||||
# Load the config file
|
||||
config = configparser.ConfigParser(allow_no_value=True)
|
||||
config.read(config_file)
|
||||
|
||||
async def _run() -> None:
|
||||
while True:
|
||||
modulebot = modulebot_constructor(config, config_file,
|
||||
module_constructors)
|
||||
await modulebot.run()
|
||||
|
||||
asyncio.run(_run())
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import configparser
|
||||
import datetime
|
||||
import logging
|
||||
from typing import List, Optional
|
||||
from typing import Callable, List, Optional
|
||||
|
||||
from .client import Client
|
||||
from .command import *
|
||||
|
|
@ -11,7 +11,7 @@ from .util import *
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__all__ = ["Bot"]
|
||||
__all__ = ["Bot", "BotConstructor"]
|
||||
|
||||
class Bot(Client):
|
||||
ALIASES: List[str] = []
|
||||
|
|
@ -25,12 +25,13 @@ class Bot(Client):
|
|||
GENERAL_SECTION = "general"
|
||||
ROOMS_SECTION = "rooms"
|
||||
|
||||
def __init__(self, config_file: str) -> None:
|
||||
def __init__(self,
|
||||
config: configparser.ConfigParser,
|
||||
config_file: str,
|
||||
) -> None:
|
||||
self.config = config
|
||||
self.config_file = config_file
|
||||
|
||||
self.config = configparser.ConfigParser(allow_no_value=True)
|
||||
self.config.read(self.config_file)
|
||||
|
||||
nick = self.config[self.GENERAL_SECTION].get("nick")
|
||||
if nick is None:
|
||||
logger.warn(("'nick' not set in config file. Defaulting to empty"
|
||||
|
|
@ -188,3 +189,5 @@ class Bot(Client):
|
|||
logger.info(f"Restarted in &{room.name} by {message.sender.atmention}")
|
||||
await message.reply(self.RESTART_REPLY)
|
||||
await self.stop()
|
||||
|
||||
BotConstructor = Callable[[configparser.ConfigParser, str], Bot]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import configparser
|
||||
import logging
|
||||
from typing import Dict, List, Optional
|
||||
from typing import Callable, Dict, List, Optional
|
||||
|
||||
from .bot import Bot
|
||||
from .command import *
|
||||
|
|
@ -10,49 +11,77 @@ from .util import *
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__all__ = ["Module", "ModuleBot"]
|
||||
__all__ = ["Module", "ModuleConstructor", "ModuleBot", "ModuleBotConstructor"]
|
||||
|
||||
class Module(Bot):
|
||||
DESCRIPTION: Optional[str] = None
|
||||
|
||||
def __init__(self, config_file: str, standalone: bool) -> None:
|
||||
super().__init__(config_file)
|
||||
def __init__(self,
|
||||
config: configparser.ConfigParser,
|
||||
config_file: str,
|
||||
standalone: bool = True,
|
||||
) -> None:
|
||||
super().__init__(config, config_file)
|
||||
|
||||
self.standalone = standalone
|
||||
|
||||
ModuleConstructor = Callable[[configparser.ConfigParser, str, bool], Module]
|
||||
|
||||
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."
|
||||
"",
|
||||
"For module-specific help, try \"!help {atmention} <module>\".",
|
||||
]
|
||||
MODULE_HELP_LIMIT = 5
|
||||
|
||||
def __init__(self, config_file: str) -> None:
|
||||
super().__init__(config_file)
|
||||
MODULES_SECTION = "modules"
|
||||
|
||||
def __init__(self,
|
||||
config: configparser.ConfigParser,
|
||||
config_file: str,
|
||||
module_constructors: Dict[str, ModuleConstructor],
|
||||
) -> None:
|
||||
super().__init__(config, config_file)
|
||||
|
||||
self.module_constructors = module_constructors
|
||||
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)
|
||||
# Load initial modules
|
||||
for module_name in self.config[self.MODULES_SECTION]:
|
||||
module_constructor = self.module_constructors.get(module_name)
|
||||
if module_constructor is None:
|
||||
logger.warn(f"Module {module_name} not found")
|
||||
continue
|
||||
# standalone is set to False
|
||||
module = module_constructor(self.config, self.config_file, False)
|
||||
self.load_module(module_name, module)
|
||||
|
||||
def register_module(self, name: str, module: Module) -> None:
|
||||
def load_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 unload_module(self, name: str) -> None:
|
||||
if name in self.modules:
|
||||
del self.modules[name]
|
||||
|
||||
# Better help messages
|
||||
|
||||
def compile_module_overview(self) -> List[str]:
|
||||
lines = []
|
||||
|
||||
if self.HELP_PRE is not None:
|
||||
lines.extend(self.HELP_PRE)
|
||||
|
||||
any_modules = False
|
||||
|
||||
modules_without_desc: List[str] = []
|
||||
for module_name in sorted(self.modules):
|
||||
any_modules = True
|
||||
|
||||
module = self.modules[module_name]
|
||||
|
||||
if module.DESCRIPTION is None:
|
||||
|
|
@ -62,7 +91,10 @@ class ModuleBot(Bot):
|
|||
lines.append(line)
|
||||
|
||||
if modules_without_desc:
|
||||
lines.append(", ".join(modules_without_desc))
|
||||
lines.append("\t" + ", ".join(modules_without_desc))
|
||||
|
||||
if not any_modules:
|
||||
lines.append("No modules loaded.")
|
||||
|
||||
if self.HELP_POST is not None:
|
||||
lines.extend(self.HELP_POST)
|
||||
|
|
@ -79,8 +111,7 @@ class ModuleBot(Bot):
|
|||
|
||||
return module.HELP_SPECIFIC
|
||||
|
||||
# Overwriting the botrulez help function
|
||||
async def cmd_help_specific(self,
|
||||
async def cmd_modules_help(self,
|
||||
room: Room,
|
||||
message: LiveMessage,
|
||||
args: SpecificArgumentData
|
||||
|
|
@ -100,6 +131,12 @@ class ModuleBot(Bot):
|
|||
|
||||
# Sending along all kinds of events
|
||||
|
||||
async def on_connected(self, room: Room) -> None:
|
||||
await super().on_connected(room)
|
||||
|
||||
for module in self.modules.values():
|
||||
await module.on_connected(room)
|
||||
|
||||
async def on_snapshot(self, room: Room, messages: List[LiveMessage]) -> None:
|
||||
await super().on_snapshot(room, messages)
|
||||
|
||||
|
|
@ -141,6 +178,18 @@ class ModuleBot(Bot):
|
|||
for module in self.modules.values():
|
||||
await module.on_edit(room, message)
|
||||
|
||||
async def on_login(self, room: Room, account_id: str) -> None:
|
||||
await super().on_login(room, account_id)
|
||||
|
||||
for module in self.modules.values():
|
||||
await module.on_login(room, account_id)
|
||||
|
||||
async def on_logout(self, room: Room) -> None:
|
||||
await super().on_logout(room)
|
||||
|
||||
for module in self.modules.values():
|
||||
await module.on_logout(room)
|
||||
|
||||
async def on_pm(self,
|
||||
room: Room,
|
||||
from_id: str,
|
||||
|
|
@ -158,3 +207,8 @@ class ModuleBot(Bot):
|
|||
|
||||
for module in self.modules.values():
|
||||
await module.on_disconnect(room, reason)
|
||||
|
||||
ModuleBotConstructor = Callable[
|
||||
[configparser.ConfigParser, str, Dict[str, ModuleConstructor]],
|
||||
Bot
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue