Cacheless Guild, Emoji, Reaction, Role

[ci skip]
This commit is contained in:
Szymon Uglis 2020-05-21 00:55:14 +02:00
parent e120c92314
commit b7b8f6167e
10 changed files with 116 additions and 93 deletions

View file

@ -64,7 +64,8 @@ class Commander {
}
Future<void> _handleMessage(MessageReceivedEvent event) async {
final context = CommandContext._new(event.message.channel, event.message.author,
/// TODO: Cache
final context = CommandContext._new(event.message.channel!, event.message.author,
event.message is GuildMessage ? (event.message as GuildMessage).guild : null, event.message);
final prefix = await _prefixHandler(context, event.message.content);

View file

@ -21,7 +21,7 @@ void main() {
if (event.message.content == "Test 10") {
await event.message.delete();
await event.message.channel.send(content: "Commander tests completed sucessfuly!");
await event.message.channel?.send(content: "Commander tests completed sucessfuly!");
exit(0);
}
});

View file

@ -145,7 +145,7 @@ class Guild extends SnowflakeEntity implements Disposable {
if (raw["roles"] != null) {
this.roles = _SnowflakeCache<Role>();
raw["roles"].forEach((o) {
final role = Role._new(o as Map<String, dynamic>, this, client);
final role = Role._new(o as Map<String, dynamic>, this.id, client);
this.roles[role.id] = role;
});
}
@ -153,7 +153,7 @@ class Guild extends SnowflakeEntity implements Disposable {
this.emojis = _SnowflakeCache();
if (raw["emojis"] != null) {
raw["emojis"].forEach((dynamic o) {
final emoji = GuildEmoji._new(o as Map<String, dynamic>, this, client);
final emoji = GuildEmoji._new(o as Map<String, dynamic>, this.id, client);
this.emojis[emoji.id] = emoji;
});
}
@ -285,7 +285,7 @@ class Guild extends SnowflakeEntity implements Disposable {
final response = await client._http._execute(BasicRequest._new("/guilds/$id/emojis/${emojiId.toString()}"));
if (response is HttpResponseSuccess) {
return GuildEmoji._new(response.jsonBody as Map<String, dynamic>, this, client);
return GuildEmoji._new(response.jsonBody as Map<String, dynamic>, this.id, client);
}
return Future.error(response);
@ -317,7 +317,7 @@ class Guild extends SnowflakeEntity implements Disposable {
._execute(BasicRequest._new("/guilds/${this.id.toString()}/emojis", method: "POST", body: body));
if (response is HttpResponseSuccess) {
return GuildEmoji._new(response.jsonBody as Map<String, dynamic>, this, client);
return GuildEmoji._new(response.jsonBody as Map<String, dynamic>, this.id, client);
}
return Future.error(response);
@ -486,7 +486,7 @@ class Guild extends SnowflakeEntity implements Disposable {
BasicRequest._new("/guilds/$id/roles", method: "POST", auditLog: auditReason, body: roleBuilder._build()));
if (response is HttpResponseSuccess) {
return Role._new(response.jsonBody as Map<String, dynamic>, this, client);
return Role._new(response.jsonBody as Map<String, dynamic>, this.id, client);
}
return Future.error(response);

View file

@ -22,24 +22,24 @@ class Role extends SnowflakeEntity implements Mentionable, GuildEntity {
/// The role's guild.
@override
late final Guild guild;
late final Guild? guild;
@override
/// The role's guild id.
late final Snowflake guildId;
/// The role's permissions.
late final Permissions permissions;
/// Returns all members which have this role assigned
Iterable<Member> get members => guild.members.find((m) => m.roles.contains(this));
@override
/// Mention of role. If role cannot be mentioned it returns name of role (@name)
String get mention => mentionable ? "<@&${this.id}>" : "@$name";
/// Reference to [Nyxx] instance
Nyxx client;
Role._new(Map<String, dynamic> raw, this.guild, this.client) : super(Snowflake(raw["id"] as String)) {
Role._new(Map<String, dynamic> raw, this.guildId, this.client) : super(Snowflake(raw["id"] as String)) {
this.name = raw["name"] as String;
this.position = raw["position"] as int;
this.hoist = raw["hoist"] as bool;
@ -47,15 +47,17 @@ class Role extends SnowflakeEntity implements Mentionable, GuildEntity {
this.mentionable = raw["mentionable"] as bool? ?? false;
this.permissions = Permissions.fromInt(raw["permissions"] as int);
this.color = DiscordColor.fromInt(raw["color"] as int);
this.guild = client.guilds[this.guildId];
}
/// Edits the role.
Future<Role> edit(RoleBuilder role, {String? auditReason}) async {
final response = await client._http._execute(BasicRequest._new("/guilds/${this.guild.id}/roles/$id",
final response = await client._http._execute(BasicRequest._new("/guilds/${this.guildId}/roles/$id",
method: "PATCH", body: role._build(), auditLog: auditReason));
if (response is HttpResponseSuccess) {
return Role._new(response.jsonBody as Map<String, dynamic>, this.guild, client);
return Role._new(response.jsonBody as Map<String, dynamic>, this.guildId, client);
}
return Future.error(response);
@ -64,12 +66,12 @@ class Role extends SnowflakeEntity implements Mentionable, GuildEntity {
/// Deletes the role.
Future<void> delete({String? auditReason}) =>
client._http
._execute(BasicRequest._new("/guilds/${this.guild.id}/roles/$id", method: "DELETE", auditLog: auditReason));
._execute(BasicRequest._new("/guilds/${this.guildId}/roles/$id", method: "DELETE", auditLog: auditReason));
/// Adds role to user.
Future<void> addToUser(User user, {String? auditReason}) =>
client._http._execute(
BasicRequest._new("/guilds/${guild.id}/members/${user.id}/roles/$id", method: "PUT", auditLog: auditReason));
BasicRequest._new("/guilds/${this.guildId}/members/${user.id}/roles/$id", method: "PUT", auditLog: auditReason));
/// Returns a mention of role. If role cannot be mentioned it returns name of role.
@override

View file

@ -7,11 +7,8 @@ abstract class Emoji {
Emoji(this.name);
// TODO: Emojis stuff
factory Emoji._deserialize(Map<String, dynamic> raw) {
if (raw["id"] != null) {
return GuildEmoji._partial(raw);
}
return UnicodeEmoji(raw["name"] as String);
}

View file

@ -1,24 +1,45 @@
part of nyxx;
abstract class IGuildEmoji extends Emoji {
/// True if emoji is partial.
final bool partial;
IGuildEmoji._new(String name, this.partial) : super(name);
}
/// Emoji object. Handles Unicode emojis and custom ones.
/// Always check if object is partial via [partial] field before accessing fields or methods,
/// due any of field can be null or empty
class GuildEmoji extends Emoji implements SnowflakeEntity, GuildEntity {
class GuildEmoji extends IGuildEmoji implements SnowflakeEntity, GuildEntity {
/// Reference tp [Nyxx] object
Nyxx? client;
Nyxx client;
/// Emojis guild
@override
late final Guild? guild;
/// Emoji guild
late final Guild guild;
/// Emojis guild id
@override
late final Snowflake guildId;
/// Snowflake id of emoji
@override
late final Snowflake id;
late final List<Snowflake> _roles;
/// Roles this emoji is whitelisted to
late final List<Role> roles;
Iterable<Role> get roles sync* {
if(this.guild != null) {
for(final roleId in this._roles) {
final role = this.guild!.roles[roleId];
if(role != null) {
yield role;
}
}
}
}
/// whether this emoji must be wrapped in colons
late final bool requireColons;
@ -34,32 +55,19 @@ class GuildEmoji extends Emoji implements SnowflakeEntity, GuildEntity {
late final bool partial;
/// Creates full emoji object
GuildEmoji._new(Map<String, dynamic> raw, this.guild, this.client) : super("") {
GuildEmoji._new(Map<String, dynamic> raw, this.guildId, this.client) : super._new(raw["name"] as String, false) {
this.id = Snowflake(raw["id"] as String);
this.guild = client.guilds[this.guildId];
this.name = raw["name"] as String;
this.requireColons = raw["require_colons"] as bool? ?? false;
this.managed = raw["managed"] as bool? ?? false;
this.animated = raw["animated"] as bool? ?? false;
this.roles = [];
if (raw["roles"] != null) {
for (final roleId in raw["roles"]) {
final role = this.guild.roles[Snowflake(roleId)];
if (role != null) {
this.roles.add(role);
}
}
}
this.partial = false;
}
/// Creates partial object - only [id] and [name]
GuildEmoji._partial(Map<String, dynamic> raw) : super(raw["name"] as String) {
this.id = Snowflake(raw["id"] as String);
this.partial = true;
this._roles = [
if (raw["roles"] != null)
for (final roleId in raw["roles"])
Snowflake(roleId)
];
}
/// Allows to edit emoji
@ -73,20 +81,20 @@ class GuildEmoji extends Emoji implements SnowflakeEntity, GuildEntity {
if (roles != null) "roles": roles.map((r) => r.toString())
};
_HttpResponse? response = await client?._http._execute(
BasicRequest._new("/guilds/${guild.id.toString()}/emojis/${this.id.toString()}", method: "PATCH", body: body));
final response = await client._http._execute(
BasicRequest._new("/guilds/${this.guildId}/emojis/${this.id.toString()}", method: "PATCH", body: body));
if (response is HttpResponseSuccess) {
return GuildEmoji._new(response.jsonBody as Map<String, dynamic>, guild, client);
return GuildEmoji._new(response.jsonBody as Map<String, dynamic>, this.guildId, client);
}
return Future.error(response ?? "Cannot edit partial emoji");
return Future.error(response);
}
/// Deletes emoji
Future<void> delete() async =>
client?._http._execute(
BasicRequest._new("/guilds/${this.guild.id.toString()}/emojis/${this.id.toString()}", method: "DELETE"));
client._http._execute(
BasicRequest._new("/guilds/${this.guildId}/emojis/${this.id.toString()}", method: "DELETE"));
/// Encodes Emoji to API format
@override

View file

@ -19,7 +19,9 @@ class Reaction {
if (rawEmoji["id"] == null) {
this.emoji = UnicodeEmoji(rawEmoji["name"] as String);
} else {
this.emoji = GuildEmoji._partial(rawEmoji);
//TODO: EMOJIS STUUF
//this.emoji = PartialGuildEmoji._new(rawEmoji);
}
}

View file

@ -205,20 +205,24 @@ class GuildBanRemoveEvent {
/// Fired when emojis are updated
class GuildEmojisUpdateEvent {
/// New list of changes emojis
late final Map<Snowflake, GuildEmoji> emojis;
final Map<Snowflake, GuildEmoji> emojis = {};
late final Snowflake guildId;
late final Guild? guild;
GuildEmojisUpdateEvent._new(Map<String, dynamic> json, Nyxx client) {
if (client.ready) {
final guild = client.guilds[Snowflake(json["d"]["guild_id"])];
this.guildId = Snowflake(json["d"]["guild_id"]);
this.guild = client.guilds[this.guildId];
for(final rawEmoji in json["d"]["emojis"]) {
final emoji = GuildEmoji._new(rawEmoji as Map<String, dynamic>, guildId, client);
this.emojis[emoji.id] = emoji;
emojis = {};
if (guild != null) {
json["d"]["emojis"].forEach((o) {
final emoji = GuildEmoji._new(o as Map<String, dynamic>, guild, client);
guild.emojis[emoji.id] = emoji;
emojis[emoji.id] = emoji;
});
guild!.emojis[emoji.id] = emoji;
emojis[emoji.id] = emoji;
}
}
}
@ -227,17 +231,19 @@ class GuildEmojisUpdateEvent {
/// Sent when a role is created.
class RoleCreateEvent {
/// The role that was created.
Role? role;
late final Role role;
late final Snowflake guildId;
late final Guild? guild;
RoleCreateEvent._new(Map<String, dynamic> json, Nyxx client) {
if (client.ready) {
final guild = client.guilds[Snowflake(json["d"]["guild_id"])];
this.guildId = Snowflake(json["d"]["guild_id"]);
this.guild = client.guilds[this.guildId];
if (guild != null) {
this.role = Role._new(json["d"]["role"] as Map<String, dynamic>, guild, client);
guild.roles[role!.id] = role!;
}
this.role = Role._new(json["d"]["role"] as Map<String, dynamic>, guildId, client);
if (guild != null) {
guild!.roles[role!.id] = role!;
}
}
}
@ -247,36 +253,41 @@ class RoleDeleteEvent {
/// The role that was deleted.
Role? role;
RoleDeleteEvent._new(Map<String, dynamic> json, Nyxx client) {
final guild = client.guilds[Snowflake(json["d"]["guild_id"])];
late final Snowflake roleId;
late final Snowflake guildId;
late final Guild? guild;
RoleDeleteEvent._new(Map<String, dynamic> json, Nyxx client) {
this.guildId = Snowflake(json["d"]["guild_id"]);
this.guild = client.guilds[this.guildId];
this.roleId = Snowflake(json["d"]["role_id"]);
if (guild != null) {
this.role = guild.roles[Snowflake(json["d"]["role_id"])];
guild.roles.remove(role!.id);
this.role = guild!.roles[this.roleId];
guild!.roles.remove(role!.id);
}
}
}
/// Sent when a role is updated.
class RoleUpdateEvent {
/// The role prior to the update.
Role? oldRole;
/// The role after the update.
Role? newRole;
late final Role role;
late final Snowflake guildId;
late final Guild? guild;
RoleUpdateEvent._new(Map<String, dynamic> json, Nyxx client) {
final guild = client.guilds[Snowflake(json["d"]["guild_id"])];
this.guildId = Snowflake(json["d"]["guild_id"]);
this.guild = client.guilds[this.guildId];
this.role = Role._new(json["d"]["role"] as Map<String, dynamic>, guildId, client);
if (guild != null) {
this.oldRole = guild.roles[Snowflake(json["d"]["role"]["id"])];
this.newRole = Role._new(json["d"]["role"] as Map<String, dynamic>, guild, client);
if (oldRole != null) {
oldRole!.guild.roles[oldRole!.id] = newRole!;
} else {
guild.roles.add(newRole!.id, newRole!);
}
this.guild!.roles[role.id] = role;
}
}
}

View file

@ -104,7 +104,8 @@ abstract class MessageReactionEvent {
if (json["d"]["emoji"]["id"] == null) {
this.emoji = UnicodeEmoji(json["d"]["emoji"]["name"] as String);
} else {
this.emoji = GuildEmoji._partial(json["d"]["emoji"] as Map<String, dynamic>);
// TODO: emojis stuff
//this.emoji = GuildEmoji._partial(json["d"]["emoji"] as Map<String, dynamic>);
}
}
}
@ -225,7 +226,8 @@ class MessageReactionRemoveEmojiEvent {
if (json["d"]["emoji"]["id"] == null) {
this.emoji = UnicodeEmoji(json["d"]["emoji"]["name"] as String);
} else {
this.emoji = GuildEmoji._partial(json["d"]["emoji"] as Map<String, dynamic>);
// TODO: emojis stuff
//this.emoji = GuildEmoji._partial(json["d"]["emoji"] as Map<String, dynamic>);
}
if (this.message != null) {

View file

@ -93,7 +93,7 @@ void main() {
});
bot.onMessageReceived.listen((e) async {
if (e.message.channel.id != Snowflake("422285619952222208") && e.message.author.id != bot.self.id) {
if (e.message.channelId != Snowflake("422285619952222208") && e.message.author.id != bot.self.id) {
return;
}
@ -124,7 +124,7 @@ void main() {
final field = embed.fields.first;
if (field.name == "Test field" && field.content == "Test value" && !field.inline!) {
await e.message.channel.send(content: "Tests completed successfully!");
await e.message.channel?.send(content: "Tests completed successfully!");
print("Nyxx tests completed successfully!");
exit(0);
}