示例#1
0
        public static async Task <CreateEntityResult <Appearance> > CreateDefaultAsync
        (
            [NotNull] Character character,
            [NotNull] TransformationService transformations
        )
        {
            var getSpeciesResult = await transformations.GetSpeciesByNameAsync("template");

            if (!getSpeciesResult.IsSuccess)
            {
                return(CreateEntityResult <Appearance> .FromError("Could not find the default species."));
            }

            var templateSpecies         = getSpeciesResult.Entity;
            var templateTransformations = new List <Transformation>();
            var templateParts           = new List <Bodypart> {
                Head, Body, Arms, Legs
            };

            // Explode the composite parts into their components
            templateParts = templateParts.SelectMany(p => p.GetComposingParts()).Distinct().ToList();

            foreach (var part in templateParts)
            {
                var getTFResult = await transformations.GetTransformationsByPartAndSpeciesAsync(part, templateSpecies);

                if (!getTFResult.IsSuccess)
                {
                    // Allow skipping of missing composing parts - a composite part might not have all of them in a TF.
                    if (part.IsComposingPart())
                    {
                        continue;
                    }

                    return(CreateEntityResult <Appearance> .FromError(getTFResult));
                }

                templateTransformations.AddRange(getTFResult.Entity);
            }

            var templateComponents = new List <AppearanceComponent>();

            foreach (var tf in templateTransformations)
            {
                if (tf.Part.IsChiral())
                {
                    templateComponents.AddRange(AppearanceComponent.CreateFromChiral(tf));
                }
                else
                {
                    templateComponents.Add(AppearanceComponent.CreateFrom(tf));
                }
            }

            var appearance = new Appearance(character);

            appearance.Components.AddRange(templateComponents);

            return(CreateEntityResult <Appearance> .FromSuccess(appearance));
        }
示例#2
0
        /// <summary>
        /// Creates a new dossier with the given title, summary, and data.
        /// </summary>
        /// <param name="title">The title of the dossier.</param>
        /// <param name="summary">The summary of the dossier.</param>
        /// <returns>A creation task which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <Dossier> > CreateDossierAsync
        (
            string title,
            string summary
        )
        {
            var dossier        = new Dossier(title, summary);
            var setTitleResult = await SetDossierTitleAsync(dossier, title);

            if (!setTitleResult.IsSuccess)
            {
                return(CreateEntityResult <Dossier> .FromError(setTitleResult));
            }

            var setSummary = await SetDossierSummaryAsync(dossier, summary);

            if (!setSummary.IsSuccess)
            {
                return(CreateEntityResult <Dossier> .FromError(setSummary));
            }

            await _database.Dossiers.AddAsync(dossier);

            await _database.SaveChangesAsync();

            return(CreateEntityResult <Dossier> .FromSuccess((await GetDossierByTitleAsync(title)).Entity));
        }
示例#3
0
        public async Task <CreateEntityResult <CharacterRole> > CreateCharacterRoleAsync
        (
            [NotNull] IRole role,
            RoleAccess access
        )
        {
            var getExistingRoleResult = await GetCharacterRoleAsync(role);

            if (getExistingRoleResult.IsSuccess)
            {
                return(CreateEntityResult <CharacterRole> .FromError
                       (
                           "That role is already registered as a character role."
                       ));
            }

            var getServerResult = await _servers.GetOrRegisterServerAsync(role.Guild);

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

            var server = getServerResult.Entity;

            var characterRole = new CharacterRole(server, (long)role.Id, access);

            _database.CharacterRoles.Update(characterRole);
            await _database.SaveChangesAsync();

            return(CreateEntityResult <CharacterRole> .FromSuccess(characterRole));
        }
