mira/README.md

157 lines
4.6 KiB
Markdown
Raw Normal View History

2021-06-12 20:47:12 +00:00
# mira
mira is a command-based bot framework for XMPP. It allows you to create
bots that react to your users' commands or notify them based on a
subscribtion system.
## Configuration
The main bot configuration is based on a TOML file:
```toml
# The JID to authenticate as
jid = "awesome-bot@example.org"
# The password
password = "s3cr3t_p4ssw0rd"
# Where the persistent data should be stored.
# Defaults to /etc/mira/storage.json
storage_path = "/home/mira/storage.json"
# Loads the file as an avatar and publishes it (OPTIONAL)
avatar = "/etc/mira/avatar.png"
# A list of modules that should be loaded
[[modules]]
# Load the "test" module that greets a user to writes
# "test" to awesome-bot@example.org
name = "mira.modules.test"
greeting = "Hello, Mr. %%user%%!"
[[modules]]
# This module reacts only to users whose JID has the
# same domain as the bot
name = "mira.modules.other_test"
restrict_local = true
```
By default, mira expects the config at `/etc/mira/config.toml`, but the path
can be overwritten by passing `--config`.
## Writing a module
Writing a module is pretty easy. The following is the base template:
```python
from mira.module import BaseModule
NAME = 'new'
class NewModule(BaseModule):
__instance = None
@staticmethod
def get_instance(base, **kwargs):
if NewModule.__instance == None:
NewModule(base, **kwargs)
return NewModule.__instance
def __init__(self, base, **kwargs):
if NewModule.__instance != None:
raise Exception('Trying to init singleton twice')
super().__init__(base, **kwargs)
NewModule.__instance = self
async def on_command(self, cmd, msg):
# ...
pass
def get_instance(base, **kwargs):
return TestModule.get_instance(base, **kwargs)
```
Currently, modules are implemented as singletons, so most of the code
is just for turning the class into a singleton. What's required is the
toplevel constant `NAME`! It is the name of the module as the same time
the "command". mira will pass all messages that start with the value of
`NAME` to the `on_command` function. It's parameters are the message body
2021-06-12 22:30:49 +00:00
whitespace separated (`cmd`) and the original `aioxmpp` message object (`msg`).
If you want to add configuration options to your bot, you can use the module's
`get_option(key, default=None)` function, which works exactly like `dict.get(...)`.
2021-06-12 20:47:12 +00:00
If you have subcommands, like "new something1" and "new something2", then you can
use a subcommand table. It is just a dictionary that tells mira which function
to call on which subcommand. In the example above, it looks like this:
```python
from mira.module import BaseModule
NAME = 'new'
class NewModule(BaseModule):
__instance = None
@staticmethod
def get_instance(base, **kwargs):
if NewModule.__instance == None:
NewModule(base, **kwargs)
return NewModule.__instance
def __init__(self, base, **kwargs):
if NewModule.__instance != None:
raise Exception('Trying to init singleton twice')
super().__init__(base, **kwargs)
NewModule.__instance = self
self._subcommand_table = {
'something1': self._something1,
'something2': self._something2,
'*': self._help
}
async def _something1(self, cmd, msg):
# ...
async def _something2(self, cmd, msg):
# ...
async def _help(self, cmd, msg):
# ...
def get_instance(base, **kwargs):
return TestModule.get_instance(base, **kwargs)
```
Note that '*' tells mira that the function should be called
everytime no other subcommand matches.
To send a message, the simplest way is to use the module's
`send_message(to, body)` function, which takes an `aioxmpp`
JID as to and a string as body.
### Storage
If your module needs to store data, then you can use the
`StorageManager`. It is available via the module's
`_stm` property. It provides the following two functions:
- `get_data(section)`: Retrieve data (dictionary) stored in the module's section. A module may have multiple sections
- `set_data(section, data)`: Stores data (dictionary) in the module's section. A module may have multiple sections
### Subscriptions
If your users should be able to subscribe to certain events, then you can use the
`SubscriptionManager`, available via the module's `_sum` property. It exposes a lot more
functions, so it is probably the better to just look at it's code at `mira/subscription.py`.
2021-06-12 22:30:49 +00:00
### Examples
If the test module `mira.modules.test` is not advanced enough, then you can find more examples here:
- [JANINE](https://git.polynom.me/PapaTutuWawa/JANINE)
- [My personal modules](https://git.polynom.me/PapaTutuWawa/mira-modules)
2021-06-12 20:47:12 +00:00
## License
See `LICENSE`.