Пример #1
0
        /// <inheritdoc/>
        public override async Task <RetrieveEntityResult <bool> > IsConditionFulfilledForUserAsync
        (
            IServiceProvider services,
            IGuildUser discordUser,
            CancellationToken ct = default
        )
        {
            var statistics = services.GetRequiredService <UserStatisticsService>();

            var channel = await discordUser.Guild.GetTextChannelAsync((ulong)this.SourceID);

            if (channel is null)
            {
                return(RetrieveEntityResult <bool> .FromError("Failed to retrieve the channel."));
            }

            var getUserStatistics = await statistics.GetOrCreateUserChannelStatisticsAsync(discordUser, channel, ct);

            if (!getUserStatistics.IsSuccess)
            {
                return(RetrieveEntityResult <bool> .FromError(getUserStatistics));
            }

            var userStatistics = getUserStatistics.Entity;

            return(userStatistics.MessageCount.HasValue && userStatistics.MessageCount >= this.RequiredCount);
        }
Пример #2
0
        /// <summary>
        /// Gets or creates server settings for the given guild.
        /// </summary>
        /// <param name="guild">The guild.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <AutoroleServerSettings> > GetOrCreateServerSettingsAsync
        (
            IGuild guild
        )
        {
            var existingSettings = await _database.AutoroleServerSettings.AsQueryable().FirstOrDefaultAsync
                                   (
                s => s.Server.DiscordID == (long)guild.Id
                                   );

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

            var getServer = await _servers.GetOrRegisterServerAsync(guild);

            if (!getServer.IsSuccess)
            {
                return(RetrieveEntityResult <AutoroleServerSettings> .FromError(getServer));
            }

            var server      = getServer.Entity;
            var newSettings = _database.CreateProxy <AutoroleServerSettings>(server);

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

            return(newSettings);
        }
        /// <summary>
        /// Gets the roleplay currently active in the given channel.
        /// </summary>
        /// <param name="textChannel">The channel.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <Roleplay> > GetActiveRoleplayAsync(ITextChannel textChannel)
        {
            var getServer = await _servers.GetOrRegisterServerAsync(textChannel.Guild);

            if (!getServer.IsSuccess)
            {
                return(RetrieveEntityResult <Roleplay> .FromError(getServer));
            }

            var server = getServer.Entity;

            var roleplay = (await _roleplays.GetRoleplaysAsync(server)).FirstOrDefault
                           (
                rp => rp.IsActive && rp.ActiveChannelID == (long)textChannel.Id
                           );

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

            return(roleplay);
        }
Пример #4
0
        public static RetrieveEntityResult <TResult> SelectFromBestLevenshteinMatch <TSource, TResult>
        (
            this IEnumerable <TSource> @this,
            Func <TSource, TResult> selector,
            Func <TSource, string> stringSelector,
            string search,
            double tolerance = 0.25
        )
            where TResult : class
            where TSource : class
        {
            var enumerable = @this as IList <TSource> ?? @this.ToList();

            var matchResult = enumerable.Select(stringSelector).BestLevenshteinMatch(search, tolerance);

            if (!matchResult.IsSuccess)
            {
                return(RetrieveEntityResult <TResult> .FromError(matchResult));
            }

            var selectedString = matchResult.Entity;

            var selectedObject = enumerable.FirstOrDefault(i => stringSelector(i) == selectedString);

            if (selectedObject is null)
            {
                return(RetrieveEntityResult <TResult> .FromError("No matching object for the selector found."));
            }

            var result = selector(selectedObject);

            return(RetrieveEntityResult <TResult> .FromSuccess(result));
        }
