[MOD] Mess a bit with rich replies, add XEPS-TBD

This should be a nice list of future XEPs to be implemented, so that I
can keep track of these without having to keep all of these in my head.
This commit is contained in:
LDA 2024-06-25 22:49:33 +02:00
commit 628a55fbca
6 changed files with 127 additions and 18 deletions

17
XEPS-TBD.TXT Normal file
View file

@ -0,0 +1,17 @@
XEPs current supported are in src/XMPPThread.c, at the IQ disco advertising.
For future XEPs:
- https://xmpp.org/extensions/xep-0444.html
This allows reactions, which Matrix also has support to. The two
systems don't seem *too* restrictive on one-another (unlike some
IM platforms I won't mention), so this doesn't sound too bad.
- https://xmpp.org/extensions/xep-0118.html
Informations on what a user is listening to. Matrix doesn't have
good support for status, to be frank. Clients (including KappaChat)
should consider having more support for those, rather than it being
stuck as a FluffyChat/Nheko feature.
If any client devs hear this, please consider adding these,
(especially if you're a smElement employee!)
- https://xmpp.org/extensions/xep-0084.html
Avatar support would be extremely useful, if just a QoL improvment.
Matrix and XMPP both have support for these.

View file

@ -289,6 +289,37 @@ ASSetName(const ParseeConfig *conf, char *user, char *name)
JsonFree(json); JsonFree(json);
Free(user); Free(user);
} }
HashMap *
ASFind(const ParseeConfig *c, char *room, char *event)
{
HttpClientContext *ctx = NULL;
HashMap *json;
char *path, *user;
if (!c || !room || !event)
{
return NULL;
}
user = StrConcat(4, "@", c->sender_localpart, ":", c->homeserver_host);
path = StrConcat(7,
"/_matrix/client/v3/rooms/",
room, "/event/", event, "?",
"user_id=", user
);
ctx = ParseeCreateRequest(c, HTTP_GET, path);
Free(path);
ASAuthenticateRequest(c, ctx);
HttpRequestSendHeaders(ctx);
HttpRequestSend(ctx);
json = JsonDecode(HttpClientStream(ctx));
HttpClientContextFree(ctx);
Free(user);
return json;
}
char * char *
ASGetName(const ParseeConfig *c, char *room, char *user) ASGetName(const ParseeConfig *c, char *room, char *user)
{ {

View file

@ -9,6 +9,7 @@
#include <string.h> #include <string.h>
#include <Routes.h> #include <Routes.h>
#include <AS.h>
ParseeData * ParseeData *
ParseeInitData(XMPPComponent *comp) ParseeInitData(XMPPComponent *comp)
@ -82,7 +83,7 @@ ParseeCleanup(void *datp)
uint64_t age = JsonValueAsInteger(HashMapGet(obj, "age")); uint64_t age = JsonValueAsInteger(HashMapGet(obj, "age"));
uint64_t dur = ts - age; uint64_t dur = ts - age;
if ((dur > (5 MINUTES))) if ((dur > (30 MINUTES)))
{ {
ArrayAdd(to_delete, StrDuplicate(stanza)); ArrayAdd(to_delete, StrDuplicate(stanza));
} }
@ -134,18 +135,44 @@ ParseeFindDatastart(char *data)
} }
#include <StringStream.h> #include <StringStream.h>
typedef struct XMPPFlags {
bool quote;
} XMPPFlags;
static char * static char *
XMPPifyElement(XMLElement *elem) XMPPifyElement(HashMap *event, XMLElement *elem, XMPPFlags flags)
{ {
char *xepd = NULL, *tmp = NULL; char *xepd = NULL, *tmp = NULL;
size_t i; size_t i;
XMLElement *child; XMLElement *child;
char *reply_id = JsonValueAsString(
JsonGet(event, 4,
"content", "m.relates_to", "m.in_reply_to", "event_id"
));
char *room_id = JsonValueAsString(HashMapGet(event, "room_id"));
HashMap *referenced;
char *subxep; char *subxep;
#define Concat(strp) tmp = xepd; \ #define Concat(strp) do \
xepd = StrConcat(2, xepd, strp); \ { \
Free(tmp) size_t cidx; \
for (cidx = 0; cidx < strlen(strp); cidx++) \
{ \
char cch[2] = { strp[cidx], 0 }; \
char nch = *cch ? strp[cidx+1] : '\0'; \
bool c = *cch == '\n' && nch != '>'; \
if (c && flags.quote) \
{ \
tmp = xepd; \
xepd = StrConcat(2, xepd, "\n>"); \
Free(tmp); \
continue; \
} \
tmp = xepd; \
xepd = StrConcat(2, xepd, cch); \
Free(tmp); \
} \
} \
while (0)
switch (elem->type) switch (elem->type)
{ {
case XML_ELEMENT_DATA: case XML_ELEMENT_DATA:
@ -158,7 +185,7 @@ XMPPifyElement(XMLElement *elem)
for (i = 0; i < ArraySize(elem->children); i++) for (i = 0; i < ArraySize(elem->children); i++)
{ {
child = ArrayGet(elem->children, i); child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child); subxep = XMPPifyElement(event, child, flags);
Concat(subxep); Concat(subxep);
Free(subxep); Free(subxep);
@ -171,7 +198,7 @@ XMPPifyElement(XMLElement *elem)
for (i = 0; i < ArraySize(elem->children); i++) for (i = 0; i < ArraySize(elem->children); i++)
{ {
child = ArrayGet(elem->children, i); child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child); subxep = XMPPifyElement(event, child, flags);
Concat(subxep); Concat(subxep);
Free(subxep); Free(subxep);
@ -184,24 +211,45 @@ XMPPifyElement(XMLElement *elem)
for (i = 0; i < ArraySize(elem->children); i++) for (i = 0; i < ArraySize(elem->children); i++)
{ {
child = ArrayGet(elem->children, i); child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child); subxep = XMPPifyElement(event, child, flags);
Concat(subxep); Concat(subxep);
Free(subxep); Free(subxep);
} }
Concat("`"); Concat("`");
} }
else if (StrEquals(elem->name, "mx-reply"))
{
char *str;
referenced = ASFind(ParseeConfigGet(), room_id, reply_id);
str = JsonValueAsString(
JsonGet(referenced, 2, "content", "body")
);
if (!str)
{
JsonFree(referenced);
return xepd;
}
Concat(">");
flags.quote = true;
Concat(str);
flags.quote = false;
Concat("\n");
JsonFree(referenced);
}
else if (StrEquals(elem->name, "blockquote")) else if (StrEquals(elem->name, "blockquote"))
{ {
Concat(">"); Concat(">");
flags.quote = true;
for (i = 0; i < ArraySize(elem->children); i++) for (i = 0; i < ArraySize(elem->children); i++)
{ {
child = ArrayGet(elem->children, i); child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child); subxep = XMPPifyElement(event, child, flags);
Concat(subxep); Concat(subxep);
Free(subxep); Free(subxep);
} }
flags.quote = false;
Concat("\n"); Concat("\n");
} }
else if (StrEquals(elem->name, "br")) else if (StrEquals(elem->name, "br"))
@ -211,11 +259,12 @@ XMPPifyElement(XMLElement *elem)
for (i = 0; i < ArraySize(elem->children); i++) for (i = 0; i < ArraySize(elem->children); i++)
{ {
child = ArrayGet(elem->children, i); child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child); subxep = XMPPifyElement(event, child, flags);
Concat(subxep); Concat(subxep);
Free(subxep); Free(subxep);
} }
Concat("\n");
} }
else if (StrEquals(elem->name, "a")) else if (StrEquals(elem->name, "a"))
{ {
@ -224,7 +273,7 @@ XMPPifyElement(XMLElement *elem)
for (i = 0; i < ArraySize(elem->children); i++) for (i = 0; i < ArraySize(elem->children); i++)
{ {
child = ArrayGet(elem->children, i); child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child); subxep = XMPPifyElement(event, child, flags);
Concat(subxep); Concat(subxep);
Free(subxep); Free(subxep);
@ -238,7 +287,7 @@ XMPPifyElement(XMLElement *elem)
for (i = 0; i < ArraySize(elem->children); i++) for (i = 0; i < ArraySize(elem->children); i++)
{ {
child = ArrayGet(elem->children, i); child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child); subxep = XMPPifyElement(event, child, flags);
Concat(subxep); Concat(subxep);
Free(subxep); Free(subxep);
@ -254,6 +303,8 @@ ParseeXMPPify(HashMap *event)
char *cntr, *type, *format, *html; char *cntr, *type, *format, *html;
char *xepd = NULL, *tmp; char *xepd = NULL, *tmp;
XMLElement *elem; XMLElement *elem;
XMPPFlags flags;
if (!event) if (!event)
{ {
return NULL; return NULL;
@ -276,9 +327,10 @@ ParseeXMPPify(HashMap *event)
html = JsonValueAsString(JsonGet(event, 2, "content", "formatted_body")); html = JsonValueAsString(JsonGet(event, 2, "content", "formatted_body"));
html = StrConcat(3, "<html>", html, "</html>"); html = StrConcat(3, "<html>", html, "</html>");
elem = XMLDecode(StrStreamReader(html), true); elem = XMLCDecode(StrStreamReader(html), true, true);
xepd = XMPPifyElement(elem); flags.quote = false;
xepd = XMPPifyElement(event, elem, flags);
XMLFreeElement(elem); XMLFreeElement(elem);
Free(html); Free(html);

View file

@ -6,7 +6,7 @@
#include <string.h> #include <string.h>
XMLElement * XMLElement *
XMLDecode(Stream *stream, bool autofree) XMLCDecode(Stream *stream, bool autofree, bool html)
{ {
#define push(x) ArrayAdd(stack, x) #define push(x) ArrayAdd(stack, x)
#define pop(x) ArrayDelete(stack, ArraySize(stack) - 1) #define pop(x) ArrayDelete(stack, ArraySize(stack) - 1)
@ -45,7 +45,12 @@ XMLDecode(Stream *stream, bool autofree)
* going to be our top of the stack */ * going to be our top of the stack */
ret = top; ret = top;
} }
/* HACK!!! */
if (!StrEquals(event->element, "br") || !html)
{
push(top); push(top);
}
break; break;
case XML_LEXER_ELEM: case XML_LEXER_ELEM:
/* Create a new element that will populated. */ /* Create a new element that will populated. */

View file

@ -26,6 +26,9 @@ extern void ASPing(const ParseeConfig *);
* as. */ * as. */
extern void ASJoin(const ParseeConfig *, char *, char *); extern void ASJoin(const ParseeConfig *, char *, char *);
/* Finds an event from a room ID and event ID */
extern HashMap * ASFind(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 char * ASSend(const ParseeConfig *, char *, char *, char *, HashMap *); extern char * ASSend(const ParseeConfig *, char *, char *, char *, HashMap *);

View file

@ -56,7 +56,8 @@ typedef struct XMLElement {
} XMLElement; } XMLElement;
/* Decodes 1 element off a stream. */ /* Decodes 1 element off a stream. */
extern XMLElement * XMLDecode(Stream *stream, bool autofree); extern XMLElement * XMLCDecode(Stream *stream, bool autofree, bool html);
#define XMLDecode(stream, autofree) XMLCDecode(stream, autofree, false)
extern XMLElement * XMLCreateTag(char *name); extern XMLElement * XMLCreateTag(char *name);
extern XMLElement * XMLCreateText(char *data); extern XMLElement * XMLCreateText(char *data);