little update.

This commit is contained in:
saces 2026-01-31 08:13:53 +01:00
parent 4d60e5918d
commit 260386bcac
28 changed files with 1070 additions and 50 deletions

View file

@ -0,0 +1 @@
from .demobot import main

View file

@ -0,0 +1,4 @@
import sys
from .demobot import main
sys.exit(main())

View 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
View 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
View 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
View 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
View 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)

View file

@ -0,0 +1,4 @@
import sys
from .smalsetup import smalsetup
sys.exit(smalsetup())

View file

@ -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