diff --git a/inc/common/common.h b/inc/common/common.h
index 074fd87b94972d8a69b397bbd103ee3202cf7da9..03c6323029262e3d1fbb59c6a360feeceff157a4 100644
--- a/inc/common/common.h
+++ b/inc/common/common.h
@@ -13,6 +13,7 @@ void __unused(void *, ...);
 long get_mtime(const char *path);
 
 void *safe_malloc(size_t size);
+void *safe_zero_malloc(size_t size);
 
 int is_utf8(const char *string);
 
diff --git a/inc/common/macro.h b/inc/common/macro.h
index cb3393ec5df88049776bc6a641be6e34b1316e1d..3e220015527cf73428f3a5799b45d417e6c0b9e5 100644
--- a/inc/common/macro.h
+++ b/inc/common/macro.h
@@ -70,15 +70,11 @@
 #define INI_MAX_SECTION_LEN 80
 
 #define URL_MAX_LEN         1024
-#define DEFAULT_URL         "https://kurisu.iiens.net"
-#define GET_ID_JSON         DEFAULT_URL "/api_karas.php?id=%ld"
-#define GET_ID_FILE         DEFAULT_URL "/download.php?id=%ld"
 
 #define SELF_EXECUTABLE_LINUX           "/proc/self/exe"
 #define SELF_EXECUTABLE_FREEBSD         "/proc/curproc/file"
 #define SELF_EXECUTABLE_SOLARIS         "/proc/self/path/a.out"
 
-
 #define LKT_MAX_SQLITE_STATEMENT        1024
 #define PROTECTED_DATABASE              "disk"
 
diff --git a/inc/lektor/config.h b/inc/lektor/config.h
index 9affc9529330628379d66d95ba60885222b68321..b60bcd73e53b5fb8a4f62a416904f380ea6f6ced 100644
--- a/inc/lektor/config.h
+++ b/inc/lektor/config.h
@@ -12,7 +12,6 @@ static const char *const lkt_default_config_file =
     "; generated binary.\n"
     "[externals]\n"
     "mkvpropedit = /usr/bin/mkvpropedit\n"
-    "sqlite3 = /usr/bin/sqlite3\n"
     "\n"
     "; Server configuration.\n"
     "[server]\n"
@@ -23,18 +22,25 @@ static const char *const lkt_default_config_file =
     "; Database configuration.\n"
     "[database]\n"
     "kara_dir = /home/kara                          ; Root for the mkv files\n"
-    "db_path = /home/kara/kara.db                   ; Sqlite3 database, must be rw\n"
-    "init_script = LKT_PREFIX/share/lektor/init.sql ; Init script for the database\n"
+    "db_path  = /home/kara/kara.db                  ; Sqlite3 database, must be rw\n"
+    "\n"
+    "; Repo configuration.\n"
+    "[repo]\n"
+    "name    = Kurisu                               ; A pretty name\n"
+    "url     = https://kurisu.iiens.net\n"
+    "json    = https://kurisu.iiens.net/api\n"
+    "id_json = https://kurisu.iiens.net/api?id=%ld\n"
+    "id_kara = https://kurisu.iiens.net/download.php?id=%ld\n"
     "\n"
     "; Player configuration, the window where the karas\n"
     "; can be seen.\n"
     "[player]\n"
-    "autoclear = true            ; Clear the queue when starting\n"
     "module = module_x11         ; Default module for the window\n"
-    "def_random = false          ; Play at random per default\n"
+    "autoclear   = true          ; Clear the queue when starting\n"
+    "def_random  = false         ; Play at random per default\n"
     "def_consume = false         ; Consume per default\n"
-    "def_single = false          ; Single per default\n"
-    "def_repeat = false          ; Repeat per default\n"
+    "def_single  = false         ; Single per default\n"
+    "def_repeat  = false         ; Repeat per default\n"
     "\n"
     "; The WinX11 module configuration. Modules are .so files\n"
     "; loaded by lektor.\n"
