Angius
Angius
Explore posts from servers
CC#
Created by Angius on 9/25/2024 in #help
✅ Rate limiting no worky
Got rate limiting all set up:
public static class RateLimiting
{
public const string Rss = nameof(Rss);
public const string Quotes = nameof(Quotes);
public const string Reports = nameof(Reports);

public static IServiceCollection AddRateLimiting(this IServiceCollection services)
{
return services.AddRateLimiter(x => x
.AddFixedWindowLimiter(policyName: Rss, options => {
options.Window = TimeSpan.FromHours(1);
})
.AddFixedWindowLimiter(policyName: Quotes, options => {
options.Window = TimeSpan.FromSeconds(10);
})
.AddFixedWindowLimiter(policyName: Reports, options => {
options.Window = TimeSpan.FromHours(1);
options.PermitLimit = 3;
})
);
}
}
public static class RateLimiting
{
public const string Rss = nameof(Rss);
public const string Quotes = nameof(Quotes);
public const string Reports = nameof(Reports);

public static IServiceCollection AddRateLimiting(this IServiceCollection services)
{
return services.AddRateLimiter(x => x
.AddFixedWindowLimiter(policyName: Rss, options => {
options.Window = TimeSpan.FromHours(1);
})
.AddFixedWindowLimiter(policyName: Quotes, options => {
options.Window = TimeSpan.FromSeconds(10);
})
.AddFixedWindowLimiter(policyName: Reports, options => {
options.Window = TimeSpan.FromHours(1);
options.PermitLimit = 3;
})
);
}
}
and registered
services.AddRateLimiting();
services.AddRateLimiting();
app.UseRateLimiter();
app.UseRateLimiter();
got rate limiting set on an endpoint:
using ReturnType = Results<NotFound, Ok<QuoteDto>>;

[Handler]
[MapGet("api/quotes/random")]
public static partial class GetRandomQuote
{
internal static void CustomizeEndpoint(IEndpointConventionBuilder endpoint) => endpoint
.RequireRateLimiting(RateLimiting.Quotes);

[UsedImplicitly]
public sealed record Query;

private static async ValueTask<ReturnType> HandleAsync(Query _, ApplicationDbContext context, CancellationToken cancellationToken)
{
var quote = await context.Database.SqlQueryRaw<QuoteDto>("""
SELECT q."Author", q."Body"
FROM "Quotes" q
TABLESAMPLE SYSTEM_ROWS(1)
LIMIT 1
""")
.FirstOrDefaultAsync(cancellationToken);

return quote is null ? TypedResults.NotFound() : TypedResults.Ok(quote);
}
}
using ReturnType = Results<NotFound, Ok<QuoteDto>>;

