forked from yuzucchii/discord.zig
breaking changes
This commit is contained in:
parent
b8c42bb22c
commit
32d9688234
@ -17,7 +17,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
const zlib = b.dependency("zlib", .{});
|
const zlib = b.dependency("zlib", .{});
|
||||||
|
|
||||||
const dzig = b.addModule("discord.zig", .{
|
const dzig = b.addModule("discord.zig", .{
|
||||||
.root_source_file = b.path("src/lib.zig"),
|
.root_source_file = b.path("src/root.zig"),
|
||||||
.link_libc = true,
|
.link_libc = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
// This is a [Semantic Version](https://semver.org/).
|
// This is a [Semantic Version](https://semver.org/).
|
||||||
// In a future version of Zig it will be used for package deduplication.
|
// In a future version of Zig it will be used for package deduplication.
|
||||||
.version = "0.0.0",
|
.version = "1.0.0",
|
||||||
|
|
||||||
// This field is optional.
|
// This field is optional.
|
||||||
// This is currently advisory only; Zig does not yet do anything
|
// This is currently advisory only; Zig does not yet do anything
|
||||||
@ -25,8 +25,8 @@
|
|||||||
// internet connectivity.
|
// internet connectivity.
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.zlib = .{
|
.zlib = .{
|
||||||
.url = "https://github.com/yuzudev/zig-zlib/archive/refs/heads/main.zip",
|
.url = "https://git.yuzucchii.xyz/yuzucchii/zlib/archive/master.tar.gz",
|
||||||
.hash = "zlib-0.1.0-AAAAAKm6QADNBB6NBPHanW9G0EOPTmgJsRO6NFT__arp",
|
.hash = "zlib-0.1.0-AAAAALW6QABbti7dQfKuK0IQb-xdcp3SI8zdTvs5ouUD",
|
||||||
},
|
},
|
||||||
.websocket = .{ .url = "https://github.com/karlseguin/websocket.zig/archive/refs/heads/master.zip", .hash = "websocket-0.1.0-ZPISdYBIAwB1yO6AFDHRHLaZSmpdh4Bz4dCmaQUqNNWh" },
|
.websocket = .{ .url = "https://github.com/karlseguin/websocket.zig/archive/refs/heads/master.zip", .hash = "websocket-0.1.0-ZPISdYBIAwB1yO6AFDHRHLaZSmpdh4Bz4dCmaQUqNNWh" },
|
||||||
},
|
},
|
||||||
|
2071
src/http/api.zig
2071
src/http/api.zig
File diff suppressed because it is too large
Load Diff
@ -310,7 +310,7 @@ pub const CacheLike = @import("cache/cache.zig").CacheLike;
|
|||||||
pub const DefaultCache = @import("cache/cache.zig").DefaultCache;
|
pub const DefaultCache = @import("cache/cache.zig").DefaultCache;
|
||||||
|
|
||||||
pub const Permissions = @import("utils/permissions.zig").Permissions;
|
pub const Permissions = @import("utils/permissions.zig").Permissions;
|
||||||
pub const Shard = @import("shard/shard.zig").Shard;
|
pub const Shard = @import("shard/shard.zig");
|
||||||
pub const zjson = @compileError("Deprecated.");
|
pub const zjson = @compileError("Deprecated.");
|
||||||
|
|
||||||
pub const Internal = @import("utils/core.zig");
|
pub const Internal = @import("utils/core.zig");
|
||||||
@ -319,12 +319,13 @@ const GatewayBotInfo = @import("shard/util.zig").GatewayBotInfo;
|
|||||||
const Log = Internal.Log;
|
const Log = Internal.Log;
|
||||||
|
|
||||||
// sharder
|
// sharder
|
||||||
pub const Sharder = @import("shard/sharder.zig").ShardManager;
|
pub const Sharder = @import("shard/sharder.zig");
|
||||||
|
|
||||||
pub const cache = @import("cache/cache.zig");
|
pub const cache = @import("cache/cache.zig");
|
||||||
|
|
||||||
pub const FetchReq = @import("http/http.zig").FetchReq;
|
pub const FetchReq = @import("http/http.zig").FetchReq;
|
||||||
pub const FileData = @import("http/http.zig").FileData;
|
pub const FileData = @import("http/http.zig").FileData;
|
||||||
|
pub const API = @import("http/api.zig");
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
@ -336,14 +337,20 @@ pub fn CustomisedSession(comptime Table: cache.TableTemplate) type {
|
|||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
allocator: mem.Allocator,
|
allocator: mem.Allocator,
|
||||||
sharder: Sharder(Table),
|
sharder: Sharder,
|
||||||
token: []const u8,
|
authorization: []const u8,
|
||||||
|
cache: cache.CacheTables(Table),
|
||||||
|
|
||||||
|
// there is only 1 api, therefore we don't need pointers
|
||||||
|
api: API,
|
||||||
|
|
||||||
pub fn init(allocator: mem.Allocator) Self {
|
pub fn init(allocator: mem.Allocator) Self {
|
||||||
return .{
|
return .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.sharder = undefined,
|
.sharder = undefined,
|
||||||
.token = undefined,
|
.authorization = undefined,
|
||||||
|
.api = undefined,
|
||||||
|
.cache = .defaults(allocator),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,7 +359,7 @@ pub fn CustomisedSession(comptime Table: cache.TableTemplate) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(self: *Self, settings: struct {
|
pub fn start(self: *Self, settings: struct {
|
||||||
token: []const u8,
|
authorization: []const u8,
|
||||||
intents: Intents,
|
intents: Intents,
|
||||||
options: struct {
|
options: struct {
|
||||||
spawn_shard_delay: u64 = 5300,
|
spawn_shard_delay: u64 = 5300,
|
||||||
@ -362,17 +369,20 @@ pub fn CustomisedSession(comptime Table: cache.TableTemplate) type {
|
|||||||
},
|
},
|
||||||
run: GatewayDispatchEvent,
|
run: GatewayDispatchEvent,
|
||||||
log: Log,
|
log: Log,
|
||||||
cache: cache.TableTemplate,
|
cache: ?cache.CacheTables(Table),
|
||||||
}) !void {
|
}) !void {
|
||||||
if (!std.mem.startsWith(u8, settings.token, "Bot")) {
|
if (!std.mem.startsWith(u8, settings.authorization, "Bot")) {
|
||||||
var buffer = [_]u8{undefined} ** 128;
|
var buffer = [_]u8{undefined} ** 128;
|
||||||
const printed = try std.fmt.bufPrint(&buffer, "Bot {s}", .{settings.token});
|
const printed = try std.fmt.bufPrint(&buffer, "Bot {s}", .{settings.authorization});
|
||||||
self.token = printed;
|
self.authorization = printed;
|
||||||
} else {
|
} else {
|
||||||
self.token = settings.token;
|
self.authorization = settings.authorization;
|
||||||
}
|
}
|
||||||
|
|
||||||
var req = FetchReq.init(self.allocator, self.token);
|
self.api = API.init(self.allocator, self.authorization);
|
||||||
|
self.cache = settings.cache orelse .defaults(self.allocator);
|
||||||
|
|
||||||
|
var req = FetchReq.init(self.allocator, self.authorization);
|
||||||
defer req.deinit();
|
defer req.deinit();
|
||||||
|
|
||||||
const res = try req.makeRequest(.GET, "/gateway/bot", null);
|
const res = try req.makeRequest(.GET, "/gateway/bot", null);
|
||||||
@ -387,11 +397,11 @@ pub fn CustomisedSession(comptime Table: cache.TableTemplate) type {
|
|||||||
const parsed = try json.parseFromSlice(GatewayBotInfo, self.allocator, body, .{});
|
const parsed = try json.parseFromSlice(GatewayBotInfo, self.allocator, body, .{});
|
||||||
defer parsed.deinit();
|
defer parsed.deinit();
|
||||||
|
|
||||||
self.sharder = try Sharder(Table).init(self.allocator, .{
|
self.sharder = try Sharder.init(self.allocator, .{
|
||||||
.token = self.token,
|
.authorization = self.authorization,
|
||||||
.intents = settings.intents,
|
.intents = settings.intents,
|
||||||
.run = settings.run,
|
.run = settings.run,
|
||||||
.options = Sharder(Table).SessionOptions{
|
.options = Sharder.SessionOptions{
|
||||||
.info = parsed.value,
|
.info = parsed.value,
|
||||||
.shard_start = settings.options.shard_start,
|
.shard_start = settings.options.shard_start,
|
||||||
.shard_end = @intCast(parsed.value.shards),
|
.shard_end = @intCast(parsed.value.shards),
|
||||||
@ -399,7 +409,6 @@ pub fn CustomisedSession(comptime Table: cache.TableTemplate) type {
|
|||||||
.spawn_shard_delay = settings.options.spawn_shard_delay,
|
.spawn_shard_delay = settings.options.spawn_shard_delay,
|
||||||
},
|
},
|
||||||
.log = settings.log,
|
.log = settings.log,
|
||||||
.cache = settings.cache,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
try self.sharder.spawnShards();
|
try self.sharder.spawnShards();
|
||||||
@ -423,7 +432,7 @@ pub const GatewayIntents = @import("./shard/intents.zig").GatewayIntents;
|
|||||||
pub const Intents = @import("./shard/intents.zig").Intents;
|
pub const Intents = @import("./shard/intents.zig").Intents;
|
||||||
|
|
||||||
pub fn start(self: *Session, settings: struct {
|
pub fn start(self: *Session, settings: struct {
|
||||||
token: []const u8,
|
authorization: []const u8,
|
||||||
intents: Intents,
|
intents: Intents,
|
||||||
options: struct {
|
options: struct {
|
||||||
spawn_shard_delay: u64 = 5300,
|
spawn_shard_delay: u64 = 5300,
|
||||||
@ -433,7 +442,7 @@ pub fn start(self: *Session, settings: struct {
|
|||||||
},
|
},
|
||||||
run: GatewayDispatchEvent,
|
run: GatewayDispatchEvent,
|
||||||
log: Log,
|
log: Log,
|
||||||
cache: cache.TableTemplate,
|
cache: cache.CacheTables(DefaultTable),
|
||||||
}) !void {
|
}) !void {
|
||||||
return self.start(settings);
|
return self.start(settings);
|
||||||
}
|
}
|
3578
src/shard/shard.zig
3578
src/shard/shard.zig
File diff suppressed because it is too large
Load Diff
@ -23,240 +23,226 @@ const ShardDetails = @import("util.zig").ShardDetails;
|
|||||||
const ConnectQueue = @import("connect_queue.zig").ConnectQueue;
|
const ConnectQueue = @import("connect_queue.zig").ConnectQueue;
|
||||||
const GatewayDispatchEvent = @import("../utils/core.zig").GatewayDispatchEvent;
|
const GatewayDispatchEvent = @import("../utils/core.zig").GatewayDispatchEvent;
|
||||||
const Log = @import("../utils/core.zig").Log;
|
const Log = @import("../utils/core.zig").Log;
|
||||||
const Shard = @import("shard.zig").Shard;
|
const Shard = @import("shard.zig");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const debug = @import("../utils/core.zig").debug;
|
const debug = @import("../utils/core.zig").debug;
|
||||||
const TableTemplate = @import("../cache/cache.zig").TableTemplate;
|
|
||||||
const CacheTables = @import("../cache/cache.zig").CacheTables;
|
|
||||||
|
|
||||||
pub fn ShardManager(comptime Table: TableTemplate) type {
|
const Self = @This();
|
||||||
return struct {
|
|
||||||
const Self = @This();
|
|
||||||
|
|
||||||
shard_details: ShardDetails,
|
shard_details: ShardDetails,
|
||||||
allocator: mem.Allocator,
|
allocator: mem.Allocator,
|
||||||
|
|
||||||
/// Queue for managing shard connections
|
/// Queue for managing shard connections
|
||||||
connect_queue: ConnectQueue(Shard(Table)),
|
connect_queue: ConnectQueue(Shard),
|
||||||
shards: std.AutoArrayHashMap(usize, Shard(Table)),
|
shards: std.AutoArrayHashMap(usize, Shard),
|
||||||
handler: GatewayDispatchEvent,
|
handler: GatewayDispatchEvent,
|
||||||
|
|
||||||
/// where we dispatch work for every thread, threads must be spawned upon shard creation
|
/// where we dispatch work for every thread, threads must be spawned upon shard creation
|
||||||
/// make sure the address of workers is stable
|
/// make sure the address of workers is stable
|
||||||
workers: std.Thread.Pool = undefined,
|
workers: std.Thread.Pool = undefined,
|
||||||
|
|
||||||
/// configuration settings
|
/// configuration settings
|
||||||
options: SessionOptions,
|
options: SessionOptions,
|
||||||
log: Log,
|
log: Log,
|
||||||
|
|
||||||
// must be initialised
|
pub const ShardData = struct {
|
||||||
cache: *CacheTables(Table),
|
/// resume seq to resume connections
|
||||||
|
resume_seq: ?usize,
|
||||||
|
|
||||||
pub const ShardData = struct {
|
/// resume_gateway_url is the url to resume the connection
|
||||||
/// resume seq to resume connections
|
/// https://discord.com/developers/docs/topics/gateway#ready-event
|
||||||
resume_seq: ?usize,
|
resume_gateway_url: ?[]const u8,
|
||||||
|
|
||||||
/// resume_gateway_url is the url to resume the connection
|
/// session_id is the unique session id of the gateway
|
||||||
/// https://discord.com/developers/docs/topics/gateway#ready-event
|
session_id: ?[]const u8,
|
||||||
resume_gateway_url: ?[]const u8,
|
};
|
||||||
|
|
||||||
/// session_id is the unique session id of the gateway
|
pub const SessionOptions = struct {
|
||||||
session_id: ?[]const u8,
|
/// Important data which is used by the manager to connect shards to the gateway. */
|
||||||
};
|
info: GatewayBotInfo,
|
||||||
|
/// Delay in milliseconds to wait before spawning next shard. OPTIMAL IS ABOVE 5100. YOU DON'T WANT TO HIT THE RATE LIMIT!!!
|
||||||
|
spawn_shard_delay: ?u64 = 5300,
|
||||||
|
/// Total amount of shards your bot uses. Useful for zero-downtime updates or resharding.
|
||||||
|
total_shards: usize = 1,
|
||||||
|
shard_start: usize = 0,
|
||||||
|
shard_end: usize = 1,
|
||||||
|
/// The payload handlers for messages on the shard.
|
||||||
|
resharding: ?struct { interval: u64, percentage: usize } = null,
|
||||||
|
/// worker threads
|
||||||
|
workers_per_shard: usize = 1,
|
||||||
|
/// The shard lifespan in milliseconds. If a shard is not connected within this time, it will be closed.
|
||||||
|
shard_lifespan: ?u64 = null,
|
||||||
|
};
|
||||||
|
|
||||||
pub const SessionOptions = struct {
|
pub fn init(allocator: mem.Allocator, settings: struct {
|
||||||
/// Important data which is used by the manager to connect shards to the gateway. */
|
authorization: []const u8,
|
||||||
info: GatewayBotInfo,
|
intents: Intents,
|
||||||
/// Delay in milliseconds to wait before spawning next shard. OPTIMAL IS ABOVE 5100. YOU DON'T WANT TO HIT THE RATE LIMIT!!!
|
options: SessionOptions,
|
||||||
spawn_shard_delay: ?u64 = 5300,
|
run: GatewayDispatchEvent,
|
||||||
/// Total amount of shards your bot uses. Useful for zero-downtime updates or resharding.
|
log: Log,
|
||||||
total_shards: usize = 1,
|
}) mem.Allocator.Error!Self {
|
||||||
shard_start: usize = 0,
|
const concurrency = settings.options.info.session_start_limit.?.max_concurrency;
|
||||||
shard_end: usize = 1,
|
|
||||||
/// The payload handlers for messages on the shard.
|
|
||||||
resharding: ?struct { interval: u64, percentage: usize } = null,
|
|
||||||
/// worker threads
|
|
||||||
workers_per_shard: usize = 1,
|
|
||||||
/// The shard lifespan in milliseconds. If a shard is not connected within this time, it will be closed.
|
|
||||||
shard_lifespan: ?u64 = null,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn init(allocator: mem.Allocator, settings: struct {
|
return .{
|
||||||
token: []const u8,
|
.allocator = allocator,
|
||||||
intents: Intents,
|
.connect_queue = try ConnectQueue(Shard).init(allocator, concurrency, 5000),
|
||||||
options: SessionOptions,
|
.shards = .init(allocator),
|
||||||
run: GatewayDispatchEvent,
|
.workers = undefined,
|
||||||
log: Log,
|
.shard_details = ShardDetails{
|
||||||
cache: TableTemplate,
|
.token = settings.authorization,
|
||||||
}) mem.Allocator.Error!Self {
|
.intents = settings.intents,
|
||||||
const concurrency = settings.options.info.session_start_limit.?.max_concurrency;
|
},
|
||||||
const cache = try allocator.create(CacheTables(Table));
|
.handler = settings.run,
|
||||||
cache.* = CacheTables(Table).defaults(allocator);
|
.options = .{
|
||||||
|
.info = .{
|
||||||
|
.url = settings.options.info.url,
|
||||||
|
.shards = settings.options.info.shards,
|
||||||
|
.session_start_limit = settings.options.info.session_start_limit,
|
||||||
|
},
|
||||||
|
.total_shards = settings.options.total_shards,
|
||||||
|
.shard_start = settings.options.shard_start,
|
||||||
|
.shard_end = settings.options.shard_end,
|
||||||
|
.workers_per_shard = settings.options.workers_per_shard,
|
||||||
|
},
|
||||||
|
.log = settings.log,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return .{
|
pub fn deinit(self: *Self) void {
|
||||||
.allocator = allocator,
|
self.connect_queue.deinit();
|
||||||
.connect_queue = try ConnectQueue(Shard(Table)).init(allocator, concurrency, 5000),
|
self.shards.deinit();
|
||||||
.shards = .init(allocator),
|
}
|
||||||
.workers = undefined,
|
|
||||||
.shard_details = ShardDetails{
|
pub fn forceIdentify(self: *Self, shard_id: usize) !void {
|
||||||
.token = settings.token,
|
self.logif("#{d} force identify", .{shard_id});
|
||||||
.intents = settings.intents,
|
const shard = try self.create(shard_id);
|
||||||
},
|
|
||||||
.handler = settings.run,
|
return shard.identify(null);
|
||||||
.options = .{
|
}
|
||||||
.info = .{
|
|
||||||
.url = settings.options.info.url,
|
pub fn disconnect(self: *Self, shard_id: usize) Shard.CloseError!void {
|
||||||
.shards = settings.options.info.shards,
|
return if (self.shards.get(shard_id)) |shard| shard.disconnect();
|
||||||
.session_start_limit = settings.options.info.session_start_limit,
|
}
|
||||||
},
|
|
||||||
.total_shards = settings.options.total_shards,
|
pub fn disconnectAll(self: *Self) Shard.CloseError!void {
|
||||||
.shard_start = settings.options.shard_start,
|
while (self.shards.iterator().next()) |shard| shard.value_ptr.disconnect();
|
||||||
.shard_end = settings.options.shard_end,
|
}
|
||||||
.workers_per_shard = settings.options.workers_per_shard,
|
|
||||||
},
|
/// spawn buckets in order
|
||||||
.log = settings.log,
|
/// Log bucket preparation
|
||||||
.cache = cache,
|
/// Divide shards into chunks based on concurrency
|
||||||
};
|
/// Assign each shard to a bucket
|
||||||
|
/// Return list of buckets
|
||||||
|
/// https://discord.com/developers/docs/events/gateway#sharding-max-concurrency
|
||||||
|
fn spawnBuckets(self: *Self) ![][]Shard {
|
||||||
|
const concurrency = self.options.info.session_start_limit.?.max_concurrency;
|
||||||
|
|
||||||
|
self.logif("{d}-{d}", .{ self.options.shard_start, self.options.shard_end });
|
||||||
|
|
||||||
|
const range = std.math.sub(usize, self.options.shard_start, self.options.shard_end) catch 1;
|
||||||
|
const bucket_count = (range + concurrency - 1) / concurrency;
|
||||||
|
|
||||||
|
self.logif("#0 preparing buckets", .{});
|
||||||
|
|
||||||
|
const buckets = try self.allocator.alloc([]Shard, bucket_count);
|
||||||
|
|
||||||
|
for (buckets, 0..) |*bucket, i| {
|
||||||
|
const bucket_size = if ((i + 1) * concurrency > range) range - (i * concurrency) else concurrency;
|
||||||
|
|
||||||
|
bucket.* = try self.allocator.alloc(Shard, bucket_size);
|
||||||
|
|
||||||
|
for (bucket.*, 0..) |*shard, j| {
|
||||||
|
shard.* = try self.create(self.options.shard_start + i * concurrency + j);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
self.logif("{d} buckets created", .{bucket_count});
|
||||||
self.connect_queue.deinit();
|
|
||||||
self.shards.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn forceIdentify(self: *Self, shard_id: usize) !void {
|
// finally defihne threads
|
||||||
self.logif("#{d} force identify", .{shard_id});
|
|
||||||
const shard = try self.create(shard_id);
|
|
||||||
|
|
||||||
return shard.identify(null);
|
try self.workers.init(.{
|
||||||
}
|
.allocator = self.allocator,
|
||||||
|
.n_jobs = self.options.workers_per_shard * self.options.total_shards,
|
||||||
|
});
|
||||||
|
|
||||||
pub fn disconnect(self: *Self, shard_id: usize) Shard(Table).CloseError!void {
|
return buckets;
|
||||||
return if (self.shards.get(shard_id)) |shard| shard.disconnect();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn disconnectAll(self: *Self) Shard(Table).CloseError!void {
|
/// creates a shard and stores it
|
||||||
while (self.shards.iterator().next()) |shard| shard.value_ptr.disconnect();
|
fn create(self: *Self, shard_id: usize) !Shard {
|
||||||
}
|
if (self.shards.get(shard_id)) |s| return s;
|
||||||
|
|
||||||
/// spawn buckets in order
|
const shard: Shard = try .init(self.allocator, shard_id, self.options.total_shards, .{
|
||||||
/// Log bucket preparation
|
.token = self.shard_details.token,
|
||||||
/// Divide shards into chunks based on concurrency
|
.intents = self.shard_details.intents,
|
||||||
/// Assign each shard to a bucket
|
.options = Shard.ShardOptions{
|
||||||
/// Return list of buckets
|
.info = self.options.info,
|
||||||
/// https://discord.com/developers/docs/events/gateway#sharding-max-concurrency
|
.ratelimit_options = .{},
|
||||||
fn spawnBuckets(self: *Self) ![][]Shard(Table) {
|
},
|
||||||
const concurrency = self.options.info.session_start_limit.?.max_concurrency;
|
.run = self.handler,
|
||||||
|
.log = self.log,
|
||||||
|
.sharder_pool = &self.workers,
|
||||||
|
});
|
||||||
|
|
||||||
self.logif("{d}-{d}", .{ self.options.shard_start, self.options.shard_end });
|
try self.shards.put(shard_id, shard);
|
||||||
|
|
||||||
const range = std.math.sub(usize, self.options.shard_start, self.options.shard_end) catch 1;
|
return shard;
|
||||||
const bucket_count = (range + concurrency - 1) / concurrency;
|
}
|
||||||
|
|
||||||
self.logif("#0 preparing buckets", .{});
|
pub fn resume_(self: *Self, shard_id: usize, shard_data: ShardData) void {
|
||||||
|
if (self.shards.contains(shard_id)) return error.CannotOverrideExistingShard;
|
||||||
|
|
||||||
const buckets = try self.allocator.alloc([]Shard(Table), bucket_count);
|
const shard = self.create(shard_id);
|
||||||
|
|
||||||
for (buckets, 0..) |*bucket, i| {
|
shard.data = shard_data;
|
||||||
const bucket_size = if ((i + 1) * concurrency > range) range - (i * concurrency) else concurrency;
|
|
||||||
|
|
||||||
bucket.* = try self.allocator.alloc(Shard(Table), bucket_size);
|
return self.connect_queue.push(.{
|
||||||
|
.shard = shard,
|
||||||
|
.callback = &callback,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
for (bucket.*, 0..) |*shard, j| {
|
fn callback(self: *ConnectQueue(Shard).RequestWithShard) anyerror!void {
|
||||||
shard.* = try self.create(self.options.shard_start + i * concurrency + j);
|
try self.shard.connect();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.logif("{d} buckets created", .{bucket_count});
|
pub fn spawnShards(self: *Self) !void {
|
||||||
|
const buckets = try self.spawnBuckets();
|
||||||
|
|
||||||
// finally defihne threads
|
self.logif("Spawning shards", .{});
|
||||||
|
|
||||||
try self.workers.init(.{
|
for (buckets) |bucket| {
|
||||||
.allocator = self.allocator,
|
for (bucket) |shard| {
|
||||||
.n_jobs = self.options.workers_per_shard * self.options.total_shards,
|
self.logif("adding {d} to connect queue", .{shard.id});
|
||||||
});
|
try self.connect_queue.push(.{
|
||||||
|
|
||||||
return buckets;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// creates a shard and stores it
|
|
||||||
fn create(self: *Self, shard_id: usize) !Shard(Table) {
|
|
||||||
if (self.shards.get(shard_id)) |s| return s;
|
|
||||||
|
|
||||||
const shard: Shard(Table) = try .init(self.allocator, shard_id, self.options.total_shards, .{
|
|
||||||
.token = self.shard_details.token,
|
|
||||||
.intents = self.shard_details.intents,
|
|
||||||
.options = Shard(Table).ShardOptions{
|
|
||||||
.info = self.options.info,
|
|
||||||
.ratelimit_options = .{},
|
|
||||||
},
|
|
||||||
.run = self.handler,
|
|
||||||
.log = self.log,
|
|
||||||
.cache = self.cache,
|
|
||||||
.sharder_pool = &self.workers,
|
|
||||||
});
|
|
||||||
|
|
||||||
try self.shards.put(shard_id, shard);
|
|
||||||
|
|
||||||
return shard;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resume_(self: *Self, shard_id: usize, shard_data: ShardData) void {
|
|
||||||
if (self.shards.contains(shard_id)) return error.CannotOverrideExistingShard;
|
|
||||||
|
|
||||||
const shard = self.create(shard_id);
|
|
||||||
|
|
||||||
shard.data = shard_data;
|
|
||||||
|
|
||||||
return self.connect_queue.push(.{
|
|
||||||
.shard = shard,
|
.shard = shard,
|
||||||
.callback = &callback,
|
.callback = &callback,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn callback(self: *ConnectQueue(Shard(Table)).RequestWithShard) anyerror!void {
|
//self.startResharder();
|
||||||
try self.shard.connect();
|
}
|
||||||
}
|
|
||||||
|
pub fn send(self: *Self, shard_id: usize, data: anytype) Shard.SendError!void {
|
||||||
pub fn spawnShards(self: *Self) !void {
|
if (self.shards.get(shard_id)) |shard| try shard.send(data);
|
||||||
const buckets = try self.spawnBuckets();
|
}
|
||||||
|
|
||||||
self.logif("Spawning shards", .{});
|
// SPEC OF THE RESHARDER:
|
||||||
|
// Class Self
|
||||||
for (buckets) |bucket| {
|
//
|
||||||
for (bucket) |shard| {
|
// Method startResharder():
|
||||||
self.logif("adding {d} to connect queue", .{shard.id});
|
// If resharding interval is not set or shard bounds are not valid:
|
||||||
try self.connect_queue.push(.{
|
// Exit
|
||||||
.shard = shard,
|
// Set up periodic check for resharding:
|
||||||
.callback = &callback,
|
// If new shards are required:
|
||||||
});
|
// Log resharding process
|
||||||
}
|
// Update options with new shard settings
|
||||||
}
|
// Disconnect old shards and clear them from manager
|
||||||
|
// Spawn shards again with updated configuration
|
||||||
//self.startResharder();
|
//
|
||||||
}
|
|
||||||
|
inline fn logif(self: *Self, comptime format: []const u8, args: anytype) void {
|
||||||
pub fn send(self: *Self, shard_id: usize, data: anytype) Shard(Table).SendError!void {
|
internalLogif(self.log, format, args);
|
||||||
if (self.shards.get(shard_id)) |shard| try shard.send(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SPEC OF THE RESHARDER:
|
|
||||||
// Class Self
|
|
||||||
//
|
|
||||||
// Method startResharder():
|
|
||||||
// If resharding interval is not set or shard bounds are not valid:
|
|
||||||
// Exit
|
|
||||||
// Set up periodic check for resharding:
|
|
||||||
// If new shards are required:
|
|
||||||
// Log resharding process
|
|
||||||
// Update options with new shard settings
|
|
||||||
// Disconnect old shards and clear them from manager
|
|
||||||
// Spawn shards again with updated configuration
|
|
||||||
//
|
|
||||||
|
|
||||||
inline fn logif(self: *Self, comptime format: []const u8, args: anytype) void {
|
|
||||||
internalLogif(self.log, format, args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ const Types = @import("../structures/types.zig");
|
|||||||
|
|
||||||
pub const debug = std.log.scoped(.@"discord.zig");
|
pub const debug = std.log.scoped(.@"discord.zig");
|
||||||
|
|
||||||
|
const Shard = @import("../shard/shard.zig");
|
||||||
pub const Log = union(enum) { yes, no };
|
pub const Log = union(enum) { yes, no };
|
||||||
|
|
||||||
pub inline fn logif(log: Log, comptime format: []const u8, args: anytype) void {
|
pub inline fn logif(log: Log, comptime format: []const u8, args: anytype) void {
|
||||||
@ -29,82 +30,82 @@ pub inline fn logif(log: Log, comptime format: []const u8, args: anytype) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const GatewayDispatchEvent = struct {
|
pub const GatewayDispatchEvent = struct {
|
||||||
application_command_permissions_update: ?*const fn (save: *anyopaque, application_command_permissions: Types.ApplicationCommandPermissions) anyerror!void = undefined,
|
application_command_permissions_update: ?*const fn (shard: *Shard, application_command_permissions: Types.ApplicationCommandPermissions) anyerror!void = undefined,
|
||||||
auto_moderation_rule_create: ?*const fn (save: *anyopaque, rule: Types.AutoModerationRule) anyerror!void = undefined,
|
auto_moderation_rule_create: ?*const fn (shard: *Shard, rule: Types.AutoModerationRule) anyerror!void = undefined,
|
||||||
auto_moderation_rule_update: ?*const fn (save: *anyopaque, rule: Types.AutoModerationRule) anyerror!void = undefined,
|
auto_moderation_rule_update: ?*const fn (shard: *Shard, rule: Types.AutoModerationRule) anyerror!void = undefined,
|
||||||
auto_moderation_rule_delete: ?*const fn (save: *anyopaque, rule: Types.AutoModerationRule) anyerror!void = undefined,
|
auto_moderation_rule_delete: ?*const fn (shard: *Shard, rule: Types.AutoModerationRule) anyerror!void = undefined,
|
||||||
auto_moderation_action_execution: ?*const fn (save: *anyopaque, action_execution: Types.AutoModerationActionExecution) anyerror!void = undefined,
|
auto_moderation_action_execution: ?*const fn (shard: *Shard, action_execution: Types.AutoModerationActionExecution) anyerror!void = undefined,
|
||||||
|
|
||||||
channel_create: ?*const fn (save: *anyopaque, chan: Types.Channel) anyerror!void = undefined,
|
channel_create: ?*const fn (shard: *Shard, chan: Types.Channel) anyerror!void = undefined,
|
||||||
channel_update: ?*const fn (save: *anyopaque, chan: Types.Channel) anyerror!void = undefined,
|
channel_update: ?*const fn (shard: *Shard, chan: Types.Channel) anyerror!void = undefined,
|
||||||
/// this isn't send when the channel is not relevant to you
|
/// this isn't send when the channel is not relevant to you
|
||||||
channel_delete: ?*const fn (save: *anyopaque, chan: Types.Channel) anyerror!void = undefined,
|
channel_delete: ?*const fn (shard: *Shard, chan: Types.Channel) anyerror!void = undefined,
|
||||||
channel_pins_update: ?*const fn (save: *anyopaque, chan_pins_update: Types.ChannelPinsUpdate) anyerror!void = undefined,
|
channel_pins_update: ?*const fn (shard: *Shard, chan_pins_update: Types.ChannelPinsUpdate) anyerror!void = undefined,
|
||||||
thread_create: ?*const fn (save: *anyopaque, thread: Types.Channel) anyerror!void = undefined,
|
thread_create: ?*const fn (shard: *Shard, thread: Types.Channel) anyerror!void = undefined,
|
||||||
thread_update: ?*const fn (save: *anyopaque, thread: Types.Channel) anyerror!void = undefined,
|
thread_update: ?*const fn (shard: *Shard, thread: Types.Channel) anyerror!void = undefined,
|
||||||
/// has `id`, `guild_id`, `parent_id`, and `type` fields.
|
/// has `id`, `guild_id`, `parent_id`, and `type` fields.
|
||||||
thread_delete: ?*const fn (save: *anyopaque, thread: Types.Partial(Types.Channel)) anyerror!void = undefined,
|
thread_delete: ?*const fn (shard: *Shard, thread: Types.Partial(Types.Channel)) anyerror!void = undefined,
|
||||||
thread_list_sync: ?*const fn (save: *anyopaque, data: Types.ThreadListSync) anyerror!void = undefined,
|
thread_list_sync: ?*const fn (shard: *Shard, data: Types.ThreadListSync) anyerror!void = undefined,
|
||||||
thread_member_update: ?*const fn (save: *anyopaque, guild_id: Types.ThreadMemberUpdate) anyerror!void = undefined,
|
thread_member_update: ?*const fn (shard: *Shard, guild_id: Types.ThreadMemberUpdate) anyerror!void = undefined,
|
||||||
thread_members_update: ?*const fn (save: *anyopaque, thread_data: Types.ThreadMembersUpdate) anyerror!void = undefined,
|
thread_members_update: ?*const fn (shard: *Shard, thread_data: Types.ThreadMembersUpdate) anyerror!void = undefined,
|
||||||
// TODO: implement // guild_audit_log_entry_create: null = null,
|
// TODO: implement // guild_audit_log_entry_create: null = null,
|
||||||
guild_create: ?*const fn (save: *anyopaque, guild: Types.Guild) anyerror!void = undefined,
|
guild_create: ?*const fn (shard: *Shard, guild: Types.Guild) anyerror!void = undefined,
|
||||||
guild_create_unavailable: ?*const fn (save: *anyopaque, guild: Types.UnavailableGuild) anyerror!void = undefined,
|
guild_create_unavailable: ?*const fn (shard: *Shard, guild: Types.UnavailableGuild) anyerror!void = undefined,
|
||||||
guild_update: ?*const fn (save: *anyopaque, guild: Types.Guild) anyerror!void = undefined,
|
guild_update: ?*const fn (shard: *Shard, guild: Types.Guild) anyerror!void = undefined,
|
||||||
/// this is not necessarily sent upon deletion of a guild
|
/// this is not necessarily sent upon deletion of a guild
|
||||||
/// but from when a user is *removed* therefrom
|
/// but from when a user is *removed* therefrom
|
||||||
guild_delete: ?*const fn (save: *anyopaque, guild: Types.UnavailableGuild) anyerror!void = undefined,
|
guild_delete: ?*const fn (shard: *Shard, guild: Types.UnavailableGuild) anyerror!void = undefined,
|
||||||
guild_ban_add: ?*const fn (save: *anyopaque, gba: Types.GuildBanAddRemove) anyerror!void = undefined,
|
guild_ban_add: ?*const fn (shard: *Shard, gba: Types.GuildBanAddRemove) anyerror!void = undefined,
|
||||||
guild_ban_remove: ?*const fn (save: *anyopaque, gbr: Types.GuildBanAddRemove) anyerror!void = undefined,
|
guild_ban_remove: ?*const fn (shard: *Shard, gbr: Types.GuildBanAddRemove) anyerror!void = undefined,
|
||||||
guild_emojis_update: ?*const fn (save: *anyopaque, fields: Types.GuildEmojisUpdate) anyerror!void = undefined,
|
guild_emojis_update: ?*const fn (shard: *Shard, fields: Types.GuildEmojisUpdate) anyerror!void = undefined,
|
||||||
guild_stickers_update: ?*const fn (save: *anyopaque, fields: Types.GuildStickersUpdate) anyerror!void = undefined,
|
guild_stickers_update: ?*const fn (shard: *Shard, fields: Types.GuildStickersUpdate) anyerror!void = undefined,
|
||||||
guild_integrations_update: ?*const fn (save: *anyopaque, fields: Types.GuildIntegrationsUpdate) anyerror!void = undefined,
|
guild_integrations_update: ?*const fn (shard: *Shard, fields: Types.GuildIntegrationsUpdate) anyerror!void = undefined,
|
||||||
guild_member_add: ?*const fn (save: *anyopaque, guild_id: Types.GuildMemberAdd) anyerror!void = undefined,
|
guild_member_add: ?*const fn (shard: *Shard, guild_id: Types.GuildMemberAdd) anyerror!void = undefined,
|
||||||
guild_member_update: ?*const fn (save: *anyopaque, fields: Types.GuildMemberUpdate) anyerror!void = undefined,
|
guild_member_update: ?*const fn (shard: *Shard, fields: Types.GuildMemberUpdate) anyerror!void = undefined,
|
||||||
guild_member_remove: ?*const fn (save: *anyopaque, user: Types.GuildMemberRemove) anyerror!void = undefined,
|
guild_member_remove: ?*const fn (shard: *Shard, user: Types.GuildMemberRemove) anyerror!void = undefined,
|
||||||
guild_members_chunk: ?*const fn (save: *anyopaque, data: Types.GuildMembersChunk) anyerror!void = undefined,
|
guild_members_chunk: ?*const fn (shard: *Shard, data: Types.GuildMembersChunk) anyerror!void = undefined,
|
||||||
guild_role_create: ?*const fn (save: *anyopaque, role: Types.GuildRoleCreate) anyerror!void = undefined,
|
guild_role_create: ?*const fn (shard: *Shard, role: Types.GuildRoleCreate) anyerror!void = undefined,
|
||||||
guild_role_delete: ?*const fn (save: *anyopaque, role: Types.GuildRoleDelete) anyerror!void = undefined,
|
guild_role_delete: ?*const fn (shard: *Shard, role: Types.GuildRoleDelete) anyerror!void = undefined,
|
||||||
guild_role_update: ?*const fn (save: *anyopaque, role: Types.GuildRoleUpdate) anyerror!void = undefined,
|
guild_role_update: ?*const fn (shard: *Shard, role: Types.GuildRoleUpdate) anyerror!void = undefined,
|
||||||
guild_scheduled_event_create: ?*const fn (save: *anyopaque, s_event: Types.ScheduledEvent) anyerror!void = undefined,
|
guild_scheduled_event_create: ?*const fn (shard: *Shard, s_event: Types.ScheduledEvent) anyerror!void = undefined,
|
||||||
guild_scheduled_event_update: ?*const fn (save: *anyopaque, s_event: Types.ScheduledEvent) anyerror!void = undefined,
|
guild_scheduled_event_update: ?*const fn (shard: *Shard, s_event: Types.ScheduledEvent) anyerror!void = undefined,
|
||||||
guild_scheduled_event_delete: ?*const fn (save: *anyopaque, s_event: Types.ScheduledEvent) anyerror!void = undefined,
|
guild_scheduled_event_delete: ?*const fn (shard: *Shard, s_event: Types.ScheduledEvent) anyerror!void = undefined,
|
||||||
guild_scheduled_event_user_add: ?*const fn (save: *anyopaque, data: Types.ScheduledEventUserAdd) anyerror!void = undefined,
|
guild_scheduled_event_user_add: ?*const fn (shard: *Shard, data: Types.ScheduledEventUserAdd) anyerror!void = undefined,
|
||||||
guild_scheduled_event_user_remove: ?*const fn (save: *anyopaque, data: Types.ScheduledEventUserRemove) anyerror!void = undefined,
|
guild_scheduled_event_user_remove: ?*const fn (shard: *Shard, data: Types.ScheduledEventUserRemove) anyerror!void = undefined,
|
||||||
integration_create: ?*const fn (save: *anyopaque, guild_id: Types.IntegrationCreateUpdate) anyerror!void = undefined,
|
integration_create: ?*const fn (shard: *Shard, guild_id: Types.IntegrationCreateUpdate) anyerror!void = undefined,
|
||||||
integration_update: ?*const fn (save: *anyopaque, guild_id: Types.IntegrationCreateUpdate) anyerror!void = undefined,
|
integration_update: ?*const fn (shard: *Shard, guild_id: Types.IntegrationCreateUpdate) anyerror!void = undefined,
|
||||||
integration_delete: ?*const fn (save: *anyopaque, guild_id: Types.IntegrationDelete) anyerror!void = undefined,
|
integration_delete: ?*const fn (shard: *Shard, guild_id: Types.IntegrationDelete) anyerror!void = undefined,
|
||||||
interaction_create: ?*const fn (save: *anyopaque, interaction: Types.MessageInteraction) anyerror!void = undefined,
|
interaction_create: ?*const fn (shard: *Shard, interaction: Types.MessageInteraction) anyerror!void = undefined,
|
||||||
invite_create: ?*const fn (save: *anyopaque, data: Types.InviteCreate) anyerror!void = undefined,
|
invite_create: ?*const fn (shard: *Shard, data: Types.InviteCreate) anyerror!void = undefined,
|
||||||
invite_delete: ?*const fn (save: *anyopaque, data: Types.InviteDelete) anyerror!void = undefined,
|
invite_delete: ?*const fn (shard: *Shard, data: Types.InviteDelete) anyerror!void = undefined,
|
||||||
message_create: ?*const fn (save: *anyopaque, message: Types.Message) anyerror!void = undefined,
|
message_create: ?*const fn (shard: *Shard, message: Types.Message) anyerror!void = undefined,
|
||||||
message_update: ?*const fn (save: *anyopaque, message: Types.Message) anyerror!void = undefined,
|
message_update: ?*const fn (shard: *Shard, message: Types.Message) anyerror!void = undefined,
|
||||||
message_delete: ?*const fn (save: *anyopaque, log: Types.MessageDelete) anyerror!void = undefined,
|
message_delete: ?*const fn (shard: *Shard, log: Types.MessageDelete) anyerror!void = undefined,
|
||||||
message_delete_bulk: ?*const fn (save: *anyopaque, log: Types.MessageDeleteBulk) anyerror!void = undefined,
|
message_delete_bulk: ?*const fn (shard: *Shard, log: Types.MessageDeleteBulk) anyerror!void = undefined,
|
||||||
message_reaction_add: ?*const fn (save: *anyopaque, log: Types.MessageReactionAdd) anyerror!void = undefined,
|
message_reaction_add: ?*const fn (shard: *Shard, log: Types.MessageReactionAdd) anyerror!void = undefined,
|
||||||
message_reaction_remove_all: ?*const fn (save: *anyopaque, data: Types.MessageReactionRemoveAll) anyerror!void = undefined,
|
message_reaction_remove_all: ?*const fn (shard: *Shard, data: Types.MessageReactionRemoveAll) anyerror!void = undefined,
|
||||||
message_reaction_remove: ?*const fn (save: *anyopaque, data: Types.MessageReactionRemove) anyerror!void = undefined,
|
message_reaction_remove: ?*const fn (shard: *Shard, data: Types.MessageReactionRemove) anyerror!void = undefined,
|
||||||
message_reaction_remove_emoji: ?*const fn (save: *anyopaque, data: Types.MessageReactionRemoveEmoji) anyerror!void = undefined,
|
message_reaction_remove_emoji: ?*const fn (shard: *Shard, data: Types.MessageReactionRemoveEmoji) anyerror!void = undefined,
|
||||||
presence_update: ?*const fn (save: *anyopaque, presence: Types.PresenceUpdate) anyerror!void = undefined,
|
presence_update: ?*const fn (shard: *Shard, presence: Types.PresenceUpdate) anyerror!void = undefined,
|
||||||
stage_instance_create: ?*const fn (save: *anyopaque, stage_instance: Types.StageInstance) anyerror!void = undefined,
|
stage_instance_create: ?*const fn (shard: *Shard, stage_instance: Types.StageInstance) anyerror!void = undefined,
|
||||||
stage_instance_update: ?*const fn (save: *anyopaque, stage_instance: Types.StageInstance) anyerror!void = undefined,
|
stage_instance_update: ?*const fn (shard: *Shard, stage_instance: Types.StageInstance) anyerror!void = undefined,
|
||||||
stage_instance_delete: ?*const fn (save: *anyopaque, stage_instance: Types.StageInstance) anyerror!void = undefined,
|
stage_instance_delete: ?*const fn (shard: *Shard, stage_instance: Types.StageInstance) anyerror!void = undefined,
|
||||||
typing_start: ?*const fn (save: *anyopaque, data: Types.TypingStart) anyerror!void = undefined,
|
typing_start: ?*const fn (shard: *Shard, data: Types.TypingStart) anyerror!void = undefined,
|
||||||
/// remember this is only sent when you change your profile yourself/your bot does
|
/// remember this is only sent when you change your profile yourself/your bot does
|
||||||
user_update: ?*const fn (save: *anyopaque, user: Types.User) anyerror!void = undefined,
|
user_update: ?*const fn (shard: *Shard, user: Types.User) anyerror!void = undefined,
|
||||||
// will do these someday, music is rather pointless at this point in time
|
// will do these someday, music is rather pointless at this point in time
|
||||||
// TODO: implement // voice_channel_effect_send: null = null,
|
// TODO: implement // voice_channel_effect_send: null = null,
|
||||||
// TODO: implement // voice_state_update: null = null,
|
// TODO: implement // voice_state_update: null = null,
|
||||||
// TODO: implement // voice_server_update: null = null,
|
// TODO: implement // voice_server_update: null = null,
|
||||||
webhooks_update: ?*const fn (save: *anyopaque, fields: Types.WebhookUpdate) anyerror!void = undefined,
|
webhooks_update: ?*const fn (shard: *Shard, fields: Types.WebhookUpdate) anyerror!void = undefined,
|
||||||
entitlement_create: ?*const fn (save: *anyopaque, entitlement: Types.Entitlement) anyerror!void = undefined,
|
entitlement_create: ?*const fn (shard: *Shard, entitlement: Types.Entitlement) anyerror!void = undefined,
|
||||||
entitlement_update: ?*const fn (save: *anyopaque, entitlement: Types.Entitlement) anyerror!void = undefined,
|
entitlement_update: ?*const fn (shard: *Shard, entitlement: Types.Entitlement) anyerror!void = undefined,
|
||||||
/// discord claims this is infrequent, therefore not throughoutly tested - Yuzu
|
/// discord claims this is infrequent, therefore not throughoutly tested - Yuzu
|
||||||
entitlement_delete: ?*const fn (save: *anyopaque, entitlement: Types.Entitlement) anyerror!void = undefined,
|
entitlement_delete: ?*const fn (shard: *Shard, entitlement: Types.Entitlement) anyerror!void = undefined,
|
||||||
message_poll_vote_add: ?*const fn (save: *anyopaque, poll: Types.PollVoteAdd) anyerror!void = undefined,
|
message_poll_vote_add: ?*const fn (shard: *Shard, poll: Types.PollVoteAdd) anyerror!void = undefined,
|
||||||
message_poll_vote_remove: ?*const fn (save: *anyopaque, poll: Types.PollVoteRemove) anyerror!void = undefined,
|
message_poll_vote_remove: ?*const fn (shard: *Shard, poll: Types.PollVoteRemove) anyerror!void = undefined,
|
||||||
|
|
||||||
ready: ?*const fn (save: *anyopaque, data: Types.Ready) anyerror!void = undefined,
|
ready: ?*const fn (shard: *Shard, data: Types.Ready) anyerror!void = undefined,
|
||||||
// TODO: implement // resumed: null = null,
|
// TODO: implement // resumed: null = null,
|
||||||
any: ?*const fn (save: *anyopaque, data: std.json.Value) anyerror!void = undefined,
|
any: ?*const fn (shard: *Shard, data: std.json.Value) anyerror!void = undefined,
|
||||||
};
|
};
|
||||||
|
@ -20,18 +20,17 @@ const Shard = Discord.Shard;
|
|||||||
const Intents = Discord.Intents;
|
const Intents = Discord.Intents;
|
||||||
|
|
||||||
const INTENTS = 53608447;
|
const INTENTS = 53608447;
|
||||||
const Cache = Discord.cache.TableTemplate{};
|
|
||||||
|
|
||||||
fn ready(_: *anyopaque, payload: Discord.Ready) !void {
|
var session: *Discord.Session = undefined;
|
||||||
|
|
||||||
|
fn ready(_: *Shard, payload: Discord.Ready) !void {
|
||||||
std.debug.print("logged in as {s}\n", .{payload.user.username});
|
std.debug.print("logged in as {s}\n", .{payload.user.username});
|
||||||
|
// cache demonstration TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
fn message_create(shard_ptr: *anyopaque, message: Discord.Message) !void {
|
fn message_create(_: *Shard, message: Discord.Message) !void {
|
||||||
// set custom cache
|
|
||||||
const session: *Shard(Cache) = @ptrCast(@alignCast(shard_ptr));
|
|
||||||
|
|
||||||
if (message.content != null and std.ascii.eqlIgnoreCase(message.content.?, "!hi")) {
|
if (message.content != null and std.ascii.eqlIgnoreCase(message.content.?, "!hi")) {
|
||||||
var result = try session.sendMessage(message.channel_id, .{ .content = "hi :)" });
|
var result = try session.api.sendMessage(message.channel_id, .{ .content = "hi :)" });
|
||||||
defer result.deinit();
|
defer result.deinit();
|
||||||
|
|
||||||
const m = result.value.unwrap();
|
const m = result.value.unwrap();
|
||||||
@ -43,8 +42,9 @@ pub fn main() !void {
|
|||||||
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
|
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
|
||||||
const allocator = gpa.allocator();
|
const allocator = gpa.allocator();
|
||||||
|
|
||||||
var handler = Discord.init(allocator);
|
session = try allocator.create(Discord.Session);
|
||||||
defer handler.deinit();
|
session.* = Discord.init(allocator);
|
||||||
|
defer session.deinit();
|
||||||
|
|
||||||
const env_map = try allocator.create(std.process.EnvMap);
|
const env_map = try allocator.create(std.process.EnvMap);
|
||||||
env_map.* = try std.process.getEnvMap(allocator);
|
env_map.* = try std.process.getEnvMap(allocator);
|
||||||
@ -54,12 +54,12 @@ pub fn main() !void {
|
|||||||
@panic("DISCORD_TOKEN not found in environment variables");
|
@panic("DISCORD_TOKEN not found in environment variables");
|
||||||
};
|
};
|
||||||
|
|
||||||
try handler.start(.{
|
try session.start(.{
|
||||||
.token = token,
|
.authorization = token,
|
||||||
.intents = Intents.fromRaw(INTENTS),
|
.intents = Intents.fromRaw(INTENTS),
|
||||||
.run = .{ .message_create = &message_create, .ready = &ready },
|
.run = .{ .message_create = &message_create, .ready = &ready },
|
||||||
.log = .yes,
|
.log = .yes,
|
||||||
.options = .{},
|
.options = .{},
|
||||||
.cache = Cache,
|
.cache = .defaults(allocator),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user