diff --git a/inc/lektor/database.h b/inc/lektor/database.h
index 2923dc854a8616e850d06b0eca577cbec253440f..0cddeaa1a7b2af6f4ae662664f9f25469c0e276d 100644
--- a/inc/lektor/database.h
+++ b/inc/lektor/database.h
@@ -45,7 +45,7 @@ bool database_queue_get_current_file (volatile sqlite3 *db, char filepath[PATH_M
 bool database_sync_mpv_state(volatile sqlite3 *db, mpv_handle **mpv);
 
 /* Update the database. */
-bool database_update              (volatile sqlite3 *db, const char *kara_dir);
+bool database_update              (volatile sqlite3 *db, const char *kara_dir, int check_timestamp);
 bool database_update_add          (volatile sqlite3 *db, const char *kara_path, struct kara_metadata *mdt, uint64_t id, bool avail);
 bool database_update_set_available(volatile sqlite3 *db, uint64_t id);
 
diff --git a/inc/lektor/net.h b/inc/lektor/net.h
index 1a4e96a780a486f11ab23410574468788560f8f2..0609d473f7a86e4b898c23192d999c2655954ad1 100644
--- a/inc/lektor/net.h
+++ b/inc/lektor/net.h
@@ -26,19 +26,19 @@ struct lkt_command {
 /* Repository, e.g. Kurisu */
 struct lkt_repo {
     /* Just the repo */
-    const char *name;
-    const char *base_url;
-    const char *kara_dir;
-    const char *get_all_json;
-    const char *get_id_json;
-    const char *get_id_file;
+    char *name;
+    char *base_url;
+    char *kara_dir;
+    char *get_all_json;
+    char *get_id_json;
+    char *get_id_file;
     const uint64_t version;
 
     /* The database */
     volatile sqlite3 *db;
 };
 
-int  repo_new (struct lkt_repo *const repo, const char *name, const char *url, volatile sqlite3 *db);
+int  repo_new (struct lkt_repo *const repo, volatile sqlite3 *db);
 void repo_free(struct lkt_repo *const repo);
 
 int repo_get_id          (struct lkt_repo *const repo, const uint64_t id, struct kara_metadata *mdt);
diff --git a/src/commands.c b/src/commands.c
index f1f3843d91069f1bed7874a3234fed2620635877..22863455515b3aa4d4ab01b21448c40cd035f017 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -48,7 +48,7 @@ static inline void *
 __rescan(void *arg)
 {
     struct lkt_state *srv = arg;
-    database_update(srv->db, srv->kara_prefix);
+    database_update(srv->db, srv->kara_prefix, true);
     return NULL;
 }
 
@@ -85,14 +85,14 @@ command_currentsong(struct lkt_state *srv, size_t c)
 
     out = lkt_message_new();
     idx = safe_snprintf(out->data, LKT_MESSAGE_MAX,
-                   "Title: %s\n"
-                   "Author: %s\n"
-                   "Source: %s\n"
-                   "Type: %s%d\n"
-                   "Category: %s\n"
-                   "Language: %s\n",
-                   kara.song_name, kara.author_name, kara.source_name, kara.song_type,
-                   kara.song_number, kara.category, kara.language);
+                        "Title: %s\n"
+                        "Author: %s\n"
+                        "Source: %s\n"
+                        "Type: %s%d\n"
+                        "Category: %s\n"
+                        "Language: %s\n",
+                        kara.song_name, kara.author_name, kara.source_name, kara.song_type,
+                        kara.song_number, kara.category, kara.language);
     out->data_len = idx;
     lkt_state_send(srv, c, out);
 
@@ -120,21 +120,21 @@ command_status(struct lkt_state *srv, size_t c)
                  ? "stop"
                  : (queue_state.paused ? "pause" : "play");
     out->data_len = safe_snprintf(out->data, LKT_MESSAGE_MAX,
-                             "volume: %d\n"
-                             "repeat: %d\n"
-                             "random: %d\n"
-                             "single: %d\n"
-                             "consume: %d\n"
-                             "state: %s\n"
-                             "song: %d\n"
-                             "playlistlength: %d\n"
-                             "elapsed: %d\n"
-                             "duration: %d\n"
-                             "songid: %d\n",
-                             queue_state.volume, queue_state.repeat, queue_state.random,
-                             queue_state.single, queue_state.consume, play_state,
-                             queue_state.current < 0 ? -1 : queue_state.current - 1,
-                             queue_state.length, elapsed, duration, songid);
+                                  "volume: %d\n"
+                                  "repeat: %d\n"
+                                  "random: %d\n"
+                                  "single: %d\n"
+                                  "consume: %d\n"
+                                  "state: %s\n"
+                                  "song: %d\n"
+                                  "playlistlength: %d\n"
+                                  "elapsed: %d\n"
+                                  "duration: %d\n"
+                                  "songid: %d\n",
+                                  queue_state.volume, queue_state.repeat, queue_state.random,
+                                  queue_state.single, queue_state.consume, play_state,
+                                  queue_state.current < 0 ? -1 : queue_state.current - 1,
+                                  queue_state.length, elapsed, duration, songid);
     lkt_state_send(srv, c, out);
     return true;
 }
