feat&fix: fix build and add initial authnetication

This commit is contained in:
2026-05-29 13:39:57 +02:00
parent 89787b36cc
commit c29b4bb008
12 changed files with 190 additions and 11 deletions
+2 -1
View File
@@ -1,3 +1,5 @@
.env
# ---> C
# Prerequisites
*.d
@@ -51,4 +53,3 @@ modules.order
Module.symvers
Mkfile.old
dkms.conf
+1 -1
View File
@@ -1,3 +1,3 @@
# discord.c
Discord API in C
A simple Discord API in C, inspired by discord.py.
+16 -1
View File
@@ -1,9 +1,24 @@
#ifndef DISCORD_DISCORD_H
#define DISCORD_DISCORD_H
#include "error.h"
// @TODO: use opaque pointer
#include <curl/curl.h>
#define DISCORD_BASE_URL "https://discord.com/api"
#define DISCORD_API_VERSION "10"
#define DISCORD_MAX_API_URL 256
#define DISCORD_MAX_TOKEN_VALUE 128
typedef struct discord_client discord_client;
typedef struct discord_client {
// char *token_type; // Bot or Bearer
char token_value[DISCORD_MAX_TOKEN_VALUE];
char api_url[DISCORD_MAX_API_URL];
CURL *curl;
} discord_client;
// remember to call curl_global_cleanup()
discord_error discord_init(discord_client *client, const char *token);
#endif
+2
View File
@@ -5,6 +5,8 @@ typedef enum discord_error {
DISCORD_OK,
DISCORD_ERR,
DISCORD_AUTH_ERR,
DISCORD_NULL_VALUE,
DISCORD_AUTH_FAILED,
} discord_error;
/**
+5
View File
@@ -0,0 +1,5 @@
headers += files(
'discord.h',
'error.h',
'request.h',
)
+8
View File
@@ -0,0 +1,8 @@
#ifndef DISCORD_REQUEST_H
#define DISCORD_REQUEST_H
#include <curl/curl.h>
int request_auth(CURL *curl, const char *token, const char *api_url);
#endif
+3 -2
View File
@@ -7,8 +7,9 @@ project(
sources = []
headers = []
include_directories('src')
include_directories('include')
subdir('src')
subdir('include')
incdir = include_directories('include')
libcurl = dependency('libcurl', required: true)
+48 -4
View File
@@ -1,6 +1,50 @@
#include "discord.h"
#include "error.h"
#include "request.h"
typedef struct discord_client {
char *token_type;
char *token_value;
} discord_client;
#include <curl/curl.h>
#include <curl/easy.h>
#include <stdio.h>
static int authenticate(discord_client *client) {
int ret;
ret = request_auth(client->curl, client->token_value, client->api_url);
if (ret != 0) {
return -1;
}
return 0;
}
discord_error discord_init(discord_client *client, const char *token) {
if (!client || !token) {
return DISCORD_NULL_VALUE;
}
int ret;
CURLcode result;
ret = snprintf(client->api_url, sizeof(client->api_url), "%s/v%s/users/@me", DISCORD_BASE_URL, DISCORD_API_VERSION);
if (ret > DISCORD_MAX_API_URL) {
return DISCORD_ERR;
}
ret = snprintf(client->token_value, sizeof(client->token_value), "%s", token);
if (ret > DISCORD_MAX_TOKEN_VALUE) {
return DISCORD_ERR;
}
result = curl_global_init(CURL_GLOBAL_ALL);
if (result != CURLE_OK) {
return DISCORD_ERR;
}
client->curl = curl_easy_init();
ret = authenticate(client);
if (ret != 0) {
return DISCORD_AUTH_ERR;
}
return DISCORD_OK;
}
+2
View File
@@ -13,6 +13,8 @@ static discord_err errors[] = {
{DISCORD_OK, "OK"},
{DISCORD_ERR, "ERR"},
{DISCORD_AUTH_ERR, "Authentication error, maybe wrong token"},
{DISCORD_NULL_VALUE, "NULL value passed"},
{DISCORD_AUTH_FAILED, "Authentication failed"},
};
const char *discord_err_str(discord_error err) {
+5 -1
View File
@@ -1 +1,5 @@
sources += files('main.c')
sources += files(
'discord.c',
'error.c',
'request.c',
)
+85
View File
@@ -0,0 +1,85 @@
#include "request.h"
#include <curl/curl.h>
#include <curl/easy.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <yyjson.h>
#define MAX_AUTH_LEN 256
struct response_buffer {
char *data;
size_t size;
};
static size_t write_cb(char *contents, size_t size, size_t nmemb, void *userp) {
size_t realsize = size * nmemb;
struct response_buffer *mem = (struct response_buffer *)userp;
char *ptr = realloc(mem->data, mem->size + realsize + 1);
if (!ptr) {
printf("not enough memory (realloc returned NULL)\n");
return 0;
}
mem->data = ptr;
memcpy(&(mem->data[mem->size]), contents, realsize);
mem->size += realsize;
mem->data[mem->size] = 0;
return realsize;
}
int request_auth(CURL *curl, const char *token, const char *api_url) {
if (!curl || !token) {
return -1;
}
CURLcode result;
struct response_buffer buffer;
memset(&buffer, 0, sizeof(buffer));
char auth[MAX_AUTH_LEN];
snprintf(auth, sizeof(auth), "Authorization: Bot %s", token);
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, auth);
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, api_url);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&buffer);
// @TODO: change url and version
curl_easy_setopt(curl, CURLOPT_USERAGENT, "DiscordBot (https://discord.com, 0.1)");
result = curl_easy_perform(curl);
if (result != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(result));
curl_slist_free_all(headers);
free(buffer.data);
return -1;
}
// Print response
fprintf(stdout, "[RESPONSE SIZE]: %ld\n", buffer.size);
fprintf(stdout, "[RESPONSE DATA]:\n%s\n", buffer.data);
// Parse json
yyjson_doc *doc = yyjson_read(buffer.data, buffer.size, 0);
yyjson_val *root = yyjson_doc_get_root(doc);
yyjson_val *username = yyjson_obj_get(root, "username");
fprintf(stdout, "[USERNAME]: %s\n", yyjson_get_str(username));
// Clear resources
yyjson_doc_free(doc);
free(buffer.data);
curl_slist_free_all(headers);
return 0;
}
+13 -1
View File
@@ -1,7 +1,19 @@
#include "discord.h"
#include "error.h"
#include <stdio.h>
int main(void) {
puts("discord.c");
puts("discord.c example");
const char token[] = "";
discord_client client;
discord_error err = discord_init(&client, token);
if (err != DISCORD_OK) {
fprintf(stderr, "discord_init(): %s\n", discord_err_str(err));
return -1;
}
return 0;
}