Esempio n. 1
0
        /// <summary>
        /// Revokes the given permission from the given Discord role.
        /// </summary>
        /// <param name="discordRole">The Discord role.</param>
        /// <param name="revokedPermission">The revoked permission.</param>
        /// <param name="target">The revoked target.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> RevokePermissionAsync
        (
            IRole discordRole,
            IPermission revokedPermission,
            PermissionTarget target,
            CancellationToken ct = default
        )
        {
            // Special All target handling
            if (target == PermissionTarget.All)
            {
                var revokeSelfResult = await RevokePermissionAsync
                                       (
                    discordRole,
                    revokedPermission,
                    PermissionTarget.Self,
                    ct
                                       );

                var revokeOtherResult = await RevokePermissionAsync
                                        (
                    discordRole,
                    revokedPermission,
                    PermissionTarget.Other,
                    ct
                                        );

                if (revokeSelfResult.IsSuccess || revokeOtherResult.IsSuccess)
                {
                    return(ModifyEntityResult.FromSuccess());
                }

                // Both are false, so we'll just inherit the self result.
                return(ModifyEntityResult.FromError(revokeSelfResult));
            }

            var getPermissionResult = await GetOrCreateRolePermissionAsync
                                      (
                discordRole,
                revokedPermission,
                target,
                ct
                                      );

            if (!getPermissionResult.IsSuccess)
            {
                return(ModifyEntityResult.FromError(getPermissionResult));
            }

            var permission = getPermissionResult.Entity;

            if (!permission.IsGranted)
            {
                return(ModifyEntityResult.FromError("The role is already prohibited from doing that."));
            }

            permission.IsGranted = false;
            await _database.SaveChangesAsync(ct);

            return(ModifyEntityResult.FromSuccess());
        }
Esempio n. 2
0
        /// <summary>
        /// Grants the specified user the given permission.
        /// </summary>
        /// <param name="discordServer">The Discord server the permission was granted on.</param>
        /// <param name="discordUser">The Discord user.</param>
        /// <param name="grantedPermission">The granted permission.</param>
        /// <param name="target">The granted target.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> GrantPermissionAsync
        (
            IGuild discordServer,
            IUser discordUser,
            IPermission grantedPermission,
            PermissionTarget target
        )
        {
            // Special All target handling
            if (target == PermissionTarget.All)
            {
                var grantSelfResult = await GrantPermissionAsync
                                      (
                    discordServer,
                    discordUser,
                    grantedPermission,
                    PermissionTarget.Self
                                      );

                var grantOtherResult = await GrantPermissionAsync
                                       (
                    discordServer,
                    discordUser,
                    grantedPermission,
                    PermissionTarget.Other
                                       );

                if (grantSelfResult.IsSuccess || grantOtherResult.IsSuccess)
                {
                    return(ModifyEntityResult.FromSuccess());
                }

                // Both are false, so we'll just inherit the error from the self grant.
                return(ModifyEntityResult.FromError(grantSelfResult));
            }

            var getPermissionResult = await GetOrCreateUserPermissionAsync
                                      (
                discordServer,
                discordUser,
                grantedPermission,
                target
                                      );

            if (!getPermissionResult.IsSuccess)
            {
                return(ModifyEntityResult.FromError(getPermissionResult));
            }

            var permission = getPermissionResult.Entity;

            if (permission.IsGranted)
            {
                return(ModifyEntityResult.FromError("The user already has permission to do that."));
            }

            permission.IsGranted = true;

            await _database.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess());
        }
