]> jfr.im git - irc/quakenet/newserv.git/blobdiff - a4stats/a4stats_db.c
Merge pull request #51 from retropc/chanserv-live
[irc/quakenet/newserv.git] / a4stats / a4stats_db.c
index 962fb6bf653cb62bf79dc9f67f1d4dde4cf309f9..dbcbe715245005ed590007b1fd5319dd9307fbbb 100644 (file)
@@ -14,6 +14,9 @@
 #define CLEANUP_INACTIVE_DAYS 30 /* disable channels where nothing happened for this many days */
 #define CLEANUP_DELETE_DAYS 5 /* delete data for channels that have been disabled for this many days */
 
+#define A4STATS_DB_TOLOWER(x) "translate(lower(" x "), E'[]\\\\~', '{}|^')"
+#define A4STATS_DB_EQ_NOCASE(x, y) A4STATS_DB_TOLOWER(x) " = " A4STATS_DB_TOLOWER(y)
+
 MODULE_VERSION("");
 
 DBAPIConn *a4statsdb;
@@ -151,56 +154,6 @@ static void a4stats_delete_dci(db_callback_info *dci) {
   free(dci);
 }
 
-static void a4stats_fetch_user_cb(const struct DBAPIResult *result, void *uarg) {
-  db_callback_info *dci = uarg;
-  time_t seen = 0, quotereset = 0;
-
-  if (result) {
-    if (result->success) {
-      while (result->next(result)) {
-        seen = (result->get(result, 0)) ? (time_t)strtoul(result->get(result, 0), NULL, 10) : 0;
-        quotereset = (result->get(result, 1)) ? (time_t)strtoul(result->get(result, 1), NULL, 10) : 0;
-      }
-    }
-
-    result->clear(result);
-  }
-
-  if (dci->interp) {
-    lua_vpcall(dci->interp, dci->callback, "llR", (long)seen, (long)quotereset, dci->uarg_index);
-    luaL_unref(dci->interp, LUA_REGISTRYINDEX, dci->uarg_index);
-  }
-
-  a4stats_delete_dci(dci);
-}
-
-static int a4stats_lua_fetch_user(lua_State *ps) {
-  const char *account, *callback;
-  unsigned long channelid, accountid;
-  db_callback_info *dci;
-
-  if (!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isnumber(ps, 3) || !lua_isstring(ps, 4))
-    LUA_RETURN(ps, LUA_FAIL);
-
-  channelid = lua_tonumber(ps, 1);
-  account = lua_tostring(ps, 2);
-  accountid = lua_tonumber(ps, 3);
-  callback = lua_tostring(ps, 4);
-
-  dci = malloc(sizeof(*dci));
-  dci->interp = ps;
-
-  strncpy(dci->callback, callback, sizeof(dci->callback));
-  dci->callback[sizeof(dci->callback) - 1] = '\0';
-
-  lua_pushvalue(ps, 5);
-  dci->uarg_index = luaL_ref(ps, LUA_REGISTRYINDEX);
-
-  a4statsdb->query(a4statsdb, a4stats_fetch_user_cb, dci, "SELECT seen, quotereset FROM ? WHERE channelid = ? AND (accountid != 0 AND accountid = ? OR accountid = 0 AND account = ?)", "TUUs", "users", channelid, accountid, account);
-
-  LUA_RETURN(ps, LUA_OK);
-}
-
 typedef struct user_update_info {
   int stage;
   char *update;
@@ -224,11 +177,15 @@ static void a4stats_update_user_cb(const struct DBAPIResult *result, void *uarg)
       free(uui->update);
       free(uui->account);
       free(uui);
-      return;
+      goto a4_uuc_return;
     }
 
     a4statsdb->query(a4statsdb, a4stats_update_user_cb, uui, "INSERT INTO ? (channelid, account, accountid, firstseen) VALUES (?, ?, ?, ?)", "TUsUt", "users", uui->channelid, uui->account, uui->accountid, time(NULL));
   }
