diff options
author | Ratakor <ratakor@disroot.org> | 2023-11-15 00:28:01 +0100 |
---|---|---|
committer | Ratakor <ratakor@disroot.org> | 2023-11-15 00:28:01 +0100 |
commit | 7af91dde680613b2627de535539a83efd81aa908 (patch) | |
tree | e69a9b71451bced43b85356fa07f0d52393df22c | |
parent | fd6978d98b672ff23901e295a7e4a22b422e3759 (diff) |
Rework quotes in zig
-rw-r--r-- | src/Makefile | 12 | ||||
-rw-r--r-- | src/nolan.h | 5 | ||||
-rw-r--r-- | src/ocr.c | 40 | ||||
-rw-r--r-- | src/quote.zig | 103 | ||||
-rw-r--r-- | src/run.c | 2 | ||||
-rw-r--r-- | src/stats.c | 71 |
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); @@ -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; + }; +} @@ -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) { |