/// <summary>
        /// Sets the nickname of the given character.
        /// </summary>
        /// <param name="db">The database containing the characters.</param>
        /// <param name="character">The character to set the nickname of.</param>
        /// <param name="newCharacterNickname">The new nickname.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> SetCharacterNicknameAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] Character character,
            [NotNull] string newCharacterNickname
        )
        {
            if (string.IsNullOrWhiteSpace(newCharacterNickname))
            {
                return(ModifyEntityResult.FromError(CommandError.BadArgCount, "You need to provide a new nickname."));
            }

            if (character.Nickname == newCharacterNickname)
            {
                return(ModifyEntityResult.FromError(CommandError.Unsuccessful, "The character already has that nickname."));
            }

            if (newCharacterNickname.Length > 32)
            {
                return(ModifyEntityResult.FromError(CommandError.Unsuccessful, "The summary is too long. Nicknames can be at most 32 characters."));
            }

            character.Nickname = newCharacterNickname;
            await db.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess(ModifyEntityAction.Edited));
        }
        /// <summary>
        /// Sets the summary of the given character.
        /// </summary>
        /// <param name="db">The database containing the characters.</param>
        /// <param name="character">The character to set the summary of.</param>
        /// <param name="newCharacterSummary">The new summary.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> SetCharacterSummaryAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] Character character,
            [NotNull] string newCharacterSummary
        )
        {
            if (string.IsNullOrWhiteSpace(newCharacterSummary))
            {
                return(ModifyEntityResult.FromError(CommandError.BadArgCount, "You need to provide a new summary."));
            }

            if (character.Summary == newCharacterSummary)
            {
                return(ModifyEntityResult.FromError(CommandError.Unsuccessful, "That's already the character's summary."));
            }

            if (newCharacterSummary.Length > 240)
            {
                return(ModifyEntityResult.FromError(CommandError.Unsuccessful, "The summary is too long. It can be at most 240 characters."));
            }

            character.Summary = newCharacterSummary;
            await db.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess(ModifyEntityAction.Edited));
        }
        public async Task <RetrieveEntityResult <Character> > GetUserCharacterByNameAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] ICommandContext context,
            [NotNull] IUser characterOwner,
            [NotNull] string characterName
        )
        {
            var character = await GetUserCharacters(db, characterOwner, context.Guild)
                            .FirstOrDefaultAsync
                            (
                ch => string.Equals(ch.Name, characterName, StringComparison.OrdinalIgnoreCase)
                            );

            if (character is null)
            {
                var isCurrentUser = context.Message.Author.Id == characterOwner.Id;
                var errorMessage  = isCurrentUser
                                        ? "You don't own a character with that name."
                                        : "The user doesn't own a character with that name.";

                return(RetrieveEntityResult <Character> .FromError(CommandError.ObjectNotFound, errorMessage));
            }

            return(RetrieveEntityResult <Character> .FromSuccess(character));
        }
        /// <summary>
        /// Sets the default character of a user.
        /// </summary>
        /// <param name="db">The database containing the characters.</param>
        /// <param name="context">The context of the operation.</param>
        /// <param name="newDefaultCharacter">The new default character.</param>
        /// <param name="targetUser">The user to set the default character of.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> SetDefaultCharacterForUserAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] ICommandContext context,
            [NotNull] Character newDefaultCharacter,
            [NotNull] User targetUser
        )
        {
            var isCurrentUser   = context.Message.Author.Id == (ulong)newDefaultCharacter.Owner.DiscordID;
            var isSameCharacter = targetUser.DefaultCharacter?.Name == newDefaultCharacter.Name;

            if (isSameCharacter)
            {
                var errorMessage = isCurrentUser
                                        ? "That's already your default character."
                                        : "That's already the user's default character.";

                return(ModifyEntityResult.FromError(CommandError.UnmetPrecondition, errorMessage));
            }

            targetUser.DefaultCharacter = newDefaultCharacter;
            await db.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess(ModifyEntityAction.Edited));
        }
        public async Task <RetrieveEntityResult <Character> > GetNamedCharacterAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] string characterName,
            [NotNull] IGuild guild
        )
        {
            var guildCharacters = db.Characters.Where(ch => ch.ServerID == (long)guild.Id);

            if (await guildCharacters.CountAsync(ch => string.Equals(ch.Name, characterName, StringComparison.OrdinalIgnoreCase)) > 1)
            {
                return(RetrieveEntityResult <Character> .FromError
                       (
                           CommandError.MultipleMatches,
                           "There's more than one character with that name. Please specify which user it belongs to."
                       ));
            }

            var character = GetCharacters(db, guild).FirstOrDefault(ch => string.Equals(ch.Name, characterName, StringComparison.OrdinalIgnoreCase));

            if (character is null)
            {
                return(RetrieveEntityResult <Character> .FromError(CommandError.ObjectNotFound, "No character with that name found."));
            }

            return(RetrieveEntityResult <Character> .FromSuccess(character));
        }
        public async Task <RetrieveEntityResult <Character> > GetCurrentCharacterAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] ICommandContext context,
            [NotNull] IUser discordUser
        )
        {
            if (!await HasActiveCharacterOnServerAsync(db, discordUser, context.Guild))
            {
                var isCurrentUser = context.Message.Author.Id == discordUser.Id;
                var errorMessage  = isCurrentUser
                                        ? "You haven't assumed a character."
                                        : "The user hasn't assumed a character.";

                return(RetrieveEntityResult <Character> .FromError(CommandError.ObjectNotFound, errorMessage));
            }

            var currentCharacter = await GetUserCharacters(db, discordUser, context.Guild)
                                   .FirstOrDefaultAsync
                                   (
                ch => ch.IsCurrent
                                   );

            if (currentCharacter is null)
            {
                return(RetrieveEntityResult <Character> .FromError(CommandError.Unsuccessful, "Failed to retrieve a current character."));
            }

            return(RetrieveEntityResult <Character> .FromSuccess(currentCharacter));
        }
        public async Task <RetrieveEntityResult <Character> > GetBestMatchingCharacterAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] ICommandContext context,
            [CanBeNull] IUser characterOwner,
            [CanBeNull] string characterName
        )
        {
            if (characterOwner is null && characterName is null)
            {
                return(await GetCurrentCharacterAsync(db, context, context.Message.Author));
            }

            if (characterOwner is null)
            {
                return(await GetNamedCharacterAsync(db, characterName, context.Guild));
            }

            if (characterName.IsNullOrWhitespace())
            {
                return(await GetCurrentCharacterAsync(db, context, characterOwner));
            }

            return(await GetUserCharacterByNameAsync(db, context, characterOwner, characterName));
        }
        /// <summary>
        /// Sets the preferred pronoun for the given character.
        /// </summary>
        /// <param name="db">The database.</param>
        /// <param name="character">The character.</param>
        /// <param name="pronounFamily">The pronoun family.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> SetCharacterPronounAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] Character character,
            [NotNull] string pronounFamily
        )
        {
            if (pronounFamily.IsNullOrWhitespace())
            {
                return(ModifyEntityResult.FromError(CommandError.BadArgCount, "You need to provide a pronoun family."));
            }

            if (!this.PronounProviders.ContainsKey(pronounFamily))
            {
                return(ModifyEntityResult.FromError(CommandError.ObjectNotFound, "Could not find a pronoun provider for that family."));
            }

            if (character.PronounProviderFamily == pronounFamily)
            {
                return(ModifyEntityResult.FromError(CommandError.Unsuccessful, "The character is already using that pronoun set."));
            }

            var pronounProvider = this.PronounProviders[pronounFamily];

            character.PronounProviderFamily = pronounProvider.Family;

            await db.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess(ModifyEntityAction.Edited));
        }
