From 04ad2756e40c6b6028ffb447f074e6cd761a98bf Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Sun, 23 May 2021 19:30:52 +0200
Subject: [PATCH] CMD: Add all commands other than search commands to the trie
 structure, also hide all the sticker sub-commands into another function

---
 inc/lektor/commands.h | 126 +++++++++++++++++----------------
 inc/lektor/database.h |   1 +
 src/base/commands.c   |  44 ++++++++++--
 src/net/listen.c      | 158 ++++++++++++++++--------------------------
 4 files changed, 166 insertions(+), 163 deletions(-)

diff --git a/inc/lektor/commands.h b/inc/lektor/commands.h
index ca399213..82463eb6 100644
--- a/inc/lektor/commands.h
+++ b/inc/lektor/commands.h
@@ -11,71 +11,69 @@ extern "C" {
 
 // clang-format off
 
-/**
- * The list of commands implemented by lektor.
+/* The list of commands implemented by lektor.
  *
  * Refer to the following link for the description of each command:
- * <https://www.musicpd.org/doc/html/protocol.html>
- */
+ * <https://www.musicpd.org/doc/html/protocol.html> */
 
 /* Querying lektor's status */
-bool command_currentsong(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_status     (struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_stats      (struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_MAX]);
+bool command_currentsong(struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_status     (struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_stats      (struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
 
 /* Controlling playback */
-bool command_next    (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_pause   (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_previous(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_play    (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_playid  (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_stop    (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
+bool command_next    (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_pause   (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_previous(struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_play    (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_playid  (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_stop    (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
 
-bool command_seek    (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_seekid  (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_seekcur (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
+bool command_seek    (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_seekid  (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_seekcur (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
 
 bool command_set_pos(struct lkt_state *srv, int index); /* FIXME: Not used in net/listen.c */
 
 /* The queue */
-bool command_add    (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX], int priority);
-bool command_addid  (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_del    (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_delid  (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_clear  (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_crop   (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_move   (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_shuffle(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_dump   (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_swap   (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_swapid (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_flat   (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-
-static inline bool
+bool command_add    (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX], int priority);
+bool command_addid  (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_del    (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_delid  (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_clear  (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_crop   (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_move   (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_shuffle(struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_dump   (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_swap   (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_swapid (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_flat   (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+
+PRIVATE_FUNCTION bool
 command_add_1(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX])
 {
     return command_add(srv, args, 1);
 }
 
-static inline bool
+PRIVATE_FUNCTION bool
 command_add_5(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX])
 {
     return command_add(srv, args, 1);
 }
 
-bool command_queue_list  (struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_queue_listid(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_MAX]);
+bool command_queue_list  (struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_queue_listid(struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
 
 /* The playlists */
-bool command_plt_create(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_plt_remove(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_plt_clear (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_plt_rename(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_plt_export(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_plt_import(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_plt_add   (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]);
-bool command_plt_list  (struct lkt_state *srv, size_t, char *args[LKT_MESSAGE_ARGS_MAX], int cont);
-bool command_plt_ctx   (struct lkt_state *srv, size_t, char *args[LKT_MESSAGE_ARGS_MAX], int cont);
+bool command_plt_create(struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_plt_remove(struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_plt_clear (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_plt_rename(struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_plt_export(struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_plt_import(struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_plt_add   (struct lkt_state *srv, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_plt_list  (struct lkt_state *srv, size_t, char *[LKT_MESSAGE_ARGS_MAX], int cont);
+bool command_plt_ctx   (struct lkt_state *srv, size_t, char *[LKT_MESSAGE_ARGS_MAX], int cont);
 
 /* The help */
 bool command_help(struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
@@ -88,7 +86,7 @@ bool command_noidle(struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX
 
 /* Find and send karas in the db that match the search expression */
 bool command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX],
-                  long continuation, bool (*init)(volatile sqlite3 *, struct lkt_search *));
+                  long continuation, database_search_init_func init);
 
 /* Set options for the lektor such as `random`, `single`, `repeat`, etc */
 typedef enum {
@@ -101,25 +99,37 @@ typedef enum {
 } LKT_PLAYBACK_OPTION;
 
 bool command_set_playback_option(struct lkt_state *srv, size_t c, LKT_PLAYBACK_OPTION opt,
-                                 char *args[LKT_MESSAGE_ARGS_MAX]);
+                                 char *[LKT_MESSAGE_ARGS_MAX]);
 
 /* Authentificate users */
-bool command_password(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
-bool command_user_add(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
+bool command_password(struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_user_add(struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
 
 /* Program management control */
-bool command_restart(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
-bool command_kill   (struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
-bool command_import (struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
-bool command_update (struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
-bool command_rescan (struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX], int forced);
-bool command_config (struct lkt_state *srv, size_t c, char UNUSED *argv[LKT_MESSAGE_ARGS_MAX]);
-
-/* Sticker management */
-bool command_sticker_create(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
-bool command_sticker_get   (struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
-bool command_sticker_set   (struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
-bool command_sticker_delete(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX]);
+bool command_restart(struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_kill   (struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_import (struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_update (struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
+bool command_rescan (struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX], int forced);
+bool command_config (struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
+
+PRIVATE_FUNCTION bool
+command_rescan_true(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
+{
+    /* Force the rescan, don't check timestamps */
+    return command_rescan(srv, c, argv, true);
+}
+
+PRIVATE_FUNCTION bool
+command_rescan_false(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
+{
+    /* Don't force the rescan, check timestamps */
+    return command_rescan(srv, c, argv, false);
+}
+
+/* Sticker management. Handle all the sticker commands, the sticker command in
+ * MPD is has a lot of subcommands... */
+bool command_sticker_handle(struct lkt_state *srv, size_t c, char *[LKT_MESSAGE_ARGS_MAX]);
 
 // clang-format on
 
diff --git a/inc/lektor/database.h b/inc/lektor/database.h
index 4a3d9921..53419677 100644
--- a/inc/lektor/database.h
+++ b/inc/lektor/database.h
@@ -143,6 +143,7 @@ size_t database_search_get_continuation(struct lkt_search *);
  * function is here if you need to abort a search. */
 void database_search_free(struct lkt_search *);
 
+typedef bool (*database_search_init_func)(volatile sqlite3 *, struct lkt_search *);
 bool database_search_database_init    (volatile sqlite3 *db, struct lkt_search *ret);
 bool database_search_queue_init       (volatile sqlite3 *db, struct lkt_search *ret);
 bool database_search_sticker_init     (volatile sqlite3 *db, struct lkt_search *ret);
diff --git a/src/base/commands.c b/src/base/commands.c
index 1a911e8c..ad5bfb3e 100644
--- a/src/base/commands.c
+++ b/src/base/commands.c
@@ -541,6 +541,7 @@ command_idle(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_MAX])
     bool once;
     size_t i;
 
+#pragma message(TODO "Use a lookup table here...")
     for (once = false, i = 0; args[i]; ++i, once |= true) {
         if (STR_MATCH(args[i], "database"))
             lkt_client_add_mask(srv, c, MPD_IDLE_DATABASE);
@@ -673,7 +674,7 @@ __iter_search(struct lkt_search *search)
 
 bool
 command_find(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_MAX], long continuation,
-             bool (*init)(volatile sqlite3 *, struct lkt_search *))
+             database_search_init_func init)
 {
     int count;
     struct lkt_uri find_uri   = { .type = URI_NULL };
@@ -1042,7 +1043,14 @@ command_user_add(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MA
 
 /* Stickers */
 
-static bool
+// clang-format off
+PRIVATE_FUNCTION bool command_sticker_create(struct lkt_state *, size_t, char *[LKT_MESSAGE_ARGS_MAX]);
+PRIVATE_FUNCTION bool command_sticker_get   (struct lkt_state *, size_t, char *[LKT_MESSAGE_ARGS_MAX]);
+PRIVATE_FUNCTION bool command_sticker_set   (struct lkt_state *, size_t, char *[LKT_MESSAGE_ARGS_MAX]);
+PRIVATE_FUNCTION bool command_sticker_delete(struct lkt_state *, size_t, char *[LKT_MESSAGE_ARGS_MAX]);
+// clang-format on
+
+PRIVATE_FUNCTION bool
 sticker_send(struct lkt_state *srv, size_t c, char *name, char UNUSED *type, int id, int value)
 {
     lkt_state_send(srv, c, lkt_message_new_fmt("%d: %s -> %d\n", id, name, value));
@@ -1050,6 +1058,30 @@ sticker_send(struct lkt_state *srv, size_t c, char *name, char UNUSED *type, int
 }
 
 bool
+command_sticker_handle(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_MAX])
+{
+#pragma message(TODO "Use a lookup table here...")
+
+    if (STR_MATCH(args[0], "get") || STR_MATCH(args[0], "list") || STR_MATCH(args[0], "find")) {
+        return command_sticker_get(srv, c, args + 1);
+    }
+
+    else if (STR_MATCH(args[0], "set")) {
+        return command_sticker_set(srv, c, args + 1);
+    }
+
+    else if (STR_MATCH(args[0], "delete")) {
+        return command_sticker_delete(srv, c, args + 1);
+    }
+
+    else if (STR_MATCH(args[0], "__create")) {
+        return command_sticker_create(srv, c, args + 1);
+    }
+
+    return false;
+}
+
+PRIVATE_FUNCTION bool
 command_sticker_create(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
     LOG_INFO("COMMAND", "Client %ld is using the sticker create command", c);
@@ -1062,7 +1094,7 @@ command_sticker_create(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_A
     return true;
 }
 
-bool
+PRIVATE_FUNCTION bool
 command_sticker_set(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
     RETURN_UNLESS(argv[0] && argv[1] && argv[2] && argv[3] && !argv[4], "Invalid argument", false);
@@ -1077,7 +1109,7 @@ command_sticker_set(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS
     return true;
 }
 
-bool
+PRIVATE_FUNCTION bool
 command_sticker_get(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
     LOG_INFO("COMMAND", "Client %ld is using the sticker get command", c);
@@ -1133,7 +1165,7 @@ unknown:
     return false;
 }
 
-bool
+PRIVATE_FUNCTION bool
 command_sticker_delete(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
     LOG_INFO("COMMAND", "Client %ld is using the sticker delete command", c);
@@ -1143,7 +1175,7 @@ command_sticker_delete(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_A
     return database_sticker_delete_specify(srv->db, argv[0], uri, argv[2]);
 }
 
-bool
+PRIVATE_FUNCTION bool
 command_sticker_destroy(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
     LOG_INFO("COMMAND", "Client %ld is using the sticker destroy command", c);
diff --git a/src/net/listen.c b/src/net/listen.c
index 355201a6..f3e1fe33 100644
--- a/src/net/listen.c
+++ b/src/net/listen.c
@@ -138,53 +138,6 @@ cmd_trie_find(struct cmd_trie_node *root, const char *signed_cmd_name)
     return root;
 }
 
-PRIVATE_FUNCTION bool
-cmd_trie_exec(struct cmd_trie_node *root, const char *signed_cmd_name, va_list *args_list)
-{
-    FAIL_UNLESS(root, "Passing an empty trie root");
-    struct cmd_trie_node *node = cmd_trie_find(root, signed_cmd_name);
-    if (node == NULL)
-        return false;
-
-    /* Possibly used variables */
-    struct lkt_state *srv;
-    size_t c;
-    char **args;
-    int arg_int;
-
-    union {
-        void (*base)(void);
-        bool (*type_simple)(struct lkt_state *, size_t, char *[LKT_MESSAGE_ARGS_MAX]);
-        bool (*type_int)(struct lkt_state *, size_t, char *[LKT_MESSAGE_ARGS_MAX], int);
-        bool (*type_anon)(struct lkt_state *, char *[LKT_MESSAGE_ARGS_MAX]);
-    } cmd;
-
-    cmd.base = node->cmd_ptr;
-
-    switch (node->type) {
-    case LKT_COMMAND_SIMPLE:
-        srv  = (struct lkt_state *)va_arg(*args_list, struct lkt_state *);
-        c    = (size_t)va_arg(*args_list, size_t);
-        args = (char **)va_arg(*args_list, char *[LKT_MESSAGE_MAX]);
-        return cmd.type_simple(srv, c, args);
-
-    case LKT_COMMAND_ANON:
-        srv  = (struct lkt_state *)va_arg(*args_list, struct lkt_state *);
-        args = (char **)va_arg(*args_list, char *[LKT_MESSAGE_MAX]);
-        return cmd.type_anon(srv, args);
-
-    case LKT_COMMAND_INTEGER:
-        srv     = (struct lkt_state *)va_arg(*args_list, struct lkt_state *);
-        c       = (size_t)va_arg(*args_list, size_t);
-        args    = (char **)va_arg(*args_list, char *[LKT_MESSAGE_MAX]);
-        arg_int = (int)va_arg(*args_list, int);
-        return cmd.type_int(srv, c, args, arg_int);
-
-    case LKT_COMMAND_NULL:
-        return false;
-    }
-}
-
 PRIVATE_FUNCTION void
 ___cmd_trie_print(struct cmd_trie_node *root, char *old_prefix, const size_t length)
 {
@@ -229,48 +182,63 @@ ___cmd_trie_init(void)
     cmd_trie_root = cmd_trie_new();
 
     // clang-format off
-    cmd_trie_insert(cmd_trie_root, "currentsong",       FUNCTION_POINTER(command_currentsong),  LKT_COMMAND_SIMPLE);
-    cmd_trie_insert(cmd_trie_root, "status",            FUNCTION_POINTER(command_status),       LKT_COMMAND_SIMPLE);
-    cmd_trie_insert(cmd_trie_root, "stats",             FUNCTION_POINTER(command_stats),        LKT_COMMAND_SIMPLE);
-
-    cmd_trie_insert(cmd_trie_root, "next",              FUNCTION_POINTER(command_next),         LKT_COMMAND_SIMPLE);
-    cmd_trie_insert(cmd_trie_root, "previous",          FUNCTION_POINTER(command_previous),     LKT_COMMAND_SIMPLE);
-    cmd_trie_insert(cmd_trie_root, "pause",             FUNCTION_POINTER(command_pause),        LKT_COMMAND_SIMPLE);
-    cmd_trie_insert(cmd_trie_root, "play",              FUNCTION_POINTER(command_next),         LKT_COMMAND_SIMPLE);
-    cmd_trie_insert(cmd_trie_root, "playid",            FUNCTION_POINTER(command_next),         LKT_COMMAND_SIMPLE);
-    cmd_trie_insert(cmd_trie_root, "stop",              FUNCTION_POINTER(command_next),         LKT_COMMAND_SIMPLE);
-    cmd_trie_insert(cmd_trie_root, "seek",              FUNCTION_POINTER(command_seek),         LKT_COMMAND_SIMPLE);
-    cmd_trie_insert(cmd_trie_root, "seekid",            FUNCTION_POINTER(command_seekid),       LKT_COMMAND_SIMPLE);
-    cmd_trie_insert(cmd_trie_root, "seekcur",           FUNCTION_POINTER(command_seekcur),      LKT_COMMAND_SIMPLE);
-
-    cmd_trie_insert(cmd_trie_root, "__insert",          FUNCTION_POINTER(command_add_5),        LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "add",               FUNCTION_POINTER(command_add_1),        LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "addid",             FUNCTION_POINTER(command_addid),        LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "del",               FUNCTION_POINTER(command_del),          LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "delid",             FUNCTION_POINTER(command_delid),        LKT_COMMAND_ANON);
-
-    cmd_trie_insert(cmd_trie_root, "clear",             FUNCTION_POINTER(command_clear),        LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "crop",              FUNCTION_POINTER(command_crop),         LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "move",              FUNCTION_POINTER(command_move),         LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "shuffle",           FUNCTION_POINTER(command_shuffle),      LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "swap",              FUNCTION_POINTER(command_swap),         LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "swapid",            FUNCTION_POINTER(command_swapid),       LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "__flat",            FUNCTION_POINTER(command_flat),         LKT_COMMAND_ANON);
-
-    cmd_trie_insert(cmd_trie_root, "playlistid",        FUNCTION_POINTER(command_queue_listid), LKT_COMMAND_SIMPLE);
-    cmd_trie_insert(cmd_trie_root, "playlist",          FUNCTION_POINTER(command_queue_list),   LKT_COMMAND_SIMPLE);
-    cmd_trie_insert(cmd_trie_root, "playlistinfo",      FUNCTION_POINTER(command_queue_list),   LKT_COMMAND_SIMPLE);
-
-    cmd_trie_insert(cmd_trie_root, "playlistclear",     FUNCTION_POINTER(command_plt_clear),    LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "rename",            FUNCTION_POINTER(command_plt_rename),   LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "playlistdelete",    FUNCTION_POINTER(command_plt_remove),   LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "rm",                FUNCTION_POINTER(command_plt_remove),   LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "playlistadd",       FUNCTION_POINTER(command_plt_add),      LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "save",              FUNCTION_POINTER(command_plt_export),   LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "__import",          FUNCTION_POINTER(command_plt_import),   LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "__dump",            FUNCTION_POINTER(command_dump),         LKT_COMMAND_ANON);
-    cmd_trie_insert(cmd_trie_root, "listplaylists",     FUNCTION_POINTER(command_plt_list),     LKT_COMMAND_INTEGER);
-    cmd_trie_insert(cmd_trie_root, "listplaylist",      FUNCTION_POINTER(command_plt_ctx),      LKT_COMMAND_INTEGER);
+#pragma message(TODO "We might want to do xdefs here with macros and one include")
+    cmd_trie_insert(cmd_trie_root, "currentsong",       FUNCTION_POINTER(command_currentsong),      LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "status",            FUNCTION_POINTER(command_status),           LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "stats",             FUNCTION_POINTER(command_stats),            LKT_COMMAND_SIMPLE);
+
+    cmd_trie_insert(cmd_trie_root, "next",              FUNCTION_POINTER(command_next),             LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "previous",          FUNCTION_POINTER(command_previous),         LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "pause",             FUNCTION_POINTER(command_pause),            LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "play",              FUNCTION_POINTER(command_next),             LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "playid",            FUNCTION_POINTER(command_next),             LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "stop",              FUNCTION_POINTER(command_next),             LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "seek",              FUNCTION_POINTER(command_seek),             LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "seekid",            FUNCTION_POINTER(command_seekid),           LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "seekcur",           FUNCTION_POINTER(command_seekcur),          LKT_COMMAND_SIMPLE);
+
+    cmd_trie_insert(cmd_trie_root, "__insert",          FUNCTION_POINTER(command_add_5),            LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "add",               FUNCTION_POINTER(command_add_1),            LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "addid",             FUNCTION_POINTER(command_addid),            LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "del",               FUNCTION_POINTER(command_del),              LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "delid",             FUNCTION_POINTER(command_delid),            LKT_COMMAND_ANON);
+
+    cmd_trie_insert(cmd_trie_root, "clear",             FUNCTION_POINTER(command_clear),            LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "crop",              FUNCTION_POINTER(command_crop),             LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "move",              FUNCTION_POINTER(command_move),             LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "shuffle",           FUNCTION_POINTER(command_shuffle),          LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "swap",              FUNCTION_POINTER(command_swap),             LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "swapid",            FUNCTION_POINTER(command_swapid),           LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "__flat",            FUNCTION_POINTER(command_flat),             LKT_COMMAND_ANON);
+
+    cmd_trie_insert(cmd_trie_root, "playlistid",        FUNCTION_POINTER(command_queue_listid),     LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "playlist",          FUNCTION_POINTER(command_queue_list),       LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "playlistinfo",      FUNCTION_POINTER(command_queue_list),       LKT_COMMAND_SIMPLE);
+
+    cmd_trie_insert(cmd_trie_root, "playlistclear",     FUNCTION_POINTER(command_plt_clear),        LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "rename",            FUNCTION_POINTER(command_plt_rename),       LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "playlistdelete",    FUNCTION_POINTER(command_plt_remove),       LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "rm",                FUNCTION_POINTER(command_plt_remove),       LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "playlistadd",       FUNCTION_POINTER(command_plt_add),          LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "save",              FUNCTION_POINTER(command_plt_export),       LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "__import",          FUNCTION_POINTER(command_plt_import),       LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "__dump",            FUNCTION_POINTER(command_dump),             LKT_COMMAND_ANON);
+    cmd_trie_insert(cmd_trie_root, "listplaylists",     FUNCTION_POINTER(command_plt_list),         LKT_COMMAND_INTEGER);
+    cmd_trie_insert(cmd_trie_root, "listplaylist",      FUNCTION_POINTER(command_plt_ctx),          LKT_COMMAND_INTEGER);
+
+    cmd_trie_insert(cmd_trie_root, "help",              FUNCTION_POINTER(command_help),             LKT_COMMAND_SIMPLE);
+
+    cmd_trie_insert(cmd_trie_root, "password",          FUNCTION_POINTER(command_password),         LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "__adduser",         FUNCTION_POINTER(command_user_add),         LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "__restart",         FUNCTION_POINTER(command_restart),          LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "kill",              FUNCTION_POINTER(command_kill),             LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "__import",          FUNCTION_POINTER(command_import),           LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "__rescan",          FUNCTION_POINTER(command_rescan_true),      LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "update",            FUNCTION_POINTER(command_update),           LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "rescan",            FUNCTION_POINTER(command_rescan_false),     LKT_COMMAND_SIMPLE);
+    cmd_trie_insert(cmd_trie_root, "config",            FUNCTION_POINTER(command_config),           LKT_COMMAND_SIMPLE);
+
+    cmd_trie_insert(cmd_trie_root, "sticker",           FUNCTION_POINTER(command_sticker_handle),   LKT_COMMAND_SIMPLE);
     // clang-format on
 
     cmd_trie_print(cmd_trie_root);
@@ -474,16 +442,8 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd)
         else if (STR_MATCH(cmd.name, "playlistfind") || STR_MATCH(cmd.name, "playlistsearch"))
             err = !command_find(srv, c, cmd.args, cmd.cont, database_search_queue_init);
 
-        else if (STR_MATCH(cmd.name, "sticker") && cmd.args[0]) {
-            if (STR_MATCH(cmd.args[0], "get") || STR_MATCH(cmd.args[0], "list") || STR_MATCH(cmd.args[0], "find"))
-                err = !command_sticker_get(srv, c, &cmd.args[1]);
-            else if (STR_MATCH(cmd.args[0], "set"))
-                err = !command_sticker_set(srv, c, &cmd.args[1]);
-            else if (STR_MATCH(cmd.args[0], "delete"))
-                err = !command_sticker_delete(srv, c, &cmd.args[1]);
-            else if (STR_MATCH(cmd.args[0], "__create"))
-                err = !command_sticker_create(srv, c, &cmd.args[1]);
-        }
+        else if (STR_MATCH(cmd.name, "sticker") && cmd.args[0])
+            err = !command_sticker_handle(srv, c, cmd.args);
 
         else if (STR_MATCH(cmd.name, "help"))
             err = !command_help(srv, c, NULL);
-- 
GitLab