137 lines
5.9 KiB
Zig
137 lines
5.9 KiB
Zig
const zmpl = @import("zmpl");
|
|
const Discord = @import("types.zig");
|
|
const std = @import("std");
|
|
const mem = std.mem;
|
|
const Snowflake = @import("shared.zig").Snowflake;
|
|
|
|
pub fn parseUser(_: mem.Allocator, obj: *zmpl.Data.Object) !Discord.User {
|
|
const avatar_decoration_data_obj = obj.getT(.object, "avatar_decoration_data");
|
|
const user = Discord.User{
|
|
.clan = null,
|
|
.id = try Snowflake.fromRaw(obj.getT(.string, "id").?),
|
|
.bot = obj.getT(.boolean, "bot") orelse false,
|
|
.username = obj.getT(.string, "username").?,
|
|
.accent_color = if (obj.getT(.integer, "accent_color")) |ac| @as(isize, @intCast(ac)) else null,
|
|
// note: for selfbots this can be typed with an enu.?,
|
|
.flags = if (obj.getT(.integer, "flags")) |fs| @as(isize, @intCast(fs)) else null,
|
|
// also for selfbot.?,
|
|
.email = obj.getT(.string, "email"),
|
|
.avatar = obj.getT(.string, "avatar"),
|
|
.locale = obj.getT(.string, "locale"),
|
|
.system = obj.getT(.boolean, "system"),
|
|
.banner = obj.getT(.string, "banner"),
|
|
.verified = obj.getT(.boolean, "verified"),
|
|
.global_name = obj.getT(.string, "global_name"),
|
|
.mfa_enabled = obj.getT(.boolean, "mfa_enabled"),
|
|
.public_flags = if (obj.getT(.integer, "public_flags")) |pfs| @as(isize, @intCast(pfs)) else null,
|
|
.premium_type = if (obj.getT(.integer, "premium_type")) |pfs| @as(Discord.PremiumTypes, @enumFromInt(pfs)) else null,
|
|
.discriminator = obj.getT(.string, "discriminator").?,
|
|
.avatar_decoration_data = if (avatar_decoration_data_obj) |add| Discord.AvatarDecorationData{
|
|
.asset = add.getT(.string, "asset").?,
|
|
.sku_id = try Snowflake.fromRaw(add.getT(.string, "sku_id").?),
|
|
} else null,
|
|
};
|
|
|
|
return user;
|
|
}
|
|
|
|
pub fn parseMember(_: mem.Allocator, obj: *zmpl.Data.Object) !Discord.Member {
|
|
const avatar_decoration_data_member_obj = obj.getT(.object, "avatar_decoration_data");
|
|
const member = Discord.Member{
|
|
.deaf = obj.getT(.boolean, "deaf"),
|
|
.mute = obj.getT(.boolean, "mute"),
|
|
.pending = obj.getT(.boolean, "pending"),
|
|
.user = null,
|
|
.nick = obj.getT(.string, "nick"),
|
|
.avatar = obj.getT(.string, "avatar"),
|
|
.roles = &[0][]const u8{},
|
|
.joined_at = obj.getT(.string, "joined_at").?,
|
|
.premium_since = obj.getT(.string, "premium_since"),
|
|
.permissions = obj.getT(.string, "permissions"),
|
|
.communication_disabled_until = obj.getT(.string, "communication_disabled_until"),
|
|
.flags = @as(isize, @intCast(obj.getT(.integer, "flags").?)),
|
|
.avatar_decoration_data = if (avatar_decoration_data_member_obj) |addm| Discord.AvatarDecorationData{
|
|
.asset = addm.getT(.string, "asset").?,
|
|
.sku_id = try Snowflake.fromRaw(addm.getT(.string, "sku_id").?),
|
|
} else null,
|
|
};
|
|
return member;
|
|
}
|
|
|
|
/// caller must free the received referenced_message if any
|
|
pub fn parseMessage(allocator: mem.Allocator, obj: *zmpl.Data.Object) !Discord.Message {
|
|
// parse mentions
|
|
const mentions_obj = obj.getT(.array, "mentions").?;
|
|
|
|
var mentions = std.ArrayList(Discord.User).init(allocator);
|
|
defer mentions.deinit();
|
|
|
|
while (mentions_obj.iterator().next()) |m| {
|
|
try mentions.append(try parseUser(allocator, &m.object));
|
|
}
|
|
|
|
std.debug.print("parsing mentions done\n", .{});
|
|
|
|
// parse member
|
|
const member = if (obj.getT(.object, "member")) |m| try parseMember(allocator, m) else null;
|
|
|
|
// parse message
|
|
const author = try parseUser(allocator, obj.getT(.object, "author").?);
|
|
|
|
// the referenced_message if any
|
|
const refmp = try allocator.create(Discord.Message);
|
|
|
|
if (obj.getT(.object, "referenced_message")) |m| {
|
|
refmp.* = try parseMessage(allocator, m);
|
|
} else {
|
|
allocator.destroy(refmp);
|
|
}
|
|
|
|
// parse message
|
|
const message = Discord.Message{
|
|
// the id
|
|
.id = try Snowflake.fromRaw(obj.getT(.string, "id").?),
|
|
.tts = obj.getT(.boolean, "tts").?,
|
|
.mention_everyone = obj.getT(.boolean, "mention_everyone").?,
|
|
.pinned = obj.getT(.boolean, "pinned").?,
|
|
.type = @as(Discord.MessageTypes, @enumFromInt(obj.getT(.integer, "type").?)),
|
|
.channel_id = try Snowflake.fromRaw(obj.getT(.string, "channel_id").?),
|
|
.author = author,
|
|
.member = member,
|
|
.content = obj.getT(.string, "content"),
|
|
.timestamp = obj.getT(.string, "timestamp").?,
|
|
.guild_id = try Snowflake.fromMaybe(obj.getT(.string, "guild_id")),
|
|
.attachments = &[0]Discord.Attachment{},
|
|
.edited_timestamp = null,
|
|
.mentions = try mentions.toOwnedSlice(),
|
|
.mention_roles = &[0]?[]const u8{},
|
|
.mention_channels = &[0]?Discord.ChannelMention{},
|
|
.embeds = &[0]Discord.Embed{},
|
|
.reactions = &[0]?Discord.Reaction{},
|
|
.nonce = if (obj.get("nonce")) |nonce| switch (nonce.*) {
|
|
.integer => |n| .{ .int = @as(isize, @intCast(n.value)) },
|
|
.string => |n| .{ .string = n.value },
|
|
.Null => null,
|
|
else => unreachable,
|
|
} else null,
|
|
.webhook_id = try Snowflake.fromMaybe(obj.getT(.string, "webhook_id")),
|
|
.activity = null,
|
|
.application = null,
|
|
.application_id = try Snowflake.fromMaybe(obj.getT(.string, "application_id")),
|
|
.message_reference = null,
|
|
.flags = if (obj.getT(.integer, "flags")) |fs| @as(Discord.MessageFlags, @bitCast(@as(u15, @intCast(fs)))) else null,
|
|
.stickers = &[0]?Discord.Sticker{},
|
|
.message_snapshots = &[0]?Discord.MessageSnapshot{},
|
|
.interaction_metadata = null,
|
|
.interaction = null,
|
|
.thread = null,
|
|
.components = null,
|
|
.sticker_items = &[0]?Discord.StickerItem{},
|
|
.position = if (obj.getT(.integer, "position")) |p| @as(isize, @intCast(p)) else null,
|
|
.poll = null,
|
|
.call = null,
|
|
.referenced_message = refmp,
|
|
};
|
|
return message;
|
|
}
|