Browse Source

Modify channel request

Alexander Memer 10 months ago
parent
commit
1a1fe3273e
7 changed files with 360 additions and 112 deletions
  1. 1
    1
      CMakeLists.txt
  2. 26
    2
      examples/main.c
  3. 18
    0
      include/discord.h
  4. 2
    0
      include/requests.h
  5. 57
    0
      lib/requests.c
  6. 114
    109
      lib/rest.c
  7. 142
    0
      lib/utils.c

+ 1
- 1
CMakeLists.txt View File

@@ -43,7 +43,7 @@ else()
43 43
 endif()
44 44
 set(CMAKE_C_STANDARD 99)
45 45
 
46
-add_library(discord lib/discord.c include/discord.h lib/rest.c lib/requests.c include/requests.h lib/log.c include/log.h)
46
+add_library(discord lib/discord.c include/discord.h lib/rest.c lib/requests.c include/requests.h lib/log.c include/log.h lib/utils.c)
47 47
 target_link_libraries(discord ${JANSSON_LIBRARIES} ${CURL_LIBRARIES})
48 48
 
49 49
 if (EXAMPLES)

+ 26
- 2
examples/main.c View File

@@ -63,7 +63,7 @@ int main(int argc, char **argv)
63 63
         fprintf(stderr, "Failed to create libdiscord context");
64 64
         return -1;
65 65
     }
66
-
66
+/*
67 67
     printf("%s\n", ld_get_gateway(ctx));
68 68
 
69 69
     struct ld_gateway_bot_resp *r = ld_get_gateway_bot(ctx);
@@ -83,12 +83,36 @@ int main(int argc, char **argv)
83 83
     {
84 84
         return -1;
85 85
     }
86
-
86
+*/
87 87
     guild_channel_t channel;
88 88
 
89 89
     ld_get_channel(ctx, "444130990252752898", &channel);
90 90
 
91 91
     log_trace(channel.guild_id);
92 92
 
93
+
94
+    struct ld_modify_channel_obj *m = malloc(sizeof(struct ld_modify_channel_obj));
95
+
96
+    memset(m, 0, sizeof(struct ld_modify_channel_obj));
97
+
98
+    m->name = "основной2";
99
+    m->user_limit = -1;
100
+    m->bitrate = -1;
101
+    m->nsfw = -1;
102
+    m->position = -1;
103
+
104
+    m->permission_overwrites = calloc(1, sizeof(overwrite_t));
105
+    m->overwrites_size = 1;
106
+    m->permission_overwrites[0].id = "472393766989201408";
107
+    m->permission_overwrites[0].type = "member";
108
+    m->permission_overwrites[0].deny = 0;
109
+    m->permission_overwrites[0].allow = 2048;
110
+
111
+    guild_channel_t c;
112
+
113
+    ld_modify_channel_result(ctx, "444130990252752898", m, &c);
114
+
115
+    free(m);
116
+
93 117
     return 0;
94 118
 }

+ 18
- 0
include/discord.h View File

@@ -8,6 +8,7 @@
8 8
 #include <stdbool.h>
9 9
 
10 10
 #include <curl/curl.h>
11
+#include <jansson.h>
11 12
 
12 13
 #define LD_API_ENDPOINT "https://discordapp.com/api"
13 14
 
@@ -244,11 +245,28 @@ typedef struct message {
244 245
     char* webhook_id;
245 246
 } message_t;
246 247
 
248
+struct ld_modify_channel_obj
249
+{
250
+    char *name;
251
+    int position;
252
+    char *topic;
253
+    int nsfw;
254
+    int bitrate;
255
+    int user_limit;
256
+    overwrite_t *permission_overwrites;
257
+    size_t overwrites_size;
258
+    char *parent_id;
259
+};
260
+
247 261
 struct ld_context *ld_create_context(struct ld_context_info *info);
248 262
 
249 263
 char *ld_get_gateway(struct ld_context *ctx);
250 264
 struct ld_gateway_bot_resp *ld_get_gateway_bot(struct ld_context *ctx);
