diff options
| author | ivar <i@oiee.no> | 2025-10-26 11:33:38 +0100 |
|---|---|---|
| committer | ivar <i@oiee.no> | 2025-10-26 11:33:38 +0100 |
| commit | 2e8ad7dc6d49361c6ee00dc628e119c0c06e2779 (patch) | |
| tree | becc4cde99eff6ed1d168f9e9c454c0f2bbbee9d /VegaData/Program.cs | |
| parent | 8de1187b627625b94ef8088de3e9255ccd17baf4 (diff) | |
| download | vegadata-2e8ad7dc6d49361c6ee00dc628e119c0c06e2779.tar.xz vegadata-2e8ad7dc6d49361c6ee00dc628e119c0c06e2779.zip | |
.
Diffstat (limited to 'VegaData/Program.cs')
| -rw-r--r-- | VegaData/Program.cs | 140 |
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 |
