示例#1
0
 internal static string GetTranscriptId(Transcript transcript)
 {
     return(FormatUtilities.CombineIdAndVersion(transcript.Id, transcript.Version));
 }
        /// <summary>
        /// Processes the image.
        /// </summary>
        /// <param name="context">
        /// the <see cref="T:System.Web.HttpContext">HttpContext</see> object that provides
        /// references to the intrinsic server objects
        /// </param>
        /// <returns>
        /// The <see cref="T:System.Threading.Tasks.Task"/>.
        /// </returns>
        private async Task ProcessImageAsync(HttpContext context)
        {
            HttpRequest request = context.Request;
            string      rawUrl  = this.GetRequestUrl(request);

            // Should we ignore this request?
            if (string.IsNullOrWhiteSpace(rawUrl) || rawUrl.ToUpperInvariant().Contains("IPIGNORE=TRUE"))
            {
                return;
            }

            // Sometimes the request is url encoded
            // See https://github.com/JimBobSquarePants/ImageProcessor/issues/478
            // This causes a bit of a nightmare as the incoming request is corrupted and cannot be used for splitting
            // out each url part. This becomes a manual job.
            string url             = rawUrl;
            string applicationPath = request.ApplicationPath;

            IImageService currentService = this.GetImageServiceForRequest(url, applicationPath);

            if (currentService != null)
            {
                // Parse url
                string requestPath, queryString;
                UrlParser.ParseUrl(url, currentService.Prefix, out requestPath, out queryString);

                // Map the request path if file local.
                bool isFileLocal = currentService.IsFileLocalService;
                if (currentService.IsFileLocalService)
                {
                    requestPath = HostingEnvironment.MapPath(requestPath);
                }

                if (string.IsNullOrWhiteSpace(requestPath))
                {
                    return;
                }

                // Parse any protocol values from settings if no protocol is present.
                if (currentService.Settings.ContainsKey("Protocol") && (ProtocolRegex.Matches(requestPath).Count == 0 || ProtocolRegex.Matches(requestPath)[0].Index > 0))
                {
                    // ReSharper disable once PossibleNullReferenceException
                    requestPath = currentService.Settings["Protocol"] + "://" + requestPath.TrimStart('/');
                }

                // Replace any presets in the querystring with the actual value.
                queryString = this.ReplacePresetsInQueryString(queryString);

                HttpContextWrapper httpContextBase = new HttpContextWrapper(context);

                // Execute the handler which can change the querystring
                //  LEGACY:
#pragma warning disable 618
                queryString = this.CheckQuerystringHandler(context, queryString, rawUrl);
#pragma warning restore 618

                // NEW WAY:
                ValidatingRequestEventArgs validatingArgs = new ValidatingRequestEventArgs(httpContextBase, queryString);
                this.OnValidatingRequest(validatingArgs);

                // If the validation has failed based on events, return
                if (validatingArgs.Cancel)
                {
                    ImageProcessorBootstrapper.Instance.Logger.Log <ImageProcessingModule>("Image processing has been cancelled by an event");
                    return;
                }

                // Re-assign based on event handlers
                queryString = validatingArgs.QueryString;

                // Break out if we don't meet critera.
                bool interceptAll = interceptAllRequests != null && interceptAllRequests.Value;
                if (string.IsNullOrWhiteSpace(requestPath) || (!interceptAll && string.IsNullOrWhiteSpace(queryString)))
                {
                    return;
                }

                // Check whether the path is valid for other requests.
                // We've already checked the unprefixed requests in GetImageServiceForRequest().
                if (!string.IsNullOrWhiteSpace(currentService.Prefix) && !currentService.IsValidRequest(requestPath))
                {
                    return;
                }

                using (await Locker.LockAsync(rawUrl))
                {
                    // Create a new cache to help process and cache the request.
                    this.imageCache = (IImageCache)ImageProcessorConfiguration.Instance
                                      .ImageCache.GetInstance(requestPath, url, queryString);

                    // Is the file new or updated?
                    bool isNewOrUpdated = await this.imageCache.IsNewOrUpdatedAsync();

                    string cachedPath = this.imageCache.CachedPath;

                    // Only process if the file has been updated.
                    if (isNewOrUpdated)
                    {
                        byte[] imageBuffer = null;
                        string mimeType;

                        try
                        {
                            imageBuffer = await currentService.GetImage(requestPath);
                        }
                        catch (HttpException ex)
                        {
                            // We want 404's to be handled by IIS so that other handlers/modules can still run.
                            if (ex.GetHttpCode() == (int)HttpStatusCode.NotFound)
                            {
                                ImageProcessorBootstrapper.Instance.Logger.Log <ImageProcessingModule>(ex.Message);
                                return;
                            }
                        }

                        if (imageBuffer == null)
                        {
                            return;
                        }

                        // Using recyclable streams here should dramatically reduce the overhead required
                        using (MemoryStream inStream = MemoryStreamPool.Shared.GetStream("inStream", imageBuffer, 0, imageBuffer.Length))
                        {
                            // Process the Image. Use a recyclable stream here to reduce the allocations
                            MemoryStream outStream = MemoryStreamPool.Shared.GetStream();

                            if (!string.IsNullOrWhiteSpace(queryString))
                            {
                                // Animation is not a processor but can be a specific request so we should allow it.
                                bool processAnimation;
                                AnimationProcessMode mode = this.ParseAnimationMode(queryString, out processAnimation);

                                // Attempt to match querystring and processors.
                                IWebGraphicsProcessor[] processors = ImageFactoryExtensions.GetMatchingProcessors(queryString);
                                if (processors.Any() || processAnimation)
                                {
                                    // Process the image.
                                    bool exif  = preserveExifMetaData != null && preserveExifMetaData.Value;
                                    bool gamma = fixGamma != null && fixGamma.Value;

                                    using (ImageFactory imageFactory = new ImageFactory(exif, gamma)
                                    {
                                        AnimationProcessMode = mode
                                    })
                                    {
                                        imageFactory.Load(inStream).AutoProcess(processors).Save(outStream);
                                        mimeType = imageFactory.CurrentImageFormat.MimeType;
                                    }
                                }
                                else if (this.ParseCacheBuster(queryString))
                                {
                                    // We're cachebustng. Allow the value to be cached
                                    await inStream.CopyToAsync(outStream);

                                    mimeType = FormatUtilities.GetFormat(outStream).MimeType;
                                }
                                else
                                {
                                    // No match? Someone is either attacking the server or hasn't read the instructions.
                                    // Either way throw an exception to prevent caching.
                                    string message = $"The request {request.Unvalidated.RawUrl} could not be understood by the server due to malformed syntax.";
                                    ImageProcessorBootstrapper.Instance.Logger.Log <ImageProcessingModule>(message);
                                    throw new HttpException((int)HttpStatusCode.BadRequest, message);
                                }
                            }
                            else
                            {
                                // We're capturing all requests.
                                await inStream.CopyToAsync(outStream);

                                mimeType = FormatUtilities.GetFormat(outStream).MimeType;
                            }

                            // Fire the post processing event.
                            EventHandler <PostProcessingEventArgs> handler = OnPostProcessing;
                            if (handler != null)
                            {
                                string extension             = Path.GetExtension(cachedPath);
                                PostProcessingEventArgs args = new PostProcessingEventArgs
                                {
                                    Context        = context,
                                    ImageStream    = outStream,
                                    ImageExtension = extension
                                };

                                handler(this, args);
                                outStream = args.ImageStream;
                            }

                            // Add to the cache.
                            await this.imageCache.AddImageToCacheAsync(outStream, mimeType);

                            // Cleanup
                            outStream.Dispose();
                        }

                        // Store the response type and cache dependency in the context for later retrieval.
                        context.Items[CachedResponseTypeKey] = mimeType;
                        bool isFileCached = new Uri(cachedPath).IsFile;

                        if (isFileLocal)
                        {
                            if (isFileCached)
                            {
                                // Some services might only provide filename so we can't monitor for the browser.
                                context.Items[CachedResponseFileDependency] = Path.GetFileName(requestPath) == requestPath
                                    ? new[] { cachedPath }
                                    : new[] { requestPath, cachedPath };
                            }
                            else
                            {
                                context.Items[CachedResponseFileDependency] = Path.GetFileName(requestPath) == requestPath
                                    ? null
                                    : new[] { requestPath };
                            }
                        }
                        else if (isFileCached)
                        {
                            context.Items[CachedResponseFileDependency] = new[] { cachedPath };
                        }
                    }

                    // The cached file is valid so just rewrite the path.
                    this.imageCache.RewritePath(context); //

                    // Redirect if not a locally store file.
                    if (!new Uri(cachedPath).IsFile)
                    {
                        context.ApplicationInstance.CompleteRequest();
                    }

                    if (isNewOrUpdated)
                    {
                        // Trim the cache.
                        await this.imageCache.TrimCacheAsync();
                    }
                }
            }
        }