251 265
 int ld_create_message(struct ld_context *ctx, char *channel_id, char *content);
252 266
 int ld_get_channel(struct ld_context *ctx, char *channel_id, guild_channel_t *target);
267
+int ld_modify_channel_result(struct ld_context *ctx, char *channel_id, struct ld_modify_channel_obj *modify, guild_channel_t *result);
268
+int ld_modify_channel(struct ld_context *ctx, char *channel_id, struct ld_modify_channel_obj *modify);
269
+
270
+void ld_channel_obj_to_type(json_t *src, guild_channel_t *channel);
253 271
 
254 272
 #endif // _DISCORD_H

+ 2
- 0
include/requests.h View File

@@ -58,6 +58,8 @@ CURLcode requests_post_headers(CURL *curl, req_t *req, char *url, char *data,
58 58
                                char **custom_hdrv, int custom_hdrc);
59 59
 CURLcode requests_put_headers(CURL *curl, req_t *req, char *url, char *data,
60 60
                               char **custom_hdrv, int custom_hdrc);
61
+CURLcode requests_patch(CURL *curl, req_t *req, char *url, char *data,
62
+                               char **custom_hdrv, int custom_hdrc, int is_json);
61 63
 char *requests_url_encode(CURL *curl, char **data, int data_size);
62 64
 
63 65
 #endif

+ 57
- 0
lib/requests.c View File

@@ -386,6 +386,63 @@ static CURLcode requests_pt(CURL *curl, req_t *req, char *url, char *data,
386 386
     return rc;
387 387
 }
388 388
 
