예제 #1
0
 internal InviteCreatedEventArgs(
     DiscordClientBase client,
     CachedGuild guild,
     SnowflakeOptional <CachedChannel> channel,
     CachedUser inviter,
     string code,
     bool isTemporary,
     int maxUses,
     int maxAge,
     DateTimeOffset createdAt) : base(client)
 {
     Guild       = guild;
     Channel     = channel;
     Inviter     = inviter;
     Code        = code;
     IsTemporary = isTemporary;
     MaxUses     = maxUses;
     MaxAge      = maxAge;
     CreatedAt   = createdAt;
 }
예제 #2
0
 internal GuildUpdatedEventArgs(CachedGuild oldGuild, CachedGuild newGuild) : base(newGuild.Client)
 {
     OldGuild = oldGuild;
     NewGuild = newGuild;
 }
예제 #3
0
        private static async Task PersistGuildAsync(CachedGuild guild, EspeonDbContext context)
        {
            await context.GetOrCreateAsync(guild.Id.RawValue, guildId => new GuildPrefixes(guildId));

            await context.GetOrCreateAsync(guild.Id.RawValue, guildId => new GuildTags(guildId));
        }
예제 #4
0
 internal GuildEmojisUpdatedEventArgs(CachedGuild guild, IReadOnlyDictionary <Snowflake, CachedGuildEmoji> oldEmojis) : base(guild.Client)
 {
     Guild     = guild;
     OldEmojis = oldEmojis;
     NewEmojis = guild.Emojis;
 }
예제 #5
0
        // TODO: possible cache inconsistencies on unavailable guilds? No idea what Discord sends nor does while it's unavailable.
        private IGatewayGuild UpdateCache(GatewayGuildJsonModel model, bool isPending)
        {
            IGatewayGuild guild = null;

            if (CacheProvider.TryGetGuilds(out var guildCache))
            {
                if (isPending)
                {
                    guild = new CachedGuild(Client, model);
                    guildCache.Add(model.Id, guild as CachedGuild);
                }
                else
                {
                    guild = guildCache.GetValueOrDefault(model.Id);
                    guild?.Update(model);
                }
            }

            guild ??= new TransientGatewayGuild(Client, model);

            if (CacheProvider.TryGetUsers(out var userCache) && CacheProvider.TryGetMembers(model.Id, out var memberCache))
            {
                foreach (var memberModel in model.Members)
                {
                    Dispatcher.GetOrAddMember(userCache, memberCache, model.Id, memberModel);
                }
            }

            if (CacheProvider.TryGetChannels(model.Id, out var channelCache))
            {
                foreach (var channelModel in model.Channels)
                {
                    if (isPending)
                    {
                        channelModel.GuildId = model.Id;
                        var channel = CachedGuildChannel.Create(Client, channelModel);
                        channelCache.Add(channel.Id, channel);
                    }
                    else
                    {
                        var channel = channelCache.GetValueOrDefault(channelModel.Id);
                        channel?.Update(channelModel);
                    }
                }

                foreach (var threadModel in model.Threads)
                {
                    if (isPending)
                    {
                        threadModel.GuildId = model.Id;
                        if (threadModel.Member.HasValue)
                        {
                            threadModel.Member.Value.Id     = threadModel.Id;
                            threadModel.Member.Value.UserId = Client.CurrentUser.Id;
                        }
                        var channel = new CachedThreadChannel(Client, threadModel);
                        channelCache.Add(channel.Id, channel);
                    }
                    else
                    {
                        var channel = channelCache.GetValueOrDefault(threadModel.Id);
                        channel?.Update(threadModel);
                    }
                }
            }

            if (CacheProvider.TryGetRoles(model.Id, out var roleCache))
            {
                foreach (var roleModel in model.Roles)
                {
                    if (isPending)
                    {
                        var role = new CachedRole(Client, model.Id, roleModel);
                        roleCache.Add(role.Id, role);
                    }
                    else
                    {
                        var role = roleCache.GetValueOrDefault(roleModel.Id);
                        role?.Update(roleModel);
                    }
                }
            }

            if (CacheProvider.TryGetVoiceStates(model.Id, out var voiceStateCache))
            {
                foreach (var voiceStateModel in model.VoiceStates)
                {
                    if (isPending)
                    {
                        var voiceState = new CachedVoiceState(Client, model.Id, voiceStateModel);
                        voiceStateCache.Add(voiceState.MemberId, voiceState);
                    }
                    else
                    {
                        var voiceState = voiceStateCache.GetValueOrDefault(voiceStateModel.UserId);
                        voiceState?.Update(voiceStateModel);
                    }
                }
            }

            if (CacheProvider.TryGetPresences(model.Id, out var presenceCache))
            {
                foreach (var presenceModel in model.Presences)
                {
                    if (isPending)
                    {
                        var presence = new CachedPresence(Client, presenceModel);
                        presenceCache.Add(presence.MemberId, presence);
                    }
                    else
                    {
                        var presence = presenceCache.GetValueOrDefault(presenceModel.User.Id);
                        presence?.Update(presenceModel);
                    }
                }
            }

            if (CacheProvider.TryGetStages(model.Id, out var stageCache))
            {
                foreach (var stageModel in model.StageInstances)
                {
                    if (isPending)
                    {
                        var stage = new CachedStage(Client, stageModel);
                        stageCache.Add(stage.Id, stage);
                    }
                    else
                    {
                        var stage = stageCache.GetValueOrDefault(stageModel.Id);
                        stage?.Update(stageModel);
                    }
                }
            }

            return(guild);
        }