Пример #5
0
        /// <summary>
        /// Adds a Discord user to the database.
        /// </summary>
        /// <param name="discordUser">The Discord user.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>The freshly created information about the user.</returns>
        /// <exception cref="ArgumentException">Thrown if the user already exists in the database.</exception>
        public async Task <RetrieveEntityResult <User> > AddUserAsync
        (
            IUser discordUser,
            CancellationToken ct = default
        )
        {
            if (discordUser.IsBot || discordUser.IsWebhook)
            {
                return(RetrieveEntityResult <User> .FromError
                       (
                           "Users cannot be viewed or created for bots or webhooks."
                       ));
            }

            if (await IsUserKnownAsync(discordUser, ct))
            {
                return(RetrieveEntityResult <User> .FromError
                       (
                           $"A user with the ID {discordUser.Id} has already been added to the database."
                       ));
            }

            var newUser = _database.CreateProxy <User>((long)discordUser.Id);

            _database.Users.Update(newUser);
            await _database.SaveChangesAsync(ct);

            return(newUser);
        }
        /// <inheritdoc />
        public async Task <RetrieveEntityResult <Character> > GetUserCharacterByNameAsync
        (
            User user,
            Server server,
            string name,
            CancellationToken ct = default
        )
        {
            user   = _database.NormalizeReference(user);
            server = _database.NormalizeReference(server);

            var character = await _database.Characters.UserScopedServersideQueryAsync
                            (
                user,
                server,
                q => q
                .Where(ch => string.Equals(ch.Name.ToLower(), name.ToLower()))
                .SingleOrDefaultAsync(ct)
                            );

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

            return(RetrieveEntityResult <Character> .FromError("The user doesn't own a character with that name."));
        }
Пример #7
0
        /// <summary>
        /// Determines whether a given user is qualified for the given autorole.
        /// </summary>
        /// <param name="autorole">The autorole.</param>
        /// <param name="user">The user.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>true if the user qualifies; otherwise, false.</returns>
        public async Task <RetrieveEntityResult <bool> > IsUserQualifiedForAutoroleAsync
        (
            AutoroleConfiguration autorole,
            IGuildUser user,
            CancellationToken ct = default
        )
        {
            foreach (var condition in autorole.Conditions)
            {
                var isFulfilledResult = await condition.IsConditionFulfilledForUserAsync(_serviceProvider, user, ct);

                if (!isFulfilledResult.IsSuccess)
                {
                    return(RetrieveEntityResult <bool> .FromError("One or more conditions were indeterminate."));
                }

                var isFulfilled = isFulfilledResult.Entity;

                if (!isFulfilled)
                {
                    return(false);
                }
            }

            return(true);
        }
        private RetrieveEntityResult <IReadOnlyList <string> > GetSampleDataSet <TType>(string subfolder)
        {
            var getBasePath = GetBaseSampleDataPath();

            if (!getBasePath.IsSuccess)
            {
                return(RetrieveEntityResult <IReadOnlyList <string> > .FromError(getBasePath));
            }

            var basePath             = Path.Combine(getBasePath.Entity, subfolder);
            var samplesDirectoryName = typeof(TType).Name.Underscore().Transform(To.UpperCase);

            if (typeof(TType).IsInterface && samplesDirectoryName.StartsWith('I'))
            {
                samplesDirectoryName = samplesDirectoryName.Substring(2);
            }

            var samplesPath = Path.Combine(basePath, samplesDirectoryName);

            if (!Directory.Exists(samplesPath))
            {
                return(RetrieveEntityResult <IReadOnlyList <string> > .FromError("No valid sample data found."));
            }

            return(Directory.EnumerateFiles(samplesPath, "*.json", SearchOption.AllDirectories).ToList());
        }
