From 23c60aa4c76b12e19e9396c4bb4463cfa449638d Mon Sep 17 00:00:00 2001 From: Kieran Date: Wed, 6 Sep 2023 16:04:24 +0100 Subject: [PATCH] Save stream goal link --- NostrStreamer/ApiModel/PatchEvent.cs | 3 + .../Configuration/UserConfiguration.cs | 1 + NostrStreamer/Database/User.cs | 5 + .../20230906145453_StreamGoal.Designer.cs | 318 ++++++++++++++++++ .../Migrations/20230906145453_StreamGoal.cs | 28 ++ .../StreamerContextModelSnapshot.cs | 3 + NostrStreamer/Services/StreamEventBuilder.cs | 7 +- NostrStreamer/Services/UserService.cs | 3 +- 8 files changed, 366 insertions(+), 2 deletions(-) create mode 100644 NostrStreamer/Migrations/20230906145453_StreamGoal.Designer.cs create mode 100644 NostrStreamer/Migrations/20230906145453_StreamGoal.cs diff --git a/NostrStreamer/ApiModel/PatchEvent.cs b/NostrStreamer/ApiModel/PatchEvent.cs index 7401376..0bad53b 100644 --- a/NostrStreamer/ApiModel/PatchEvent.cs +++ b/NostrStreamer/ApiModel/PatchEvent.cs @@ -18,4 +18,7 @@ public class PatchEvent [JsonProperty("content_warning")] public string? ContentWarning { get; init; } + + [JsonProperty("goal")] + public string? Goal { get; init; } } diff --git a/NostrStreamer/Database/Configuration/UserConfiguration.cs b/NostrStreamer/Database/Configuration/UserConfiguration.cs index c63b4fa..5898059 100644 --- a/NostrStreamer/Database/Configuration/UserConfiguration.cs +++ b/NostrStreamer/Database/Configuration/UserConfiguration.cs @@ -21,5 +21,6 @@ public class UserConfiguration : IEntityTypeConfiguration builder.Property(a => a.Tags); builder.Property(a => a.ContentWarning); + builder.Property(a => a.Goal); } } diff --git a/NostrStreamer/Database/User.cs b/NostrStreamer/Database/User.cs index 775d6d5..d176abf 100644 --- a/NostrStreamer/Database/User.cs +++ b/NostrStreamer/Database/User.cs @@ -43,6 +43,11 @@ public class User /// Date when user accepted TOS /// public DateTime? TosAccepted { get; init; } + + /// + /// Stream goal + /// + public string? Goal { get; init; } /// /// Concurrency token diff --git a/NostrStreamer/Migrations/20230906145453_StreamGoal.Designer.cs b/NostrStreamer/Migrations/20230906145453_StreamGoal.Designer.cs new file mode 100644 index 0000000..5ca73d0 --- /dev/null +++ b/NostrStreamer/Migrations/20230906145453_StreamGoal.Designer.cs @@ -0,0 +1,318 @@ +// +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NostrStreamer.Database; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NostrStreamer.Migrations +{ + [DbContext(typeof(StreamerContext))] + [Migration("20230906145453_StreamGoal")] + partial class StreamGoal + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("NostrStreamer.Database.IngestEndpoint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("App") + .IsRequired() + .HasColumnType("text"); + + b.Property>("Capabilities") + .IsRequired() + .HasColumnType("text[]"); + + b.Property("Cost") + .HasColumnType("integer"); + + b.Property("Forward") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("App") + .IsUnique(); + + b.ToTable("Endpoints"); + }); + + modelBuilder.Entity("NostrStreamer.Database.Payment", b => + { + b.Property("PaymentHash") + .HasColumnType("text"); + + b.Property("Amount") + .HasColumnType("numeric(20,0)"); + + b.Property("Created") + .HasColumnType("timestamp with time zone"); + + b.Property("Invoice") + .HasColumnType("text"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("Nostr") + .HasColumnType("text"); + + b.Property("PubKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("PaymentHash"); + + b.HasIndex("PubKey"); + + b.ToTable("Payments"); + }); + + modelBuilder.Entity("NostrStreamer.Database.User", b => + { + b.Property("PubKey") + .HasColumnType("text"); + + b.Property("Balance") + .HasColumnType("bigint"); + + b.Property("ContentWarning") + .HasColumnType("text"); + + b.Property("Goal") + .HasColumnType("text"); + + b.Property("Image") + .HasColumnType("text"); + + b.Property("StreamKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("Summary") + .HasColumnType("text"); + + b.Property("Tags") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.Property("TosAccepted") + .HasColumnType("timestamp with time zone"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PubKey"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("NostrStreamer.Database.UserStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EdgeIp") + .IsRequired() + .HasColumnType("text"); + + b.Property("EndpointId") + .HasColumnType("uuid"); + + b.Property("Ends") + .HasColumnType("timestamp with time zone"); + + b.Property("Event") + .IsRequired() + .HasColumnType("text"); + + b.Property("ForwardClientId") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastSegment") + .HasColumnType("timestamp with time zone"); + + b.Property("PubKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("Starts") + .HasColumnType("timestamp with time zone"); + + b.Property("State") + .HasColumnType("integer"); + + b.Property("StreamId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Thumbnail") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("EndpointId"); + + b.HasIndex("PubKey"); + + b.ToTable("Streams"); + }); + + modelBuilder.Entity("NostrStreamer.Database.UserStreamGuest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("PubKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("Relay") + .HasColumnType("text"); + + b.Property("Role") + .HasColumnType("text"); + + b.Property("Sig") + .HasColumnType("text"); + + b.Property("StreamId") + .HasColumnType("uuid"); + + b.Property("ZapSplit") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("StreamId", "PubKey") + .IsUnique(); + + b.ToTable("Guests"); + }); + + modelBuilder.Entity("NostrStreamer.Database.UserStreamRecording", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Duration") + .HasColumnType("double precision"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserStreamId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserStreamId"); + + b.ToTable("Recordings"); + }); + + modelBuilder.Entity("NostrStreamer.Database.Payment", b => + { + b.HasOne("NostrStreamer.Database.User", "User") + .WithMany("Payments") + .HasForeignKey("PubKey") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NostrStreamer.Database.UserStream", b => + { + b.HasOne("NostrStreamer.Database.IngestEndpoint", "Endpoint") + .WithMany() + .HasForeignKey("EndpointId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NostrStreamer.Database.User", "User") + .WithMany("Streams") + .HasForeignKey("PubKey") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Endpoint"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NostrStreamer.Database.UserStreamGuest", b => + { + b.HasOne("NostrStreamer.Database.UserStream", "Stream") + .WithMany("Guests") + .HasForeignKey("StreamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Stream"); + }); + + modelBuilder.Entity("NostrStreamer.Database.UserStreamRecording", b => + { + b.HasOne("NostrStreamer.Database.UserStream", "Stream") + .WithMany() + .HasForeignKey("UserStreamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Stream"); + }); + + modelBuilder.Entity("NostrStreamer.Database.User", b => + { + b.Navigation("Payments"); + + b.Navigation("Streams"); + }); + + modelBuilder.Entity("NostrStreamer.Database.UserStream", b => + { + b.Navigation("Guests"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/NostrStreamer/Migrations/20230906145453_StreamGoal.cs b/NostrStreamer/Migrations/20230906145453_StreamGoal.cs new file mode 100644 index 0000000..323f01e --- /dev/null +++ b/NostrStreamer/Migrations/20230906145453_StreamGoal.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace NostrStreamer.Migrations +{ + /// + public partial class StreamGoal : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Goal", + table: "Users", + type: "text", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Goal", + table: "Users"); + } + } +} diff --git a/NostrStreamer/Migrations/StreamerContextModelSnapshot.cs b/NostrStreamer/Migrations/StreamerContextModelSnapshot.cs index a0f4011..67b2241 100644 --- a/NostrStreamer/Migrations/StreamerContextModelSnapshot.cs +++ b/NostrStreamer/Migrations/StreamerContextModelSnapshot.cs @@ -101,6 +101,9 @@ namespace NostrStreamer.Migrations b.Property("ContentWarning") .HasColumnType("text"); + b.Property("Goal") + .HasColumnType("text"); + b.Property("Image") .HasColumnType("text"); diff --git a/NostrStreamer/Services/StreamEventBuilder.cs b/NostrStreamer/Services/StreamEventBuilder.cs index 20c0f05..1fe1556 100644 --- a/NostrStreamer/Services/StreamEventBuilder.cs +++ b/NostrStreamer/Services/StreamEventBuilder.cs @@ -40,7 +40,7 @@ public class StreamEventBuilder new("image", stream.Thumbnail ?? user.Image ?? ""), new("status", status), new("p", user.PubKey, "", "host"), - new("relays", _config.Relays), + new("relays", _config.Relays) }; if (status == "live") @@ -66,6 +66,11 @@ public class StreamEventBuilder tags.Add(new("t", tag)); } + if (!string.IsNullOrEmpty(user.Goal)) + { + tags.Add(new("goal", user.Goal)); + } + var ev = new NostrEvent { Kind = StreamEventKind, diff --git a/NostrStreamer/Services/UserService.cs b/NostrStreamer/Services/UserService.cs index e5014ac..6c24a2f 100644 --- a/NostrStreamer/Services/UserService.cs +++ b/NostrStreamer/Services/UserService.cs @@ -98,6 +98,7 @@ public class UserService .SetProperty(v => v.Summary, req.Summary) .SetProperty(v => v.Image, req.Image) .SetProperty(v => v.Tags, req.Tags.Length > 0 ? string.Join(",", req.Tags) : null) - .SetProperty(v => v.ContentWarning, req.ContentWarning)); + .SetProperty(v => v.ContentWarning, req.ContentWarning) + .SetProperty(v => v.Goal, req.Goal)); } }