예제 #9
0
        /// <summary>
        /// Removes the given character's bodypart.
        /// </summary>
        /// <param name="db">The database where characters and transformations are stored.</param>
        /// <param name="context">The context of the command.</param>
        /// <param name="character">The character to shift.</param>
        /// <param name="bodyPart">The bodypart to remove.</param>
        /// <param name="chirality">The chirality of the bodypart.</param>
        /// <returns>A shifting result which may or may not have succeeded.</returns>
        public async Task <ShiftBodypartResult> RemoveBodypartAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] ICommandContext context,
            [NotNull] Character character,
            Bodypart bodyPart,
            Chirality chirality = Chirality.Center
        )
        {
            var discordUser = await context.Guild.GetUserAsync((ulong)character.Owner.DiscordID);

            var canTransformResult = await CanUserTransformUserAsync(db, context.Guild, context.User, discordUser);

            if (!canTransformResult.IsSuccess)
            {
                return(ShiftBodypartResult.FromError(canTransformResult));
            }

            if (!character.TryGetAppearanceComponent(bodyPart, chirality, out var component))
            {
                return(ShiftBodypartResult.FromError(CommandError.ObjectNotFound, "The character doesn't have that bodypart."));
            }

            character.CurrentAppearance.Components.Remove(component);
            await db.SaveChangesAsync();

            string removeMessage = this.DescriptionBuilder.BuildRemoveMessage(character, component);

            return(ShiftBodypartResult.FromSuccess(removeMessage));
        }
        /// <summary>
        /// Updates the location of the dossier data, matching it to the dossier's name.
        /// </summary>
        /// <param name="db">The database containing the dossier metadata.</param>
        /// <param name="dossier">The dossier to update.</param>
        /// <returns>An entity modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> UpdateDossierDataLocationAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] Dossier dossier
        )
        {
            var originalDossierPath = dossier.Path;
            var newDossierPath      = Path.GetFullPath(Path.Combine(this.Content.BaseDossierPath, $"{dossier.Title}.pdf"));

            if (Directory.GetParent(newDossierPath).FullName != this.Content.BaseDossierPath)
            {
                return(ModifyEntityResult.FromError(CommandError.Exception, "Invalid data path."));
            }

            if (originalDossierPath.IsNullOrWhitespace() || !File.Exists(originalDossierPath) || originalDossierPath == newDossierPath)
            {
                return(ModifyEntityResult.FromSuccess(ModifyEntityAction.Edited));
            }

            try
            {
                File.Move(originalDossierPath, newDossierPath);
            }
            catch (Exception e)
            {
                return(ModifyEntityResult.FromError(CommandError.Exception, e.Message));
            }

            dossier.Path = newDossierPath;
            await db.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess(ModifyEntityAction.Edited));
        }