Esempio n. 3
0
        /// <summary>
        /// Grants the specified role the given permission.
        /// </summary>
        /// <param name="discordRole">The Discord role.</param>
        /// <param name="grantedPermission">The granted permission.</param>
        /// <param name="target">The granted target.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> GrantPermissionAsync
        (
            IRole discordRole,
            IPermission grantedPermission,
            PermissionTarget target,
            CancellationToken ct = default
        )
        {
            // Special All target handling
            if (target == PermissionTarget.All)
            {
                var grantSelfResult = await GrantPermissionAsync
                                      (
                    discordRole,
                    grantedPermission,
                    PermissionTarget.Self,
                    ct
                                      );

                var grantOtherResult = await GrantPermissionAsync
                                       (
                    discordRole,
                    grantedPermission,
                    PermissionTarget.Other,
                    ct
                                       );

                if (grantSelfResult.IsSuccess || grantOtherResult.IsSuccess)
                {
                    return(ModifyEntityResult.FromSuccess());
                }

                // Both are false, so we'll just inherit the self result.
                return(ModifyEntityResult.FromError(grantSelfResult));
            }

            var getPermissionResult = await GetOrCreateRolePermissionAsync
                                      (
                discordRole,
                grantedPermission,
                target,
                ct
                                      );

            if (!getPermissionResult.IsSuccess)
            {
                return(ModifyEntityResult.FromError(getPermissionResult));
            }

            var permission = getPermissionResult.Entity;

            if (permission.IsGranted)
            {
                return(ModifyEntityResult.FromError("The user already has permission to do that."));
            }

            permission.IsGranted = true;
            await _database.SaveChangesAsync(ct);

            return(ModifyEntityResult.FromSuccess());
        }
Esempio n. 4
0
        /// <summary>
        /// Revokes the given permission from the given Discord user. If the user does not have the permission, no
        /// changes are made.
        /// </summary>
        /// <param name="discordServer">The Discord server the permission was revoked on.</param>
        /// <param name="discordUser">The Discord user.</param>
        /// <param name="revokedPermission">The revoked permission.</param>
        /// <param name="target">The revoked target.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> RevokePermissionAsync
        (
            IGuild discordServer,
            IUser discordUser,
            IPermission revokedPermission,
            PermissionTarget target
        )
        {
            // Special All target handling
            if (target == PermissionTarget.All)
            {
                var revokeSelfResult = await RevokePermissionAsync
                                       (
                    discordServer,
                    discordUser,
                    revokedPermission,
                    PermissionTarget.Self
                                       );

                var revokeOtherResult = await RevokePermissionAsync
                                        (
                    discordServer,
                    discordUser,
                    revokedPermission,
                    PermissionTarget.Other
                                        );

                if (revokeSelfResult.IsSuccess || revokeOtherResult.IsSuccess)
                {
                    return(ModifyEntityResult.FromSuccess());
                }

                // Both are false, so we'll just inherit the self result.
                return(ModifyEntityResult.FromError(revokeSelfResult));
            }

            var getPermissionResult = await GetOrCreateUserPermissionAsync
                                      (
                discordServer,
                discordUser,
                revokedPermission,
                target
                                      );

            if (!getPermissionResult.IsSuccess)
            {
                return(ModifyEntityResult.FromError(getPermissionResult));
            }

            var permission = getPermissionResult.Entity;

            if (!permission.IsGranted)
            {
                return(ModifyEntityResult.FromError("The user is already prohibited from doing that."));
            }

            permission.IsGranted = false;

            await _database.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess());
        }
