cleanup request json building

This commit is contained in:
2025-05-23 17:14:59 +02:00
parent bd63a1292e
commit 2b05e5a8f3
5 changed files with 97 additions and 32 deletions

5
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"clangd.arguments": [
"--header-insertion=never",
]
}

View File

@@ -69,9 +69,9 @@ typedef struct tgbot_cbquery_t tgbot_cbquery;
typedef void (*Callback)(tgbot *bot, tgbot_cbquery *query); typedef void (*Callback)(tgbot *bot, tgbot_cbquery *query);
/** /**
* @brief A structure to represent error codes. * @brief An enum to represent error codes.
*/ */
enum tgbot_rc { enum tgbot_rc_t {
TGBOT_OK = 0, TGBOT_OK = 0,
TGBOT_INIT_ERROR, TGBOT_INIT_ERROR,
TGBOT_REQUEST_ERROR, TGBOT_REQUEST_ERROR,
@@ -82,6 +82,22 @@ enum tgbot_rc {
TGBOT_SENDDICE_ERROR, TGBOT_SENDDICE_ERROR,
TGBOT_TELEGRAM_OK_ERROR, TGBOT_TELEGRAM_OK_ERROR,
}; };
typedef enum tgbot_rc tgbot_rc; typedef enum tgbot_rc_t tgbot_rc;
enum tgbot_json_opt_type_t {
tgbot_opt_int,
tgbot_opt_int64,
tgbot_opt_string,
tgbot_opt_inlinekeyboard,
tgbot_opt_null,
};
typedef enum tgbot_json_opt_type_t tgbot_json_opt_type;
struct tgbot_json_option_t {
char key[32];
void *value;
tgbot_json_opt_type type;
};
typedef struct tgbot_json_option_t tgbot_json_option;
#endif #endif

View File

@@ -4,6 +4,7 @@
#include "types.h" #include "types.h"
#include <json-c/json.h> #include <json-c/json.h>
json_object *tgbot_json_builder(tgbot_json_option *options, size_t optionslen);
json_object *tgbot_new_inlinekeyboardmarkup(tgbot_inlinekeyboard *keyboard); json_object *tgbot_new_inlinekeyboardmarkup(tgbot_inlinekeyboard *keyboard);
#endif #endif

View File

@@ -2,6 +2,32 @@
#include "json.h" #include "json.h"
json_object *tgbot_json_builder(tgbot_json_option *options, size_t optionslen) {
json_object *rjson = json_object_new_object();
for (size_t i = 0; i < optionslen; ++i) {
if (options[i].type == tgbot_opt_int) {
json_object_object_add(rjson, options[i].key, json_object_new_int(*((int32_t *)options[i].value)));
} else if (options[i].type == tgbot_opt_string) {
if (!options[i].value) {
continue;
}
json_object_object_add(rjson, options[i].key, json_object_new_string((char *)options[i].value));
} else if (options[i].type == tgbot_opt_int64) {
json_object_object_add(rjson, options[i].key, json_object_new_int64(*((int64_t *)options[i].value)));
} else if (options[i].type == tgbot_opt_inlinekeyboard) {
if (options[i].value != NULL) {
json_object *reply_markup = tgbot_new_inlinekeyboardmarkup((tgbot_inlinekeyboard *)options[i].value);
json_object_object_add(rjson, "reply_markup", reply_markup);
}
} else if (options[i].type == tgbot_opt_null) {
continue;
}
}
return rjson;
}
json_object *tgbot_new_inlinekeyboardmarkup(tgbot_inlinekeyboard *keyboard) { json_object *tgbot_new_inlinekeyboardmarkup(tgbot_inlinekeyboard *keyboard) {
json_object *reply_markup = json_object_new_object(); json_object *reply_markup = json_object_new_object();
json_object *inline_keyboard_array = json_object_new_array(); json_object *inline_keyboard_array = json_object_new_array();

View File

@@ -102,6 +102,8 @@ tgbot_rc tgbot_parse_message(tgbot *bot, tgbot_update *update, json_object *resu
} }
tgbot_rc tgbot_parse_cbquery(tgbot *bot, tgbot_cbquery *query, json_object *result, Callback cbq_handler) { tgbot_rc tgbot_parse_cbquery(tgbot *bot, tgbot_cbquery *query, json_object *result, Callback cbq_handler) {
/* TODO: add NULL checks */
json_object *update_id = json_object_object_get(result, "update_id"); json_object *update_id = json_object_object_get(result, "update_id");
bot->offset = json_object_get_int(update_id) + 1; bot->offset = json_object_get_int(update_id) + 1;
query->update_id = json_object_get_int(update_id); query->update_id = json_object_get_int(update_id);
@@ -110,20 +112,35 @@ tgbot_rc tgbot_parse_cbquery(tgbot *bot, tgbot_cbquery *query, json_object *resu
json_object *message = json_object_object_get(callback_query, "message"); json_object *message = json_object_object_get(callback_query, "message");
json_object *message_id = json_object_object_get(message, "message_id"); json_object *message_id = json_object_object_get(message, "message_id");
query->message_id = json_object_get_int(message_id); query->message_id = json_object_get_int(message_id);
json_object *chat = json_object_object_get(message, "chat"); json_object *chat = json_object_object_get(message, "chat");
json_object *chat_id = json_object_object_get(chat, "id"); json_object *chat_id = json_object_object_get(chat, "id");
query->chat_id = json_object_get_int64(chat_id); query->chat_id = json_object_get_int64(chat_id);
json_object *chat_username = json_object_object_get(chat, "username"); json_object *chat_username = json_object_object_get(chat, "username");
/* TODO: add NULL checks */ if (chat_username) {
strncpy(query->chat_username, json_object_get_string(chat_username), sizeof(query->chat_username) - 1); strncpy(query->chat_username, json_object_get_string(chat_username), sizeof(query->chat_username) - 1);
}
json_object *date = json_object_object_get(message, "date"); json_object *date = json_object_object_get(message, "date");
query->date = json_object_get_int(date); if (date) {
query->date = json_object_get_int(date);
}
json_object *text = json_object_object_get(message, "text"); json_object *text = json_object_object_get(message, "text");
strncpy(query->text, json_object_get_string(text), sizeof(query->text) - 1); if (text) {
strncpy(query->text, json_object_get_string(text), sizeof(query->text) - 1);
}
json_object *chat_instance = json_object_object_get(callback_query, "chat_instance"); json_object *chat_instance = json_object_object_get(callback_query, "chat_instance");
strncpy(query->chat_instance, json_object_get_string(chat_instance), sizeof(query->chat_instance) - 1); if (chat_instance) {
strncpy(query->chat_instance, json_object_get_string(chat_instance), sizeof(query->chat_instance) - 1);
}
json_object *data = json_object_object_get(callback_query, "data"); json_object *data = json_object_object_get(callback_query, "data");
strncpy(query->data, json_object_get_string(data), sizeof(query->data) - 1); if (data) {
strncpy(query->data, json_object_get_string(data), sizeof(query->data) - 1);
}
cbq_handler(bot, query); cbq_handler(bot, query);
@@ -143,6 +160,7 @@ size_t write_callback(void *ptr, size_t size, size_t nmemb, char **userdata) {
} }
tgbot_rc tgbot_request(tgbot *bot, char *url, struct memory_buffer **mb, json_object *json) { tgbot_rc tgbot_request(tgbot *bot, char *url, struct memory_buffer **mb, json_object *json) {
/* TODO: accept mb as NULL */
const char *json_string = NULL; const char *json_string = NULL;
*mb = calloc(1, sizeof(struct memory_buffer)); *mb = calloc(1, sizeof(struct memory_buffer));
@@ -154,7 +172,7 @@ tgbot_rc tgbot_request(tgbot *bot, char *url, struct memory_buffer **mb, json_ob
curl_easy_setopt(bot->curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(bot->curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(bot->curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)write_callback); curl_easy_setopt(bot->curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)write_callback);
curl_easy_setopt(bot->curl, CURLOPT_WRITEDATA, *mb); curl_easy_setopt(bot->curl, CURLOPT_WRITEDATA, *mb);
curl_easy_setopt(bot->curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(bot->curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(bot->curl, CURLOPT_TCP_KEEPALIVE, 30L); curl_easy_setopt(bot->curl, CURLOPT_TCP_KEEPALIVE, 30L);
if (json != NULL) { if (json != NULL) {
@@ -215,15 +233,14 @@ tgbot_rc tgbot_get_me(tgbot *bot, tgbot_me *me) {
tgbot_rc tgbot_send_message(tgbot *bot, int64_t chat_id, const char *text, const char *parse_mode, tgbot_inlinekeyboard *keyboard) { tgbot_rc tgbot_send_message(tgbot *bot, int64_t chat_id, const char *text, const char *parse_mode, tgbot_inlinekeyboard *keyboard) {
char url[1024]; char url[1024];
json_object *rjson = json_object_new_object(); tgbot_json_option options[4] = {
json_object_object_add(rjson, "chat_id", json_object_new_int64(chat_id)); {"chat_id", &chat_id, tgbot_opt_int64},
json_object_object_add(rjson, "text", json_object_new_string(text)); {"text", (void *)text, tgbot_opt_string},
json_object_object_add(rjson, "parse_mode", json_object_new_string(parse_mode)); {"parse_mode", (void *)parse_mode, tgbot_opt_string},
{"reply_markup", keyboard, tgbot_opt_inlinekeyboard},
};
if (keyboard != NULL) { json_object *rjson = tgbot_json_builder(options, 4);
json_object *reply_markup = tgbot_new_inlinekeyboardmarkup(keyboard);
json_object_object_add(rjson, "reply_markup", reply_markup);
}
snprintf(url, sizeof(url), "%ssendMessage", bot->api); snprintf(url, sizeof(url), "%ssendMessage", bot->api);
@@ -243,18 +260,17 @@ tgbot_rc tgbot_send_message(tgbot *bot, int64_t chat_id, const char *text, const
tgbot_rc tgbot_edit_message_text(tgbot *bot, int64_t chat_id, long message_id, const char *text, tgbot_inlinekeyboard *keyboard) { tgbot_rc tgbot_edit_message_text(tgbot *bot, int64_t chat_id, long message_id, const char *text, tgbot_inlinekeyboard *keyboard) {
char url[1024]; char url[1024];
json_object *rjson = json_object_new_object(); tgbot_json_option options[4] = {
json_object_object_add(rjson, "chat_id", json_object_new_int64(chat_id)); {"chat_id", &chat_id, tgbot_opt_int64},
json_object_object_add(rjson, "message_id", json_object_new_int(message_id)); {"message_id", &message_id, tgbot_opt_int},
json_object_object_add(rjson, "text", json_object_new_string(text)); {"text", (void *)text, tgbot_opt_string},
{"reply_markup", keyboard, tgbot_opt_inlinekeyboard},
};
json_object *rjson = tgbot_json_builder(options, 4);
snprintf(url, sizeof(url), "%seditMessageText", bot->api); snprintf(url, sizeof(url), "%seditMessageText", bot->api);
if (keyboard != NULL) {
json_object *reply_markup = tgbot_new_inlinekeyboardmarkup(keyboard);
json_object_object_add(rjson, "reply_markup", reply_markup);
}
struct memory_buffer *mb; struct memory_buffer *mb;
tgbot_rc ret = tgbot_request(bot, url, &mb, rjson); tgbot_rc ret = tgbot_request(bot, url, &mb, rjson);
json_object_put(rjson); json_object_put(rjson);
@@ -271,11 +287,12 @@ tgbot_rc tgbot_edit_message_text(tgbot *bot, int64_t chat_id, long message_id, c
tgbot_rc tgbot_send_dice(tgbot *bot, int64_t chat_id, const char *emoji) { tgbot_rc tgbot_send_dice(tgbot *bot, int64_t chat_id, const char *emoji) {
char url[1024]; char url[1024];
json_object *rjson = json_object_new_object(); tgbot_json_option options[2] = {
json_object_object_add(rjson, "chat_id", json_object_new_int64(chat_id)); {"chat_id", &chat_id, tgbot_opt_int64},
if (emoji != NULL) { {"emoji", (void *)emoji, tgbot_opt_string},
json_object_object_add(rjson, "emoji", json_object_new_string(emoji)); };
}
json_object *rjson = tgbot_json_builder(options, 2);
snprintf(url, sizeof(url), "%ssendDice", bot->api); snprintf(url, sizeof(url), "%ssendDice", bot->api);