diff --git a/include/telebot-common.h b/include/telebot-common.h index 5d723a2..bacdc3b 100644 --- a/include/telebot-common.h +++ b/include/telebot-common.h @@ -51,7 +51,6 @@ typedef enum { TELEBOT_ERROR_INVALID_PARAMETER = -5, /**< Invalid parameter */ } telebot_error_e; - /** * @} // end of APIs */ diff --git a/include/telebot-core.h b/include/telebot-core.h index 16add73..60652dc 100644 --- a/include/telebot-core.h +++ b/include/telebot-core.h @@ -49,8 +49,12 @@ typedef struct telebot_core_handler { char *resp_data; /**< Telegam response object */ size_t resp_size; /**< Telegam response size */ bool busy; /**< Mark another request is in progress */ + char *proxy_addr; + char *proxy_auth; } telebot_core_handler_t; +telebot_error_e telebot_core_init_proxy(telebot_core_handler_t *core_h, char *addr, char *auth); + /** * @brief Start function to use telebot core APIs. * @@ -283,6 +287,30 @@ telebot_error_e telebot_core_send_video(telebot_core_handler_t *core_h, long long int chat_id, char *video, bool is_file, int duration, char *caption, bool disable_notification, int reply_to_message_id, char *reply_markup); +/** + * @brief This function is used to send video files, Telegram clients support + * mp4 videos (other formats may be sent as Document). + * @param core_h The telebot core handler created with #telebot_core_create(). + * @param chat_id Unique identifier for the target chat or username of the + * target channel (in the format \@channelusername). + * @param video Video file to send. It is either a file_id as String to resend + * a video that is already on the Telegram servers, or a path to video file. + * @param is_file False if video is file_id, true, if video is a file path. + * @param duration Duration of sent video in seconds. + * @param caption Video caption (may also be used when resending videos). + * @param disable_notification Sends the message silently. Users will receive a + * notification with no sound. + * @param reply_to_message_id If the message is a reply, ID of the original message. + * @param reply_markup Additional interface options. An object for a custom reply + * keyboard, instructions to hide keyboard or to force a reply from the user. + * @return on Success, TELEBOT_ERROR_NONE is returned, otherwise a negative + * error value. Response is placed in core_h->resp_data that contains the sent + * message. It MUST be freed after use. + */ +telebot_error_e telebot_core_send_animation(telebot_core_handler_t *core_h, + long long int chat_id, char *video, bool is_file, int duration, char *caption, + bool disable_notification, int reply_to_message_id, char *reply_markup); + /** * @brief This function is used to send audio files, if you want Telegram * clients to display the file as a playable voice message. For this to work, diff --git a/include/telebot-methods.h b/include/telebot-methods.h index 4dbad1c..5bf22e4 100644 --- a/include/telebot-methods.h +++ b/include/telebot-methods.h @@ -36,6 +36,8 @@ extern "C" { * @{ */ +telebot_error_e telebot_use_proxy(telebot_handler_t handle, char *addr, char *auth); + /** * @brief Initial function to use telebot APIs. * @@ -315,6 +317,35 @@ telebot_error_e telebot_send_video(telebot_handler_t handle, long long int chat_ char *caption, bool disable_notification, int reply_to_message_id, char *reply_markup); +/** + * @brief This function is used to send video files as animations, + * Telegram clients support mp4 videos (other formats may be sent as Document). + * + * @param[in] handle The telebot handler created with #telebot_create(). + * @param[in] chat_id Unique identifier for the target chat or username of the + * target channel (in the format \@channelusername). + * @param[in] video Video file to send. It is either a file_id to resend + * a video that is already on the Telegram servers, or a path to video file. + * @param[in] is_file False if video is file_id, true, if video is a file path. + * @param[in] width Video width. + * @param[in] height Video height. + * @param[in] duration Duration of sent video in seconds. + * @param[in] caption Video caption (may also be used when resending videos). + * @param[in] disable_notification Sends the message silently. Users will receive + * a notification with no sound. + * @param[in] reply_to_message_id If the message is a reply, ID of the original + * message. + * @param[in] reply_markup Additional interface options. An object for a custom + * reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return on Success, TELEBOT_ERROR_NONE is returned, otherwise a negative + * error value. + */ +telebot_error_e telebot_send_animation(telebot_handler_t handle, long long int chat_id, + char *video, bool is_file, int duration, int width, int height, + char *caption, bool disable_notification, int reply_to_message_id, + char *reply_markup); + + /** * @brief This function is used to send audio files, if you want Telegram * clients to display the file as a playable voice message. For this to work, diff --git a/include/telebot-private.h b/include/telebot-private.h index 30a0cd0..28b441f 100644 --- a/include/telebot-private.h +++ b/include/telebot-private.h @@ -35,6 +35,7 @@ #define TELEBOT_METHOD_SEND_AUDIO "sendAudio" #define TELEBOT_METHOD_SEND_DOCUMENT "sendDocument" #define TELEBOT_METHOD_SEND_VIDEO "sendVideo" +#define TELEBOT_METHOD_SEND_ANIMATION "sendAnimation" #define TELEBOT_METHOD_SEND_VOICE "sendVoice" #define TELEBOT_METHOD_SEND_VIDEO_NOTE "sendVideoNote" #define TELEBOT_METHOD_SEND_MEDIA_GROUP "sendMediaGroup" @@ -71,7 +72,7 @@ #define TELEBOT_METHOD_DELETE_MESSAGE "deleteMessage" #define TELEBOT_METHOD_SEND_STICKER "sendSticker" -#ifdef DEBUG +#ifndef DEBUG #define ERR(fmt, args...) printf("[ERROR][%s:%d]" fmt "\n", __func__, __LINE__, ##args) #define DBG(fmt, args...) printf("[DEBUG][%s:%d]" fmt "\n", __func__, __LINE__, ##args) #else diff --git a/include/telebot-types.h b/include/telebot-types.h index ef36bce..3bdb088 100644 --- a/include/telebot-types.h +++ b/include/telebot-types.h @@ -214,6 +214,9 @@ typedef struct telebot_message { /** Optional. Message is a video, information about the video */ struct telebot_video *video; + /** Optional. Message is a animation, information about the animation */ + struct telebot_animation *animation; + /** Optional. Message is a voice message, information about the file */ struct telebot_voice *voice; @@ -421,6 +424,31 @@ typedef struct telebot_video { int file_size; } telebot_video_t; +/** + * @brief This object represents a video file. + */ +typedef struct telebot_animation { + /** Unique identifier for this file */ + char *file_id; + + /** Video width as defined by sender */ + int width; + + /** Video height as defined by sender */ + int height; + + /** Duration of the video in seconds as defined by sender */ + int duration; + + /** Optional. Video thumbnail */ + struct telebot_photo *thumb; + + /** Optional. Mime type of a file as defined by sender */ + char *mime_type; + + /** Optional. File size */ + int file_size; +} telebot_animation_t; /** * @brief This object represents a voice note. diff --git a/src/telebot-core.c b/src/telebot-core.c index f3de3fb..2ecba44 100644 --- a/src/telebot-core.c +++ b/src/telebot-core.c @@ -74,6 +74,15 @@ static telebot_error_e telebot_core_curl_perform(telebot_core_handler_t *core_h, curl_easy_setopt(curl_h, CURLOPT_URL, URL); curl_easy_setopt(curl_h, CURLOPT_WRITEFUNCTION, write_data_cb); curl_easy_setopt(curl_h, CURLOPT_WRITEDATA, core_h); + + if (core_h->proxy_addr != NULL) { + curl_easy_setopt(curl_h, CURLOPT_PROXY, core_h->proxy_addr); + + if (core_h->proxy_auth != NULL) { + curl_easy_setopt(curl_h, CURLOPT_PROXYAUTH, CURLAUTH_ANY); + curl_easy_setopt(curl_h, CURLOPT_PROXYUSERPWD, core_h->proxy_auth); + } + } if (post != NULL) curl_easy_setopt(curl_h, CURLOPT_HTTPPOST, post); @@ -109,6 +118,18 @@ static telebot_error_e telebot_core_curl_perform(telebot_core_handler_t *core_h, return TELEBOT_ERROR_NONE; } +telebot_error_e telebot_core_init_proxy(telebot_core_handler_t *core_h, char *addr, char *auth) +{ + if ((addr == NULL) || (core_h == NULL)) { + return TELEBOT_ERROR_INVALID_PARAMETER; + } + + core_h->proxy_addr = strdup(addr); + if (auth != NULL) core_h->proxy_auth = strdup(auth); + + return TELEBOT_ERROR_NONE; +} + telebot_error_e telebot_core_create(telebot_core_handler_t **core_h, char *token) { if ((token == NULL) || (core_h == NULL)) { @@ -125,6 +146,8 @@ telebot_error_e telebot_core_create(telebot_core_handler_t **core_h, char *token _core_h->resp_data = NULL; _core_h->resp_size = 0; _core_h->busy = false; + _core_h->proxy_addr = NULL; + _core_h->proxy_auth = NULL; curl_global_init(CURL_GLOBAL_DEFAULT); @@ -148,6 +171,18 @@ telebot_error_e telebot_core_destroy(telebot_core_handler_t *core_h) core_h->token = NULL; } + if (core_h->proxy_addr != NULL) { + memset(core_h->proxy_addr, 'M', strlen(core_h->proxy_addr)); + free(core_h->proxy_addr); + core_h->proxy_addr = NULL; + } + + if (core_h->proxy_auth != NULL) { + memset(core_h->proxy_auth, 'M', strlen(core_h->proxy_auth)); + free(core_h->proxy_auth); + core_h->proxy_auth = NULL; + } + if (core_h->resp_data != NULL) free(core_h->resp_data); @@ -504,6 +539,55 @@ telebot_error_e telebot_core_send_video(telebot_core_handler_t *core_h, return telebot_core_curl_perform(core_h, TELEBOT_METHOD_SEND_VIDEO, post); } +telebot_error_e telebot_core_send_animation(telebot_core_handler_t *core_h, + long long int chat_id, char *video, bool is_file, int duration, char *caption, + bool disable_notification, int reply_to_message_id, char *reply_markup) +{ + if ((core_h == NULL) || (core_h->token == NULL) || (video == NULL)) { + ERR("Handler, token or document is NULL"); + return TELEBOT_ERROR_INVALID_PARAMETER; + } + + struct curl_httppost *post = NULL; + struct curl_httppost *last = NULL; + + char chat_id_str[16]; + snprintf(chat_id_str, sizeof(chat_id_str), "%lld", chat_id); + curl_formadd(&post, &last, CURLFORM_COPYNAME, "chat_id", + CURLFORM_COPYCONTENTS, chat_id_str, CURLFORM_END); + if (is_file) + curl_formadd(&post, &last, CURLFORM_COPYNAME, "animation", + CURLFORM_FILE, video, CURLFORM_END); + else + curl_formadd(&post, &last, CURLFORM_COPYNAME, "animation", + CURLFORM_COPYCONTENTS, video, CURLFORM_END); + if (duration > 0) { + char duration_str[16]; + snprintf(duration_str, sizeof(duration_str), "%d", duration); + curl_formadd(&post, &last, CURLFORM_COPYNAME, "duration", + CURLFORM_COPYCONTENTS, duration_str, CURLFORM_END); + } + if (caption) + curl_formadd(&post, &last, CURLFORM_COPYNAME, "caption", + CURLFORM_COPYCONTENTS, caption, CURLFORM_END); + curl_formadd(&post, &last, CURLFORM_COPYNAME, "disable_notification", + CURLFORM_COPYCONTENTS, (disable_notification) ? "true" : "false", + CURLFORM_END); + if (reply_to_message_id > 0) { + char reply_to_message_id_str[16]; + snprintf(reply_to_message_id_str, sizeof(reply_to_message_id_str), "%d", + reply_to_message_id); + curl_formadd(&post, &last, CURLFORM_COPYNAME, "reply_to_message_id", + CURLFORM_COPYCONTENTS, reply_to_message_id_str, CURLFORM_END); + } + if (reply_markup) + curl_formadd(&post, &last, CURLFORM_COPYNAME, "reply_markup", + CURLFORM_COPYCONTENTS, reply_markup, CURLFORM_END); + + return telebot_core_curl_perform(core_h, TELEBOT_METHOD_SEND_ANIMATION, post); +} + + telebot_error_e telebot_core_send_voice(telebot_core_handler_t *core_h, long long int chat_id, char *voice, bool is_file, int duration, bool disable_notification, int reply_to_message_id, char *reply_markup) diff --git a/src/telebot.c b/src/telebot.c index a4426e7..3a18cb8 100644 --- a/src/telebot.c +++ b/src/telebot.c @@ -58,6 +58,7 @@ static void telebot_free_document(telebot_document_t *document); static void telebot_free_photo(telebot_photo_t *photo); static void telebot_free_sticker(telebot_sticker_t *sticker); static void telebot_free_video(telebot_video_t *video); +static void telebot_free_animation(telebot_animation_t *animation); static void telebot_free_voice(telebot_voice_t *voice); static void telebot_free_video_note(telebot_video_note_t *vnote); static void telebot_free_contact(telebot_contact_t *contact); @@ -69,6 +70,22 @@ static void telebot_free_mask_position(telebot_mask_position_t *mask); //static void telebot_free_invoice(telebot_invoice_t *invoice); //static void telebot_free_payment(telebot_successful_payment_t *payment); +telebot_error_e telebot_use_proxy(telebot_handler_t handle, char *addr, char *auth) +{ + if (addr == NULL) + return TELEBOT_ERROR_INVALID_PARAMETER; + + telebot_hdata_t * _handle = (telebot_hdata_t *)handle; + if (_handle == NULL) + return TELEBOT_ERROR_NOT_SUPPORTED; + + telebot_error_e ret = telebot_core_init_proxy(_handle->core_h, addr, auth); + if (ret != TELEBOT_ERROR_NONE) + return ret; + + return TELEBOT_ERROR_NONE; +} + telebot_error_e telebot_create(telebot_handler_t *handle, char *token) { if ((token == NULL) || (handle == NULL)) @@ -510,6 +527,27 @@ telebot_error_e telebot_send_video(telebot_handler_t handle, long long int chat_ return ret; } +telebot_error_e telebot_send_animation(telebot_handler_t handle, long long int chat_id, + char *video, bool is_file, int duration, int width, int height, + char *caption, bool disable_notification, int reply_to_message_id, + char *reply_markup) +{ + telebot_hdata_t * _handle = (telebot_hdata_t *)handle; + if (_handle == NULL) + return TELEBOT_ERROR_NOT_SUPPORTED; + + if (video == NULL) + return TELEBOT_ERROR_INVALID_PARAMETER; + + telebot_error_e ret = telebot_core_send_animation(_handle->core_h, chat_id, video, + is_file, duration, caption, disable_notification, reply_to_message_id, + reply_markup); + + tb_sfree_zcnt(_handle->core_h->resp_data, _handle->core_h->resp_size); + + return ret; +} + telebot_error_e telebot_send_voice(telebot_handler_t handle, long long int chat_id, char *voice, bool is_file, char *caption, int duration, bool disable_notification, int reply_to_message_id, char *reply_markup) @@ -843,6 +881,9 @@ static void telebot_free_message(telebot_message_t *msg) telebot_free_video(msg->video); tb_sfree(msg->video); + telebot_free_animation(msg->animation); + tb_sfree(msg->animation); + telebot_free_voice(msg->voice); tb_sfree(msg->voice); @@ -938,6 +979,16 @@ static void telebot_free_video(telebot_video_t *video) tb_sfree(video->mime_type); } +static void telebot_free_animation(telebot_animation_t *animation) +{ + if (animation == NULL) return; + + tb_sfree(animation->file_id); + telebot_free_photo(animation->thumb); + tb_sfree(animation->thumb); + tb_sfree(animation->mime_type); +} + static void telebot_free_voice(telebot_voice_t *voice) { if (voice == NULL) return;