[ADD/WIP] On-the-fly forms

Still WIP-tier, also I need to make a way to index a multi-option list
like a regular array with the forms thing, the current one-at-a-time
idea is not great...
This commit is contained in:
LDA 2024-07-14 22:24:59 +02:00
commit 0cb19a15d8
4 changed files with 146 additions and 6 deletions

View file

@ -13,6 +13,7 @@ struct XMPPCommand {
/* TODO: On-the-fly generation of options */ /* TODO: On-the-fly generation of options */
Array *options; Array *options;
XMPPOptionWriter otf;
}; };
XMPPCommand * XMPPCommand *
@ -35,8 +36,20 @@ XMPPBasicCmd(char *node, char *name, XMPPCmdCallback callback_funct)
/* No options -> no form required */ /* No options -> no form required */
cmd->options = NULL; cmd->options = NULL;
cmd->otf = NULL;
return cmd; return cmd;
} }
void
XMPPCmdOptionsCreator(XMPPCommand *cmd, XMPPOptionWriter writer)
{
if (!cmd)
{
return;
}
cmd->otf = writer;
}
void void
XMPPSetFormTitle(XMPPCommand *cmd, char *title) XMPPSetFormTitle(XMPPCommand *cmd, char *title)
{ {
@ -95,12 +108,28 @@ XMPPAddOption(XMPPCommand *cmd, XMPPOption *opt)
} }
XMLElement * XMLElement *
XMPPFormifyCommand(XMPPCommand *cmd) XMPPFormifyCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from)
{ {
XMLElement *x, *field; XMLElement *x, *field;
size_t i; size_t i;
if (!cmd || !cmd->options) if (!cmd || !m)
{
return NULL;
}
if (cmd->otf)
{
for (i = 0; i < ArraySize(cmd->options); i++)
{
XMPPOption *opt = ArrayGet(cmd->options, i);
XMPPFreeOption(opt);
}
ArrayFree(cmd->options);
cmd->options = NULL;
cmd->otf(m, cmd, from);
}
if (!cmd->options)
{ {
return NULL; return NULL;
} }
@ -152,7 +181,7 @@ XMPPGetCommandDesc(XMPPCommand *cmd)
bool bool
XMPPCommandRequiresForm(XMPPCommand *cmd) XMPPCommandRequiresForm(XMPPCommand *cmd)
{ {
return cmd ? !!cmd->options : false; return cmd ? (cmd->otf || !!cmd->options) : false;
} }
void void
XMPPExecuteCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from, XMLElement *to, XMLElement *form) XMPPExecuteCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from, XMLElement *to, XMLElement *form)

View file

@ -271,7 +271,7 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
XMLAddChild(command_xml, actions); XMLAddChild(command_xml, actions);
XMLAddChild(iq, command_xml); XMLAddChild(iq, command_xml);
x = XMPPFormifyCommand(cmd); x = XMPPFormifyCommand(m, cmd, from);
XMLAddChild(command_xml, x); XMLAddChild(command_xml, x);
pthread_mutex_lock(&jabber->write_lock); pthread_mutex_lock(&jabber->write_lock);

View file

@ -0,0 +1,99 @@
#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
DelAdminCallback(XMPPCommandManager *m, char *from, XMLElement *form, XMLElement *out)
{
ParseeData *data = XMPPGetManagerCookie(m);
char *trimmed = ParseeTrimJID(from);
char *glob = NULL;
DbRef *admins;
Array *admin_list;
size_t i;
bool removed = false;
GetFieldValue(glob, "glob", form);
if (!ParseeIsAdmin(data, trimmed))
{
SetNote("error", "User is not authorised to execute command.");
Free(trimmed);
return;
}
if (!glob)
{
SetNote("error", "No glob found.");
Free(trimmed);
return;
}
Log(LOG_INFO, "glob=%s", glob);
admins = DbLock(data->db, 1, "admins");
admin_list = GrabArray(DbJson(admins), 1, "admins");
for (i = 0; i < ArraySize(admin_list); i++)
{
char *admin = JsonValueAsString(ArrayGet(admin_list, i));
if (StrEquals(admin, glob))
{
SetNote("info", "Admin sucessfully removed.");
removed = true;
JsonValueFree(ArrayDelete(admin_list, i));
break;
}
}
DbUnlock(data->db, admins);
Free(trimmed);
if (!removed)
{
SetNote("warn", "Glob wasn't in list.");
}
/* TODO */
}
void
FormDelAdminCallback(XMPPCommandManager *m, XMPPCommand *cmd, char *from)
{
ParseeData *data = XMPPGetManagerCookie(m);
DbRef *admins;
Array *admin_list;
size_t i;
XMPPOption *admin_opt;
char *trimmed = ParseeTrimJID(from);
if (!ParseeIsAdmin(data, trimmed))
{
Free(trimmed);
admin_opt = XMPPCreateList(true, true, "glob", "[NOT AUTHORIZED!]");
XMPPAddOption(cmd, admin_opt);
return;
}
Free(trimmed);
admin_opt = XMPPCreateList(true, true, "glob", "[NVM!]");
admins = DbLock(data->db, 1, "admins");
admin_list = GrabArray(DbJson(admins), 1, "admins");
for (i = 0; i < ArraySize(admin_list); i++)
{
char *glob = JsonValueAsString(ArrayGet(admin_list, i));
XMPPAddListOption(admin_opt, glob);
}
DbUnlock(data->db, admins);
XMPPAddOption(cmd, admin_opt);
}