Esempio n. 5
0
        public async Task <ModifyEntityResult> StartRoleplayAsync(ICommandContext context, Roleplay roleplay)
        {
            var getDedicatedChannelResult = await GetDedicatedRoleplayChannelAsync
                                            (
                context.Guild,
                roleplay
                                            );

            // Identify the channel to start the RP in. Preference is given to the roleplay's dedicated channel.
            ISocketMessageChannel channel;

            if (getDedicatedChannelResult.IsSuccess)
            {
                channel = (ISocketMessageChannel)getDedicatedChannelResult.Entity;
            }
            else
            {
                channel = (ISocketMessageChannel)context.Channel;
            }

            var isNsfwChannel = channel is ITextChannel textChannel && textChannel.IsNsfw;

            if (roleplay.IsNSFW && !isNsfwChannel)
            {
                return(ModifyEntityResult.FromError
                       (
                           "This channel is not marked as NSFW, while your roleplay is... naughty!"
                       ));
            }

            if (await HasActiveRoleplayAsync(channel))
            {
                var currentRoleplayResult = await GetActiveRoleplayAsync(channel);

                if (!currentRoleplayResult.IsSuccess)
                {
                    return(ModifyEntityResult.FromError(currentRoleplayResult));
                }

                var currentRoleplay   = currentRoleplayResult.Entity;
                var timeOfLastMessage = currentRoleplay.Messages.Last().Timestamp;
                var currentTime       = DateTimeOffset.Now;

                if (timeOfLastMessage < currentTime.AddHours(-4))
                {
                    currentRoleplay.IsActive = false;
                }
                else
                {
                    return(ModifyEntityResult.FromError("There's already a roleplay active in this channel."));
                }
            }

            if (roleplay.ActiveChannelID != (long)channel.Id)
            {
                roleplay.ActiveChannelID = (long)channel.Id;
            }

            roleplay.IsActive    = true;
            roleplay.LastUpdated = DateTime.Now;

            await _database.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess());
        }