示例#3
0
        public async Task SearchAsync(
            [Summary("The user whose infractions are to be displayed.")]
            [Remainder] DiscordUserOrMessageAuthorEntity subjectEntity)
        {
            var requestor = Context.User.Mention;
            var subject   = await UserService.GetGuildUserSummaryAsync(Context.Guild.Id, subjectEntity.UserId);

            var infractions = await ModerationService.SearchInfractionsAsync(
                new InfractionSearchCriteria
            {
                GuildId   = Context.Guild.Id,
                SubjectId = subjectEntity.UserId,
                IsDeleted = false
            },
                new[]
            {
                new SortingCriteria()
                {
                    PropertyName = nameof(InfractionSummary.CreateAction.Created),
                    Direction    = SortDirection.Descending,
                },
            });

            if (infractions.Count == 0)
            {
                await ReplyAsync(Format.Code("No infractions"));

                return;
            }

            var infractionQuery = infractions.Select(infraction => new
            {
                Id        = infraction.Id,
                Created   = infraction.CreateAction.Created.ToUniversalTime().ToString("yyyy MMM dd"),
                Type      = infraction.Type,
                Reason    = infraction.Reason,
                Rescinded = infraction.RescindAction != null
            });

            var counts = await ModerationService.GetInfractionCountsForUserAsync(subjectEntity.UserId);

            // https://modix.gg/infractions?subject=12345
            var url = new UriBuilder(Config.WebsiteBaseUrl)
            {
                Path  = "/infractions",
                Query = $"subject={subject.UserId}"
            }.RemoveDefaultPort().ToString();

            var builder = new EmbedBuilder()
                          .WithTitle($"Infractions for user: {subject.GetFullUsername()}")
                          .WithDescription(FormatUtilities.FormatInfractionCounts(counts))
                          .WithUrl(url)
                          .WithColor(new Color(0xA3BF0B));

            foreach (var infraction in infractionQuery)
            {
                // https://modix.gg/infractions?id=123
                var infractionUrl = new UriBuilder(Config.WebsiteBaseUrl)
                {
                    Path  = "/infractions",
                    Query = $"id={infraction.Id}"
                }.ToString();

                var emoji = GetEmojiForInfractionType(infraction.Type);

                builder.AddField(
                    $"#{infraction.Id} - \\{emoji} {infraction.Type} - Created: {infraction.Created}{(infraction.Rescinded ? " - [RESCINDED]" : "")}",
                    Format.Url($"Reason: {infraction.Reason}", infractionUrl)
                    );
            }

            var embed = builder.Build();

            await Context.Channel.SendMessageAsync(
                $"Requested by {requestor}",
                embed : embed)
            .ConfigureAwait(false);
        }
示例#4
0
        private void AddPromotionsToEmbed(StringBuilder builder, IReadOnlyCollection <PromotionCampaignSummary> promotions)
        {
            if (promotions.Count == 0)
            {
                return;
            }

            builder.AppendLine();
            builder.AppendLine(Format.Bold("\u276F Promotion History"));

            foreach (var promotion in promotions.OrderByDescending(x => x.CloseAction.Id).Take(5))
            {
                builder.AppendLine($"• {MentionUtils.MentionRole(promotion.TargetRole.Id)} {FormatUtilities.FormatTimeAgo(_utcNow, promotion.CloseAction.Created)}");
            }
        }
 public void SplitVersion_ReturnNull_WithNullInput()
 {
     var result = FormatUtilities.SplitVersion(null);
     Assert.Null(result.Id);
     Assert.Equal(0, result.Version);
 }
示例#6
0
        private static CacheFile TryMatchFilename(string ndbPath, Func <string, Match> matcher, MiniCacheType type,
                                                  ChromosomeRenamer renamer)
        {
            string filename = Path.GetFileName(ndbPath);

            if (filename == null)
            {
                return(null);
            }

            var match = matcher(filename);

            if (!match.Success)
            {
                return(null);
            }

            IUpdater updater;
            string   id, transcriptDataSource;
            int      position;
            ushort   refIndex;

            switch (type)
            {
            case MiniCacheType.Transcript:
                var tuple = FormatUtilities.SplitVersion(match.Groups[1].Value);
                id                   = tuple.Item1;
                refIndex             = renamer.GetReferenceIndex(match.Groups[2].Value);
                transcriptDataSource = match.Groups[3].Value;
                updater              = new TranscriptUpdater(id, refIndex, transcriptDataSource);
                break;

            case MiniCacheType.Regulatory:
                id                   = match.Groups[1].Value;
                refIndex             = renamer.GetReferenceIndex(match.Groups[2].Value);
                transcriptDataSource = match.Groups[3].Value;
                updater              = new RegulatoryUpdater(id, refIndex, transcriptDataSource);
                break;

            case MiniCacheType.Position:
                refIndex = renamer.GetReferenceIndex(match.Groups[1].Value);
                position = int.Parse(match.Groups[2].Value);
                string refAllele = match.Groups[3].Value;
                string altAllele = match.Groups[4].Value;
                transcriptDataSource = match.Groups[5].Value;
                updater = new PositionUpdater(refIndex, position, refAllele, altAllele, transcriptDataSource);
                break;

            case MiniCacheType.PositionRange:
                refIndex = renamer.GetReferenceIndex(match.Groups[1].Value);
                position = int.Parse(match.Groups[2].Value);
                int endPosition = int.Parse(match.Groups[3].Value);
                transcriptDataSource = match.Groups[4].Value;
                updater = new PositionRangeUpdater(refIndex, position, endPosition, transcriptDataSource);
                break;

            default:
                throw new GeneralException($"Unexpected mini-cache type encountered: {type}");
            }

            return(new CacheFile(ndbPath, updater.RefIndex, ConvertTranscriptDataSource(updater.TranscriptDataSource),
                                 type, updater));
        }