View file

@ -11,6 +11,7 @@ typedef struct XMPPCommandManager XMPPCommandManager;
typedef struct XMPPCommand XMPPCommand; typedef struct XMPPCommand XMPPCommand;
typedef struct XMPPOption XMPPOption; typedef struct XMPPOption XMPPOption;
typedef void (*XMPPCmdCallback)(XMPPCommandManager *, char *, XMLElement *, XMLElement *); typedef void (*XMPPCmdCallback)(XMPPCommandManager *, char *, XMLElement *, XMLElement *);
typedef void (*XMPPOptionWriter)(XMPPCommandManager *, XMPPCommand *, char *);
/** Creates a simple XMPP command manager, which routes commands /** Creates a simple XMPP command manager, which routes commands
* with a single-stage form system, with a {cookie} * with a single-stage form system, with a {cookie}
@ -27,8 +28,9 @@ extern void * XMPPGetManagerCookie(XMPPCommandManager *manager);
* Modifies: NOTHING * Modifies: NOTHING
* See-Also: XMPPRegisterCommand */ * See-Also: XMPPRegisterCommand */
extern XMPPCommand * XMPPBasicCmd(char *node, char *name, XMPPCmdCallback cb); extern XMPPCommand * XMPPBasicCmd(char *node, char *name, XMPPCmdCallback cb);
extern void XMPPCmdOptionsCreator(XMPPCommand *cmd, XMPPOptionWriter writer);
extern void XMPPAddOption(XMPPCommand *cmd, XMPPOption *opt); extern void XMPPAddOption(XMPPCommand *cmd, XMPPOption *opt);
extern XMLElement * XMPPFormifyCommand(XMPPCommand *cmd); extern XMLElement * XMPPFormifyCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from);
extern char * XMPPGetCommandNode(XMPPCommand *cmd); extern char * XMPPGetCommandNode(XMPPCommand *cmd);
extern char * XMPPGetCommandDesc(XMPPCommand *cmd); extern char * XMPPGetCommandDesc(XMPPCommand *cmd);
extern void XMPPSetFormInstruction(XMPPCommand *cmd, char *instruction); extern void XMPPSetFormInstruction(XMPPCommand *cmd, char *instruction);
@ -91,6 +93,7 @@ extern bool XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeD
/* --------------------------------- COMMANDS --------------------------------- */ /* --------------------------------- COMMANDS --------------------------------- */
/* Please edit stc/XMPPThread.c (you can just force-save) for these to apply! */
#define XMPPCOMMANDS \ #define XMPPCOMMANDS \
XMPP_COMMAND(StatusCallback, "stats", "Get Parsee statistics", {}) \ XMPP_COMMAND(StatusCallback, "stats", "Get Parsee statistics", {}) \
XMPP_COMMAND(CleanCallback, "clean", "Cleanup temporary Parsee data", {}) \ XMPP_COMMAND(CleanCallback, "clean", "Cleanup temporary Parsee data", {}) \
@ -104,6 +107,11 @@ extern bool XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeD
XMPPSetFormTitle(cmd, "Admin addition form"); \ XMPPSetFormTitle(cmd, "Admin addition form"); \
XMPPSetFormInstruction(cmd, "Select a glob pattern to add as an admin"); \ XMPPSetFormInstruction(cmd, "Select a glob pattern to add as an admin"); \
}) \ }) \
XMPP_COMMAND(DelAdminCallback, "del-admin", "Removes a glob from admin rights", { \
XMPPCmdOptionsCreator(cmd, FormDelAdminCallback); \
XMPPSetFormTitle(cmd, "Admin removal form"); \
XMPPSetFormInstruction(cmd, "Select a glob pattern to remove as an admin"); \
}) \
XMPP_COMMAND(AddNoflyCallback, "add-nofly", "Adds user to nofly", { \ XMPP_COMMAND(AddNoflyCallback, "add-nofly", "Adds user to nofly", { \
XMPPOption *entity = XMPPCreateText(true, "entity", ""); \ XMPPOption *entity = XMPPCreateText(true, "entity", ""); \
XMPPOption *reason = XMPPCreateText(false, "reason", "Not behaving"); \ XMPPOption *reason = XMPPCreateText(false, "reason", "Not behaving"); \
@ -118,7 +126,11 @@ extern bool XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeD
#define XMPP_COMMAND(f,n,t,s) \ #define XMPP_COMMAND(f,n,t,s) \
extern void \ extern void \
f(XMPPCommandManager *, char *, XMLElement *, XMLElement *); f(XMPPCommandManager *, char *, XMLElement *, XMLElement *); \
/* This symbol might not exist. We do, however, not care, as
* it is not always done. */ \
extern void \
Form##f(XMPPCommandManager *, XMPPCommand *, char *); \
XMPPCOMMANDS XMPPCOMMANDS