예제 #6
0
 internal LeftGuildEventArgs(CachedGuild guild) : base(guild.Client)
 {
     Guild = guild;
 }
예제 #7
0
 internal GuildUnavailableEventArgs(CachedGuild guild) : base(guild.Client)
 {
     Guild = guild;
 }
        public static async Task <(bool success, string failureReason)> UnmuteUserAsync(CachedGuild guild, IMember user, Config config)
        {
            IRole mutedRole = await GetMutedRoleAsync(guild);

            if (mutedRole == null)
            {
                return(false, "Failed getting/creating muted role");
            }

            await user.RevokeRoleAsync(mutedRole.Id);

            config.GetOrAddGuild(guild.Id).CurrentMutes.Remove(user.Id, out Mute muteInfo);

            foreach (ulong roleId in muteInfo?.RoleIds ?? new ulong[0])
            {
                try
                {
                    await user.GrantRoleAsync(roleId);
                }
                catch
                {
                    // Do nothing, ignoring roles that stopped existing since the mute
                }
            }

            return(true, string.Empty);
        }
        public static async Task <(bool success, string failureReason)> MuteUserAsync(CachedGuild guild, IMember user, string time, Config config)
        {
            IRole mutedRole = await GetMutedRoleAsync(guild);

            if (mutedRole == null)
            {
                return(false, "Failed getting/creating muted role");
            }

            if (user.RoleIds.Contains(mutedRole.Id))
            {
                return(false, "User is already muted");
            }

            TimeSpan muteTime = ParseTime(time);

            if (muteTime == TimeSpan.Zero)
            {
                return(false, "Failed parsing mute time, please give in the format '1d6h30m'");
            }

            List <ulong> revokedRoles = new();

            foreach (ulong role in user.RoleIds)
            {
                try
                {
                    await user.RevokeRoleAsync(role);

                    revokedRoles.Add(role);
                }
                catch
                {
                    // Do nothing, ignoring roles that the bot has no perms to remove
                }
            }

            await user.GrantRoleAsync(mutedRole.Id);

            config.GetOrAddGuild(guild.Id).CurrentMutes[user.Id] = new Mute
            {
                GuildId    = guild.Id,
                UserId     = user.Id,
                RoleIds    = revokedRoles.ToArray(),
                UnmuteTime = DateTime.Now + muteTime
            };

            return(true, string.Empty);
        }
예제 #10
0
        private async Task SendByeMessageAsync(GuildsEntity guildDb, CachedUser user, CachedGuild guild)
        {
            if (guildDb is null)
            {
                return;
            }
            if (!guildDb.ByeNotification)
            {
                return;
            }
            if (string.IsNullOrEmpty(guildDb.ByeMessage))
            {
                return;
            }
            if (guildDb.ByeWebhookId == 0)
            {
                return;
            }

            var currentMember = guild.CurrentMember;

            if (!currentMember.Permissions.ManageWebhooks)
            {
                return;
            }

            var guildWebhook = await guild.GetWebhookAsync(guildDb.ByeWebhookId);

            if (_webhooks.TryGetValue(guildDb.ByeWebhookId, out var webhook))
            {
                if (guildWebhook is null)
                {
                    _webhooks.TryRemove(guildDb.ByeWebhookId, out _);
                    webhook.Dispose();
                    await DisableByeAsync(guild);

                    return;
                }
            }
            else
            {
                if (guildWebhook != null)
                {
                    webhook = new RestWebhookClient(guildWebhook);
                    _webhooks.TryAdd(guildWebhook.Id, webhook);
                }
                else
                {
                    await DisableByeAsync(guild);

                    return;
                }
            }

            if (webhook is null)
            {
                return;
            }

            var byeMsg = ReplacePlaceholders(user, guildDb.ByeMessage);

            if (RiasUtilities.TryParseEmbed(byeMsg, out var embed))
            {
                await webhook.ExecuteAsync(embeds : new[] { embed.Build() });
            }
            else
            {
                await webhook.ExecuteAsync(byeMsg);
            }
        }
