mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 21:25:11 +00:00
303 lines
7.9 KiB
C
303 lines
7.9 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 <Matrix.h>
|
|
#include <AS.h>
|
|
|
|
#define GrabString(obj, ...) JsonValueAsString(JsonGet(obj, __VA_ARGS__))
|
|
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 bot = !strncmp(sender + 1, local, strlen(local));
|
|
ASJoin(conf, room_id, state_key);
|
|
|
|
jid = ParseeDecodeLocalJID(conf, state_key);
|
|
|
|
ref = DbCreate(data->db, 3, "rooms", room_id, "data");
|
|
json = DbJson(ref);
|
|
HashMapSet(json, "is_direct", JsonValueBoolean(!bot));
|
|
HashMapSet(json, "xmpp_user", JsonValueString(jid));
|
|
DbUnlock(data->db, ref);
|
|
|
|
ParseePushDMRoom(data, sender, jid, room_id);
|
|
/* Pretend everything is a dm, ignoring is_direct */
|
|
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++;
|
|
#define BAN_USER "ban-user"
|
|
#define BAN_LIST "ban-list"
|
|
#define LS_USERS "ls-flying"
|
|
cmd = CommandParse(body);
|
|
if (cmd && StrEquals(cmd->command, BAN_USER))
|
|
{
|
|
char *user = HashMapGet(cmd->arguments, "user");
|
|
char *room = HashMapGet(cmd->arguments, "user");
|
|
char *msg;
|
|
|
|
if (!user || !room)
|
|
{
|
|
goto end;
|
|
}
|
|
ASBan(data->config, room, user);
|
|
|
|
msg = StrConcat(3, "Banning '", user, "'...");
|
|
Free(ASSend(
|
|
data->config, id, profile,
|
|
"m.room.message",
|
|
MatrixCreateNotice(msg)
|
|
));
|
|
Free(msg);
|
|
}
|
|
else if (cmd && StrEquals(cmd->command, LS_USERS))
|
|
{
|
|
DbRef *listed = DbLock(data->db, 1, "global_bans");
|
|
HashMap *json = DbJson(listed);
|
|
char *str = NULL, *tmp = NULL, *banned;
|
|
JsonValue *val;
|
|
|
|
while (HashMapIterate(json, &banned, (void **) &val))
|
|
{
|
|
tmp = str;
|
|
str = StrConcat(4, str, "- ", banned, "\n");
|
|
Free(tmp);
|
|
}
|
|
|
|
Free(ASSend(
|
|
data->config, id, profile,
|
|
"m.room.message",
|
|
MatrixCreateNotice("No-fly listed users:")
|
|
));
|
|
Free(ASSend(
|
|
data->config, id, profile,
|
|
"m.room.message",
|
|
MatrixCreateNotice(str)
|
|
));
|
|
|
|
Free(str);
|
|
DbUnlock(data->db, listed);
|
|
}
|
|
else if (cmd && StrEquals(cmd->command, BAN_LIST))
|
|
{
|
|
char *user = HashMapGet(cmd->arguments, "user");
|
|
char *msg;
|
|
|
|
if (!user)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
msg = StrConcat(3, "Banning '", user, "'...");
|
|
Free(ASSend(
|
|
data->config, id, profile,
|
|
"m.room.message",
|
|
MatrixCreateNotice(msg)
|
|
));
|
|
Free(msg);
|
|
ParseeGlobalBan(data, user);
|
|
}
|
|
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"));
|
|
DbUnlock(data->db, ref);
|
|
|
|
if (ParseeIsPuppet(data->config, sender) ||
|
|
ParseeManageBan(data, sender, id))
|
|
{
|
|
Free(chat_id);
|
|
Free(reply_id);
|
|
Free(xepd);
|
|
return;
|
|
}
|
|
|
|
if (!direct && !chat_id)
|
|
{
|
|
ParseeBotHandler(data, event);
|
|
|
|
Free(chat_id);
|
|
Free(reply_id);
|
|
Free(xepd);
|
|
return;
|
|
}
|
|
|
|
|
|
if (direct)
|
|
{
|
|
char *user = GrabString(json, 1, "xmpp_user");
|
|
char *local = ParseeEncodeMXID(sender);
|
|
|
|
XMPPSendPlain(jabber, local, user, body, NULL, NULL, NULL, ev_id, NULL);
|
|
|
|
Free(chat_id);
|
|
Free(local);
|
|
Free(reply_id);
|
|
Free(xepd);
|
|
return;
|
|
}
|
|
|
|
/* 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);
|
|
if (reply_id)
|
|
{
|
|
ParseeGetStanzaInfo(data, chat_id, reply_id, &stanza, &sender);
|
|
}
|
|
XMPPJoinMUC(jabber, jid, rev);
|
|
XMPPSendPlain(
|
|
jabber, jid, muc_id,
|
|
xepd ? xepd : body, "groupchat",
|
|
stanza, sender, ev_id, unauth
|
|
);
|
|
Free(rev);
|
|
Free(name);
|
|
Free(stanza);
|
|
Free(sender);
|
|
Free(unauth);
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|