示例#7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PhysicalFileSystemCacheResolver"/> class.
 /// </summary>
 /// <param name="metaFileInfo">The cached metadata file info.</param>
 /// <param name="formatUtilities">
 /// Contains various format helper methods based on the current configuration.
 /// </param>
 public PhysicalFileSystemCacheResolver(IFileInfo metaFileInfo, FormatUtilities formatUtilities)
 {
     this.metaFileInfo    = metaFileInfo;
     this.formatUtilities = formatUtilities;
 }
示例#8
0
        public async Task ReplInvokeAsync(
            [Remainder]
            [Summary("The code to execute.")]
            string code)
        {
            if (!(Context.Channel is IGuildChannel) || !(Context.User is IGuildUser guildUser))
            {
                await ModifyOrSendErrorEmbed("The REPL can only be executed in public guild channels.");

                return;
            }

            var message = await Context.Channel
                          .SendMessageAsync(embed : new EmbedBuilder()
                                            .WithTitle("REPL Executing")
                                            .WithUserAsAuthor(Context.User)
                                            .WithColor(Color.LightOrange)
                                            .WithDescription($"Compiling and Executing [your code]({Context.Message.GetJumpUrl()})...")
                                            .Build());

            var content = FormatUtilities.BuildContent(code);

            HttpResponseMessage res;

            try
            {
                var client = _httpClientFactory.CreateClient();
                res = await client.PostAsync(_replUrl, content);
            }
            catch (IOException ex)
            {
                await ModifyOrSendErrorEmbed("Recieved an invalid response from the REPL service." +
                                             $"\n\n{Format.Bold("Details:")}\n{ex.Message}", message);

                return;
            }
            catch (Exception ex)
            {
                await ModifyOrSendErrorEmbed("An error occurred while sending a request to the REPL service. " +
                                             "This is probably due to container exhaustion - try again later." +
                                             $"\n\n{Format.Bold("Details:")}\n{ex.Message}", message);

                return;
            }

            if (!res.IsSuccessStatusCode & res.StatusCode != HttpStatusCode.BadRequest)
            {
                await ModifyOrSendErrorEmbed($"Status Code: {(int)res.StatusCode} {res.StatusCode}", message);

                return;
            }

            var parsedResult = JsonConvert.DeserializeObject <Result>(await res.Content.ReadAsStringAsync());

            var embed = await BuildEmbedAsync(guildUser, parsedResult);

            await _autoRemoveMessageService.RegisterRemovableMessageAsync(Context.User, embed, async (e) =>
            {
                await message.ModifyAsync(a =>
                {
                    a.Content = string.Empty;
                    a.Embed   = e.Build();
                });
                return(message);
            });

            await Context.Message.DeleteAsync();
        }
示例#9
0
        private async Task AddPromotionsToEmbedAsync(ulong userId, StringBuilder builder)
        {
            var promotions = await _promotionsService.GetPromotionsForUserAsync(Context.Guild.Id, userId);

            if (promotions.Count == 0)
            {
                return;
            }

            builder.AppendLine();
            builder.AppendLine(Format.Bold("\u276F Promotion History"));

            foreach (var promotion in promotions.OrderByDescending(x => x.CloseAction.Id).Take(5))
            {
                builder.AppendLine($"• {MentionUtils.MentionRole(promotion.TargetRole.Id)} {FormatUtilities.FormatTimeAgo(_utcNow, promotion.CloseAction.Created)}");
            }
        }
