docs: Add a readme
This commit is contained in:
parent
5e5d3083f3
commit
6bfa10a4e2
147
README.md
Normal file
147
README.md
Normal file
@ -0,0 +1,147 @@
|
||||
# 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
|
||||
whitespace separated (`cmd`) and the original `aioxmpp` message object (`msg`)
|
||||
|
||||
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`.
|
||||
|
||||
## License
|
||||
|
||||
See `LICENSE`.
|
Loading…
Reference in New Issue
Block a user