[MOD] Start separating Parsee functions more

This commit is contained in:
LDA 2024-08-19 20:25:00 +02:00
commit 1b62072a3a
12 changed files with 468 additions and 431 deletions

View file

@ -4,7 +4,6 @@
#include <Cytoplasm/Json.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Log.h>
#include <Cytoplasm/Sha.h>
#include <string.h>
#include <stdlib.h>

View file

@ -6,11 +6,9 @@
#include <Cytoplasm/Log.h>
#include <Cytoplasm/Str.h>
#include <string.h>
#include <stdlib.h>
#include <Routes.h>
#include <Glob.h>
#include <AS.h>
ParseeData *
@ -206,244 +204,7 @@ ParseeCleanup(void *datp)
DbListFree(chats);
Log(LOG_DEBUG, "Cleant up %d entries...", entries);
}
int
ParseeFindDatastart(char *data)
{
char *startline;
bool found = false;
if (!data)
{
return 0;
}
startline = data;
while (startline)
{
char *endline = strchr(startline, '\n');
if (*startline != '>')
{
found = true;
break;
}
startline = endline ? endline + 1 : NULL;
}
if (!found)
{
return 0;
}
return (int) (startline - data);
}
#include <StringStream.h>
typedef struct XMPPFlags {
bool quote;
} XMPPFlags;
static char *
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) do \
{ \
size_t cidx; \
size_t len = strp ? strlen(strp) : 0; \
for (cidx = 0; cidx < len; 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:
Concat(elem->data);
break;
case XML_ELEMENT_TAG:
if (StrEquals(elem->name, "b") || StrEquals(elem->name, "strong"))
{
Concat("*");
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
Concat("*");
}
else if (StrEquals(elem->name, "em"))
{
Concat("_");
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
Concat("_");
}
else if (StrEquals(elem->name, "code"))
{
Concat("`");
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
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(event, child, flags);
Concat(subxep);
Free(subxep);
}
flags.quote = false;
Concat("\n");
}
else if (StrEquals(elem->name, "br"))
{
Concat("\n");
/* HTML fucking SUCKS */
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
Concat("\n");
}
else if (StrEquals(elem->name, "a"))
{
char *href = HashMapGet(elem->attrs, "href");
Concat("(");
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
Concat(" points to ");
Concat(href);
Concat(" )");
}
else
{
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
}
break;
default:
break;
}
return xepd;
}
char *
ParseeXMPPify(HashMap *event)
{
char *type, *format, *html;
char *xepd = NULL;
XMLElement *elem;
XMPPFlags flags;
if (!event)
{
return NULL;
}
/* Check if it is a message event. */
type = JsonValueAsString(HashMapGet(event, "type"));
if (!StrEquals(type, "m.room.message"))
{
return NULL;
}
format = JsonValueAsString(JsonGet(event, 2, "content", "format"));
if (!StrEquals(format, "org.matrix.custom.html"))
{
/* Settle for the raw body instead. */
char *body = JsonValueAsString(JsonGet(event, 2, "content", "body"));
return StrDuplicate(body);
}
html = JsonValueAsString(JsonGet(event, 2, "content", "formatted_body"));
html = StrConcat(3, "<html>", html, "</html>");
elem = XMLCDecode(StrStreamReader(html), true, true);
flags.quote = false;
xepd = XMPPifyElement(event, elem, flags);
XMLFreeElement(elem);
Free(html);
return xepd;
}
void
ParseePushDMStanza(ParseeData *data, char *room_id, char *stanza_id, char *id, char *ev, char *sender)
{
@ -738,189 +499,3 @@ end:
return ret;
}
void
ParseeGlobalBan(ParseeData *data, char *glob, char *reason)
{
DbRef *ref;
HashMap *j, *obj;
if (!data || !glob)
{
return;
}
ref = DbLock(data->db, 1, "global_bans");
if (!ref)
{
ref = DbCreate(data->db, 1, "global_bans");
}
j = DbJson(ref);
obj = HashMapCreate();
if (reason)
{
HashMapSet(obj, "reason", JsonValueString(reason));
}
HashMapSet(obj, "date", JsonValueInteger(UtilTsMillis()));
JsonValueFree(HashMapSet(j, glob, JsonValueObject(obj)));
DbUnlock(data->db, ref);
}
bool
ParseeManageBan(ParseeData *data, char *user, char *room)
{
DbRef *ref;
HashMap *j;
char *key;
JsonValue *val;
bool banned = false , matches = false;
if (!data || !user)
{
return false;
}
ref = DbLockIntent(data->db, DB_HINT_READONLY, 1, "global_bans");
j = DbJson(ref);
while (HashMapIterate(j, &key, (void **) &val))
{
HashMap *obj = JsonValueAsObject(val);
if (matches)
{
continue;
}
if (GlobMatches(key, user))
{
banned = true;
matches = true;
if (room)
{
/* TODO: Use the object to set the reason */
ASBan(data->config, room, user);
(void) obj;
}
}
}
DbUnlock(data->db, ref);
return banned;
}
char *
ParseeStringifyDate(uint64_t millis)
{
uint64_t rest = millis;
uint64_t hours, minutes, seconds;
char *hs, *ms, *ss, *out;
hours = rest / (1 HOURS);
rest = rest % (1 HOURS);
minutes = rest / (1 MINUTES);
rest = rest % (1 MINUTES);
seconds = rest / (1 SECONDS);
hs = StrInt(hours);
ms = StrInt(minutes);
ss = StrInt(seconds);
out = StrConcat(8,
hours ? hs : "",
hours ? " hours" : "",
(hours && minutes) ? ", " : "",
minutes ? ms : "",
minutes ? " minutes" : "",
(minutes && seconds) ? ", " : "",
seconds ? ss : "",
seconds ? " seconds" : ""
);
Free(hs);
Free(ms);
Free(ss);
return out;
}
void
ParseeAchievement(const char *func, const char *msg, bool die)
{
Log(LOG_ERR, "=========== Achievement GET! ===========");
Log(LOG_ERR, "%s: %s.", func, msg);
Log(LOG_ERR, "THIS IS, LET'S SAY, NOT GOOD, AND A SIGN OF ");
Log(LOG_ERR, "A PROGRAMMER ERROR. PLEASE KILLALL -9 PARSEE.");
Log(LOG_ERR, "");
Log(LOG_ERR, "YOU, HOWEVER, GET TO WIN AN AWARD FOR THIS.");
Log(LOG_ERR, "I AM SIMPLY JEALOUS OF YOU GETTING SUCH A ");
Log(LOG_ERR, "GOOD ERROR MESSAGE.");
Log(LOG_ERR, "=========== Achievement GET! ===========");
if (die)
{
abort();
}
}
char *
ParseeGenerateMTO(char *common_id)
{
char *matrix_to;
if (!common_id)
{
return NULL;
}
common_id = HttpUrlEncode(common_id);
matrix_to = StrConcat(2, "https://matrix.to/#/", common_id);
Free(common_id);
return matrix_to;
}
void
ParseeGenerateHelp(const Argument *list)
{
if (!list)
{
return;
}
while (!list->end)
{
char *str = list->value_req ?
StrConcat(3, " [", list->value_descr, "]") :
StrDuplicate("");
Log(LOG_INFO, "-%c%s", list->argument, str);
LogConfigIndent(LogConfigGlobal());
Log(LOG_INFO, "%s", list->description);
LogConfigUnindent(LogConfigGlobal());
list++;
Free(str);
}
return;
}
char *
ParseeGenerateGetopt(const Argument *list)
{
char *ret = NULL, *tmp = NULL;
if (!list)
{
return NULL;
}
while (!list->end)
{
char buffer[3] = {
list->argument, list->value_req ? ':' : '\0',
'\0'
};
tmp = ret;
ret = StrConcat(2, ret, buffer);
Free(tmp);
list++;
}
return ret;
}

