From 21fd08383ac96128fcd3f4e97105c174e707a3f7 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Fri, 16 Aug 2024 13:19:25 +0200 Subject: [PATCH 01/44] fix(datastore): add cache methods --- .../cache/cache_provider_contract.dart | 26 +++++++++++-------- .../datastore/parts/channel_part.dart | 8 +++--- .../datastore/parts/server_part.dart | 14 +++++----- .../listeners/channel_delete_packet.dart | 7 +++-- .../listeners/channel_pins_update_packet.dart | 10 +++---- .../listeners/channel_update_packet.dart | 12 ++++----- .../listeners/guild_ban_add_packet.dart | 7 ++--- .../listeners/guild_member_add_packet.dart | 13 ++++------ .../listeners/guild_member_remove_packet.dart | 7 +++-- .../listeners/guild_member_update_packet.dart | 12 +++------ .../listeners/guild_role_create_packet.dart | 11 +++----- .../listeners/guild_role_delete_packet.dart | 6 ++--- .../listeners/guild_role_update_packet.dart | 11 +++----- .../listeners/message_create_packet.dart | 22 ++++++---------- 14 files changed, 70 insertions(+), 96 deletions(-) diff --git a/lib/infrastructure/internals/cache/cache_provider_contract.dart b/lib/infrastructure/internals/cache/cache_provider_contract.dart index 30847556..35c16c2d 100644 --- a/lib/infrastructure/internals/cache/cache_provider_contract.dart +++ b/lib/infrastructure/internals/cache/cache_provider_contract.dart @@ -9,29 +9,33 @@ abstract interface class CacheProviderContract { FutureOr init(); - Future length(); + FutureOr length(); - Future> inspect(); + FutureOr> inspect(); FutureOr?> get(String? key); + FutureOr?>> getMany(List keys); + FutureOr> getOrFail(String key, {Exception Function()? onFail}); - Future?> whereKeyStartsWith(String prefix); + FutureOr?> whereKeyStartsWith(String prefix); + + FutureOr> whereKeyStartsWithOrFail(String prefix, {Exception Function()? onFail}); - Future> whereKeyStartsWithOrFail(String prefix, {Exception Function()? onFail}); + FutureOr has(String key); - Future has(String key); + FutureOr put(String key, T object); - Future put(String key, T object); + FutureOr putMany(Map object); - Future remove(String key); + FutureOr remove(String key); - Future removeMany(List key); + FutureOr removeMany(List key); - Future clear(); + FutureOr clear(); - Future dispose(); + FutureOr dispose(); - Future getHealth(); + FutureOr getHealth(); } diff --git a/lib/infrastructure/internals/datastore/parts/channel_part.dart b/lib/infrastructure/internals/datastore/parts/channel_part.dart index 788af69c..b3b8bf88 100644 --- a/lib/infrastructure/internals/datastore/parts/channel_part.dart +++ b/lib/infrastructure/internals/datastore/parts/channel_part.dart @@ -149,9 +149,9 @@ final class ChannelPart implements DataStorePart { final rawServer = await _kernel.marshaller.serializers.server.deserialize(server); - await Future.wait([ - _kernel.marshaller.cache.put('server-${server.id}', rawServer), - _kernel.marshaller.cache.put('server-${server.id}/channel-${channel.id}', rawChannel) - ]); + await _kernel.marshaller.cache.putMany({ + _kernel.marshaller.cacheKey.server(server.id): rawServer, + _kernel.marshaller.cacheKey.channel(channel.id): rawChannel, + }); } } diff --git a/lib/infrastructure/internals/datastore/parts/server_part.dart b/lib/infrastructure/internals/datastore/parts/server_part.dart index 73781706..2b849388 100644 --- a/lib/infrastructure/internals/datastore/parts/server_part.dart +++ b/lib/infrastructure/internals/datastore/parts/server_part.dart @@ -37,21 +37,21 @@ final class ServerPart implements DataStorePart { 'members': membersResponse.body }); - await Future.wait([ - _kernel.marshaller.cache.put(serverCacheKey, await _kernel.marshaller.serializers.server.deserialize(server)), - ...server.channels.list.values.map((channel) { + await _kernel.marshaller.cache.putMany({ + serverCacheKey: await _kernel.marshaller.serializers.server.deserialize(server), + ...server.channels.list.values.fold({}, (acc, channel) { final channelCacheKey = cacheKey.channel(channel.id); final rawChannel = _kernel.marshaller.serializers.channels.deserialize(channel); - return _kernel.marshaller.cache.put(channelCacheKey, rawChannel); + return { ...acc, channelCacheKey: rawChannel }; }), - ...server.members.list.values.map((member) { + ...server.members.list.values.fold({}, (acc, member) { final memberCacheKey = cacheKey.serverMember(serverId: id, memberId: member.id); final rawMember = _kernel.marshaller.serializers.member.deserialize(member); - return _kernel.marshaller.cache.put(memberCacheKey, rawMember); + return { ...acc, memberCacheKey: rawMember }; }) - ]); + }); return server; } diff --git a/lib/infrastructure/internals/packets/listeners/channel_delete_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_delete_packet.dart index 4cfba3d3..5c08ef82 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_delete_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_delete_packet.dart @@ -35,10 +35,9 @@ final class ChannelDeletePacket implements ListenablePacket { server.channels.list.remove(channel.id); final rawServer = await marshaller.serializers.server.deserialize(server); - await Future.wait([ - marshaller.cache.put(serverCacheKey, rawServer), - marshaller.cache.remove(channelCacheKey) - ]); + + await marshaller.cache.put(serverCacheKey, rawServer); + await marshaller.cache.remove(channelCacheKey); dispatch(event: Event.serverChannelDelete, params: [channel]); } diff --git a/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart index 9237e381..4fb5e0a7 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart @@ -29,18 +29,16 @@ final class ChannelPinsUpdatePacket implements ListenablePacket { Future registerServerChannelPins(ServerChannel channel, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(channel.guildId); - final serverCacheKey = marshaller.cacheKey.server(server.id); - final channelCacheKey = marshaller.cacheKey.channel(channel.id); server.channels.list.update(channel.id, (_) => channel); final rawServer = await marshaller.serializers.server.deserialize(server); final rawChannel = await marshaller.serializers.channels.deserialize(channel); - await Future.wait([ - marshaller.cache.put(serverCacheKey, rawServer), - marshaller.cache.put(channelCacheKey, rawChannel) - ]); + await marshaller.cache.putMany({ + marshaller.cacheKey.server(server.id): rawServer, + marshaller.cacheKey.channel(channel.id): rawChannel + }); dispatch(event: Event.serverChannelPinsUpdate, params: [server, channel]); } diff --git a/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart index 2b2729f8..be113b2c 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart @@ -29,9 +29,6 @@ final class ChannelUpdatePacket implements ListenablePacket { Future registerServerChannel(ServerChannel channel, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(channel.guildId); - final serverCacheKey = marshaller.cacheKey.server(server.id); - final channelCacheKey = - marshaller.cacheKey.channel(channel.id); final before = server.channels.list[channel.id]; @@ -40,10 +37,11 @@ final class ChannelUpdatePacket implements ListenablePacket { final rawServer = await marshaller.serializers.server.deserialize(server); final rawChannel = await marshaller.serializers.channels.deserialize(channel); - await Future.wait([ - marshaller.cache.put(serverCacheKey, rawServer), - marshaller.cache.put(channelCacheKey, rawChannel) - ]); + + await marshaller.cache.putMany({ + marshaller.cacheKey.server(server.id): rawServer, + marshaller.cacheKey.channel(channel.id): rawChannel + }); dispatch(event: Event.serverChannelUpdate, params: [before, channel]); } diff --git a/lib/infrastructure/internals/packets/listeners/guild_ban_add_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_ban_add_packet.dart index a50c2d53..936630f5 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_ban_add_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_ban_add_packet.dart @@ -3,7 +3,6 @@ import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; import 'package:mineral/infrastructure/internals/packets/listenable_packet.dart'; import 'package:mineral/infrastructure/internals/packets/packet_type.dart'; import 'package:mineral/infrastructure/internals/wss/shard_message.dart'; -import 'package:mineral/infrastructure/services/logger/logger.dart'; final class GuildBanAddPacket implements ListenablePacket { @override @@ -27,10 +26,8 @@ final class GuildBanAddPacket implements ListenablePacket { server.members.list.remove(user.id); - await Future.wait([ - marshaller.cache.remove(memberCacheKey), - marshaller.cache.put(serverCacheKey, rawServer), - ]); + await marshaller.cache.remove(memberCacheKey); + await marshaller.cache.put(serverCacheKey, rawServer); dispatch(event: Event.serverBanAdd, params: [member, user, server]); } diff --git a/lib/infrastructure/internals/packets/listeners/guild_member_add_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_member_add_packet.dart index bb43d5ee..b7c2654c 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_member_add_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_member_add_packet.dart @@ -20,18 +20,15 @@ final class GuildMemberAddPacket implements ListenablePacket { final member = await marshaller.serializers.member .serializeRemote({...message.payload, 'guild_roles': server.roles.list.values.toList()}); - final serverCacheKey = marshaller.cacheKey.server(server.id); - final memberCacheKey = - marshaller.cacheKey.serverMember(serverId: server.id, memberId: member.id); - server.members.list.putIfAbsent(member.id, () => member); final rawServer = await marshaller.serializers.server.deserialize(server); final rawMember = await marshaller.serializers.member.deserialize(member); - await Future.wait([ - marshaller.cache.put(memberCacheKey, rawMember), - marshaller.cache.put(serverCacheKey, rawServer) - ]); + + await marshaller.cache.putMany({ + marshaller.cacheKey.server(server.id): rawServer, + marshaller.cacheKey.serverMember(serverId: server.id, memberId: member.id): rawMember + }); dispatch(event: Event.serverMemberAdd, params: [member, server]); } diff --git a/lib/infrastructure/internals/packets/listeners/guild_member_remove_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_member_remove_packet.dart index 491208a2..8095c027 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_member_remove_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_member_remove_packet.dart @@ -30,10 +30,9 @@ final class GuildMemberRemovePacket implements ListenablePacket { server.members.list.remove(memberId); final rawServer = await marshaller.serializers.server.deserialize(server); - await Future.wait([ - marshaller.cache.put(serverCacheKey, rawServer), - marshaller.cache.remove(memberCacheKey), - ]); + + await marshaller.cache.put(serverCacheKey, rawServer); + await marshaller.cache.remove(memberCacheKey); dispatch(event: Event.serverMemberRemove, params: [user, server]); } diff --git a/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart index 88add8f1..9e75882b 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart @@ -28,17 +28,13 @@ final class GuildMemberUpdatePacket implements ListenablePacket { server.members.list.update(after.id, (_) => after); - final serverCacheKey = marshaller.cacheKey.server(server.id); - final memberCacheKey = - marshaller.cacheKey.serverMember(serverId: server.id, memberId: after.id); - final rawServer = await marshaller.serializers.server.deserialize(server); final rawMember = await marshaller.serializers.member.deserialize(after); - await Future.wait([ - marshaller.cache.put(serverCacheKey, rawServer), - marshaller.cache.put(memberCacheKey, rawMember), - ]); + await marshaller.cache.putMany({ + marshaller.cacheKey.server(server.id): rawServer, + marshaller.cacheKey.serverMember(serverId: server.id, memberId: after.id): rawMember + }); dispatch(event: Event.serverMemberUpdate, params: [before, after]); } diff --git a/lib/infrastructure/internals/packets/listeners/guild_role_create_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_role_create_packet.dart index af097b22..ac38d669 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_role_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_role_create_packet.dart @@ -19,18 +19,15 @@ final class GuildRoleCreatePacket implements ListenablePacket { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); final role = await marshaller.serializers.role.serializeRemote(message.payload['role']); - final serverCacheKey = marshaller.cacheKey.server(server.id); - final roleCacheKey = marshaller.cacheKey.serverRole(serverId: server.id, roleId: role.id); - server.roles.list.putIfAbsent(role.id, () => role); final rawServer = await marshaller.serializers.server.deserialize(server); final rawRole = await marshaller.serializers.role.deserialize(role); - await Future.wait([ - marshaller.cache.put(serverCacheKey, rawServer), - marshaller.cache.put(roleCacheKey, rawRole), - ]); + await marshaller.cache.putMany({ + marshaller.cacheKey.server(server.id): rawServer, + marshaller.cacheKey.serverRole(serverId: server.id, roleId: role.id): rawRole, + }); dispatch(event: Event.serverRoleCreate, params: [role, server]); } diff --git a/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart index 2a5ee640..dc9bbe15 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart @@ -28,10 +28,8 @@ final class GuildRoleDeletePacket implements ListenablePacket { final roleCacheKey = marshaller.cacheKey.serverRole(serverId: server.id, roleId: role.id); final rawServer = await marshaller.serializers.server.deserialize(server); - await Future.wait([ - marshaller.cache.put(serverCacheKey, rawServer), - marshaller.cache.remove(roleCacheKey), - ]); + await marshaller.cache.put(serverCacheKey, rawServer); + await marshaller.cache.remove(roleCacheKey); dispatch(event: Event.serverRoleDelete, params: [role, server]); } diff --git a/lib/infrastructure/internals/packets/listeners/guild_role_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_role_update_packet.dart index d519fd44..8fd39fe9 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_role_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_role_update_packet.dart @@ -23,17 +23,14 @@ final class GuildRoleUpdatePacket implements ListenablePacket { server.roles.list.update(after.id, (_) => after); - final serverCacheKey = marshaller.cacheKey.server(server.id); - final roleCacheKey = marshaller.cacheKey.serverRole(serverId: server.id, roleId: after.id); - final rawServer = await marshaller.serializers.server.deserialize(server); final rawRole = await marshaller.serializers.role.deserialize(after); dispatch(event: Event.serverRoleUpdate, params: [before, after, server]); - await Future.wait([ - marshaller.cache.put(serverCacheKey, rawServer), - marshaller.cache.put(roleCacheKey, rawRole), - ]); + await marshaller.cache.putMany({ + marshaller.cacheKey.server(server.id): rawServer, + marshaller.cacheKey.serverRole(serverId: server.id, roleId: after.id): rawRole, + }); } } diff --git a/lib/infrastructure/internals/packets/listeners/message_create_packet.dart b/lib/infrastructure/internals/packets/listeners/message_create_packet.dart index 25ac9118..ee4cb675 100644 --- a/lib/infrastructure/internals/packets/listeners/message_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/message_create_packet.dart @@ -48,16 +48,13 @@ final class MessageCreatePacket implements ListenablePacket { case ServerAnnouncementChannel(): channel.messages.list.putIfAbsent(message.id, () => message); } - final serverCacheKey = marshaller.cacheKey.server(server.id); - final messageCacheKey = marshaller.cacheKey.serverMessage(channelId: channel!.id, messageId: message.id); - final rawServer = await marshaller.serializers.server.deserialize(server); final rawMessage = await marshaller.serializers.serverMessage.deserialize(message); - await Future.wait([ - marshaller.cache.put(serverCacheKey, rawServer), - marshaller.cache.put(messageCacheKey, rawMessage), - ]); + await marshaller.cache.putMany({ + marshaller.cacheKey.server(server.id): rawServer, + marshaller.cacheKey.serverMessage(channelId: channel!.id, messageId: message.id): rawMessage, + }); dispatch(event: Event.serverMessageCreate, params: [message]); } @@ -70,16 +67,13 @@ final class MessageCreatePacket implements ListenablePacket { message.channel = channel; channel.messages.list.putIfAbsent(message.id, () => message); - final channelCacheKey = marshaller.cacheKey.channel(channel.id); - final messageCacheKey = marshaller.cacheKey.privateMessage(channelId: channel.id, messageId: message.id); - final rawChannel = await marshaller.serializers.channels.deserialize(channel); final rawMessage = await marshaller.serializers.privateMessage.deserialize(message); - await Future.wait([ - marshaller.cache.put(channelCacheKey, rawChannel), - marshaller.cache.put(messageCacheKey, rawMessage), - ]); + await marshaller.cache.putMany({ + marshaller.cacheKey.channel(channel.id): rawChannel, + marshaller.cacheKey.privateMessage(channelId: channel.id, messageId: message.id): rawMessage, + }); dispatch(event: Event.privateMessageCreate, params: [message]); } From a59e6e6f717c750dfb7a79144d964d2556191fda Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Fri, 16 Aug 2024 21:44:15 +0200 Subject: [PATCH 02/44] fix(datastore): rework server serializers --- lib/api/common/emoji.dart | 2 - lib/api/common/polls/poll.dart | 3 + lib/api/server/managers/channel_manager.dart | 29 ++- lib/api/server/member.dart | 2 - lib/api/server/member_assets.dart | 16 +- .../internals/marshaller/cache_key.dart | 65 +++--- .../internals/marshaller/marshaller.dart | 4 +- .../marshaller/serializer_bucket.dart | 15 +- ...annel_permission_overwrite_serializer.dart | 25 +- .../serializers/embed_serializer.dart | 25 +- .../serializers/emoji_serializer.dart | 47 ++-- .../serializers/member_assets_serializer.dart | 52 +++++ .../serializers/member_serializer.dart | 110 ++++----- .../serializers/poll_serializer.dart | 53 +++-- .../serializers/role_serializer.dart | 19 +- .../serializers/server_assets_serializer.dart | 30 ++- .../serializers/server_serializer.dart | 215 ++++++------------ .../server_settings_serializer.dart | 69 ++++-- .../marshaller/types/serializer.dart | 4 +- pubspec.yaml | 1 + 20 files changed, 428 insertions(+), 358 deletions(-) create mode 100644 lib/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart diff --git a/lib/api/common/emoji.dart b/lib/api/common/emoji.dart index 6706d957..8146d0d4 100644 --- a/lib/api/common/emoji.dart +++ b/lib/api/common/emoji.dart @@ -3,7 +3,6 @@ import 'package:mineral/api/common/snowflake.dart'; import 'package:mineral/api/server/role.dart'; final class Emoji extends PartialEmoji { - final String? globalName; final Map roles; final bool managed; final bool available; @@ -11,7 +10,6 @@ final class Emoji extends PartialEmoji { Emoji({ required Snowflake id, required String name, - required this.globalName, required this.roles, required this.managed, required this.available, diff --git a/lib/api/common/polls/poll.dart b/lib/api/common/polls/poll.dart index 602665c5..3004a203 100644 --- a/lib/api/common/polls/poll.dart +++ b/lib/api/common/polls/poll.dart @@ -1,12 +1,14 @@ import 'package:mineral/api/common/polls/poll_answer.dart'; import 'package:mineral/api/common/polls/poll_layout.dart'; import 'package:mineral/api/common/polls/poll_question.dart'; +import 'package:mineral/api/common/snowflake.dart'; final class Poll { final PollQuestion question; final List answers; final Duration? expireAt; final bool isAllowMultiple; + final Snowflake messageId; final PollLayout layout; Poll({ @@ -14,6 +16,7 @@ final class Poll { required this.answers, required this.expireAt, required this.isAllowMultiple, + required this.messageId, this.layout = PollLayout.initial, }); } diff --git a/lib/api/server/managers/channel_manager.dart b/lib/api/server/managers/channel_manager.dart index 7c2f10bd..0009676a 100644 --- a/lib/api/server/managers/channel_manager.dart +++ b/lib/api/server/managers/channel_manager.dart @@ -14,16 +14,17 @@ enum _ServerNamedChannel { final class ChannelManager { final Map<_ServerNamedChannel, Snowflake?> _namedChannels = {}; - final Map _channels = {}; - - ChannelManager(Map json) { - _namedChannels..putIfAbsent( - _ServerNamedChannel.afkChannel, () => json['afk_channel_id'])..putIfAbsent( - _ServerNamedChannel.systemChannel, () => json['system_channel_id'])..putIfAbsent( - _ServerNamedChannel.rulesChannel, () => json['rules_channel_id'])..putIfAbsent( - _ServerNamedChannel - .publicUpdatesChannel, () => json['public_updates_channel_id'])..putIfAbsent( - _ServerNamedChannel.safetyAlertsChannel, () => json['safety_alerts_channel_id']); + final Map _channels; + + ChannelManager(this._channels, Map json) { + _namedChannels + ..putIfAbsent(_ServerNamedChannel.afkChannel, () => json['afk_channel_id']) + ..putIfAbsent(_ServerNamedChannel.systemChannel, () => json['system_channel_id']) + ..putIfAbsent(_ServerNamedChannel.rulesChannel, () => json['rules_channel_id']) + ..putIfAbsent( + _ServerNamedChannel.publicUpdatesChannel, () => json['public_updates_channel_id']) + ..putIfAbsent( + _ServerNamedChannel.safetyAlertsChannel, () => json['safety_alerts_channel_id']); } Map get list => _channels; @@ -51,4 +52,12 @@ final class ChannelManager { ServerTextChannel? get widgetChannel => getOrNull(_namedChannels[_ServerNamedChannel.widgetChannel]); + + factory ChannelManager.fromList(List channels, payload) { + return ChannelManager( + Map.from(channels.fold({}, (value, element) { + return {...value, element.id: element}; + })), + payload); + } } diff --git a/lib/api/server/member.dart b/lib/api/server/member.dart index f5f258bd..59c2fa64 100644 --- a/lib/api/server/member.dart +++ b/lib/api/server/member.dart @@ -37,7 +37,6 @@ final class Member { final PremiumTier premiumType; final DateTime? joinedAt; final Permissions permissions; - final bool pending; final int? accentColor; final MemberFlagsManager flags; Presence? presence; @@ -114,7 +113,6 @@ final class Member { required this.premiumType, required this.joinedAt, required this.permissions, - required this.pending, required this.accentColor, required this.presence, }) { diff --git a/lib/api/server/member_assets.dart b/lib/api/server/member_assets.dart index f4adbb92..423c2da7 100644 --- a/lib/api/server/member_assets.dart +++ b/lib/api/server/member_assets.dart @@ -1,26 +1,16 @@ import 'package:mineral/api/common/image_asset.dart'; -import 'package:mineral/infrastructure/commons/helper.dart'; +import 'package:mineral/api/common/snowflake.dart'; final class MemberAssets { final ImageAsset? avatar; final ImageAsset? avatarDecoration; final ImageAsset? banner; + final Snowflake memberId; MemberAssets({ required this.avatar, required this.avatarDecoration, required this.banner, + required this.memberId, }); - - factory MemberAssets.fromJson(Map json) { - return MemberAssets( - avatar: Helper.createOrNull( - field: json['avatar'], fn: () => ImageAsset(['avatars', json['id']], json['avatar'])), - avatarDecoration: Helper.createOrNull( - field: json['avatar_decoration_data']?['sku_id'], - fn: () => ImageAsset(['avatar-decorations', json['id']], json['avatar_decoration_data']['sku_id'])), - banner: Helper.createOrNull( - field: json['banner'], fn: () => ImageAsset(['banners', json['id']], json['banner'])), - ); - } } diff --git a/lib/infrastructure/internals/marshaller/cache_key.dart b/lib/infrastructure/internals/marshaller/cache_key.dart index 4983e71e..0adb5283 100644 --- a/lib/infrastructure/internals/marshaller/cache_key.dart +++ b/lib/infrastructure/internals/marshaller/cache_key.dart @@ -1,46 +1,53 @@ import 'package:mineral/api/common/snowflake.dart'; +import 'package:uuid/uuid.dart'; -abstract interface class CacheKeyContract { - String server(Snowflake id); +final class CacheKey { + String server(Snowflake id, {bool ref = false}) { + final key = 'server/$id'; + return ref ? '$key:ref' : key; + } - String channel(Snowflake id); + String serverAssets(Snowflake serverId, {bool ref = false}) { + final key = '${server(serverId)}/assets'; + return ref ? 'ref:$key' : key; + } - String serverRole({required Snowflake serverId, required Snowflake roleId}); + String serverSettings(Snowflake serverId, {bool ref = false}) { + final key = '${server(serverId)}/settings'; + return ref ? 'ref:$key' : key; + } - String serverMember({required Snowflake serverId, required Snowflake memberId}); + String channel(Snowflake channelId, {Snowflake? serverId}) => + serverId != null ? '${server(serverId)}/channels/$channelId' : 'channel/$channelId'; - String serverEmoji({required Snowflake serverId, required Snowflake emojiId}); + String channelPermission(Snowflake channelId, {Snowflake? serverId}) => + '${channel(channelId, serverId: serverId)}/permissions'; - String serverMessage({required Snowflake channelId, required Snowflake messageId}); + String serverRole(Snowflake serverId, Snowflake roleId, {bool ref = false}) => + '${server(serverId)}/role/$roleId'; - String privateMessage({required Snowflake channelId, required Snowflake messageId}); -} - -final class CacheKey implements CacheKeyContract { - @override - String server(Snowflake id) => 'server-$id'; - - @override - String channel(Snowflake channelId) => - 'channel-$channelId'; + String member(Snowflake serverId, Snowflake memberId, {bool ref = false}) { + final key = '${server(serverId)}/members/$memberId'; + return ref ? 'ref:$key' : key; + } - @override - String serverRole({required Snowflake serverId, required Snowflake roleId}) => - '${server(serverId)}/role-$roleId'; + String memberAssets(Snowflake serverId, Snowflake memberId, {bool ref = false}) { + final key = '${member(serverId, memberId)}/assets'; + return ref ? 'ref:$key' : key; + } - @override - String serverMember({required Snowflake serverId, required Snowflake memberId}) => - '${server(serverId)}/member-$memberId'; + String serverEmoji(Snowflake serverId, Snowflake emojiId, {bool ref = false}) { + final key = '${server(serverId)}/emojis/$emojiId'; + return ref ? 'ref:$key' : key; + } - @override - String serverEmoji({required Snowflake serverId, required Snowflake emojiId}) => - '${server(serverId)}/emoji-$emojiId'; - - @override String serverMessage({required Snowflake channelId, required Snowflake messageId}) => '${channel(channelId)}/message-$messageId'; - @override String privateMessage({required Snowflake channelId, required Snowflake messageId}) => '${channel(channelId)}/message-$messageId'; + + String embed(Snowflake messageId, { String? uid }) => 'messages/$messageId/embeds/${uid ?? Uuid().v4()}'; + + String poll(Snowflake messageId, { String? uid }) => 'messages/$messageId/polls/${uid ?? Uuid().v4()}'; } diff --git a/lib/infrastructure/internals/marshaller/marshaller.dart b/lib/infrastructure/internals/marshaller/marshaller.dart index ceb335b4..17c075b8 100644 --- a/lib/infrastructure/internals/marshaller/marshaller.dart +++ b/lib/infrastructure/internals/marshaller/marshaller.dart @@ -14,7 +14,7 @@ abstract interface class MarshallerContract { CacheProviderContract get cache; - CacheKeyContract get cacheKey; + CacheKey get cacheKey; } final class Marshaller implements MarshallerContract { @@ -31,7 +31,7 @@ final class Marshaller implements MarshallerContract { final CacheProviderContract cache; @override - final CacheKeyContract cacheKey = CacheKey(); + final CacheKey cacheKey = CacheKey(); Marshaller(this.logger, this.cache) { serializers = SerializerBucket(this); diff --git a/lib/infrastructure/internals/marshaller/serializer_bucket.dart b/lib/infrastructure/internals/marshaller/serializer_bucket.dart index a2328831..a39f544c 100644 --- a/lib/infrastructure/internals/marshaller/serializer_bucket.dart +++ b/lib/infrastructure/internals/marshaller/serializer_bucket.dart @@ -7,6 +7,7 @@ import 'package:mineral/api/common/sticker.dart'; import 'package:mineral/api/private/private_message.dart'; import 'package:mineral/api/private/user.dart'; import 'package:mineral/api/server/member.dart'; +import 'package:mineral/api/server/member_assets.dart'; import 'package:mineral/api/server/role.dart'; import 'package:mineral/api/server/server.dart'; import 'package:mineral/api/server/server_assets.dart'; @@ -21,6 +22,7 @@ import 'package:mineral/infrastructure/internals/marshaller/serializers/channel_ import 'package:mineral/infrastructure/internals/marshaller/serializers/embed_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/emoji_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/global_command_context_serializer.dart'; +import 'package:mineral/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/member_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/poll_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/private_message_serializer.dart'; @@ -42,6 +44,8 @@ final class SerializerBucket { final SerializerContract member; + final SerializerContract memberAssets; + final SerializerContract user; final SerializerContract role; @@ -74,18 +78,19 @@ final class SerializerBucket { : channels = ChannelSerializer(marshaller), server = ServerSerializer(marshaller), member = MemberSerializer(marshaller), - user = UserSerializer(), + memberAssets = MemberAssetsSerializer(marshaller), + user = UserSerializer(marshaller), role = RoleSerializer(marshaller), - serverSubscription = ServerSubscriptionSerializer(), + serverSubscription = ServerSubscriptionSerializer(marshaller), serverSettings = ServerSettingsSerializer(marshaller), serversAsset = ServerAssetsSerializer(marshaller), emojis = EmojiSerializer(marshaller), - sticker = StickerSerializer(), + sticker = StickerSerializer(marshaller), channelPermissionOverwrite = ChannelPermissionOverwriteSerializer(marshaller), serverMessage = ServerMessageSerializer(marshaller), privateMessage = PrivateMessageSerializer(marshaller), - embed = EmbedSerializer(), + embed = EmbedSerializer(marshaller), globalCommandContext = GlobalCommandContextSerializer(marshaller), guildCommandContext = ServerCommandContextSerializer(marshaller), - poll = PollSerializer(); + poll = PollSerializer(marshaller); } diff --git a/lib/infrastructure/internals/marshaller/serializers/channel_permission_overwrite_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/channel_permission_overwrite_serializer.dart index 45a3b9d0..36d9b552 100644 --- a/lib/infrastructure/internals/marshaller/serializers/channel_permission_overwrite_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/channel_permission_overwrite_serializer.dart @@ -11,17 +11,26 @@ final class ChannelPermissionOverwriteSerializer ChannelPermissionOverwriteSerializer(this.marshaller); @override - ChannelPermissionOverwrite serializeRemote(Map json) => _serialize(json); + Future normalize(Map json) async { + final payload = { + 'id': json['id'], + 'type': json['type'], + 'allow': json['allow'], + 'deny': json['deny'], + }; - @override - ChannelPermissionOverwrite serializeCache(Map json) => _serialize(json); + final cacheKey = marshaller.cacheKey + .channelPermission(Snowflake(payload['id']), serverId: json['server_id']); + await marshaller.cache.put(cacheKey, payload); + } - ChannelPermissionOverwrite _serialize(Map payload) { + @override + ChannelPermissionOverwrite serialize(Map json) { return ChannelPermissionOverwrite( - id: Snowflake(payload['id']), - type: findInEnum(ChannelPermissionOverwriteType.values, payload['type']), - allow: payload['allow'], - deny: payload['deny'], + id: Snowflake(json['id']), + type: findInEnum(ChannelPermissionOverwriteType.values, json['type']), + allow: json['allow'], + deny: json['deny'], ); } diff --git a/lib/infrastructure/internals/marshaller/serializers/embed_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/embed_serializer.dart index 700ef1b4..6a34fbf6 100644 --- a/lib/infrastructure/internals/marshaller/serializers/embed_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/embed_serializer.dart @@ -12,7 +12,25 @@ import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dar final class EmbedSerializer implements SerializerContract { @override - MessageEmbed serializeRemote(Map json) { + Future normalize(Map json) async { + final payload = { + 'title': json['title'], + 'description': json['description'], + 'type': json['type'], + 'url': json['url'], + 'timestamp': json['timestamp'], + 'assets': json['assets'], + 'provider': json['provider'], + 'fields': json['fields'], + 'color': json['color'] + }; + + final cacheKey = _marshaller.cacheKey.embed(json['id']); + await _marshaller.cache.put(cacheKey, payload); + } + + @override + Future serialize(Map json) async { return MessageEmbed( title: json['title'], description: json['description'], @@ -31,11 +49,6 @@ final class EmbedSerializer implements SerializerContract { ); } - @override - Future serializeCache(Map json) { - throw UnimplementedError(); - } - @override Map deserialize(MessageEmbed embed) { return { diff --git a/lib/infrastructure/internals/marshaller/serializers/emoji_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/emoji_serializer.dart index e2efe4ed..25f949db 100644 --- a/lib/infrastructure/internals/marshaller/serializers/emoji_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/emoji_serializer.dart @@ -1,9 +1,6 @@ import 'dart:async'; -import 'package:collection/collection.dart'; import 'package:mineral/api/common/emoji.dart'; -import 'package:mineral/api/common/snowflake.dart'; -import 'package:mineral/api/server/role.dart'; import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; @@ -13,42 +10,32 @@ final class EmojiSerializer implements SerializerContract { EmojiSerializer(this._marshaller); @override - Emoji serializeRemote(Map json) { - final guildRoles = List.from(json['guildRoles']); - - final Map roles = List.from(json['roles']).fold({}, (value, element) { - final role = guildRoles.firstWhereOrNull((role) => role.id.value == element); - - if (role == null) { - // Todo add report case - return value; - } - - return {...value, role.id: role}; - }); + Future normalize(Map json) async { + final payload = { + 'id': json['id'], + 'name': json['name'], + 'managed': json['managed'] ?? false, + 'available': json['available'] ?? false, + 'animated': json['animated'] ?? false, + 'roles': List.from(json['roles']) + .map((element) => _marshaller.cacheKey.serverEmoji(json['server_id'], element['id'])) + .toList(), + }; - return Emoji( - id: json['id'], - name: json['name'], - globalName: json['global_name'], - roles: roles, - managed: json['managed'], - animated: json['animated'], - available: json['available'], - ); + final cacheKey = _marshaller.cacheKey.serverEmoji(json['server_id'], json['id']); + await _marshaller.cache.put(cacheKey, payload); } @override - Future serializeCache(Map json) async { - final roles = await List.from(json['roles']).map((id) async { - final rawRole = await _marshaller.cache.getOrFail('server-${json['serverId']}/role-$id'); - return _marshaller.serializers.role.serializeCache(rawRole); + Future serialize(Map json) async { + final rawRoles = await _marshaller.cache.getMany(json['roles']); + final roles = await rawRoles.nonNulls.map((element) async { + return _marshaller.serializers.role.serialize(element); }).wait; return Emoji( id: json['id'], name: json['name'], - globalName: json['global_name'], roles: roles.fold({}, (value, element) => {...value, element.id: element}), managed: json['managed'], animated: json['animated'], diff --git a/lib/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart new file mode 100644 index 00000000..85ee0916 --- /dev/null +++ b/lib/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart @@ -0,0 +1,52 @@ +import 'package:mineral/api/common/image_asset.dart'; +import 'package:mineral/api/common/snowflake.dart'; +import 'package:mineral/api/server/member_assets.dart'; +import 'package:mineral/infrastructure/commons/helper.dart'; +import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; +import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; + +final class MemberAssetsSerializer implements SerializerContract { + final MarshallerContract _marshaller; + + MemberAssetsSerializer(this._marshaller); + + @override + Future normalize(Map json) async { + final payload = { + 'member_id': json['member_id'], + 'avatar': json['avatar'], + 'avatar_decoration': json['avatar_decoration_data']?['sku_id'], + 'banner': json['banner'], + }; + + final cacheKey = _marshaller.cacheKey.memberAssets(json['guild_id'], json['user']['id']); + await _marshaller.cache.put(cacheKey, payload); + } + + @override + Future serialize(Map json) async { + return MemberAssets( + avatar: Helper.createOrNull( + field: json['avatar'], + fn: () => ImageAsset(['avatars', json['member_id']], json['avatar'])), + avatarDecoration: Helper.createOrNull( + field: json['avatar_decoration'], + fn: () => + ImageAsset(['avatar-decorations', json['member_id']], json['avatar_decoration'])), + banner: Helper.createOrNull( + field: json['banner'], + fn: () => ImageAsset(['banners', json['member_id']], json['banner'])), + memberId: Snowflake(json['member_id']), + ); + } + + @override + Map deserialize(MemberAssets assets) { + return { + 'member_id': assets.memberId.value, + 'avatar': assets.avatar?.hash, + 'avatar_decoration': assets.avatarDecoration?.hash, + 'banner': assets.banner?.hash, + }; + } +} diff --git a/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart index d36aaf6d..3fd1106d 100644 --- a/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart @@ -4,10 +4,8 @@ import 'package:mineral/api/common/presence.dart'; import 'package:mineral/api/server/enums/member_flag.dart'; import 'package:mineral/api/server/managers/member_role_manager.dart'; import 'package:mineral/api/server/member.dart'; -import 'package:mineral/api/server/member_assets.dart'; import 'package:mineral/api/server/member_flags.dart'; import 'package:mineral/api/server/member_timeout.dart'; -import 'package:mineral/api/server/role.dart'; import 'package:mineral/infrastructure/commons/helper.dart'; import 'package:mineral/infrastructure/commons/utils.dart'; import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; @@ -19,81 +17,74 @@ final class MemberSerializer implements SerializerContract { MemberSerializer(this._marshaller); @override - Future serializeRemote(Map json) async { - final serverRoles = json.entries.firstWhere((element) => element.key == 'guild_roles', - orElse: () => throw FormatException('Server roles not found in member structure')); + Future normalize(Map json) async { + await _marshaller.serializers.memberAssets.normalize({ + ...json, + 'member_id': json['id'], + }); - final member = Member( - id: json['user']['id'], - username: json['user']['nick'] ?? json['user']['username'], - nickname: json['nick'] ?? json['user']['display_name'], - globalName: json['user']['global_name'], - discriminator: json['user']['discriminator'], - assets: MemberAssets.fromJson(json['user']), - flags: MemberFlagsManager(bitfieldToList(MemberFlag.values, json['flags'])), - premiumSince: Helper.createOrNull( - field: json['premium_since'], fn: () => DateTime.parse(json['premium_since'])), - publicFlags: json['user']['public_flags'], - roles: MemberRoleManager.fromList(serverRoles.value), - isBot: json['user']['bot'] ?? false, - isPending: json['pending'] ?? false, - timeout: MemberTimeout( - duration: Helper.createOrNull( - field: json['communication_disabled_until'], - fn: () => DateTime.parse(json['communication_disabled_until']))), - mfaEnabled: json['user']['mfa_enabled'] ?? false, - locale: json['user']['locale'], - premiumType: PremiumTier.values - .firstWhere((e) => e == json['user']['premium_type'], orElse: () => PremiumTier.none), - joinedAt: Helper.createOrNull( - field: json['joined_at'], fn: () => DateTime.parse(json['joined_at'])), - permissions: switch (json['permissions']) { - int() => Permissions.fromInt(json['permissions']), - String() => Permissions.fromInt(int.parse(json['permissions'])), - _ => Permissions.fromInt(0), - }, - pending: json['pending'] ?? false, - accentColor: json['accent_color'], - presence: json['presence'] != null ? Presence.fromJson(json['presence']) : null, - ); - - member.roles.member = member; - member.flags.member = member; + final payload = { + 'id': json['user']['id'], + 'username': json['user']['username'], + 'nickname': json['nick'], + 'global_name': json['user']['global_name'], + 'discriminator': json['user']['discriminator'], + 'assets': _marshaller.cacheKey.memberAssets(json['server_id'], json['user']['id']), + 'flags': json['flags'], + 'roles': List.from(json['roles']) + .map((element) => _marshaller.cacheKey.serverRole(json['server_id_id'], element['id'])) + .toList(), + 'premium_since': json['premium_since'], + 'public_flags': json['user']['public_flags'], + 'is_bot': json['user']['bot'] ?? false, + 'is_pending': json['pending'] ?? false, + 'timeout': json['communication_disabled_until'], + 'mfa_enabled': json['user']['mfa_enabled'] ?? false, + 'locale': json['user']['locale'], + 'premium_type': json['user']['premium_type'], + 'joined_at': json['joined_at'], + 'permissions': json['permissions'], + 'pending': json['pending'] ?? false, + 'accent_color': json['accent_color'], + // TODO : presence + }; - return member; + final cacheKey = _marshaller.cacheKey.member(json['guild_id'], json['user']['id']); + await _marshaller.cache.put(cacheKey, payload); } @override - Future serializeCache(Map json) async { - final List serializedRoles = await List.from(json['roles']).map((element) async { - final cacheKey = _marshaller.cacheKey.serverRole(serverId: json['guild_id'], roleId: element); + Future serialize(Map json) async { + final rawAssets = await _marshaller.cache.getOrFail(json['assets']); + final assets = await _marshaller.serializers.memberAssets.serialize(rawAssets); - final rawRole = await _marshaller.cache.getOrFail(cacheKey); - return _marshaller.serializers.role.serializeCache(rawRole); + final rawRoles = await _marshaller.cache.getMany(json['roles']); + final roles = await rawRoles.nonNulls.map((element) async { + return _marshaller.serializers.role.serialize(element); }).wait; final member = Member( - id: json['user']['id'], - username: json['user']['nick'] ?? json['user']['username'], - nickname: json['nick'] ?? json['user']['display_name'], - globalName: json['user']['global_name'], - discriminator: json['user']['discriminator'], - assets: MemberAssets.fromJson(json['user']), + id: json['id'], + username: json['nick'] ?? json['username'], + nickname: json['nick'] ?? json['display_name'], + globalName: json['global_name'], + discriminator: json['discriminator'], + assets: assets, flags: MemberFlagsManager(bitfieldToList(MemberFlag.values, json['flags'])), premiumSince: Helper.createOrNull( field: json['premium_since'], fn: () => DateTime.parse(json['premium_since'])), - publicFlags: json['user']['public_flags'], - roles: MemberRoleManager.fromList(serializedRoles), - isBot: json['user']['bot'] ?? false, + publicFlags: json['public_flags'], + roles: MemberRoleManager.fromList(roles), + isBot: json['is_bot'] ?? false, isPending: json['pending'] ?? false, timeout: MemberTimeout( duration: Helper.createOrNull( field: json['communication_disabled_until'], fn: () => DateTime.parse(json['communication_disabled_until']))), - mfaEnabled: json['user']['mfa_enabled'] ?? false, - locale: json['user']['locale'], + mfaEnabled: json['mfa_enabled'] ?? false, + locale: json['locale'], premiumType: PremiumTier.values - .firstWhere((e) => e == json['user']['premium_type'], orElse: () => PremiumTier.none), + .firstWhere((e) => e == json['premium_type'], orElse: () => PremiumTier.none), joinedAt: Helper.createOrNull( field: json['joined_at'], fn: () => DateTime.parse(json['joined_at'])), permissions: switch (json['permissions']) { @@ -101,7 +92,6 @@ final class MemberSerializer implements SerializerContract { String() => Permissions.fromInt(int.parse(json['permissions'])), _ => Permissions.fromInt(0), }, - pending: json['pending'] ?? false, accentColor: json['accent_color'], presence: json['presence'] != null ? Presence.fromJson(json['presence']) : null, ); diff --git a/lib/infrastructure/internals/marshaller/serializers/poll_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/poll_serializer.dart index 7426e351..16c7adc3 100644 --- a/lib/infrastructure/internals/marshaller/serializers/poll_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/poll_serializer.dart @@ -1,38 +1,61 @@ +import 'package:mineral/api/common/partial_emoji.dart'; import 'package:mineral/api/common/polls/poll.dart'; import 'package:mineral/api/common/polls/poll_answer.dart'; import 'package:mineral/api/common/polls/poll_layout.dart'; import 'package:mineral/api/common/polls/poll_question.dart'; +import 'package:mineral/api/common/snowflake.dart'; import 'package:mineral/infrastructure/commons/helper.dart'; import 'package:mineral/infrastructure/commons/utils.dart'; import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; final class PollSerializer implements SerializerContract { @override - Poll serializeRemote(Map json) { + Future normalize(Map json) async { + final payload = { + 'message_id': json['message_id'], + 'question_text': json['question']['text'], + 'answers': List.from(json['answers']).map((element) => element['text']).toList(), + 'expiry': json['expiry'], + 'allow_multiselect': json['allow_multiselect'], + 'layout_type': json['layout_type'], + }; + + final cacheKey = _marshaller.cacheKey.poll(json['message_id']); + await _marshaller.cache.put(cacheKey, payload); + } + + @override + Poll serialize(Map json) { return Poll( - question: PollQuestion(content: json['question']['text']), + messageId: Snowflake(json['message_id']), + question: PollQuestion(content: json['question_text']), answers: List.from(json['answers']) - .map((element) => PollAnswer(content: element['text'])) + .map((element) => PollAnswer( + content: element['text'], + emoji: Helper.createOrNull( + field: element['emoji'], fn: () => PartialEmoji.fromUnicode(element['emoji'])))) .toList(), - expireAt: - Helper.createOrNull(field: json['expiry'], fn: () => DateTime.parse(json['expiry']).difference(DateTime.now())), + expireAt: Helper.createOrNull( + field: json['expiry'], + fn: () => DateTime.parse(json['expiry']).difference(DateTime.now())), isAllowMultiple: json['allow_multiselect'], layout: findInEnum(PollLayout.values, json['layout_type'])); } - @override - Future serializeCache(Map json) { - throw UnimplementedError(); - } - @override Map deserialize(Poll poll) { + final answers = poll.answers.map((element) { + return { + 'emoji': element.emoji, + 'text': element.content, + }; + }).toList(); + return { - 'question': { - 'text': poll.question.content, - }, - 'answers': poll.answers.map((e) => e.toJson()).toList(), - 'duration': poll.expireAt?.inHours, + 'message_id': poll.messageId, + 'question_text': poll.question.content, + 'answers': answers, + 'expiry': poll.expireAt?.inMilliseconds, 'allow_multiselect': poll.isAllowMultiple, 'layout_type': poll.layout.value, }; diff --git a/lib/infrastructure/internals/marshaller/serializers/role_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/role_serializer.dart index 5590aef8..4366b8f5 100644 --- a/lib/infrastructure/internals/marshaller/serializers/role_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/role_serializer.dart @@ -12,10 +12,25 @@ final class RoleSerializer implements SerializerContract { RoleSerializer(this.marshaller); @override - Future serializeRemote(Map json) async => _serialize(json); + Future normalize(Map json) async { + final payload = { + 'id': json['id'], + 'name': json['name'], + 'color': json['color'], + 'hoist': json['hoist'], + 'position': json['position'], + 'permissions': json['permissions'], + 'managed': json['managed'], + 'mentionable': json['mentionable'], + 'flags': json['flags'], + }; + + final cacheKey = marshaller.cacheKey.serverRole(json['server_id'], json['id']); + await marshaller.cache.put(cacheKey, payload); + } @override - Future serializeCache(Map json) async => _serialize(json); + Future serialize(Map json) async => _serialize(json); Role _serialize(Map payload) { return Role( diff --git a/lib/infrastructure/internals/marshaller/serializers/server_assets_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_assets_serializer.dart index 31bc694a..31c88ada 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_assets_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_assets_serializer.dart @@ -13,10 +13,36 @@ final class ServerAssetsSerializer implements SerializerContract { ServerAssetsSerializer(this._marshaller); @override - ServerAsset serializeRemote(Map json) => _serialize(json); + Future normalize(Map json) async { + final cacheKey = _marshaller.cacheKey.serverAssets(json['id']); + + await List.from(json['roles']).map((element) async { + return _marshaller.serializers.role.normalize({...element, 'server_id': json['id']}); + }).wait; + + await List.from(json['emojis']).map((element) async { + return _marshaller.serializers.emojis.normalize({...element, 'server_id': json['id']}); + }).wait; + + final payload = { + 'icon': json['icon'], + 'icon_hash': json['icon_hash'], + 'splash': json['splash'], + 'discovery_splash': json['discovery_splash'], + 'banner': json['banner'], + 'roles': List.from(json['roles']) + .map((element) => _marshaller.cacheKey.serverRole(json['id'], element['id'])) + .toList(), + 'emojis': List.from(json['emojis']) + .map((element) => _marshaller.cacheKey.serverEmoji(json['id'], element['id'])) + .toList(), + }; + + _marshaller.cache.put(cacheKey, payload); + } @override - ServerAsset serializeCache(Map json) => _serialize(json); + ServerAsset serialize(Map json) => _serialize(json); ServerAsset _serialize(Map json) { final guildRoles = List.from(json['guildRoles']); diff --git a/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart index e0c57780..ded54667 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart @@ -1,8 +1,6 @@ import 'dart:async'; -import 'package:mineral/api/common/channel.dart'; import 'package:mineral/api/common/snowflake.dart'; -import 'package:mineral/api/common/types/channel_type.dart'; import 'package:mineral/api/server/channels/server_announcement_channel.dart'; import 'package:mineral/api/server/channels/server_category_channel.dart'; import 'package:mineral/api/server/channels/server_channel.dart'; @@ -13,7 +11,6 @@ import 'package:mineral/api/server/channels/server_voice_channel.dart'; import 'package:mineral/api/server/managers/channel_manager.dart'; import 'package:mineral/api/server/managers/member_manager.dart'; import 'package:mineral/api/server/managers/role_manager.dart'; -import 'package:mineral/api/server/role.dart'; import 'package:mineral/api/server/server.dart'; import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; @@ -24,147 +21,75 @@ final class ServerSerializer implements SerializerContract { ServerSerializer(this._marshaller); @override - Future serializeRemote(Map json) async { - final roleWithoutEveryone = - List.from(json['roles']).where((element) => element['id'] != json['id']); - - final List serializedRoles = await roleWithoutEveryone.map((element) async { - final role = await _marshaller.serializers.role.serializeRemote(element); - final cacheKey = _marshaller.cacheKey.serverRole(serverId: json['id'], roleId: role.id); - - final rawRole = await _marshaller.serializers.role.deserialize(role); - await _marshaller.cache.put(cacheKey, rawRole); - - return role; - }).wait; - - final serializedMembers = await List.from(json['members']).map((element) async { - final member = await _marshaller.serializers.member - .serializeRemote({...element, 'guild_roles': serializedRoles}); - final cacheKey = _marshaller.cacheKey.serverMember(serverId: json['id'], memberId: member.id); - - final rawMember = await _marshaller.serializers.member.deserialize(member); - _marshaller.cache.put(cacheKey, rawMember); - - return member; - }).wait; - - final channelManager = ChannelManager(json); - - final availableCategoryChannels = List.from(json['channels']) - .where((element) => element['type'] == ChannelType.guildCategory.value); - - final availableChannels = List.from(json['channels']) - .where((element) => element['type'] != ChannelType.guildCategory.value); - - FutureOr serializeChannel(Map element) => - _marshaller.serializers.channels.serializeRemote({...element, 'guild_id': json['id']}); - - await availableCategoryChannels.map((element) async { - final channel = await serializeChannel(element); - - if (channel is ServerCategoryChannel) { - channelManager.list.putIfAbsent(channel.id, () => channel); - - final cacheKey = _marshaller.cacheKey.channel(channel.id); - - final rawChannel = await _marshaller.serializers.channels.deserialize(channel); - await _marshaller.cache.put(cacheKey, rawChannel); - - return channel; - } + Future normalize(Map json) async { + await List.from(json['members']).map((element) async { + return _marshaller.serializers.member.normalize({...element, 'server_id': json['id']}); }).wait; - await availableChannels.map((element) async { - final channel = await serializeChannel(element); - if (channel is ServerChannel) { - channelManager.list.putIfAbsent(channel.id, () => channel); - - final cacheKey = _marshaller.cacheKey.channel(channel.id); - - final rawChannel = await _marshaller.serializers.channels.deserialize(channel); - await _marshaller.cache.put(cacheKey, rawChannel); - - return channel; - } + await List.from(json['channels']).map((element) async { + return _marshaller.serializers.channels.normalize(element); }).wait; - final roleManager = RoleManager.fromList(serializedRoles); - final owner = serializedMembers.firstWhere((member) => member.id == json['owner_id']); - final serverAssets = await _marshaller.serializers.serversAsset - .serializeRemote({'guildRoles': serializedRoles, ...json}); - - final server = Server( - id: json['id'], - name: json['name'], - members: MemberManager.fromList(serializedMembers), - settings: await _marshaller.serializers.serverSettings.serializeRemote(json), - roles: roleManager, - channels: channelManager, - description: json['description'], - applicationId: json['application_id'], - assets: serverAssets, - owner: owner, - ); - - for (final channel in server.channels.list.values) { - channel.server = server; - await assignCategoryChannel(server.id, channel); - } - - for (final member in server.members.list.values) { - member.server = server; - member.roles.server = server; - member.flags.server = server; - } + await _marshaller.serializers.serversAsset.normalize(json); + + final Map serverPayload = { + 'id': json['id'], + 'name': json['name'], + 'description': json['description'], + 'application_id': json['application_id'], + 'owner': _marshaller.cacheKey.member(json['id'], json['owner_id']), + 'assets': _marshaller.cacheKey.serverAssets(json['id']), + 'settings': _marshaller.cacheKey.serverSettings(json['id']), + 'members': List.from(json['members']) + .map((element) => _marshaller.cacheKey.member(json['id'], element['id'])) + .toList(), + 'channels': List.from(json['channels']) + .map((element) => _marshaller.cacheKey.channel(element['id'], serverId: json['id'])) + .toList(), + }; - return server; + final serverCacheKey = _marshaller.cacheKey.server(json['id']); + await _marshaller.cache.put(serverCacheKey, serverPayload); } @override - Future serializeCache(Map payload) async { - final serverKey = _marshaller.cacheKey.server(payload['id']); - - final rawServer = await _marshaller.cache.getOrFail(serverKey); - final channelManager = ChannelManager(rawServer); + Future serialize(Map payload) async { + final rawMembers = await _marshaller.cache.getMany(payload['members']); + final members = await rawMembers.nonNulls.map((element) async { + return _marshaller.serializers.member.serialize(element); + }).wait; - final roles = await _marshaller.cache.whereKeyStartsWithOrFail('$serverKey/role-'); - final List serializedRoles = await roles.entries.map((element) async { - return _marshaller.serializers.role.serializeCache(element.value); + final rawRoles = await _marshaller.cache.getMany(payload['roles']); + final roles = await rawRoles.nonNulls.map((element) async { + return _marshaller.serializers.role.serialize(element); }).wait; - final members = await _marshaller.cache.whereKeyStartsWithOrFail('$serverKey/member-'); - final serializedMembers = await members.entries.map((element) async { - return _marshaller.serializers.member.serializeCache({ - ...element.value, - 'guild_id': payload['id'], - }); + final rawChannels = await _marshaller.cache.getMany(payload['channels']); + final channels = await rawChannels.nonNulls.map((element) async { + return _marshaller.serializers.channels.serialize(element); }).wait; - await List.from(rawServer['channels']).map((key) async { - final rawChannel = await _marshaller.cache.getOrFail(key); + final channelManager = ChannelManager.fromList(channels as List, payload); + final roleManager = RoleManager.fromList(roles); - final channel = await _marshaller.serializers.channels.serializeCache(rawChannel); - if (channel is ServerChannel) { - channelManager.list.putIfAbsent(channel.id, () => channel); - return channel; - } - }).wait; + final rawOwner = await _marshaller.cache.getOrFail(payload['owner_id']); + final owner = await _marshaller.serializers.member.serialize(rawOwner); - final roleManager = RoleManager.fromList(serializedRoles); - final owner = serializedMembers.firstWhere((member) => member.id == rawServer['owner_id']); - final serverAssets = await _marshaller.serializers.serversAsset - .serializeCache({'guildRoles': serializedRoles, ...rawServer}); + final rawAssets = await _marshaller.cache.getOrFail(payload['assets']); + final serverAssets = await _marshaller.serializers.serversAsset.serialize(rawAssets); + + final rawSettings = await _marshaller.cache.getOrFail(payload['settings']); + final serverSettings = await _marshaller.serializers.serverSettings.serialize(rawSettings); final server = Server( - id: rawServer['id'], - name: rawServer['name'], - members: MemberManager.fromList(serializedMembers), - settings: await _marshaller.serializers.serverSettings.serializeCache(rawServer), + id: payload['id'], + name: payload['name'], + description: payload['description'], + applicationId: payload['application_id'], + members: MemberManager.fromList(members), + settings: serverSettings, roles: roleManager, channels: channelManager, - description: rawServer['description'], - applicationId: rawServer['application_id'], assets: serverAssets, owner: owner, ); @@ -185,29 +110,19 @@ final class ServerSerializer implements SerializerContract { @override Future> deserialize(Server server) async { - final assets = await _marshaller.serializers.serversAsset.deserialize(server.assets); - final settings = await _marshaller.serializers.serverSettings.deserialize(server.settings); - - final members = server.members.list.values.map((member) { - return _marshaller.cacheKey.serverMember(serverId: server.id, memberId: member.id); - }).toList(); - - final channels = server.channels.list.values.map((channel) { - return _marshaller.cacheKey.channel(channel.id); - }).toList(); - return { 'id': server.id, - 'owner_id': server.owner.id, 'name': server.name, - 'members': members, - 'channels': channels, 'description': server.description, - 'applicationId': server.applicationId, - 'assets': await _marshaller.serializers.serversAsset.deserialize(server.assets), - 'owner': await _marshaller.serializers.member.deserialize(server.owner), - ...assets, - ...settings, + 'application_id': server.applicationId, + 'owner': _marshaller.cacheKey.member(server.id, server.owner.id), + 'assets': _marshaller.cacheKey.serverAssets(server.id), + 'settings': _marshaller.cacheKey.serverSettings(server.id), + 'members': + server.members.list.keys.map((id) => _marshaller.cacheKey.member(server.id, id)).toList(), + 'channels': server.channels.list.keys + .map((id) => _marshaller.cacheKey.channel(id, serverId: server.id)) + .toList(), }; } @@ -221,10 +136,14 @@ final class ServerSerializer implements SerializerContract { _ => null, }; - final rawChannel = await _marshaller.cache.get('server-$serverId/channel-$categoryId'); - final category = rawChannel != null - ? await _marshaller.serializers.channels.serializeCache(rawChannel) - : null; + if (categoryId == null) { + return; + } + + final channelCacheKey = _marshaller.cacheKey.channel(categoryId, serverId: serverId); + final rawChannel = await _marshaller.cache.get(channelCacheKey); + final category = + rawChannel != null ? await _marshaller.serializers.channels.serialize(rawChannel) : null; if (category is ServerCategoryChannel?) { switch (channel) { diff --git a/lib/infrastructure/internals/marshaller/serializers/server_settings_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_settings_serializer.dart index f97e534e..2120de4a 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_settings_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_settings_serializer.dart @@ -15,12 +15,38 @@ final class ServerSettingsSerializer implements SerializerContract serializeRemote(Map json) => _serialize(json); + Future normalize(Map json) async { + final payload = { + 'permissions': json['permissions'], + 'afk_timeout': json['afk_timeout'], + 'widget_enabled': json['widget_enabled'] ?? false, + 'explicit_content_filter': json['explicit_content_filter'], + 'verification_level': json['verification_level'], + 'default_message_notifications': json['default_message_notifications'], + 'features': List.from(json['features']), + 'mfa_level': json['mfa_level'], + 'system_channel_flags': json['system_channel_flags'], + 'vanity_url_code': json['vanity_url_code'], + 'premium_tier': json['premium_tier'], + 'premium_subscription_count': json['premium_subscription_count'], + 'premium_progress_bar_enabled': json['premium_progress_bar_enabled'], + 'preferred_locale': json['preferred_locale'], + 'max_video_channel_users': json['max_video_channel_users'], + 'nsfw_level': json['nsfw_level'], + }; + + final cacheKey = _marshaller.cacheKey.serverSettings(json['id']); + await _marshaller.cache.put(cacheKey, payload); + } @override - Future serializeCache(Map json) => _serialize(json); + Future serialize(Map json) async { + final subscription = await _marshaller.serializers.serverSubscription.serialize({ + 'premium_tier': json['premium_tier'], + 'premium_subscription_count': json['premium_subscription_count'], + 'premium_progress_bar_enabled': json['premium_progress_bar_enabled'], + }); - Future _serialize(Map json) async { return ServerSettings( bitfieldPermission: json['permissions'], afkTimeout: json['afk_timeout'], @@ -34,32 +60,31 @@ final class ServerSettingsSerializer implements SerializerContract> deserialize(ServerSettings object) async { - final subscriptions = - await _marshaller.serializers.serverSubscription.deserialize(object.subscription); - + Future> deserialize(ServerSettings settings) async { return { - 'permissions': object.bitfieldPermission, - 'afk_timeout': object.afkTimeout, - 'widget_enabled': object.hasWidgetEnabled, - 'explicit_content_filter': object.explicitContentFilter.value, - 'verification_level': object.verificationLevel.value, - 'default_message_notifications': object.defaultMessageNotifications.value, - 'features': object.features, - 'mfa_level': object.mfaLevel.value, - 'system_channel_flags': listToBitfield(object.systemChannelFlags), - 'vanity_url_code': object.vanityUrlCode, - 'preferred_locale': object.preferredLocale, - 'max_video_channel_users': object.maxVideoChannelUsers, - 'nsfw_level': object.nsfwLevel.value, - ...subscriptions + 'permissions': settings.bitfieldPermission, + 'afk_timeout': settings.afkTimeout, + 'widget_enabled': settings.hasWidgetEnabled, + 'explicit_content_filter': settings.explicitContentFilter.value, + 'verification_level': settings.verificationLevel.value, + 'default_message_notifications': settings.defaultMessageNotifications.value, + 'features': settings.features, + 'mfa_level': settings.mfaLevel.value, + 'system_channel_flags': settings.systemChannelFlags, + 'vanity_url_code': settings.vanityUrlCode, + 'premium_tier': settings.subscription.tier.value, + 'premium_subscription_count': settings.subscription.subscriptionCount, + 'premium_progress_bar_enabled': settings.subscription.hasEnabledProgressBar, + 'preferred_locale': settings.preferredLocale, + 'max_video_channel_users': settings.maxVideoChannelUsers, + 'nsfw_level': settings.nsfwLevel.value, }; } } diff --git a/lib/infrastructure/internals/marshaller/types/serializer.dart b/lib/infrastructure/internals/marshaller/types/serializer.dart index f6612517..52a56e2e 100644 --- a/lib/infrastructure/internals/marshaller/types/serializer.dart +++ b/lib/infrastructure/internals/marshaller/types/serializer.dart @@ -1,7 +1,7 @@ import 'dart:async'; abstract interface class SerializerContract { - FutureOr serializeRemote(Map json); - FutureOr serializeCache(Map json); + FutureOr normalize(Map json); + FutureOr serialize(Map json); FutureOr> deserialize(T object); } diff --git a/pubspec.yaml b/pubspec.yaml index 07ed2559..cd5e5f7d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,7 @@ dependencies: yaml: ^3.1.2 toml: ^0.16.0 mansion: ^0.1.0 + uuid: ^4.4.2 dev_dependencies: lints: ^3.0.0 From dcd4bff6beec63cd0048faa8989b1fd6e9328215 Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Fri, 16 Aug 2024 22:23:07 +0200 Subject: [PATCH 03/44] feat(serialization): delete file server role, unused --- .../serializers/server_role_serializer.dart | 53 ------------------- 1 file changed, 53 deletions(-) delete mode 100644 lib/infrastructure/internals/marshaller/serializers/server_role_serializer.dart diff --git a/lib/infrastructure/internals/marshaller/serializers/server_role_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_role_serializer.dart deleted file mode 100644 index 97606eb8..00000000 --- a/lib/infrastructure/internals/marshaller/serializers/server_role_serializer.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:mineral/api/common/permissions.dart'; -import 'package:mineral/api/common/snowflake.dart'; -import 'package:mineral/api/server/role.dart'; -import 'package:mineral/infrastructure/commons/utils.dart'; -import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; -import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; - -final class RoleSerializer implements SerializerContract { - final MarshallerContract marshaller; - - RoleSerializer(this.marshaller); - - @override - Role serializeRemote(Map json) => _serialize(json); - - @override - Role serializeCache(Map json) => _serialize(json); - - Role _serialize(Map json) { - return Role( - id: Snowflake(json['id']), - name: json['name'], - color: json['color'], - hoist: json['hoist'], - position: json['position'], - permissions: switch (json['permissions']) { - int() => Permissions.fromInt(json['permissions']), - String() => Permissions.fromInt(int.parse(json['permissions'])), - _ => Permissions.fromInt(0), - }, - managed: json['managed'], - mentionable: json['mentionable'], - flags: json['flags'], - icon: json['icon'], - unicodeEmoji: json['unicode_emoji'], - ); - } - - @override - Map deserialize(Role object) { - return { - 'id': object.id, - 'name': object.name, - 'color': object.color, - 'hoist': object.hoist, - 'position': object.position, - 'permissions': listToBitfield(object.permissions.list), - 'managed': object.managed, - 'mentionable': object.mentionable, - 'flags': object.flags, - }; - } -} From 6f1f7adb6f9af8bc94c4e68f7b5c9b506c4266c9 Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Fri, 16 Aug 2024 22:30:14 +0200 Subject: [PATCH 04/44] feat(serialization): stickers --- .../internals/marshaller/cache_key.dart | 2 ++ .../serializers/sticker_serializer.dart | 22 +++++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/infrastructure/internals/marshaller/cache_key.dart b/lib/infrastructure/internals/marshaller/cache_key.dart index 0adb5283..bf310c7a 100644 --- a/lib/infrastructure/internals/marshaller/cache_key.dart +++ b/lib/infrastructure/internals/marshaller/cache_key.dart @@ -50,4 +50,6 @@ final class CacheKey { String embed(Snowflake messageId, { String? uid }) => 'messages/$messageId/embeds/${uid ?? Uuid().v4()}'; String poll(Snowflake messageId, { String? uid }) => 'messages/$messageId/polls/${uid ?? Uuid().v4()}'; + + String sticker(Snowflake stickerId) => 'stickers/$stickerId'; } diff --git a/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart index 51719148..ea4fd491 100644 --- a/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart @@ -6,12 +6,26 @@ import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dar final class StickerSerializer implements SerializerContract { @override - Sticker serializeRemote(Map json) => _serialize(json); + Future normalize(Map json) async { + final payload = { + 'id': json['id'], + 'name': json['name'], + 'type': json['type'], + 'available': json['available'], + 'pack_id': json['pack_id'], + 'description': json['description'], + 'tags': json['tags'], + 'asset': json['asset'], + 'format_type': json['format_type'], + 'sort_value': json['sort_value'], + }; - @override - Sticker serializeCache(Map json) => _serialize(json); + final cacheKey = _marshaller.cacheKey.sticker(json['id']); + await _marshaller.cache.put(cacheKey, payload); + } - Sticker _serialize(Map json) { + @override + Sticker serialize(Map json) { return Sticker( id: Snowflake(json['id']), name: json['name'], From f586c812be12be1496582e77d98fc0953ea88b83 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Fri, 16 Aug 2024 22:47:26 +0200 Subject: [PATCH 05/44] feat(marshaller): rework member and user serialization --- lib/api/private/user_assets.dart | 15 +--- .../internals/marshaller/cache_key.dart | 10 +++ .../marshaller/serializer_bucket.dart | 5 ++ .../serializers/member_serializer.dart | 57 +++++++++----- .../serializers/user_assets_serializer.dart | 53 +++++++++++++ .../serializers/user_serializer.dart | 77 ++++++++++--------- 6 files changed, 147 insertions(+), 70 deletions(-) create mode 100644 lib/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart diff --git a/lib/api/private/user_assets.dart b/lib/api/private/user_assets.dart index 7c075795..e3f15675 100644 --- a/lib/api/private/user_assets.dart +++ b/lib/api/private/user_assets.dart @@ -1,26 +1,17 @@ import 'package:mineral/api/common/image_asset.dart'; +import 'package:mineral/api/common/snowflake.dart'; import 'package:mineral/infrastructure/commons/helper.dart'; final class UserAssets { + final Snowflake userId; final ImageAsset? avatar; final ImageAsset? avatarDecoration; final ImageAsset? banner; UserAssets({ + required this.userId, required this.avatar, required this.avatarDecoration, required this.banner, }); - - factory UserAssets.fromJson(Map json) { - return UserAssets( - avatar: Helper.createOrNull( - field: json['avatar'], fn: () => ImageAsset(['avatars', json['id']], json['avatar'])), - avatarDecoration: Helper.createOrNull( - field: json['avatar_decoration_data']?['sku_id'], - fn: () => ImageAsset(['avatar-decorations', json['id']], json['avatar_decoration_data']['sku_id'])), - banner: Helper.createOrNull( - field: json['banner'], fn: () => ImageAsset(['banners', json['id']], json['banner'])), - ); - } } diff --git a/lib/infrastructure/internals/marshaller/cache_key.dart b/lib/infrastructure/internals/marshaller/cache_key.dart index bf310c7a..21d346cf 100644 --- a/lib/infrastructure/internals/marshaller/cache_key.dart +++ b/lib/infrastructure/internals/marshaller/cache_key.dart @@ -36,6 +36,16 @@ final class CacheKey { return ref ? 'ref:$key' : key; } + String user(Snowflake userId, {bool ref = false}) { + final key = 'users/$userId'; + return ref ? 'ref:$key' : key; + } + + String userAssets(Snowflake userId, {bool ref = false}) { + final key = '${user(userId)}/assets'; + return ref ? 'ref:$key' : key; + } + String serverEmoji(Snowflake serverId, Snowflake emojiId, {bool ref = false}) { final key = '${server(serverId)}/emojis/$emojiId'; return ref ? 'ref:$key' : key; diff --git a/lib/infrastructure/internals/marshaller/serializer_bucket.dart b/lib/infrastructure/internals/marshaller/serializer_bucket.dart index a39f544c..42dbb71c 100644 --- a/lib/infrastructure/internals/marshaller/serializer_bucket.dart +++ b/lib/infrastructure/internals/marshaller/serializer_bucket.dart @@ -6,6 +6,7 @@ import 'package:mineral/api/common/polls/poll.dart'; import 'package:mineral/api/common/sticker.dart'; import 'package:mineral/api/private/private_message.dart'; import 'package:mineral/api/private/user.dart'; +import 'package:mineral/api/private/user_assets.dart'; import 'package:mineral/api/server/member.dart'; import 'package:mineral/api/server/member_assets.dart'; import 'package:mineral/api/server/role.dart'; @@ -34,6 +35,7 @@ import 'package:mineral/infrastructure/internals/marshaller/serializers/server_s import 'package:mineral/infrastructure/internals/marshaller/serializers/server_settings_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/server_subscription_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/sticker_serializer.dart'; +import 'package:mineral/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/user_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; @@ -48,6 +50,8 @@ final class SerializerBucket { final SerializerContract user; + final SerializerContract userAssets; + final SerializerContract role; final SerializerContract serverSubscription; @@ -80,6 +84,7 @@ final class SerializerBucket { member = MemberSerializer(marshaller), memberAssets = MemberAssetsSerializer(marshaller), user = UserSerializer(marshaller), + userAssets = UserAssetsSerializer(marshaller), role = RoleSerializer(marshaller), serverSubscription = ServerSubscriptionSerializer(marshaller), serverSettings = ServerSettingsSerializer(marshaller), diff --git a/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart index 3fd1106d..c3029406 100644 --- a/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart @@ -44,7 +44,6 @@ final class MemberSerializer implements SerializerContract { 'premium_type': json['user']['premium_type'], 'joined_at': json['joined_at'], 'permissions': json['permissions'], - 'pending': json['pending'] ?? false, 'accent_color': json['accent_color'], // TODO : presence }; @@ -76,7 +75,7 @@ final class MemberSerializer implements SerializerContract { publicFlags: json['public_flags'], roles: MemberRoleManager.fromList(roles), isBot: json['is_bot'] ?? false, - isPending: json['pending'] ?? false, + isPending: json['is_pending'] ?? false, timeout: MemberTimeout( duration: Helper.createOrNull( field: json['communication_disabled_until'], @@ -93,7 +92,8 @@ final class MemberSerializer implements SerializerContract { _ => Permissions.fromInt(0), }, accentColor: json['accent_color'], - presence: json['presence'] != null ? Presence.fromJson(json['presence']) : null, + // TODO : presence + presence: null, ); member.roles.member = member; @@ -103,26 +103,41 @@ final class MemberSerializer implements SerializerContract { } @override - Map deserialize(Member member) { + Future> deserialize(Member member) async { + final rawAsset = await _marshaller.serializers.memberAssets.deserialize(member.assets); + final rawRoles = await member.roles.list.entries.map((role) async { + final cacheKey = _marshaller.cacheKey.serverRole(member.server.id, role.key); + return {cacheKey: await _marshaller.serializers.role.deserialize(role.value)}; + }).wait; + + await _marshaller.cache.putMany({ + _marshaller.cacheKey.memberAssets(member.server.id, member.id): rawAsset, + ...rawRoles.fold({}, (prev, element) => {...prev, ...element}), + }); + return { - 'nick': member.nickname, - 'user': { - 'id': member.id, - 'username': member.username, - 'discriminator': member.discriminator, - 'global_name': member.globalName, - 'avatar': member.assets.avatar?.hash, - 'avatar_decoration': member.assets.avatarDecoration?.hash, - 'banner': member.assets.banner?.hash, - 'bot': member.isBot, - 'flags': listToBitfield(member.flags.list), - 'public_flags': member.publicFlags, - }, - 'roles': member.roles.list.keys.toList(), - 'premium_since': member.premiumSince?.toIso8601String(), + 'id': member.id, + 'username': member.username, + 'nickname': member.nickname, + 'global_name': member.globalName, + 'discriminator': member.discriminator, + 'assets': _marshaller.cacheKey.memberAssets(member.server.id, member.id), 'flags': listToBitfield(member.flags.list), - 'pending': member.isPending, - 'communication_disabled_until': member.timeout.duration?.toIso8601String(), + 'roles': member.roles.list.keys + .map((id) => _marshaller.cacheKey.serverRole(member.server.id, id)) + .toList(), + 'premium_since': member.premiumSince?.toIso8601String(), + 'public_flags': member.publicFlags, + 'is_bot': member.isBot, + 'is_pending': member.isPending, + 'timeout': member.timeout.duration?.toIso8601String(), + 'mfa_enabled': member.mfaEnabled, + 'locale': member.locale, + 'premium_type': member.premiumType.value, + 'joined_at': member.joinedAt?.toIso8601String(), + 'permissions': listToBitfield(member.permissions.list), + 'accent_color': member.accentColor, + // TODO : presence }; } } diff --git a/lib/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart new file mode 100644 index 00000000..7e317daa --- /dev/null +++ b/lib/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart @@ -0,0 +1,53 @@ +import 'package:mineral/api/common/image_asset.dart'; +import 'package:mineral/api/common/snowflake.dart'; +import 'package:mineral/api/private/user_assets.dart'; +import 'package:mineral/api/server/member_assets.dart'; +import 'package:mineral/infrastructure/commons/helper.dart'; +import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; +import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; + +final class UserAssetsSerializer implements SerializerContract { + final MarshallerContract _marshaller; + + UserAssetsSerializer(this._marshaller); + + @override + Future normalize(Map json) async { + final payload = { + 'user_id': json['user_id'], + 'avatar': json['avatar'], + 'avatar_decoration': json['avatar_decoration_data']?['sku_id'], + 'banner': json['banner'], + }; + + final cacheKey = _marshaller.cacheKey.userAssets(json['user_id']); + await _marshaller.cache.put(cacheKey, payload); + } + + @override + Future serialize(Map json) async { + return UserAssets( + avatar: Helper.createOrNull( + field: json['avatar'], + fn: () => ImageAsset(['avatars', json['member_id']], json['avatar'])), + avatarDecoration: Helper.createOrNull( + field: json['avatar_decoration'], + fn: () => + ImageAsset(['avatar-decorations', json['member_id']], json['avatar_decoration'])), + banner: Helper.createOrNull( + field: json['banner'], + fn: () => ImageAsset(['banners', json['member_id']], json['banner'])), + userId: Snowflake(json['user_id']), + ); + } + + @override + Map deserialize(UserAssets assets) { + return { + 'user_id': assets.userId.value, + 'avatar': assets.avatar?.hash, + 'avatar_decoration': assets.avatarDecoration?.hash, + 'banner': assets.banner?.hash, + }; + } +} diff --git a/lib/infrastructure/internals/marshaller/serializers/user_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/user_serializer.dart index 9795caa2..f53736ce 100644 --- a/lib/infrastructure/internals/marshaller/serializers/user_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/user_serializer.dart @@ -1,3 +1,4 @@ +import 'package:mineral/api/common/premium_tier.dart'; import 'package:mineral/api/common/presence.dart'; import 'package:mineral/api/private/user.dart'; import 'package:mineral/api/private/user_assets.dart'; @@ -6,29 +7,58 @@ import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dar final class UserSerializer implements SerializerContract { @override - User serializeRemote(Map json) => _serialize(json); + Future normalize(Map json) async { + await _marshaller.serializers.userAssets.normalize({ + ...json, + 'user_id': json['id'], + }); + + final payload = { + 'id': json['id'], + 'username': json['username'], + 'discriminator': json['discriminator'], + 'flags': json['flags'], + 'public_flags': json['public_flags'], + 'avatar': json['avatar'], + 'is_bot': json['bot'], + 'system': json['system'], + 'mfa_enabled': json['mfa_enabled'], + 'locale': json['locale'], + 'verified': json['verified'], + 'email': json['email'], + 'premium_type': json['premium_type'], + 'assets': _marshaller.cacheKey.userAssets(json['id']), + }; + + final cacheKey = _marshaller.cacheKey.user(json['id']); + await _marshaller.cache.put(cacheKey, payload); + } @override - User serializeCache(Map json) => _serialize(json); + Future serialize(Map json) async { + final rawAssets = await _marshaller.cache.getOrFail(json['assets']); + final assets = await _marshaller.serializers.userAssets.serialize(rawAssets); - User _serialize(Map json) { return User( id: json['id'], username: json['username'], discriminator: json['discriminator'], avatar: json['avatar'], - bot: json['bot'], + bot: json['is_bot'], system: json['system'], mfaEnabled: json['mfa_enabled'], locale: json['locale'], verified: json['verified'], email: json['email'], flags: json['flags'], - premiumType: json['premium_type'], + premiumType: PremiumTier.values + .firstWhere((e) => e == json['premium_type'], orElse: () => PremiumTier.none), publicFlags: json['public_flags'], - assets: UserAssets.fromJson(json), - createdAt: json['created_at'], - presence: json['presence'] != null ? Presence.fromJson(json['presence']) : null, + assets: assets, + createdAt: Helper.createOrNull( + field: json['created_at'], fn: () => DateTime.parse(json['created_at'])), + // TODO: Implement presence deserialization + presence: null, ); } @@ -41,42 +71,15 @@ final class UserSerializer implements SerializerContract { 'flags': user.flags, 'public_flags': user.publicFlags, 'avatar': user.avatar, - 'bot': user.bot, + 'is_bot': user.bot, 'system': user.system, 'mfa_enabled': user.mfaEnabled, 'locale': user.locale, 'verified': user.verified, 'email': user.email, 'premium_type': user.premiumType?.value, - 'assets': { - 'avatar': user.assets.avatar?.hash, - 'avatar_decoration_data': { - 'sku_id': user.assets.avatarDecoration?.hash, - }, - 'banner': user.assets.banner?.hash, - }, 'created_at': user.createdAt?.toIso8601String(), - 'presence': Helper.createOrNull( - field: user.presence, - fn: () => { - 'since': user.presence!.since?.toIso8601String(), - 'activities': user.presence!.activities.map((element) => { - 'name': element.name, - 'type': element.type.value, - 'url': element.url, - 'created_at': element.createdAt.toIso8601String(), - 'details': element.details, - 'state': element.state, - 'emoji': element.emoji != null ? { - 'name': element.emoji!.name, - 'id': element.emoji!.id, - 'animated': element.emoji!.animated, - } : null, - }).toList(), - 'status': user.presence!.status.value, - 'afk': user.presence!.afk, - } - ), + // TODO: Implement presence serialization }; } } From 167bf399b1e3bf979ce5c7e70619400ee877d6dc Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:17:13 +0200 Subject: [PATCH 06/44] feat(serialization): replace all serialize --- .../internals/packets/listeners/channel_create_packet.dart | 2 +- .../internals/packets/listeners/channel_delete_packet.dart | 2 +- .../packets/listeners/channel_pins_update_packet.dart | 2 +- .../internals/packets/listeners/channel_update_packet.dart | 2 +- .../internals/packets/listeners/guild_ban_add_packet.dart | 4 ++-- .../internals/packets/listeners/guild_ban_remove_packet.dart | 2 +- .../internals/packets/listeners/guild_create_packet.dart | 2 +- .../packets/listeners/guild_emojis_update_packet.dart | 2 +- .../internals/packets/listeners/guild_member_add_packet.dart | 5 ++--- .../packets/listeners/guild_member_chunk_packet.dart | 4 ++-- .../packets/listeners/guild_member_remove_packet.dart | 4 ++-- .../packets/listeners/guild_member_update_packet.dart | 5 ++--- .../packets/listeners/guild_role_create_packet.dart | 4 ++-- .../packets/listeners/guild_role_delete_packet.dart | 2 +- .../packets/listeners/guild_role_update_packet.dart | 4 ++-- .../internals/packets/listeners/guild_update_packet.dart | 2 +- .../interactions/select_interaction_create_packet.dart | 4 ++-- .../internals/packets/listeners/message_create_packet.dart | 4 ++-- .../internals/packets/listeners/presence_update_packet.dart | 4 ++-- 19 files changed, 29 insertions(+), 31 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/channel_create_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_create_packet.dart index 8094a4b6..3e297e06 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_create_packet.dart @@ -18,7 +18,7 @@ final class ChannelCreatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { - final channel = await marshaller.serializers.channels.serializeRemote(message.payload); + final channel = await marshaller.serializers.channels.serialize(message.payload); return switch (channel) { ServerChannel() => registerServerChannel(channel, dispatch), diff --git a/lib/infrastructure/internals/packets/listeners/channel_delete_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_delete_packet.dart index 5c08ef82..6dc4e11b 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_delete_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_delete_packet.dart @@ -18,7 +18,7 @@ final class ChannelDeletePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { - final channel = await marshaller.serializers.channels.serializeRemote(message.payload); + final channel = await marshaller.serializers.channels.serialize(message.payload); switch (channel) { case ServerChannel(): diff --git a/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart index 4fb5e0a7..97af1720 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart @@ -18,7 +18,7 @@ final class ChannelPinsUpdatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { - final channel = await marshaller.serializers.channels.serializeRemote(message.payload); + final channel = await marshaller.serializers.channels.serialize(message.payload); return switch (channel) { ServerChannel() => registerServerChannelPins(channel, dispatch), diff --git a/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart index be113b2c..29f5c6e5 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart @@ -18,7 +18,7 @@ final class ChannelUpdatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { - final channel = await marshaller.serializers.channels.serializeRemote(message.payload); + final channel = await marshaller.serializers.channels.serialize(message.payload); return switch (channel) { ServerChannel() => registerServerChannel(channel, dispatch), diff --git a/lib/infrastructure/internals/packets/listeners/guild_ban_add_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_ban_add_packet.dart index 936630f5..15f8df0a 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_ban_add_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_ban_add_packet.dart @@ -16,11 +16,11 @@ final class GuildBanAddPacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); - final user = await marshaller.serializers.user.serializeRemote(message.payload['user']); + final user = await marshaller.serializers.user.serialize(message.payload['user']); final member = server.members.list[user.id]; final memberId = message.payload['user']['id']; - final memberCacheKey = marshaller.cacheKey.serverMember(serverId: server.id, memberId: memberId); + final memberCacheKey = marshaller.cacheKey.member(server.id, memberId); final rawServer = await marshaller.serializers.server.deserialize(server); final serverCacheKey = marshaller.cacheKey.server(server.id); diff --git a/lib/infrastructure/internals/packets/listeners/guild_ban_remove_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_ban_remove_packet.dart index f29aa90f..32b91228 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_ban_remove_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_ban_remove_packet.dart @@ -17,7 +17,7 @@ final class GuildBanRemovePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); - final user = await marshaller.serializers.user.serializeRemote(message.payload['user']); + final user = await marshaller.serializers.user.serialize(message.payload['user']); dispatch(event: Event.serverBanRemove, params: [user, server]); } diff --git a/lib/infrastructure/internals/packets/listeners/guild_create_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_create_packet.dart index 6bf13cec..3a10c1e7 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_create_packet.dart @@ -19,7 +19,7 @@ final class GuildCreatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { - final server = await marshaller.serializers.server.serializeRemote(message.payload); + final server = await marshaller.serializers.server.serialize(message.payload); final cacheKey = marshaller.cacheKey.server(server.id); final rawServer = await marshaller.serializers.server.deserialize(server); diff --git a/lib/infrastructure/internals/packets/listeners/guild_emojis_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_emojis_update_packet.dart index 18b3df5b..8a9ecc18 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_emojis_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_emojis_update_packet.dart @@ -24,7 +24,7 @@ final class GuildEmojisUpdatePacket implements ListenablePacket { payload: message.payload['emojis'], roles: server.roles.list.values.toList()); await emojiManager.list.values.map((emoji) async { - final emojiCacheKey = marshaller.cacheKey.serverEmoji(serverId: server.id, emojiId: emoji.id!); + final emojiCacheKey = marshaller.cacheKey.serverEmoji(server.id, emoji.id!); final rawEmoji = await marshaller.serializers.emojis.deserialize(emoji); return marshaller.cache.put(emojiCacheKey, rawEmoji); diff --git a/lib/infrastructure/internals/packets/listeners/guild_member_add_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_member_add_packet.dart index b7c2654c..c94dd6f8 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_member_add_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_member_add_packet.dart @@ -17,8 +17,7 @@ final class GuildMemberAddPacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); - final member = await marshaller.serializers.member - .serializeRemote({...message.payload, 'guild_roles': server.roles.list.values.toList()}); + final member = await marshaller.serializers.member.serialize({...message.payload, 'guild_roles': server.roles.list.values.toList()}); server.members.list.putIfAbsent(member.id, () => member); @@ -27,7 +26,7 @@ final class GuildMemberAddPacket implements ListenablePacket { await marshaller.cache.putMany({ marshaller.cacheKey.server(server.id): rawServer, - marshaller.cacheKey.serverMember(serverId: server.id, memberId: member.id): rawMember + marshaller.cacheKey.member(server.id, member.id): rawMember }); dispatch(event: Event.serverMemberAdd, params: [member, server]); diff --git a/lib/infrastructure/internals/packets/listeners/guild_member_chunk_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_member_chunk_packet.dart index 4acfd5e7..6d433970 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_member_chunk_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_member_chunk_packet.dart @@ -23,8 +23,8 @@ final class GuildMemberChunkPacket implements ListenablePacket { final presences = message.payload['presences']; for (final element in members) { - final member = await marshaller.serializers.member.serializeRemote(element); - final memberCacheKey = marshaller.cacheKey.serverMember(serverId: server.id, memberId: member.id); + final member = await marshaller.serializers.member.serialize(element); + final memberCacheKey = marshaller.cacheKey.member(server.id, member.id); final rawMember = await marshaller.serializers.member.deserialize(member); await marshaller.cache.put(memberCacheKey, rawMember); diff --git a/lib/infrastructure/internals/packets/listeners/guild_member_remove_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_member_remove_packet.dart index 8095c027..c32f5827 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_member_remove_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_member_remove_packet.dart @@ -21,11 +21,11 @@ final class GuildMemberRemovePacket implements ListenablePacket { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); final serverCacheKey = marshaller.cacheKey.server(server.id); final memberCacheKey = - marshaller.cacheKey.serverMember(serverId: server.id, memberId: memberId); + marshaller.cacheKey.member(server.id, memberId); final rawMember = await marshaller.cache.get(memberCacheKey); final user = - rawMember != null ? await marshaller.serializers.user.serializeCache(rawMember) : null; + rawMember != null ? await marshaller.serializers.user.serialize(rawMember) : null; server.members.list.remove(memberId); diff --git a/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart index 9e75882b..4dbe2b98 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart @@ -23,8 +23,7 @@ final class GuildMemberUpdatePacket implements ListenablePacket { memberId: message.payload['user']['id'], ); - final after = await marshaller.serializers.member - .serializeRemote({...message.payload, 'guild_roles': server.roles.list.values.toList()}); + final after = await marshaller.serializers.member.serialize({...message.payload, 'guild_roles': server.roles.list.values.toList()}); server.members.list.update(after.id, (_) => after); @@ -33,7 +32,7 @@ final class GuildMemberUpdatePacket implements ListenablePacket { await marshaller.cache.putMany({ marshaller.cacheKey.server(server.id): rawServer, - marshaller.cacheKey.serverMember(serverId: server.id, memberId: after.id): rawMember + marshaller.cacheKey.member(server.id, after.id): rawMember }); dispatch(event: Event.serverMemberUpdate, params: [before, after]); diff --git a/lib/infrastructure/internals/packets/listeners/guild_role_create_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_role_create_packet.dart index ac38d669..35422010 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_role_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_role_create_packet.dart @@ -17,7 +17,7 @@ final class GuildRoleCreatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); - final role = await marshaller.serializers.role.serializeRemote(message.payload['role']); + final role = await marshaller.serializers.role.serialize(message.payload['role']); server.roles.list.putIfAbsent(role.id, () => role); @@ -26,7 +26,7 @@ final class GuildRoleCreatePacket implements ListenablePacket { await marshaller.cache.putMany({ marshaller.cacheKey.server(server.id): rawServer, - marshaller.cacheKey.serverRole(serverId: server.id, roleId: role.id): rawRole, + marshaller.cacheKey.serverRole( server.id, role.id): rawRole, }); dispatch(event: Event.serverRoleCreate, params: [role, server]); diff --git a/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart index dc9bbe15..51c0de49 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart @@ -25,7 +25,7 @@ final class GuildRoleDeletePacket implements ListenablePacket { server.roles.list.remove(role.id); final serverCacheKey = marshaller.cacheKey.server(server.id); - final roleCacheKey = marshaller.cacheKey.serverRole(serverId: server.id, roleId: role.id); + final roleCacheKey = marshaller.cacheKey.serverRole(server.id, role.id); final rawServer = await marshaller.serializers.server.deserialize(server); await marshaller.cache.put(serverCacheKey, rawServer); diff --git a/lib/infrastructure/internals/packets/listeners/guild_role_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_role_update_packet.dart index 8fd39fe9..96c856d3 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_role_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_role_update_packet.dart @@ -19,7 +19,7 @@ final class GuildRoleUpdatePacket implements ListenablePacket { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); final before = server.roles.list[message.payload['role']['id']]; - final after = await marshaller.serializers.role.serializeRemote(message.payload['role']); + final after = await marshaller.serializers.role.serialize(message.payload['role']); server.roles.list.update(after.id, (_) => after); @@ -30,7 +30,7 @@ final class GuildRoleUpdatePacket implements ListenablePacket { await marshaller.cache.putMany({ marshaller.cacheKey.server(server.id): rawServer, - marshaller.cacheKey.serverRole(serverId: server.id, roleId: after.id): rawRole, + marshaller.cacheKey.serverRole(server.id, after.id): rawRole, }); } } diff --git a/lib/infrastructure/internals/packets/listeners/guild_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_update_packet.dart index 5c308913..0d52937b 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_update_packet.dart @@ -17,7 +17,7 @@ final class GuildUpdatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { final before = await marshaller.dataStore.server.getServer(message.payload['id']); - final after = await marshaller.serializers.server.serializeRemote(message.payload); + final after = await marshaller.serializers.server.serialize(message.payload); final cacheKey = marshaller.cacheKey.server(after.id); final rawServer = await marshaller.serializers.server.deserialize(after); diff --git a/lib/infrastructure/internals/packets/listeners/interactions/select_interaction_create_packet.dart b/lib/infrastructure/internals/packets/listeners/interactions/select_interaction_create_packet.dart index a68c01f3..b4907b4d 100644 --- a/lib/infrastructure/internals/packets/listeners/interactions/select_interaction_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/interactions/select_interaction_create_packet.dart @@ -66,7 +66,7 @@ final class SelectInteractionCreatePacket implements ListenablePacket { final cacheKey = marshaller.cacheKey.channel(Snowflake(id)); final rawChannel = await marshaller.cache.getOrFail(cacheKey); - return marshaller.serializers.channels.serializeCache(rawChannel) as Future; + return marshaller.serializers.channelsserialize(rawChannel) as Future; })); } @@ -93,7 +93,7 @@ final class SelectInteractionCreatePacket implements ListenablePacket { marshaller.cacheKey.serverRole(serverId: payload['guild_id'], roleId: Snowflake(id)); final rawRole = await marshaller.cache.getOrFail(cacheKey); - return marshaller.serializers.role.serializeCache(rawRole); + return marshaller.serializers.roleserialize(rawRole); })); dispatch( diff --git a/lib/infrastructure/internals/packets/listeners/message_create_packet.dart b/lib/infrastructure/internals/packets/listeners/message_create_packet.dart index ee4cb675..fcbdad4f 100644 --- a/lib/infrastructure/internals/packets/listeners/message_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/message_create_packet.dart @@ -36,7 +36,7 @@ final class MessageCreatePacket implements ListenablePacket { final server = await marshaller.dataStore.server.getServer(json['message_reference']['guild_id']); final channel = server.channels.list[json['channel_id']]; - final message = await marshaller.serializers.serverMessage.serializeRemote(json); + final message = await marshaller.serializers.serverMessage.serialize(json); if (channel is ServerChannel) { message.channel = channel; @@ -61,7 +61,7 @@ final class MessageCreatePacket implements ListenablePacket { Future sendPrivateMessage(DispatchEvent dispatch, Map json) async { final channel = await marshaller.dataStore.channel.getChannel(json['channel_id']); - final message = await marshaller.serializers.privateMessage.serializeRemote(json); + final message = await marshaller.serializers.privateMessage.serialize(json); if (channel is PrivateChannel) { message.channel = channel; diff --git a/lib/infrastructure/internals/packets/listeners/presence_update_packet.dart b/lib/infrastructure/internals/packets/listeners/presence_update_packet.dart index 69c99162..d2034f19 100644 --- a/lib/infrastructure/internals/packets/listeners/presence_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/presence_update_packet.dart @@ -20,10 +20,10 @@ final class PresenceUpdatePacket implements ListenablePacket { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); final serverCacheKey = marshaller.cacheKey.server(server.id); final memberCacheKey = marshaller.cacheKey - .serverMember(serverId: server.id, memberId: message.payload['user']['id']); + .member(server.id, message.payload['user']['id']); final rawMember = await marshaller.cache.getOrFail(memberCacheKey); - final member = await marshaller.serializers.member.serializeCache({ + final member = await marshaller.serializers.member.serialize({ ...rawMember, 'guild_id': server.id.value, }); From 9a9993713c1bd564637fbc26971f3043ed31df8b Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:18:11 +0200 Subject: [PATCH 07/44] feat(serialization): replace all serialize --- .../interactions/select_interaction_create_packet.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/interactions/select_interaction_create_packet.dart b/lib/infrastructure/internals/packets/listeners/interactions/select_interaction_create_packet.dart index b4907b4d..0a48fe02 100644 --- a/lib/infrastructure/internals/packets/listeners/interactions/select_interaction_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/interactions/select_interaction_create_packet.dart @@ -66,7 +66,7 @@ final class SelectInteractionCreatePacket implements ListenablePacket { final cacheKey = marshaller.cacheKey.channel(Snowflake(id)); final rawChannel = await marshaller.cache.getOrFail(cacheKey); - return marshaller.serializers.channelsserialize(rawChannel) as Future; + return marshaller.serializers.channels.serialize(rawChannel) as Future; })); } @@ -90,10 +90,10 @@ final class SelectInteractionCreatePacket implements ListenablePacket { final List resolvedRoles = await Future.wait(roleIds.map((id) async { final cacheKey = - marshaller.cacheKey.serverRole(serverId: payload['guild_id'], roleId: Snowflake(id)); + marshaller.cacheKey.serverRole(payload['guild_id'], Snowflake(id)); final rawRole = await marshaller.cache.getOrFail(cacheKey); - return marshaller.serializers.roleserialize(rawRole); + return marshaller.serializers.role.serialize(rawRole); })); dispatch( From fff2e2adb7afd68fd14fc9eaf62f8656c38d58ea Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:18:57 +0200 Subject: [PATCH 08/44] feat(serialization): refractor channels factories --- lib/api/common/channel_properties.dart | 8 ++-- .../channels/private_channel_factory.dart | 26 +++++++++--- .../server_announcement_channel_factory.dart | 31 +++++++++----- .../server_category_channel_factory.dart | 19 +++++++-- .../server_forum_channel_factory.dart | 42 ++++++++----------- .../server_stage_channel_factory.dart | 25 +++++++---- .../channels/server_text_channel_factory.dart | 25 +++++++---- .../server_voice_channel_factory.dart | 18 ++++++-- .../serializers/channel_serializer.dart | 8 ++-- .../server_message_serializer.dart | 27 ++++++------ .../server_subscription_serializer.dart | 8 ++-- .../marshaller/types/channel_factory.dart | 8 ++-- 12 files changed, 150 insertions(+), 95 deletions(-) diff --git a/lib/api/common/channel_properties.dart b/lib/api/common/channel_properties.dart index 4e72d231..f81d3b1b 100644 --- a/lib/api/common/channel_properties.dart +++ b/lib/api/common/channel_properties.dart @@ -83,7 +83,7 @@ final class ChannelProperties { fn: () async => Future.wait( List.from(element['permission_overwrites']) .map((json) async => - marshaller.serializers.channelPermissionOverwrite.serializeRemote(json)) + marshaller.serializers.channelPermissionOverwrite.serialize(json)) .toList(), )); @@ -91,7 +91,7 @@ final class ChannelProperties { field: element['recipients'], fn: () async => Future.wait( List.from(element['recipients']) - .map((json) async => marshaller.serializers.user.serializeRemote(json)) + .map((json) async => marshaller.serializers.user.serialize(json)) .toList(), )); @@ -139,7 +139,7 @@ final class ChannelProperties { fn: () async => Future.wait( List.from(element['permission_overwrites']) .map((json) async => - marshaller.serializers.channelPermissionOverwrite.serializeRemote(json)) + marshaller.serializers.channelPermissionOverwrite.serialize(json)) .toList(), )); @@ -147,7 +147,7 @@ final class ChannelProperties { field: element['recipients'], fn: () async => Future.wait( List.from(element['recipients']) - .map((json) async => marshaller.serializers.user.serializeRemote(json)) + .map((json) async => marshaller.serializers.user.serialize(json)) .toList(), )); diff --git a/lib/infrastructure/internals/marshaller/factories/channels/private_channel_factory.dart b/lib/infrastructure/internals/marshaller/factories/channels/private_channel_factory.dart index 198f0a60..f22cb413 100644 --- a/lib/infrastructure/internals/marshaller/factories/channels/private_channel_factory.dart +++ b/lib/infrastructure/internals/marshaller/factories/channels/private_channel_factory.dart @@ -9,23 +9,37 @@ final class PrivateChannelFactory implements ChannelFactoryContract ChannelType.dm; @override - Future serializeRemote(MarshallerContract marshaller, String guildId, Map json) async { - final properties = await ChannelProperties.serializeRemote(marshaller, json); + Future serialize(MarshallerContract marshaller, Map json) async { + final properties = await ChannelProperties.serializeCache(marshaller, json); return PrivateChannel(properties); } @override - Future serializeCache(MarshallerContract marshaller, String guildId, Map json) async { - final properties = await ChannelProperties.serializeCache(marshaller, json); - return PrivateChannel(properties); + Future normalize(MarshallerContract marshaller, Map json) async { + final payload = { + 'id': json['id'], + 'type': json['type'], + 'recipients': json['recipients'], + 'name': json['name'] ?? json['recipients'].join(', '), + 'description': json['description'], + 'message_count': json['message_count'], + 'user_count': json['user_count'], + }; + + final cacheKey = marshaller.cacheKey.channel(json['id']); + await marshaller.cache.put(cacheKey, payload); } @override - Future> deserialize(MarshallerContract marshaller, PrivateChannel channel) async { + Map deserialize(MarshallerContract marshaller, PrivateChannel channel) { return { 'id': channel.id.value, 'type': channel.type.value, 'recipients': channel.recipients.map((user) => user.id.value).toList(), + 'name': channel.name, + 'description': channel.description, + 'message_count': channel.messageCount, + 'user_count': channel.userCount, }; } } diff --git a/lib/infrastructure/internals/marshaller/factories/channels/server_announcement_channel_factory.dart b/lib/infrastructure/internals/marshaller/factories/channels/server_announcement_channel_factory.dart index dd2590dd..420f800a 100644 --- a/lib/infrastructure/internals/marshaller/factories/channels/server_announcement_channel_factory.dart +++ b/lib/infrastructure/internals/marshaller/factories/channels/server_announcement_channel_factory.dart @@ -1,33 +1,42 @@ +import 'dart:async'; + import 'package:mineral/api/common/channel_properties.dart'; import 'package:mineral/api/common/types/channel_type.dart'; import 'package:mineral/api/server/channels/server_announcement_channel.dart'; import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; import 'package:mineral/infrastructure/internals/marshaller/types/channel_factory.dart'; -final class ServerAnnouncementChannelFactory - implements ChannelFactoryContract { +final class ServerAnnouncementChannelFactory implements ChannelFactoryContract { @override ChannelType get type => ChannelType.guildAnnouncement; @override - Future serializeRemote(MarshallerContract marshaller, String guildId, - Map json) async { - final properties = await ChannelProperties.serializeRemote(marshaller, json); + Future normalize(MarshallerContract marshaller, Map json) async { + final payload = { + 'id': json['id'], + 'type': json['type'], + 'position': json['position'], + 'name': json['name'], + 'description': json['topic'], + 'nsfw': json['nsfw'], + 'guild_id': json['guild_id'], + 'category_id': json['parent_id'], + 'permission_overwrites': json['permission_overwrites'], + }; - return ServerAnnouncementChannel(properties); + final cacheKey = marshaller.cacheKey.channel(json['id']); + await marshaller.cache.put(cacheKey, payload); } @override - Future serializeCache(MarshallerContract marshaller, String guildId, Map json) async { + Future serialize(MarshallerContract marshaller, Map json) async { final properties = await ChannelProperties.serializeCache(marshaller, json); return ServerAnnouncementChannel(properties); } @override - Future> deserialize(MarshallerContract marshaller, - ServerAnnouncementChannel channel) async { - final permissions = await Future.wait(channel.permissions.map((element) async => - marshaller.serializers.channelPermissionOverwrite.deserialize(element))); + Future> deserialize(MarshallerContract marshaller, ServerAnnouncementChannel channel) async { + final permissions = await Future.wait(channel.permissions.map((element) async => marshaller.serializers.channelPermissionOverwrite.deserialize(element))); return { 'id': channel.id.value, diff --git a/lib/infrastructure/internals/marshaller/factories/channels/server_category_channel_factory.dart b/lib/infrastructure/internals/marshaller/factories/channels/server_category_channel_factory.dart index 360d3435..d37f8384 100644 --- a/lib/infrastructure/internals/marshaller/factories/channels/server_category_channel_factory.dart +++ b/lib/infrastructure/internals/marshaller/factories/channels/server_category_channel_factory.dart @@ -9,13 +9,24 @@ final class ServerCategoryChannelFactory implements ChannelFactoryContract ChannelType.guildCategory; @override - Future serializeRemote(MarshallerContract marshaller, String guildId, Map json) async { - final properties = await ChannelProperties.serializeRemote(marshaller, json); - return ServerCategoryChannel(properties); + Future normalize(MarshallerContract marshaller, Map json) async { + final payload = { + 'id': json['id'], + 'type': json['type'], + 'position': json['position'], + 'name': json['name'], + 'description': json['topic'], + 'nsfw': json['nsfw'], + 'guild_id': json['guild_id'], + 'permission_overwrites': json['permission_overwrites'], + }; + + final cacheKey = marshaller.cacheKey.channel(json['id']); + await marshaller.cache.put(cacheKey, payload); } @override - Future serializeCache(MarshallerContract marshaller, String guildId, Map json) async { + Future serialize(MarshallerContract marshaller, Map json) async { final properties = await ChannelProperties.serializeRemote(marshaller, json); return ServerCategoryChannel(properties); } diff --git a/lib/infrastructure/internals/marshaller/factories/channels/server_forum_channel_factory.dart b/lib/infrastructure/internals/marshaller/factories/channels/server_forum_channel_factory.dart index 81d7f6ae..7317e079 100644 --- a/lib/infrastructure/internals/marshaller/factories/channels/server_forum_channel_factory.dart +++ b/lib/infrastructure/internals/marshaller/factories/channels/server_forum_channel_factory.dart @@ -13,41 +13,35 @@ final class ServerForumChannelFactory implements ChannelFactoryContract ChannelType.guildForum; @override - Future serializeRemote( - MarshallerContract marshaller, String guildId, Map json) async { - final properties = await ChannelProperties.serializeRemote(marshaller, json); + Future normalize(MarshallerContract marshaller, Map json) async { + final payload = { + 'id': json['id'], + 'type': json['type'], + 'position': json['position'], + 'name': json['name'], + 'description': json['topic'], + 'nsfw': json['nsfw'], + 'guild_id': json['guild_id'], + 'permission_overwrites': json['permission_overwrites'], + }; - return ServerForumChannel( - properties, - sortOrder: Helper.createOrNull( - field: json['default_sort_order'], - fn: () => findInEnum(SortOrderType.values, json['default_sort_order'])), - layoutType: Helper.createOrNull( - field: json['default_forum_layout'], - fn: () => findInEnum(ForumLayoutType.values, json['default_forum_layout'])), - ); + final cacheKey = marshaller.cacheKey.channel(json['id']); + await marshaller.cache.put(cacheKey, payload); } @override - Future serializeCache( - MarshallerContract marshaller, String guildId, Map json) async { + Future serialize(MarshallerContract marshaller, Map json) async { final properties = await ChannelProperties.serializeCache(marshaller, json); return ServerForumChannel( properties, - sortOrder: Helper.createOrNull( - field: json['default_sort_order'], - fn: () => findInEnum(SortOrderType.values, json['default_sort_order'])), - layoutType: Helper.createOrNull( - field: json['default_forum_layout'], - fn: () => findInEnum(ForumLayoutType.values, json['default_forum_layout'])), + sortOrder: Helper.createOrNull(field: json['default_sort_order'], fn: () => findInEnum(SortOrderType.values, json['default_sort_order'])), + layoutType: Helper.createOrNull(field: json['default_forum_layout'], fn: () => findInEnum(ForumLayoutType.values, json['default_forum_layout'])), ); } @override - Future> deserialize( - MarshallerContract marshaller, ServerForumChannel channel) async { - final permissions = await Future.wait(channel.permissions.map( - (element) async => marshaller.serializers.channelPermissionOverwrite.deserialize(element))); + Future> deserialize(MarshallerContract marshaller, ServerForumChannel channel) async { + final permissions = await Future.wait(channel.permissions.map((element) async => marshaller.serializers.channelPermissionOverwrite.deserialize(element))); return { 'id': channel.id.value, diff --git a/lib/infrastructure/internals/marshaller/factories/channels/server_stage_channel_factory.dart b/lib/infrastructure/internals/marshaller/factories/channels/server_stage_channel_factory.dart index fdc6dbb5..126df9ba 100644 --- a/lib/infrastructure/internals/marshaller/factories/channels/server_stage_channel_factory.dart +++ b/lib/infrastructure/internals/marshaller/factories/channels/server_stage_channel_factory.dart @@ -9,24 +9,31 @@ final class ServerStageChannelFactory implements ChannelFactoryContract ChannelType.guildStageVoice; @override - Future serializeRemote( - MarshallerContract marshaller, String guildId, Map json) async { - final properties = await ChannelProperties.serializeRemote(marshaller, json); + Future normalize(MarshallerContract marshaller, Map json) async { + final payload = { + 'id': json['id'], + 'type': json['type'], + 'position': json['position'], + 'name': json['name'], + 'description': json['topic'], + 'guild_id': json['guild_id'], + 'parent_id': json['parent_id'], + 'permission_overwrites': json['permission_overwrites'], + }; - return ServerStageChannel(properties); + final cacheKey = marshaller.cacheKey.channel(json['id']); + await marshaller.cache.put(cacheKey, payload); } @override - Future serializeCache(MarshallerContract marshaller, String guildId, Map json) async { + Future serialize(MarshallerContract marshaller, Map json) async { final properties = await ChannelProperties.serializeCache(marshaller, json); return ServerStageChannel(properties); } @override - Future> deserialize( - MarshallerContract marshaller, ServerStageChannel channel) async { - final permissions = await Future.wait(channel.permissions.map( - (element) async => marshaller.serializers.channelPermissionOverwrite.deserialize(element))); + Future> deserialize(MarshallerContract marshaller, ServerStageChannel channel) async { + final permissions = await Future.wait(channel.permissions.map((element) async => marshaller.serializers.channelPermissionOverwrite.deserialize(element))); return { 'id': channel.id.value, diff --git a/lib/infrastructure/internals/marshaller/factories/channels/server_text_channel_factory.dart b/lib/infrastructure/internals/marshaller/factories/channels/server_text_channel_factory.dart index 74bd647b..20e64268 100644 --- a/lib/infrastructure/internals/marshaller/factories/channels/server_text_channel_factory.dart +++ b/lib/infrastructure/internals/marshaller/factories/channels/server_text_channel_factory.dart @@ -9,24 +9,31 @@ final class ServerTextChannelFactory implements ChannelFactoryContract ChannelType.guildText; @override - Future serializeRemote( - MarshallerContract marshaller, String guildId, Map json) async { - final properties = await ChannelProperties.serializeRemote(marshaller, json); + Future normalize(MarshallerContract marshaller, Map json) async { + final payload = { + 'id': json['id'], + 'type': json['type'], + 'position': json['position'], + 'name': json['name'], + 'description': json['topic'], + 'guild_id': json['guild_id'], + 'parent_id': json['parent_id'], + 'permission_overwrites': json['permission_overwrites'], + }; - return ServerTextChannel(properties); + final cacheKey = marshaller.cacheKey.channel(json['id']); + await marshaller.cache.put(cacheKey, payload); } @override - Future serializeCache(MarshallerContract marshaller, String guildId, Map json) async { + Future serialize(MarshallerContract marshaller, Map json) async { final properties = await ChannelProperties.serializeCache(marshaller, json); return ServerTextChannel(properties); } @override - Future> deserialize( - MarshallerContract marshaller, ServerTextChannel channel) async { - final permissions = await Future.wait(channel.permissions.map( - (element) async => marshaller.serializers.channelPermissionOverwrite.deserialize(element))); + Future> deserialize(MarshallerContract marshaller, ServerTextChannel channel) async { + final permissions = await Future.wait(channel.permissions.map((element) async => marshaller.serializers.channelPermissionOverwrite.deserialize(element))); return { 'id': channel.id.value, diff --git a/lib/infrastructure/internals/marshaller/factories/channels/server_voice_channel_factory.dart b/lib/infrastructure/internals/marshaller/factories/channels/server_voice_channel_factory.dart index 7e21b288..f46f188b 100644 --- a/lib/infrastructure/internals/marshaller/factories/channels/server_voice_channel_factory.dart +++ b/lib/infrastructure/internals/marshaller/factories/channels/server_voice_channel_factory.dart @@ -9,13 +9,23 @@ final class ServerVoiceChannelFactory implements ChannelFactoryContract ChannelType.guildVoice; @override - Future serializeRemote(MarshallerContract marshaller, String guildId, Map json) async { - final properties = await ChannelProperties.serializeRemote(marshaller, json); - return ServerVoiceChannel(properties); + Future normalize(MarshallerContract marshaller, Map json) async { + final payload = { + 'id': json['id'], + 'type': json['type'], + 'position': json['position'], + 'name': json['name'], + 'guild_id': json['guild_id'], + 'parent_id': json['parent_id'], + 'permission_overwrites': json['permission_overwrites'], + }; + + final cacheKey = marshaller.cacheKey.channel(json['id']); + await marshaller.cache.put(cacheKey, payload); } @override - Future serializeCache(MarshallerContract marshaller, String guildId, Map json) async { + Future serialize(MarshallerContract marshaller, Map json) async { final properties = await ChannelProperties.serializeCache(marshaller, json); return ServerVoiceChannel(properties); } diff --git a/lib/infrastructure/internals/marshaller/serializers/channel_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/channel_serializer.dart index 6c322d19..d2111ec2 100644 --- a/lib/infrastructure/internals/marshaller/serializers/channel_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/channel_serializer.dart @@ -29,18 +29,18 @@ final class ChannelSerializer implements SerializerContract< ChannelSerializer(this._marshaller); @override - Future serializeRemote(Map json) async { + Future normalize(Map json) async { final channelFactory = _factories.firstWhereOrNull((element) => element.type.value == json['type']); if (channelFactory == null) { _marshaller.logger.warn('Channel type not found ${json['type']}'); return null as T; } - return channelFactory.serializeRemote(_marshaller, json['guild_id'] ?? json['id'], json) as Future; + return channelFactory.normalize(_marshaller, json) as Future; } @override - Future serializeCache(Map json) { + Future serialize(Map json) { final channelFactory = _factories.firstWhereOrNull((element) => element.type.value == json['type']); if (channelFactory == null) { @@ -48,7 +48,7 @@ final class ChannelSerializer implements SerializerContract< throw Exception('Channel type not found ${json['type']}'); } - return channelFactory.serializeCache(_marshaller, json['guild_id'] ?? json['id'], json) as Future; + return channelFactory.serialize(_marshaller, json) as Future; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart index bdb5b114..8b104d9a 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart @@ -11,23 +11,24 @@ final class ServerMessageSerializer implements SerializerContract ServerMessageSerializer(this.marshaller); @override - Future serializeRemote(Map json) async { - final channel = await marshaller.dataStore.channel.getChannel(Snowflake(json['channel_id'])); - - if (channel == null) { - throw Exception('Channel not found'); - } - - final server = await marshaller.dataStore.server.getServer(channel.guildId); - final member = server.members.list[json['author']['id']]; - - final messageProperties = MessageProperties.fromJson(channel, json); + Future normalize(Map json) async { + final payload = { + 'id': json['id'], + 'content': json['content'], + 'embeds': json['embeds'], + // 'components': json['components'], + 'channel_id': json['channel_id'], + 'guild_id': json['guild_id'], + 'timestamp': json['timestamp'], + 'edited_timestamp': json['edited_timestamp'], + }; - return ServerMessage(messageProperties, author: member!); + final cacheKey = marshaller.cacheKey.serverMessage(messageId: json['id'], channelId: Snowflake(json['channel_id'])); + await marshaller.cache.put(cacheKey, payload); } @override - Future serializeCache(Map json) async { + Future serialize(Map json) async { final channel = await marshaller.dataStore.channel .getChannel(Snowflake(json['channel_id'])); diff --git a/lib/infrastructure/internals/marshaller/serializers/server_subscription_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_subscription_serializer.dart index f615820a..5bddf649 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_subscription_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_subscription_serializer.dart @@ -5,12 +5,12 @@ import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dar final class ServerSubscriptionSerializer implements SerializerContract { @override - ServerSubscription serializeRemote(Map json) => _serialize(json); + Future normalize(Map json) async { + throw UnimplementedError(); + } @override - ServerSubscription serializeCache(Map json) => _serialize(json); - - ServerSubscription _serialize(Map json) { + ServerSubscription serialize(Map json) { return ServerSubscription( tier: findInEnum(PremiumTier.values, json['premium_tier']), subscriptionCount: json['premium_subscription_count'], diff --git a/lib/infrastructure/internals/marshaller/types/channel_factory.dart b/lib/infrastructure/internals/marshaller/types/channel_factory.dart index a4228a47..a10cdd01 100644 --- a/lib/infrastructure/internals/marshaller/types/channel_factory.dart +++ b/lib/infrastructure/internals/marshaller/types/channel_factory.dart @@ -1,10 +1,12 @@ +import 'dart:async'; + import 'package:mineral/api/common/channel.dart'; import 'package:mineral/api/common/types/channel_type.dart'; import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; abstract interface class ChannelFactoryContract { ChannelType get type; - Future serializeRemote(MarshallerContract marshaller, String guildId, Map json); - Future serializeCache(MarshallerContract marshaller, String guildId, Map json); - Future> deserialize(MarshallerContract marshaller, T channel); + FutureOr normalize(MarshallerContract marshaller, Map json); + FutureOr serialize(MarshallerContract marshaller, Map json); + FutureOr> deserialize(MarshallerContract marshaller, T channel); } From 9a52f37c8dc1484f741491642dae037d9a8c3ab6 Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:19:23 +0200 Subject: [PATCH 09/44] feat(serialization): replace all serialize --- lib/api/common/message_properties.dart | 2 +- lib/api/server/managers/emoji_manager.dart | 2 +- lib/api/server/managers/sticker_manager.dart | 2 +- .../factories/messages/private_message_factory.dart | 2 +- .../serializers/global_command_context_serializer.dart | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/api/common/message_properties.dart b/lib/api/common/message_properties.dart index 37d20a2c..47be0a4c 100644 --- a/lib/api/common/message_properties.dart +++ b/lib/api/common/message_properties.dart @@ -25,7 +25,7 @@ final class MessageProperties { factory MessageProperties.fromJson(T channel, Map json) { final embedSerializer = ioc.resolve().serializers.embed; final embeds = List.from(json['embeds']) - .map((element) => embedSerializer.serializeRemote(element) as MessageEmbed) + .map((element) => embedSerializer.serialize(element) as MessageEmbed) .toList(); return MessageProperties( diff --git a/lib/api/server/managers/emoji_manager.dart b/lib/api/server/managers/emoji_manager.dart index c0183f12..2f9d6df7 100644 --- a/lib/api/server/managers/emoji_manager.dart +++ b/lib/api/server/managers/emoji_manager.dart @@ -13,7 +13,7 @@ final class EmojiManager { factory EmojiManager.fromJson(MarshallerContract marshaller, {required List roles, required List payload}) { return EmojiManager(Map.from(payload.fold({}, (value, element) { - final emoji = marshaller.serializers.emojis.serializeRemote({ + final emoji = marshaller.serializers.emojis.serialize({ 'guildRoles': roles, ...element, }) as Emoji; diff --git a/lib/api/server/managers/sticker_manager.dart b/lib/api/server/managers/sticker_manager.dart index 780dc964..3b67c213 100644 --- a/lib/api/server/managers/sticker_manager.dart +++ b/lib/api/server/managers/sticker_manager.dart @@ -11,7 +11,7 @@ final class StickerManager { factory StickerManager.fromJson(MarshallerContract marshaller, List payload) { final Map stickers = payload.fold({}, (value, element) { - final sticker = marshaller.serializers.sticker.serializeRemote(element) as Sticker; + final sticker = marshaller.serializers.sticker.serialize(element) as Sticker; return {...value, sticker.id: sticker}; }); diff --git a/lib/infrastructure/internals/marshaller/factories/messages/private_message_factory.dart b/lib/infrastructure/internals/marshaller/factories/messages/private_message_factory.dart index 269098b1..c5d49a39 100644 --- a/lib/infrastructure/internals/marshaller/factories/messages/private_message_factory.dart +++ b/lib/infrastructure/internals/marshaller/factories/messages/private_message_factory.dart @@ -11,7 +11,7 @@ final class PrivateMessageFactory implements MessageFactory { final channel = await marshaller.dataStore.channel.getChannel(json['channel_id']); final messageProperties = MessageProperties.fromJson(channel as PrivateChannel, json); - final user = await marshaller.serializers.user.serializeRemote(json['author']); + final user = await marshaller.serializers.user.serialize(json['author']); return PrivateMessage(messageProperties, userId: json['author']['id'], author: user); } diff --git a/lib/infrastructure/internals/marshaller/serializers/global_command_context_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/global_command_context_serializer.dart index 6469dd8d..9bf61a92 100644 --- a/lib/infrastructure/internals/marshaller/serializers/global_command_context_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/global_command_context_serializer.dart @@ -17,8 +17,8 @@ final class GlobalCommandContextSerializer implements SerializerContract Date: Fri, 16 Aug 2024 23:19:51 +0200 Subject: [PATCH 10/44] feat(serialization): replace the Snowflake to nullable --- lib/api/common/polls/poll.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/api/common/polls/poll.dart b/lib/api/common/polls/poll.dart index 3004a203..181963fd 100644 --- a/lib/api/common/polls/poll.dart +++ b/lib/api/common/polls/poll.dart @@ -8,7 +8,7 @@ final class Poll { final List answers; final Duration? expireAt; final bool isAllowMultiple; - final Snowflake messageId; + final Snowflake? messageId; final PollLayout layout; Poll({ @@ -16,7 +16,7 @@ final class Poll { required this.answers, required this.expireAt, required this.isAllowMultiple, - required this.messageId, + this.messageId, this.layout = PollLayout.initial, }); } From a84af4e7a22f91a5eaac3f77e7afc9dcd2958de4 Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:20:03 +0200 Subject: [PATCH 11/44] feat(serialization): replace String to Snowflake --- lib/api/private/private_message.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/private/private_message.dart b/lib/api/private/private_message.dart index a96acd5c..d85bb7a6 100644 --- a/lib/api/private/private_message.dart +++ b/lib/api/private/private_message.dart @@ -26,7 +26,7 @@ final class PrivateMessage implements Message { DateTime? get updatedAt => _properties.updatedAt; - final String userId; + final Snowflake userId; final User author; From 0e860dc455f41051aa536ca6665f1b647aeb5fd2 Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:20:17 +0200 Subject: [PATCH 12/44] feat(serialization): finish message serialization --- .../private_message_serializer.dart | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart index 90108ad3..cb552183 100644 --- a/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart @@ -11,18 +11,34 @@ final class PrivateMessageSerializer implements SerializerContract serializeRemote(Map json) async { - final channel = await marshaller.dataStore.channel.getChannel(Snowflake(json['channel_id'])); - - final messageProperties = MessageProperties.fromJson(channel as PrivateChannel, json); - final user = await marshaller.serializers.user.serializeRemote(json['author']); + Future normalize(Map json) async { + final payload = { + 'id': json['id'], + 'content': json['content'], + 'embeds': json['embeds'], + 'channel_id': json['channel_id'], + 'created_at': json['created_at'], + 'updated_at': json['updated_at'], + }; - return PrivateMessage(messageProperties, userId: json['author']['id'], author: user); + final cacheKey = marshaller.cacheKey.privateMessage(messageId: json['id'], channelId: Snowflake(json['channel_id'])); + await marshaller.cache.put(cacheKey, payload); } @override - Future serializeCache(Map json) { - throw UnimplementedError(); + Future serialize(Map json) async { + final properties = MessageProperties( + id: Snowflake(json['id']), + content: json['content'], + embeds: json['embeds'], + createdAt: DateTime.parse(json['created_at']), + updatedAt: json['updated_at'] != null ? DateTime.parse(json['updated_at']) : null, + channelId: Snowflake(json['channel_id']), + ); + + final user = await marshaller.serializers.user.serialize(json['user']); + + return PrivateMessage(properties, userId: user.id, author: user); } @override From 730430407a0ac0f5ceaa9164fde9ff1bcba25e28 Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:23:57 +0200 Subject: [PATCH 13/44] feat(serialization): set the new serialize service --- .../internals/datastore/parts/channel_part.dart | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/infrastructure/internals/datastore/parts/channel_part.dart b/lib/infrastructure/internals/datastore/parts/channel_part.dart index b3b8bf88..cb7a01ac 100644 --- a/lib/infrastructure/internals/datastore/parts/channel_part.dart +++ b/lib/infrastructure/internals/datastore/parts/channel_part.dart @@ -30,7 +30,7 @@ final class ChannelPart implements DataStorePart { final cachedChannel = await _kernel.marshaller.cache.get(key); if (cachedChannel != null) { - return _kernel.marshaller.serializers.channels.serializeCache(cachedChannel) as Future; + return _kernel.marshaller.serializers.channels.serialize(cachedChannel) as Future; } final response = await _kernel.dataStore.client.get('/channels/$id'); @@ -115,17 +115,20 @@ final class ChannelPart implements DataStorePart { _ => throw Exception('Unknown channel type: $channel'), } as SerializerContract; - final Message message = await serializer.serializeRemote(response.body); + await serializer.normalize(response.body); + final Message message = await serializer.serialize(response.body); await _kernel.marshaller.cache.put(message.id.value, {...response.body, 'guild_id': guildId}); return message as T; } - Future serializeChannelResponse(Response response) { + Future serializeChannelResponse(Response response) async { return switch (response.statusCode) { - int() when status.isSuccess(response.statusCode) => - _kernel.marshaller.serializers.channels.serializeRemote(response.body), + int() when status.isSuccess(response.statusCode) => { + await _kernel.marshaller.serializers.channels.normalize(response.body), + _kernel.marshaller.serializers.channels.serialize(response.body), + }, int() when status.isError(response.statusCode) => throw HttpException(response.bodyString), _ => throw Exception('Unknown status code: ${response.statusCode} ${response.bodyString}'), } as Future; From 7a4a58c48fda988db0a8ee019ea284ced39c3ee9 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Sat, 17 Aug 2024 00:33:02 +0200 Subject: [PATCH 14/44] feat(marshaller): add normalize return map --- .../factories/channels/private_channel_factory.dart | 4 +++- .../channels/server_announcement_channel_factory.dart | 4 +++- .../factories/channels/server_category_channel_factory.dart | 4 +++- .../factories/channels/server_forum_channel_factory.dart | 4 +++- .../factories/channels/server_stage_channel_factory.dart | 4 +++- .../factories/channels/server_text_channel_factory.dart | 4 +++- .../factories/channels/server_voice_channel_factory.dart | 4 +++- .../channel_permission_overwrite_serializer.dart | 4 +++- .../marshaller/serializers/channel_serializer.dart | 6 +++--- .../internals/marshaller/serializers/embed_serializer.dart | 4 +++- .../internals/marshaller/serializers/emoji_serializer.dart | 4 +++- .../marshaller/serializers/member_assets_serializer.dart | 4 +++- .../internals/marshaller/serializers/member_serializer.dart | 4 +++- .../internals/marshaller/serializers/poll_serializer.dart | 4 +++- .../marshaller/serializers/private_message_serializer.dart | 4 +++- .../internals/marshaller/serializers/role_serializer.dart | 4 +++- .../marshaller/serializers/server_assets_serializer.dart | 4 +++- .../marshaller/serializers/server_message_serializer.dart | 4 +++- .../internals/marshaller/serializers/server_serializer.dart | 4 +++- .../marshaller/serializers/server_settings_serializer.dart | 4 +++- .../serializers/server_subscription_serializer.dart | 2 +- .../marshaller/serializers/sticker_serializer.dart | 4 +++- .../marshaller/serializers/user_assets_serializer.dart | 4 +++- .../internals/marshaller/serializers/user_serializer.dart | 4 +++- .../internals/marshaller/types/channel_factory.dart | 2 +- .../internals/marshaller/types/serializer.dart | 2 +- 26 files changed, 72 insertions(+), 28 deletions(-) diff --git a/lib/infrastructure/internals/marshaller/factories/channels/private_channel_factory.dart b/lib/infrastructure/internals/marshaller/factories/channels/private_channel_factory.dart index f22cb413..1c5d3949 100644 --- a/lib/infrastructure/internals/marshaller/factories/channels/private_channel_factory.dart +++ b/lib/infrastructure/internals/marshaller/factories/channels/private_channel_factory.dart @@ -15,7 +15,7 @@ final class PrivateChannelFactory implements ChannelFactoryContract normalize(MarshallerContract marshaller, Map json) async { + Future> normalize(MarshallerContract marshaller, Map json) async { final payload = { 'id': json['id'], 'type': json['type'], @@ -28,6 +28,8 @@ final class PrivateChannelFactory implements ChannelFactoryContract ChannelType.guildAnnouncement; @override - Future normalize(MarshallerContract marshaller, Map json) async { + Future> normalize(MarshallerContract marshaller, Map json) async { final payload = { 'id': json['id'], 'type': json['type'], @@ -26,6 +26,8 @@ final class ServerAnnouncementChannelFactory implements ChannelFactoryContract ChannelType.guildCategory; @override - Future normalize(MarshallerContract marshaller, Map json) async { + Future> normalize(MarshallerContract marshaller, Map json) async { final payload = { 'id': json['id'], 'type': json['type'], @@ -23,6 +23,8 @@ final class ServerCategoryChannelFactory implements ChannelFactoryContract ChannelType.guildForum; @override - Future normalize(MarshallerContract marshaller, Map json) async { + Future> normalize(MarshallerContract marshaller, Map json) async { final payload = { 'id': json['id'], 'type': json['type'], @@ -27,6 +27,8 @@ final class ServerForumChannelFactory implements ChannelFactoryContract ChannelType.guildStageVoice; @override - Future normalize(MarshallerContract marshaller, Map json) async { + Future> normalize(MarshallerContract marshaller, Map json) async { final payload = { 'id': json['id'], 'type': json['type'], @@ -23,6 +23,8 @@ final class ServerStageChannelFactory implements ChannelFactoryContract ChannelType.guildText; @override - Future normalize(MarshallerContract marshaller, Map json) async { + Future> normalize(MarshallerContract marshaller, Map json) async { final payload = { 'id': json['id'], 'type': json['type'], @@ -23,6 +23,8 @@ final class ServerTextChannelFactory implements ChannelFactoryContract ChannelType.guildVoice; @override - Future normalize(MarshallerContract marshaller, Map json) async { + Future> normalize(MarshallerContract marshaller, Map json) async { final payload = { 'id': json['id'], 'type': json['type'], @@ -22,6 +22,8 @@ final class ServerVoiceChannelFactory implements ChannelFactoryContract normalize(Map json) async { + Future> normalize(Map json) async { final payload = { 'id': json['id'], 'type': json['type'], @@ -22,6 +22,8 @@ final class ChannelPermissionOverwriteSerializer final cacheKey = marshaller.cacheKey .channelPermission(Snowflake(payload['id']), serverId: json['server_id']); await marshaller.cache.put(cacheKey, payload); + + return payload; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/channel_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/channel_serializer.dart index d2111ec2..e3ee1cab 100644 --- a/lib/infrastructure/internals/marshaller/serializers/channel_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/channel_serializer.dart @@ -29,14 +29,14 @@ final class ChannelSerializer implements SerializerContract< ChannelSerializer(this._marshaller); @override - Future normalize(Map json) async { + Future> normalize(Map json) async { final channelFactory = _factories.firstWhereOrNull((element) => element.type.value == json['type']); if (channelFactory == null) { _marshaller.logger.warn('Channel type not found ${json['type']}'); - return null as T; + return {}; } - return channelFactory.normalize(_marshaller, json) as Future; + return channelFactory.normalize(_marshaller, json); } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/embed_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/embed_serializer.dart index 6a34fbf6..b704f213 100644 --- a/lib/infrastructure/internals/marshaller/serializers/embed_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/embed_serializer.dart @@ -12,7 +12,7 @@ import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dar final class EmbedSerializer implements SerializerContract { @override - Future normalize(Map json) async { + Future> normalize(Map json) async { final payload = { 'title': json['title'], 'description': json['description'], @@ -27,6 +27,8 @@ final class EmbedSerializer implements SerializerContract { final cacheKey = _marshaller.cacheKey.embed(json['id']); await _marshaller.cache.put(cacheKey, payload); + + return payload; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/emoji_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/emoji_serializer.dart index 25f949db..567a30ce 100644 --- a/lib/infrastructure/internals/marshaller/serializers/emoji_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/emoji_serializer.dart @@ -10,7 +10,7 @@ final class EmojiSerializer implements SerializerContract { EmojiSerializer(this._marshaller); @override - Future normalize(Map json) async { + Future> normalize(Map json) async { final payload = { 'id': json['id'], 'name': json['name'], @@ -24,6 +24,8 @@ final class EmojiSerializer implements SerializerContract { final cacheKey = _marshaller.cacheKey.serverEmoji(json['server_id'], json['id']); await _marshaller.cache.put(cacheKey, payload); + + return payload; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart index 85ee0916..003e15d4 100644 --- a/lib/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart @@ -11,7 +11,7 @@ final class MemberAssetsSerializer implements SerializerContract { MemberAssetsSerializer(this._marshaller); @override - Future normalize(Map json) async { + Future> normalize(Map json) async { final payload = { 'member_id': json['member_id'], 'avatar': json['avatar'], @@ -21,6 +21,8 @@ final class MemberAssetsSerializer implements SerializerContract { final cacheKey = _marshaller.cacheKey.memberAssets(json['guild_id'], json['user']['id']); await _marshaller.cache.put(cacheKey, payload); + + return payload; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart index c3029406..01381267 100644 --- a/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart @@ -17,7 +17,7 @@ final class MemberSerializer implements SerializerContract { MemberSerializer(this._marshaller); @override - Future normalize(Map json) async { + Future> normalize(Map json) async { await _marshaller.serializers.memberAssets.normalize({ ...json, 'member_id': json['id'], @@ -50,6 +50,8 @@ final class MemberSerializer implements SerializerContract { final cacheKey = _marshaller.cacheKey.member(json['guild_id'], json['user']['id']); await _marshaller.cache.put(cacheKey, payload); + + return payload; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/poll_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/poll_serializer.dart index 16c7adc3..1ab8e32e 100644 --- a/lib/infrastructure/internals/marshaller/serializers/poll_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/poll_serializer.dart @@ -10,7 +10,7 @@ import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dar final class PollSerializer implements SerializerContract { @override - Future normalize(Map json) async { + Future> normalize(Map json) async { final payload = { 'message_id': json['message_id'], 'question_text': json['question']['text'], @@ -22,6 +22,8 @@ final class PollSerializer implements SerializerContract { final cacheKey = _marshaller.cacheKey.poll(json['message_id']); await _marshaller.cache.put(cacheKey, payload); + + return payload; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart index cb552183..7d670c71 100644 --- a/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart @@ -11,7 +11,7 @@ final class PrivateMessageSerializer implements SerializerContract normalize(Map json) async { + Future> normalize(Map json) async { final payload = { 'id': json['id'], 'content': json['content'], @@ -23,6 +23,8 @@ final class PrivateMessageSerializer implements SerializerContract { RoleSerializer(this.marshaller); @override - Future normalize(Map json) async { + Future> normalize(Map json) async { final payload = { 'id': json['id'], 'name': json['name'], @@ -27,6 +27,8 @@ final class RoleSerializer implements SerializerContract { final cacheKey = marshaller.cacheKey.serverRole(json['server_id'], json['id']); await marshaller.cache.put(cacheKey, payload); + + return payload; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/server_assets_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_assets_serializer.dart index 31c88ada..bdb15a4f 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_assets_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_assets_serializer.dart @@ -13,7 +13,7 @@ final class ServerAssetsSerializer implements SerializerContract { ServerAssetsSerializer(this._marshaller); @override - Future normalize(Map json) async { + Future> normalize(Map json) async { final cacheKey = _marshaller.cacheKey.serverAssets(json['id']); await List.from(json['roles']).map((element) async { @@ -39,6 +39,8 @@ final class ServerAssetsSerializer implements SerializerContract { }; _marshaller.cache.put(cacheKey, payload); + + return payload; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart index 8b104d9a..6c2ebf69 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart @@ -11,7 +11,7 @@ final class ServerMessageSerializer implements SerializerContract ServerMessageSerializer(this.marshaller); @override - Future normalize(Map json) async { + Future> normalize(Map json) async { final payload = { 'id': json['id'], 'content': json['content'], @@ -25,6 +25,8 @@ final class ServerMessageSerializer implements SerializerContract final cacheKey = marshaller.cacheKey.serverMessage(messageId: json['id'], channelId: Snowflake(json['channel_id'])); await marshaller.cache.put(cacheKey, payload); + + return payload; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart index ded54667..976aebda 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart @@ -21,7 +21,7 @@ final class ServerSerializer implements SerializerContract { ServerSerializer(this._marshaller); @override - Future normalize(Map json) async { + Future> normalize(Map json) async { await List.from(json['members']).map((element) async { return _marshaller.serializers.member.normalize({...element, 'server_id': json['id']}); }).wait; @@ -50,6 +50,8 @@ final class ServerSerializer implements SerializerContract { final serverCacheKey = _marshaller.cacheKey.server(json['id']); await _marshaller.cache.put(serverCacheKey, serverPayload); + + return serverPayload; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/server_settings_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_settings_serializer.dart index 2120de4a..b9292d80 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_settings_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_settings_serializer.dart @@ -15,7 +15,7 @@ final class ServerSettingsSerializer implements SerializerContract normalize(Map json) async { + Future> normalize(Map json) async { final payload = { 'permissions': json['permissions'], 'afk_timeout': json['afk_timeout'], @@ -37,6 +37,8 @@ final class ServerSettingsSerializer implements SerializerContract { @override - Future normalize(Map json) async { + Future> normalize(Map json) async { throw UnimplementedError(); } diff --git a/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart index ea4fd491..2f4d9f32 100644 --- a/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart @@ -6,7 +6,7 @@ import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dar final class StickerSerializer implements SerializerContract { @override - Future normalize(Map json) async { + Future> normalize(Map json) async { final payload = { 'id': json['id'], 'name': json['name'], @@ -22,6 +22,8 @@ final class StickerSerializer implements SerializerContract { final cacheKey = _marshaller.cacheKey.sticker(json['id']); await _marshaller.cache.put(cacheKey, payload); + + return payload; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart index 7e317daa..e4dc2fa5 100644 --- a/lib/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart @@ -12,7 +12,7 @@ final class UserAssetsSerializer implements SerializerContract { UserAssetsSerializer(this._marshaller); @override - Future normalize(Map json) async { + Future> normalize(Map json) async { final payload = { 'user_id': json['user_id'], 'avatar': json['avatar'], @@ -22,6 +22,8 @@ final class UserAssetsSerializer implements SerializerContract { final cacheKey = _marshaller.cacheKey.userAssets(json['user_id']); await _marshaller.cache.put(cacheKey, payload); + + return payload; } @override diff --git a/lib/infrastructure/internals/marshaller/serializers/user_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/user_serializer.dart index f53736ce..8455c94d 100644 --- a/lib/infrastructure/internals/marshaller/serializers/user_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/user_serializer.dart @@ -7,7 +7,7 @@ import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dar final class UserSerializer implements SerializerContract { @override - Future normalize(Map json) async { + Future> normalize(Map json) async { await _marshaller.serializers.userAssets.normalize({ ...json, 'user_id': json['id'], @@ -32,6 +32,8 @@ final class UserSerializer implements SerializerContract { final cacheKey = _marshaller.cacheKey.user(json['id']); await _marshaller.cache.put(cacheKey, payload); + + return payload; } @override diff --git a/lib/infrastructure/internals/marshaller/types/channel_factory.dart b/lib/infrastructure/internals/marshaller/types/channel_factory.dart index a10cdd01..166dd52e 100644 --- a/lib/infrastructure/internals/marshaller/types/channel_factory.dart +++ b/lib/infrastructure/internals/marshaller/types/channel_factory.dart @@ -6,7 +6,7 @@ import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; abstract interface class ChannelFactoryContract { ChannelType get type; - FutureOr normalize(MarshallerContract marshaller, Map json); + FutureOr> normalize(MarshallerContract marshaller, Map json); FutureOr serialize(MarshallerContract marshaller, Map json); FutureOr> deserialize(MarshallerContract marshaller, T channel); } diff --git a/lib/infrastructure/internals/marshaller/types/serializer.dart b/lib/infrastructure/internals/marshaller/types/serializer.dart index 52a56e2e..eec258d3 100644 --- a/lib/infrastructure/internals/marshaller/types/serializer.dart +++ b/lib/infrastructure/internals/marshaller/types/serializer.dart @@ -1,7 +1,7 @@ import 'dart:async'; abstract interface class SerializerContract { - FutureOr normalize(Map json); + FutureOr> normalize(Map json); FutureOr serialize(Map json); FutureOr> deserialize(T object); } From eb44c9b5bf1248eda83f90d7a376771281d22519 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Sat, 17 Aug 2024 00:33:22 +0200 Subject: [PATCH 15/44] feat(marshaller): rework member part --- .../datastore/parts/member_part.dart | 95 +++++++------------ 1 file changed, 34 insertions(+), 61 deletions(-) diff --git a/lib/infrastructure/internals/datastore/parts/member_part.dart b/lib/infrastructure/internals/datastore/parts/member_part.dart index 491fd7e1..117dc53c 100644 --- a/lib/infrastructure/internals/datastore/parts/member_part.dart +++ b/lib/infrastructure/internals/datastore/parts/member_part.dart @@ -8,7 +8,6 @@ import 'package:mineral/infrastructure/internals/http/discord_header.dart'; import 'package:mineral/infrastructure/kernel/kernel.dart'; import 'package:mineral/infrastructure/services/http/http_client_status.dart'; import 'package:mineral/infrastructure/services/http/http_request_option.dart'; -import 'package:mineral/infrastructure/services/http/response.dart'; final class MemberPart implements DataStorePart { final KernelContract _kernel; @@ -19,56 +18,47 @@ final class MemberPart implements DataStorePart { Future getMember({required Snowflake guildId, required Snowflake memberId}) async { final cacheKeys = _kernel.marshaller.cacheKey; - final memberCacheKey = cacheKeys.serverMember(serverId: guildId, memberId: memberId); + final memberCacheKey = cacheKeys.member(guildId, memberId); - final cachedRawMember = await _kernel.marshaller.cache.get(memberCacheKey); - final roles = await _kernel.dataStore.server.getRoles(guildId); + Map? cachedRawMember = await _kernel.marshaller.cache.get(memberCacheKey); if (cachedRawMember != null) { - return _kernel.marshaller.serializers.member.serializeRemote({ - ...cachedRawMember, - 'guild_roles': roles, - }); + return _kernel.marshaller.serializers.member.serialize(cachedRawMember); } final response = await _kernel.dataStore.client.get('/guilds/$guildId/members/$memberId'); - final member = await switch (response.statusCode) { - int() when status.isSuccess(response.statusCode) => - _kernel.marshaller.serializers.member.serializeRemote({ - ...response.body, - 'guild_roles': roles, - }), - int() when status.isError(response.statusCode) => throw HttpException(response.body), - _ => throw Exception('Unknown status code: ${response.statusCode}'), - }; - - final rawMember = await _kernel.marshaller.serializers.member.deserialize(member); - await _kernel.marshaller.cache.put(memberCacheKey, rawMember); - - return member; - } + if (status.isError(response.statusCode)) { + throw HttpException(response.body); + } - Future> getMembers(Snowflake guildId, {bool force = false}) async { - if (force) { - final response = await _kernel.dataStore.client.get('/guilds/$guildId/members'); - final members = await _serializeMembersResponse(response); + await _kernel.marshaller.serializers.member.normalize(response.body); - await Future.wait( - members.map((member) async => _kernel.marshaller.serializers.member.deserialize(member))); + cachedRawMember = await _kernel.marshaller.cache.getOrFail(memberCacheKey); - return members; + return _kernel.marshaller.serializers.member.serialize(cachedRawMember); + } + + Future> getMembers(Snowflake guildId, {bool force = false}) async { + final serverCacheKey = _kernel.marshaller.cacheKey.server(guildId); + final rawServer = await _kernel.marshaller.cache.getOrFail(serverCacheKey); + + final rawMemberIds = List.from(rawServer['members']); + final rawCachedMembers = await _kernel.marshaller.cache.getMany(rawMemberIds); + if (rawMemberIds.length == rawCachedMembers.length) { + return Future.wait(rawCachedMembers.nonNulls + .map((element) async => _kernel.marshaller.serializers.member.serialize(element)) + .toList()); } - final rawServer = await _kernel.marshaller.cache.getOrFail(guildId.value); - final roles = await _kernel.dataStore.server.getRoles(guildId); + final response = await _kernel.dataStore.client.get('/guilds/$guildId/members'); + if (status.isError(response.statusCode)) { + throw HttpException(response.body); + } - return Future.wait(List.from(rawServer['members']).map((id) async { - final rawMember = await _kernel.marshaller.cache.getOrFail(id); - return _kernel.marshaller.serializers.member.serializeRemote({ - ...rawMember, - 'guild_roles': roles, - }); - })); + return List.from(response.body).map((id) async { + final payload = await _kernel.marshaller.serializers.member.normalize(id); + return _kernel.marshaller.serializers.member.serialize(payload); + }).wait; } Future updateMember( @@ -80,17 +70,12 @@ final class MemberPart implements DataStorePart { body: payload, option: HttpRequestOptionImpl(headers: {DiscordHeader.auditLogReason(reason)})); - final member = await switch (response.statusCode) { - int() when status.isSuccess(response.statusCode) => - _kernel.marshaller.serializers.member.serializeRemote(response.body), - int() when status.isError(response.statusCode) => throw HttpException(response.body), - _ => throw Exception('Unknown status code: ${response.statusCode}'), - }; - - final rawMember = await _kernel.marshaller.serializers.member.deserialize(member); - await _kernel.marshaller.cache.put(memberId.value, rawMember); + if (status.isError(response.statusCode)) { + throw HttpException(response.body); + } - return member; + final rawMember = await _kernel.marshaller.serializers.member.normalize(response.body); + return _kernel.marshaller.serializers.member.serialize(rawMember); } Future banMember( @@ -116,16 +101,4 @@ final class MemberPart implements DataStorePart { return; } } - - Future> _serializeMembersResponse(Response response) { - final awaitedMembers = switch (response.statusCode) { - int() when status.isSuccess(response.statusCode) => List.from(response.body) - .map((element) async => _kernel.marshaller.serializers.member.serializeRemote(element)) - .toList(), - int() when status.isError(response.statusCode) => throw HttpException(response.body), - _ => throw Exception('Unknown status code: ${response.statusCode}'), - }; - - return Future.wait(awaitedMembers); - } } From 3ff8661119d3798180245d0f176807ead7194c30 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Sat, 17 Aug 2024 01:18:45 +0200 Subject: [PATCH 16/44] feat(marshaller): rework server part --- .../internals/datastore/parts/role_part.dart | 35 ++---- .../datastore/parts/server_part.dart | 103 +++++++----------- 2 files changed, 47 insertions(+), 91 deletions(-) diff --git a/lib/infrastructure/internals/datastore/parts/role_part.dart b/lib/infrastructure/internals/datastore/parts/role_part.dart index 72a618d4..d7321a3f 100644 --- a/lib/infrastructure/internals/datastore/parts/role_part.dart +++ b/lib/infrastructure/internals/datastore/parts/role_part.dart @@ -18,22 +18,20 @@ final class RolePart implements DataStorePart { RolePart(this._kernel); Future getRole({required Snowflake guildId, required Snowflake roleId}) async { - final cacheKey = _kernel.marshaller.cacheKey.serverRole(serverId: guildId, roleId: roleId); + final cacheKey = _kernel.marshaller.cacheKey.serverRole(guildId, roleId); final rawRole = await _kernel.marshaller.cache.get(cacheKey); if (rawRole != null) { - return _kernel.marshaller.serializers.role.serializeRemote(rawRole); + return _kernel.marshaller.serializers.role.serialize(rawRole); } final response = await _kernel.dataStore.client.get('/guilds/$guildId/roles/$roleId'); - final role = await serializeRoleResponse(response); - - if (role != null) { - final rawRole = _kernel.marshaller.serializers.role.deserialize(response.body); - await _kernel.marshaller.cache.put(cacheKey, rawRole); + if (status.isError(response.statusCode)) { + throw HttpException(response.body); } - return role!; + final payload = await _kernel.marshaller.serializers.role.normalize(response.body); + return _kernel.marshaller.serializers.role.serialize(payload); } Future addRole( @@ -73,16 +71,12 @@ final class RolePart implements DataStorePart { body: payload, option: HttpRequestOptionImpl(headers: {DiscordHeader.auditLogReason(reason)})); - final Role? role = await serializeRoleResponse(response); - - if (role != null) { - final roleCacheKey = _kernel.marshaller.cacheKey.serverRole(serverId: serverId, roleId: id); - final rawRole = _kernel.marshaller.serializers.role.deserialize(response.body); - - await _kernel.marshaller.cache.put(roleCacheKey, rawRole); + if (status.isError(response.statusCode)) { + throw HttpException(response.body); } - return role; + final body = await _kernel.marshaller.serializers.role.normalize(response.body); + return _kernel.marshaller.serializers.role.serialize(body); } Future deleteRole( @@ -90,13 +84,4 @@ final class RolePart implements DataStorePart { await _kernel.dataStore.client.delete('/guilds/$guildId/roles/$id', option: HttpRequestOptionImpl(headers: {DiscordHeader.auditLogReason(reason)})); } - - Future serializeRoleResponse(Response response) { - return switch (response.statusCode) { - int() when status.isSuccess(response.statusCode) => - _kernel.marshaller.serializers.role.serializeRemote(response.body), - int() when status.isError(response.statusCode) => throw HttpException(response.bodyString), - _ => throw Exception('Unknown status code: ${response.statusCode} ${response.bodyString}'), - } as Future; - } } diff --git a/lib/infrastructure/internals/datastore/parts/server_part.dart b/lib/infrastructure/internals/datastore/parts/server_part.dart index 2b849388..386fadb5 100644 --- a/lib/infrastructure/internals/datastore/parts/server_part.dart +++ b/lib/infrastructure/internals/datastore/parts/server_part.dart @@ -2,12 +2,12 @@ import 'dart:async'; import 'dart:io'; import 'package:mineral/api/common/snowflake.dart'; +import 'package:mineral/api/server/channels/server_channel.dart'; import 'package:mineral/api/server/role.dart'; import 'package:mineral/api/server/server.dart'; import 'package:mineral/infrastructure/internals/datastore/data_store_part.dart'; import 'package:mineral/infrastructure/kernel/kernel.dart'; import 'package:mineral/infrastructure/services/http/http_client_status.dart'; -import 'package:mineral/infrastructure/services/http/response.dart'; final class ServerPart implements DataStorePart { final KernelContract _kernel; @@ -22,83 +22,54 @@ final class ServerPart implements DataStorePart { final rawServer = await _kernel.marshaller.cache.get(serverCacheKey); if (rawServer != null) { - return _kernel.marshaller.serializers.server.serializeCache(rawServer); + return _kernel.marshaller.serializers.server.serialize(rawServer); } - final [serverResponse, channelsResponse, membersResponse] = await Future.wait([ - _kernel.dataStore.client.get('/guilds/$id'), - _kernel.dataStore.client.get('/guilds/$id/channels'), - _kernel.dataStore.client.get('/guilds/$id/members') - ]); - - final server = await _kernel.marshaller.serializers.server.serializeRemote({ - ...serverResponse.body, - 'channels': channelsResponse.body, - 'members': membersResponse.body - }); - - await _kernel.marshaller.cache.putMany({ - serverCacheKey: await _kernel.marshaller.serializers.server.deserialize(server), - ...server.channels.list.values.fold({}, (acc, channel) { - final channelCacheKey = cacheKey.channel(channel.id); - final rawChannel = _kernel.marshaller.serializers.channels.deserialize(channel); - - return { ...acc, channelCacheKey: rawChannel }; - }), - ...server.members.list.values.fold({}, (acc, member) { - final memberCacheKey = cacheKey.serverMember(serverId: id, memberId: member.id); - final rawMember = _kernel.marshaller.serializers.member.deserialize(member); - - return { ...acc, memberCacheKey: rawMember }; - }) - }); - - return server; - } - - Future getRole(Snowflake guildId, Snowflake id) async { - final cachedRawRole = await _kernel.marshaller.cache.get(id.value); - if (cachedRawRole != null) { - return _kernel.marshaller.serializers.role.serializeRemote(cachedRawRole); - } + final serverResponse = await _kernel.dataStore.client.get('/guilds/$id'); - final response = await _kernel.dataStore.client.get('/guilds/$guildId/roles'); - final roles = await _serializeRolesResponse(response); - final role = roles.firstWhere((role) => role.id == id); - - final roleCacheKey = _kernel.marshaller.cacheKey.serverRole(serverId: guildId, roleId: id); - final rawRole = await _kernel.marshaller.serializers.role.deserialize(role); - await _kernel.marshaller.cache.put(roleCacheKey, rawRole); + await getChannels(id); + await _kernel.dataStore.member.getMembers(id); - return role; + return _kernel.marshaller.serializers.server.serialize(serverResponse.body); } - Future> getRoles(Snowflake guildId, {bool force = false}) async { - if (force) { - final response = await _kernel.dataStore.client.get('/guilds/$guildId/roles'); - final roles = await _serializeRolesResponse(response); + Future> getChannels(Snowflake id) async { + final response = await _kernel.dataStore.client.get('/guilds/$id/channels'); + if (status.isError(response.statusCode)) { + throw HttpException(response.body); + } - for (final role in roles) { - final roleCacheKey = - _kernel.marshaller.cacheKey.serverRole(serverId: guildId, roleId: role.id); - final rawRole = await _kernel.marshaller.serializers.role.deserialize(role); + return Future.wait(List.from(response.body).map((element) async { + final channel = await _kernel.marshaller.serializers.channels.normalize(element); + return _kernel.marshaller.serializers.channels.serialize(channel) as Future; + }).toList()); + } - await _kernel.marshaller.cache.put(roleCacheKey, rawRole); - } + Future getRole(Snowflake serverId, Snowflake roleId) async { + final roleCacheKey = _kernel.marshaller.cacheKey.serverRole(serverId, roleId); + final cachedRawRole = await _kernel.marshaller.cache.get(roleCacheKey); + if (cachedRawRole != null) { + return _kernel.marshaller.serializers.role.serialize(cachedRawRole); + } - return roles; + final response = await _kernel.dataStore.client.get('/guilds/$serverId/roles/$roleId'); + if (status.isError(response.statusCode)) { + throw HttpException(response.body); } - final rowServer = await _kernel.dataStore.server.getServer(guildId); - return rowServer.roles.list.values.toList(); + final rolePayload = await _kernel.marshaller.serializers.role.normalize(response.body); + return _kernel.marshaller.serializers.role.serialize(rolePayload); } - Future> _serializeRolesResponse(Response response) { - return switch (response.statusCode) { - int() when status.isSuccess(response.statusCode) => List.from(response.body) - .map((element) => _kernel.marshaller.serializers.channels.serializeRemote(element)), - int() when status.isError(response.statusCode) => throw HttpException(response.body), - _ => throw Exception('Unknown status code: ${response.statusCode}'), - } as Future>; + Future> getRoles(Snowflake guildId, {bool force = false}) async { + final response = await _kernel.dataStore.client.get('/guilds/$guildId/roles'); + if (status.isError(response.statusCode)) { + throw HttpException(response.body); + } + + return Future.wait(List.from(response.body).map((element) async { + final payload = await _kernel.marshaller.serializers.role.normalize(element); + return _kernel.marshaller.serializers.role.serialize(payload); + }).toList()); } } From bec06418cdf1a87a1bca4277e4405f273b510242 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Sat, 17 Aug 2024 01:20:33 +0200 Subject: [PATCH 17/44] feat(marshaller): rework user part --- .../internals/datastore/parts/user_part.dart | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/lib/infrastructure/internals/datastore/parts/user_part.dart b/lib/infrastructure/internals/datastore/parts/user_part.dart index a3863e85..bd6c986d 100644 --- a/lib/infrastructure/internals/datastore/parts/user_part.dart +++ b/lib/infrastructure/internals/datastore/parts/user_part.dart @@ -15,22 +15,18 @@ final class UserPart implements DataStorePart { UserPart(this._kernel); Future getUser(Snowflake userId) async { - final cachedRawUser = await _kernel.marshaller.cache.get(userId.value); + final cacheKey = _kernel.marshaller.cacheKey.user(userId); + final cachedRawUser = await _kernel.marshaller.cache.get(cacheKey); if (cachedRawUser != null) { - return _kernel.marshaller.serializers.user.serializeCache(cachedRawUser); + return _kernel.marshaller.serializers.user.serialize(cachedRawUser); } final response = await _kernel.dataStore.client.get('/users/$userId'); - final user = await switch (response.statusCode) { - int() when status.isSuccess(response.statusCode) => - _kernel.marshaller.serializers.user.serializeRemote(response.body), - int() when status.isError(response.statusCode) => throw HttpException(response.body), - _ => throw Exception('Unknown status code: ${response.statusCode}'), - }; - - final rawUser = await _kernel.marshaller.serializers.user.deserialize(user); - await _kernel.marshaller.cache.put(userId.value, rawUser); + if (status.isError(response.statusCode)) { + throw HttpException(response.body); + } - return user; + final payload = await _kernel.marshaller.serializers.user.normalize(response.body); + return _kernel.marshaller.serializers.user.serialize(payload); } } From 18862a47597d06a737444c5f94a9c5e018617e61 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Sat, 17 Aug 2024 10:09:12 +0200 Subject: [PATCH 18/44] feat(datastore): rework message part --- .../datastore/parts/message_part.dart | 71 ++++++++++--------- .../internals/datastore/parts/role_part.dart | 1 - .../internals/marshaller/cache_key.dart | 10 +-- .../server_message_serializer.dart | 6 +- 4 files changed, 43 insertions(+), 45 deletions(-) diff --git a/lib/infrastructure/internals/datastore/parts/message_part.dart b/lib/infrastructure/internals/datastore/parts/message_part.dart index 219ae7eb..ae9d1590 100644 --- a/lib/infrastructure/internals/datastore/parts/message_part.dart +++ b/lib/infrastructure/internals/datastore/parts/message_part.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:mineral/api/common/snowflake.dart'; import 'package:mineral/api/private/channels/private_channel.dart'; import 'package:mineral/api/private/private_message.dart'; @@ -5,65 +7,66 @@ import 'package:mineral/api/server/channels/server_channel.dart'; import 'package:mineral/api/server/server_message.dart'; import 'package:mineral/infrastructure/internals/datastore/data_store_part.dart'; import 'package:mineral/infrastructure/kernel/kernel.dart'; +import 'package:mineral/infrastructure/services/http/http_client_status.dart'; final class MessagePart implements DataStorePart { final KernelContract _kernel; + HttpClientStatus get status => _kernel.dataStore.client.status; + MessagePart(this._kernel); Future getServerMessage( {required Snowflake messageId, required Snowflake channelId}) async { - final messageCacheKey = - _kernel.marshaller.cacheKey.serverMessage(messageId: messageId, channelId: channelId); - - final message = await _kernel.marshaller.cache.get(messageCacheKey); - if (message != null) { - return _kernel.marshaller.serializers.serverMessage.serializeCache(message); - } + final messageCacheKey = _kernel.marshaller.cacheKey.message(channelId, channelId); + final channelCacheKey = _kernel.marshaller.cacheKey.channel(channelId); - final response = await _kernel.dataStore.client.get('/channels/$channelId/messages/$messageId'); + final rawMessage = await _kernel.marshaller.cache.get(messageCacheKey); + final rawChannel = await _kernel.marshaller.cache.getOrFail(channelCacheKey); + final serverChannel = + await _kernel.marshaller.serializers.channels.serialize(rawChannel) as ServerChannel; - final serverMessage = - await _kernel.marshaller.serializers.serverMessage.serializeRemote(response.body); + if (rawMessage != null) { + final message = await _kernel.marshaller.serializers.serverMessage.serialize(rawMessage) + ..channel = serverChannel; - final channelCacheKey = _kernel.marshaller.cacheKey.channel(channelId); - final rawChannel = await _kernel.marshaller.cache.getOrFail(channelCacheKey); - serverMessage.channel = - await _kernel.marshaller.serializers.channels.serializeCache(rawChannel) as ServerChannel; + return message; + } - final rawMessage = - await _kernel.marshaller.serializers.serverMessage.deserialize(serverMessage); + final response = await _kernel.dataStore.client.get('/channels/$channelId/messages/$messageId'); + if (status.isError(response.statusCode)) { + throw HttpException(response.body); + } - await _kernel.marshaller.cache.put(messageCacheKey, rawMessage); + final payload = await _kernel.marshaller.serializers.serverMessage.normalize(response.body); + final serverMessage = await _kernel.marshaller.serializers.serverMessage.serialize(payload); + serverMessage.channel = serverChannel; return serverMessage; } Future getPrivateMessage( {required Snowflake messageId, required Snowflake channelId}) async { - final messageCacheKey = - _kernel.marshaller.cacheKey.privateMessage(messageId: messageId, channelId: channelId); - - final message = await _kernel.marshaller.cache.get(messageCacheKey); - if (message != null) { - return _kernel.marshaller.serializers.privateMessage.serializeCache(message); - } + final messageCacheKey = _kernel.marshaller.cacheKey.message(channelId, channelId); + final channelCacheKey = _kernel.marshaller.cacheKey.channel(channelId); - final response = await _kernel.dataStore.client.get('/channels/$channelId/messages/$messageId'); + final rawMessage = await _kernel.marshaller.cache.get(messageCacheKey); + final rawChannel = await _kernel.marshaller.cache.getOrFail(channelCacheKey); + final channel = await _kernel.marshaller.serializers.channels.serialize(rawChannel) as PrivateChannel; - final privateMessage = - await _kernel.marshaller.serializers.privateMessage.serializeRemote(response.body); + if (rawMessage != null) { + final message = await _kernel.marshaller.serializers.privateMessage.serialize(rawMessage) + ..channel = channel; - final channelCacheKey = _kernel.marshaller.cacheKey.channel(channelId); - final rawChannel = await _kernel.marshaller.cache.getOrFail(channelCacheKey); - privateMessage.channel = - await _kernel.marshaller.serializers.channels.serializeCache(rawChannel) as PrivateChannel; + return message; + } - final rawMessage = - await _kernel.marshaller.serializers.privateMessage.deserialize(privateMessage); + final response = await _kernel.dataStore.client.get('/channels/$channelId/messages/$messageId'); - await _kernel.marshaller.cache.put(messageCacheKey, rawMessage); + final payload = await _kernel.marshaller.serializers.serverMessage.normalize(response.body); + final privateMessage = await _kernel.marshaller.serializers.privateMessage.serialize(payload); + privateMessage.channel = channel; return privateMessage; } } diff --git a/lib/infrastructure/internals/datastore/parts/role_part.dart b/lib/infrastructure/internals/datastore/parts/role_part.dart index d7321a3f..0ca23b58 100644 --- a/lib/infrastructure/internals/datastore/parts/role_part.dart +++ b/lib/infrastructure/internals/datastore/parts/role_part.dart @@ -8,7 +8,6 @@ import 'package:mineral/infrastructure/internals/http/discord_header.dart'; import 'package:mineral/infrastructure/kernel/kernel.dart'; import 'package:mineral/infrastructure/services/http/http_client_status.dart'; import 'package:mineral/infrastructure/services/http/http_request_option.dart'; -import 'package:mineral/infrastructure/services/http/response.dart'; final class RolePart implements DataStorePart { final KernelContract _kernel; diff --git a/lib/infrastructure/internals/marshaller/cache_key.dart b/lib/infrastructure/internals/marshaller/cache_key.dart index 21d346cf..09aace71 100644 --- a/lib/infrastructure/internals/marshaller/cache_key.dart +++ b/lib/infrastructure/internals/marshaller/cache_key.dart @@ -17,8 +17,7 @@ final class CacheKey { return ref ? 'ref:$key' : key; } - String channel(Snowflake channelId, {Snowflake? serverId}) => - serverId != null ? '${server(serverId)}/channels/$channelId' : 'channel/$channelId'; + String channel(Snowflake channelId) => 'channels/$channelId'; String channelPermission(Snowflake channelId, {Snowflake? serverId}) => '${channel(channelId, serverId: serverId)}/permissions'; @@ -51,11 +50,8 @@ final class CacheKey { return ref ? 'ref:$key' : key; } - String serverMessage({required Snowflake channelId, required Snowflake messageId}) => - '${channel(channelId)}/message-$messageId'; - - String privateMessage({required Snowflake channelId, required Snowflake messageId}) => - '${channel(channelId)}/message-$messageId'; + String message(Snowflake channelId, Snowflake messageId) => + '${channel(channelId)}/messages/$messageId'; String embed(Snowflake messageId, { String? uid }) => 'messages/$messageId/embeds/${uid ?? Uuid().v4()}'; diff --git a/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart index 6c2ebf69..fc8fd55c 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart @@ -18,7 +18,7 @@ final class ServerMessageSerializer implements SerializerContract 'embeds': json['embeds'], // 'components': json['components'], 'channel_id': json['channel_id'], - 'guild_id': json['guild_id'], + 'server_id': json['guild_id'], 'timestamp': json['timestamp'], 'edited_timestamp': json['edited_timestamp'], }; @@ -34,7 +34,7 @@ final class ServerMessageSerializer implements SerializerContract final channel = await marshaller.dataStore.channel .getChannel(Snowflake(json['channel_id'])); - final server = await marshaller.dataStore.server.getServer(json['guild_id']); + final server = await marshaller.dataStore.server.getServer(json['server_id']); final member = server.members.list[json['author_id']]; final messageProperties = MessageProperties.fromJson(channel as ServerChannel, json); @@ -54,7 +54,7 @@ final class ServerMessageSerializer implements SerializerContract 'embeds': embeds, 'author_id': object.author.id.value, 'channel_id': object.channel.id.value, - 'guild_id': object.channel.guildId.value, + 'server_id': object.channel.guildId.value, 'timestamp': object.createdAt.toIso8601String(), 'edited_timestamp': object.updatedAt?.toIso8601String(), }; From 62bad8d6c55f0edfa8ab6c97fda151820704084b Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Sat, 17 Aug 2024 10:15:18 +0200 Subject: [PATCH 19/44] feat(marshaller): apply newer channel key --- .../marshaller/serializers/server_message_serializer.dart | 2 +- .../internals/marshaller/serializers/server_serializer.dart | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart index fc8fd55c..021ce0af 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart @@ -23,7 +23,7 @@ final class ServerMessageSerializer implements SerializerContract 'edited_timestamp': json['edited_timestamp'], }; - final cacheKey = marshaller.cacheKey.serverMessage(messageId: json['id'], channelId: Snowflake(json['channel_id'])); + final cacheKey = marshaller.cacheKey.message(Snowflake(json['channel_id']), Snowflake(json['id'])); await marshaller.cache.put(cacheKey, payload); return payload; diff --git a/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart index 976aebda..cd0c7c4f 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart @@ -44,7 +44,7 @@ final class ServerSerializer implements SerializerContract { .map((element) => _marshaller.cacheKey.member(json['id'], element['id'])) .toList(), 'channels': List.from(json['channels']) - .map((element) => _marshaller.cacheKey.channel(element['id'], serverId: json['id'])) + .map((element) => _marshaller.cacheKey.channel(element['id'])) .toList(), }; @@ -123,7 +123,7 @@ final class ServerSerializer implements SerializerContract { 'members': server.members.list.keys.map((id) => _marshaller.cacheKey.member(server.id, id)).toList(), 'channels': server.channels.list.keys - .map((id) => _marshaller.cacheKey.channel(id, serverId: server.id)) + .map((id) => _marshaller.cacheKey.channel(id)) .toList(), }; } @@ -142,7 +142,7 @@ final class ServerSerializer implements SerializerContract { return; } - final channelCacheKey = _marshaller.cacheKey.channel(categoryId, serverId: serverId); + final channelCacheKey = _marshaller.cacheKey.channel(categoryId); final rawChannel = await _marshaller.cache.get(channelCacheKey); final category = rawChannel != null ? await _marshaller.serializers.channels.serialize(rawChannel) : null; From 4c9cc10aa5520932b93a56acefc5dfba129e0bdb Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Sat, 17 Aug 2024 14:46:24 +0200 Subject: [PATCH 20/44] feat(serialization): rework channel part --- .../datastore/parts/channel_part.dart | 42 +++++++------------ 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/lib/infrastructure/internals/datastore/parts/channel_part.dart b/lib/infrastructure/internals/datastore/parts/channel_part.dart index cb7a01ac..96bb5c27 100644 --- a/lib/infrastructure/internals/datastore/parts/channel_part.dart +++ b/lib/infrastructure/internals/datastore/parts/channel_part.dart @@ -36,8 +36,6 @@ final class ChannelPart implements DataStorePart { final response = await _kernel.dataStore.client.get('/channels/$id'); final Channel? channel = await serializeChannelResponse(response); - _putInCache(channel, id, response); - return channel as T?; } @@ -50,7 +48,6 @@ final class ChannelPart implements DataStorePart { option: HttpRequestOptionImpl(headers: {DiscordHeader.auditLogReason(reason)})); final Channel? channel = await serializeChannelResponse(response); - _putInCache(channel, id, response); return channel as T?; } @@ -61,7 +58,6 @@ final class ChannelPart implements DataStorePart { .post('/users/@me/channels', body: {'recipient_id': recipientId}); final Channel? channel = await serializeChannelResponse(response); - _putInCache(channel, id, response); return channel as PrivateChannel?; } @@ -75,7 +71,6 @@ final class ChannelPart implements DataStorePart { option: HttpRequestOptionImpl(headers: {DiscordHeader.auditLogReason(reason)})); final Channel? channel = await serializeChannelResponse(response); - _putInCache(channel, id, response); return channel as T?; } @@ -115,38 +110,32 @@ final class ChannelPart implements DataStorePart { _ => throw Exception('Unknown channel type: $channel'), } as SerializerContract; - await serializer.normalize(response.body); - final Message message = await serializer.serialize(response.body); - - await _kernel.marshaller.cache.put(message.id.value, {...response.body, 'guild_id': guildId}); + final payload = await serializer.normalize({ + ...response.body, + 'guild_id': guildId, + }); - return message as T; + return serializer.serialize(payload) as T; } Future serializeChannelResponse(Response response) async { return switch (response.statusCode) { - int() when status.isSuccess(response.statusCode) => { - await _kernel.marshaller.serializers.channels.normalize(response.body), - _kernel.marshaller.serializers.channels.serialize(response.body), + int() when status.isSuccess(response.statusCode) => () async { + final payload = await _kernel.marshaller.serializers.channels.normalize(response.body); + final channel = await _kernel.marshaller.serializers.channels.serialize(payload); + + if (channel is ServerChannel) { + await _updateCacheFromChannelServer(channel.id, channel, payload); + } + + return channel as T?; }, int() when status.isError(response.statusCode) => throw HttpException(response.bodyString), _ => throw Exception('Unknown status code: ${response.statusCode} ${response.bodyString}'), } as Future; } - Future _putInCache(Channel? channel, Snowflake id, Response response) async { - switch (channel) { - case ServerChannel(): - _updateCacheFromChannelServer(id, channel, response.body); - case PrivateChannel(): - _kernel.marshaller.cache.put('channel-${channel.id}', response.body); - default: - throw Exception('Unknown channel type: $channel'); - } - } - - Future _updateCacheFromChannelServer( - Snowflake id, ServerChannel channel, Map rawChannel) async { + Future _updateCacheFromChannelServer(Snowflake id, ServerChannel channel, Map rawChannel) async { final server = await _kernel.dataStore.server.getServer(rawChannel['guild_id']); server.channels.list[channel.id] = channel; @@ -154,7 +143,6 @@ final class ChannelPart implements DataStorePart { await _kernel.marshaller.cache.putMany({ _kernel.marshaller.cacheKey.server(server.id): rawServer, - _kernel.marshaller.cacheKey.channel(channel.id): rawChannel, }); } } From 9202b7a57d53fe6c29fefe37ea4a790e2b7d07c1 Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Sat, 17 Aug 2024 14:49:37 +0200 Subject: [PATCH 21/44] feat(serialization): change guild to server --- .../internals/marshaller/serializer_bucket.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/infrastructure/internals/marshaller/serializer_bucket.dart b/lib/infrastructure/internals/marshaller/serializer_bucket.dart index 42dbb71c..6537b314 100644 --- a/lib/infrastructure/internals/marshaller/serializer_bucket.dart +++ b/lib/infrastructure/internals/marshaller/serializer_bucket.dart @@ -76,7 +76,7 @@ final class SerializerBucket { final SerializerContract globalCommandContext; - final SerializerContract guildCommandContext; + final SerializerContract serverCommandContext; SerializerBucket(MarshallerContract marshaller) : channels = ChannelSerializer(marshaller), @@ -96,6 +96,6 @@ final class SerializerBucket { privateMessage = PrivateMessageSerializer(marshaller), embed = EmbedSerializer(marshaller), globalCommandContext = GlobalCommandContextSerializer(marshaller), - guildCommandContext = ServerCommandContextSerializer(marshaller), + serverCommandContext = ServerCommandContextSerializer(marshaller), poll = PollSerializer(marshaller); } From 964da39ab02986716c96032ed7adce8b9a89231c Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Sat, 17 Aug 2024 14:49:49 +0200 Subject: [PATCH 22/44] feat(serialization): rework serialization uses --- .../commands/command_interaction_dispatcher.dart | 10 +++++----- .../dialog/contexts/private_dialog_context.dart | 2 +- .../selects/contexts/private_select_context.dart | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/domains/commands/command_interaction_dispatcher.dart b/lib/domains/commands/command_interaction_dispatcher.dart index 68a8eeee..22b2bf03 100644 --- a/lib/domains/commands/command_interaction_dispatcher.dart +++ b/lib/domains/commands/command_interaction_dispatcher.dart @@ -55,8 +55,8 @@ final class CommandInteractionDispatcher implements InteractionDispatcherContrac .firstWhere((command) => command.$1 == data['data']['name']); final commandContext = switch (data['data']['guild_id']) { - String() => await _marshaller.serializers.guildCommandContext.serializeRemote(data), - _ => await _marshaller.serializers.globalCommandContext.serializeRemote(data), + String() => await _marshaller.serializers.serverCommandContext.serialize(data), + _ => await _marshaller.serializers.globalCommandContext.serialize(data), }; final Map options = {}; @@ -74,12 +74,12 @@ final class CommandInteractionDispatcher implements InteractionDispatcherContrac CommandOptionType.user => switch (commandContext) { ServerCommandContext() => await _marshaller.dataStore.member .getMember(guildId: commandContext.server.id, memberId: option['value']), - _ => _marshaller.serializers.user.serializeRemote(option['value']), + _ => _marshaller.serializers.user.serialize(option['value']), }, CommandOptionType.channel => - await _marshaller.serializers.channels.serializeRemote(option['value']), + await _marshaller.serializers.channels.serialize(option['value']), CommandOptionType.role => - await _marshaller.serializers.role.serializeRemote(option['value']), + await _marshaller.serializers.role.serialize(option['value']), // TODO attachement _ => option['value'], }; diff --git a/lib/domains/components/dialog/contexts/private_dialog_context.dart b/lib/domains/components/dialog/contexts/private_dialog_context.dart index c4a0f6e6..2cc2693a 100644 --- a/lib/domains/components/dialog/contexts/private_dialog_context.dart +++ b/lib/domains/components/dialog/contexts/private_dialog_context.dart @@ -43,7 +43,7 @@ final class PrivateDialogContext implements DialogContext { applicationId: Snowflake(payload['application_id']), token: payload['token'], version: payload['version'], - user: await marshaller.serializers.user.serializeRemote(payload['user']), + user: await marshaller.serializers.user.serialize(payload['user']), ); } } diff --git a/lib/domains/components/selects/contexts/private_select_context.dart b/lib/domains/components/selects/contexts/private_select_context.dart index b954c8bb..59caa3cf 100644 --- a/lib/domains/components/selects/contexts/private_select_context.dart +++ b/lib/domains/components/selects/contexts/private_select_context.dart @@ -40,7 +40,7 @@ final class PrivateSelectContext implements SelectContext { interaction = Interaction(token, id); } - static Future fromMap(MarshallerContract marshaller, Map payload) async{ + static Future fromMap(MarshallerContract marshaller, Map payload) async { return PrivateSelectContext( customId: payload['data']['custom_id'], id: Snowflake(payload['id']), @@ -51,7 +51,7 @@ final class PrivateSelectContext implements SelectContext { messageId: Snowflake(payload['message']['id']), channelId: Snowflake(payload['channel_id']), ), - user: await marshaller.serializers.user.serializeRemote(payload['user']), + user: await marshaller.serializers.user.serialize(payload['user']), ); } } From d6fc4fd47e999477fe3c303c537cb52c203fccdd Mon Sep 17 00:00:00 2001 From: PandaGuerrier <76222146+PandaGuerrier@users.noreply.github.com> Date: Sat, 17 Aug 2024 14:51:59 +0200 Subject: [PATCH 23/44] fix(serialization): fix somes littles things --- lib/infrastructure/internals/marshaller/cache_key.dart | 2 +- .../internals/packets/listeners/message_create_packet.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/infrastructure/internals/marshaller/cache_key.dart b/lib/infrastructure/internals/marshaller/cache_key.dart index 09aace71..c330d47e 100644 --- a/lib/infrastructure/internals/marshaller/cache_key.dart +++ b/lib/infrastructure/internals/marshaller/cache_key.dart @@ -20,7 +20,7 @@ final class CacheKey { String channel(Snowflake channelId) => 'channels/$channelId'; String channelPermission(Snowflake channelId, {Snowflake? serverId}) => - '${channel(channelId, serverId: serverId)}/permissions'; + '${channel(channelId)}/permissions'; String serverRole(Snowflake serverId, Snowflake roleId, {bool ref = false}) => '${server(serverId)}/role/$roleId'; diff --git a/lib/infrastructure/internals/packets/listeners/message_create_packet.dart b/lib/infrastructure/internals/packets/listeners/message_create_packet.dart index fcbdad4f..bebd79f6 100644 --- a/lib/infrastructure/internals/packets/listeners/message_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/message_create_packet.dart @@ -53,7 +53,7 @@ final class MessageCreatePacket implements ListenablePacket { await marshaller.cache.putMany({ marshaller.cacheKey.server(server.id): rawServer, - marshaller.cacheKey.serverMessage(channelId: channel!.id, messageId: message.id): rawMessage, + marshaller.cacheKey.message(channel!.id, message.id): rawMessage, }); dispatch(event: Event.serverMessageCreate, params: [message]); @@ -72,7 +72,7 @@ final class MessageCreatePacket implements ListenablePacket { await marshaller.cache.putMany({ marshaller.cacheKey.channel(channel.id): rawChannel, - marshaller.cacheKey.privateMessage(channelId: channel.id, messageId: message.id): rawMessage, + marshaller.cacheKey.message(channel.id, message.id): rawMessage, }); dispatch(event: Event.privateMessageCreate, params: [message]); From e8ceb99b9d8ec37a97b57b85050cbd8e96950304 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Mon, 19 Aug 2024 21:57:38 +0200 Subject: [PATCH 24/44] feat: restore required marshaller service --- .../internals/marshaller/serializers/embed_serializer.dart | 5 +++++ .../internals/marshaller/serializers/poll_serializer.dart | 5 +++++ .../marshaller/serializers/private_message_serializer.dart | 2 +- .../marshaller/serializers/sticker_serializer.dart | 5 +++++ .../internals/marshaller/serializers/user_serializer.dart | 7 +++++-- 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/infrastructure/internals/marshaller/serializers/embed_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/embed_serializer.dart index b704f213..6a6c2e37 100644 --- a/lib/infrastructure/internals/marshaller/serializers/embed_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/embed_serializer.dart @@ -8,9 +8,14 @@ import 'package:mineral/api/common/embed/message_embed_provider.dart'; import 'package:mineral/api/common/embed/message_embed_type.dart'; import 'package:mineral/infrastructure/commons/helper.dart'; import 'package:mineral/infrastructure/commons/utils.dart'; +import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; final class EmbedSerializer implements SerializerContract { + final MarshallerContract _marshaller; + + EmbedSerializer(this._marshaller); + @override Future> normalize(Map json) async { final payload = { diff --git a/lib/infrastructure/internals/marshaller/serializers/poll_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/poll_serializer.dart index 1ab8e32e..6c9424b8 100644 --- a/lib/infrastructure/internals/marshaller/serializers/poll_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/poll_serializer.dart @@ -6,9 +6,14 @@ import 'package:mineral/api/common/polls/poll_question.dart'; import 'package:mineral/api/common/snowflake.dart'; import 'package:mineral/infrastructure/commons/helper.dart'; import 'package:mineral/infrastructure/commons/utils.dart'; +import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; final class PollSerializer implements SerializerContract { + final MarshallerContract _marshaller; + + PollSerializer(this._marshaller); + @override Future> normalize(Map json) async { final payload = { diff --git a/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart index 7d670c71..cf0e8722 100644 --- a/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart @@ -21,7 +21,7 @@ final class PrivateMessageSerializer implements SerializerContract { + final MarshallerContract _marshaller; + + StickerSerializer(this._marshaller); + @override Future> normalize(Map json) async { final payload = { diff --git a/lib/infrastructure/internals/marshaller/serializers/user_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/user_serializer.dart index 8455c94d..740649cf 100644 --- a/lib/infrastructure/internals/marshaller/serializers/user_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/user_serializer.dart @@ -1,11 +1,14 @@ import 'package:mineral/api/common/premium_tier.dart'; -import 'package:mineral/api/common/presence.dart'; import 'package:mineral/api/private/user.dart'; -import 'package:mineral/api/private/user_assets.dart'; import 'package:mineral/infrastructure/commons/helper.dart'; +import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; final class UserSerializer implements SerializerContract { + final MarshallerContract _marshaller; + + UserSerializer(this._marshaller); + @override Future> normalize(Map json) async { await _marshaller.serializers.userAssets.normalize({ From a2052e786ff27426fbb9654ad036e73d916e1f2b Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Mon, 19 Aug 2024 22:03:29 +0200 Subject: [PATCH 25/44] feat(marshaller): implement server subscription serializer --- .../internals/marshaller/cache_key.dart | 5 +++++ .../server_subscription_serializer.dart | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/infrastructure/internals/marshaller/cache_key.dart b/lib/infrastructure/internals/marshaller/cache_key.dart index c330d47e..8d4595dd 100644 --- a/lib/infrastructure/internals/marshaller/cache_key.dart +++ b/lib/infrastructure/internals/marshaller/cache_key.dart @@ -17,6 +17,11 @@ final class CacheKey { return ref ? 'ref:$key' : key; } + String serverSubscription(Snowflake serverId, {bool ref = false}) { + final key = '${server(serverId)}/subscriptions'; + return ref ? 'ref:$key' : key; + } + String channel(Snowflake channelId) => 'channels/$channelId'; String channelPermission(Snowflake channelId, {Snowflake? serverId}) => diff --git a/lib/infrastructure/internals/marshaller/serializers/server_subscription_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_subscription_serializer.dart index 01d8f30d..cf6cd696 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_subscription_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_subscription_serializer.dart @@ -1,12 +1,26 @@ import 'package:mineral/api/common/premium_tier.dart'; import 'package:mineral/api/server/server_subscription.dart'; import 'package:mineral/infrastructure/commons/utils.dart'; +import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; final class ServerSubscriptionSerializer implements SerializerContract { + final MarshallerContract _marshaller; + + ServerSubscriptionSerializer(this._marshaller); + @override Future> normalize(Map json) async { - throw UnimplementedError(); + final payload = { + 'premium_tier': json['premium_tier'], + 'premium_subscription_count': json['premium_subscription_count'], + 'premium_progress_bar_enabled': json['premium_progress_bar_enabled'], + }; + + final cacheKey = _marshaller.cacheKey.serverSubscription(json['server_id']); + await _marshaller.cache.put(cacheKey, payload); + + return payload; } @override From 23eed28b57b7e7c92d36a21018705adb3c61aa4b Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 00:42:08 +0200 Subject: [PATCH 26/44] feat(marshaller): implement newer serialization and support server and message create --- lib/api/common/channel_properties.dart | 10 ++-- .../channels/server_announcement_channel.dart | 2 +- .../channels/server_category_channel.dart | 2 +- lib/api/server/channels/server_channel.dart | 2 +- .../server/channels/server_forum_channel.dart | 2 +- .../server/channels/server_stage_channel.dart | 4 +- .../server/channels/server_text_channel.dart | 4 +- .../server/channels/server_voice_channel.dart | 2 +- lib/api/server/managers/emoji_manager.dart | 12 ++--- lib/api/server/managers/sticker_manager.dart | 11 ++-- lib/api/server/member_assets.dart | 2 + lib/api/server/server_assets.dart | 7 ++- .../command_interaction_dispatcher.dart | 16 +++--- .../contexts/global_command_context.dart | 13 +++++ ...ntext.dart => server_command_context.dart} | 26 ++++++++-- .../contexts/server_dialog_context.dart | 2 +- .../contexts/server_select_context.dart | 2 +- .../internals/datastore/data_store.dart | 7 +++ .../datastore/parts/member_part.dart | 6 +-- .../internals/datastore/parts/role_part.dart | 6 +-- .../datastore/parts/sticker_part.dart | 37 ++++++++++++++ .../internals/marshaller/cache_key.dart | 9 ++-- .../server_announcement_channel_factory.dart | 4 +- .../server_category_channel_factory.dart | 4 +- .../server_forum_channel_factory.dart | 4 +- .../server_stage_channel_factory.dart | 4 +- .../channels/server_text_channel_factory.dart | 4 +- .../server_voice_channel_factory.dart | 4 +- .../messages/server_message_factory.dart | 2 +- .../marshaller/serializer_bucket.dart | 10 +--- .../global_command_context_serializer.dart | 41 --------------- .../serializers/member_assets_serializer.dart | 5 +- .../serializers/member_serializer.dart | 6 +-- .../private_message_serializer.dart | 17 +++++-- .../serializers/server_assets_serializer.dart | 50 ++++++++++++++----- .../server_command_context_serializer.dart | 33 ------------ .../server_message_serializer.dart | 18 ++++--- .../serializers/server_serializer.dart | 17 +++++-- .../serializers/sticker_serializer.dart | 2 +- .../serializers/user_assets_serializer.dart | 6 +-- .../listeners/channel_create_packet.dart | 2 +- .../listeners/channel_pins_update_packet.dart | 2 +- .../listeners/channel_update_packet.dart | 2 +- .../listeners/guild_ban_add_packet.dart | 1 + .../listeners/guild_create_packet.dart | 7 +-- .../listeners/guild_emojis_update_packet.dart | 12 ++++- .../listeners/guild_member_update_packet.dart | 2 +- .../listeners/guild_role_delete_packet.dart | 2 +- .../guild_stickers_update_packet.dart | 7 ++- .../select_interaction_create_packet.dart | 5 +- .../listeners/message_create_packet.dart | 29 +++++------ lib/infrastructure/kernel/client.dart | 8 +-- lib/infrastructure/kernel/kernel.dart | 2 +- 53 files changed, 272 insertions(+), 224 deletions(-) rename lib/domains/commands/contexts/{guild_command_context.dart => server_command_context.dart} (51%) create mode 100644 lib/infrastructure/internals/datastore/parts/sticker_part.dart delete mode 100644 lib/infrastructure/internals/marshaller/serializers/global_command_context_serializer.dart delete mode 100644 lib/infrastructure/internals/marshaller/serializers/server_command_context_serializer.dart diff --git a/lib/api/common/channel_properties.dart b/lib/api/common/channel_properties.dart index f81d3b1b..32234a25 100644 --- a/lib/api/common/channel_properties.dart +++ b/lib/api/common/channel_properties.dart @@ -16,7 +16,7 @@ final class ChannelProperties { final ChannelType type; final String? name; final String? description; - final Snowflake? guildId; + final Snowflake? serverId; final Snowflake? categoryId; final int? position; final bool nsfw; @@ -48,7 +48,7 @@ final class ChannelProperties { required this.type, required this.name, required this.description, - required this.guildId, + required this.serverId, required this.categoryId, required this.position, required this.nsfw, @@ -100,7 +100,7 @@ final class ChannelProperties { type: findInEnum(ChannelType.values, element['type']), name: element['name'], description: element['description'], - guildId: Helper.createOrNull( + serverId: Helper.createOrNull( field: element['guild_id'], fn: () => Snowflake(element['guild_id'])), categoryId: Helper.createOrNull( field: element['parent_id'], fn: () => Snowflake(element['parent_id'])), @@ -156,8 +156,8 @@ final class ChannelProperties { type: findInEnum(ChannelType.values, element['type']), name: element['name'], description: element['description'], - guildId: Helper.createOrNull( - field: element['guild_id'], fn: () => Snowflake(element['guild_id'])), + serverId: Helper.createOrNull( + field: element['server_id'], fn: () => Snowflake(element['server_id'])), categoryId: Helper.createOrNull( field: element['parent_id'], fn: () => Snowflake(element['parent_id'])), position: element['position'], diff --git a/lib/api/server/channels/server_announcement_channel.dart b/lib/api/server/channels/server_announcement_channel.dart index ae06e167..590dac53 100644 --- a/lib/api/server/channels/server_announcement_channel.dart +++ b/lib/api/server/channels/server_announcement_channel.dart @@ -34,7 +34,7 @@ final class ServerAnnouncementChannel extends ServerChannel { bool get isNsfw => _properties.nsfw; @override - Snowflake get guildId => _properties.guildId!; + Snowflake get serverId => _properties.serverId!; Snowflake? get categoryId => _properties.categoryId; diff --git a/lib/api/server/channels/server_category_channel.dart b/lib/api/server/channels/server_category_channel.dart index 02e8bd3f..93e8db33 100644 --- a/lib/api/server/channels/server_category_channel.dart +++ b/lib/api/server/channels/server_category_channel.dart @@ -25,7 +25,7 @@ final class ServerCategoryChannel extends ServerChannel { List get permissions => _properties.permissions!; @override - Snowflake get guildId => _properties.guildId!; + Snowflake get serverId => _properties.serverId!; ServerCategoryChannel(this._properties): _methods = ChannelMethods(_properties.id); diff --git a/lib/api/server/channels/server_channel.dart b/lib/api/server/channels/server_channel.dart index b0c3dcbe..0128b5d1 100644 --- a/lib/api/server/channels/server_channel.dart +++ b/lib/api/server/channels/server_channel.dart @@ -8,7 +8,7 @@ abstract class ServerChannel implements Channel { String get name; List get permissions; int get position; - Snowflake get guildId; + Snowflake get serverId; @override T cast() => this as T; diff --git a/lib/api/server/channels/server_forum_channel.dart b/lib/api/server/channels/server_forum_channel.dart index 4dbd6045..604d9cea 100644 --- a/lib/api/server/channels/server_forum_channel.dart +++ b/lib/api/server/channels/server_forum_channel.dart @@ -36,7 +36,7 @@ final class ServerForumChannel extends ServerChannel { late final ServerCategoryChannel? category; @override - Snowflake get guildId => _properties.guildId!; + Snowflake get serverId => _properties.serverId!; ServerForumChannel(this._properties, {required this.sortOrder, required this.layoutType}); diff --git a/lib/api/server/channels/server_stage_channel.dart b/lib/api/server/channels/server_stage_channel.dart index 51822fd0..d4aa3cbc 100644 --- a/lib/api/server/channels/server_stage_channel.dart +++ b/lib/api/server/channels/server_stage_channel.dart @@ -34,7 +34,7 @@ final class ServerStageChannel extends ServerChannel { String? get description => _properties.description; @override - Snowflake get guildId => _properties.guildId!; + Snowflake get serverId => _properties.serverId!; Snowflake? get categoryId => _properties.categoryId; @@ -65,7 +65,7 @@ final class ServerStageChannel extends ServerChannel { _methods.setDefaultThreadRateLimitPerUser(value, reason); Future send({String? content, List? embeds, Poll? poll}) => - _methods.send(guildId: _properties.guildId, content: content, embeds: embeds, poll: poll); + _methods.send(guildId: _properties.serverId, content: content, embeds: embeds, poll: poll); Future delete({String? reason}) => _methods.delete(reason); } diff --git a/lib/api/server/channels/server_text_channel.dart b/lib/api/server/channels/server_text_channel.dart index fc16d86d..079b3b6e 100644 --- a/lib/api/server/channels/server_text_channel.dart +++ b/lib/api/server/channels/server_text_channel.dart @@ -35,7 +35,7 @@ final class ServerTextChannel extends ServerChannel { String? get description => _properties.description; @override - Snowflake get guildId => _properties.guildId!; + Snowflake get serverId => _properties.serverId!; Snowflake? get categoryId => _properties.categoryId; @@ -71,7 +71,7 @@ final class ServerTextChannel extends ServerChannel { Poll? poll, List? components}) => _methods.send( - guildId: _properties.guildId, + guildId: _properties.serverId, content: content, embeds: embeds, poll: poll, diff --git a/lib/api/server/channels/server_voice_channel.dart b/lib/api/server/channels/server_voice_channel.dart index fb766c5d..4e83d83f 100644 --- a/lib/api/server/channels/server_voice_channel.dart +++ b/lib/api/server/channels/server_voice_channel.dart @@ -31,7 +31,7 @@ final class ServerVoiceChannel extends ServerChannel { List get permissions => _properties.permissions!; @override - Snowflake get guildId => _properties.guildId!; + Snowflake get serverId => _properties.serverId!; Snowflake? get categoryId => _properties.categoryId; diff --git a/lib/api/server/managers/emoji_manager.dart b/lib/api/server/managers/emoji_manager.dart index 2f9d6df7..8d093122 100644 --- a/lib/api/server/managers/emoji_manager.dart +++ b/lib/api/server/managers/emoji_manager.dart @@ -10,15 +10,9 @@ final class EmojiManager { Map get list => _emojis; - factory EmojiManager.fromJson(MarshallerContract marshaller, - {required List roles, required List payload}) { - return EmojiManager(Map.from(payload.fold({}, (value, element) { - final emoji = marshaller.serializers.emojis.serialize({ - 'guildRoles': roles, - ...element, - }) as Emoji; - - return {...value, emoji.id: emoji}; + factory EmojiManager.fromList(List roles, List emojis) { + return EmojiManager(Map.from(emojis.fold({}, (value, element) { + return {...value, element.id: element}; }))); } } diff --git a/lib/api/server/managers/sticker_manager.dart b/lib/api/server/managers/sticker_manager.dart index 3b67c213..4304a751 100644 --- a/lib/api/server/managers/sticker_manager.dart +++ b/lib/api/server/managers/sticker_manager.dart @@ -9,12 +9,9 @@ final class StickerManager { Map get list => _stickers; - factory StickerManager.fromJson(MarshallerContract marshaller, List payload) { - final Map stickers = payload.fold({}, (value, element) { - final sticker = marshaller.serializers.sticker.serialize(element) as Sticker; - return {...value, sticker.id: sticker}; - }); - - return StickerManager(stickers); + factory StickerManager.fromList(List stickers) { + return StickerManager(stickers.fold({}, (acc, sticker) { + return {...acc, sticker.id: sticker}; + })); } } diff --git a/lib/api/server/member_assets.dart b/lib/api/server/member_assets.dart index 423c2da7..8eec7743 100644 --- a/lib/api/server/member_assets.dart +++ b/lib/api/server/member_assets.dart @@ -6,11 +6,13 @@ final class MemberAssets { final ImageAsset? avatarDecoration; final ImageAsset? banner; final Snowflake memberId; + final Snowflake serverId; MemberAssets({ required this.avatar, required this.avatarDecoration, required this.banner, required this.memberId, + required this.serverId, }); } diff --git a/lib/api/server/server_assets.dart b/lib/api/server/server_assets.dart index 5c5dd49b..0b460f70 100644 --- a/lib/api/server/server_assets.dart +++ b/lib/api/server/server_assets.dart @@ -1,16 +1,19 @@ import 'package:mineral/api/common/image_asset.dart'; +import 'package:mineral/api/common/snowflake.dart'; import 'package:mineral/api/server/managers/emoji_manager.dart'; import 'package:mineral/api/server/managers/sticker_manager.dart'; final class ServerAsset { - EmojiManager emojis; - StickerManager stickers; + final Snowflake serverId; final ImageAsset? icon; final ImageAsset? splash; final ImageAsset? banner; final ImageAsset? discoverySplash; + EmojiManager emojis; + StickerManager stickers; ServerAsset({ + required this.serverId, required this.emojis, required this.stickers, required this.icon, diff --git a/lib/domains/commands/command_interaction_dispatcher.dart b/lib/domains/commands/command_interaction_dispatcher.dart index 22b2bf03..821616c2 100644 --- a/lib/domains/commands/command_interaction_dispatcher.dart +++ b/lib/domains/commands/command_interaction_dispatcher.dart @@ -5,7 +5,8 @@ import 'package:mineral/api/common/commands/command_option_type.dart'; import 'package:mineral/api/common/commands/command_type.dart'; import 'package:mineral/api/common/types/interaction_type.dart'; import 'package:mineral/domains/commands/command_interaction_manager.dart'; -import 'package:mineral/domains/commands/contexts/guild_command_context.dart'; +import 'package:mineral/domains/commands/contexts/global_command_context.dart'; +import 'package:mineral/domains/commands/contexts/server_command_context.dart'; import 'package:mineral/infrastructure/internals/interactions/types/interaction_dispatcher_contract.dart'; import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; @@ -44,7 +45,7 @@ final class CommandInteractionDispatcher implements InteractionDispatcherContrac continue; } - return switch(type) { + return switch (type) { CommandType.subCommand => await _handleSubCommand(data, option), CommandType.subCommandGroup => await _handleGroups(data, option), }; @@ -54,9 +55,9 @@ final class CommandInteractionDispatcher implements InteractionDispatcherContrac final command = _interactionManager.commandsHandler .firstWhere((command) => command.$1 == data['data']['name']); - final commandContext = switch (data['data']['guild_id']) { - String() => await _marshaller.serializers.serverCommandContext.serialize(data), - _ => await _marshaller.serializers.globalCommandContext.serialize(data), + final commandContext = await switch (data['data']['guild_id']) { + String() => ServerCommandContext.fromMap(_marshaller, data), + _ => GlobalCommandContext.fromMap(_marshaller, data), }; final Map options = {}; @@ -73,13 +74,12 @@ final class CommandInteractionDispatcher implements InteractionDispatcherContrac options[Symbol(option['name'])] = switch (type) { CommandOptionType.user => switch (commandContext) { ServerCommandContext() => await _marshaller.dataStore.member - .getMember(guildId: commandContext.server.id, memberId: option['value']), + .getMember(serverId: commandContext.server.id, memberId: option['value']), _ => _marshaller.serializers.user.serialize(option['value']), }, CommandOptionType.channel => await _marshaller.serializers.channels.serialize(option['value']), - CommandOptionType.role => - await _marshaller.serializers.role.serialize(option['value']), + CommandOptionType.role => await _marshaller.serializers.role.serialize(option['value']), // TODO attachement _ => option['value'], }; diff --git a/lib/domains/commands/contexts/global_command_context.dart b/lib/domains/commands/contexts/global_command_context.dart index 7e70eb65..2e509b3f 100644 --- a/lib/domains/commands/contexts/global_command_context.dart +++ b/lib/domains/commands/contexts/global_command_context.dart @@ -2,6 +2,7 @@ import 'package:mineral/api/common/channel.dart'; import 'package:mineral/api/common/snowflake.dart'; import 'package:mineral/api/private/user.dart'; import 'package:mineral/domains/commands/command_context.dart'; +import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; final class GlobalCommandContext implements CommandContext { @override @@ -24,4 +25,16 @@ final class GlobalCommandContext implements CommandContext { required this.user, this.channel, }); + + static Future fromMap( + MarshallerContract marshaller, Map payload) async { + return GlobalCommandContext( + id: Snowflake(payload['id']), + applicationId: Snowflake(payload['application_id']), + token: payload['token'], + version: payload['version'], + user: await marshaller.dataStore.user.getUser(Snowflake(payload['member']['user']['id'])), + channel: await marshaller.dataStore.channel.getChannel(Snowflake(payload['channel_id'])), + ); + } } diff --git a/lib/domains/commands/contexts/guild_command_context.dart b/lib/domains/commands/contexts/server_command_context.dart similarity index 51% rename from lib/domains/commands/contexts/guild_command_context.dart rename to lib/domains/commands/contexts/server_command_context.dart index a9972e3f..13ed6fbf 100644 --- a/lib/domains/commands/contexts/guild_command_context.dart +++ b/lib/domains/commands/contexts/server_command_context.dart @@ -1,22 +1,26 @@ import 'package:mineral/api/common/channel.dart'; import 'package:mineral/api/common/snowflake.dart'; -import 'package:mineral/api/private/user.dart'; +import 'package:mineral/api/server/member.dart'; import 'package:mineral/api/server/server.dart'; import 'package:mineral/domains/commands/command_context.dart'; import 'package:mineral/infrastructure/internals/interactions/interaction.dart'; import 'package:mineral/infrastructure/internals/interactions/types/interaction_contract.dart'; +import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; final class ServerCommandContext implements CommandContext { @override final Snowflake id; + @override final Snowflake applicationId; + @override final String token; + @override final int version; - final User user; + final Member member; final Channel? channel; final Server server; late final InteractionContract interaction; @@ -26,10 +30,26 @@ final class ServerCommandContext implements CommandContext { required this.applicationId, required this.token, required this.version, - required this.user, + required this.member, required this.server, this.channel, }) { interaction = Interaction(token, id); } + + static Future fromMap( + MarshallerContract marshaller, Map payload) async { + return ServerCommandContext( + id: Snowflake(payload['id']), + applicationId: Snowflake(payload['application_id']), + token: payload['token'], + version: payload['version'], + member: await marshaller.dataStore.member.getMember( + serverId: Snowflake(payload['guild_id']), + memberId: Snowflake(payload['member']['user']['id']), + ), + server: await marshaller.dataStore.server.getServer(Snowflake(payload['guild_id'])), + channel: await marshaller.dataStore.channel.getChannel(Snowflake(payload['channel_id'])), + ); + } } diff --git a/lib/domains/components/dialog/contexts/server_dialog_context.dart b/lib/domains/components/dialog/contexts/server_dialog_context.dart index 733d6cdf..cda5ce01 100644 --- a/lib/domains/components/dialog/contexts/server_dialog_context.dart +++ b/lib/domains/components/dialog/contexts/server_dialog_context.dart @@ -44,7 +44,7 @@ final class ServerDialogContext implements DialogContext { token: payload['token'], version: payload['version'], member: await marshaller.dataStore.member.getMember( - guildId: Snowflake(payload['guild_id']), + serverId: Snowflake(payload['guild_id']), memberId: Snowflake(payload['member']['user']['id']), ), ); diff --git a/lib/domains/components/selects/contexts/server_select_context.dart b/lib/domains/components/selects/contexts/server_select_context.dart index 1d29a8f1..80d85f3a 100644 --- a/lib/domains/components/selects/contexts/server_select_context.dart +++ b/lib/domains/components/selects/contexts/server_select_context.dart @@ -52,7 +52,7 @@ final class ServerSelectContext implements SelectContext { channelId: Snowflake(payload['channel_id']), ), member: await marshaller.dataStore.member.getMember( - guildId: Snowflake(payload['guild_id']), + serverId: Snowflake(payload['guild_id']), memberId: Snowflake(payload['member']['user']['id']), ), ); diff --git a/lib/infrastructure/internals/datastore/data_store.dart b/lib/infrastructure/internals/datastore/data_store.dart index 6b77b0f7..5d4ee8c0 100644 --- a/lib/infrastructure/internals/datastore/data_store.dart +++ b/lib/infrastructure/internals/datastore/data_store.dart @@ -4,6 +4,7 @@ import 'package:mineral/infrastructure/internals/datastore/parts/member_part.dar import 'package:mineral/infrastructure/internals/datastore/parts/message_part.dart'; import 'package:mineral/infrastructure/internals/datastore/parts/role_part.dart'; import 'package:mineral/infrastructure/internals/datastore/parts/server_part.dart'; +import 'package:mineral/infrastructure/internals/datastore/parts/sticker_part.dart'; import 'package:mineral/infrastructure/internals/datastore/parts/user_part.dart'; import 'package:mineral/infrastructure/kernel/kernel.dart'; import 'package:mineral/infrastructure/services/http/http_client.dart'; @@ -24,6 +25,8 @@ abstract class DataStoreContract { MessagePart get message; InteractionPart get interaction; + + StickerPart get sticker; } final class DataStore implements DataStoreContract { @@ -53,6 +56,9 @@ final class DataStore implements DataStoreContract { @override late final InteractionPart interaction; + @override + late final StickerPart sticker; + DataStore(this.client); void init() { @@ -63,5 +69,6 @@ final class DataStore implements DataStoreContract { role = RolePart(kernel); message = MessagePart(kernel); interaction = InteractionPart(kernel); + sticker = StickerPart(kernel); } } diff --git a/lib/infrastructure/internals/datastore/parts/member_part.dart b/lib/infrastructure/internals/datastore/parts/member_part.dart index 117dc53c..c27e9ede 100644 --- a/lib/infrastructure/internals/datastore/parts/member_part.dart +++ b/lib/infrastructure/internals/datastore/parts/member_part.dart @@ -16,9 +16,9 @@ final class MemberPart implements DataStorePart { MemberPart(this._kernel); - Future getMember({required Snowflake guildId, required Snowflake memberId}) async { + Future getMember({required Snowflake serverId, required Snowflake memberId}) async { final cacheKeys = _kernel.marshaller.cacheKey; - final memberCacheKey = cacheKeys.member(guildId, memberId); + final memberCacheKey = cacheKeys.member(serverId, memberId); Map? cachedRawMember = await _kernel.marshaller.cache.get(memberCacheKey); @@ -26,7 +26,7 @@ final class MemberPart implements DataStorePart { return _kernel.marshaller.serializers.member.serialize(cachedRawMember); } - final response = await _kernel.dataStore.client.get('/guilds/$guildId/members/$memberId'); + final response = await _kernel.dataStore.client.get('/guilds/$serverId/members/$memberId'); if (status.isError(response.statusCode)) { throw HttpException(response.body); } diff --git a/lib/infrastructure/internals/datastore/parts/role_part.dart b/lib/infrastructure/internals/datastore/parts/role_part.dart index 0ca23b58..6457cb2f 100644 --- a/lib/infrastructure/internals/datastore/parts/role_part.dart +++ b/lib/infrastructure/internals/datastore/parts/role_part.dart @@ -16,15 +16,15 @@ final class RolePart implements DataStorePart { RolePart(this._kernel); - Future getRole({required Snowflake guildId, required Snowflake roleId}) async { - final cacheKey = _kernel.marshaller.cacheKey.serverRole(guildId, roleId); + Future getRole({required Snowflake serverId, required Snowflake roleId}) async { + final cacheKey = _kernel.marshaller.cacheKey.serverRole(serverId, roleId); final rawRole = await _kernel.marshaller.cache.get(cacheKey); if (rawRole != null) { return _kernel.marshaller.serializers.role.serialize(rawRole); } - final response = await _kernel.dataStore.client.get('/guilds/$guildId/roles/$roleId'); + final response = await _kernel.dataStore.client.get('/guilds/$serverId/roles/$roleId'); if (status.isError(response.statusCode)) { throw HttpException(response.body); } diff --git a/lib/infrastructure/internals/datastore/parts/sticker_part.dart b/lib/infrastructure/internals/datastore/parts/sticker_part.dart new file mode 100644 index 00000000..7957a1d6 --- /dev/null +++ b/lib/infrastructure/internals/datastore/parts/sticker_part.dart @@ -0,0 +1,37 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:mineral/api/common/snowflake.dart'; +import 'package:mineral/api/common/sticker.dart'; +import 'package:mineral/api/server/member.dart'; +import 'package:mineral/infrastructure/internals/datastore/data_store_part.dart'; +import 'package:mineral/infrastructure/internals/http/discord_header.dart'; +import 'package:mineral/infrastructure/kernel/kernel.dart'; +import 'package:mineral/infrastructure/services/http/http_client_status.dart'; +import 'package:mineral/infrastructure/services/http/http_request_option.dart'; + +final class StickerPart implements DataStorePart { + final KernelContract _kernel; + + HttpClientStatus get status => _kernel.dataStore.client.status; + + StickerPart(this._kernel); + + Future getSticker(Snowflake serverId, Snowflake stickerId) async { + final stickerCacheKey = _kernel.marshaller.cacheKey.sticker(serverId, stickerId); + + final Map? cachedRawSticker = await _kernel.marshaller.cache.get(stickerCacheKey); + + if (cachedRawSticker != null) { + return _kernel.marshaller.serializers.sticker.serialize(cachedRawSticker); + } + + final response = await _kernel.dataStore.client.get('/guilds/$serverId/stickers/$stickerId}'); + if (status.isError(response.statusCode)) { + throw HttpException(response.body); + } + + final payload = await _kernel.marshaller.serializers.sticker.normalize(response.body); + return _kernel.marshaller.serializers.sticker.serialize(payload); + } +} diff --git a/lib/infrastructure/internals/marshaller/cache_key.dart b/lib/infrastructure/internals/marshaller/cache_key.dart index 8d4595dd..dcdd716f 100644 --- a/lib/infrastructure/internals/marshaller/cache_key.dart +++ b/lib/infrastructure/internals/marshaller/cache_key.dart @@ -58,9 +58,12 @@ final class CacheKey { String message(Snowflake channelId, Snowflake messageId) => '${channel(channelId)}/messages/$messageId'; - String embed(Snowflake messageId, { String? uid }) => 'messages/$messageId/embeds/${uid ?? Uuid().v4()}'; + String embed(Snowflake messageId, {String? uid}) => + 'messages/$messageId/embeds/${uid ?? Uuid().v4()}'; - String poll(Snowflake messageId, { String? uid }) => 'messages/$messageId/polls/${uid ?? Uuid().v4()}'; + String poll(Snowflake messageId, {String? uid}) => + 'messages/$messageId/polls/${uid ?? Uuid().v4()}'; - String sticker(Snowflake stickerId) => 'stickers/$stickerId'; + String sticker(Snowflake serverId, Snowflake stickerId) => + '${server(serverId)}/stickers/$stickerId'; } diff --git a/lib/infrastructure/internals/marshaller/factories/channels/server_announcement_channel_factory.dart b/lib/infrastructure/internals/marshaller/factories/channels/server_announcement_channel_factory.dart index 8fe062ac..4065ee1a 100644 --- a/lib/infrastructure/internals/marshaller/factories/channels/server_announcement_channel_factory.dart +++ b/lib/infrastructure/internals/marshaller/factories/channels/server_announcement_channel_factory.dart @@ -19,7 +19,7 @@ final class ServerAnnouncementChannelFactory implements ChannelFactoryContract { 'content': message.content, 'embeds': message.embeds.map(marshaller.serializers.embed.deserialize).toList(), 'channel_id': message.channel.id, - 'guild_id': message.channel.guildId, + 'guild_id': message.channel.serverId, 'created_at': message.createdAt.toIso8601String(), 'updated_at': message.updatedAt?.toIso8601String(), }; diff --git a/lib/infrastructure/internals/marshaller/serializer_bucket.dart b/lib/infrastructure/internals/marshaller/serializer_bucket.dart index 6537b314..4ba6a862 100644 --- a/lib/infrastructure/internals/marshaller/serializer_bucket.dart +++ b/lib/infrastructure/internals/marshaller/serializer_bucket.dart @@ -16,20 +16,18 @@ import 'package:mineral/api/server/server_message.dart'; import 'package:mineral/api/server/server_settings.dart'; import 'package:mineral/api/server/server_subscription.dart'; import 'package:mineral/domains/commands/contexts/global_command_context.dart'; -import 'package:mineral/domains/commands/contexts/guild_command_context.dart'; +import 'package:mineral/domains/commands/contexts/server_command_context.dart'; import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/channel_permission_overwrite_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/channel_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/embed_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/emoji_serializer.dart'; -import 'package:mineral/infrastructure/internals/marshaller/serializers/global_command_context_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/member_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/poll_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/private_message_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/role_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/server_assets_serializer.dart'; -import 'package:mineral/infrastructure/internals/marshaller/serializers/server_command_context_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/server_message_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/server_serializer.dart'; import 'package:mineral/infrastructure/internals/marshaller/serializers/server_settings_serializer.dart'; @@ -74,10 +72,6 @@ final class SerializerBucket { final SerializerContract poll; - final SerializerContract globalCommandContext; - - final SerializerContract serverCommandContext; - SerializerBucket(MarshallerContract marshaller) : channels = ChannelSerializer(marshaller), server = ServerSerializer(marshaller), @@ -95,7 +89,5 @@ final class SerializerBucket { serverMessage = ServerMessageSerializer(marshaller), privateMessage = PrivateMessageSerializer(marshaller), embed = EmbedSerializer(marshaller), - globalCommandContext = GlobalCommandContextSerializer(marshaller), - serverCommandContext = ServerCommandContextSerializer(marshaller), poll = PollSerializer(marshaller); } diff --git a/lib/infrastructure/internals/marshaller/serializers/global_command_context_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/global_command_context_serializer.dart deleted file mode 100644 index 9bf61a92..00000000 --- a/lib/infrastructure/internals/marshaller/serializers/global_command_context_serializer.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'dart:async'; - -import 'package:mineral/api/common/snowflake.dart'; -import 'package:mineral/domains/commands/contexts/global_command_context.dart'; -import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; -import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; - -final class GlobalCommandContextSerializer implements SerializerContract { - final MarshallerContract marshaller; - - GlobalCommandContextSerializer(this.marshaller); - - @override - Future serializeRemote(Map json) async { - return GlobalCommandContext( - id: Snowflake(json['id']), - applicationId: Snowflake(json['application_id']), - version: json['version'], - token: json['token'], - channel: await marshaller.serializers.channels.serialize(json['channel']), - user: await marshaller.serializers.user.serialize(json['user']), - ); - } - - @override - Future serializeCache(Map json) async { - return GlobalCommandContext( - id: Snowflake(json['id']), - applicationId: Snowflake(json['application_id']), - version: json['version'], - token: json['token'], - channel: await marshaller.serializers.channels.serialize(json['channel']), - user: await marshaller.serializers.user.serialize(json['user']), - ); - } - - @override - Map deserialize(GlobalCommandContext permission) { - return {}; - } -} diff --git a/lib/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart index 003e15d4..8adce777 100644 --- a/lib/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/member_assets_serializer.dart @@ -13,13 +13,14 @@ final class MemberAssetsSerializer implements SerializerContract { @override Future> normalize(Map json) async { final payload = { + 'server_id': json['server_id'], 'member_id': json['member_id'], 'avatar': json['avatar'], 'avatar_decoration': json['avatar_decoration_data']?['sku_id'], 'banner': json['banner'], }; - final cacheKey = _marshaller.cacheKey.memberAssets(json['guild_id'], json['user']['id']); + final cacheKey = _marshaller.cacheKey.memberAssets(json['server_id'], json['user']['id']); await _marshaller.cache.put(cacheKey, payload); return payload; @@ -39,12 +40,14 @@ final class MemberAssetsSerializer implements SerializerContract { field: json['banner'], fn: () => ImageAsset(['banners', json['member_id']], json['banner'])), memberId: Snowflake(json['member_id']), + serverId: Snowflake(json['server_id']), ); } @override Map deserialize(MemberAssets assets) { return { + 'server_id': assets.serverId.value, 'member_id': assets.memberId.value, 'avatar': assets.avatar?.hash, 'avatar_decoration': assets.avatarDecoration?.hash, diff --git a/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart index 01381267..abf9e859 100644 --- a/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/member_serializer.dart @@ -20,7 +20,7 @@ final class MemberSerializer implements SerializerContract { Future> normalize(Map json) async { await _marshaller.serializers.memberAssets.normalize({ ...json, - 'member_id': json['id'], + 'member_id': json['user']['id'], }); final payload = { @@ -32,7 +32,7 @@ final class MemberSerializer implements SerializerContract { 'assets': _marshaller.cacheKey.memberAssets(json['server_id'], json['user']['id']), 'flags': json['flags'], 'roles': List.from(json['roles']) - .map((element) => _marshaller.cacheKey.serverRole(json['server_id_id'], element['id'])) + .map((element) => _marshaller.cacheKey.serverRole(json['server_id'], element)) .toList(), 'premium_since': json['premium_since'], 'public_flags': json['user']['public_flags'], @@ -48,7 +48,7 @@ final class MemberSerializer implements SerializerContract { // TODO : presence }; - final cacheKey = _marshaller.cacheKey.member(json['guild_id'], json['user']['id']); + final cacheKey = _marshaller.cacheKey.member(json['server_id'], json['user']['id']); await _marshaller.cache.put(cacheKey, payload); return payload; diff --git a/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart index cf0e8722..b8c46e77 100644 --- a/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/private_message_serializer.dart @@ -1,3 +1,4 @@ +import 'package:mineral/api/common/embed/message_embed.dart'; import 'package:mineral/api/common/message_properties.dart'; import 'package:mineral/api/common/snowflake.dart'; import 'package:mineral/api/private/channels/private_channel.dart'; @@ -17,8 +18,9 @@ final class PrivateMessageSerializer implements SerializerContract serialize(Map json) async { + final List embeds = await Future.wait(List.from(json['embeds']).map((message) async { + return marshaller.serializers.embed.serialize(message); + })); + final properties = MessageProperties( id: Snowflake(json['id']), content: json['content'], - embeds: json['embeds'], + embeds: embeds, createdAt: DateTime.parse(json['created_at']), updatedAt: json['updated_at'] != null ? DateTime.parse(json['updated_at']) : null, channelId: Snowflake(json['channel_id']), ); - final user = await marshaller.serializers.user.serialize(json['user']); + final user = await marshaller.dataStore.user.getUser(json['user_id']); return PrivateMessage(properties, userId: user.id, author: user); } @@ -52,10 +58,11 @@ final class PrivateMessageSerializer implements SerializerContract { return _marshaller.serializers.emojis.normalize({...element, 'server_id': json['id']}); }).wait; + await List.from(json['stickers']).map((element) async { + return _marshaller.serializers.sticker.normalize({...element, 'server_id': json['id']}); + }).wait; + final payload = { 'icon': json['icon'], 'icon_hash': json['icon_hash'], 'splash': json['splash'], 'discovery_splash': json['discovery_splash'], 'banner': json['banner'], + 'stickers': List.from(json['stickers']) + .map((element) => _marshaller.cacheKey.sticker(json['id'], element['id'])) + .toList(), 'roles': List.from(json['roles']) .map((element) => _marshaller.cacheKey.serverRole(json['id'], element['id'])) .toList(), 'emojis': List.from(json['emojis']) .map((element) => _marshaller.cacheKey.serverEmoji(json['id'], element['id'])) .toList(), + 'server_id': json['id'], }; _marshaller.cache.put(cacheKey, payload); @@ -44,38 +53,53 @@ final class ServerAssetsSerializer implements SerializerContract { } @override - ServerAsset serialize(Map json) => _serialize(json); + Future serialize(Map json) async { + final rawRoles = await _marshaller.cache.getMany(json['roles']); + final roles = await rawRoles.nonNulls.map((element) async { + return _marshaller.serializers.role.serialize(element); + }).wait; - ServerAsset _serialize(Map json) { - final guildRoles = List.from(json['guildRoles']); + final rawEmojis = await _marshaller.cache.getMany(json['emojis']); + final emojis = await rawEmojis.nonNulls.map((id) async { + return _marshaller.serializers.emojis.serialize(id); + }).wait; + + final rawStickers = await _marshaller.cache.getMany(json['stickers']); + final stickers = await rawStickers.nonNulls.map((id) async { + return _marshaller.serializers.sticker.serialize(id); + }).wait; return ServerAsset( - emojis: EmojiManager.fromJson(_marshaller, roles: guildRoles, payload: json['emojis']), - stickers: StickerManager.fromJson(_marshaller, json['stickers']), + emojis: EmojiManager.fromList(roles, emojis), + stickers: StickerManager.fromList(stickers), icon: Helper.createOrNull( - field: json['icon'], fn: () => ImageAsset(['icons', json['id']], json['icon'])), + field: json['icon'], fn: () => ImageAsset(['icons', json['server_id']], json['icon'])), splash: Helper.createOrNull( - field: json['splash'], fn: () => ImageAsset(['splashes', json['id']], json['splash'])), + field: json['splash'], fn: () => ImageAsset(['splashes', json['server_id']], json['splash'])), banner: Helper.createOrNull( - field: json['banner'], fn: () => ImageAsset(['banners', json['id']], json['banner'])), + field: json['banner'], fn: () => ImageAsset(['banners', json['server_id']], json['banner'])), discoverySplash: Helper.createOrNull( field: json['discovery_splash'], fn: () => ImageAsset(['discovery-splashes', json['id']], json['discovery_splash'])), + serverId: Snowflake(json['server_id']), ); } @override - Map deserialize(ServerAsset object) { - final emojis = object.emojis.list.values.map(_marshaller.serializers.emojis.deserialize); - final stickers = object.stickers.list.values.map(_marshaller.serializers.sticker.deserialize); + Future> deserialize(ServerAsset object) async { + final emojis = await Future.wait(object.emojis.list.values + .map((element) async => _marshaller.serializers.emojis.deserialize(element))); + final stickers = await Future.wait(object.stickers.list.values + .map((element) async => _marshaller.serializers.sticker.deserialize(element))); return { - 'emojis': emojis.toList(), - 'stickers': stickers.toList(), + 'emojis': emojis.map((element) => element['id']).toList(), + 'stickers': stickers.map((element) => element['id']).toList(), 'icon': object.icon?.hash, 'splash': object.splash?.hash, 'banner': object.banner?.hash, 'discovery_splash': object.discoverySplash?.hash, + 'server_id': object.serverId.value, }; } } diff --git a/lib/infrastructure/internals/marshaller/serializers/server_command_context_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_command_context_serializer.dart deleted file mode 100644 index c63f863c..00000000 --- a/lib/infrastructure/internals/marshaller/serializers/server_command_context_serializer.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:mineral/api/common/snowflake.dart'; -import 'package:mineral/domains/commands/contexts/guild_command_context.dart'; -import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; -import 'package:mineral/infrastructure/internals/marshaller/types/serializer.dart'; - -final class ServerCommandContextSerializer implements SerializerContract { - final MarshallerContract marshaller; - - ServerCommandContextSerializer(this.marshaller); - - @override - Future serializeRemote(Map json) async { - return ServerCommandContext( - id: Snowflake(json['id']), - applicationId: Snowflake(json['application_id']), - version: json['version'], - token: json['token'], - channel: await marshaller.serializers.channels.serializeRemote(json['channel']), - user: await marshaller.serializers.user.serializeRemote(json['member']['user']), - server: await marshaller.dataStore.server.getServer(json['guild_id']), - ); - } - - @override - Future serializeCache(Map json) { - throw UnimplementedError(); - } - - @override - Map deserialize(ServerCommandContext permission) { - return {}; - } -} diff --git a/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart index 021ce0af..64ee9845 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_message_serializer.dart @@ -14,16 +14,18 @@ final class ServerMessageSerializer implements SerializerContract Future> normalize(Map json) async { final payload = { 'id': json['id'], + 'author_id': json['author']['id'], 'content': json['content'], 'embeds': json['embeds'], - // 'components': json['components'], + // 'components': json['components'], 'channel_id': json['channel_id'], - 'server_id': json['guild_id'], + 'server_id': json['server_id'], 'timestamp': json['timestamp'], 'edited_timestamp': json['edited_timestamp'], }; - final cacheKey = marshaller.cacheKey.message(Snowflake(json['channel_id']), Snowflake(json['id'])); + final cacheKey = + marshaller.cacheKey.message(Snowflake(json['channel_id']), Snowflake(json['id'])); await marshaller.cache.put(cacheKey, payload); return payload; @@ -31,15 +33,15 @@ final class ServerMessageSerializer implements SerializerContract @override Future serialize(Map json) async { - final channel = await marshaller.dataStore.channel - .getChannel(Snowflake(json['channel_id'])); + final channel = await marshaller.dataStore.channel.getChannel(Snowflake(json['channel_id'])); final server = await marshaller.dataStore.server.getServer(json['server_id']); - final member = server.members.list[json['author_id']]; + final member = await marshaller.dataStore.member + .getMember(serverId: server.id, memberId: json['author_id']); final messageProperties = MessageProperties.fromJson(channel as ServerChannel, json); - return ServerMessage(messageProperties, author: member!); + return ServerMessage(messageProperties, author: member); } @override @@ -54,7 +56,7 @@ final class ServerMessageSerializer implements SerializerContract 'embeds': embeds, 'author_id': object.author.id.value, 'channel_id': object.channel.id.value, - 'server_id': object.channel.guildId.value, + 'server_id': object.channel.serverId.value, 'timestamp': object.createdAt.toIso8601String(), 'edited_timestamp': object.updatedAt?.toIso8601String(), }; diff --git a/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart index cd0c7c4f..cf549781 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart @@ -27,21 +27,28 @@ final class ServerSerializer implements SerializerContract { }).wait; await List.from(json['channels']).map((element) async { - return _marshaller.serializers.channels.normalize(element); + return _marshaller.serializers.channels.normalize({ + ...element, + 'server_id': json['id'], + }); }).wait; await _marshaller.serializers.serversAsset.normalize(json); + await _marshaller.serializers.serverSettings.normalize(json); final Map serverPayload = { 'id': json['id'], 'name': json['name'], 'description': json['description'], 'application_id': json['application_id'], - 'owner': _marshaller.cacheKey.member(json['id'], json['owner_id']), + 'owner_id': _marshaller.cacheKey.member(json['id'], json['owner_id']), 'assets': _marshaller.cacheKey.serverAssets(json['id']), 'settings': _marshaller.cacheKey.serverSettings(json['id']), + 'roles': List.from(json['roles']) + .map((element) => _marshaller.cacheKey.serverRole(json['id'], element['id'])) + .toList(), 'members': List.from(json['members']) - .map((element) => _marshaller.cacheKey.member(json['id'], element['id'])) + .map((element) => _marshaller.cacheKey.member(json['id'], element['user']['id'])) .toList(), 'channels': List.from(json['channels']) .map((element) => _marshaller.cacheKey.channel(element['id'])) @@ -68,10 +75,10 @@ final class ServerSerializer implements SerializerContract { final rawChannels = await _marshaller.cache.getMany(payload['channels']); final channels = await rawChannels.nonNulls.map((element) async { - return _marshaller.serializers.channels.serialize(element); + return _marshaller.serializers.channels.serialize(element) as Future; }).wait; - final channelManager = ChannelManager.fromList(channels as List, payload); + final channelManager = ChannelManager.fromList(channels, payload); final roleManager = RoleManager.fromList(roles); final rawOwner = await _marshaller.cache.getOrFail(payload['owner_id']); diff --git a/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart index 243c46e7..6b049991 100644 --- a/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart @@ -25,7 +25,7 @@ final class StickerSerializer implements SerializerContract { 'sort_value': json['sort_value'], }; - final cacheKey = _marshaller.cacheKey.sticker(json['id']); + final cacheKey = _marshaller.cacheKey.sticker(Snowflake(''), json['id']); await _marshaller.cache.put(cacheKey, payload); return payload; diff --git a/lib/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart index e4dc2fa5..ca72dc82 100644 --- a/lib/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/user_assets_serializer.dart @@ -31,14 +31,14 @@ final class UserAssetsSerializer implements SerializerContract { return UserAssets( avatar: Helper.createOrNull( field: json['avatar'], - fn: () => ImageAsset(['avatars', json['member_id']], json['avatar'])), + fn: () => ImageAsset(['avatars', json['user_id']], json['avatar'])), avatarDecoration: Helper.createOrNull( field: json['avatar_decoration'], fn: () => - ImageAsset(['avatar-decorations', json['member_id']], json['avatar_decoration'])), + ImageAsset(['avatar-decorations', json['user_id']], json['avatar_decoration'])), banner: Helper.createOrNull( field: json['banner'], - fn: () => ImageAsset(['banners', json['member_id']], json['banner'])), + fn: () => ImageAsset(['banners', json['user_id']], json['banner'])), userId: Snowflake(json['user_id']), ); } diff --git a/lib/infrastructure/internals/packets/listeners/channel_create_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_create_packet.dart index 3e297e06..cd62dbd9 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_create_packet.dart @@ -28,7 +28,7 @@ final class ChannelCreatePacket implements ListenablePacket { } Future registerServerChannel(ServerChannel channel, DispatchEvent dispatch) async { - final server = await marshaller.dataStore.server.getServer(channel.guildId); + final server = await marshaller.dataStore.server.getServer(channel.serverId); final serverCacheKey = marshaller.cacheKey.server(server.id); final channelCacheKey = marshaller.cacheKey.channel(channel.id); diff --git a/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart index 97af1720..ef760a75 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart @@ -28,7 +28,7 @@ final class ChannelPinsUpdatePacket implements ListenablePacket { } Future registerServerChannelPins(ServerChannel channel, DispatchEvent dispatch) async { - final server = await marshaller.dataStore.server.getServer(channel.guildId); + final server = await marshaller.dataStore.server.getServer(channel.serverId); server.channels.list.update(channel.id, (_) => channel); diff --git a/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart index 29f5c6e5..3f8e762b 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart @@ -28,7 +28,7 @@ final class ChannelUpdatePacket implements ListenablePacket { } Future registerServerChannel(ServerChannel channel, DispatchEvent dispatch) async { - final server = await marshaller.dataStore.server.getServer(channel.guildId); + final server = await marshaller.dataStore.server.getServer(channel.serverId); final before = server.channels.list[channel.id]; diff --git a/lib/infrastructure/internals/packets/listeners/guild_ban_add_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_ban_add_packet.dart index 15f8df0a..52237e7f 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_ban_add_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_ban_add_packet.dart @@ -3,6 +3,7 @@ import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart'; import 'package:mineral/infrastructure/internals/packets/listenable_packet.dart'; import 'package:mineral/infrastructure/internals/packets/packet_type.dart'; import 'package:mineral/infrastructure/internals/wss/shard_message.dart'; +import 'package:mineral/infrastructure/services/logger/logger.dart'; final class GuildBanAddPacket implements ListenablePacket { @override diff --git a/lib/infrastructure/internals/packets/listeners/guild_create_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_create_packet.dart index 3a10c1e7..27af1fb7 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_create_packet.dart @@ -19,11 +19,8 @@ final class GuildCreatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { - final server = await marshaller.serializers.server.serialize(message.payload); - final cacheKey = marshaller.cacheKey.server(server.id); - - final rawServer = await marshaller.serializers.server.deserialize(server); - await marshaller.cache.put(cacheKey, rawServer); + final rawServer = await marshaller.serializers.server.normalize(message.payload); + final server = await marshaller.serializers.server.serialize(rawServer); final bot = ioc.resolve(); diff --git a/lib/infrastructure/internals/packets/listeners/guild_emojis_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_emojis_update_packet.dart index 8a9ecc18..afc43d37 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_emojis_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_emojis_update_packet.dart @@ -20,8 +20,16 @@ final class GuildEmojisUpdatePacket implements ListenablePacket { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); final serverCacheKey = marshaller.cacheKey.server(server.id); - final EmojiManager emojiManager = EmojiManager.fromJson(marshaller, - payload: message.payload['emojis'], roles: server.roles.list.values.toList()); + final rawEmojis = await List.from(message.payload['emojis']) + .map((element) async => marshaller.serializers.emojis.normalize(element)) + .wait; + + final emojis = await rawEmojis.map((element) async { + return marshaller.serializers.emojis.serialize(element); + }).wait; + + final EmojiManager emojiManager = + EmojiManager.fromList(server.roles.list.values.toList(), emojis); await emojiManager.list.values.map((emoji) async { final emojiCacheKey = marshaller.cacheKey.serverEmoji(server.id, emoji.id!); diff --git a/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart index 4dbe2b98..05533931 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart @@ -19,7 +19,7 @@ final class GuildMemberUpdatePacket implements ListenablePacket { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); final before = marshaller.dataStore.member.getMember( - guildId: server.id, + serverId: server.id, memberId: message.payload['user']['id'], ); diff --git a/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart index 51c0de49..331603d0 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart @@ -18,7 +18,7 @@ final class GuildRoleDeletePacket implements ListenablePacket { Future listen(ShardMessage message, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); final role = await marshaller.dataStore.role.getRole( - guildId: server.id, + serverId: server.id, roleId: message.payload['role_id'], ); diff --git a/lib/infrastructure/internals/packets/listeners/guild_stickers_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_stickers_update_packet.dart index d91b5ac7..a5c5ffd2 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_stickers_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_stickers_update_packet.dart @@ -18,7 +18,12 @@ final class GuildStickersUpdatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); - final StickerManager stickerManager = StickerManager.fromJson(marshaller, message.payload['stickers']); + + final stickers = await List.from(message.payload['stickers']).map((element) async { + return marshaller.dataStore.sticker.getSticker(server.id, element['id']); + }).wait; + + final StickerManager stickerManager = StickerManager.fromList(stickers); server.assets.stickers = stickerManager; diff --git a/lib/infrastructure/internals/packets/listeners/interactions/select_interaction_create_packet.dart b/lib/infrastructure/internals/packets/listeners/interactions/select_interaction_create_packet.dart index 0a48fe02..f056e0e6 100644 --- a/lib/infrastructure/internals/packets/listeners/interactions/select_interaction_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/interactions/select_interaction_create_packet.dart @@ -89,8 +89,7 @@ final class SelectInteractionCreatePacket implements ListenablePacket { final roleIds = Map.from(resolvedData['roles']).keys; final List resolvedRoles = await Future.wait(roleIds.map((id) async { - final cacheKey = - marshaller.cacheKey.serverRole(payload['guild_id'], Snowflake(id)); + final cacheKey = marshaller.cacheKey.serverRole(payload['guild_id'], Snowflake(id)); final rawRole = await marshaller.cache.getOrFail(cacheKey); return marshaller.serializers.role.serialize(rawRole); @@ -121,7 +120,7 @@ final class SelectInteractionCreatePacket implements ListenablePacket { final resolvedResource = await switch (ctx) { ServerSelectContext() => Future.wait(userIds.map((id) { return marshaller.dataStore.member.getMember( - guildId: Snowflake(payload['guild_id']), + serverId: Snowflake(payload['guild_id']), memberId: Snowflake(id), ); })), diff --git a/lib/infrastructure/internals/packets/listeners/message_create_packet.dart b/lib/infrastructure/internals/packets/listeners/message_create_packet.dart index bebd79f6..4a7e53f2 100644 --- a/lib/infrastructure/internals/packets/listeners/message_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/message_create_packet.dart @@ -1,3 +1,4 @@ +import 'package:mineral/api/common/channel.dart'; import 'package:mineral/api/common/message_type.dart'; import 'package:mineral/api/private/channels/private_channel.dart'; import 'package:mineral/api/server/channels/server_announcement_channel.dart'; @@ -26,21 +27,21 @@ final class MessageCreatePacket implements ListenablePacket { return; } - return switch (message.payload['message_reference']?['guild_id']) { - String() => sendServerMessage(dispatch, message.payload), - _ => sendPrivateMessage(dispatch, message.payload), + final channel = await marshaller.dataStore.channel.getChannel(message.payload['channel_id']); + return switch (channel) { + ServerChannel() => sendServerMessage(dispatch, channel, message.payload), + Channel() => sendPrivateMessage(dispatch, channel, message.payload), + _ => logger.error('Unknown channel type: ${channel.runtimeType}'), }; } - Future sendServerMessage(DispatchEvent dispatch, Map json) async { - final server = await marshaller.dataStore.server.getServer(json['message_reference']['guild_id']); - final channel = server.channels.list[json['channel_id']]; + Future sendServerMessage(DispatchEvent dispatch, ServerChannel channel, Map json) async { + final server = await marshaller.dataStore.server.getServer(channel.serverId); - final message = await marshaller.serializers.serverMessage.serialize(json); + final payload = await marshaller.serializers.serverMessage.normalize({...json, 'server_id': server.id.value}); + final message = await marshaller.serializers.serverMessage.serialize(payload); - if (channel is ServerChannel) { - message.channel = channel; - } + message.channel = channel; switch (channel) { case ServerTextChannel(): channel.messages.list.putIfAbsent(message.id, () => message); @@ -53,15 +54,15 @@ final class MessageCreatePacket implements ListenablePacket { await marshaller.cache.putMany({ marshaller.cacheKey.server(server.id): rawServer, - marshaller.cacheKey.message(channel!.id, message.id): rawMessage, + marshaller.cacheKey.message(channel.id, message.id): rawMessage, }); dispatch(event: Event.serverMessageCreate, params: [message]); } - Future sendPrivateMessage(DispatchEvent dispatch, Map json) async { - final channel = await marshaller.dataStore.channel.getChannel(json['channel_id']); - final message = await marshaller.serializers.privateMessage.serialize(json); + Future sendPrivateMessage(DispatchEvent dispatch, Channel channel, Map json) async { + final payload = await marshaller.serializers.privateMessage.normalize(json); + final message = await marshaller.serializers.privateMessage.serialize(payload); if (channel is PrivateChannel) { message.channel = channel; diff --git a/lib/infrastructure/kernel/client.dart b/lib/infrastructure/kernel/client.dart index 85ea8f24..55c68612 100644 --- a/lib/infrastructure/kernel/client.dart +++ b/lib/infrastructure/kernel/client.dart @@ -121,10 +121,10 @@ final class Client { _createCache(); final token = _env.get(AppEnv.token); - final httpVersion = _env.get(AppEnv.httpVersion); - final shardVersion = _env.get(AppEnv.wssVersion); - final intent = _env.get(AppEnv.intent); - final hmr = _env.get(AppEnv.hmr); + final httpVersion = int.parse(_env.get(AppEnv.httpVersion)); + final shardVersion = int.parse(_env.get(AppEnv.wssVersion)); + final intent = int.parse(_env.get(AppEnv.intent)); + final hmr = bool.parse(_env.get(AppEnv.hmr)); if (hmr && !_hasDefinedDevPort) { throw Exception('HMR is enabled but no dev port defined'); diff --git a/lib/infrastructure/kernel/kernel.dart b/lib/infrastructure/kernel/kernel.dart index 1d8b9242..f3cc1b28 100644 --- a/lib/infrastructure/kernel/kernel.dart +++ b/lib/infrastructure/kernel/kernel.dart @@ -124,7 +124,7 @@ final class Kernel implements KernelContract { @override Future init() async { - final useHmr = environment.get(AppEnv.hmr); + final useHmr = bool.parse(environment.get(AppEnv.hmr)); if ((useHmr && Isolate.current.debugName != 'main') || !useHmr) { await providerManager.ready(); From 5fc6abe44c2bba0df382d1ce938c91ccd860ab0b Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 09:08:49 +0200 Subject: [PATCH 27/44] feat(packets): rework channel create packet --- .../marshaller/serializers/server_serializer.dart | 7 ++++--- .../packets/listeners/channel_create_packet.dart | 12 ++---------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart index cf549781..f66472b1 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart @@ -127,11 +127,12 @@ final class ServerSerializer implements SerializerContract { 'owner': _marshaller.cacheKey.member(server.id, server.owner.id), 'assets': _marshaller.cacheKey.serverAssets(server.id), 'settings': _marshaller.cacheKey.serverSettings(server.id), + 'roles': server.roles.list.keys + .map((id) => _marshaller.cacheKey.serverRole(server.id, id)) + .toList(), 'members': server.members.list.keys.map((id) => _marshaller.cacheKey.member(server.id, id)).toList(), - 'channels': server.channels.list.keys - .map((id) => _marshaller.cacheKey.channel(id)) - .toList(), + 'channels': server.channels.list.keys.map((id) => _marshaller.cacheKey.channel(id)).toList(), }; } diff --git a/lib/infrastructure/internals/packets/listeners/channel_create_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_create_packet.dart index cd62dbd9..0535ba7f 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_create_packet.dart @@ -18,7 +18,8 @@ final class ChannelCreatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { - final channel = await marshaller.serializers.channels.serialize(message.payload); + final rawChannel = await marshaller.serializers.channels.normalize(message.payload); + final channel = await marshaller.serializers.channels.serialize(rawChannel); return switch (channel) { ServerChannel() => registerServerChannel(channel, dispatch), @@ -30,7 +31,6 @@ final class ChannelCreatePacket implements ListenablePacket { Future registerServerChannel(ServerChannel channel, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(channel.serverId); final serverCacheKey = marshaller.cacheKey.server(server.id); - final channelCacheKey = marshaller.cacheKey.channel(channel.id); channel.server = server; server.channels.list.putIfAbsent(channel.id, () => channel); @@ -38,18 +38,10 @@ final class ChannelCreatePacket implements ListenablePacket { final rawServer = await marshaller.serializers.server.deserialize(server); await marshaller.cache.put(serverCacheKey, rawServer); - final rawChannel = await marshaller.serializers.channels.deserialize(channel); - await marshaller.cache.put(channelCacheKey, rawChannel); - dispatch(event: Event.serverChannelCreate, params: [channel]); } Future registerPrivateChannel(PrivateChannel channel, DispatchEvent dispatch) async { - final cacheKey = marshaller.cacheKey.channel(channel.id); - - final rawChannel = await marshaller.serializers.channels.deserialize(channel); - await marshaller.cache.put(cacheKey, rawChannel); - dispatch(event: Event.privateChannelCreate, params: [channel]); } } From 424b257d105fb4d78278f33242b50848e71084dd Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 09:11:22 +0200 Subject: [PATCH 28/44] feat(packets): rework channel delete packet --- .../packets/listeners/channel_delete_packet.dart | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/channel_delete_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_delete_packet.dart index 6dc4e11b..5a9a1b4c 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_delete_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_delete_packet.dart @@ -18,16 +18,17 @@ final class ChannelDeletePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { - final channel = await marshaller.serializers.channels.serialize(message.payload); + final rawChannel = await marshaller.serializers.channels.normalize(message.payload); + final channel = await marshaller.serializers.channels.serialize(rawChannel); switch (channel) { case ServerChannel(): - await registerServerChannel(message.payload['guild_id'], channel, dispatch); + await registerServerChannel(channel, dispatch); } } - Future registerServerChannel(Snowflake guildId, ServerChannel channel, DispatchEvent dispatch) async { - final server = await marshaller.dataStore.server.getServer(guildId); + Future registerServerChannel(ServerChannel channel, DispatchEvent dispatch) async { + final server = await marshaller.dataStore.server.getServer(channel.serverId); final serverCacheKey = marshaller.cacheKey.server(server.id); final channelCacheKey = marshaller.cacheKey.channel(channel.id); From 12c7abff695208e5f40a20ea29747400b5794685 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 09:12:55 +0200 Subject: [PATCH 29/44] feat(packets): rework channel pin updates packet --- .../listeners/channel_pins_update_packet.dart | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart index ef760a75..a6b13d3c 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_pins_update_packet.dart @@ -18,7 +18,8 @@ final class ChannelPinsUpdatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { - final channel = await marshaller.serializers.channels.serialize(message.payload); + final rawChannel = await marshaller.serializers.channels.normalize(message.payload); + final channel = await marshaller.serializers.channels.serialize(rawChannel); return switch (channel) { ServerChannel() => registerServerChannelPins(channel, dispatch), @@ -33,22 +34,14 @@ final class ChannelPinsUpdatePacket implements ListenablePacket { server.channels.list.update(channel.id, (_) => channel); final rawServer = await marshaller.serializers.server.deserialize(server); - final rawChannel = await marshaller.serializers.channels.deserialize(channel); + final cacheKey = marshaller.cacheKey.server(server.id); - await marshaller.cache.putMany({ - marshaller.cacheKey.server(server.id): rawServer, - marshaller.cacheKey.channel(channel.id): rawChannel - }); + await marshaller.cache.put(cacheKey, rawServer); dispatch(event: Event.serverChannelPinsUpdate, params: [server, channel]); } Future registerPrivateChannelPins(PrivateChannel channel, DispatchEvent dispatch) async { - final channelCacheKey = marshaller.cacheKey.channel(channel.id); - - final rawChannel = await marshaller.serializers.channels.deserialize(channel); - await marshaller.cache.put(channelCacheKey, rawChannel); - dispatch(event: Event.privateChannelPinsUpdate, params: [channel]); } } From a23b8192c99603a2f9cdfd6f700919adb8c599d5 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 09:21:18 +0200 Subject: [PATCH 30/44] feat(packets): rework channel update packet --- .../listeners/channel_update_packet.dart | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart b/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart index 3f8e762b..88e80e66 100644 --- a/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/channel_update_packet.dart @@ -18,41 +18,36 @@ final class ChannelUpdatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { - final channel = await marshaller.serializers.channels.serialize(message.payload); + final rawBeforeChannel = await marshaller.cache.get(message.payload['id']); + final beforeChannel = rawBeforeChannel != null + ? await marshaller.serializers.channels.serialize(rawBeforeChannel) + : null; + + final rawChannel = await marshaller.serializers.channels.normalize(message.payload); + final channel = await marshaller.serializers.channels.serialize(rawChannel); return switch (channel) { - ServerChannel() => registerServerChannel(channel, dispatch), - PrivateChannel() => registerPrivateChannel(channel, dispatch), + ServerChannel() => registerServerChannel(channel, beforeChannel as ServerChannel?, dispatch), + PrivateChannel() => registerPrivateChannel(channel, beforeChannel as PrivateChannel?, dispatch), _ => logger.warn("Unknown channel type: $channel contact Mineral's core team.") }; } - Future registerServerChannel(ServerChannel channel, DispatchEvent dispatch) async { + Future registerServerChannel(ServerChannel channel, ServerChannel? before, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(channel.serverId); - final before = server.channels.list[channel.id]; - channel.server = server; server.channels.list.update(channel.id, (_) => channel); + final serverCacheKey = marshaller.cacheKey.server(server.id); final rawServer = await marshaller.serializers.server.deserialize(server); - final rawChannel = await marshaller.serializers.channels.deserialize(channel); - await marshaller.cache.putMany({ - marshaller.cacheKey.server(server.id): rawServer, - marshaller.cacheKey.channel(channel.id): rawChannel - }); + await marshaller.cache.put(serverCacheKey, rawServer); dispatch(event: Event.serverChannelUpdate, params: [before, channel]); } - Future registerPrivateChannel(PrivateChannel channel, DispatchEvent dispatch) async { - final cacheKey = marshaller.cacheKey.channel(channel.id); - final before = marshaller.dataStore.channel.getChannel(channel.id); - - final rawChannel = await marshaller.serializers.channels.deserialize(channel); - await marshaller.cache.put(cacheKey, rawChannel); - + Future registerPrivateChannel(PrivateChannel channel, PrivateChannel? before, DispatchEvent dispatch) async { dispatch(event: Event.serverChannelUpdate, params: [before, channel]); } } From 2cd2e62d5282043f05c5e5f7f3bf8e7a3373aa09 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 12:29:59 +0200 Subject: [PATCH 31/44] feat(packets): rework server delete packet --- .../events/contracts/server/server_delete_event.dart | 4 ++-- .../internals/datastore/parts/message_part.dart | 6 +++++- .../internals/marshaller/serializers/server_serializer.dart | 2 +- .../internals/packets/listeners/guild_delete_packet.dart | 5 ++++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/domains/events/contracts/server/server_delete_event.dart b/lib/domains/events/contracts/server/server_delete_event.dart index 8d8a34b6..4ba409f6 100644 --- a/lib/domains/events/contracts/server/server_delete_event.dart +++ b/lib/domains/events/contracts/server/server_delete_event.dart @@ -4,7 +4,7 @@ import 'package:mineral/api/server/server.dart'; import 'package:mineral/domains/events/event.dart'; import 'package:mineral/domains/events/types/listenable_event.dart'; -typedef ServerDeleteEventHandler = FutureOr Function(Server); +typedef ServerDeleteEventHandler = FutureOr Function(Server?); abstract class ServerDeleteEvent implements ListenableEvent { @override @@ -13,5 +13,5 @@ abstract class ServerDeleteEvent implements ListenableEvent { @override String? customId; - FutureOr handle(Server server); + FutureOr handle(Server? server); } diff --git a/lib/infrastructure/internals/datastore/parts/message_part.dart b/lib/infrastructure/internals/datastore/parts/message_part.dart index ae9d1590..975f6496 100644 --- a/lib/infrastructure/internals/datastore/parts/message_part.dart +++ b/lib/infrastructure/internals/datastore/parts/message_part.dart @@ -38,7 +38,11 @@ final class MessagePart implements DataStorePart { throw HttpException(response.body); } - final payload = await _kernel.marshaller.serializers.serverMessage.normalize(response.body); + final payload = await _kernel.marshaller.serializers.serverMessage.normalize({ + ...response.body, + 'server_id': serverChannel.serverId.value, + }); + final serverMessage = await _kernel.marshaller.serializers.serverMessage.serialize(payload); serverMessage.channel = serverChannel; diff --git a/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart index f66472b1..8a7fc687 100644 --- a/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/server_serializer.dart @@ -124,7 +124,7 @@ final class ServerSerializer implements SerializerContract { 'name': server.name, 'description': server.description, 'application_id': server.applicationId, - 'owner': _marshaller.cacheKey.member(server.id, server.owner.id), + 'owner_id': _marshaller.cacheKey.member(server.id, server.owner.id), 'assets': _marshaller.cacheKey.serverAssets(server.id), 'settings': _marshaller.cacheKey.serverSettings(server.id), 'roles': server.roles.list.keys diff --git a/lib/infrastructure/internals/packets/listeners/guild_delete_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_delete_packet.dart index d1f2e2c9..264c14b8 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_delete_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_delete_packet.dart @@ -17,7 +17,10 @@ final class GuildDeletePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { final cacheKey = marshaller.cacheKey.server(message.payload['id']); - final server = await marshaller.dataStore.server.getServer(message.payload['id']); + final rawServer = await marshaller.cache.get(cacheKey); + final server = rawServer != null + ? await marshaller.serializers.server.serialize(rawServer) + : null; dispatch(event: Event.serverDelete, params: [server]); From 317f37f141ce45302d960bfb12d2f1661372c357 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 12:31:43 +0200 Subject: [PATCH 32/44] feat(packets): rework server emoji updates packet --- .../packets/listeners/guild_emojis_update_packet.dart | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/guild_emojis_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_emojis_update_packet.dart index afc43d37..0d4d97d1 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_emojis_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_emojis_update_packet.dart @@ -31,13 +31,6 @@ final class GuildEmojisUpdatePacket implements ListenablePacket { final EmojiManager emojiManager = EmojiManager.fromList(server.roles.list.values.toList(), emojis); - await emojiManager.list.values.map((emoji) async { - final emojiCacheKey = marshaller.cacheKey.serverEmoji(server.id, emoji.id!); - final rawEmoji = await marshaller.serializers.emojis.deserialize(emoji); - - return marshaller.cache.put(emojiCacheKey, rawEmoji); - }).wait; - server.assets.emojis = emojiManager; final rawServer = await marshaller.serializers.server.deserialize(server); From c7fb33c6e124f34472d6a3f205fc1c7eca1d10d5 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 13:18:16 +0200 Subject: [PATCH 33/44] feat(packets): rework server member add packet --- .../packets/listeners/guild_member_add_packet.dart | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/guild_member_add_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_member_add_packet.dart index c94dd6f8..3346160e 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_member_add_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_member_add_packet.dart @@ -17,17 +17,16 @@ final class GuildMemberAddPacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); - final member = await marshaller.serializers.member.serialize({...message.payload, 'guild_roles': server.roles.list.values.toList()}); + + final rawMember = await marshaller.serializers.member.normalize(message.payload); + final member = await marshaller.serializers.member.serialize(rawMember); server.members.list.putIfAbsent(member.id, () => member); final rawServer = await marshaller.serializers.server.deserialize(server); - final rawMember = await marshaller.serializers.member.deserialize(member); - await marshaller.cache.putMany({ - marshaller.cacheKey.server(server.id): rawServer, - marshaller.cacheKey.member(server.id, member.id): rawMember - }); + final serverCacheKey = marshaller.cacheKey.server(server.id); + await marshaller.cache.put(serverCacheKey, rawServer); dispatch(event: Event.serverMemberAdd, params: [member, server]); } From a34d8bb17f68c4517efd04e065be2770c9e67fa0 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 22:56:31 +0200 Subject: [PATCH 34/44] feat(hmr): enhance hmr declaration --- .../internals/environment/app_env.dart | 4 +-- lib/infrastructure/kernel/client.dart | 13 ++------ lib/infrastructure/kernel/kernel.dart | 6 +++- .../services/logger/logger.dart | 32 +++++++++++++++++-- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/lib/infrastructure/internals/environment/app_env.dart b/lib/infrastructure/internals/environment/app_env.dart index f71c85a2..40255d21 100644 --- a/lib/infrastructure/internals/environment/app_env.dart +++ b/lib/infrastructure/internals/environment/app_env.dart @@ -1,12 +1,12 @@ import 'package:mineral/infrastructure/internals/environment/env_schema.dart'; enum AppEnv implements EnvSchema { + dartEnv('DART_ENV', required: true), token('TOKEN', required: true), httpVersion('HTTP_VERSION', required: true), wssVersion('WSS_VERSION', required: true), intent('INTENT', required: true), - logLevel('LOG_LEVEL', required: true), - hmr('HMR', required: true); + logLevel('LOG_LEVEL', required: true); @override final String key; diff --git a/lib/infrastructure/kernel/client.dart b/lib/infrastructure/kernel/client.dart index 55c68612..872dd85a 100644 --- a/lib/infrastructure/kernel/client.dart +++ b/lib/infrastructure/kernel/client.dart @@ -36,7 +36,7 @@ final class Client { final WatcherConfig _watcherConfig = WatcherConfig(); Client() { - _logger = Logger(_env.get(AppEnv.logLevel)); + _logger = Logger(_env); } Client setToken(String token) { @@ -64,11 +64,6 @@ final class Client { return this; } - Client setHmr(bool hmr) { - _env.list[AppEnv.hmr.key] = hmr.toString(); - return this; - } - Client setHmrDevPort(SendPort? devPort) { _devPort = devPort; _hasDefinedDevPort = true; @@ -124,11 +119,6 @@ final class Client { final httpVersion = int.parse(_env.get(AppEnv.httpVersion)); final shardVersion = int.parse(_env.get(AppEnv.wssVersion)); final intent = int.parse(_env.get(AppEnv.intent)); - final hmr = bool.parse(_env.get(AppEnv.hmr)); - - if (hmr && !_hasDefinedDevPort) { - throw Exception('HMR is enabled but no dev port defined'); - } final http = HttpClient( config: HttpClientConfigImpl( @@ -156,6 +146,7 @@ final class Client { final providerManager = ProviderManager(); final kernel = Kernel( + _hasDefinedDevPort, _devPort, watcherConfig: _watcherConfig, logger: _logger, diff --git a/lib/infrastructure/kernel/kernel.dart b/lib/infrastructure/kernel/kernel.dart index f3cc1b28..aa82cff4 100644 --- a/lib/infrastructure/kernel/kernel.dart +++ b/lib/infrastructure/kernel/kernel.dart @@ -52,6 +52,8 @@ abstract interface class KernelContract { final class Kernel implements KernelContract { final _watch = Stopwatch(); + final bool _hasDefinedDevPort; + final SendPort? _devPort; final WatcherConfig watcherConfig; @@ -93,6 +95,7 @@ final class Kernel implements KernelContract { final CommandInteractionManagerContract commands; Kernel( + this._hasDefinedDevPort, this._devPort, { required this.logger, required this.environment, @@ -124,7 +127,8 @@ final class Kernel implements KernelContract { @override Future init() async { - final useHmr = bool.parse(environment.get(AppEnv.hmr)); + final isDevelopmentMode = environment.get(AppEnv.dartEnv) == 'development'; + final useHmr = isDevelopmentMode && _hasDefinedDevPort; if ((useHmr && Isolate.current.debugName != 'main') || !useHmr) { await providerManager.ready(); diff --git a/lib/infrastructure/services/logger/logger.dart b/lib/infrastructure/services/logger/logger.dart index f26578fb..f1043c5a 100644 --- a/lib/infrastructure/services/logger/logger.dart +++ b/lib/infrastructure/services/logger/logger.dart @@ -3,6 +3,8 @@ import 'dart:io'; import 'package:intl/intl.dart'; import 'package:logging/logging.dart' as logging; import 'package:mansion/mansion.dart'; +import 'package:mineral/infrastructure/internals/environment/app_env.dart'; +import 'package:mineral/infrastructure/internals/environment/environment.dart'; abstract interface class LoggerContract { void trace(Object message); @@ -20,9 +22,13 @@ final class Logger implements LoggerContract { static Color get primaryColor => Color.fromRGB(140, 169, 238); static Color get mutedColor => Color.brightBlack; + final EnvContract _env; final _logger = logging.Logger('Core'); - Logger(String level) { + Logger(this._env) { + final level = _env.get(AppEnv.logLevel); + final dartEnv = _env.get(AppEnv.dartEnv); + const logLevels = { 'TRACE': logging.Level.FINEST, 'FATAL': logging.Level.SHOUT, @@ -65,7 +71,17 @@ final class Logger implements LoggerContract { _ => makeMessage('unknown', Color.blue, [Print(record.message)]), }; - stdout.writeAnsiAll(message); + if (dartEnv == 'production') { + message.writeWithoutAnsi(); + return; + } + + if (stdout.supportsAnsiEscapes) { + stdout.writeAnsiAll(message); + return; + } + + message.writeWithoutAnsi(); }); } @@ -84,3 +100,15 @@ final class Logger implements LoggerContract { @override void warn(String message) => _logger.warning(message); } + +extension on List { + void writeWithoutAnsi() { + for (final sequence in this) { + switch(sequence) { + case Print(:final text): stdout.write(text); + case AsciiControl(:final writeAnsiString): writeAnsiString(stdout); + default: + } + } + } +} From 3ded0e793d8fc4692defa2f01974c98ab6923e47 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 22:56:43 +0200 Subject: [PATCH 35/44] feat(packets): rework server member chunk packet --- .../listeners/guild_member_chunk_packet.dart | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/guild_member_chunk_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_member_chunk_packet.dart index 6d433970..5dae6e60 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_member_chunk_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_member_chunk_packet.dart @@ -17,20 +17,17 @@ final class GuildMemberChunkPacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); - final serverCacheKey = marshaller.cacheKey.server(server.id); - final members = message.payload['members']; - final presences = message.payload['presences']; + final rawMembers = await List.from(message.payload['members']).map((element) async { + return marshaller.serializers.member.normalize(element); + }).wait; - for (final element in members) { + await rawMembers.nonNulls.map((element) async { final member = await marshaller.serializers.member.serialize(element); - final memberCacheKey = marshaller.cacheKey.member(server.id, member.id); + server.members.list.update(member.id, (value) => member, ifAbsent: () => member); + }).wait; - final rawMember = await marshaller.serializers.member.deserialize(member); - await marshaller.cache.put(memberCacheKey, rawMember); - - server.members.list.putIfAbsent(member.id, () => member); - } + final presences = message.payload['presences']; for (final rawPresence in presences) { final presence = Presence.fromJson(rawPresence); @@ -38,6 +35,8 @@ final class GuildMemberChunkPacket implements ListenablePacket { } final rawServer = await marshaller.serializers.server.deserialize(server); + final serverCacheKey = marshaller.cacheKey.server(server.id); + await marshaller.cache.put(serverCacheKey, rawServer); } } From 9322bfce9c8982d7dfbf5c471bee38cec45a9f5c Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 23:05:57 +0200 Subject: [PATCH 36/44] feat(packets): rework server member remove packet --- .../packets/listeners/guild_member_remove_packet.dart | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/guild_member_remove_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_member_remove_packet.dart index c32f5827..2f90b1b5 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_member_remove_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_member_remove_packet.dart @@ -16,16 +16,13 @@ final class GuildMemberRemovePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { + final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); final memberId = message.payload['user']['id']; - final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); final serverCacheKey = marshaller.cacheKey.server(server.id); - final memberCacheKey = - marshaller.cacheKey.member(server.id, memberId); + final memberCacheKey = marshaller.cacheKey.member(server.id, memberId); - final rawMember = await marshaller.cache.get(memberCacheKey); - final user = - rawMember != null ? await marshaller.serializers.user.serialize(rawMember) : null; + final user = await marshaller.dataStore.user.getUser(memberId); server.members.list.remove(memberId); From faab9ac87ecc8c4db2a760f75fc640fd17a18315 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 23:08:07 +0200 Subject: [PATCH 37/44] feat(packets): rework server member update packet --- .../listeners/guild_member_update_packet.dart | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart index 05533931..e8e1453d 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_member_update_packet.dart @@ -23,18 +23,17 @@ final class GuildMemberUpdatePacket implements ListenablePacket { memberId: message.payload['user']['id'], ); - final after = await marshaller.serializers.member.serialize({...message.payload, 'guild_roles': server.roles.list.values.toList()}); + final rawMember = await marshaller.serializers.member.normalize(message.payload); + final member = await marshaller.serializers.member.serialize(rawMember); - server.members.list.update(after.id, (_) => after); + member.server = server; + server.members.list.update(member.id, (_) => member); + final serverCacheKey = marshaller.cacheKey.server(server.id); final rawServer = await marshaller.serializers.server.deserialize(server); - final rawMember = await marshaller.serializers.member.deserialize(after); - await marshaller.cache.putMany({ - marshaller.cacheKey.server(server.id): rawServer, - marshaller.cacheKey.member(server.id, after.id): rawMember - }); + await marshaller.cache.put(serverCacheKey, rawServer); - dispatch(event: Event.serverMemberUpdate, params: [before, after]); + dispatch(event: Event.serverMemberUpdate, params: [before, member]); } } From 7af7da89e5b1301d2b4540475d7e01de4a11a9ab Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Tue, 20 Aug 2024 23:11:27 +0200 Subject: [PATCH 38/44] feat(packets): rework server role create packet --- .../listeners/guild_role_create_packet.dart | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/guild_role_create_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_role_create_packet.dart index 35422010..2142d863 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_role_create_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_role_create_packet.dart @@ -17,17 +17,19 @@ final class GuildRoleCreatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); - final role = await marshaller.serializers.role.serialize(message.payload['role']); + final rawRole = await marshaller.serializers.role.normalize({ + ...message.payload['role'], + 'server_id': server.id, + }); + + final role = await marshaller.serializers.role.serialize(rawRole); server.roles.list.putIfAbsent(role.id, () => role); + final serverCacheKey = marshaller.cacheKey.server(server.id); final rawServer = await marshaller.serializers.server.deserialize(server); - final rawRole = await marshaller.serializers.role.deserialize(role); - await marshaller.cache.putMany({ - marshaller.cacheKey.server(server.id): rawServer, - marshaller.cacheKey.serverRole( server.id, role.id): rawRole, - }); + await marshaller.cache.put(serverCacheKey, rawServer); dispatch(event: Event.serverRoleCreate, params: [role, server]); } From beaeeea2ff135e9675299a5daf5d0823ea22f768 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Wed, 21 Aug 2024 09:20:27 +0200 Subject: [PATCH 39/44] feat(packets): rework server role delete packet --- .../packets/listeners/guild_role_delete_packet.dart | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart index 331603d0..eb959826 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_role_delete_packet.dart @@ -17,15 +17,16 @@ final class GuildRoleDeletePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); - final role = await marshaller.dataStore.role.getRole( - serverId: server.id, - roleId: message.payload['role_id'], - ); - server.roles.list.remove(role.id); + final roleId = message.payload['role']['id']; + + final roleCacheKey = marshaller.cacheKey.serverRole(server.id, roleId); + final rawRole = await marshaller.cache.get(roleCacheKey); + final role = rawRole != null ? await marshaller.serializers.role.serialize(rawRole) : null; + + server.roles.list.remove(roleId); final serverCacheKey = marshaller.cacheKey.server(server.id); - final roleCacheKey = marshaller.cacheKey.serverRole(server.id, role.id); final rawServer = await marshaller.serializers.server.deserialize(server); await marshaller.cache.put(serverCacheKey, rawServer); From b14af17996ef2377537a08e26e41ab4aa460eda1 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Wed, 21 Aug 2024 09:27:38 +0200 Subject: [PATCH 40/44] feat(packets): rework server role update packet --- .../listeners/guild_role_update_packet.dart | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/guild_role_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_role_update_packet.dart index 96c856d3..471598df 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_role_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_role_update_packet.dart @@ -16,21 +16,22 @@ final class GuildRoleUpdatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { + final serverCacheKey = marshaller.cacheKey.server(message.payload['guild_id']); final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); - final before = server.roles.list[message.payload['role']['id']]; - final after = await marshaller.serializers.role.serialize(message.payload['role']); + final roleCacheKey = marshaller.cacheKey.serverRole(server.id, message.payload['role']['id']); + final rawBefore = await marshaller.cache.get(roleCacheKey); + final before = rawBefore != null ? marshaller.serializers.role.serialize(rawBefore) : null; - server.roles.list.update(after.id, (_) => after); + final rawRole = await marshaller.serializers.role.normalize(message.payload['role']); + final role = await marshaller.serializers.role.serialize(rawRole); - final rawServer = await marshaller.serializers.server.deserialize(server); - final rawRole = await marshaller.serializers.role.deserialize(after); + server.roles.list.update(role.id, (_) => role); + role.server = server; - dispatch(event: Event.serverRoleUpdate, params: [before, after, server]); + final rawServer = await marshaller.serializers.server.deserialize(server); + await marshaller.cache.put(serverCacheKey, rawServer); - await marshaller.cache.putMany({ - marshaller.cacheKey.server(server.id): rawServer, - marshaller.cacheKey.serverRole(server.id, after.id): rawRole, - }); + dispatch(event: Event.serverRoleUpdate, params: [before, role, server]); } } From 1e1bc96c1f133e8bbb732d2e1d5f782350b7e2fe Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Wed, 21 Aug 2024 20:43:50 +0200 Subject: [PATCH 41/44] feat(packets): rework server stickers update packet --- lib/api/common/sticker.dart | 2 ++ .../marshaller/serializers/sticker_serializer.dart | 5 ++++- .../listeners/guild_stickers_update_packet.dart | 11 +++++++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/api/common/sticker.dart b/lib/api/common/sticker.dart index e4f4df8f..e3a79a87 100644 --- a/lib/api/common/sticker.dart +++ b/lib/api/common/sticker.dart @@ -13,6 +13,7 @@ final class Sticker { final FormatType? formatType; final bool isAvailable; final int? sortValue; + final Snowflake? serverId; Sticker({ required this.id, @@ -25,5 +26,6 @@ final class Sticker { this.asset, this.formatType, this.sortValue, + this.serverId, }); } diff --git a/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart b/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart index 6b049991..8ceec618 100644 --- a/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart +++ b/lib/infrastructure/internals/marshaller/serializers/sticker_serializer.dart @@ -23,9 +23,10 @@ final class StickerSerializer implements SerializerContract { 'asset': json['asset'], 'format_type': json['format_type'], 'sort_value': json['sort_value'], + 'server_id': json['server_id'], }; - final cacheKey = _marshaller.cacheKey.sticker(Snowflake(''), json['id']); + final cacheKey = _marshaller.cacheKey.sticker(Snowflake(json['server_id']), json['id']); await _marshaller.cache.put(cacheKey, payload); return payload; @@ -44,6 +45,7 @@ final class StickerSerializer implements SerializerContract { asset: json['asset'], formatType: FormatType.values.firstWhere((element) => element.value == json['format_type']), sortValue: json['sort_value'], + serverId: Snowflake(json['server_id']), ); } @@ -60,6 +62,7 @@ final class StickerSerializer implements SerializerContract { 'asset': sticker.asset, 'format_type': sticker.formatType?.value, 'sort_value': sticker.sortValue, + 'server_id': sticker.serverId, }; } } diff --git a/lib/infrastructure/internals/packets/listeners/guild_stickers_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_stickers_update_packet.dart index a5c5ffd2..bdac7ffe 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_stickers_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_stickers_update_packet.dart @@ -19,8 +19,15 @@ final class GuildStickersUpdatePacket implements ListenablePacket { Future listen(ShardMessage message, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); - final stickers = await List.from(message.payload['stickers']).map((element) async { - return marshaller.dataStore.sticker.getSticker(server.id, element['id']); + final rawStickers = await List.from(message.payload['stickers']).map((element) async { + return marshaller.serializers.sticker.normalize({ + 'server_id': server.id, + ...element, + }); + }).wait; + + final stickers = await List.from(rawStickers).map((element) async { + return marshaller.serializers.sticker.serialize(element); }).wait; final StickerManager stickerManager = StickerManager.fromList(stickers); From c9fcf1343db5d1a305fd4571873a28df3667f6e8 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Wed, 21 Aug 2024 20:57:14 +0200 Subject: [PATCH 42/44] feat(packets): rework server update packet --- .../packets/listeners/guild_update_packet.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/guild_update_packet.dart b/lib/infrastructure/internals/packets/listeners/guild_update_packet.dart index 0d52937b..94c19bc9 100644 --- a/lib/infrastructure/internals/packets/listeners/guild_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/guild_update_packet.dart @@ -16,14 +16,14 @@ final class GuildUpdatePacket implements ListenablePacket { @override Future listen(ShardMessage message, DispatchEvent dispatch) async { - final before = await marshaller.dataStore.server.getServer(message.payload['id']); - final after = await marshaller.serializers.server.serialize(message.payload); + final serverCacheKey = marshaller.cacheKey.server(message.payload['id']); + final rawServer = await marshaller.cache.get(serverCacheKey); + final before = + rawServer != null ? await marshaller.serializers.server.serialize(rawServer) : null; - final cacheKey = marshaller.cacheKey.server(after.id); - final rawServer = await marshaller.serializers.server.deserialize(after); + final rawAfter = await marshaller.serializers.server.normalize(message.payload); + final after = await marshaller.serializers.server.serialize(rawAfter); dispatch(event: Event.serverUpdate, params: [before, after]); - - marshaller.cache.put(cacheKey, rawServer); } } From 8893cdcbd032bd9c03125c8557ee6a349f735990 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Wed, 21 Aug 2024 22:55:28 +0200 Subject: [PATCH 43/44] feat(packets): rework presence update packet --- .../packets/listeners/presence_update_packet.dart | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/infrastructure/internals/packets/listeners/presence_update_packet.dart b/lib/infrastructure/internals/packets/listeners/presence_update_packet.dart index d2034f19..409ddeb8 100644 --- a/lib/infrastructure/internals/packets/listeners/presence_update_packet.dart +++ b/lib/infrastructure/internals/packets/listeners/presence_update_packet.dart @@ -19,20 +19,16 @@ final class PresenceUpdatePacket implements ListenablePacket { Future listen(ShardMessage message, DispatchEvent dispatch) async { final server = await marshaller.dataStore.server.getServer(message.payload['guild_id']); final serverCacheKey = marshaller.cacheKey.server(server.id); - final memberCacheKey = marshaller.cacheKey - .member(server.id, message.payload['user']['id']); + final memberCacheKey = marshaller.cacheKey.member(server.id, message.payload['user']['id']); - final rawMember = await marshaller.cache.getOrFail(memberCacheKey); - final member = await marshaller.serializers.member.serialize({ - ...rawMember, - 'guild_id': server.id.value, - }); + final member = await marshaller.dataStore.member + .getMember(memberId: message.payload['user']['id'], serverId: server.id); final presence = Presence.fromJson(message.payload); member.presence = presence; - final rawServer = await marshaller.serializers.server.deserialize(server); - await marshaller.cache.put(serverCacheKey, rawServer); + final rawMember = await marshaller.serializers.member.deserialize(member); + await marshaller.cache.put(memberCacheKey, rawMember); dispatch(event: Event.serverPresenceUpdate, params: [member, server, presence]); } From 4f8b7fda3410cb628870b4800bdb717b5eef9a3f Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Thu, 22 Aug 2024 00:36:19 +0200 Subject: [PATCH 44/44] feat(packets): make adjustments --- lib/api/common/channel.dart | 10 ++++++++++ lib/api/common/types/channel_type.dart | 3 ++- .../internals/datastore/parts/server_part.dart | 3 ++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/api/common/channel.dart b/lib/api/common/channel.dart index 20ad80a9..47309d84 100644 --- a/lib/api/common/channel.dart +++ b/lib/api/common/channel.dart @@ -6,3 +6,13 @@ abstract class Channel { ChannelType get type; T cast() => this as T; } + +final class UnknownChannel extends Channel { + @override + final Snowflake id; + + @override + final ChannelType type = ChannelType.unknown; + + UnknownChannel(this.id); +} diff --git a/lib/api/common/types/channel_type.dart b/lib/api/common/types/channel_type.dart index 5fbb92e3..d997dd63 100644 --- a/lib/api/common/types/channel_type.dart +++ b/lib/api/common/types/channel_type.dart @@ -13,7 +13,8 @@ enum ChannelType implements EnhancedEnum{ guildStageVoice(13), guildDirectory(14), guildForum(15), - guildMedia(16); + guildMedia(16), + unknown(-1); @override final int value; diff --git a/lib/infrastructure/internals/datastore/parts/server_part.dart b/lib/infrastructure/internals/datastore/parts/server_part.dart index 386fadb5..62499349 100644 --- a/lib/infrastructure/internals/datastore/parts/server_part.dart +++ b/lib/infrastructure/internals/datastore/parts/server_part.dart @@ -30,7 +30,8 @@ final class ServerPart implements DataStorePart { await getChannels(id); await _kernel.dataStore.member.getMembers(id); - return _kernel.marshaller.serializers.server.serialize(serverResponse.body); + final payload = await _kernel.marshaller.serializers.server.normalize(serverResponse.body); + return _kernel.marshaller.serializers.server.serialize(payload); } Future> getChannels(Snowflake id) async {