Parsee/src/XMPPThread.c
LDA b820a441ed [MOD] Add x-parsee tag with metadata, global nicks
Still need to grab it on the room-level from the room state if possible,
otherwise just rollback to the MXID.

I also need to consider profile pictures and bridging media, and check
if the nick was present XMPP-side first, as that can and will cause
issues, especially around semi-anonymous MUCs.
2024-06-22 22:43:58 +02:00

145 lines
4.3 KiB
C

#include <Parsee.h>
#include <pthread.h>
#include <string.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Log.h>
#include <Cytoplasm/Str.h>
#include <Matrix.h>
#include <XMPP.h>
#include <XML.h>
#include <AS.h>
static pthread_mutex_t cond_var_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER;
void
ParseeWakeupThread(void)
{
pthread_mutex_lock(&cond_var_lock);
pthread_cond_signal(&cond_var);
pthread_mutex_unlock(&cond_var_lock);
}
static void
ParseeDMHandler(char *room, char *from, XMLElement *data, const ParseeConfig *c)
{
ASSend(
c, room, from,
"m.room.message", MatrixCreateMessage(data->data)
);
}
void *
ParseeXMPPThread(void *argp)
{
ParseeData *args = argp;
XMPPComponent *jabber = args->jabber;
XMLElement *stanza = NULL;
while (true)
{
XMLElement *body = NULL;
XMLElement *data = NULL;
XMLElement *stanza_id = NULL;
char *to, *room, *from, *from_matrix;
char *chat_id, *mroom_id;
stanza = XMLDecode(jabber->stream, false);
if (!stanza)
{
continue;
}
if (StrEquals(stanza->name, "presence"))
{
XMLFreeElement(stanza);
continue;
}
else if (StrEquals(stanza->name, "message"))
{
size_t i;
if (XMPPIsKiller(stanza))
{
const char *killer = "killer";
const char *suspend="suspend";
from = HashMapGet(stanza->attrs, "from");
if (!strncmp(from, killer, strlen(killer)))
{
XMLFreeElement(stanza);
break;
}
else if (!strncmp(from, suspend, strlen(suspend)))
{
XMLFreeElement(stanza);
pthread_mutex_lock(&cond_var_lock);
pthread_cond_wait(&cond_var, &cond_var_lock);
pthread_mutex_unlock(&cond_var_lock);
continue;
}
}
body = XMLookForUnique(stanza, "body");
if (!body)
{
XMLFreeElement(stanza);
continue;
}
stanza_id = XMLookForUnique(stanza, "stanza-id");
to = ParseeDecodeMXID(HashMapGet(stanza->attrs, "to"));
from = HashMapGet(stanza->attrs, "from");
from_matrix = ParseeEncodeJID(args->config, from, true);
room = ParseeFindDMRoom(args, to, from);
data = ArrayGet(body->children, 0);
/* TODO: Consider having rich messages, and move that out
* to separate functions */
chat_id = ParseeGetFromMUCID(args, from);
mroom_id = ParseeGetRoomID(args, chat_id);
if (room)
{
ParseeDMHandler(room, from_matrix, data, args->config);
}
if (mroom_id && !XMPPIsParseeStanza(stanza))
{
char *res = ParseeGetResource(from);
char *encoded = ParseeEncodeJID(args->config, from, false);
char *s_id_str = HashMapGet(stanza_id->attrs, "id");
/* TODO: Create smarter puppet names, and send presence
* in every room at Parsee's bootup. */
if (ParseeVerifyStanza(args, chat_id, s_id_str))
{
ASRegisterUser(args->config, encoded);
ASSetName(args->config, encoded, res);
ASJoin(args->config, mroom_id, encoded);
ASSend(
args->config, mroom_id, encoded,
"m.room.message", MatrixCreateMessage(data->data)
);
ParseePushStanza(args, chat_id, s_id_str);
}
Free(res);
Free(encoded);
}
Free(chat_id);
Free(mroom_id);
Free(from_matrix);
Free(room);
Free(to);
}
else
{
Log(LOG_WARNING, "Unknown stanza '%s':", stanza->name);
XMLEncode(StreamStdout(), stanza);
StreamPrintf(StreamStdout(), "\n");
StreamFlush(StreamStdout());
}
XMLFreeElement(stanza);
}
return NULL;
}