Program.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. using System.Text;
  2. using System.Text.Json;
  3. using System.Text.RegularExpressions;
  4. var builder = WebApplication.CreateBuilder(args);
  5. var app = builder.Build();
  6. string? m3u = null;
  7. string? xml = null;
  8. DateTime lastParsed = DateTime.MinValue;
  9. bool stillParsing = false;
  10. Dictionary<int, string> channels = [];
  11. if (Environment.GetCommandLineArgs().Length < 2) return;
  12. var HOST = Environment.GetCommandLineArgs()[1];
  13. async Task Parse(bool force = false) {
  14. if (stillParsing) return;
  15. if (!force && (DateTime.Now - lastParsed).TotalMinutes < 15 && m3u != null && xml != null) return;
  16. stillParsing = true;
  17. var client = new HttpClient();
  18. var jsonString = await client.GetStringAsync(@"https://ppv.to/api/streams");
  19. using var doc = JsonDocument.Parse(jsonString);
  20. var categories = doc.RootElement.GetProperty("streams").EnumerateArray();
  21. m3u = "#EXTM3U\n";
  22. xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><tv>\n";
  23. foreach (var category in categories) {
  24. var streams = category.GetProperty("streams").EnumerateArray();
  25. foreach (var stream in streams) {
  26. if (stream.GetProperty("always_live").GetInt32() == 1) continue;
  27. var iframe = stream.GetProperty("iframe").GetString();
  28. var name = stream.GetProperty("name").GetString();
  29. var id = stream.GetProperty("id").GetInt32();
  30. var tag = stream.GetProperty("tag").GetString();
  31. var poster = stream.GetProperty("poster").GetString();
  32. var cat = stream.GetProperty("category_name").GetString();
  33. var startUnix = stream.GetProperty("starts_at").GetInt64();
  34. var endUnix = stream.GetProperty("ends_at").GetInt64();
  35. // if (DateTimeOffset.FromUnixTimeSeconds(startUnix).AddHours(-4) > DateTimeOffset.UtcNow) continue;
  36. var thisM3u = "\n";
  37. thisM3u += $"#EXTINF:-1 tvg-name=\"{name}\" tvg-id=\"{id}\" tvg-chno=\"{id}\" tvg-logo=\"{poster}\" tvg-group=\"{cat}\",{tag}\n";
  38. thisM3u += $"#EXTVLCOPT:http-origin=\"https://ppv.to\"\n";
  39. thisM3u += $"#EXTVLCOPT:http-referrer=\"https://ppv.to\"\n";
  40. thisM3u += $"#EXTVLCOPT:http-user-agent=\"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:138.0) Gecko/20100101 Firefox/138.0\"\n";
  41. thisM3u += $"{HOST}/stream/{id}.m3u8\n";
  42. m3u += thisM3u;
  43. var start = DateTimeOffset.FromUnixTimeSeconds(startUnix).ToString("yyyyMMddHHmmss +0000");
  44. var end = DateTimeOffset.FromUnixTimeSeconds(endUnix).ToString("yyyyMMddHHmmss +0000");
  45. xml += $"<channel id=\"{id}\"><display-name>{tag}</display-name><icon src=\"\"/></channel>\n";
  46. xml += $"<programme start=\"{start}\" stop=\"{end}\" channel=\"{id}\"><title>{name}</title><desc>{cat}</desc></programme>\n";
  47. channels[id] = iframe!;
  48. }
  49. }
  50. xml += "</tv>";
  51. stillParsing = false;
  52. }
  53. app.MapGet("stream/{idFile}", async (string idFile) => {
  54. var id = int.Parse(idFile.Split('.')[0]);
  55. var client = new HttpClient();
  56. var embed = await client.GetStringAsync(channels[id]);
  57. var matches = Regex.Matches(embed, "atob\\(\"([^\"]+)\"\\);");
  58. foreach (Match match in matches) {
  59. var url = Encoding.ASCII.GetString(Convert.FromBase64String(match.Groups[1].Value));
  60. // url = url.Replace("index.m3u8", "tracks-v1a1/mono.ts.m3u8");
  61. if (url.Contains(".m3u8")) {
  62. return Results.Redirect(url, false, true);
  63. }
  64. }
  65. return Results.NotFound();
  66. });
  67. app.MapGet("/m3u", async (bool force = false) => {
  68. await Parse();
  69. return Results.Text(m3u, "application/vnd.apple.mpegurl");
  70. });
  71. app.MapGet("/xml", async (bool force = false) => {
  72. await Parse();
  73. return Results.Text(xml, "application/xml");
  74. });
  75. app.Run();