+
+a4_uuc_return:
+  if (result)
+    result->clear(result);
 }
 
 static int a4stats_lua_update_user(lua_State *ps) {
@@ -297,11 +254,11 @@ static void a4stats_update_relation_cb(const struct DBAPIResult *result, void *u
     a4statsdb->query(a4statsdb, a4stats_update_relation_cb, rui, "UPDATE ? SET score = score + 1, seen = ? "
       "WHERE channelid = ? AND first = ? AND firstid = ? AND second = ? AND secondid = ?",
       "TtUsUsU", "relations", time(NULL), rui->channelid, rui->first, rui->firstid, rui->second, rui->secondid);
-    return;
+    goto a4_urc_return;
   } else if (rui->stage == 2 && result && result->affected == 0) {
     a4statsdb->query(a4statsdb, a4stats_update_relation_cb, rui, "INSERT INTO ? (channelid, first, firstid, second, secondid, seen) VALUES (?, ?, ?, ?, ?, ?)",
       "TUsUsUt", "relations", rui->channelid, rui->first, rui->firstid, rui->second, rui->secondid, time(NULL));
-    return;
+    goto a4_urc_return;
   }
 
   if (!result || result->affected == 0)
@@ -310,6 +267,10 @@ static void a4stats_update_relation_cb(const struct DBAPIResult *result, void *u
   free(rui->first);
   free(rui->second);
   free(rui);
+
+a4_urc_return:
+  if (result)
+    result->clear(result);
 }
 
 static int a4stats_lua_update_relation(lua_State *ps) {
@@ -358,7 +319,7 @@ static int a4stats_lua_add_line(lua_State *ps) {
   channel = lua_tostring(ps, 1);
   hour = lua_tonumber(ps, 2);
 
-  snprintf(query, sizeof(query), "UPDATE ? SET h%d = h%d + 1 WHERE name = ?", hour, hour);
+  snprintf(query, sizeof(query), "UPDATE ? SET h%d = h%d + 1 WHERE " A4STATS_DB_EQ_NOCASE("name", "?"), hour, hour);
 
   a4statsdb->squery(a4statsdb, query, "Ts", "channels", channel);
 
@@ -508,7 +469,7 @@ static int a4stats_lua_enable_channel(lua_State *ps) {
     LUA_RETURN(ps, LUA_FAIL);
 
   a4statsdb->squery(a4statsdb, "INSERT INTO ? (name, timestamp) VALUES (?, ?)", "Tst", "channels", lua_tostring(ps, 1), time(NULL));
-  a4statsdb->squery(a4statsdb, "UPDATE ? SET active = 1, deleted = 0 WHERE name = ?", "Ts", "channels", lua_tostring(ps, 1));
+  a4statsdb->squery(a4statsdb, "UPDATE ? SET active = 1, deleted = 0 WHERE " A4STATS_DB_EQ_NOCASE("name", "?"), "Ts", "channels", lua_tostring(ps, 1));
 
   LUA_RETURN(ps, LUA_OK);
 }
@@ -517,8 +478,22 @@ static int a4stats_lua_disable_channel(lua_State *ps) {
   if (!lua_isstring(ps, 1))
     LUA_RETURN(ps, LUA_FAIL);
 
-  a4statsdb->squery(a4statsdb, "UPDATE ? SET active = 0, deleted = ? WHERE name = ?", "Tts", "channels", time(NULL), lua_tostring(ps, 1));
+  a4statsdb->squery(a4statsdb, "UPDATE ? SET active = 0, deleted = ? WHERE " A4STATS_DB_EQ_NOCASE("name", "?"), "Tts", "channels", time(NULL), lua_tostring(ps, 1));
+
+  LUA_RETURN(ps, LUA_OK);
+}
+
+static int a4stats_lua_set_privacy(lua_State *ps) {
+  const char *channel;
+  unsigned long privacy;
+
+  if (!lua_isstring(ps, 1) || !lua_isnumber(ps, 2))
+    LUA_RETURN(ps, LUA_FAIL);
+
+  channel = lua_tostring(ps, 1);
+  privacy = lua_tonumber(ps, 2);
 
+  a4statsdb->squery(a4statsdb, "UPDATE ? SET privacy = ? WHERE " A4STATS_DB_EQ_NOCASE("name", "?"), "TUs", "channels", privacy, channel);
   LUA_RETURN(ps, LUA_OK);
 }
 
@@ -560,20 +535,32 @@ static int a4stats_lua_add_topic(lua_State *ps) {
   LUA_RETURN(ps, LUA_OK);
 }
 
+static int a4stats_lua_db_begin(lua_State *ps) {
+  a4statsdb->query(a4statsdb, NULL, NULL, "BEGIN TRANSACTION", "");
+  LUA_RETURN(ps, LUA_OK);
+}
+
+static int a4stats_lua_db_commit(lua_State *ps) {
+  a4statsdb->query(a4statsdb, NULL, NULL, "COMMIT TRANSACTION", "");
+  LUA_RETURN(ps, LUA_OK);
+}
+
 static void a4stats_hook_loadscript(int hooknum, void *arg) {
   void **args = arg;
   lua_State *l = args[1];
 
   lua_register(l, "a4_enable_channel", a4stats_lua_enable_channel);
   lua_register(l, "a4_disable_channel", a4stats_lua_disable_channel);
+  lua_register(l, "a4_set_privacy", a4stats_lua_set_privacy);
   lua_register(l, "a4_fetch_channels", a4stats_lua_fetch_channels);
   lua_register(l, "a4_add_kick", a4stats_lua_add_kick);
   lua_register(l, "a4_add_topic", a4stats_lua_add_topic);
   lua_register(l, "a4_add_line", a4stats_lua_add_line);
-  lua_register(l, "a4_fetch_user", a4stats_lua_fetch_user);
   lua_register(l, "a4_update_user", a4stats_lua_update_user);
   lua_register(l, "a4_update_relation", a4stats_lua_update_relation);
   lua_register(l, "a4_escape_string", a4stats_lua_escape_string);
+  lua_register(l, "a4_db_begin", a4stats_lua_db_begin);
+  lua_register(l, "a4_db_commit", a4stats_lua_db_commit);
 }
 
 #define lua_unregister(L, n) (lua_pushnil(L), lua_setglobal(L, n))
@@ -619,6 +606,7 @@ void _fini(void) {
 
     lua_unregister(l->l, "a4_enable_channel");
     lua_unregister(l->l, "a4_disable_channel");
+    lua_unregister(l->l, "a4_set_privacy");
     lua_unregister(l->l, "a4_fetch_channels");
     lua_unregister(l->l, "a4_add_kick");
     lua_unregister(l->l, "a4_add_topic");
@@ -627,6 +615,8 @@ void _fini(void) {
     lua_unregister(l->l, "a4_update_user");
     lua_unregister(l->l, "a4_update_relation");
     lua_unregister(l->l, "a4_escape_string");
+    lua_unregister(l->l, "a4_db_begin");
+    lua_unregister(l->l, "a4_db_commit");
   }
 
   deregisterhook(HOOK_LUA_LOADSCRIPT, a4stats_hook_loadscript);