[Handler]
[MapGet("api/quotes/random")]
public static partial class GetRandomQuote
{
internal static void CustomizeEndpoint(IEndpointConventionBuilder endpoint) => endpoint
.RequireRateLimiting(RateLimiting.Quotes);

[UsedImplicitly]
public sealed record Query;

private static async ValueTask<ReturnType> HandleAsync(Query _, ApplicationDbContext context, CancellationToken cancellationToken)
{
var quote = await context.Database.SqlQueryRaw<QuoteDto>("""
SELECT q."Author", q."Body"
FROM "Quotes" q
TABLESAMPLE SYSTEM_ROWS(1)
LIMIT 1
""")
.FirstOrDefaultAsync(cancellationToken);

return quote is null ? TypedResults.NotFound() : TypedResults.Ok(quote);
}
}
and yet I can spam it ad infinitum and rate limiting never triggers. What gives?
74 replies
CC#
Created by Angius on 9/12/2024 in #help
EF Core 1-1 relationship with automatic discriminator
I have a CommentsThread entity and multiple ICommentable entities (Blogpost, Profile, Document, etc.) that all reference it:
public sealed class CommentsThread
{
public long Id { get; init; }
//...
}
public interface ICommentable
{
long CommentsThreadId { get; set; }
CommentsThread CommentsThread { get; set; }
}
public sealed Blogpost : ICommentable
{
public long CommentsThreadId { get; set; }
public CommentsThread CommentsThread { get; set; }
}
public sealed class CommentsThread
{
public long Id { get; init; }
//...
}
public interface ICommentable
{
long CommentsThreadId { get; set; }
CommentsThread CommentsThread { get; set; }
}
public sealed Blogpost : ICommentable
{
public long CommentsThreadId { get; set; }
public CommentsThread CommentsThread { get; set; }
}
now, I would like a way to easily find what the comments thread belongs to. Does it contain comments of a blogpost? User profile? Document? One way I figured was to reverse the relationship, and instead have a bunch of nullable FKs in the CommentsThread entity, pointing to all the ICommentables. That way, I could do some
string type;
if (thread.BlogpostId is not null) type = "blogpost";
else if (thread.ProfileId is not null) type = "profile";
else if (thread.DocumentId is not null) type = "document";
else type = "unknown";
string type;
if (thread.BlogpostId is not null) type = "blogpost";
else if (thread.ProfileId is not null) type = "profile";
else if (thread.DocumentId is not null) type = "document";
else type = "unknown";
but it all seems iffy at best. Ideally, what I would like instead, was some
public CommentsSource Source { get; private set; }
public long SourceId { get; private set; }
public CommentsSource Source { get; private set; }
public long SourceId { get; private set; }
properties on the CommentsThread, with CommentsSource being an enum. Problem is, I have nary a clue how to do that. I considered maybe computed columns, but they seemingly can only reference the current entity.
20 replies
CC#
Created by Angius on 8/7/2024 in #help
Adding Blazor to an existing Razor Pages project
I decided that messing around with SSR and JS for the admin panel is not worth the hassle and I'll just make it with Blazor. I don't care about the bundle size, I don't care about SignalR connections, seems to be a perfect fit. I think I did everything correctly, but I'm still getting errors out the wazoo.
//...
services.AddRazorComponents().AddInteractiveServerComponents();
//...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseBanMiddleware();
app.UseAntiforgery();
app.UseEndpoints(endpoints => {
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapOgma3Endpoints();
endpoints.MapGroup("panel")
.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
});
//...
services.AddRazorComponents().AddInteractiveServerComponents();
//...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseBanMiddleware();
app.UseAntiforgery();
app.UseEndpoints(endpoints => {
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapOgma3Endpoints();
endpoints.MapGroup("panel")
.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
});
but going to /panel results in the following:
An unhandled exception has occurred while executing the request.
System.InvalidOperationException: Unable to find the provided template 'panel/'
An unhandled exception has occurred while executing the request.
System.InvalidOperationException: Unable to find the provided template 'panel/'
With the whole log being https://pastie.io/bcixjg.yml
3 replies
DDeno
Created by Angius on 7/30/2024 in #help
Typing `parseArgs` from `@std/cli` properly
I'm having trouble figuring out how would I type the result of parseArgs with collect setting.
import { parseArgs } from "@std/cli";

const args = parseArgs(Deno.args, { collect: ["path"] });

generatePaths(params[0].toString(), args["path"]);
^^^^^^^^^^^^
import { parseArgs } from "@std/cli";

const args = parseArgs(Deno.args, { collect: ["path"] });

