Initial Commit for testing
This commit is contained in:
commit
0118c68690
5 files changed
+121
No files matched your search
@@ -0,0 +1,23 @@
|
||||
pkgname=matrix-status-bot
|
||||
pkgver=0.1.0
|
||||
pkgrel=1
|
||||
pkgdesc="Mirror a makerspace's open/closed state into a Matrix room name and avatar"
|
||||
arch=(any)
|
||||
license=(MIT)
|
||||
depends=(python)
|
||||
backup=(etc/matrix-status-bot.conf)
|
||||
source=(status.py
|
||||
matrix-status-bot.service
|
||||
matrix-status-bot-set@.service
|
||||
matrix-status-bot.conf)
|
||||
sha256sums=('42b130bfd22dad0ab03335b4774db4a9413581bc8e4e21792228c88a6bf61f30'
|
||||
'019a9b6a728cc1bb0a9f674c3cbbd9b2b561d6d40355bdb80413f7ab9e6f55d7'
|
||||
'9fbfb7f67f7eb747c638749da99fa1f3c356c765ae228e6f9605028ee7673a6b'
|
||||
'c53c003089c47087efd24a1d9abcf8b1bd69e391f58093a45a18a6370c3784f6')
|
||||
|
||||
package() {
|
||||
install -Dm755 status.py "$pkgdir/usr/bin/matrix-status-bot"
|
||||
install -Dm644 -t "$pkgdir/usr/lib/systemd/system" \
|
||||
matrix-status-bot.service matrix-status-bot-set@.service
|
||||
install -Dm600 matrix-status-bot.conf "$pkgdir/etc/matrix-status-bot.conf"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Set Matrix makerspace status to %i
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
EnvironmentFile=/etc/matrix-status-bot.conf
|
||||
ExecStart=/usr/bin/matrix-status-bot %i
|
||||
DynamicUser=yes
|
||||
@@ -0,0 +1,14 @@
|
||||
# matrix-status-bot configuration (read by systemd as root; keep mode 600)
|
||||
MATRIX_HS=https://matrix.example.org
|
||||
MATRIX_TOKEN=
|
||||
MATRIX_ROOM=!roomid:example.org
|
||||
|
||||
# Used by matrix-status-bot.service (polling mode)
|
||||
SPACEAPI_URL=https://example.org/spaceapi.json
|
||||
POLL_INTERVAL=60
|
||||
|
||||
# Optional
|
||||
#NAME_OPEN=🟢 Space is open
|
||||
#NAME_CLOSED=🔴 Space is closed
|
||||
#AVATAR_OPEN=mxc://example.org/green
|
||||
#AVATAR_CLOSED=mxc://example.org/red
|
||||
@@ -0,0 +1,19 @@
|
||||
[Unit]
|
||||
Description=Matrix makerspace status bot (SpaceAPI -> room name/avatar)
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
EnvironmentFile=/etc/matrix-status-bot.conf
|
||||
ExecStart=/usr/bin/matrix-status-bot --spaceapi $SPACEAPI_URL $POLL_INTERVAL
|
||||
Restart=on-failure
|
||||
RestartSec=30
|
||||
DynamicUser=yes
|
||||
ProtectHome=yes
|
||||
PrivateDevices=yes
|
||||
CapabilityBoundingSet=
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
SystemCallFilter=@system-service
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Minimal Matrix status-room bot: mirrors open/closed into a room's name (and avatar).
|
||||
|
||||
Usage:
|
||||
status.py open|closed set once (door switch, button, cron, ...)
|
||||
status.py --spaceapi URL [SECS] poll a SpaceAPI endpoint every SECS seconds (default 60)
|
||||
|
||||
Env: MATRIX_HS (https://matrix.example.org), MATRIX_TOKEN, MATRIX_ROOM (!id:server)
|
||||
Optional: NAME_OPEN / NAME_CLOSED, AVATAR_OPEN / AVATAR_CLOSED (mxc:// URIs)
|
||||
"""
|
||||
import json, os, sys, time, urllib.error, urllib.parse, urllib.request
|
||||
|
||||
HS, TOKEN, ROOM = (os.environ[k] for k in ("MATRIX_HS", "MATRIX_TOKEN", "MATRIX_ROOM"))
|
||||
NAMES = {True: os.getenv("NAME_OPEN", "🟢 Space is open"), False: os.getenv("NAME_CLOSED", "🔴 Space is closed")}
|
||||
AVATARS = {True: os.getenv("AVATAR_OPEN"), False: os.getenv("AVATAR_CLOSED")}
|
||||
|
||||
|
||||
def state(method, event_type, body=None):
|
||||
url = f"{HS.rstrip('/')}/_matrix/client/v3/rooms/{urllib.parse.quote(ROOM, safe='')}/state/{event_type}"
|
||||
req = urllib.request.Request(url, method=method, data=body and json.dumps(body).encode(),
|
||||
headers={"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"})
|
||||
with urllib.request.urlopen(req, timeout=10) as r:
|
||||
return json.load(r)
|
||||
|
||||
|
||||
def set_status(is_open):
|
||||
try:
|
||||
if state("GET", "m.room.name").get("name") == NAMES[is_open]:
|
||||
return # unchanged: don't add a "changed the room name" line
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code != 404: # 404 = room has no name yet
|
||||
raise
|
||||
state("PUT", "m.room.name", {"name": NAMES[is_open]})
|
||||
if AVATARS[is_open]:
|
||||
state("PUT", "m.room.avatar", {"url": AVATARS[is_open]})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = sys.argv[1:]
|
||||
if args in (["open"], ["closed"]):
|
||||
set_status(args[0] == "open")
|
||||
elif args[:1] == ["--spaceapi"] and len(args) in (2, 3):
|
||||
last = None
|
||||
while True:
|
||||
try:
|
||||
with urllib.request.urlopen(args[1], timeout=10) as r:
|
||||
is_open = bool(json.load(r)["state"]["open"])
|
||||
if is_open != last:
|
||||
set_status(is_open)
|
||||
last = is_open
|
||||
except Exception as e:
|
||||
print("error:", e, file=sys.stderr)
|
||||
time.sleep(int(args[2]) if len(args) == 3 else 60)
|
||||
else:
|
||||
sys.exit(__doc__)
|
||||
Reference in new issue
Block a user