View file

@ -3,7 +3,6 @@
#include <Cytoplasm/HashMap.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Sha.h>
#include <pthread.h>
static pthread_mutex_t nick_lock;

View file

@ -4,7 +4,6 @@
#include <Cytoplasm/Json.h>
#include <Cytoplasm/Util.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Sha.h>
#include <Cytoplasm/Log.h>
#include <string.h>

View file

@ -0,0 +1,26 @@
#include <Parsee.h>
#include <Cytoplasm/Log.h>
#include <stdlib.h>
void
ParseeAchievement(const char *func, const char *msg, bool die)
{
Log(LOG_ERR, "=========== Achievement GET! ===========");
Log(LOG_ERR, "%s: %s.", func, msg);
Log(LOG_ERR, "THIS IS, LET'S SAY, NOT GOOD, AND A SIGN OF ");
Log(LOG_ERR, "A PROGRAMMER ERROR. PLEASE KILLALL -9 PARSEE.");
Log(LOG_ERR, "");
Log(LOG_ERR, "YOU, HOWEVER, GET TO WIN AN AWARD FOR THIS.");
Log(LOG_ERR, "I AM SIMPLY JEALOUS OF YOU GETTING SUCH A ");
Log(LOG_ERR, "GOOD ERROR MESSAGE.");
Log(LOG_ERR, "=========== Achievement GET! ===========");
if (die)
{
abort();
}
}

