added guild enpoints

This commit is contained in:
Yuzu 2024-12-06 00:03:46 -05:00
parent 42f6a93245
commit 5c3d9fe397
11 changed files with 2516 additions and 104 deletions

1378
:w Normal file

File diff suppressed because it is too large Load Diff

View File

@ -20,11 +20,13 @@ const Self = @This();
allocator: mem.Allocator,
sharder: Sharder,
token: []const u8,
pub fn init(allocator: mem.Allocator) Self {
return .{
.allocator = allocator,
.sharder = undefined,
.token = undefined,
};
}
@ -44,6 +46,7 @@ pub fn start(self: *Self, settings: struct {
run: GatewayDispatchEvent(*Shard),
log: Log,
}) !void {
self.token = settings.token;
var req = FetchReq.init(self.allocator, settings.token);
defer req.deinit();

View File

@ -1,9 +1,24 @@
const std = @import("std");
const mem = std.mem;
const http = std.http;
const json = std.json;
const zjson = @import("json");
pub const BASE_URL = "https://discord.com/api/v10";
// zig fmt: off
pub const MakeRequestError = (
std.fmt.BufPrintError
|| http.Client.ConnectTcpError
|| http.Client.Request.WaitError
|| http.Client.Request.FinishError
|| http.Client.Request.Writer.Error
|| http.Client.Request.Reader.Error
|| std.Uri.ResolveInPlaceError
|| error{StreamTooLong}
);
// zig fmt: on
pub const FetchReq = struct {
allocator: mem.Allocator,
token: []const u8,
@ -25,11 +40,107 @@ pub const FetchReq = struct {
self.body.deinit();
}
pub fn makeRequest(self: *FetchReq, method: http.Method, path: []const u8, to_post: ?[]const u8) !http.Client.FetchResult {
pub fn get(self: *FetchReq, comptime T: type, path: []const u8) !zjson.Owned(T) {
const result = try self.makeRequest(.GET, path, null);
if (result.status != .ok)
return error.FailedRequest;
const output = try zjson.parse(T, self.allocator, try self.body.toOwnedSlice());
return output;
}
pub fn delete(self: *FetchReq, path: []const u8) !void {
const result = try self.makeRequest(.DELETE, path, null);
if (result.status != .no_content)
return error.FailedRequest;
}
pub fn patch(self: *FetchReq, comptime T: type, path: []const u8, object: anytype) !zjson.Owned(T) {
var buf: [4096]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buf);
var string = std.ArrayList(u8).init(fba.allocator());
errdefer string.deinit();
try json.stringify(object, .{}, string.writer());
const result = try self.makeRequest(.PATCH, path, try string.toOwnedSlice());
if (result.status != .ok)
return error.FailedRequest;
return try zjson.parse(T, self.allocator, try self.body.toOwnedSlice());
}
pub fn patch2(self: *FetchReq, path: []const u8, object: anytype) !void {
var buf: [4096]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buf);
var string = std.ArrayList(u8).init(fba.allocator());
errdefer string.deinit();
try json.stringify(object, .{}, string.writer());
const result = try self.makeRequest(.PATCH, path, try string.toOwnedSlice());
if (result.status != .no_content)
return error.FailedRequest;
}
pub fn put(self: *FetchReq, comptime T: type, path: []const u8, object: anytype) !zjson.Owned(T) {
var buf: [4096]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buf);
var string = std.ArrayList(u8).init(fba.allocator());
errdefer string.deinit();
try json.stringify(object, .{}, string.writer());
const result = try self.makeRequest(.PUT, path, try string.toOwnedSlice());
if (result.status != .ok)
return error.FailedRequest;
return try zjson.parse(T, self.allocator, try self.body.toOwnedSlice());
}
pub fn put2(self: *FetchReq, comptime T: type, path: []const u8, object: anytype) !?zjson.Owned(T) {
var buf: [4096]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buf);
var string = std.ArrayList(u8).init(fba.allocator());
errdefer string.deinit();
try json.stringify(object, .{}, string.writer());
const result = try self.makeRequest(.PUT, path, try string.toOwnedSlice());
if (result.status == .no_content)
return null;
return try zjson.parse(T, self.allocator, try self.body.toOwnedSlice());
}
pub fn put3(self: *FetchReq, path: []const u8) !void {
const result = try self.makeRequest(.PUT, path, null);
if (result.status != .no_content)
return error.FailedRequest;
}
pub fn post(self: *FetchReq, comptime T: type, path: []const u8, object: anytype) !zjson.Owned(T) {
var buf: [4096]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buf);
var string = std.ArrayList(u8).init(fba.allocator());
errdefer string.deinit();
try json.stringify(object, .{}, string.writer());
const result = try self.makeRequest(.POST, path, try string.toOwnedSlice());
if (result.status != .ok)
return error.FailedRequest;
return try zjson.parse(T, self.allocator, try self.body.toOwnedSlice());
}
pub fn makeRequest(self: *FetchReq, method: http.Method, path: []const u8, to_post: ?[]const u8) MakeRequestError!http.Client.FetchResult {
var buf: [256]u8 = undefined;
const constructed = try std.fmt.bufPrint(&buf, "{s}{s}", .{ BASE_URL, path });
var fetch_options = http.Client.FetchOptions{
.location = http.Client.FetchOptions.Location{
.url = try std.fmt.allocPrint(self.allocator, "{s}{s}", .{ BASE_URL, path }),
},
.location = http.Client.FetchOptions.Location{ .url = constructed },
.extra_headers = &[_]http.Header{
http.Header{ .name = "Accept", .value = "application/json" },
http.Header{ .name = "Content-Type", .value = "application/json" },

View File

@ -15,10 +15,6 @@ const zjson = @import("json");
const Self = @This();
const GatewayPayload = @import("./structures/types.zig").GatewayPayload;
const Opcode = @import("./structures/types.zig").GatewayOpcodes;
const Intents = @import("./structures/types.zig").Intents;
const IdentifyProperties = @import("internal.zig").IdentifyProperties;
const GatewayInfo = @import("internal.zig").GatewayInfo;
const GatewayBotInfo = @import("internal.zig").GatewayBotInfo;
@ -31,7 +27,14 @@ const Bucket = @import("internal.zig").Bucket;
const default_identify_properties = @import("internal.zig").default_identify_properties;
const Types = @import("./structures/types.zig");
const GatewayPayload = Types.GatewayPayload;
const Opcode = Types.GatewayOpcodes;
const Intents = Types.Intents;
const Snowflake = @import("./structures/snowflake.zig").Snowflake;
const FetchReq = @import("http.zig").FetchReq;
const MakeRequestError = @import("http.zig").MakeRequestError;
const Partial = Types.Partial;
pub const ShardSocketCloseCodes = enum(u16) {
Shutdown = 3000,
@ -742,25 +745,25 @@ pub fn handleEvent(self: *Self, name: []const u8, payload: []const u8) !void {
}
if (mem.eql(u8, name, "AUTO_MODERATION_RULE_CREATE")) {
const rule = try zjson.parse(GatewayPayload(Types.AutoModerationRule));
const rule = try zjson.parse(GatewayPayload(Types.AutoModerationRule), self.allocator, payload);
if (self.handler.auto_moderation_rule_create) |event| try event(self, rule.value.d.?);
}
if (mem.eql(u8, name, "AUTO_MODERATION_RULE_UPDATE")) {
const rule = try zjson.parse(GatewayPayload(Types.AutoModerationRule));
const rule = try zjson.parse(GatewayPayload(Types.AutoModerationRule), self.allocator, payload);
if (self.handler.auto_moderation_rule_update) |event| try event(self, rule.value.d.?);
}
if (mem.eql(u8, name, "AUTO_MODERATION_RULE_DELETE")) {
const rule = try zjson.parse(GatewayPayload(Types.AutoModerationRule));
const rule = try zjson.parse(GatewayPayload(Types.AutoModerationRule), self.allocator, payload);
if (self.handler.auto_moderation_rule_delete) |event| try event(self, rule.value.d.?);
}
if (mem.eql(u8, name, "AUTO_MODERATION_ACTION_EXECUTION")) {
const ax = try zjson.parse(GatewayPayload(Types.AutoModerationActionExecution));
const ax = try zjson.parse(GatewayPayload(Types.AutoModerationActionExecution), self.allocator, payload);
if (self.handler.auto_moderation_action_execution) |event| try event(self, ax.value.d.?);
}
@ -768,3 +771,742 @@ pub fn handleEvent(self: *Self, name: []const u8, payload: []const u8) !void {
if (self.handler.any) |anyEvent|
try anyEvent(self, payload);
}
pub const RequestFailedError = zjson.ParserError || MakeRequestError || error{FailedRequest};
// start http methods
/// Method to send a message
pub fn sendMessage(self: *Self, channel_id: Snowflake, create_message: Partial(Types.CreateMessage)) RequestFailedError!zjson.Owned(Types.Message) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/channels/{d}/messages", .{channel_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.post(Types.Message, path, create_message);
return res;
}
/// Method to delete a message
pub fn deleteMessage(self: *Self, channel_id: Snowflake, message_id: Snowflake) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/channels/{d}/messages/{d}", .{ channel_id.into(), message_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
try req.delete(path);
}
/// Method to edit a message
pub fn editMessage(self: *Self, channel_id: Snowflake, message_id: Snowflake, edit_message: Partial(Types.CreateMessage)) RequestFailedError!zjson.Owned(Types.Message) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/channels/{d}/messages/{d}", .{ channel_id.into(), message_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.patch(Types.Message, path, edit_message);
return res;
}
/// Method to get a message
pub fn fetchMessage(self: *Self, channel_id: Snowflake, message_id: Snowflake) RequestFailedError!zjson.Owned(Types.Message) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/channels/{d}/messages/{d}", .{ channel_id.into(), message_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.get(Types.Message, path);
return res;
}
// Methods for channel-related actions
/// Method to fetch a channel
pub fn fetchChannel(self: *Self, channel_id: Snowflake) RequestFailedError!zjson.Owned(Types.Channel) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/channels/{d}", .{channel_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.get(Types.Channel, path);
return res;
}
/// Method to delete a channel
pub fn deleteChannel(self: *Self, channel_id: Snowflake) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/channels/{d}", .{channel_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
try req.delete(path);
}
/// Method to edit a channel
pub fn editChannel(self: *Self, channel_id: Snowflake, edit_channel: Types.ModifyChannel) RequestFailedError!zjson.Owned(Types.Channel) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/channels/{d}", .{channel_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.patch(Types.Channel, path, edit_channel);
return res;
}
/// Method to create a channel
pub fn createChannel(self: *Self, guild_id: Snowflake, create_channel: Types.CreateGuildChannel) RequestFailedError!zjson.Owned(Types.Channel) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/channels", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.post(Types.Channel, path, create_channel);
return res;
}
// Methods for guild-related actions
/// Method to fetch a guild
/// Returns the guild object for the given id.
/// If `with_counts` is set to true, this endpoint will also return `approximate_member_count` and `approximate_presence_count` for the guild.
pub fn fetchGuild(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned(Types.Guild) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.get(Types.Guild, path);
return res;
}
/// Method to fetch a guild preview
/// Returns the guild preview object for the given id. If the user is not in the guild, then the guild must be discoverable.
pub fn fetchGuildPreview(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned(Types.GuildPreview) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/preview", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.get(Types.GuildPreview, path);
return res;
}
/// Method to fetch a guild's channels
/// Returns a list of guild channel objects. Does not include threads.
/// TODO: implement query string parameters
pub fn fetchGuildChannels(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned([]Types.Channel) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/channels", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.get([]Types.Channel, path);
return res;
}
/// Method to create a guild channel
/// Create a new channel object for the guild.
/// Requires the `MANAGE_CHANNELS` permission.
/// If setting permission overwrites, only permissions your bot has in the guild can be allowed/denied.
/// Setting `MANAGE_ROLES` permission in channels is only possible for guild administrators.
/// Returns the new channel object on success. Fires a Channel Create Gateway event.
pub fn createGuildChannel(self: *Self, guild_id: Snowflake, create_guild_channel: Types.CreateGuildChannel) RequestFailedError!zjson.Owned(Types.Channel) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/channels", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.post(Types.Channel, path, create_guild_channel);
return res;
}
/// Method to edit a guild channel's positions
/// Create a new channel object for the guild.
/// Requires the `MANAGE_CHANNELS` permission.
/// If setting permission overwrites, only permissions your bot has in the guild can be allowed/denied.
/// Setting `MANAGE_ROLES` permission in channels is only possible for guild administrators.
/// Returns the new channel object on success. Fires a Channel Create Gateway event.
pub fn editGuildChannelPositions(self: *Self, guild_id: Snowflake, edit_guild_channel: Types.ModifyGuildChannelPositions) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/channels", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
try req.patch2(void, path, edit_guild_channel);
}
/// Method to get a guild's active threads
/// Returns all active threads in the guild, including public and private threads.
/// Threads are ordered by their `id`, in descending order.
/// TODO: implement query string parameters
pub fn fetchGuildActiveThreads(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned(Types.Channel) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/threads/active", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.get([]Types.Channel, path);
return res;
}
/// Method to get a member
/// Returns a guild member object for the specified user.
pub fn fetchMember(self: *Self, guild_id: Snowflake, user_id: Snowflake) RequestFailedError!zjson.Owned(Types.Member) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/members/{d}", .{ guild_id.into(), user_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.get(Types.Member, path);
return res;
}
/// Method to get the members of a guild
/// Returns a list of guild member objects that are members of the guild.
/// TODO: implement query string parameters
pub fn fetchMembers(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned([]Types.Member) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/members", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.get([]Types.Member, path);
return res;
}
/// Method to find members
/// Returns a list of guild member objects whose username or nickname starts with a provided string.
pub fn searchMembers(self: *Self, guild_id: Snowflake, query: struct {
query: []const u8,
limit: usize,
}) RequestFailedError!zjson.Owned([]Types.Member) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/members/search?query={s}&limit={d}", .{
guild_id.into(),
query.query,
query.limit,
});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.get([]Types.Member, path);
return res;
}
/// Adds a user to the guild, provided you have a valid oauth2 access token for the user with the guilds.join scope.
/// Returns a 201 Created with the guild member as the body, or 204 No Content if the user is already a member of the guild.
/// Fires a Guild Member Add Gateway event.
///
/// For guilds with Membership Screening enabled, this endpoint will default to adding new members as pending in the guild member object.
/// Members that are pending will have to complete membership screening before they become full members that can talk.
pub fn addMember(self: *Self, guild_id: Snowflake, user_id: Snowflake, credentials: Types.AddGuildMember) RequestFailedError!?zjson.Owned(Types.Member) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/members/{d}", .{ guild_id.into(), user_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.put2(Types.Member, path, credentials);
return res;
}
/// Method to edit a member's attributes
/// Modify attributes of a guild member.
/// Returns a 200 OK with the guild member as the body.
/// Fires a Guild Member Update Gateway event. If the channel_id is set to null,
/// this will force the target user to be disconnected from voice.
pub fn editMember(self: *Self, guild_id: Snowflake, user_id: Snowflake, attributes: Types.ModifyGuildMember) RequestFailedError!?zjson.Owned(Types.Member) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/members/{d}", .{ guild_id.into(), user_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.patch(Types.Member, path, attributes);
return res;
}
/// Method to edit a ones's attributes
pub fn editCurrentMember(self: *Self, guild_id: Snowflake, attributes: Types.ModifyGuildMember) RequestFailedError!?zjson.Owned(Types.Member) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/members/@me", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.patch(Types.Member, path, attributes);
return res;
}
/// change's someones's nickname
pub fn changeNickname(self: *Self, guild_id: Snowflake, user_id: Snowflake, attributes: Types.ModifyGuildMember) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/members/{d}", .{ guild_id.into(), user_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.patch(Types.Member, path, attributes);
defer res.deinit();
}
/// change's someones's nickname
pub fn changeMyNickname(self: *Self, guild_id: Snowflake, attributes: Types.ModifyGuildMember) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/members/@me", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.patch(Types.Member, path, attributes);
defer res.deinit();
}
/// Adds a role to a guild member. Requires the `MANAGE_ROLES` permission.
/// Returns a 204 empty response on success.
/// Fires a Guild Member Update Gateway event.
pub fn addRole(
self: *Self,
guild_id: Snowflake,
user_id: Snowflake,
role_id: Snowflake,
) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/members/{d}/roles/{d}", .{
guild_id.into(),
user_id.into(),
role_id.into(),
});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
try req.put3(path);
}
/// Removes a role from a guild member.
/// Requires the `MANAGE_ROLES` permission.
/// Returns a 204 empty response on success.
/// Fires a Guild Member Update Gateway event.
pub fn removeRole(
self: *Self,
guild_id: Snowflake,
user_id: Snowflake,
role_id: Snowflake,
) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/members/{d}/roles/{d}", .{
guild_id.into(),
user_id.into(),
role_id.into(),
});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
try req.delete(path);
}
/// Remove a member from a guild.
/// Requires `KICK_MEMBERS` permission.
/// Returns a 204 empty response on success.
/// Fires a Guild Member Remove Gateway event.
pub fn kickMember(
self: *Self,
guild_id: Snowflake,
user_id: Snowflake,
) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/members/{d}", .{ guild_id.into(), user_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
try req.delete(path);
}
/// Returns a list of ban objects for the users banned from this guild.
/// Requires the `BAN_MEMBERS` permission.
/// TODO: add query params
pub fn fetchBans(
self: *Self,
guild_id: Snowflake,
) RequestFailedError!zjson.Owned([]Types.Ban) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/bans", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.get([]Types.Ban, path);
return res;
}
/// Returns a ban object for the given user or a 404 not found if the ban cannot be found.
/// Requires the `BAN_MEMBERS` permission.
pub fn fetchBan(self: *Self, guild_id: Snowflake, user_id: Snowflake) RequestFailedError!zjson.Owned(Types.Ban) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/bans/{d}", .{ guild_id.into(), user_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.get(Types.Ban, path);
return res;
}
/// Create a guild ban, and optionally delete previous messages sent by the banned user.
/// Requires the `BAN_MEMBERS` permission.
/// Returns a 204 empty response on success.
/// Fires a Guild Ban Add Gateway event.
pub fn ban(self: *Self, guild_id: Snowflake, user_id: Snowflake) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/bans/{d}", .{ guild_id.into(), user_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
try req.put3(path);
}
/// Remove the ban for a user. Requires the `BAN_MEMBERS` permissions.
/// Returns a 204 empty response on success.
/// Fires a Guild Ban Remove Gateway event.
pub fn unban(self: *Self, guild_id: Snowflake, user_id: Snowflake) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/bans/{d}", .{ guild_id.into(), user_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
try req.delete(path);
}
/// Ban up to 200 users from a guild, and optionally delete previous messages sent by the banned users.
/// Requires both the `BAN_MEMBERS` and `MANAGE_GUILD` permissions.
/// Returns a 200 response on success, including the fields banned_users with the IDs of the banned users
/// and failed_users with IDs that could not be banned or were already banned.
pub fn bulkBan(self: *Self, guild_id: Snowflake, bulk_ban: Types.CreateGuildBan) RequestFailedError!zjson.Owned(Types.BulkBan) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/bulk-ban", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.post(Types.BulkBan, path, bulk_ban);
return res;
}
/// Method to delete a guild
/// Delete a guild permanently. User must be owner.
/// Returns 204 No Content on success.
/// Fires a Guild Delete Gateway event.
pub fn deleteGuild(self: *Self, guild_id: Snowflake) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
try req.delete(path);
}
/// Method to edit a guild
/// Modify a guild's settings. Requires the `MANAGE_GUILD` permission.
/// Returns the updated guild object on success.
/// Fires a Guild Update Gateway event.
pub fn editGuild(self: *Self, guild_id: Snowflake, edit_guild: Types.ModifyGuild) RequestFailedError!zjson.Owned(Types.Guild) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.patch(Types.Guild, path, edit_guild);
return res;
}
/// Method to create a guild
pub fn createGuild(self: *Self, create_guild: Partial(Types.CreateGuild)) RequestFailedError!zjson.Owned(Types.Guild) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds", .{});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.post(Types.Guild, path, create_guild);
return res;
}
/// Create a new role for the guild.
/// Requires the `MANAGE_ROLES` permission.
/// Returns the new role object on success.
/// Fires a Guild Role Create Gateway event.
/// All JSON params are optional.
pub fn createRole(self: *Self, guild_id: Snowflake, create_role: Partial(Types.CreateGuildRole)) RequestFailedError!zjson.Owned(Types.Role) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/roles", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.post(Types.Role, path, create_role);
return res;
}
/// Modify the positions of a set of role objects for the guild.
/// Requires the `MANAGE_ROLES` permission.
/// Returns a list of all of the guild's role objects on success.
/// Fires multiple Guild Role Update Gateway events.
pub fn editRole(self: *Self, guild_id: Snowflake, role_id: Snowflake, edit_role: Partial(Types.ModifyGuildRole)) RequestFailedError!zjson.Owned(Types.Role) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/roles/{d}", .{ guild_id.into(), role_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const res = try req.patch(Types.Role, path, edit_role);
return res;
}
/// Modify a guild's MFA level.
/// Requires guild ownership.
/// Returns the updated level on success.
/// Fires a Guild Update Gateway event.
pub fn modifyMFALevel(self: *Self, guild_id: Snowflake) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/mfa", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
try req.delete(Types.Role, path);
}
/// Delete a guild role.
/// Requires the `MANAGE_ROLES` permission.
/// Returns a 204 empty response on success.
/// Fires a Guild Role Delete Gateway event.
pub fn deleteRole(self: *Self, guild_id: Snowflake, role_id: Snowflake) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/roles/{d}", .{ guild_id.into(), role_id.into() });
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
try req.delete(Types.Role, path);
}
/// Returns an object with one pruned key indicating the number of members that would be removed in a prune operation.
/// Requires the `MANAGE_GUILD` and `KICK_MEMBERS` permissions.
/// By default, prune will not remove users with roles.
/// You can optionally include specific roles in your prune by providing the include_roles parameter.
/// Any inactive user that has a subset of the provided role(s) will be counted in the prune and users with additional roles will not.
/// TODO: implement query
pub fn fetchPruneCount(self: *Self, guild_id: Snowflake, _: Types.GetGuildPruneCountQuery) RequestFailedError!zjson.Owned(struct { pruned: isize }) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/prune", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const pruned = try req.get(struct { pruned: isize }, path);
return pruned;
}
/// Begin a prune operation.
/// Requires the `MANAGE_GUILD` and `KICK_MEMBERS` permissions.
/// Returns an object with one `pruned` key indicating the number of members that were removed in the prune operation.
/// For large guilds it's recommended to set the `compute_prune_count` option to false, forcing `pruned` to `null`.
/// Fires multiple Guild Member Remove Gateway events.
///
/// By default, prune will not remove users with roles.
/// You can optionally include specific roles in your prune by providing the `include_roles` parameter.
/// Any inactive user that has a subset of the provided role(s) will be included in the prune and users with additional roles will not.
pub fn beginGuildPrune(self: *Self, guild_id: Snowflake, params: Types.BeginGuildPrune) RequestFailedError!zjson.Owned(struct { pruned: isize }) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/prune", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const pruned = try req.post(struct { pruned: isize }, path, params);
return pruned;
}
/// Returns a list of voice region objects for the guild.
/// Unlike the similar /voice route, this returns VIP servers when the guild is VIP-enabled.
pub fn fetchVoiceRegion(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned([]Types.VoiceRegion) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/regions", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const regions = try req.get([]Types.VoiceRegion, path);
return regions;
}
/// Returns a list of invite objects (with invite metadata) for the guild.
/// Requires the `MANAGE_GUILD` permission.
pub fn fetchInvites(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned([]Types.Invite) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/invites", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const invites = try req.get([]Types.Invite, path);
return invites;
}
/// Returns a list of integration objects for the guild.
/// Requires the `MANAGE_GUILD` permission.
pub fn fetchIntegrations(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned([]Types.Integration) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/integrations", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const integrations = try req.get([]Types.integrations, path);
return integrations;
}
/// Returns a list of integration objects for the guild.
/// Requires the `MANAGE_GUILD` permission.
pub fn deleteIntegration(
self: *Self,
guild_id: Snowflake,
integration_id: Snowflake,
) RequestFailedError!void {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/integrations/{d}", .{
guild_id.into(),
integration_id.into(),
});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
try req.delete(path);
}
/// Returns a guild widget settings object.
/// Requires the `MANAGE_GUILD` permission.
pub fn fetchWidgetSettings(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned(Types.GuildWidgetSettings) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/widget", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const widget = try req.get(Types.GuildWidgetSettings, path);
return widget;
}
/// Modify a guild widget settings object for the guild.
/// All attributes may be passed in with JSON and modified.
/// Requires the `MANAGE_GUILD` permission.
/// Returns the updated guild widget settings object.
/// Fires a Guild Update Gateway event.
pub fn editWidget(self: *Self, guild_id: Snowflake, attributes: Partial(Types.GuildWidget)) RequestFailedError!zjson.Owned(Types.GuildWidget) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/widget", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const widget = try req.patch(Types.GuildWidget, path, attributes);
return widget;
}
/// Returns the widget for the guild.
/// Fires an Invite Create Gateway event when an invite channel is defined and a new Invite is generated.
pub fn fetchWidget(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned(Types.GuildWidget) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/widget.json", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const widget = try req.get(Types.GuildWidget, path);
return widget;
}
/// Returns a partial invite object for guilds with that feature enabled.
/// Requires the `MANAGE_GUILD` permission. code will be null if a vanity url for the guild is not set.
pub fn fetchVanityUrl(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned(Partial(Types.Invite)) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/vanity-url", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const invite = try req.get(Partial(Types.Invite), path);
return invite;
}
/// Returns a PNG image widget for the guild.
/// Requires no permissions or authentication.
pub fn fetchWidgetImage(self: *Self, guild_id: Snowflake) RequestFailedError![]const u8 {
_ = self;
_ = guild_id;
@panic("unimplemented");
}
/// Modify the guild's Welcome Screen.
/// Requires the `MANAGE_GUILD` permission.
/// Returns the updated Welcome Screen object. May fire a Guild Update Gateway event.
/// TODO: add query params
pub fn fetchWelcomeScreen(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned(Types.WelcomeScreen) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/welcome-screen", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const welcome_screen = try req.get(Types.WelcomeScreen, path);
return welcome_screen;
}
/// Returns the Onboarding object for the guild.
pub fn fetchOnboarding(self: *Self, guild_id: Snowflake) RequestFailedError!zjson.Owned(Types.GuildOnboarding) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/onboarding", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const ob = try req.get(Types.GuildOnboarding, path);
return ob;
}
/// Returns the Onboarding object for the guild.
pub fn editOnboarding(self: *Self, guild_id: Snowflake, onboarding: Types.GuildOnboardingPromptOption) RequestFailedError!zjson.Owned(Types.GuildOnboarding) {
var buf: [256]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/guilds/{d}/onboarding", .{guild_id.into()});
var req = FetchReq.init(self.allocator, self.details.token);
defer req.deinit();
const ob = try req.put(Types.GuildOnboarding, path, onboarding);
return ob;
}

