Parsee/src/MatrixEventHandler.c
2024-06-30 17:15:03 +02:00

258 lines
6.7 KiB
C

#include <Parsee.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Json.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Log.h>
#include <string.h>
#include <stdlib.h>
#include <Matrix.h>
#include <AS.h>
static void
ParseeMemberHandler(ParseeData *data, HashMap *event)
{
char *state_key = GrabString(event, 1, "state_key");
char *membership = GrabString(event, 2, "content", "membership");
char *room_id = GrabString(event, 1, "room_id");
char *sender = GrabString(event, 1, "sender");
char *chat_id;
char *local = data->config->sender_localpart;
const ParseeConfig *conf = data->config;
if (StrEquals(membership, "invite") && ParseeIsPuppet(conf, state_key))
{
DbRef *ref;
HashMap *json;
char *jid;
bool direct = GrabBoolean(event, 2, "content", "is_direct");
bool bot = !strncmp(sender + 1, local, strlen(local));
ASJoin(conf, room_id, state_key);
jid = ParseeDecodeLocalJID(conf, state_key);
if (direct && !bot)
{
ref = DbCreate(data->db, 3, "rooms", room_id, "data");
json = DbJson(ref);
HashMapSet(json, "is_direct", JsonValueBoolean(direct && !bot));
HashMapSet(json, "xmpp_user", JsonValueString(jid));
DbUnlock(data->db, ref);
ParseePushDMRoom(data, sender, jid, room_id);
}
if (jid)
{
Free(jid);
}
}
else if (StrEquals(membership, "join") && !ParseeIsPuppet(conf, state_key))
{
char *jid = ParseeEncodeMXID(state_key);
chat_id = ParseeGetFromRoomID(data, room_id);
if (chat_id)
{
char *muc = ParseeGetMUCID(data, chat_id);
char *rev = StrConcat(2, muc, "/parsee");
/* Make the user join the MUC */
XMPPJoinMUC(data->jabber, jid, rev);
Free(rev);
Free(muc);
}
Free(jid);
Free(chat_id);
}
}
static void
ParseeBotHandler(ParseeData *data, HashMap *event)
{
char *msgtype = GrabString(event, 2, "content", "msgtype");
char *body = GrabString(event, 2, "content", "body");
char *id = GrabString(event, 1, "room_id");
char *ev_id = GrabString(event, 1, "event_id");
char *sender = GrabString(event, 1, "sender");
char *profile = StrConcat(4,
"@", data->config->sender_localpart,
":", data->config->homeserver_host
);
Command *cmd;
if (StrEquals(msgtype, "m.notice"))
{
Free(profile);
return;
}
if (*body != '!')
{
/* All commands are to be marked with a ! */
Free(ASSend(
data->config, id, profile,
"m.room.message",
MatrixCreateNotice("Please enter a valid command")
));
Free(profile);
return;
}
/* TODO: Make an improvment. This is the bare minimum */
if (!StrEquals(sender, data->config->matrix_admin))
{
Free(ASSend(
data->config, id, profile,
"m.room.message",
MatrixCreateNotice("You are not the admin")
));
Free(profile);
return;
}
body++;
cmd = CommandParse(body);
{
ParseeCmdArg arg;
arg.data = data;
arg.event = event;
RouteCommand(data->handler, cmd, &arg);
}
end:
Free(profile);
CommandFree(cmd);
}
static void
ParseeMessageHandler(ParseeData *data, HashMap *event)
{
XMPPComponent *jabber = data->jabber;
DbRef *ref;
HashMap *json;
char *msgtype = GrabString(event, 2, "content", "msgtype");
char *body = GrabString(event, 2, "content", "body");
char *id = GrabString(event, 1, "room_id");
char *ev_id = GrabString(event, 1, "event_id");
char *sender = GrabString(event, 1, "sender");
char *chat_id, *muc_id, *jid;
char *reply_id = MatrixGetReply(event);
char *xepd = ParseeXMPPify(event);
char *cmd_lp = data->config->sender_localpart;
bool direct = false;
chat_id = ParseeGetFromRoomID(data, id);
ref = DbLock(data->db, 3, "rooms", id, "data");
json = DbJson(ref);
direct = JsonValueAsBoolean(HashMapGet(json, "is_direct"));
if (ParseeIsPuppet(data->config, sender) ||
ParseeManageBan(data, sender, id))
{
DbUnlock(data->db, ref);
Free(chat_id);
Free(reply_id);
Free(xepd);
return;
}
if (!direct && !chat_id)
{
ParseeBotHandler(data, event);
DbUnlock(data->db, ref);
Free(chat_id);
Free(reply_id);
Free(xepd);
return;
}
if (direct)
{
char *user = GrabString(json, 1, "xmpp_user");
char *local = ParseeEncodeMXID(sender);
Log(LOG_INFO," Sending to %s as %s", user, local);
XMPPSendPlain(jabber, local, user, body, "chat", NULL, NULL, ev_id, NULL, NULL);
DbUnlock(data->db, ref);
Free(chat_id);
Free(local);
Free(reply_id);
Free(xepd);
return;
}
DbUnlock(data->db, ref);
/* Try to find the chat ID */
muc_id = ParseeGetMUCID(data, chat_id);
if (!chat_id)
{
Free(reply_id);
Free(xepd);
return;
}
jid = ParseeEncodeMXID(sender);
{
/* TODO: Check the name's validity */
char *name = ASGetName(data->config, id, sender);
char *rev = StrConcat(4, muc_id, "/", name, "[p]");
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, origin_id
);
Free(rev);
Free(name);
Free(stanza);
Free(sender);
Free(unauth);
Free(origin_id);
Free(unedited_id);
}
Free(chat_id);
Free(muc_id);
Free(jid);
Free(reply_id);
Free(xepd);
}
void
ParseeEventHandler(ParseeData *data, HashMap *event)
{
char *event_type;
if (!data || !event)
{
return;
}
event_type = GrabString(event, 1, "type");
if (StrEquals(event_type, "m.room.member"))
{
ParseeMemberHandler(data, event);
return;
}
if (StrEquals(event_type, "m.room.message"))
{
ParseeMessageHandler(data, event);
return;
}
}