diff --git a/Pages/Index.cshtml b/Pages/Index.cshtml
index ed6f0fb..9347543 100644
--- a/Pages/Index.cshtml
+++ b/Pages/Index.cshtml
@@ -1,17 +1,22 @@
@page
+@using global::c3stream.DataModels
@model IndexModel
@{
- ViewData["Title"] = "Home";
- var cookie = c3stream.UpdateCookie(Request, Response, "/");
+ ViewData["Title"] = "Home";
+ var cookie = c3stream.UpdateCookie(Request, Response, "/");
+ var marked = new Database.DbConn().States.Any(p => p.UserId == cookie && p.State == "marked");
}
-
Welcome to c3stream!
- Your bookmark link:
-
https://@Request.Host.Value?bookmark=@cookie
-
- @foreach (var conf in c3stream.Conferences) {
-
@conf.Acronym
- }
-
+
Welcome to c3stream!
+ Your bookmark link:
+
https://@Request.Host.Value?bookmark=@cookie
+
\ No newline at end of file
diff --git a/Pages/Watchlist.cshtml b/Pages/Watchlist.cshtml
new file mode 100644
index 0000000..504ac9a
--- /dev/null
+++ b/Pages/Watchlist.cshtml
@@ -0,0 +1,110 @@
+@page
+@model WatchlistModel
+@using System.Net
+@using global::c3stream.DataModels
+@using static WatchlistModel
+@{
+ var cookie = c3stream.UpdateCookie(Request, Response, $"/Watchlist");
+ ViewData["Title"] = "Watchlist";
+ await using var db = new Database.DbConn();
+ var states = db.States.ToList();
+ var marked = db.States.Where(p => p.UserId == cookie && p.State == "marked").Select(p => p.TalkId).ToList();
+ var watchlist = c3stream.GetEventsByGuid(marked);
+}
+
+
+
+
+ Conference |
+ Event |
+
+ @Html.Raw(Request.Query["orderby"] == "published" ? $"Published" : $"Date")
+ |
+ Category |
+ Title |
+ Speaker(s) |
+ Lang |
+ Actions |
+
+
+
+ @foreach (var talk in Request.Query["orderby"] == "published" ? watchlist.OrderByDescending(p => p.ReleaseDate) : watchlist.OrderBy(p => p.Date)) {
+ var state = states.FirstOrDefault(p => p.TalkId == talk.Guid && p.UserId == cookie)?.State;
+ var isWatched = state == "watched";
+ var isMarked = state == "marked";
+ var file = $"{talk.Slug}.mp4";
+ var conference = c3stream.GetConferenceByEventGuid(talk.Guid);
+ var eventName = talk.Tags.Count <= 1 ? conference.Acronym : talk.Tags[0].Replace("-", "-
");
+ var category = talk.Tags.Count switch {
+ 0 => "",
+ 1 => talk.Tags[0],
+ 2 => "",
+ 3 => talk.Tags[2],
+ 4 => talk.Tags[3],
+ 5 => talk.Tags[3],
+ 6 => talk.Tags[3], // rc3: is this correct?
+ _ => ""
+ };
+
+ @Html.Raw(eventName) |
+ @(Request.Query["orderby"] == "published" ? talk.ReleaseDate?.Date.ToShortDateString() : talk.Date?.Date.ToShortDateString()) |
+ @category |
+ @if (isWatched) {
+ @talk.Title |
+ }
+ else if (isMarked) {
+ @talk.Title |
+ }
+ else {
+ @talk.Title |
+ }
+ @(talk.Persons.Any() ? talk.Persons.Aggregate((s, s1) => $"{s}, {s1}") : "") |
+ @talk.OriginalLanguage |
+
+
+
+
+
+ @if (System.IO.File.Exists(System.IO.Path.Combine(c3stream.CachePath, conference.Acronym, file))) {
+
+
+
+ }
+ else {
+
+
+
+ }
+
+
+
+ @if (isWatched) {
+
+
+ }
+ else if (isMarked) {
+
+
+ }
+ else {
+
+
+ }
+
+ |
+
+ }
+
+
\ No newline at end of file
diff --git a/Pages/Watchlist.cshtml.cs b/Pages/Watchlist.cshtml.cs
new file mode 100644
index 0000000..8a9b367
--- /dev/null
+++ b/Pages/Watchlist.cshtml.cs
@@ -0,0 +1,39 @@
+using System.Collections.Generic;
+using System.Linq;
+using c3stream.DataModels;
+using c3stream.DataModels.Tables;
+using LinqToDB;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+
+namespace c3stream.Pages {
+ public class WatchlistModel : PageModel {
+ private readonly ILogger _logger;
+
+ public WatchlistModel(ILogger logger) => _logger = logger;
+
+ public void OnGet() {
+ var guid = Request.Query["guid"].ToString();
+ var state = Request.Query["state"].ToString();
+ var userid = Request.Cookies["bookmark"];
+ if (string.IsNullOrWhiteSpace(guid) || string.IsNullOrWhiteSpace(state) || !Request.Cookies.ContainsKey("bookmark"))
+ return;
+
+ using var db = new Database.DbConn();
+ var existing = db.States.FirstOrDefault(p => p.TalkId == guid && p.UserId == userid);
+ if (existing != null)
+ if (state == "unwatched")
+ db.States.Delete(p => p == existing);
+ else {
+ existing.State = state;
+ db.Update(existing);
+ }
+ else
+ db.Insert(new States {
+ State = state, TalkId = guid, UserId = userid
+ });
+ Response.Redirect("/");
+ }
+ }
+}
\ No newline at end of file
diff --git a/c3stream.cs b/c3stream.cs
index a1c005b..598c146 100644
--- a/c3stream.cs
+++ b/c3stream.cs
@@ -9,127 +9,129 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
-namespace c3stream {
- public static class c3stream {
- public const string DataPath = "data";
- public const string DbFile = "c3stream.sqlite";
- public const string CachePath = "/mnt/storage/archive/Video/congress/";
- public const string CacheUrl = "https://mirror.c3stream.de/";
- public static object Lock = new();
- public static string DbPath = Path.Combine(DataPath, DbFile);
+namespace c3stream;
- public static readonly List Conferences = new() {
- new ConferenceObject("rc3-2021", true),
- new ConferenceObject("rc3"),
- new ConferenceObject("36c3"),
- new ConferenceObject("camp2019"),
- new ConferenceObject("gpn19"),
- new ConferenceObject("35c3"),
- new ConferenceObject("34c3"),
- new ConferenceObject("33c3"),
- new ConferenceObject("32c3"),
- new ConferenceObject("31c3"),
- new ConferenceObject("30c3")
- };
+public static class c3stream {
+ public const string DataPath = "data";
+ public const string DbFile = "c3stream.sqlite";
+ public const string CachePath = "/mnt/storage/archive/Video/congress/";
+ public const string CacheUrl = "https://mirror.c3stream.de/";
+ public static object Lock = new();
+ public static string DbPath = Path.Combine(DataPath, DbFile);
- public static void Main(string[] args) {
- if (!Directory.Exists(DataPath))
- Directory.CreateDirectory(DataPath);
- if (!File.Exists(DbPath))
- File.Copy(Path.Combine(DataPath, "database.init.sqlite"), DbPath);
+ public static readonly List Conferences = new() {
+ new ConferenceObject("rc3-2021", true),
+ new ConferenceObject("rc3"),
+ new ConferenceObject("36c3"),
+ new ConferenceObject("camp2019"),
+ new ConferenceObject("gpn19"),
+ new ConferenceObject("35c3"),
+ new ConferenceObject("34c3"),
+ new ConferenceObject("33c3"),
+ new ConferenceObject("32c3"),
+ new ConferenceObject("31c3"),
+ new ConferenceObject("30c3")
+ };
- DataConnection.DefaultSettings = new Database.Settings();
+ public static void Main(string[] args) {
+ if (!Directory.Exists(DataPath))
+ Directory.CreateDirectory(DataPath);
+ if (!File.Exists(DbPath))
+ File.Copy(Path.Combine(DataPath, "database.init.sqlite"), DbPath);
- foreach (var conference in Conferences)
- UpdateConference(conference);
+ DataConnection.DefaultSettings = new Database.Settings();
+ Migrations.RunMigrations();
- if (args.Length != 0) {
- if (args[0] == "logo")
- foreach (var conference in Conferences) {
- Console.WriteLine($"wget {conference.LogoUri} -O {Path.Combine(CachePath, conference.Acronym, "logo.png")}");
- }
- else if (Conferences.All(p => p.Acronym != args[0]))
- Console.WriteLine("No matching conference found.");
- else
- foreach (var talk in Conferences.First(p => p.Acronym == args[0]).Talks)
- Console.WriteLine($"youtube-dl -f \"best[ext = mp4]\" {talk.FrontendLink} -o \"{Path.Combine(CachePath, args[0], talk.Slug)}.mp4\"");
- }
- else {
- CreateHostBuilder(args).Build().Run();
- }
+ foreach (var conference in Conferences)
+ UpdateConference(conference);
+
+ if (args.Length != 0) {
+ if (args[0] == "logo")
+ foreach (var conference in Conferences)
+ Console.WriteLine($"wget {conference.LogoUri} -O {Path.Combine(CachePath, conference.Acronym, "logo.png")}");
+ else if (Conferences.All(p => p.Acronym != args[0]))
+ Console.WriteLine("No matching conference found.");
+ else
+ foreach (var talk in Conferences.First(p => p.Acronym == args[0]).Talks)
+ Console.WriteLine($"youtube-dl -f \"best[ext = mp4]\" {talk.FrontendLink} -o \"{Path.Combine(CachePath, args[0], talk.Slug)}.mp4\"");
+ }
+ else {
+ CreateHostBuilder(args).Build().Run();
+ }
+ }
+
+ //TODO: move this to the database as well
+ public static void UpdateConference(ConferenceObject conference) {
+ using var httpc = new HttpClient();
+
+ var jsonpath = Path.Combine(DataPath, conference.Acronym + "_index.json");
+ var json = "";
+ if (!File.Exists(jsonpath)) {
+ json = httpc.GetStringAsync($"https://api.media.ccc.de/public/conferences/{conference.Acronym}").Result;
+ File.WriteAllText(jsonpath, json);
+ }
+ else if (conference.Ongoing) {
+ json = httpc.GetStringAsync($"https://api.media.ccc.de/public/conferences/{conference.Acronym}").Result;
+ }
+ else {
+ json = File.ReadAllText(jsonpath);
}
- //TODO: move this to the database as well
- public static void UpdateConference(ConferenceObject conference) {
- using var httpc = new HttpClient();
+ var parsed = Conference.FromJson(json);
+ lock (Lock) {
+ conference.Talks.Clear();
+ conference.LogoUri = parsed.LogoUrl.AbsoluteUri;
+ conference.Talks.AddRange(parsed.Events);
+ conference.Talks.ForEach(p => p.Guid = p.Guid.Trim());
+ }
+ }
- var jsonpath = Path.Combine(DataPath, conference.Acronym + "_index.json");
- var json = "";
- if (!File.Exists(jsonpath)) {
- json = httpc.GetStringAsync($"https://api.media.ccc.de/public/conferences/{conference.Acronym}").Result;
- File.WriteAllText(jsonpath, json);
- }
- else if (conference.Ongoing) {
- json = httpc.GetStringAsync($"https://api.media.ccc.de/public/conferences/{conference.Acronym}").Result;
- }
- else {
- json = File.ReadAllText(jsonpath);
- }
-
- var parsed = Conference.FromJson(json);
- lock (Lock) {
- conference.Talks.Clear();
- conference.LogoUri = parsed.LogoUrl.AbsoluteUri;
- conference.Talks.AddRange(parsed.Events);
- conference.Talks.ForEach(p => p.Guid = p.Guid.Trim());
- }
+ public static string UpdateCookie(HttpRequest request, HttpResponse response, string redirectUri) {
+ var cookie = "";
+ //if new bookmark is in uri
+ if (request.Query.ContainsKey("bookmark") && Guid.TryParseExact(request.Query["bookmark"], "D", out _)) {
+ response.Cookies.Append("bookmark", request.Query["bookmark"], new CookieOptions { Expires = DateTimeOffset.MaxValue });
+ cookie = request.Query["bookmark"];
+ }
+ //if no cookie exists or cookie is invalid
+ else if (!request.Cookies.ContainsKey("bookmark") || !Guid.TryParseExact(request.Cookies["bookmark"], "D", out _)) {
+ var guid = Guid.NewGuid().ToString();
+ response.Cookies.Append("bookmark", guid, new CookieOptions { Expires = DateTimeOffset.MaxValue });
+ cookie = guid;
+ }
+ else {
+ cookie = request.Cookies["bookmark"];
}
- public static string UpdateCookie(HttpRequest request, HttpResponse response, string redirectUri) {
- var cookie = "";
- //if new bookmark is in uri
- if (request.Query.ContainsKey("bookmark") && Guid.TryParseExact(request.Query["bookmark"], "D", out _)) {
- response.Cookies.Append("bookmark", request.Query["bookmark"], new CookieOptions { Expires = DateTimeOffset.MaxValue });
- cookie = request.Query["bookmark"];
- }
- //if no cookie exists or cookie is invalid
- else if (!request.Cookies.ContainsKey("bookmark") || !Guid.TryParseExact(request.Cookies["bookmark"], "D", out _)) {
- var guid = Guid.NewGuid().ToString();
- response.Cookies.Append("bookmark", guid, new CookieOptions { Expires = DateTimeOffset.MaxValue });
- cookie = guid;
- }
- else {
- cookie = request.Cookies["bookmark"];
- }
+ if (request.Query.ContainsKey("bookmark"))
+ response.Redirect(redirectUri);
- if (request.Query.ContainsKey("bookmark")) {
- response.Redirect(redirectUri);
- }
+ return cookie;
+ }
- return cookie;
- }
+ public static Event GetEventByGuid(string guid) {
+ return Conferences.SelectMany(c => c.Talks.Where(e => e.Guid == guid)).FirstOrDefault();
+ }
- public static Event GetEventByGuid(string guid) {
- return Conferences.SelectMany(c => c.Talks.Where(talk => talk.Guid.ToString() == guid)).FirstOrDefault();
- }
+ public static IEnumerable GetEventsByGuid(IEnumerable guids) {
+ return Conferences.SelectMany(c => c.Talks.Where(e => guids.Contains(e.Guid)));
+ }
- public static ConferenceObject GetConferenceByEventGuid(string guid) {
- return Conferences.FirstOrDefault(c => c.Talks.Any(t => t.Guid.ToString() == guid));
- }
+ public static ConferenceObject GetConferenceByEventGuid(string guid) {
+ return Conferences.FirstOrDefault(c => c.Talks.Any(t => t.Guid == guid));
+ }
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); });
+ public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); });
- public class ConferenceObject {
- public string Acronym;
- public bool Ongoing;
- public string LogoUri;
- public List Talks = new();
+ public class ConferenceObject {
+ public string Acronym;
+ public string LogoUri;
+ public bool Ongoing;
+ public List Talks = new();
- public ConferenceObject(string acronym, bool ongoing = false) {
- Acronym = acronym;
- Ongoing = ongoing;
- }
+ public ConferenceObject(string acronym, bool ongoing = false) {
+ Acronym = acronym;
+ Ongoing = ongoing;
}
}
}
\ No newline at end of file