예제 #11
0
        public async Task <RetrieveEntityResult <Roleplay> > GetBestMatchingRoleplayAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] ICommandContext context,
            [CanBeNull] IUser roleplayOwner,
            [CanBeNull] string roleplayName
        )
        {
            if (roleplayOwner is null && roleplayName is null)
            {
                return(await GetActiveRoleplayAsync(db, context));
            }

            if (roleplayOwner is null)
            {
                return(await GetNamedRoleplayAsync(db, roleplayName, context.Guild));
            }

            if (roleplayName.IsNullOrWhitespace())
            {
                return(await GetActiveRoleplayAsync(db, context));
            }

            return(await GetUserRoleplayByNameAsync(db, context, roleplayOwner, roleplayName));
        }
예제 #12
0
        public async Task <RetrieveEntityResult <Roleplay> > GetUserRoleplayByNameAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] ICommandContext context,
            [NotNull] IUser roleplayOwner,
            [NotNull] string roleplayName
        )
        {
            var roleplay = await GetRoleplays(db, context.Guild)
                           .FirstOrDefaultAsync
                           (
                rp =>
                rp.Name.Equals(roleplayName, StringComparison.OrdinalIgnoreCase) &&
                rp.Owner.DiscordID == (long)roleplayOwner.Id
                           );

            if (roleplay is null)
            {
                var isCurrentUser = context.Message.Author.Id == roleplayOwner.Id;
                var errorMessage  = isCurrentUser
                                        ? "You don't own a roleplay with that name."
                                        : "The user doesn't own a roleplay with that name.";

                return(RetrieveEntityResult <Roleplay> .FromError(CommandError.ObjectNotFound, errorMessage));
            }

            return(RetrieveEntityResult <Roleplay> .FromSuccess(roleplay));
        }
