/// <summary>
    /// Gets or creates a set of server-specific roleplaying settings for the given server.
    /// </summary>
    /// <param name="serverID">The ID of the server.</param>
    /// <returns>A retrieval result which may or may not have succeeded.</returns>
    public async Task <Result <ServerRoleplaySettings> > GetOrCreateServerRoleplaySettingsAsync(Snowflake serverID)
    {
        var getServer = await _servers.GetOrRegisterServerAsync(serverID);

        if (!getServer.IsSuccess)
        {
            return(Result <ServerRoleplaySettings> .FromError(getServer));
        }

        var server = getServer.Entity;

        var settings = await _database.ServerSettings.ServersideQueryAsync
                       (
            q => q
            .Where(s => s.Server == server)
            .SingleOrDefaultAsync()
                       );

        if (settings is not null)
        {
            return(settings);
        }

        var newSettings = _database.CreateProxy <ServerRoleplaySettings>(server);

        _database.ServerSettings.Update(newSettings);

        await _database.SaveChangesAsync();

        return(newSettings);
    }
Пример #2
0
        /// <summary>
        /// Gets or creates a set of server-specific roleplaying settings for the given server.
        /// </summary>
        /// <param name="server">The server.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <ServerRoleplaySettings> > GetOrCreateServerRoleplaySettingsAsync
        (
            Server server
        )
        {
            var settings = await _database.ServerSettings.ServersideQueryAsync
                           (
                q => q
                .Where(s => s.Server == server)
                .SingleOrDefaultAsync()
                           );

            if (!(settings is null))
            {
                return(settings);
            }

            var newSettings = _database.CreateProxy <ServerRoleplaySettings>(server);

            _database.ServerSettings.Update(newSettings);

            await _database.SaveChangesAsync();

            return(newSettings);
        }
Пример #3
0
        /// <summary>
        /// Gets or creates a set of server-specific roleplaying settings for the given server.
        /// </summary>
        /// <param name="server">The server.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <ServerRoleplaySettings> > GetOrCreateServerRoleplaySettingsAsync
        (
            Server server
        )
        {
            var existingSettings = await _database.ServerSettings.AsQueryable().FirstOrDefaultAsync
                                   (
                s => s.Server == server
                                   );

            if (!(existingSettings is null))
            {
                return(RetrieveEntityResult <ServerRoleplaySettings> .FromSuccess(existingSettings));
            }

            var newSettings = _database.CreateProxy <ServerRoleplaySettings>(server);

            _database.ServerSettings.Update(newSettings);
            await _database.SaveChangesAsync();

            return(newSettings);
        }
Пример #4
0
    /// <summary>
    /// Creates a roleplay with the given parameters.
    /// </summary>
    /// <param name="owner">The user that owns the roleplay.</param>
    /// <param name="server">The server that the roleplay is associated with.</param>
    /// <param name="roleplayName">The name of the roleplay.</param>
    /// <param name="roleplaySummary">The summary of the roleplay.</param>
    /// <param name="isNSFW">Whether or not the roleplay is NSFW.</param>
    /// <param name="isPublic">Whether or not the roleplay is public.</param>
    /// <param name="ct">The cancellation token in use.</param>
    /// <returns>A creation result which may or may not have been successful.</returns>
    public async Task <Result <Roleplay> > CreateRoleplayAsync
    (
        User owner,
        Server server,
        string roleplayName,
        string roleplaySummary,
        bool isNSFW,
        bool isPublic,
        CancellationToken ct = default
    )
    {
        owner  = _database.NormalizeReference(owner);
        server = _database.NormalizeReference(server);

        // Use a dummy name, since we'll be setting it using the service.
        var roleplay = _database.CreateProxy <Roleplay>(server, owner, string.Empty, string.Empty);

        _database.Roleplays.Update(roleplay);

        var ownerParticipant = _database.CreateProxy <RoleplayParticipant>(roleplay, owner);

        _database.Update(ownerParticipant);

        ownerParticipant.Status = ParticipantStatus.Joined;
        roleplay.ParticipatingUsers.Add(ownerParticipant);

        var setNameResult = await SetRoleplayNameAsync(roleplay, roleplayName, ct);

        if (!setNameResult.IsSuccess)
        {
            return(Result <Roleplay> .FromError(setNameResult));
        }

        var setSummaryResult = await SetRoleplaySummaryAsync(roleplay, roleplaySummary, ct);

        if (!setSummaryResult.IsSuccess)
        {
            return(Result <Roleplay> .FromError(setSummaryResult));
        }

        roleplay.IsNSFW   = isNSFW;
        roleplay.IsPublic = isPublic;

        await _database.SaveChangesAsync(ct);

        return(roleplay);
    }
