/*
* Luis Alberto
* Twitter @albertobsd
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<curl/curl.h>
#include<sys/stat.h>
#include<errno.h>
#include"telegram.h"
#include"jsmn.h"
char *telegram_buffer;
int telegram_buffer_size = 1024;
int telegram_buffer_offset = 0;
char *telegram_baseurl = "https://api.telegram.org/bot";
char *telegram_fileurl = "https://api.telegram.org/file/bot";
char *telegram_token;
int telegram_error = 0;
int telegram_error_code = 0;
char *telegram_error_buffer;
char *message_names[] = {"message_id","from","date","chat",
"forward_from","forward_date","reply_to_message",
"text","audio","document","photo","sticker","video",
"voice","caption","contact","location",
"new_chat_participant","left_chat_participant",
"new_chat_title","new_chat_photo","delete_chat_photo",
"group_chat_created","supergroup_chat_created",
"channel_chat_created","migrate_to_chat_id","migrate_from_chat_id",NULL};
char *contact_names[] = {"phone_number","first_name","last_name","user_id",NULL};
char *chat_names[] = {"id","type","title","username","first_name","last_name",NULL};
char *chat_type_names[] = {"private","group","supergroup","channel",NULL};
char *sticker_names[] = {"file_id","width","height","thumb","file_size",NULL};
char *photosize_names[] = {"file_id","width","height","file_size",NULL};
char *voice_names[] = {"file_id","duration","mime_type","file_size",NULL};
char *location_names[] = {"longitude","latitude",NULL};
char *document_names[] = {"file_id","thumb","file_name","mime_type","file_size",NULL};
char *video_names[] = {"file_id","width","height","duration","thumb","mime_type","file_size",NULL};
char *response_names[] = {"ok","description","result","error_code",NULL};
char *user_names[] = {"id","first_name","last_name","username",NULL};
char *update_names[] = {"update_id","message","inline_query","chosen_inline_result",NULL};
char *file_names[] = {"file_id","file_size","file_path",NULL};
int message_states[3][5] = {{4,1,4,4,4},{4,4,4,2,4},{4,1,1,1,1}};
int parse_array_states[2][5] = {{4,4,1,4,4},{4,1,4,4,4}};
Response *telegram_parse_response(char *str,int *count) {
Response *response;
int r,n =1,c,i =0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
response = calloc(2,sizeof(Response));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+2,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];i++;break;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];i++;break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];i++;
switch(indexOf(variable,response_names)){
case 0:response->ok = value;break;
case 1:response->description = value;
telegram_error_buffer = calloc(strlen(value)+2,sizeof(char));
memcpy(telegram_error_buffer,value,strlen(value)*sizeof(char));
entrar = 0;break;
case 2:response->result = value;
entrar = 0;break;
case 3:
response->error_code = strtol(value,NULL,10);
telegram_error = 1;telegram_error_code = response->error_code;
free(value);break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;break;}
free(variable);break;
case 3:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;break;
default:
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+=r;
return response;
}
int telegram_jsmn_init
(jsmn_parser *parser,jsmntok_t **t,char *buffer,int *n){
int r;
jsmntok_t *toks;
jsmn_init(parser);
toks = calloc(n[0]+2,sizeof(jsmntok_t));
if(toks != NULL){
r = jsmn_parse(parser, buffer, strlen(buffer), toks, n[0]);
while (r == JSMN_ERROR_NOMEM){
n[0]*=2;toks = realloc(toks, sizeof(jsmntok_t) * (n[0] + 2));
r = jsmn_parse(parser, buffer, strlen(buffer), toks, n[0]);}
if (r == JSMN_ERROR_INVAL){telegram_set_error("jsmn_parse: invalid JSON string",JSMN_ERROR_INVAL);}
if (r == JSMN_ERROR_PART){telegram_set_error("jsmn_parse: truncated JSON string",JSMN_ERROR_PART);}
t[0] = toks;}else{telegram_set_error("calloc: error",0xDEAD);}
return r;}
int telegram_set_error(char *error_str,int error_code) {
telegram_error_buffer = error_str;
telegram_error_code = error_code;
telegram_error = 1;
return 0;
}
Response* telegram_free_response(Response *res) {
if(res) {
if(res->ok) {free(res->ok);}
if(res->result) {free(res->result);}
if(res->description){free(res->description);}
memset(res,0,sizeof(Response));
free(res);
}
return NULL;
}
User* telegram_free_user(User *user){
if(user){
if(user->username != NULL){free(user->username);}
if(user->first_name != NULL){free(user->first_name);}
if(user->last_name != NULL){free(user->last_name);}
memset(user,0,sizeof(User));
free(user);
}
return NULL;}
int indexOf(char *str,char **ptr_strings){
int i = 0,entrar = 1;
while(entrar && ptr_strings[i] != NULL){
if(strcmp(ptr_strings[i],str) == 0){entrar = 0;i--;}
i++;
}
if(entrar){i = -1;}
return i;}
char * telegram_jsmn_get_token(jsmntok_t token,char *full){
char *str;int size = token.end - token.start;
str = calloc(size+2,sizeof(char));
memcpy(str,full+token.start,size);
return str;}
void telegram_dump_token(jsmntok_t token,char *str){
char *temp;
temp = telegram_jsmn_get_token(token,str);
printf("Token: %s\n",temp);
free(temp);
printf("type: %i\n",token.type);
printf("start: %i\n",token.start);
printf("end: %i\n",token.end);
printf("size: %i\n",token.size);
#ifdef JSMN_PARENT_LINKS
printf("size: %i\n",token.parent);
#endif
}
User* telegram_getMe() {
CURL *curl;
CURLcode res;
Response *response = NULL;
User *user = NULL;
char *url = NULL;
int i;
url = telegram_makeurl("/getMe");
curl = telegram_curl_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
res = curl_easy_perform(curl);
free(url);
if(res == CURLE_OK) {
response = telegram_parse_response(telegram_buffer,&i);
if(!telegram_error) {
user = telegram_parse_user(response->result,&i);
}
telegram_free_response(response);
telegram_reset_buffer();
curl_easy_cleanup(curl);
}
else {
telegram_set_error("curl: curl_easy_perform()",-1000);
}
return user;
}
File* telegram_getFile(char *file_id) {
CURL *curl;
CURLcode res;
Response *response = NULL;
File *file = NULL;
char *url = NULL;
char *postdata = NULL;
char *variables[] = {"file_id",NULL};
char *values[] = {file_id,NULL};
int i;
if(file_id){
curl = telegram_curl_init();
url = telegram_makeurl("/getFile");
curl_easy_setopt(curl, CURLOPT_URL, url);
postdata = telegram_build_post(variables,values);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata);
res = curl_easy_perform(curl);
free(url);
if(res == CURLE_OK) {
response = telegram_parse_response(telegram_buffer,&i);
if(!telegram_error) {
file = telegram_parse_file(response->result,&i);
}
telegram_free_response(response);
telegram_reset_buffer();
}
else {
telegram_set_error("curl_easy_perform() failed!",-1000);
}
free(postdata);
curl_easy_cleanup(curl);
}
else {
telegram_set_error("NULL file_id",-10);
}
return file;
}
char *telegram_makeurl(char *telegram_method) {
char *url;
int l;
int size_base;
int size_token;
int size_method;
size_base = strlen(telegram_baseurl);
size_token = strlen(telegram_token);
size_method = strlen(telegram_method);
l = size_base + size_token + size_method;
url = calloc(l+2,sizeof(char));
if(url != NULL) {
snprintf(url,l+1,"%s%s%s",telegram_baseurl,telegram_token,telegram_method);
}
else {
fprintf(stderr,"calloc error\n");
exit(1);
}
return url;
}
User* telegram_parse_user(char *str,int *count) {
User *user;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
char *token,*token1;
jsmntok_t *toks;
jsmn_parser parser;
user = calloc(2,sizeof(User));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];
i++;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
switch(indexOf(variable,user_names)) {
case 0:
user->id = strtol(value,NULL,10);
free(value);
break;
case 1:
user->first_name = value;
break;
case 2:
user->last_name = value;
break;
case 3:
user->username = value;
break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;
break;
}
free(variable);
break;
case 3:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0] += r;
return user;
}
int telegram_reset_buffer() {
memset(telegram_buffer,0,telegram_buffer_size);
telegram_buffer_offset = 0;
return 0;
};
size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata ) {
size_t new_len = telegram_buffer_offset + size*nmemb;
if(new_len >= telegram_buffer_size) {
do {
telegram_buffer_size*=2;
}while(new_len >= telegram_buffer_size);
telegram_buffer = realloc(telegram_buffer, (telegram_buffer_size +2)*sizeof(char));
if (telegram_buffer == NULL) {
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
}
memcpy(telegram_buffer + telegram_buffer_offset, ptr, size*nmemb);
telegram_buffer[new_len] = '\0';
telegram_buffer_offset+= size*nmemb;
return size*nmemb;
}
off_t fsize(const char *filename) {
struct stat st;
if (stat(filename, &st) == 0)
return st.st_size;
fprintf(stderr, "Cannot determine size of %s: %s\n",filename, strerror(errno));
return -1;
}
Updates * telegram_getUpdates() {
CURL *curl;
CURLcode res;
Response *response = NULL;
Updates *updates = NULL;
char *url = telegram_makeurl("/getUpdates");
int i;
curl = telegram_curl_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
res = curl_easy_perform(curl);
free(url);
if(res == CURLE_OK) {
response = telegram_parse_response(telegram_buffer,&i);
if(!telegram_error) {
if(response && response->result){
updates = telegram_parse_updates(response->result,&i);
}
}
telegram_free_response(response);
telegram_reset_buffer();
curl_easy_cleanup(curl);
}
else {
telegram_set_error("curl: curl_easy_perform()",-1000);
}
return updates;
}
Updates * telegram_parse_updates(char *str,int *count) {
Updates *updates;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *value;
updates = calloc(2,sizeof(Updates));
updates->list = calloc(2,sizeof(Update*));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+2,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = parse_array_states[state][toks[i].type];
i++;
break;
case 1:
value = telegram_jsmn_get_token(toks[i],str);
state = parse_array_states[state][toks[i].type];
updates->list[updates->length] = telegram_parse_update(value,&i);
updates->length++;
updates->list = realloc(updates->list,(updates->length+2)*sizeof(Update *));
break;
case 4:
telegram_dump_token(toks[i],str);
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+=r;
return updates;
}
Update * telegram_parse_update(char *str,int *count) {
Update *update = NULL;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
update = calloc(2,sizeof(Update));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+1,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];
i++;
break;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
switch(indexOf(variable,update_names)) {
case 0:
update->update_id = strtol(value,NULL,10);
free(value);
i++;
break;
case 1:
update->item.message = telegram_parse_message(value,&i);
free(value);
break;
case 2:
case 3:
telegram_set_error("Fixme",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
free(value);
entrar = 0;
break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;
break;
}
free(variable);
break;
case 3:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
default:
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+= r;
return update;
}
Message* telegram_parse_message(char *str,int *count) {
Message *message;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
message = calloc(2,sizeof(Message));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+1,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];
i++;
break;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
c = indexOf(variable,message_names);
switch(c) {
case 0: //message_id
message->message_id = strtol(value,NULL,10);
free(value);
i++;
break;
case 1: //from
message->from = telegram_parse_user(value,&i);
free(value);
break;
case 2: //date
message->date = strtol(value,NULL,10);
free(value);
i++;
break;
case 3: //chat
message->chat= telegram_parse_chat(value,&i);
free(value);
break;
case 4: //forward_from
message->forward_from = telegram_parse_user(value,&i);
free(value);
break;
case 5: //forward_date
message->forward_date = strtol(value,NULL,10);
free(value);
i++;
break;
case 6: //reply_to_message
message->reply_to_message = telegram_parse_message(value,&i);
free(value);
break;
case 7: //text
message->text = value;
i++;
break;
case 8: //audio
printf("error with token %s\n",value);
entrar = 0;
free(value);
i++;
break;
case 9: //document
message->document = telegram_parse_document(value,&i);
free(value);
break;
case 10: //photo
message->photo = telegram_parse_photos(value,&i);
free(value);
break;
case 11:
message->sticker = telegram_parse_sticker(value,&i);
free(value);
break;
case 12: //video
message->video = telegram_parse_video(value,&i);
break;
case 13: //voice
message->voice = telegram_parse_voice(value,&i);
free(value);
break;
case 14: //Cption
message->caption = value;
i++;
break;
case 15: //contact
message->contact = telegram_parse_contact(value,&i);
free(value);
break;
case 16: //location
message->location = telegram_parse_location(value,&i);
free(value);
break;
case 17: //new_chat_participant
message->new_chat_participant = telegram_parse_user(value,&i);
free(value);
break;
case 18: //left_chat_participant
message->left_chat_participant = telegram_parse_user(value,&i);
free(value);
break;
case 19: //new_chat_title
message->new_chat_title = value;
i++;
break;
case 20: //new_chat_photo
message->new_chat_photo = telegram_parse_photos(value,&i);
free(value);
break;
case 21: //delete_chat_photo
message->delete_chat_photo = strtol(value,NULL,10);
free(value);
i++;
break;
case 22: //group_chat_created
message->group_chat_created = strtol(value,NULL,10);
free(value);
i++;
break;
case 23: //supergroup_chat_created
message->supergroup_chat_created = strtol(value,NULL,10);
free(value);
i++;
break;
case 24: //channel_chat_created
message->channel_chat_created = strtol(value,NULL,10);
free(value);
i++;
break;
case 25: //migrate_to_chat_id
message->migrate_to_chat_id = strtol(value,NULL,10);
free(value);
i++;
break;
case 26: //migrate_from_chat_id
message->migrate_from_chat_id = strtol(value,NULL,10);
free(value);
i++;
break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;
break;
}
free(variable);
break;
case 4:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
default:
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+=r;
return message;
}
Chat* telegram_parse_chat(char *str,int *count) {
Chat *chat = NULL;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
chat = calloc(2,sizeof(Chat));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+1,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];
i++;
break;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
switch(indexOf(variable,chat_names)) {
case 0:
chat->id = strtol(value,NULL,10);
free(value);
break;
case 1:
chat->type = indexOf(variable,chat_type_names);
break;
case 2:
chat->title = value;
break;
case 3:
chat->username = value;
break;
case 4:
chat->first_name = value;
break;
case 5:
chat->last_name = value;
break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;
break;
}
free(variable);
break;
case 4:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+=r;
return chat;
}
Sticker* telegram_parse_sticker(char *str,int *count) {
Sticker *sticker = NULL;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
sticker = calloc(2,sizeof(Sticker));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+1,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];
i++;
break;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
switch(indexOf(variable,sticker_names)) {
case 0:
sticker->file_id = value;
i++;
break;
case 1:
sticker->width = strtol(value,NULL,10);
free(value);
i++;
break;
case 2:
sticker->height = strtol(value,NULL,10);
free(value);
i++;
break;
case 3:
sticker->thumb = telegram_parse_photosize(value,&i);
free(value);
break;
case 4:
sticker->file_size = strtol(value,NULL,10);
free(value);
i++;
break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;
break;
}
free(variable);
break;
case 4:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+=r;
return sticker;
}
PhotoSize* telegram_parse_photosize(char *str,int *count) {
PhotoSize *photosize = NULL;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
photosize = calloc(2,sizeof(PhotoSize));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+1,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];
i++;
break;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
c = indexOf(variable,photosize_names);
switch(c) {
case 0:
photosize->file_id = value;
i++;
break;
case 1:
photosize->width = strtol(value,NULL,10);
free(value);
i++;
break;
case 2:
photosize->height = strtol(value,NULL,10);
free(value);
i++;
break;
case 3:
photosize->file_size = strtol(value,NULL,10);
free(value);
i++;
break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;
break;
}
free(variable);
break;
case 4:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+=r;
return photosize;
}
Photos* telegram_parse_photos(char *str,int *count) {
Photos *photos = NULL;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *value;
photos = calloc(2,sizeof(Photos));
photos->length = 0;
photos->item = calloc(2,sizeof(PhotoSize *));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+1,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = parse_array_states[state][toks[i].type];
i++;
break;
case 1:
value = telegram_jsmn_get_token(toks[i],str);
state = parse_array_states[state][toks[i].type];
photos->item[photos->length] = telegram_parse_photosize(value,&i);
photos->length++;
photos->item = realloc(photos->item,(photos->length+2) * sizeof(PhotoSize*));
break;
case 4:
telegram_dump_token(toks[i],str);
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+= r;
return photos;
}
Voice* telegram_parse_voice(char *str,int *count) {
Voice *voice;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
voice = calloc(2,sizeof(Voice));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+1,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];
i++;
break;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
c = indexOf(variable,voice_names);
i++;
switch(c) {
case 0:
voice->file_id = value;
break;
case 1:
voice->duration = strtol(value,NULL,10);
free(value);
break;
case 2:
voice->mime_type = value;
;
case 3:
voice->file_size = strtol(value,NULL,10);
free(value);
break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;
break;
}
free(variable);
break;
case 4:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+=r;
return voice;
}
Location* telegram_parse_location(char *str,int *count) {
Location *location;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
location = calloc(2,sizeof(Location));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+1,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];
i++;
break;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
c = indexOf(variable,location_names);
i++;
switch(c) {
case 0:
location->longitude = strtof(value,NULL);
break;
case 1:
location->latitude = strtof(value,NULL);
break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;
break;
}
free(value);
free(variable);
break;
case 4:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+=r;
return location;
}
Contact* telegram_parse_contact(char *str,int *count) {
Contact *contact;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
contact = calloc(2,sizeof(Contact));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+1,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];
i++;
break;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
c = indexOf(variable,contact_names);
i++;
switch(c) {
case 0:
contact->phone_number = value;
break;
case 1:
contact->first_name = value;
break;
case 2:
contact->last_name = value;
break;
case 3:
contact->user_id = strtol(value,NULL,10);
break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;
break;
}
free(variable);
break;
case 4:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+=r;
return contact;
}
Document* telegram_parse_document(char *str,int *count) {
Document *document;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
document = calloc(2,sizeof(Document));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+1,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];
i++;
break;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
c = indexOf(variable,document_names);
switch(c) {
case 0:
document->file_id = value;
i++;
break;
case 1:
document->thumb = telegram_parse_photosize(value,&i);
free(value);
break;
case 2:
document->file_name = value;
i++;
break;
case 3:
document->mime_type = value;
i++;
break;
case 4:
document->file_size = strtol(value,NULL,10);
free(value);
i++;
break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;
break;
}
free(variable);
break;
case 4:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+=r;
return document;
}
Video * telegram_parse_video(char *str,int *count) {
Video *video;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
video = calloc(2,sizeof(Video));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+1,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];
i++;
break;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
c = indexOf(variable,video_names);
switch(c) {
case 0:
video->file_id = value;
i++;
break;
case 1:
video->width = strtol(value,NULL,10);
free(value);
i++;
break;
case 2:
video->height = strtol(value,NULL,10);
free(value);
i++;
break;
case 3:
video->duration = strtol(value,NULL,10);
free(value);
i++;
break;
case 4:
video->thumb = telegram_parse_photosize(value,&i);
free(value);
break;
case 5:
video->mime_type = value;
free(value);
i++;
break;
case 6:
video->file_size = strtol(value,NULL,10);
free(value);
i++;
break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;
break;
}
free(variable);
break;
case 4:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+=r;
return video;
}
int telegram_init(char *token) {
int size;
size = strlen(token);
telegram_token = calloc(size,sizeof(char));
if(telegram_token == NULL) {
fprintf(stderr, "calloc() failed\n");
exit(1);
}
telegram_buffer = calloc(telegram_buffer_size,sizeof(char));
if(telegram_buffer == NULL) {
fprintf(stderr, "calloc() failed\n");
exit(1);
}
memcpy(telegram_token,token,size);
return 0;
}
char *telegram_get_error() {
telegram_error = 0;
return telegram_error_buffer;
}
int telegram_is_error() {
return telegram_error;
}
char* telegram_build_post(char **variables,char **values) {
int i = 0,l = 0,size= 0,offset = 0;
char *buffer = NULL;
//printf("%X %X\n",variables,values);
if(variables && values) {
while( variables[l] && values[l]) {
//printf("%x %x\n",variables[l],values[l]);
size += (strlen(variables[l])+ strlen(values[l])+2);
l++;
}
}
//printf("size = %i\nl = %i\n",size,l);
buffer = calloc(size+1,sizeof(char));
if(buffer) {
while(i<l) {
if(i==0) {
sprintf(buffer+offset,"%s=%s",variables[i],values[i]);
offset+= (1 +strlen(variables[i]) +strlen(values[i]));
}
else {
sprintf(buffer+offset,"&%s=%s",variables[i],values[i]);
offset+= (1 +strlen(variables[i]) +strlen(values[i]));
}
i++;
}
}
else {
fprintf(stderr,"error callo()");
exit(0);
}
return buffer;
}
File* telegram_parse_file(char *str,int *count) {
File *file;
int r,n =1,c,i = 0;
unsigned int state = 0,entrar = 1;
char *variable,*value;
file = calloc(2,sizeof(File));
jsmntok_t *toks;
jsmn_parser parser;
toks = calloc(n+1,sizeof(jsmntok_t));
r = telegram_jsmn_init(&parser,&toks,str,&n);
while(entrar && i < r) {
switch(state) {
case 0:
state = message_states[state][toks[i].type];
i++;
break;
case 1:
variable = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
i++;
break;
case 2:
value = telegram_jsmn_get_token(toks[i],str);
state = message_states[state][toks[i].type];
c = indexOf(variable,file_names);
switch(c) {
case 0:
file->file_id = value;
i++;
break;
case 1:
file->file_size = strtol(value,NULL,10);
free(value);
i++;
break;
case 2:
file->file_path = value;
free(value);
i++;
break;
default:
telegram_set_error("UNEXPECTED TOKEN VALUE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE);
entrar = 0;
break;
}
free(variable);
break;
case 4:
telegram_set_error("UNEXPECTED TOKEN TYPE",TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE);
entrar = 0;
break;
}
}
memset(toks,0,n*sizeof(jsmntok_t));
free(toks);
count[0]+=r;
return file;
}
char* telegra_makeDownloadURL(File *file) {
char *url = NULL;
char *temp = NULL;
int l;
int size_base;
int size_token;
int size_path;
size_base = strlen(telegram_fileurl);
size_token = strlen(telegram_token);
size_path = strlen(file->file_path);
l = size_base + size_token + size_path;
temp = calloc(l+10,sizeof(char));
if(temp) {
snprintf(temp,l+3,"%s%s/%s",telegram_fileurl,telegram_token,file->file_path);
url = telegram_process_slash(temp);
free(temp);
}
else {
fprintf(stderr,"calloc error\n");
exit(1);
}
return url;
}
char* telegram_downloadFile(File *file,char *name) {
CURL *curl;
CURLcode res;
char *toreturn = NULL;
FILE *toLocalFile = NULL;
char **test = NULL;
char *url = telegra_makeDownloadURL(file);
curl = telegram_curl_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
res = curl_easy_perform(curl);
free(url);
if(res == CURLE_OK) {
if(file->file_size == telegram_buffer_offset) {
toLocalFile = fopen(name,"w");
if(toLocalFile) {
if(fwrite(telegram_buffer,sizeof(char),telegram_buffer_offset,toLocalFile) == telegram_buffer_offset) {
toreturn = name;
}
else {
telegram_set_error("stdio: fwrite()",-1000);
}
fclose(toLocalFile);
}
else {
telegram_set_error("stdio: fopen()",-1000);
}
telegram_reset_buffer();
}
else {
printf("Diff %i %i\n",file->file_size,telegram_buffer_offset);
}
curl_easy_cleanup(curl);
}
else {
telegram_set_error("curl: curl_easy_perform()",-1000);
}
return toreturn;
}
char* telegram_process_slash(char *str) {
int i = 0,j =0;
char *temp = NULL;
if(str) {
temp = calloc(strlen(str)+2,sizeof(char));
while(str[j] != 0) { // '\0'
if(str[j] == '\\')
j++;
temp[i] = str[j];
i++;
j++;
}
}
else {
telegram_set_error("NULL funtion argument",-10);
}
return temp;
}
CURL* telegram_curl_init() {
CURL *curl = NULL;
//printf("CURL INIT\n");
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
}
return curl;
}
Updates* telegram_free_updates(Updates *updates) {
if(updates) {
int i = 0;
while(i < updates->length) {
if(updates->list[i])
telegram_free_update(updates->list[i]);
i++;
}
memset(updates,0,sizeof(Updates));
free(updates);
}
return NULL;
}
Update* telegram_free_update(Update *update) {
if(update) {
switch(update->type) {
case 0:
telegram_free_message(update->item.message);
break;
}
memset(update,0,sizeof(Update));
free(update);
}
return NULL;
}
Message* telegram_free_message(Message *message) {
if(message) {
if(message->from) {
telegram_free_user(message->from);
}
if(message->chat) {
telegram_free_chat(message->chat);
}
if(message->forward_from) {
telegram_free_user(message->forward_from);
}
if(message->reply_to_message) {
telegram_free_message(message->reply_to_message);
}
if(message->audio) {
telegram_free_audio(message->audio);
}
if(message->document) {
telegram_free_document(message->document);
}
if(message->photo) {
telegram_free_photos(message->photo);
}
if(message->sticker) {
telegram_free_sticker(message->sticker);
}
if(message->video) {
telegram_free_video(message->video);
}
if(message->voice) {
telegram_free_voice(message->voice);
}
if(message->contact) {
telegram_free_contact(message->contact);
}
if(message->location) {
telegram_free_location(message->location);
}
if(message->new_chat_participant) {
telegram_free_user(message->new_chat_participant);
}
if(message->left_chat_participant) {
telegram_free_user(message->left_chat_participant);
}
if(message->new_chat_photo) {
telegram_free_photos(message->new_chat_photo);
}
memset(message,0,sizeof(Message));
free(message);
}
return NULL;
}
Location* telegram_free_location(Location *location) {
if(location) {
memset(location,0,sizeof(Location));
free(location);
}
return NULL;
}
Voice* telegram_free_voice(Voice *voice) {
if(voice) {
if(voice->file_id) {
free(voice->file_id);
}
if(voice->mime_type) {
free(voice->mime_type);
}
memset(voice,0,sizeof(Voice));
free(voice);
}
return NULL;
}
Contact* telegram_free_contact(Contact *contact) {
if(contact) {
if(contact->phone_number) {
free(contact->phone_number);
}
if(contact->first_name) {
free(contact->first_name);
}
if(contact->last_name) {
free(contact->last_name);
}
memset(contact,0,sizeof(Contact));
free(contact);
}
return NULL;
}
Document* telegram_free_document(Document *document) {
if(document) {
if(document->file_id) {
free(document->file_id);
}
if(document->mime_type) {
free(document->mime_type);
}
if(document->file_name) {
free(document->file_name);
}
if(document->thumb) {
telegram_free_photosize(document->thumb);
}
memset(document,0,sizeof(Document));
free(document);
}
return NULL;
}
Chat* telegram_free_chat(Chat *chat) {
if(chat) {
if(chat->title) {
free(chat->title);
}
if(chat->username) {
free(chat->username);
}
if(chat->first_name) {
free(chat->first_name);
}
if(chat->last_name) {
free(chat->last_name);
}
memset(chat,0,sizeof(Chat));
free(chat);
}
return NULL;
}
Audio* telegram_free_audio(Audio *audio) {
if(audio) {
if(audio->file_id) {
free(audio->file_id);
}
if(audio->performer) {
free(audio->performer);
}
if(audio->title) {
free(audio->title);
}
if(audio->mime_type) {
free(audio->mime_type);
}
memset(audio,0,sizeof(Audio));
free(audio);
}
return NULL;
}
Sticker* telegram_free_sticker(Sticker *sticker) {
if(sticker) {
if(sticker->file_id) {
free(sticker->file_id);
}
if(sticker->thumb) {
telegram_free_photosize(sticker->thumb);
}
memset(sticker,0,sizeof(Sticker));
free(sticker);
}
return NULL;
}
PhotoSize* telegram_free_photosize(PhotoSize *photosize) {
if(photosize) {
if(photosize->file_id) {
free(photosize->file_id);
}
memset(photosize,0,sizeof(PhotoSize));
free(photosize);
}
return NULL;
}
Photos* telegram_free_photos(Photos *photos) {
int i = 0;
if(photos) {
while(i < photos->length) {
if(photos->item[i])
telegram_free_photosize(photos->item[i]);
i++;
}
free(photos->item);
memset(photos,0,sizeof(Photos));
free(photos);
}
return NULL;
}
Video* telegram_free_video(Video *video) {
if(video) {
if(video->file_id) {
free(video->file_id);
}
if(video->mime_type) {
free(video->mime_type);
}
if(video->thumb) {
telegram_free_photosize(video->thumb);
}
memset(video,0,sizeof(Video));
free(video);
}
return NULL;
}
Message* telegram_sendMessage(char *postdata) {
CURL *curl = NULL;
CURLcode res;
Response *response = NULL;
Message *message = NULL;
int i;
char *url = NULL;
url = telegram_makeurl("/sendMessage");
curl = telegram_curl_init();
curl_easy_setopt(curl, CURLOPT_URL , url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS , postdata);
res = curl_easy_perform(curl);
free(url);
if(res == CURLE_OK) {
response = telegram_parse_response(telegram_buffer,&i);
if(!telegram_error) {
message = telegram_parse_message(response->result,&i);
}
telegram_free_response(response);
telegram_reset_buffer();
curl_easy_cleanup(curl);
}
else {
telegram_set_error("curl: curl_easy_perform()",-1000);
}
return message;
}
Message* telegram_sendDocument(char *filename,char **variables, char **valores) {
CURL *curl = NULL;
CURLcode res;
struct curl_httppost *formpost=NULL;
struct curl_httppost *lastptr=NULL;
struct curl_slist *headerlist=NULL;
static const char buf[] = "Expect:";
Response *response = NULL;
Message *message = NULL;
char *url = NULL;
int i;
if(filename){
url = telegram_makeurl("/sendDocument");
curl = telegram_curl_init();
i = 0;
while(variables[i] != NULL && valores[i] != NULL) {
curl_formadd(&formpost,&lastptr,CURLFORM_COPYNAME, variables[i],CURLFORM_COPYCONTENTS, valores[i],CURLFORM_END);
i++;
}
curl_formadd(&formpost,&lastptr,CURLFORM_COPYNAME, "document",CURLFORM_FILE, filename,CURLFORM_END);
headerlist = curl_slist_append(headerlist, buf);
curl_easy_setopt(curl, CURLOPT_URL , url);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
res = curl_easy_perform(curl);
if(res == CURLE_OK) {
response = telegram_parse_response(telegram_buffer,&i);
if(!telegram_error) {
message = telegram_parse_message(response->result,&i);
}
else {
telegram_set_error(response->description,1);
}
free(url);
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all (headerlist);
}
else {
telegram_set_error("curl",1);
}
}
else {
telegram_set_error("NULL argument",1);
}
return message;
}
Message* sendLocation(char postdata) {
CURL *curl = NULL;
CURLcode res;
Response *response = NULL;
Message *message = NULL;
int i;
char *url = NULL;
url = telegram_makeurl("/sendLocation");
curl = telegram_curl_init();
curl_easy_setopt(curl, CURLOPT_URL , url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS , postdata);
res = curl_easy_perform(curl);
free(url);
if(res == CURLE_OK) {
response = telegram_parse_response(telegram_buffer,&i);
if(!telegram_error) {
message = telegram_parse_message(response->result,&i);
}
telegram_free_response(response);
telegram_reset_buffer();
curl_easy_cleanup(curl);
}
else {
telegram_set_error("curl: curl_easy_perform()",-1000);
}
return message;
}
viernes, 24 de noviembre de 2023
Bot telegram (1)main.c
Suscribirse a:
Entradas (Atom)