Implement NyxxRest. Migrate initially existing code
This commit is contained in:
parent
26c5929ac4
commit
21e3cd2f95
|
@ -25,9 +25,6 @@ class CommandContext {
|
|||
/// Shard on which message was sent
|
||||
int get shardId => this.guild != null ? this.guild!.shard.id : 0;
|
||||
|
||||
/// Returns shard on which message was sent
|
||||
Shard get shard => this.client.shardManager.shards.toList()[shardId];
|
||||
|
||||
/// Substring by which command was matched
|
||||
final String commandMatcher;
|
||||
|
||||
|
@ -139,7 +136,7 @@ class CommandContext {
|
|||
Future<Map<IEmoji, int>> awaitEmojis(Message msg, Duration duration){
|
||||
final collectedEmoji = <IEmoji, int>{};
|
||||
return Future<Map<IEmoji, int>>(() async {
|
||||
await for (final event in (msg.client as Nyxx).onMessageReactionAdded.where((evnt) => evnt.message != null && evnt.message!.id == msg.id)) {
|
||||
await for (final event in client.onMessageReactionAdded.where((evnt) => evnt.message != null && evnt.message!.id == msg.id)) {
|
||||
if (collectedEmoji.containsKey(event.emoji)) {
|
||||
// TODO: NNBD: weird stuff
|
||||
var value = collectedEmoji[event.emoji];
|
||||
|
@ -161,7 +158,7 @@ class CommandContext {
|
|||
/// Waits for first [TypingEvent] and returns it. If timed out returns null.
|
||||
/// Can listen to specific user by specifying [user]
|
||||
Future<TypingEvent?> waitForTyping(User user, {Duration timeout = const Duration(seconds: 30)}) =>
|
||||
Future<TypingEvent?>(() => (user.client as Nyxx).onTyping.firstWhere((e) => e.user == user && e.channel == this.channel)).timeout(timeout, onTimeout: () => null);
|
||||
Future<TypingEvent?>(() => client.onTyping.firstWhere((e) => e.user == user && e.channel == this.channel)).timeout(timeout, onTimeout: () => null);
|
||||
|
||||
/// Gets all context channel messages that satisfies [predicate].
|
||||
///
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: nyxx_commander
|
||||
version: 1.1.0-dev.6
|
||||
version: 1.1.0-dev.1
|
||||
description: A Discord library for Dart.
|
||||
homepage: https://github.com/l7ssha/nyxx
|
||||
repository: https://github.com/l7ssha/nyxx
|
||||
|
@ -7,9 +7,13 @@ documentation: https://github.com/l7ssha/nyxx/wiki
|
|||
issue_tracker: https://github.com/l7ssha/nyxx/issue
|
||||
|
||||
environment:
|
||||
sdk: '>=2.12.0 <2.13.0'
|
||||
sdk: '>=2.12.0-51.0.dev <3.0.0'
|
||||
|
||||
dependencies:
|
||||
http: "^0.13.0"
|
||||
logging: "^1.0.1"
|
||||
nyxx: "^1.1.0-dev.5"
|
||||
logging: "^1.0.0-nullsafety.0"
|
||||
nyxx: "^1.1.0-dev.1"
|
||||
|
||||
dependency_overrides:
|
||||
nyxx:
|
||||
path: "../nyxx"
|
||||
|
|
|
@ -38,7 +38,7 @@ extension MessageResolverExtension on Message {
|
|||
return "";
|
||||
}
|
||||
|
||||
return MessageResolver(this.client,
|
||||
return MessageResolver(this.client as Nyxx,
|
||||
userTagHandling: userTagHandling,
|
||||
roleTagHandling: roleTagHandling,
|
||||
everyoneTagHandling: everyoneTagHandling,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: nyxx_extensions
|
||||
version: 1.1.0-dev.3
|
||||
version: 1.1.0-dev.2
|
||||
description: Extensions for Nyxx library
|
||||
homepage: https://github.com/l7ssha/nyxx
|
||||
repository: https://github.com/l7ssha/nyxx
|
||||
|
@ -7,8 +7,12 @@ documentation: https://github.com/l7ssha/nyxx/wiki
|
|||
issue_tracker: https://github.com/l7ssha/nyxx/issue
|
||||
|
||||
environment:
|
||||
sdk: '>=2.12.0 <2.13.0'
|
||||
sdk: '>=2.12.0-51.0.dev <3.0.0'
|
||||
|
||||
dependencies:
|
||||
nyxx: "^1.1.0-dev.1"
|
||||
http: "^0.13.0"
|
||||
nyxx: "1.1.0-dev.4"
|
||||
|
||||
dependency_overrides:
|
||||
nyxx:
|
||||
path: "../nyxx"
|
|
@ -1,5 +1,176 @@
|
|||
part of nyxx;
|
||||
|
||||
abstract class INyxx implements Disposable {
|
||||
_HttpHandler get _http;
|
||||
_HttpEndpoints get _httpEndpoints;
|
||||
|
||||
ClientOptions get _options;
|
||||
CacheOptions get _cacheOptions;
|
||||
|
||||
String get _token;
|
||||
|
||||
/// All of the guilds the bot is in. Can be empty or can miss guilds on (READY_EVENT).
|
||||
Cache<Snowflake, Guild> get guilds;
|
||||
|
||||
/// All of the channels the bot can see.
|
||||
ChannelCache get channels;
|
||||
|
||||
/// All of the users the bot can see. Does not have offline users
|
||||
/// without `forceFetchUsers` enabled.
|
||||
Cache<Snowflake, User> get users;
|
||||
|
||||
/// Returns handler for all available REST API action.
|
||||
IHttpEndpoints get httpEndpoints => this._httpEndpoints;
|
||||
|
||||
/// Emitted when a successful HTTP response is received.
|
||||
late final StreamController<HttpResponseEvent> _onHttpResponse;
|
||||
|
||||
/// Emitted when a HTTP request failed.
|
||||
late final StreamController<HttpErrorEvent> _onHttpError;
|
||||
|
||||
/// Sent when the client is ratelimited, either by the ratelimit handler itself,
|
||||
/// or when a 429 is received.
|
||||
late final StreamController<RatelimitEvent> _onRatelimited;
|
||||
|
||||
/// Emitted when a successful HTTP response is received.
|
||||
late Stream<HttpResponseEvent> onHttpResponse;
|
||||
|
||||
/// Emitted when a HTTP request failed.
|
||||
late Stream<HttpErrorEvent> onHttpError;
|
||||
|
||||
/// Sent when the client is ratelimited, either by the ratelimit handler itself,
|
||||
/// or when a 429 is received.
|
||||
late Stream<RatelimitEvent> onRatelimited;
|
||||
}
|
||||
|
||||
/// Lightweight client which do not start ws connections.
|
||||
class NyxxRest extends INyxx {
|
||||
@override
|
||||
final String _token;
|
||||
|
||||
final DateTime _startTime = DateTime.now();
|
||||
|
||||
@override
|
||||
late final ClientOptions _options;
|
||||
@override
|
||||
late final CacheOptions _cacheOptions;
|
||||
@override
|
||||
late final _HttpHandler _http;
|
||||
@override
|
||||
late final _HttpEndpoints _httpEndpoints;
|
||||
|
||||
/// When identifying to the gateway, you have to specify an intents parameter which
|
||||
/// allows you to conditionally subscribe to pre-defined "intents", groups of events defined by Discord.
|
||||
/// If you do not specify a certain intent, you will not receive any of the gateway events that are batched into that group.
|
||||
/// Since api v8 its required upon connecting to gateway.
|
||||
final int intents;
|
||||
|
||||
/// The current bot user.
|
||||
late ClientUser self;
|
||||
|
||||
/// The bot"s OAuth2 app.
|
||||
late ClientOAuth2Application app;
|
||||
|
||||
/// All of the guilds the bot is in. Can be empty or can miss guilds on (READY_EVENT).
|
||||
@override
|
||||
late final Cache<Snowflake, Guild> guilds;
|
||||
|
||||
/// All of the channels the bot can see.
|
||||
@override
|
||||
late final ChannelCache channels;
|
||||
|
||||
/// All of the users the bot can see. Does not have offline users
|
||||
/// without `forceFetchUsers` enabled.
|
||||
@override
|
||||
late final Cache<Snowflake, User> users;
|
||||
|
||||
/// True if client is ready.
|
||||
bool ready = false;
|
||||
|
||||
/// The current version of `nyxx`
|
||||
final String version = Constants.version;
|
||||
|
||||
/// Logger instance
|
||||
final Logger _logger = Logger("Client");
|
||||
|
||||
/// Gets an bot invite link with zero permissions
|
||||
String get inviteLink => app.getInviteUrl();
|
||||
|
||||
/// Can be used to edit options after client initialised. Used by Nyxx.interactions to enable raw events
|
||||
ClientOptions get options => this._options;
|
||||
|
||||
/// Creates and logs in a new client. If [ignoreExceptions] is true (by default is)
|
||||
/// isolate will ignore all exceptions and continue to work.
|
||||
NyxxRest(this._token, this.intents,
|
||||
{ClientOptions? options,
|
||||
CacheOptions? cacheOptions,
|
||||
bool ignoreExceptions = true,
|
||||
bool useDefaultLogger = true,
|
||||
Level? defaultLoggerLogLevel}) {
|
||||
|
||||
if (useDefaultLogger) {
|
||||
Logger.root.level = defaultLoggerLogLevel ?? Level.ALL;
|
||||
|
||||
Logger.root.onRecord.listen((LogRecord rec) {
|
||||
print(
|
||||
"[${rec.time}] [${rec.level.name}] [${rec.loggerName}] ${rec.message}");
|
||||
});
|
||||
}
|
||||
|
||||
this._logger.info("Starting bot with pid: $pid");
|
||||
|
||||
if (_token.isEmpty) {
|
||||
throw MissingTokenError();
|
||||
}
|
||||
|
||||
if (!Platform.isWindows) {
|
||||
ProcessSignal.sigterm.watch().forEach((event) async {
|
||||
await this.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
ProcessSignal.sigint.watch().forEach((event) async {
|
||||
await this.dispose();
|
||||
});
|
||||
|
||||
if (ignoreExceptions) {
|
||||
Isolate.current.setErrorsFatal(false);
|
||||
|
||||
final errorsPort = ReceivePort();
|
||||
errorsPort.listen((err) {
|
||||
_logger.severe("ERROR: ${err[0]} \n ${err[1]}");
|
||||
});
|
||||
Isolate.current.addErrorListener(errorsPort.sendPort);
|
||||
}
|
||||
|
||||
this._options = options ?? ClientOptions();
|
||||
this._cacheOptions = cacheOptions ?? CacheOptions();
|
||||
|
||||
this.guilds = _SnowflakeCache();
|
||||
this.channels = ChannelCache._new();
|
||||
this.users = _SnowflakeCache();
|
||||
|
||||
this._http = _HttpHandler._new(this);
|
||||
this._httpEndpoints = _HttpEndpoints._new(this);
|
||||
|
||||
this._onHttpError = StreamController.broadcast();
|
||||
this.onHttpError = _onHttpError.stream;
|
||||
|
||||
this._onHttpResponse = StreamController.broadcast();
|
||||
this.onHttpResponse = _onHttpResponse.stream;
|
||||
|
||||
this._onRatelimited = StreamController.broadcast();
|
||||
this.onRatelimited = _onRatelimited.stream;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> dispose() async {
|
||||
await this._onHttpResponse.close();
|
||||
await this._onHttpError.close();
|
||||
await this._onRatelimited.close();
|
||||
}
|
||||
}
|
||||
|
||||
/// The main place to start with interacting with the Discord API and creating discord bot.
|
||||
/// From there you can subscribe to various [Stream]s to listen to [Events](https://github.com/l7ssha/nyxx/wiki/EventList)
|
||||
/// and fetch data from API with provided methods or get cached data.
|
||||
|
@ -17,63 +188,16 @@ part of nyxx;
|
|||
/// });
|
||||
/// ```
|
||||
/// or setup `CommandsFramework` and `Voice`.
|
||||
class Nyxx implements Disposable {
|
||||
final String _token;
|
||||
final DateTime _startTime = DateTime.now();
|
||||
|
||||
late final ClientOptions _options;
|
||||
late final CacheOptions _cacheOptions;
|
||||
|
||||
class Nyxx extends NyxxRest {
|
||||
late final _ConnectionManager _ws; // ignore: unused_field
|
||||
late final _EventController _events;
|
||||
|
||||
late final _HttpHandler _http;
|
||||
late final _HttpEndpoints _httpEndpoints;
|
||||
|
||||
/// When identifying to the gateway, you have to specify an intents parameter which
|
||||
/// allows you to conditionally subscribe to pre-defined "intents", groups of events defined by Discord.
|
||||
/// If you do not specify a certain intent, you will not receive any of the gateway events that are batched into that group.
|
||||
/// Since api v8 its required upon connecting to gateway.
|
||||
final int intents;
|
||||
|
||||
/// The current bot user.
|
||||
late ClientUser self;
|
||||
|
||||
/// The bot"s OAuth2 app.
|
||||
late ClientOAuth2Application app;
|
||||
|
||||
/// All of the guilds the bot is in. Can be empty or can miss guilds on (READY_EVENT).
|
||||
late final Cache<Snowflake, Guild> guilds;
|
||||
|
||||
/// All of the channels the bot can see.
|
||||
late final ChannelCache channels;
|
||||
|
||||
/// All of the users the bot can see. Does not have offline users
|
||||
/// without `forceFetchUsers` enabled.
|
||||
late final Cache<Snowflake, User> users;
|
||||
|
||||
/// True if client is ready.
|
||||
bool ready = false;
|
||||
|
||||
/// The current version of `nyxx`
|
||||
final String version = Constants.version;
|
||||
|
||||
/// Current client"s shard
|
||||
late ShardManager shardManager;
|
||||
|
||||
/// Emitted when a shard is disconnected from the websocket.
|
||||
late Stream<DisconnectEvent> onDisconnect;
|
||||
|
||||
/// Emitted when a successful HTTP response is received.
|
||||
late Stream<HttpResponseEvent> onHttpResponse;
|
||||
|
||||
/// Emitted when a HTTP request failed.
|
||||
late Stream<HttpErrorEvent> onHttpError;
|
||||
|
||||
/// Sent when the client is ratelimited, either by the ratelimit handler itself,
|
||||
/// or when a 429 is received.
|
||||
late Stream<RatelimitEvent> onRatelimited;
|
||||
|
||||
/// Emitted when the client is ready. Should be sent only once.
|
||||
late Stream<ReadyEvent> onReady;
|
||||
|
||||
|
@ -177,75 +301,22 @@ class Nyxx implements Disposable {
|
|||
/// Emitted when a bot removes all instances of a given emoji from the reactions of a message
|
||||
late Stream<MessageReactionRemoveEmojiEvent> onMessageReactionRemoveEmoji;
|
||||
|
||||
/// Logger instance
|
||||
final Logger _logger = Logger("Client");
|
||||
|
||||
/// Gets an bot invite link with zero permissions
|
||||
String get inviteLink => app.getInviteUrl();
|
||||
|
||||
/// Can be used to edit options after client initialised. Used by Nyxx.interactions to enable raw events
|
||||
ClientOptions get options => this._options;
|
||||
|
||||
/// Returns handler for all available REST API action.
|
||||
IHttpEndpoints get httpEndpoints => this._httpEndpoints;
|
||||
|
||||
/// Creates and logs in a new client. If [ignoreExceptions] is true (by default is)
|
||||
/// isolate will ignore all exceptions and continue to work.
|
||||
Nyxx(this._token, this.intents,
|
||||
Nyxx(String token, int intents,
|
||||
{ClientOptions? options,
|
||||
CacheOptions? cacheOptions,
|
||||
bool ignoreExceptions = true,
|
||||
bool useDefaultLogger = true,
|
||||
Level? defaultLoggerLogLevel}) {
|
||||
if (useDefaultLogger) {
|
||||
Logger.root.level = defaultLoggerLogLevel ?? Level.ALL;
|
||||
|
||||
Logger.root.onRecord.listen((LogRecord rec) {
|
||||
print(
|
||||
"[${rec.time}] [${rec.level.name}] [${rec.loggerName}] ${rec.message}");
|
||||
});
|
||||
}
|
||||
|
||||
this._logger.info("Starting bot with pid: $pid");
|
||||
|
||||
if (_token.isEmpty) {
|
||||
throw MissingTokenError();
|
||||
}
|
||||
|
||||
if (!Platform.isWindows) {
|
||||
ProcessSignal.sigterm.watch().forEach((event) async {
|
||||
await this.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
ProcessSignal.sigint.watch().forEach((event) async {
|
||||
await this.dispose();
|
||||
});
|
||||
|
||||
if (ignoreExceptions) {
|
||||
Isolate.current.setErrorsFatal(false);
|
||||
|
||||
final errorsPort = ReceivePort();
|
||||
errorsPort.listen((err) {
|
||||
_logger.severe("ERROR: ${err[0]}; ${err[1]}");
|
||||
});
|
||||
Isolate.current.addErrorListener(errorsPort.sendPort);
|
||||
}
|
||||
|
||||
this._options = options ?? ClientOptions();
|
||||
this._cacheOptions = cacheOptions ?? CacheOptions();
|
||||
|
||||
this.guilds = _SnowflakeCache();
|
||||
this.channels = ChannelCache._new();
|
||||
this.users = _SnowflakeCache();
|
||||
|
||||
this._http = _HttpHandler._new(this);
|
||||
this._httpEndpoints = _HttpEndpoints._new(this);
|
||||
|
||||
Level? defaultLoggerLogLevel}) :
|
||||
super(token, intents, options: options, cacheOptions: cacheOptions,
|
||||
ignoreExceptions: ignoreExceptions, useDefaultLogger: useDefaultLogger,
|
||||
defaultLoggerLogLevel: defaultLoggerLogLevel
|
||||
) {
|
||||
this._events = _EventController(this);
|
||||
this.onSelfMention = this
|
||||
.onMessageReceived
|
||||
.where((event) => event.message.mentions.any((element) => element.id == this.self.id));
|
||||
.where((event) => event.message.mentions.contains(this.self));
|
||||
this.onDmReceived =
|
||||
this.onMessageReceived.where((event) => event.message is DMMessage);
|
||||
|
||||
|
@ -280,6 +351,29 @@ class Nyxx implements Disposable {
|
|||
Future<User> fetchUser(Snowflake userId) =>
|
||||
this._httpEndpoints.fetchUser(userId);
|
||||
|
||||
// /// Creates new guild with provided builder.
|
||||
// /// Only for bots with less than 10 guilds otherwise it will return Future with error.
|
||||
// ///
|
||||
// /// ```
|
||||
// /// var guildBuilder = GuildBuilder()
|
||||
// /// ..name = "Example Guild"
|
||||
// /// ..roles = [RoleBuilder()..name = "Example Role]
|
||||
// /// var newGuild = await client.createGuild(guildBuilder);
|
||||
// /// ```
|
||||
// Future<Guild> createGuild(GuildBuilder builder) async {
|
||||
// if (this.guilds.count >= 10) {
|
||||
// return Future.error(ArgumentError("Guild cannot be created if bot is in 10 or more guilds"));
|
||||
// }
|
||||
//
|
||||
// final response = await this._http._execute(BasicRequest._new("/guilds", method: "POST"));
|
||||
//
|
||||
// if (response is HttpResponseSuccess) {
|
||||
// return Guild._new(this, response.jsonBody as Map<String, dynamic>);
|
||||
// }
|
||||
//
|
||||
// return Future.error(response);
|
||||
// }
|
||||
|
||||
/// Gets a webhook by its id and/or token.
|
||||
/// If token is supplied authentication is not needed.
|
||||
Future<Webhook> fetchWebhook(Snowflake id, {String token = ""}) =>
|
||||
|
|
|
@ -18,7 +18,7 @@ class Invite {
|
|||
late final Cacheable<Snowflake, User>? targetUser;
|
||||
|
||||
/// Reference to bot instance
|
||||
final Nyxx client;
|
||||
final INyxx client;
|
||||
|
||||
/// Returns url to invite
|
||||
String get url => "https://discord.gg/$code";
|
||||
|
@ -93,7 +93,7 @@ class InviteWithMeta extends Invite {
|
|||
return ageValidity && expiryValidity;
|
||||
}
|
||||
|
||||
InviteWithMeta._new(Map<String, dynamic> raw, Nyxx client) : super._new(raw, client) {
|
||||
InviteWithMeta._new(Map<String, dynamic> raw, INyxx client) : super._new(raw, client) {
|
||||
this.createdAt = DateTime.parse(raw["created_at"] as String);
|
||||
this.temporary = raw["temporary"] as bool;
|
||||
this.uses = raw["uses"] as int;
|
||||
|
|
|
@ -17,7 +17,7 @@ class AuditLog {
|
|||
Iterable<AuditLogEntry> filter(bool Function(AuditLogEntry) test) =>
|
||||
entries.values.where(test);
|
||||
|
||||
AuditLog._new(Map<String, dynamic> raw, Nyxx client) {
|
||||
AuditLog._new(Map<String, dynamic> raw, INyxx client) {
|
||||
webhooks = {};
|
||||
users = {};
|
||||
entries = {};
|
||||
|
|
|
@ -22,7 +22,7 @@ class AuditLogEntry extends SnowflakeEntity {
|
|||
/// The reason for the change
|
||||
String? reason;
|
||||
|
||||
AuditLogEntry._new(Map<String, dynamic> raw, Nyxx client) : super(Snowflake(raw["id"] as String)) {
|
||||
AuditLogEntry._new(Map<String, dynamic> raw, INyxx client) : super(Snowflake(raw["id"] as String)) {
|
||||
this.targetId = raw["targetId"] as String;
|
||||
|
||||
this.changes = [
|
||||
|
|
|
@ -8,13 +8,13 @@ abstract class IChannel extends SnowflakeEntity implements Disposable {
|
|||
late final ChannelType channelType;
|
||||
|
||||
/// Reference to client
|
||||
final Nyxx client;
|
||||
final INyxx client;
|
||||
|
||||
IChannel._new(this.client, Map<String, dynamic> raw): super(Snowflake(raw["id"])){
|
||||
this.channelType = ChannelType.from(raw["type"] as int);
|
||||
}
|
||||
|
||||
factory IChannel._deserialize(Nyxx client, Map<String, dynamic> raw, [Snowflake? guildId]) {
|
||||
factory IChannel._deserialize(INyxx client, Map<String, dynamic> raw, [Snowflake? guildId]) {
|
||||
final type = raw["type"] as int;
|
||||
|
||||
switch (type) {
|
||||
|
@ -43,7 +43,7 @@ abstract class IChannel extends SnowflakeEntity implements Disposable {
|
|||
}
|
||||
|
||||
class _InternalChannel extends GuildChannel {
|
||||
_InternalChannel._new(Nyxx client, Map<String, dynamic> raw, [Snowflake? guildId]): super._new(client, raw, guildId);
|
||||
_InternalChannel._new(INyxx client, Map<String, dynamic> raw, [Snowflake? guildId]): super._new(client, raw, guildId);
|
||||
}
|
||||
|
||||
/// Enum for possible channel types
|
||||
|
|
|
@ -19,7 +19,7 @@ class DMChannel extends IChannel implements TextChannel {
|
|||
/// Returns other user in chat if channel is not group dm. Will throw [ArgumentError] if channel is group dm.
|
||||
User get participant => !this.isGroupDM ? participants.first : throw new ArgumentError("Channel is not direct DM");
|
||||
|
||||
DMChannel._new(Nyxx client, Map<String, dynamic> raw): super._new(client, raw) {
|
||||
DMChannel._new(INyxx client, Map<String, dynamic> raw): super._new(client, raw) {
|
||||
if (raw["recipients"] != null) {
|
||||
this.participants = [
|
||||
for (final userRaw in raw["recipients"])
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
part of nyxx;
|
||||
|
||||
class CategoryGuildChannel extends GuildChannel {
|
||||
CategoryGuildChannel._new(Nyxx client, Map<String, dynamic> raw, [Snowflake? guildId]): super._new(client, raw, guildId);
|
||||
CategoryGuildChannel._new(INyxx client, Map<String, dynamic> raw, [Snowflake? guildId]): super._new(client, raw, guildId);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ abstract class GuildChannel extends IChannel {
|
|||
/// Permission override for channel
|
||||
late final List<PermissionsOverrides> permissionOverrides;
|
||||
|
||||
GuildChannel._new(Nyxx client, Map<String, dynamic> raw, [Snowflake? guildId]) : super._new(client, raw) {
|
||||
GuildChannel._new(INyxx client, Map<String, dynamic> raw, [Snowflake? guildId]) : super._new(client, raw) {
|
||||
this.name = raw["name"] as String;
|
||||
this.position = raw["position"] as int;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class TextGuildChannel extends GuildChannel implements TextChannel {
|
|||
// Used to create infinite typing loop
|
||||
Timer? _typing;
|
||||
|
||||
TextGuildChannel._new(Nyxx client, Map<String, dynamic> raw, [Snowflake? guildId]) : super._new(client, raw, guildId) {
|
||||
TextGuildChannel._new(INyxx client, Map<String, dynamic> raw, [Snowflake? guildId]) : super._new(client, raw, guildId) {
|
||||
this.topic = raw["topic"] as String?;
|
||||
this.slowModeThreshold = raw["rate_limit_per_user"] as int? ?? 0;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ class VoiceGuildChannel extends GuildChannel {
|
|||
/// The channel's user limit.
|
||||
late final int? userLimit;
|
||||
|
||||
VoiceGuildChannel._new(Nyxx client, Map<String, dynamic> raw, [Snowflake? guildId]) : super._new(client, raw, guildId) {
|
||||
VoiceGuildChannel._new(INyxx client, Map<String, dynamic> raw, [Snowflake? guildId]) : super._new(client, raw, guildId) {
|
||||
this.bitrate = raw["bitrate"] as int?;
|
||||
this.userLimit = raw["user_limit"] as int?;
|
||||
}
|
||||
|
@ -18,8 +18,12 @@ class VoiceGuildChannel extends GuildChannel {
|
|||
|
||||
/// Connects client to channel
|
||||
void connect({bool selfMute = false, bool selfDeafen = false}) {
|
||||
if (this.client is! Nyxx) {
|
||||
throw new UnsupportedError("Cannot connect with NyxxRest");
|
||||
}
|
||||
|
||||
try {
|
||||
final shard = this.client.shardManager.shards.firstWhere((element) => element.guilds.contains(this.guild.id));
|
||||
final shard = (this.client as Nyxx).shardManager.shards.firstWhere((element) => element.guilds.contains(this.guild.id));
|
||||
|
||||
shard.changeVoiceState(this.guild.id, this.id, selfMute: selfMute, selfDeafen: selfDeafen);
|
||||
} on Error {
|
||||
|
@ -29,8 +33,12 @@ class VoiceGuildChannel extends GuildChannel {
|
|||
|
||||
/// Disconnects use from channel.
|
||||
void disconnect() {
|
||||
if (this.client is! Nyxx) {
|
||||
throw new UnsupportedError("Cannot connect with NyxxRest");
|
||||
}
|
||||
|
||||
try {
|
||||
final shard = this.client.shardManager.shards.firstWhere((element) => element.guilds.contains(this.guild.id));
|
||||
final shard = (this.client as Nyxx).shardManager.shards.firstWhere((element) => element.guilds.contains(this.guild.id));
|
||||
|
||||
shard.changeVoiceState(this.guild.id, null);
|
||||
} on Error {
|
||||
|
|
|
@ -8,7 +8,7 @@ class Ban {
|
|||
/// Banned user
|
||||
late final User user;
|
||||
|
||||
Ban._new(Map<String, dynamic> raw, Nyxx client) {
|
||||
Ban._new(Map<String, dynamic> raw, INyxx client) {
|
||||
this.reason = raw["reason"] as String;
|
||||
this.user = User._new(client, raw["user"] as Map<String, dynamic>);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ part of nyxx;
|
|||
|
||||
class Guild extends SnowflakeEntity {
|
||||
/// Reference to [Nyxx] instance
|
||||
Nyxx client;
|
||||
final INyxx client;
|
||||
|
||||
/// The guild's name.
|
||||
late final String name;
|
||||
|
@ -97,7 +97,13 @@ class Guild extends SnowflakeEntity {
|
|||
Role get everyoneRole => roles.values.firstWhere((r) => r.name == "@everyone");
|
||||
|
||||
/// Returns member object for bot user
|
||||
Member? get selfMember => members[client.self.id];
|
||||
Member? get selfMember {
|
||||
if (this.client is! Nyxx) {
|
||||
throw new UnsupportedError("Cannot use this property with NyxxRest");
|
||||
}
|
||||
|
||||
return members[(client as Nyxx).self.id];
|
||||
}
|
||||
|
||||
/// File upload limit for channel in bytes.
|
||||
int get fileUploadLimit {
|
||||
|
@ -115,7 +121,13 @@ class Guild extends SnowflakeEntity {
|
|||
}
|
||||
|
||||
/// Returns this guilds shard
|
||||
Shard get shard => client.shardManager.shards.firstWhere((_shard) => _shard.guilds.contains(this.id));
|
||||
Shard get shard {
|
||||
if (this.client is! Nyxx) {
|
||||
throw new UnsupportedError("Cannot use this property with NyxxRest");
|
||||
}
|
||||
|
||||
return (client as Nyxx).shardManager.shards.firstWhere((_shard) => _shard.guilds.contains(this.id));
|
||||
}
|
||||
|
||||
Guild._new(this.client, Map<String, dynamic> raw, [bool guildCreate = false]) : super(Snowflake(raw["id"])) {
|
||||
this.name = raw["name"] as String;
|
||||
|
|
|
@ -4,7 +4,7 @@ part of nyxx;
|
|||
/// This endpoint is only for Public guilds.
|
||||
class GuildPreview extends SnowflakeEntity {
|
||||
/// Reference to client
|
||||
final Nyxx client;
|
||||
final INyxx client;
|
||||
|
||||
/// Guild name
|
||||
late final String name;
|
||||
|
|
|
@ -2,7 +2,7 @@ part of nyxx;
|
|||
|
||||
class Role extends SnowflakeEntity implements Mentionable {
|
||||
/// Reference to client
|
||||
final Nyxx client;
|
||||
final INyxx client;
|
||||
|
||||
/// Cachealble or guild attached to this role instance
|
||||
late final Cacheable<Snowflake, Guild> guild;
|
||||
|
|
|
@ -62,7 +62,7 @@ class Webhook extends SnowflakeEntity implements IMessageAuthor {
|
|||
String get tag => "";
|
||||
|
||||
/// Reference to [Nyxx] object
|
||||
final Nyxx client;
|
||||
final INyxx client;
|
||||
|
||||
Webhook._new(Map<String, dynamic> raw, this.client) : super(Snowflake(raw["id"] as String)) {
|
||||
this.name = raw["name"] as String?;
|
||||
|
|
|
@ -32,7 +32,7 @@ class GuildEmojiPartial extends IGuildEmoji implements IEmoji {
|
|||
|
||||
class GuildEmoji extends GuildEmojiPartial implements IEmoji {
|
||||
/// Reference to client
|
||||
final Nyxx client;
|
||||
final INyxx client;
|
||||
|
||||
/// Reference to guild where emoji belongs to
|
||||
late final Cacheable<Snowflake, Guild> guild;
|
||||
|
|
|
@ -2,7 +2,7 @@ part of nyxx;
|
|||
|
||||
abstract class Message extends SnowflakeEntity implements Disposable {
|
||||
/// Reference to bot instance
|
||||
final Nyxx client;
|
||||
final INyxx client;
|
||||
|
||||
/// The message's content.
|
||||
late String content;
|
||||
|
@ -52,7 +52,7 @@ abstract class Message extends SnowflakeEntity implements Disposable {
|
|||
/// Message reply
|
||||
late final ReferencedMessage? referencedMessage;
|
||||
|
||||
factory Message._deserialize(Nyxx client, Map<String, dynamic> raw) {
|
||||
factory Message._deserialize(INyxx client, Map<String, dynamic> raw) {
|
||||
if (raw["guild_id"] != null) {
|
||||
return GuildMessage._new(client, raw);
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ class DMMessage extends Message {
|
|||
String get url => "https://discordapp.com/channels/@me"
|
||||
"/${this.channel.id}/${this.id}";
|
||||
|
||||
DMMessage._new(Nyxx client, Map<String, dynamic> raw) : super._new(client, raw) {
|
||||
DMMessage._new(INyxx client, Map<String, dynamic> raw) : super._new(client, raw) {
|
||||
final user = client.users[Snowflake(raw["author"]["id"])];
|
||||
|
||||
if (user == null) {
|
||||
|
@ -228,7 +228,7 @@ class GuildMessage extends Message {
|
|||
/// Role mentions in this message
|
||||
late final List<Cacheable<Snowflake, Role>> roleMentions;
|
||||
|
||||
GuildMessage._new(Nyxx client, Map<String, dynamic> raw) : super._new(client, raw) {
|
||||
GuildMessage._new(INyxx client, Map<String, dynamic> raw) : super._new(client, raw) {
|
||||
if (raw["message_reference"] != null) {
|
||||
this.crossPostReference = MessageReference._new(
|
||||
raw["message_reference"] as Map<String, dynamic>, client);
|
||||
|
|
|
@ -11,7 +11,7 @@ class MessageReference {
|
|||
/// Original guild
|
||||
late final Cacheable<Snowflake, Guild>? guild;
|
||||
|
||||
MessageReference._new(Map<String, dynamic> raw, Nyxx client) {
|
||||
MessageReference._new(Map<String, dynamic> raw, INyxx client) {
|
||||
this.channel = _ChannelCacheable(client, Snowflake(raw["channel_id"]));
|
||||
|
||||
if (raw["message_id"] != null) {
|
||||
|
|
|
@ -16,7 +16,7 @@ class ReferencedMessage {
|
|||
/// True if references message exists and is available
|
||||
bool get exists => !isDeleted && !isBackendFetchError;
|
||||
|
||||
ReferencedMessage._new(Nyxx client, Map<String, dynamic> raw) {
|
||||
ReferencedMessage._new(INyxx client, Map<String, dynamic> raw) {
|
||||
if (!raw.containsKey("referenced_message")) {
|
||||
this.message = null;
|
||||
this.isBackendFetchError = true;
|
||||
|
|
|
@ -2,7 +2,7 @@ part of nyxx;
|
|||
|
||||
class Member extends SnowflakeEntity {
|
||||
/// Reference to client
|
||||
final Nyxx client;
|
||||
final INyxx client;
|
||||
|
||||
/// [Cacheable] for this [Guild] member
|
||||
late final Cacheable<Snowflake, User> user;
|
||||
|
|
|
@ -3,7 +3,7 @@ part of nyxx;
|
|||
/// Represents a single user of Discord, either a human or a bot, outside of any specific guild's context.
|
||||
class User extends SnowflakeEntity with Mentionable, IMessageAuthor implements ISend {
|
||||
/// Reference to client
|
||||
final Nyxx client;
|
||||
final INyxx client;
|
||||
|
||||
/// The user's username.
|
||||
@override
|
||||
|
|
|
@ -33,7 +33,7 @@ class VoiceState {
|
|||
/// Whether this user's camera is enabled
|
||||
late final bool selfVideo;
|
||||
|
||||
VoiceState._new(Nyxx client, Map<String, dynamic> raw) {
|
||||
VoiceState._new(INyxx client, Map<String, dynamic> raw) {
|
||||
if (raw["channel_id"] != null) {
|
||||
this.channel = _ChannelCacheable(client, Snowflake(raw["channel_id"]));
|
||||
} else {
|
||||
|
|
|
@ -5,16 +5,6 @@ class _EventController implements Disposable {
|
|||
/// Emitted when a shard is disconnected from the websocket.
|
||||
late final StreamController<DisconnectEvent> onDisconnect;
|
||||
|
||||
/// Emitted when a successful HTTP response is received.
|
||||
late final StreamController<HttpResponseEvent> onHttpResponse;
|
||||
|
||||
/// Emitted when a HTTP request failed.
|
||||
late final StreamController<HttpErrorEvent> onHttpError;
|
||||
|
||||
/// Sent when the client is ratelimited, either by the ratelimit handler itself,
|
||||
/// or when a 429 is received.
|
||||
late final StreamController<RatelimitEvent> onRatelimited;
|
||||
|
||||
/// Emitted when the client is ready.
|
||||
late final StreamController<ReadyEvent> onReady;
|
||||
|
||||
|
@ -116,15 +106,6 @@ class _EventController implements Disposable {
|
|||
this.onDisconnect = StreamController.broadcast();
|
||||
_client.onDisconnect = this.onDisconnect.stream;
|
||||
|
||||
this.onHttpResponse = StreamController.broadcast();
|
||||
_client.onHttpResponse = this.onHttpResponse.stream;
|
||||
|
||||
this.onHttpError = StreamController.broadcast();
|
||||
_client.onHttpError = this.onHttpError.stream;
|
||||
|
||||
this.onRatelimited = StreamController.broadcast();
|
||||
_client.onRatelimited = this.onRatelimited.stream;
|
||||
|
||||
this.onReady = StreamController.broadcast();
|
||||
_client.onReady = this.onReady.stream;
|
||||
|
||||
|
@ -225,9 +206,6 @@ class _EventController implements Disposable {
|
|||
@override
|
||||
Future<void> dispose() async {
|
||||
await this.onDisconnect.close();
|
||||
await this.onHttpResponse.close();
|
||||
await this.onHttpError.close();
|
||||
await this.onRatelimited.close();
|
||||
await this.onGuildUpdate.close();
|
||||
await this.onReady.close();
|
||||
await this.onMessageReceived.close();
|
||||
|
|
|
@ -275,7 +275,7 @@ abstract class IHttpEndpoints {
|
|||
|
||||
class _HttpEndpoints implements IHttpEndpoints {
|
||||
late final _HttpHandler _httpClient;
|
||||
final Nyxx _client;
|
||||
final INyxx _client;
|
||||
|
||||
_HttpEndpoints._new(this._client) {
|
||||
this._httpClient = this._client._http;
|
||||
|
|
14
nyxx/lib/src/internal/cache/Cacheable.dart
vendored
14
nyxx/lib/src/internal/cache/Cacheable.dart
vendored
|
@ -4,7 +4,7 @@ part of nyxx;
|
|||
/// Always provides [id] of entity. `download()` method tries to get entity from API and returns it upon success or
|
||||
/// throws Error if something happens in the process.
|
||||
abstract class Cacheable<T extends Snowflake, S extends SnowflakeEntity> {
|
||||
final Nyxx _client;
|
||||
final INyxx _client;
|
||||
|
||||
/// Id of entity
|
||||
final T id;
|
||||
|
@ -39,7 +39,7 @@ abstract class Cacheable<T extends Snowflake, S extends SnowflakeEntity> {
|
|||
class _RoleCacheable extends Cacheable<Snowflake, Role> {
|
||||
final Cacheable<Snowflake, Guild> guild;
|
||||
|
||||
_RoleCacheable(Nyxx client, Snowflake id, this.guild): super._new(client, id);
|
||||
_RoleCacheable(INyxx client, Snowflake id, this.guild): super._new(client, id);
|
||||
|
||||
@override
|
||||
Future<Role> download() async => this._fetchGuildRole();
|
||||
|
@ -68,7 +68,7 @@ class _RoleCacheable extends Cacheable<Snowflake, Role> {
|
|||
}
|
||||
|
||||
class _ChannelCacheable<T extends IChannel> extends Cacheable<Snowflake, T> {
|
||||
_ChannelCacheable(Nyxx client, Snowflake id): super._new(client, id);
|
||||
_ChannelCacheable(INyxx client, Snowflake id): super._new(client, id);
|
||||
|
||||
@override
|
||||
T? getFromCache() => this._client.channels[this.id] as T?;
|
||||
|
@ -78,7 +78,7 @@ class _ChannelCacheable<T extends IChannel> extends Cacheable<Snowflake, T> {
|
|||
}
|
||||
|
||||
class _GuildCacheable extends Cacheable<Snowflake, Guild> {
|
||||
_GuildCacheable(Nyxx client, Snowflake id): super._new(client, id);
|
||||
_GuildCacheable(INyxx client, Snowflake id): super._new(client, id);
|
||||
|
||||
@override
|
||||
Guild? getFromCache() => this._client.guilds[this.id];
|
||||
|
@ -88,7 +88,7 @@ class _GuildCacheable extends Cacheable<Snowflake, Guild> {
|
|||
}
|
||||
|
||||
class _UserCacheable extends Cacheable<Snowflake, User> {
|
||||
_UserCacheable(Nyxx client, Snowflake id): super._new(client, id);
|
||||
_UserCacheable(INyxx client, Snowflake id): super._new(client, id);
|
||||
|
||||
@override
|
||||
Future<User> download() => _client._httpEndpoints.fetchUser(this.id);
|
||||
|
@ -100,7 +100,7 @@ class _UserCacheable extends Cacheable<Snowflake, User> {
|
|||
class _MemberCacheable extends Cacheable<Snowflake, Member> {
|
||||
final Cacheable<Snowflake, Guild> guild;
|
||||
|
||||
_MemberCacheable(Nyxx client, Snowflake id, this.guild): super._new(client, id);
|
||||
_MemberCacheable(INyxx client, Snowflake id, this.guild): super._new(client, id);
|
||||
|
||||
@override
|
||||
Future<Member> download() =>
|
||||
|
@ -121,7 +121,7 @@ class _MemberCacheable extends Cacheable<Snowflake, Member> {
|
|||
class _MessageCacheable<U extends TextChannel> extends Cacheable<Snowflake, Message> {
|
||||
final Cacheable<Snowflake, U> channel;
|
||||
|
||||
_MessageCacheable(Nyxx client, Snowflake id, this.channel) : super._new(client, id);
|
||||
_MessageCacheable(INyxx client, Snowflake id, this.channel) : super._new(client, id);
|
||||
|
||||
@override
|
||||
Future<Message> download() async {
|
||||
|
|
|
@ -22,7 +22,7 @@ class _HttpBucket {
|
|||
final waitTime = resetAt!.millisecondsSinceEpoch - now.millisecondsSinceEpoch;
|
||||
|
||||
if (waitTime > 0) {
|
||||
_httpHandler.client._events.onRatelimited.add(RatelimitEvent._new(request, true));
|
||||
_httpHandler.client._onRatelimited.add(RatelimitEvent._new(request, true));
|
||||
_httpHandler._logger.warning(
|
||||
"Rate limited internally on endpoint: ${request.uri}. Trying to send request again in $waitTime ms...");
|
||||
|
||||
|
@ -49,7 +49,7 @@ class _HttpBucket {
|
|||
final responseBody = jsonDecode(await response.stream.bytesToString());
|
||||
final retryAfter = ((responseBody["retry_after"] as double) * 1000).round();
|
||||
|
||||
_httpHandler.client._events.onRatelimited.add(RatelimitEvent._new(request, false, response));
|
||||
_httpHandler.client._onRatelimited.add(RatelimitEvent._new(request, false, response));
|
||||
_httpHandler._logger.warning(
|
||||
"Rate limited via 429 on endpoint: ${request.uri}. Trying to send request again in $retryAfter ms...");
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ class _HttpHandler {
|
|||
|
||||
final Logger _logger = Logger("Http");
|
||||
late final _HttpClient _httpClient;
|
||||
final Nyxx client;
|
||||
final INyxx client;
|
||||
|
||||
_HttpHandler._new(this.client) {
|
||||
this._noRateBucket = _HttpBucket(Uri.parse("noratelimit"), this);
|
||||
|
@ -38,14 +38,14 @@ class _HttpHandler {
|
|||
final responseSuccess = HttpResponseSuccess._new(response);
|
||||
await responseSuccess._finalize();
|
||||
|
||||
client._events.onHttpResponse.add(HttpResponseEvent._new(responseSuccess));
|
||||
client._onHttpResponse.add(HttpResponseEvent._new(responseSuccess));
|
||||
return responseSuccess;
|
||||
}
|
||||
|
||||
final responseError = HttpResponseError._new(response);
|
||||
await responseError._finalize();
|
||||
|
||||
client._events.onHttpError.add(HttpErrorEvent._new(responseError));
|
||||
client._onHttpError.add(HttpErrorEvent._new(responseError));
|
||||
return responseError;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ class _HttpClient extends http.BaseClient {
|
|||
final http.Client _innerClient = http.Client();
|
||||
|
||||
// ignore: public_member_api_docs
|
||||
_HttpClient(Nyxx client) {
|
||||
_HttpClient(INyxx client) {
|
||||
this._authHeader = {
|
||||
"Authorization" : "Bot ${client._token}"
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: nyxx
|
||||
version: 1.1.0-dev.6
|
||||
version: 1.1.0-dev.3
|
||||
description: A Discord library for Dart.
|
||||
homepage: https://github.com/l7ssha/nyxx
|
||||
repository: https://github.com/l7ssha/nyxx
|
||||
|
@ -7,12 +7,12 @@ documentation: https://github.com/l7ssha/nyxx/wiki
|
|||
issue_tracker: https://github.com/l7ssha/nyxx/issue
|
||||
|
||||
environment:
|
||||
sdk: '>=2.12.0 <2.13.0'
|
||||
sdk: '>=2.12.0-51.0.dev <3.0.0'
|
||||
|
||||
dependencies:
|
||||
logging: "^1.0.0-nullsafety.0"
|
||||
http: "^0.13.0"
|
||||
logging: "^1.0.1"
|
||||
path: "^1.8.0"
|
||||
path: "^1.8.0-nullsafety.3"
|
||||
|
||||
dev_dependencies:
|
||||
test: "^1.16.8"
|
||||
test: "^1.16.2"
|
||||
|
|
Loading…
Reference in a new issue