View File

@ -186,3 +186,15 @@ pub const DefaultReactionEmoji = struct {
/// The unicode character of the emoji
emoji_name: ?[]const u8,
};
/// https://discord.com/developers/docs/resources/guild#modify-guild-channel-positions
pub const ModifyGuildChannelPositions = struct {
/// Channel id
id: Snowflake,
/// Sorting position of the channel (channels with the same position are sorted by id)
position: ?isize,
/// Syncs the permission overwrites with the new parent, if moving to a new category
lock_positions: ?bool,
/// The new parent ID for the channel that is moved
parent_id: ?Snowflake,
};

View File

@ -844,78 +844,6 @@ pub const TeamMemberRole = enum {
read_only,
};
/// https://discord.com/developers/docs/monetization/entitlements#entitlement-object-entitlement-structure
pub const Entitlement = struct {
/// ID of the entitlement
id: Snowflake,
/// ID of the SKU
sku_id: Snowflake,
/// ID of the user that is granted access to the entitlement's sku
user_id: ?Snowflake,
/// ID of the guild that is granted access to the entitlement's sku
guild_id: ?Snowflake,
/// ID of the parent application
application_id: Snowflake,
/// Type of entitlement
type: EntitlementType,
/// Entitlement was deleted
deleted: bool,
/// Start date at which the entitlement is valid. Not present when using test entitlements
starts_at: ?[]const u8,
/// Date at which the entitlement is no longer valid. Not present when using test entitlements
ends_at: ?[]const u8,
/// For consumable items, whether or not the entitlement has been consumed
consumed: ?bool,
};
/// https://discord.com/developers/docs/monetization/entitlements#entitlement-object-entitlement-types
pub const EntitlementType = enum(u4) {
/// Entitlement was purchased by user
Purchase = 1,
///Entitlement for Nitro subscription
PremiumSubscription = 2,
/// Entitlement was gifted by developer
DeveloperGift = 3,
/// Entitlement was purchased by a dev in application test mode
TestModePurchase = 4,
/// Entitlement was granted when the SKU was free
FreePurchase = 5,
/// Entitlement was gifted by another user
UserGift = 6,
/// Entitlement was claimed by user for free as a Nitro Subscriber
PremiumPurchase = 7,
/// Entitlement was purchased as an app subscription
ApplicationSubscription = 8,
};
/// https://discord.com/developers/docs/monetization/skus#sku-object-sku-structure
pub const Sku = struct {
/// ID of SKU
id: Snowflake,
/// Type of SKU
type: SkuType,
/// ID of the parent application
application_id: Snowflake,
/// Customer-facing name of your premium offering
name: []const u8,
/// System-generated URL slug based on the SKU's name
slug: []const u8,
/// SKU flags combined as a bitfield
flags: SkuFlags,
};
/// https://discord.com/developers/docs/monetization/skus#sku-object-sku-types
pub const SkuType = enum(u4) {
/// Durable one-time purchase
Durable = 2,
/// Consumable one-time purchase
Consumable = 3,
/// Represents a recurring subscription
Subscription = 5,
/// System-generated group for each SUBSCRIPTION SKU created
SubscriptionGroup = 6,
};
/// https://discord.com/developers/docs/resources/guild#bulk-guild-ban
pub const BulkBan = struct {
/// list of user ids, that were successfully banned

View File

@ -202,3 +202,182 @@ pub const GuildPreview = struct {
/// Custom guild stickers
stickers: []Sticker,
};
/// https://discord.com/developers/docs/resources/guild#create-guild
pub const CreateGuild = struct {
/// Name of the guild (1-100 characters)
name: []const u8,
/// Base64 128x128 image for the guild icon
icon: ?[]const u8,
/// Verification level
verification_level: ?VerificationLevels,
/// Default message notification level
default_message_notifications: DefaultMessageNotificationLevels,
/// Explicit content filter level
explicit_content_filter: ?ExplicitContentFilterLevels,
/// New guild roles (first role is the everyone role)
roles: ?[]Role,
/// New guild's channels
channels: ?[]Partial(Channel),
/// Id for afk channel
afk_channel_id: ?[]const u8,
/// Afk timeout in seconds
afk_timeout: ?isize,
/// The id of the channel where guild notices such as welcome messages and boost events are posted
system_channel_id: ?[]const u8,
/// System channel flags
system_channel_flags: ?SystemChannelFlags,
};
/// https://discord.com/developers/docs/resources/guild#modify-guild
pub const ModifyGuild = struct {
/// Guild name
name: ?[]const u8,
/// Verification level
verification_level: ?VerificationLevels,
/// Default message notification filter level
default_message_notifications: ?DefaultMessageNotificationLevels,
/// Explicit content filter level
explicit_content_filter: ?ExplicitContentFilterLevels,
/// Id for afk channel
afk_channel_id: ?Snowflake,
/// Afk timeout in seconds
afk_timeout: ?isize,
/// Base64 1024x1024 png/jpeg/gif image for the guild icon (can be animated gif when the server has the `ANIMATED_ICON` feature)
icon: ?[]const u8,
/// User id to transfer guild ownership to (must be owner)
owner_id: ?Snowflake,
/// Base64 16:9 png/jpeg image for the guild splash (when the server has `INVITE_SPLASH` fe
splash: ?[]const u8,
/// Base64 16:9 png/jpeg image for the guild discovery spash (when the server has the `DISCOVERABLE` feature)
discovery_splash: ?[]const u8,
/// Base64 16:9 png/jpeg image for the guild banner (when the server has BANNER feature)
banner: ?[]const u8,
/// The id of the channel where guild notices such as welcome messages and boost events are posted
system_channel_id: ?Snowflake,
/// System channel flags
system_channel_flags: ?SystemChannelFlags,
/// The id of the channel where Community guilds display rules and/or guidelines
rules_channel_id: ?Snowflake,
/// The id of the channel where admins and moderators of Community guilds receive notices from Discord
public_updates_channel_id: ?Snowflake,
/// The preferred locale of a Community guild used in server discovery and notices from Discord; defaults to "en-US"
preferred_locale: ?[]const u8,
/// Enabled guild features
features: ?[]GuildFeatures,
/// Whether the guild's boost progress bar should be enabled
premium_progress_bar_enabled: ?bool,
};
pub const CreateGuildBan = struct {
/// list of user ids to ban (max 200)
user_ids: []Snowflake,
/// number of seconds to delete messages for, between 0 and 604800 (7 days)
delete_message_seconds: ?isize,
};
/// https://discord.com/developers/docs/resources/guild#get-guild-prune-count
pub const GetGuildPruneCountQuery = struct {
/// Number of days to count prune for (1 or more), default: 7
days: ?isize,
/// Role(s) to include, default: none
include_roles: ?[]Snowflake,
};
/// https://discord.com/developers/docs/resources/guild#begin-guild-prune
pub const BeginGuildPrune = struct {
/// Number of days to prune (1 or more), default: 7
days: ?isize,
/// Whether 'pruned' is returned, discouraged for large guilds, default: true
compute_prune_count: ?bool,
/// Role(s) ro include, default: none
include_roles: ?[]Snowflake,
};
/// https://discord.com/developers/docs/resources/guild#modify-guild-onboarding-json-params
pub const ModifyGuildOnboarding = struct {
/// Prompts shown during onboarding and in customize community
prompts: []GuildOnboardingPrompt,
/// Channel IDs that members get opted into automatically
defaultChannelIds: []Snowflake,
/// Whether onboarding is enabled in the guild
enabled: bool,
/// Current mode of onboarding
mode: GuildOnboardingMode,
};
/// https://discord.com/developers/docs/resources/guild#guild-onboarding-object-guild-onboarding-structure
pub const GuildOnboarding = struct {
/// ID of the guild this onboarding is part of
guild_id: []const u8,
/// Prompts shown during onboarding and in customize community
prompts: []GuildOnboardingPrompt,
/// Channel IDs that members get opted into automatically
default_channel_ids: [][]const u8,
/// Whether onboarding is enabled in the guild
enabled: bool,
/// Current mode of onboarding
mode: GuildOnboardingMode,
};
/// https://discord.com/developers/docs/resources/guild#guild-onboarding-object-onboarding-prompt-structure
pub const GuildOnboardingPrompt = struct {
/// ID of the prompt
id: Snowflake,
/// Type of prompt
type: GuildOnboardingPromptType,
/// Options available within the prompt
options: []GuildOnboardingPromptOption,
/// Title of the prompt
title: []const u8,
/// Indicates whether users are limited to selecting one option for the prompt
single_select: bool,
/// Indicates whether the prompt is required before a user completes the onboarding flow
required: bool,
/// Indicates whether the prompt is present in the onboarding flow. If `false`, the prompt will only appear in the Channels & Roles tab
in_onboarding: bool,
};
/// https://discord.com/developers/docs/resources/guild#guild-onboarding-object-prompt-option-structure
pub const GuildOnboardingPromptOption = struct {
/// ID of the prompt option
id: Snowflake,
/// IDs for channels a member is added to when the option is selected
channel_ids: [][]const u8,
/// IDs for roles assigned to a member when the option is selected
role_ids: []Snowflake,
/// Emoji of the option
/// @remarks
/// When creating or updating a prompt option, the `emoji_id`, `emoji_name`, and `emoji_animated` fields must be used instead of the emoji object.
emoji: ?Emoji,
/// Emoji ID of the option
/// @remarks
/// When creating or updating a prompt option, the `emoji_id`, `emoji_name`, and `emoji_animated` fields must be used instead of the emoji object.
emoji_id: ?[]const u8,
/// Emoji name of the option
/// @remarks
/// When creating or updating a prompt option, the `emoji_id`, `emoji_name`, and `emoji_animated` fields must be used instead of the emoji object.
emoji_name: ?[]const u8,
/// Whether the emoji is animated
/// @remarks
/// When creating or updating a prompt option, the `emoji_id`, `emoji_name`, and `emoji_animated` fields must be used instead of the emoji object.
emoji_animated: bool,
/// Title of the option
title: []const u8,
/// Description of the option
description: ?[]const u8,
};
/// https://discord.com/developers/docs/resources/guild#guild-onboarding-object-prompt-types
pub const GuildOnboardingPromptType = enum {
MultipleChoice,
DropDown,
};
/// https://discord.com/developers/docs/resources/guild#guild-onboarding-object-onboarding-mode
pub const GuildOnboardingMode = enum {
/// Counts only Default Channels towards constraints
OnboardingDefault,
/// Counts Default Channels and Questions towards constraints
OnboardingAdvanced,
};

View File

@ -1,4 +1,5 @@
const User = @import("user.zig").User;
const Snowflake = @import("snowflake.zig").Snowflake;
const AvatarDecorationData = @import("user.zig").AvatarDecorationData;
/// https://discord.com/developers/docs/resources/guild#guild-member-object
@ -60,3 +61,35 @@ pub const MemberWithUser = struct {
/// The user object for this member
user: User,
};
/// https://discord.com/developers/docs/resources/guild#add-guild-member-json-params
pub const AddGuildMember = struct {
/// access token of a user that has granted your app the `guilds.join` scope
access_token: []const u8,
/// Value to set user's nickname to. Requires MANAGE_NICKNAMES permission on the bot
nick: ?[]const u8,
/// Array of role ids the member is assigned. Requires MANAGE_ROLES permission on the bot
roles: ?[][]const u8,
/// Whether the user is muted in voice channels. Requires MUTE_MEMBERS permission on the bot
mute: ?bool,
/// Whether the user is deafened in voice channels. Requires DEAFEN_MEMBERS permission on the bot
deaf: ?bool,
};
/// https://discord.com/developers/docs/resources/guild#modify-guild-member
pub const ModifyGuildMember = struct {
/// Value to set users nickname to. Requires the `MANAGE_NICKNAMES` permission
nick: ?[]const u8,
/// Array of role ids the member is assigned. Requires the `MANAGE_ROLES` permission
roles: ?Snowflake,
/// Whether the user is muted in voice channels. Will throw a 400 if the user is not in a voice channel. Requires the `MUTE_MEMBERS` permission
mute: ?bool,
/// Whether the user is deafened in voice channels. Will throw a 400 if the user is not in a voice channel. Requires the `MOVE_MEMBERS` permission
deaf: ?bool,
/// Id of channel to move user to (if they are connected to voice). Requires the `MOVE_MEMBERS` permission
channel_id: ?Snowflake,
/// When the user's timeout will expire and the user will be able to communicate in the guild again (up to 28 days in the future), set to null to remove timeout. Requires the `MODERATE_MEMBERS` permission. The date must be given in a ISO string form.
communication_disabled_until: ?[]const u8,
/// Set the flags for the guild member. Requires the `MANAGE_GUILD` or `MANAGE_ROLES` or the combination of `MODERATE_MEMBERS` and `KICK_MEMBERS` and `BAN_MEMBERS`
flags: ?isize,
};

View File

@ -47,3 +47,39 @@ pub const RoleTags = struct {
/// Tags with type ?bool represent booleans. They will be present and set to null if they are "true", and will be not present if they are "false".
guild_connections: ?bool,
};
/// https://discord.com/developers/docs/resources/guild#create-guild-role
pub const CreateGuildRole = struct {
/// Name of the role, max 100 characters, default: "new role"
name: ?[]const u8,
/// Bitwise value of the enabled/disabled permissions, default: everyone permissions in guild
permissions: ?[][]const u8,
/// RGB color value, default: 0
color: ?isize,
/// Whether the role should be displayed separately in the sidebar, default: false
hoist: ?bool,
/// Whether the role should be mentionable, default: false
mentionable: ?bool,
/// The role's unicode emoji (if the guild has the `ROLE_ICONS` feature)
unicode_emoji: ?[]const u8,
/// the role's icon image (if the guild has the `ROLE_ICONS` feature)
icon: ?[]const u8,
};
/// https://discord.com/developers/docs/resources/guild#modify-guild-role
pub const ModifyGuildRole = struct {
/// Name of the role, max 100 characters, default: "new role"
name: ?[]const u8,
/// Bitwise value of the enabled/disabled permissions, default: everyone permissions in guild
permissions: ?[][]const u8,
/// RGB color value, default: 0
color: ?isize,
/// Whether the role should be displayed separately in the sidebar, default: false
hoist: ?bool,
/// Whether the role should be mentionable, default: false
mentionable: ?bool,
/// The role's unicode emoji (if the guild has the `ROLE_ICONS` feature)
unicodeEmoji: ?[]const u8,
/// the role's icon image (if the guild has the `ROLE_ICONS` feature)
icon: ?[]const u8,
};

View File

@ -13,35 +13,24 @@ fn ready(_: *Shard, payload: Discord.Ready) !void {
std.debug.print("logged in as {s}\n", .{payload.user.username});
}
fn message_create(session: *Shard, message: Discord.Message) fmt.AllocPrintError!void {
fn message_create(session: *Shard, message: Discord.Message) !void {
std.debug.print("captured: {?s} send by {s}\n", .{ message.content, message.author.username });
if (message.content) |mc| if (std.ascii.eqlIgnoreCase(mc, "!hi")) {
var req = FetchReq.init(session.allocator, session.details.token);
defer req.deinit();
const payload: Discord.Partial(Discord.CreateMessage) = .{ .content = "Hi, I'm hang man, your personal assistant" };
const json = std.json.stringifyAlloc(session.allocator, payload, .{}) catch unreachable;
defer session.allocator.free(json);
const path = try fmt.allocPrint(session.allocator, "/channels/{d}/messages", .{message.channel_id.into()});
_ = req.makeRequest(.POST, path, json) catch unreachable;
const payload: Discord.Partial(Discord.CreateMessage) = .{
.content = "discord.zig best library",
};
_ = try session.sendMessage(message.channel_id, payload);
};
}
fn message_reaction_add(_: *Shard, _: Discord.MessageReactionAdd) !void {}
fn guild_create(_: *Shard, guild: Discord.Guild) !void {
std.debug.print("{any}\n", .{guild});
}
pub fn main() !void {
var tsa = std.heap.ThreadSafeAllocator{ .child_allocator = std.heap.c_allocator };
var handler = Discord.init(tsa.allocator());
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
var handler = Discord.init(gpa.allocator());
try handler.start(.{
.token = std.posix.getenv("DISCORD_TOKEN").?,
.intents = Intents.fromRaw(INTENTS),
.run = .{ .message_create = &message_create, .ready = &ready, .message_reaction_add = &message_reaction_add },
.run = .{ .message_create = &message_create, .ready = &ready },
.log = .yes,
.options = .{},
});

View File

@ -928,6 +928,7 @@ pub const Error = std.mem.Allocator.Error || ParserError;
/// but will someday
pub fn parseInto(comptime T: type, allocator: mem.Allocator, value: JsonType) Error!T {
switch (@typeInfo(T)) {
.void => return {},
.bool => {
return value.bool;
},
@ -1101,7 +1102,7 @@ pub fn Owned(comptime Struct: type) type {
/// parse any string containing a JSON object root `{...}`
/// casts the value into `T`
pub fn parse(comptime T: type, child_allocator: mem.Allocator, data: []const u8) (std.meta.IntToEnumError || ParserError)!Owned(T) {
pub fn parse(comptime T: type, child_allocator: mem.Allocator, data: []const u8) ParserError!Owned(T) {
var owned: Owned(T) = .{
.arena = try child_allocator.create(std.heap.ArenaAllocator),
.value = undefined,