示例#4
0
        /// <summary>
        /// Adds a kink to a user's preference list.
        /// </summary>
        /// <param name="discordUser">The user.</param>
        /// <param name="kink">The kink.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <UserKink> > AddUserKinkAsync
        (
            IUser discordUser,
            Kink kink
        )
        {
            var getUserKinksResult = await GetUserKinksAsync(discordUser);

            if (!getUserKinksResult.IsSuccess)
            {
                return(CreateEntityResult <UserKink> .FromError(getUserKinksResult));
            }

            var userKinks = getUserKinksResult.Entity;

            if (userKinks.Any(k => k.Kink.FListID == kink.FListID))
            {
                return(CreateEntityResult <UserKink> .FromError("The user already has a preference for that kink."));
            }

            var getUserResult = await _users.GetOrRegisterUserAsync(discordUser);

            if (!getUserResult.IsSuccess)
            {
                return(CreateEntityResult <UserKink> .FromError(getUserResult));
            }

            var user = getUserResult.Entity;

            var userKink = new UserKink(user, kink);

            _database.UserKinks.Update(userKink);

            await _database.SaveChangesAsync();

            return(CreateEntityResult <UserKink> .FromSuccess(userKink));
        }
        /// <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));
        }
        /// <summary>
        /// Creates a default appearance using the template species (a featureless, agendered species).
        /// </summary>
        /// <param name="db">The database.</param>
        /// <param name="transformations">The transformation service.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public static async Task <CreateEntityResult <Appearance> > CreateDefaultAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] TransformationService transformations
        )
        {
            var getSpeciesResult = await transformations.GetSpeciesByNameAsync(db, "template");

            if (!getSpeciesResult.IsSuccess)
            {
                return(CreateEntityResult <Appearance> .FromError(CommandError.ObjectNotFound, "Could not find the default species."));
            }

            var templateSpecies         = getSpeciesResult.Entity;
            var templateTransformations = new List <Transformation>();
            var templateParts           = new List <Bodypart> {
                Head, Body, Arms, Legs
            };

            // Explode the composite parts into their components
            templateParts = templateParts.SelectMany(p => p.GetComposingParts()).Distinct().ToList();

            foreach (var part in templateParts)
            {
                var getTFResult = await transformations.GetTransformationByPartAndSpeciesAsync(db, part, templateSpecies);

                if (!getTFResult.IsSuccess)
                {
                    // Allow skipping of missing composing parts - a composite part might not have all of them in a TF.
                    if (part.IsComposingPart())
                    {
                        continue;
                    }

                    return(CreateEntityResult <Appearance> .FromError(getTFResult));
                }

                templateTransformations.Add(getTFResult.Entity);
            }

            var templateComponents = new List <AppearanceComponent>();

            foreach (var tf in templateTransformations)
            {
                if (tf.Part.IsChiral())
                {
                    templateComponents.AddRange(AppearanceComponent.CreateFromChiral(tf));
                }
                else
                {
                    templateComponents.Add(AppearanceComponent.CreateFrom(tf));
                }
            }

            var appearance = new Appearance
            {
                Components  = templateComponents,
                Height      = 1.8,
                Weight      = 80,
                GenderScale = 0,
                Muscularity = 0.5
            };

            return(CreateEntityResult <Appearance> .FromSuccess(appearance));
        }
        /// <summary>
        /// Creates a warning for the given user.
        /// </summary>
        /// <param name="authorUser">The author of the warning.</param>
        /// <param name="guildUser">The user.</param>
        /// <param name="reason">The reason of the warning.</param>
        /// <param name="messageID">The message that caused the warning, if any.</param>
        /// <param name="expiresOn">The expiry date for the warning, if any.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <UserWarning> > CreateWarningAsync
        (
            [NotNull] IUser authorUser,
            [NotNull] IGuildUser guildUser,
            [NotNull] string reason,
            [CanBeNull] long?messageID     = null,
            [CanBeNull] DateTime?expiresOn = null
        )
        {
            var getServer = await _servers.GetOrRegisterServerAsync(guildUser.Guild);

            if (!getServer.IsSuccess)
            {
                return(CreateEntityResult <UserWarning> .FromError(getServer));
            }

            var server = getServer.Entity;

            var getUser = await _users.GetOrRegisterUserAsync(guildUser);

            if (!getUser.IsSuccess)
            {
                return(CreateEntityResult <UserWarning> .FromError(getUser));
            }

            var user = getUser.Entity;

            var getAuthor = await _users.GetOrRegisterUserAsync(authorUser);

            if (!getAuthor.IsSuccess)
            {
                return(CreateEntityResult <UserWarning> .FromError(getAuthor));
            }

            var author = getAuthor.Entity;

            var warning = new UserWarning(server, user, author, string.Empty);

            var setReason = await SetWarningReasonAsync(warning, reason);

            if (!setReason.IsSuccess)
            {
                return(CreateEntityResult <UserWarning> .FromError(setReason));
            }

            if (!(messageID is null))
            {
                var setMessage = await SetWarningContextMessageAsync(warning, messageID.Value);

                if (!setMessage.IsSuccess)
                {
                    return(CreateEntityResult <UserWarning> .FromError(setMessage));
                }
            }

            if (!(expiresOn is null))
            {
                var setExpiry = await SetWarningExpiryDateAsync(warning, expiresOn.Value);

                if (!setExpiry.IsSuccess)
                {
                    return(CreateEntityResult <UserWarning> .FromError(setExpiry));
                }
            }

            _database.UserWarnings.Update(warning);

            await _database.SaveChangesAsync();

            // Requery the database
            var getWarning = await GetWarningAsync(guildUser.Guild, warning.ID);

            if (!getWarning.IsSuccess)
            {
                return(CreateEntityResult <UserWarning> .FromError(getWarning));
            }

            return(CreateEntityResult <UserWarning> .FromSuccess(getWarning.Entity));
        }