diff --git a/src/common.c b/src/common.c
index 636bf3d5459a7f8a8810b99c27418ef7994f60c7..23a0ca394a144c3a530465ac719121b825ef6934 100644
--- a/src/common.c
+++ b/src/common.c
@@ -151,6 +151,14 @@ safe_malloc(size_t size)
     return tmp;
 }
 
+void *
+safe_zero_malloc(size_t size)
+{
+    void *ret = safe_malloc(size);
+    memset(ret, 0, size);
+    return ret;
+}
+
 int
 read_self_exe(char *path, size_t len)
 {
diff --git a/src/config.c b/src/config.c
index 707c48ecd7d904405b0863e7467cda4942b4b1b4..4d2a0a3089f384d6d6622baa2a5d58552516b29a 100644
--- a/src/config.c
+++ b/src/config.c
@@ -156,10 +156,10 @@ load_module_by_name(volatile sqlite3 *db, const char *name, void *mod)
 inline static int
 validate_conf(volatile sqlite3 *db)
 {
-#define CHK_OPTION(section, name)                                       \
-    if (!database_config_exists(db, section, name)) {                   \
-        LOG_ERROR("%s", "Missing option "name" in section "section);    \
-        return 1;                                                       \
+#define CHK_OPTION(section, name)                                               \
+    if (!database_config_exists(db, section, name)) {                           \
+        LOG_ERROR("%s", "Missing option \""name"\" in section \""section"\"");  \
+        return 1;                                                               \
     }
 
     CHK_OPTION("externals", "mkvpropedit");
@@ -171,6 +171,12 @@ validate_conf(volatile sqlite3 *db)
     CHK_OPTION("database", "kara_dir");
     CHK_OPTION("database", "db_path");
 
+    CHK_OPTION("repo", "name");
+    CHK_OPTION("repo", "url");
+    CHK_OPTION("repo", "json");
+    CHK_OPTION("repo", "id_json");
+    CHK_OPTION("repo", "id_kara");
+
     CHK_OPTION("player", "autoclear");
     CHK_OPTION("player", "def_random");
     CHK_OPTION("player", "def_consume");
diff --git a/src/database/stickers.c b/src/database/stickers.c
index a0a7c7f001c9961549b5f016f6e859501e04bbe0..8863b827b0d3ac61f982c31ff1d42f0180c3d811 100644
--- a/src/database/stickers.c
+++ b/src/database/stickers.c
@@ -100,7 +100,7 @@ database_sticker_delete_specify(volatile sqlite3 *db, const char *type, int uri,
     }
 
     safe_snprintf(SQL, LKT_MAX_SQLITE_STATEMENT, "DELETE FROM 'stickers.%s' "
-             "WHERE 'stickers.%s' = ? ", type, type);
+                  "WHERE 'stickers.%s' = ? ", type, type);
 
     /* If there is a name specified. */
     if (!name) {
diff --git a/src/database/update.c b/src/database/update.c
index 145a60199a5eccdded3248c6c834ae3e27ab8145..369df055ec700de599b43b47300194508d5c0f5c 100644
--- a/src/database/update.c
+++ b/src/database/update.c
@@ -21,21 +21,44 @@ database_add_kara(volatile sqlite3 *db, const char *filename)
         "INSERT INTO "
         "kara (song_name, source_name, category, song_type, language, file_path, is_new, author_name, author_year, song_number)"
         "SELECT ?, ?, ?, ?, ?, ?, ?, ?, strftime('%s','now'), ?";
+    static const char *SQL_STMT_WITH_ID =
+        "INSERT INTO "
+        "kara (song_name, source_name, category, song_type, language, file_path, is_new, author_name, author_year, song_number, id)"
+        "SELECT ?, ?, ?, ?, ?, ?, ?, ?, strftime('%s','now'), ?, ?";
     sqlite3_stmt *stmt = NULL;
-    int code = SQLITE_OK, status = false;
+    long code = SQLITE_OK, status = false, kara_id;
     struct kara_metadata data;
     time_t the_time = time(NULL);
     struct tm *the_local_time = localtime(&the_time);
-    char year[10];
+    char year[10], path[PATH_MAX], *saveptr = NULL, *token, *id = NULL;
+
+    /* A timestamp */
     code = safe_snprintf(year, 10, "%d", the_local_time->tm_year + 1900);
     RETURN_IF(code < 0 || code >= 10, "Failed to get the year of the current date", false);
 
+    /* Metadata */
     if (kara_metadata_read(&data, filename) != 0) {
         LOG_ERROR("Failed to get mdt for the kara '%s'", filename);
         return false;
     }
 
-    SQLITE_PREPARE(db, stmt, SQL_STMT, error);
+    /* Try to find an id in the filename, reuse of variables, it's ugly */
+    path[PATH_MAX - 1] = '\0';
+    memcpy(path, filename, (strlen(filename) + 1) * sizeof(char));
+    while (NULL != (token = strtok_r(path, "/", &saveptr)))
+        id = token;
+    size_t id_len = strspn(id, "0123456789");
+    id[id_len] = '\0';  /* Replace the . of .mkv */
+    STRTOL(kara_id, id, token, id_len);
+    if (!id_len && STR_MATCH(&token[1], "mkv")) {
+        /* Use the found id, most of the time, normally */
+        LOG_INFO_SCT("DB", "Found id '%ld' in kara '%s'", kara_id, filename);
+        SQLITE_PREPARE(db, stmt, SQL_STMT_WITH_ID, error);
+        SQLITE_BIND_INT(db, stmt, 10, (int) kara_id, error);
+    } else {
+        /* Generate a new id */
+        SQLITE_PREPARE(db, stmt, SQL_STMT, error);
+    }
 
     if ((sqlite3_bind_text(stmt, 1, data.song_name,   -1, 0) != SQLITE_OK)  ||
         (sqlite3_bind_text(stmt, 2, data.source_name, -1, 0) != SQLITE_OK)  ||
@@ -50,7 +73,6 @@ database_add_kara(volatile sqlite3 *db, const char *filename)
         LOG_ERROR_SCT("DB", "Failed to bind for kara %s: %s", filename, sqlite3_errmsg((sqlite3 *) db));
         goto error;
     }
-
     SQLITE_STEP_DONE(db, stmt, error);
     status = true;
 error:
@@ -121,7 +143,7 @@ error_no_sqlite:
 }
 
 bool
-database_update(volatile sqlite3 *db, const char *kara_dir)
+database_update(volatile sqlite3 *db, const char *kara_dir, int check_timestamp)
 {
     DIR *d;
     struct dirent *dir;
@@ -139,8 +161,10 @@ database_update(volatile sqlite3 *db, const char *kara_dir)
         strncat(path, dir->d_name, PATH_MAX - 1);
 
         if (dir->d_type == DT_REG) {
-            if (get_mtime(path) < database_get_timestamp(db))
+            if (check_timestamp && get_mtime(path) < database_get_timestamp(db)) {
+                LOG_INFO_SCT("DB", "Skip update of kara '%s' be cause of timestamps", path);
                 continue;
+            }
             database_add_kara(db, path);
             database_stamp(db);
         }
@@ -148,7 +172,7 @@ database_update(volatile sqlite3 *db, const char *kara_dir)
         else if (dir->d_type == DT_DIR          &&
                  !STR_MATCH(dir->d_name, ".")   &&
                  !STR_MATCH(dir->d_name, ".."))
-            database_update(db, path);
+            database_update(db, path, check_timestamp);
     }
 
     LOG_INFO("Passed directory '%s'", kara_dir);
diff --git a/src/main/lktadm.c b/src/main/lktadm.c
index d4b25a85a70ef67216438c99410045e56ca384cf..78d00eb952b91342a822b58675804d961aa6ef64 100644
--- a/src/main/lktadm.c
+++ b/src/main/lktadm.c
@@ -34,8 +34,7 @@ fail(const char *format, ...)
  * ----------------- */
 
 static sqlite3 *db = NULL;
-static char kara_dir[PATH_MAX], db_path[PATH_MAX], mkvpropedit[PATH_MAX], sqlite3_bin[PATH_MAX],
-       init_script[PATH_MAX], buf[100];
+static char kara_dir[PATH_MAX], db_path[PATH_MAX], mkvpropedit[PATH_MAX], buf[100];
 
 void
 open_db(void)
@@ -49,17 +48,11 @@ open_db(void)
     if (!database_config_get_text(db, "externals", "mkvpropedit", mkvpropedit, PATH_MAX))
         fail("Not found externals->mkvpropedit");
 
-    if (!database_config_get_text(db, "externals", "sqlite3", sqlite3_bin, PATH_MAX))
-        fail("Not found externals->sqlite3");
-
     if (!database_config_get_text(db, "database", "db_path", db_path, PATH_MAX))
         fail("Not found database->db_path");
 
     if (!database_config_get_text(db, "database", "kara_dir", kara_dir, PATH_MAX))
         fail("Not found database->kara_dir");
-
-    if (!database_config_get_text(db, "database", "init_script", init_script, PATH_MAX))
-        fail("Not found database->init_script");
 }
 
 noreturn void
@@ -108,7 +101,7 @@ init_populate__(struct lkt_cmd_args *args)
     open_db();
     if (!database_open(db, db_path))
         fail("Failed to open database");
-    database_update(db, kara_dir);
+    database_update(db, kara_dir, false);
     sqlite3_close(db);
     exit(EXIT_SUCCESS);
 }
