0

I'm trying to build a Discord API with C (libdiscord it's constantly crashing).

I have found this promosing code (found here):

#include <stdio.h> /* printf, sprintf */
#include <stdlib.h> /* exit */
#include <unistd.h> /* read, write, close */
#include <string.h> /* memcpy, memset */
#include <sys/socket.h> /* socket, connect */
#include <netinet/in.h> /* struct sockaddr_in, struct sockaddr */
#include <netdb.h> /* struct hostent, gethostbyname */

void error(const char *msg) { perror(msg); exit(0); }

int main(int argc,char *argv[])
{
    /* first what are we going to send and where are we going to send it? */
    int portno =        80;
    char *host =        "api.somesite.com";
    char *message_fmt = "POST /apikey=%s&command=%s HTTP/1.0\r\n\r\n";

    struct hostent *server;
    struct sockaddr_in serv_addr;
    int sockfd, bytes, sent, received, total;
    char message[1024],response[4096];

    if (argc < 3) { puts("Parameters: <apikey> <command>"); exit(0); }

    /* fill in the parameters */
    sprintf(message,message_fmt,argv[1],argv[2]);
    printf("Request:\n%s\n",message);

    /* create the socket */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) error("ERROR opening socket");

    /* lookup the ip address */
    server = gethostbyname(host);
    if (server == NULL) error("ERROR, no such host");

    /* fill in the structure */
    memset(&serv_addr,0,sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(portno);
    memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);

    /* connect the socket */
    if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
        error("ERROR connecting");

    /* send the request */
    total = strlen(message);
    sent = 0;
    do {
        bytes = write(sockfd,message+sent,total-sent);
        if (bytes < 0)
            error("ERROR writing message to socket");
        if (bytes == 0)
            break;
        sent+=bytes;
    } while (sent < total);

    /* receive the response */
    memset(response,0,sizeof(response));
    total = sizeof(response)-1;
    received = 0;
    do {
        bytes = read(sockfd,response+received,total-received);
        if (bytes < 0)
            error("ERROR reading response from socket");
        if (bytes == 0)
            break;
        received+=bytes;
    } while (received < total);

    if (received == total)
        error("ERROR storing complete response from socket");

    /* close the socket */
    close(sockfd);

    /* process response */
    printf("Response:\n%s\n",response);

    return 0;
}

But I need to send a header and data, according to this post (in Python):

import requests
import json

channelID = "your_id_goes_here" # enable dev mode on discord, right-click on the channel, copy ID
botToken = "your_token_here"    # get from the bot page. must be a bot, not a discord app

baseURL = "https://discordapp.com/api/channels/{}/messages".format(channelID)
headers = { "Authorization":"Bot {}".format(botToken),
            "User-Agent":"myBotThing (http://some.url, v0.1)",
            "Content-Type":"application/json", }

message = "hello world"

POSTedJSON =  json.dumps ( {"content":message} )

r = requests.post(baseURL, headers = headers, data = POSTedJSON)

I'm sorry, I don't know the protocols in detail.

I'd like to read messages too, but for now I'm OK just writing they.

UPDATE:

My new code (error 400, bad request).

#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
    CURL *curl = NULL;
    CURLcode res;
    const char *data = "{\"content\": \"data to send\"}";
    const char *ID = "...";
    const char *token = "...";

    char tmp[1024];

    curl = curl_easy_init();

    if(curl != NULL) {
        struct curl_slist *headers = NULL;

        /* Remove a header curl would otherwise add by itself */
        headers = curl_slist_append(headers, "Accept:");

        /* Add a custom header */
        sprintf(tmp, "Host: https://discordapp.com/api/channels/%s/messages", ID);
        headers = curl_slist_append(headers, tmp);
        sprintf(tmp, "Authorization: Bot %s", token);
        headers = curl_slist_append(headers, tmp);
        headers = curl_slist_append(headers, "User-Agent: myBotThing (http://some.url, v0.1)");
        headers = curl_slist_append(headers, "Content-Type: application/json");

        /* set our custom set of headers */
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

        sprintf(tmp, "https://discordapp.com/api/channels/%s/messages", ID);
        curl_easy_setopt(curl, CURLOPT_URL, tmp);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

        // POST
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);

        res = curl_easy_perform(curl);

        /* Check for errors */
        if(res != CURLE_OK) printf("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));


        curl_easy_cleanup(curl);
        curl_slist_free_all(headers);
    }

    return 0;
}
  • You are trying something that is way above your current skill level. I suggest you first complete some C course before trying to write anything functional. Especially performing HTTP requests and parsing JSON responses are particularly masochistic to do in C. – Cheatah May 16 '20 at 21:32
  • @Cheatah I understand all the C code, and the Python one. The problem it's the HTTP protocol (what to send via socket). Can you help me with that? – Roger Miranda Perez May 16 '20 at 22:01
  • You literally copied and pasted code that you found somewhere. That tells me that you don't know how to write code. You already know that you're dealing with the HTTP protocol. So read some more about that protocol and it should be very easy to combine the information in the two pieces of code you found. Then your next problem is JSON. C and JSON are not friends. You had better start using libraries like cURL and jansson. – Cheatah May 16 '20 at 22:13
  • @Cheatah If something is already done, don't do it again. That's why I have copied it. I need an example of the protocol, so I can mix the codes. Without it I can't do anything. Plus, I think Discord uses HTTPs protocol (not HTTP). – Roger Miranda Perez May 16 '20 at 22:52
  • Then why are you interested in implementing the HTTP protocol if it's already done? Why did you think I referred to cURL? By the way, HTTPS is pretty much just HTTP over TLS. I wonder how you thought to overcome that with your TCP socket. Like, are you going to implement TLS yourself? – Cheatah May 16 '20 at 23:41
  • @Cheatah you're right, I didn't know about cURL. I have updated the post. – Roger Miranda Perez May 17 '20 at 00:29

0 Answers0