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(); } } } }
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); }
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); }
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)); }
/// <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; }
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(); }
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)}"); } }
/// <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; }
/// <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}"); }
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; }
/// <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); }
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(); }
/// <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); }
/// <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(); } } } }
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()); }
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(); }
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); }
/// <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}"); }
internal static (string Id, byte Version) GetMaxVersion(string originalId, byte originalVersion) { var(pureId, idVersion) = FormatUtilities.SplitVersion(originalId); return(pureId, Math.Max(originalVersion, idVersion)); }
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())); }
public void SplitVersion(string combinedId, string expectedId, byte expectedVersion) { var result = FormatUtilities.SplitVersion(combinedId); Assert.Equal(expectedId, result.Id); Assert.Equal(expectedVersion, result.Version); }