@@ -171,8 +164,11 @@ get__(struct lkt_cmd_args *args)
         fail("Invalid argument");
 
     int i = atoi(args->argv[0]);
+    open_db();
+    if (!database_open(db, db_path))
+        fail("Failed to open database");
 
-    if (repo_new(&repo, "kurisu", "https://kurisu.iiens.net", NULL))
+    if (repo_new(&repo, db))
         fail("Cound not create repo");
 
     if (repo_get_id(&repo, i, &data))
@@ -208,8 +204,11 @@ download__(struct lkt_cmd_args *args)
     struct lkt_repo repo;
     struct kara_metadata data;
     int i = atoi(args->argv[0]);
+    open_db();
+    if (!database_open(db, db_path))
+        fail("Failed to open database");
 
-    if (repo_new(&repo, "kurisu", "https://kurisu.iiens.net", NULL))
+    if (repo_new(&repo, db))
         fail("Could not create the repo");
 
     if (repo_download_id_sync(&repo, i, args->argv[1], &data))
@@ -259,6 +258,12 @@ source__(struct lkt_cmd_args *args)
     CHK_OPTION("player", "def_single");
     CHK_OPTION("player", "def_repeat");
 
+    CHK_OPTION("repo", "name");
+    CHK_OPTION("repo", "url");
+    CHK_OPTION("repo", "json");
+    CHK_OPTION("repo", "id_json");
+    CHK_OPTION("repo", "id_kara");
+
     CHK_OPTION("database", "kara_dir");
     CHK_OPTION("database", "db_path");
 