예제 #11
0
        public override async ValueTask <EventArgs> HandleDispatchAsync(IGatewayApiClient shard, GatewayGuildJsonModel model)
        {
            IGatewayGuild guild = null;

            // Check if the event is guild availability or we joined a new guild.
            if (model.Unavailable.HasValue)
            {
                // A guild became available.
                var isPending = _readyHandler.IsPendingGuild(shard.Id, model.Id);
                try
                {
                    if (CacheProvider.TryGetGuilds(out var guildCache))
                    {
                        if (isPending)
                        {
                            guild = new CachedGuild(Client, model);
                            guildCache.Add(model.Id, guild as CachedGuild);
                        }
                        else
                        {
                            guild = guildCache.GetValueOrDefault(model.Id);
                            guild?.Update(model);
                        }
                    }

                    if (guild == null)
                    {
                        guild = new TransientGatewayGuild(Client, model);
                    }

                    // TODO: optimise member cache retrieval
                    if (CacheProvider.TryGetMembers(model.Id, out var memberCache))
                    {
                        foreach (var memberModel in model.Members)
                        {
                            Dispatcher.GetOrAddMember(model.Id, memberModel);
                        }
                    }

                    if (CacheProvider.TryGetChannels(model.Id, out var channelCache))
                    {
                        foreach (var channelModel in model.Channels)
                        {
                            if (isPending)
                            {
                                var channel = CachedGuildChannel.Create(Client, model.Id, channelModel);
                                channelCache.Add(channel.Id, channel);
                            }
                            else
                            {
                                var channel = channelCache.GetValueOrDefault(channelModel.Id);
                                channel?.Update(channelModel);
                            }
                        }
                    }

                    if (CacheProvider.TryGetRoles(model.Id, out var roleCache))
                    {
                        foreach (var roleModel in model.Roles)
                        {
                            if (isPending)
                            {
                                var role = new CachedRole(Client, model.Id, roleModel);
                                roleCache.Add(role.Id, role);
                            }
                            else
                            {
                                var role = roleCache.GetValueOrDefault(roleModel.Id);
                                role?.Update(roleModel);
                            }
                        }
                    }

                    if (CacheProvider.TryGetVoiceStates(model.Id, out var voiceStateCache))
                    {
                        foreach (var voiceStateModel in model.VoiceStates)
                        {
                            if (isPending)
                            {
                                var voiceState = new CachedVoiceState(Client, model.Id, voiceStateModel);
                                voiceStateCache.Add(voiceState.Id, voiceState);
                            }
                            else
                            {
                                var voiceState = voiceStateCache.GetValueOrDefault(voiceStateModel.UserId);
                                voiceState?.Update(voiceStateModel);
                            }
                        }
                    }

                    var logLevel = isPending
                        ? LogLevel.Debug
                        : LogLevel.Information;
                    var message = isPending
                        ? "Pending guild {0} ({1}) is available."
                        : "Guild {0} ({1}) became available.";
                    shard.Logger.Log(logLevel, message, guild.Name, guild.Id.RawValue);

                    //  Invoke the event and possibly invoke ready afterwards.
                    await InvokeEventAsync(new GuildAvailableEventArgs(guild)).ConfigureAwait(false);
                }
                finally
                {
                    if (isPending)
                    {
                        _readyHandler.PopPendingGuild(shard.Id, model.Id);
                    }
                }

                return(null);
            }
            else
            {
                // We joined a new guild.
                if (Client.CacheProvider.TryGetGuilds(out var cache))
                {
                    guild = new CachedGuild(Client, model);
                    cache.Add(model.Id, guild as CachedGuild);
                }
                else
                {
                    guild = new TransientGatewayGuild(Client, model);
                }

                // TODO: optimise member cache retrieval
                if (CacheProvider.TryGetMembers(model.Id, out var memberCache))
                {
                    foreach (var memberModel in model.Members)
                    {
                        Dispatcher.GetOrAddMember(model.Id, memberModel);
                    }
                }

                if (CacheProvider.TryGetChannels(model.Id, out var channelCache))
                {
                    foreach (var channelModel in model.Channels)
                    {
                        var channel = CachedGuildChannel.Create(Client, model.Id, channelModel);
                        channelCache.Add(channel.Id, channel);
                    }
                }

                if (CacheProvider.TryGetRoles(model.Id, out var roleCache))
                {
                    foreach (var roleModel in model.Roles)
                    {
                        var role = new CachedRole(Client, model.Id, roleModel);
                        roleCache.Add(role.Id, role);
                    }
                }

                shard.Logger.LogInformation("Joined guild {0} ({1}).", guild.Name, guild.Id.RawValue);
                return(new JoinedGuildEventArgs(guild));
            }
        }
 public IEnumerable <CachedRole> GetIgnoredRoles(CachedGuild guild)
 {
     return(IgnoredRoles.Select(roleUlong => guild.GetRole(roleUlong)));
 }
 public IEnumerable <CachedTextChannel> GetIgnoredChannels(CachedGuild guild)
 {
     return(IgnoredChannels.Select(channelUlong => guild.GetTextChannel(channelUlong)));
 }