示例#8
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));
        }
示例#9
0
        public async Task <CreateEntityResult <Character> > CreateCharacterAsync
        (
            [NotNull] ICommandContext context,
            [NotNull] string characterName,
            [NotNull] string characterAvatarUrl,
            [CanBeNull] string characterNickname,
            [CanBeNull] string characterSummary,
            [CanBeNull] string characterDescription
        )
        {
            // Default the nickname to the character name
            characterNickname = characterNickname ?? characterName;

            var getOwnerResult = await _users.GetOrRegisterUserAsync(context.Message.Author);

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

            var owner = getOwnerResult.Entity;

            // Use a dummy name here, because we'll set it using the service afterwards
            var character = new Character((long)context.Guild.Id, owner, string.Empty);

            var modifyEntityResult = await SetCharacterNameAsync(context, character, characterName);

            if (!modifyEntityResult.IsSuccess)
            {
                return(CreateEntityResult <Character> .FromError(modifyEntityResult));
            }

            modifyEntityResult = await SetCharacterAvatarAsync(character, characterAvatarUrl);

            if (!modifyEntityResult.IsSuccess)
            {
                return(CreateEntityResult <Character> .FromError(modifyEntityResult));
            }

            modifyEntityResult = await SetCharacterNicknameAsync(character, characterNickname);

            if (!modifyEntityResult.IsSuccess)
            {
                return(CreateEntityResult <Character> .FromError(modifyEntityResult));
            }

            if (!(characterSummary is null))
            {
                modifyEntityResult = await SetCharacterSummaryAsync(character, characterSummary);

                if (!modifyEntityResult.IsSuccess)
                {
                    return(CreateEntityResult <Character> .FromError(modifyEntityResult));
                }
            }

            if (!(characterDescription is null))
            {
                modifyEntityResult = await SetCharacterDescriptionAsync(character, characterDescription);

                if (!modifyEntityResult.IsSuccess)
                {
                    return(CreateEntityResult <Character> .FromError(modifyEntityResult));
                }
            }

            _database.Characters.Update(character);
            await _database.SaveChangesAsync();

            return(CreateEntityResult <Character> .FromSuccess(character));
        }