summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrumeet <yuuta@yuuta.moe>2023-03-19 15:51:17 -0700
committerTrumeet <yuuta@yuuta.moe>2023-03-19 15:51:17 -0700
commit92829eb1abde84916d92b22e107fc3ae7dc4bad2 (patch)
treefaf6ff5e400784c2259f645b66f287bf662b326c
parentfc54fc6a79e10701f25548d0db5b7df0144322e4 (diff)
downloadksyxbot-92829eb1abde84916d92b22e107fc3ae7dc4bad2.tar
ksyxbot-92829eb1abde84916d92b22e107fc3ae7dc4bad2.tar.gz
ksyxbot-92829eb1abde84916d92b22e107fc3ae7dc4bad2.tar.bz2
ksyxbot-92829eb1abde84916d92b22e107fc3ae7dc4bad2.zip
Refactor handle_inline()
-rw-r--r--db.c39
-rw-r--r--db.h6
-rw-r--r--query.c229
3 files changed, 129 insertions, 145 deletions
diff --git a/db.c b/db.c
index 4c340ba..4400341 100644
--- a/db.c
+++ b/db.c
@@ -30,6 +30,12 @@ sqlite3 *db = NULL;
sqlite3_stmt *stmt_global_stat = NULL;
+sqlite3_stmt *stmt_personal_stat = NULL;
+
+sqlite3_stmt *stmt_search = NULL;
+
+sqlite3_stmt *stmt_random = NULL;
+
void db_init(void) {
int r;
r = sqlite3_open(cmd.db_path, &db);
@@ -76,6 +82,27 @@ void db_init(void) {
errmsg = (char *) sqlite3_errstr(r);
goto sql_err;
}
+
+ if ((r = sqlite3_prepare_v2(db, "SELECT i FROM stats WHERE user = ?", -1, &stmt_personal_stat, NULL))) {
+ errmsg = (char *) sqlite3_errstr(r);
+ goto sql_err;
+ }
+
+ if ((r = sqlite3_prepare_v2(db, "SELECT id, t, url FROM says WHERE t LIKE ? LIMIT 10;",
+ -1,
+ &stmt_search,
+ NULL))) {
+ errmsg = (char *) sqlite3_errstr(r);
+ goto sql_err;
+ }
+
+ if ((r = sqlite3_prepare_v2(db, "SELECT id, t, url FROM says ORDER BY RANDOM() LIMIT 10;",
+ -1,
+ &stmt_random,
+ NULL))) {
+ errmsg = (char *) sqlite3_errstr(r);
+ goto sql_err;
+ }
}
void db_close(void) {
@@ -85,6 +112,18 @@ void db_close(void) {
sqlite3_finalize(stmt_global_stat);
stmt_global_stat = NULL;
}
+ if (stmt_personal_stat) {
+ sqlite3_finalize(stmt_personal_stat);
+ stmt_personal_stat = NULL;
+ }
+ if (stmt_random) {
+ sqlite3_finalize(stmt_random);
+ stmt_random = NULL;
+ }
+ if (stmt_search) {
+ sqlite3_finalize(stmt_search);
+ stmt_search = NULL;
+ }
sqlite3_close(db);
db = NULL;
}
diff --git a/db.h b/db.h
index e121593..7bfa371 100644
--- a/db.h
+++ b/db.h
@@ -15,6 +15,12 @@
extern sqlite3_stmt *stmt_global_stat;
+extern sqlite3_stmt *stmt_personal_stat;
+
+extern sqlite3_stmt *stmt_random;
+
+extern sqlite3_stmt *stmt_search;
+
extern sqlite3 *db;
void db_init(void);
diff --git a/query.c b/query.c
index 6ec7a1f..1423d65 100644
--- a/query.c
+++ b/query.c
@@ -13,17 +13,6 @@
#include <errno.h>
#include <assert.h>
-struct result {
- char id[32];
- /* Title in selection */
- char *title;
- /* Description in selection */
- char *description;
- /* Text after sending */
- char *text;
- char *url;
-};
-
static void cb_answer(bool successful, struct TdObject *result, struct TdError *error, void *cb_arg) {
if (!successful) {
LOGEV("Cannot answer inline request: %s.",
@@ -31,182 +20,132 @@ static void cb_answer(bool successful, struct TdObject *result, struct TdError *
}
}
+static struct TdInputInlineQueryResultArticle *create_inline_result(char *id,
+ char *title,
+ char *descr,
+ char *text) {
+ struct TdInputInlineQueryResultArticle *r = TdCreateObjectInputInlineQueryResultArticle(
+ id,
+ NULL,
+ false,
+ title,
+ descr,
+ NULL,
+ 0,
+ 0,
+ NULL,
+ (struct TdInputMessageContent *) TdCreateObjectInputMessageText(
+ TdCreateObjectFormattedText(text,
+ (struct TdVectorTextEntity *) TdCreateObjectVectorObject(0,
+ NULL)),
+ true,
+ false
+ ));
+ /* No allocation fail detection here */
+ return r;
+}
+
int handle_inline(struct TdUpdateNewInlineQuery *update) {
- struct result results[11];
- memset(results, 0, sizeof(results));
- sqlite3_stmt *stmt;
int r;
+ /* May return < 10 rows. Start with 0, so we can free the initial stat one if that produces an error. */
+ int effective_items_count = 0;
+ struct TdInputInlineQueryResultArticle *results_inline[11];
const bool query = update->query_;
+ char *query_str = NULL;
+ int personal_stat = 0;
+ char id_temp[32];
+ char msg_stat[32];
+ sqlite3_stmt *stmt_query = query ? stmt_search : stmt_random;
- if ((r = sqlite3_prepare_v2(db, "SELECT i FROM stats WHERE user = ?", -1, &stmt, NULL))) {
- goto sql_err;
- sql_err:
- 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;
- if (stmt) sqlite3_finalize(stmt);
- goto answer;
- }
+ memset(results_inline, 0, sizeof(results_inline));
- if ((r = sqlite3_bind_int64(stmt, 1, update->sender_user_id_))) {
+ if ((r = sqlite3_bind_int64(stmt_personal_stat, 1, update->sender_user_id_))) {
goto sql_err;
+ sql_err:
+ LOGEV("Cannot query: %s.", sqlite3_errstr(r));
+ for (int i = 0; i < effective_items_count; i ++) {
+ TdDestroyObjectInputInlineQueryResultArticle(results_inline[i]);
+ }
+ goto cleanup;
}
- char msg_stat[32];
- int st;
- switch (r = sqlite3_step(stmt)) {
+ switch (r = sqlite3_step(stmt_personal_stat)) {
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_);
+ personal_stat = sqlite3_column_int(stmt_personal_stat, 0);
break;
}
case SQLITE_DONE: {
- st = 0;
- goto st_answer;
+ break;
}
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;
- }
+ snprintf(msg_stat, sizeof(msg_stat), "我已经卖了 %d 句菜", personal_stat);
+ snprintf(id_temp, sizeof(id_temp), "s%lld", update->sender_user_id_);
+ results_inline[0] = create_inline_result(id_temp, "卖菜统计", "点击发送卖菜统计", msg_stat);
+ effective_items_count ++;
- char *query_str = NULL;
if (query) {
const size_t raw_query_len = strlen(update->query_);
if (!(query_str = calloc(raw_query_len + 3, sizeof(char)))) {
r = errno;
LOGEV("Cannot allocate memory: %s.", strerror(r));
- sqlite3_finalize(stmt);
return r;
}
sprintf(query_str, "%%%s%%", update->query_);
- if ((r = sqlite3_bind_text(stmt, 1, query_str, ((int) raw_query_len + 3), NULL))) {
- free(query_str);
+ if ((r = sqlite3_bind_text(stmt_search, 1, query_str, ((int) raw_query_len + 3), NULL))) {
goto sql_err;
}
}
- int j = 1;
- goto step;
- step:
- switch (r = sqlite3_step(stmt)) {
- case SQLITE_ROW: {
- char *t = (char *) sqlite3_column_text(stmt, 1);
- char *url = (char *) sqlite3_column_text(stmt, 2);
-
- char *url1 = NULL;
- char *title = NULL;
- char *t1 = NULL;
-
- if (url && !(url1 = strdup(url))) {
- LOGEV("Cannot allocate memory: %s.", strerror(errno));
- break;
- }
- if (!(title = strdup(t))) {
- LOGEV("Cannot allocate memory: %s.", strerror(errno));
- break;
- }
- if (!(t1 = strdup(t))) {
- LOGEV("Cannot allocate memory: %s.", strerror(errno));
- break;
- }
- results[j].title = title;
- 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) > 10) break;
- goto step;
- }
- case SQLITE_DONE: {
+ for (; effective_items_count < sizeof(results_inline) / sizeof(struct TdInputInlineQueryResultArticle *);
+ effective_items_count ++) {
+ r = sqlite3_step(stmt_query);
+ if (r == SQLITE_DONE) {
break;
}
- default: {
+ if (r != SQLITE_ROW) {
goto sql_err;
}
- }
- if (query_str) free(query_str);
- sqlite3_finalize(stmt);
+ int id = sqlite3_column_int(stmt_query, 0);
+ char *t = (char *) sqlite3_column_text(stmt_query, 1);
+ char *url = (char *) sqlite3_column_text(stmt_query, 2);
- /* There must be a stat option. */
- assert(results[0].title);
- goto answer;
- answer:
- {
- 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];
- if (!res.title) {
- break;
- }
- results_inline[i] = TdCreateObjectInputInlineQueryResultArticle(
- res.id,
- NULL,
- false,
- res.title,
- res.description,
- NULL,
- 0,
- 0,
- NULL,
- (struct TdInputMessageContent *) TdCreateObjectInputMessageText(
- TdCreateObjectFormattedText(res.text,
- (struct TdVectorTextEntity *) TdCreateObjectVectorObject(0,
- NULL)),
- true,
- false
- ));
- }
- td_send(TdCreateObjectAnswerInlineQuery(update->id_,
- false,
- (struct TdVectorInputInlineQueryResult *)
- TdCreateObjectVectorObject(i,
- (struct TdObject **) results_inline),
- 0,
- NULL,
- NULL,
- NULL),
- &cb_answer,
- NULL);
- 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;
+ snprintf(id_temp, 32, "x_%d", id);
+ results_inline[effective_items_count] =
+ create_inline_result(id_temp,
+ t,
+ url,
+ t);
}
+
+ td_send(TdCreateObjectAnswerInlineQuery(update->id_,
+ false,
+ (struct TdVectorInputInlineQueryResult *)
+ TdCreateObjectVectorObject(effective_items_count,
+ (struct TdObject **) results_inline),
+ 0,
+ NULL,
+ NULL,
+ NULL),
+ &cb_answer,
+ NULL);
+
+ goto cleanup;
+ cleanup:
+ if (query_str) free(query_str);
+ sqlite3_reset(stmt_personal_stat);
+ sqlite3_reset(stmt_query);
+ return r;
}
int handle_inline_chosen(struct TdUpdateNewChosenInlineResult *update) {
if (!update->result_id_ || update->result_id_[0] != 'x' ||
- update->result_id_[1] != '_') return 0;
+ 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))) {