Пример #9
0
        public async Task <RetrieveEntityResult <IReadOnlyList <Transformation> > > GetTransformationsByPartAndSpeciesAsync
        (
            Bodypart bodypart,
            Species species
        )
        {
            var bodyparts = new List <Bodypart>();

            if (bodypart.IsComposite())
            {
                bodyparts.AddRange(bodypart.GetComposingParts());
            }
            else
            {
                bodyparts.Add(bodypart);
            }

            var transformations = await _database.Transformations.AsQueryable()
                                  .Where(tf => bodyparts.Contains(tf.Part) && tf.Species.Name.ToLower().Equals(species.Name.ToLower()))
                                  .ToListAsync();

            if (!transformations.Any())
            {
                return(RetrieveEntityResult <IReadOnlyList <Transformation> > .FromError
                       (
                           "No transformation found for that combination."
                       ));
            }

            return(RetrieveEntityResult <IReadOnlyList <Transformation> > .FromSuccess(transformations));
        }
Пример #10
0
        public async Task <RetrieveEntityResult <Roleplay> > GetUserRoleplayByNameAsync
        (
            [NotNull] ICommandContext context,
            [NotNull] IUser roleplayOwner,
            [NotNull] string roleplayName
        )
        {
            var roleplay = await GetRoleplays(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(errorMessage));
            }

            return(RetrieveEntityResult <Roleplay> .FromSuccess(roleplay));
        }
Пример #11
0
        /// <inheritdoc />
        public override async Task <RetrieveEntityResult <bool> > IsConditionFulfilledForUserAsync
        (
            IServiceProvider services,
            IGuildUser discordUser,
            CancellationToken ct = default
        )
        {
            var statistics = services.GetRequiredService <UserStatisticsService>();

            var getUserStatistics = await statistics.GetOrCreateUserServerStatisticsAsync(discordUser, ct);

            if (!getUserStatistics.IsSuccess)
            {
                return(RetrieveEntityResult <bool> .FromError(getUserStatistics));
            }

            var userStatistics = getUserStatistics.Entity;

            if (userStatistics.LastActivityTime is null)
            {
                // The user has never been active
                return(false);
            }

            var timeSinceLastActivity = DateTime.UtcNow - userStatistics.LastActivityTime;

            return(timeSinceLastActivity <= this.RequiredTime);
        }
Пример #12
0
        public async Task <RetrieveEntityResult <IGuildChannel> > GetDedicatedRoleplayChannelAsync
        (
            [NotNull] IGuild guild,
            [NotNull] Roleplay roleplay
        )
        {
            if (!(roleplay.DedicatedChannelID is null))
            {
                var guildChannel = await guild.GetChannelAsync((ulong)roleplay.DedicatedChannelID.Value);

                if (!(guildChannel is null))
                {
                    return(RetrieveEntityResult <IGuildChannel> .FromSuccess(guildChannel));
                }

                return(RetrieveEntityResult <IGuildChannel> .FromError
                       (
                           "Attempted to delete a channel, but it appears to have been deleted."
                       ));
            }

            return(RetrieveEntityResult <IGuildChannel> .FromError
                   (
                       "The roleplay doesn't have a dedicated channel."
                   ));
        }
Пример #13
0
        private RetrieveEntityResult <TUser> FindBestMatchingUserBy <TUser>
        (
            IEnumerable <TUser> users,
            Func <TUser, string> selector,
            string value
        )
            where TUser : class, IUser
        {
            var values = users.Select(u => (User: u, Value: selector(u))).ToImmutableList();

            var literalMatch = values.FirstOrDefault(uv => uv.Value == value).User;

            if (!(literalMatch is null))
            {
                return(RetrieveEntityResult <TUser> .FromSuccess(literalMatch));
            }

            var partialMatch = values.FirstOrDefault
                               (
                uv =>
                string.Equals(uv.Value, value, StringComparison.OrdinalIgnoreCase)
                               ).User;

            if (!(partialMatch is null))
            {
                return(RetrieveEntityResult <TUser> .FromSuccess(partialMatch));
            }

            return(RetrieveEntityResult <TUser> .FromError("No matching user found."));
        }
Пример #14
0
        /// <inheritdoc />
        protected override async Task <RetrieveEntityResult <Roleplay> > RetrieveEntityAsync
        (
            IUser?entityOwner,
            string?entityName,
            ICommandContext context,
            IServiceProvider services
        )
        {
            var roleplayService = services.GetRequiredService <RoleplayDiscordService>();

            if (!(context.Channel is ITextChannel textChannel))
            {
                return(RetrieveEntityResult <Roleplay> .FromError("The channel was not a text channel."));
            }

            if (!entityName.IsNullOrWhitespace() && string.Equals(entityName, "current", StringComparison.OrdinalIgnoreCase))
            {
                return(await roleplayService.GetActiveRoleplayAsync(textChannel));
            }

            return(await roleplayService.GetBestMatchingRoleplayAsync
                   (
                       (ITextChannel)context.Channel,
                       context.Guild,
                       entityOwner,
                       entityName
                   ));
        }
        /// <inheritdoc />
        public async Task <RetrieveEntityResult <Character> > GetCurrentCharacterAsync
        (
            User user,
            Server server,
            CancellationToken ct = default
        )
        {
            user   = _database.NormalizeReference(user);
            server = _database.NormalizeReference(server);

            if (!await HasCurrentCharacterAsync(user, server, ct))
            {
                return(RetrieveEntityResult <Character> .FromError("The user hasn't assumed a character."));
            }

            var currentCharacter = await _database.Characters.UserScopedServersideQueryAsync
                                   (
                user,
                server,
                q => q
                .Where(ch => ch.IsCurrent)
                .SingleOrDefaultAsync(ct)
                                   );

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

            return(RetrieveEntityResult <Character> .FromError("Failed to retrieve a current character."));
        }
Пример #16
0
        /// <summary>
        /// Gets the current appearance for the given character, cloning it from the default appearance if one does not
        /// exist.
        /// </summary>
        /// <param name="character">The character.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <Appearance> > GetOrCreateCurrentAppearanceAsync
        (
            Character character
        )
        {
            var getCurrentAppearanceResult = await GetCurrentAppearanceAsync(character);

            if (getCurrentAppearanceResult.IsSuccess)
            {
                return(getCurrentAppearanceResult);
            }

            // There's no current appearance, so we'll grab the default one and copy it
            var getDefaultAppearance = await GetOrCreateDefaultAppearanceAsync(character);

            if (!getDefaultAppearance.IsSuccess)
            {
                return(RetrieveEntityResult <Appearance> .FromError(getDefaultAppearance));
            }

            var defaultAppearance = getDefaultAppearance.Entity;

            var currentAppearance = Appearance.CopyFrom(defaultAppearance);

            currentAppearance.IsCurrent = true;

            _database.Appearances.Update(currentAppearance);

            await _database.SaveChangesAsync();

            // Requery the database
            return(await GetOrCreateCurrentAppearanceAsync(character));
        }
        /// <inheritdoc />
        public async Task <RetrieveEntityResult <Character> > GetCharacterByNameAsync
        (
            Server server,
            string name,
            CancellationToken ct = default
        )
        {
            server = _database.NormalizeReference(server);

            var characters = await _database.Characters.ServerScopedServersideQueryAsync
                             (
                server,
                q => q.Where(ch => string.Equals(ch.Name.ToLower(), name.ToLower())),
                ct
                             );

            if (characters.Count > 1)
            {
                return(RetrieveEntityResult <Character> .FromError
                       (
                           "There's more than one character with that name. Please specify which user it belongs to."
                       ));
            }

            var character = characters.SingleOrDefault();

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

            return(RetrieveEntityResult <Character> .FromError("No character with that name found."));
        }