generatePaths(params[0].toString(), args["path"]);
^^^^^^^^^^^^
the error is caused by the function taking a { [key: string] string } as the second parameter, while args[path] is typed as unknown[]. The code works, just so we're clear, it's just the types that error out.
2 replies
NNuxt
Created by Angius on 7/8/2024 in #❓・help
Error 500 during prerendering, only on Cloudflare Pages
nuxt generate generates the site perfectly well on my machine. The same command used to build the site on Cloudflare Pages throws this at me:
18:27:09.253 [log] [nitro]
18:27:09.254 Errors prerendering:
18:27:09.254 [log] [nitro] ├─ /about (365ms)
18:27:09.254 │ ├── Error: [500]
18:27:09.254 │ └── Linked from /
18:27:09.254 [log] [nitro]
18:27:09.255 [error] Exiting due to prerender errors.
18:27:09.255 at prerender (node_modules/nitropack/dist/chunks/prerender.mjs:218:11)
18:27:09.255 at async node_modules/nuxt/dist/index.mjs:3540:7
18:27:09.255 at async build (node_modules/nuxt/dist/index.mjs:5333:5)
18:27:09.255 at async Object.run (node_modules/nuxi/dist/chunks/build.mjs:94:5)
18:27:09.256 at async Object.run (node_modules/nuxi/dist/chunks/generate.mjs:55:5)
18:27:09.256 at async runCommand$1 (node_modules/nuxi/dist/shared/nuxi.6aad497e.mjs:1648:16)
18:27:09.256 at async runCommand$1 (node_modules/nuxi/dist/shared/nuxi.6aad497e.mjs:1639:11)
18:27:09.256 at async runMain$1 (node_modules/nuxi/dist/shared/nuxi.6aad497e.mjs:1777:7)
18:27:09.256
18:27:09.256 [error] Exiting due to prerender errors.
18:27:09.305 error: script "generate" exited with code 1
18:27:09.310 Failed: Error while executing user command. Exited with error code: 1
18:27:09.322 Failed: build command exited with code: 1
18:27:11.109 Failed: error occurred while running build command
18:27:09.253 [log] [nitro]
18:27:09.254 Errors prerendering:
18:27:09.254 [log] [nitro] ├─ /about (365ms)
18:27:09.254 │ ├── Error: [500]
18:27:09.254 │ └── Linked from /
18:27:09.254 [log] [nitro]
18:27:09.255 [error] Exiting due to prerender errors.
18:27:09.255 at prerender (node_modules/nitropack/dist/chunks/prerender.mjs:218:11)
18:27:09.255 at async node_modules/nuxt/dist/index.mjs:3540:7
18:27:09.255 at async build (node_modules/nuxt/dist/index.mjs:5333:5)
18:27:09.255 at async Object.run (node_modules/nuxi/dist/chunks/build.mjs:94:5)
18:27:09.256 at async Object.run (node_modules/nuxi/dist/chunks/generate.mjs:55:5)
18:27:09.256 at async runCommand$1 (node_modules/nuxi/dist/shared/nuxi.6aad497e.mjs:1648:16)
18:27:09.256 at async runCommand$1 (node_modules/nuxi/dist/shared/nuxi.6aad497e.mjs:1639:11)
18:27:09.256 at async runMain$1 (node_modules/nuxi/dist/shared/nuxi.6aad497e.mjs:1777:7)
18:27:09.256
18:27:09.256 [error] Exiting due to prerender errors.
18:27:09.305 error: script "generate" exited with code 1
18:27:09.310 Failed: Error while executing user command. Exited with error code: 1
18:27:09.322 Failed: build command exited with code: 1
18:27:11.109 Failed: error occurred while running build command
1 replies
CC#
Created by Angius on 6/27/2024 in #help
`Microsoft.Extensions.Logging` and Serilog compatible timing library?
I'm currently using https://github.com/nblumhardt/serilog-timings to log how much time a given operation took. It was nice and all when I was using a static logger, but I wanted to switch to an injected ILogger instance. Problem is, SerilogTimings works on a Serilog.ILogger instance, not MEL.ILogger which feels kinda smelly to me. Is there any other library I could use with Serilog and MEL that would let me easily time whatever operations?
4 replies
CC#
Created by Angius on 5/28/2024 in #help
Getting route data from a WebAPI without Swagger
The way I'm currently generating TS clients, is I use NSwag to get the OpenAPI spec, then I have a tool written in JS that parses that json and generates TS clients. I was thinking of eliminating some steps from that, though. The way I see it, I should be able to make a console app that references my WebAPI project, and somehow get the route data from there. All nicely typed and all. Bypassing Swagger completely. Can't figure out how, though
15 replies
CC#
Created by Angius on 4/24/2024 in #help
Random temperature curve generation too biased
No description
16 replies
CC#
Created by Angius on 4/4/2024 in #help
✅ SkiaSharp canvas scale not scaling
I have a method that takes an int[,] array with ones and zeroes. Based on that, I want to create an image, that is optionally resized and blurred. Creating the image at 1:1 scale works, blurring it works as well, but for the love of me I cannot get it to scale...
byte[] CreateImage(int[,] arr, float? scale = null, float? blur = null)
{
var wSize = arr.GetLength(0);
var hSize = arr.GetLength(1);

var bmp = new SKBitmap(wSize, hSize);
using (var canvas = new SKCanvas(bmp))
{
for (var w = 0; w < wSize; w++)
{
for (var h = 0; h < hSize; h++)
{
canvas.DrawPoint(w, h, arr[w, h] == 0 ? SKColors.White : SKColors.Black);
}
}

if (scale is {} s)
{
canvas.Scale(s);
}
}

if (blur is {} b)
{
var newBmp = new SKBitmap((int)(wSize * scale ?? 1), (int)(hSize * scale ?? 1));
using var canvas = new SKCanvas(newBmp);
using var paint = new SKPaint();

paint.ImageFilter = SKImageFilter.CreateBlur(b, b);
canvas.DrawImage(SKImage.FromBitmap(bmp), 0, 0, paint);

using var blurredImage = SKImage.FromBitmap(newBmp);
return blurredImage.Encode().ToArray();
}

using var image = SKImage.FromBitmap(bmp);
return image.Encode().ToArray();
}
byte[] CreateImage(int[,] arr, float? scale = null, float? blur = null)
{
var wSize = arr.GetLength(0);
var hSize = arr.GetLength(1);

var bmp = new SKBitmap(wSize, hSize);
using (var canvas = new SKCanvas(bmp))
{
for (var w = 0; w < wSize; w++)
{
for (var h = 0; h < hSize; h++)
{
canvas.DrawPoint(w, h, arr[w, h] == 0 ? SKColors.White : SKColors.Black);
}
}

if (scale is {} s)
{
canvas.Scale(s);
}
}

if (blur is {} b)
{
var newBmp = new SKBitmap((int)(wSize * scale ?? 1), (int)(hSize * scale ?? 1));
using var canvas = new SKCanvas(newBmp);
using var paint = new SKPaint();

paint.ImageFilter = SKImageFilter.CreateBlur(b, b);
canvas.DrawImage(SKImage.FromBitmap(bmp), 0, 0, paint);

using var blurredImage = SKImage.FromBitmap(newBmp);
return blurredImage.Encode().ToArray();
}

using var image = SKImage.FromBitmap(bmp);
return image.Encode().ToArray();
}
5 replies
CC#
Created by Angius on 2/9/2024 in #help
✅ Hex color converter breaks on 3-digit and 4-digit values
No description
5 replies
CC#
Created by Angius on 1/17/2024 in #help
Is there any way to *conditionally* set a property with EF `.ExecuteUpdateAsync()`?
Right now, I'm doing
var thing = await _ctx.Things.FirstOrDefaultAsync(t => t.Id == req.Id);
if (thing.Name != req.Name) thing.Name = req.Name;
if (thing.Count != req.Count) thing.Count = req.Count;
await _ctx.SaveChangesAsync();
var thing = await _ctx.Things.FirstOrDefaultAsync(t => t.Id == req.Id);
if (thing.Name != req.Name) thing.Name = req.Name;
if (thing.Count != req.Count) thing.Count = req.Count;
await _ctx.SaveChangesAsync();
but I'm not sure how would I do something similar, as in, something that avoids setting x.Name = x.Name, with the Execute method. Something like
var rows = await _ctx.Things.Where(t => t.Id == req.Id)
.ExecuteUpdateAsync(props => props
.SetPropertyIf(t => t.Name != req.Name, t => t.Name, req.Name)
.SetPropertyIf(t => t.Count != req.Count, t => t.Count, req.Count))
var rows = await _ctx.Things.Where(t => t.Id == req.Id)
.ExecuteUpdateAsync(props => props
.SetPropertyIf(t => t.Name != req.Name, t => t.Name, req.Name)
.SetPropertyIf(t => t.Count != req.Count, t => t.Count, req.Count))
but no such thing seems to exist.
20 replies
CC#
Created by Angius on 7/17/2023 in #help
❔ Azure DevOps repo remote unpack failed
I have a Git repo set up, it's an UE5 project which means large binaries, and Azure repos have unlimited size, so that's why not Github. I'm trying to push the project over SSH, but I'm getting some weird errors
❯ git push -u origin --all
Enter passphrase for key [key]:
Enumerating objects: 2462, done.
Counting objects: 100% (2462/2462), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2433/2433), done.
remote: The archive entry was compressed using an unsupported compression method.
send-pack: unexpected disconnect while reading sideband packet
fatal: sha1 file '<stdout>' write error: Broken pipe
error: remote unpack failed: error The archive entry was compressed using an unsupported compression method.
fatal: the remote end hung up unexpectedly
❯ git push -u origin --all
Enter passphrase for key [key]:
Enumerating objects: 2462, done.
Counting objects: 100% (2462/2462), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2433/2433), done.
remote: The archive entry was compressed using an unsupported compression method.
send-pack: unexpected disconnect while reading sideband packet
fatal: sha1 file '<stdout>' write error: Broken pipe
error: remote unpack failed: error The archive entry was compressed using an unsupported compression method.
fatal: the remote end hung up unexpectedly
23 replies
CC#
Created by Angius on 6/25/2023 in #help
❔ Code from the new Gundam episode
11 replies
CC#
Created by Angius on 6/21/2023 in #help
❔ Windows - system restore on PC shutdown
Not a C# question, I know, but I've no idea where else to turn to lol Students at my school do all sorts of stuff with the PCs. Weird wallpapers, meatspin in autostart, weird bat files, installing Roblox, all kinds of stuff like that. Not everything can be prevented with just an admin password, AFAIK. Back in college, they had some system set up that would roll back the PC on shutdown (or was it startup?) to a set restore point. So all the software and stuff was still there, but all the settings would be rolled back, and all the newly-installed stuff would be removed. I'd like to use something like that in this school as well, but for the love of me I cannot remember the name of the soft
12 replies
CC#
Created by Angius on 5/21/2023 in #help
❔ Properly including XML templates in a class library
I'm writing a library for generating .epub files. Since they're just glorified zips with XML files inside, I'll need to generate that XML somehow. The easiest way is to just have some templates with the XML and placeholders, and run a .Replace() on them or use some templating library. Question is, how do I store those templates properly? Using triple-quoted string constants would be the easiest, but some of the XML is quite large. I could just store loose files and load them with File.ReadAllTextAsync(), but not sure how well that'd work in the class lib context. Not to mention, I'd like those templates to be available at all times, I'd rather avoid reading them from the filesystem each time I want to generate an epub. Using DI somehow is an idea, I could read the templates once and inject them as a singleton or something, but how do I even make DI work in a class lib, not knowing if the user of the library even uses DI in the first place? I'd consider source generators and just reading files on compile time and adding them to some Template const in each class that needs it, but source generators can't read files... Any ideas would be welcome
21 replies
CC#
Created by Angius on 4/22/2023 in #help
✅ Avalonia — stop children from triggering parent events
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3"
Orientation="Horizontal"
Background="Black"
Opacity="0.7" PointerPressed="InputElement_OnPointerPressed">
<Button Command="{Binding NewWindowCommand}">S</Button>
<Button Command="{Binding MainViewCommand}">Home</Button>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3"
Orientation="Horizontal"
Background="Black"
Opacity="0.7" PointerPressed="InputElement_OnPointerPressed">
<Button Command="{Binding NewWindowCommand}">S</Button>
<Button Command="{Binding MainViewCommand}">Home</Button>
</StackPanel>
with the following codebehind
private void InputElement_OnPointerPressed(object? sender, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void InputElement_OnPointerPressed(object? sender, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
makes it so that clicking on the buttons doesn't trigger their commands, but rather the click gets captured by the parent and the window gets dragged
24 replies
CC#
Created by Angius on 2/16/2023 in #help
❔ Ownership-based permission system...?
So, in my ASP.NET 7 app I have a system of user clubs. Each club can have a founder and members, and each member can also be a mod for that community. The roles of a founder and moderator are represented as an enum on the join table. Now, I want to restrict some stuff to given roles. Like, only the founder can edit the settings of the club, and only the moderators or founders can kick or ban users. And you need to be a member to post there, etc. Currently, I just add one more .Where() to each query that checks for the given role, but maybe there's some better solution? Some middleware or something that'd let me just slap [Authorize(PolicyNames.ClubFounder)] onto a controller and be done with it?
13 replies
CC#
Created by Angius on 1/29/2023 in #help
❔ ✅ Rider is out of its mind about `async` code
7 replies
CC#
Created by Angius on 1/1/2023 in #help
❔ Return gets ignored for some godforsaken reason
82 replies