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.
|
||||
* High Performance: Faster than whichever library you can name (WIP)
|
||||
* Flexible Payload Parsing: Supports payload parsing through both zlib and zstd*.
|
||||
* Language Agnostic: Primarily in Zig, but also compatible with JavaScript. (PERHAPS?)
|
||||
|
||||
```zig
|
||||
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
|
||||
| Endpoint | Support |
|
||||
|----------------------------------------|---------|
|
||||
| Application related | ❌ |
|
||||
| Audit log | ❌ |
|
||||
| Automod | ❌ |
|
||||
| Channel related | ✅ |
|
||||
| Emoji related | ✅ |
|
||||
| Entitlement related | ❌ |
|
||||
| Guild related | ✅ |
|
||||
| Guild Scheduled Event related | ❌ |
|
||||
| Guild template related | ❌ |
|
||||
| Invite related | ✅ |
|
||||
| Message related | ✅ |
|
||||
| Poll related | ✅ |
|
||||
| SKU related | ❌ |
|
||||
| Soundboard related | ❌ |
|
||||
| Stage Instance related | ❌ |
|
||||
| Sticker related | ❌ |
|
||||
| Subscription related | ❌ |
|
||||
| User related | ✅ |
|
||||
| Voice 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 });
|
||||
}
|
||||
|
||||
pub fn addQueryParam(self: *FetchReq, name: []const u8, value: []const u8) !void {
|
||||
try self.query_params.put(name, value);
|
||||
pub fn addQueryParam(self: *FetchReq, name: []const u8, value: anytype) !void {
|
||||
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 {
|
||||
@ -171,6 +174,15 @@ pub const FetchReq = struct {
|
||||
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) {
|
||||
var buf: [4096]u8 = undefined;
|
||||
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 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.
|
||||
/// TODO: add query params
|
||||
pub fn fetchMessages(self: *Self, channel_id: Snowflake) RequestFailedError!zjson.Owned([]Types.Message) {
|
||||
pub fn fetchMessages(self: *Self, channel_id: Snowflake, query: Types.GetMessagesQuery) 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();
|
||||
|
||||
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);
|
||||
return messages;
|
||||
}
|
||||
@ -2423,7 +2427,8 @@ pub fn fetchAnswerVoters(
|
||||
/// Immediately ends the poll.
|
||||
/// 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(
|
||||
self: *Self,
|
||||
channel_id: Snowflake,
|
||||
@ -2438,3 +2443,141 @@ pub fn endPoll(
|
||||
const msg = try req.post(Types.Message, path);
|
||||
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: []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
|
||||
pub const ActivityLocationKind = enum {
|
||||
pub const ActivityLocationKind = union(enum) {
|
||||
/// The Location is a Guild Channel
|
||||
gc,
|
||||
/// 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)
|
||||
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
|
||||
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
|
||||
pub fn Owned(comptime Struct: type) type {
|
||||
if (@typeInfo(Struct) != .@"struct") @compileError("expected a `struct` type");
|
||||
pub fn Owned(comptime T: type) type {
|
||||
// if (@typeInfo(Struct) != .@"struct") @compileError("expected a `struct` type");
|
||||
|
||||
return struct {
|
||||
arena: *std.heap.ArenaAllocator,
|
||||
value: Struct,
|
||||
value: T,
|
||||
|
||||
pub fn deinit(self: @This()) void {
|
||||
const allocator = self.arena.child_allocator;
|
||||
|
Loading…
x
Reference in New Issue
Block a user