mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 18:35:11 +00:00
[ADD/WIP] Create and use basic command parser
Still need to write the router.
This commit is contained in:
parent
f434f7aa87
commit
c4b7d1b92a
6 changed files with 220 additions and 12 deletions
133
src/Command/Parser.c
Normal file
133
src/Command/Parser.c
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
#include <Command.h>
|
||||||
|
|
||||||
|
#include <Cytoplasm/Memory.h>
|
||||||
|
#include <Cytoplasm/Str.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
typedef enum CommandState {
|
||||||
|
STATE_WHITE,
|
||||||
|
STATE_NAME,
|
||||||
|
STATE_VALUE
|
||||||
|
} CommandState;
|
||||||
|
|
||||||
|
Command *
|
||||||
|
CommandParse(char *cmd)
|
||||||
|
{
|
||||||
|
Command *ret;
|
||||||
|
char *end_data, *cur, *namestart;
|
||||||
|
char *key = NULL, *val = NULL;
|
||||||
|
size_t len;
|
||||||
|
CommandState state = STATE_WHITE;
|
||||||
|
if (!cmd)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
end_data = strchr(cmd, ' ');
|
||||||
|
if (!end_data)
|
||||||
|
{
|
||||||
|
ret = Malloc(sizeof(*ret));
|
||||||
|
ret->command = StrDuplicate(cmd);
|
||||||
|
ret->arguments = HashMapCreate();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = end_data - cmd;
|
||||||
|
ret = Malloc(sizeof(*ret));
|
||||||
|
ret->arguments = HashMapCreate();
|
||||||
|
ret->command = Malloc(len + 1);
|
||||||
|
memcpy(ret->command, cmd, len);
|
||||||
|
ret->command[len] = '\0';
|
||||||
|
|
||||||
|
cur = end_data + 1;
|
||||||
|
|
||||||
|
/* Parse arguments */
|
||||||
|
while (*cur)
|
||||||
|
{
|
||||||
|
char c = *cur;
|
||||||
|
char *tmp;
|
||||||
|
bool type;
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case STATE_WHITE:
|
||||||
|
if (!isblank(c))
|
||||||
|
{
|
||||||
|
state = STATE_NAME;
|
||||||
|
namestart = cur;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STATE_NAME:
|
||||||
|
if (c == '=')
|
||||||
|
{
|
||||||
|
len = cur - namestart;
|
||||||
|
key = Malloc(len + 1);
|
||||||
|
memcpy(key, namestart, len);
|
||||||
|
key[len] = '\0';
|
||||||
|
state = STATE_VALUE;
|
||||||
|
cur++;
|
||||||
|
val = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STATE_VALUE:
|
||||||
|
type = c == '"';
|
||||||
|
if (type)
|
||||||
|
{
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
while (*cur)
|
||||||
|
{
|
||||||
|
char c = *cur;
|
||||||
|
char cb[2] = { c, '\0' };
|
||||||
|
if ((type && c == '"') || (!type && isblank(c)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '\\' && *(cur + 1) == '"')
|
||||||
|
{
|
||||||
|
cb[0] = '"';
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
tmp = val;
|
||||||
|
val = StrConcat(2, val, cb);
|
||||||
|
Free(tmp);
|
||||||
|
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
Free(HashMapSet(ret->arguments, key, val));
|
||||||
|
Free(key);
|
||||||
|
key = NULL;
|
||||||
|
val = NULL;
|
||||||
|
state = STATE_WHITE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
Free(key);
|
||||||
|
Free(val);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CommandFree(Command *command)
|
||||||
|
{
|
||||||
|
char *key, *val;
|
||||||
|
if (!command)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (HashMapIterate(command->arguments, &key, (void **) &val))
|
||||||
|
{
|
||||||
|
Free(val);
|
||||||
|
}
|
||||||
|
HashMapFree(command->arguments);
|
||||||
|
|
||||||
|
Free(command->command);
|
||||||
|
Free(command);
|
||||||
|
}
|
||||||
49
src/Command/Router.c
Normal file
49
src/Command/Router.c
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include <Command.h>
|
||||||
|
|
||||||
|
#include <Cytoplasm/Memory.h>
|
||||||
|
|
||||||
|
struct CommandRouter {
|
||||||
|
HashMap *routes;
|
||||||
|
};
|
||||||
|
CommandRouter *
|
||||||
|
CommandCreateRouter(void)
|
||||||
|
{
|
||||||
|
CommandRouter *router = Malloc(sizeof(*router));
|
||||||
|
router->routes = HashMapCreate();
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
CommandAddCommand(CommandRouter *rter, char *c, CommandRoute rte)
|
||||||
|
{
|
||||||
|
if (!rter || !c || !rte)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HashMapSet(rter->routes, c, rte);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
RouteCommand(CommandRouter *rter, Command *cmd, void *d)
|
||||||
|
{
|
||||||
|
CommandRoute route;
|
||||||
|
if (!rter || !cmd)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
route = HashMapGet(rter->routes, cmd->command);
|
||||||
|
if (route)
|
||||||
|
{
|
||||||
|
route(cmd, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void
|
||||||
|
CommandFreeRouter(CommandRouter *rter)
|
||||||
|
{
|
||||||
|
if (!rter)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMapFree(rter->routes);
|
||||||
|
Free(rter);
|
||||||
|
}
|
||||||
|
|
@ -73,6 +73,7 @@ ParseeBotHandler(ParseeData *data, HashMap *event)
|
||||||
"@", data->config->sender_localpart,
|
"@", data->config->sender_localpart,
|
||||||
":", data->config->homeserver_host
|
":", data->config->homeserver_host
|
||||||
);
|
);
|
||||||
|
Command *cmd;
|
||||||
|
|
||||||
if (StrEquals(msgtype, "m.notice"))
|
if (StrEquals(msgtype, "m.notice"))
|
||||||
{
|
{
|
||||||
|
|
@ -107,14 +108,14 @@ ParseeBotHandler(ParseeData *data, HashMap *event)
|
||||||
#define BAN_USER "ban-user"
|
#define BAN_USER "ban-user"
|
||||||
#define BAN_LIST "ban-list"
|
#define BAN_LIST "ban-list"
|
||||||
#define LS_USERS "ls-flying"
|
#define LS_USERS "ls-flying"
|
||||||
if (!strncmp(body, BAN_USER, strlen(BAN_USER)))
|
cmd = CommandParse(body);
|
||||||
|
if (cmd && StrEquals(cmd->command, BAN_USER))
|
||||||
{
|
{
|
||||||
char user[256] = { 0 };
|
char *user = HashMapGet(cmd->arguments, "user");
|
||||||
char room[256] = { 0 };
|
char *room = HashMapGet(cmd->arguments, "user");
|
||||||
char *msg;
|
char *msg;
|
||||||
|
|
||||||
body += strlen(BAN_USER);
|
if (!user || !room)
|
||||||
if (sscanf(body, "%255s %255s", &user, &room) != 2)
|
|
||||||
{
|
{
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
@ -128,7 +129,7 @@ ParseeBotHandler(ParseeData *data, HashMap *event)
|
||||||
));
|
));
|
||||||
Free(msg);
|
Free(msg);
|
||||||
}
|
}
|
||||||
else if (!strncmp(body, LS_USERS, strlen(LS_USERS)))
|
else if (cmd && StrEquals(cmd->command, LS_USERS))
|
||||||
{
|
{
|
||||||
DbRef *listed = DbLock(data->db, 1, "global_bans");
|
DbRef *listed = DbLock(data->db, 1, "global_bans");
|
||||||
HashMap *json = DbJson(listed);
|
HashMap *json = DbJson(listed);
|
||||||
|
|
@ -156,13 +157,12 @@ ParseeBotHandler(ParseeData *data, HashMap *event)
|
||||||
Free(str);
|
Free(str);
|
||||||
DbUnlock(data->db, listed);
|
DbUnlock(data->db, listed);
|
||||||
}
|
}
|
||||||
else if (!strncmp(body, BAN_LIST, strlen(BAN_LIST)))
|
else if (cmd && StrEquals(cmd->command, BAN_LIST))
|
||||||
{
|
{
|
||||||
char user[256] = { 0 };
|
char *user = HashMapGet(cmd->arguments, "user");
|
||||||
char *msg;
|
char *msg;
|
||||||
|
|
||||||
body += strlen(BAN_USER);
|
if (!user)
|
||||||
if (sscanf(body, "%255s", &user) != 1)
|
|
||||||
{
|
{
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
@ -178,6 +178,7 @@ ParseeBotHandler(ParseeData *data, HashMap *event)
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
Free(profile);
|
Free(profile);
|
||||||
|
CommandFree(cmd);
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
ParseeMessageHandler(ParseeData *data, HashMap *event)
|
ParseeMessageHandler(ParseeData *data, HashMap *event)
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ ParseeInitData(XMPPComponent *comp)
|
||||||
data->config = ParseeConfigGet();
|
data->config = ParseeConfigGet();
|
||||||
data->router = HttpRouterCreate();
|
data->router = HttpRouterCreate();
|
||||||
data->jabber = comp;
|
data->jabber = comp;
|
||||||
|
data->handler = CommandCreateRouter();
|
||||||
data->db = DbOpen(data->config->db_path, 0);
|
data->db = DbOpen(data->config->db_path, 0);
|
||||||
|
|
||||||
#define X_ROUTE(path, func) do {\
|
#define X_ROUTE(path, func) do {\
|
||||||
|
|
@ -48,6 +49,7 @@ ParseeFreeData(ParseeData *data)
|
||||||
XMPPEndCompStream(data->jabber);
|
XMPPEndCompStream(data->jabber);
|
||||||
DbClose(data->db);
|
DbClose(data->db);
|
||||||
HttpRouterFree(data->router);
|
HttpRouterFree(data->router);
|
||||||
|
CommandFreeRouter(data->handler);
|
||||||
Free(data);
|
Free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
21
src/include/Command.h
Normal file
21
src/include/Command.h
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef PARSEE_COMMAND_H
|
||||||
|
#define PARSEE_COMMAND_H
|
||||||
|
|
||||||
|
#include <Cytoplasm/HashMap.h>
|
||||||
|
|
||||||
|
typedef struct Command {
|
||||||
|
char *command;
|
||||||
|
HashMap *arguments;
|
||||||
|
} Command;
|
||||||
|
|
||||||
|
typedef struct CommandRouter CommandRouter;
|
||||||
|
typedef void (*CommandRoute)(Command *cmd, void *data);
|
||||||
|
|
||||||
|
extern CommandRouter * CommandCreateRouter(void);
|
||||||
|
extern void CommandAddCommand(CommandRouter *rter, char *c, CommandRoute rte);
|
||||||
|
extern void RouteCommand(CommandRouter *rter, Command *cmd, void *data);
|
||||||
|
extern void CommandFreeRouter(CommandRouter *rter);
|
||||||
|
|
||||||
|
extern Command * CommandParse(char *cmd);
|
||||||
|
extern void CommandFree(Command *command);
|
||||||
|
#endif
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include <Command.h>
|
||||||
#include <XMPP.h>
|
#include <XMPP.h>
|
||||||
|
|
||||||
typedef struct ParseeConfig {
|
typedef struct ParseeConfig {
|
||||||
|
|
@ -43,6 +44,7 @@ typedef struct ParseeConfig {
|
||||||
typedef struct ParseeData {
|
typedef struct ParseeData {
|
||||||
const ParseeConfig *config;
|
const ParseeConfig *config;
|
||||||
HttpRouter *router;
|
HttpRouter *router;
|
||||||
|
CommandRouter *handler;
|
||||||
|
|
||||||
XMPPComponent *jabber;
|
XMPPComponent *jabber;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue