From 8472ada95393600b52042ad133c1effc859710a9 Mon Sep 17 00:00:00 2001 From: LDA Date: Sat, 29 Jun 2024 19:10:28 +0200 Subject: [PATCH] [ADD/MOD] Help/stats and two-way modification More on the Reverse Ideology! --- XEPS-TBD.TXT | 11 ++++++--- src/Commands/Help.c | 42 +++++++++++++++++++++++++++++++ src/Commands/Stats.c | 53 ++++++++++++++++++++++++++++++++++++++++ src/Events.c | 13 ++++++++++ src/MatrixEventHandler.c | 14 ++++++++--- src/Parsee/Data.c | 2 +- src/Parsee/User.c | 32 ++++++++++++++++++++++++ src/XMPP/Stanza.c | 10 +++++++- src/XMPPThread.c | 6 +++++ src/include/Matrix.h | 1 + src/include/Parsee.h | 1 + src/include/Routes.h | 30 +++++++++++++++++++---- src/include/XMPP.h | 2 +- 13 files changed, 203 insertions(+), 14 deletions(-) create mode 100644 src/Commands/Help.c create mode 100644 src/Commands/Stats.c diff --git a/XEPS-TBD.TXT b/XEPS-TBD.TXT index 8f34671..0c1e217 100644 --- a/XEPS-TBD.TXT +++ b/XEPS-TBD.TXT @@ -5,10 +5,11 @@ Somewhat implemented XEPs: This allows reactions, which Matrix also has support to. The two systems don't seem *too* restrictive on one-another (unlike some IM platforms I won't mention), so this doesn't sound too bad to do - HALF-IMPLEMENTED: Removing stickers won't work. + HALF-IMPLEMENTED: Removing reacts won't work. For future XEPs: - + - https://xmpp.org/extensions/xep-0421.html + Using the occupant ID in semi-anonymous MUCs is a desirable property. - https://xmpp.org/extensions/xep-0118.html Informations on what a user is listening to. Matrix doesn't have good support for status, to be frank. Clients (including KappaChat) @@ -18,6 +19,9 @@ For future XEPs: As such, if _any_ client devs hear this, please consider adding these, (especially if you're a smElement employee!) + - https://xmpp.org/extensions/xep-0080.html + Doxxing people over two protocols is great! + - https://xmpp.org/extensions/xep-0084.html Avatar support would be extremely useful, if just a QoL improvment. Matrix and XMPP both have support for these. @@ -26,6 +30,7 @@ For future XEPs: Stickers are great. Matrix and XMPP somewhat has support for them, so might be a nice-to-have, and also to push over XMPP support. -Not XEPs, but ideas that needs to be added: +Not XEPs, but ideas that _needs_ to be added: - "GIVE THE PUPPETS APPROPRIATE PLS/ROLES" - Hydro/t4d "also it [Bifrost] doesn't respect voice either" + - https://www.youtube.com/watch?v=InL414iDZmY diff --git a/src/Commands/Help.c b/src/Commands/Help.c new file mode 100644 index 0000000..6dbf06b --- /dev/null +++ b/src/Commands/Help.c @@ -0,0 +1,42 @@ +#include + +#include +#include +#include + +#include +#include + +CommandHead(CmdHelp, cmd, argp) +{ + ParseeCmdArg *args = argp; + ParseeData *data = args->data; + HashMap *json, *event = args->event; + char *profile = StrConcat(4, + "@", data->config->sender_localpart, + ":", data->config->homeserver_host + ); + char *id = GrabString(event, 1, "room_id"); + char *msg; + + Free(ASSend( + data->config, id, profile, + "m.room.message", + MatrixCreateNotice("Commands: ") + )); + +#define X_COMMAND(path, name, desc) { \ + msg = StrConcat(3, path, "-", desc);\ + Free(ASSend( \ + data->config, id, profile, \ + "m.room.message", \ + MatrixCreateNotice(msg) \ + )); \ + Free(msg); \ + } \ + while (0); + COMMANDS +#undef X_COMMAND + + Free(profile); +} diff --git a/src/Commands/Stats.c b/src/Commands/Stats.c new file mode 100644 index 0000000..8aead0f --- /dev/null +++ b/src/Commands/Stats.c @@ -0,0 +1,53 @@ +#include + +#include +#include +#include + +#include +#include + +CommandHead(CmdStats, cmd, argp) +{ + ParseeCmdArg *args = argp; + ParseeData *data = args->data; + HashMap *json, *event = args->event; + char *profile = StrConcat(4, + "@", data->config->sender_localpart, + ":", data->config->homeserver_host + ); + char *id = GrabString(event, 1, "room_id"); + char *msg; + size_t alloc = MemoryAllocated(); + size_t kb = alloc >> 10; + size_t mb = kb >> 10; + size_t gb = mb >> 10; + size_t min = gb ? gb : (mb ? mb : (kb ? kb : alloc)); + char *unit = gb ? "GB" : (mb ? "MB" : (kb ? "KB" : "B")); + char *l = StrInt(min); + + msg = StrConcat(3, + "Information for " NAME " (", + CytoplasmGetVersionStr(), ")" + ); + Free(ASSend( + data->config, id, profile, + "m.room.message", + MatrixCreateNotice(msg) + )); + Free(msg); + + msg = StrConcat(5, + "- Memory usage: ", l, " ", unit, + " (reported by Cytoplasm)" + ); + Free(ASSend( + data->config, id, profile, + "m.room.message", + MatrixCreateNotice(msg) + )); + Free(msg); + Free(l); + + Free(profile); +} diff --git a/src/Events.c b/src/Events.c index 0c28657..e0d56a4 100644 --- a/src/Events.c +++ b/src/Events.c @@ -129,6 +129,19 @@ MatrixGetReply(HashMap *event) "event_id") )); } +char * +MatrixGetEdit(HashMap *event) +{ + if (!event) + { + return NULL; + } + + return StrDuplicate(JsonValueAsString( + JsonGet(event, 3, "content", + "m.relates_to", "event_id") + )); +} HashMap * MatrixCreateReplace(char *event, char *body) { diff --git a/src/MatrixEventHandler.c b/src/MatrixEventHandler.c index 606e92e..94ac8fa 100644 --- a/src/MatrixEventHandler.c +++ b/src/MatrixEventHandler.c @@ -112,7 +112,6 @@ ParseeBotHandler(ParseeData *data, HashMap *event) arg.data = data; arg.event = event; - Log(LOG_INFO, "Routing..."); RouteCommand(data->handler, cmd, &arg); } end: @@ -171,7 +170,7 @@ ParseeMessageHandler(ParseeData *data, HashMap *event) char *user = GrabString(json, 1, "xmpp_user"); char *local = ParseeEncodeMXID(sender); - XMPPSendPlain(jabber, local, user, body, NULL, NULL, NULL, ev_id, NULL); + XMPPSendPlain(jabber, local, user, body, NULL, NULL, NULL, ev_id, NULL, NULL); DbUnlock(data->db, ref); Free(chat_id); @@ -198,21 +197,30 @@ ParseeMessageHandler(ParseeData *data, HashMap *event) char *stanza = NULL, *sender = NULL; char *url = GrabString(event, 2, "content", "url"); char *unauth = ParseeToUnauth(data, url); + + char *unedited_id = MatrixGetEdit(event); + char *origin_id = NULL; if (reply_id) { ParseeGetStanzaInfo(data, chat_id, reply_id, &stanza, &sender); } + else if (unedited_id) + { + ParseeGetOrigin(data, chat_id, unedited_id, &origin_id); + } XMPPJoinMUC(jabber, jid, rev); XMPPSendPlain( jabber, jid, muc_id, xepd ? xepd : body, "groupchat", - stanza, sender, ev_id, unauth + stanza, sender, ev_id, unauth, origin_id ); Free(rev); Free(name); Free(stanza); Free(sender); Free(unauth); + Free(origin_id); + Free(unedited_id); } Free(chat_id); Free(muc_id); diff --git a/src/Parsee/Data.c b/src/Parsee/Data.c index edd299c..4f34406 100644 --- a/src/Parsee/Data.c +++ b/src/Parsee/Data.c @@ -36,7 +36,7 @@ ParseeInitData(XMPPComponent *comp) while (0); ROUTES #undef X_ROUTE -#define X_COMMAND(path, name) CommandAddCommand(data->handler, path, name); +#define X_COMMAND(path,n,d) CommandAddCommand(data->handler, path, n); COMMANDS #undef X_COMMAND return data; diff --git a/src/Parsee/User.c b/src/Parsee/User.c index 2390217..c299417 100644 --- a/src/Parsee/User.c +++ b/src/Parsee/User.c @@ -599,6 +599,38 @@ end: DbUnlock(data->db, ref); return ret; } +bool +ParseeGetOrigin(ParseeData *data, char *chat_id, char *ev, char **o) +{ + DbRef *ref = NULL; + HashMap *j = NULL; + HashMap *event = NULL; + bool ret = false; + if (!data || !chat_id || !ev || !o) + { + return false; + } + + ref = DbLock(data->db, 2, "chats", chat_id); + j = DbJson(ref); + if (!ref) + { + goto end; + } + + + event = JsonValueAsObject(JsonGet(j, 2, "events", ev)); + if (!event) + { + goto end; + } + *o = StrDuplicate(JsonValueAsString(HashMapGet(event, "origin"))); + ret = true; +end: + DbUnlock(data->db, ref); + return ret; + +} #include char * diff --git a/src/XMPP/Stanza.c b/src/XMPP/Stanza.c index 56be1a6..a98e71d 100644 --- a/src/XMPP/Stanza.c +++ b/src/XMPP/Stanza.c @@ -8,7 +8,7 @@ #include void -XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob) +XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob, char *edit) { XMLElement *message, *body, *data, *parsee; char *from; @@ -65,6 +65,14 @@ XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, ch /* TODO: Add custom fields depending on the caller's wishes */ } + if (edit) + { + XMLElement *xedit = XMLCreateTag("replace"); + XMLAddAttr(xedit, "xmlns", "urn:xmpp:message-correct:0"); + XMLAddAttr(xedit, "id", edit); + XMLAddChild(message, xedit); + } + if (oob) { XMLElement *xoob, *oob_data, *oob_url; diff --git a/src/XMPPThread.c b/src/XMPPThread.c index 2eaea67..065441e 100644 --- a/src/XMPPThread.c +++ b/src/XMPPThread.c @@ -64,6 +64,12 @@ MessageStanza(ParseeData *args, XMLElement *stanza) to = ParseeDecodeMXID(HashMapGet(stanza->attrs, "to")); from = HashMapGet(stanza->attrs, "from"); + + /* TODO: On semi-anonymous MUCs, it might be preferable to use a + * form of the occupant ID as the base, as it is more unique, and + * less prone to trigger the character limit on Matrix. + * + * See: https://xmpp.org/extensions/xep-0421.html */ decode_from = ParseeLookupJID(from); from_matrix = ParseeEncodeJID(args->config, decode_from, true); room = ParseeFindDMRoom(args, to, from); diff --git a/src/include/Matrix.h b/src/include/Matrix.h index 726d336..9073352 100644 --- a/src/include/Matrix.h +++ b/src/include/Matrix.h @@ -28,4 +28,5 @@ extern HashMap * MatrixCreateNickChange(char *nick); /* Get the event ID of the reply if existent */ extern char * MatrixGetReply(HashMap *event); +extern char * MatrixGetEdit(HashMap *event); #endif diff --git a/src/include/Parsee.h b/src/include/Parsee.h index b6a6ea4..c3a86c1 100644 --- a/src/include/Parsee.h +++ b/src/include/Parsee.h @@ -165,6 +165,7 @@ extern bool ParseeVerifyStanza(ParseeData *, char *chat_id, char *stanza_id); /* Gets the stanza ID and sender of an event */ extern bool ParseeGetStanzaInfo(ParseeData *, char *c_id, char *e, char **st, char **se); +extern bool ParseeGetOrigin(ParseeData *data, char *chat_id, char *ev, char **o); /* Sends presence requests for every MUC around as a fake JID */ extern void ParseeSendPresence(ParseeData *); diff --git a/src/include/Routes.h b/src/include/Routes.h index 02577d6..e7c55db 100644 --- a/src/include/Routes.h +++ b/src/include/Routes.h @@ -14,12 +14,32 @@ typedef struct ParseeCmdArg { } ParseeCmdArg; /* A list of all commands. */ -#define COMMANDS X_COMMAND("ban-user", CmdBanUser) \ - X_COMMAND("ban-list", CmdNoFlyList) \ - X_COMMAND("list-bans", CmdListBans) \ - X_COMMAND("set-pl", CmdSetPL) \ +#define COMMANDS X_COMMAND( \ + "ban-user", CmdBanUser, \ + "Bans a user from a room or a MUC" \ + ) \ + X_COMMAND( \ + "ban-list", CmdNoFlyList, \ + "Globally bans a user from using Parsee" \ + ) \ + X_COMMAND( \ + "list-bans", CmdListBans, \ + "Shows all global bans from Parsee" \ + ) \ + X_COMMAND( \ + "set-pl", CmdSetPL, \ + "Sets the power level in a Parsee room" \ + ) \ + X_COMMAND( \ + "help", CmdHelp, \ + "Shows the command list" \ + ) \ + X_COMMAND( \ + "stats", CmdStats, \ + "Shows some Parsee statistics." \ + ) -#define X_COMMAND(path, name) extern void name(Command *, void *); +#define X_COMMAND(path, name,d) extern void name(Command *, void *); COMMANDS #undef X_COMMAND #define CommandHead(name, cmd, argp) void \ diff --git a/src/include/XMPP.h b/src/include/XMPP.h index 8c8adff..0171b3d 100644 --- a/src/include/XMPP.h +++ b/src/include/XMPP.h @@ -28,7 +28,7 @@ extern bool XMPPAuthenticateCompStream(XMPPComponent *comp, char *shared); extern void XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc); /* TODO: XMPP stuff, I don't fucking know, I'm not a Jabbernerd. */ -extern void XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob); +extern void XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob, char *id); /* Closes a raw component stream. */ extern void XMPPEndCompStream(XMPPComponent *stream);