diff --git a/XEPS-TBD.TXT b/XEPS-TBD.TXT index 1a3444f..dfcdf4d 100644 --- a/XEPS-TBD.TXT +++ b/XEPS-TBD.TXT @@ -1,10 +1,12 @@ XEPs current supported are in src/XMPPThread.c, at the IQ disco advertising. For future XEPs: - - https://xmpp.org/extensions/xep-0444.html + ~ https://xmpp.org/extensions/xep-0444.html 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. + HALF-IMPLEMENTED + - 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) @@ -12,6 +14,7 @@ For future XEPs: stuck as a FluffyChat/Nheko feature. If any client devs hear this, please consider adding these, (especially if you're a smElement employee!) + - 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. diff --git a/src/Events.c b/src/Events.c index 6a3137d..0c28657 100644 --- a/src/Events.c +++ b/src/Events.c @@ -157,3 +157,25 @@ MatrixCreateReplace(char *event, char *body) return map; } +HashMap * +MatrixCreateReact(char *event, char *body) +{ + HashMap *map; + HashMap *rel; + if (!body || !event) + { + return NULL; + } + + map = HashMapCreate(); + + rel = HashMapCreate(); + HashMapSet(rel, "rel_type", JsonValueString("m.annotation")); + HashMapSet(rel, "event_id", JsonValueString(event)); + HashMapSet(rel, "key", JsonValueString(body)); + + HashMapSet(map, "m.relates_to", JsonValueObject(rel)); + + return map; + +} diff --git a/src/Main.c b/src/Main.c index 7f1d50d..850092b 100644 --- a/src/Main.c +++ b/src/Main.c @@ -76,7 +76,7 @@ Main(void) Log(LOG_NOTICE, "Starting up local cronjobs..."); cron = CronCreate( 10 SECONDS ); - CronEvery(cron, 30 MINUTES, ParseeCleanup, conf.handlerArgs); + CronEvery(cron, 5 MINUTES, ParseeCleanup, conf.handlerArgs); CronStart(cron); diff --git a/src/Parsee/Data.c b/src/Parsee/Data.c index b698e3f..28a7e73 100644 --- a/src/Parsee/Data.c +++ b/src/Parsee/Data.c @@ -102,9 +102,9 @@ ParseeCleanup(void *datp) } \ while (0) - CleanupField(stanza, 5 MINUTES); - CleanupField(event, 5 MINUTES); - CleanupField(id, 5 MINUTES); + CleanupField(stanza, 15 MINUTES); + CleanupField(event, 15 MINUTES); + CleanupField(id, 15 MINUTES); DbUnlock(data->db, ref); } @@ -377,6 +377,7 @@ ParseePushStanza(ParseeData *data, char *chat_id, char *stanza_id, char *id, cha obj = HashMapCreate(); HashMapSet(obj, "age", JsonValueInteger(age)); + HashMapSet(obj, "event", JsonValueString(ev)); JsonValueFree(HashMapSet(stanzas, stanza_id, JsonValueObject(obj))); if (new_stanzas) @@ -484,3 +485,34 @@ end: DbUnlock(data->db, ref); return ret; } +char * +ParseeEventFromSID(ParseeData *data, char *chat_id, char *id) +{ + DbRef *ref = NULL; + HashMap *j = NULL; + HashMap *ids = NULL; + char *ret = NULL; + if (!data || !chat_id || !id) + { + return NULL; + } + + ref = DbLock(data->db, 2, "chats", chat_id); + j = DbJson(ref); + if (!ref) + { + goto end; + } + + ids = JsonValueAsObject(HashMapGet(j, "stanzas")); + if (!ids) + { + goto end; + } + + ret = JsonValueAsString(JsonGet(ids, 2, id, "event")); + ret = StrDuplicate(ret); +end: + DbUnlock(data->db, ref); + return ret; +} diff --git a/src/XMPPThread.c b/src/XMPPThread.c index 8515aa8..a747a80 100644 --- a/src/XMPPThread.c +++ b/src/XMPPThread.c @@ -38,6 +38,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza) { XMPPComponent *jabber = args->jabber; + XMLElement *reactions = NULL; XMLElement *body = NULL; XMLElement *data = NULL; @@ -71,7 +72,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza) char *s_id_str = XMPPGetStanzaID(stanza); char *o_id_str = XMPPGetOriginID(stanza); char *id_str = HashMapGet(stanza->attrs, "id"); - char *event_id; + char *event_id = NULL; char *replaced = XMPPGetReplacedID(stanza); /* TODO: Create smarter puppet names */ @@ -85,6 +86,9 @@ MessageStanza(ParseeData *args, XMLElement *stanza) /* Check if it is a media link */ oob = XMLookForTKV(stanza, "x", "xmlns", "jabber:x:oob"); + reactions = XMLookForTKV(stanza, + "reactions", "xmlns", "urn:xmpp:reactions:0" + ); if (oob) { char *mxc, *mime = NULL; @@ -102,6 +106,28 @@ MessageStanza(ParseeData *args, XMLElement *stanza) Free(mime); Free(mxc); } + else if (reactions) + { + char *reacted_id = HashMapGet(reactions->attrs, "id"); + Array *react_child = reactions->children; + size_t reacts = ArraySize(react_child); + event_id = ParseeEventFromSID(args, chat_id, reacted_id); + for (i = 0; i < reacts; i++) + { + XMLElement *reaction, *react_data; + reaction = ArrayGet(react_child, i); + react_data = ArrayGet(reaction->children, 0); + + /* TODO: We should manage removed reactions. */ + Free(ASSend( + args->config, mroom_id, encoded, + "m.reaction", + MatrixCreateReact(event_id, react_data->data) + )); + } + Free(event_id); + event_id = NULL; + } else { event_id = ASSend( @@ -166,6 +192,7 @@ IQDiscoGet(ParseeData *args, XMPPComponent *jabber, XMLElement *stanza) while (0) AdvertiseSimple("urn:xmpp:message-correct:0"); + AdvertiseSimple("urn:xmpp:reactions:0"); AdvertiseSimple("urn:xmpp:styling:0"); AdvertiseSimple("urn:xmpp:reply:0"); AdvertiseSimple("urn:xmpp:sid:0"); diff --git a/src/include/Matrix.h b/src/include/Matrix.h index bfb2685..726d336 100644 --- a/src/include/Matrix.h +++ b/src/include/Matrix.h @@ -12,6 +12,8 @@ extern HashMap * MatrixCreateNotice(char *body); /* Creates the content for a normal message. */ extern HashMap * MatrixCreateMessage(char *body); +extern HashMap * MatrixCreateReact(char *event, char *body); + /* Creates the content for a replace message. */ extern HashMap * MatrixCreateReplace(char *event, char *body); diff --git a/src/include/Parsee.h b/src/include/Parsee.h index b61ec2e..d34c942 100644 --- a/src/include/Parsee.h +++ b/src/include/Parsee.h @@ -170,4 +170,5 @@ extern char * ParseeXMPPify(HashMap *event); /* Finds an event ID from an ID in the stanza's attributes */ extern char * ParseeEventFromID(ParseeData *d, char *c_id, char *ori_id); +extern char * ParseeEventFromSID(ParseeData *d, char *c_id, char *ori_id); #endif