little update.
This commit is contained in:
parent
4d60e5918d
commit
260386bcac
28 changed files with 1070 additions and 50 deletions
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
Simple Matrix Application Library
|
||||
=================================
|
||||
16
smal/README.txt
Normal file
16
smal/README.txt
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
Simple Matrix Application Library
|
||||
=================================
|
||||
|
||||
sub libs:
|
||||
- pymxutils: matrix cli utils
|
||||
- smal: the lib itself
|
||||
- smbl: simplematrixbotlib compat layer experiments (if any)
|
||||
- demobot: simple demo bot
|
||||
|
||||
install: pip install .
|
||||
|
||||
usage:
|
||||
- run `smalsetup <matrixid>` in an empty dir.
|
||||
- start the bot `demobot`.
|
||||
- simple demo bot. no further configuration required
|
||||
|
|
@ -9,7 +9,7 @@ requires-python = ">=3.11"
|
|||
description = "smal - simple matrix application library"
|
||||
authors = [{ name = "saces" }]
|
||||
license = "AGPL-3.0-only"
|
||||
readme = "README"
|
||||
readme = "README.txt"
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Programming Language :: Python",
|
||||
|
|
@ -19,6 +19,7 @@ classifiers = [
|
|||
"pymxutils" = "src/pymxutils"
|
||||
"smal" = "src/smal"
|
||||
"smbl" = "src/smbl"
|
||||
"demobot" = "src/demobot"
|
||||
|
||||
[project.urls]
|
||||
repository = "https://codeberg.org/saces/pygomx"
|
||||
|
|
@ -34,3 +35,4 @@ mxaccountinfo = "pymxutils.mxutils:accountinfo"
|
|||
mxclearaccount = "pymxutils.mxutils:clearaccount"
|
||||
mxserverinfo = "pymxutils.mxutils:serverinfo"
|
||||
smalsetup = "smal.smalsetup:smalsetup"
|
||||
demobot = "demobot:main"
|
||||
|
|
|
|||
1
smal/src/demobot/__init__.py
Normal file
1
smal/src/demobot/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from .demobot import main
|
||||
4
smal/src/demobot/__main__.py
Normal file
4
smal/src/demobot/__main__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import sys
|
||||
from .demobot import main
|
||||
|
||||
sys.exit(main())
|
||||
74
smal/src/demobot/demobot.py
Normal file
74
smal/src/demobot/demobot.py
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import os
|
||||
from time import time_ns
|
||||
import logging
|
||||
import json
|
||||
from smal.bot import SMALBot
|
||||
from _pygomx import lib, ffi
|
||||
|
||||
# setup logging, we want timestamps
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s.%(msecs)03d %(levelname)s %(name)s - %(funcName)s: %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S",
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(level=logging.INFO)
|
||||
|
||||
|
||||
DEFAULT_PREFIX = "!"
|
||||
|
||||
|
||||
@ffi.callback("void(char*)")
|
||||
def on_event(evt):
|
||||
e = ffi.string(evt)
|
||||
print("Got an event: ", e)
|
||||
|
||||
|
||||
@ffi.callback("void(char*)")
|
||||
def on_message(msg):
|
||||
m = ffi.string(msg).decode("utf-8")
|
||||
|
||||
msg = json.loads(m)
|
||||
|
||||
if msg["type"] != "m.room.message":
|
||||
# not a room message
|
||||
logger.error(f"not a room message: {msg}")
|
||||
return
|
||||
|
||||
if msg["sender"] == "get own id from missing code":
|
||||
# ignore own messages
|
||||
# for now just do not send valid commands by yourself
|
||||
logger.info(f"ignore own message: {msg}")
|
||||
return
|
||||
|
||||
if "msgtype" in msg["content"].keys() and msg["content"]["msgtype"] != "m.text":
|
||||
# only react to messages, not emotes
|
||||
logger.debug(f"ignore unknown message type: {msg}")
|
||||
return
|
||||
|
||||
if msg["content"]["body"] == "!stop":
|
||||
logger.info(f"stopping the bot")
|
||||
bot.stop()
|
||||
return
|
||||
|
||||
if msg["content"]["body"].startswith("!echo"):
|
||||
logger.error(f"reply to this: {msg}")
|
||||
|
||||
bot.sendmessage(msg["roomid"], "huhu")
|
||||
|
||||
return
|
||||
|
||||
logger.info(f"ignored a message: {msg}")
|
||||
|
||||
|
||||
def main():
|
||||
# create and run the bot
|
||||
global bot
|
||||
bot = SMALBot(DEFAULT_PREFIX)
|
||||
bot.SetOnEventHandler(on_event)
|
||||
bot.SetOnMessageHandler(on_message)
|
||||
bot.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
18
smal/src/smal/app.py
Normal file
18
smal/src/smal/app.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from .pygomx import _MXClient
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
"""
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class SMALApp(_MXClient):
|
||||
""" """
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
34
smal/src/smal/bot.py
Normal file
34
smal/src/smal/bot.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
from .app import SMALApp
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
"""
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class SMALBot(SMALApp):
|
||||
""" """
|
||||
|
||||
def __init__(self, sigil: String):
|
||||
super().__init__()
|
||||
self._sigil = sigil
|
||||
|
||||
def run(self):
|
||||
self._sync()
|
||||
|
||||
def stop(self):
|
||||
self._stopsync()
|
||||
|
||||
def sendmessage(self, roomid, text):
|
||||
data = {}
|
||||
data["roomid"] = roomid
|
||||
data["content"] = {}
|
||||
data["content"]["body"] = text
|
||||
|
||||
self._sendmessage(data)
|
||||
13
smal/src/smal/errors.py
Normal file
13
smal/src/smal/errors.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
class APIError(Exception):
|
||||
"""Exception raised for api usage errors.
|
||||
|
||||
Attributes:
|
||||
message -- explanation of the error
|
||||
"""
|
||||
|
||||
def __init__(self, message):
|
||||
self.message = message[4:]
|
||||
super().__init__(self.message)
|
||||
67
smal/src/smal/pygomx.py
Normal file
67
smal/src/smal/pygomx.py
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
from _pygomx import lib, ffi
|
||||
import json
|
||||
from .errors import APIError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class _MXClient:
|
||||
"""
|
||||
core binding
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._createMXClient()
|
||||
|
||||
def _createMXClient(self):
|
||||
r = lib.apiv0_createclient_pass(b".mxpass", b".", b"*", b"*", b"*")
|
||||
|
||||
result = ffi.string(r)
|
||||
lib.FreeCString(r)
|
||||
if result.startswith(b"ERR:"):
|
||||
raise APIError(result)
|
||||
|
||||
result_dict = json.loads(result)
|
||||
self.client_id = result_dict["id"]
|
||||
|
||||
def SetOnEventHandler(self, fn):
|
||||
r = lib.apiv0_set_on_event_handler(self.client_id, fn)
|
||||
result = ffi.string(r)
|
||||
lib.FreeCString(r)
|
||||
if result.startswith(b"ERR:"):
|
||||
raise APIError(result)
|
||||
|
||||
def SetOnMessageHandler(self, fn):
|
||||
r = lib.apiv0_set_on_message_handler(self.client_id, fn)
|
||||
result = ffi.string(r)
|
||||
lib.FreeCString(r)
|
||||
if result.startswith(b"ERR:"):
|
||||
raise APIError(result)
|
||||
|
||||
def _sync(self):
|
||||
r = lib.apiv0_startclient(self.client_id)
|
||||
result = ffi.string(r)
|
||||
lib.FreeCString(r)
|
||||
# if result.startswith(b"ERR:"):
|
||||
# raise APIError(result)
|
||||
print("_sync: ", result)
|
||||
|
||||
def _stopsync(self):
|
||||
r = lib.apiv0_stopclient(self.client_id)
|
||||
result = ffi.string(r)
|
||||
lib.FreeCString(r)
|
||||
# if result.startswith(b"ERR:"):
|
||||
# raise APIError(result)
|
||||
print("_stopsync: ", result)
|
||||
|
||||
def _sendmessage(self, data_dict):
|
||||
data = json.dumps(data_dict).encode(encoding="utf-8")
|
||||
r = lib.apiv0_sendmessage(self.client_id, data)
|
||||
result = ffi.string(r)
|
||||
lib.FreeCString(r)
|
||||
# if result.startswith(b"ERR:"):
|
||||
# raise APIError(result)
|
||||
print("_sendmessage: ", result)
|
||||
4
smal/src/smal/smalsetup/__main__.py
Normal file
4
smal/src/smal/smalsetup/__main__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import sys
|
||||
from .smalsetup import smalsetup
|
||||
|
||||
sys.exit(smalsetup())
|
||||
|
|
@ -1,2 +1,47 @@
|
|||
import sys
|
||||
import os
|
||||
import getpass
|
||||
import json
|
||||
from _pygomx import lib, ffi
|
||||
|
||||
|
||||
def smalsetup():
|
||||
return 99
|
||||
if len(sys.argv) != 2:
|
||||
print("usage: ", sys.argv[0], " matrixid")
|
||||
return 1
|
||||
|
||||
mxid = sys.argv[1].encode(encoding="utf-8")
|
||||
|
||||
r = lib.apiv0_discover(mxid)
|
||||
result = ffi.string(r).decode("utf-8")
|
||||
lib.FreeCString(r)
|
||||
|
||||
if result.startswith("ERR:"):
|
||||
print(result)
|
||||
return 1
|
||||
|
||||
result_dict = json.loads(result)
|
||||
result_dict["password"] = getpass.getpass(prompt="Password: ")
|
||||
data = json.dumps(result_dict).encode(encoding="utf-8")
|
||||
|
||||
r = lib.apiv0_login(data)
|
||||
result = ffi.string(r).decode("utf-8")
|
||||
lib.FreeCString(r)
|
||||
|
||||
if result.startswith("ERR:"):
|
||||
print(result)
|
||||
return 1
|
||||
|
||||
# Set restrictive umask (owner only)
|
||||
new_umask = 0o077
|
||||
old_umask = os.umask(new_umask)
|
||||
|
||||
# Create file with new umask
|
||||
with open(".mxpass", "w") as f:
|
||||
f.write(result)
|
||||
|
||||
# Restore original umask
|
||||
os.umask(old_umask)
|
||||
|
||||
print("login created. start your bot now.")
|
||||
return 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue