#include #include #include #include #include #include #include #include #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; } }