Пример #5
0
        public async Task <CreateEntityResult <Roleplay> > CreateRoleplayAsync
        (
            [NotNull] ICommandContext context,
            [NotNull] string roleplayName,
            [NotNull] string roleplaySummary,
            bool isNSFW,
            bool isPublic
        )
        {
            var getOwnerResult = await _users.GetOrRegisterUserAsync(context.User);

            if (!getOwnerResult.IsSuccess)
            {
                return(CreateEntityResult <Roleplay> .FromError(getOwnerResult));
            }

            // Ensure the user is attached, so we don't create any conflicts.
            var owner = getOwnerResult.Entity;

            _database.Attach(owner);

            // Use a dummy name, since we'll be setting it useng the service.
            var roleplay = new Roleplay((long)context.Guild.Id, owner, string.Empty);

            var ownerParticipant = new RoleplayParticipant(roleplay, owner)
            {
                Status = ParticipantStatus.Joined
            };

            roleplay.ParticipatingUsers.Add(ownerParticipant);

            var setNameResult = await SetRoleplayNameAsync(context, roleplay, roleplayName);

            if (!setNameResult.IsSuccess)
            {
                return(CreateEntityResult <Roleplay> .FromError(setNameResult));
            }

            var setSummaryResult = await SetRoleplaySummaryAsync(roleplay, roleplaySummary);

            if (!setSummaryResult.IsSuccess)
            {
                return(CreateEntityResult <Roleplay> .FromError(setSummaryResult));
            }

            var setIsNSFWResult = await SetRoleplayIsNSFWAsync(roleplay, isNSFW);

            if (!setIsNSFWResult.IsSuccess)
            {
                return(CreateEntityResult <Roleplay> .FromError(setIsNSFWResult));
            }

            var setIsPublicResult = await SetRoleplayIsPublicAsync(roleplay, isPublic);

            if (!setIsPublicResult.IsSuccess)
            {
                return(CreateEntityResult <Roleplay> .FromError(setIsPublicResult));
            }

            _database.Roleplays.Update(roleplay);

            await _database.SaveChangesAsync();

            var roleplayResult = await GetUserRoleplayByNameAsync(context, context.Message.Author, roleplayName);

            if (!roleplayResult.IsSuccess)
            {
                return(CreateEntityResult <Roleplay> .FromError(roleplayResult));
            }

            return(CreateEntityResult <Roleplay> .FromSuccess(roleplayResult.Entity));
        }
        /// <summary>
        /// Creates a dedicated channel for the roleplay.
        /// </summary>
        /// <param name="guild">The guild in which the request was made.</param>
        /// <param name="roleplay">The roleplay to create the channel for.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <ITextChannel> > CreateDedicatedChannelAsync
        (
            IGuild guild,
            Roleplay roleplay
        )
        {
            var getServerResult = await _servers.GetOrRegisterServerAsync(guild);

            if (!getServerResult.IsSuccess)
            {
                return(CreateEntityResult <ITextChannel> .FromError(getServerResult));
            }

            var server = getServerResult.Entity;

            if (!(await guild.GetUserAsync(_client.CurrentUser.Id)).GuildPermissions.ManageChannels)
            {
                return(CreateEntityResult <ITextChannel> .FromError
                       (
                           "I don't have permission to manage channels, so I can't create dedicated RP channels."
                       ));
            }

            var getExistingChannelResult = await GetDedicatedChannelAsync(guild, roleplay);

            if (getExistingChannelResult.IsSuccess)
            {
                return(CreateEntityResult <ITextChannel> .FromError
                       (
                           "The roleplay already has a dedicated channel."
                       ));
            }

            var getSettingsResult = await _serverSettings.GetOrCreateServerRoleplaySettingsAsync(server);

            if (!getSettingsResult.IsSuccess)
            {
                return(CreateEntityResult <ITextChannel> .FromError(getSettingsResult));
            }

            var settings = getSettingsResult.Entity;

            if (!(settings.DedicatedRoleplayChannelsCategory is null))
            {
                var categoryChannelCount = (await guild.GetTextChannelsAsync())
                                           .Count(c => c.CategoryId == (ulong)settings.DedicatedRoleplayChannelsCategory);

                if (categoryChannelCount >= 50)
                {
                    return(CreateEntityResult <ITextChannel> .FromError
                           (
                               "The server's roleplaying category has reached its maximum number of channels. Try " +
                               "contacting the server's owners and either removing some old roleplays or setting up " +
                               "a new category."
                           ));
                }
            }

            Optional <ulong?> categoryId;

            if (settings.DedicatedRoleplayChannelsCategory is null)
            {
                categoryId = null;
            }
            else
            {
                categoryId = (ulong?)settings.DedicatedRoleplayChannelsCategory;
            }

            var dedicatedChannel = await guild.CreateTextChannelAsync
                                   (
                $"{roleplay.Name}-rp",
                properties =>
            {
                properties.CategoryId = categoryId;
                properties.IsNsfw     = roleplay.IsNSFW;
                properties.Topic      = $"Dedicated roleplay channel for {roleplay.Name}. {roleplay.Summary}";
            }
                                   );

            roleplay.DedicatedChannelID = (long)dedicatedChannel.Id;

            var resetPermissions = await ResetChannelPermissionsAsync(dedicatedChannel, roleplay);

            if (!resetPermissions.IsSuccess)
            {
                return(CreateEntityResult <ITextChannel> .FromError(resetPermissions));
            }

            await _database.SaveChangesAsync();

            return(CreateEntityResult <ITextChannel> .FromSuccess(dedicatedChannel));
        }
Пример #7
0
        /// <summary>
        /// Creates a dedicated channel for the roleplay.
        /// </summary>
        /// <param name="guild">The guild in which the request was made.</param>
        /// <param name="roleplay">The roleplay to create the channel for.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <ITextChannel> > CreateDedicatedChannelAsync
        (
            IGuild guild,
            Roleplay roleplay
        )
        {
            var getServerResult = await _servers.GetOrRegisterServerAsync(guild);

            if (!getServerResult.IsSuccess)
            {
                return(CreateEntityResult <ITextChannel> .FromError(getServerResult));
            }

            var server = getServerResult.Entity;

            if (!(await guild.GetUserAsync(_client.CurrentUser.Id)).GuildPermissions.ManageChannels)
            {
                return(CreateEntityResult <ITextChannel> .FromError
                       (
                           "I don't have permission to manage channels, so I can't create dedicated RP channels."
                       ));
            }

            var getExistingChannelResult = await GetDedicatedChannelAsync(guild, roleplay);

            if (getExistingChannelResult.IsSuccess)
            {
                return(CreateEntityResult <ITextChannel> .FromError
                       (
                           "The roleplay already has a dedicated channel."
                       ));
            }

            var getSettingsResult = await _serverSettings.GetOrCreateServerRoleplaySettingsAsync(server);

            if (!getSettingsResult.IsSuccess)
            {
                return(CreateEntityResult <ITextChannel> .FromError(getSettingsResult));
            }

            var settings = getSettingsResult.Entity;

            if (settings.DedicatedRoleplayChannelsCategory is null)
            {
                return(CreateEntityResult <ITextChannel> .FromError
                       (
                           "No dedicated channel category has been configured."
                       ));
            }

            var categoryChannelCount = (await guild.GetTextChannelsAsync())
                                       .Count(c => c.CategoryId == (ulong)settings.DedicatedRoleplayChannelsCategory);

            if (categoryChannelCount >= 50)
            {
                return(CreateEntityResult <ITextChannel> .FromError
                       (
                           "The server's roleplaying category has reached its maximum number of channels. Try " +
                           "contacting the server's owners and either removing some old roleplays or setting up " +
                           "a new category."
                       ));
            }

            Optional <ulong?> categoryId = (ulong?)settings.DedicatedRoleplayChannelsCategory;

            var dedicatedChannel = await guild.CreateTextChannelAsync
                                   (
                $"{roleplay.Name}-rp",
                properties =>
            {
                properties.CategoryId = categoryId;
                properties.IsNsfw     = roleplay.IsNSFW;
                properties.Topic      = $"Dedicated roleplay channel for {roleplay.Name}. {roleplay.Summary}";
            }
                                   );

            roleplay.DedicatedChannelID = (long)dedicatedChannel.Id;

            // This can fail in all manner of ways because of Discord.NET. Try, catch, etc...
            try
            {
                var resetPermissions = await ResetChannelPermissionsAsync(dedicatedChannel, roleplay);

                if (!resetPermissions.IsSuccess)
                {
                    return(CreateEntityResult <ITextChannel> .FromError(resetPermissions));
                }
            }
            catch (HttpException hex) when(hex.HttpCode == HttpStatusCode.Forbidden)
            {
                return(CreateEntityResult <ITextChannel> .FromError
                       (
                           "Failed to update channel permissions. Does the bot have permissions to manage permissions on " +
                           "new channels?"
                       ));
            }
            catch (Exception ex)
            {
                await dedicatedChannel.DeleteAsync();

                return(CreateEntityResult <ITextChannel> .FromError(ex));
            }

            await _database.SaveChangesAsync();

            return(CreateEntityResult <ITextChannel> .FromSuccess(dedicatedChannel));
        }