Esempio n. 6
0
        /// <summary>
        /// Updates the roles of the given user, removing old roles and applying new ones.
        /// </summary>
        /// <param name="guildUser">The user.</param>
        /// <param name="previousCharacter">The character they previously were.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> UpdateUserRolesAsync
        (
            IGuildUser guildUser,
            Character?previousCharacter = null,
            CancellationToken ct        = default
        )
        {
            var getUser = await _users.GetOrRegisterUserAsync(guildUser, ct);

            if (!getUser.IsSuccess)
            {
                return(ModifyEntityResult.FromError(getUser));
            }

            var getServer = await _servers.GetOrRegisterServerAsync(guildUser.Guild, ct);

            if (!getServer.IsSuccess)
            {
                return(ModifyEntityResult.FromError(getServer));
            }

            var user   = getUser.Entity;
            var server = getServer.Entity;

            var getNewCharacter = await _characters.GetCurrentCharacterAsync(user, server, ct);

            if (!getNewCharacter.IsSuccess)
            {
                // Clear any old role
                if (previousCharacter?.Role is null)
                {
                    return(ModifyEntityResult.FromSuccess());
                }

                var oldRole = guildUser.Guild.GetRole((ulong)previousCharacter.Role.DiscordID);
                if (oldRole is null)
                {
                    return(ModifyEntityResult.FromSuccess());
                }

                var removeRole = await _discord.RemoveUserRoleAsync(guildUser, oldRole);

                if (!removeRole.IsSuccess)
                {
                    return(removeRole);
                }

                return(ModifyEntityResult.FromSuccess());
            }

            var newCharacter = getNewCharacter.Entity;

            // First, quick sanity check - do we need to remove the role?
            if (!(previousCharacter?.Role is null) && newCharacter.Role == previousCharacter.Role)
            {
                return(ModifyEntityResult.FromSuccess());
            }

            // Clear any old role
            if (!(previousCharacter?.Role is null))
            {
                var oldRole = guildUser.Guild.GetRole((ulong)previousCharacter.Role.DiscordID);
                if (!(oldRole is null))
                {
                    var removeRole = await _discord.RemoveUserRoleAsync(guildUser, oldRole);

                    if (!removeRole.IsSuccess)
                    {
                        return(removeRole);
                    }
                }
            }

            if (newCharacter.Role is null)
            {
                return(ModifyEntityResult.FromSuccess());
            }

            // Apply any new role
            var newRole = guildUser.Guild.GetRole((ulong)newCharacter.Role.DiscordID);

            if (newRole is null)
            {
                return(ModifyEntityResult.FromSuccess());
            }

            var addRole = await _discord.AddUserRoleAsync(guildUser, newRole);

            if (!addRole.IsSuccess)
            {
                return(addRole);
            }

            return(ModifyEntityResult.FromSuccess());
        }
        /// <summary>
        /// Starts the given roleplay in the current channel, or the dedicated channel if one exists.
        /// </summary>
        /// <param name="currentChannel">The current channel.</param>
        /// <param name="roleplay">The roleplay.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> StartRoleplayAsync(ITextChannel currentChannel, Roleplay roleplay)
        {
            var guild = currentChannel.Guild;

            var getDedicatedChannelResult = await _dedicatedChannels.GetDedicatedChannelAsync
                                            (
                guild,
                roleplay
                                            );

            // Identify the channel to start the RP in. Preference is given to the roleplay's dedicated channel.
            var channel = getDedicatedChannelResult.IsSuccess ? getDedicatedChannelResult.Entity : currentChannel;

            if (roleplay.IsNSFW && !channel.IsNsfw)
            {
                return(ModifyEntityResult.FromError
                       (
                           "This channel is not marked as NSFW, while your roleplay is... naughty!"
                       ));
            }

            if (await HasActiveRoleplayAsync(channel))
            {
                var currentRoleplayResult = await GetActiveRoleplayAsync(channel);

                if (!currentRoleplayResult.IsSuccess)
                {
                    return(ModifyEntityResult.FromError(currentRoleplayResult));
                }

                var currentRoleplay   = currentRoleplayResult.Entity;
                var timeOfLastMessage = currentRoleplay.Messages.Last().Timestamp;
                var currentTime       = DateTimeOffset.Now;

                if (timeOfLastMessage < currentTime.AddHours(-4))
                {
                    currentRoleplay.IsActive = false;
                }
                else
                {
                    return(ModifyEntityResult.FromError("There's already a roleplay active in this channel."));
                }
            }

            var start = await _roleplays.StartRoleplayAsync(roleplay, (long)channel.Id);

            if (!start.IsSuccess)
            {
                return(start);
            }

            // If the channel in question is the roleplay's dedicated channel, enable it
            if (!roleplay.DedicatedChannelID.HasValue)
            {
                return(ModifyEntityResult.FromSuccess());
            }

            var enableChannel = await _dedicatedChannels.UpdateParticipantPermissionsAsync(guild, roleplay);

            if (!enableChannel.IsSuccess)
            {
                return(enableChannel);
            }

            return(ModifyEntityResult.FromSuccess());
        }
        public async Task <ModifyEntityResult> SetDossierDataAsync
        (
            [NotNull] Dossier dossier,
            [NotNull] ICommandContext context
        )
        {
            if (context.Message.Attachments.Count <= 0)
            {
                return(ModifyEntityResult.FromError("No file provided. Please attach a PDF with the dossier data."));
            }

            var dossierAttachment = context.Message.Attachments.First();

            if (!dossierAttachment.Filename.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase))
            {
                return(ModifyEntityResult.FromError("Invalid dossier format. PDF files are accepted."));
            }

            using (var client = new HttpClient())
            {
                client.Timeout = TimeSpan.FromSeconds(2);

                try
                {
                    var dossierPath = GetDossierDataPath(dossier);
                    using (var dataStream = await client.GetStreamAsync(dossierAttachment.Url))
                    {
                        try
                        {
                            using (var dataFile = _content.FileSystem.CreateFile(dossierPath))
                            {
                                await dataStream.CopyToAsync(dataFile);

                                if (!await dataFile.HasSignatureAsync(FileSignatures.PDF))
                                {
                                    return(ModifyEntityResult.FromError
                                           (
                                               "Invalid dossier format. PDF files are accepted."
                                           ));
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            return(ModifyEntityResult.FromError(e));
                        }

                        await _database.SaveChangesAsync();
                    }
                }
                catch (TaskCanceledException)
                {
                    return(ModifyEntityResult.FromError
                           (
                               "The download operation timed out. The data file was not added."
                           ));
                }
            }

            return(ModifyEntityResult.FromSuccess());
        }