[MOD] Carve the way to XMPP rich replies

Bifrost could *never*!
This commit is contained in:
LDA 2024-06-23 23:46:46 +02:00
commit fe77906cde
10 changed files with 126 additions and 18 deletions

View file

@ -169,16 +169,17 @@ ASSetState(const ParseeConfig *conf, char *id, char *type, char *key, char *mask
HttpClientContextFree(ctx);
JsonFree(state);
}
void
char *
ASSend(const ParseeConfig *conf, char *id, char *user, char *type, HashMap *c)
{
HttpClientContext *ctx = NULL;
char *path, *params;
char *txn;
char *txn, *ret;
HashMap *reply;
if (!conf || !id || !type || !user || !c)
{
JsonFree(c);
return;
return NULL;
}
txn = StrRandom(16);
@ -194,8 +195,14 @@ ASSend(const ParseeConfig *conf, char *id, char *user, char *type, HashMap *c)
ASAuthenticateRequest(conf, ctx);
ParseeSetRequestJSON(ctx, c);
reply = JsonDecode(HttpClientStream(ctx));
ret = StrDuplicate(JsonValueAsString(HashMapGet(reply, "event_id")));
JsonFree(reply);
HttpClientContextFree(ctx);
JsonFree(c);
return ret;
}
char *
ASCreateRoom(const ParseeConfig *conf, char *by, char *alias)

View file

@ -114,3 +114,18 @@ MatrixCreateMedia(char *mxc, char *body, char *mime)
return map;
}
char *
MatrixGetReply(HashMap *event)
{
if (!event)
{
return NULL;
}
return StrDuplicate(JsonValueAsString(
JsonGet(event, 4, "content",
"m.relates_to", "m.in_reply_to",
"event_id")
));
}

View file

@ -69,16 +69,24 @@ ParseeMessageHandler(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 *chat_id, *muc_id, *jid;
char *reply_id = MatrixGetReply(event);
bool direct = false;
if (ParseeIsPuppet(data->config, sender))
{
Free(reply_id);
return;
}
if (reply_id)
{
Log(LOG_INFO, "reply=%s", reply_id);
}
ref = DbLock(data->db, 3, "rooms", id, "data");
json = DbJson(ref);
direct = JsonValueAsBoolean(HashMapGet(json, "is_direct"));
@ -89,9 +97,10 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
char *user = GrabString(json, 1, "xmpp_user");
char *local = ParseeEncodeMXID(sender);
XMPPSendPlain(jabber, local, user, body, NULL);
XMPPSendPlain(jabber, local, user, body, NULL, NULL, NULL);
Free(local);
Free(reply_id);
return;
}
@ -100,6 +109,7 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
muc_id = ParseeGetMUCID(data, chat_id);
if (!chat_id)
{
Free(reply_id);
return;
}
jid = ParseeEncodeMXID(sender);
@ -107,14 +117,24 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
/* TODO: Check the name's validity */
char *name = ASGetName(data->config, NULL, sender);
char *rev = StrConcat(3, muc_id, "/", name);
char *stanza = NULL, *sender = NULL;
if (reply_id)
{
ParseeGetStanzaInfo(data, chat_id, reply_id, &stanza, &sender);
Log(LOG_INFO, "Replying to %s by %s", stanza, sender);
}
XMPPJoinMUC(jabber, jid, rev);
XMPPSendPlain(jabber, jid, muc_id, body, "groupchat");
XMPPSendPlain(jabber, jid, muc_id, body, "groupchat", stanza, sender);
Free(rev);
Free(name);
Free(stanza);
Free(sender);
}
Free(chat_id);
Free(muc_id);
Free(jid);
Free(reply_id);
}
void

View file

@ -541,14 +541,14 @@ ParseeGetMUCID(ParseeData *data, char *chat_id)
}
void
ParseePushStanza(ParseeData *data, char *chat_id, char *stanza_id)
ParseePushStanza(ParseeData *data, char *chat_id, char *stanza_id, char *ev, char *sender)
{
DbRef *ref;
HashMap *j;
HashMap *stanzas, *obj;
bool new_stanzas = false;
HashMap *stanzas, *obj, *events;
bool new_stanzas = false, new_events = false;
uint64_t age = UtilTsMillis();
if (!data || !chat_id || !stanza_id)
if (!data || !chat_id || !stanza_id || !ev || !sender)
{
return;
}
@ -576,6 +576,20 @@ ParseePushStanza(ParseeData *data, char *chat_id, char *stanza_id)
HashMapSet(j, "stanzas", JsonValueObject(stanzas));
}
events = JsonValueAsObject(HashMapGet(j, "events"));
if (!events)
{
events = HashMapCreate();
new_events = true;
}
obj = HashMapCreate();
HashMapSet(obj, "stanza", JsonValueString(stanza_id));
HashMapSet(obj, "sender", JsonValueString(sender));
JsonValueFree(HashMapSet(events, ev, JsonValueObject(obj)));
if (new_events)
{
HashMapSet(j, "events", JsonValueObject(events));
}
DbUnlock(data->db, ref);
}
@ -636,3 +650,38 @@ ParseeSendPresence(ParseeData *data)
}
DbUnlock(data->db, ref);
}
bool
ParseeGetStanzaInfo(ParseeData *data, char *chat_id, char *ev, char **st, char **se)
{
DbRef *ref = NULL;
HashMap *j = NULL;
HashMap *event = NULL;
bool ret = false;
if (!data || !chat_id || !ev || !st || !se)
{
Log(LOG_INFO, "%p %p %p %p %p", data, chat_id, ev, st, se);
return false;
}
ref = DbLock(data->db, 2, "chats", chat_id);
j = DbJson(ref);
if (!ref)
{
Log(LOG_INFO, "LF");
goto end;
}
event = JsonValueAsObject(JsonGet(j, 2, "events", ev));
if (!event)
{
Log(LOG_INFO, "EF %s", ev);
goto end;
}
*st = StrDuplicate(JsonValueAsString(HashMapGet(event, "stanza")));
*se = StrDuplicate(JsonValueAsString(HashMapGet(event, "sender")));
ret = true;
end:
DbUnlock(data->db, ref);
return ret;
}

