mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 12:15:12 +00:00
[ADD/MOD] Cleanup cmd, change Matrix user format
This commit is contained in:
parent
9e5e741989
commit
91d373addb
13 changed files with 217 additions and 77 deletions
|
|
@ -35,13 +35,15 @@ TODO
|
|||
TODO
|
||||
|
||||
## TODOS
|
||||
- Mess with Cytoplasm to make it have support for something like Berkeley DB as
|
||||
an *optional* dependency. This should increase reliability and speed for anyone.
|
||||
- Mess with Cytoplasm to make it have support for something like LMDB as an
|
||||
*optional* dependency. This should increase reliability and speed for anyone.
|
||||
- Nesting might be an issue we'll need to deal with. libdb and Berkley DB
|
||||
seem to lack support for them. If we can shove entries at specific indices,
|
||||
we _might_ just manage to get some system that can at least emulate that,
|
||||
and hopefully be reasonably faster than the filesystem, with some added
|
||||
reliability.
|
||||
- Starting a DM from XMPP to a Matrix user(and also get rid of the '?'-syntax and
|
||||
use another invalid Matrix char/valid XMPP char ('$'?) for escaped)
|
||||
|
||||
- PROPER FUCKING AVATARS
|
||||
XEP-0084 IS THE WORST PIECE OF SHIT KNOWN TO MAN. If any Jabberbros want to
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ For future XEPs:
|
|||
- https://xmpp.org/extensions/xep-0449.html
|
||||
Stickers are great. Matrix and XMPP somewhat has support for them, so
|
||||
might be a nice-to-have, and also to push over XMPP support.
|
||||
A minor issue with that is pack management. XMPP requires a pack field
|
||||
which is used along PEP, it seems, and meanwhile Matrix has ''support''
|
||||
for packs too, tracking them is between "annoyance" and "yeah, no.".
|
||||
- https://xmpp.org/extensions/xep-0050.html
|
||||
Ad-hoc commands that bridge maintainers can deal with XMPP-style are
|
||||
also a nice to have.
|
||||
|
|
@ -46,6 +49,7 @@ THESE I WANT TO SEND THEM A NICE, BRIGHT GIFT:
|
|||
Not XEPs, but ideas that _needs_ to be added:
|
||||
- "GIVE THE PUPPETS APPROPRIATE PLS/ROLES" - Hydro/t4d
|
||||
"also it [Bifrost] doesn't respect voice either"
|
||||
- Standalone/Static Parsee, ideally as small as it can be(if not as APE).
|
||||
- https://www.youtube.com/watch?v=InL414iDZmY
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,13 @@ static HttpServer *server = NULL;
|
|||
static pthread_t xmpp_thr;
|
||||
static XMPPComponent *jabber = NULL;
|
||||
|
||||
static volatile uint64_t start;
|
||||
uint64_t
|
||||
ParseeUptime(void)
|
||||
{
|
||||
return UtilTsMillis() - start;
|
||||
}
|
||||
|
||||
int
|
||||
Main(void)
|
||||
{
|
||||
|
|
@ -30,6 +37,8 @@ Main(void)
|
|||
Stream *yaml;
|
||||
Cron *cron = NULL;
|
||||
|
||||
start = UtilTsMillis();
|
||||
|
||||
memset(&conf, 0, sizeof(conf));
|
||||
Log(LOG_INFO,
|
||||
"%s - v%s (Cytoplasm %s)",
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ ParseeMemberHandler(ParseeData *data, HashMap *event)
|
|||
XMPPJoinMUC(data->jabber, jid, rev);
|
||||
Free(rev);
|
||||
Free(muc);
|
||||
|
||||
/* TODO: XEP-0084 magic to advertise a new avatar if possible. */
|
||||
}
|
||||
Free(jid);
|
||||
Free(chat_id);
|
||||
|
|
|
|||
|
|
@ -824,3 +824,40 @@ ParseeManageBan(ParseeData *data, char *user, char *room)
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,22 +39,6 @@ ParseeIsPuppet(const ParseeConfig *conf, char *user)
|
|||
* room. */
|
||||
return flag;
|
||||
}
|
||||
bool
|
||||
ParseeIsJabberPuppet(const ParseeConfig *config, char *jid)
|
||||
{
|
||||
char *resource;
|
||||
bool ret;
|
||||
if (!config || !jid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
resource = ParseeGetResource(jid);
|
||||
ret = *resource == '%';
|
||||
Free(resource);
|
||||
|
||||
return ret;
|
||||
}
|
||||
char *
|
||||
ParseeDecodeJID(char *str, char term)
|
||||
{
|
||||
|
|
@ -155,6 +139,7 @@ ParseeDecodeLocalMUC(const ParseeConfig *c, char *alias)
|
|||
return ParseeDecodeJID(data_start, ':');
|
||||
}
|
||||
|
||||
static const char *HEX = "0123456789abcdef";
|
||||
char *
|
||||
ParseeEncodeJID(const ParseeConfig *c, char *jid, bool trim)
|
||||
{
|
||||
|
|
@ -168,7 +153,6 @@ ParseeEncodeJID(const ParseeConfig *c, char *jid, bool trim)
|
|||
ret = StrConcat(2, c->namespace_base, "_l_");
|
||||
for (i = 0; i < strlen(jid); i++)
|
||||
{
|
||||
const char *HEX = "0123456789abcdef";
|
||||
char cpy = jid[i];
|
||||
char cs[4] = { 0 };
|
||||
cs[0] = cpy;
|
||||
|
|
@ -237,60 +221,75 @@ char *
|
|||
ParseeEncodeMXID(char *mxid)
|
||||
{
|
||||
char *ret;
|
||||
size_t i;
|
||||
size_t i, j;
|
||||
if (!mxid)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
ret = Malloc(strlen(mxid) + 1);
|
||||
for (i = 0; i < strlen(mxid) + 1; i++)
|
||||
|
||||
/* Worst case scenario of 3-bytes the char */
|
||||
ret = Malloc(strlen(mxid) * 3 + 1);
|
||||
for (i = 0, j = 0; i < strlen(mxid); i++)
|
||||
{
|
||||
char src = mxid[i];
|
||||
|
||||
/* TODO: More robust system */
|
||||
if (src == '@')
|
||||
if (src <= 0x20 ||
|
||||
(src == '"' || src == '&' ||
|
||||
src == '\'' || src == '/' ||
|
||||
src == ':' || src == '<' ||
|
||||
src == '>' || src == '@' ||
|
||||
src == 0x7F))
|
||||
{
|
||||
src = '%';
|
||||
ret[j++] = '?';
|
||||
ret[j++] = HEX[(src & 0xF0) >> 4];
|
||||
ret[j++] = HEX[(src & 0x0F) >> 0];
|
||||
continue;
|
||||
}
|
||||
else if (src == ':')
|
||||
{
|
||||
src = '=';
|
||||
}
|
||||
ret[i] = src;
|
||||
ret[j++] = src;
|
||||
}
|
||||
ret[j] = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
char *
|
||||
ParseeDecodeMXID(char *mxid)
|
||||
{
|
||||
char *ret;
|
||||
size_t i;
|
||||
char *out = NULL;
|
||||
if (!mxid)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
ret = Malloc(strlen(mxid) + 1);
|
||||
for (i = 0; i < strlen(mxid) + 1; i++)
|
||||
#define Okay(c) ((c) && (c != '@'))
|
||||
while (Okay(*mxid))
|
||||
{
|
||||
char src = mxid[i];
|
||||
if (src == '%')
|
||||
char c = *mxid;
|
||||
char buf[3] = { 0 };
|
||||
char *tmp;
|
||||
if (c == '?' && Okay(*(mxid + 1)) && Okay(*(mxid + 2)))
|
||||
{
|
||||
src = '@';
|
||||
}
|
||||
else if (src == '=')
|
||||
{
|
||||
src = ':';
|
||||
}
|
||||
else if (src == '@')
|
||||
{
|
||||
ret[i] = '\0';
|
||||
break;
|
||||
}
|
||||
ret[i] = src;
|
||||
}
|
||||
mxid++;
|
||||
|
||||
return ret;
|
||||
memcpy(buf, mxid, 2);
|
||||
buf[0] = strtol(buf, NULL, 16);
|
||||
buf[1] = '\0';
|
||||
|
||||
tmp = StrConcat(2, out, buf);
|
||||
Free(out);
|
||||
out = tmp;
|
||||
|
||||
mxid += 2;
|
||||
continue;
|
||||
}
|
||||
memcpy(buf, mxid, 1);
|
||||
tmp = StrConcat(2, out, buf);
|
||||
Free(out);
|
||||
out = tmp;
|
||||
|
||||
mxid++;
|
||||
}
|
||||
#undef Okay
|
||||
return out;
|
||||
}
|
||||
char *
|
||||
ParseeGetDMID(char *mxid, char *jid)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ struct XMPPCommand {
|
|||
XMPPCmdCallback callback;
|
||||
char *node, *name;
|
||||
|
||||
char *form_instruction;
|
||||
char *form_title;
|
||||
|
||||
/* TODO: On-the-fly generation of options */
|
||||
Array *options;
|
||||
};
|
||||
|
||||
|
|
@ -25,12 +29,34 @@ XMPPBasicCmd(char *node, char *name, XMPPCmdCallback callback_funct)
|
|||
cmd->callback = callback_funct;
|
||||
cmd->node = StrDuplicate(node);
|
||||
cmd->name = StrDuplicate(name);
|
||||
cmd->form_instruction = NULL;
|
||||
cmd->form_title = NULL;
|
||||
|
||||
/* No options -> no form required */
|
||||
cmd->options = NULL;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
void
|
||||
XMPPSetFormTitle(XMPPCommand *cmd, char *title)
|
||||
{
|
||||
if (!cmd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Free(cmd->form_title);
|
||||
cmd->form_title = StrDuplicate(title);
|
||||
}
|
||||
void
|
||||
XMPPSetFormInstruction(XMPPCommand *cmd, char *instruction)
|
||||
{
|
||||
if (!cmd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Free(cmd->form_instruction);
|
||||
cmd->form_instruction = StrDuplicate(instruction);
|
||||
}
|
||||
void
|
||||
XMPPFreeCommand(XMPPCommand *cmd)
|
||||
{
|
||||
|
|
@ -47,6 +73,8 @@ XMPPFreeCommand(XMPPCommand *cmd)
|
|||
}
|
||||
ArrayFree(cmd->options);
|
||||
|
||||
XMPPSetFormInstruction(cmd, NULL);
|
||||
XMPPSetFormTitle(cmd, NULL);
|
||||
Free(cmd->node);
|
||||
Free(cmd->name);
|
||||
Free(cmd);
|
||||
|
|
@ -80,6 +108,25 @@ XMPPFormifyCommand(XMPPCommand *cmd)
|
|||
x = XMLCreateTag("x");
|
||||
XMLAddAttr(x, "xmlns", "jabber:x:data");
|
||||
XMLAddAttr(x, "type", "form");
|
||||
|
||||
if (cmd->form_title)
|
||||
{
|
||||
XMLElement *instr_xml, *instr_txt;
|
||||
|
||||
instr_xml = XMLCreateTag("title");
|
||||
instr_txt = XMLCreateText(cmd->form_title);
|
||||
XMLAddChild(instr_xml, instr_txt);
|
||||
XMLAddChild(x, instr_xml);
|
||||
}
|
||||
if (cmd->form_instruction)
|
||||
{
|
||||
XMLElement *instr_xml, *instr_txt;
|
||||
|
||||
instr_xml = XMLCreateTag("instructions");
|
||||
instr_txt = XMLCreateText(cmd->form_instruction);
|
||||
XMLAddChild(instr_xml, instr_txt);
|
||||
XMLAddChild(x, instr_xml);
|
||||
}
|
||||
/* TODO: Other fields */
|
||||
|
||||
for (i = 0; i < ArraySize(cmd->options); i++)
|
||||
|
|
@ -117,23 +164,6 @@ XMPPExecuteCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from, XMLEleme
|
|||
cmd->callback(m, from, form, to);
|
||||
}
|
||||
|
||||
void
|
||||
XMPPShoveOptions(XMPPCommand *cmd, XMLElement *form)
|
||||
{
|
||||
size_t i;
|
||||
if (!cmd || !form)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ArraySize(cmd->options); i++)
|
||||
{
|
||||
XMPPOption *opt = ArrayGet(cmd->options, i);
|
||||
XMLElement *xml = XMPPOptionToXML(opt);
|
||||
|
||||
XMLAddChild(form, xml);
|
||||
}
|
||||
}
|
||||
bool
|
||||
XMPPVerifyForm(XMPPCommand *cmd, XMLElement *form)
|
||||
{
|
||||
|
|
@ -157,7 +187,7 @@ XMPPVerifyForm(XMPPCommand *cmd, XMLElement *form)
|
|||
/* Required field not found; die. */
|
||||
return false;
|
||||
}
|
||||
/* TODO */
|
||||
/* TODO: Verify type, array membership, uniqueness, etc... */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
|
|||
{
|
||||
XMLElement *actions = XMLCreateTag("actions");
|
||||
XMLElement *completed = XMLCreateTag("complete");
|
||||
XMLElement *x = XMLCreateTag("x");
|
||||
XMLElement *x;
|
||||
XMLAddChild(actions, completed);
|
||||
|
||||
session_id = XMPPRegisterSession(m, to, from, node);
|
||||
|
|
@ -271,9 +271,7 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
|
|||
XMLAddChild(command_xml, actions);
|
||||
XMLAddChild(iq, command_xml);
|
||||
|
||||
XMLAddAttr(x, "xmlns", "jabber:x:data");
|
||||
XMLAddAttr(x, "type", "form");
|
||||
XMPPShoveOptions(cmd, x);
|
||||
x = XMPPFormifyCommand(cmd);
|
||||
XMLAddChild(command_xml, x);
|
||||
|
||||
pthread_mutex_lock(&jabber->write_lock);
|
||||
|
|
@ -286,6 +284,11 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
|
|||
}
|
||||
|
||||
/* Doesn't need to be freed, as it lives with m. */
|
||||
|
||||
/* TODO: I've noticed memory leakages around here with a
|
||||
* StrDuplicate'd session ID. I think StrDuplicate should
|
||||
* just "rat out" the original source in cases of leaks
|
||||
* like this, maybe with extra data beyond the NULL-terminator */
|
||||
session_id = XMPPRegisterSession(m, to, from, node);
|
||||
|
||||
/* No forms, we good. */
|
||||
|
|
|
|||
|
|
@ -175,6 +175,8 @@ XMPPOptionToXML(XMPPOption *opt)
|
|||
data = XMLCreateText(opt->desc);
|
||||
XMLAddChild(desc, data);
|
||||
XMLAddChild(elem, desc);
|
||||
|
||||
XMLAddAttr(elem, "label", opt->desc);
|
||||
}
|
||||
|
||||
if (opt->type == XMPP_OPTION_LIST)
|
||||
|
|
|
|||
32
src/XMPPCommands/Cleanup.c
Normal file
32
src/XMPPCommands/Cleanup.c
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#include <Cytoplasm/HashMap.h>
|
||||
#include <Cytoplasm/Memory.h>
|
||||
#include <Cytoplasm/Json.h>
|
||||
#include <Cytoplasm/Util.h>
|
||||
#include <Cytoplasm/Str.h>
|
||||
#include <Cytoplasm/Log.h>
|
||||
|
||||
#include <XMPPFormTool.h>
|
||||
#include <XMPPCommand.h>
|
||||
#include <Parsee.h>
|
||||
#include <XMPP.h>
|
||||
#include <XML.h>
|
||||
|
||||
void
|
||||
CleanCallback(XMPPCommandManager *m, char *from, XMLElement *form, XMLElement *out)
|
||||
{
|
||||
ParseeData *data = XMPPGetManagerCookie(m);
|
||||
char *trimmed = ParseeTrimJID(from);
|
||||
|
||||
if (!ParseeIsAdmin(data, trimmed))
|
||||
{
|
||||
SetNote("error", "User is not authorised to execute command.");
|
||||
|
||||
Free(trimmed);
|
||||
return;
|
||||
}
|
||||
Free(trimmed);
|
||||
|
||||
ParseeCleanup(data);
|
||||
/* TODO: Cleanup old sessions? */
|
||||
SetNote("info", "Parsee data was sucessfully cleant up.");
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ StatusCallback(XMPPCommandManager *m, char *from, XMLElement *form, XMLElement *
|
|||
size_t gb = mb >> 10;
|
||||
size_t min = gb ? gb : (mb ? mb : (kb ? kb : alloc));
|
||||
char *unit = gb ? "GB" : (mb ? "MB" : (kb ? "KB" : "B"));
|
||||
|
||||
XMLElement *x;
|
||||
XMLElement *title, *txt;
|
||||
|
||||
|
|
@ -52,6 +53,7 @@ StatusCallback(XMPPCommandManager *m, char *from, XMLElement *form, XMLElement *
|
|||
/* Report */
|
||||
Report("mem-alloc", "Heap allocated with Cytoplasm");
|
||||
Report("xml-congest", "Unprocessed stanzas(congestion)");
|
||||
Report("uptime", "Parsee uptime");
|
||||
|
||||
/* Set */
|
||||
BeginItem();
|
||||
|
|
@ -59,13 +61,16 @@ StatusCallback(XMPPCommandManager *m, char *from, XMLElement *form, XMLElement *
|
|||
char *min_str = StrInt(min);
|
||||
char *congest = StrInt(ParseeCongestion());
|
||||
char *alloc = StrConcat(3, min_str, " ", unit);
|
||||
char *up = ParseeStringifyDate(ParseeUptime());
|
||||
|
||||
SetField("mem-alloc", alloc);
|
||||
SetField("xml-congest", congest);
|
||||
SetField("uptime", up);
|
||||
|
||||
Free(congest);
|
||||
Free(min_str);
|
||||
Free(alloc);
|
||||
Free(up);
|
||||
}
|
||||
EndItem();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ typedef struct ParseeData {
|
|||
#define GrabObject(obj, ...) JsonValueAsObject(JsonGet(obj, __VA_ARGS__))
|
||||
#define GrabArray(obj, ...) JsonValueAsArray(JsonGet(obj, __VA_ARGS__))
|
||||
|
||||
/* Milliseconds to UNIT macros, to be used like 30 SECONDS and 1 MINUTE
|
||||
/* Milliseconds to UNIT macros, to be used like 30 SECONDS and 1 MINUTES
|
||||
* in timestamps */
|
||||
#define SECONDS * 1000
|
||||
#define MINUTES * 60 SECONDS
|
||||
|
|
@ -90,9 +90,6 @@ extern void ParseeEventHandler(ParseeData *, HashMap *);
|
|||
/* Verifies if a user is a Parsee puppet user. */
|
||||
extern bool ParseeIsPuppet(const ParseeConfig *, char *);
|
||||
|
||||
/* Verifies if a user is a Parsee puppet user on XMPP. */
|
||||
extern bool ParseeIsJabberPuppet(const ParseeConfig *, char *);
|
||||
|
||||
/* Decodes a local JID for a user into a string. */
|
||||
extern char * ParseeDecodeLocalJID(const ParseeConfig *, char *);
|
||||
|
||||
|
|
@ -230,4 +227,10 @@ extern bool ParseeVerifyDMStanza(ParseeData *data, char *room_id, char *id);
|
|||
|
||||
/* Checks if any user is an admin */
|
||||
extern bool ParseeIsAdmin(ParseeData *data, char *user);
|
||||
|
||||
/* Measures Parsee's overall uptime */
|
||||
extern uint64_t ParseeUptime(void);
|
||||
|
||||
/* Turns a date into a nice "X minutes, Y seconds" string */
|
||||
extern char * ParseeStringifyDate(uint64_t millis);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ extern void XMPPAddOption(XMPPCommand *cmd, XMPPOption *opt);
|
|||
extern XMLElement * XMPPFormifyCommand(XMPPCommand *cmd);
|
||||
extern char * XMPPGetCommandNode(XMPPCommand *cmd);
|
||||
extern char * XMPPGetCommandDesc(XMPPCommand *cmd);
|
||||
extern void XMPPSetFormInstruction(XMPPCommand *cmd, char *instruction);
|
||||
extern void XMPPSetFormTitle(XMPPCommand *cmd, char *title);
|
||||
extern bool XMPPCommandRequiresForm(XMPPCommand *cmd);
|
||||
extern void XMPPExecuteCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from, XMLElement *to, XMLElement *form);
|
||||
|
||||
|
|
@ -51,7 +53,6 @@ extern bool XMPPIsOptionRequired(XMPPOption *opt);
|
|||
extern char * XMPPOptionVar(XMPPOption *opt);
|
||||
|
||||
extern XMLElement * XMPPOptionToXML(XMPPOption *opt);
|
||||
extern void XMPPShoveOptions(XMPPCommand *cmd, XMLElement *form);
|
||||
|
||||
extern void XMPPFreeOption(XMPPOption *opt);
|
||||
extern void XMPPFreeCommand(XMPPCommand *cmd);
|
||||
|
|
@ -92,11 +93,16 @@ extern bool XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeD
|
|||
/* --------------------------------- COMMANDS --------------------------------- */
|
||||
#define XMPPCOMMANDS \
|
||||
XMPP_COMMAND(StatusCallback, "stats", "Get Parsee statistics", {}) \
|
||||
XMPP_COMMAND(CleanCallback, "clean", "Cleanup temporary Parsee data", {}) \
|
||||
XMPP_COMMAND(AdminsCallback, "admin", "Get Parsee admin list", {}) \
|
||||
XMPP_COMMAND(NoflyCallback, "nofly", "Get Parsee nofly list", {}) \
|
||||
XMPP_COMMAND(AddAdminCallback, "add-admin", "Adds glob as admin", { \
|
||||
XMPPOption *glob = XMPPCreateText(true, "glob", ""); \
|
||||
XMPPSetDescription(glob, "Glob pattern to set as admin"); \
|
||||
XMPPAddOption(cmd, glob); \
|
||||
\
|
||||
XMPPSetFormTitle(cmd, "Admin addition form"); \
|
||||
XMPPSetFormInstruction(cmd, "Select a glob pattern to add as an admin"); \
|
||||
}) \
|
||||
XMPP_COMMAND(AddNoflyCallback, "add-nofly", "Adds user to nofly", { \
|
||||
XMPPOption *entity = XMPPCreateText(true, "entity", ""); \
|
||||
|
|
@ -105,10 +111,16 @@ extern bool XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeD
|
|||
XMPPAddOption(cmd, entity); \
|
||||
XMPPSetDescription(reason, "Reason for the no-fly"); \
|
||||
XMPPAddOption(cmd, reason); \
|
||||
\
|
||||
XMPPSetFormTitle(cmd, "No-fly addition form"); \
|
||||
XMPPSetFormInstruction(cmd, "Select a glob pattern to add to the nofly"); \
|
||||
}) \
|
||||
XMPP_COMMAND(NoflyCallback, "nofly", "Get Parsee nofly list", {})
|
||||
|
||||
#define XMPP_COMMAND(f,n,t,s) extern void f(XMPPCommandManager *, char *, XMLElement *, XMLElement *);
|
||||
#define XMPP_COMMAND(f,n,t,s) \
|
||||
extern void \
|
||||
f(XMPPCommandManager *, char *, XMLElement *, XMLElement *);
|
||||
|
||||
XMPPCOMMANDS
|
||||
|
||||
#undef XMPP_COMMAND
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue