/// <summary>
        /// Gets the next kink in its category by its predecessor's F-List ID.
        /// </summary>
        /// <param name="db">The database.</param>
        /// <param name="precedingFListID">The F-List ID of the preceding kink.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <Kink> > GetNextKinkByCurrentFListIDAsync([NotNull] GlobalInfoContext db, int precedingFListID)
        {
            var getKinkResult = await GetKinkByFListIDAsync(db, precedingFListID);

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

            var currentKink    = getKinkResult.Entity;
            var getKinksResult = await GetKinksByCategoryAsync(db, currentKink.Category);

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

            var group    = getKinksResult.Entity;
            var nextKink = group.SkipUntil(k => k.FListID == precedingFListID).FirstOrDefault();

            if (nextKink is null)
            {
                return(RetrieveEntityResult <Kink> .FromError(CommandError.ObjectNotFound, "The current kink was the last one in the category."));
            }

            return(RetrieveEntityResult <Kink> .FromSuccess(nextKink));
        }
        /// <summary>
        /// Gets a user's kink preferences by the F-List kink ID.
        /// </summary>
        /// <param name="db">The database.</param>
        /// <param name="discordUser">The discord user.</param>
        /// <param name="onlineKinkID">The F-List kink ID.</param>
        /// <returns>The user's kink preference.</returns>
        public async Task <RetrieveEntityResult <UserKink> > GetUserKinkByFListIDAsync([NotNull] GlobalInfoContext db, IUser discordUser, int onlineKinkID)
        {
            var getKinkResult = await GetKinkByFListIDAsync(db, onlineKinkID);

            if (!getKinkResult.IsSuccess)
            {
                return(RetrieveEntityResult <UserKink> .FromError(getKinkResult));
            }

            var user = await db.GetOrRegisterUserAsync(discordUser);

            var userKink = user.Kinks.FirstOrDefault(k => k.Kink.FListID == onlineKinkID);

            if (!(userKink is null))
            {
                return(RetrieveEntityResult <UserKink> .FromSuccess(userKink));
            }

            var kink          = getKinkResult.Entity;
            var addKinkResult = await AddUserKinkAsync(db, discordUser, kink);

            if (!addKinkResult.IsSuccess)
            {
                return(RetrieveEntityResult <UserKink> .FromError(addKinkResult));
            }

            return(RetrieveEntityResult <UserKink> .FromSuccess(addKinkResult.Entity));
        }
        public RetrieveEntityResult <FileStream> OpenLocalStream([PathReference][NotNull] string path, [CanBeNull] string subdirectory = null, FileMode fileMode = FileMode.Open)
        {
            var absolutePath = Path.GetFullPath(path);

            if (!absolutePath.StartsWith(this.BaseContentPath))
            {
                return(RetrieveEntityResult <FileStream> .FromError
                       (
                           CommandError.Unsuccessful,
                           "The path pointed to something that wasn't in the content folder."
                       ));
            }

            if (!(subdirectory is null))
            {
                var subdirectoryParentDir = Path.Combine(this.BaseContentPath, subdirectory);
                if (!absolutePath.StartsWith(subdirectoryParentDir))
                {
                    return(RetrieveEntityResult <FileStream> .FromError
                           (
                               CommandError.Unsuccessful,
                               "The path pointed to something that wasn't in the specified subdirectory."
                           ));
                }
            }

            // Make sure that the directory chain is created
            Directory.CreateDirectory(Directory.GetParent(absolutePath).FullName);

            return(RetrieveEntityResult <FileStream> .FromSuccess(File.Open(absolutePath, fileMode)));
        }
Example #4
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));
        }
        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));
        }
        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));
        }
Example #8
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));
        }
        public RetrieveEntityResult <FileStream> GetDossierStream([NotNull] Dossier dossier)
        {
            if (!File.Exists(dossier.Path) || dossier.Path.IsNullOrWhitespace())
            {
                return(RetrieveEntityResult <FileStream> .FromError(CommandError.ObjectNotFound, "No file data set."));
            }

            return(OpenLocalStream(dossier.Path, "Dossiers"));
        }
        /// <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));
        }
        /// <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 async Task <RetrieveEntityResult <Dossier> > GetDossierByTitleAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] string title
        )
        {
            var dossier = await db.Dossiers.FirstOrDefaultAsync(d => string.Equals(d.Title, title, StringComparison.OrdinalIgnoreCase));

            if (dossier is null)
            {
                return(RetrieveEntityResult <Dossier> .FromError(CommandError.ObjectNotFound, "No dossier with that title found."));
            }

            return(RetrieveEntityResult <Dossier> .FromSuccess(dossier));
        }
        /// <summary>
        /// Gets a list of all kinks in a 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 <IEnumerable <Kink> > > GetKinksByCategoryAsync([NotNull] GlobalInfoContext db, KinkCategory category)
        {
            var group = await db.Kinks.GroupBy(k => k.Category).FirstOrDefaultAsync(g => g.Key == category);

            if (group is null)
            {
                return(RetrieveEntityResult <IEnumerable <Kink> > .FromError
                       (
                           CommandError.ObjectNotFound,
                           "There are no kinks in that category."
                       ));
            }

            return(RetrieveEntityResult <IEnumerable <Kink> > .FromSuccess(group));
        }
        public async Task <RetrieveEntityResult <Stream> > GetAttachmentStreamAsync([NotNull] Attachment attachment)
        {
            try
            {
                var stream = await Client.GetStreamAsync(attachment.Url);

                return(RetrieveEntityResult <Stream> .FromSuccess(stream));
            }
            catch (HttpRequestException hex)
            {
                return(RetrieveEntityResult <Stream> .FromError(CommandError.Exception, hex.ToString()));
            }
            catch (TaskCanceledException)
            {
                return(RetrieveEntityResult <Stream> .FromError(CommandError.Unsuccessful, "The download operation timed out."));
            }
        }
        public async Task <RetrieveEntityResult <IReadOnlyList <Transformation> > > DiscoverBundledTransformationsAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] TransformationService transformation,
            [NotNull] Species species
        )
        {
            const string speciesFilename = "Species.yml";

            var speciesDir          = GetSpeciesDirectory(species);
            var transformationFiles = Directory.EnumerateFiles(speciesDir).Where(p => !p.EndsWith(speciesFilename));

            var transformations = new List <Transformation>();
            var deser           = new DeserializerBuilder()
                                  .WithTypeConverter(new ColourYamlConverter())
                                  .WithTypeConverter(new SpeciesYamlConverter(db, transformation))
                                  .WithNodeDeserializer(i => new ValidatingNodeDeserializer(i), s => s.InsteadOf <ObjectNodeDeserializer>())
                                  .WithNamingConvention(new UnderscoredNamingConvention())
                                  .Build();

            foreach (var transformationFile in transformationFiles)
            {
                string content = await FileAsync.ReadAllTextAsync(transformationFile);

                try
                {
                    transformations.Add(deser.Deserialize <Transformation>(content));
                }
                catch (YamlException yex)
                {
                    if (yex.InnerException is SerializationException sex)
                    {
                        return(RetrieveEntityResult <IReadOnlyList <Transformation> > .FromError(sex));
                    }

                    return(RetrieveEntityResult <IReadOnlyList <Transformation> > .FromError(yex));
                }
            }

            return(RetrieveEntityResult <IReadOnlyList <Transformation> > .FromSuccess(transformations));
        }
Example #16
0
        public async Task <RetrieveEntityResult <Roleplay> > GetActiveRoleplayAsync
        (
            [NotNull] GlobalInfoContext db,
            [NotNull] ICommandContext context
        )
        {
            if (context.Guild is null)
            {
                return(RetrieveEntityResult <Roleplay> .FromError(CommandError.ObjectNotFound, "You're not in a server."));
            }

            var roleplay = await GetRoleplays(db, context.Guild)
                           .FirstOrDefaultAsync(rp => rp.IsActive && rp.ActiveChannelID == (long)context.Channel.Id);

            if (roleplay is null)
            {
                return(RetrieveEntityResult <Roleplay> .FromError(CommandError.ObjectNotFound, "There is no roleplay that is currently active in this channel."));
            }

            return(RetrieveEntityResult <Roleplay> .FromSuccess(roleplay));
        }
        public async Task <RetrieveEntityResult <IReadOnlyList <Species> > > DiscoverBundledSpeciesAsync()
        {
            const string speciesFilename = "Species.yml";

            var deser = new DeserializerBuilder()
                        .WithNodeDeserializer(i => new ValidatingNodeDeserializer(i), s => s.InsteadOf <ObjectNodeDeserializer>())
                        .WithNamingConvention(new UnderscoredNamingConvention())
                        .Build();

            var species        = new List <Species>();
            var speciesFolders = Directory.EnumerateDirectories(this.BaseTransformationSpeciesPath);

            foreach (string directory in speciesFolders)
            {
                string speciesFilePath = Path.Combine(directory, speciesFilename);
                if (!File.Exists(speciesFilePath))
                {
                    continue;
                }

                string content = await FileAsync.ReadAllTextAsync(speciesFilePath, Encoding.UTF8);

                try
                {
                    species.Add(deser.Deserialize <Species>(content));
                }
                catch (YamlException yex)
                {
                    if (yex.InnerException is SerializationException sex)
                    {
                        return(RetrieveEntityResult <IReadOnlyList <Species> > .FromError(sex));
                    }

                    return(RetrieveEntityResult <IReadOnlyList <Species> > .FromError(yex));
                }
            }

            return(RetrieveEntityResult <IReadOnlyList <Species> > .FromSuccess(species));
        }
        /// <summary>
        /// Gets the first kink that the given uses does not have a set preference for in the given category.
        /// </summary>
        /// <param name="db">The database.</param>
        /// <param name="user">The user.</param>
        /// <param name="category">The category.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <Kink> > GetFirstKinkWithoutPreferenceInCategoryAsync([NotNull] GlobalInfoContext db, IUser user, KinkCategory category)
        {
            var getKinksResult = await GetKinksByCategoryAsync(db, category);

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

            var kinks     = getKinksResult.Entity;
            var userKinks = (await GetUserKinksByCategoryAsync(db, user, category)).ToList();

            // Find the first kink that the user either has in their list with no preference, or does not exist
            // in their list
            var kinkWithoutPreference = kinks.FirstOrDefault
                                        (
                k =>
                userKinks.Any
                (
                    uk =>
                    k.FListID == uk.Kink.FListID && uk.Preference == KinkPreference.NoPreference
                ) ||
                userKinks.All
                (
                    uk =>
                    k.FListID != uk.Kink.FListID
                )
                                        );

            if (kinkWithoutPreference is null)
            {
                return(RetrieveEntityResult <Kink> .FromError(CommandError.ObjectNotFound, "No kink without a set preference found."));
            }

            return(RetrieveEntityResult <Kink> .FromSuccess(kinkWithoutPreference));
        }