[ADD/WIP] Start unifying DMs and MUCs

I really need to dispatch XMPP stanza management.
This commit is contained in:
LDA 2024-07-03 14:40:26 +02:00
commit 5f2c3a9cb8
10 changed files with 570 additions and 87 deletions

View file

@ -15,15 +15,15 @@
#include <AS.h>
#define IQ_ADVERT \
AdvertiseSimple("http://jabber.org/protocol/caps") \
AdvertiseSimple("http://jabber.org/protocol/chatstates") \
AdvertiseSimple("http://jabber.org/protocol/caps") \
AdvertiseSimple("urn:xmpp:avatar:metadata+notify") \
AdvertiseSimple("urn:xmpp:message-correct:0") \
AdvertiseSimple("urn:xmpp:reactions:0") \
AdvertiseSimple("urn:xmpp:styling:0") \
AdvertiseSimple("urn:xmpp:reply:0") \
AdvertiseSimple("jabber:x:oob") \
AdvertiseSimple("vcard-temp") \
AdvertiseSimple("urn:xmpp:avatar:metadata+notify") \
AdvertiseSimple("jabber:iq:version") \
AdvertiseSimple("urn:parsee:x-parsee:0") \
AdvertiseSimple("urn:parsee:jealousy:0")
@ -162,13 +162,112 @@ ParseeWakeupThread(void)
pthread_mutex_unlock(&cond_var_lock);
}
static void
ParseeDMHandler(char *room, char *from, XMLElement *data, const ParseeConfig *c)
static char *
ParseeGetBridgedRoom(ParseeData *data, XMLElement *stanza)
{
Free(ASSend(
c, room, from,
"m.room.message", MatrixCreateMessage(data->data)
));
char *to = ParseeDecodeMXID(HashMapGet(stanza->attrs, "to"));
char *from = (HashMapGet(stanza->attrs, "from"));
char *chat_id = ParseeGetFromMUCID(data, from);
char *mroom_id = ParseeGetRoomID(data, chat_id);
char *ret;
Free(chat_id);
if (mroom_id)
{
Free(to);
return mroom_id;
}
/* Not a MUC, find the DMd room. */
ret = ParseeFindDMRoom(data, to, from);
Free(to);
return ret;
}
static char *
ParseeGetEventFromID(ParseeData *data, XMLElement *stanza, char *id)
{
char *from = (HashMapGet(stanza->attrs, "from"));
char *chat_id = ParseeGetFromMUCID(data, from);
char *ret = ParseeEventFromSID(data, chat_id, id);
char *mroom_id = ParseeGetBridgedRoom(data, stanza);
if (!ret)
{
Free(ret);
ret = ParseeEventFromID(data, chat_id, id);
}
Free(chat_id);
if (ret)
{
Free(mroom_id);
return ret;
}
ret = ParseeDMEventFromID(data, mroom_id, id);
Free(mroom_id);
return ret;
}
static char *
ParseeGetReactedEvent(ParseeData *data, XMLElement *stanza)
{
XMLElement *reactions = XMLookForTKV(stanza,
"reactions", "xmlns", "urn:xmpp:reactions:0"
);
char *from = (HashMapGet(stanza->attrs, "from"));
char *reacted_id = reactions ? HashMapGet(reactions->attrs, "id") : NULL;
return ParseeGetEventFromID(data, stanza, reacted_id);
}
static void
ParseePushAllStanza(ParseeData *args, XMLElement *stanza, char *event)
{
char *xmpp_from = HashMapGet(stanza->attrs, "from");
char *mroom_id = ParseeGetBridgedRoom(args, stanza);
char *chat_id = ParseeGetFromMUCID(args, xmpp_from);
char *id_str = HashMapGet(stanza->attrs, "id");
char *s_id_str = XMPPGetStanzaID(stanza);
char *o_id_str = XMPPGetOriginID(stanza);
if (!chat_id)
{
ParseePushDMStanza(
args, mroom_id, s_id_str,
id_str, event, xmpp_from
);
}
ParseePushStanza(args, chat_id, s_id_str, id_str, event, xmpp_from);
Free(mroom_id);
Free(chat_id);
}
static bool
ParseeVerifyAllStanza(ParseeData *args, XMLElement *stanza)
{
char *to, *room;
char *from = HashMapGet(stanza->attrs, "from");
char *id = HashMapGet(stanza->attrs, "id");
char *chat_id = ParseeGetFromMUCID(args, from);
bool ret;
if (chat_id)
{
char *s_id_str = XMPPGetStanzaID(stanza);
ret = ParseeVerifyStanza(args, chat_id, s_id_str);
Free(chat_id);
return ret;
}
to = ParseeDecodeMXID(HashMapGet(stanza->attrs, "to"));
room = ParseeFindDMRoom(args, to, from);
ret = ParseeVerifyDMStanza(args, chat_id, id);
Free(room);
Free(to);
return ret;
}
/* TODO: Clean up all of this. We are currently separating DMs from MUCs,
@ -225,7 +324,6 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
return false;
}
/* 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.
@ -237,12 +335,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
room = ParseeFindDMRoom(args, to, from);
data = ArrayGet(body->children, 0);
chat_id = ParseeGetFromMUCID(args, from);
mroom_id = ParseeGetRoomID(args, chat_id);
if (room)
{
ParseeDMHandler(room, from_matrix, data, args->config);
}
mroom_id = ParseeGetBridgedRoom(args, stanza);
if (mroom_id && !XMPPIsParseeStanza(stanza))
{
char *res = ParseeGetResource(from);
@ -253,13 +346,24 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
char *event_id = NULL;
char *replaced = XMPPGetReplacedID(stanza);
char *reply_to = XMPPGetReply(stanza);
bool chat = false;
if (ParseeVerifyStanza(args, chat_id, s_id_str) && !replaced)
if (StrEquals(HashMapGet(stanza->attrs, "type"), "chat"))
{
Free(encoded);
encoded = StrDuplicate(from_matrix);
chat = true;
}
if (ParseeVerifyAllStanza(args, stanza) && !replaced)
{
XMLElement *oob, *oob_data;
ASRegisterUser(args->config, encoded);
ASSetName(args->config, encoded, res);
if (!chat)
{
ASSetName(args->config, encoded, res);
}
ASInvite(args->config, mroom_id, encoded);
ASJoin(args->config, mroom_id, encoded);
@ -290,7 +394,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
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);
event_id = ParseeGetReactedEvent(args, stanza);
for (i = 0; i < reacts; i++)
{
XMLElement *reaction, *react_data;
@ -311,15 +415,13 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
{
/* TODO: Use HTML-formatted bodies, and respect the fallback
* trims the stanza provides us if possible. Element does
* not like raw bodies on replies. Go figure. */
* not like raw bodies on replies too. Go figure. */
size_t off =
reply_to ? ParseeFindDatastart(data->data) : 0;
HashMap *ev = MatrixCreateMessage(data->data + off);
if (reply_to)
{
char *reply_id = ParseeEventFromSID(
args, chat_id, reply_to
);
char *reply_id = ParseeGetEventFromID(args, stanza, reply_to);
MatrixSetReply(ev, reply_id);
Free(reply_id);
}
@ -328,16 +430,17 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
"m.room.message", ev
);
}
ParseePushStanza(args, chat_id, s_id_str, id_str, event_id, from);
ParseePushAllStanza(args, stanza, event_id);
Free(event_id);
}
else if (replaced)
{
event_id = ParseeEventFromID(args, chat_id, replaced);
event_id = ParseeGetEventFromID(args, stanza, replaced);
Free(ASSend(
args->config, mroom_id, encoded,
"m.room.message", MatrixCreateReplace(event_id, data->data)
));
ParseePushAllStanza(args, stanza, event_id);
Free(event_id);
}
@ -345,19 +448,16 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
Free(res);
Free(encoded);
}
else if (mroom_id)
else
{
XMLElement *parsee = XMLookForUnique(stanza, "x-parsee");
XMLElement *event = XMLookForUnique(parsee, "event-id");
XMLElement *e_d = ArrayGet(event ? event->children : NULL, 0);
char *s_id_str = XMPPGetStanzaID(stanza);
char *id_str = HashMapGet(stanza->attrs, "id");
if (ParseeVerifyStanza(args, chat_id, s_id_str))
{
ParseePushStanza(args, chat_id, s_id_str, id_str, e_d->data, from);
}
ParseePushAllStanza(args, stanza, e_d->data);
}
Free(chat_id);
Free(mroom_id);
Free(from_matrix);
Free(decode_from);
@ -579,6 +679,7 @@ ParseeXMPPThread(void *argp)
const char *killer = "killer";
const char *suspend="suspend";
from = HashMapGet(stanza->attrs, "from");
Log(LOG_INFO, "Killer.");
if (!strncmp(from, killer, strlen(killer)))
{
XMLFreeElement(stanza);