예제 #13
0
        public async Task <RetrieveEntityResult <Roleplay> > GetNamedRoleplayAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] string roleplayName,
            [NotNull] IGuild guild
        )
        {
            if (await db.Roleplays.CountAsync(rp => string.Equals(rp.Name, roleplayName, StringComparison.OrdinalIgnoreCase)) > 1)
            {
                return(RetrieveEntityResult <Roleplay> .FromError
                       (
                           CommandError.MultipleMatches,
                           "There's more than one roleplay with that name. Please specify which user it belongs to."
                       ));
            }

            var roleplay = GetRoleplays(db, guild)
                           .FirstOrDefault(rp => string.Equals(rp.Name, roleplayName, StringComparison.OrdinalIgnoreCase));

            if (roleplay is null)
            {
                return(RetrieveEntityResult <Roleplay> .FromError(CommandError.ObjectNotFound, "No roleplay with that name found."));
            }

            return(RetrieveEntityResult <Roleplay> .FromSuccess(roleplay));
        }
예제 #14
0
        /// <summary>
        /// Sets the user's preference for the given kink.
        /// </summary>
        /// <param name="db">The database.</param>
        /// <param name="userKink">The user's kink.</param>
        /// <param name="preference">The new preference.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> SetKinkPreferenceAsync([NotNull] GlobalInfoContext db, [NotNull] UserKink userKink, KinkPreference preference)
        {
            userKink.Preference = preference;
            await db.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess(ModifyEntityAction.Edited));
        }
        /// <summary>
        /// Adds the given image with the given metadata to the given character.
        /// </summary>
        /// <param name="db">The database where the characters and images are stored.</param>
        /// <param name="character">The character to add the image to.</param>
        /// <param name="imageName">The name of the image.</param>
        /// <param name="imageUrl">The url of the image.</param>
        /// <param name="imageCaption">The caption of the image.</param>
        /// <param name="isNSFW">Whether or not the image is NSFW</param>
        /// <returns>An execution result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> AddImageToCharacterAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] Character character,
            [NotNull] string imageName,
            [NotNull] string imageUrl,
            [CanBeNull] string imageCaption = null,
            bool isNSFW = false
        )
        {
            bool isImageNameUnique = !character.Images.Any(i => string.Equals(i.Name, imageName, StringComparison.OrdinalIgnoreCase));

            if (!isImageNameUnique)
            {
                return(ModifyEntityResult.FromError(CommandError.MultipleMatches, "The character already has an image with that name."));
            }

            var image = new Image
            {
                Name    = imageName,
                Caption = imageCaption,
                Url     = imageUrl,
                IsNSFW  = isNSFW
            };

            character.Images.Add(image);
            await db.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess(ModifyEntityAction.Added));
        }
        /// <summary>
        /// Creates a new dossier with the given title, summary, and data.
        /// </summary>
        /// <param name="db">The database where the dossier should be stored.</param>
        /// <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
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] string title,
            [NotNull] string summary
        )
        {
            var dossier        = new Dossier();
            var setTitleResult = await SetDossierTitleAsync(db, dossier, title);

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

            var setSummary = await SetDossierSummaryAsync(db, dossier, summary);

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

            await db.Dossiers.AddAsync(dossier);

            await db.SaveChangesAsync();

            return(CreateEntityResult <Dossier> .FromSuccess((await GetDossierByTitleAsync(db, title)).Entity));
        }
예제 #17
0
        /// <summary>
        /// Grants consent to store user data for a given user.
        /// </summary>
        /// <param name="db">The database.</param>
        /// <param name="discordUser">The user that has granted consent.</param>
        /// <returns>A task that must be awaited.</returns>
        public async Task GrantUserConsentAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] IUser discordUser
        )
        {
            var userConsent = await db.UserConsents.FirstOrDefaultAsync(uc => uc.DiscordID == (long)discordUser.Id);

            if (userConsent is null)
            {
                userConsent = new UserConsent
                {
                    DiscordID    = (long)discordUser.Id,
                    HasConsented = true
                };

                db.UserConsents.Add(userConsent);
            }
            else
            {
                userConsent.HasConsented = true;
            }

            await db.SaveChangesAsync();
        }