View file

@ -7,7 +7,7 @@
#include <XML.h>
void
XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type)
XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse)
{
XMLElement *message, *body, *data, *parsee;
char *from;
@ -50,6 +50,15 @@ XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type)
/* TODO: Add custom fields depending on the caller's wishes */
}
if (rst && rse)
{
XMLElement *reply = XMLCreateTag("reply");
XMLAddAttr(reply, "to", rse);
XMLAddAttr(reply, "id", rst);
XMLAddAttr(reply, "xmlns", "urn:xmpp:reply:0");
XMLAddChild(message, reply);
}
XMLAddChild(message, body);
XMLAddChild(message, parsee);
XMLAddChild(body, data);

View file

@ -27,10 +27,10 @@ ParseeWakeupThread(void)
static void
ParseeDMHandler(char *room, char *from, XMLElement *data, const ParseeConfig *c)
{
ASSend(
Free(ASSend(
c, room, from,
"m.room.message", MatrixCreateMessage(data->data)
);
));
}
static bool
@ -71,6 +71,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
char *res = ParseeGetResource(from);
char *encoded = ParseeEncodeJID(args->config, from, false);
char *s_id_str = HashMapGet(stanza_id->attrs, "id");
char *event_id;
/* TODO: Create smarter puppet names */
if (ParseeVerifyStanza(args, chat_id, s_id_str))
@ -93,7 +94,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
mxc = ASReupload(args->config, oob_data->data, &mime);
content = MatrixCreateMedia(mxc, data->data, mime);
ASSend(
event_id = ASSend(
args->config, mroom_id, encoded,
"m.room.message", content
);
@ -102,12 +103,13 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
}
else
{
ASSend(
event_id = ASSend(
args->config, mroom_id, encoded,
"m.room.message", MatrixCreateMessage(data->data)
);
}
ParseePushStanza(args, chat_id, s_id_str);
ParseePushStanza(args, chat_id, s_id_str, event_id, from);
Free(event_id);
}
Free(res);

View file

@ -28,7 +28,7 @@ extern void ASJoin(const ParseeConfig *, char *, char *);
/* Sends a message event with a specific type and body.
* Said body is freed during the function's execution. */
extern void ASSend(const ParseeConfig *, char *, char *, char *, HashMap *);
extern char * ASSend(const ParseeConfig *, char *, char *, char *, HashMap *);
/* Sets a state event with a specific type and body */
extern void ASSetState(const ParseeConfig *conf, char *id, char *type, char *key, char *mask, HashMap *event);

View file

@ -20,4 +20,7 @@ extern HashMap * MatrixCreateNameState(char *name);
/* Creates a join membership with a specific nickname */
extern HashMap * MatrixCreateNickChange(char *nick);
/* Get the event ID of the reply if existent */
extern char * MatrixGetReply(HashMap *event);
#endif

View file

@ -145,11 +145,14 @@ extern char * ParseeGetRoomID(ParseeData *, char *chat_id);
extern char * ParseeGetMUCID(ParseeData *, char *chat_id);
/* Pushes a stanza ID to a chat ID */
extern void ParseePushStanza(ParseeData *, char *chat_id, char *stanza_id);
extern void ParseePushStanza(ParseeData *, char *chat_id, char *stanza_id, char *event, char *sender);
/* Checks if a stanza is not duplicated in a chat ID */
extern bool ParseeVerifyStanza(ParseeData *, char *chat_id, char *stanza_id);
/* Gets the stanza ID and sender of an event */
extern bool ParseeGetStanzaInfo(ParseeData *, char *c_id, char *e, char **st, char **se);
/* Sends presence requests for every MUC around as a fake JID */
extern void ParseeSendPresence(ParseeData *);

View file

@ -28,7 +28,7 @@ extern bool XMPPAuthenticateCompStream(XMPPComponent *comp, char *shared);
extern void XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc);
/* TODO: XMPP stuff, I don't fucking know, I'm not a Jabbernerd. */
extern void XMPPSendPlain(XMPPComponent *c, char *f, char *t, char *m, char *type);
extern void XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse);
extern void XMPPSendMUC(XMPPComponent *comp, char *fr, char *as, char *to, char *msg, char *type);
/* Closes a raw component stream. */