diff --git a/src/net/downloader.c b/src/net/downloader.c
index 9645a50b446424eccad001a8fae29b33cb9841e7..b25ebac890df8e24b9ce60e3f6a43c0010beda0b 100644
--- a/src/net/downloader.c
+++ b/src/net/downloader.c
@@ -52,8 +52,9 @@ write_disk__(char *data, size_t size, size_t nmem, void *user)
 }
 
 int
-repo_new(struct lkt_repo *const repo_, const char *name_, const char *url_, volatile sqlite3 *db)
+repo_new(struct lkt_repo *const repo_, volatile sqlite3 *db)
 {
+    RETURN_UNLESS(db, "Invalid argument", 1);
     if (!curl_init) {
         curl_global_init(CURL_GLOBAL_ALL);
         curl_init = 1;
@@ -61,19 +62,24 @@ repo_new(struct lkt_repo *const repo_, const char *name_, const char *url_, vola
         ++curl_init;
 
     struct lkt_repo repo = {
-        /* Just the repo */
-        .name = name_,
-        .base_url = url_,
-        .get_id_json = GET_ID_JSON,
-        .get_id_file = GET_ID_FILE,
-        .get_all_json = DEFAULT_URL "/api_karas.php", // TODO
-        .kara_dir = "/home/kara/", // TODO
         .version = 1,
-
-        /* The db */
         .db = db,
+        .name         = safe_zero_malloc(INI_MAX_LINE_LEN * sizeof(char)),
+        .kara_dir     = safe_zero_malloc(PATH_MAX * sizeof(char)),
+        .get_id_json  = safe_zero_malloc(URL_MAX_LEN * sizeof(char)),
+        .get_id_file  = safe_zero_malloc(URL_MAX_LEN * sizeof(char)),
+        .get_all_json = safe_zero_malloc(URL_MAX_LEN * sizeof(char)),
+        .base_url     = safe_zero_malloc(URL_MAX_LEN * sizeof(char)),
     };
 
+    /* Copies */
+    if (!database_config_get_text(db, "database", "kara_dir", repo.kara_dir, PATH_MAX - 1)  ||
+        !database_config_get_text(db, "repo", "name",    repo.name, INI_MAX_LINE_LEN)       ||
+        !database_config_get_text(db, "repo", "url",     repo.base_url, URL_MAX_LEN)        ||
+        !database_config_get_text(db, "repo", "id_json", repo.get_id_json, URL_MAX_LEN)     ||
+        !database_config_get_text(db, "repo", "id_kara", repo.get_id_file, URL_MAX_LEN)     ||
+        !database_config_get_text(db, "repo", "json",    repo.get_all_json, URL_MAX_LEN))
+        return 1;
     memcpy(repo_, &repo, sizeof(struct lkt_repo));
     return 0;
 }
@@ -85,6 +91,11 @@ repo_free(struct lkt_repo *const repo)
     --curl_init;
     if (!curl_init)
         curl_global_cleanup();
+    free(repo->kara_dir);
+    free(repo->get_id_json);
+    free(repo->get_id_file);
+    free(repo->base_url);
+    free(repo->get_all_json);
 }
 
 int
@@ -137,11 +148,9 @@ int
 __json_sync(struct lkt_repo *const repo, struct json_object **json)
 {
     RETURN_UNLESS(json, "Invalid argument", 1);
-
     CURL *curl_handle;
     CURLcode res;
     int ret = 1;
-
     struct memory file = {
         .mem = NULL,
         .size = 0.
@@ -170,14 +179,12 @@ err:
 int
 repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata *mdt)
 {
+    RETURN_UNLESS(mdt, "Invalid argument", 1);
     CURL *curl_handle;
     CURLcode res;
     struct json_object *jobj, *field;
     int ret = 1, err = 0;
     char url[URL_MAX_LEN];
-
-    RETURN_UNLESS(mdt, "Invalid argument", 1);
-
     struct memory file = {
         .mem = NULL,
         .size = 0,
@@ -203,41 +210,19 @@ repo_get_id(struct lkt_repo *const repo, const uint64_t id, struct kara_metadata
     /* Read the json. */
 
     jobj = json_tokener_parse(file.mem);
-
     if (json_object_object_get_ex(jobj, "message", &field)) {
         LOG_ERROR("Kara with id %lu not found, message is: %s", id, json_object_get_string(field));
         goto err;
     }
 
     LOG_INFO("Got kara with id %lu", id);
-
-    err |= safe_json_get_string(jobj, "song_name", mdt->song_name, LEKTOR_TAG_MAX);
-    err |= safe_json_get_string(jobj, "source_name", mdt->source_name, LEKTOR_TAG_MAX);
-    err |= safe_json_get_string(jobj, "category", mdt->category, LEKTOR_TAG_MAX);
-    err |= safe_json_get_string(jobj, "language", mdt->language, LEKTOR_TAG_MAX);
-    err |= safe_json_get_string(jobj, "author_name", mdt->author_name, LEKTOR_TAG_MAX);
-    err |= safe_json_get_string(jobj, "song_type", mdt->song_type, LEKTOR_TAG_MAX);
-
-    errno = 0;
-
-    if (!json_object_object_get_ex(jobj, "song_number", &field)) {
-        LOG_ERROR("%s", "No object with key 'song_number' in json, error");
-        goto err;
-    }
-
-    mdt->song_number = json_object_get_int(field);
-
-    if (errno == EINVAL) {
-        LOG_ERROR("%s", "Invalid integer for field with key 'song_number'");
-        goto err;
-    }
-
-    if (mdt->song_number == INT32_MAX || mdt->song_number == INT32_MIN) {
-        LOG_ERROR("Out of bound int32_t '%d' for field with key 'song_number'", mdt->song_number);
-        goto err;
-    }
-
-
+    err |= safe_json_get_string(jobj, "song_name",          mdt->song_name,     LEKTOR_TAG_MAX);
+    err |= safe_json_get_string(jobj, "source_name",        mdt->source_name,   LEKTOR_TAG_MAX);
+    err |= safe_json_get_string(jobj, "category",           mdt->category,      LEKTOR_TAG_MAX);
+    err |= safe_json_get_string(jobj, "language",           mdt->language,      LEKTOR_TAG_MAX);
+    err |= safe_json_get_string(jobj, "author_name",        mdt->author_name,   LEKTOR_TAG_MAX);
+    err |= safe_json_get_string(jobj, "song_type",          mdt->song_type,     LEKTOR_TAG_MAX);
+    GOTO_IF(err || safe_json_get_int32(jobj, "song_number", &mdt->song_number), "Invalid json", err);
     ret = 0;
 err:
     json_object_put(jobj); /* Delete object. */
@@ -337,7 +322,7 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec
     size_t i, len = json_object_array_length(json);
     struct json_object *kara_json;
     int32_t integer, err;
-    struct kara *kara;
+    struct kara kara;
     char url[URL_MAX_LEN];
     long filestamp, timestamp;
     RETURN_UNLESS(len > 0 && json_object_get_array(json), "Json invalid or array empty", NOTHING);
@@ -345,74 +330,61 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec
     LOG_INFO_SCT("REPO", "Starting to process json for repo %s", repo->name);
     for (i = 0; i < len; ++i) {
         kara_json = json_object_array_get_idx(json, i);
-        kara = calloc(1, sizeof(struct kara));
-        RETURN_UNLESS(kara, "Out of memory", NOTHING);
         err = 0;
 
         /* Get the id of the kara. */
         if (safe_json_get_int32(kara_json, "id", &integer))
             continue;
-        kara->id = integer;
+        kara.id = integer;
 
         /* Craft a fake filepath here, it will be used later. */
         size_t kara_dir_len = strlen(repo->kara_dir);
-        memcpy(kara->filename, repo->kara_dir, sizeof(char) * (kara_dir_len + 1));
-        if (kara->filename[kara_dir_len - 1] != '/') {
-            strncat(kara->filename, "/", PATH_MAX - 1);
-            kara->filename[++kara_dir_len] = 0;
+        memcpy(kara.filename, repo->kara_dir, sizeof(char) * (kara_dir_len + 1));
+        if (kara.filename[kara_dir_len - 1] != '/') {
+            strncat(kara.filename, "/", PATH_MAX - 1);
+            kara.filename[++kara_dir_len] = 0;
         }
-        safe_snprintf(kara->filename + kara_dir_len, PATH_MAX - kara_dir_len, "%d.mkv", integer);
-        LOG_INFO_SCT("REPO", "Crafted filename is '%s'", kara->filename);
+        safe_snprintf(kara.filename + kara_dir_len, PATH_MAX - kara_dir_len, "%d.mkv", integer);
 
         /* Timestamp verification */
         if (safe_json_get_long(kara_json, "unix_timestamp", &timestamp))
             continue;
-        filestamp = get_mtime(kara->filename);
-        if (database_get_timestamp(db) < filestamp) {
-            LOG_WARN_SCT("REPO", "Kara file %s is more recent than database timestamp, download it", kara->filename);
-            goto do_it;
-        }
-        if (filestamp > timestamp) {
-            LOG_INFO_SCT("REPO", "Ignore kara '%ld', last timestamp was %ld, new is %ld", kara->id, filestamp, timestamp);
+        filestamp = get_mtime(kara.filename);
+        if (database_get_timestamp(db) >= filestamp && filestamp > timestamp) {
+            LOG_INFO_SCT("REPO", "Ignore kara '%ld' with path '%s'", kara.id, kara.filename);
             continue;
         }
-do_it:
-
-        err |= safe_json_get_string(kara_json, "song_name",   kara->mdt.song_name,   LEKTOR_TAG_MAX);
-        err |= safe_json_get_string(kara_json, "source_name", kara->mdt.source_name, LEKTOR_TAG_MAX);
-        err |= safe_json_get_string(kara_json, "category",    kara->mdt.category,    LEKTOR_TAG_MAX);
-        err |= safe_json_get_string(kara_json, "language",    kara->mdt.language,    LEKTOR_TAG_MAX);
-        err |= safe_json_get_string(kara_json, "author_name", kara->mdt.author_name, LEKTOR_TAG_MAX);
-        err |= safe_json_get_string(kara_json, "song_type",   kara->mdt.song_type,   LEKTOR_TAG_MAX);
-        GOTO_IF(err, "Invalid json", err);
-
-        if (safe_json_get_int32(kara_json, "song_number", &kara->mdt.song_number))
-            goto err;
-
-        if (!database_update_add((sqlite3 *) db, kara->filename, &kara->mdt, kara->id, false)) {
-            LOG_ERROR_SCT("REPO", "Could not add unavailable kara %ld to db", kara->id);
+        LOG_WARN_SCT("REPO", "Download kara '%ld' with path '%s'", kara.id, kara.filename);
+
+        err |= safe_json_get_string(kara_json, "song_name",   kara.mdt.song_name,   LEKTOR_TAG_MAX);
+        err |= safe_json_get_string(kara_json, "source_name", kara.mdt.source_name, LEKTOR_TAG_MAX);
+        err |= safe_json_get_string(kara_json, "category",    kara.mdt.category,    LEKTOR_TAG_MAX);
+        err |= safe_json_get_string(kara_json, "language",    kara.mdt.language,    LEKTOR_TAG_MAX);
+        err |= safe_json_get_string(kara_json, "author_name", kara.mdt.author_name, LEKTOR_TAG_MAX);
+        err |= safe_json_get_string(kara_json, "song_type",   kara.mdt.song_type,   LEKTOR_TAG_MAX);
+        RETURN_IF(err || safe_json_get_int32(kara_json, "song_number", &kara.mdt.song_number),
+                  "Invalid json", NOTHING);
+
+        if (!database_update_add((sqlite3 *) db, kara.filename, &kara.mdt, kara.id, false)) {
+            LOG_ERROR_SCT("REPO", "Could not add unavailable kara %ld to db", kara.id);
             continue;
         }
 
-        safe_snprintf(url, URL_MAX_LEN, repo->get_id_file, kara->id);
+        safe_snprintf(url, URL_MAX_LEN, repo->get_id_file, kara.id);
 
-        if (__download_kara(url, kara->filename, true)) {
-            LOG_WARN_SCT("REPO", "Could not download kara %ld at path '%s'", kara->id, kara->filename);
+        if (__download_kara(url, kara.filename, true)) {
+            LOG_WARN_SCT("REPO", "Could not download kara %ld at path '%s'", kara.id, kara.filename);
             continue;
         }
 
-        if (!database_update_set_available((sqlite3 *) db, kara->id)) {
-            LOG_WARN_SCT("REPO", "Could not set kara %ld available", kara->id);
+        if (!database_update_set_available((sqlite3 *) db, kara.id)) {
+            LOG_WARN_SCT("REPO", "Could not set kara %ld available", kara.id);
             continue;
         }
 
         database_stamp(db);
-
-        LOG_INFO_SCT("REPO", "Added kara %ld from repo %s, filepath is %s", kara->id, repo->name, kara->filename);
+        LOG_INFO_SCT("REPO", "Added kara %ld from repo %s, filepath is %s", kara.id, repo->name, kara.filename);
     }
-
-err:
-    free(kara);
 }
 
 void *
@@ -421,7 +393,7 @@ __repo_get_all_id_async(void *arg)
     struct json_object *json;
     struct lkt_repo *const repo = arg;
     LOG_INFO_SCT("REPO", "Download kara list from %s (%s), directory is %s",
-                 repo->name, repo->base_url, repo->kara_dir);
+                 repo->name, repo->get_all_json, repo->kara_dir);
     __json_sync(repo, &json);
     __handle_got_json(repo->db, repo, json);
     LOG_INFO_SCT("REPO", "%s", "Finished to download and insert kara list");
diff --git a/src/net/listen.c b/src/net/listen.c
index 84ec3db308ef37eaa5a69c25adb0c7eca123369e..a31deb4425083a4274d3bd33b79f796b34d8f341 100644
--- a/src/net/listen.c
+++ b/src/net/listen.c
@@ -738,9 +738,9 @@ lkt_listen(void)
     if (autoclear)
         database_queue_clear(srv.db);
 
-    RETURN_IF    (repo_new(&srv.repo, "kurisu", "https://kurisu.iiens.net", srv.db), "Failed to create repo", 4);
-    RETURN_UNLESS(load_module_by_name(srv.db, player_mod, &srv.win),                 "Can't load module",     3);
-    RETURN_UNLESS(srv.win.new(&srv.win),                                             "Can't create window",   3);
+    RETURN_IF    (repo_new(&srv.repo, srv.db),                          "Failed to create repo", 4);
+    RETURN_UNLESS(load_module_by_name(srv.db, player_mod, &srv.win),    "Can't load module",     3);
+    RETURN_UNLESS(srv.win.new(&srv.win),                                "Can't create window",   3);
     srv.win.attach(&srv.win, &srv);
 
     for (;;) {