bunch of changes
This commit is contained in:
parent
0412d6b404
commit
2ecad41c52
11
README.md
11
README.md
@ -5,7 +5,6 @@ A high-performance bleeding edge Discord library in Zig, featuring full API cove
|
|||||||
* 100% API Coverage & Fully Typed: Offers complete access to Discord's API with strict typing for reliable and safe code.
|
* 100% API Coverage & Fully Typed: Offers complete access to Discord's API with strict typing for reliable and safe code.
|
||||||
* High Performance: Faster than whichever library you can name (WIP)
|
* High Performance: Faster than whichever library you can name (WIP)
|
||||||
* Flexible Payload Parsing: Supports payload parsing through both zlib and zstd*.
|
* Flexible Payload Parsing: Supports payload parsing through both zlib and zstd*.
|
||||||
* Language Agnostic: Primarily in Zig, but also compatible with JavaScript. (PERHAPS?)
|
|
||||||
|
|
||||||
```zig
|
```zig
|
||||||
const Client = @import("discord.zig").Client;
|
const Client = @import("discord.zig").Client;
|
||||||
@ -75,23 +74,13 @@ Contributions are welcome! Please open an issue or pull request if you'd like to
|
|||||||
## http methods missing
|
## http methods missing
|
||||||
| Endpoint | Support |
|
| Endpoint | Support |
|
||||||
|----------------------------------------|---------|
|
|----------------------------------------|---------|
|
||||||
| Application related | ❌ |
|
|
||||||
| Audit log | ❌ |
|
| Audit log | ❌ |
|
||||||
| Automod | ❌ |
|
| Automod | ❌ |
|
||||||
| Channel related | ✅ |
|
|
||||||
| Emoji related | ✅ |
|
|
||||||
| Entitlement related | ❌ |
|
|
||||||
| Guild related | ✅ |
|
|
||||||
| Guild Scheduled Event related | ❌ |
|
| Guild Scheduled Event related | ❌ |
|
||||||
| Guild template related | ❌ |
|
| Guild template related | ❌ |
|
||||||
| Invite related | ✅ |
|
|
||||||
| Message related | ✅ |
|
|
||||||
| Poll related | ✅ |
|
|
||||||
| SKU related | ❌ |
|
|
||||||
| Soundboard related | ❌ |
|
| Soundboard related | ❌ |
|
||||||
| Stage Instance related | ❌ |
|
| Stage Instance related | ❌ |
|
||||||
| Sticker related | ❌ |
|
| Sticker related | ❌ |
|
||||||
| Subscription related | ❌ |
|
| Subscription related | ❌ |
|
||||||
| User related | ✅ |
|
|
||||||
| Voice related | ❌ |
|
| Voice related | ❌ |
|
||||||
| Webhook related | ❌ |
|
| Webhook related | ❌ |
|
||||||
|
16
src/http.zig
16
src/http.zig
@ -65,8 +65,11 @@ pub const FetchReq = struct {
|
|||||||
try self.extra_headers.append(http.Header{ .name = name, .value = value });
|
try self.extra_headers.append(http.Header{ .name = name, .value = value });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addQueryParam(self: *FetchReq, name: []const u8, value: []const u8) !void {
|
pub fn addQueryParam(self: *FetchReq, name: []const u8, value: anytype) !void {
|
||||||
try self.query_params.put(name, value);
|
if (value == null)
|
||||||
|
return;
|
||||||
|
var buf: [256]u8 = undefined;
|
||||||
|
try self.query_params.put(name, try std.fmt.bufPrint(&buf, "{any}", .{value}));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn formatQueryParams(self: *FetchReq) ![]const u8 {
|
fn formatQueryParams(self: *FetchReq) ![]const u8 {
|
||||||
@ -171,6 +174,15 @@ pub const FetchReq = struct {
|
|||||||
return error.FailedRequest;
|
return error.FailedRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn put4(self: *FetchReq, comptime T: type, path: []const u8) !zjson.Owned(T) {
|
||||||
|
const result = try self.makeRequest(.PUT, path, null);
|
||||||
|
|
||||||
|
if (result.status != .ok)
|
||||||
|
return error.FailedRequest;
|
||||||
|
|
||||||
|
return try zjson.parse(T, self.allocator, try self.body.toOwnedSlice());
|
||||||
|
}
|
||||||
|
|
||||||
pub fn post(self: *FetchReq, comptime T: type, path: []const u8, object: anytype) !zjson.Owned(T) {
|
pub fn post(self: *FetchReq, comptime T: type, path: []const u8, object: anytype) !zjson.Owned(T) {
|
||||||
var buf: [4096]u8 = undefined;
|
var buf: [4096]u8 = undefined;
|
||||||
var fba = std.heap.FixedBufferAllocator.init(&buf);
|
var fba = std.heap.FixedBufferAllocator.init(&buf);
|
||||||
|
149
src/shard.zig
149
src/shard.zig
@ -796,14 +796,18 @@ pub const RequestFailedError = zjson.ParserError || MakeRequestError || error{Fa
|
|||||||
/// If operating on a guild channel, this endpoint requires the current user to have the `VIEW_CHANNEL` permission.
|
/// If operating on a guild channel, this endpoint requires the current user to have the `VIEW_CHANNEL` permission.
|
||||||
/// If the channel is a voice channel, they must also have the `CONNECT` permission.
|
/// If the channel is a voice channel, they must also have the `CONNECT` permission.
|
||||||
/// If the current user is missing the `READ_MESSAGE_HISTORY` permission in the channel, then no messages will be returned.
|
/// If the current user is missing the `READ_MESSAGE_HISTORY` permission in the channel, then no messages will be returned.
|
||||||
/// TODO: add query params
|
pub fn fetchMessages(self: *Self, channel_id: Snowflake, query: Types.GetMessagesQuery) RequestFailedError!zjson.Owned([]Types.Message) {
|
||||||
pub fn fetchMessages(self: *Self, channel_id: Snowflake) RequestFailedError!zjson.Owned([]Types.Message) {
|
|
||||||
var buf: [256]u8 = undefined;
|
var buf: [256]u8 = undefined;
|
||||||
const path = try std.fmt.bufPrint(&buf, "/channels/{d}/messages", .{channel_id.into()});
|
const path = try std.fmt.bufPrint(&buf, "/channels/{d}/messages", .{channel_id.into()});
|
||||||
|
|
||||||
var req = FetchReq.init(self.allocator, self.details.token);
|
var req = FetchReq.init(self.allocator, self.details.token);
|
||||||
defer req.deinit();
|
defer req.deinit();
|
||||||
|
|
||||||
|
try req.addQueryParam("limit", query.limit);
|
||||||
|
try req.addQueryParam("around", query.around);
|
||||||
|
try req.addQueryParam("before", query.before);
|
||||||
|
try req.addQueryParam("after", query.after);
|
||||||
|
|
||||||
const messages = try req.get([]Types.Message, path);
|
const messages = try req.get([]Types.Message, path);
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
@ -2423,7 +2427,8 @@ pub fn fetchAnswerVoters(
|
|||||||
/// Immediately ends the poll.
|
/// Immediately ends the poll.
|
||||||
/// You cannot end polls from other users.
|
/// You cannot end polls from other users.
|
||||||
///
|
///
|
||||||
/// Returns a message object. Fires a Message Update Gateway event.
|
/// Returns a message object.
|
||||||
|
/// Fires a Message Update Gateway event.
|
||||||
pub fn endPoll(
|
pub fn endPoll(
|
||||||
self: *Self,
|
self: *Self,
|
||||||
channel_id: Snowflake,
|
channel_id: Snowflake,
|
||||||
@ -2438,3 +2443,141 @@ pub fn endPoll(
|
|||||||
const msg = try req.post(Types.Message, path);
|
const msg = try req.post(Types.Message, path);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the application object associated with the requesting bot user.
|
||||||
|
pub fn fetchMyApplication(self: *Self) RequestFailedError!zjson.Owned(Types.Application) {
|
||||||
|
var req = FetchReq.init(self.allocator, self.details.token);
|
||||||
|
defer req.deinit();
|
||||||
|
|
||||||
|
const app = try req.get(Types.Application, "/applications/@me");
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Edit properties of the app associated with the requesting bot user.
|
||||||
|
/// Only properties that are passed will be updated.
|
||||||
|
/// Returns the updated application object on success.
|
||||||
|
pub fn editMyApplication(self: *Self, params: Types.ModifyApplication) RequestFailedError!zjson.Owned(Types.Application) {
|
||||||
|
var req = FetchReq.init(self.allocator, self.details.token);
|
||||||
|
defer req.deinit();
|
||||||
|
|
||||||
|
const app = try req.patch(Types.Application, "/applications/@me", params);
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a serialized activity instance, if it exists.
|
||||||
|
/// Useful for preventing unwanted activity sessions.
|
||||||
|
pub fn fetchActivityInstance(self: *Self, application_id: Snowflake, insance: []const u8) RequestFailedError!zjson.Owned(Types.ActivityInstance) {
|
||||||
|
var buf: [256]u8 = undefined;
|
||||||
|
const path = try std.fmt.bufPrint(&buf, "/applications/{d}/activity-instances/{s}", .{ application_id.into(), insance });
|
||||||
|
|
||||||
|
var req = FetchReq.init(self.allocator, self.details.token);
|
||||||
|
defer req.deinit();
|
||||||
|
|
||||||
|
const activity_instance = try req.get(Types.ActivityInstance, path);
|
||||||
|
return activity_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a list of application role connection metadata objects for the given application.
|
||||||
|
pub fn fetchApplicationRoleConnectionMetadataRecords(self: *Self, application_id: Snowflake) RequestFailedError!zjson.Owned([]Types.ApplicationRoleConnection) {
|
||||||
|
var buf: [256]u8 = undefined;
|
||||||
|
const path = try std.fmt.bufPrint(&buf, "/applications/{d}/role-connection/metadata", .{application_id.into()});
|
||||||
|
|
||||||
|
var req = FetchReq.init(self.allocator, self.details.token);
|
||||||
|
defer req.deinit();
|
||||||
|
|
||||||
|
return req.get([]Types.ApplicationRoleConnection, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates and returns a list of application role connection metadata objects for the given application.
|
||||||
|
pub fn updateApplicationRoleConnectionMetadataRecords(self: *Self, application_id: Snowflake) RequestFailedError!zjson.Owned([]Types.ApplicationRoleConnection) {
|
||||||
|
var buf: [256]u8 = undefined;
|
||||||
|
const path = try std.fmt.bufPrint(&buf, "/applications/{d}/role-connection/metadata", .{application_id.into()});
|
||||||
|
|
||||||
|
var req = FetchReq.init(self.allocator, self.details.token);
|
||||||
|
defer req.deinit();
|
||||||
|
|
||||||
|
return req.put4([]Types.ApplicationRoleConnection, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all entitlements for a given app, active and expired.
|
||||||
|
pub fn fetchEntitlements(self: *Self, application_id: Snowflake) RequestFailedError!zjson.Owned([]Types.Entitlement) {
|
||||||
|
var buf: [256]u8 = undefined;
|
||||||
|
const path = try std.fmt.bufPrint(&buf, "/applications/{d}/entitlements", .{application_id.into()});
|
||||||
|
|
||||||
|
var req = FetchReq.init(self.allocator, self.details.token);
|
||||||
|
defer req.deinit();
|
||||||
|
|
||||||
|
const entitlements = try req.get([]Types.Entitlement, path);
|
||||||
|
return entitlements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an entitlement.
|
||||||
|
pub fn fetchEntitlement(self: *Self, application_id: Snowflake, entitlement_id: Snowflake) RequestFailedError!zjson.Owned(Types.Entitlement) {
|
||||||
|
var buf: [256]u8 = undefined;
|
||||||
|
const path = try std.fmt.bufPrint(&buf, "/applications/{d}/entitlements/{d}", .{ application_id.into(), entitlement_id.into() });
|
||||||
|
|
||||||
|
var req = FetchReq.init(self.allocator, self.details.token);
|
||||||
|
defer req.deinit();
|
||||||
|
|
||||||
|
const entitlement = try req.get(Types.Entitlement, path);
|
||||||
|
return entitlement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// For One-Time Purchase consumable SKUs, marks a given entitlement for the user as consumed.
|
||||||
|
/// The entitlement will have consumed: true when using List Entitlements.
|
||||||
|
///
|
||||||
|
/// Returns a 204 No Content on success.
|
||||||
|
pub fn consumeEntitlement(self: *Self, application_id: Snowflake, entitlement_id: Snowflake) RequestFailedError!void {
|
||||||
|
var buf: [256]u8 = undefined;
|
||||||
|
const path = try std.fmt.bufPrint(&buf, "/applications/{d}/entitlements/{d}/consume", .{ application_id.into(), entitlement_id.into() });
|
||||||
|
|
||||||
|
var req = FetchReq.init(self.allocator, self.details.token);
|
||||||
|
defer req.deinit();
|
||||||
|
|
||||||
|
try req.post5(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a test entitlement to a given SKU for a given guild or user.
|
||||||
|
/// Discord will act as though that user or guild has entitlement to your premium offering.
|
||||||
|
///
|
||||||
|
/// This endpoint returns a partial entitlement object. It will not contain `subscription_id`, `starts_at`, or `ends_at`, as it's valid in perpetuity.
|
||||||
|
///
|
||||||
|
/// After creating a test entitlement, you'll need to reload your Discord client. After doing so, you'll see that your server or user now has premium access.
|
||||||
|
pub fn createTestEntitlement(
|
||||||
|
self: *Self,
|
||||||
|
application_id: Snowflake,
|
||||||
|
params: Types.CreateTestEntitlement,
|
||||||
|
) RequestFailedError!zjson.Owned(Partial(Types.Entitlement)) {
|
||||||
|
var buf: [256]u8 = undefined;
|
||||||
|
const path = try std.fmt.bufPrint(&buf, "/applications/{d}/entitlements", .{application_id.into()});
|
||||||
|
|
||||||
|
var req = FetchReq.init(self.allocator, self.details.token);
|
||||||
|
defer req.deinit();
|
||||||
|
|
||||||
|
return req.post(Partial(Types.Entitlement), path, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes a currently-active test entitlement. Discord will act as though that user or guild no longer has entitlement to your premium offering.
|
||||||
|
///
|
||||||
|
/// Returns 204 No Content on success.
|
||||||
|
pub fn deleteTestEntitlement(self: *Self, application_id: Snowflake) RequestFailedError!void {
|
||||||
|
var buf: [256]u8 = undefined;
|
||||||
|
const path = try std.fmt.bufPrint(&buf, "/applications/{d}/entitlements", .{application_id.into()});
|
||||||
|
|
||||||
|
var req = FetchReq.init(self.allocator, self.details.token);
|
||||||
|
defer req.deinit();
|
||||||
|
|
||||||
|
try req.delete(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all SKUs for a given application.
|
||||||
|
pub fn fetchSkus(self: *Self, application_id: Snowflake) RequestFailedError!zjson.Owner([]Types.Sku) {
|
||||||
|
var buf: [256]u8 = undefined;
|
||||||
|
const path = try std.fmt.bufPrint(&buf, "/applications/{d}/skus", .{application_id.into()});
|
||||||
|
|
||||||
|
var req = FetchReq.init(self.allocator, self.details.token);
|
||||||
|
defer req.deinit();
|
||||||
|
|
||||||
|
const skus = try req.get([]Types.Sku, path);
|
||||||
|
return skus;
|
||||||
|
}
|
||||||
|
@ -107,3 +107,57 @@ pub const InstallParams = struct {
|
|||||||
/// Permissions to request for the bot role
|
/// Permissions to request for the bot role
|
||||||
permissions: []const u8,
|
permissions: []const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const ModifyApplication = struct {
|
||||||
|
/// Default custom authorization URL for the app, if enabled
|
||||||
|
custom_install_url: ?[]const u8,
|
||||||
|
/// Description of the app
|
||||||
|
description: ?[]const u8,
|
||||||
|
/// Role connection verification URL for the app
|
||||||
|
role_connections_verification_url: ?[]const u8,
|
||||||
|
/// Settings for the app's default in-app authorization link, if enabled
|
||||||
|
install_params: ?InstallParams,
|
||||||
|
/// Default scopes and permissions for each supported installation context.
|
||||||
|
integration_types_config: ?ApplicationIntegrationType,
|
||||||
|
/// App's public flags
|
||||||
|
/// @remarks
|
||||||
|
/// Only limited intent flags (`GATEWAY_PRESENCE_LIMITED`, `GATEWAY_GUILD_MEMBERS_LIMITED`, and `GATEWAY_MESSAGE_CONTENT_LIMITED`) can be updated via the API.
|
||||||
|
flags: ?ApplicationFlags,
|
||||||
|
/// Icon for the app
|
||||||
|
icon: ?[]const u8,
|
||||||
|
/// Default rich presence invite cover image for the app
|
||||||
|
cover_image: ?[]const u8,
|
||||||
|
/// Interactions endpoint URL for the app
|
||||||
|
/// @remarks
|
||||||
|
/// To update an Interactions endpoint URL via the API, the URL must be valid
|
||||||
|
interaction_endpoint_url: ?[]const u8,
|
||||||
|
/// List of tags describing the content and functionality of the app (max of 20 characters per tag)
|
||||||
|
/// @remarks
|
||||||
|
/// There can only be a max of 5 tags
|
||||||
|
tags: ?[][]const u8,
|
||||||
|
/// Event webhook URL for the app to receive webhook events
|
||||||
|
event_webhooks_url: ?[]const u8,
|
||||||
|
/// If webhook events are enabled for the app. 1 to disable, and 2 to enable.
|
||||||
|
event_webhooks_status: ?ApplicationEventWebhookStatus,
|
||||||
|
/// List of Webhook event types the app subscribes to
|
||||||
|
event_webhooks_types: ?[]WebhookEventType,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ApplicationEventWebhookStatus = enum(u8) {
|
||||||
|
/// Webhook events are disabled by developer
|
||||||
|
Disabled = 1,
|
||||||
|
/// Webhook events are enabled by developer */
|
||||||
|
Enabled = 2,
|
||||||
|
/// Webhook events are disabled by Discord, usually due to inactivity */
|
||||||
|
DisabledByDiscord = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// https://discord.com/developers/docs/events/webhook-events#event-types
|
||||||
|
pub const WebhookEventType = union(enum) {
|
||||||
|
/// Sent when an app was authorized by a user to a server or their account
|
||||||
|
APPLICATION_AUTHORIZED,
|
||||||
|
/// Entitlement was created
|
||||||
|
ENTITLEMENT_CREATE,
|
||||||
|
/// User was added to a Quest (currently unavailable)
|
||||||
|
QUEST_USER_ENROLLMENT,
|
||||||
|
};
|
||||||
|
@ -126,7 +126,7 @@ pub const ActivityLocation = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// https://discord.com/developers/docs/resources/application#get-application-activity-instance-activity-location-kind-enum
|
/// https://discord.com/developers/docs/resources/application#get-application-activity-instance-activity-location-kind-enum
|
||||||
pub const ActivityLocationKind = enum {
|
pub const ActivityLocationKind = union(enum) {
|
||||||
/// The Location is a Guild Channel
|
/// The Location is a Guild Channel
|
||||||
gc,
|
gc,
|
||||||
/// The Location is a Private Channel, such as a DM or GDM
|
/// The Location is a Private Channel, such as a DM or GDM
|
||||||
|
@ -370,3 +370,14 @@ pub const AllowedMentions = struct {
|
|||||||
/// For replies, whether to mention the author of the message being replied to (default false)
|
/// For replies, whether to mention the author of the message being replied to (default false)
|
||||||
replied_user: ?bool,
|
replied_user: ?bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const GetMessagesQuery = struct {
|
||||||
|
/// Get messages around this message ID,
|
||||||
|
around: ?Snowflake,
|
||||||
|
/// Get messages before this message ID
|
||||||
|
before: ?Snowflake,
|
||||||
|
/// Get messages after this message ID
|
||||||
|
after: ?Snowflake,
|
||||||
|
/// Max number of messages to return (1-100),
|
||||||
|
limit: ?usize = 50,
|
||||||
|
};
|
||||||
|
@ -88,3 +88,15 @@ pub const SkuType = enum(u4) {
|
|||||||
/// System-generated group for each SUBSCRIPTION SKU created
|
/// System-generated group for each SUBSCRIPTION SKU created
|
||||||
SubscriptionGroup = 6,
|
SubscriptionGroup = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const CreateTestEntitlement = struct {
|
||||||
|
/// ID of the SKU to grant the entitlement to
|
||||||
|
sku_id: []const u8,
|
||||||
|
/// ID of the guild or user to grant the entitlement top
|
||||||
|
owner_id: []const u8,
|
||||||
|
/// 1 for a guild subscription, 2 for a user subscription
|
||||||
|
owner_type: enum(u8) {
|
||||||
|
guild_subscription = 1,
|
||||||
|
user_subscription = 2,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
6
vendor/zjson/json.zig
vendored
6
vendor/zjson/json.zig
vendored
@ -1101,12 +1101,12 @@ pub fn parseInto(comptime T: type, allocator: mem.Allocator, value: JsonType) Er
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// meant to handle a `JsonType` value and handling the deinitialization thereof
|
/// meant to handle a `JsonType` value and handling the deinitialization thereof
|
||||||
pub fn Owned(comptime Struct: type) type {
|
pub fn Owned(comptime T: type) type {
|
||||||
if (@typeInfo(Struct) != .@"struct") @compileError("expected a `struct` type");
|
// if (@typeInfo(Struct) != .@"struct") @compileError("expected a `struct` type");
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
arena: *std.heap.ArenaAllocator,
|
arena: *std.heap.ArenaAllocator,
|
||||||
value: Struct,
|
value: T,
|
||||||
|
|
||||||
pub fn deinit(self: @This()) void {
|
pub fn deinit(self: @This()) void {
|
||||||
const allocator = self.arena.child_allocator;
|
const allocator = self.arena.child_allocator;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user