part of nyxx; /// Wraps [SnowflakeEntity] that can be taken from cache or optionally downloaded from API. /// Always provides [id] of entity. `download()` method tries to get entity from API and returns it upon success or /// throws Error if something happens in the process. abstract class Cacheable { final Nyxx _client; /// Id of entity final T id; Cacheable._new(this._client, this.id); /// Returns entity from cache or null if not present S? getFromCache(); /// Downloads entity from cache and caches result Future download(); /// Returns entity from cache or tries to download from API if not found. /// If downloading is successful it caches results FutureOr getOrDownload() async { final cacheResult = this.getFromCache(); if (cacheResult != null) { return cacheResult; } return this.download(); } @override bool operator ==(Object other) => other is Cacheable && other.id == this.id; @override int get hashCode => id.hashCode; } class _RoleCacheable extends Cacheable { final Cacheable guild; _RoleCacheable(Nyxx client, Snowflake id, this.guild): super._new(client, id); @override Future download() async => this._fetchGuildRole(); @override Role? getFromCache() { final guildInstance = guild.getFromCache(); if (guildInstance == null) { return null; } return guildInstance.roles[this.id]; } // We cant download single role Future _fetchGuildRole() async { final roles = await _client._httpEndpoints.fetchGuildRoles(this.id).toList(); try { return roles.firstWhere((element) => element.id == this.id); } on Exception { throw ArgumentError("Cannot fetch role with id `${this.id}` in guild with id `${this.guild.id}`"); } } } class _ChannelCacheable extends Cacheable { _ChannelCacheable(Nyxx client, Snowflake id): super._new(client, id); @override T? getFromCache() => this._client.channels[this.id] as T?; @override Future download() => _client._httpEndpoints.fetchChannel(this.id); } class _GuildCacheable extends Cacheable { _GuildCacheable(Nyxx client, Snowflake id): super._new(client, id); @override Guild? getFromCache() => this._client.guilds[this.id]; @override Future download() => _client._httpEndpoints.fetchGuild(this.id); } class _UserCacheable extends Cacheable { _UserCacheable(Nyxx client, Snowflake id): super._new(client, id); @override Future download() => _client._httpEndpoints.fetchUser(this.id); @override User? getFromCache() => this._client.users[this.id]; } class _MemberCacheable extends Cacheable { final Cacheable guild; _MemberCacheable(Nyxx client, Snowflake id, this.guild): super._new(client, id); @override Future download() => this._client._httpEndpoints.fetchGuildMember(guild.id, id); @override Member? getFromCache() { final guildInstance = this.guild.getFromCache(); if (guildInstance != null) { return guildInstance.members[this.id]; } return null; } } class _MessageCacheable extends Cacheable { final Cacheable channel; _MessageCacheable(Nyxx client, Snowflake id, this.channel) : super._new(client, id); @override Future download() async { final channelInstance = await this.channel.getOrDownload(); return channelInstance.fetchMessage(this.id); } @override Message? getFromCache() { final channelInstance = this.channel.getFromCache(); if (channelInstance != null) { return channelInstance.messageCache[this.id]; } return null; } }