Пример #18
0
        /// <summary>
        /// Gets or creates the global transformation protection data for the given user.
        /// </summary>
        /// <param name="discordUser">The user.</param>
        /// <returns>Global protection data for the given user.</returns>
        public async Task <RetrieveEntityResult <GlobalUserProtection> > GetOrCreateGlobalUserProtectionAsync
        (
            IUser discordUser
        )
        {
            var protection = await _database.GlobalUserProtections.AsQueryable()
                             .FirstOrDefaultAsync(p => p.User.DiscordID == (long)discordUser.Id);

            if (!(protection is null))
            {
                return(RetrieveEntityResult <GlobalUserProtection> .FromSuccess(protection));
            }

            var getUserResult = await _users.GetOrRegisterUserAsync(discordUser);

            if (!getUserResult.IsSuccess)
            {
                return(RetrieveEntityResult <GlobalUserProtection> .FromError(getUserResult));
            }

            var user = getUserResult.Entity;

            protection = new GlobalUserProtection(user);

            _database.GlobalUserProtections.Update(protection);

            await _database.SaveChangesAsync();

            return(RetrieveEntityResult <GlobalUserProtection> .FromSuccess(protection));
        }
        /// <inheritdoc />
        public async Task <RetrieveEntityResult <Character> > GetDefaultCharacterAsync
        (
            User user,
            Server server,
            CancellationToken ct = default
        )
        {
            user   = _database.NormalizeReference(user);
            server = _database.NormalizeReference(server);

            var defaultCharacter = await _database.Characters.UserScopedServersideQueryAsync
                                   (
                user,
                server,
                q => q
                .Where(ch => ch.IsDefault)
                .SingleOrDefaultAsync(ct)
                                   );

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

            return(RetrieveEntityResult <Character> .FromError("The user doesn't have a default character."));
        }
Пример #20
0
        /// <summary>
        /// Gets the default appearance for the given character, or creates one if one does not exist.
        /// </summary>
        /// <param name="character">The character.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <Appearance> > GetOrCreateDefaultAppearanceAsync
        (
            Character character
        )
        {
            var getDefaultAppearance = await GetDefaultAppearanceAsync(character);

            if (getDefaultAppearance.IsSuccess)
            {
                return(getDefaultAppearance);
            }

            var createDefaultAppearanceResult = await Appearance.CreateDefaultAsync(character, this);

            if (!createDefaultAppearanceResult.IsSuccess)
            {
                return(RetrieveEntityResult <Appearance> .FromError(createDefaultAppearanceResult));
            }

            var defaultAppearance = createDefaultAppearanceResult.Entity;

            defaultAppearance.IsDefault = true;

            _database.Appearances.Update(defaultAppearance);

            await _database.SaveChangesAsync();

            // Requery the database
            return(await GetOrCreateDefaultAppearanceAsync(character));
        }
Пример #21
0
        /// <summary>
        /// Gets or creates server settings for the given guild.
        /// </summary>
        /// <param name="guild">The guild.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <AutoroleServerSettings> > GetOrCreateServerSettingsAsync
        (
            IGuild guild,
            CancellationToken ct = default
        )
        {
            var settings = await _database.AutoroleServerSettings.ServersideQueryAsync
                           (
                q => q
                .Where(s => s.Server.DiscordID == (long)guild.Id)
                .SingleOrDefaultAsync(ct)
                           );

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

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

            if (!getServer.IsSuccess)
            {
                return(RetrieveEntityResult <AutoroleServerSettings> .FromError(getServer));
            }

            var server = getServer.Entity;

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

            _database.AutoroleServerSettings.Update(newSettings);
            await _database.SaveChangesAsync(ct);

            return(newSettings);
        }
        /// <summary>
        /// Gets the current character of the given user.
        /// </summary>
        /// <param name="guildUser">The user.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <Character> > GetCurrentCharacterAsync
        (
            IGuildUser guildUser,
            CancellationToken ct = default
        )
        {
            var getUser = await _users.GetOrRegisterUserAsync(guildUser, ct);

            if (!getUser.IsSuccess)
            {
                return(RetrieveEntityResult <Character> .FromError(getUser));
            }

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

            if (!getServer.IsSuccess)
            {
                return(RetrieveEntityResult <Character> .FromError(getServer));
            }

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

            return(await _characters.GetCurrentCharacterAsync(user, server, ct));
        }
