This commit is contained in:
Yuzu 2024-11-06 13:25:33 +00:00
parent f8b2052d26
commit 31944901d9
5 changed files with 42 additions and 26 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
lib/zlib lib/zlib
zig-out
.zig-cache .zig-cache
.env .env

View File

@ -106,7 +106,7 @@ Contributions are welcome! Please open an issue or pull request if you'd like to
| message_create: ?*const fn (message: Discord.Message) void | ✅ | | message_create: ?*const fn (message: Discord.Message) void | ✅ |
| message_update: ?*const fn (message: Discord.Message) void | ✅ | | message_update: ?*const fn (message: Discord.Message) void | ✅ |
| message_delete: ?*const fn (message: Discord.MessageDelete) void | ✅ | | message_delete: ?*const fn (message: Discord.MessageDelete) void | ✅ |
| message_delete_bulk: ?*const fn (message: Discord.MessageDelete) void | ✅ | | message_delete_bulk: ?*const fn (message: Discord.MessageDeleteBulk) void | ✅ |
| message_reaction_add | ❌ | | message_reaction_add | ❌ |
| message_reaction_remove | ❌ | | message_reaction_remove | ❌ |
| message_reaction_remove_all | ❌ | | message_reaction_remove_all | ❌ |
@ -128,5 +128,5 @@ Contributions are welcome! Please open an issue or pull request if you'd like to
| message_poll_vote_remove | ❌ | | message_poll_vote_remove | ❌ |
| ready: ?*const fn (data: Discord.Ready) void | ✅ | | ready: ?*const fn (data: Discord.Ready) void | ✅ |
| resumed | ❌ | | resumed | ❌ |
| any: ?*const fn (data: []u8) void | ✅ | | any: ?*const fn (data: []const u8) void | ✅ |

View File

