[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);
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 *
ASGetName(const ParseeConfig *c, char *room, char *user)
{

View file

@ -9,6 +9,7 @@
#include <string.h>
#include <Routes.h>
#include <AS.h>
ParseeData *
ParseeInitData(XMPPComponent *comp)
@ -82,7 +83,7 @@ ParseeCleanup(void *datp)
uint64_t age = JsonValueAsInteger(HashMapGet(obj, "age"));
uint64_t dur = ts - age;
if ((dur > (5 MINUTES)))
if ((dur > (30 MINUTES)))
{
ArrayAdd(to_delete, StrDuplicate(stanza));
}
@ -134,18 +135,44 @@ ParseeFindDatastart(char *data)
}
#include <StringStream.h>
typedef struct XMPPFlags {
bool quote;
} XMPPFlags;
static char *
XMPPifyElement(XMLElement *elem)
XMPPifyElement(HashMap *event, XMLElement *elem, XMPPFlags flags)
{
char *xepd = NULL, *tmp = NULL;
size_t i;
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;
#define Concat(strp) tmp = xepd; \
xepd = StrConcat(2, xepd, strp); \
Free(tmp)
#define Concat(strp) do \
{ \
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)
{
case XML_ELEMENT_DATA:
@ -158,7 +185,7 @@ XMPPifyElement(XMLElement *elem)
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
@ -171,7 +198,7 @@ XMPPifyElement(XMLElement *elem)
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
@ -184,24 +211,45 @@ XMPPifyElement(XMLElement *elem)
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
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"))
{
Concat(">");
flags.quote = true;
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
flags.quote = false;
Concat("\n");
}
else if (StrEquals(elem->name, "br"))
@ -211,11 +259,12 @@ XMPPifyElement(XMLElement *elem)
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
Concat("\n");
}
else if (StrEquals(elem->name, "a"))
{
@ -224,7 +273,7 @@ XMPPifyElement(XMLElement *elem)
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
@ -238,7 +287,7 @@ XMPPifyElement(XMLElement *elem)
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(child);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
@ -254,6 +303,8 @@ ParseeXMPPify(HashMap *event)
char *cntr, *type, *format, *html;
char *xepd = NULL, *tmp;
XMLElement *elem;
XMPPFlags flags;
if (!event)
{
return NULL;
@ -276,9 +327,10 @@ ParseeXMPPify(HashMap *event)
html = JsonValueAsString(JsonGet(event, 2, "content", "formatted_body"));
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);
Free(html);

View file

@ -6,7 +6,7 @@
#include <string.h>
XMLElement *
XMLDecode(Stream *stream, bool autofree)
XMLCDecode(Stream *stream, bool autofree, bool html)
{
#define push(x) ArrayAdd(stack, x)
#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 */
ret = top;
}
/* HACK!!! */
if (!StrEquals(event->element, "br") || !html)
{
push(top);
}
break;
case XML_LEXER_ELEM:
/* Create a new element that will populated. */

View file

@ -26,6 +26,9 @@ extern void ASPing(const ParseeConfig *);
* as. */
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.
* Said body is freed during the function's execution. */
extern char * ASSend(const ParseeConfig *, char *, char *, char *, HashMap *);

View file

@ -56,7 +56,8 @@ typedef struct XMLElement {
} XMLElement;
/* 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 * XMLCreateText(char *data);