mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 16:55:10 +00:00
[MOD] Carve the way to XMPP rich replies
Bifrost could *never*!
This commit is contained in:
parent
10e140e2a2
commit
fe77906cde
10 changed files with 126 additions and 18 deletions
13
src/AS.c
13
src/AS.c
|
|
@ -169,16 +169,17 @@ ASSetState(const ParseeConfig *conf, char *id, char *type, char *key, char *mask
|
||||||
HttpClientContextFree(ctx);
|
HttpClientContextFree(ctx);
|
||||||
JsonFree(state);
|
JsonFree(state);
|
||||||
}
|
}
|
||||||
void
|
char *
|
||||||
ASSend(const ParseeConfig *conf, char *id, char *user, char *type, HashMap *c)
|
ASSend(const ParseeConfig *conf, char *id, char *user, char *type, HashMap *c)
|
||||||
{
|
{
|
||||||
HttpClientContext *ctx = NULL;
|
HttpClientContext *ctx = NULL;
|
||||||
char *path, *params;
|
char *path, *params;
|
||||||
char *txn;
|
char *txn, *ret;
|
||||||
|
HashMap *reply;
|
||||||
if (!conf || !id || !type || !user || !c)
|
if (!conf || !id || !type || !user || !c)
|
||||||
{
|
{
|
||||||
JsonFree(c);
|
JsonFree(c);
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
txn = StrRandom(16);
|
txn = StrRandom(16);
|
||||||
|
|
@ -194,8 +195,14 @@ ASSend(const ParseeConfig *conf, char *id, char *user, char *type, HashMap *c)
|
||||||
ASAuthenticateRequest(conf, ctx);
|
ASAuthenticateRequest(conf, ctx);
|
||||||
ParseeSetRequestJSON(ctx, c);
|
ParseeSetRequestJSON(ctx, c);
|
||||||
|
|
||||||
|
reply = JsonDecode(HttpClientStream(ctx));
|
||||||
|
ret = StrDuplicate(JsonValueAsString(HashMapGet(reply, "event_id")));
|
||||||
|
JsonFree(reply);
|
||||||
|
|
||||||
HttpClientContextFree(ctx);
|
HttpClientContextFree(ctx);
|
||||||
JsonFree(c);
|
JsonFree(c);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
char *
|
char *
|
||||||
ASCreateRoom(const ParseeConfig *conf, char *by, char *alias)
|
ASCreateRoom(const ParseeConfig *conf, char *by, char *alias)
|
||||||
|
|
|
||||||
15
src/Events.c
15
src/Events.c
|
|
@ -114,3 +114,18 @@ MatrixCreateMedia(char *mxc, char *body, char *mime)
|
||||||
|
|
||||||
return map;
|
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")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,16 +69,24 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
|
||||||
char *msgtype = GrabString(event, 2, "content", "msgtype");
|
char *msgtype = GrabString(event, 2, "content", "msgtype");
|
||||||
char *body = GrabString(event, 2, "content", "body");
|
char *body = GrabString(event, 2, "content", "body");
|
||||||
char *id = GrabString(event, 1, "room_id");
|
char *id = GrabString(event, 1, "room_id");
|
||||||
|
char *ev_id = GrabString(event, 1, "event_id");
|
||||||
char *sender = GrabString(event, 1, "sender");
|
char *sender = GrabString(event, 1, "sender");
|
||||||
char *chat_id, *muc_id, *jid;
|
char *chat_id, *muc_id, *jid;
|
||||||
|
char *reply_id = MatrixGetReply(event);
|
||||||
|
|
||||||
bool direct = false;
|
bool direct = false;
|
||||||
|
|
||||||
if (ParseeIsPuppet(data->config, sender))
|
if (ParseeIsPuppet(data->config, sender))
|
||||||
{
|
{
|
||||||
|
Free(reply_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reply_id)
|
||||||
|
{
|
||||||
|
Log(LOG_INFO, "reply=%s", reply_id);
|
||||||
|
}
|
||||||
|
|
||||||
ref = DbLock(data->db, 3, "rooms", id, "data");
|
ref = DbLock(data->db, 3, "rooms", id, "data");
|
||||||
json = DbJson(ref);
|
json = DbJson(ref);
|
||||||
direct = JsonValueAsBoolean(HashMapGet(json, "is_direct"));
|
direct = JsonValueAsBoolean(HashMapGet(json, "is_direct"));
|
||||||
|
|
@ -89,9 +97,10 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
|
||||||
char *user = GrabString(json, 1, "xmpp_user");
|
char *user = GrabString(json, 1, "xmpp_user");
|
||||||
char *local = ParseeEncodeMXID(sender);
|
char *local = ParseeEncodeMXID(sender);
|
||||||
|
|
||||||
XMPPSendPlain(jabber, local, user, body, NULL);
|
XMPPSendPlain(jabber, local, user, body, NULL, NULL, NULL);
|
||||||
|
|
||||||
Free(local);
|
Free(local);
|
||||||
|
Free(reply_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,6 +109,7 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
|
||||||
muc_id = ParseeGetMUCID(data, chat_id);
|
muc_id = ParseeGetMUCID(data, chat_id);
|
||||||
if (!chat_id)
|
if (!chat_id)
|
||||||
{
|
{
|
||||||
|
Free(reply_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
jid = ParseeEncodeMXID(sender);
|
jid = ParseeEncodeMXID(sender);
|
||||||
|
|
@ -107,14 +117,24 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
|
||||||
/* TODO: Check the name's validity */
|
/* TODO: Check the name's validity */
|
||||||
char *name = ASGetName(data->config, NULL, sender);
|
char *name = ASGetName(data->config, NULL, sender);
|
||||||
char *rev = StrConcat(3, muc_id, "/", name);
|
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);
|
XMPPJoinMUC(jabber, jid, rev);
|
||||||
XMPPSendPlain(jabber, jid, muc_id, body, "groupchat");
|
XMPPSendPlain(jabber, jid, muc_id, body, "groupchat", stanza, sender);
|
||||||
Free(rev);
|
Free(rev);
|
||||||
Free(name);
|
Free(name);
|
||||||
|
Free(stanza);
|
||||||
|
Free(sender);
|
||||||
}
|
}
|
||||||
Free(chat_id);
|
Free(chat_id);
|
||||||
Free(muc_id);
|
Free(muc_id);
|
||||||
Free(jid);
|
Free(jid);
|
||||||
|
Free(reply_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -541,14 +541,14 @@ ParseeGetMUCID(ParseeData *data, char *chat_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
DbRef *ref;
|
||||||
HashMap *j;
|
HashMap *j;
|
||||||
HashMap *stanzas, *obj;
|
HashMap *stanzas, *obj, *events;
|
||||||
bool new_stanzas = false;
|
bool new_stanzas = false, new_events = false;
|
||||||
uint64_t age = UtilTsMillis();
|
uint64_t age = UtilTsMillis();
|
||||||
if (!data || !chat_id || !stanza_id)
|
if (!data || !chat_id || !stanza_id || !ev || !sender)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -576,6 +576,20 @@ ParseePushStanza(ParseeData *data, char *chat_id, char *stanza_id)
|
||||||
HashMapSet(j, "stanzas", JsonValueObject(stanzas));
|
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);
|
DbUnlock(data->db, ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -636,3 +650,38 @@ ParseeSendPresence(ParseeData *data)
|
||||||
}
|
}
|
||||||
DbUnlock(data->db, ref);
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
#include <XML.h>
|
#include <XML.h>
|
||||||
|
|
||||||
void
|
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;
|
XMLElement *message, *body, *data, *parsee;
|
||||||
char *from;
|
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 */
|
/* 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, body);
|
||||||
XMLAddChild(message, parsee);
|
XMLAddChild(message, parsee);
|
||||||
XMLAddChild(body, data);
|
XMLAddChild(body, data);
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,10 @@ ParseeWakeupThread(void)
|
||||||
static void
|
static void
|
||||||
ParseeDMHandler(char *room, char *from, XMLElement *data, const ParseeConfig *c)
|
ParseeDMHandler(char *room, char *from, XMLElement *data, const ParseeConfig *c)
|
||||||
{
|
{
|
||||||
ASSend(
|
Free(ASSend(
|
||||||
c, room, from,
|
c, room, from,
|
||||||
"m.room.message", MatrixCreateMessage(data->data)
|
"m.room.message", MatrixCreateMessage(data->data)
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
@ -71,6 +71,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
|
||||||
char *res = ParseeGetResource(from);
|
char *res = ParseeGetResource(from);
|
||||||
char *encoded = ParseeEncodeJID(args->config, from, false);
|
char *encoded = ParseeEncodeJID(args->config, from, false);
|
||||||
char *s_id_str = HashMapGet(stanza_id->attrs, "id");
|
char *s_id_str = HashMapGet(stanza_id->attrs, "id");
|
||||||
|
char *event_id;
|
||||||
|
|
||||||
/* TODO: Create smarter puppet names */
|
/* TODO: Create smarter puppet names */
|
||||||
if (ParseeVerifyStanza(args, chat_id, s_id_str))
|
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);
|
mxc = ASReupload(args->config, oob_data->data, &mime);
|
||||||
content = MatrixCreateMedia(mxc, data->data, mime);
|
content = MatrixCreateMedia(mxc, data->data, mime);
|
||||||
|
|
||||||
ASSend(
|
event_id = ASSend(
|
||||||
args->config, mroom_id, encoded,
|
args->config, mroom_id, encoded,
|
||||||
"m.room.message", content
|
"m.room.message", content
|
||||||
);
|
);
|
||||||
|
|
@ -102,12 +103,13 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSend(
|
event_id = ASSend(
|
||||||
args->config, mroom_id, encoded,
|
args->config, mroom_id, encoded,
|
||||||
"m.room.message", MatrixCreateMessage(data->data)
|
"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);
|
Free(res);
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ extern void ASJoin(const ParseeConfig *, char *, char *);
|
||||||
|
|
||||||
/* Sends a message event with a specific type and body.
|
/* Sends a message event with a specific type and body.
|
||||||
* Said body is freed during the function's execution. */
|
* 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 */
|
/* 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);
|
extern void ASSetState(const ParseeConfig *conf, char *id, char *type, char *key, char *mask, HashMap *event);
|
||||||
|
|
|
||||||
|
|
@ -20,4 +20,7 @@ extern HashMap * MatrixCreateNameState(char *name);
|
||||||
|
|
||||||
/* Creates a join membership with a specific nickname */
|
/* Creates a join membership with a specific nickname */
|
||||||
extern HashMap * MatrixCreateNickChange(char *nick);
|
extern HashMap * MatrixCreateNickChange(char *nick);
|
||||||
|
|
||||||
|
/* Get the event ID of the reply if existent */
|
||||||
|
extern char * MatrixGetReply(HashMap *event);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -145,11 +145,14 @@ extern char * ParseeGetRoomID(ParseeData *, char *chat_id);
|
||||||
extern char * ParseeGetMUCID(ParseeData *, char *chat_id);
|
extern char * ParseeGetMUCID(ParseeData *, char *chat_id);
|
||||||
|
|
||||||
/* Pushes a stanza ID to a 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 */
|
/* Checks if a stanza is not duplicated in a chat ID */
|
||||||
extern bool ParseeVerifyStanza(ParseeData *, char *chat_id, char *stanza_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 */
|
/* Sends presence requests for every MUC around as a fake JID */
|
||||||
extern void ParseeSendPresence(ParseeData *);
|
extern void ParseeSendPresence(ParseeData *);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ extern bool XMPPAuthenticateCompStream(XMPPComponent *comp, char *shared);
|
||||||
extern void XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc);
|
extern void XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc);
|
||||||
|
|
||||||
/* TODO: XMPP stuff, I don't fucking know, I'm not a Jabbernerd. */
|
/* 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);
|
extern void XMPPSendMUC(XMPPComponent *comp, char *fr, char *as, char *to, char *msg, char *type);
|
||||||
|
|
||||||
/* Closes a raw component stream. */
|
/* Closes a raw component stream. */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue