Add Ntfy message box
This commit is contained in:
parent
ca997d10b1
commit
82dc4f227e
4 changed files with 160 additions and 4 deletions
|
@ -1,5 +1,8 @@
|
||||||
@page "/"
|
@page "/"
|
||||||
|
@using System.ComponentModel.DataAnnotations
|
||||||
|
@using System.Text.Json
|
||||||
@using PancakesWeb.Data
|
@using PancakesWeb.Data
|
||||||
|
@using PancakesWeb.Schema
|
||||||
|
|
||||||
<PageTitle>Home</PageTitle>
|
<PageTitle>Home</PageTitle>
|
||||||
|
|
||||||
|
@ -121,4 +124,41 @@
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<h2 id="notify">Notify</h2>
|
||||||
|
<p>Send me a push notification. This will be a silent notification on my phone with no popup, vibration, or sound.</p>
|
||||||
|
|
||||||
|
<EditForm Model="Ntfy" OnValidSubmit="SubmitNtfy" FormName="Ntfy">
|
||||||
|
<DataAnnotationsValidator/>
|
||||||
|
<InputText @bind-Value="Ntfy.Message" maxlength="128" placeholder="Message"/>
|
||||||
|
<button type="submit">Send</button>
|
||||||
|
<ValidationSummary/>
|
||||||
|
</EditForm>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Inject] private HttpClient Http { get; set; } = null!;
|
||||||
|
[Inject] private IConfiguration Config { get; set; } = null!;
|
||||||
|
|
||||||
|
[SupplyParameterFromForm] private NtfyModel Ntfy { get; set; } = new NtfyModel();
|
||||||
|
|
||||||
|
private async Task SubmitNtfy()
|
||||||
|
{
|
||||||
|
var ntfy = new NtfyRequest
|
||||||
|
{
|
||||||
|
Topic = Config["Ntfy:Topic"]!,
|
||||||
|
Message = Ntfy.Message,
|
||||||
|
Title = "pancakes.gay",
|
||||||
|
Priority = 2,
|
||||||
|
Tags = ["black_cat"]
|
||||||
|
};
|
||||||
|
|
||||||
|
await Http.PostAsJsonAsync(Config["Ntfy:Url"], ntfy, JsonSerializerOptions.Web);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NtfyModel
|
||||||
|
{
|
||||||
|
[StringLength(128)]
|
||||||
|
public string Message { get; set; } = "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,14 @@ var builder = WebApplication.CreateBuilder(args);
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
builder.Services.AddRazorComponents()
|
builder.Services.AddRazorComponents()
|
||||||
.AddInteractiveServerComponents();
|
.AddInteractiveServerComponents();
|
||||||
|
builder.Services.AddHttpClient();
|
||||||
|
|
||||||
|
builder.Configuration.AddEnvironmentVariables();
|
||||||
|
|
||||||
|
if (builder.Configuration["Ntfy:Url"] == null)
|
||||||
|
throw new Exception("Ntfy:Url is unset");
|
||||||
|
if (builder.Configuration["Ntfy:Topic"] == null)
|
||||||
|
throw new Exception("Ntfy:Topic is unset");
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
|
88
PancakesWeb/Schema/NtfyRequest.cs
Normal file
88
PancakesWeb/Schema/NtfyRequest.cs
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace PancakesWeb.Schema;
|
||||||
|
|
||||||
|
public class NtfyRequest
|
||||||
|
{
|
||||||
|
public required string Topic { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Message { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Title { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public List<string>? Tags { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public int? Priority { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public List<NtfyAction>? Actions { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Click { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Attach { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public bool? Markdown { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Icon { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Filename { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Delay { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Email { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Call { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonDerivedType(typeof(NtfyViewAction), "view")]
|
||||||
|
[JsonDerivedType(typeof(NtfyBroadcastAction), "broadcast")]
|
||||||
|
[JsonDerivedType(typeof(NtfyHttpAction), "http")]
|
||||||
|
[JsonPolymorphic(TypeDiscriminatorPropertyName = "action",
|
||||||
|
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)]
|
||||||
|
public abstract class NtfyAction
|
||||||
|
{
|
||||||
|
public required string Label { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public bool? Clear { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NtfyViewAction : NtfyAction
|
||||||
|
{
|
||||||
|
public required string Url { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NtfyBroadcastAction : NtfyAction
|
||||||
|
{
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Intent { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public Dictionary<string, string>? Extras { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NtfyHttpAction : NtfyAction
|
||||||
|
{
|
||||||
|
public required string Url { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Method { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public Dictionary<string, string>? Headers { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public string? Body { get; set; }
|
||||||
|
}
|
|
@ -109,7 +109,7 @@ pre code {
|
||||||
text-wrap: nowrap;
|
text-wrap: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button, input[type=submit] {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0.5em 1em;
|
padding: 0.5em 1em;
|
||||||
|
|
||||||
|
@ -121,12 +121,28 @@ button {
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: 0.2s background-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover, button:focus {
|
button:hover, button:focus, input[type=submit]:hover, input[type=submit]:focus {
|
||||||
background-color: color-mix(in srgb, var(--accent) 80%, var(--background));
|
background-color: color-mix(in srgb, var(--accent) 80%, var(--background));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input, textarea {
|
||||||
|
padding: 0.5rem;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
background-color: var(--foreground);
|
||||||
|
color: var(--text);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
transition: 0.2s border;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, textarea:focus {
|
||||||
|
border-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
.copy-code-button {
|
.copy-code-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -166,6 +182,10 @@ pre code:hover + .copy-code-button, .copy-code-button:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.validation-errors {
|
||||||
|
color: var(--error);
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes title-fade-in {
|
@keyframes title-fade-in {
|
||||||
0% {
|
0% {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue