From 08b49f458c6adf2ac040a980cfde8ac0fdaf773f Mon Sep 17 00:00:00 2001 From: Trumeet Date: Sun, 3 Apr 2022 11:12:53 -0700 Subject: Add stats --- query.c | 130 +++++++++++++++++++++++++++++++++++++++++++++--------------- sql/1_2.sql | 9 +++++ tdutils.c | 2 + tdutils.h | 2 + 4 files changed, 110 insertions(+), 33 deletions(-) create mode 100644 sql/1_2.sql diff --git a/query.c b/query.c index b7c5058..6ec7a1f 100644 --- a/query.c +++ b/query.c @@ -14,7 +14,7 @@ #include struct result { - char id[10]; + char id[32]; /* Title in selection */ char *title; /* Description in selection */ @@ -32,31 +32,64 @@ static void cb_answer(bool successful, struct TdObject *result, struct TdError * } int handle_inline(struct TdUpdateNewInlineQuery *update) { - struct result results[10]; + struct result results[11]; memset(results, 0, sizeof(results)); sqlite3_stmt *stmt; int r; const bool query = update->query_; - bool sys = false; - if ((r = sqlite3_prepare_v2(db, - query ? "SELECT id, t, url FROM says WHERE t LIKE ? LIMIT 10;" - :"SELECT id, t, url FROM says ORDER BY RANDOM() LIMIT 10;", - -1, - &stmt, - NULL))) { + + if ((r = sqlite3_prepare_v2(db, "SELECT i FROM stats WHERE user = ?", -1, &stmt, NULL))) { goto sql_err; sql_err: - snprintf(results[0].id, 10, "e%d", r); + snprintf(results[0].id, 32, "e%d", r); char *msg = (char *) sqlite3_errstr(r); LOGEV("Cannot query: %s.", msg); results[0].title = "Error!"; results[0].text = msg; results[0].description = msg; - sys = true; - sqlite3_finalize(stmt); + if (stmt) sqlite3_finalize(stmt); goto answer; } + if ((r = sqlite3_bind_int64(stmt, 1, update->sender_user_id_))) { + goto sql_err; + } + + char msg_stat[32]; + int st; + switch (r = sqlite3_step(stmt)) { + case SQLITE_ROW: { + st = sqlite3_column_int(stmt, 0); + goto st_answer; + st_answer: + snprintf(msg_stat, 32, "我已经卖了 %d 句菜", st); + results[0].title = "卖菜统计"; + results[0].text = msg_stat; + results[0].description = "点击发送卖菜统计"; + snprintf(results[0].id, 32, "s%lld", update->sender_user_id_); + break; + } + case SQLITE_DONE: { + st = 0; + goto st_answer; + } + default: { + goto sql_err; + } + } + + sqlite3_finalize(stmt); + stmt = NULL; + + if ((r = sqlite3_prepare_v2(db, + query ? "SELECT id, t, url FROM says WHERE t LIKE ? LIMIT 10;" + : "SELECT id, t, url FROM says ORDER BY RANDOM() LIMIT 10;", + -1, + &stmt, + NULL))) { + goto sql_err; + } + char *query_str = NULL; if (query) { const size_t raw_query_len = strlen(update->query_); @@ -73,7 +106,7 @@ int handle_inline(struct TdUpdateNewInlineQuery *update) { } } - int j = 0; + int j = 1; goto step; step: switch (r = sqlite3_step(stmt)) { @@ -98,11 +131,11 @@ int handle_inline(struct TdUpdateNewInlineQuery *update) { break; } results[j].title = title; - snprintf(results[j].id, 10, "%d", sqlite3_column_int(stmt, 0)); + snprintf(results[j].id, 32, "x_%d", sqlite3_column_int(stmt, 0)); results[j].text = t1; results[j].url = url1; results[j].description = url1; - if ((++j) > 9) break; + if ((++j) > 10) break; goto step; } case SQLITE_DONE: { @@ -116,19 +149,12 @@ int handle_inline(struct TdUpdateNewInlineQuery *update) { if (query_str) free(query_str); sqlite3_finalize(stmt); - if (!j) { - results[0].title = "No data"; - results[0].description = "No data is available."; - sprintf(results[0].id, "e_nodat"); - results[0].text = "No data is available. Adjust your search terms or check it out later.\n\n" - "https://www.youtube.com/watch?v=dQw4w9WgXcQ"; - sys = true; - } + /* There must be a stat option. */ assert(results[0].title); goto answer; answer: { - struct TdInputInlineQueryResultArticle *results_inline[10]; /* No need to memset(). Var 'i' will assure that. */ + struct TdInputInlineQueryResultArticle *results_inline[11]; /* No need to memset(). Var 'i' will assure that. */ int i; for (i = 0; i < sizeof(results) / sizeof(struct result); i++) { struct result res = results[i]; @@ -164,17 +190,55 @@ int handle_inline(struct TdUpdateNewInlineQuery *update) { NULL), &cb_answer, NULL); - if (!sys) { - for (i = 0; i < sizeof(results) / sizeof(struct result); i++) { - struct result res = results[i]; - if (!res.title) { - break; - } - free(res.title); - if (res.url) free(res.url); - free(res.text); + for (i = 1 /* 0 is error message or stats */; + i < sizeof(results) / sizeof(struct result); i++) { + struct result res = results[i]; + if (!res.title) { + break; } + free(res.title); + if (res.url) free(res.url); + free(res.text); } return r; } } + +int handle_inline_chosen(struct TdUpdateNewChosenInlineResult *update) { + if (!update->result_id_ || update->result_id_[0] != 'x' || + update->result_id_[1] != '_') return 0; + int r; + sqlite3_stmt *stmt = NULL; + if ((r = sqlite3_prepare_v2(db, "UPDATE stats SET i = i + 1 WHERE user = ?;", -1, &stmt, NULL))) { + goto sql_err; + sql_err: + LOGEV("Cannot change stat: %s.", sqlite3_errstr(r)); + if (stmt) sqlite3_finalize(stmt); + return r; + } + if ((r = sqlite3_bind_int64(stmt, 1, update->sender_user_id_))) { + goto sql_err; + } + if ((r = sqlite3_step(stmt)) != SQLITE_DONE) { + goto sql_err; + } + sqlite3_finalize(stmt); + stmt = NULL; + if (sqlite3_changes(db)) { + return 0; + } + if ((r = sqlite3_prepare_v2(db, "INSERT INTO stats(user, i) VALUES(?, 1);", + -1, + &stmt, + NULL))) { + goto sql_err; + } + if ((r = sqlite3_bind_int64(stmt, 1, update->sender_user_id_))) { + goto sql_err; + } + if ((r = sqlite3_step(stmt)) != SQLITE_DONE) { + goto sql_err; + } + sqlite3_finalize(stmt); + return 0; +} diff --git a/sql/1_2.sql b/sql/1_2.sql new file mode 100644 index 0000000..37d2168 --- /dev/null +++ b/sql/1_2.sql @@ -0,0 +1,9 @@ +-- Add stats +CREATE TABLE "stats" +( + "user" INTEGER UNIQUE, + "i" INTEGER NOT NULL, + PRIMARY KEY("user") +); + +PRAGMA user_version = 2; \ No newline at end of file diff --git a/tdutils.c b/tdutils.c index 89fb3b2..0df00c3 100644 --- a/tdutils.c +++ b/tdutils.c @@ -323,6 +323,8 @@ static int handle_update(const struct TdUpdate *update) { return handle_inline((struct TdUpdateNewInlineQuery *) update); case CODE_UpdateOption: return handle_option((struct TdUpdateOption *) update); + case CODE_UpdateNewChosenInlineResult: + return handle_inline_chosen((struct TdUpdateNewChosenInlineResult *) update); default: return 0; } diff --git a/tdutils.h b/tdutils.h index c0653d5..db2f6de 100644 --- a/tdutils.h +++ b/tdutils.h @@ -25,4 +25,6 @@ int handle_message(struct TdUpdateNewMessage *update); int handle_inline(struct TdUpdateNewInlineQuery * update); +int handle_inline_chosen(struct TdUpdateNewChosenInlineResult *); + #endif /* _TDUTILS_H */ \ No newline at end of file -- cgit v1.2.3