aboutsummaryrefslogtreecommitdiffstats
path: root/VegaData/Program.cs
diff options
context:
space:
mode:
authorivar <i@oiee.no>2025-10-26 11:33:38 +0100
committerivar <i@oiee.no>2025-10-26 11:33:38 +0100
commit2e8ad7dc6d49361c6ee00dc628e119c0c06e2779 (patch)
treebecc4cde99eff6ed1d168f9e9c454c0f2bbbee9d /VegaData/Program.cs
parent8de1187b627625b94ef8088de3e9255ccd17baf4 (diff)
downloadvegadata-2e8ad7dc6d49361c6ee00dc628e119c0c06e2779.tar.xz
vegadata-2e8ad7dc6d49361c6ee00dc628e119c0c06e2779.zip
.
Diffstat (limited to 'VegaData/Program.cs')
-rw-r--r--VegaData/Program.cs140
1 files changed, 140 insertions, 0 deletions
diff --git a/VegaData/Program.cs b/VegaData/Program.cs
new file mode 100644
index 0000000..76fd8e2
--- /dev/null
+++ b/VegaData/Program.cs
@@ -0,0 +1,140 @@
+using System.Text.Json.Serialization;
+using Microsoft.EntityFrameworkCore;
+
+var builder = WebApplication.CreateBuilder(args);
+
+builder.Services.AddHttpClient();
+builder.Services.AddDbContext<Database>(o => o.UseSqlite("Data Source=data/main.db"));
+builder.Services.AddHostedService<DataWorker>();
+
+var app = builder.Build();
+try {
+ using var scope = app.Services.CreateScope();
+ scope.ServiceProvider.GetRequiredService<Database>().Database.EnsureCreated();
+} catch (Exception e) {
+ Console.WriteLine(e);
+}
+
+app.MapStaticAssets();
+app.MapGet("shows", (Database db) => db.Shows.Where(c => c.StartDateTime >= DateTime.Now).ToList());
+app.MapGet("tz", () => TimeZoneInfo.Local.Id);
+app.MapGet("/", () => Results.Redirect("/index.html"));
+app.Run();
+
+class Database(DbContextOptions<Database> options) : DbContext(options)
+{
+ public DbSet<Show> Shows { get; set; }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder) {
+ modelBuilder.Entity<Show>().HasIndex(p => new {
+ p.Title,
+ p.StartDateTime
+ })
+ .IsUnique();
+ base.OnModelCreating(modelBuilder);
+ }
+}
+
+class Show
+{
+ public int Id { get; set; }
+ public required string Title { get; set; }
+ public required string Scene { get; set; }
+ public required DateTime StartDateTime { get; set; }
+ public required string TicketUrl { get; set; }
+ public required string Type { get; set; }
+ public required string MovieVersion { get; set; }
+ public required string MovieMainVersion { get; set; }
+ public required string[] Tags { get; set; }
+}
+
+class DataWorker(IServiceScopeFactory serviceScopeFactory) : BackgroundService
+{
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
+ const int interval = 1000 * 60 * 60;
+ while (!stoppingToken.IsCancellationRequested) {
+ try {
+ await Work(stoppingToken);
+ await Task.Delay(interval, stoppingToken);
+ } catch (Exception e) {
+ Console.WriteLine(e);
+ }
+ }
+ }
+
+ async Task Work(CancellationToken ct) {
+ using var scope = serviceScopeFactory.CreateScope();
+ var db = scope.ServiceProvider.GetRequiredService<Database>();
+ var http = scope.ServiceProvider.GetRequiredService<HttpClient>();
+ var logger = scope.ServiceProvider.GetRequiredService<ILogger<DataWorker>>();
+ var refreshData = Environment.GetEnvironmentVariable("VEGADATA_REFRESH_DATA") == "1";
+ logger.LogInformation("Syncing data. Refresh={RefreshData}", refreshData);
+ var shows = await http.GetFromJsonAsync<ShowsResponse>("https://www.vegascene.no/api/program", ct);
+ var addedCount = 0;
+ if (refreshData) {
+ File.Copy("data/main.db", $"data/main-{Random.Shared.Next(10000)}.db");
+ db.Shows.RemoveRange(db.Shows);
+ await db.SaveChangesAsync(ct);
+ }
+
+ var count = await db.Shows.CountAsync(ct);
+
+ foreach (var show in shows?.Shows ?? []) {
+ if (string.IsNullOrWhiteSpace(show.TicketSaleUrl)) continue;
+ var existing = await db.Shows.AnyAsync(s => s.Title == show.MovieTitle && s.StartDateTime == show.ShowStart, ct);
+ if (existing) continue;
+ logger.LogInformation("Adding show {Title} at {StartDateTime}", show.MovieTitle, show.ShowStart);
+ db.Shows.Add(new Show() {
+ Title = show.MovieTitle,
+ Scene = show.ScreenName,
+ StartDateTime = show.ShowStart,
+ MovieMainVersion = show.MovieMainVersionId,
+ MovieVersion = show.MovieVersionId,
+ TicketUrl = show.TicketSaleUrl,
+ Type = show.ShowType,
+ Tags = show.VersionTags.Select(t => t.Tag).ToArray()
+ });
+ addedCount++;
+ }
+ await db.SaveChangesAsync(ct);
+ logger.LogInformation("Synced data, old count:{Count}, new count:{AddedCount}", count, addedCount);
+ }
+
+ class ShowsResponse
+ {
+ public required List<VegaShow> Shows { get; set; }
+ }
+
+ class VegaShow
+ {
+ [JsonPropertyName("screenName")]
+ public required string ScreenName { get; set; }
+
+ [JsonPropertyName("ticketSaleUrl")]
+ public required string TicketSaleUrl { get; set; }
+
+ [JsonPropertyName("showType")]
+ public required string ShowType { get; set; }
+
+ [JsonPropertyName("showStart")]
+ public required DateTime ShowStart { get; set; }
+
+ [JsonPropertyName("movieVersionId")]
+ public required string MovieVersionId { get; set; }
+
+ [JsonPropertyName("movieMainVersionId")]
+ public required string MovieMainVersionId { get; set; }
+
+ [JsonPropertyName("movieTitle")]
+ public required string MovieTitle { get; set; }
+
+ [JsonPropertyName("versionTags")]
+ public required VersionTag[] VersionTags { get; set; }
+ }
+
+ public class VersionTag
+ {
+ [JsonPropertyName("tag")]
+ public required string Tag { get; set; }
+ }
+} \ No newline at end of file