389
+// Extension for patch requests
390
+CURLcode requests_patch(CURL *curl, req_t *req, char *url, char *data,
391
+                               char **custom_hdrv, int custom_hdrc, int is_json)
392
+{
393
+    CURLcode rc;
394
+    struct curl_slist *slist = NULL;
395
+    req->url = url;
396
+
397
+    /* body data */
398
+    if (data != NULL) {
399
+        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
400
+    } else {
401
+        /* content length header defaults to -1, which causes request to fail
402
+           sometimes, so we need to manually set it to 0 */
403
+        char *cl_header = "Content-Length: 0";
404
+        slist = curl_slist_append(slist, cl_header);
405
+        if (slist == NULL)
406
+            return -1;
407
+        if (custom_hdrv == NULL)
408
+            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
409
+
410
+        hdrv_append(&req->req_hdrv, &req->req_hdrc, cl_header);
411
+    }
412
+
413
+    /* headers */
414
+    if (custom_hdrv != NULL) {
415
+        rc = process_custom_headers(&slist, req, custom_hdrv, custom_hdrc);
416
+        if (rc != CURLE_OK)
417
+            return rc;
418
+        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
419
+    }
420
+
421
+    if (is_json) {
422
+        curl_slist_append(slist, "Content-Type: application/json");
423
+    }
424
+
425
+    common_opt(curl, req);
426
+    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
427
+    char *ua = user_agent();
428
+    curl_easy_setopt(curl, CURLOPT_USERAGENT, ua);
429
+    rc = curl_easy_perform(curl);
430
+    if (rc != CURLE_OK)
431
+        return rc;
432
+
433
+    long code;
434
+    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
435
+    req->code = code;
436
+    req->ok = check_ok(code);
437
+
438
+    if (slist != NULL)
439
+        curl_slist_free_all(slist);
440
+    free(ua);
441
+    curl_easy_cleanup(curl);
442
+
443
+    return rc;
444
+}
445
+
389 446
 /*
390 447
  * process_custom_headers - Adds custom headers to request and populates the
391 448
  * req_headerv and req_hdrc fields of the request struct using the supplied

+ 114
- 109
lib/rest.c View File

@@ -125,6 +125,51 @@ json_t *ld_post_request(struct ld_context *ctx, char *url, json_t *contents)
125 125
     return res;
126 126
 }
127 127
 
128
+json_t *ld_patch_request(struct ld_context *ctx, char *url, json_t *contents)
129
+{
130
+    req_t req;
131
+    ctx->curl_handle = requests_init(&req);
132
+
133
+    char *target = malloc(strlen(LD_API_ENDPOINT) + strlen(url) + 1);
134
+    char *auth = malloc(strlen("Authorization: Bot ") + strlen(ctx->bot_token) + 1);
135
+
136
+    sprintf(target, "%s%s", LD_API_ENDPOINT, url);
137
+    sprintf(auth, "%s%s", "Authorization: Bot ", ctx->bot_token);
138
+
139
+    if (!contents)
140
+    {
141
+        requests_patch(ctx->curl_handle, &req, target, "", &auth, 1, 1);
142
+    }
143
+    else
144
+    {
145
+        requests_patch(ctx->curl_handle, &req, target, json_dumps(contents, 0), &auth, 1, 1);
146
+    }
147
+
148
+    free(target);
149
+    free(auth);
150
+
151
+    if(!req.ok)
152
+    {
153
+        _ld_set_last_rest_error(ctx, &req);
154
+        return NULL;
155
+    }
156
+
157
+    json_t *res;
158
+    json_error_t err;
159
+
160
+    res = json_loads(req.text, 0, &err);
161
+
162
+    requests_close(&req);
163
+
164
+    if (!res)
165
+    {
166
+        log_error("failed to parse json on line %d: %s", err.line, err.text);
167
+        return NULL;
168
+    }
169
+
170
+    return res;
171
+}
172
+
128 173
 char *ld_get_gateway(struct ld_context *ctx)
129 174
 {
130 175
     json_t *res = ld_get_request(ctx, "/gateway");
@@ -232,138 +277,98 @@ int ld_get_channel(struct ld_context *ctx, char *channel_id, guild_channel_t *ch
232 277
         return -1;
233 278
     }
234 279
 
235
-    log_trace("%s", json_dumps(res, 0));
280
+    ld_channel_obj_to_type(res, channel);
236 281
 
237
-    json_t *id = json_object_get(res, "id");
238
-    channel->id = strdup(json_string_value(id));
239
-    json_decref(id);
282
+    return 0;
283
+}
240 284
 
241
-    json_t *type = json_object_get(res, "type");
242
-    channel->type = (int)json_integer_value(type);
243
-    json_decref(type);
285
+int ld_modify_channel(struct ld_context *ctx, char *channel_id, struct ld_modify_channel_obj *modify)
286
+{
287
+    ld_modify_channel_result(ctx, channel_id, modify, NULL);
288
+}
244 289
 
245
-    if (channel->type == GUILD_TEXT || channel->type == GUILD_CATEGORY)
290
+int ld_modify_channel_result(struct ld_context *ctx, char *channel_id, struct ld_modify_channel_obj *modify, guild_channel_t *result)
291
+{
292
+
293
+    json_t *contents = json_object();
294
+
295
+    if (modify->name)
246 296
     {
247
-        json_t *guild_id = json_object_get(res, "guild_id");
248
-        channel->guild_id = strdup(json_string_value(guild_id));
249
-        json_decref(guild_id);
297
+        json_object_set_new(contents, "name", json_string(modify->name));
298
+    }
250 299
 
251
-        json_t *permission_overwrites = json_object_get(res, "permission_overwrites");
252
-        size_t osize = json_array_size(permission_overwrites);
300
+    if (modify->position != -1)
301
+    {
302
+        json_object_set_new(contents, "position", json_integer(modify->position));
303
+    }
253 304
 
254
-        channel->permission_overwrites = calloc(osize, sizeof(overwrite_t));
305
+    if (modify->topic)
306
+    {
307
+        json_object_set_new(contents, "topic", json_string(modify->topic));
308
+    }
255 309
 
256
-        size_t index;
257
-        json_t *value;
310
+    if (modify->parent_id)
311
+    {
312
+        json_object_set_new(contents, "parent_id", json_string(modify->parent_id));
313
+    }
258 314
 
259
-        json_array_foreach(permission_overwrites, index, value)
260
-        {
261
-            overwrite_t temp;
315
+    if (modify->nsfw != -1)
316
+    {
317
+        json_object_set_new(contents, "nsfw", json_boolean(modify->nsfw));
318
+    }
262 319
 
263
-            temp.id = (char*)json_string_value(json_object_get(value, "id"));
264
-            temp.type = (char*)json_string_value(json_object_get(value, "type"));
265
-            temp.deny = (int)json_integer_value(json_object_get(value, "deny"));
266
-            temp.allow = (int)json_integer_value(json_object_get(value, "allow"));
267
-            channel->permission_overwrites[index] = temp;
268
-        }
320
+    if (modify->bitrate != -1)
321
+    {
322
+        json_object_set_new(contents, "bitrate", json_integer(modify->bitrate));
323
+    }
269 324
 
270
-        json_decref(permission_overwrites);
325
+    if (modify->user_limit != -1)
326
+    {
327
+        json_object_set_new(contents, "user_limit", json_integer(modify->user_limit));
328
+    }
271 329
 
272
-        json_t *name = json_object_get(res, "name");
273
-        channel->name = strdup(json_string_value(name));
274
-        json_decref(name);
275
-        if (channel->type == GUILD_TEXT)
276
-        {
277
-            // Topic is nullable
278
-            json_t *topic = json_object_get(res, "topic");
279
-            if (json_is_string(topic)) {
280
-                channel->topic = strdup(json_string_value(topic));
281
-            }
282
-            json_decref(topic);
283
-
284
-            json_t *nsfw = json_object_get(res, "nsfw");
285
-            channel->nsfw = json_boolean_value(nsfw);
286
-            json_decref(nsfw);
287
-
288
-            json_t *last_message_id = json_object_get(res, "last_message_id");
289
-            if (last_message_id) {
290
-                if (json_is_string(last_message_id)) {
291
-                    channel->last_message_id = strdup(json_string_value(last_message_id));
292
-                }
293
-                json_decref(last_message_id);
294
-            }
295
-        }
330
+    if (modify->permission_overwrites && modify->overwrites_size > 0)
331
+    {
332
+        json_t *overwrites = json_array();
296 333
 
297
-        json_t *parent_id = json_object_get(res, "parent_id");
298
-        if (json_is_string(parent_id))
334
+        for (int i = 0; i < modify->overwrites_size; i++)
299 335
         {
300
-            channel->parent_id = strdup(json_string_value(parent_id));
301
-        }
302
-        json_decref(parent_id);
336
+            json_t *overwrite = json_object();
303 337
 
304
-        json_t *position = json_object_get(res, "position");
305
-        channel->position = (int)json_integer_value(position);
306
-        json_decref(position);
307
-    }
308
-    else if (channel->type == GUILD_VOICE)
309
-    {
310
-        json_t *bitrate = json_object_get(res, "bitrate");
311
-        channel->bitrate = (int)json_integer_value(bitrate);
312
-        json_decref(bitrate);
338
+            json_object_set_new(overwrite, "id", json_string(modify->permission_overwrites[i].id));
339
+            json_object_set_new(overwrite, "type", json_string(modify->permission_overwrites[i].type));
340
+            json_object_set_new(overwrite, "deny", json_integer(modify->permission_overwrites[i].deny));
341
+            json_object_set_new(overwrite, "allow", json_integer(modify->permission_overwrites[i].allow));
313 342
 
314
-        json_t *user_limit = json_object_get(res, "user_limit");
315
-        channel->user_limit = (int)json_integer_value(user_limit);
316
-        json_decref(user_limit);
317
-    }
318
-    else if (channel->type == DM || channel->type == GROUP_DM)
319
-    {
343
+            json_array_append_new(overwrites, overwrite);
344
+        }
320 345
 
321
-        json_t *recipients = json_object_get(res, "recipients");
322
-        size_t rsize = json_array_size(recipients);
346
+        json_object_set_new(contents, "permission_overwrites", overwrites);
347
+    }
323 348
 
324
-        channel->recipients = calloc(rsize, sizeof(user_t));
349
+    char *target = malloc(strlen("/channels/") + strlen(channel_id));
325 350
 
326
-        size_t index;
327
-        json_t *value;
351
+    sprintf(target, "/channels/%s", channel_id);
328 352
 
329
-        json_array_foreach(recipients, index, value)
330
-        {
331
-            user_t temp;
332
-            // TODO: Create function for converting json user objects to structs
333
-            temp.id = (char*)json_string_value(json_object_get(value, "id"));
334
-            temp.username = (char*)json_string_value(json_object_get(value, "username"));
335
-            temp.discriminator = (char*)json_string_value(json_object_get(value, "discriminator"));
336
-            json_t *avatar = json_object_get(value, "avatar");
337
-            if (avatar)
338
-            {
339
-                temp.avatar = (char*)json_string_value(avatar);
340
-                json_decref(avatar);
341
-            }
342
-
343
-            channel->recipients[index] = temp;
344
-        }
353
+    json_t *res = ld_patch_request(ctx, target, contents);
345 354
 
346
-        json_t *icon = json_object_get(res, "icon");
347
-        if (icon)
348
-        {
349
-            if (json_is_string(icon))
350
-            {
351
-                channel->icon = strdup(json_string_value(icon));
352
-            }
353
-            json_decref(icon);
354
-        }
355
+    free(target);
356
+    free(contents);
355 357
 
356
-        json_t *owner_id = json_object_get(res, "owner_id");
357
-        channel->owner_id = strdup(json_string_value(owner_id));
358
-        json_decref(owner_id);
358
+    if (!res)
359
+    {
360
+        log_error("probably failed to modify channel");
361
+        return -1;
362
+    }
359 363
 
360
-        json_t *application_id = json_object_get(res, "application_id");
361
-        if (application_id)
362
-        {
363
-            channel->application_id = strdup(json_string_value(application_id));
364
-            json_decref(application_id);
365
-        }
364
+    if (!result)
365
+    {
366
+        json_decref(res);
367
+        return 0;
366 368
     }
367 369
 
370
+    ld_channel_obj_to_type(res, result);
371
+
368 372
     return 0;
373
+
369 374
 }

+ 142
- 0
lib/utils.c View File

@@ -0,0 +1,142 @@
1
+//
2
+// Created by Memer on 25.08.18.
3
+// Copyright (c) 2018 Alexander Memer. All rights reserved.
4
+//
5
+
6
+#include <discord.h>
7
+#include <jansson.h>
8
+#include <string.h>
9
+
10
+void ld_channel_obj_to_type(json_t *src, guild_channel_t *channel)
11
+{
12
+    json_t *id = json_object_get(src, "id");
13
+    channel->id = strdup(json_string_value(id));
14
+    json_decref(id);
15
+
16
+    json_t *type = json_object_get(src, "type");
17
+    channel->type = (int)json_integer_value(type);
18
+    json_decref(type);
19
+
20
+    if (channel->type == GUILD_TEXT || channel->type == GUILD_CATEGORY)
21
+    {
22
+        json_t *guild_id = json_object_get(src, "guild_id");
23
+        channel->guild_id = strdup(json_string_value(guild_id));
24
+        json_decref(guild_id);
25
+
26
+        json_t *permission_overwrites = json_object_get(src, "permission_overwrites");
27
+        size_t osize = json_array_size(permission_overwrites);
28
+
29
+        channel->permission_overwrites = calloc(osize, sizeof(overwrite_t));
30
+
31
+        size_t index;
32
+        json_t *value;
33
+
34
+        json_array_foreach(permission_overwrites, index, value)
35
+        {
36
+            overwrite_t temp;
37
+
38
+            temp.id = strdup((char*)json_string_value(json_object_get(value, "id")));
39
+            temp.type = strdup((char*)json_string_value(json_object_get(value, "type")));
40
+            temp.deny = (int)json_integer_value(json_object_get(value, "deny"));
41
+            temp.allow = (int)json_integer_value(json_object_get(value, "allow"));
42
+            channel->permission_overwrites[index] = temp;
43
+        }
44
+
45
+        json_decref(permission_overwrites);
46
+
47
+        json_t *name = json_object_get(src, "name");
48
+        channel->name = strdup(json_string_value(name));
49
+        json_decref(name);
50
+        if (channel->type == GUILD_TEXT)
51
+        {
52
+            // Topic is nullable
53
+            json_t *topic = json_object_get(src, "topic");
54
+            if (json_is_string(topic)) {
55
+                channel->topic = strdup(json_string_value(topic));
56
+            }
57
+            json_decref(topic);
58
+
59
+            json_t *nsfw = json_object_get(src, "nsfw");
60
+            channel->nsfw = json_boolean_value(nsfw);
61
+            json_decref(nsfw);
62
+
63
+            json_t *last_message_id = json_object_get(src, "last_message_id");
64
+            if (last_message_id) {
65
+                if (json_is_string(last_message_id)) {
66
+                    channel->last_message_id = strdup(json_string_value(last_message_id));
67
+                }
68
+                json_decref(last_message_id);
69
+            }
70
+        }
71
+
72
+        json_t *parent_id = json_object_get(src, "parent_id");
73
+        if (json_is_string(parent_id))
74
+        {
75
+            channel->parent_id = strdup(json_string_value(parent_id));
76
+        }
77
+        json_decref(parent_id);
78
+
79
+        json_t *position = json_object_get(src, "position");
80
+        channel->position = (int)json_integer_value(position);
81
+        json_decref(position);
82
+    }
83
+    else if (channel->type == GUILD_VOICE)
84
+    {
85
+        json_t *bitrate = json_object_get(src, "bitrate");
86
+        channel->bitrate = (int)json_integer_value(bitrate);
87
+        json_decref(bitrate);
88
+
89
+        json_t *user_limit = json_object_get(src, "user_limit");
90
+        channel->user_limit = (int)json_integer_value(user_limit);
91
+        json_decref(user_limit);
92
+    }
93
+    else if (channel->type == DM || channel->type == GROUP_DM)
94
+    {
95
+
96
+        json_t *recipients = json_object_get(src, "recipients");
97
+        size_t rsize = json_array_size(recipients);
98
+
99
+        channel->recipients = calloc(rsize, sizeof(user_t));
100
+
101
+        size_t index;
102
+        json_t *value;
103
+
104
+        json_array_foreach(recipients, index, value)
105
+        {
106
+            user_t temp;
107
+            // TODO: Create function for converting json user objects to structs
108
+            temp.id = (char*)json_string_value(json_object_get(value, "id"));
109
+            temp.username = (char*)json_string_value(json_object_get(value, "username"));
110
+            temp.discriminator = (char*)json_string_value(json_object_get(value, "discriminator"));
111
+            json_t *avatar = json_object_get(value, "avatar");
112
+            if (avatar)
113
+            {
114
+                temp.avatar = (char*)json_string_value(avatar);
115
+                json_decref(avatar);
116
+            }
117
+
118
+            channel->recipients[index] = temp;
119
+        }
120
+
121
+        json_t *icon = json_object_get(src, "icon");
122
+        if (icon)
123
+        {
124
+            if (json_is_string(icon))
125
+            {
126
+                channel->icon = strdup(json_string_value(icon));
127
+            }
128
+            json_decref(icon);
129
+        }
130
+
131
+        json_t *owner_id = json_object_get(src, "owner_id");
132
+        channel->owner_id = strdup(json_string_value(owner_id));
133
+        json_decref(owner_id);
134
+
135
+        json_t *application_id = json_object_get(src, "application_id");
136
+        if (application_id)
137
+        {
138
+            channel->application_id = strdup(json_string_value(application_id));
139
+            json_decref(application_id);
140
+        }
141
+    }
142
+}

Loading…
Cancel
Save