예제 #14
0
 internal VoiceServerUpdatedEventArgs(CachedGuild guild, string token, string endpoint) : base(guild.Client)
 {
     Guild    = guild;
     Token    = token;
     Endpoint = endpoint;
 }
예제 #15
0
        public override async ValueTask <EventArgs> HandleDispatchAsync(IGatewayApiClient shard, UnavailableGuildJsonModel model)
        {
            CachedGuild guild = null;

            if (model.Unavailable.HasValue)
            {
                var isPending = _readyHandler.IsPendingGuild(shard.Id, model.Id);
                try
                {
                    if (CacheProvider.TryGetGuilds(out var cache))
                    {
                        if (isPending)
                        {
                            // TODO: cache the id or such if the guild isn't available
                        }
                        else
                        {
                            guild = cache.GetValueOrDefault(model.Id);
                            guild?.Update(model);
                        }
                    }

                    if (isPending)
                    {
                        shard.Logger.LogInformation("Pending guild {0} is unavailable.", model.Id.RawValue);
                    }
                    else
                    {
                        if (guild != null)
                        {
                            shard.Logger.LogInformation("Guild {0} ({1}) became unavailable.", guild.Name, guild.Id.RawValue);
                        }
                        else
                        {
                            shard.Logger.LogInformation("Uncached guild {0} became unavailable.", model.Id.RawValue);
                        }
                    }

                    //  Invoke the event and possibly invoke ready afterwards.
                    await InvokeEventAsync(new GuildUnavailableEventArgs(model.Id, guild)).ConfigureAwait(false);
                }
                finally
                {
                    if (isPending)
                    {
                        _readyHandler.PopPendingGuild(shard.Id, model.Id);
                    }
                }

                return(null);
            }
            else
            {
                if (Client.CacheProvider.TryGetGuilds(out var cache))
                {
                    cache.TryRemove(model.Id, out guild);
                }

                Client.CacheProvider.TryRemoveCache <CachedGuildChannel>(model.Id, out _);
                Client.CacheProvider.TryRemoveCache <CachedRole>(model.Id, out _);
                Client.CacheProvider.TryRemoveCache <CachedVoiceState>(model.Id, out _);

                if (guild == null)
                {
                    shard.Logger.LogInformation("Left uncached guild {0}.", model.Id.RawValue);
                    return(null);
                }

                shard.Logger.LogInformation("Left guild '{0}' ({1}).", guild.Name, guild.Id.RawValue);
                return(new LeftGuildEventArgs(model.Id, guild));
            }
        }
예제 #16
0
 /// <summary>
 ///     Initializes a new <see cref="LogMessage"/> struct with the severity, source, message of the event, and
 ///     optionally, an exception.
 /// </summary>
 /// <param name="severity">The severity of the event.</param>
 /// <param name="source">The source of the event.</param>
 /// <param name="message">The message of the event.</param>
 /// <param name="exception">The exception of the event.</param>
 public LogMessage(LogSeverity severity, string source, string message, Exception exception = null, CachedGuild guild = null)
 {
     Severity  = severity;
     Source    = source;
     Message   = message;
     Exception = exception;
     Guild     = guild;
 }