View file

@ -0,0 +1,53 @@
#include <Parsee.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Log.h>
#include <Cytoplasm/Str.h>
void
ParseeGenerateHelp(const Argument *list)
{
if (!list)
{
return;
}
while (!list->end)
{
char *str = list->value_req ?
StrConcat(3, " [", list->value_descr, "]") :
StrDuplicate("");
Log(LOG_INFO, "-%c%s", list->argument, str);
LogConfigIndent(LogConfigGlobal());
Log(LOG_INFO, "%s", list->description);
LogConfigUnindent(LogConfigGlobal());
list++;
Free(str);
}
return;
}
char *
ParseeGenerateGetopt(const Argument *list)
{
char *ret = NULL, *tmp = NULL;
if (!list)
{
return NULL;
}
while (!list->end)
{
char buffer[3] = {
list->argument, list->value_req ? ':' : '\0',
'\0'
};
tmp = ret;
ret = StrConcat(2, ret, buffer);
Free(tmp);
list++;
}
return ret;
}

View file

@ -0,0 +1,237 @@
#include <Parsee.h>
#include <Cytoplasm/HashMap.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Http.h>
#include <Cytoplasm/Json.h>
#include <Cytoplasm/Str.h>
#include <stdbool.h>
#include <string.h>
#include <StringStream.h>
#include <XML.h>
#include <AS.h>
typedef struct XMPPFlags {
bool quote;
} XMPPFlags;
static char *
XMPPifyElement(HashMap *event, XMLElement *elem, XMPPFlags flags)
{
char *xepd = NULL, *tmp = NULL;
size_t i;
XMLElement *child;
char *reply_id = GrabString(
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) do \
{ \
size_t cidx; \
size_t len = strp ? strlen(strp) : 0; \
for (cidx = 0; cidx < len; 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:
Concat(elem->data);
break;
case XML_ELEMENT_TAG:
if (StrEquals(elem->name, "b") || StrEquals(elem->name, "strong"))
{
Concat("*");
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
Concat("*");
}
else if (StrEquals(elem->name, "em"))
{
Concat("_");
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
Concat("_");
}
else if (StrEquals(elem->name, "code"))
{
Concat("`");
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
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(event, child, flags);
Concat(subxep);
Free(subxep);
}
flags.quote = false;
Concat("\n");
}
else if (StrEquals(elem->name, "br"))
{
Concat("\n");
/* HTML fucking SUCKS */
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
Concat("\n");
}
else if (StrEquals(elem->name, "a"))
{
char *href = HashMapGet(elem->attrs, "href");
Concat("(");
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
Concat(" points to ");
Concat(href);
Concat(" )");
}
else
{
for (i = 0; i < ArraySize(elem->children); i++)
{
child = ArrayGet(elem->children, i);
subxep = XMPPifyElement(event, child, flags);
Concat(subxep);
Free(subxep);
}
}
break;
default:
break;
}
return xepd;
}
char *
ParseeXMPPify(HashMap *event)
{
char *type, *format, *html;
char *xepd = NULL;
XMLElement *elem;
XMPPFlags flags;
if (!event)
{
return NULL;
}
/* Check if it is a message event. */
type = JsonValueAsString(HashMapGet(event, "type"));
if (!StrEquals(type, "m.room.message"))
{
return NULL;
}
format = JsonValueAsString(JsonGet(event, 2, "content", "format"));
if (!StrEquals(format, "org.matrix.custom.html"))
{
/* Settle for the raw body instead. */
char *body = JsonValueAsString(JsonGet(event, 2, "content", "body"));
return StrDuplicate(body);
}
html = JsonValueAsString(JsonGet(event, 2, "content", "formatted_body"));
html = StrConcat(3, "<html>", html, "</html>");
elem = XMLCDecode(StrStreamReader(html), true, true);
flags.quote = false;
xepd = XMPPifyElement(event, elem, flags);
XMLFreeElement(elem);
Free(html);
return xepd;
}
char *
ParseeGenerateMTO(char *common_id)
{
char *matrix_to;
if (!common_id)
{
return NULL;
}
common_id = HttpUrlEncode(common_id);
matrix_to = StrConcat(2, "https://matrix.to/#/", common_id);
Free(common_id);
return matrix_to;
}