예제 #18
0
        /// <summary>
        /// Grants the specified user the given permission. If the user already has the permission, it is augmented with
        /// the new scope and target (if they are more permissive than the existing ones).
        /// </summary>
        /// <param name="db">The database.</param>
        /// <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>
        /// <returns>A task wrapping the granting of the permission.</returns>
        public async Task GrantLocalPermissionAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] IGuild discordServer,
            [NotNull] IUser discordUser,
            [NotNull] LocalPermission grantedPermission
        )
        {
            var existingPermission = await GetLocalUserPermissions(db, discordUser, discordServer).FirstOrDefaultAsync
                                     (
                p =>
                p.Permission == grantedPermission.Permission &&
                p.ServerDiscordID == (long)discordServer.Id
                                     );

            if (existingPermission is null)
            {
                await db.LocalPermissions.AddAsync(grantedPermission);
            }
            else
            {
                // Include the new target permissions
                existingPermission.Target |= grantedPermission.Target;
            }

            await db.SaveChangesAsync();
        }
예제 #19
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DossierCommands"/> class.
 /// </summary>
 /// <param name="database">A database context from the context pool.</param>
 /// <param name="feedback">The feedback service.</param>
 /// <param name="content">The content service.</param>
 /// <param name="dossiers">The dossier service.</param>
 public DossierCommands(GlobalInfoContext database, UserFeedbackService feedback, ContentService content, DossierService dossiers)
 {
     this.Database = database;
     this.Feedback = feedback;
     this.Content  = content;
     this.Dossiers = dossiers;
 }
        /// <summary>
        /// Creates a new template character with a given appearance.
        /// </summary>
        /// <param name="db">The database.</param>
        /// <param name="context">The context of the command.</param>
        /// <param name="characterName">The name of the new character.</param>
        /// <param name="appearance">The appearance that the new character should have.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <Character> > CreateCharacterFromAppearanceAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] ICommandContext context,
            [NotNull] string characterName,
            [NotNull] Appearance appearance
        )
        {
            var createCharacterResult = await CreateCharacterAsync(db, context, characterName);

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

            var newCharacter = createCharacterResult.Entity;

            newCharacter.DefaultAppearance = appearance;

            await db.SaveChangesAsync();

            var getCharacterResult = await GetUserCharacterByNameAsync(db, context, context.Message.Author, characterName);

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

            return(CreateEntityResult <Character> .FromSuccess(getCharacterResult.Entity));
        }