Пример #23
0
        public static async Task <RetrieveEntityResult <TResult> > SelectFromBestLevenshteinMatchAsync <TSource, TResult>
        (
            this IQueryable <TSource> @this,
            Func <TSource, TResult> selector,
            Expression <Func <TSource, string> > stringSelector,
            string search,
            double tolerance = 0.25
        )
            where TResult : class
            where TSource : class
        {
            var matchResult = (await @this.Select(stringSelector).ToListAsync()).BestLevenshteinMatch(search, tolerance);

            if (!matchResult.IsSuccess)
            {
                return(RetrieveEntityResult <TResult> .FromError(matchResult));
            }

            var selectedString = matchResult.Entity;

            var selectorFunc = stringSelector.Compile();

            var selectedObject = await @this.FirstOrDefaultAsync(i => selectorFunc(i) == selectedString);

            if (selectedObject is null)
            {
                return(RetrieveEntityResult <TResult> .FromError("No matching object for the selector found."));
            }

            var result = selector(selectedObject);

            return(RetrieveEntityResult <TResult> .FromSuccess(result));
        }
        /// <summary>
        /// Gets the best matching character for the given owner and name combination. If no owner is provided, then the
        /// global list is searched for a unique name. If no name is provided, then the user's current character is
        /// used. If neither are set, no character will ever be returned.
        /// </summary>
        /// <param name="guild">The guild the user is on.</param>
        /// <param name="guildUser">The user.</param>
        /// <param name="name">The name of the character.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <Character> > GetBestMatchingCharacterAsync
        (
            IGuild guild,
            IGuildUser?guildUser,
            string?name,
            CancellationToken ct = default
        )
        {
            var getServer = await _servers.GetOrRegisterServerAsync(guild, ct);

            if (!getServer.IsSuccess)
            {
                return(RetrieveEntityResult <Character> .FromError(getServer));
            }

            var server = getServer.Entity;

            if (guildUser is null)
            {
                return(await _characters.GetBestMatchingCharacterAsync(server, null, name, ct));
            }

            var getUser = await _users.GetOrRegisterUserAsync(guildUser, ct);

            if (!getUser.IsSuccess)
            {
                return(RetrieveEntityResult <Character> .FromError(getUser));
            }

            var user = getUser.Entity;

            return(await _characters.GetBestMatchingCharacterAsync(server, user, name, ct));
        }
Пример #25
0
        /// <summary>
        /// Gets a condition of the specified ID and type from the given autorole.
        /// </summary>
        /// <param name="autorole">The autorole.</param>
        /// <param name="conditionID">The ID of the condition.</param>
        /// <typeparam name="TCondition">The type of the condition.</typeparam>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public RetrieveEntityResult <TCondition> GetCondition <TCondition>
        (
            AutoroleConfiguration autorole,
            long conditionID
        )
            where TCondition : AutoroleCondition
        {
            var condition = autorole.Conditions.FirstOrDefault(c => c.ID == conditionID);

            if (condition is null)
            {
                return(RetrieveEntityResult <TCondition> .FromError
                       (
                           "The autorole doesn't have any condition with that ID."
                       ));
            }

            if (!(condition is TCondition))
            {
                return(RetrieveEntityResult <TCondition> .FromError
                       (
                           "The condition with that ID isn't this kind of condition."
                       ));
            }

            return((TCondition)condition);
        }
        /// <summary>
        /// Determines whether the given name is unique among the given user's characters.
        /// </summary>
        /// <param name="guildUser">The user.</param>
        /// <param name="name">The name.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public async Task <RetrieveEntityResult <bool> > IsNameUniqueForUserAsync
        (
            IGuildUser guildUser,
            string name,
            CancellationToken ct = default
        )
        {
            var getUser = await _users.GetOrRegisterUserAsync(guildUser, ct);

            if (!getUser.IsSuccess)
            {
                return(RetrieveEntityResult <bool> .FromError(getUser));
            }

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

            if (!getServer.IsSuccess)
            {
                return(RetrieveEntityResult <bool> .FromError(getServer));
            }

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

            return(await _characters.IsNameUniqueForUserAsync(user, server, name, ct));
        }
