Support commands
Closes https://git.autonomic.zone/decentral1se/xbotlib/issues/12.
This commit is contained in:
parent
d8bbacc258
commit
a463aa91f1
@ -7,6 +7,7 @@
|
|||||||
- Remove `--no-input` option and detect it automatically ([#14](https://git.autonomic.zone/decentral1se/xbotlib/issues/14))
|
- 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))
|
- 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))
|
- `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)
|
# xbotlib 0.7.1 (2021-01-13)
|
||||||
|
|
||||||
|
14
README.md
14
README.md
@ -95,6 +95,20 @@ Attributes:
|
|||||||
- **nickname**: the nickname of the sender
|
- **nickname**: the nickname of the sender
|
||||||
- **type**: the type of message (`chat` or `groupchat`)
|
- **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
|
## Configure your bot
|
||||||
|
|
||||||
All the ways you can pass configuration details to your bot.
|
All the ways you can pass configuration details to your bot.
|
||||||
|
17
poetry.lock
generated
17
poetry.lock
generated
@ -85,6 +85,17 @@ mccabe = ">=0.6.0,<0.7.0"
|
|||||||
pycodestyle = ">=2.6.0a1,<2.7.0"
|
pycodestyle = ">=2.6.0a1,<2.7.0"
|
||||||
pyflakes = ">=2.2.0,<2.3.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]]
|
[[package]]
|
||||||
name = "importlib-metadata"
|
name = "importlib-metadata"
|
||||||
version = "3.3.0"
|
version = "3.3.0"
|
||||||
@ -259,7 +270,7 @@ testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.6"
|
python-versions = "^3.6"
|
||||||
content-hash = "077e5cd9d069cbe55c52ca17d9b401be8338b6d9c79126440364c69f4e40c94b"
|
content-hash = "1ff81969f837d57f7f28e6acdba690cde00aeedef64516953504c6f816ac73dd"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
aiodns = [
|
aiodns = [
|
||||||
@ -324,6 +335,10 @@ flake8 = [
|
|||||||
{file = "flake8-3.8.4-py2.py3-none-any.whl", hash = "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839"},
|
{file = "flake8-3.8.4-py2.py3-none-any.whl", hash = "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839"},
|
||||||
{file = "flake8-3.8.4.tar.gz", hash = "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"},
|
{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 = [
|
importlib-metadata = [
|
||||||
{file = "importlib_metadata-3.3.0-py3-none-any.whl", hash = "sha256:bf792d480abbd5eda85794e4afb09dd538393f7d6e6ffef6e9f03d2014cf9450"},
|
{file = "importlib_metadata-3.3.0-py3-none-any.whl", hash = "sha256:bf792d480abbd5eda85794e4afb09dd538393f7d6e6ffef6e9f03d2014cf9450"},
|
||||||
{file = "importlib_metadata-3.3.0.tar.gz", hash = "sha256:5c5a2720817414a6c41f0a49993908068243ae02c1635a228126519b509c8aed"},
|
{file = "importlib_metadata-3.3.0.tar.gz", hash = "sha256:5c5a2720817414a6c41f0a49993908068243ae02c1635a228126519b509c8aed"},
|
||||||
|
@ -16,6 +16,7 @@ keywords = []
|
|||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.6"
|
python = "^3.6"
|
||||||
slixmpp = "^1.6.0"
|
slixmpp = "^1.6.0"
|
||||||
|
humanize = "^3.2.0"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
black = "^19.10b0"
|
black = "^19.10b0"
|
||||||
|
43
xbotlib.py
43
xbotlib.py
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
|
from datetime import datetime as dt
|
||||||
from getpass import getpass
|
from getpass import getpass
|
||||||
from logging import DEBUG, INFO, basicConfig, getLogger
|
from logging import DEBUG, INFO, basicConfig, getLogger
|
||||||
from os import environ
|
from os import environ
|
||||||
@ -9,6 +10,7 @@ from os.path import exists
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from sys import exit, stdout
|
from sys import exit, stdout
|
||||||
|
|
||||||
|
from humanize import naturaldelta
|
||||||
from slixmpp import ClientXMPP
|
from slixmpp import ClientXMPP
|
||||||
|
|
||||||
|
|
||||||
@ -69,6 +71,8 @@ class Bot(ClientXMPP):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.name = type(self).__name__.lower()
|
self.name = type(self).__name__.lower()
|
||||||
|
self.start = dt.now()
|
||||||
|
|
||||||
self.CONFIG_FILE = f"{self.name}.conf"
|
self.CONFIG_FILE = f"{self.name}.conf"
|
||||||
|
|
||||||
self.parse_arguments()
|
self.parse_arguments()
|
||||||
@ -191,8 +195,14 @@ class Bot(ClientXMPP):
|
|||||||
def direct_message(self, message):
|
def direct_message(self, message):
|
||||||
"""Handle message event."""
|
"""Handle message event."""
|
||||||
if message["type"] in ("chat", "normal"):
|
if message["type"] in ("chat", "normal"):
|
||||||
|
_message = SimpleMessage(message)
|
||||||
|
|
||||||
|
if _message.body.startswith("!"):
|
||||||
|
self.command(_message, to=_message.sender)
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.direct(SimpleMessage(message))
|
self.direct(_message)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.log.info("Bot.direct not implemented")
|
self.log.info("Bot.direct not implemented")
|
||||||
|
|
||||||
@ -209,8 +219,14 @@ class Bot(ClientXMPP):
|
|||||||
"""Handle groupchat_message event."""
|
"""Handle groupchat_message event."""
|
||||||
if message["type"] in ("groupchat", "normal"):
|
if message["type"] in ("groupchat", "normal"):
|
||||||
if message["mucnick"] != self.config.nick:
|
if message["mucnick"] != self.config.nick:
|
||||||
|
_message = SimpleMessage(message)
|
||||||
|
|
||||||
|
if f"{self.nick}:!" in _message.body:
|
||||||
|
self.command(_message, room=_message.room)
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.group(SimpleMessage(message))
|
self.group(_message)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.log.info("Bot.group not implemented")
|
self.log.info("Bot.group not implemented")
|
||||||
|
|
||||||
@ -249,6 +265,25 @@ class Bot(ClientXMPP):
|
|||||||
|
|
||||||
self.send_message(**kwargs)
|
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):
|
class EchoBot(Bot):
|
||||||
"""Responds with whatever you send.
|
"""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):
|
def direct(self, message):
|
||||||
"""Send back whatever we receive."""
|
"""Send back whatever we receive."""
|
||||||
self.reply(message.body, to=message.sender)
|
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):
|
def direct(self, message):
|
||||||
"""Receive private messages and whisper them into group chats."""
|
"""Receive private messages and whisper them into group chats."""
|
||||||
self.reply(f"*pssttt...* {message.body}", room=message.room)
|
self.reply(f"*pssttt...* {message.body}", room=message.room)
|
||||||
|
Reference in New Issue
Block a user