using System.Net.WebSockets; using Newtonsoft.Json; using Nostr.Client.Json; namespace NostrRelay; public static class Extensions { public static void MapRelay(this WebApplication app, string path, RelayDocument? document = null, string? landingPage = null) where TRelay : INostrRelay, IDisposable { app.MapGet(path, async ctx => { if (ctx.WebSockets.IsWebSocketRequest) { var logger = app.Services.GetRequiredService>>(); using var handler = app.Services.GetRequiredService(); try { var ws = await ctx.WebSockets.AcceptWebSocketAsync(); var wsCtx = new NostrClientContext(ws, ctx.Connection.RemoteIpAddress!, ctx.Request.Headers.UserAgent.FirstOrDefault() ?? string.Empty); var nostrRelay = new NostrRelay(handler, wsCtx, ctx.RequestAborted, logger); await nostrRelay.Read(); await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, null, ctx.RequestAborted); } catch (Exception ex) { logger.LogDebug(ex.Message); } } else { var isRelayDocRequest = ctx.Request.Headers.Accept.FirstOrDefault() ?.Equals("application/nostr+json", StringComparison.InvariantCultureIgnoreCase) ?? false; if (isRelayDocRequest) { var doc = document ?? new RelayDocument { Name = typeof(TRelay).Name, Description = "NostrServices C# Relay Framework", Pubkey = "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed", SupportedNips = [1], Software = "NostrServices", Icon = "https://void.cat/d/CtXsF5EvqNLG3K85TgezCt.webp", Limitation = new() { RestrictedWrites = false, AuthRequired = false, PaymentRequired = false } }; if (ctx.Response.Headers.AccessControlAllowOrigin.Count == 0) { ctx.Response.Headers.AccessControlAllowOrigin = "*"; } ctx.Response.ContentType = "application/json"; await ctx.Response.WriteAsync(JsonConvert.SerializeObject(doc, NostrSerializer.Settings)); } else { ctx.Response.ContentType = "text/html"; await ctx.Response.WriteAsync(landingPage ?? @$" NostrServices Relay

Welcome to {typeof(TRelay).Name}

"); } } }); } }