From 3a4f6cdbdb5d22c743a8d31e922f4f6719998dda Mon Sep 17 00:00:00 2001 From: saces Date: Fri, 13 Feb 2026 23:51:41 +0100 Subject: [PATCH] add 3rd callback type for non-matrix and non-sync things --- libmxclient/mxclient/client.go | 3 ++- libmxclient/mxclientlib.go | 36 +++++++++++++++++++++++++++++++--- pygomx-module/build_ffi.py | 2 ++ smal/src/demobot/demobot.py | 3 +++ smal/src/smal/pygomx.py | 22 +++++++++++++++++++++ 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/libmxclient/mxclient/client.go b/libmxclient/mxclient/client.go index 77e870a..5171370 100644 --- a/libmxclient/mxclient/client.go +++ b/libmxclient/mxclient/client.go @@ -27,6 +27,7 @@ type MXClient struct { *mautrix.Client OnEvent func(string) OnMessage func(string) + OnSystem func(string) _directMap map[id.RoomID][]id.UserID } @@ -240,7 +241,7 @@ func NewMXClient(homeserverURL string, userID id.UserID, accessToken string) (*M client.Store = cryptoStore - mxclient := &MXClient{client, nil, nil, make(map[id.RoomID][]id.UserID)} + mxclient := &MXClient{client, nil, nil, nil, make(map[id.RoomID][]id.UserID)} syncer.ParseEventContent = true syncer.OnEvent(client.StateStoreSyncHandler) diff --git a/libmxclient/mxclientlib.go b/libmxclient/mxclientlib.go index 8f30a1b..9e63803 100644 --- a/libmxclient/mxclientlib.go +++ b/libmxclient/mxclientlib.go @@ -19,6 +19,7 @@ import ( #include typedef void (*on_event_handler_ptr) (char*, void*); typedef void (*on_message_handler_ptr) (char*, void*); +typedef void (*on_sys_handler_ptr) (char*, void*); static inline void call_c_on_event_handler(on_event_handler_ptr ptr, char* jsonStr, void* pobj) { (ptr)(jsonStr, pobj); @@ -28,6 +29,10 @@ static inline void call_c_on_message_handler(on_message_handler_ptr ptr, char* j (ptr)(jsonStr, pobj); } +static inline void call_c_on_sys_handler(on_message_handler_ptr ptr, char* jsonStr, void* pobj) { + (ptr)(jsonStr, pobj); +} + */ import "C" @@ -42,6 +47,8 @@ type CBClient struct { on_event_handler_pobj unsafe.Pointer on_message_handler C.on_message_handler_ptr on_message_handler_pobj unsafe.Pointer + on_sys_handler C.on_sys_handler_ptr + on_sys_handler_pobj unsafe.Pointer syncCancelFunc context.CancelCauseFunc } @@ -57,6 +64,12 @@ func (cli *CBClient) OnMessage(s string) { C.call_c_on_message_handler(cli.on_message_handler, cStr, cli.on_message_handler_pobj) } +func (cli *CBClient) OnSystem(s string) { + cStr := C.CString(s) + defer C.free(unsafe.Pointer(cStr)) + C.call_c_on_sys_handler(cli.on_sys_handler, cStr, cli.on_sys_handler_pobj) +} + func (cli *CBClient) Set_on_event_handler(fn C.on_event_handler_ptr, pobj unsafe.Pointer) { cli.on_event_handler = fn cli.on_event_handler_pobj = pobj @@ -67,13 +80,18 @@ func (cli *CBClient) Set_on_message_handler(fn C.on_message_handler_ptr, pobj un cli.on_message_handler_pobj = pobj } +func (cli *CBClient) Set_on_sys_handler(fn C.on_sys_handler_ptr, pobj unsafe.Pointer) { + cli.on_sys_handler = fn + cli.on_sys_handler_pobj = pobj +} + // NewCClient creates a new Matrix Client ready for syncing func NewCBClient(homeserverURL string, userID id.UserID, accessToken string) (*CBClient, error) { client, err := mxclient.NewMXClient(homeserverURL, userID, accessToken) if err != nil { return nil, err } - return &CBClient{client, nil, nil, nil, nil, nil}, nil + return &CBClient{client, nil, nil, nil, nil, nil, nil, nil}, nil } /* @@ -187,7 +205,7 @@ func apiv0_createclient(storage_path *C.char, url *C.char, userID *C.char, acces if err != nil { return C.CString(fmt.Sprintf("ERR: %v", err)) } - client := &CBClient{mxclient, nil, nil, nil, nil, nil} + client := &CBClient{mxclient, nil, nil, nil, nil, nil, nil, nil} cclients = append(cclients, client) return C.CString(fmt.Sprintf("{ \"id:\"SUCESS. ID=%d\n", len(cclients))) } @@ -198,9 +216,10 @@ func apiv0_createclient_pass(mxpassfile_path *C.char, storage_path *C.char, url if err != nil { return C.CString(fmt.Sprintf("ERR: %v", err)) } - client := &CBClient{mxclient, nil, nil, nil, nil, nil} + client := &CBClient{mxclient, nil, nil, nil, nil, nil, nil, nil} mxclient.OnEvent = client.OnEvent mxclient.OnMessage = client.OnMessage + mxclient.OnSystem = client.OnSystem cclients = append(cclients, client) out, err := json.Marshal(map[string]any{"id": len(cclients) - 1, "userid": client.UserID.String(), "deviceid": client.DeviceID.String()}) if err != nil { @@ -232,6 +251,17 @@ func apiv0_set_on_message_handler(cid C.int, fn C.on_message_handler_ptr, pobj u return C.CString("SUCCESS.") } +//export apiv0_set_on_sys_handler +func apiv0_set_on_sys_handler(cid C.int, fn C.on_sys_handler_ptr, pobj unsafe.Pointer) *C.char { + cli, err := getClient(int(cid)) + if err != nil { + return C.CString(fmt.Sprintf("ERR: %v", err)) + } + + cli.Set_on_sys_handler(fn, pobj) + return C.CString("SUCCESS.") +} + //export apiv0_startclient func apiv0_startclient(cid C.int) *C.char { cli, err := getClient(int(cid)) diff --git a/pygomx-module/build_ffi.py b/pygomx-module/build_ffi.py index 7d71c9c..cd7fbab 100644 --- a/pygomx-module/build_ffi.py +++ b/pygomx-module/build_ffi.py @@ -27,6 +27,7 @@ ffibuilder.cdef( csource=""" typedef void (*on_event_handler_ptr) (char*, void*); typedef void (*on_message_handler_ptr) (char*, void*); + typedef void (*on_sys_handler_ptr) (char*, void*); extern void FreeCString(char* s); extern char* cli_discoverhs(char* mxid); extern char* cli_mkmxtoken(char* mxid, char* pw); @@ -42,6 +43,7 @@ ffibuilder.cdef( extern char* apiv0_createclient_pass(char* mxpassfile, char* storage_path, char* hs, char* localpart, char* domain); extern char* apiv0_set_on_event_handler(int cid, on_event_handler_ptr ptr, void* pobj); extern char* apiv0_set_on_message_handler(int cid, on_message_handler_ptr ptr, void* pobj); + extern char* apiv0_set_on_sys_handler(int cid, on_sys_handler_ptr ptr, void* pobj); extern char* apiv0_startclient(int cid); extern char* apiv0_stopclient(int cid); extern char* apiv0_sendmessage(int cid, char* data); diff --git a/smal/src/demobot/demobot.py b/smal/src/demobot/demobot.py index f8e32e4..0f88f80 100644 --- a/smal/src/demobot/demobot.py +++ b/smal/src/demobot/demobot.py @@ -16,6 +16,9 @@ DEFAULT_PREFIX = "!" class DemoBot(SMALBot): + def on_sys(self, ntf): + print("Got a system notification: ", ntf) + def on_event(self, evt): print("Got an event: ", e) diff --git a/smal/src/smal/pygomx.py b/smal/src/smal/pygomx.py index 7f54220..2979901 100644 --- a/smal/src/smal/pygomx.py +++ b/smal/src/smal/pygomx.py @@ -50,6 +50,14 @@ class _MXClient: if result.startswith(b"ERR:"): raise APIError(result) + r = lib.apiv0_set_on_sys_handler( + self.client_id, on_sys_callback, self._ffi_selfhandle + ) + result = ffi.string(r) + lib.FreeCString(r) + if result.startswith(b"ERR:"): + raise APIError(result) + def _createMXClient(self): r = lib.apiv0_createclient_pass(b".mxpass", b".", b"*", b"*", b"*") @@ -97,6 +105,12 @@ class _MXClient: else: logger.warn(f"got message but on_message not declared: {msg}") + def process_sys(self, ntf): + if hasattr(self, "on_sys") and callable(self.on_sys): + self.on_sys(ntf) + else: + logger.warn(f"got systen notification but on_sys not declared: {ntf}") + @ffi.callback("void(char*, void*)") def on_event_callback(evt, pobj): @@ -112,3 +126,11 @@ def on_message_callback(msg, pobj): m = ffi.string(msg).decode("utf-8") msg = json.loads(m) cli.process_message(msg) + + +@ffi.callback("void(char*, void*)") +def on_sys_callback(msg, pobj): + cli = ffi.from_handle(pobj) + m = ffi.string(msg).decode("utf-8") + sys = json.loads(m) + cli.process_sys(sys)