75
src/Parsee/Utils/Nofly.c Normal file
View file

@ -0,0 +1,75 @@
#include <Parsee.h>
#include <Cytoplasm/Json.h>
#include <Cytoplasm/Util.h>
#include <Glob.h>
#include <AS.h>
void
ParseeGlobalBan(ParseeData *data, char *glob, char *reason)
{
DbRef *ref;
HashMap *j, *obj;
if (!data || !glob)
{
return;
}
ref = DbLock(data->db, 1, "global_bans");
if (!ref)
{
ref = DbCreate(data->db, 1, "global_bans");
}
j = DbJson(ref);
obj = HashMapCreate();
if (reason)
{
HashMapSet(obj, "reason", JsonValueString(reason));
}
HashMapSet(obj, "date", JsonValueInteger(UtilTsMillis()));
JsonValueFree(HashMapSet(j, glob, JsonValueObject(obj)));
DbUnlock(data->db, ref);
}
bool
ParseeManageBan(ParseeData *data, char *user, char *room)
{
DbRef *ref;
HashMap *j;
char *key;
JsonValue *val;
bool banned = false , matches = false;
if (!data || !user)
{
return false;
}
ref = DbLockIntent(data->db, DB_HINT_READONLY, 1, "global_bans");
j = DbJson(ref);
while (HashMapIterate(j, &key, (void **) &val))
{
HashMap *obj = JsonValueAsObject(val);
if (matches)
{
continue;
}
if (GlobMatches(key, user))
{
banned = true;
matches = true;
if (room)
{
/* TODO: Use the object to set the reason */
ASBan(data->config, room, user);
(void) obj;
}
}
}
DbUnlock(data->db, ref);
return banned;
}

77
src/Parsee/Utils/String.c Normal file
View file

@ -0,0 +1,77 @@
#include <Parsee.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Str.h>
#include <stdbool.h>
#include <string.h>
int
ParseeFindDatastart(char *data)
{
char *startline;
bool found = false;
if (!data)
{
return 0;
}
startline = data;
while (startline)
{
char *endline = strchr(startline, '\n');
if (*startline != '>')
{
found = true;
break;
}
startline = endline ? endline + 1 : NULL;
}
if (!found)
{
return 0;
}
return (int) (startline - data);
}
char *
ParseeStringifyDate(uint64_t millis)
{
uint64_t rest = millis;
uint64_t hours, minutes, seconds;
char *hs, *ms, *ss, *out;
hours = rest / (1 HOURS);
rest = rest % (1 HOURS);
minutes = rest / (1 MINUTES);
rest = rest % (1 MINUTES);
seconds = rest / (1 SECONDS);
hs = StrInt(hours);
ms = StrInt(minutes);
ss = StrInt(seconds);
out = StrConcat(8,
hours ? hs : "",
hours ? " hours" : "",
(hours && minutes) ? ", " : "",
minutes ? ms : "",
minutes ? " minutes" : "",
(minutes && seconds) ? ", " : "",
seconds ? ss : "",
seconds ? " seconds" : ""
);
Free(hs);
Free(ms);
Free(ss);
return out;
}

View file

@ -77,7 +77,6 @@ XMPPInitialiseCompStream(char *host, int port)
return comp;
}
#include <Cytoplasm/Sha.h>
static char *
ComputeHandshake(char *shared, char *stream)
{

View file

@ -3,7 +3,6 @@
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Log.h>
#include <Cytoplasm/Sha.h>
#include <Parsee.h>

View file

@ -13,7 +13,6 @@
#include <Cytoplasm/Util.h>
#include <Cytoplasm/Log.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Sha.h>
#include <StringStream.h>
#include <XMPPCommand.h>