const std = @import("std"); const os = std.os; const c = @cImport({ @cInclude("stdio.h"); @cInclude("stdlib.h"); @cInclude("sys/stat.h"); @cInclude("string.h"); @cInclude("time.h"); }); const warn = std.debug.warn; const allocator = std.heap.c_allocator; fn sliceify(ptr: [*]u8) []u8 { return ptr[0..c.strlen(ptr)]; } fn sliceifyKnown(slice: []u8) []u8 { return slice[0..c.strlen(slice.ptr)]; } export fn journal_open(topic_cptr: ?[*]u8) os.fd_t { const topic = sliceify(topic_cptr.?); const journal_dir = std.fs.path.resolve(allocator, [_][]const u8{ std.os.getenvC(c"HOME").?, ".lunabot", }) catch |err| { warn("failed to resolve paths: {}\n", err); return -1; }; warn("journal_dir = {}\n", journal_dir); std.fs.makeDir(journal_dir) catch |err| { if (err != error.PathAlreadyExists) { warn("failed to create journal dir {}: {}\n", journal_dir, err); return -1; } }; const journal_path = std.fmt.allocPrint(allocator, "{}/{}", journal_dir, topic) catch |err| { warn("failed to allocprint journal path: {}\n", err); return -1; }; defer allocator.free(journal_path); warn("journal_path = {}\n", journal_path); const fd = std.os.open( journal_path, std.os.O_WRONLY | std.os.O_CREAT | std.os.O_APPEND, 0o755, ) catch |err| { warn("failed to open {}: {}\n", journal_path, err); return -1; }; return fd; } export fn journal_write(journal: os.fd_t, message_cptr: ?[*]u8) void { std.os.write( journal, sliceify(message_cptr.?), ) catch |err| { std.debug.warn("Error while writing to file: {}\n", err); return; }; } export fn journal_close(journal: os.fd_t) void { std.os.close(journal); } export fn journal_write_topic( journal: os.fd_t, topic_cptr: ?[*]u8, message_cptr: ?[*]u8, ) void { warn("zig uwu\n"); var topic = sliceify(topic_cptr.?); var message = sliceify(message_cptr.?); var tstamp_total = allocator.alloc(u8, 128) catch |err| { warn("failed to allocate string for timestamp\n"); return; }; defer allocator.free(tstamp_total); var rawtime: c.time_t = undefined; _ = c.time(&rawtime); var cur_time: [*c]const c.struct_tm = c.gmtime(&rawtime); _ = c.strftime(tstamp_total.ptr, usize(128), c"%c", cur_time); var tstamp = sliceifyKnown(tstamp_total); std.debug.warn("tstamp: {}\ntopic: {}\nmsg: {}\n", tstamp, topic, message); var fmt_msg = std.fmt.allocPrint( allocator, "[{}] [{}]: {}\n", tstamp, topic, message, ) catch |err| { warn("Failed to make formatted message: {}\n", err); return; }; // catch unreachable is intended. var fmt_msg_cstr = std.cstr.addNullByte( allocator, fmt_msg, ) catch unreachable; journal_write(journal, fmt_msg_cstr.ptr); }