예제 #21
0
        /// <summary>
        /// Kicks the given user from the given roleplay.
        /// </summary>
        /// <param name="db">The database where the roleplays are stored.</param>
        /// <param name="context">The context of the user.</param>
        /// <param name="roleplay">The roleplay to remove the user from.</param>
        /// <param name="kickedUser">The user to remove from the roleplay.</param>
        /// <returns>An execution result which may or may not have succeeded.</returns>
        public async Task <ExecuteResult> KickUserFromRoleplayAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] SocketCommandContext context,
            [NotNull] Roleplay roleplay,
            [NotNull] IUser kickedUser
        )
        {
            if (!roleplay.HasJoined(kickedUser) && !roleplay.IsInvited(kickedUser))
            {
                return(ExecuteResult.FromError(CommandError.ObjectNotFound, "That user is neither invited to or a participant of the roleplay."));
            }

            if (!roleplay.HasJoined(kickedUser))
            {
                var removeUserResult = await RemoveUserFromRoleplayAsync(db, context, roleplay, kickedUser);

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

            var participantEntry = roleplay.JoinedUsers.First(p => p.User.DiscordID == (long)kickedUser.Id);

            participantEntry.Status = ParticipantStatus.Kicked;

            await db.SaveChangesAsync();

            return(ExecuteResult.FromSuccess());
        }
예제 #22
0
        /// <summary>
        /// Shifts the given character's bodypart to the given species.
        /// </summary>
        /// <param name="db">The database where characters and transformations are stored.</param>
        /// <param name="context">The context of the command.</param>
        /// <param name="character">The character to shift.</param>
        /// <param name="bodyPart">The bodypart to shift.</param>
        /// <param name="species">The species to shift the bodypart into.</param>
        /// <param name="chirality">The chirality of the bodypart.</param>
        /// <returns>A shifting result which may or may not have succeeded.</returns>
        public async Task <ShiftBodypartResult> ShiftBodypartAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] ICommandContext context,
            [NotNull] Character character,
            Bodypart bodyPart,
            [NotNull] string species,
            Chirality chirality = Chirality.Center
        )
        {
            var discordUser = await context.Guild.GetUserAsync((ulong)character.Owner.DiscordID);

            var canTransformResult = await CanUserTransformUserAsync(db, context.Guild, context.User, discordUser);

            if (!canTransformResult.IsSuccess)
            {
                return(ShiftBodypartResult.FromError(canTransformResult));
            }

            var getSpeciesResult = await GetSpeciesByNameAsync(db, species);

            if (!getSpeciesResult.IsSuccess)
            {
                return(ShiftBodypartResult.FromError(getSpeciesResult));
            }

            var getTFResult = await GetTransformationByPartAndSpeciesAsync(db, bodyPart, getSpeciesResult.Entity);

            if (!getTFResult.IsSuccess)
            {
                return(ShiftBodypartResult.FromError(getTFResult));
            }

            string shiftMessage;
            var    transformation = getTFResult.Entity;

            if (!character.TryGetAppearanceComponent(bodyPart, chirality, out var currentComponent))
            {
                currentComponent = AppearanceComponent.CreateFrom(transformation, chirality);
                character.CurrentAppearance.Components.Add(currentComponent);

                shiftMessage = this.DescriptionBuilder.BuildGrowMessage(character, currentComponent);
            }
            else
            {
                if (currentComponent.Transformation.Species.Name.Equals(transformation.Species.Name))
                {
                    return(ShiftBodypartResult.FromError(CommandError.Unsuccessful, "The user's bodypart is already that form."));
                }

                currentComponent.Transformation = transformation;

                shiftMessage = this.DescriptionBuilder.BuildShiftMessage(character, currentComponent);
            }

            await db.SaveChangesAsync();

            return(ShiftBodypartResult.FromSuccess(shiftMessage));
        }
예제 #23
0
        /// <summary>
        /// Resets the user's kink preferences.
        /// </summary>
        /// <param name="db">The database.</param>
        /// <param name="discordUser">The user.</param>
        /// <returns>A task that must be awaited.</returns>
        public async Task ResetUserKinksAsync([NotNull] GlobalInfoContext db, [NotNull] IUser discordUser)
        {
            var user = await db.GetOrRegisterUserAsync(discordUser);

            user.Kinks.Clear();

            await db.SaveChangesAsync();
        }
예제 #24
0
 public IQueryable <Roleplay> GetUserRoleplays([NotNull] GlobalInfoContext db, [NotNull] IUser discordUser, [NotNull] IGuild guild)
 {
     return(GetRoleplays(db, guild)
            .Where
            (
                rp =>
                rp.Owner.DiscordID == (long)discordUser.Id
            ));
 }