@ -60,6 +60,8 @@ pub fn build(b: *std.Build) void {
marin.root_module.addImport("zmpl", zmpl.module("zmpl")); marin.root_module.addImport("zmpl", zmpl.module("zmpl"));
marin.root_module.addImport("deque", deque.module("zig-deque")); marin.root_module.addImport("deque", deque.module("zig-deque"));
b.installArtifact(marin);
// test // test
const run_cmd = b.addRunArtifact(marin); const run_cmd = b.addRunArtifact(marin);
run_cmd.step.dependOn(b.getInstallStep()); run_cmd.step.dependOn(b.getInstallStep());

View File

@ -1,8 +1,9 @@
const zmpl = @import("zmpl"); const zmpl = @import("zmpl");
const Discord = @import("types.zig"); const Discord = @import("types.zig");
const std = @import("std"); const std = @import("std");
const mem = std.mem;
pub fn parseUser(obj: *zmpl.Data.Object) Discord.User { pub fn parseUser(_: mem.Allocator, obj: *zmpl.Data.Object) !Discord.User {
const avatar_decoration_data_obj = obj.getT(.object, "avatar_decoration_data"); const avatar_decoration_data_obj = obj.getT(.object, "avatar_decoration_data");
const user = Discord.User{ const user = Discord.User{
.clan = null, .clan = null,
@ -33,7 +34,7 @@ pub fn parseUser(obj: *zmpl.Data.Object) Discord.User {
return user; return user;
} }
pub fn parseMember(obj: *zmpl.Data.Object) Discord.Member { pub fn parseMember(_: mem.Allocator, obj: *zmpl.Data.Object) !Discord.Member {
const avatar_decoration_data_member_obj = obj.getT(.object, "avatar_decoration_data"); const avatar_decoration_data_member_obj = obj.getT(.object, "avatar_decoration_data");
const member = Discord.Member{ const member = Discord.Member{
.deaf = obj.getT(.boolean, "deaf"), .deaf = obj.getT(.boolean, "deaf"),
@ -56,27 +57,35 @@ pub fn parseMember(obj: *zmpl.Data.Object) Discord.Member {
return member; return member;
} }
pub fn parseMessage(obj: *zmpl.Data.Object) Discord.Message { /// caller must free the received referenced_message if any
var buf: [1000]u8 = undefined; pub fn parseMessage(allocator: mem.Allocator, obj: *zmpl.Data.Object) !Discord.Message {
var fba = std.heap.FixedBufferAllocator.init(&buf);
// parse mentions // parse mentions
const mentions_obj = obj.getT(.array, "mentions").?; const mentions_obj = obj.getT(.array, "mentions").?;
var mentions = std.ArrayList(Discord.User).init(fba.allocator()); var mentions = std.ArrayList(Discord.User).init(allocator);
defer mentions.deinit(); defer mentions.deinit();
while (mentions_obj.iterator().next()) |m| { while (mentions_obj.iterator().next()) |m| {
mentions.append(parseUser(&m.object)) catch unreachable; try mentions.append(try parseUser(allocator, &m.object));
} }
// parse member // parse member
const member = parseMember(obj.getT(.object, "member").?); const member = try parseMember(allocator, obj.getT(.object, "member").?);
// parse message // parse message
const author = parseUser(obj.getT(.object, "author").?); const author = try parseUser(allocator, obj.getT(.object, "author").?);
//_ = if (obj.getT(.object, "referenced_message")) |m| parseMessage(m) else null; // the referenced_message if any
const refmp = try allocator.create(Discord.Message);
var invalid_ptr = false;
if (obj.getT(.object, "referenced_message")) |m| {
refmp.* = try parseMessage(allocator, m);
} else {
allocator.destroy(refmp);
invalid_ptr = true;
}
// parse message // parse message
const message = Discord.Message{ const message = Discord.Message{
@ -94,7 +103,7 @@ pub fn parseMessage(obj: *zmpl.Data.Object) Discord.Message {
.guild_id = obj.getT(.string, "guild_id"), .guild_id = obj.getT(.string, "guild_id"),
.attachments = &[0]Discord.Attachment{}, .attachments = &[0]Discord.Attachment{},
.edited_timestamp = null, .edited_timestamp = null,
.mentions = mentions.items, .mentions = try mentions.toOwnedSlice(),
.mention_roles = &[0]?[]const u8{}, .mention_roles = &[0]?[]const u8{},
.mention_channels = &[0]?Discord.ChannelMention{}, .mention_channels = &[0]?Discord.ChannelMention{},
.embeds = &[0]Discord.Embed{}, .embeds = &[0]Discord.Embed{},
@ -116,7 +125,7 @@ pub fn parseMessage(obj: *zmpl.Data.Object) Discord.Message {
.position = if (obj.getT(.integer, "position")) |p| @as(isize, @intCast(p)) else null, .position = if (obj.getT(.integer, "position")) |p| @as(isize, @intCast(p)) else null,
.poll = null, .poll = null,
.call = null, .call = null,
.referenced_message = null, .referenced_message = if (invalid_ptr) null else refmp,
}; };
return message; return message;
} }

View File

@ -104,7 +104,7 @@ pub const GatewayDispatchEvent = struct {
ready: ?*const fn (data: Discord.Ready) void = undefined, ready: ?*const fn (data: Discord.Ready) void = undefined,
// TODO: implement // resumed: null = null, // TODO: implement // resumed: null = null,
any: ?*const fn (data: []u8) void = undefined, any: ?*const fn (data: []const u8) void = undefined,
}; };
const FetchReq = struct { const FetchReq = struct {
@ -498,7 +498,7 @@ pub fn handleEvent(self: *Self, name: []const u8, payload: []const u8) !void {
self.logif("new gateway url: {s}", .{self.gatewayUrl()}); self.logif("new gateway url: {s}", .{self.gatewayUrl()});
const application = obj.getT(.object, "application").?; const application = obj.getT(.object, "application").?;
const user = Parser.parseUser(obj.getT(.object, "user").?); const user = try Parser.parseUser(self.allocator, obj.getT(.object, "user").?);
var ready = Discord.Ready{ var ready = Discord.Ready{
.v = @as(isize, @intCast(obj.getT(.integer, "v").?)), .v = @as(isize, @intCast(obj.getT(.integer, "v").?)),
@ -535,7 +535,7 @@ pub fn handleEvent(self: *Self, name: []const u8, payload: []const u8) !void {
.bot = null, .bot = null,
.redirect_uris = null, .redirect_uris = null,
.interactions_endpoint_url = null, .interactions_endpoint_url = null,
.flags = .{ .Embedded = true }, //@as(Discord.ApplicationFlags, @bitCast(@as(u25, @intCast(application.getT(.integer, "flags").?)))), .flags = @as(Discord.ApplicationFlags, @bitCast(@as(u25, @intCast(application.getT(.integer, "flags").?)))),
.id = application.getT(.string, "id").?, .id = application.getT(.string, "id").?,
}, },
}; };
@ -548,7 +548,7 @@ pub fn handleEvent(self: *Self, name: []const u8, payload: []const u8) !void {
else => unreachable, else => unreachable,
}; };
} }
if (self.handler.ready) |event| @call(.auto, event, .{ready}); if (self.handler.ready) |event| event(ready);
} }
if (std.ascii.eqlIgnoreCase(name, "message_delete")) { if (std.ascii.eqlIgnoreCase(name, "message_delete")) {
@ -560,7 +560,7 @@ pub fn handleEvent(self: *Self, name: []const u8, payload: []const u8) !void {
.guild_id = obj.getT(.string, "guild_id"), .guild_id = obj.getT(.string, "guild_id"),
}; };
if (self.handler.message_delete) |event| @call(.auto, event, .{data}); if (self.handler.message_delete) |event| event(data);
} }
if (std.ascii.eqlIgnoreCase(name, "message_delete_bulk")) { if (std.ascii.eqlIgnoreCase(name, "message_delete_bulk")) {
@ -578,26 +578,30 @@ pub fn handleEvent(self: *Self, name: []const u8, payload: []const u8) !void {
.guild_id = obj.getT(.string, "guild_id"), .guild_id = obj.getT(.string, "guild_id"),
}; };
if (self.handler.message_delete_bulk) |event| @call(.auto, event, .{data}); if (self.handler.message_delete_bulk) |event| event(data);
} }
if (std.ascii.eqlIgnoreCase(name, "message_update")) { if (std.ascii.eqlIgnoreCase(name, "message_update")) {
const attempt = try self.parseJson(payload); const attempt = try self.parseJson(payload);
const obj = attempt.getT(.object, "d").?; const obj = attempt.getT(.object, "d").?;
const message = Parser.parseMessage(obj); const message = try Parser.parseMessage(self.allocator, obj);
defer if (message.referenced_message) |mptr| self.allocator.destroy(mptr);
if (self.handler.message_update) |event| @call(.auto, event, .{message}); if (self.handler.message_update) |event| event(message);
} }
if (std.ascii.eqlIgnoreCase(name, "message_create")) { if (std.ascii.eqlIgnoreCase(name, "message_create")) {
const attempt = try self.parseJson(payload); const attempt = try self.parseJson(payload);
const obj = attempt.getT(.object, "d").?; const obj = attempt.getT(.object, "d").?;
const message = Parser.parseMessage(obj); const message = try Parser.parseMessage(self.allocator, obj);
defer if (message.referenced_message) |mptr| self.allocator.destroy(mptr);
if (self.handler.message_create) |event| @call(.auto, event, .{message}); if (self.handler.message_create) |event| event(message);
} else {} } else {
if (self.handler.any) |anyEvent| anyEvent(payload);
}
} }
inline fn logif(self: *Self, comptime format: []const u8, args: anytype) void { inline fn logif(self: *Self, comptime format: []const u8, args: anytype) void {