summaryrefslogtreecommitdiffstats
path: root/src/api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/api.c')
-rw-r--r--src/api.c189
1 files changed, 97 insertions, 92 deletions
diff --git a/src/api.c b/src/api.c
index f798aff..e456e53 100644
--- a/src/api.c
+++ b/src/api.c
@@ -18,9 +18,9 @@
#define DC_API_PREFIX "https://discord.com/api/v8/" /* this can be a format string, DO NOT use format characters inside */
#define DC_LOGIN_FORMAT "{\"login\":\"%s\",\"password\":\"%s\",\"undelete\":false,\"captcha_key\":null,\"login_source\":null,\"gift_code_sku_id\":null}"
#define DC_USER_AGENT "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36"
-/* #define DC_ERROR(e, s, l, m, ...) (dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__)) */
-#define DC_ERROR(e, s, l, m, ...) (fprintf(stderr, "%s()@" __FILE__ ":%d: " m "\n", __func__, __LINE__ __VA_OPT__(,) __VA_ARGS__))
-#define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */
+#define DC_ERROR(c, m, ...) (dc_push_error(c, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__))
+/* #define DC_ERROR(c, m, ...) (fprintf(stderr, "%s()@" __FILE__ ":%d: " m "\n", __func__, __LINE__ __VA_OPT__(,) __VA_ARGS__)) */
+#define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */
#define DC_CAPI(c, body, endpoint, ...) dc_api(c, body, 0##__VA_OPT__(1), endpoint __VA_OPT__(,) __VA_ARGS__)
#define cJSON_GetObjectItem2(root, name1, name2) (cJSON_GetObjectItem(root, name1) ? cJSON_GetObjectItem(cJSON_GetObjectItem(root, name1), name2) : NULL)
#define DC_TIMESTAMP_FORMAT "%Y-%m-%dT%H:%M:%S.XXXXXX%z"
@@ -105,6 +105,7 @@ struct dc_channel {
_Atomic(struct dc_guild *) guild; /* nofree, nouiw */
struct dc_message ** messages; /* yesfree, nouiw */
_Atomic(size_t) messages_sizeof; /* nouiw */
+ int slowmode; /* number of seconds to wait in case of slowmode, HANDLED BY THE USER INTERFACE!! */
};
void dc_channel_free (struct dc_channel * ch) { /* noui, noapi, nolock - only called by dc_guild_free */
free(ch->name); ch->name = NULL;
@@ -153,6 +154,7 @@ struct dc_client {
struct dc_message ** sent_messages; /* yesfree - ui appends, api pops and moves to messages */
_Atomic(size_t) sent_messages_sizeof;
pthread_rwlock_t * sent_messages_lock;
+ _Atomic(time_t) last_sent_message; /* for slowmode implementations */
};
struct dc_client * dc_client_init () { /* gives you a prepared dc_client */
struct dc_client * c = calloc(1, sizeof(struct dc_client));
@@ -196,11 +198,17 @@ void dc_client_free (struct dc_client * c) { /* noui, noapi, nolock - only calle
DC_CFLD(c->sent_messages);
free(c);
}
-int dc_push_error (struct dc_error ** e, _Atomic size_t * s, pthread_rwlock_t * lock, const char * c, char * f, size_t l, unsigned short int isfmt, char * m, ...) {
- if (lock && pthread_rwlock_wrlock(lock))
+int dc_push_error (struct dc_client * c, const char * caller, char * f, size_t l, unsigned short int isfmt, char * m, ...) {
+#define DC_PEE /* dc scalnia oziroma push error error */ c->errors[c->errors_sizeof-1]
+ if (!c)
+ return -2;
+ pthread_rwlock_t * lock = c->errors_lock;
+ if (!lock)
+ return -3;
+ if (pthread_rwlock_wrlock(lock))
return -1; /* does not report an error as that may make things even worse. I could try writing to stderr here but meh */
- e = realloc(e, sizeof(struct dc_error *)*++*s); /* note: format arguments are evaluated twice */
- e[*s-1] = malloc(sizeof(struct dc_error));
+ c->errors = realloc(c->errors, sizeof(struct dc_error *)*++c->errors_sizeof); /* note: format arguments are evaluated twice */
+ DC_PEE = malloc(sizeof(struct dc_error));
size_t strlenm = strlen(m);
size_t va_count = parse_printf_format(m, 0, NULL);
if (isfmt && va_count > 0) {
@@ -208,19 +216,19 @@ int dc_push_error (struct dc_error ** e, _Atomic size_t * s, pthread_rwlock_t *
va_start(ap, m);
va_copy(ap2, ap);
strlenm = vsnprintf(NULL, 0, m, ap);
- e[*s-1]->message = malloc(sizeof(char)*strlenm+1);
- vsnprintf(e[*s-1]->message, strlenm+1, m, ap2);
+ DC_PEE->message = malloc(sizeof(char)*strlenm+1);
+ vsnprintf(DC_PEE->message, strlenm+1, m, ap2);
va_end(ap);
va_end(ap2);
} else {
- e[*s-1]->message = malloc(sizeof(char)*strlenm+1);
- strcpy(e[*s-1]->message, m);
- }
- e[*s-1]->file = f;
- e[*s-1]->line = l;
- e[*s-1]->function = c /* Caller */;
- e[*s-1]->time = time(NULL);
- e[*s-1]->reported = 0;
+ DC_PEE->message = malloc(sizeof(char)*strlenm+1);
+ strcpy(DC_PEE->message, m);
+ }
+ DC_PEE->file = f;
+ DC_PEE->line = l;
+ DC_PEE->function = caller /* Caller */;
+ DC_PEE->time = time(NULL);
+ DC_PEE->reported = 0;
if (lock && pthread_rwlock_unlock(lock))
return -2;
return 1;
@@ -240,14 +248,15 @@ cJSON * dc_api (struct dc_client * c, char * body, int isfmt, char * endpoint, .
return NULL;
}
cJSON * json = NULL;
- struct writefunc_string s, h;
+ struct writefunc_string * s = malloc(sizeof(struct writefunc_string));
+ struct writefunc_string * h = malloc(sizeof(struct writefunc_string));
size_t va_count = parse_printf_format(endpoint, 0, NULL);
char * endpoint_formatted = NULL;
int retried = 0;
long response_code = 0;
retry:
- init_writefunc_string(&s);
- init_writefunc_string(&h);
+ init_writefunc_string(s);
+ init_writefunc_string(h);
if (isfmt && va_count > 0 && endpoint_formatted == NULL) {
va_list ap, ap2;
va_start(ap, endpoint);
@@ -259,34 +268,41 @@ cJSON * dc_api (struct dc_client * c, char * body, int isfmt, char * endpoint, .
va_end(ap2);
}
curl_easy_setopt(c->curl, CURLOPT_URL, endpoint_formatted ? endpoint_formatted : endpoint);
- if (!body)
- curl_easy_setopt(c->curl, CURLOPT_HTTPGET, 1L);
curl_easy_setopt(c->curl, CURLOPT_POSTFIELDS, body); /* yes, even null is okay, it's actually a must as it makes sure curl clears old pointers and does not read freed memory. see https://github.com/curl/curl/issues/3214#issuecomment-435335974 */
- curl_easy_setopt(c->curl, CURLOPT_WRITEDATA, &s);
- curl_easy_setopt(c->curl, CURLOPT_HEADERDATA, &h);
+ if (!body)
+ curl_easy_setopt(c->curl, CURLOPT_HTTPGET, 1L); /* this must be done after postfields */
+ curl_easy_setopt(c->curl, CURLOPT_WRITEDATA, s);
+ curl_easy_setopt(c->curl, CURLOPT_NOSIGNAL, 1L);
+ curl_easy_setopt(c->curl, CURLOPT_HEADERDATA, h);
+ curl_easy_setopt(c->curl, CURLOPT_FOLLOWLOCATION, 1L);
+ curl_easy_setopt(c->curl, CURLOPT_HTTPHEADER, c->curl_headers);
+ curl_easy_setopt(c->curl, CURLOPT_TIMEOUT, 20L); /* 20 second timeout */
curl_easy_setopt(c->curl, CURLOPT_HEADERFUNCTION, writefunc);
+ curl_easy_setopt(c->curl, CURLOPT_WRITEFUNCTION, writefunc);
if (curl_easy_perform(c->curl) != CURLE_OK) {
DC_CLIENT_ERROR(c, "curl_easy_perform(curl) != CURLE_OK");
goto rc;
} else {
curl_easy_getinfo(c->curl, CURLINFO_RESPONSE_CODE, &response_code);
}
- fprintf(netreq, "%s\n%s\n%s\n%s====================================\n", endpoint_formatted ? endpoint_formatted : endpoint, body ? body : "GET", h.ptr, s.ptr);
+ fprintf(netreq, "%s\n%s\n%s\n%s====================================\n", endpoint_formatted ? endpoint_formatted : endpoint, body ? body : "GET", h->ptr, s->ptr);
fflush(netreq);
- char * cp = strstr(h.ptr, "\nx-ratelimit-reset-after: ");
+ char * cp = strstr(h->ptr, "\nx-ratelimit-reset-after: ");
if (cp == NULL)
goto norlheaders;
cp += strlen("\nx-ratelimit-reset-after: ");
double retry_after = strtod(cp, NULL);
- cp = strstr(h.ptr, "\nx-ratelimit-remaining: ");
+ cp = strstr(h->ptr, "\nx-ratelimit-remaining: ");
if (cp == NULL)
goto norlheaders;
cp += strlen("\nx-ratelimit-remaining: ");
if (cp[0] >= '0' && cp[0] <= '9' && atoi(cp) == 0) { /* X-RateLimit-Remaining: 0 */
DC_CLIENT_ERROR(c, DC_I18N_HITRL " %lfs. endpoint = %s", retry_after, endpoint_formatted ? endpoint_formatted : endpoint);
sleep(ceil(retry_after)+1); /* TODO: prevent hanging entire thread just for this */
- free(s.ptr); s.ptr = NULL;
- free(h.ptr); h.ptr = NULL;
+ free(s->ptr); s->ptr = NULL;
+ free(h->ptr); h->ptr = NULL;
+ free(s); s = NULL;
+ free(h); h = NULL;
cJSON_Delete(json);
json = NULL;
if (retried++)
@@ -294,26 +310,27 @@ cJSON * dc_api (struct dc_client * c, char * body, int isfmt, char * endpoint, .
goto retry;
}
norlheaders:
- json = cJSON_Parse(s.ptr);
+ json = cJSON_Parse(s->ptr);
if (!json) {
const char * error_ptr = cJSON_GetErrorPtr();
if (error_ptr) {
- DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED ": " DC_I18N_JSON_ERROR_BEFORE ": %.21s s.ptr = %s", error_ptr, s.ptr);
+ DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED ": " DC_I18N_JSON_ERROR_BEFORE ": %.21s s->ptr = %s", error_ptr, s->ptr);
} else {
- DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED ". s.ptr = %s", s.ptr ? s.ptr : "NULL");
+ DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED ". s->ptr = %s", s->ptr ? s->ptr : "NULL");
}
goto rc;
}
rc:
curl_easy_setopt(c->curl, CURLOPT_HEADERFUNCTION, NULL); /* for usages that don't use headerfunction */
free(endpoint_formatted);
- free(s.ptr); s.ptr = NULL;
- free(h.ptr); h.ptr = NULL;
+ free(s->ptr); s->ptr = NULL;
+ free(h->ptr); h->ptr = NULL;
+ free(s); s = NULL;
+ free(h); h = NULL;
return json;
}
int dc_login (struct dc_client * c) { /* noui */
int rs = 1;
- struct writefunc_string s;
char * data = NULL;
cJSON * json = NULL;
if (!c)
@@ -328,34 +345,15 @@ int dc_login (struct dc_client * c) { /* noui */
DC_CLIENT_ERROR(c, "curl_easy_init() " DC_I18N_FAILED);
return -3;
}
- init_writefunc_string(&s);
- data = malloc(snprintf(data, 0, DC_LOGIN_FORMAT, c->email, c->password)+1);
+ data = malloc(snprintf(NULL, 0, DC_LOGIN_FORMAT, c->email, c->password)+1);
sprintf(data, DC_LOGIN_FORMAT, c->email, c->password);
- CURLcode res;
- curl_slist_free_all(c->curl_headers);
+ /* curl_slist_free_all(c->curl_headers); */
c->curl_headers = curl_slist_append(c->curl_headers, "Content-Type: application/json");
c->curl_headers = curl_slist_append(c->curl_headers, "User-Agent: " DC_USER_AGENT);
- curl_easy_setopt(c->curl, CURLOPT_URL, DC_API_PREFIX "auth/login");
- curl_easy_setopt(c->curl, CURLOPT_FOLLOWLOCATION, 1L);
- curl_easy_setopt(c->curl, CURLOPT_POSTFIELDS, data);
- curl_easy_setopt(c->curl, CURLOPT_WRITEFUNCTION, writefunc);
- curl_easy_setopt(c->curl, CURLOPT_HTTPHEADER, c->curl_headers);
- curl_easy_setopt(c->curl, CURLOPT_WRITEDATA, &s);
- res = curl_easy_perform(c->curl);
- if (res != CURLE_OK) {
- DC_CLIENT_ERROR(c, "curl_easy_perform() " DC_I18N_FAILED ": %s", curl_easy_strerror(res)); /* yeah, format strings are supported */
- rs = -4;
- goto rc;
- }
- json = cJSON_Parse(s.ptr);
+ json = DC_CAPI(c, data, DC_API_PREFIX "auth/login");
if (!json) {
- const char *error_ptr = cJSON_GetErrorPtr();
- if (error_ptr) {
- DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED ": " DC_I18N_JSON_ERROR_BEFORE ": %s", error_ptr);
- } else {
- DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED);
- }
- rs = -5;
+ DC_CLIENT_ERROR(c, "!DC_CAPI auth/login, data = %s", data);
+ rs = -4;
goto rc;
}
cJSON * token = cJSON_GetObjectItem(json, "token");
@@ -371,29 +369,12 @@ int dc_login (struct dc_client * c) { /* noui */
strcpy(data, "Authorization: ");
strcat(data, c->authorization);
if (DC_CUE(c, c->authorization_lock)) {rs = -8; goto rc;}
- free(s.ptr); s.ptr = NULL;
- init_writefunc_string(&s);
- curl_easy_setopt(c->curl, CURLOPT_URL, DC_API_PREFIX "users/@me");
- curl_easy_setopt(c->curl, CURLOPT_HTTPGET, 1L);
- curl_easy_setopt(c->curl, CURLOPT_POSTFIELDS, NULL);
- curl_easy_setopt(c->curl, CURLOPT_WRITEDATA, &s);
c->curl_headers = curl_slist_append(c->curl_headers, data);
- res = curl_easy_perform(c->curl);
- if (res != CURLE_OK) {
- DC_CLIENT_ERROR(c, "curl_easy_perform() " DC_I18N_FAILED ": %s", curl_easy_strerror(res));
- rs = -9;
- goto rc;
- }
cJSON_Delete(json);
- json = cJSON_Parse(s.ptr);
+ json = DC_CAPI(c, NULL, DC_API_PREFIX "users/@me");
if (!json) {
- const char *error_ptr = cJSON_GetErrorPtr();
- if (error_ptr) {
- DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED ": " DC_I18N_JSON_ERROR_BEFORE ": %s", error_ptr);
- } else {
- DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED);
- }
- rs = -10;
+ DC_CLIENT_ERROR(c, "!DC_CAPI users/@me");
+ rs = -7;
goto rc;
}
token = cJSON_GetObjectItem(json, "username");
@@ -409,7 +390,6 @@ int dc_login (struct dc_client * c) { /* noui */
if (DC_CUE(c, c->username_lock)) {rs = -12; goto rc;}
c->discriminator = strtol(token2->valuestring, NULL, 10);
rc:
- free(s.ptr); s.ptr = NULL;
free(data); data = NULL;
cJSON_Delete(json);
return rs;
@@ -441,6 +421,7 @@ int dc_fetch_guilds (struct dc_client * c) {
if(DC_CWLE(c, c->guilds_lock)) {rs = -5; goto rc;}
cJSON * guild = NULL;
cJSON_ArrayForEach(guild, json) {
+ int skip = 0;
value = cJSON_GetStringValue(cJSON_GetObjectItem(guild, "name"));
value2 = cJSON_GetStringValue(cJSON_GetObjectItem(guild, "id"));
if (!value || !value2) {
@@ -451,8 +432,11 @@ int dc_fetch_guilds (struct dc_client * c) {
}
unsigned long long int idull = strtoull(value2, NULL, 10);
for (int i = 0; i < c->guilds_sizeof; i++)
- if (idull == c->guilds[i]->id)
- continue; /* remove duplicates */
+ if (idull == c->guilds[i]->id) {
+ skip = 1;
+ break; /* remove duplicates */
+ }
+ if (skip) continue;
c->guilds = realloc(c->guilds, sizeof(struct dc_guild *)*++c->guilds_sizeof);
c->guilds[c->guilds_sizeof-1] = malloc(sizeof(struct dc_guild));
c->guilds[c->guilds_sizeof-1]->name = malloc(strlen(value)+1);
@@ -496,13 +480,22 @@ int dc_fetch_channels (struct dc_guild * g) {
goto rc;
}
cJSON * channel = NULL;
+ cJSON * perms = NULL;
+ cJSON * perm = NULL;
/* we lock all client guilds when doing stuff with channels */
if (DC_CWLE(c, c->guilds_lock)) {rs = -7; goto rc;}
cJSON_ArrayForEach(channel, json) {
+ int skip = 0;
+ if (cJSON_IsArray(perms = cJSON_GetObjectItem(channel, "permission_overwrites"))); /* not supported */
+ cJSON_ArrayForEach(perm, perms) {
+ skip++;
+ }
+ if (skip) continue;
char * topic = cJSON_GetStringValue(cJSON_GetObjectItem(channel, "topic"));
char * name = cJSON_GetStringValue(cJSON_GetObjectItem(channel, "name"));
char * id = cJSON_GetStringValue(cJSON_GetObjectItem(channel, "id"));
double type = cJSON_GetNumberValue(cJSON_GetObjectItem(channel, "type"));
+ double slowmode = cJSON_GetNumberValue(cJSON_GetObjectItem(channel, "rate_limit_per_user"));
if (!id || !name || type == NAN) {
DC_CLIENT_ERROR(c, "!id || !name || type == NAN");
continue;
@@ -513,8 +506,11 @@ int dc_fetch_channels (struct dc_guild * g) {
topic = "";
unsigned long long int idull = strtoull(id, NULL, 10);
for (int i = 0; i < g->channels_sizeof; i++)
- if (idull == g->channels[i]->id)
- continue; /* remove duplicates */
+ if (idull == g->channels[i]->id) {
+ skip++;
+ break;
+ }
+ if (skip) continue;
g->channels = realloc(g->channels, sizeof(struct dc_channel *)*++g->channels_sizeof);
g->channels[g->channels_sizeof-1] = malloc(sizeof(struct dc_channel));
g->channels[g->channels_sizeof-1]->name = malloc(strlen(name)+1);
@@ -525,6 +521,7 @@ int dc_fetch_channels (struct dc_guild * g) {
g->channels[g->channels_sizeof-1]->guild = g;
g->channels[g->channels_sizeof-1]->messages = NULL;
g->channels[g->channels_sizeof-1]->messages_sizeof = 0;
+ g->channels[g->channels_sizeof-1]->slowmode = slowmode != NAN ? slowmode : 0;
}
if (DC_CUE(c, c->guilds_lock)) {rs = -8; goto rc;}
rc:
@@ -583,6 +580,7 @@ int dc_send_message (struct dc_message * m) { /* nolock - once message is append
rc:
free(body); body = NULL;
cJSON_Delete(json); json = NULL;
+ c->last_sent_message = time(NULL);
return rs;
}
int dc_fetch_messages (struct dc_channel * ch) {
@@ -616,6 +614,7 @@ int dc_fetch_messages (struct dc_channel * ch) {
if (DC_CWLE(c, c->guilds_lock)) {rs = -7; goto rc;} /* we lock all guilds of a client when writing messages */
cJSON * message = NULL;
cJSON_ArrayForEach(message, json) {
+ int skip = 0;
char * timestamp = cJSON_GetStringValue(cJSON_GetObjectItem(message, "timestamp"));
char * content = cJSON_GetStringValue(cJSON_GetObjectItem(message, "content"));
char * id = cJSON_GetStringValue(cJSON_GetObjectItem(message, "id"));
@@ -637,11 +636,15 @@ int dc_fetch_messages (struct dc_channel * ch) {
}
unsigned long long int idull = strtoull(id, NULL, 10);
for (int i = 0; i < ch->messages_sizeof; i++)
- if (idull == ch->messages[i]->id)
- continue; /* remove duplicates */
+ if (idull == ch->messages[i]->id) {
+ skip++;
+ break; /* remove duplicates */
+ }
+ if (skip) continue;
ch->messages = realloc(ch->messages, sizeof(struct dc_message *)*++ch->messages_sizeof);
#define DC_FMTM /* fetch messages this message */ ch->messages[ch->messages_sizeof-1]
- DC_FMTM = malloc(sizeof(struct dc_message));
+ /* DC_CLIENT_ERROR(c, "recvd msg %llu", idull); */ /* remember: continue in a nested forloop is not useful in some cases (: */
+ DC_FMTM = calloc(1, sizeof(struct dc_message));
DC_FMTM->time = mktime(&tm);
DC_FMTM->content = malloc(strlen(content)+1);
strcpy(DC_FMTM->content, content);
@@ -651,7 +654,7 @@ int dc_fetch_messages (struct dc_channel * ch) {
DC_FMTM->discriminator = strtol(discriminator, NULL, 10);
DC_FMTM->channel = ch;
}
- qsort(ch->messages, ch->messages_sizeof, sizeof(struct dc_message), dc_message_compare); /* we sort so that present messages are in the start of the array and old messages are to the end of the array */
+ qsort(ch->messages, ch->messages_sizeof, sizeof(struct dc_message *), dc_message_compare); /* we sort so that present messages are in the start of the array and old messages are to the end of the array */
if (DC_CUE(c, c->guilds_lock)) {rs = -8; goto rc;}
rc:
cJSON_Delete(json); json = NULL;
@@ -670,6 +673,7 @@ struct dc_thread_control {
};
int dc_api_thread (struct dc_thread_control * t) { /* updates messages and sends messages when they are in the outbox */
while (!t->power_api) usleep(250000); /* so as to not make the switcher go bankrupt */
+ curl_global_init(CURL_GLOBAL_ALL);
/* if (pthread_rwlock_wrlock(t->clients_lock))
return -1; */ /* clients are not locked yet */
for (int i = 0; i < t->clients_sizeof && t->power_api != 2; i++)
@@ -683,9 +687,9 @@ int dc_api_thread (struct dc_thread_control * t) { /* updates messages and sends
for (int j = 0; j < t->clients[i]->guilds_sizeof; j++) {
if (!t->clients[i]->guilds[j]->channels_sizeof /*|| !(rand() % 100)*/) /* roughly every 100+inf cycles we'll update channels */
dc_fetch_channels(t->clients[i]->guilds[j]);
- for (int k = 0; k < t->clients[i]->guilds[j]->channels_sizeof; k++)
- if (!(rand() % 10)) /* roughly every 10 cycles we'll update messages */
- dc_fetch_messages(t->clients[i]->guilds[j]->channels[k]);
+ /* for (int k = 0; k < t->clients[i]->guilds[j]->channels_sizeof; k++) */
+ if (!(rand() % 10) && t->clients[i]->joinedchannel) /* roughly every 10 cycles we'll update messages in the joined ch */
+ dc_fetch_messages(t->clients[i]->joinedchannel);
}
if (DC_CWLE(t->clients[i], t->clients[i]->sent_messages_lock)) continue;
if (t->clients[i]->sent_messages_sizeof > 0) {
@@ -695,7 +699,7 @@ int dc_api_thread (struct dc_thread_control * t) { /* updates messages and sends
msg2send->channel->messages = realloc(msg2send->channel->messages, sizeof(struct dc_message *)*++msg2send->channel->messages_sizeof);
msg2send->channel->messages[msg2send->channel->messages_sizeof-1] = msg2send;
DC_CUE(t->clients[i], t->clients[i]->guilds_lock); */ /* we will no longer do this, let the thread fetch the msg */
- for (int j = 0; j <= t->clients[i]->sent_messages_sizeof; j++) /* shift, we removed one from the start */
+ for (int j = 0; j < t->clients[i]->sent_messages_sizeof-1; j++) /* shift, we removed one from the start */
t->clients[i]->sent_messages[j] = t->clients[i]->sent_messages[j+1];
t->clients[i]->sent_messages_sizeof--;
}
@@ -705,6 +709,7 @@ int dc_api_thread (struct dc_thread_control * t) { /* updates messages and sends
}
usleep(250000);
}
+ curl_global_cleanup();
/* if (pthread_rwlock_unlock(t->clients_lock))
return -2; */
return 1;