예제 #25
0
        /// <summary>
        /// Adds the given user to the given roleplay.
        /// </summary>
        /// <param name="db">The database where the roleplays are stored.</param>
        /// <param name="context">The context of the user.</param>
        /// <param name="roleplay">The roleplay to add the user to.</param>
        /// <param name="newUser">The user to add to the roleplay.</param>
        /// <returns>An execution result which may or may not have succeeded.</returns>
        public async Task <ExecuteResult> AddUserToRoleplayAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] SocketCommandContext context,
            [NotNull] Roleplay roleplay,
            [NotNull] IUser newUser
        )
        {
            var isCurrentUser = context.Message.Author.Id == newUser.Id;

            if (roleplay.HasJoined(newUser))
            {
                var errorMessage = isCurrentUser
                                        ? "You're already in that roleplay."
                                        : "The user is aleady in that roleplay.";

                return(ExecuteResult.FromError(CommandError.Unsuccessful, errorMessage));
            }

            if (roleplay.IsKicked(newUser))
            {
                var errorMessage = isCurrentUser
                                        ? "You've been kicked from that roleplay, and can't rejoin unless invited."
                                        : "The user has been kicked from that roleplay, and can't rejoin unless invited.";

                return(ExecuteResult.FromError(CommandError.UnmetPrecondition, errorMessage));
            }

            // Check the invite list for nonpublic roleplays.
            if (!roleplay.IsPublic && !roleplay.IsInvited(newUser))
            {
                var errorMessage = isCurrentUser
                                        ? "You haven't been invited to that roleplay."
                                        : "The user hasn't been invited to that roleplay.";

                return(ExecuteResult.FromError(CommandError.UnmetPrecondition, errorMessage));
            }

            var participantEntry = roleplay.ParticipatingUsers.FirstOrDefault(p => p.User.DiscordID == (long)newUser.Id);

            if (participantEntry is null)
            {
                var user = await db.GetOrRegisterUserAsync(newUser);

                participantEntry = new RoleplayParticipant(roleplay, user, ParticipantStatus.Joined);
                roleplay.ParticipatingUsers.Add(participantEntry);
            }
            else
            {
                participantEntry.Status = ParticipantStatus.Joined;
            }

            await db.SaveChangesAsync();

            return(ExecuteResult.FromSuccess());
        }
예제 #26
0
        /// <summary>
        /// Determines whether or not the given user has granted consent to store user data.
        /// </summary>
        /// <param name="db">The database.</param>
        /// <param name="discordUser">The user.</param>
        /// <returns>true if the user has granted consent; Otherwise, false.</returns>
        public async Task <bool> HasUserConsentedAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] IUser discordUser
        )
        {
            var userConsent = await db.UserConsents.FirstOrDefaultAsync(uc => uc.DiscordID == (long)discordUser.Id);

            return(!(userConsent is null) && userConsent.HasConsented);
        }
예제 #27
0
        /// <summary>
        /// Gets a kink by its F-list ID.
        /// </summary>
        /// <param name="db">The database.</param>
        /// <param name="onlineKinkID">The F-List kink ID.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <Kink> > GetKinkByFListIDAsync([NotNull] GlobalInfoContext db, int onlineKinkID)
        {
            var kink = await db.Kinks.FirstOrDefaultAsync(k => k.FListID == onlineKinkID);

            if (kink is null)
            {
                return(RetrieveEntityResult <Kink> .FromError(CommandError.ObjectNotFound, "No kink with that ID found."));
            }

            return(RetrieveEntityResult <Kink> .FromSuccess(kink));
        }
예제 #28
0
        /// <summary>
        /// Gets the first kink in the given category.
        /// </summary>
        /// <param name="db">The database.</param>
        /// <param name="category">The category.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <Kink> > GetFirstKinkInCategoryAsync([NotNull] GlobalInfoContext db, KinkCategory category)
        {
            var getKinksResult = await GetKinksByCategoryAsync(db, category);

            if (!getKinksResult.IsSuccess)
            {
                return(RetrieveEntityResult <Kink> .FromError(getKinksResult));
            }

            return(RetrieveEntityResult <Kink> .FromSuccess(getKinksResult.Entity.First()));
        }
        public IQueryable <Character> GetUserCharacters
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] IUser discordUser,
            [NotNull] IGuild guild
        )
        {
            var characters = GetCharacters(db, guild).Where(ch => ch.Owner.DiscordID == (long)discordUser.Id);

            return(characters);
        }
예제 #30
0
        /// <summary>
        /// Sets whether or not a roleplay is public.
        /// </summary>
        /// <param name="db">The database containing the roleplays.</param>
        /// <param name="roleplay">The roleplay to set the value in.</param>
        /// <param name="isPublic">The new value.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> SetRoleplayIsPublicAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] Roleplay roleplay,
            bool isPublic
        )
        {
            roleplay.IsPublic = isPublic;
            await db.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess(ModifyEntityAction.Edited));
        }