Tweaks
Add DogstatsD, Move to inheritance for manipulators, Add Metrics counting for endpoint
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Exsersewo.Common.Extensions;
|
||||
using Kynareth.Helpers;
|
||||
using Kynareth.Models;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using StatsdClient;
|
||||
|
||||
namespace Kynareth.Attributes;
|
||||
|
||||
@@ -10,30 +13,65 @@ public class EndpointMetricsAttribute : ActionFilterAttribute
|
||||
{
|
||||
public string EndpointMetricName;
|
||||
|
||||
private Stopwatch watch = new Stopwatch();
|
||||
|
||||
public EndpointMetricsAttribute(string metricName)
|
||||
{
|
||||
EndpointMetricName = metricName;
|
||||
}
|
||||
|
||||
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
base.OnActionExecuting(context);
|
||||
|
||||
#if DEBUG
|
||||
Debug.WriteLine("Executing");
|
||||
#endif
|
||||
|
||||
watch.Restart();
|
||||
watch.Start();
|
||||
}
|
||||
|
||||
public override void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
base.OnActionExecuted(context);
|
||||
|
||||
watch.Stop();
|
||||
|
||||
#if DEBUG
|
||||
Debug.WriteLine("Executed");
|
||||
#endif
|
||||
|
||||
string key = context.HttpContext.Request.GetToken();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(key))
|
||||
{
|
||||
using var database = context.HttpContext.RequestServices.GetRequiredService<KynarethDbContext>();
|
||||
|
||||
var token = database.Tokens.FirstOrDefault(x => x.Token.Equals(key));
|
||||
|
||||
if (token is not null)
|
||||
{
|
||||
token.ApiCalls.Add(new()
|
||||
{
|
||||
TimeStamp = DateTime.UtcNow,
|
||||
Route = EndpointMetricName
|
||||
});
|
||||
|
||||
database.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
string environment = new StringBuilder("environment:")
|
||||
#if DEBUG
|
||||
.Append("dev")
|
||||
#else
|
||||
.Append("production")
|
||||
#endif
|
||||
.ToString();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(key)) return;
|
||||
|
||||
using var database = context.HttpContext.RequestServices.GetRequiredService<KynarethDbContext>();
|
||||
|
||||
var token = database.Tokens.FirstOrDefault(x => x.Token.Equals(key));
|
||||
|
||||
if (token is null) return;
|
||||
DogStatsd.Gauge(EndpointMetricName, watch.Elapsed.TotalSeconds, tags: new[] { environment });
|
||||
|
||||
token.ApiCalls.Add(new() {
|
||||
TimeStamp = DateTime.UtcNow,
|
||||
Route = EndpointMetricName
|
||||
});
|
||||
|
||||
database.SaveChanges();
|
||||
DogStatsd.Increment(EndpointMetricName, tags: new[] { environment });
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,23 @@ using Kynareth.Attributes;
|
||||
using Kynareth.Helpers;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Kynareth.Extensions;
|
||||
using Kynareth.Helpers.AmongUs;
|
||||
|
||||
namespace Kynareth.Controllers;
|
||||
|
||||
[Route("amogus")]
|
||||
public class AmogusController : BaseController<AmogusController>
|
||||
{
|
||||
public AmogusController(IConfiguration configuration, ILoggerFactory loggerFactory, IWebHostEnvironment appEnvironment) : base(configuration, loggerFactory, appEnvironment)
|
||||
private AmongUsGenerator _amongUs;
|
||||
|
||||
public AmogusController(
|
||||
AmongUsGenerator amongUs,
|
||||
IConfiguration configuration,
|
||||
ILoggerFactory loggerFactory,
|
||||
IWebHostEnvironment appEnvironment
|
||||
) : base(configuration, loggerFactory, appEnvironment)
|
||||
{
|
||||
_amongUs = amongUs;
|
||||
}
|
||||
|
||||
[HttpGet("eject")]
|
||||
@@ -19,7 +28,7 @@ public class AmogusController : BaseController<AmogusController>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name)) return StatusCode(StatusCodes.Status400BadRequest, EventResult.FromFailure(nameof(name) + " needs to be provided."));
|
||||
|
||||
using var result = AmogusHelper.GenerateEjectionGif(name, colour, role, skin);
|
||||
using var result = _amongUs.GenerateEjectionGif(name, colour, role, skin);
|
||||
|
||||
if (result is MagickImageCollection data)
|
||||
{
|
||||
|
||||
@@ -12,8 +12,17 @@ namespace Kynareth.Controllers;
|
||||
[Route("image/generate")]
|
||||
public class ImageGenerationController : BaseController<ImageGenerationController>
|
||||
{
|
||||
public ImageGenerationController(IConfiguration configuration, ILoggerFactory loggerFactory, IWebHostEnvironment environment) : base(configuration, loggerFactory, environment)
|
||||
{ }
|
||||
private ImageGenerator _generator;
|
||||
|
||||
public ImageGenerationController(
|
||||
ImageGenerator generator,
|
||||
IConfiguration configuration,
|
||||
ILoggerFactory loggerFactory,
|
||||
IWebHostEnvironment environment
|
||||
) : base(configuration, loggerFactory, environment)
|
||||
{
|
||||
_generator = generator;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[EndpointMetrics("image.generate.get.templates")]
|
||||
@@ -21,7 +30,7 @@ public class ImageGenerationController : BaseController<ImageGenerationControlle
|
||||
[ProducesResponseType(typeof(IEnumerable<ImageGenerationEndpointRead>), StatusCodes.Status200OK)]
|
||||
public Task<object> GetTemplates()
|
||||
{
|
||||
return Task.FromResult(HttpContext.Send(EventResult.FromSuccess(ImageManager.GetGenerationEndpoints())));
|
||||
return Task.FromResult(HttpContext.Send(EventResult.FromSuccess(_generator.GetGenerationEndpoints())));
|
||||
}
|
||||
|
||||
[HttpGet("{template}")]
|
||||
@@ -35,7 +44,7 @@ public class ImageGenerationController : BaseController<ImageGenerationControlle
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await ImageManager.GenerateImageAsync(template, variant, sources, Request.HttpContext.RequestAborted);
|
||||
var result = await _generator.GenerateImageAsync(template, variant, sources, Request.HttpContext.RequestAborted);
|
||||
|
||||
if (result is byte[] data)
|
||||
{
|
||||
@@ -68,7 +77,7 @@ public class ImageGenerationController : BaseController<ImageGenerationControlle
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(template))
|
||||
{
|
||||
var result = await ImageManager.GenerateImageAsync(template, variant, Request.HttpContext.RequestAborted);
|
||||
var result = await _generator.GenerateImageAsync(template, variant, Request.HttpContext.RequestAborted);
|
||||
|
||||
if (result is byte[] data)
|
||||
{
|
||||
@@ -100,7 +109,7 @@ public class ImageGenerationController : BaseController<ImageGenerationControlle
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await ImageManager.GenerateImageAsync(Request.HttpContext.RequestAborted);
|
||||
var result = await _generator.GenerateImageAsync(Request.HttpContext.RequestAborted);
|
||||
|
||||
if (result is byte[] data)
|
||||
{
|
||||
|
||||
@@ -10,8 +10,20 @@ namespace Kynareth.Controllers;
|
||||
[Route("image/manipulation")]
|
||||
public class ImageManipulationController : BaseController<ImageManipulationController>
|
||||
{
|
||||
public ImageManipulationController(IConfiguration configuration, ILoggerFactory loggerFactory, IWebHostEnvironment appEnvironment) : base(configuration, loggerFactory, appEnvironment)
|
||||
{ }
|
||||
private ImageMagiker _magiker;
|
||||
private ImageManipulator _manipulator;
|
||||
|
||||
public ImageManipulationController(
|
||||
ImageMagiker magiker,
|
||||
ImageManipulator manipulator,
|
||||
IConfiguration configuration,
|
||||
ILoggerFactory loggerFactory,
|
||||
IWebHostEnvironment appEnvironment
|
||||
) : base(configuration, loggerFactory, appEnvironment)
|
||||
{
|
||||
_magiker = magiker;
|
||||
_manipulator = manipulator;
|
||||
}
|
||||
|
||||
/// ---------- ///
|
||||
/// MAGIK ///
|
||||
@@ -28,7 +40,7 @@ public class ImageManipulationController : BaseController<ImageManipulationContr
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(image))
|
||||
{
|
||||
var (data, contentType) = await ImageManager.GetLiquidRescaledImageAsync(image, HttpContext.RequestAborted);
|
||||
var (data, contentType) = await _magiker.GetLiquidRescaledImageAsync(image, HttpContext.RequestAborted);
|
||||
|
||||
return HttpContext.SendStream(data, contentType);
|
||||
}
|
||||
@@ -54,7 +66,7 @@ public class ImageManipulationController : BaseController<ImageManipulationContr
|
||||
[ProducesResponseType(typeof(IEnumerable<ImageGenerationEndpointRead>), StatusCodes.Status200OK)]
|
||||
public Task<object> GetTemplates()
|
||||
{
|
||||
return Task.FromResult(HttpContext.Send(EventResult.FromSuccess(ImageManager.GetManipulationEndpoints())));
|
||||
return Task.FromResult(HttpContext.Send(EventResult.FromSuccess(_manipulator.GetManipulationEndpoints())));
|
||||
}
|
||||
|
||||
[HttpGet("{template}")]
|
||||
@@ -69,7 +81,7 @@ public class ImageManipulationController : BaseController<ImageManipulationContr
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(template))
|
||||
{
|
||||
var result = await ImageManager.GenerateMemeImageAsync(template, text, HttpContext.RequestAborted);
|
||||
var result = await _manipulator.GenerateMemeImageAsync(template, text, HttpContext.RequestAborted);
|
||||
|
||||
if (result is byte[] data)
|
||||
{
|
||||
|
||||
@@ -1,49 +1,12 @@
|
||||
using System.Globalization;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using ICU4N.Text;
|
||||
using ImageMagick;
|
||||
using Kynareth.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Kynareth.Managers;
|
||||
namespace Kynareth.Extensions;
|
||||
|
||||
public static partial class ImageManager
|
||||
public static class MagickImageExtensions
|
||||
{
|
||||
public static void Configure(IConfiguration configuration, IWebHostEnvironment appEnvironment)
|
||||
{
|
||||
ConfigureGeneration(configuration, appEnvironment);
|
||||
ConfigureManipulation(configuration, appEnvironment);
|
||||
}
|
||||
|
||||
static BreakIterator lineBreakIterator = BreakIterator.GetLineInstance(CultureInfo.InvariantCulture);
|
||||
|
||||
private static ObjectResult GetResult(int statusCode, object data) => new(data) { StatusCode = statusCode };
|
||||
|
||||
private static string GetText(string text)
|
||||
{
|
||||
StringBuilder newText = new();
|
||||
|
||||
// set the text to be broken
|
||||
lineBreakIterator.SetText(text);
|
||||
|
||||
// get the first boundary
|
||||
int start = lineBreakIterator.First();
|
||||
|
||||
// iterate over all boundaries
|
||||
for (int end = lineBreakIterator.Next(); end != BreakIterator.Done; start = end, end = lineBreakIterator.Next())
|
||||
{
|
||||
// get the current line
|
||||
string line = text.Substring(start, end - start);
|
||||
|
||||
// do something with the line
|
||||
newText.AppendLine(line);
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
|
||||
return newText.ToString();
|
||||
}
|
||||
|
||||
public static MagickImage WriteText(this MagickImage image, string text, PositionRect rect, MagickColor fontColor, Encoding encoding, string font = "Impact", int strokeWidth = 2, MagickColor? strokeColor = null, bool wrapText = true, Gravity textGravity = Gravity.Northwest)
|
||||
{
|
||||
using var label = new MagickImage($"{(wrapText ? "caption" : "label")}:{text}", new MagickReadSettings()
|
||||
@@ -1,208 +1,18 @@
|
||||
using System.Drawing;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using ImageMagick;
|
||||
using Kynareth.Managers;
|
||||
using Kynareth.Extensions;
|
||||
using CollectionExtensions = Kynareth.Extensions.CollectionExtensions;
|
||||
|
||||
namespace Kynareth.Helpers;
|
||||
namespace Kynareth.Helpers.AmongUs;
|
||||
|
||||
public enum AmogusRole
|
||||
public class AmongUsGenerator
|
||||
{
|
||||
Imposter,
|
||||
Crewmate,
|
||||
Unknown
|
||||
}
|
||||
|
||||
public enum AmogusColour
|
||||
{
|
||||
Red,
|
||||
Blue,
|
||||
Green,
|
||||
Pink,
|
||||
Orange,
|
||||
Yellow,
|
||||
Black,
|
||||
White,
|
||||
Purple,
|
||||
Brown,
|
||||
Cyan,
|
||||
Lime,
|
||||
Maroon,
|
||||
Rose,
|
||||
Banana,
|
||||
Gray,
|
||||
Tan,
|
||||
Coral,
|
||||
}
|
||||
|
||||
public enum AmogusSkin
|
||||
{
|
||||
Archaeologist,
|
||||
Astronaut,
|
||||
Captain,
|
||||
Hazmat,
|
||||
Mechanic,
|
||||
Military,
|
||||
Miner,
|
||||
Police,
|
||||
SecurityGuard,
|
||||
Scientist,
|
||||
BlackSuit,
|
||||
WhiteSuit,
|
||||
Tarmac,
|
||||
Wall,
|
||||
Winter,
|
||||
None,
|
||||
}
|
||||
|
||||
public static class AmogusHelper
|
||||
{
|
||||
#region CoreVariables
|
||||
public class ColourHelper
|
||||
{
|
||||
private static readonly Dictionary<AmogusColour, MagickColor> _RedReplaceColors = new()
|
||||
{
|
||||
{ AmogusColour.Red, new(215, 30, 34, 255) },
|
||||
{ AmogusColour.Blue, new(29, 60, 233, 255) },
|
||||
{ AmogusColour.Green, new(27, 145, 62, 255) },
|
||||
{ AmogusColour.Pink, new(255, 99, 212, 255) },
|
||||
{ AmogusColour.Orange, new(255, 141, 28, 255) },
|
||||
{ AmogusColour.Yellow, new(255, 255, 103, 255) },
|
||||
{ AmogusColour.Black, new(74, 86, 94, 255) },
|
||||
{ AmogusColour.White, new(233, 247, 255, 255) },
|
||||
{ AmogusColour.Purple, new(120, 61, 210, 255) },
|
||||
{ AmogusColour.Brown, new(128, 88, 45, 255) },
|
||||
{ AmogusColour.Cyan, new(68, 255, 247, 255) },
|
||||
{ AmogusColour.Lime, new(91, 255, 75, 255) },
|
||||
{ AmogusColour.Maroon, new(108, 43, 61, 255) },
|
||||
{ AmogusColour.Rose, new(255, 214, 236, 255) },
|
||||
{ AmogusColour.Banana, new(255, 255, 190, 255) },
|
||||
{ AmogusColour.Gray, new(131, 151, 167, 255) },
|
||||
{ AmogusColour.Tan, new(159, 153, 137, 255) },
|
||||
{ AmogusColour.Coral, new(236, 117, 120, 255) },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<AmogusColour, MagickColor> _BlueReplaceColors = new()
|
||||
{
|
||||
{ AmogusColour.Red, new(122, 8, 56, 255) },
|
||||
{ AmogusColour.Blue, new(9, 21, 142, 255) },
|
||||
{ AmogusColour.Green, new(10, 77, 46, 255) },
|
||||
{ AmogusColour.Pink, new(172, 43, 174, 255) },
|
||||
{ AmogusColour.Orange, new(180, 62, 21, 255) },
|
||||
{ AmogusColour.Yellow, new(195, 136, 34, 255) },
|
||||
{ AmogusColour.Black, new(30, 31, 38, 255) },
|
||||
{ AmogusColour.White, new(132, 149, 192, 255) },
|
||||
{ AmogusColour.Purple, new(59, 23, 124, 255) },
|
||||
{ AmogusColour.Brown, new(94, 38, 21, 255) },
|
||||
{ AmogusColour.Cyan, new(36, 169, 191, 255) },
|
||||
{ AmogusColour.Lime, new(21, 168, 66, 255) },
|
||||
{ AmogusColour.Maroon, new(65, 15, 26, 255) },
|
||||
{ AmogusColour.Rose, new(222, 146, 179, 255) },
|
||||
{ AmogusColour.Banana, new(210, 188, 137, 255) },
|
||||
{ AmogusColour.Gray, new(70, 86, 100, 255) },
|
||||
{ AmogusColour.Tan, new(81, 65, 62, 255) },
|
||||
{ AmogusColour.Coral, new(180, 67, 98, 255) },
|
||||
};
|
||||
|
||||
private static readonly MagickColor _green = new MagickColor(149, 202, 220, 255);
|
||||
private readonly MagickColor _red;
|
||||
private readonly MagickColor _blue;
|
||||
|
||||
public MagickColor Red => _red;
|
||||
public MagickColor Green => _green;
|
||||
public MagickColor Blue => _blue;
|
||||
|
||||
public ColourHelper(AmogusColour colour = AmogusColour.Blue)
|
||||
{
|
||||
_red = _RedReplaceColors[colour];
|
||||
_blue = _BlueReplaceColors[colour];
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly Dictionary<AmogusSkin, string> IdleSkins = new()
|
||||
{
|
||||
{ AmogusSkin.Archaeologist, "archae-idle.png" },
|
||||
{ AmogusSkin.Astronaut, "astro-idle.png" },
|
||||
{ AmogusSkin.Captain, "captain-idle.png" },
|
||||
{ AmogusSkin.Hazmat, "hazmat-idle.png" },
|
||||
{ AmogusSkin.Mechanic, "mech-idle.png" },
|
||||
{ AmogusSkin.Military, "military-idle.png" },
|
||||
{ AmogusSkin.Miner, "miner-idle.png" },
|
||||
{ AmogusSkin.Police, "pol-idle.png" },
|
||||
{ AmogusSkin.SecurityGuard, "secguard-idle.png" },
|
||||
{ AmogusSkin.Scientist, "sci-idle.png" },
|
||||
{ AmogusSkin.BlackSuit, "suitBlack-idle.png" },
|
||||
{ AmogusSkin.WhiteSuit, "suitWhite-idle.png" },
|
||||
{ AmogusSkin.Tarmac, "tarmac-idle.png" },
|
||||
{ AmogusSkin.Wall, "wall-idle.png" },
|
||||
{ AmogusSkin.Winter, "winter-idle.png" },
|
||||
};
|
||||
|
||||
public static readonly Dictionary<AmogusSkin, string> EjectSkins = new()
|
||||
{
|
||||
{ AmogusSkin.Archaeologist, "archae-eject.png" },
|
||||
{ AmogusSkin.Astronaut, "astro-eject.png" },
|
||||
{ AmogusSkin.Captain, "captain-eject.png" },
|
||||
{ AmogusSkin.Hazmat, "hazmat-eject.png" },
|
||||
{ AmogusSkin.Mechanic, "mech-eject.png" },
|
||||
{ AmogusSkin.Military, "military-eject.png" },
|
||||
{ AmogusSkin.Miner, "miner-eject.png" },
|
||||
{ AmogusSkin.Police, "police-eject.png" },
|
||||
{ AmogusSkin.SecurityGuard, "secguard-eject.png" },
|
||||
{ AmogusSkin.Scientist, "sci-eject.png" },
|
||||
{ AmogusSkin.BlackSuit, "suitBlack-eject.png" },
|
||||
{ AmogusSkin.WhiteSuit, "suitWhite-eject.png" },
|
||||
{ AmogusSkin.Tarmac, "tarmac-eject.png" },
|
||||
{ AmogusSkin.Wall, "wall-eject.png" },
|
||||
{ AmogusSkin.Winter, "winter-eject.png" },
|
||||
};
|
||||
|
||||
public static readonly Dictionary<AmogusSkin, Point> IdleOffset = new()
|
||||
{
|
||||
{ AmogusSkin.Archaeologist, new(13, 41) },
|
||||
{ AmogusSkin.Astronaut, new(13, 46) },
|
||||
{ AmogusSkin.Captain, new(14, 45) },
|
||||
{ AmogusSkin.Hazmat, new(12, 34) },
|
||||
{ AmogusSkin.Mechanic, new(13, 46) },
|
||||
{ AmogusSkin.Military, new(11, 45) },
|
||||
{ AmogusSkin.Miner, new(13, 40) },
|
||||
{ AmogusSkin.Police, new(10, 45) },
|
||||
{ AmogusSkin.SecurityGuard, new(13, 42) },
|
||||
{ AmogusSkin.Scientist, new(14, 43) },
|
||||
{ AmogusSkin.BlackSuit, new(14, 44) },
|
||||
{ AmogusSkin.WhiteSuit, new(14, 44) },
|
||||
{ AmogusSkin.Tarmac, new(14, 40) },
|
||||
{ AmogusSkin.Wall, new(10, 44) },
|
||||
{ AmogusSkin.Winter, new(9, 35) },
|
||||
};
|
||||
|
||||
public static readonly Dictionary<AmogusSkin, Point> EjectOffset = new()
|
||||
{
|
||||
{ AmogusSkin.Archaeologist, new(12, 35) },
|
||||
{ AmogusSkin.Astronaut, new(12, 35) },
|
||||
{ AmogusSkin.Captain, new(12, 35) },
|
||||
{ AmogusSkin.Hazmat, new(13, 37) },
|
||||
{ AmogusSkin.Mechanic, new(13, 35) },
|
||||
{ AmogusSkin.Military, new(12, 35) },
|
||||
{ AmogusSkin.Miner, new(12, 36) },
|
||||
{ AmogusSkin.Police, new(12, 35) },
|
||||
{ AmogusSkin.SecurityGuard, new(13, 35) },
|
||||
{ AmogusSkin.Scientist, new(-10, 35) },
|
||||
{ AmogusSkin.BlackSuit, new(12, 35) },
|
||||
{ AmogusSkin.WhiteSuit, new(11, 35) },
|
||||
{ AmogusSkin.Tarmac, new(14, 37) },
|
||||
{ AmogusSkin.Wall, new(12, 35) },
|
||||
{ AmogusSkin.Winter, new(5, 30) },
|
||||
};
|
||||
|
||||
public static string IdleRoot, EjectRoot, CommonRoot;
|
||||
|
||||
public const string Arial = "Arial";
|
||||
#endregion CoreVariables
|
||||
|
||||
public static void Configure(IWebHostEnvironment appEnvironment)
|
||||
|
||||
public AmongUsGenerator(IConfiguration configuration, IWebHostEnvironment appEnvironment)
|
||||
{
|
||||
string amogusBase = Path.Combine(appEnvironment.WebRootPath, "amogus");
|
||||
|
||||
@@ -221,7 +31,7 @@ public static class AmogusHelper
|
||||
static MagickImage GenerateBase(string baseImageName = "idle.png", AmogusColour colour = AmogusColour.Blue)
|
||||
{
|
||||
string baseIdle = Path.Combine(CommonRoot, baseImageName);
|
||||
MagickImage body = new MagickImage(baseIdle);
|
||||
MagickImage body = new(baseIdle);
|
||||
|
||||
body = ColourReplace(body, colour);
|
||||
body.BackgroundColor = MagickColors.Transparent;
|
||||
@@ -237,7 +47,7 @@ public static class AmogusHelper
|
||||
/// <returns>Colour Replaced Amogie Crewmate</returns>
|
||||
static MagickImage ColourReplace(MagickImage image, AmogusColour colour = AmogusColour.Blue)
|
||||
{
|
||||
var colours = new ColourHelper(colour);
|
||||
ColourHelper colours = new(colour);
|
||||
|
||||
var pixels = image.GetPixels();
|
||||
|
||||
@@ -382,7 +192,7 @@ public static class AmogusHelper
|
||||
skinImage = new MagickImage(
|
||||
Path.Combine(
|
||||
ejected ? EjectRoot : IdleRoot,
|
||||
ejected ? EjectSkins[skin] : IdleSkins[skin]
|
||||
ejected ? AmongUsGeneratorHelper.EjectSkins[skin] : AmongUsGeneratorHelper.IdleSkins[skin]
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -391,7 +201,7 @@ public static class AmogusHelper
|
||||
ApplyLayer(
|
||||
baseImage,
|
||||
skinImage,
|
||||
ejected ? EjectOffset[skin] : IdleOffset[skin], new Point(0, 0)
|
||||
ejected ? AmongUsGeneratorHelper.EjectOffset[skin] : AmongUsGeneratorHelper.IdleOffset[skin], new Point(0, 0)
|
||||
) : baseImage;
|
||||
|
||||
outImage.Trim();
|
||||
@@ -457,14 +267,14 @@ public static class AmogusHelper
|
||||
/// <param name="skin"></param>
|
||||
/// <param name="role"></param>
|
||||
/// <returns>A <see cref="MemoryStream"/> containing the Amogus Ejected Gif</returns>
|
||||
public static MagickImageCollection GenerateEjectionGif(string name, AmogusColour? colour = null, AmogusRole? role = null, AmogusSkin? skin = null, bool addStars = true)
|
||||
public MagickImageCollection GenerateEjectionGif(string name, AmogusColour? colour = null, AmogusRole? role = null, AmogusSkin? skin = null, bool addStars = true)
|
||||
{
|
||||
if (role is null) role = EnumHelper.GetRandomEnumValue<AmogusRole>();
|
||||
|
||||
return GenerateCustomEjectionGif(GenerateEjectionMessage(name, role.Value), colour, role, skin, addStars);
|
||||
}
|
||||
|
||||
public static MagickImageCollection GenerateCustomEjectionGif(string text, AmogusColour? colour = null, AmogusRole? role = null, AmogusSkin? skin = null, bool addStars = true)
|
||||
public MagickImageCollection GenerateCustomEjectionGif(string text, AmogusColour? colour = null, AmogusRole? role = null, AmogusSkin? skin = null, bool addStars = true)
|
||||
{
|
||||
if (colour is null) colour = EnumHelper.GetRandomEnumValue<AmogusColour>();
|
||||
if (role is null) role = EnumHelper.GetRandomEnumValue<AmogusRole>();
|
||||
191
src/Helpers/AmongUs/AmongUs.Models.cs
Normal file
191
src/Helpers/AmongUs/AmongUs.Models.cs
Normal file
@@ -0,0 +1,191 @@
|
||||
using System.Drawing;
|
||||
using ImageMagick;
|
||||
|
||||
namespace Kynareth.Helpers.AmongUs;
|
||||
|
||||
public enum AmogusRole
|
||||
{
|
||||
Imposter,
|
||||
Crewmate,
|
||||
Unknown
|
||||
}
|
||||
|
||||
public enum AmogusColour
|
||||
{
|
||||
Red,
|
||||
Blue,
|
||||
Green,
|
||||
Pink,
|
||||
Orange,
|
||||
Yellow,
|
||||
Black,
|
||||
White,
|
||||
Purple,
|
||||
Brown,
|
||||
Cyan,
|
||||
Lime,
|
||||
Maroon,
|
||||
Rose,
|
||||
Banana,
|
||||
Gray,
|
||||
Tan,
|
||||
Coral,
|
||||
}
|
||||
|
||||
public enum AmogusSkin
|
||||
{
|
||||
Archaeologist,
|
||||
Astronaut,
|
||||
Captain,
|
||||
Hazmat,
|
||||
Mechanic,
|
||||
Military,
|
||||
Miner,
|
||||
Police,
|
||||
SecurityGuard,
|
||||
Scientist,
|
||||
BlackSuit,
|
||||
WhiteSuit,
|
||||
Tarmac,
|
||||
Wall,
|
||||
Winter,
|
||||
None,
|
||||
}
|
||||
|
||||
public readonly struct ColourHelper
|
||||
{
|
||||
private static readonly Dictionary<AmogusColour, MagickColor> RedReplaceColors = new() {
|
||||
{ AmogusColour.Red, new(215, 30, 34, 255) },
|
||||
{ AmogusColour.Blue, new(29, 60, 233, 255) },
|
||||
{ AmogusColour.Green, new(27, 145, 62, 255) },
|
||||
{ AmogusColour.Pink, new(255, 99, 212, 255) },
|
||||
{ AmogusColour.Orange, new(255, 141, 28, 255) },
|
||||
{ AmogusColour.Yellow, new(255, 255, 103, 255) },
|
||||
{ AmogusColour.Black, new(74, 86, 94, 255) },
|
||||
{ AmogusColour.White, new(233, 247, 255, 255) },
|
||||
{ AmogusColour.Purple, new(120, 61, 210, 255) },
|
||||
{ AmogusColour.Brown, new(128, 88, 45, 255) },
|
||||
{ AmogusColour.Cyan, new(68, 255, 247, 255) },
|
||||
{ AmogusColour.Lime, new(91, 255, 75, 255) },
|
||||
{ AmogusColour.Maroon, new(108, 43, 61, 255) },
|
||||
{ AmogusColour.Rose, new(255, 214, 236, 255) },
|
||||
{ AmogusColour.Banana, new(255, 255, 190, 255) },
|
||||
{ AmogusColour.Gray, new(131, 151, 167, 255) },
|
||||
{ AmogusColour.Tan, new(159, 153, 137, 255) },
|
||||
{ AmogusColour.Coral, new(236, 117, 120, 255) },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<AmogusColour, MagickColor> BlueReplaceColors = new() {
|
||||
{ AmogusColour.Red, new(122, 8, 56, 255) },
|
||||
{ AmogusColour.Blue, new(9, 21, 142, 255) },
|
||||
{ AmogusColour.Green, new(10, 77, 46, 255) },
|
||||
{ AmogusColour.Pink, new(172, 43, 174, 255) },
|
||||
{ AmogusColour.Orange, new(180, 62, 21, 255) },
|
||||
{ AmogusColour.Yellow, new(195, 136, 34, 255) },
|
||||
{ AmogusColour.Black, new(30, 31, 38, 255) },
|
||||
{ AmogusColour.White, new(132, 149, 192, 255) },
|
||||
{ AmogusColour.Purple, new(59, 23, 124, 255) },
|
||||
{ AmogusColour.Brown, new(94, 38, 21, 255) },
|
||||
{ AmogusColour.Cyan, new(36, 169, 191, 255) },
|
||||
{ AmogusColour.Lime, new(21, 168, 66, 255) },
|
||||
{ AmogusColour.Maroon, new(65, 15, 26, 255) },
|
||||
{ AmogusColour.Rose, new(222, 146, 179, 255) },
|
||||
{ AmogusColour.Banana, new(210, 188, 137, 255) },
|
||||
{ AmogusColour.Gray, new(70, 86, 100, 255) },
|
||||
{ AmogusColour.Tan, new(81, 65, 62, 255) },
|
||||
{ AmogusColour.Coral, new(180, 67, 98, 255) },
|
||||
};
|
||||
|
||||
private readonly MagickColor _green = new(149, 202, 220, 255);
|
||||
private readonly MagickColor _red;
|
||||
private readonly MagickColor _blue;
|
||||
|
||||
public MagickColor Red => _red;
|
||||
public MagickColor Green => _green;
|
||||
public MagickColor Blue => _blue;
|
||||
|
||||
public ColourHelper(AmogusColour colour = AmogusColour.Blue)
|
||||
{
|
||||
_red = RedReplaceColors[colour];
|
||||
_blue = BlueReplaceColors[colour];
|
||||
}
|
||||
}
|
||||
|
||||
public static class AmongUsGeneratorHelper
|
||||
{
|
||||
public static readonly Dictionary<AmogusSkin, string> IdleSkins = new()
|
||||
{
|
||||
{ AmogusSkin.Archaeologist, "archae-idle.png" },
|
||||
{ AmogusSkin.Astronaut, "astro-idle.png" },
|
||||
{ AmogusSkin.Captain, "captain-idle.png" },
|
||||
{ AmogusSkin.Hazmat, "hazmat-idle.png" },
|
||||
{ AmogusSkin.Mechanic, "mech-idle.png" },
|
||||
{ AmogusSkin.Military, "military-idle.png" },
|
||||
{ AmogusSkin.Miner, "miner-idle.png" },
|
||||
{ AmogusSkin.Police, "pol-idle.png" },
|
||||
{ AmogusSkin.SecurityGuard, "secguard-idle.png" },
|
||||
{ AmogusSkin.Scientist, "sci-idle.png" },
|
||||
{ AmogusSkin.BlackSuit, "suitBlack-idle.png" },
|
||||
{ AmogusSkin.WhiteSuit, "suitWhite-idle.png" },
|
||||
{ AmogusSkin.Tarmac, "tarmac-idle.png" },
|
||||
{ AmogusSkin.Wall, "wall-idle.png" },
|
||||
{ AmogusSkin.Winter, "winter-idle.png" },
|
||||
};
|
||||
|
||||
public static readonly Dictionary<AmogusSkin, string> EjectSkins = new()
|
||||
{
|
||||
{ AmogusSkin.Archaeologist, "archae-eject.png" },
|
||||
{ AmogusSkin.Astronaut, "astro-eject.png" },
|
||||
{ AmogusSkin.Captain, "captain-eject.png" },
|
||||
{ AmogusSkin.Hazmat, "hazmat-eject.png" },
|
||||
{ AmogusSkin.Mechanic, "mech-eject.png" },
|
||||
{ AmogusSkin.Military, "military-eject.png" },
|
||||
{ AmogusSkin.Miner, "miner-eject.png" },
|
||||
{ AmogusSkin.Police, "police-eject.png" },
|
||||
{ AmogusSkin.SecurityGuard, "secguard-eject.png" },
|
||||
{ AmogusSkin.Scientist, "sci-eject.png" },
|
||||
{ AmogusSkin.BlackSuit, "suitBlack-eject.png" },
|
||||
{ AmogusSkin.WhiteSuit, "suitWhite-eject.png" },
|
||||
{ AmogusSkin.Tarmac, "tarmac-eject.png" },
|
||||
{ AmogusSkin.Wall, "wall-eject.png" },
|
||||
{ AmogusSkin.Winter, "winter-eject.png" },
|
||||
};
|
||||
|
||||
public static readonly Dictionary<AmogusSkin, Point> IdleOffset = new()
|
||||
{
|
||||
{ AmogusSkin.Archaeologist, new(13, 41) },
|
||||
{ AmogusSkin.Astronaut, new(13, 46) },
|
||||
{ AmogusSkin.Captain, new(14, 45) },
|
||||
{ AmogusSkin.Hazmat, new(12, 34) },
|
||||
{ AmogusSkin.Mechanic, new(13, 46) },
|
||||
{ AmogusSkin.Military, new(11, 45) },
|
||||
{ AmogusSkin.Miner, new(13, 40) },
|
||||
{ AmogusSkin.Police, new(10, 45) },
|
||||
{ AmogusSkin.SecurityGuard, new(13, 42) },
|
||||
{ AmogusSkin.Scientist, new(14, 43) },
|
||||
{ AmogusSkin.BlackSuit, new(14, 44) },
|
||||
{ AmogusSkin.WhiteSuit, new(14, 44) },
|
||||
{ AmogusSkin.Tarmac, new(14, 40) },
|
||||
{ AmogusSkin.Wall, new(10, 44) },
|
||||
{ AmogusSkin.Winter, new(9, 35) },
|
||||
};
|
||||
|
||||
public static readonly Dictionary<AmogusSkin, Point> EjectOffset = new()
|
||||
{
|
||||
{ AmogusSkin.Archaeologist, new(12, 35) },
|
||||
{ AmogusSkin.Astronaut, new(12, 35) },
|
||||
{ AmogusSkin.Captain, new(12, 35) },
|
||||
{ AmogusSkin.Hazmat, new(13, 37) },
|
||||
{ AmogusSkin.Mechanic, new(13, 35) },
|
||||
{ AmogusSkin.Military, new(12, 35) },
|
||||
{ AmogusSkin.Miner, new(12, 36) },
|
||||
{ AmogusSkin.Police, new(12, 35) },
|
||||
{ AmogusSkin.SecurityGuard, new(13, 35) },
|
||||
{ AmogusSkin.Scientist, new(-10, 35) },
|
||||
{ AmogusSkin.BlackSuit, new(12, 35) },
|
||||
{ AmogusSkin.WhiteSuit, new(11, 35) },
|
||||
{ AmogusSkin.Tarmac, new(14, 37) },
|
||||
{ AmogusSkin.Wall, new(12, 35) },
|
||||
{ AmogusSkin.Winter, new(5, 30) },
|
||||
};
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DogStatsD-CSharp-Client" Version="8.0.0" />
|
||||
<PackageReference Include="Exsersewo.Common" Version="2023.1.14" />
|
||||
<PackageReference Include="ICU4N" Version="60.1.0-alpha.356" />
|
||||
<PackageReference Include="JwtSharp" Version="1.1.0" />
|
||||
|
||||
@@ -7,21 +7,21 @@ using Kynareth.Extensions;
|
||||
|
||||
namespace Kynareth.Managers;
|
||||
|
||||
public static partial class ImageManager
|
||||
public class ImageGenerator : ImageModifier
|
||||
{
|
||||
private static List<ImageGenerationEndpoint> GenerationEndpoints;
|
||||
private static IReadOnlyList<string> sourceFiles;
|
||||
|
||||
private static string GenerationTemplateBaseFolder;
|
||||
|
||||
static void ConfigureGeneration(IConfiguration configuration, IWebHostEnvironment _appEnvironment)
|
||||
public ImageGenerator(IConfiguration configuration, IWebHostEnvironment appEnvironment)
|
||||
{
|
||||
sourceFiles = Directory.EnumerateFiles(Path.Combine(_appEnvironment.WebRootPath, configuration.GetValue<string>("ShitpostBot:Folder"), "..", "random")).ToImmutableList();
|
||||
GenerationTemplateBaseFolder = Path.Combine(_appEnvironment.WebRootPath, configuration.GetValue<string>("ShitpostBot:Folder"));
|
||||
sourceFiles = Directory.EnumerateFiles(Path.Combine(appEnvironment.WebRootPath, configuration.GetValue<string>("ShitpostBot:Folder"), "..", "random")).ToImmutableList();
|
||||
GenerationTemplateBaseFolder = Path.Combine(appEnvironment.WebRootPath, configuration.GetValue<string>("ShitpostBot:Folder"));
|
||||
GenerationEndpoints = configuration.GetSection("ShitpostBot:Templates").Get<List<ImageGenerationEndpoint>>();
|
||||
}
|
||||
|
||||
public static async Task<Object> GenerateImageAsync(CancellationToken cancellationToken)
|
||||
public async Task<Object> GenerateImageAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
ImageGenerationImage imageTemplate = null;
|
||||
|
||||
@@ -45,7 +45,7 @@ public static partial class ImageManager
|
||||
return await GenerateImageAsync(endpoint.Name, variant, sources, cancellationToken);
|
||||
}
|
||||
|
||||
public static async Task<Object> GenerateImageAsync(string template, string variant, CancellationToken cancellationToken)
|
||||
public async Task<Object> GenerateImageAsync(string template, string variant, CancellationToken cancellationToken)
|
||||
{
|
||||
ImageGenerationImage imageTemplate = null;
|
||||
|
||||
@@ -63,7 +63,7 @@ public static partial class ImageManager
|
||||
return await GenerateImageAsync(template, variant, sources, cancellationToken);
|
||||
}
|
||||
|
||||
public static async Task<object> GenerateImageAsync(string template, string variant, string[] sources, CancellationToken cancellationToken)
|
||||
public async Task<object> GenerateImageAsync(string template, string variant, string[] sources, CancellationToken cancellationToken)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
@@ -188,7 +188,7 @@ public static partial class ImageManager
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<ImageGenerationEndpointRead> GetGenerationEndpoints()
|
||||
public IEnumerable<ImageGenerationEndpointRead> GetGenerationEndpoints()
|
||||
{
|
||||
return GenerationEndpoints.Select(e => new ImageGenerationEndpointRead
|
||||
{
|
||||
@@ -1,15 +1,11 @@
|
||||
using System.Text;
|
||||
using Exsersewo.Common.Utilities;
|
||||
using Exsersewo.Common.Utilities;
|
||||
using ImageMagick;
|
||||
|
||||
namespace Kynareth.Managers;
|
||||
|
||||
public static partial class ImageManager
|
||||
public class ImageMagiker : ImageModifier
|
||||
{
|
||||
readonly static Encoding s_defaultEncoding = Encoding.Unicode;
|
||||
const double c_defaultFontSize = 20;
|
||||
|
||||
public static async Task<(MemoryStream data, string contentType)> GetLiquidRescaledImageAsync(string image, CancellationToken cancellationToken)
|
||||
public async Task<(MemoryStream data, string contentType)> GetLiquidRescaledImageAsync(string image, CancellationToken cancellationToken)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
@@ -1,23 +1,24 @@
|
||||
using System.Text;
|
||||
using Exsersewo.Common.Utilities;
|
||||
using ImageMagick;
|
||||
using Kynareth.Extensions;
|
||||
using Kynareth.Models;
|
||||
|
||||
namespace Kynareth.Managers;
|
||||
|
||||
public static partial class ImageManager
|
||||
public class ImageManipulator : ImageModifier
|
||||
{
|
||||
private static List<ImageManipulationImage> ManipulationEndpoints;
|
||||
|
||||
private static string ManipulationTemplateBaseFolder;
|
||||
|
||||
static void ConfigureManipulation(IConfiguration configuration, IWebHostEnvironment _appEnvironment)
|
||||
public ImageManipulator(IConfiguration configuration, IWebHostEnvironment appEnvironment)
|
||||
{
|
||||
ManipulationTemplateBaseFolder = Path.Combine(_appEnvironment.WebRootPath, configuration.GetValue<string>("ImageManipulation:Folder"));
|
||||
ManipulationTemplateBaseFolder = Path.Combine(appEnvironment.WebRootPath, configuration.GetValue<string>("ImageManipulation:Folder"));
|
||||
ManipulationEndpoints = configuration.GetSection("ImageManipulation:Templates").Get<List<ImageManipulationImage>>();
|
||||
}
|
||||
|
||||
public static IEnumerable<ImageManipulationImageRead> GetManipulationEndpoints()
|
||||
public IEnumerable<ImageManipulationImageRead> GetManipulationEndpoints()
|
||||
{
|
||||
return ManipulationEndpoints.Select(e => new ImageManipulationImageRead
|
||||
{
|
||||
@@ -26,7 +27,7 @@ public static partial class ImageManager
|
||||
});
|
||||
}
|
||||
|
||||
public static async Task<object> GenerateMemeImageAsync(string template, string[] texts, CancellationToken cancellationToken)
|
||||
public async Task<object> GenerateMemeImageAsync(string template, string[] texts, CancellationToken cancellationToken)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
38
src/Managers/ImageModifier.cs
Normal file
38
src/Managers/ImageModifier.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using ICU4N.Text;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Kynareth.Managers;
|
||||
|
||||
public class ImageModifier
|
||||
{
|
||||
protected static BreakIterator lineBreakIterator = BreakIterator.GetLineInstance(CultureInfo.InvariantCulture);
|
||||
|
||||
protected string GetText(string text)
|
||||
{
|
||||
StringBuilder newText = new();
|
||||
|
||||
// set the text to be broken
|
||||
lineBreakIterator.SetText(text);
|
||||
|
||||
// get the first boundary
|
||||
int start = lineBreakIterator.First();
|
||||
|
||||
// iterate over all boundaries
|
||||
for (int end = lineBreakIterator.Next(); end != BreakIterator.Done; start = end, end = lineBreakIterator.Next())
|
||||
{
|
||||
// get the current line
|
||||
string line = text.Substring(start, end - start);
|
||||
|
||||
// do something with the line
|
||||
newText.AppendLine(line);
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
|
||||
return newText.ToString();
|
||||
}
|
||||
|
||||
protected ObjectResult GetResult(int statusCode, object data)
|
||||
=> new(data) { StatusCode = statusCode };
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
using Exsersewo.Common.Utilities;
|
||||
using Kynareth.Helpers;
|
||||
using Kynareth.Helpers.AmongUs;
|
||||
using Kynareth.Managers;
|
||||
using Kynareth.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using StatsdClient;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.WebHost.UseKestrel();
|
||||
@@ -30,11 +32,24 @@ builder.Services.AddDbContext<KynarethDbContext>(options =>
|
||||
options.UseLazyLoadingProxies();
|
||||
}, contextLifetime: ServiceLifetime.Transient, optionsLifetime: ServiceLifetime.Singleton);
|
||||
|
||||
builder.Services.AddSingleton(builder.Environment);
|
||||
builder.Services.AddSingleton(builder.Configuration);
|
||||
builder.Services.AddSingleton<ImageManipulator>();
|
||||
builder.Services.AddSingleton<ImageGenerator>();
|
||||
builder.Services.AddSingleton<ImageMagiker>();
|
||||
builder.Services.AddSingleton<AmongUsGenerator>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
RequestHelper.Configure(app);
|
||||
ImageManager.Configure(app.Configuration, app.Environment);
|
||||
AmogusHelper.Configure(app.Environment);
|
||||
|
||||
var dogstatsdConfig = new StatsdConfig
|
||||
{
|
||||
StatsdServerName = "127.0.0.1",
|
||||
StatsdPort = 8125,
|
||||
};
|
||||
|
||||
DogStatsd.Configure(dogstatsdConfig);
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
//if (app.Environment.IsDevelopment())
|
||||
|
||||
Reference in New Issue
Block a user