Support commands

Closes https://git.autonomic.zone/decentral1se/xbotlib/issues/12.
This commit is contained in:
Luke Murphy 2021-01-14 23:45:23 +01:00
parent d8bbacc258
commit a463aa91f1
No known key found for this signature in database
GPG Key ID: 5E2EF5A63E3718CC
5 changed files with 73 additions and 3 deletions

View File

@ -7,6 +7,7 @@
- Remove `--no-input` option and detect it automatically ([#14](https://git.autonomic.zone/decentral1se/xbotlib/issues/14))
- Refer to `jid` as `account` from now on both internally and externally ([#14](https://git.autonomic.zone/decentral1se/xbotlib/issues/14))
- `bot.conf` -> `$name.conf` ([#3](https://git.autonomic.zone/decentral1se/xbotlib/issues/3))
- Support `!` style commands ([#12](https://git.autonomic.zone/decentral1se/xbotlib/issues/12))
# xbotlib 0.7.1 (2021-01-13)

View File

@ -95,6 +95,20 @@ Attributes:
- **nickname**: the nickname of the sender
- **type**: the type of message (`chat` or `groupchat`)
## Documenting your bot
Add a `help = "my help"` to your `Bot` class like so.
```python
class MyBot(Bot):
help = "My help"
```
The bot will then respond to:
- `!uptime` commands in direct messages
- `<nick>:!uptime` commands in group chats (use your own nick)
## Configure your bot
All the ways you can pass configuration details to your bot.

17
poetry.lock generated
View File

@ -85,6 +85,17 @@ mccabe = ">=0.6.0,<0.7.0"
pycodestyle = ">=2.6.0a1,<2.7.0"
pyflakes = ">=2.2.0,<2.3.0"
[[package]]
name = "humanize"
version = "3.2.0"
description = "Python humanize utilities"
category = "main"
optional = false
python-versions = ">=3.6"
[package.extras]
tests = ["freezegun", "pytest", "pytest-cov"]
[[package]]
name = "importlib-metadata"
version = "3.3.0"
@ -259,7 +270,7 @@ testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake
[metadata]
lock-version = "1.1"
python-versions = "^3.6"
content-hash = "077e5cd9d069cbe55c52ca17d9b401be8338b6d9c79126440364c69f4e40c94b"
content-hash = "1ff81969f837d57f7f28e6acdba690cde00aeedef64516953504c6f816ac73dd"
[metadata.files]
aiodns = [
@ -324,6 +335,10 @@ flake8 = [
{file = "flake8-3.8.4-py2.py3-none-any.whl", hash = "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839"},
{file = "flake8-3.8.4.tar.gz", hash = "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"},
]
humanize = [
{file = "humanize-3.2.0-py3-none-any.whl", hash = "sha256:d47d80cd47c1511ed3e49ca5f10c82ed940ea020b45b49ab106ed77fa8bb9d22"},
{file = "humanize-3.2.0.tar.gz", hash = "sha256:ab69004895689951b79f2ae4fdd6b8127ff0c180aff107856d5d98119a33f026"},
]
importlib-metadata = [
{file = "importlib_metadata-3.3.0-py3-none-any.whl", hash = "sha256:bf792d480abbd5eda85794e4afb09dd538393f7d6e6ffef6e9f03d2014cf9450"},
{file = "importlib_metadata-3.3.0.tar.gz", hash = "sha256:5c5a2720817414a6c41f0a49993908068243ae02c1635a228126519b509c8aed"},

View File

@ -16,6 +16,7 @@ keywords = []
[tool.poetry.dependencies]
python = "^3.6"
slixmpp = "^1.6.0"
humanize = "^3.2.0"
[tool.poetry.dev-dependencies]
black = "^19.10b0"

View File

@ -2,6 +2,7 @@
from argparse import ArgumentParser
from configparser import ConfigParser
from datetime import datetime as dt
from getpass import getpass
from logging import DEBUG, INFO, basicConfig, getLogger
from os import environ
@ -9,6 +10,7 @@ from os.path import exists
from pathlib import Path
from sys import exit, stdout
from humanize import naturaldelta
from slixmpp import ClientXMPP
@ -69,6 +71,8 @@ class Bot(ClientXMPP):
def __init__(self):
self.name = type(self).__name__.lower()
self.start = dt.now()
self.CONFIG_FILE = f"{self.name}.conf"
self.parse_arguments()
@ -191,8 +195,14 @@ class Bot(ClientXMPP):
def direct_message(self, message):
"""Handle message event."""
if message["type"] in ("chat", "normal"):
_message = SimpleMessage(message)
if _message.body.startswith("!"):
self.command(_message, to=_message.sender)
return
try:
self.direct(SimpleMessage(message))
self.direct(_message)
except AttributeError:
self.log.info("Bot.direct not implemented")
@ -209,8 +219,14 @@ class Bot(ClientXMPP):
"""Handle groupchat_message event."""
if message["type"] in ("groupchat", "normal"):
if message["mucnick"] != self.config.nick:
_message = SimpleMessage(message)
if f"{self.nick}:!" in _message.body:
self.command(_message, room=_message.room)
return
try:
self.group(SimpleMessage(message))
self.group(_message)
except AttributeError:
self.log.info("Bot.group not implemented")
@ -249,6 +265,25 @@ class Bot(ClientXMPP):
self.send_message(**kwargs)
@property
def uptime(self):
"""Time since the bot came up."""
return naturaldelta(self.start - dt.now())
def command(self, message, **kwargs):
"""Handle "!" style commands with built-in responses."""
command = message.body.split("!")[-1]
if command == "uptime":
self.reply(self.uptime, **kwargs)
elif command == "help":
try:
self.reply(self.help, **kwargs)
except AttributeError:
self.reply("No help found 🤔️", **kwargs)
else:
self.log.error(f"'{command}' direct command is not recognised")
class EchoBot(Bot):
"""Responds with whatever you send.
@ -261,6 +296,8 @@ class EchoBot(Bot):
"""
help = "I echo back whatever you send to me 🖖️"
def direct(self, message):
"""Send back whatever we receive."""
self.reply(message.body, to=message.sender)
@ -282,6 +319,8 @@ class WhisperBot(Bot):
"""
help = "I whisper your private messages into group chats 😌️"
def direct(self, message):
"""Receive private messages and whisper them into group chats."""
self.reply(f"*pssttt...* {message.body}", room=message.room)