Пример #27
0
        public static RetrieveEntityResult <string> BestLevenshteinMatch
        (
            this IEnumerable <string> @this,
            string search,
            double tolerance = 0.25
        )
        {
            var candidates = @this.Select
                             (
                s =>
            {
                var distance = LevenshteinDistance.Compute
                               (
                    s.ToLowerInvariant(),
                    search.ToLowerInvariant()
                               );

                var maxDistance = Math.Max(s.Length, search.Length);
                var percentile  = distance / (float)maxDistance;

                return(value: s, distance, percentile);
            }
                             );

            var passing = candidates.Where(c => c.percentile <= tolerance).ToList();

            if (!passing.Any())
            {
                return(RetrieveEntityResult <string> .FromError("No sufficiently close match found."));
            }

            var best = passing.MinBy(c => c.distance).First();

            return(RetrieveEntityResult <string> .FromSuccess(best.value));
        }
        /// <inheritdoc />
        public async Task <RetrieveEntityResult <Character> > GetBestMatchingCharacterAsync
        (
            Server server,
            User?user,
            string?name,
            CancellationToken ct = default
        )
        {
            server = _database.NormalizeReference(server);
            if (!(user is null))
            {
                user = _database.NormalizeReference(user);
            }

            if (user is null && name is null)
            {
                return(RetrieveEntityResult <Character> .FromError("No user and no name specified."));
            }

            if (user is null)
            {
                return(await GetCharacterByNameAsync(server, name !, ct));
            }

            if (name.IsNullOrWhitespace())
            {
                return(await GetCurrentCharacterAsync(user, server, ct));
            }

            return(await GetUserCharacterByNameAsync(user, server, name, ct));
        }
        /// <summary>
        /// Loads and retrieves the bundled transformation messages.
        /// </summary>
        /// <param name="this">The content service.</param>
        /// <returns>A retrieval result which may or may not have succeeded.</returns>
        public static RetrieveEntityResult <TransformationText> GetTransformationMessages
        (
            [NotNull] this ContentService @this
        )
        {
            if ([email protected](TransformationMessagesPath))
            {
                return(RetrieveEntityResult <TransformationText> .FromError("Transformation messages not found."));
            }

            using
            (
                var reader = new StreamReader
                             (
                    @this.FileSystem.OpenFile
                    (
                        TransformationMessagesPath,
                        FileMode.Open,
                        FileAccess.Read,
                        FileShare.Read
                    )
                             )
            )
            {
                var content = reader.ReadToEnd();
                if (!TransformationText.TryDeserialize(content, out var text))
                {
                    return(RetrieveEntityResult <TransformationText> .FromError("Failed to parse the messages."));
                }

                return(RetrieveEntityResult <TransformationText> .FromSuccess(text));
            }
        }
Пример #30
0
        public async Task <RetrieveEntityResult <Roleplay> > GetUserRoleplayByNameAsync
        (
            Server server,
            User roleplayOwner,
            string roleplayName
        )
        {
            roleplayOwner = _database.NormalizeReference(roleplayOwner);
            server        = _database.NormalizeReference(server);

            var roleplay = await GetRoleplays(server)
                           .FirstOrDefaultAsync
                           (
                rp =>
                rp.Name.ToLower().Equals(roleplayName.ToLower()) &&
                rp.Owner == roleplayOwner
                           );

            if (roleplay is null)
            {
                return(RetrieveEntityResult <Roleplay> .FromError("You don't own a roleplay with that name."));
            }

            return(RetrieveEntityResult <Roleplay> .FromSuccess(roleplay));
        }