epg.js 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. const Config = {
  2. repository: 'live.fanmingming.com'
  3. };
  4. async function jq_fetch(request) {
  5. let response = await fetch(request);
  6. for (let i = 0; i < 5 && (response.status === 301 || response.status === 302 || response.redirected); i++) {
  7. const location = response.headers.get('location') || response.url;
  8. response = await fetch(new Request(location, { headers: { cookie: response.headers.get('set-cookie') } }));
  9. }
  10. return response;
  11. }
  12. function makeRes(body, status = 200, headers = { 'access-control-allow-origin': '*' }) {
  13. return new Response(body, { status, headers });
  14. }
  15. function formatDateTime(time = '') {
  16. const now = new Date();
  17. const year = now.getFullYear();
  18. const month = String(now.getMonth() + 1).padStart(2, '0');
  19. const day = String(now.getDate()).padStart(2, '0');
  20. const defaultDate = `${year}-${month}-${day}`;
  21. if (time.length < 8) return { date: defaultDate, time: '' };
  22. const [inputYear, inputMonth, inputDay] = [time.substring(0, 4), time.substring(4, 6), time.substring(6, 8)];
  23. const formattedDate = `${inputYear}-${inputMonth}-${inputDay}`;
  24. const formattedTime = time.length >= 12 ? `${time.substring(8, 10)}:${time.substring(10, 12)}` : '';
  25. return { date: formattedDate, time: formattedTime };
  26. }
  27. async function diypHandle(channel, date, request) {
  28. const tag = date.replace(/-/g, '.');
  29. const res = await jq_fetch(new Request(`https://github.com/celetor/epg/releases/download/${tag}/112114.json`, request));
  30. const data = await res.json();
  31. const program_info = {
  32. date,
  33. channel_name: channel,
  34. url: `https://${Config.repository}`,
  35. epg_data: data.filter(element => element['@channel'] === channel && element['@start'].startsWith(date.replace(/-/g, '')))
  36. .map(element => ({
  37. start: formatDateTime(element['@start']).time,
  38. end: formatDateTime(element['@stop']).time,
  39. title: element['title']['#text'] || '未知节目',
  40. desc: element['desc']?.['#text'] || ''
  41. }))
  42. };
  43. if (program_info.epg_data.length === 0) {
  44. program_info.epg_data.push({ start: "00:00", end: "23:59", title: "未知节目", desc: "" });
  45. }
  46. return makeRes(JSON.stringify(program_info), 200, { 'content-type': 'application/json' });
  47. }
  48. async function fetchHandler(event) {
  49. const request = event.request;
  50. const url = new URL(request.url);
  51. if (url.pathname === '/' && !url.searchParams.has('ch')) {
  52. return Response.redirect(`https://${Config.repository}/e.xml`, 302);
  53. }
  54. const channel = (url.searchParams.get("ch") || '').toUpperCase().replace(/-/g, '');
  55. const dateParam = url.searchParams.get("date");
  56. const date = formatDateTime(dateParam ? dateParam.replace(/\D+/g, '') : '').date;
  57. if (parseInt(date.replace(/-/g, '')) >= 20240531) {
  58. return diypHandle(channel, date, request);
  59. } else {
  60. return makeRes(JSON.stringify({
  61. date,
  62. channel_name: channel,
  63. url: `https://${Config.repository}`,
  64. epg_data: [{ start: "00:00", end: "23:59", title: "未知节目", desc: "" }]
  65. }), 200, { 'content-type': 'application/json' });
  66. }
  67. }
  68. addEventListener('fetch', event => {
  69. event.respondWith(fetchHandler(event).catch(err => makeRes(`error:\n${err.stack}`, 502)));
  70. });