/* * Created by yuuta on 4/1/22. */ #include "tdutils.h" #include "logic.h" #include "log.h" #include "db.h" #include #include #include #include #include static void cb_answer(bool successful, struct TdObject *result, struct TdError *error, void *cb_arg) { if (!successful) { LOGEV("Cannot answer inline request: %s.", error ? error->message_ : "(NULL)"); } } 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) { 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; int ranking = 0; int total = 0; char id_temp[32]; char msg_stat[512]; sqlite3_stmt *stmt_query = query ? stmt_search : stmt_random; memset(results_inline, 0, sizeof(results_inline)); 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; } if ((r = sqlite3_bind_int64(stmt_personal_stat, 2, update->sender_user_id_))) { goto sql_err; } switch (r = sqlite3_step(stmt_personal_stat)) { case SQLITE_ROW: { personal_stat = sqlite3_column_int(stmt_personal_stat, 0); ranking = sqlite3_column_int(stmt_personal_stat, 1); total = sqlite3_column_int(stmt_personal_stat, 2); break; } case SQLITE_DONE: { break; } default: { goto sql_err; } } if (ranking > 0) { snprintf(msg_stat, sizeof(msg_stat), "我已经卖了 %d 句菜,TGCN 排名 %d / %d", personal_stat, ranking, total); } else { snprintf(msg_stat, sizeof(msg_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++; 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)); return r; } sprintf(query_str, "%%%s%%", update->query_); if ((r = sqlite3_bind_text(stmt_search, 1, query_str, ((int) raw_query_len + 3), NULL))) { goto sql_err; } } for (; effective_items_count < sizeof(results_inline) / sizeof(struct TdInputInlineQueryResultArticle *); effective_items_count++) { r = sqlite3_step(stmt_query); if (r == SQLITE_DONE) { break; } if (r != SQLITE_ROW) { goto sql_err; } int id = sqlite3_column_int(stmt_query, 0); char *t = (char *) sqlite3_column_text(stmt_query, 1); int index = sqlite3_column_int(stmt_query, 2); char descr_temp[32]; snprintf(descr_temp, sizeof(descr_temp), "#%d", index); snprintf(id_temp, 32, "x_%d", id); results_inline[effective_items_count] = create_inline_result(id_temp, t, descr_temp, t); } td_send(TdCreateObjectAnswerInlineQuery(update->id_, /* inline_query_id */ false, /* is_personal */ NULL, /* button */ (struct TdVectorInputInlineQueryResult *) /* results */ TdCreateObjectVectorObject(effective_items_count, (struct TdObject **) results_inline), 0, /* cache_time */ NULL /* next_offset */ ), &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) { LOGDV("Handling %s", update->result_id_); 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; }