using System.Globalization; using System.Text.RegularExpressions; List users = new(); while (Console.In.ReadLine() is { } entry) { if (!entry.Contains("\"cdn.chaos.stream\" \"GET /hls/")) continue; if (!entry.Contains(".ts HTTP")) continue; var match = Regex.Match(entry, "^\\[(.*?)\\].*?GET \\/hls\\/(.+?)-(\\d+)\\.ts HTTP\\/\\d\\.\\d\" 200"); if (!match.Success) continue; var timestamp = match.Groups[1].Value; var streamkey = match.Groups[2].Value; var fragmentId = match.Groups[3].Value; if (users.All(p => p.Streamkey != streamkey)) users.Add(new User(streamkey)); var user = users.First(p => p.Streamkey == streamkey); if (user.Fragments.All(p => p.Id != fragmentId)) user.Fragments.Add(new Fragment(timestamp, fragmentId)); else user.Fragments.First(p => p.Id == fragmentId).Count++; UpdateScreen(); } void UpdateScreen() { var output = new List<(string streamkey, int count)>(); foreach (var user in users.OrderBy(p => p.Streamkey)) { user.Fragments.RemoveAll(p => p.Time < DateTime.Now - TimeSpan.FromMinutes(1)); if (user.Fragments.Any()) output.Add((user.Streamkey, user.Fragments.TakeLast(6).First().Count)); } var paddingOffset = users.Select(p => p.Streamkey).Aggregate("", (max, cur) => max.Length > cur.Length ? max : cur).Length; Console.Clear(); Console.WriteLine($"Viewcount as of {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); foreach (var item in output) { Console.WriteLine($"{item.streamkey.PadRight(paddingOffset)} - {item.count}"); } } internal class User { public List Fragments = new(); public string Streamkey; public User(string streamkey) { Streamkey = streamkey; } } internal class Fragment { public string Id; public DateTime Time; public int Count = 1; public Fragment(string timestamp, string id) { Time = DateTime.ParseExact(timestamp, "dd/MMM/yyyy:HH:mm:ss K", DateTimeFormatInfo.InvariantInfo); Id = id; } }