aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRatakor <ratakor@disroot.org>2023-11-15 00:28:01 +0100
committerRatakor <ratakor@disroot.org>2023-11-15 00:28:01 +0100
commit7af91dde680613b2627de535539a83efd81aa908 (patch)
treee69a9b71451bced43b85356fa07f0d52393df22c
parentfd6978d98b672ff23901e295a7e4a22b422e3759 (diff)
Rework quotes in zig
-rw-r--r--src/Makefile12
-rw-r--r--src/nolan.h5
-rw-r--r--src/ocr.c40
-rw-r--r--src/quote.zig103
-rw-r--r--src/run.c2
-rw-r--r--src/stats.c71
6 files changed, 117 insertions, 116 deletions
diff --git a/src/Makefile b/src/Makefile
index 56eb03e..ea8a0b0 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -2,6 +2,7 @@
BIN = ../nolan
CONFIG_H = ../config.h
+CC = zig cc
OBJS = cmd_correct.o \
cmd_help.o \
@@ -21,6 +22,8 @@ OBJS = cmd_correct.o \
stats.o \
util.o
+ZIG_OBJS = quote.o
+
DISCORDLIBS = -ldiscord -lcurl -lpthread
TESSLIBS = -ltesseract -lleptonica
GDLIBS = -lgd -lpng -lz -ljpeg -lfreetype -lm
@@ -38,13 +41,16 @@ echo:
@echo "LDFLAGS = ${LDFLAGS}"
@echo "OBJS = ${OBJS}"
-${BIN}: ${CONFIG_H} ${OBJS}
- ${CC} ${OBJS} ${LDFLAGS} -o $@
+${BIN}: ${CONFIG_H} ${OBJS} ${ZIG_OBJS}
+ ${CC} ${OBJS} ${ZIG_OBJS} ${LDFLAGS} -o $@
+
+${ZIG_OBJS}:
+ zig build-obj -OReleaseFast -lc -lcurl ${@:.o=.zig}
${CONFIG_H}:
@cp ../config.def.h $@
clean:
- rm -f ${OBJS} ${BIN}
+ rm -f ${OBJS} ${ZIG_OBJS} ${BIN}
.PHONY: all echo clean
diff --git a/src/nolan.h b/src/nolan.h
index e90b591..61ec86f 100644
--- a/src/nolan.h
+++ b/src/nolan.h
@@ -143,12 +143,15 @@ void on_interaction(struct discord *client,
const struct discord_interaction *ev);
void on_message(struct discord *client, const struct discord_message *ev);
+
/* ocr.c */
-char *curl(char *url);
CURLcode curl_file(char *url, char *fname);
int crop(char *fname, int type);
char *ocr(const char *fname, const char *lang);
+/* quote.zig */
+size_t write_quote(char *buffer, size_t size);
+
/* stats.c */
void create_slash_stats(struct discord *client);
uint32_t trim_stat(const char *str);
diff --git a/src/ocr.c b/src/ocr.c
index e3f38f0..2d8feaa 100644
--- a/src/ocr.c
+++ b/src/ocr.c
@@ -15,48 +15,8 @@
/* #define WHITE 12000000 */
#define WHITE 10000000
-struct Slice {
- char *data;
- size_t siz;
-};
-
-static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream);
static int write_rect(gdRect *rect, gdImagePtr im);
-size_t
-write_data(void *ptr, size_t siz, size_t nmemb, void *stream)
-{
- struct Slice *buf;
-
- if (siz && nmemb > (size_t) -1 / siz)
- die(1, "realloc: %s", strerror(ENOMEM));
-
- siz *= nmemb;
- buf = (struct Slice *)stream;
- buf->data = xrealloc(buf->data, buf->siz + siz + 1);
- memcpy(buf->data + buf->siz, ptr, siz);
- buf->siz += siz;
- buf->data[buf->siz] = '\0';
-
- return buf->siz;
-}
-
-char *
-curl(char *url)
-{
- CURL *handle;
- struct Slice buf = { .data = NULL, .siz = 0 };
-
- handle = curl_easy_init();
- curl_easy_setopt(handle, CURLOPT_URL, url);
- curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data);
- curl_easy_setopt(handle, CURLOPT_WRITEDATA, &buf);
- curl_easy_perform(handle);
- curl_easy_cleanup(handle);
-
- return buf.data;
-}
-
CURLcode
curl_file(char *url, char *fname)
{
diff --git a/src/quote.zig b/src/quote.zig
new file mode 100644
index 0000000..42c2e49
--- /dev/null
+++ b/src/quote.zig
@@ -0,0 +1,103 @@
+const std = @import("std");
+const cURL = @cImport({
+ @cInclude("curl/curl.h");
+});
+
+const KaamelottResponse = struct {
+ status: u32,
+ citation: struct {
+ citation: []const u8,
+ infos: struct {
+ auteur: []const u8,
+ acteur: []const u8,
+ personnage: []const u8,
+ saison: []const u8,
+ episode: []const u8,
+ },
+ },
+
+ const api_url = "https://kaamelott.chaudie.re/api/random";
+};
+
+const Oss117Response = struct {
+ sentence: []const u8,
+ character: struct {
+ name: []const u8,
+ slug: []const u8,
+ },
+
+ const api_url = "https://api.oss117quotes.xyz/v1/random";
+};
+
+const ChuckNorrisResponse = struct {
+ categories: [][]const u8,
+ created_at: []const u8,
+ icon_url: []const u8,
+ id: []const u8,
+ updated_at: []const u8,
+ url: []const u8,
+ value: []const u8,
+
+ const api_url = "https://api.chucknorris.io/jokes/random";
+};
+
+fn writeToArrayListCallback(data: *anyopaque, size: c_uint, nmemb: c_uint, user_data: *anyopaque) callconv(.C) c_uint {
+ var buffer: *std.ArrayList(u8) = @alignCast(@ptrCast(user_data));
+ var typed_data: [*]u8 = @ptrCast(data);
+ buffer.appendSlice(typed_data[0 .. nmemb * size]) catch return 0;
+ return nmemb * size;
+}
+
+fn writeQuote(comptime Response: type, buf: []u8) !usize {
+ var arena = std.heap.ArenaAllocator.init(std.heap.c_allocator);
+ defer arena.deinit();
+ const allocator = arena.allocator();
+
+ const handle = cURL.curl_easy_init() orelse return error.CURLHandleInitFailed;
+ defer cURL.curl_easy_cleanup(handle);
+
+ var buffer = std.ArrayList(u8).init(allocator);
+ // defer buffer.deinit();
+
+ if (cURL.curl_easy_setopt(handle, cURL.CURLOPT_URL, Response.api_url) != cURL.CURLE_OK)
+ return error.CouldNotSetURL;
+ if (cURL.curl_easy_setopt(handle, cURL.CURLOPT_WRITEFUNCTION, writeToArrayListCallback) != cURL.CURLE_OK)
+ return error.CouldNotSetWriteCallback;
+ if (cURL.curl_easy_setopt(handle, cURL.CURLOPT_WRITEDATA, &buffer) != cURL.CURLE_OK)
+ return error.CouldNotSetWriteCallback;
+
+ if (cURL.curl_easy_perform(handle) != cURL.CURLE_OK)
+ return error.FailedToPerformRequest;
+
+ const response = try std.json.parseFromSliceLeaky(Response, allocator, buffer.items, .{});
+
+ return (switch (Response) {
+ KaamelottResponse => try std.fmt.bufPrintZ(buf, "{s}\n> {s} (Kaamelott)\n\n", .{
+ response.citation.citation,
+ response.citation.infos.personnage,
+ }),
+ Oss117Response => try std.fmt.bufPrintZ(buf, "{s}\n> {s} (OSS 117)\n\n", .{
+ response.sentence,
+ response.character.name,
+ }),
+ ChuckNorrisResponse => try std.fmt.bufPrintZ(buf, "{s} (Chuck Norris)\n\n", .{response.value}),
+ else => unreachable,
+ }).len;
+}
+
+var count = std.atomic.Atomic(usize).init(0);
+
+export fn write_quote(buffer: [*]u8, size: usize) usize {
+ return switch (count.fetchAdd(1, .AcqRel)) {
+ 0 => writeQuote(KaamelottResponse, buffer[0..size]),
+ 1 => writeQuote(Oss117Response, buffer[0..size]),
+ else => blk: {
+ count.store(0, .Release);
+ break :blk writeQuote(ChuckNorrisResponse, buffer[0..size]);
+ },
+ } catch |err| blk: {
+ std.log.warn("write_quote: {}", .{err});
+ buffer[0] = 0;
+ break :blk 0;
+ };
+}
diff --git a/src/run.c b/src/run.c
index 069d562..6f4ce07 100644
--- a/src/run.c
+++ b/src/run.c
@@ -55,7 +55,7 @@ on_message(struct discord *client, const struct discord_message *ev)
#ifdef DEVEL
if (ev->channel_id == DEVEL)
- on_raids(client, ev);
+ on_stats(client, ev);
return;
#endif /* DEVEL */
diff --git a/src/stats.c b/src/stats.c
index 584d68a..d18542c 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -7,8 +7,6 @@
#include "nolan.h"
-#define URL "https://api.oss117quotes.xyz/v1/random"
-
struct Field {
const char *const key;
const unsigned int val;
@@ -20,8 +18,6 @@ enum { ENGLISH, FRENCH };
static uint32_t playtime_to_u32(char *playtime, int lang);
static void parse_line(Player *player, char *line);
static void for_line(Player *player, char *txt);
-static char *get_quote(void);
-static size_t write_quote(char *buf, size_t siz);
static void update_player(char *buf, size_t siz, Player *player,
Player *new_player);
static Player *update_players(char *buf, size_t siz, Player *new_player);
@@ -255,73 +251,6 @@ for_line(Player *player, char *txt)
}
}
-char *
-get_quote(void)
-{
- char *quote, *p, *sentence, *name, *tmp, *op, *otmp;
-
- quote = curl(URL);
- if ((sentence = nstrchr(quote, '"', 3)) == NULL) {
- free(quote);
- return NULL;
- }
- sentence++;
- if ((name = nstrchr(quote, '"', 8)) == NULL) {
- free(quote);
- return NULL;
- }
- *name++ = '\n';
- *name++ = '>';
- *name = ' ';
- name -= 2;
-
- if ((p = strchr(sentence, '"')) == NULL) {
- free(quote);
- return NULL;
- }
- *p = '\0';
- if ((p = strchr(name, '"')) == NULL) {
- free(quote);
- return NULL;
- }
- *p = '\0';
-
- p = quote;
- while ((*p++ = *sentence++));
- p--;
- while ((*p++ = *name++));
-
- /* change '*' to "\*", must need a large enough buffer */
- p = quote;
- while ((p = strchr(p, '*')) != NULL) {
- tmp = xstrdup(p);
- op = p;
- otmp = tmp;
- *p++ = '\\';
- while ((*p++ = *tmp++));
- p = op + 2;
- free(otmp);
- }
-
- return quote;
-}
-
-size_t
-write_quote(char *buf, size_t siz)
-{
- char *quote;
- size_t ret;
-
- quote = get_quote();
- if (quote == NULL)
- return 0;
-
- ret = snprintf(buf, siz, "%s\n\n", quote);
- free(quote);
-
- return ret;
-}
-
void
update_player(char *buf, size_t siz, Player *player, Player *new_player)
{