示例#10
0
        /// <summary>
        /// Processes the image.
        /// </summary>
        /// <param name="context">
        /// the <see cref="T:System.Web.HttpContext">HttpContext</see> object that provides
        /// references to the intrinsic server objects
        /// </param>
        /// <returns>
        /// The <see cref="T:System.Threading.Tasks.Task"/>.
        /// </returns>
        private async Task ProcessImageAsync(HttpContext context)
        {
            HttpRequest request = context.Request;
            string      rawUrl  = this.GetRequestUrl(request);

            // Should we ignore this request?
            if (string.IsNullOrWhiteSpace(rawUrl) || rawUrl.IndexOf("ipignore=true", StringComparison.OrdinalIgnoreCase) >= 0)
            {
                return;
            }

            // Sometimes the request is url encoded
            // See https://github.com/JimBobSquarePants/ImageProcessor/issues/478
            // This causes a bit of a nightmare as the incoming request is corrupted and cannot be used for splitting
            // out each url part. This becomes a manual job.
            string url             = rawUrl;
            string applicationPath = request.ApplicationPath;

            IImageService currentService = this.GetImageServiceForRequest(url, applicationPath);

            if (currentService == null)
            {
                return;
            }

            // Parse url
            UrlParser.ParseUrl(url, currentService.Prefix, out string requestPath, out string queryString);
            string originalQueryString = queryString;

            // Replace any presets in the querystring with the actual value.
            queryString = this.ReplacePresetsInQueryString(queryString);

            var httpContextBase = new HttpContextWrapper(context);

            // Execute the handler which can change the querystring
            var validatingArgs = new ValidatingRequestEventArgs(httpContextBase, queryString);

            this.OnValidatingRequest(validatingArgs);

            // If the validation has failed based on events, return
            if (validatingArgs.Cancel)
            {
                ImageProcessorBootstrapper.Instance.Logger.Log <ImageProcessingModule>($"Image processing for {url} has been cancelled by an event");
                return;
            }

            // Re-assign based on event handlers
            queryString = validatingArgs.QueryString;
            if (string.IsNullOrWhiteSpace(originalQueryString) && !string.IsNullOrWhiteSpace(queryString))
            {
                // Add new query string to URL
                url = url + "?" + queryString;
            }
            else if (!string.IsNullOrWhiteSpace(queryString) && !string.Equals(originalQueryString, queryString))
            {
                url = Regex.Replace(url, Regex.Escape(originalQueryString), queryString, RegexOptions.IgnoreCase);
            }

            // Map the request path if file local.
            bool isFileLocal = currentService.IsFileLocalService;

            if (currentService.IsFileLocalService)
            {
                requestPath = HostingEnvironment.MapPath(requestPath);
            }

            if (string.IsNullOrWhiteSpace(requestPath))
            {
                return;
            }

            // Parse any protocol values from settings if no protocol is present.
            if (currentService.Settings.TryGetValue("Protocol", out var protocol) && (ProtocolRegex.Matches(requestPath) is var matches && (matches.Count == 0 || matches[0].Index > 0)))
            {
                // ReSharper disable once PossibleNullReferenceException
                requestPath = protocol + "://" + requestPath.TrimStart('/');
            }

            // Break out if we don't meet critera.
            // First check that the request path is valid and whether we are intercepting all requests or the querystring is valid.
            bool interceptAll = interceptAllRequests != null && interceptAllRequests.Value;

            if (string.IsNullOrWhiteSpace(requestPath) || (!interceptAll && string.IsNullOrWhiteSpace(queryString)))
            {
                return;
            }

            // Check whether the path is valid for other requests.
            // We've already checked the unprefixed requests in GetImageServiceForRequest().
            if (!string.IsNullOrWhiteSpace(currentService.Prefix) && !currentService.IsValidRequest(requestPath))
            {
                return;
            }

            bool   isNewOrUpdated = false;
            string cachedPath     = string.Empty;
            bool   processing     = false;

            IWebGraphicsProcessor[] processors = null;
            AnimationProcessMode    mode       = AnimationProcessMode.First;

            using (await Locker.ReaderLockAsync(rawUrl).ConfigureAwait(false))
            {
                // Parse the url to see whether we should be doing any work.
                // If we're not intercepting all requests and we don't have valid instructions we shoul break here.
                if (!string.IsNullOrWhiteSpace(queryString))
                {
                    // Attempt to match querystring and processors.
                    processors = ImageFactoryExtensions.GetMatchingProcessors(queryString);

                    // Animation is not a processor but can be a specific request so we should allow it.
                    mode = this.ParseAnimationMode(queryString, out bool processAnimation);

                    // Are we processing or cache busting?
                    processing = processors != null && (processors.Length > 0 || processAnimation);
                    bool cacheBusting = ParseCacheBuster(queryString);
                    if (!processing && !cacheBusting)
                    {
                        // No? Someone is either attacking the server or hasn't read the instructions.
                        string message = $"The request {request.Unvalidated.RawUrl} could not be understood by the server due to malformed syntax.";
                        ImageProcessorBootstrapper.Instance.Logger.Log <ImageProcessingModule>(message);
                        return;
                    }
                }

                // Create a new cache to help process and cache the request.
                this.imageCache = (IImageCache)ImageProcessorConfiguration.Instance
                                  .ImageCache.GetInstance(requestPath, url, queryString);

                // Is the file new or updated?
                isNewOrUpdated = await this.imageCache.IsNewOrUpdatedAsync().ConfigureAwait(false);

                cachedPath = this.imageCache.CachedPath;

                if (!isNewOrUpdated)
                {
                    // The cached file is valid so just rewrite the path.
                    this.imageCache.RewritePath(context);

                    // Redirect if not a locally store file.
                    if (!new Uri(cachedPath).IsFile)
                    {
                        context.ApplicationInstance.CompleteRequest();
                    }

                    return;
                }
            }

            // Only process if the file has been updated.
            using (await Locker.WriterLockAsync(rawUrl).ConfigureAwait(false))
            {
                // Ok let's get the image
                byte[] imageBuffer = null;
                string mimeType;

                try
                {
                    if (currentService is IImageService2 imageService2)
                    {
                        imageBuffer = await imageService2.GetImage(requestPath, context).ConfigureAwait(false);
                    }
                    else
                    {
                        imageBuffer = await currentService.GetImage(requestPath).ConfigureAwait(false);
                    }
                }
                catch (HttpException ex)
                {
                    // We want 404's to be handled by IIS so that other handlers/modules can still run.
                    if (ex.GetHttpCode() == (int)HttpStatusCode.NotFound)
                    {
                        ImageProcessorBootstrapper.Instance.Logger.Log <ImageProcessingModule>(ex.Message);
                        return;
                    }
                }

                if (imageBuffer == null)
                {
                    return;
                }

                // Using recyclable streams here should dramatically reduce the overhead required
                using (MemoryStream inStream = MemoryStreamPool.Shared.GetStream("inStream", imageBuffer, 0, imageBuffer.Length))
                {
                    // Process the Image. Use a recyclable stream here to reduce the allocations
                    MemoryStream outStream = MemoryStreamPool.Shared.GetStream();

                    if (!string.IsNullOrWhiteSpace(queryString))
                    {
                        if (processing)
                        {
                            // Process the image.
                            bool         exif     = preserveExifMetaData != null && preserveExifMetaData.Value;
                            MetaDataMode metaMode = !exif ? MetaDataMode.None : metaDataMode.Value;
                            bool         gamma    = fixGamma != null && fixGamma.Value;

                            try
                            {
                                using (var imageFactory = new ImageFactory(metaMode, gamma)
                                {
                                    AnimationProcessMode = mode
                                })
                                {
                                    imageFactory.Load(inStream).AutoProcess(processors).Save(outStream);
                                    mimeType = imageFactory.CurrentImageFormat.MimeType;
                                }
                            }
                            catch (ImageFormatException)
                            {
                                ImageProcessorBootstrapper.Instance.Logger.Log <ImageProcessingModule>($"Request {url} is not a valid image.");
                                return;
                            }
                        }
                        else
                        {
                            // We're cache-busting. Allow the value to be cached
                            await inStream.CopyToAsync(outStream).ConfigureAwait(false);

                            mimeType = FormatUtilities.GetFormat(outStream).MimeType;
                        }
                    }
                    else
                    {
                        // We're capturing all requests.
                        await inStream.CopyToAsync(outStream).ConfigureAwait(false);

                        mimeType = FormatUtilities.GetFormat(outStream).MimeType;
                    }

                    // Fire the post processing event.
                    EventHandler <PostProcessingEventArgs> handler = OnPostProcessing;
                    if (handler != null)
                    {
                        string extension = Path.GetExtension(cachedPath);
                        var    args      = new PostProcessingEventArgs
                        {
                            Context        = context,
                            ImageStream    = outStream,
                            ImageExtension = extension
                        };

                        handler(this, args);
                        outStream = args.ImageStream;
                    }

                    // Add to the cache.
                    await this.imageCache.AddImageToCacheAsync(outStream, mimeType).ConfigureAwait(false);

                    // Cleanup
                    outStream.Dispose();
                }

                // Store the response type and cache dependency in the context for later retrieval.
                context.Items[CachedResponseTypeKey] = mimeType;
                bool isFileCached = new Uri(cachedPath).IsFile;

                if (isFileLocal)
                {
                    if (isFileCached)
                    {
                        // Some services might only provide filename so we can't monitor for the browser.
                        context.Items[CachedResponseFileDependency] = Path.GetFileName(requestPath) == requestPath
                            ? new[] { cachedPath }
                            : new[] { requestPath, cachedPath };
                    }
                    else
                    {
                        context.Items[CachedResponseFileDependency] = Path.GetFileName(requestPath) == requestPath
                            ? null
                            : new[] { requestPath };
                    }
                }
                else if (isFileCached)
                {
                    context.Items[CachedResponseFileDependency] = new[] { cachedPath };
                }

                // The cached file has been saved so now rewrite the path.
                this.imageCache.RewritePath(context);

                // Redirect if not a locally store file.
                if (!new Uri(cachedPath).IsFile)
                {
                    context.ApplicationInstance.CompleteRequest();
                }

                // Trim the cache.
                await this.imageCache.TrimCacheAsync().ConfigureAwait(false);
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="FileSystemImageProvider"/> class.
 /// </summary>
 /// <param name="fileSystem">The file system.</param>
 /// <param name="formatUtilities">The format utilities.</param>
 public FileSystemImageProvider(IFileSystem fileSystem, FormatUtilities formatUtilities)
 {
     this.fileSystem      = fileSystem;
     this.formatUtilities = formatUtilities;
 }
示例#12
0
        /// <inheritdoc />
        public async Task HandleNotificationAsync(MessageReceivedNotification notification, CancellationToken cancellationToken = default)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            if (!(notification.Message is IUserMessage userMessage) ||
                (userMessage.Author is null))
            {
                return;
            }

            if (!(userMessage.Author is IGuildUser author) ||
                (author.Guild is null) ||
                author.IsBot ||
                author.IsWebhook)
            {
                return;
            }

            if (userMessage.Content.Length <= 1)
            {
                return;
            }

            var argPos = await _commandPrefixParser.TryFindCommandArgPosAsync(userMessage, cancellationToken);

            if (argPos is null)
            {
                return;
            }

            var commandContext = new CommandContext(DiscordClient, userMessage);

            await AuthorizationService.OnAuthenticatedAsync(author);

            IResult commandResult = null;
            var     commandTimer  = Stopwatch.StartNew();

            try
            {
                commandResult = await CommandService.ExecuteAsync(commandContext, argPos.Value, ServiceProvider);
            }
            finally
            {
                commandTimer.Stop();
                var duration = commandTimer.ElapsedMilliseconds;

                if (!(_stats is null) && (commandResult.IsSuccess || !string.Equals(commandResult.ErrorReason, "UnknownCommand", StringComparison.OrdinalIgnoreCase)))
                {
                    var commandInfo = CommandService.Search(commandContext, argPos.Value).Commands?.FirstOrDefault();
                    if (commandInfo is { } match)
                    {
                        var name = match.Command?.Name.ToLowerInvariant();

                        _stats?.Timer("command_duration_ms", duration,
                                      tags: new[] { $"guild:{commandContext.Guild.Name}", $"success:{commandResult.IsSuccess}", $"command:{name}" });
                    }
                }
            }

            if (!commandResult.IsSuccess)
            {
                var error = $"{commandResult.Error}: {commandResult.ErrorReason}";

                if (string.Equals(commandResult.ErrorReason, "UnknownCommand", StringComparison.OrdinalIgnoreCase))
                {
                    Log.Error(error);
                }
                else
                {
                    Log.Warning(error);
                }

                if (commandResult.Error == CommandError.Exception)
                {
                    await commandContext.Channel.SendMessageAsync($"Error: {FormatUtilities.SanitizeEveryone(commandResult.ErrorReason)}");
                }
                else
                {
                    await CommandErrorHandler.AssociateError(userMessage, error);
                }
            }

            stopwatch.Stop();
            Log.Information($"Command took {stopwatch.ElapsedMilliseconds}ms to process: {commandContext.Message}");
        }
示例#13
0
 public AppImageProvider(IOptions <AppSettingsModel> appSettings, IFileProvider fileProvider, FormatUtilities formatUtilities)
 {
     this.appSettings     = appSettings;
     this.fileProvider    = fileProvider;
     this.formatUtilities = formatUtilities;
     this.requestPath     = this.appSettings.Value.Common.RoutePrefix;
 }
示例#14
0
        /// <summary>
        /// Loads the image to process. Always call this method first.
        /// </summary>
        /// <param name="imagePath">The absolute path to the image to load.</param>
        /// <returns>
        /// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
        /// </returns>
        public ImageFactory Load(string imagePath)
        {
            FileInfo fileInfo = new FileInfo(imagePath);

            if (fileInfo.Exists)
            {
                this.ImagePath = imagePath;

                // Open a file stream to prevent the need for lock.
                using (FileStream fileStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
                {
                    ISupportedImageFormat format = FormatUtilities.GetFormat(fileStream);

                    if (format == null)
                    {
                        throw new ImageFormatException("Input stream is not a supported format.");
                    }

                    MemoryStream memoryStream = new MemoryStream();

                    // Copy the stream.
                    fileStream.CopyTo(memoryStream);

                    // Set the position to 0 afterwards.
                    memoryStream.Position = 0;

                    // Set our image as the memory stream value.
                    this.Image = format.Load(memoryStream);

                    // Store the stream so we can dispose of it later.
                    this.InputStream = memoryStream;

                    // Set the other properties.
                    format.Quality   = DefaultQuality;
                    format.IsIndexed = FormatUtilities.IsIndexed(this.Image);

                    this.backupFormat       = format;
                    this.CurrentImageFormat = format;

                    // Always load the data.
                    foreach (PropertyItem propertyItem in this.Image.PropertyItems)
                    {
                        this.ExifPropertyItems[propertyItem.Id] = propertyItem;
                    }

                    this.backupExifPropertyItems = this.ExifPropertyItems;

                    // Ensure the image is in the most efficient format.
                    Image formatted = this.Image.Copy();
                    this.Image.Dispose();
                    this.Image = formatted;

                    this.ShouldProcess = true;
                }
            }
            else
            {
                throw new FileNotFoundException(imagePath);
            }

            return(this);
        }
示例#15
0
文件: IlModule.cs 项目: ofcith/MODiX
        public async Task ReplInvokeAsync(
            [Remainder]
            [Summary("The code to decompile.")]
            string code)
        {
            if (!(Context.Channel is SocketGuildChannel))
            {
                await ReplyAsync("il can only be executed in public guild channels.");

                return;
            }
            code = FormatUtilities.StripFormatting(code);
            if (code.Length > 1000)
            {
                await ReplyAsync("Decompile Failed: Code is greater than 1000 characters in length");

                return;
            }

            var guildUser = Context.User as SocketGuildUser;
            var message   = await Context.Channel.SendMessageAsync("Working...");

            var content = FormatUtilities.BuildContent(code);

            HttpResponseMessage res;

            try
            {
                var client = _httpClientFactory.CreateClient();

                using (var tokenSrc = new CancellationTokenSource(30000))
                {
                    res = await client.PostAsync(_ilUrl, content, tokenSrc.Token);
                }
            }
            catch (TaskCanceledException)
            {
                await message.ModifyAsync(a => { a.Content = $"Gave up waiting for a response from the Decompile service."; });

                return;
            }
            catch (Exception ex)
            {
                await message.ModifyAsync(a => { a.Content = $"Decompile failed: {ex.Message}"; });

                Log.Error(ex, "Decompile Failed");
                return;
            }

            if (!res.IsSuccessStatusCode & res.StatusCode != HttpStatusCode.BadRequest)
            {
                await message.ModifyAsync(a => { a.Content = $"Decompile failed: {res.StatusCode}"; });

                return;
            }

            var parsedResult = await res.Content.ReadAsStringAsync();

            var embed = await BuildEmbedAsync(guildUser, code, parsedResult);

            await _autoRemoveMessageService.RegisterRemovableMessageAsync(Context.User, embed, async (e) =>
            {
                await message.ModifyAsync(a =>
                {
                    a.Content = string.Empty;
                    a.Embed   = e.Build();
                });
                return(message);
            });

            await Context.Message.DeleteAsync();
        }
示例#16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CacheHash"/> class.
 /// </summary>
 /// <param name="options">The middleware configuration options</param>
 public CacheHashBaseline(IOptions <ImageSharpMiddlewareOptions> options)
 {
     this.options         = options.Value;
     this.formatUtilities = new FormatUtilities(this.options.Configuration);
 }
示例#17
0
        /// <summary>
        /// Processes the image.
        /// </summary>
        /// <param name="context">
        /// the <see cref="T:System.Web.HttpContext">HttpContext</see> object that provides
        /// references to the intrinsic server objects
        /// </param>
        /// <returns>
        /// The <see cref="T:System.Threading.Tasks.Task"/>.
        /// </returns>
        private async Task ProcessImageAsync(HttpContext context)
        {
            HttpRequest request = context.Request;

            // Should we ignore this request?
            if (request.Unvalidated.RawUrl.ToUpperInvariant().Contains("IPIGNORE=TRUE"))
            {
                return;
            }

            IImageService currentService = this.GetImageServiceForRequest(request);

            if (currentService != null)
            {
                bool   isFileLocal    = currentService.IsFileLocalService;
                string url            = request.Url.ToString();
                bool   isLegacy       = ProtocolRegex.Matches(url).Count > 1;
                bool   hasMultiParams = url.Count(f => f == '?') > 1;
                string requestPath;
                string queryString   = string.Empty;
                string urlParameters = string.Empty;

                // Legacy support. I'd like to remove this asap.
                if (isLegacy && hasMultiParams)
                {
                    // We need to split the querystring to get the actual values we want.
                    string[] paths = url.Split('?');
                    requestPath = paths[1];

                    // Handle extension-less urls.
                    if (paths.Length > 3)
                    {
                        queryString   = paths[3];
                        urlParameters = paths[2];
                    }
                    else if (paths.Length > 1)
                    {
                        queryString = paths[2];
                    }
                }
                else
                {
                    if (string.IsNullOrWhiteSpace(currentService.Prefix))
                    {
                        requestPath = currentService.IsFileLocalService
                            ? HostingEnvironment.MapPath(request.Path)
                            : request.Path;
                        queryString = request.QueryString.ToString();
                    }
                    else
                    {
                        // Parse any protocol values from settings.
                        string protocol = currentService.Settings.ContainsKey("Protocol")
                                              ? currentService.Settings["Protocol"] + "://"
                                              : currentService.GetType() == typeof(RemoteImageService) ? request.Url.Scheme + "://" : string.Empty;

                        // Handle requests that require parameters.
                        if (hasMultiParams)
                        {
                            string[] paths = url.Split('?');
                            requestPath = protocol
                                          + request.Path.TrimStart('/').Remove(0, currentService.Prefix.Length).TrimStart('/')
                                          + "?" + paths[1];
                            queryString = paths[2];
                        }
                        else
                        {
                            requestPath = protocol + request.Path.TrimStart('/').Remove(0, currentService.Prefix.Length).TrimStart('/');
                            queryString = request.QueryString.ToString();
                        }
                    }
                }

                // Replace any presets in the querystring with the actual value.
                queryString = this.ReplacePresetsInQueryString(queryString);

                // Execute the handler which can change the querystring
                queryString = this.CheckQuerystringHandler(context, queryString, request.Unvalidated.RawUrl);

                // Break out if we don't meet critera.
                bool interceptAll = interceptAllRequests != null && interceptAllRequests.Value;
                if (string.IsNullOrWhiteSpace(requestPath) || (!interceptAll && string.IsNullOrWhiteSpace(queryString)))
                {
                    return;
                }

                string parts    = !string.IsNullOrWhiteSpace(urlParameters) ? "?" + urlParameters : string.Empty;
                string fullPath = string.Format("{0}{1}?{2}", requestPath, parts, queryString);
                object resourcePath;

                // More legacy support code.
                if (hasMultiParams)
                {
                    resourcePath = string.IsNullOrWhiteSpace(urlParameters)
                        ? new Uri(requestPath, UriKind.RelativeOrAbsolute)
                        : new Uri(requestPath + "?" + urlParameters, UriKind.RelativeOrAbsolute);
                }
                else
                {
                    resourcePath = requestPath;
                }

                // Check whether the path is valid for other requests.
                if (!currentService.IsValidRequest(resourcePath.ToString()))
                {
                    return;
                }

                string combined = requestPath + fullPath + queryString;
                using (await Locker.LockAsync(combined))
                {
                    // Create a new cache to help process and cache the request.
                    this.imageCache = (IImageCache)ImageProcessorConfiguration.Instance
                                      .ImageCache.GetInstance(requestPath, fullPath, queryString);

                    // Is the file new or updated?
                    bool isNewOrUpdated = await this.imageCache.IsNewOrUpdatedAsync();

                    string cachedPath = this.imageCache.CachedPath;

                    // Only process if the file has been updated.
                    if (isNewOrUpdated)
                    {
                        // Process the image.
                        bool exif  = preserveExifMetaData != null && preserveExifMetaData.Value;
                        bool gamma = fixGamma != null && fixGamma.Value;
                        AnimationProcessMode mode = this.ParseAnimationMode(queryString);

                        using (ImageFactory imageFactory = new ImageFactory(exif, gamma)
                        {
                            AnimationProcessMode = mode
                        })
                        {
                            byte[] imageBuffer = null;
                            string mimeType;

                            try
                            {
                                imageBuffer = await currentService.GetImage(resourcePath);
                            }
                            catch (HttpException ex)
                            {
                                // We want 404's to be handled by IIS so that other handlers/modules can still run.
                                if (ex.GetHttpCode() == (int)HttpStatusCode.NotFound)
                                {
                                    return;
                                }
                            }

                            if (imageBuffer == null)
                            {
                                return;
                            }

                            using (MemoryStream inStream = new MemoryStream(imageBuffer))
                            {
                                // Process the Image
                                MemoryStream outStream = new MemoryStream();

                                if (!string.IsNullOrWhiteSpace(queryString))
                                {
                                    imageFactory.Load(inStream).AutoProcess(queryString).Save(outStream);
                                    mimeType = imageFactory.CurrentImageFormat.MimeType;
                                }
                                else
                                {
                                    await inStream.CopyToAsync(outStream);

                                    mimeType = FormatUtilities.GetFormat(outStream).MimeType;
                                }

                                // Fire the post processing event.
                                EventHandler <PostProcessingEventArgs> handler = OnPostProcessing;
                                if (handler != null)
                                {
                                    string extension             = Path.GetExtension(cachedPath);
                                    PostProcessingEventArgs args = new PostProcessingEventArgs
                                    {
                                        Context        = context,
                                        ImageStream    = outStream,
                                        ImageExtension = extension
                                    };

                                    handler(this, args);
                                    outStream = args.ImageStream;
                                }

                                // Add to the cache.
                                await this.imageCache.AddImageToCacheAsync(outStream, mimeType);

                                // Cleanup
                                outStream.Dispose();
                            }

                            // Store the response type and cache dependency in the context for later retrieval.
                            context.Items[CachedResponseTypeKey] = mimeType;
                            bool isFileCached = new Uri(cachedPath).IsFile;

                            if (isFileLocal)
                            {
                                if (isFileCached)
                                {
                                    // Some services might only provide filename so we can't monitor for the browser.
                                    context.Items[CachedResponseFileDependency] = Path.GetFileName(requestPath) == requestPath
                                        ? new List <string> {
                                        cachedPath
                                    }
                                        : new List <string> {
                                        requestPath, cachedPath
                                    };
                                }
                                else
                                {
                                    context.Items[CachedResponseFileDependency] = Path.GetFileName(requestPath) == requestPath
                                        ? null
                                        : new List <string> {
                                        requestPath
                                    };
                                }
                            }
                            else if (isFileCached)
                            {
                                context.Items[CachedResponseFileDependency] = new List <string> {
                                    cachedPath
                                };
                            }
                        }
                    }

                    // The cached file is valid so just rewrite the path.
                    this.imageCache.RewritePath(context);

                    // Redirect if not a locally store file.
                    if (!new Uri(cachedPath).IsFile)
                    {
                        context.ApplicationInstance.CompleteRequest();
                    }
                }
            }
        }
示例#18
0
        public async Task GetUserInfoAsync(
            [Summary("The user to retrieve information about, if any.")]
            DiscordUserEntity user = null)
        {
            user = user ?? new DiscordUserEntity(Context.User.Id);

            var timer = Stopwatch.StartNew();

            var userInfo = await UserService.GetUserInformationAsync(Context.Guild.Id, user.Id);

            if (userInfo == null)
            {
                await ReplyAsync("", embed : new EmbedBuilder()
                                 .WithTitle("Retrieval Error")
                                 .WithColor(Color.Red)
                                 .WithDescription("Sorry, we don't have any data for that user - and we couldn't find any, either.")
                                 .AddField("User Id", user.Id)
                                 .Build());

                return;
            }

            var builder = new StringBuilder();

            builder.AppendLine("**\u276F User Information**");
            builder.AppendLine("ID: " + userInfo.Id);
            builder.AppendLine("Profile: " + MentionUtils.MentionUser(userInfo.Id));

            if (userInfo.IsBanned)
            {
                builder.AppendLine("Status: **Banned** \\🔨");

                if (await AuthorizationService.HasClaimsAsync(Context.User as IGuildUser, AuthorizationClaim.ModerationRead))
                {
                    builder.AppendLine($"Ban Reason: {userInfo.BanReason}");
                }
            }
            else
            {
                builder.AppendLine($"Status: {userInfo.Status.Humanize()}");
            }

            if (userInfo.FirstSeen is DateTimeOffset firstSeen)
            {
                builder.AppendLine($"First Seen: {FormatUtilities.FormatTimeAgo(_utcNow, firstSeen)}");
            }

            if (userInfo.LastSeen is DateTimeOffset lastSeen)
            {
                builder.AppendLine($"Last Seen: {FormatUtilities.FormatTimeAgo(_utcNow, lastSeen)}");
            }

            try
            {
                await AddParticipationToEmbedAsync(user.Id, builder);
            }
            catch (Exception ex)
            {
                Log.LogError(ex, "An error occured while retrieving a user's message count.");
            }

            var embedBuilder = new EmbedBuilder()
                               .WithAuthor(userInfo.Username + "#" + userInfo.Discriminator)
                               .WithTimestamp(_utcNow);

            var avatar = userInfo.GetDefiniteAvatarUrl();

            embedBuilder.ThumbnailUrl   = avatar;
            embedBuilder.Author.IconUrl = avatar;

            await AddMemberInformationToEmbedAsync(userInfo, builder, embedBuilder);

            if (await AuthorizationService.HasClaimsAsync(Context.User as IGuildUser, AuthorizationClaim.ModerationRead))
            {
                await AddInfractionsToEmbedAsync(user.Id, builder);
            }

            embedBuilder.Description = builder.ToString();

            timer.Stop();
            embedBuilder.WithFooter(footer => footer.Text = $"Completed after {timer.ElapsedMilliseconds} ms");

            await ReplyAsync(string.Empty, embed : embedBuilder.Build());
        }
示例#19
0
        public async Task ReplInvoke([Remainder] string code)
        {
            if (!(Context.Channel is SocketGuildChannel))
            {
                await ReplyAsync("exec can only be executed in public guild channels.");

                return;
            }

            if (code.Length > 1000)
            {
                await ReplyAsync("Exec failed: Code is greater than 1000 characters in length");

                return;
            }

            var guildUser = Context.User as SocketGuildUser;
            var message   = await Context.Channel.SendMessageAsync("Working...");

            var content = FormatUtilities.BuildContent(code);

            HttpResponseMessage res;

            try
            {
                var tokenSrc = new CancellationTokenSource(30000);
                res = await _client.PostAsync(ReplRemoteUrl, content, tokenSrc.Token);
            }
            catch (TaskCanceledException)
            {
                await message.ModifyAsync(a => { a.Content = $"Gave up waiting for a response from the REPL service."; });

                return;
            }
            catch (Exception ex)
            {
                await message.ModifyAsync(a => { a.Content = $"Exec failed: {ex.Message}"; });

                Log.Error(ex, "Exec Failed");
                return;
            }

            if (!res.IsSuccessStatusCode & res.StatusCode != HttpStatusCode.BadRequest)
            {
                await message.ModifyAsync(a => { a.Content = $"Exec failed: {res.StatusCode}"; });

                return;
            }

            var parsedResult = JsonConvert.DeserializeObject <Result>(await res.Content.ReadAsStringAsync());

            var embed = await BuildEmbed(guildUser, parsedResult);

            await message.ModifyAsync(a =>
            {
                a.Content = string.Empty;
                a.Embed   = embed.Build();
            });

            await Context.Message.DeleteAsync();
        }
示例#20
0
        public async Task Search(
            [Summary("The user whose infractions are to be displayed.")]
            ulong subjectId)
        {
            var requestor = Context.User.Mention;
            var subject   = await UserService.GetGuildUserSummaryAsync(Context.Guild.Id, subjectId);

            var infractions = await ModerationService.SearchInfractionsAsync(
                new InfractionSearchCriteria
            {
                GuildId   = Context.Guild.Id,
                SubjectId = subjectId,
                IsDeleted = false
            },
                new[]
            {
                new SortingCriteria {
                    PropertyName = "CreateAction.Created", Direction = SortDirection.Descending
                }
            });

            if (infractions.Count == 0)
            {
                await ReplyAsync(Format.Code("No infractions"));

                return;
            }

            var infractionQuery = infractions.Select(infraction => new
            {
                Id        = infraction.Id,
                Created   = infraction.CreateAction.Created.ToUniversalTime().ToString("yyyy MMM dd"),
                Type      = infraction.Type.ToString(),
                Subject   = infraction.Subject.Username,
                Creator   = infraction.CreateAction.CreatedBy.DisplayName,
                Reason    = infraction.Reason,
                Rescinded = infraction.RescindAction != null
            }).OrderBy(s => s.Type);

            var counts = await ModerationService.GetInfractionCountsForUserAsync(subjectId);

            var builder = new EmbedBuilder()
                          .WithTitle($"Infractions for user: {subject.Username}#{subject.Discriminator}")
                          .WithDescription(FormatUtilities.FormatInfractionCounts(counts))
                          .WithUrl($"https://mod.gg/infractions/?subject={subject.UserId}")
                          .WithColor(new Color(0xA3BF0B))
                          .WithTimestamp(DateTimeOffset.UtcNow);

            foreach (var infraction in infractionQuery)
            {
                builder.AddField(
                    $"#{infraction.Id} - {infraction.Type} - Created: {infraction.Created}{(infraction.Rescinded ? " - [RESCINDED]" : "")}",
                    $"[Reason: {infraction.Reason}](https://mod.gg/infractions/?id={infraction.Id})"
                    );
            }

            var embed = builder.Build();

            await Context.Channel.SendMessageAsync(
                $"Requested by {requestor}",
                embed : embed)
            .ConfigureAwait(false);
        }
示例#21
0
        /// <inheritdoc />
        public async Task HandleNotificationAsync(MessageReceivedNotification notification, CancellationToken cancellationToken = default)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            if (!(notification.Message is IUserMessage userMessage) ||
                (userMessage.Author is null))
            {
                return;
            }

            if (!(userMessage.Author is IGuildUser author) ||
                (author.Guild is null) ||
                author.IsBot ||
                author.IsWebhook)
            {
                return;
            }

            var argPos = 0;

            if (!userMessage.HasCharPrefix('!', ref argPos) && !userMessage.HasMentionPrefix(DiscordClient.CurrentUser, ref argPos))
            {
                return;
            }

            if (userMessage.Content.Length <= 1)
            {
                return;
            }

            var commandContext = new CommandContext(DiscordClient, userMessage);

            await AuthorizationService.OnAuthenticatedAsync(author);

            var commandResult = await CommandService.ExecuteAsync(commandContext, argPos, ServiceProvider);

            if (!commandResult.IsSuccess)
            {
                var error = $"{commandResult.Error}: {commandResult.ErrorReason}";

                if (string.Equals(commandResult.ErrorReason, "UnknownCommand", StringComparison.OrdinalIgnoreCase))
                {
                    Log.Error(error);
                }
                else
                {
                    Log.Warning(error);
                }

                if (commandResult.Error == CommandError.Exception)
                {
                    await commandContext.Channel.SendMessageAsync($"Error: {FormatUtilities.SanitizeEveryone(error)}");
                }
                else
                {
                    await CommandErrorHandler.AssociateError(userMessage, error);
                }
            }

            stopwatch.Stop();
            Log.Information($"Command took {stopwatch.ElapsedMilliseconds}ms to process: {commandContext.Message}");
        }
示例#22
0
 internal static (string Id, byte Version) GetMaxVersion(string originalId, byte originalVersion)
 {
     var(pureId, idVersion) = FormatUtilities.SplitVersion(originalId);
     return(pureId, Math.Max(originalVersion, idVersion));
 }
示例#23
0
        public async Task GetUserInfoAsync(
            [Summary("The user to retrieve information about, if any.")]
            [Remainder] DiscordUserOrMessageAuthorEntity user = null)
        {
            var userId = user?.UserId ?? Context.User.Id;

            var timer = Stopwatch.StartNew();

            var userInfo = await _userService.GetUserInformationAsync(Context.Guild.Id, userId);

            if (userInfo == null)
            {
                var embed = new EmbedBuilder()
                            .WithTitle("Retrieval Error")
                            .WithColor(Color.Red)
                            .WithDescription("Sorry, we don't have any data for that user - and we couldn't find any, either.")
                            .AddField("User Id", userId);
                await _autoRemoveMessageService.RegisterRemovableMessageAsync(
                    Context.User,
                    embed,
                    async (embedBuilder) => await ReplyAsync(embed: embedBuilder.Build()));

                return;
            }

            var builder = new StringBuilder();

            builder.AppendLine("**\u276F User Information**");
            builder.AppendLine("ID: " + userId);
            builder.AppendLine("Profile: " + MentionUtils.MentionUser(userId));

            var embedBuilder = new EmbedBuilder()
                               .WithUserAsAuthor(userInfo)
                               .WithTimestamp(_utcNow);

            var avatar = userInfo.GetDefiniteAvatarUrl();

            embedBuilder.ThumbnailUrl   = avatar;
            embedBuilder.Author.IconUrl = avatar;

            ValueTask <Color> colorTask = default;

            if ((userInfo.GetAvatarUrl(size: 16) ?? userInfo.GetDefaultAvatarUrl()) is { } avatarUrl)
            {
                colorTask = _imageService.GetDominantColorAsync(new Uri(avatarUrl));
            }

            var moderationRead = await _authorizationService.HasClaimsAsync(Context.User as IGuildUser, AuthorizationClaim.ModerationRead);

            var promotions = await _promotionsService.GetPromotionsForUserAsync(Context.Guild.Id, userId);

            if (userInfo.IsBanned)
            {
                builder.AppendLine("Status: **Banned** \\🔨");

                if (moderationRead)
                {
                    builder.AppendLine($"Ban Reason: {userInfo.BanReason}");
                }
            }
            else
            {
                builder.AppendLine($"Status: {userInfo.Status.Humanize()}");
            }

            if (userInfo.FirstSeen is DateTimeOffset firstSeen)
            {
                builder.AppendLine($"First Seen: {FormatUtilities.FormatTimeAgo(_utcNow, firstSeen)}");
            }

            if (userInfo.LastSeen is DateTimeOffset lastSeen)
            {
                builder.AppendLine($"Last Seen: {FormatUtilities.FormatTimeAgo(_utcNow, lastSeen)}");
            }

            try
            {
                var userRank = await _messageRepository.GetGuildUserParticipationStatistics(Context.Guild.Id, userId);

                var messagesByDate = await _messageRepository.GetGuildUserMessageCountByDate(Context.Guild.Id, userId, TimeSpan.FromDays(30));

                var messageCountsByChannel = await _messageRepository.GetGuildUserMessageCountByChannel(Context.Guild.Id, userId, TimeSpan.FromDays(30));

                var emojiCounts = await _emojiRepository.GetEmojiStatsAsync(Context.Guild.Id, SortDirection.Ascending, 1, userId : userId);

                await AddParticipationToEmbedAsync(userId, builder, userRank, messagesByDate, messageCountsByChannel, emojiCounts);
            }
            catch (Exception ex)
            {
                _log.LogError(ex, "An error occured while retrieving a user's message count.");
            }

            AddMemberInformationToEmbed(userInfo, builder);
            AddPromotionsToEmbed(builder, promotions);

            if (moderationRead)
            {
                await AddInfractionsToEmbedAsync(userId, builder);
            }

            embedBuilder.Description = builder.ToString();

            embedBuilder.WithColor(await colorTask);

            timer.Stop();
            embedBuilder.WithFooter(footer => footer.Text = $"Completed after {timer.ElapsedMilliseconds} ms");

            await _autoRemoveMessageService.RegisterRemovableMessageAsync(
                userInfo.Id == Context.User.Id?new[] { userInfo } : new[] { userInfo, Context.User },
                embedBuilder,
                async (embedBuilder) => await ReplyAsync(embed: embedBuilder.Build()));
        }
示例#24
0
 public void SplitVersion(string combinedId, string expectedId, byte expectedVersion)
 {
     var result = FormatUtilities.SplitVersion(combinedId);
     Assert.Equal(expectedId, result.Id);
     Assert.Equal(expectedVersion, result.Version);
 }