[ADD/WIP] Start adding reactions

This commit is contained in:
LDA 2024-06-27 03:41:24 +02:00
commit 1126497d5b
7 changed files with 93 additions and 6 deletions

View file

@ -1,10 +1,12 @@
XEPs current supported are in src/XMPPThread.c, at the IQ disco advertising. XEPs current supported are in src/XMPPThread.c, at the IQ disco advertising.
For future XEPs: 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 This allows reactions, which Matrix also has support to. The two
systems don't seem *too* restrictive on one-another (unlike some systems don't seem *too* restrictive on one-another (unlike some
IM platforms I won't mention), so this doesn't sound too bad. IM platforms I won't mention), so this doesn't sound too bad.
HALF-IMPLEMENTED
- https://xmpp.org/extensions/xep-0118.html - https://xmpp.org/extensions/xep-0118.html
Informations on what a user is listening to. Matrix doesn't have Informations on what a user is listening to. Matrix doesn't have
good support for status, to be frank. Clients (including KappaChat) good support for status, to be frank. Clients (including KappaChat)
@ -12,6 +14,7 @@ For future XEPs:
stuck as a FluffyChat/Nheko feature. stuck as a FluffyChat/Nheko feature.
If any client devs hear this, please consider adding these, If any client devs hear this, please consider adding these,
(especially if you're a smElement employee!) (especially if you're a smElement employee!)
- https://xmpp.org/extensions/xep-0084.html - https://xmpp.org/extensions/xep-0084.html
Avatar support would be extremely useful, if just a QoL improvment. Avatar support would be extremely useful, if just a QoL improvment.
Matrix and XMPP both have support for these. Matrix and XMPP both have support for these.

View file

@ -157,3 +157,25 @@ MatrixCreateReplace(char *event, char *body)
return map; 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;
}

View file

@ -76,7 +76,7 @@ Main(void)
Log(LOG_NOTICE, "Starting up local cronjobs..."); Log(LOG_NOTICE, "Starting up local cronjobs...");
cron = CronCreate( 10 SECONDS ); cron = CronCreate( 10 SECONDS );
CronEvery(cron, 30 MINUTES, ParseeCleanup, conf.handlerArgs); CronEvery(cron, 5 MINUTES, ParseeCleanup, conf.handlerArgs);
CronStart(cron); CronStart(cron);

View file

@ -102,9 +102,9 @@ ParseeCleanup(void *datp)
} \ } \
while (0) while (0)
CleanupField(stanza, 5 MINUTES); CleanupField(stanza, 15 MINUTES);
CleanupField(event, 5 MINUTES); CleanupField(event, 15 MINUTES);
CleanupField(id, 5 MINUTES); CleanupField(id, 15 MINUTES);
DbUnlock(data->db, ref); DbUnlock(data->db, ref);
} }
@ -377,6 +377,7 @@ ParseePushStanza(ParseeData *data, char *chat_id, char *stanza_id, char *id, cha
obj = HashMapCreate(); obj = HashMapCreate();
HashMapSet(obj, "age", JsonValueInteger(age)); HashMapSet(obj, "age", JsonValueInteger(age));
HashMapSet(obj, "event", JsonValueString(ev));
JsonValueFree(HashMapSet(stanzas, stanza_id, JsonValueObject(obj))); JsonValueFree(HashMapSet(stanzas, stanza_id, JsonValueObject(obj)));
if (new_stanzas) if (new_stanzas)
@ -484,3 +485,34 @@ end:
DbUnlock(data->db, ref); DbUnlock(data->db, ref);
return ret; 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;
}

View file

@ -38,6 +38,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
{ {
XMPPComponent *jabber = args->jabber; XMPPComponent *jabber = args->jabber;
XMLElement *reactions = NULL;
XMLElement *body = NULL; XMLElement *body = NULL;
XMLElement *data = NULL; XMLElement *data = NULL;
@ -71,7 +72,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
char *s_id_str = XMPPGetStanzaID(stanza); char *s_id_str = XMPPGetStanzaID(stanza);
char *o_id_str = XMPPGetOriginID(stanza); char *o_id_str = XMPPGetOriginID(stanza);
char *id_str = HashMapGet(stanza->attrs, "id"); char *id_str = HashMapGet(stanza->attrs, "id");
char *event_id; char *event_id = NULL;
char *replaced = XMPPGetReplacedID(stanza); char *replaced = XMPPGetReplacedID(stanza);
/* TODO: Create smarter puppet names */ /* TODO: Create smarter puppet names */
@ -85,6 +86,9 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
/* Check if it is a media link */ /* Check if it is a media link */
oob = XMLookForTKV(stanza, "x", "xmlns", "jabber:x:oob"); oob = XMLookForTKV(stanza, "x", "xmlns", "jabber:x:oob");
reactions = XMLookForTKV(stanza,
"reactions", "xmlns", "urn:xmpp:reactions:0"
);
if (oob) if (oob)
{ {
char *mxc, *mime = NULL; char *mxc, *mime = NULL;
@ -102,6 +106,28 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
Free(mime); Free(mime);
Free(mxc); 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 else
{ {
event_id = ASSend( event_id = ASSend(
@ -166,6 +192,7 @@ IQDiscoGet(ParseeData *args, XMPPComponent *jabber, XMLElement *stanza)
while (0) while (0)
AdvertiseSimple("urn:xmpp:message-correct:0"); AdvertiseSimple("urn:xmpp:message-correct:0");
AdvertiseSimple("urn:xmpp:reactions:0");
AdvertiseSimple("urn:xmpp:styling:0"); AdvertiseSimple("urn:xmpp:styling:0");
AdvertiseSimple("urn:xmpp:reply:0"); AdvertiseSimple("urn:xmpp:reply:0");
AdvertiseSimple("urn:xmpp:sid:0"); AdvertiseSimple("urn:xmpp:sid:0");

View file

@ -12,6 +12,8 @@ extern HashMap * MatrixCreateNotice(char *body);
/* Creates the content for a normal message. */ /* Creates the content for a normal message. */
extern HashMap * MatrixCreateMessage(char *body); extern HashMap * MatrixCreateMessage(char *body);
extern HashMap * MatrixCreateReact(char *event, char *body);
/* Creates the content for a replace message. */ /* Creates the content for a replace message. */
extern HashMap * MatrixCreateReplace(char *event, char *body); extern HashMap * MatrixCreateReplace(char *event, char *body);

View file

@ -170,4 +170,5 @@ extern char * ParseeXMPPify(HashMap *event);
/* Finds an event ID from an ID in the stanza's attributes */ /* 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 * ParseeEventFromID(ParseeData *d, char *c_id, char *ori_id);
extern char * ParseeEventFromSID(ParseeData *d, char *c_id, char *ori_id);
#endif #endif