mirror of
https://github.com/iptv-org/epg.git
synced 2025-05-09 08:30:06 -04:00
Compare commits
1306 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
522bf757f9 | ||
![]() |
63fdc88d01 | ||
![]() |
539000fe61 | ||
![]() |
b572572616 | ||
![]() |
e505444f00 | ||
![]() |
db56a4d6c0 | ||
![]() |
113395c6b5 | ||
![]() |
87c14f0203 | ||
![]() |
b4c4d51b07 | ||
![]() |
11cab21cfc | ||
![]() |
22dc9a06d1 | ||
![]() |
8e363d0e83 | ||
![]() |
d681fcb3d5 | ||
![]() |
e54dfb4042 | ||
![]() |
9f93a30988 | ||
![]() |
7a193e37e1 | ||
![]() |
48457d0d10 | ||
![]() |
af86d7204f | ||
![]() |
7e1fbcbe15 | ||
![]() |
f91f53a0de | ||
![]() |
af465601ab | ||
![]() |
704c04f261 | ||
![]() |
f26e075e96 | ||
![]() |
697c6bf0f6 | ||
![]() |
925f4c4974 | ||
![]() |
cc4dfce239 | ||
![]() |
46c599dc85 | ||
![]() |
4df25c92bc | ||
![]() |
0728f6cca2 | ||
![]() |
01dff65bf9 | ||
![]() |
ccfe7dbc5b | ||
![]() |
f4b0156fad | ||
![]() |
5e0a1bd8b7 | ||
![]() |
a4d1c48bbd | ||
![]() |
3e36c64ef9 | ||
![]() |
36a900a90f | ||
![]() |
fbc0d92a1e | ||
![]() |
5dd131e2d3 | ||
![]() |
37664b49b9 | ||
![]() |
510d89c8c8 | ||
![]() |
0e4521a504 | ||
![]() |
6755affc2f | ||
![]() |
b8dd5e7c3a | ||
![]() |
fd31b9f8e9 | ||
![]() |
96b3aa421c | ||
![]() |
482974e7b9 | ||
![]() |
6a4404b663 | ||
![]() |
c79491f48e | ||
![]() |
281a581ed8 | ||
![]() |
ad2dd69287 | ||
![]() |
4bdcdf0962 | ||
![]() |
c4cea0e73c | ||
![]() |
de6d577a66 | ||
![]() |
1dd76b1f58 | ||
![]() |
b14ff83f13 | ||
![]() |
c3ed9f4502 | ||
![]() |
66304d7432 | ||
![]() |
92159813a6 | ||
![]() |
59703efaab | ||
![]() |
a98a457011 | ||
![]() |
bdaff97c36 | ||
![]() |
c12254f80d | ||
![]() |
9090f55229 | ||
![]() |
13b915796a | ||
![]() |
6e35d4364d | ||
![]() |
c032886eb7 | ||
![]() |
f52927c0ec | ||
![]() |
f6814444e6 | ||
![]() |
ff60520443 | ||
![]() |
31089a8035 | ||
![]() |
dc27551a5f | ||
![]() |
f3c4918d44 | ||
![]() |
f2e6041372 | ||
![]() |
3fd6e47d4f | ||
![]() |
642070d16d | ||
![]() |
95b39b8348 | ||
![]() |
bd5cdcf892 | ||
![]() |
3cada89a0e | ||
![]() |
9accacd41c | ||
![]() |
30dc0517be | ||
![]() |
138842009b | ||
![]() |
0b5dd5f78e | ||
![]() |
45a1478e2e | ||
![]() |
0b5ef21877 | ||
![]() |
348e8c1e9e | ||
![]() |
637f7a8d32 | ||
![]() |
f40f058d9a | ||
![]() |
6066df8a91 | ||
![]() |
1e8d10eac8 | ||
![]() |
23de62777f | ||
![]() |
240151015a | ||
![]() |
9d94560c5f | ||
![]() |
d8e4d13ebb | ||
![]() |
c7b21d029f | ||
![]() |
6ff3a943ec | ||
![]() |
4102d60406 | ||
![]() |
71621070ed | ||
![]() |
cf82b4089e | ||
![]() |
d410d0e126 | ||
![]() |
917c622724 | ||
![]() |
46c1799ecd | ||
![]() |
8e6dc5c923 | ||
![]() |
40c9af82d6 | ||
![]() |
0044f19615 | ||
![]() |
3e406a413c | ||
![]() |
e2504ad546 | ||
![]() |
f6265954ff | ||
![]() |
15c51c1d7d | ||
![]() |
145ed8c831 | ||
![]() |
5095b20e55 | ||
![]() |
f3df393df6 | ||
![]() |
9fec63b3b1 | ||
![]() |
53f2bad13e | ||
![]() |
363e0077a3 | ||
![]() |
1500ed5a21 | ||
![]() |
b33260b20f | ||
![]() |
0bb74b4c1b | ||
![]() |
5f48b22a28 | ||
![]() |
2235f0c2cd | ||
![]() |
f9534bd23a | ||
![]() |
93da6d0878 | ||
![]() |
d7e4a3fd51 | ||
![]() |
c021aa3e01 | ||
![]() |
2721fe1ba0 | ||
![]() |
09e96c5d10 | ||
![]() |
893f741473 | ||
![]() |
f2759f8b39 | ||
![]() |
667c3944c5 | ||
![]() |
fab5f9ad08 | ||
![]() |
9345e39533 | ||
![]() |
ba9fd0f099 | ||
![]() |
3100db9226 | ||
![]() |
d877f4405b | ||
![]() |
d75ce33915 | ||
![]() |
cd7182ddb3 | ||
![]() |
eec8f4ea47 | ||
![]() |
39c4c5143e | ||
![]() |
e04953580b | ||
![]() |
40977023d6 | ||
![]() |
f856934f90 | ||
![]() |
a5a305e654 | ||
![]() |
0fe8456b16 | ||
![]() |
655f2b1a71 | ||
![]() |
210f51bfd6 | ||
![]() |
3540d581fc | ||
![]() |
6fd72128ef | ||
![]() |
1c9a2cc088 | ||
![]() |
3339ea9711 | ||
![]() |
e75dab9553 | ||
![]() |
bfb5d59bb8 | ||
![]() |
f5623a4485 | ||
![]() |
e80ca4502a | ||
![]() |
0b9276ca8a | ||
![]() |
6cbe64f2dd | ||
![]() |
9aeb0b75e4 | ||
![]() |
5ed1375c25 | ||
![]() |
42631558fc | ||
![]() |
d97cd5ea7f | ||
![]() |
5601636ff2 | ||
![]() |
0afb84d7d2 | ||
![]() |
9f61346bdb | ||
![]() |
06b01b3a2a | ||
![]() |
38030a3745 | ||
![]() |
1cecb1ec04 | ||
![]() |
654c89f20b | ||
![]() |
9996055b15 | ||
![]() |
ddd7f1aa6e | ||
![]() |
041e227e56 | ||
![]() |
50d143bedd | ||
![]() |
063cf6bcd3 | ||
![]() |
b0feab33ec | ||
![]() |
378985f4cd | ||
![]() |
acc5f21587 | ||
![]() |
b901e76950 | ||
![]() |
361641c861 | ||
![]() |
e952ba2585 | ||
![]() |
e0d059de5c | ||
![]() |
65ea39cc9e | ||
![]() |
7f6849869f | ||
![]() |
6ee49862f6 | ||
![]() |
fbaae670d9 | ||
![]() |
e8a0856be2 | ||
![]() |
1a6f5954e2 | ||
![]() |
6b45cd9bd6 | ||
![]() |
8664602da9 | ||
![]() |
b6657aae92 | ||
![]() |
4d964e03e4 | ||
![]() |
a39cb77cc0 | ||
![]() |
f1f387c872 | ||
![]() |
a2748d7383 | ||
![]() |
b391288442 | ||
![]() |
abe6322c10 | ||
![]() |
7705f1bc40 | ||
![]() |
ce3d396dad | ||
![]() |
150725bdc5 | ||
![]() |
32af543a87 | ||
![]() |
8064f6fe0a | ||
![]() |
dc3b4606af | ||
![]() |
352038fb56 | ||
![]() |
637edef019 | ||
![]() |
466d8b2147 | ||
![]() |
b2588e80df | ||
![]() |
3719cd725d | ||
![]() |
b042e14b9a | ||
![]() |
2c55431482 | ||
![]() |
2b7be2e588 | ||
![]() |
c697a9ff68 | ||
![]() |
f4fec9896e | ||
![]() |
2932771e91 | ||
![]() |
a7946884f5 | ||
![]() |
b0eb51edd8 | ||
![]() |
dd195256de | ||
![]() |
6ed275e228 | ||
![]() |
5026600be6 | ||
![]() |
a9f0012c23 | ||
![]() |
ac67940233 | ||
![]() |
edf05c6f49 | ||
![]() |
fb5119bacd | ||
![]() |
d6786495e2 | ||
![]() |
41dd41623d | ||
![]() |
f8e7142f54 | ||
![]() |
f982aae18f | ||
![]() |
bcc7189d74 | ||
![]() |
f7e1c1558c | ||
![]() |
a58cea4aa7 | ||
![]() |
bd96957975 | ||
![]() |
411efb9a8d | ||
![]() |
7b008ccf71 | ||
![]() |
73cebeac29 | ||
![]() |
abd6d0531d | ||
![]() |
e275e04c67 | ||
![]() |
34dcd59903 | ||
![]() |
51827d1bff | ||
![]() |
12e22efeff | ||
![]() |
103a6e7227 | ||
![]() |
b8285b1970 | ||
![]() |
c7fa5cd062 | ||
![]() |
51cb17c2c4 | ||
![]() |
0baabed2ed | ||
![]() |
f55f2bc807 | ||
![]() |
96faa53325 | ||
![]() |
765a638af1 | ||
![]() |
4cb6f66070 | ||
![]() |
a592234794 | ||
![]() |
1affea63ca | ||
![]() |
b7d58195f1 | ||
![]() |
8427dd9087 | ||
![]() |
7f7e4c0825 | ||
![]() |
ab7f1edbc6 | ||
![]() |
a3a7dfb8e0 | ||
![]() |
f01856c130 | ||
![]() |
2c6559b2c9 | ||
![]() |
e57dfaff41 | ||
![]() |
3e4deda7bf | ||
![]() |
09a0621b03 | ||
![]() |
106ae083d2 | ||
![]() |
380bf5f8d9 | ||
![]() |
f4e18a3dc1 | ||
![]() |
6d26b12b6c | ||
![]() |
1f4535c77a | ||
![]() |
765b43dcb2 | ||
![]() |
a45a346ec8 | ||
![]() |
33428dd37c | ||
![]() |
cffd2a635f | ||
![]() |
378d138694 | ||
![]() |
42ce11a6ba | ||
![]() |
c0d4c631f8 | ||
![]() |
cb10f7a162 | ||
![]() |
5cc9896314 | ||
![]() |
a274b63c17 | ||
![]() |
a57ac947f3 | ||
![]() |
f4c7371a34 | ||
![]() |
b9fe49f763 | ||
![]() |
7682eb28f1 | ||
![]() |
dbda25d4a8 | ||
![]() |
71ab07fbea | ||
![]() |
833ae634c9 | ||
![]() |
0da74de608 | ||
![]() |
7445722a22 | ||
![]() |
40f0b0460e | ||
![]() |
2202affe80 | ||
![]() |
4c58425893 | ||
![]() |
c726d85fc9 | ||
![]() |
5e80d754ac | ||
![]() |
25cc9aa0b3 | ||
![]() |
e2ea1f294d | ||
![]() |
9c74146cb7 | ||
![]() |
b4d776e152 | ||
![]() |
e6c6394121 | ||
![]() |
50dddecfe8 | ||
![]() |
504398f079 | ||
![]() |
78577e8fc0 | ||
![]() |
01b99fe98f | ||
![]() |
71aca65d86 | ||
![]() |
eef2bf2815 | ||
![]() |
e17ce1c403 | ||
![]() |
5652ed22c6 | ||
![]() |
7b9fcf3851 | ||
![]() |
8517679998 | ||
![]() |
d15b21bfd3 | ||
![]() |
b8c50654f6 | ||
![]() |
e02e46562a | ||
![]() |
3f22ac12f5 | ||
![]() |
a7b80f88a4 | ||
![]() |
f624029d05 | ||
![]() |
4ff6a1ab34 | ||
![]() |
d027e0072f | ||
![]() |
db94809828 | ||
![]() |
9ec69b31b1 | ||
![]() |
966cd16725 | ||
![]() |
c725adea6e | ||
![]() |
98bccc0faa | ||
![]() |
bc4b7fcfd5 | ||
![]() |
384f64e37b | ||
![]() |
de2d160012 | ||
![]() |
7f39511ed0 | ||
![]() |
195c6c5ebb | ||
![]() |
bd3bfa460d | ||
![]() |
44bb8a5788 | ||
![]() |
7e07f40809 | ||
![]() |
81f2665235 | ||
![]() |
002a3ec5c6 | ||
![]() |
700de1b737 | ||
![]() |
bb31e873bf | ||
![]() |
130b130946 | ||
![]() |
b69d61af5e | ||
![]() |
39bca4f7cc | ||
![]() |
6b3dea313e | ||
![]() |
5082657ad3 | ||
![]() |
868a6f89a3 | ||
![]() |
6010fc4978 | ||
![]() |
6b0af46203 | ||
![]() |
06e4382002 | ||
![]() |
a4bd81606b | ||
![]() |
e8cbb980ba | ||
![]() |
4fc65bf540 | ||
![]() |
6f1305d029 | ||
![]() |
83ac2d9908 | ||
![]() |
6f25c6ea3a | ||
![]() |
68144804d9 | ||
![]() |
2e8a3e4fc1 | ||
![]() |
d35d897f77 | ||
![]() |
e571bcb722 | ||
![]() |
524846fefb | ||
![]() |
f1eddf579e | ||
![]() |
9b0badadf6 | ||
![]() |
4dd4f0c488 | ||
![]() |
8a572ae021 | ||
![]() |
a99179aec7 | ||
![]() |
de1dbc68d0 | ||
![]() |
6a5df080c4 | ||
![]() |
9b862fa27b | ||
![]() |
06598014d8 | ||
![]() |
3fc55f3499 | ||
![]() |
71d0a6f312 | ||
![]() |
276210609a | ||
![]() |
89471b618d | ||
![]() |
411269587f | ||
![]() |
ad45f29cb0 | ||
![]() |
5c1488d600 | ||
![]() |
e2a21cbc46 | ||
![]() |
7b2cfba7f5 | ||
![]() |
4223fa26d0 | ||
![]() |
7d9d9b7008 | ||
![]() |
69597e5a11 | ||
![]() |
52d075d39c | ||
![]() |
73fb5049c9 | ||
![]() |
3f76f28da4 | ||
![]() |
51a5f39832 | ||
![]() |
2ff7c63ff9 | ||
![]() |
e2ad8c75db | ||
![]() |
ec1ab09a3f | ||
![]() |
5a984241f0 | ||
![]() |
37998865b3 | ||
![]() |
4cfed04fa3 | ||
![]() |
5c9cdfd38a | ||
![]() |
7f932a8033 | ||
![]() |
26ce4346f5 | ||
![]() |
ca9c3dcb61 | ||
![]() |
e1bc533e8b | ||
![]() |
4d0df65510 | ||
![]() |
96704b45de | ||
![]() |
62640b3371 | ||
![]() |
791179daf6 | ||
![]() |
cb863682b1 | ||
![]() |
4f8df0076b | ||
![]() |
ed5191caf4 | ||
![]() |
fe3479eb3a | ||
![]() |
c25d2a7440 | ||
![]() |
a5436a5928 | ||
![]() |
a37d616457 | ||
![]() |
b02ccd55f0 | ||
![]() |
fc204e8edb | ||
![]() |
cfa571f62d | ||
![]() |
e8945874ae | ||
![]() |
19c9c61fd4 | ||
![]() |
b884b2942c | ||
![]() |
cf2bd4ad0c | ||
![]() |
c064d2ac69 | ||
![]() |
7766b497e8 | ||
![]() |
dbb744cc89 | ||
![]() |
4d0c5c109a | ||
![]() |
2674459b35 | ||
![]() |
cc2161fb54 | ||
![]() |
e4f4199e8f | ||
![]() |
4445d13452 | ||
![]() |
0e33226192 | ||
![]() |
74ce38b66c | ||
![]() |
03ee512427 | ||
![]() |
45a06e961c | ||
![]() |
da2cf51202 | ||
![]() |
92d4bc5b3e | ||
![]() |
20f5d00657 | ||
![]() |
f9a474f7fb | ||
![]() |
692c8c1031 | ||
![]() |
fe2fd07f96 | ||
![]() |
d33410261a | ||
![]() |
8f00e104b7 | ||
![]() |
5740d94962 | ||
![]() |
a0a48e24ec | ||
![]() |
4eb4096692 | ||
![]() |
426525e3b2 | ||
![]() |
3fbbc0e6db | ||
![]() |
57dce730dd | ||
![]() |
dfd87070a5 | ||
![]() |
6930ddd934 | ||
![]() |
d04cc1e26a | ||
![]() |
d819507765 | ||
![]() |
3d4ced9e88 | ||
![]() |
a52c9b3c3a | ||
![]() |
a3ab9d6a81 | ||
![]() |
edfedd72a5 | ||
![]() |
7cd9ce61b4 | ||
![]() |
72c360bc5c | ||
![]() |
cfa3c11f98 | ||
![]() |
ffb88e9b8e | ||
![]() |
7ca923b753 | ||
![]() |
d9b3fe8d07 | ||
![]() |
9a4fe43729 | ||
![]() |
2e28ca2539 | ||
![]() |
e19b4c6318 | ||
![]() |
a49655aa53 | ||
![]() |
eb1d70c82b | ||
![]() |
2f2485d9c0 | ||
![]() |
65147a45e9 | ||
![]() |
4b744355f9 | ||
![]() |
96b6a21150 | ||
![]() |
b8c515bfcb | ||
![]() |
f04a9bce17 | ||
![]() |
c338fdb0f4 | ||
![]() |
f518547f8d | ||
![]() |
e84967722a | ||
![]() |
50bcaaa847 | ||
![]() |
655c930fec | ||
![]() |
50c418e8ad | ||
![]() |
4e7d45f692 | ||
![]() |
630f031239 | ||
![]() |
f5a5beacc6 | ||
![]() |
3a2757b79c | ||
![]() |
9836992122 | ||
![]() |
706cf7ec72 | ||
![]() |
1c21203769 | ||
![]() |
7b02fffc21 | ||
![]() |
f989ec2e57 | ||
![]() |
196434f5f6 | ||
![]() |
1d1adcf1d2 | ||
![]() |
0a69951b59 | ||
![]() |
01acf6d6d4 | ||
![]() |
a55681e99b | ||
![]() |
7d0511207b | ||
![]() |
a2d0cb3a8d | ||
![]() |
35f55e4df5 | ||
![]() |
65f7b58065 | ||
![]() |
e27ac9ee19 | ||
![]() |
b6b2521498 | ||
![]() |
0d45f08352 | ||
![]() |
80828e5446 | ||
![]() |
d81b994161 | ||
![]() |
7f31017756 | ||
![]() |
ee8960d2c4 | ||
![]() |
eb20530812 | ||
![]() |
c8085e6b3f | ||
![]() |
7445c4c27a | ||
![]() |
bbd20848b2 | ||
![]() |
8082cf9544 | ||
![]() |
5b9f7ffa6a | ||
![]() |
b05f48a5a0 | ||
![]() |
50ddd0c20c | ||
![]() |
4b129ef72b | ||
![]() |
d2d174cac2 | ||
![]() |
5958c77c65 | ||
![]() |
72c33722a5 | ||
![]() |
12bd54bf0b | ||
![]() |
8619ff9445 | ||
![]() |
ecda45d9f8 | ||
![]() |
add8250c24 | ||
![]() |
4c06176e8e | ||
![]() |
3aaea0abde | ||
![]() |
422b9ad6a9 | ||
![]() |
0e4e7d8281 | ||
![]() |
e07202015b | ||
![]() |
9fc2f93793 | ||
![]() |
1a4b3c9939 | ||
![]() |
e44b1c0c45 | ||
![]() |
8362e6035e | ||
![]() |
9f4a3c80d2 | ||
![]() |
52965a6090 | ||
![]() |
b8ba5dfe0d | ||
![]() |
103b201554 | ||
![]() |
cffbd24b0a | ||
![]() |
1dd640ccf6 | ||
![]() |
b98a31c99e | ||
![]() |
0d7cc47042 | ||
![]() |
d1f96419ea | ||
![]() |
2434bd2dc9 | ||
![]() |
506c7fd18e | ||
![]() |
b85abb2885 | ||
![]() |
2915e93408 | ||
![]() |
2c5d68812e | ||
![]() |
29ab6b0d64 | ||
![]() |
50b14fedb6 | ||
![]() |
8efe4177cf | ||
![]() |
0e45c85070 | ||
![]() |
56ce54c406 | ||
![]() |
3d8124b983 | ||
![]() |
7891d9fa3b | ||
![]() |
7dc51b5147 | ||
![]() |
1ae99d5470 | ||
![]() |
3789b88d0e | ||
![]() |
bc311ae5b9 | ||
![]() |
e842ada752 | ||
![]() |
f16550ff57 | ||
![]() |
8202218682 | ||
![]() |
860186316d | ||
![]() |
d5b53157ed | ||
![]() |
63d5f4877f | ||
![]() |
a66a06b4ea | ||
![]() |
2d9b29b94c | ||
![]() |
2cf1dc6219 | ||
![]() |
8d1348cc46 | ||
![]() |
10475ab929 | ||
![]() |
d1e5ca200c | ||
![]() |
8ac56b050d | ||
![]() |
679c042197 | ||
![]() |
92d0afcb79 | ||
![]() |
415aa3d476 | ||
![]() |
885a5593d3 | ||
![]() |
c56b0a1ed8 | ||
![]() |
2c51e8fadb | ||
![]() |
601f51570b | ||
![]() |
78d31e2352 | ||
![]() |
dbdba905cc | ||
![]() |
55942f1cd4 | ||
![]() |
f7346b6bc5 | ||
![]() |
409fa926e8 | ||
![]() |
febfced926 | ||
![]() |
43dadde4d6 | ||
![]() |
c9ea7ceab1 | ||
![]() |
69a06785b7 | ||
![]() |
ef1714fca8 | ||
![]() |
df7e1f82f8 | ||
![]() |
6013889b27 | ||
![]() |
6cc31e82e9 | ||
![]() |
edfbff31d2 | ||
![]() |
f2311ca484 | ||
![]() |
cb1921d008 | ||
![]() |
54ec0074a4 | ||
![]() |
318ab3cc38 | ||
![]() |
133792f498 | ||
![]() |
69159b2cf1 | ||
![]() |
8e19193621 | ||
![]() |
0db9e84b8e | ||
![]() |
f987c2e4a7 | ||
![]() |
9f573e48d8 | ||
![]() |
7ab9abdc86 | ||
![]() |
a1f6152608 | ||
![]() |
052e8ec3f0 | ||
![]() |
36cd2a5868 | ||
![]() |
201baf16c6 | ||
![]() |
6185d6d484 | ||
![]() |
db98255128 | ||
![]() |
e2d86b59d8 | ||
![]() |
84e46fdb0d | ||
![]() |
f863e3eb9a | ||
![]() |
f407a12832 | ||
![]() |
40a96b927e | ||
![]() |
65331dff1c | ||
![]() |
e3573b6316 | ||
![]() |
ebe672631c | ||
![]() |
f76c933d58 | ||
![]() |
0b5c90c856 | ||
![]() |
32ceca725d | ||
![]() |
7b0b9df858 | ||
![]() |
4b21347c6f | ||
![]() |
338504bd67 | ||
![]() |
4cd79c2d57 | ||
![]() |
91a6d207b2 | ||
![]() |
1b5ed2b357 | ||
![]() |
a7670f0cc8 | ||
![]() |
9b887be0eb | ||
![]() |
fa7f1eb2ec | ||
![]() |
9599038a10 | ||
![]() |
ceb4932e6e | ||
![]() |
c8bc5109fc | ||
![]() |
a650a4a23c | ||
![]() |
f8d0f435ac | ||
![]() |
8803045cd8 | ||
![]() |
46f8f41d84 | ||
![]() |
48bae7af1f | ||
![]() |
773eb2a335 | ||
![]() |
a6b8c49b91 | ||
![]() |
a7a7dcd018 | ||
![]() |
82559cedf2 | ||
![]() |
6111cb8f04 | ||
![]() |
9087b4d104 | ||
![]() |
f83e7d33d7 | ||
![]() |
f48a302fa8 | ||
![]() |
d7d5b110d3 | ||
![]() |
4dcf79b8b9 | ||
![]() |
1b3a4d3bd4 | ||
![]() |
cd23e28e7e | ||
![]() |
5521c4e2e1 | ||
![]() |
8989cb8d38 | ||
![]() |
ba877ece1e | ||
![]() |
8c73df923b | ||
![]() |
0ef69335a2 | ||
![]() |
156adee979 | ||
![]() |
6138c472ac | ||
![]() |
b0711e5233 | ||
![]() |
368500ab51 | ||
![]() |
2d37b52229 | ||
![]() |
89ad9efd77 | ||
![]() |
5fae8484ce | ||
![]() |
9d185dcf38 | ||
![]() |
11f3ccd5a5 | ||
![]() |
991d399fc3 | ||
![]() |
0563d75e5d | ||
![]() |
76df1541d8 | ||
![]() |
ba08df2daa | ||
![]() |
0f8e2ee41f | ||
![]() |
1d289d2542 | ||
![]() |
ea59a806f5 | ||
![]() |
8656e3fe6a | ||
![]() |
3e651ae356 | ||
![]() |
c79f360184 | ||
![]() |
f0afea8c5e | ||
![]() |
527e17003c | ||
![]() |
60a1959ac4 | ||
![]() |
6c79a2739d | ||
![]() |
1e285fadb4 | ||
![]() |
f7d038a5ba | ||
![]() |
a9a359d69b | ||
![]() |
5167a43fb7 | ||
![]() |
b8e6d12d6a | ||
![]() |
fba07b17e7 | ||
![]() |
f7c09afb84 | ||
![]() |
f5f37a7441 | ||
![]() |
55a6a2fecc | ||
![]() |
eca069cd04 | ||
![]() |
4eff318722 | ||
![]() |
8be65cc04f | ||
![]() |
9a565f16f4 | ||
![]() |
c4189460cb | ||
![]() |
2e64b51b79 | ||
![]() |
bc4b5bd187 | ||
![]() |
8cdff31159 | ||
![]() |
5218372e20 | ||
![]() |
e68a5b5f7f | ||
![]() |
dd3844f6dd | ||
![]() |
3e6fb2b1d3 | ||
![]() |
6285025a53 | ||
![]() |
89bc036b01 | ||
![]() |
71d777e235 | ||
![]() |
767aa12ef8 | ||
![]() |
53d81b8f4b | ||
![]() |
6def709352 | ||
![]() |
d33aae5d84 | ||
![]() |
78623a2930 | ||
![]() |
f32e7ac7e7 | ||
![]() |
0473274b90 | ||
![]() |
3118077673 | ||
![]() |
3dbece7ff0 | ||
![]() |
3c19dd1725 | ||
![]() |
cd74b66445 | ||
![]() |
af1dcdd45e | ||
![]() |
c6d56eefed | ||
![]() |
7c3d32191d | ||
![]() |
aa9f0b7b86 | ||
![]() |
4d539fb709 | ||
![]() |
2ec54202d0 | ||
![]() |
0e921f0d7a | ||
![]() |
27c92d6dfb | ||
![]() |
f093251308 | ||
![]() |
24d64575cb | ||
![]() |
4087766349 | ||
![]() |
0b3f92cb50 | ||
![]() |
73664749f3 | ||
![]() |
67265aa79b | ||
![]() |
297b68d0e3 | ||
![]() |
9970a63d50 | ||
![]() |
2535942b5c | ||
![]() |
b8de28e035 | ||
![]() |
cfa34bc99c | ||
![]() |
7cce6d737e | ||
![]() |
aa1356e10b | ||
![]() |
5176fb349d | ||
![]() |
edfb7da0f5 | ||
![]() |
0aea37d39b | ||
![]() |
cb333f5cae | ||
![]() |
84add7d84c | ||
![]() |
0255dfb19d | ||
![]() |
979db51d7e | ||
![]() |
e5e1988824 | ||
![]() |
68ba143c67 | ||
![]() |
8e39af2a4d | ||
![]() |
8a5ec2cfac | ||
![]() |
c436e7589e | ||
![]() |
d7e28ae732 | ||
![]() |
3c858ecca9 | ||
![]() |
4c44d449db | ||
![]() |
e1ffd61618 | ||
![]() |
cfb53d754f | ||
![]() |
bb9248df1d | ||
![]() |
0b8782a9eb | ||
![]() |
7171e11d21 | ||
![]() |
ded5e881bb | ||
![]() |
95e9e670ff | ||
![]() |
e15d812750 | ||
![]() |
e7bbc7db23 | ||
![]() |
25093cb927 | ||
![]() |
0f92463d05 | ||
![]() |
c8055f10d6 | ||
![]() |
fd136c856d | ||
![]() |
d3b96723e0 | ||
![]() |
8d1e94ad04 | ||
![]() |
67bd130763 | ||
![]() |
2db99a538e | ||
![]() |
6e2a814487 | ||
![]() |
ae7b32b079 | ||
![]() |
e8f89b216c | ||
![]() |
8b0952b915 | ||
![]() |
4aad8125f5 | ||
![]() |
82f6fc114b | ||
![]() |
904f72254e | ||
![]() |
cf52b0c3b0 | ||
![]() |
d156add197 | ||
![]() |
b44dc80a77 | ||
![]() |
adda13bfd6 | ||
![]() |
1e126da5d5 | ||
![]() |
89e0fe5306 | ||
![]() |
f4d5719e7e | ||
![]() |
711d85309a | ||
![]() |
c5ee8a7597 | ||
![]() |
01419410eb | ||
![]() |
69057f29f8 | ||
![]() |
35abd1f9e8 | ||
![]() |
1c29228baa | ||
![]() |
0f4fd3472f | ||
![]() |
dfdac39bb4 | ||
![]() |
f07514b3e4 | ||
![]() |
c9bfb3ddfa | ||
![]() |
a3caf2393d | ||
![]() |
d64c934831 | ||
![]() |
7e303db1f5 | ||
![]() |
fef6c50bf1 | ||
![]() |
786e95a388 | ||
![]() |
532386af91 | ||
![]() |
e2bf048d54 | ||
![]() |
382d4a310e | ||
![]() |
a89e26855b | ||
![]() |
3525735885 | ||
![]() |
bb36840b72 | ||
![]() |
cbeac9dd35 | ||
![]() |
7fee216cb1 | ||
![]() |
85442212dc | ||
![]() |
12740941d5 | ||
![]() |
0baf1be2c0 | ||
![]() |
9a9d21dfe7 | ||
![]() |
a738c3b211 | ||
![]() |
5c90340165 | ||
![]() |
49a3902fb1 | ||
![]() |
9bbc6b8706 | ||
![]() |
ca1a916b85 | ||
![]() |
9ef413eef4 | ||
![]() |
06827b20ce | ||
![]() |
2c22600a27 | ||
![]() |
76a902ae9c | ||
![]() |
aeaef329e7 | ||
![]() |
dd29cb338c | ||
![]() |
54f1b03c33 | ||
![]() |
5f2219b672 | ||
![]() |
f11ed412ee | ||
![]() |
67509d97b1 | ||
![]() |
5c3df01cef | ||
![]() |
d134f2d044 | ||
![]() |
222e65b3ea | ||
![]() |
2f670a5467 | ||
![]() |
b0c8dffa1a | ||
![]() |
66be6c5a81 | ||
![]() |
5df982bb7c | ||
![]() |
d6d20b6413 | ||
![]() |
784216a82d | ||
![]() |
4788ff1e31 | ||
![]() |
9af374c72b | ||
![]() |
b99765c743 | ||
![]() |
c9f730bac4 | ||
![]() |
65c1447785 | ||
![]() |
7840829424 | ||
![]() |
3db2e6a950 | ||
![]() |
ad80c82882 | ||
![]() |
a37973f10e | ||
![]() |
a5b8fa12ae | ||
![]() |
1b62393008 | ||
![]() |
7322f9eb61 | ||
![]() |
1aeaf49dc2 | ||
![]() |
5b280dfbc8 | ||
![]() |
60f3604ea5 | ||
![]() |
7783d752cc | ||
![]() |
6fb40b5c07 | ||
![]() |
0d32c3dedd | ||
![]() |
d7b281304b | ||
![]() |
5ffe285c1e | ||
![]() |
8a8262eacb | ||
![]() |
15790a24ee | ||
![]() |
368304fb2e | ||
![]() |
7e7efaa487 | ||
![]() |
345be3a71d | ||
![]() |
e1a501b0bd | ||
![]() |
b4dafb2dc1 | ||
![]() |
312b654937 | ||
![]() |
af1149548e | ||
![]() |
8dce850c60 | ||
![]() |
c3c70ae627 | ||
![]() |
1d150e0ab7 | ||
![]() |
7be265e4dd | ||
![]() |
2c35704fb0 | ||
![]() |
d9a70f2a1f | ||
![]() |
0c99219400 | ||
![]() |
31463dcf39 | ||
![]() |
bfb9a4413b | ||
![]() |
a8e52738f6 | ||
![]() |
71ad567b75 | ||
![]() |
1d24fdca1d | ||
![]() |
695e3ffb09 | ||
![]() |
633137b7f9 | ||
![]() |
a0d66974b2 | ||
![]() |
c10b464f29 | ||
![]() |
b282583262 | ||
![]() |
d9bce3edc3 | ||
![]() |
ccde465dcf | ||
![]() |
651920498b | ||
![]() |
6f6005e413 | ||
![]() |
6470fb4d88 | ||
![]() |
8ba5c44964 | ||
![]() |
06fcce0ef0 | ||
![]() |
2ef74b7743 | ||
![]() |
c4952f1eaa | ||
![]() |
16334d520c | ||
![]() |
32c2fbdafc | ||
![]() |
c1add31472 | ||
![]() |
d59f68b9f1 | ||
![]() |
ed3ebb2021 | ||
![]() |
d9c8e20a24 | ||
![]() |
81c7b29a05 | ||
![]() |
eff2f6ba15 | ||
![]() |
f469665e69 | ||
![]() |
62b6bb134e | ||
![]() |
24a90462a5 | ||
![]() |
141fc210c4 | ||
![]() |
38579f14cb | ||
![]() |
5d874ea163 | ||
![]() |
64bc70dbb2 | ||
![]() |
8b1a77bd40 | ||
![]() |
5e420b23e1 | ||
![]() |
ae8dca6c55 | ||
![]() |
f2b46645ce | ||
![]() |
1da991cb79 | ||
![]() |
1d142e304e | ||
![]() |
7de965ec82 | ||
![]() |
2711e8134a | ||
![]() |
baa6e36c43 | ||
![]() |
22a061a384 | ||
![]() |
5b4240288d | ||
![]() |
634188f008 | ||
![]() |
14c4ca3916 | ||
![]() |
6bca27bf0b | ||
![]() |
d7eeec1901 | ||
![]() |
3aec73d2c9 | ||
![]() |
f13a5ba0f2 | ||
![]() |
19952d37e5 | ||
![]() |
2ef311b8a2 | ||
![]() |
2bba1fadda | ||
![]() |
f51439d6fb | ||
![]() |
9b9131526e | ||
![]() |
1db77a4529 | ||
![]() |
56da008b2a | ||
![]() |
5e40b51957 | ||
![]() |
8285ea04f2 | ||
![]() |
19130007fd | ||
![]() |
925ef03d36 | ||
![]() |
87b52610a4 | ||
![]() |
770b9c856d | ||
![]() |
ff84be91f8 | ||
![]() |
03bcf1fd70 | ||
![]() |
4975f04127 | ||
![]() |
88a4afd4bd | ||
![]() |
a7bd3204be | ||
![]() |
eb10f8207b | ||
![]() |
bb956bcf07 | ||
![]() |
73a80fbb3b | ||
![]() |
c108aa586e | ||
![]() |
08a6e61f3f | ||
![]() |
d70147cb72 | ||
![]() |
37e27c8cf8 | ||
![]() |
838620b698 | ||
![]() |
a5229d3af0 | ||
![]() |
916b5f5234 | ||
![]() |
ceebaed60f | ||
![]() |
f00d53cb7b | ||
![]() |
f7eefb173e | ||
![]() |
fd91a9c532 | ||
![]() |
f6ff5076ae | ||
![]() |
259af9879c | ||
![]() |
470605534a | ||
![]() |
b0cf90be1f | ||
![]() |
f6c67b239b | ||
![]() |
f501229b65 | ||
![]() |
d0acdfe25a | ||
![]() |
53e05d1bce | ||
![]() |
e00efc77b9 | ||
![]() |
67e7f13c02 | ||
![]() |
4a7d324c7b | ||
![]() |
e1cda12de3 | ||
![]() |
51bbe74046 | ||
![]() |
782f911d3e | ||
![]() |
8374cd5885 | ||
![]() |
38ab58d03a | ||
![]() |
ed3ede914c | ||
![]() |
7a9ece8e59 | ||
![]() |
4f2f73e6e0 | ||
![]() |
74ce38bc07 | ||
![]() |
b72ea4ab08 | ||
![]() |
5ca80a9f1d | ||
![]() |
fd284303ce | ||
![]() |
a7ee0415e7 | ||
![]() |
28e00b209a | ||
![]() |
af932a972c | ||
![]() |
5431648dbf | ||
![]() |
7096beec7d | ||
![]() |
865b7beca7 | ||
![]() |
ee36284d54 | ||
![]() |
aebd280b64 | ||
![]() |
f644583a65 | ||
![]() |
d50bc8ee2f | ||
![]() |
0b2e2db664 | ||
![]() |
60e246080b | ||
![]() |
76ef025765 | ||
![]() |
43b6679fa0 | ||
![]() |
d92b106514 | ||
![]() |
ca43ef969c | ||
![]() |
91f72c5bb2 | ||
![]() |
5fd4eaf869 | ||
![]() |
aba9bff1e1 | ||
![]() |
cba34bd351 | ||
![]() |
4a7f522397 | ||
![]() |
d236606a63 | ||
![]() |
6677161431 | ||
![]() |
7237a62d94 | ||
![]() |
9227e76eb2 | ||
![]() |
8110659652 | ||
![]() |
300380af90 | ||
![]() |
07eadd7c93 | ||
![]() |
b79b3336a0 | ||
![]() |
458cac0894 | ||
![]() |
b9bbd32d35 | ||
![]() |
271094555d | ||
![]() |
0e27c4d917 | ||
![]() |
efd24aac90 | ||
![]() |
2a0d7cf004 | ||
![]() |
28c8e3d74f | ||
![]() |
ac914c7081 | ||
![]() |
9f89cd2160 | ||
![]() |
5f8f2509c1 | ||
![]() |
ba47fb481c | ||
![]() |
0c048691df | ||
![]() |
c54509f95e | ||
![]() |
70e37c6760 | ||
![]() |
581f5e0ca9 | ||
![]() |
b4ca127825 | ||
![]() |
769379a707 | ||
![]() |
0cda076648 | ||
![]() |
37505d391b | ||
![]() |
32c32206a0 | ||
![]() |
f9c8fc1b2d | ||
![]() |
aa04d9482e | ||
![]() |
0e0d2f06b4 | ||
![]() |
81509d07c5 | ||
![]() |
4aa23fa862 | ||
![]() |
34da0a19eb | ||
![]() |
ce4f3e6935 | ||
![]() |
dbee67e132 | ||
![]() |
f9515b3962 | ||
![]() |
f6815932dc | ||
![]() |
ca95a7aaec | ||
![]() |
581441834a | ||
![]() |
4ea82f7738 | ||
![]() |
bac72f5044 | ||
![]() |
4c706f49a4 | ||
![]() |
9c6978deba | ||
![]() |
864e0ac2c4 | ||
![]() |
d16a81e5a1 | ||
![]() |
964590ac80 | ||
![]() |
ca64f1fb23 | ||
![]() |
296d6162ec | ||
![]() |
bdb3a1c617 | ||
![]() |
b9af697c17 | ||
![]() |
2bd9b22520 | ||
![]() |
3ff01091c8 | ||
![]() |
b275a318bd | ||
![]() |
ffd195141f | ||
![]() |
62d02baa88 | ||
![]() |
f628a8035a | ||
![]() |
69259aee97 | ||
![]() |
975abcd1b4 | ||
![]() |
1883338c0a | ||
![]() |
047b9db726 | ||
![]() |
a3314923f0 | ||
![]() |
da18b70ddb | ||
![]() |
3856ad2f3f | ||
![]() |
e5f0850b3b | ||
![]() |
1d3008d144 | ||
![]() |
11c618c3e5 | ||
![]() |
78dad4cfb4 | ||
![]() |
e09316dc63 | ||
![]() |
b311572748 | ||
![]() |
f2c8b78cf9 | ||
![]() |
683d153acb | ||
![]() |
332fda82d2 | ||
![]() |
29bdcc94c3 | ||
![]() |
e54b28ba14 | ||
![]() |
61afe090b6 | ||
![]() |
3fdd0953e0 | ||
![]() |
d15911006e | ||
![]() |
152764276b | ||
![]() |
6261018ff8 | ||
![]() |
bc59424bb9 | ||
![]() |
5ffe5b492a | ||
![]() |
61b202e89a | ||
![]() |
46b096821f | ||
![]() |
9d6b1c3a07 | ||
![]() |
af72a08e5f | ||
![]() |
1f8d82e869 | ||
![]() |
2d03b36bb3 | ||
![]() |
f6d53587f3 | ||
![]() |
9ab13c3583 | ||
![]() |
4c6e9a85bf | ||
![]() |
dd5e3aa18a | ||
![]() |
e54a15e3f8 | ||
![]() |
8693a1b062 | ||
![]() |
684762ef3e | ||
![]() |
b491620697 | ||
![]() |
5d33db08b8 | ||
![]() |
4979d2f178 | ||
![]() |
ea02e243c6 | ||
![]() |
5fb5e4c18b | ||
![]() |
3a8ea65cd4 | ||
![]() |
28b12e0635 | ||
![]() |
7610f7b9f5 | ||
![]() |
a3e7661f95 | ||
![]() |
3b7a36b6b3 | ||
![]() |
3559fa7206 | ||
![]() |
aa77d8abe6 | ||
![]() |
276414bc63 | ||
![]() |
fd382db08d | ||
![]() |
2241bc261f | ||
![]() |
47dc060370 | ||
![]() |
d388019d5e | ||
![]() |
4fb094f958 | ||
![]() |
8f743fb091 | ||
![]() |
713dbf60a1 | ||
![]() |
d90c7a54b9 | ||
![]() |
225b88ebc1 | ||
![]() |
48a95e8e63 | ||
![]() |
53f7672966 | ||
![]() |
9c8353cc73 | ||
![]() |
e92787862c | ||
![]() |
fbff9fe72b | ||
![]() |
20aa77f179 | ||
![]() |
fb130f8ef5 | ||
![]() |
4acd7bbcda | ||
![]() |
8567f94606 | ||
![]() |
bfe1340236 | ||
![]() |
c69f3c93b1 | ||
![]() |
0ebcc922f8 | ||
![]() |
b3966a11d4 | ||
![]() |
58aec98334 | ||
![]() |
faaa83a553 | ||
![]() |
46ee9deb3d | ||
![]() |
e7335a8662 | ||
![]() |
0cf0421731 | ||
![]() |
cb74f26744 | ||
![]() |
4e3b06a86e | ||
![]() |
696af9445e | ||
![]() |
b25303d4b8 | ||
![]() |
a1dbe00f5f | ||
![]() |
649d358c0e | ||
![]() |
a7a4b3c95b | ||
![]() |
5600003128 | ||
![]() |
e3ae8f4292 | ||
![]() |
60d77bd797 | ||
![]() |
b74954eb90 | ||
![]() |
1ccb266519 | ||
![]() |
4ef4930f28 | ||
![]() |
8075318ba0 | ||
![]() |
2484afa989 | ||
![]() |
56161b5301 | ||
![]() |
badfc0a7cd | ||
![]() |
55ab874160 | ||
![]() |
f641443a9d | ||
![]() |
74e40a8e6d | ||
![]() |
98fd78075f | ||
![]() |
eb12de48fd | ||
![]() |
270e85cfae | ||
![]() |
1a7c1cac4c | ||
![]() |
9d3623294e | ||
![]() |
c4783349b2 | ||
![]() |
793c74ca39 | ||
![]() |
8069622f59 | ||
![]() |
4bc62d1849 | ||
![]() |
b9e4d9483a | ||
![]() |
c6bdfea482 | ||
![]() |
ef3503c0ad | ||
![]() |
d5b79b61fd | ||
![]() |
acc18d1f07 | ||
![]() |
704b6b3583 | ||
![]() |
84525ca40c | ||
![]() |
9096014b64 | ||
![]() |
b627ec0f56 | ||
![]() |
faa6fa6cd5 | ||
![]() |
6d8c08fa6b | ||
![]() |
7d9c7dc20d | ||
![]() |
85939cddfd | ||
![]() |
cd084edc9b | ||
![]() |
a3b46c7a23 | ||
![]() |
b52ff68fd9 | ||
![]() |
a0e26763c9 | ||
![]() |
1a703ce4ab | ||
![]() |
0973a6bd4f | ||
![]() |
0b74e95558 | ||
![]() |
356bcf2120 | ||
![]() |
51244812c5 | ||
![]() |
bb6771f539 | ||
![]() |
1dd0f2f970 | ||
![]() |
4c255ea7d8 | ||
![]() |
5b376e916e | ||
![]() |
95ad473a62 | ||
![]() |
8b9a1f9f1d | ||
![]() |
e52718ff56 | ||
![]() |
f6e1a12ef2 | ||
![]() |
9fbc6f4aa3 | ||
![]() |
241ffe358b | ||
![]() |
2d6a5e0fd2 | ||
![]() |
85a9758533 | ||
![]() |
df0b4bda25 | ||
![]() |
dea1656a37 | ||
![]() |
6968d6f7c0 | ||
![]() |
983c92ce8e | ||
![]() |
1d8bb576dc | ||
![]() |
f94086afc7 | ||
![]() |
ebee0d0b5f | ||
![]() |
d3b5e65622 | ||
![]() |
0eaff54a31 | ||
![]() |
18e1b1aabe | ||
![]() |
3a80661c6b | ||
![]() |
ae6cefd4b3 | ||
![]() |
4b915de665 | ||
![]() |
33c14f36da | ||
![]() |
13d2d84fd4 | ||
![]() |
3f62207d47 | ||
![]() |
c1835ac2eb | ||
![]() |
fee7c4b2ab | ||
![]() |
73c4192b64 | ||
![]() |
a69793064a | ||
![]() |
9be9a35a6c | ||
![]() |
ffb999a7bc | ||
![]() |
e2f96199b7 | ||
![]() |
8f82e249a7 | ||
![]() |
ceac5b280b | ||
![]() |
06a4a8fe1d | ||
![]() |
0d8b4333e3 | ||
![]() |
297fd5b874 | ||
![]() |
a186195795 | ||
![]() |
4c3212de03 | ||
![]() |
9aae181496 | ||
![]() |
00f078dc75 | ||
![]() |
d9c138815d | ||
![]() |
d4abf29012 | ||
![]() |
40fd3b9e1e | ||
![]() |
51694c0b23 | ||
![]() |
80b70804ca | ||
![]() |
71b21dc42d | ||
![]() |
7e42eb0141 | ||
![]() |
79462c20bb | ||
![]() |
b3aacb3fa1 | ||
![]() |
9851f4e99f | ||
![]() |
69a57edd3f | ||
![]() |
145bbbf356 | ||
![]() |
2cd911f294 | ||
![]() |
c7285cadc9 | ||
![]() |
2be8cebc68 | ||
![]() |
ca3bb355b0 | ||
![]() |
8b5c618e89 | ||
![]() |
c3c0c26048 | ||
![]() |
8f15484315 | ||
![]() |
f4d108f668 | ||
![]() |
e91d6ccb5d | ||
![]() |
4b25e9ffcc | ||
![]() |
79a6c2ea78 | ||
![]() |
677640d119 | ||
![]() |
3a1ab102d3 | ||
![]() |
8a01e20a45 | ||
![]() |
54fc157381 | ||
![]() |
277f27da05 | ||
![]() |
96bea1e4f5 | ||
![]() |
1982200ab2 | ||
![]() |
ff773b7260 | ||
![]() |
3a90d66a9e | ||
![]() |
e0266b8038 | ||
![]() |
e2575d3c0a | ||
![]() |
7e80e85ac0 | ||
![]() |
11b8e7e738 | ||
![]() |
09a8f5f1b3 | ||
![]() |
2499652c8e | ||
![]() |
494a8fd3f3 | ||
![]() |
4ad07c9dd9 | ||
![]() |
21caa7ab84 | ||
![]() |
d57b46469c | ||
![]() |
d70bed6c98 | ||
![]() |
818ffdea10 | ||
![]() |
70ac020248 | ||
![]() |
ff9d52bc09 | ||
![]() |
70a9af0c4e | ||
![]() |
4914a32db7 | ||
![]() |
9f29c83d49 | ||
![]() |
a1ca6b3335 | ||
![]() |
58987b81a5 | ||
![]() |
eee14ca3f6 | ||
![]() |
d6f90caa18 | ||
![]() |
4597be781e | ||
![]() |
ca0069b86d | ||
![]() |
89edd2f36b | ||
![]() |
3faa9c2bdd | ||
![]() |
11e8576c2b | ||
![]() |
22f5fb2dbd | ||
![]() |
d7396072f2 | ||
![]() |
2709a1d075 | ||
![]() |
51fa709319 | ||
![]() |
109be00bbc | ||
![]() |
2fd0581746 | ||
![]() |
eb277f1f2a | ||
![]() |
5c52c4dd14 | ||
![]() |
8a1669d134 | ||
![]() |
96e948d6af | ||
![]() |
d86d0c8711 | ||
![]() |
44e70d7f23 | ||
![]() |
4b8f3fad10 | ||
![]() |
c19810a03d | ||
![]() |
f39f687078 | ||
![]() |
bca08d994e | ||
![]() |
bb9c859a70 | ||
![]() |
3e5af1ae3b | ||
![]() |
43b4dfff92 | ||
![]() |
c2b2989665 | ||
![]() |
f7c52c8cd1 | ||
![]() |
7c64de6f82 | ||
![]() |
fc5d1c295d | ||
![]() |
8ee4df1668 | ||
![]() |
53a8bc2728 | ||
![]() |
15ab6429de | ||
![]() |
35c92189e3 | ||
![]() |
8b6cc7cb56 | ||
![]() |
381b07907d | ||
![]() |
019c7274e4 | ||
![]() |
2212f38f19 | ||
![]() |
4aed895db7 | ||
![]() |
70d895093f | ||
![]() |
b55137acd7 | ||
![]() |
ca06116397 | ||
![]() |
2f2a4fcd92 | ||
![]() |
688df489e4 | ||
![]() |
38dd5264f2 | ||
![]() |
3efd67800c | ||
![]() |
485e674b33 | ||
![]() |
2a24447824 | ||
![]() |
2027cb84b6 | ||
![]() |
826099ebf1 | ||
![]() |
d639ed991f | ||
![]() |
99ae79c9b1 | ||
![]() |
5ac1b0a0cf | ||
![]() |
cc78a87d38 | ||
![]() |
b487e3ffb3 | ||
![]() |
31af44e311 | ||
![]() |
d4e9f8d062 | ||
![]() |
7844d3fc03 | ||
![]() |
c228d4c0cc | ||
![]() |
59750c9620 |
1320 changed files with 325877 additions and 52677 deletions
|
@ -1,39 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"es2021": true,
|
||||
"jest": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"no-case-declarations": "off",
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"windows"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single",
|
||||
{
|
||||
"avoidEscape": true
|
||||
}
|
||||
],
|
||||
"semi": [
|
||||
"error",
|
||||
"never"
|
||||
]
|
||||
}
|
||||
}
|
30
.github/ISSUE_TEMPLATE/2_channel-request.yml
vendored
Normal file
30
.github/ISSUE_TEMPLATE/2_channel-request.yml
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
name: ✍️ Channel Request
|
||||
description: Request to add a channel to the guide
|
||||
labels: ['channel request']
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please fill out the request as much as possible so we can efficiently process your request.
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Site
|
||||
description: The name of the site
|
||||
placeholder: 'guidatv.sky.it'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Channels
|
||||
description: List of channels to be added
|
||||
placeholder: 'BBC One'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Notes
|
||||
description: Anything else we should know?
|
24
.github/ISSUE_TEMPLATE/4_feature-request.yml
vendored
Normal file
24
.github/ISSUE_TEMPLATE/4_feature-request.yml
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
name: ✨ Feature request
|
||||
description: Ask for a feature to be added to the guide
|
||||
labels: ['feature request']
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please fill out the issue template as much as you can so we could efficiently process your request.
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Site
|
||||
description: The name of the site
|
||||
placeholder: 'guidatv.sky.it'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: Detailed description of the feature.
|
||||
validations:
|
||||
required: true
|
3
.github/ISSUE_TEMPLATE/config.yml
vendored
3
.github/ISSUE_TEMPLATE/config.yml
vendored
|
@ -1,8 +1,5 @@
|
|||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: 💡 Feature request
|
||||
url: https://github.com/orgs/iptv-org/discussions/categories/ideas
|
||||
about: For any ideas or feature requests
|
||||
- name: ❓ Ask a question
|
||||
url: https://github.com/orgs/iptv-org/discussions/categories/q-a
|
||||
about: Ask questions about this project
|
||||
|
|
52
.github/workflows/check.yml
vendored
Normal file
52
.github/workflows/check.yml
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
name: check
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, edited]
|
||||
branches:
|
||||
- master
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- name: changed files
|
||||
id: files
|
||||
run: |
|
||||
JS_ANY_CHANGED=false
|
||||
JS_ALL_CHANGED_FILES=$(git diff --name-only tests/**/*.js tests/**/*.ts scripts/**/*.js scripts/**/*.mts scripts/**/*.ts sites/**/*.js sites/**/*.ts | tr '\n' ' ')
|
||||
if [ -n "${JS_ALL_CHANGED_FILES}" ]; then
|
||||
JS_ANY_CHANGED=true
|
||||
fi
|
||||
echo "js_all_changed_files=$JS_ALL_CHANGED_FILES" >> "$GITHUB_OUTPUT"
|
||||
echo "js_any_changed=$JS_ANY_CHANGED" >> "$GITHUB_OUTPUT"
|
||||
CHANNELS_ANY_CHANGED=false
|
||||
CHANNELS_ALL_CHANGED_FILES=$(git diff --name-only sites/**/*.channels.xml | tr '\n' ' ')
|
||||
if [ -n "${CHANNELS_ALL_CHANGED_FILES}" ]; then
|
||||
CHANNELS_ANY_CHANGED=true
|
||||
fi
|
||||
echo "channels_all_changed_files=$CHANNELS_ALL_CHANGED_FILES" >> "$GITHUB_OUTPUT"
|
||||
echo "channels_any_changed=$CHANNELS_ANY_CHANGED" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-node@v4
|
||||
if: ${{ !env.ACT && (steps.files.outputs.js_any_changed == 'true' || steps.files.outputs.channels_any_changed == 'true') }}
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'npm'
|
||||
- name: install dependencies
|
||||
if: steps.files.outputs.js_any_changed == 'true' || steps.files.outputs.channels_any_changed == 'true'
|
||||
run: SKIP_POSTINSTALL=1 npm install
|
||||
- name: check changed js-files
|
||||
if: steps.files.outputs.js_any_changed == 'true'
|
||||
run: |
|
||||
npx eslint ${{ steps.files.outputs.js_all_changed_files }}
|
||||
- name: check changed *.channels.xml
|
||||
if: steps.files.outputs.channels_any_changed == 'true'
|
||||
run: |
|
||||
npm run channels:lint -- ${{ steps.files.outputs.channels_all_changed_files }}
|
||||
npm run postinstall
|
||||
npm run channels:validate -- ${{ steps.files.outputs.channels_all_changed_files }}
|
15
.github/workflows/update.yml
vendored
15
.github/workflows/update.yml
vendored
|
@ -25,13 +25,26 @@ jobs:
|
|||
- uses: actions/setup-node@v3
|
||||
if: ${{ !env.ACT }}
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 22
|
||||
cache: 'npm'
|
||||
- name: install dependencies
|
||||
run: npm install
|
||||
- name: check *.channels.xml
|
||||
run: |
|
||||
npm run channels:lint
|
||||
- name: update sites.md
|
||||
run: npm run sites:update
|
||||
- run: git status
|
||||
- name: commit changes to sites.md
|
||||
if: ${{ !env.ACT && github.ref == 'refs/heads/master' }}
|
||||
run: |
|
||||
SITE=SITES.md
|
||||
CHANGED=$(git diff ${SITE})
|
||||
if [ -n "${CHANGED}" ]; then
|
||||
git add ${SITE}
|
||||
git commit -m "[Bot] Update ${SITE}" -m "Committed by [iptv-bot](https://github.com/apps/iptv-bot) via [update](https://github.com/iptv-org/epg/actions/runs/${{ github.run_id }}) workflow." --no-verify
|
||||
git push
|
||||
fi
|
||||
- name: generate .api/guides.json
|
||||
run: npm run api:generate
|
||||
- run: git status
|
||||
|
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -2,4 +2,7 @@
|
|||
/temp/
|
||||
/channels.xml
|
||||
/guide.xml
|
||||
/guide.xml.gz
|
||||
/guide.xml.gz
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
7
.husky/channels_lint.sh
Executable file
7
.husky/channels_lint.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
channels_changed="$(git diff --staged --name-only --diff-filter=ACMR -- 'sites/**/*.channels.xml' | sed 's| |\\ |g')"
|
||||
|
||||
if [ ! -z "$channels_changed" ]; then
|
||||
npm run channels:lint -- $channels_changed
|
||||
fi
|
7
.husky/channels_validate.sh
Executable file
7
.husky/channels_validate.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
channels_changed="$(git diff --staged --name-only --diff-filter=ACMR -- 'sites/**/*.channels.xml' | sed 's| |\\ |g')"
|
||||
|
||||
if [ ! -z "$channels_changed" ]; then
|
||||
npm run channels:validate -- $channels_changed
|
||||
fi
|
3
.husky/pre-commit
Normal file
3
.husky/pre-commit
Normal file
|
@ -0,0 +1,3 @@
|
|||
.husky/scripts_lint.sh
|
||||
.husky/channels_lint.sh
|
||||
.husky/channels_validate.sh
|
7
.husky/scripts_lint.sh
Executable file
7
.husky/scripts_lint.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
scripts_changed="$(git diff --staged --name-only --diff-filter=ACMR -- 'tests/**/*.ts' 'tests/**/*.js' 'scripts/**/*.ts' 'scripts/**/*.mts' 'scripts/**/*.js' 'sites/**/*.js' 'sites/**/*.ts' | sed 's| |\\ |g')"
|
||||
|
||||
if [ ! -z "$scripts_changed" ]; then
|
||||
npx eslint $scripts_changed
|
||||
fi
|
|
@ -1,7 +1,7 @@
|
|||
module.exports = {
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
endOfLine: 'lf',
|
||||
endOfLine: 'crlf',
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
printWidth: 100,
|
||||
|
|
363
CONTRIBUTING.md
363
CONTRIBUTING.md
|
@ -8,47 +8,247 @@
|
|||
|
||||
### How to add a channel to the guide?
|
||||
|
||||
Open the [/sites](/sites) folder and select the source that you know has the guide for the channel you want.
|
||||
To ask for help with adding a channel simply fill out this [form](https://github.com/iptv-org/epg/issues/new?assignees=&labels=channel+request&projects=&template=2_channel-request.yml).
|
||||
|
||||
Then in the selected folder open the file `*.channels.xml` and add to it:
|
||||
If you want to add a channel to the list yourself, here are the instructions on how to do it.
|
||||
|
||||
First select the site from [SITES.md](SITES.md) that you know has a guide for the channel you need. Then go to the folder with its config and open the file `*.channels.xml`.
|
||||
|
||||
Make sure that the desired channel is not already in the list. If it is not, simply add its description to the end of the list as shown here:
|
||||
|
||||
```xml
|
||||
<channel site="SITE" lang="LANGUAGE_CODE" xmltv_id="CHANNEL_ID" site_id="SITE_ID">CHANNEL_NAME</channel>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
...
|
||||
<channel site="SITE" lang="LANGUAGE_CODE" xmltv_id="CHANNEL_ID" site_id="SITE_ID">CHANNEL_NAME</channel>
|
||||
</channels>
|
||||
```
|
||||
|
||||
| Attribute | Description | Example |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------- |
|
||||
| SITE | Site domain name. | `example.com` |
|
||||
| LANGUAGE_CODE | Language of the guide ([ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code). | `en` |
|
||||
| CHANNEL_ID | Channel ID from [iptv-org/database](https://github.com/iptv-org/database). A complete list of supported channels can also be found at https://iptv-org.github.io/. | `BBCOne.uk` |
|
||||
| SITE_ID | Unique ID of the channel used in the source. | `bbc1` |
|
||||
| CHANNEL_NAME | Name of the channel used in the source. | `BBC 1` |
|
||||
| Attribute | Description | Example |
|
||||
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
|
||||
| SITE | Site domain name. | `example.com` |
|
||||
| LANGUAGE_CODE | Language of the guide ([ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code). | `en` |
|
||||
| CHANNEL_ID | ID of the channel. Full list of supported channels with corresponding ID could be found on [iptv-org.github.io](https://iptv-org.github.io/). | `HBO.us@East` |
|
||||
| SITE_ID | Unique ID of the channel used in the source. | `hbo` |
|
||||
| CHANNEL_NAME | Name of the channel used in the source. | `HBO East` |
|
||||
|
||||
After that just commit all changes and send a pull request.
|
||||
After that just [commit](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/about-commits) all changes and send a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests).
|
||||
|
||||
### How to report broken guide?
|
||||
|
||||
If you start to get errors when downloading the guide or if nothing loads at all, please let us know via this [form](https://github.com/iptv-org/epg/issues/new?assignees=&labels=broken+guide&projects=&template=3_broken-guide.yml).
|
||||
|
||||
### How to add a new source to the repository?
|
||||
|
||||
To do this, you must create a new folder in the [/sites](/sites) with at least 3 files:
|
||||
If you are not familiar with javascript programming, you can ask for help from other community members through this [form](https://github.com/iptv-org/epg/issues/new?assignees=&labels=source+request&projects=&template=1_source-request.yml). Otherwise, below are the instructions for you.
|
||||
|
||||
To start with, you need to create a new folder in the [/sites](/sites) folder and put at least 4 files in it:
|
||||
|
||||
<details>
|
||||
<summary>example.com.config.js</summary>
|
||||
<br>
|
||||
|
||||
This file describes what kind of request we need to send to get the guide for a particular channel on a certain date. It also describes how to parse the response.
|
||||
This file describes what kind of request we need to send to get the guide for a particular channel on a certain date and how to parse the response.
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
site: 'example.com',
|
||||
url: function ({ channel, date }) {
|
||||
url({ channel, date }) {
|
||||
return `https://example.com/api/${channel.site_id}/${date.format('YYYY-MM-DD')}`
|
||||
},
|
||||
parser: function ({ content }) {
|
||||
return JSON.parse(content)
|
||||
parser(context) {
|
||||
try {
|
||||
return JSON.parse(context.content)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
More detailed instructions for this file can be found here: https://github.com/freearhey/epg-grabber#site-config
|
||||
### Context Object
|
||||
|
||||
From each function in `config.js` you can access a `context` object containing the following data:
|
||||
|
||||
- `channel`: The object describing the current channel (xmltv_id, site_id, name, lang)
|
||||
- `date`: The 'dayjs' instance with the requested date
|
||||
- `content`: The response data as a String
|
||||
- `buffer`: The response data as an ArrayBuffer
|
||||
- `headers`: The response headers
|
||||
- `request`: The request config
|
||||
- `cached`: A boolean to check whether this request was cached or not
|
||||
|
||||
### Program Properties
|
||||
|
||||
List of properties that can be assigned to each program during parsing.
|
||||
|
||||
| Property | Aliases | Type | Required |
|
||||
| --------------- | -------------------------------- | ------------------------------------------ | -------- |
|
||||
| start | | `String \| Number \| Date()` | true |
|
||||
| stop | | `String \| Number \| Date()` | true |
|
||||
| title | titles | `String \| Object \| String[] \| Object[]` | true |
|
||||
| subTitle | subTitles, sub_title, sub_titles | `String \| Object \| String[] \| Object[]` | false |
|
||||
| description | desc, descriptions | `String \| Object \| String[] \| Object[]` | false |
|
||||
| date | | `String \| Number \| Date()` | false |
|
||||
| category | categories | `String \| Object \| String[] \| Object[]` | false |
|
||||
| keyword | keywords | `String \| Object \| String[] \| Object[]` | false |
|
||||
| language | languages | `String \| Object \| String[] \| Object[]` | false |
|
||||
| origLanguage | origLanguages | `String \| Object \| String[] \| Object[]` | false |
|
||||
| length | | `String \| Object \| String[] \| Object[]` | false |
|
||||
| url | urls | `String \| Object \| String[] \| Object[]` | false |
|
||||
| country | countries | `String \| Object \| String[] \| Object[]` | false |
|
||||
| video | | `Object` | false |
|
||||
| audio | | `Object` | false |
|
||||
| season | | `String \| Number` | false |
|
||||
| episode | | `String \| Number` | false |
|
||||
| episodeNumber | episodeNum, episodeNumbers | `Object` | false |
|
||||
| previouslyShown | | `String \| Object \| String[] \| Object[]` | false |
|
||||
| premiere | | `String \| Object \| String[] \| Object[]` | false |
|
||||
| lastChance | | `String \| Object \| String[] \| Object[]` | false |
|
||||
| new | | `Boolean` | false |
|
||||
| subtitles | | `Object \| Object[]` | false |
|
||||
| rating | ratings | `String \| Object \| String[] \| Object[]` | false |
|
||||
| starRating | starRatings | `String \| Object \| String[] \| Object[]` | false |
|
||||
| review | reviews | `String \| Object \| String[] \| Object[]` | false |
|
||||
| director | directors | `String \| Object \| String[] \| Object[]` | false |
|
||||
| actor | actors | `String \| Object \| String[] \| Object[]` | false |
|
||||
| writer | writers | `String \| Object \| String[] \| Object[]` | false |
|
||||
| adapter | adapters | `String \| Object \| String[] \| Object[]` | false |
|
||||
| producer | producers | `String \| Object \| String[] \| Object[]` | false |
|
||||
| presenter | presenters | `String \| Object \| String[] \| Object[]` | false |
|
||||
| composer | composers | `String \| Object \| String[] \| Object[]` | false |
|
||||
| editor | editors | `String \| Object \| String[] \| Object[]` | false |
|
||||
| commentator | commentators | `String \| Object \| String[] \| Object[]` | false |
|
||||
| guest | guests | `String \| Object \| String[] \| Object[]` | false |
|
||||
| image | images | `String \| Object \| String[] \| Object[]` | false |
|
||||
| icon | icons | `String \| Object \| String[] \| Object[]` | false |
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
{
|
||||
start: '2021-03-19T06:00:00.000Z',
|
||||
stop: '2021-03-19T06:30:00.000Z',
|
||||
title: 'Program 1',
|
||||
subTitle: 'Sub-title & 1',
|
||||
description: 'Description for Program 1',
|
||||
date: '2022-05-06',
|
||||
categories: ['Comedy', 'Drama'],
|
||||
keywords: [
|
||||
{ lang: 'en', value: 'physical-comedy' },
|
||||
{ lang: 'en', value: 'romantic' }
|
||||
],
|
||||
language: 'English',
|
||||
origLanguage: { lang: 'en', value: 'French' },
|
||||
length: { units: 'minutes', value: '60' },
|
||||
url: 'http://example.com/title.html',
|
||||
country: 'US',
|
||||
video: {
|
||||
present: 'yes',
|
||||
colour: 'no',
|
||||
aspect: '16:9',
|
||||
quality: 'HDTV'
|
||||
},
|
||||
audio: {
|
||||
present: 'yes',
|
||||
stereo: 'Dolby Digital'
|
||||
},
|
||||
season: 9,
|
||||
episode: 239,
|
||||
previouslyShown: [{ start: '20080711000000', channel: 'channel-two.tv' }],
|
||||
premiere: 'First time on British TV',
|
||||
lastChance: [{ lang: 'en', value: 'Last time on this channel' }],
|
||||
new: true,
|
||||
subtitles: [
|
||||
{ type: 'teletext', language: 'English' },
|
||||
{ type: 'onscreen', language: [{ lang: 'en', value: 'Spanish' }] }
|
||||
],
|
||||
rating: {
|
||||
system: 'MPAA',
|
||||
value: 'P&G',
|
||||
icon: 'http://example.com/pg_symbol.png'
|
||||
},
|
||||
starRatings: [
|
||||
{
|
||||
system: 'TV Guide',
|
||||
value: '4/5',
|
||||
icon: [{ src: 'stars.png', width: 100, height: 100 }]
|
||||
},
|
||||
{
|
||||
system: 'IMDB',
|
||||
value: '8/10'
|
||||
}
|
||||
],
|
||||
reviews: [
|
||||
{
|
||||
type: 'text',
|
||||
source: 'Rotten Tomatoes',
|
||||
reviewer: 'Joe Bloggs',
|
||||
lang: 'en',
|
||||
value: 'This is a fantastic show!'
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
source: 'IDMB',
|
||||
reviewer: 'Jane Doe',
|
||||
lang: 'en',
|
||||
value: 'I love this show!'
|
||||
},
|
||||
{
|
||||
type: 'url',
|
||||
source: 'Rotten Tomatoes',
|
||||
reviewer: 'Joe Bloggs',
|
||||
lang: 'en',
|
||||
value: 'https://example.com/programme_one_review'
|
||||
}
|
||||
],
|
||||
directors: [
|
||||
{
|
||||
value: 'Director 1',
|
||||
url: { value: 'http://example.com/director1.html', system: 'TestSystem' },
|
||||
image: [
|
||||
'https://example.com/image1.jpg',
|
||||
{
|
||||
value: 'https://example.com/image2.jpg',
|
||||
type: 'person',
|
||||
size: '2',
|
||||
system: 'TestSystem',
|
||||
orient: 'P'
|
||||
}
|
||||
]
|
||||
},
|
||||
'Director 2'
|
||||
],
|
||||
actors: ['Actor 1', 'Actor 2'],
|
||||
writer: 'Writer 1',
|
||||
producers: 'Roger Dobkowitz',
|
||||
presenters: 'Drew Carey',
|
||||
images: [
|
||||
{
|
||||
type: 'poster',
|
||||
size: '1',
|
||||
orient: 'P',
|
||||
system: 'tvdb',
|
||||
value: 'https://tvdb.com/programme_one_poster_1.jpg'
|
||||
},
|
||||
{
|
||||
type: 'poster',
|
||||
size: '2',
|
||||
orient: 'P',
|
||||
system: 'tmdb',
|
||||
value: 'https://tmdb.com/programme_one_poster_2.jpg'
|
||||
},
|
||||
{
|
||||
type: 'backdrop',
|
||||
size: '3',
|
||||
orient: 'L',
|
||||
system: 'tvdb',
|
||||
value: 'https://tvdb.com/programme_one_backdrop_3.jpg'
|
||||
}
|
||||
],
|
||||
icon: 'https://example.com/images/Program1.png?x=шеллы&sid=777'
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -59,44 +259,50 @@ More detailed instructions for this file can be found here: https://github.com/f
|
|||
With this file we can test the previously created config and make sure it works as you expect.
|
||||
|
||||
```js
|
||||
const { url, parser } = require('./example.com.config.js')
|
||||
const { parser, url } = require('./example.com.config.js')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
dayjs.extend(customParseFormat)
|
||||
dayjs.extend(utc)
|
||||
|
||||
const date = dayjs.utc('2022-11-18', 'YYYY-MM-DD').startOf('d')
|
||||
const channel = { site_id: 'bbc1', xmltv_id: 'BBCOne.uk', lang: 'en' }
|
||||
const date = dayjs.utc('2025-01-12', 'YYYY-MM-DD').startOf('d')
|
||||
const channel = { site_id: 'bbc1', xmltv_id: 'BBCOne.uk' }
|
||||
|
||||
it('can generate valid url', () => {
|
||||
expect(url({ channel, date })).toBe('https://example.com/api/bbc1/2022-11-18')
|
||||
expect(url({ channel, date })).toBe('https://example.com/api/bbc1/2025-01-12')
|
||||
})
|
||||
|
||||
it('can parse response', () => {
|
||||
const content = `[{"start":"2022-11-18T01:30:00.000Z","stop":"2022-11-18T02:00:00.000Z","title":"Program 1"}]`
|
||||
const content =
|
||||
'[{"title":"Program 1","start":"2025-01-12T00:00:00.000Z","stop":"2025-01-12T00:30:00.000Z"},{"title":"Program 2","start":"2025-01-12T00:30:00.000Z","stop":"2025-01-12T01:00:00.000Z"}]'
|
||||
|
||||
const results = parser({ content })
|
||||
|
||||
expect(results).toMatchObject([
|
||||
{
|
||||
start: '2022-11-18T01:30:00.000Z',
|
||||
stop: '2022-11-18T02:00:00.000Z',
|
||||
title: 'Program 1'
|
||||
}
|
||||
])
|
||||
expect(results.length).toBe(2)
|
||||
expect(results[0]).toMatchObject({
|
||||
title: 'Program 1',
|
||||
start: '2025-01-12T00:00:00.000Z',
|
||||
stop: '2025-01-12T00:30:00.000Z'
|
||||
})
|
||||
expect(results[1]).toMatchObject({
|
||||
title: 'Program 2',
|
||||
start: '2025-01-12T00:30:00.000Z',
|
||||
stop: '2025-01-12T01:00:00.000Z'
|
||||
})
|
||||
})
|
||||
|
||||
it('can handle empty guide', () => {
|
||||
const results = parser({ content: '' })
|
||||
const result = parser({
|
||||
date,
|
||||
channel,
|
||||
content: ''
|
||||
})
|
||||
|
||||
expect(results).toMatchObject([])
|
||||
expect(result).toMatchObject([])
|
||||
})
|
||||
```
|
||||
|
||||
To run the tests you can use the following command:
|
||||
|
||||
```sh
|
||||
npm test -- example.com
|
||||
```
|
||||
|
||||
Detailed documentation for the tests can be found here: https://jestjs.io/docs/using-matchers
|
||||
|
||||
</details>
|
||||
|
@ -110,21 +316,89 @@ This file contains a list of channels available at the source.
|
|||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<channels>
|
||||
<channel site="example.com" lang="en" xmltv_id="BBCOne.uk" site_id="bbc1">BBC 1</channel>
|
||||
<channel site="example.com" lang="en" xmltv_id="BBCOne.uk" site_id="bbc1">BBC One</channel>
|
||||
</channels>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
After creating all the files we can make sure that the guide loads correctly and has no errors using the command:
|
||||
<details>
|
||||
<summary>readme.md</summary>
|
||||
<br>
|
||||
|
||||
This file contains instructions on how to use this config.
|
||||
|
||||
````
|
||||
# example.com
|
||||
|
||||
https://example.com
|
||||
|
||||
### Download the guide
|
||||
|
||||
```sh
|
||||
npm run grab -- --site=example.com
|
||||
npm run grab --- --site=example.com
|
||||
```
|
||||
|
||||
If the download is successful, the `guide.xml` file with the ready to use program should appear in the root directory.
|
||||
### Test
|
||||
|
||||
After that, all that remains is to commit all the changes and send a pull request.
|
||||
```sh
|
||||
npm test --- example.com
|
||||
```
|
||||
````
|
||||
|
||||
</details>
|
||||
|
||||
The fastest way to create all these files is to use the command:
|
||||
|
||||
```sh
|
||||
npm run sites:init --- example.com
|
||||
```
|
||||
|
||||
After you finish working on the files you can make sure that everything works by running the config test:
|
||||
|
||||
```
|
||||
npm test --- example.com
|
||||
```
|
||||
|
||||
Then check that all channels have the correct `xmltv-id`:
|
||||
|
||||
```
|
||||
npm run channels:validate sites/example.com/example.com.channels.xml
|
||||
```
|
||||
|
||||
And then try downloading the guide itself:
|
||||
|
||||
```
|
||||
npm run grab --- example.com
|
||||
```
|
||||
|
||||
If everything goes well just [commit](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/about-commits) all changes and send us a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests).
|
||||
|
||||
### How to map the channels?
|
||||
|
||||
In order for the guides to be linked with playlists from [iptv-org/iptv](https://github.com/iptv-org/iptv) and also with our other projects, each channel must have the same ID in the description as in our [iptv-org/database](https://github.com/iptv-org/database).
|
||||
|
||||
To check this, select one of the sites in the [SITES.md](SITES.md), open its `*.channels.xml` file and check that all channels have a valid `xmltv_id`. A list of all channels with corresponding IDs can be found at [iptv-org.github.io](https://iptv-org.github.io/).
|
||||
|
||||
If the channel is not in our database yet, you can add it to it through this [form](https://github.com/iptv-org/database/issues/new?assignees=&labels=channels%3Aadd&projects=&template=1_channels_add.yml&title=Add%3A+).
|
||||
|
||||
If the `*.channels.xml` file contains many channels without `xmltv_id`, you can speed up the process by running the command in the [Console](https://en.wikipedia.org/wiki/Windows_Console) (or [Terminal](<https://en.wikipedia.org/wiki/Terminal_(macOS)>) if you have macOS):
|
||||
|
||||
```sh
|
||||
npm run channels:edit path/to/channels.xml
|
||||
```
|
||||
|
||||
This way, you can map channels by simply selecting the proper ID from the list:
|
||||
|
||||
```sh
|
||||
? Select channel ID for "BBC One" (bbc1): (Use arrow keys)
|
||||
❯ BBCOne.uk (BBC One, BBC1, BBC Television, BBC Television Service)
|
||||
BBCOneHD.uk (BBC One HD)
|
||||
Type...
|
||||
Skip
|
||||
```
|
||||
|
||||
Once complete, [commit](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/about-commits) all changes and send a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests).
|
||||
|
||||
## Project Structure
|
||||
|
||||
|
@ -147,13 +421,16 @@ For scripts to work, you must have [Node.js](https://nodejs.org/en) installed on
|
|||
|
||||
To run scripts use the `npm run <script-name>` command.
|
||||
|
||||
- `act:check`: allows to test the [check](https://github.com/iptv-org/iptv/blob/master/.github/workflows/check.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act).
|
||||
- `act:update`: allows to test the [update](https://github.com/iptv-org/iptv/blob/master/.github/workflows/update.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act).
|
||||
- `api:load`: downloads the latest channels data from the [iptv-org/api](https://github.com/iptv-org/api).
|
||||
- `api:generate`: generates a JSON file with all channels for the [iptv-org/api](https://github.com/iptv-org/api) repository.
|
||||
- `channels:lint`: сhecks the channel lists for syntax errors.
|
||||
- `channels:parse`: generates a list of channels based on the site configuration.
|
||||
- `channels:editor`: utility for quick channels markup.
|
||||
- `channels:edit`: utility for quick channels mapping.
|
||||
- `channels:validate`: checks the description of channels for errors.
|
||||
- `sites:init`: creates a new site config from the template.
|
||||
- `sites:update`: updates the list of sites and their status in [SITES.md](SITES.md).
|
||||
- `grab`: downloads a program from a specified source.
|
||||
- `serve`: starts the [web server](https://github.com/vercel/serve).
|
||||
- `lint`: сhecks the scripts for syntax errors.
|
||||
|
|
24
Dockerfile
Normal file
24
Dockerfile
Normal file
|
@ -0,0 +1,24 @@
|
|||
FROM node:22-alpine
|
||||
ARG GIT_REPO=https://github.com/iptv-org/epg.git
|
||||
ARG GIT_BRANCH=master
|
||||
ARG WORKDIR=/epg
|
||||
ENV CRON_SCHEDULE="0 0 * * *"
|
||||
ENV GZIP=false
|
||||
ENV MAX_CONNECTIONS=1
|
||||
ENV DAYS=
|
||||
RUN apk update \
|
||||
&& apk upgrade --available \
|
||||
&& apk add curl git tzdata bash \
|
||||
&& npm install -g npm@latest \
|
||||
&& npm install pm2 -g \
|
||||
&& mkdir $(echo "${WORKDIR}") -p \
|
||||
&& cd $WORKDIR \
|
||||
&& git clone --depth 1 -b $(echo "${GIT_BRANCH} ${GIT_REPO}") . \
|
||||
&& npm install \
|
||||
&& mkdir /public
|
||||
RUN apk del git curl \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
COPY pm2.config.js $WORKDIR
|
||||
WORKDIR $WORKDIR
|
||||
EXPOSE 3000
|
||||
CMD [ "pm2-runtime", "pm2.config.js" ]
|
142
README.md
142
README.md
|
@ -1,4 +1,4 @@
|
|||
# EPG
|
||||
# EPG [](https://github.com/iptv-org/epg/actions/workflows/update.yml)
|
||||
|
||||
Tools for downloading the EPG (Electronic Program Guide) for thousands of TV channels from hundreds of sources.
|
||||
|
||||
|
@ -7,6 +7,7 @@ Tools for downloading the EPG (Electronic Program Guide) for thousands of TV cha
|
|||
- ✨ [Installation](#installation)
|
||||
- 🚀 [Usage](#usage)
|
||||
- 💫 [Update](#update)
|
||||
- 🐋 [Docker](#docker)
|
||||
- 📺 [Playlists](#playlists)
|
||||
- 🗄 [Database](#database)
|
||||
- 👨💻 [API](#api)
|
||||
|
@ -39,50 +40,31 @@ npm install
|
|||
|
||||
## Usage
|
||||
|
||||
To start the download of the guide, select one of the [supported sites](SITES.md) and paste its name into the command below:
|
||||
To start the download of the guide, select one of the supported sites from [SITES.md](SITES.md) file and paste its name into the command below:
|
||||
|
||||
```sh
|
||||
npm run grab -- --site=example.com
|
||||
npm run grab --- --site=example.com
|
||||
```
|
||||
|
||||
And once the download is complete, the guide will be saved to the `guide.xml` file.
|
||||
Then run it and wait for the guide to finish downloading. When finished, a new `guide.xml` file will appear in the current directory.
|
||||
|
||||
You can also customize the behavior of the script using this options:
|
||||
|
||||
```sh
|
||||
Usage: npm run grab -- [options]
|
||||
Usage: npm run grab --- [options]
|
||||
|
||||
Options:
|
||||
-s, --site <name> Name of the site to parse
|
||||
-c, --channels <path> Path to *.channels.xml file (required if the "--site" attribute is
|
||||
not specified)
|
||||
-o, --output <path> Path to output file (default: "guide.xml")
|
||||
-l, --lang <code> Filter channels by language (ISO 639-2 code)
|
||||
-t, --timeout <milliseconds> Override the default timeout for each request
|
||||
-d, --delay <milliseconds> Override the default delay between request
|
||||
--days <days> Override the number of days for which the program will be loaded
|
||||
(defaults to the value from the site config)
|
||||
--maxConnections <number> Limit on the number of concurrent requests (default: 1)
|
||||
--cron <expression> Schedule a script run (example: "0 0 * * *")
|
||||
--gzip Create a compressed version of the guide as well (default: false)
|
||||
```
|
||||
|
||||
### Access the guide by URL
|
||||
|
||||
You can make the guide available via URL by running your own server:
|
||||
|
||||
```sh
|
||||
npm run serve
|
||||
```
|
||||
|
||||
After that, the guide will be available at the link:
|
||||
|
||||
```
|
||||
http://localhost:3000/guide.xml
|
||||
```
|
||||
|
||||
In addition it will be available to other devices on the same local network at the address:
|
||||
|
||||
```
|
||||
http://<your_local_ip_address>:3000/guide.xml
|
||||
-l, --lang <codes> Allows you to restrict downloading to channels in specified languages only (example: "en,id")
|
||||
-t, --timeout <milliseconds> Timeout for each request in milliseconds (default: 0)
|
||||
-d, --delay <milliseconds> Delay between request in milliseconds (default: 0)
|
||||
-x, --proxy <url> Use the specified proxy (example: "socks5://username:password@127.0.0.1:1234")
|
||||
--days <days> Number of days for which the program will be loaded (defaults to the value from the site config)
|
||||
--maxConnections <number> Number of concurrent requests (default: 1)
|
||||
--gzip Specifies whether or not to create a compressed version of the guide (default: false)
|
||||
```
|
||||
|
||||
### Parallel downloading
|
||||
|
@ -90,7 +72,7 @@ http://<your_local_ip_address>:3000/guide.xml
|
|||
By default, the guide for each channel is downloaded one by one, but you can change this behavior by increasing the number of simultaneous requests using the `--maxConnections` attribute:
|
||||
|
||||
```sh
|
||||
npm run grab -- --site=example.com --maxConnections=10
|
||||
npm run grab --- --site=example.com --maxConnections=10
|
||||
```
|
||||
|
||||
But be aware that under heavy load, some sites may start return an error or completely block your access.
|
||||
|
@ -110,17 +92,47 @@ Create an XML file and copy the descriptions of all the channels you need from t
|
|||
And then specify the path to that file via the `--channels` attribute:
|
||||
|
||||
```sh
|
||||
npm run grab -- --channels=path/to/custom.channels.xml
|
||||
npm run grab --- --channels=path/to/custom.channels.xml
|
||||
```
|
||||
|
||||
### Run on schedule
|
||||
|
||||
If you want to download the guide automatically on a schedule, you need to pass a valid [cron expression](https://crontab.guru/) to the script using the `--cron` attribute:
|
||||
To download the guide on a schedule, you can use the included process manager. Just run it with desire [cron expression](https://crontab.guru/) and the `grab` options:
|
||||
|
||||
```sh
|
||||
npm run grab -- --site=example.com --cron="0 0 * * *"
|
||||
npx pm2 start npm --no-autorestart --cron-restart="0 0,12 * * *" -- run grab --- --site=example.com
|
||||
```
|
||||
|
||||
To track the process, you can use the command:
|
||||
|
||||
```sh
|
||||
npx pm2 logs
|
||||
```
|
||||
|
||||
For more info go to [pm2](https://pm2.keymetrics.io/docs/usage/quick-start/) documentation.
|
||||
|
||||
### Access the guide by URL
|
||||
|
||||
You can make the guide available via URL by running your own server. The easiest way to do this is to run this command:
|
||||
|
||||
```sh
|
||||
npx serve
|
||||
```
|
||||
|
||||
After that, the guide will be available at the link:
|
||||
|
||||
```
|
||||
http://localhost:3000/guide.xml
|
||||
```
|
||||
|
||||
In addition it will be available to other devices on the same local network at the address:
|
||||
|
||||
```
|
||||
http://<your_local_ip_address>:3000/guide.xml
|
||||
```
|
||||
|
||||
For more info go to [serve](https://github.com/vercel/serve) documentation.
|
||||
|
||||
## Update
|
||||
|
||||
If you have downloaded the repository code according to the instructions above, then to update it will be enough to run the command:
|
||||
|
@ -135,9 +147,61 @@ And then update all the dependencies:
|
|||
npm install
|
||||
```
|
||||
|
||||
## Playlists
|
||||
## Docker
|
||||
|
||||
Playlists with already linked guides can be found in the [iptv-org/iptv](https://github.com/iptv-org/iptv) repository.
|
||||
### Build an image
|
||||
|
||||
```sh
|
||||
docker build -t iptv-org/epg --no-cache .
|
||||
```
|
||||
|
||||
### Create and run container
|
||||
|
||||
```sh
|
||||
docker run -p 3000:3000 -v /path/to/channels.xml:/epg/channels.xml iptv-org/epg
|
||||
```
|
||||
|
||||
By default, the guide will be downloaded every day at 00:00 UTC and saved to the `/epg/public/guide.xml` file inside the container.
|
||||
|
||||
From the outside, it will be available at this link:
|
||||
|
||||
```
|
||||
http://localhost:3000/guide.xml
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
http://<your_local_ip_address>:3000/guide.xml
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
To fine-tune the execution, you can pass environment variables to the container as follows:
|
||||
|
||||
```sh
|
||||
docker run \
|
||||
-p 5000:3000 \
|
||||
-v /path/to/channels.xml:/epg/channels.xml \
|
||||
-e CRON_SCHEDULE="0 0,12 * * *" \
|
||||
-e MAX_CONNECTIONS=10 \
|
||||
-e GZIP=true \
|
||||
-e PROXY="socks5://127.0.0.1:1234" \
|
||||
-e DAYS=14 \
|
||||
-e TIMEOUT=5 \
|
||||
-e DELAY=2 \
|
||||
iptv-org/epg
|
||||
```
|
||||
|
||||
| Variable | Description |
|
||||
| --------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| CRON_SCHEDULE | A [cron expression](https://crontab.guru/) describing the schedule of the guide loadings (default: "0 0 \* \* \*") |
|
||||
| MAX_CONNECTIONS | Limit on the number of concurrent requests (default: 1) |
|
||||
| GZIP | Boolean value indicating whether to create a compressed version of the guide (default: false) |
|
||||
| PROXY | Use the specified proxy |
|
||||
| DAYS | Number of days for which the guide will be loaded (defaults to the value from the site config) |
|
||||
| TIMEOUT | Timeout for each request in milliseconds (default: 0) |
|
||||
| DELAY | Delay between request in milliseconds (default: 0) |
|
||||
|
||||
## Database
|
||||
|
||||
|
|
432
SITES.md
432
SITES.md
|
@ -1,195 +1,237 @@
|
|||
# Sites
|
||||
|
||||
| Site | Status | Notes |
|
||||
| ------------------------------------------------------------------ | ------ | ------------------------------------------- |
|
||||
| [9tv.co.il](sites/9tv.co.il) | 🟢 | |
|
||||
| [abc.net.au](sites/abc.net.au) | 🟢 | |
|
||||
| [allente.dk](sites/allente.dk) | 🟢 | |
|
||||
| [allente.fi](sites/allente.fi) | 🟢 | |
|
||||
| [allente.no](sites/allente.no) | 🟢 | |
|
||||
| [allente.se](sites/allente.se) | 🟢 | |
|
||||
| [andorradifusio.ad](sites/andorradifusio.ad) | 🟢 | |
|
||||
| [anteltv.com.uy](sites/anteltv.com.uy) | 🟢 | |
|
||||
| [arianaafgtv.com](sites/arianaafgtv.com) | 🟢 | |
|
||||
| [arianatelevision.com](sites/arianatelevision.com) | 🟢 | |
|
||||
| [arirang.com](sites/arirang.com) | 🟢 | |
|
||||
| [artonline.tv](sites/artonline.tv) | 🟢 | |
|
||||
| [bein.com](sites/bein.com) | 🟢 | |
|
||||
| [beinsports.com](sites/beinsports.com) | 🟢 | |
|
||||
| [berrymedia.co.kr](sites/berrymedia.co.kr) | 🟢 | |
|
||||
| [bt.com](sites/bt.com) | 🔴 | https://github.com/iptv-org/epg/issues/2221 |
|
||||
| [cablego.com.pe](sites/cablego.com.pe) | 🟢 | |
|
||||
| [cableplus.com.uy](sites/cableplus.com.uy) | 🟢 | |
|
||||
| [canalplus-haiti.com](sites/canalplus-haiti.com) | 🔴 | https://github.com/iptv-org/epg/issues/2237 |
|
||||
| [canalplus.com](sites/canalplus.com) | 🟢 | |
|
||||
| [cgates.lt](sites/cgates.lt) | 🟢 | |
|
||||
| [chaines-tv.orange.fr](sites/chaines-tv.orange.fr) | 🟢 | |
|
||||
| [clickthecity.com](sites/clickthecity.com) | 🟢 | |
|
||||
| [comteco.com.bo](sites/comteco.com.bo) | 🔴 | https://github.com/iptv-org/epg/issues/2239 |
|
||||
| [content.astro.com.my](sites/content.astro.com.my) | 🟢 | |
|
||||
| [cosmote.gr](sites/cosmote.gr) | 🟢 | |
|
||||
| [cubmu.com](sites/cubmu.com) | 🟢 | |
|
||||
| [dens.tv](sites/dens.tv) | 🟢 | |
|
||||
| [digiturk.com.tr](sites/digiturk.com.tr) | 🟢 | |
|
||||
| [directv.com](sites/directv.com) | 🟢 | |
|
||||
| [directv.com.ar](sites/directv.com.ar) | 🔴 | https://github.com/iptv-org/epg/issues/2248 |
|
||||
| [directv.com.uy](sites/directv.com.uy) | 🟢 | |
|
||||
| [dishtv.in](sites/dishtv.in) | 🟢 | |
|
||||
| [disneystar.com](sites/disneystar.com) | 🟢 | |
|
||||
| [dsmart.com.tr](sites/dsmart.com.tr) | 🟢 | |
|
||||
| [dstv.com](sites/dstv.com) | 🟢 | |
|
||||
| [elcinema.com](sites/elcinema.com) | 🟢 | |
|
||||
| [ena.skylifetv.co.kr](sites/ena.skylifetv.co.kr) | 🟢 | |
|
||||
| [energeek.cl](sites/energeek.cl) | 🟢 | |
|
||||
| [entertainment.ie](sites/entertainment.ie) | 🟢 | |
|
||||
| [epg.i-cable.com](sites/epg.i-cable.com) | 🔴 | https://github.com/iptv-org/epg/issues/2228 |
|
||||
| [firstmedia.com](sites/firstmedia.com) | 🟢 | |
|
||||
| [flixed.io](sites/flixed.io) | 🟢 | |
|
||||
| [foxsports.com.au](sites/foxsports.com.au) | 🟢 | |
|
||||
| [foxtel.com.au](sites/foxtel.com.au) | 🟢 | |
|
||||
| [frikanalen.no](sites/frikanalen.no) | 🟢 | |
|
||||
| [gatotv.com](sites/gatotv.com) | 🟢 | |
|
||||
| [getafteritmedia.com](sites/getafteritmedia.com) | 🟢 | |
|
||||
| [guida.tv](sites/guida.tv) | 🟢 | |
|
||||
| [guidatv.sky.it](sites/guidatv.sky.it) | 🟢 | |
|
||||
| [hd-plus.de](sites/hd-plus.de) | 🔴 | https://github.com/iptv-org/epg/issues/2173 |
|
||||
| [horizon.tv](sites/horizon.tv) | 🟢 | |
|
||||
| [i.mjh.nz](sites/i.mjh.nz) | 🟢 | |
|
||||
| [i24news.tv](sites/i24news.tv) | 🟢 | |
|
||||
| [iltalehti.fi](sites/iltalehti.fi) | 🟢 | |
|
||||
| [indihometv.com](sites/indihometv.com) | 🟢 | |
|
||||
| [ionplustv.com](sites/ionplustv.com) | 🟢 | |
|
||||
| [ipko.com](sites/ipko.com) | 🟢 | |
|
||||
| [kan.org.il](sites/kan.org.il) | 🔴 | https://github.com/iptv-org/epg/issues/2273 |
|
||||
| [knr.gl](sites/knr.gl) | 🟢 | |
|
||||
| [kplus.vn](sites/kplus.vn) | 🔴 | https://github.com/iptv-org/epg/issues/2240 |
|
||||
| [kvf.fo](sites/kvf.fo) | 🟢 | |
|
||||
| [m.tv.sms.cz](sites/m.tv.sms.cz) | 🔴 | https://github.com/iptv-org/epg/issues/2241 |
|
||||
| [m.tving.com](sites/m.tving.com) | 🟢 | |
|
||||
| [magticom.ge](sites/magticom.ge) | 🟢 | |
|
||||
| [mako.co.il](sites/mako.co.il) | 🟢 | |
|
||||
| [maxtv.hrvatskitelekom.hr](sites/maxtv.hrvatskitelekom.hr) | 🟢 | |
|
||||
| [maxtvgo.mk](sites/maxtvgo.mk) | 🟢 | |
|
||||
| [mediagenie.co.kr](sites/mediagenie.co.kr) | 🟢 | |
|
||||
| [mediaklikk.hu](sites/mediaklikk.hu) | 🟢 | |
|
||||
| [mediaset.it](sites/mediaset.it) | 🟢 | |
|
||||
| [melita.com](sites/melita.com) | 🟢 | |
|
||||
| [meo.pt](sites/meo.pt) | 🟢 | |
|
||||
| [meuguia.tv](sites/meuguia.tv) | 🟢 | |
|
||||
| [mewatch.sg](sites/mewatch.sg) | 🟢 | |
|
||||
| [mi.tv](sites/mi.tv) | 🟢 | |
|
||||
| [mncvision.id](sites/mncvision.id) | 🟢 | |
|
||||
| [moji.id](sites/moji.id) | 🟢 | |
|
||||
| [mon-programme-tv.be](sites/mon-programme-tv.be) | 🟢 | |
|
||||
| [movistarplus.es](sites/movistarplus.es) | 🟢 | |
|
||||
| [mtel.ba](sites/mtel.ba) | 🟢 | |
|
||||
| [mts.rs](sites/mts.rs) | 🟢 | |
|
||||
| [mujtvprogram.cz](sites/mujtvprogram.cz) | 🟢 | |
|
||||
| [musor.tv](sites/musor.tv) | 🟢 | |
|
||||
| [myafn.dodmedia.osd.mil](sites/myafn.dodmedia.osd.mil) | 🟢 | |
|
||||
| [mysky.com.ph](sites/mysky.com.ph) | 🟢 | |
|
||||
| [mytelly.co.uk](sites/mytelly.co.uk) | 🟢 | |
|
||||
| [mytvsuper.com](sites/mytvsuper.com) | 🟢 | |
|
||||
| [nhk.or.jp](sites/nhk.or.jp) | 🟢 | |
|
||||
| [nhkworldpremium.com](sites/nhkworldpremium.com) | 🟢 | |
|
||||
| [nos.pt](sites/nos.pt) | 🔴 | https://github.com/iptv-org/epg/issues/2183 |
|
||||
| [novacyprus.com](sites/novacyprus.com) | 🟢 | |
|
||||
| [novasports.gr](sites/novasports.gr) | 🟢 | |
|
||||
| [nowplayer.now.com](sites/nowplayer.now.com) | 🔴 | https://github.com/iptv-org/epg/issues/2247 |
|
||||
| [nuevosiglo.com.uy](sites/nuevosiglo.com.uy) | 🟢 | |
|
||||
| [nzxmltv.com](sites/nzxmltv.com) | 🟢 | |
|
||||
| [ontvtonight.com](sites/ontvtonight.com) | 🟢 | |
|
||||
| [osn.com](sites/osn.com) | 🟢 | |
|
||||
| [pbsguam.org](sites/pbsguam.org) | 🟢 | |
|
||||
| [playtv.unifi.com.my](sites/playtv.unifi.com.my) | 🟢 | |
|
||||
| [plex.tv](sites/plex.tv) | 🟢 | |
|
||||
| [programacion-tv.elpais.com](sites/programacion-tv.elpais.com) | 🟢 | |
|
||||
| [programacion.tcc.com.uy](sites/programacion.tcc.com.uy) | 🟢 | |
|
||||
| [programetv.ro](sites/programetv.ro) | 🟢 | |
|
||||
| [programme-tv.net](sites/programme-tv.net) | 🟢 | |
|
||||
| [programme-tv.vini.pf](sites/programme-tv.vini.pf) | 🟢 | |
|
||||
| [programme.tvb.com](sites/programme.tvb.com) | 🔴 | https://github.com/iptv-org/epg/issues/2254 |
|
||||
| [programtv.onet.pl](sites/programtv.onet.pl) | 🟢 | |
|
||||
| [proximusmwc.be](sites/proximusmwc.be) | 🔴 | https://github.com/iptv-org/epg/issues/2212 |
|
||||
| [raiplay.it](sites/raiplay.it) | 🟢 | |
|
||||
| [reportv.com.ar](sites/reportv.com.ar) | 🟢 | |
|
||||
| [rev.bs](sites/rev.bs) | 🔴 | https://github.com/iptv-org/epg/issues/2255 |
|
||||
| [rotana.net](sites/rotana.net) | 🔴 | https://github.com/iptv-org/epg/issues/2256 |
|
||||
| [rtb.gov.bn](sites/rtb.gov.bn) | 🔴 | https://github.com/iptv-org/epg/issues/2257 |
|
||||
| [rthk.hk](sites/rthk.hk) | 🟢 | |
|
||||
| [rtmklik.rtm.gov.my](sites/rtmklik.rtm.gov.my) | 🟢 | |
|
||||
| [rtp.pt](sites/rtp.pt) | 🟢 | |
|
||||
| [ruv.is](sites/ruv.is) | 🟢 | |
|
||||
| [sat.tv](sites/sat.tv) | 🟢 | |
|
||||
| [shahid.mbc.net](sites/shahid.mbc.net) | 🟢 | |
|
||||
| [siba.com.co](sites/siba.com.co) | 🟢 | |
|
||||
| [singtel.com](sites/singtel.com) | 🟢 | |
|
||||
| [sjonvarp.is](sites/sjonvarp.is) | 🟢 | |
|
||||
| [sky.co.nz](sites/sky.co.nz) | 🟢 | |
|
||||
| [sky.com](sites/sky.com) | 🟢 | |
|
||||
| [sky.de](sites/sky.de) | 🟢 | |
|
||||
| [starhubtvplus.com](sites/starhubtvplus.com) | 🟢 | |
|
||||
| [startimestv.com](sites/startimestv.com) | 🟢 | |
|
||||
| [streamingtvguides.com](sites/streamingtvguides.com) | 🟢 | |
|
||||
| [superguidatv.it](sites/superguidatv.it) | 🟢 | |
|
||||
| [taiwanplus.com](sites/taiwanplus.com) | 🟢 | |
|
||||
| [tapdmv.com](sites/tapdmv.com) | 🟢 | |
|
||||
| [telenet.tv](sites/telenet.tv) | 🟢 | |
|
||||
| [teliatv.ee](sites/teliatv.ee) | 🟢 | |
|
||||
| [telkussa.fi](sites/telkussa.fi) | 🟢 | |
|
||||
| [telsu.fi](sites/telsu.fi) | 🟢 | |
|
||||
| [tivu.tv](sites/tivu.tv) | 🟢 | |
|
||||
| [toonamiaftermath.com](sites/toonamiaftermath.com) | 🟢 | |
|
||||
| [turksatkablo.com.tr](sites/turksatkablo.com.tr) | 🟢 | |
|
||||
| [tv-programme.telecablesat.fr](sites/tv-programme.telecablesat.fr) | 🟢 | |
|
||||
| [tv.blue.ch](sites/tv.blue.ch) | 🟢 | |
|
||||
| [tv.cctv.com](sites/tv.cctv.com) | 🟢 | |
|
||||
| [tv.dir.bg](sites/tv.dir.bg) | 🟢 | |
|
||||
| [tv.lv](sites/tv.lv) | 🟢 | |
|
||||
| [tv.magenta.at](sites/tv.magenta.at) | 🟢 | |
|
||||
| [tv.mail.ru](sites/tv.mail.ru) | 🟢 | |
|
||||
| [tv.movistar.com.pe](sites/tv.movistar.com.pe) | 🟢 | |
|
||||
| [tv.nu](sites/tv.nu) | 🟢 | |
|
||||
| [tv.post.lu](sites/tv.post.lu) | 🟢 | |
|
||||
| [tv.trueid.net](sites/tv.trueid.net) | 🔴 | https://github.com/iptv-org/epg/issues/2164 |
|
||||
| [tv.yandex.ru](sites/tv.yandex.ru) | 🟢 | |
|
||||
| [tv.yettel.hu](sites/tv.yettel.hu) | 🔴 | https://github.com/iptv-org/epg/issues/2263 |
|
||||
| [tv2go.t-2.net](sites/tv2go.t-2.net) | 🟢 | |
|
||||
| [tv24.co.uk](sites/tv24.co.uk) | 🟢 | |
|
||||
| [tv24.se](sites/tv24.se) | 🟢 | |
|
||||
| [tva.tv](sites/tva.tv) | 🔴 | https://github.com/iptv-org/epg/issues/2264 |
|
||||
| [tvarenasport.com](sites/tvarenasport.com) | 🔴 | https://github.com/iptv-org/epg/issues/2266 |
|
||||
| [tvarenasport.hr](sites/tvarenasport.hr) | 🔴 | https://github.com/iptv-org/epg/issues/2267 |
|
||||
| [tvcesoir.fr](sites/tvcesoir.fr) | 🟢 | |
|
||||
| [tvcubana.icrt.cu](sites/tvcubana.icrt.cu) | 🟢 | |
|
||||
| [tvgids.nl](sites/tvgids.nl) | 🟢 | |
|
||||
| [tvguide.com](sites/tvguide.com) | 🟢 | |
|
||||
| [tvguide.myjcom.jp](sites/tvguide.myjcom.jp) | 🟢 | |
|
||||
| [tvhebdo.com](sites/tvhebdo.com) | 🟢 | |
|
||||
| [tvheute.at](sites/tvheute.at) | 🟢 | |
|
||||
| [tvim.tv](sites/tvim.tv) | 🟢 | |
|
||||
| [tvireland.ie](sites/tvireland.ie) | 🟢 | |
|
||||
| [tvmi.mt](sites/tvmi.mt) | 🟢 | |
|
||||
| [tvmusor.hu](sites/tvmusor.hu) | 🟢 | |
|
||||
| [tvpassport.com](sites/tvpassport.com) | 🟢 | |
|
||||
| [tvplus.com.tr](sites/tvplus.com.tr) | 🟢 | |
|
||||
| [tvprofil.com](sites/tvprofil.com) | 🟢 | |
|
||||
| [tvtv.us](sites/tvtv.us) | 🔴 | https://github.com/iptv-org/epg/issues/2176 |
|
||||
| [vidio.com](sites/vidio.com) | 🟢 | |
|
||||
| [virginmediatelevision.ie](sites/virginmediatelevision.ie) | 🟢 | |
|
||||
| [virgintvgo.virginmedia.com](sites/virgintvgo.virginmedia.com) | 🟢 | |
|
||||
| [visionplus.id](sites/visionplus.id) | 🟢 | |
|
||||
| [vivacom.bg](sites/vivacom.bg) | 🔴 | https://github.com/iptv-org/epg/issues/2270 |
|
||||
| [vtm.be](sites/vtm.be) | 🟢 | |
|
||||
| [walesi.com.fj](sites/walesi.com.fj) | 🟢 | |
|
||||
| [watch.sportsnet.ca](sites/watch.sportsnet.ca) | 🟢 | |
|
||||
| [watchyour.tv](sites/watchyour.tv) | 🟢 | |
|
||||
| [wavve.com](sites/wavve.com) | 🟢 | |
|
||||
| [web.magentatv.de](sites/web.magentatv.de) | 🟢 | |
|
||||
| [webtv.delta.nl](sites/webtv.delta.nl) | 🟢 | |
|
||||
| [worldfishingnetwork.com](sites/worldfishingnetwork.com) | 🟢 | |
|
||||
| [xumo.tv](sites/xumo.tv) | 🟢 | |
|
||||
| [zap.co.ao](sites/zap.co.ao) | 🟢 | |
|
||||
| [ziggogo.tv](sites/ziggogo.tv) | 🟢 | |
|
||||
| [znbc.co.zm](sites/znbc.co.zm) | 🟢 | |
|
||||
| [zuragt.mn](sites/zuragt.mn) | 🟢 | |
|
||||
# Sites
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th align="left">Site</th><th align="left" colspan="2">Channels<br>(total / with xmltv-id)</th><th align="left">Status</th><th align="left">Notes</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td><a href="sites/9tv.co.il">9tv.co.il</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/abc.net.au">abc.net.au</a></td><td align="right">548</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/allente.dk">allente.dk</a></td><td align="right">74</td><td align="right">44</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/allente.fi">allente.fi</a></td><td align="right">71</td><td align="right">25</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/allente.no">allente.no</a></td><td align="right">84</td><td align="right">53</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/allente.se">allente.se</a></td><td align="right">92</td><td align="right">92</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/andorradifusio.ad">andorradifusio.ad</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/anteltv.com.uy">anteltv.com.uy</a></td><td align="right">53</td><td align="right">47</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/antennaeurope.gr">antennaeurope.gr</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/antennapacific.gr">antennapacific.gr</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/antennasatellite.gr">antennasatellite.gr</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/arianaafgtv.com">arianaafgtv.com</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/arianatelevision.com">arianatelevision.com</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/arirang.com">arirang.com</a></td><td align="right">3</td><td align="right">3</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/artonline.tv">artonline.tv</a></td><td align="right">5</td><td align="right">5</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/awilime.com">awilime.com</a></td><td align="right">111</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/bein.com">bein.com</a></td><td align="right">160</td><td align="right">160</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/beinsports.com">beinsports.com</a></td><td align="right">104</td><td align="right">81</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/berrymedia.co.kr">berrymedia.co.kr</a></td><td align="right">5</td><td align="right">5</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cableplus.com.uy">cableplus.com.uy</a></td><td align="right">171</td><td align="right">47</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/canalplus.com">canalplus.com</a></td><td align="right">11720</td><td align="right">212</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cgates.lt">cgates.lt</a></td><td align="right">102</td><td align="right">61</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/chada.ma">chada.ma</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/chaines-tv.orange.fr">chaines-tv.orange.fr</a></td><td align="right">296</td><td align="right">147</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/clickthecity.com">clickthecity.com</a></td><td align="right">32</td><td align="right">30</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/content.astro.com.my">content.astro.com.my</a></td><td align="right">157</td><td align="right">112</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cosmotetv.gr">cosmotetv.gr</a></td><td align="right">108</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cubmu.com">cubmu.com</a></td><td align="right">174</td><td align="right">122</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cyta.com.cy">cyta.com.cy</a></td><td align="right">116</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/dens.tv">dens.tv</a></td><td align="right">67</td><td align="right">64</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/digea.gr">digea.gr</a></td><td align="right">92</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/digiturk.com.tr">digiturk.com.tr</a></td><td align="right">108</td><td align="right">107</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/directv.com">directv.com</a></td><td align="right">1043</td><td align="right">698</td><td align="center">🔴</td><td>https://github.com/iptv-org/epg/issues/2284</td></tr>
|
||||
<tr><td><a href="sites/directv.com.ar">directv.com.ar</a></td><td align="right">412</td><td align="right">229</td><td align="center">🔴</td><td>https://github.com/iptv-org/epg/issues/2339</td></tr>
|
||||
<tr><td><a href="sites/directv.com.uy">directv.com.uy</a></td><td align="right">143</td><td align="right">142</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/dishtv.in">dishtv.in</a></td><td align="right">448</td><td align="right">89</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/dna.fi">dna.fi</a></td><td align="right">122</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/dsmart.com.tr">dsmart.com.tr</a></td><td align="right">104</td><td align="right">90</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/dstv.com">dstv.com</a></td><td align="right">6983</td><td align="right">181</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/dtv8.net">dtv8.net</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/elcinema.com">elcinema.com</a></td><td align="right">262</td><td align="right">226</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/ena.skylifetv.co.kr">ena.skylifetv.co.kr</a></td><td align="right">6</td><td align="right">6</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/energeek.cl">energeek.cl</a></td><td align="right">6</td><td align="right">3</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/entertainment.ie">entertainment.ie</a></td><td align="right">109</td><td align="right">95</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/epg.112114.xyz">epg.112114.xyz</a></td><td align="right">930</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/epg.iptvx.one">epg.iptvx.one</a></td><td align="right">2862</td><td align="right">747</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/epg.telemach.ba">epg.telemach.ba</a></td><td align="right">259</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/epg.telemach.me">epg.telemach.me</a></td><td align="right">216</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/epgshare01.online">epgshare01.online</a></td><td align="right">20970</td><td align="right">17</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/firstmedia.com">firstmedia.com</a></td><td align="right">116</td><td align="right">101</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/foxsports.com.au">foxsports.com.au</a></td><td align="right">7</td><td align="right">7</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/foxtel.com.au">foxtel.com.au</a></td><td align="right">155</td><td align="right">87</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/freetv.tv">freetv.tv</a></td><td align="right">7</td><td align="right">7</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/freeview.co.uk">freeview.co.uk</a></td><td align="right">171</td><td align="right">101</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/frikanalen.no">frikanalen.no</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/galamtv.kz">galamtv.kz</a></td><td align="right">27</td><td align="right">22</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/gatotv.com">gatotv.com</a></td><td align="right">475</td><td align="right">362</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/getafteritmedia.com">getafteritmedia.com</a></td><td align="right">5</td><td align="right">5</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/gigatv.3bbtv.co.th">gigatv.3bbtv.co.th</a></td><td align="right">79</td><td align="right">38</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/guiadetv.com">guiadetv.com</a></td><td align="right">124</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/guida.tv">guida.tv</a></td><td align="right">88</td><td align="right">88</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/guidatv.sky.it">guidatv.sky.it</a></td><td align="right">168</td><td align="right">153</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/horizon.tv">horizon.tv</a></td><td align="right">184</td><td align="right">172</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/hoy.tv">hoy.tv</a></td><td align="right">3</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/i.mjh.nz">i.mjh.nz</a></td><td align="right">6458</td><td align="right">1489</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/i24news.tv">i24news.tv</a></td><td align="right">4</td><td align="right">3</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/iltalehti.fi">iltalehti.fi</a></td><td align="right">142</td><td align="right">44</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/indihometv.com">indihometv.com</a></td><td align="right">130</td><td align="right">124</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/ionplustv.com">ionplustv.com</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/ipko.tv">ipko.tv</a></td><td align="right">194</td><td align="right">152</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/jiotv.com">jiotv.com</a></td><td align="right">1094</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/kan.org.il">kan.org.il</a></td><td align="right">3</td><td align="right">3</td><td align="center">🔴</td><td>https://github.com/iptv-org/epg/issues/2273</td></tr>
|
||||
<tr><td><a href="sites/knr.gl">knr.gl</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/kvf.fo">kvf.fo</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/m.tv.sms.cz">m.tv.sms.cz</a></td><td align="right">1027</td><td align="right">451</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/m.tving.com">m.tving.com</a></td><td align="right">30</td><td align="right">26</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/magticom.ge">magticom.ge</a></td><td align="right">240</td><td align="right">110</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mako.co.il">mako.co.il</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/makrodigitaltelevision.com">makrodigitaltelevision.com</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/maxtvgo.mk">maxtvgo.mk</a></td><td align="right">110</td><td align="right">48</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mediagenie.co.kr">mediagenie.co.kr</a></td><td align="right">5</td><td align="right">4</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mediaklikk.hu">mediaklikk.hu</a></td><td align="right">8</td><td align="right">8</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mediasetinfinity.mediaset.it">mediasetinfinity.mediaset.it</a></td><td align="right">13</td><td align="right">13</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/melita.com">melita.com</a></td><td align="right">127</td><td align="right">111</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/meo.pt">meo.pt</a></td><td align="right">216</td><td align="right">192</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/meuguia.tv">meuguia.tv</a></td><td align="right">102</td><td align="right">97</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mewatch.sg">mewatch.sg</a></td><td align="right">25</td><td align="right">24</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mi.tv">mi.tv</a></td><td align="right">2084</td><td align="right">620</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mncvision.id">mncvision.id</a></td><td align="right">276</td><td align="right">223</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/moji.id">moji.id</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mojmaxtv.hrvatskitelekom.hr">mojmaxtv.hrvatskitelekom.hr</a></td><td align="right">243</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mon-programme-tv.be">mon-programme-tv.be</a></td><td align="right">111</td><td align="right">95</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/movistarplus.es">movistarplus.es</a></td><td align="right">178</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mtel.ba">mtel.ba</a></td><td align="right">501</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mts.rs">mts.rs</a></td><td align="right">457</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mujtvprogram.cz">mujtvprogram.cz</a></td><td align="right">216</td><td align="right">203</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/musor.tv">musor.tv</a></td><td align="right">181</td><td align="right">146</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mysky.com.ph">mysky.com.ph</a></td><td align="right">115</td><td align="right">43</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mytelly.co.uk">mytelly.co.uk</a></td><td align="right">488</td><td align="right">401</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mytvsuper.com">mytvsuper.com</a></td><td align="right">108</td><td align="right">99</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/neo.io">neo.io</a></td><td align="right">337</td><td align="right">241</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/nhkworldpremium.com">nhkworldpremium.com</a></td><td align="right">2</td><td align="right">2</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/nhl.com">nhl.com</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/nostv.pt">nostv.pt</a></td><td align="right">168</td><td align="right">155</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/novacyprus.com">novacyprus.com</a></td><td align="right">29</td><td align="right">24</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/novasports.gr">novasports.gr</a></td><td align="right">16</td><td align="right">16</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/nowplayer.now.com">nowplayer.now.com</a></td><td align="right">288</td><td align="right">229</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/nuevosiglo.com.uy">nuevosiglo.com.uy</a></td><td align="right">173</td><td align="right">47</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/nzxmltv.com">nzxmltv.com</a></td><td align="right">532</td><td align="right">118</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/ontvtonight.com">ontvtonight.com</a></td><td align="right">5177</td><td align="right">532</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/opto.sic.pt">opto.sic.pt</a></td><td align="right">4</td><td align="right">4</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/orangetv.orange.es">orangetv.orange.es</a></td><td align="right">168</td><td align="right">165</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/osn.com">osn.com</a></td><td align="right">118</td><td align="right">98</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/pbsguam.org">pbsguam.org</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/pickx.be">pickx.be</a></td><td align="right">404</td><td align="right">391</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/player.ee.co.uk">player.ee.co.uk</a></td><td align="right">241</td><td align="right">206</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/playtv.unifi.com.my">playtv.unifi.com.my</a></td><td align="right">66</td><td align="right">61</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/plex.tv">plex.tv</a></td><td align="right">170</td><td align="right">119</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/pluto.tv">pluto.tv</a></td><td align="right">3302</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programacion-tv.elpais.com">programacion-tv.elpais.com</a></td><td align="right">195</td><td align="right">105</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programacion.tcc.com.uy">programacion.tcc.com.uy</a></td><td align="right">149</td><td align="right">56</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programetv.ro">programetv.ro</a></td><td align="right">331</td><td align="right">225</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programme-tv.net">programme-tv.net</a></td><td align="right">295</td><td align="right">197</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programme-tv.vini.pf">programme-tv.vini.pf</a></td><td align="right">58</td><td align="right">2</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programme.tvb.com">programme.tvb.com</a></td><td align="right">8</td><td align="right">6</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programtv.onet.pl">programtv.onet.pl</a></td><td align="right">590</td><td align="right">363</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/raiplay.it">raiplay.it</a></td><td align="right">17</td><td align="right">13</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/reportv.com.ar">reportv.com.ar</a></td><td align="right">163</td><td align="right">97</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/rikstv.no">rikstv.no</a></td><td align="right">80</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/rotana.net">rotana.net</a></td><td align="right">32</td><td align="right">28</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/rtb.gov.bn">rtb.gov.bn</a></td><td align="right">3</td><td align="right">3</td><td align="center">🔴</td><td>https://github.com/iptv-org/epg/issues/2257</td></tr>
|
||||
<tr><td><a href="sites/rthk.hk">rthk.hk</a></td><td align="right">8</td><td align="right">8</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/rtmklik.rtm.gov.my">rtmklik.rtm.gov.my</a></td><td align="right">8</td><td align="right">6</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/rtp.pt">rtp.pt</a></td><td align="right">10</td><td align="right">10</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/ruv.is">ruv.is</a></td><td align="right">2</td><td align="right">2</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/s.mxtv.jp">s.mxtv.jp</a></td><td align="right">2</td><td align="right">2</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/sat.tv">sat.tv</a></td><td align="right">31173</td><td align="right">277</td><td align="center">🔴</td><td>https://github.com/iptv-org/epg/issues/2685</td></tr>
|
||||
<tr><td><a href="sites/shahid.mbc.net">shahid.mbc.net</a></td><td align="right">231</td><td align="right">165</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/siba.com.co">siba.com.co</a></td><td align="right">98</td><td align="right">96</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/singtel.com">singtel.com</a></td><td align="right">155</td><td align="right">113</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/sjonvarp.is">sjonvarp.is</a></td><td align="right">13</td><td align="right">13</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/sky.co.nz">sky.co.nz</a></td><td align="right">111</td><td align="right">93</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/sky.com">sky.com</a></td><td align="right">532</td><td align="right">433</td><td align="center">🟢</td><td>https://github.com/iptv-org/epg/issues/2763</td></tr>
|
||||
<tr><td><a href="sites/sky.de">sky.de</a></td><td align="right">75</td><td align="right">75</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/skylife.co.kr">skylife.co.kr</a></td><td align="right">251</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/skyperfectv.co.jp">skyperfectv.co.jp</a></td><td align="right">137</td><td align="right">130</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/snrt.ma">snrt.ma</a></td><td align="right">11</td><td align="right">7</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/sporttv.pt">sporttv.pt</a></td><td align="right">9</td><td align="right">8</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/starhubtvplus.com">starhubtvplus.com</a></td><td align="right">232</td><td align="right">208</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/startimestv.com">startimestv.com</a></td><td align="right">77</td><td align="right">58</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/stod2.is">stod2.is</a></td><td align="right">12</td><td align="right">8</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/streamingtvguides.com">streamingtvguides.com</a></td><td align="right">3066</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/superguidatv.it">superguidatv.it</a></td><td align="right">204</td><td align="right">163</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/taiwanplus.com">taiwanplus.com</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tapdmv.com">tapdmv.com</a></td><td align="right">39</td><td align="right">7</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/telebilbao.es">telebilbao.es</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/teleboy.ch">teleboy.ch</a></td><td align="right">325</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/telenet.tv">telenet.tv</a></td><td align="right">260</td><td align="right">91</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/teliatv.ee">teliatv.ee</a></td><td align="right">342</td><td align="right">233</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/telkussa.fi">telkussa.fi</a></td><td align="right">66</td><td align="right">32</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/telsu.fi">telsu.fi</a></td><td align="right">17</td><td align="right">15</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/thesportplus.com">thesportplus.com</a></td><td align="right">3</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tivie.id">tivie.id</a></td><td align="right">50</td><td align="right">49</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tivu.tv">tivu.tv</a></td><td align="right">69</td><td align="right">66</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/toonamiaftermath.com">toonamiaftermath.com</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/turksatkablo.com.tr">turksatkablo.com.tr</a></td><td align="right">175</td><td align="right">167</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv-programme.telecablesat.fr">tv-programme.telecablesat.fr</a></td><td align="right">268</td><td align="right">250</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv-spored.siol.net">tv-spored.siol.net</a></td><td align="right">312</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.blue.ch">tv.blue.ch</a></td><td align="right">1030</td><td align="right">565</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.cctv.com">tv.cctv.com</a></td><td align="right">94</td><td align="right">88</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.dir.bg">tv.dir.bg</a></td><td align="right">111</td><td align="right">96</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.lv">tv.lv</a></td><td align="right">137</td><td align="right">49</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.magenta.at">tv.magenta.at</a></td><td align="right">307</td><td align="right">228</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.mail.ru">tv.mail.ru</a></td><td align="right">664</td><td align="right">644</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.movistar.com.pe">tv.movistar.com.pe</a></td><td align="right">282</td><td align="right">40</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.nu">tv.nu</a></td><td align="right">199</td><td align="right">181</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.post.lu">tv.post.lu</a></td><td align="right">332</td><td align="right">242</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.sfr.fr">tv.sfr.fr</a></td><td align="right">503</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.trueid.net">tv.trueid.net</a></td><td align="right">266</td><td align="right">74</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.yandex.ru">tv.yandex.ru</a></td><td align="right">97</td><td align="right">67</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv24.co.uk">tv24.co.uk</a></td><td align="right">1072</td><td align="right">39</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv24.se">tv24.se</a></td><td align="right">326</td><td align="right">157</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv2go.t-2.net">tv2go.t-2.net</a></td><td align="right">335</td><td align="right">254</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvarenasport.com">tvarenasport.com</a></td><td align="right">14</td><td align="right">12</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvarenasport.hr">tvarenasport.hr</a></td><td align="right">10</td><td align="right">10</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvcesoir.fr">tvcesoir.fr</a></td><td align="right">135</td><td align="right">133</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvcubana.icrt.cu">tvcubana.icrt.cu</a></td><td align="right">10</td><td align="right">10</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvgids.nl">tvgids.nl</a></td><td align="right">115</td><td align="right">90</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvguide.com">tvguide.com</a></td><td align="right">153</td><td align="right">150</td><td align="center">🟡</td><td>https://github.com/iptv-org/epg/issues/2644</td></tr>
|
||||
<tr><td><a href="sites/tvguide.myjcom.jp">tvguide.myjcom.jp</a></td><td align="right">145</td><td align="right">140</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvhebdo.com">tvhebdo.com</a></td><td align="right">317</td><td align="right">215</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvheute.at">tvheute.at</a></td><td align="right">53</td><td align="right">53</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvi.iol.pt">tvi.iol.pt</a></td><td align="right">6</td><td align="right">6</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvim.tv">tvim.tv</a></td><td align="right">25</td><td align="right">19</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvinsider.com">tvinsider.com</a></td><td align="right">374</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvireland.ie">tvireland.ie</a></td><td align="right">334</td><td align="right">304</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvkaista.org">tvkaista.org</a></td><td align="right">149</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvmi.mt">tvmi.mt</a></td><td align="right">3</td><td align="right">3</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvmusor.hu">tvmusor.hu</a></td><td align="right">99</td><td align="right">68</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvmustra.hu">tvmustra.hu</a></td><td align="right">188</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvpassport.com">tvpassport.com</a></td><td align="right">19287</td><td align="right">2511</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvplus.com.tr">tvplus.com.tr</a></td><td align="right">143</td><td align="right">134</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvprofil.com">tvprofil.com</a></td><td align="right">5836</td><td align="right">457</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvtv.us">tvtv.us</a></td><td align="right">2299</td><td align="right">2256</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/v3.myafn.dodmedia.osd.mil">v3.myafn.dodmedia.osd.mil</a></td><td align="right">8</td><td align="right">8</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/vidio.com">vidio.com</a></td><td align="right">47</td><td align="right">46</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/virginmediatelevision.ie">virginmediatelevision.ie</a></td><td align="right">5</td><td align="right">5</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/virgintvgo.virginmedia.com">virgintvgo.virginmedia.com</a></td><td align="right">238</td><td align="right">195</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/visionplus.id">visionplus.id</a></td><td align="right">250</td><td align="right">226</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/vivoplay.com.br">vivoplay.com.br</a></td><td align="right">389</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/vtm.be">vtm.be</a></td><td align="right">7</td><td align="right">6</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/walesi.com.fj">walesi.com.fj</a></td><td align="right">9</td><td align="right">8</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/watch.sportsnet.ca">watch.sportsnet.ca</a></td><td align="right">8</td><td align="right">8</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/watchyour.tv">watchyour.tv</a></td><td align="right">40</td><td align="right">24</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/wavve.com">wavve.com</a></td><td align="right">77</td><td align="right">76</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/web.magentatv.de">web.magentatv.de</a></td><td align="right">348</td><td align="right">247</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/webtv.delta.nl">webtv.delta.nl</a></td><td align="right">247</td><td align="right">218</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/winplay.co">winplay.co</a></td><td align="right">2</td><td align="right">2</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/worldfishingnetwork.com">worldfishingnetwork.com</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/www3.nhk.or.jp">www3.nhk.or.jp</a></td><td align="right">1</td><td align="right">1</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/xem.kplus.vn">xem.kplus.vn</a></td><td align="right">77</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/xumo.tv">xumo.tv</a></td><td align="right">350</td><td align="right">33</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/yes.co.il">yes.co.il</a></td><td align="right">174</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/zap.co.ao">zap.co.ao</a></td><td align="right">114</td><td align="right">64</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/zap2it.com">zap2it.com</a></td><td align="right">595</td><td align="right">0</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/ziggogo.tv">ziggogo.tv</a></td><td align="right">152</td><td align="right">130</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/znbc.co.zm">znbc.co.zm</a></td><td align="right">4</td><td align="right">4</td><td align="center">🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/zuragt.mn">zuragt.mn</a></td><td align="right">36</td><td align="right">25</td><td align="center">🟢</td><td></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
55
eslint.config.mjs
Normal file
55
eslint.config.mjs
Normal file
|
@ -0,0 +1,55 @@
|
|||
import typescriptEslint from '@typescript-eslint/eslint-plugin'
|
||||
import globals from 'globals'
|
||||
import tsParser from '@typescript-eslint/parser'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import js from '@eslint/js'
|
||||
import { FlatCompat } from '@eslint/eslintrc'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
recommendedConfig: js.configs.recommended,
|
||||
allConfig: js.configs.all
|
||||
})
|
||||
|
||||
export default [
|
||||
...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'),
|
||||
{
|
||||
plugins: {
|
||||
'@typescript-eslint': typescriptEslint
|
||||
},
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.jest
|
||||
},
|
||||
|
||||
parser: tsParser,
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module'
|
||||
},
|
||||
|
||||
rules: {
|
||||
'@typescript-eslint/no-require-imports': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'no-case-declarations': 'off',
|
||||
'linebreak-style': ['error', 'windows'],
|
||||
|
||||
quotes: [
|
||||
'error',
|
||||
'single',
|
||||
{
|
||||
avoidEscape: true
|
||||
}
|
||||
],
|
||||
|
||||
semi: ['error', 'never']
|
||||
}
|
||||
},
|
||||
{
|
||||
ignores: ['tests/__data__/']
|
||||
}
|
||||
]
|
7488
package-lock.json
generated
7488
package-lock.json
generated
File diff suppressed because it is too large
Load diff
81
package.json
81
package.json
|
@ -1,36 +1,55 @@
|
|||
{
|
||||
"name": "epg",
|
||||
"scripts": {
|
||||
"act:check": "act pull_request -W .github/workflows/check.yml",
|
||||
"act:update": "act workflow_dispatch -W .github/workflows/update.yml",
|
||||
"api:load": "npx tsx scripts/commands/api/load.ts",
|
||||
"api:generate": "npx tsx scripts/commands/api/generate.ts",
|
||||
"channels:lint": "npx tsx scripts/commands/channels/lint.ts",
|
||||
"channels:lint": "npx tsx scripts/commands/channels/lint.mts",
|
||||
"channels:parse": "npx tsx scripts/commands/channels/parse.ts",
|
||||
"channels:editor": "npx tsx scripts/commands/channels/editor.ts",
|
||||
"channels:edit": "npx tsx scripts/commands/channels/edit.ts",
|
||||
"channels:validate": "npx tsx scripts/commands/channels/validate.ts",
|
||||
"sites:init": "npx tsx scripts/commands/sites/init.ts",
|
||||
"sites:update": "npx tsx scripts/commands/sites/update.ts",
|
||||
"grab": "npx tsx scripts/commands/epg/grab.ts",
|
||||
"serve": "npx serve",
|
||||
"lint": "npx eslint \"{scripts,tests}/**/*.{ts,js}\"",
|
||||
"lint": "npx eslint \"{scripts,tests,sites}/**/*.{ts,mts,js}\"",
|
||||
"test": "run-script-os",
|
||||
"test:win32": "SET \"TZ=Pacific/Nauru\" && npx jest --runInBand",
|
||||
"test:default": "TZ=Pacific/Nauru npx jest --runInBand",
|
||||
"postinstall": "npm run api:load"
|
||||
"postinstall": "skip-postinstall || npm run api:load",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"private": true,
|
||||
"author": "Arhey",
|
||||
"license": "MIT",
|
||||
"license": "UNLICENSED",
|
||||
"jest": {
|
||||
"setupFiles": [
|
||||
"<rootDir>/node_modules/jest-offline"
|
||||
],
|
||||
"transform": {
|
||||
"^.+\\.(ts|js)$": "ts-jest"
|
||||
"^.+\\.(ts|js)$": "@swc/jest"
|
||||
},
|
||||
"testRegex": "(tests|sites)/(.*?/)?.*test.(js|ts)$",
|
||||
"testTimeout": 10000
|
||||
"testMatch": [
|
||||
"<rootDir>/sites/**/*.test.(js|ts)",
|
||||
"<rootDir>/tests/commands/**/*.test.(js|ts)"
|
||||
],
|
||||
"testTimeout": 10000,
|
||||
"transformIgnorePatterns": [
|
||||
"<rootDir>/node_modules/(?!parse-duration/.*)"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@alex_neo/jest-expect-message": "^1.0.5",
|
||||
"@freearhey/core": "^0.3.1",
|
||||
"@freearhey/search-js": "^0.1.1",
|
||||
"@octokit/core": "^4.1.0",
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.17.0",
|
||||
"@freearhey/core": "^0.7.0",
|
||||
"@freearhey/search-js": "^0.1.2",
|
||||
"@ntlab/sfetch": "^1.2.0",
|
||||
"@octokit/core": "^6.1.3",
|
||||
"@octokit/plugin-paginate-rest": "^11.3.6",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^13.2.6",
|
||||
"@swc/core": "^1.10.4",
|
||||
"@swc/jest": "^0.2.37",
|
||||
"@types/cli-progress": "^3.11.3",
|
||||
"@types/fs-extra": "^11.0.2",
|
||||
"@types/inquirer": "^9.0.3",
|
||||
|
@ -38,53 +57,57 @@
|
|||
"@types/lodash": "^4.14.199",
|
||||
"@types/node-cleanup": "^2.1.2",
|
||||
"@types/numeral": "^2.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.3",
|
||||
"@typescript-eslint/eslint-plugin": "^8.18.0",
|
||||
"@typescript-eslint/parser": "^8.20.0",
|
||||
"axios": "^1.5.1",
|
||||
"axios-cookiejar-support": "^4.0.7",
|
||||
"axios-cookiejar-support": "^5.0.4",
|
||||
"chalk": "^4.1.2",
|
||||
"cheerio": "^1.0.0-rc.10",
|
||||
"cli-progress": "^3.12.0",
|
||||
"commander": "^8.2.0",
|
||||
"consola": "^3.2.3",
|
||||
"cron": "^2.4.3",
|
||||
"csv-parser": "^3.0.0",
|
||||
"cwait": "^1.1.2",
|
||||
"dayjs": "^1.11.10",
|
||||
"epg-grabber": "^0.36.1",
|
||||
"epg-parser": "^0.2.0",
|
||||
"eslint": "^8.17.0",
|
||||
"epg-grabber": "^0.38.0",
|
||||
"epg-parser": "^0.3.1",
|
||||
"eslint": "^9.17.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"form-data": "^4.0.0",
|
||||
"fs-extra": "^10.0.1",
|
||||
"glob": "^7.2.0",
|
||||
"globals": "^15.14.0",
|
||||
"husky": "^9.1.7",
|
||||
"iconv-lite": "^0.4.24",
|
||||
"inquirer": "^8.2.6",
|
||||
"inquirer": "^12.5.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-offline": "^1.0.1",
|
||||
"langs": "^2.0.0",
|
||||
"libxmljs2": "^0.33.0",
|
||||
"libxml2-wasm": "^0.5.0",
|
||||
"lodash": "^4.17.21",
|
||||
"luxon": "^3.3.0",
|
||||
"markdown-include": "^0.4.3",
|
||||
"mockdate": "^3.0.5",
|
||||
"nedb-promises": "^6.0.3",
|
||||
"node-cleanup": "^2.1.2",
|
||||
"node-gzip": "^1.1.2",
|
||||
"numeral": "^2.0.6",
|
||||
"parse-duration": "^1.0.0",
|
||||
"pako": "^2.1.0",
|
||||
"parse-duration": "^2.1.3",
|
||||
"pdf-parse": "^1.1.1",
|
||||
"serve": "^14.2.0",
|
||||
"pm2": "^5.4.3",
|
||||
"readline": "^1.3.0",
|
||||
"run-script-os": "^1.1.6",
|
||||
"serve": "^14.2.4",
|
||||
"signale": "^1.4.0",
|
||||
"skip-postinstall": "^1.0.0",
|
||||
"socks-proxy-agent": "^8.0.5",
|
||||
"srcset": "^4.0.0",
|
||||
"table2array": "^0.0.2",
|
||||
"tabletojson": "^2.0.7",
|
||||
"tough-cookie": "^4.1.3",
|
||||
"tough-cookie": "^5.0.0",
|
||||
"transliteration": "^2.2.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"tsx": "^3.13.0",
|
||||
"tsx": "^4.19.2",
|
||||
"unzipit": "^1.4.0",
|
||||
"wildcard-match": "^5.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"run-script-os": "^1.1.6"
|
||||
}
|
||||
}
|
||||
|
|
23
pm2.config.js
Normal file
23
pm2.config.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: 'serve',
|
||||
script: 'npx serve -- public',
|
||||
instances: 1,
|
||||
watch: false,
|
||||
autorestart: true
|
||||
},
|
||||
{
|
||||
name: 'grab',
|
||||
script: process.env.SITE
|
||||
? `npm run grab -- --site=${process.env.SITE} ${
|
||||
process.env.CLANG ? `--lang=${process.env.CLANG}` : ''
|
||||
} --output=public/guide.xml`
|
||||
: 'npm run grab -- --channels=channels.xml --output=public/guide.xml',
|
||||
cron_restart: process.env.CRON || null,
|
||||
instances: 1,
|
||||
watch: false,
|
||||
autorestart: false
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,51 +1,56 @@
|
|||
import { Logger, Storage, Collection } from '@freearhey/core'
|
||||
import { ChannelsParser } from '../../core'
|
||||
import path from 'path'
|
||||
import { SITES_DIR, API_DIR } from '../../constants'
|
||||
import { Channel } from 'epg-grabber'
|
||||
|
||||
type OutputItem = {
|
||||
channel: string | null
|
||||
site: string
|
||||
site_id: string
|
||||
site_name: string
|
||||
lang: string
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const logger = new Logger()
|
||||
|
||||
logger.start('staring...')
|
||||
|
||||
logger.info('loading channels...')
|
||||
const sitesStorage = new Storage(SITES_DIR)
|
||||
const parser = new ChannelsParser({ storage: sitesStorage })
|
||||
|
||||
let files: string[] = []
|
||||
files = await sitesStorage.list('**/*.channels.xml')
|
||||
|
||||
let parsedChannels = new Collection()
|
||||
for (const filepath of files) {
|
||||
parsedChannels = parsedChannels.concat(await parser.parse(filepath))
|
||||
}
|
||||
|
||||
logger.info(` found ${parsedChannels.count()} channel(s)`)
|
||||
|
||||
const output = parsedChannels.map((channel: Channel): OutputItem => {
|
||||
return {
|
||||
channel: channel.xmltv_id || null,
|
||||
site: channel.site || '',
|
||||
site_id: channel.site_id || '',
|
||||
site_name: channel.name,
|
||||
lang: channel.lang || ''
|
||||
}
|
||||
})
|
||||
|
||||
const apiStorage = new Storage(API_DIR)
|
||||
const outputFilename = 'guides.json'
|
||||
await apiStorage.save('guides.json', output.toJSON())
|
||||
|
||||
logger.info(`saved to "${path.join(API_DIR, outputFilename)}"`)
|
||||
}
|
||||
|
||||
main()
|
||||
import { Logger, Storage, Collection } from '@freearhey/core'
|
||||
import { ChannelsParser } from '../../core'
|
||||
import path from 'path'
|
||||
import { SITES_DIR, API_DIR } from '../../constants'
|
||||
import epgGrabber from 'epg-grabber'
|
||||
|
||||
type OutputItem = {
|
||||
channel: string | null
|
||||
feed: string | null
|
||||
site: string
|
||||
site_id: string
|
||||
site_name: string
|
||||
lang: string
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const logger = new Logger()
|
||||
|
||||
logger.start('staring...')
|
||||
|
||||
logger.info('loading channels...')
|
||||
const sitesStorage = new Storage(SITES_DIR)
|
||||
const parser = new ChannelsParser({ storage: sitesStorage })
|
||||
|
||||
let files: string[] = []
|
||||
files = await sitesStorage.list('**/*.channels.xml')
|
||||
|
||||
let parsedChannels = new Collection()
|
||||
for (const filepath of files) {
|
||||
parsedChannels = parsedChannels.concat(await parser.parse(filepath))
|
||||
}
|
||||
|
||||
logger.info(` found ${parsedChannels.count()} channel(s)`)
|
||||
|
||||
const output = parsedChannels.map((channel: epgGrabber.Channel): OutputItem => {
|
||||
const xmltv_id = channel.xmltv_id || ''
|
||||
const [channelId, feedId] = xmltv_id.split('@')
|
||||
|
||||
return {
|
||||
channel: channelId || null,
|
||||
feed: feedId || null,
|
||||
site: channel.site || '',
|
||||
site_id: channel.site_id || '',
|
||||
site_name: channel.name,
|
||||
lang: channel.lang || ''
|
||||
}
|
||||
})
|
||||
|
||||
const apiStorage = new Storage(API_DIR)
|
||||
const outputFilename = 'guides.json'
|
||||
await apiStorage.save('guides.json', output.toJSON())
|
||||
|
||||
logger.info(`saved to "${path.join(API_DIR, outputFilename)}"`)
|
||||
}
|
||||
|
||||
main()
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
import { Logger } from '@freearhey/core'
|
||||
import { ApiClient } from '../../core'
|
||||
import { DATA_DIR } from '../../constants'
|
||||
import { Storage } from '@freearhey/core'
|
||||
import { DataLoader } from '../../core'
|
||||
|
||||
async function main() {
|
||||
const logger = new Logger()
|
||||
const client = new ApiClient({ logger })
|
||||
const storage = new Storage(DATA_DIR)
|
||||
const loader = new DataLoader({ storage })
|
||||
|
||||
const requests = [
|
||||
client.download('channels.json'),
|
||||
client.download('countries.json'),
|
||||
client.download('regions.json'),
|
||||
client.download('subdivisions.json')
|
||||
]
|
||||
|
||||
await Promise.all(requests)
|
||||
await Promise.all([
|
||||
loader.download('blocklist.json'),
|
||||
loader.download('categories.json'),
|
||||
loader.download('channels.json'),
|
||||
loader.download('countries.json'),
|
||||
loader.download('languages.json'),
|
||||
loader.download('regions.json'),
|
||||
loader.download('subdivisions.json'),
|
||||
loader.download('feeds.json'),
|
||||
loader.download('timezones.json'),
|
||||
loader.download('guides.json'),
|
||||
loader.download('streams.json')
|
||||
])
|
||||
}
|
||||
|
||||
main()
|
||||
|
|
1
scripts/commands/channels/.gitignore
vendored
1
scripts/commands/channels/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/replace.ts
|
217
scripts/commands/channels/edit.ts
Normal file
217
scripts/commands/channels/edit.ts
Normal file
|
@ -0,0 +1,217 @@
|
|||
import { Storage, Collection, Logger, Dictionary } from '@freearhey/core'
|
||||
import { select, input } from '@inquirer/prompts'
|
||||
import { ChannelsParser, XML } from '../../core'
|
||||
import { Channel, Feed } from '../../models'
|
||||
import { DATA_DIR } from '../../constants'
|
||||
import nodeCleanup from 'node-cleanup'
|
||||
import { Command } from 'commander'
|
||||
import readline from 'readline'
|
||||
import sjs from '@freearhey/search-js'
|
||||
import { DataProcessor, DataLoader } from '../../core'
|
||||
import type { DataLoaderData } from '../../types/dataLoader'
|
||||
import type { DataProcessorData } from '../../types/dataProcessor'
|
||||
import epgGrabber from 'epg-grabber'
|
||||
import { ChannelSearchableData } from '../../types/channel'
|
||||
|
||||
type ChoiceValue = { type: string; value?: Feed | Channel }
|
||||
type Choice = { name: string; short?: string; value: ChoiceValue; default?: boolean }
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
readline
|
||||
.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
})
|
||||
.on('SIGINT', function () {
|
||||
process.emit('SIGINT')
|
||||
})
|
||||
}
|
||||
|
||||
const program = new Command()
|
||||
|
||||
program.argument('<filepath>', 'Path to *.channels.xml file to edit').parse(process.argv)
|
||||
|
||||
const filepath = program.args[0]
|
||||
const logger = new Logger()
|
||||
const storage = new Storage()
|
||||
let parsedChannels = new Collection()
|
||||
|
||||
main(filepath)
|
||||
nodeCleanup(() => {
|
||||
save(filepath)
|
||||
})
|
||||
|
||||
export default async function main(filepath: string) {
|
||||
if (!(await storage.exists(filepath))) {
|
||||
throw new Error(`File "${filepath}" does not exists`)
|
||||
}
|
||||
|
||||
logger.info('loading data from api...')
|
||||
const processor = new DataProcessor()
|
||||
const dataStorage = new Storage(DATA_DIR)
|
||||
const loader = new DataLoader({ storage: dataStorage })
|
||||
const data: DataLoaderData = await loader.load()
|
||||
const { feedsGroupedByChannelId, channels, channelsKeyById }: DataProcessorData =
|
||||
processor.process(data)
|
||||
|
||||
logger.info('loading channels...')
|
||||
const parser = new ChannelsParser({ storage })
|
||||
parsedChannels = await parser.parse(filepath)
|
||||
const parsedChannelsWithoutId = parsedChannels.filter(
|
||||
(channel: epgGrabber.Channel) => !channel.xmltv_id
|
||||
)
|
||||
|
||||
logger.info(
|
||||
`found ${parsedChannels.count()} channels (including ${parsedChannelsWithoutId.count()} without ID)`
|
||||
)
|
||||
|
||||
logger.info('creating search index...')
|
||||
const items = channels.map((channel: Channel) => channel.getSearchable()).all()
|
||||
const searchIndex = sjs.createIndex(items, {
|
||||
searchable: ['name', 'altNames', 'guideNames', 'streamNames', 'feedFullNames']
|
||||
})
|
||||
|
||||
logger.info('starting...\n')
|
||||
|
||||
for (const parsedChannel of parsedChannelsWithoutId.all()) {
|
||||
try {
|
||||
parsedChannel.xmltv_id = await selectChannel(
|
||||
parsedChannel,
|
||||
searchIndex,
|
||||
feedsGroupedByChannelId,
|
||||
channelsKeyById
|
||||
)
|
||||
} catch (err) {
|
||||
logger.info(err.message)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
parsedChannelsWithoutId.forEach((channel: epgGrabber.Channel) => {
|
||||
if (channel.xmltv_id === '-') {
|
||||
channel.xmltv_id = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function selectChannel(
|
||||
channel: epgGrabber.Channel,
|
||||
searchIndex,
|
||||
feedsGroupedByChannelId: Dictionary,
|
||||
channelsKeyById: Dictionary
|
||||
): Promise<string> {
|
||||
const query = escapeRegex(channel.name)
|
||||
const similarChannels = searchIndex
|
||||
.search(query)
|
||||
.map((item: ChannelSearchableData) => channelsKeyById.get(item.id))
|
||||
|
||||
const selected: ChoiceValue = await select({
|
||||
message: `Select channel ID for "${channel.name}" (${channel.site_id}):`,
|
||||
choices: getChannelChoises(new Collection(similarChannels)),
|
||||
pageSize: 10
|
||||
})
|
||||
|
||||
switch (selected.type) {
|
||||
case 'skip':
|
||||
return '-'
|
||||
case 'type': {
|
||||
const typedChannelId = await input({ message: ' Channel ID:' })
|
||||
if (!typedChannelId) return ''
|
||||
const selectedFeedId = await selectFeed(typedChannelId, feedsGroupedByChannelId)
|
||||
if (selectedFeedId === '-') return typedChannelId
|
||||
return [typedChannelId, selectedFeedId].join('@')
|
||||
}
|
||||
case 'channel': {
|
||||
const selectedChannel = selected.value
|
||||
if (!selectedChannel) return ''
|
||||
const selectedFeedId = await selectFeed(selectedChannel.id, feedsGroupedByChannelId)
|
||||
if (selectedFeedId === '-') return selectedChannel.id
|
||||
return [selectedChannel.id, selectedFeedId].join('@')
|
||||
}
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
async function selectFeed(channelId: string, feedsGroupedByChannelId: Dictionary): Promise<string> {
|
||||
const channelFeeds = feedsGroupedByChannelId.has(channelId)
|
||||
? new Collection(feedsGroupedByChannelId.get(channelId))
|
||||
: new Collection()
|
||||
const choices = getFeedChoises(channelFeeds)
|
||||
|
||||
const selected: ChoiceValue = await select({
|
||||
message: `Select feed ID for "${channelId}":`,
|
||||
choices,
|
||||
pageSize: 10
|
||||
})
|
||||
|
||||
switch (selected.type) {
|
||||
case 'skip':
|
||||
return '-'
|
||||
case 'type':
|
||||
return await input({ message: ' Feed ID:', default: 'SD' })
|
||||
case 'feed':
|
||||
const selectedFeed = selected.value
|
||||
if (!selectedFeed) return ''
|
||||
return selectedFeed.id
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
function getChannelChoises(channels: Collection): Choice[] {
|
||||
const choises: Choice[] = []
|
||||
|
||||
channels.forEach((channel: Channel) => {
|
||||
const names = new Collection([channel.name, ...channel.getAltNames().all()]).uniq().join(', ')
|
||||
|
||||
choises.push({
|
||||
value: {
|
||||
type: 'channel',
|
||||
value: channel
|
||||
},
|
||||
name: `${channel.id} (${names})`,
|
||||
short: `${channel.id}`
|
||||
})
|
||||
})
|
||||
|
||||
choises.push({ name: 'Type...', value: { type: 'type' } })
|
||||
choises.push({ name: 'Skip', value: { type: 'skip' } })
|
||||
|
||||
return choises
|
||||
}
|
||||
|
||||
function getFeedChoises(feeds: Collection): Choice[] {
|
||||
const choises: Choice[] = []
|
||||
|
||||
feeds.forEach((feed: Feed) => {
|
||||
let name = `${feed.id} (${feed.name})`
|
||||
if (feed.isMain) name += ' [main]'
|
||||
|
||||
choises.push({
|
||||
value: {
|
||||
type: 'feed',
|
||||
value: feed
|
||||
},
|
||||
default: feed.isMain,
|
||||
name,
|
||||
short: feed.id
|
||||
})
|
||||
})
|
||||
|
||||
choises.push({ name: 'Type...', value: { type: 'type' } })
|
||||
choises.push({ name: 'Skip', value: { type: 'skip' } })
|
||||
|
||||
return choises
|
||||
}
|
||||
|
||||
function save(filepath: string) {
|
||||
if (!storage.existsSync(filepath)) return
|
||||
const xml = new XML(parsedChannels)
|
||||
storage.saveSync(filepath, xml.toString())
|
||||
logger.info(`\nFile '${filepath}' successfully saved`)
|
||||
}
|
||||
|
||||
function escapeRegex(string: string) {
|
||||
return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&')
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
import { DATA_DIR } from '../../constants'
|
||||
import { Storage, Collection, Dictionary, Logger } from '@freearhey/core'
|
||||
import { ChannelsParser, XML, ApiChannel } from '../../core'
|
||||
import { Channel } from 'epg-grabber'
|
||||
import { transliterate } from 'transliteration'
|
||||
import nodeCleanup from 'node-cleanup'
|
||||
import { program } from 'commander'
|
||||
import inquirer, { QuestionCollection } from 'inquirer'
|
||||
import sj from '@freearhey/search-js'
|
||||
|
||||
program
|
||||
.argument('<filepath>', 'Path to *.channels.xml file to edit')
|
||||
.option('-c, --country <name>', 'Default country (ISO 3166 code)', 'US')
|
||||
.parse(process.argv)
|
||||
|
||||
const filepath = program.args[0]
|
||||
const programOptions = program.opts()
|
||||
const defaultCountry = programOptions.country.toLowerCase()
|
||||
const newLabel = ' [new]'
|
||||
|
||||
let options = new Collection()
|
||||
|
||||
async function main() {
|
||||
const storage = new Storage()
|
||||
|
||||
if (!(await storage.exists(filepath))) {
|
||||
throw new Error(`File "${filepath}" does not exists`)
|
||||
}
|
||||
|
||||
const parser = new ChannelsParser({ storage })
|
||||
|
||||
const parsedChannels = await parser.parse(filepath)
|
||||
options = parsedChannels.map((channel: Channel): { channel: Channel; delete: boolean } => {
|
||||
return {
|
||||
channel,
|
||||
delete: false
|
||||
}
|
||||
})
|
||||
|
||||
const dataStorage = new Storage(DATA_DIR)
|
||||
const channelsContent = await dataStorage.json('channels.json')
|
||||
|
||||
const channelsIndex = sj.createIndex(channelsContent)
|
||||
|
||||
const buffer = new Dictionary()
|
||||
for (let option of options.all()) {
|
||||
const channel: Channel = option.channel
|
||||
if (channel.xmltv_id) {
|
||||
if (channel.xmltv_id !== '-') {
|
||||
buffer.set(`${channel.xmltv_id}/${channel.lang}`, true)
|
||||
}
|
||||
continue
|
||||
}
|
||||
const choices = getOptions(channelsIndex, channel)
|
||||
const question: QuestionCollection = {
|
||||
name: 'option',
|
||||
message: `Choose xmltv_id for "${channel.name}" (${channel.site_id}):`,
|
||||
type: 'list',
|
||||
choices,
|
||||
pageSize: 10
|
||||
}
|
||||
|
||||
await inquirer.prompt(question).then(async selected => {
|
||||
switch (selected.option) {
|
||||
case 'Overwrite':
|
||||
const input = await getInput(channel)
|
||||
channel.xmltv_id = input.xmltv_id
|
||||
break
|
||||
case 'Skip':
|
||||
channel.xmltv_id = '-'
|
||||
break
|
||||
default:
|
||||
const [, xmltv_id] = selected.option
|
||||
.replace(/ \[.*\]/, '')
|
||||
.split('|')
|
||||
.map((i: string) => i.trim().replace(newLabel, ''))
|
||||
channel.xmltv_id = xmltv_id
|
||||
break
|
||||
}
|
||||
|
||||
const found = buffer.has(`${channel.xmltv_id}/${channel.lang}`)
|
||||
if (found) {
|
||||
const question: QuestionCollection = {
|
||||
name: 'option',
|
||||
message: `"${channel.xmltv_id}" already on the list. Choose an option:`,
|
||||
type: 'list',
|
||||
choices: ['Skip', 'Add', 'Delete'],
|
||||
pageSize: 5
|
||||
}
|
||||
await inquirer.prompt(question).then(async selected => {
|
||||
switch (selected.option) {
|
||||
case 'Skip':
|
||||
channel.xmltv_id = '-'
|
||||
break
|
||||
case 'Delete':
|
||||
option.delete = true
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if (channel.xmltv_id !== '-') {
|
||||
buffer.set(`${channel.xmltv_id}/${channel.lang}`, true)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
function save() {
|
||||
const logger = new Logger()
|
||||
const storage = new Storage()
|
||||
|
||||
if (!storage.existsSync(filepath)) return
|
||||
|
||||
const channels = options
|
||||
.filter((option: { channel: Channel; delete: boolean }) => !option.delete)
|
||||
.map((option: { channel: Channel; delete: boolean }) => option.channel)
|
||||
|
||||
const xml = new XML(channels)
|
||||
|
||||
storage.saveSync(filepath, xml.toString())
|
||||
|
||||
logger.info(`\nFile '${filepath}' successfully saved`)
|
||||
}
|
||||
|
||||
nodeCleanup(() => {
|
||||
save()
|
||||
})
|
||||
|
||||
async function getInput(channel: Channel) {
|
||||
const name = channel.name.trim()
|
||||
const input = await inquirer.prompt([
|
||||
{
|
||||
name: 'xmltv_id',
|
||||
message: ' ID:',
|
||||
type: 'input',
|
||||
default: generateCode(name, defaultCountry)
|
||||
}
|
||||
])
|
||||
|
||||
return { name, xmltv_id: input['xmltv_id'] }
|
||||
}
|
||||
|
||||
function getOptions(channelsIndex, channel: Channel) {
|
||||
const channelId = generateCode(channel.name, defaultCountry)
|
||||
const query = channel.name
|
||||
.replace(/\s(SD|TV|HD|SD\/HD|HDTV)$/i, '')
|
||||
.replace(/(\(|\)|,)/gi, '')
|
||||
.replace(/\-/gi, ' ')
|
||||
.replace(/\+/gi, '')
|
||||
const similar = channelsIndex.search(query).map(item => new ApiChannel(item))
|
||||
|
||||
const variants = new Collection()
|
||||
variants.add(`${channel.name.trim()} | ${channelId}${newLabel}`)
|
||||
similar.forEach((_channel: ApiChannel) => {
|
||||
const altNames = _channel.altNames.notEmpty() ? ` (${_channel.altNames.join(',')})` : ''
|
||||
const closed = _channel.closed ? ` [closed:${_channel.closed}]` : ''
|
||||
const replacedBy = _channel.replacedBy ? `[replaced_by:${_channel.replacedBy}]` : ''
|
||||
|
||||
variants.add(`${_channel.name}${altNames} | ${_channel.id}${closed}${replacedBy}`)
|
||||
})
|
||||
variants.add('Overwrite')
|
||||
variants.add('Skip')
|
||||
|
||||
return variants.all()
|
||||
}
|
||||
|
||||
function generateCode(name: string, country: string) {
|
||||
const channelId: string = transliterate(name)
|
||||
.replace(/\+/gi, 'Plus')
|
||||
.replace(/^&/gi, 'And')
|
||||
.replace(/[^a-z\d]+/gi, '')
|
||||
|
||||
return `${channelId}.${country}`
|
||||
}
|
108
scripts/commands/channels/lint.mts
Normal file
108
scripts/commands/channels/lint.mts
Normal file
|
@ -0,0 +1,108 @@
|
|||
import chalk from 'chalk'
|
||||
import { program } from 'commander'
|
||||
import { Storage, File } from '@freearhey/core'
|
||||
import { XmlDocument, XsdValidator, XmlValidateError, ErrorDetail } from 'libxml2-wasm'
|
||||
|
||||
const xsd = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
|
||||
<xs:element name="channels">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" ref="channel"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="channel">
|
||||
<xs:complexType mixed="true">
|
||||
<xs:attribute use="required" ref="site"/>
|
||||
<xs:attribute use="required" ref="lang"/>
|
||||
<xs:attribute use="required" ref="site_id"/>
|
||||
<xs:attribute name="xmltv_id" use="required" type="xs:string"/>
|
||||
<xs:attribute name="logo" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:attribute name="site">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="site_id">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="lang">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:minLength value="1"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:schema>`
|
||||
|
||||
program.argument('[filepath]', 'Path to *.channels.xml files to check').parse(process.argv)
|
||||
|
||||
async function main() {
|
||||
const storage = new Storage()
|
||||
|
||||
let errors: ErrorDetail[] = []
|
||||
|
||||
const files = program.args.length ? program.args : await storage.list('sites/**/*.channels.xml')
|
||||
for (const filepath of files) {
|
||||
const file = new File(filepath)
|
||||
if (file.extension() !== 'xml') continue
|
||||
|
||||
const xml = await storage.load(filepath)
|
||||
|
||||
let localErrors: ErrorDetail[] = []
|
||||
|
||||
try {
|
||||
const schema = XmlDocument.fromString(xsd)
|
||||
const validator = XsdValidator.fromDoc(schema)
|
||||
const doc = XmlDocument.fromString(xml)
|
||||
|
||||
validator.validate(doc)
|
||||
|
||||
schema.dispose()
|
||||
validator.dispose()
|
||||
doc.dispose()
|
||||
} catch (_error) {
|
||||
const error = _error as XmlValidateError
|
||||
|
||||
localErrors = localErrors.concat(error.details)
|
||||
}
|
||||
|
||||
xml.split('\n').forEach((line: string, lineIndex: number) => {
|
||||
const found = line.match(/='/)
|
||||
if (found) {
|
||||
const colIndex = found.index || 0
|
||||
localErrors.push({
|
||||
line: lineIndex + 1,
|
||||
col: colIndex + 1,
|
||||
message: 'Single quotes cannot be used in attributes'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if (localErrors.length) {
|
||||
console.log(`\n${chalk.underline(filepath)}`)
|
||||
localErrors.forEach((error: ErrorDetail) => {
|
||||
const position = `${error.line}:${error.col}`
|
||||
console.log(` ${chalk.gray(position.padEnd(4, ' '))} ${error.message.trim()}`)
|
||||
})
|
||||
|
||||
errors = errors.concat(localErrors)
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length) {
|
||||
console.log(chalk.red(`\n${errors.length} error(s)`))
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
|
@ -1,78 +0,0 @@
|
|||
import chalk from 'chalk'
|
||||
import libxml, { ValidationError } from 'libxmljs2'
|
||||
import { program } from 'commander'
|
||||
import { Logger, Storage, File } from '@freearhey/core'
|
||||
|
||||
const xsd = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
|
||||
<xs:element name="channels">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" ref="channel"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="channel">
|
||||
<xs:complexType mixed="true">
|
||||
<xs:attribute name="site" use="required" type="xs:string"/>
|
||||
<xs:attribute name="lang" use="required" type="xs:string"/>
|
||||
<xs:attribute name="site_id" use="required" type="xs:string"/>
|
||||
<xs:attribute name="xmltv_id" use="required" type="xs:string"/>
|
||||
<xs:attribute name="logo" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>`
|
||||
|
||||
program
|
||||
.option(
|
||||
'-c, --channels <path>',
|
||||
'Path to channels.xml file to validate',
|
||||
'sites/**/*.channels.xml'
|
||||
)
|
||||
.parse(process.argv)
|
||||
|
||||
const options = program.opts()
|
||||
|
||||
async function main() {
|
||||
const logger = new Logger()
|
||||
const storage = new Storage()
|
||||
|
||||
logger.info('options:')
|
||||
logger.tree(options)
|
||||
|
||||
let errors: ValidationError[] = []
|
||||
|
||||
const files: string[] = await storage.list(options.channels)
|
||||
for (const filepath of files) {
|
||||
const file = new File(filepath)
|
||||
if (file.extension() !== 'xml') continue
|
||||
|
||||
const xml = await storage.load(filepath)
|
||||
|
||||
let localErrors: ValidationError[] = []
|
||||
|
||||
const xsdDoc = libxml.parseXml(xsd)
|
||||
const doc = libxml.parseXml(xml)
|
||||
|
||||
if (!doc.validate(xsdDoc)) {
|
||||
localErrors = doc.validationErrors
|
||||
}
|
||||
|
||||
if (localErrors.length) {
|
||||
console.log(`\n${chalk.underline(filepath)}`)
|
||||
localErrors.forEach((error: ValidationError) => {
|
||||
const position = `${error.line}:${error.column}`
|
||||
console.log(` ${chalk.gray(position.padEnd(4, ' '))} ${error.message.trim()}`)
|
||||
})
|
||||
|
||||
errors = errors.concat(localErrors)
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length) {
|
||||
console.log(chalk.red(`\n${errors.length} error(s)`))
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
|
@ -2,7 +2,7 @@ import { Logger, File, Collection, Storage } from '@freearhey/core'
|
|||
import { ChannelsParser, XML } from '../../core'
|
||||
import { Channel } from 'epg-grabber'
|
||||
import { Command } from 'commander'
|
||||
import path from 'path'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
|
||||
const program = new Command()
|
||||
program
|
||||
|
@ -26,7 +26,7 @@ async function main() {
|
|||
const logger = new Logger()
|
||||
const file = new File(options.config)
|
||||
const dir = file.dirname()
|
||||
const config = require(path.resolve(options.config))
|
||||
const config = (await import(pathToFileURL(options.config).toString())).default
|
||||
const outputFilepath = options.output || `${dir}/${config.site}.channels.xml`
|
||||
|
||||
let channels = new Collection()
|
||||
|
|
|
@ -1,20 +1,13 @@
|
|||
import { Storage, Collection, Dictionary, File, Logger } from '@freearhey/core'
|
||||
import { ChannelsParser, ApiChannel } from '../../core'
|
||||
import { Storage, Collection, Dictionary, File } from '@freearhey/core'
|
||||
import { ChannelsParser } from '../../core'
|
||||
import { Channel } from '../../models'
|
||||
import { program } from 'commander'
|
||||
import chalk from 'chalk'
|
||||
import langs from 'langs'
|
||||
import { DATA_DIR } from '../../constants'
|
||||
import { Channel } from 'epg-grabber'
|
||||
import epgGrabber from 'epg-grabber'
|
||||
|
||||
program
|
||||
.option(
|
||||
'-c, --channels <path>',
|
||||
'Path to channels.xml file to validate',
|
||||
'sites/**/*.channels.xml'
|
||||
)
|
||||
.parse(process.argv)
|
||||
|
||||
const options = program.opts()
|
||||
program.argument('[filepath]', 'Path to *.channels.xml files to validate').parse(process.argv)
|
||||
|
||||
type ValidationError = {
|
||||
type: 'duplicate' | 'wrong_xmltv_id' | 'wrong_lang'
|
||||
|
@ -26,34 +19,30 @@ type ValidationError = {
|
|||
}
|
||||
|
||||
async function main() {
|
||||
const logger = new Logger()
|
||||
|
||||
logger.info('options:')
|
||||
logger.tree(options)
|
||||
|
||||
const parser = new ChannelsParser({ storage: new Storage() })
|
||||
|
||||
const dataStorage = new Storage(DATA_DIR)
|
||||
const channelsContent = await dataStorage.json('channels.json')
|
||||
const channels = new Collection(channelsContent).map(data => new ApiChannel(data))
|
||||
const channelsData = await dataStorage.json('channels.json')
|
||||
const channels = new Collection(channelsData).map(data => new Channel(data))
|
||||
const channelsGroupedById = channels.groupBy((channel: Channel) => channel.id)
|
||||
|
||||
let totalFiles = 0
|
||||
let totalErrors = 0
|
||||
|
||||
const storage = new Storage()
|
||||
const files: string[] = await storage.list(options.channels)
|
||||
const files = program.args.length ? program.args : await storage.list('sites/**/*.channels.xml')
|
||||
for (const filepath of files) {
|
||||
const file = new File(filepath)
|
||||
if (file.extension() !== 'xml') continue
|
||||
|
||||
const parsedChannels = await parser.parse(filepath)
|
||||
|
||||
const bufferById = new Dictionary()
|
||||
const bufferBySiteId = new Dictionary()
|
||||
const errors: ValidationError[] = []
|
||||
parsedChannels.forEach((channel: Channel) => {
|
||||
const bufferSiteId: string = `${channel.site_id}:${channel.lang}`
|
||||
if (bufferBySiteId.missing(bufferSiteId)) {
|
||||
bufferBySiteId.set(bufferSiteId, true)
|
||||
parsedChannels.forEach((channel: epgGrabber.Channel) => {
|
||||
const bufferId: string = channel.site_id
|
||||
if (bufferBySiteId.missing(bufferId)) {
|
||||
bufferBySiteId.set(bufferId, true)
|
||||
} else {
|
||||
errors.push({ type: 'duplicate', ...channel })
|
||||
totalErrors++
|
||||
|
@ -65,24 +54,12 @@ async function main() {
|
|||
}
|
||||
|
||||
if (!channel.xmltv_id) return
|
||||
|
||||
const foundChannel = channels.first(
|
||||
(_channel: ApiChannel) => _channel.id === channel.xmltv_id
|
||||
)
|
||||
const [channelId] = channel.xmltv_id.split('@')
|
||||
const foundChannel = channelsGroupedById.get(channelId)
|
||||
if (!foundChannel) {
|
||||
errors.push({ type: 'wrong_xmltv_id', ...channel })
|
||||
totalErrors++
|
||||
}
|
||||
|
||||
// if (foundChannel && foundChannel.replacedBy) {
|
||||
// errors.push({ type: 'replaced', ...channel })
|
||||
// totalErrors++
|
||||
// }
|
||||
|
||||
// if (foundChannel && foundChannel.closed && !foundChannel.replacedBy) {
|
||||
// errors.push({ type: 'closed', ...channel })
|
||||
// totalErrors++
|
||||
// }
|
||||
})
|
||||
|
||||
if (errors.length) {
|
||||
|
|
|
@ -1,34 +1,49 @@
|
|||
import { Logger, Timer, Storage, Collection } from '@freearhey/core'
|
||||
import { program } from 'commander'
|
||||
import { CronJob } from 'cron'
|
||||
import { Option, program } from 'commander'
|
||||
import { QueueCreator, Job, ChannelsParser } from '../../core'
|
||||
import { Channel } from 'epg-grabber'
|
||||
import path from 'path'
|
||||
import { SITES_DIR } from '../../constants'
|
||||
|
||||
program
|
||||
.option('-s, --site <name>', 'Name of the site to parse')
|
||||
.option(
|
||||
'-c, --channels <path>',
|
||||
'Path to *.channels.xml file (required if the "--site" attribute is not specified)'
|
||||
.addOption(new Option('-s, --site <name>', 'Name of the site to parse'))
|
||||
.addOption(
|
||||
new Option(
|
||||
'-c, --channels <path>',
|
||||
'Path to *.channels.xml file (required if the "--site" attribute is not specified)'
|
||||
)
|
||||
)
|
||||
.option('-o, --output <path>', 'Path to output file', 'guide.xml')
|
||||
.option('-l, --lang <code>', 'Filter channels by language (ISO 639-2 code)')
|
||||
.option('-t, --timeout <milliseconds>', 'Override the default timeout for each request')
|
||||
.option('-d, --delay <milliseconds>', 'Override the default delay between request')
|
||||
.option(
|
||||
'--days <days>',
|
||||
'Override the number of days for which the program will be loaded (defaults to the value from the site config)',
|
||||
value => parseInt(value)
|
||||
.addOption(new Option('-o, --output <path>', 'Path to output file').default('guide.xml'))
|
||||
.addOption(new Option('-l, --lang <codes>', 'Filter channels by languages (ISO 639-1 codes)'))
|
||||
.addOption(
|
||||
new Option('-t, --timeout <milliseconds>', 'Override the default timeout for each request').env(
|
||||
'TIMEOUT'
|
||||
)
|
||||
)
|
||||
.option(
|
||||
'--maxConnections <number>',
|
||||
'Limit on the number of concurrent requests',
|
||||
value => parseInt(value),
|
||||
1
|
||||
.addOption(
|
||||
new Option('-d, --delay <milliseconds>', 'Override the default delay between request').env(
|
||||
'DELAY'
|
||||
)
|
||||
)
|
||||
.addOption(new Option('-x, --proxy <url>', 'Use the specified proxy').env('PROXY'))
|
||||
.addOption(
|
||||
new Option(
|
||||
'--days <days>',
|
||||
'Override the number of days for which the program will be loaded (defaults to the value from the site config)'
|
||||
)
|
||||
.argParser(value => parseInt(value))
|
||||
.env('DAYS')
|
||||
)
|
||||
.addOption(
|
||||
new Option('--maxConnections <number>', 'Limit on the number of concurrent requests')
|
||||
.default(1)
|
||||
.env('MAX_CONNECTIONS')
|
||||
)
|
||||
.addOption(
|
||||
new Option('--gzip', 'Create a compressed version of the guide as well')
|
||||
.default(false)
|
||||
.env('GZIP')
|
||||
)
|
||||
.option('--cron <expression>', 'Schedule a script run (example: "0 0 * * *")')
|
||||
.option('--gzip', 'Create a compressed version of the guide as well', false)
|
||||
.parse(process.argv)
|
||||
|
||||
export type GrabOptions = {
|
||||
|
@ -41,7 +56,7 @@ export type GrabOptions = {
|
|||
delay?: string
|
||||
lang?: string
|
||||
days?: number
|
||||
cron?: string
|
||||
proxy?: string
|
||||
}
|
||||
|
||||
const options: GrabOptions = program.opts()
|
||||
|
@ -75,22 +90,16 @@ async function main() {
|
|||
parsedChannels = parsedChannels.concat(await parser.parse(filepath))
|
||||
}
|
||||
if (options.lang) {
|
||||
parsedChannels = parsedChannels.filter((channel: Channel) => channel.lang === options.lang)
|
||||
parsedChannels = parsedChannels.filter((channel: Channel) => {
|
||||
if (!options.lang || !channel.lang) return true
|
||||
|
||||
return options.lang.includes(channel.lang)
|
||||
})
|
||||
}
|
||||
logger.info(` found ${parsedChannels.count()} channel(s)`)
|
||||
|
||||
let runIndex = 1
|
||||
if (options.cron) {
|
||||
const cronJob = new CronJob(options.cron, async () => {
|
||||
logger.info(`run #${runIndex}:`)
|
||||
await runJob({ logger, parsedChannels })
|
||||
runIndex++
|
||||
})
|
||||
cronJob.start()
|
||||
} else {
|
||||
logger.info(`run #${runIndex}:`)
|
||||
runJob({ logger, parsedChannels })
|
||||
}
|
||||
logger.info('run:')
|
||||
runJob({ logger, parsedChannels })
|
||||
}
|
||||
|
||||
main()
|
||||
|
|
45
scripts/commands/sites/init.ts
Normal file
45
scripts/commands/sites/init.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import { Logger, Storage } from '@freearhey/core'
|
||||
import { SITES_DIR } from '../../constants'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { program } from 'commander'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
program.argument('<site>', 'Domain name of the site').parse(process.argv)
|
||||
|
||||
const domain = program.args[0]
|
||||
|
||||
async function main() {
|
||||
const storage = new Storage(SITES_DIR)
|
||||
const logger = new Logger()
|
||||
|
||||
logger.info(`Initializing "${domain}"...\r\n`)
|
||||
|
||||
const dir = domain
|
||||
if (await storage.exists(dir)) {
|
||||
throw new Error(`Folder "${dir}" already exists`)
|
||||
}
|
||||
|
||||
await storage.createDir(dir)
|
||||
|
||||
logger.info(`Creating "${dir}/${domain}.test.js"...`)
|
||||
const testTemplate = fs.readFileSync(pathToFileURL('scripts/templates/_test.js'), {
|
||||
encoding: 'utf8'
|
||||
})
|
||||
await storage.save(`${dir}/${domain}.test.js`, testTemplate.replace(/<DOMAIN>/g, domain))
|
||||
|
||||
logger.info(`Creating "${dir}/${domain}.config.js"...`)
|
||||
const configTemplate = fs.readFileSync(pathToFileURL('scripts/templates/_config.js'), {
|
||||
encoding: 'utf8'
|
||||
})
|
||||
await storage.save(`${dir}/${domain}.config.js`, configTemplate.replace(/<DOMAIN>/g, domain))
|
||||
|
||||
logger.info(`Creating "${dir}/readme.md"...`)
|
||||
const readmeTemplate = fs.readFileSync(pathToFileURL('scripts/templates/_readme.md'), {
|
||||
encoding: 'utf8'
|
||||
})
|
||||
await storage.save(`${dir}/readme.md`, readmeTemplate.replace(/<DOMAIN>/g, domain))
|
||||
|
||||
logger.info('\r\nDone')
|
||||
}
|
||||
|
||||
main()
|
70
scripts/commands/sites/update.ts
Normal file
70
scripts/commands/sites/update.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
import { IssueLoader, HTMLTable, ChannelsParser } from '../../core'
|
||||
import { Logger, Storage, Collection } from '@freearhey/core'
|
||||
import { SITES_DIR, ROOT_DIR } from '../../constants'
|
||||
import { Issue, Site } from '../../models'
|
||||
import { Channel } from 'epg-grabber'
|
||||
|
||||
async function main() {
|
||||
const logger = new Logger({ disabled: true })
|
||||
const loader = new IssueLoader()
|
||||
const sitesStorage = new Storage(SITES_DIR)
|
||||
const channelsParser = new ChannelsParser({ storage: sitesStorage })
|
||||
const sites = new Collection()
|
||||
|
||||
logger.info('loading list of sites')
|
||||
const folders = await sitesStorage.list('*/')
|
||||
|
||||
logger.info('loading issues...')
|
||||
const issues = await loader.load()
|
||||
|
||||
logger.info('putting the data together...')
|
||||
const brokenGuideReports = issues.filter(issue =>
|
||||
issue.labels.find((label: string) => label === 'broken guide')
|
||||
)
|
||||
for (const domain of folders) {
|
||||
const filteredIssues = brokenGuideReports.filter(
|
||||
(issue: Issue) => domain === issue.data.get('site')
|
||||
)
|
||||
|
||||
const site = new Site({
|
||||
domain,
|
||||
issues: filteredIssues
|
||||
})
|
||||
|
||||
const files = await sitesStorage.list(`${domain}/*.channels.xml`)
|
||||
for (const filepath of files) {
|
||||
const channels = await channelsParser.parse(filepath)
|
||||
|
||||
site.totalChannels += channels.count()
|
||||
site.markedChannels += channels.filter((channel: Channel) => channel.xmltv_id).count()
|
||||
}
|
||||
|
||||
sites.add(site)
|
||||
}
|
||||
|
||||
logger.info('creating sites table...')
|
||||
const data = new Collection()
|
||||
sites.forEach((site: Site) => {
|
||||
data.add([
|
||||
{ value: `<a href="sites/${site.domain}">${site.domain}</a>` },
|
||||
{ value: site.totalChannels, align: 'right' },
|
||||
{ value: site.markedChannels, align: 'right' },
|
||||
{ value: site.getStatus().emoji, align: 'center' },
|
||||
{ value: site.getIssues().all().join(', ') }
|
||||
])
|
||||
})
|
||||
|
||||
logger.info('updating sites.md...')
|
||||
const table = new HTMLTable(data.all(), [
|
||||
{ name: 'Site', align: 'left' },
|
||||
{ name: 'Channels<br>(total / with xmltv-id)', colspan: 2, align: 'left' },
|
||||
{ name: 'Status', align: 'left' },
|
||||
{ name: 'Notes', align: 'left' }
|
||||
])
|
||||
const rootStorage = new Storage(ROOT_DIR)
|
||||
const sitesTemplate = await new Storage().load('scripts/templates/_sites.md')
|
||||
const sitesContent = sitesTemplate.replace('_TABLE_', table.toString())
|
||||
await rootStorage.save('SITES.md', sitesContent)
|
||||
}
|
||||
|
||||
main()
|
|
@ -1,4 +1,9 @@
|
|||
export const ROOT_DIR = process.env.ROOT_DIR || '.'
|
||||
export const SITES_DIR = process.env.SITES_DIR || './sites'
|
||||
export const GUIDES_DIR = process.env.GUIDES_DIR || './guides'
|
||||
export const DATA_DIR = process.env.DATA_DIR || './temp/data'
|
||||
export const API_DIR = process.env.API_DIR || '.api'
|
||||
export const DOT_SITES_DIR = process.env.DOT_SITES_DIR || './.sites'
|
||||
export const TESTING = process.env.NODE_ENV === 'test' ? true : false
|
||||
export const OWNER = 'iptv-org'
|
||||
export const REPO = 'epg'
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
import { Collection } from '@freearhey/core'
|
||||
|
||||
type ApiChannelProps = {
|
||||
id: string
|
||||
name: string
|
||||
alt_names: string[]
|
||||
network: string
|
||||
owners: string[]
|
||||
country: string
|
||||
subdivision: string
|
||||
city: string
|
||||
broadcast_area: string[]
|
||||
languages: string[]
|
||||
categories: string[]
|
||||
is_nsfw: boolean
|
||||
launched: string
|
||||
closed: string
|
||||
replaced_by: string
|
||||
website: string
|
||||
logo: string
|
||||
}
|
||||
|
||||
export class ApiChannel {
|
||||
id: string
|
||||
name: string
|
||||
altNames: Collection
|
||||
network: string
|
||||
owners: Collection
|
||||
country: string
|
||||
subdivision: string
|
||||
city: string
|
||||
broadcastArea: Collection
|
||||
languages: Collection
|
||||
categories: Collection
|
||||
isNSFW: boolean
|
||||
launched: string
|
||||
closed: string
|
||||
replacedBy: string
|
||||
website: string
|
||||
logo: string
|
||||
|
||||
constructor({
|
||||
id,
|
||||
name,
|
||||
alt_names,
|
||||
network,
|
||||
owners,
|
||||
country,
|
||||
subdivision,
|
||||
city,
|
||||
broadcast_area,
|
||||
languages,
|
||||
categories,
|
||||
is_nsfw,
|
||||
launched,
|
||||
closed,
|
||||
replaced_by,
|
||||
website,
|
||||
logo
|
||||
}: ApiChannelProps) {
|
||||
this.id = id
|
||||
this.name = name
|
||||
this.altNames = new Collection(alt_names)
|
||||
this.network = network
|
||||
this.owners = new Collection(owners)
|
||||
this.country = country
|
||||
this.subdivision = subdivision
|
||||
this.city = city
|
||||
this.broadcastArea = new Collection(broadcast_area)
|
||||
this.languages = new Collection(languages)
|
||||
this.categories = new Collection(categories)
|
||||
this.isNSFW = is_nsfw
|
||||
this.launched = launched
|
||||
this.closed = closed
|
||||
this.replacedBy = replaced_by
|
||||
this.website = website
|
||||
this.logo = logo
|
||||
}
|
||||
}
|
|
@ -1,59 +1,16 @@
|
|||
import { Logger, Storage } from '@freearhey/core'
|
||||
import axios, { AxiosInstance, AxiosResponse, AxiosProgressEvent } from 'axios'
|
||||
import cliProgress, { MultiBar } from 'cli-progress'
|
||||
import numeral from 'numeral'
|
||||
import axios, { AxiosInstance, AxiosResponse, AxiosRequestConfig } from 'axios'
|
||||
|
||||
export class ApiClient {
|
||||
progressBar: MultiBar
|
||||
client: AxiosInstance
|
||||
storage: Storage
|
||||
logger: Logger
|
||||
instance: AxiosInstance
|
||||
|
||||
constructor({ logger }: { logger: Logger }) {
|
||||
this.logger = logger
|
||||
this.client = axios.create({
|
||||
constructor() {
|
||||
this.instance = axios.create({
|
||||
baseURL: 'https://iptv-org.github.io/api',
|
||||
responseType: 'stream'
|
||||
})
|
||||
this.storage = new Storage()
|
||||
this.progressBar = new cliProgress.MultiBar({
|
||||
stopOnComplete: true,
|
||||
hideCursor: true,
|
||||
forceRedraw: true,
|
||||
barsize: 36,
|
||||
format(options, params, payload) {
|
||||
const filename = payload.filename.padEnd(18, ' ')
|
||||
const barsize = options.barsize || 40
|
||||
const percent = (params.progress * 100).toFixed(2)
|
||||
const speed = payload.speed ? numeral(payload.speed).format('0.0 b') + '/s' : 'N/A'
|
||||
const total = numeral(params.total).format('0.0 b')
|
||||
const completeSize = Math.round(params.progress * barsize)
|
||||
const incompleteSize = barsize - completeSize
|
||||
const bar =
|
||||
options.barCompleteString && options.barIncompleteString
|
||||
? options.barCompleteString.substr(0, completeSize) +
|
||||
options.barGlue +
|
||||
options.barIncompleteString.substr(0, incompleteSize)
|
||||
: '-'.repeat(barsize)
|
||||
|
||||
return `${filename} [${bar}] ${percent}% | ETA: ${params.eta}s | ${total} | ${speed}`
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async download(filename: string) {
|
||||
const stream = await this.storage.createStream(`/temp/data/${filename}`)
|
||||
|
||||
const bar = this.progressBar.create(0, 0, { filename })
|
||||
|
||||
this.client
|
||||
.get(`https://iptv-org.github.io/api/${filename}`, {
|
||||
onDownloadProgress({ total, loaded, rate }: AxiosProgressEvent) {
|
||||
if (total) bar.setTotal(total)
|
||||
bar.update(loaded, { speed: rate })
|
||||
}
|
||||
})
|
||||
.then((response: AxiosResponse) => {
|
||||
response.data.pipe(stream)
|
||||
})
|
||||
get(url: string, options: AxiosRequestConfig): Promise<AxiosResponse> {
|
||||
return this.instance.get(url, options)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ export class ConfigLoader {
|
|||
const fileUrl = pathToFileURL(filepath).toString()
|
||||
const config = (await import(fileUrl)).default
|
||||
const defaultConfig = {
|
||||
days: 2,
|
||||
days: 1,
|
||||
delay: 0,
|
||||
output: 'guide.xml',
|
||||
request: {
|
||||
|
|
100
scripts/core/dataLoader.ts
Normal file
100
scripts/core/dataLoader.ts
Normal file
|
@ -0,0 +1,100 @@
|
|||
import type { DataLoaderProps, DataLoaderData } from '../types/dataLoader'
|
||||
import cliProgress, { MultiBar } from 'cli-progress'
|
||||
import { Storage } from '@freearhey/core'
|
||||
import { ApiClient } from './apiClient'
|
||||
import numeral from 'numeral'
|
||||
|
||||
export class DataLoader {
|
||||
client: ApiClient
|
||||
storage: Storage
|
||||
progressBar: MultiBar
|
||||
|
||||
constructor(props: DataLoaderProps) {
|
||||
this.client = new ApiClient()
|
||||
this.storage = props.storage
|
||||
this.progressBar = new cliProgress.MultiBar({
|
||||
stopOnComplete: true,
|
||||
hideCursor: true,
|
||||
forceRedraw: true,
|
||||
barsize: 36,
|
||||
format(options, params, payload) {
|
||||
const filename = payload.filename.padEnd(18, ' ')
|
||||
const barsize = options.barsize || 40
|
||||
const percent = (params.progress * 100).toFixed(2)
|
||||
const speed = payload.speed ? numeral(payload.speed).format('0.0 b') + '/s' : 'N/A'
|
||||
const total = numeral(params.total).format('0.0 b')
|
||||
const completeSize = Math.round(params.progress * barsize)
|
||||
const incompleteSize = barsize - completeSize
|
||||
const bar =
|
||||
options.barCompleteString && options.barIncompleteString
|
||||
? options.barCompleteString.substr(0, completeSize) +
|
||||
options.barGlue +
|
||||
options.barIncompleteString.substr(0, incompleteSize)
|
||||
: '-'.repeat(barsize)
|
||||
|
||||
return `${filename} [${bar}] ${percent}% | ETA: ${params.eta}s | ${total} | ${speed}`
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async load(): Promise<DataLoaderData> {
|
||||
const [
|
||||
countries,
|
||||
regions,
|
||||
subdivisions,
|
||||
languages,
|
||||
categories,
|
||||
blocklist,
|
||||
channels,
|
||||
feeds,
|
||||
timezones,
|
||||
guides,
|
||||
streams
|
||||
] = await Promise.all([
|
||||
this.storage.json('countries.json'),
|
||||
this.storage.json('regions.json'),
|
||||
this.storage.json('subdivisions.json'),
|
||||
this.storage.json('languages.json'),
|
||||
this.storage.json('categories.json'),
|
||||
this.storage.json('blocklist.json'),
|
||||
this.storage.json('channels.json'),
|
||||
this.storage.json('feeds.json'),
|
||||
this.storage.json('timezones.json'),
|
||||
this.storage.json('guides.json'),
|
||||
this.storage.json('streams.json')
|
||||
])
|
||||
|
||||
return {
|
||||
countries,
|
||||
regions,
|
||||
subdivisions,
|
||||
languages,
|
||||
categories,
|
||||
blocklist,
|
||||
channels,
|
||||
feeds,
|
||||
timezones,
|
||||
guides,
|
||||
streams
|
||||
}
|
||||
}
|
||||
|
||||
async download(filename: string) {
|
||||
if (!this.storage || !this.progressBar) return
|
||||
|
||||
const stream = await this.storage.createStream(filename)
|
||||
const progressBar = this.progressBar.create(0, 0, { filename })
|
||||
|
||||
this.client
|
||||
.get(filename, {
|
||||
responseType: 'stream',
|
||||
onDownloadProgress({ total, loaded, rate }) {
|
||||
if (total) progressBar.setTotal(total)
|
||||
progressBar.update(loaded, { speed: rate })
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
response.data.pipe(stream)
|
||||
})
|
||||
}
|
||||
}
|
39
scripts/core/dataProcessor.ts
Normal file
39
scripts/core/dataProcessor.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
import { DataLoaderData } from '../types/dataLoader'
|
||||
import { Collection } from '@freearhey/core'
|
||||
import { Channel, Feed, Guide, Stream } from '../models'
|
||||
|
||||
export class DataProcessor {
|
||||
constructor() {}
|
||||
|
||||
process(data: DataLoaderData) {
|
||||
let channels = new Collection(data.channels).map(data => new Channel(data))
|
||||
const channelsKeyById = channels.keyBy((channel: Channel) => channel.id)
|
||||
|
||||
const guides = new Collection(data.guides).map(data => new Guide(data))
|
||||
const guidesGroupedByStreamId = guides.groupBy((guide: Guide) => guide.getStreamId())
|
||||
|
||||
const streams = new Collection(data.streams).map(data => new Stream(data))
|
||||
const streamsGroupedById = streams.groupBy((stream: Stream) => stream.getId())
|
||||
|
||||
const feeds = new Collection(data.feeds).map(data =>
|
||||
new Feed(data)
|
||||
.withGuides(guidesGroupedByStreamId)
|
||||
.withStreams(streamsGroupedById)
|
||||
.withChannel(channelsKeyById)
|
||||
)
|
||||
const feedsGroupedByChannelId = feeds.groupBy((feed: Feed) => feed.channelId)
|
||||
|
||||
channels = channels.map((channel: Channel) => channel.withFeeds(feedsGroupedByChannelId))
|
||||
|
||||
return {
|
||||
feedsGroupedByChannelId,
|
||||
guidesGroupedByStreamId,
|
||||
streamsGroupedById,
|
||||
channelsKeyById,
|
||||
channels,
|
||||
streams,
|
||||
guides,
|
||||
feeds
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
import dayjs from 'dayjs'
|
||||
import utc from 'dayjs/plugin/utc'
|
||||
|
||||
dayjs.extend(utc)
|
||||
|
||||
const date = {}
|
||||
|
@ -10,4 +11,4 @@ date.getUTC = function (d = null) {
|
|||
return dayjs.utc().startOf('d')
|
||||
}
|
||||
|
||||
module.exports = date
|
||||
export default date
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { EPGGrabber, GrabCallbackData, EPGGrabberMock, SiteConfig, Channel } from 'epg-grabber'
|
||||
import { Logger, Collection } from '@freearhey/core'
|
||||
import { Queue } from './'
|
||||
import { Queue, ProxyParser } from './'
|
||||
import { GrabOptions } from '../commands/epg/grab'
|
||||
import { TaskQueue, PromisyClass } from 'cwait'
|
||||
import { SocksProxyAgent } from 'socks-proxy-agent'
|
||||
|
||||
type GrabberProps = {
|
||||
logger: Logger
|
||||
|
@ -14,6 +15,7 @@ export class Grabber {
|
|||
logger: Logger
|
||||
queue: Queue
|
||||
options: GrabOptions
|
||||
grabber: EPGGrabber | EPGGrabberMock
|
||||
|
||||
constructor({ logger, queue, options }: GrabberProps) {
|
||||
this.logger = logger
|
||||
|
@ -23,6 +25,7 @@ export class Grabber {
|
|||
}
|
||||
|
||||
async grab(): Promise<{ channels: Collection; programs: Collection }> {
|
||||
const proxyParser = new ProxyParser()
|
||||
const taskQueue = new TaskQueue(Promise as PromisyClass, this.options.maxConnections)
|
||||
|
||||
const total = this.queue.size()
|
||||
|
@ -49,6 +52,24 @@ export class Grabber {
|
|||
config.delay = delay
|
||||
}
|
||||
|
||||
if (this.options.proxy !== undefined) {
|
||||
const proxy = proxyParser.parse(this.options.proxy)
|
||||
|
||||
if (
|
||||
proxy.protocol &&
|
||||
['socks', 'socks5', 'socks5h', 'socks4', 'socks4a'].includes(String(proxy.protocol))
|
||||
) {
|
||||
const socksProxyAgent = new SocksProxyAgent(this.options.proxy)
|
||||
|
||||
config.request = {
|
||||
...config.request,
|
||||
...{ httpAgent: socksProxyAgent, httpsAgent: socksProxyAgent }
|
||||
}
|
||||
} else {
|
||||
config.request = { ...config.request, ...{ proxy } }
|
||||
}
|
||||
}
|
||||
|
||||
const _programs = await this.grabber.grab(
|
||||
channel,
|
||||
date,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Collection, Logger, DateTime, Storage, Zip } from '@freearhey/core'
|
||||
import { Channel } from 'epg-grabber'
|
||||
import { XMLTV } from '../core'
|
||||
import path from 'path'
|
||||
|
||||
type GuideProps = {
|
||||
channels: Collection
|
||||
|
@ -22,7 +23,7 @@ export class Guide {
|
|||
this.channels = channels
|
||||
this.programs = programs
|
||||
this.logger = logger
|
||||
this.storage = new Storage()
|
||||
this.storage = new Storage(path.dirname(filepath))
|
||||
this.filepath = filepath
|
||||
this.gzip = gzip || false
|
||||
}
|
||||
|
@ -43,15 +44,17 @@ export class Guide {
|
|||
})
|
||||
|
||||
const xmlFilepath = this.filepath
|
||||
const xmlFilename = path.basename(xmlFilepath)
|
||||
this.logger.info(` saving to "${xmlFilepath}"...`)
|
||||
await this.storage.save(xmlFilepath, xmltv.toString())
|
||||
await this.storage.save(xmlFilename, xmltv.toString())
|
||||
|
||||
if (this.gzip) {
|
||||
const zip = new Zip()
|
||||
const compressed = await zip.compress(xmltv.toString())
|
||||
const gzFilepath = `${this.filepath}.gz`
|
||||
const gzFilename = path.basename(gzFilepath)
|
||||
this.logger.info(` saving to "${gzFilepath}"...`)
|
||||
await this.storage.save(gzFilepath, compressed)
|
||||
await this.storage.save(gzFilename, compressed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
55
scripts/core/htmlTable.ts
Normal file
55
scripts/core/htmlTable.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
type Column = {
|
||||
name: string
|
||||
nowrap?: boolean
|
||||
align?: string
|
||||
colspan?: number
|
||||
}
|
||||
|
||||
type DataItem = {
|
||||
value: string
|
||||
nowrap?: boolean
|
||||
align?: string
|
||||
colspan?: number
|
||||
}[]
|
||||
|
||||
export class HTMLTable {
|
||||
data: DataItem[]
|
||||
columns: Column[]
|
||||
|
||||
constructor(data: DataItem[], columns: Column[]) {
|
||||
this.data = data
|
||||
this.columns = columns
|
||||
}
|
||||
|
||||
toString() {
|
||||
let output = '<table>\r\n'
|
||||
|
||||
output += ' <thead>\r\n <tr>'
|
||||
for (const column of this.columns) {
|
||||
const nowrap = column.nowrap ? ' nowrap' : ''
|
||||
const align = column.align ? ` align="${column.align}"` : ''
|
||||
const colspan = column.colspan ? ` colspan="${column.colspan}"` : ''
|
||||
|
||||
output += `<th${align}${nowrap}${colspan}>${column.name}</th>`
|
||||
}
|
||||
output += '</tr>\r\n </thead>\r\n'
|
||||
|
||||
output += ' <tbody>\r\n'
|
||||
for (const row of this.data) {
|
||||
output += ' <tr>'
|
||||
for (const item of row) {
|
||||
const nowrap = item.nowrap ? ' nowrap' : ''
|
||||
const align = item.align ? ` align="${item.align}"` : ''
|
||||
const colspan = item.colspan ? ` colspan="${item.colspan}"` : ''
|
||||
|
||||
output += `<td${align}${nowrap}${colspan}>${item.value}</td>`
|
||||
}
|
||||
output += '</tr>\r\n'
|
||||
}
|
||||
output += ' </tbody>\r\n'
|
||||
|
||||
output += '</table>'
|
||||
|
||||
return output
|
||||
}
|
||||
}
|
|
@ -1,12 +1,17 @@
|
|||
export * from './xml'
|
||||
export * from './channelsParser'
|
||||
export * from './xmltv'
|
||||
export * from './configLoader'
|
||||
export * from './grabber'
|
||||
export * from './job'
|
||||
export * from './queue'
|
||||
export * from './guideManager'
|
||||
export * from './guide'
|
||||
export * from './apiChannel'
|
||||
export * from './apiClient'
|
||||
export * from './channelsParser'
|
||||
export * from './configLoader'
|
||||
export * from './dataLoader'
|
||||
export * from './dataProcessor'
|
||||
export * from './grabber'
|
||||
export * from './guide'
|
||||
export * from './guideManager'
|
||||
export * from './htmlTable'
|
||||
export * from './issueLoader'
|
||||
export * from './issueParser'
|
||||
export * from './job'
|
||||
export * from './proxyParser'
|
||||
export * from './queue'
|
||||
export * from './queueCreator'
|
||||
export * from './xml'
|
||||
export * from './xmltv'
|
||||
|
|
36
scripts/core/issueLoader.ts
Normal file
36
scripts/core/issueLoader.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { restEndpointMethods } from '@octokit/plugin-rest-endpoint-methods'
|
||||
import { paginateRest } from '@octokit/plugin-paginate-rest'
|
||||
import { TESTING, OWNER, REPO } from '../constants'
|
||||
import { Collection } from '@freearhey/core'
|
||||
import { Octokit } from '@octokit/core'
|
||||
import { IssueParser } from './'
|
||||
|
||||
const CustomOctokit = Octokit.plugin(paginateRest, restEndpointMethods)
|
||||
const octokit = new CustomOctokit()
|
||||
|
||||
export class IssueLoader {
|
||||
async load(props?: { labels: string[] | string }) {
|
||||
let labels = ''
|
||||
if (props && props.labels) {
|
||||
labels = Array.isArray(props.labels) ? props.labels.join(',') : props.labels
|
||||
}
|
||||
let issues: object[] = []
|
||||
if (TESTING) {
|
||||
issues = (await import('../../tests/__data__/input/sites_update/issues.mjs')).default
|
||||
} else {
|
||||
issues = await octokit.paginate(octokit.rest.issues.listForRepo, {
|
||||
owner: OWNER,
|
||||
repo: REPO,
|
||||
per_page: 100,
|
||||
labels,
|
||||
headers: {
|
||||
'X-GitHub-Api-Version': '2022-11-28'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const parser = new IssueParser()
|
||||
|
||||
return new Collection(issues).map(parser.parse)
|
||||
}
|
||||
}
|
34
scripts/core/issueParser.ts
Normal file
34
scripts/core/issueParser.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { Dictionary } from '@freearhey/core'
|
||||
import { Issue } from '../models'
|
||||
|
||||
const FIELDS = new Dictionary({
|
||||
Site: 'site'
|
||||
})
|
||||
|
||||
export class IssueParser {
|
||||
parse(issue: { number: number; body: string; labels: { name: string }[] }): Issue {
|
||||
const fields = issue.body.split('###')
|
||||
|
||||
const data = new Dictionary()
|
||||
fields.forEach((field: string) => {
|
||||
const parsed = field.split(/\r?\n/).filter(Boolean)
|
||||
let _label = parsed.shift()
|
||||
_label = _label ? _label.trim() : ''
|
||||
let _value = parsed.join('\r\n')
|
||||
_value = _value ? _value.trim() : ''
|
||||
|
||||
if (!_label || !_value) return data
|
||||
|
||||
const id: string = FIELDS.get(_label)
|
||||
const value: string = _value === '_No response_' || _value === 'None' ? '' : _value
|
||||
|
||||
if (!id) return
|
||||
|
||||
data.set(id, value)
|
||||
})
|
||||
|
||||
const labels = issue.labels.map(label => label.name)
|
||||
|
||||
return new Issue({ number: issue.number, labels, data })
|
||||
}
|
||||
}
|
27
scripts/core/proxyParser.ts
Normal file
27
scripts/core/proxyParser.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { URL } from 'node:url'
|
||||
|
||||
type ProxyParserResult = {
|
||||
protocol: string | null
|
||||
auth: {
|
||||
username: string | null
|
||||
password: string | null
|
||||
}
|
||||
host: string
|
||||
port: number | null
|
||||
}
|
||||
|
||||
export class ProxyParser {
|
||||
parse(_url: string): ProxyParserResult {
|
||||
const parsed = new URL(_url)
|
||||
|
||||
return {
|
||||
protocol: parsed.protocol.replace(':', '') || null,
|
||||
auth: {
|
||||
username: parsed.username || null,
|
||||
password: parsed.password || null
|
||||
},
|
||||
host: parsed.hostname,
|
||||
port: parsed.port ? parseInt(parsed.port) : null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
import { Storage, Collection, DateTime, Logger } from '@freearhey/core'
|
||||
import { ChannelsParser, ConfigLoader, ApiChannel, Queue } from './'
|
||||
import { ChannelsParser, ConfigLoader, Queue } from './'
|
||||
import { SITES_DIR, DATA_DIR } from '../constants'
|
||||
import { Channel, SiteConfig } from 'epg-grabber'
|
||||
import { SiteConfig } from 'epg-grabber'
|
||||
import path from 'path'
|
||||
import { GrabOptions } from '../commands/epg/grab'
|
||||
import { Channel } from '../models'
|
||||
|
||||
type QueueCreatorProps = {
|
||||
logger: Logger
|
||||
|
@ -32,23 +33,24 @@ export class QueueCreator {
|
|||
|
||||
async create(): Promise<Queue> {
|
||||
const channelsContent = await this.dataStorage.json('channels.json')
|
||||
const channels = new Collection(channelsContent).map(data => new ApiChannel(data))
|
||||
const channels = new Collection(channelsContent).map(data => new Channel(data))
|
||||
|
||||
const queue = new Queue()
|
||||
for (const channel of this.parsedChannels.all()) {
|
||||
if (!channel.site || !channel.site_id || !channel.name) continue
|
||||
if (this.options.lang && channel.lang !== this.options.lang) continue
|
||||
|
||||
const configPath = path.resolve(SITES_DIR, `${channel.site}/${channel.site}.config.js`)
|
||||
const config: SiteConfig = await this.configLoader.load(configPath)
|
||||
|
||||
if (channel.xmltv_id) {
|
||||
const found: ApiChannel = channels.first(
|
||||
(_channel: ApiChannel) => _channel.id === channel.xmltv_id
|
||||
)
|
||||
if (found) {
|
||||
channel.logo = found.logo
|
||||
channel.name = found.name
|
||||
if (!channel.icon) {
|
||||
const found: Channel = channels.first(
|
||||
(_channel: Channel) => _channel.id === channel.xmltv_id
|
||||
)
|
||||
|
||||
if (found) {
|
||||
channel.icon = found.logo
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.xmltv_id = channel.site_id
|
||||
|
|
113
scripts/models/channel.ts
Normal file
113
scripts/models/channel.ts
Normal file
|
@ -0,0 +1,113 @@
|
|||
import { ChannelData, ChannelSearchableData } from '../types/channel'
|
||||
import { Collection, Dictionary } from '@freearhey/core'
|
||||
import { Stream, Guide, Feed } from './'
|
||||
|
||||
export class Channel {
|
||||
id: string
|
||||
name: string
|
||||
altNames?: Collection
|
||||
network?: string
|
||||
owners?: Collection
|
||||
countryCode: string
|
||||
subdivisionCode?: string
|
||||
cityName?: string
|
||||
categoryIds?: Collection
|
||||
isNSFW: boolean
|
||||
launched?: string
|
||||
closed?: string
|
||||
replacedBy?: string
|
||||
website?: string
|
||||
logo?: string
|
||||
feeds?: Collection
|
||||
|
||||
constructor(data: ChannelData) {
|
||||
this.id = data.id
|
||||
this.name = data.name
|
||||
this.altNames = new Collection(data.alt_names)
|
||||
this.network = data.network || undefined
|
||||
this.owners = new Collection(data.owners)
|
||||
this.countryCode = data.country
|
||||
this.subdivisionCode = data.subdivision || undefined
|
||||
this.cityName = data.city || undefined
|
||||
this.categoryIds = new Collection(data.categories)
|
||||
this.isNSFW = data.is_nsfw
|
||||
this.launched = data.launched || undefined
|
||||
this.closed = data.closed || undefined
|
||||
this.replacedBy = data.replaced_by || undefined
|
||||
this.website = data.website || undefined
|
||||
this.logo = data.logo
|
||||
}
|
||||
|
||||
withFeeds(feedsGroupedByChannelId: Dictionary): this {
|
||||
this.feeds = new Collection(feedsGroupedByChannelId.get(this.id))
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
getFeeds(): Collection {
|
||||
if (!this.feeds) return new Collection()
|
||||
|
||||
return this.feeds
|
||||
}
|
||||
|
||||
getGuides(): Collection {
|
||||
let guides = new Collection()
|
||||
|
||||
this.getFeeds().forEach((feed: Feed) => {
|
||||
guides = guides.concat(feed.getGuides())
|
||||
})
|
||||
|
||||
return guides
|
||||
}
|
||||
|
||||
getGuideNames(): Collection {
|
||||
return this.getGuides()
|
||||
.map((guide: Guide) => guide.siteName)
|
||||
.uniq()
|
||||
}
|
||||
|
||||
getStreams(): Collection {
|
||||
let streams = new Collection()
|
||||
|
||||
this.getFeeds().forEach((feed: Feed) => {
|
||||
streams = streams.concat(feed.getStreams())
|
||||
})
|
||||
|
||||
return streams
|
||||
}
|
||||
|
||||
getStreamNames(): Collection {
|
||||
return this.getStreams()
|
||||
.map((stream: Stream) => stream.getName())
|
||||
.uniq()
|
||||
}
|
||||
|
||||
getFeedFullNames(): Collection {
|
||||
return this.getFeeds()
|
||||
.map((feed: Feed) => feed.getFullName())
|
||||
.uniq()
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
return this.name || ''
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
return this.id || ''
|
||||
}
|
||||
|
||||
getAltNames(): Collection {
|
||||
return this.altNames || new Collection()
|
||||
}
|
||||
|
||||
getSearchable(): ChannelSearchableData {
|
||||
return {
|
||||
id: this.getId(),
|
||||
name: this.getName(),
|
||||
altNames: this.getAltNames().all(),
|
||||
guideNames: this.getGuideNames().all(),
|
||||
streamNames: this.getStreamNames().all(),
|
||||
feedFullNames: this.getFeedFullNames().all()
|
||||
}
|
||||
}
|
||||
}
|
72
scripts/models/feed.ts
Normal file
72
scripts/models/feed.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
import { Collection, Dictionary } from '@freearhey/core'
|
||||
import { FeedData } from '../types/feed'
|
||||
import { Channel } from './channel'
|
||||
|
||||
export class Feed {
|
||||
channelId: string
|
||||
channel?: Channel
|
||||
id: string
|
||||
name: string
|
||||
isMain: boolean
|
||||
broadcastAreaCodes: Collection
|
||||
languageCodes: Collection
|
||||
timezoneIds: Collection
|
||||
videoFormat: string
|
||||
guides?: Collection
|
||||
streams?: Collection
|
||||
|
||||
constructor(data: FeedData) {
|
||||
this.channelId = data.channel
|
||||
this.id = data.id
|
||||
this.name = data.name
|
||||
this.isMain = data.is_main
|
||||
this.broadcastAreaCodes = new Collection(data.broadcast_area)
|
||||
this.languageCodes = new Collection(data.languages)
|
||||
this.timezoneIds = new Collection(data.timezones)
|
||||
this.videoFormat = data.video_format
|
||||
}
|
||||
|
||||
withChannel(channelsKeyById: Dictionary): this {
|
||||
this.channel = channelsKeyById.get(this.channelId)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
withStreams(streamsGroupedById: Dictionary): this {
|
||||
this.streams = new Collection(streamsGroupedById.get(`${this.channelId}@${this.id}`))
|
||||
|
||||
if (this.isMain) {
|
||||
this.streams = this.streams.concat(new Collection(streamsGroupedById.get(this.channelId)))
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
withGuides(guidesGroupedByStreamId: Dictionary): this {
|
||||
this.guides = new Collection(guidesGroupedByStreamId.get(`${this.channelId}@${this.id}`))
|
||||
|
||||
if (this.isMain) {
|
||||
this.guides = this.guides.concat(new Collection(guidesGroupedByStreamId.get(this.channelId)))
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
getGuides(): Collection {
|
||||
if (!this.guides) return new Collection()
|
||||
|
||||
return this.guides
|
||||
}
|
||||
|
||||
getStreams(): Collection {
|
||||
if (!this.streams) return new Collection()
|
||||
|
||||
return this.streams
|
||||
}
|
||||
|
||||
getFullName(): string {
|
||||
if (!this.channel) return ''
|
||||
|
||||
return `${this.channel.name} ${this.name}`
|
||||
}
|
||||
}
|
35
scripts/models/guide.ts
Normal file
35
scripts/models/guide.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import type { GuideData } from '../types/guide'
|
||||
import { uniqueId } from 'lodash'
|
||||
|
||||
export class Guide {
|
||||
channelId?: string
|
||||
feedId?: string
|
||||
siteDomain?: string
|
||||
siteId?: string
|
||||
siteName?: string
|
||||
languageCode?: string
|
||||
|
||||
constructor(data?: GuideData) {
|
||||
if (!data) return
|
||||
|
||||
this.channelId = data.channel
|
||||
this.feedId = data.feed
|
||||
this.siteDomain = data.site
|
||||
this.siteId = data.site_id
|
||||
this.siteName = data.site_name
|
||||
this.languageCode = data.lang
|
||||
}
|
||||
|
||||
getUUID(): string {
|
||||
if (!this.getStreamId() || !this.siteId) return uniqueId()
|
||||
|
||||
return this.getStreamId() + this.siteId
|
||||
}
|
||||
|
||||
getStreamId(): string | undefined {
|
||||
if (!this.channelId) return undefined
|
||||
if (!this.feedId) return this.channelId
|
||||
|
||||
return `${this.channelId}@${this.feedId}`
|
||||
}
|
||||
}
|
6
scripts/models/index.ts
Normal file
6
scripts/models/index.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
export * from './issue'
|
||||
export * from './site'
|
||||
export * from './channel'
|
||||
export * from './feed'
|
||||
export * from './stream'
|
||||
export * from './guide'
|
24
scripts/models/issue.ts
Normal file
24
scripts/models/issue.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { Dictionary } from '@freearhey/core'
|
||||
import { OWNER, REPO } from '../constants'
|
||||
|
||||
type IssueProps = {
|
||||
number: number
|
||||
labels: string[]
|
||||
data: Dictionary
|
||||
}
|
||||
|
||||
export class Issue {
|
||||
number: number
|
||||
labels: string[]
|
||||
data: Dictionary
|
||||
|
||||
constructor({ number, labels, data }: IssueProps) {
|
||||
this.number = number
|
||||
this.labels = labels
|
||||
this.data = data
|
||||
}
|
||||
|
||||
getURL() {
|
||||
return `https://github.com/${OWNER}/${REPO}/issues/${this.number}`
|
||||
}
|
||||
}
|
63
scripts/models/site.ts
Normal file
63
scripts/models/site.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
import { Collection } from '@freearhey/core'
|
||||
import { Issue } from './'
|
||||
|
||||
enum StatusCode {
|
||||
DOWN = 'down',
|
||||
WARNING = 'warning',
|
||||
OK = 'ok'
|
||||
}
|
||||
|
||||
type Status = {
|
||||
code: StatusCode
|
||||
emoji: string
|
||||
}
|
||||
|
||||
type SiteProps = {
|
||||
domain: string
|
||||
totalChannels?: number
|
||||
markedChannels?: number
|
||||
issues: Collection
|
||||
}
|
||||
|
||||
export class Site {
|
||||
domain: string
|
||||
totalChannels: number
|
||||
markedChannels: number
|
||||
issues: Collection
|
||||
|
||||
constructor({ domain, totalChannels = 0, markedChannels = 0, issues }: SiteProps) {
|
||||
this.domain = domain
|
||||
this.totalChannels = totalChannels
|
||||
this.markedChannels = markedChannels
|
||||
this.issues = issues
|
||||
}
|
||||
|
||||
getStatus(): Status {
|
||||
const issuesWithStatusDown = this.issues.filter((issue: Issue) =>
|
||||
issue.labels.find(label => label === 'status:down')
|
||||
)
|
||||
if (issuesWithStatusDown.notEmpty())
|
||||
return {
|
||||
code: StatusCode.DOWN,
|
||||
emoji: '🔴'
|
||||
}
|
||||
|
||||
const issuesWithStatusWarning = this.issues.filter((issue: Issue) =>
|
||||
issue.labels.find(label => label === 'status:warning')
|
||||
)
|
||||
if (issuesWithStatusWarning.notEmpty())
|
||||
return {
|
||||
code: StatusCode.WARNING,
|
||||
emoji: '🟡'
|
||||
}
|
||||
|
||||
return {
|
||||
code: StatusCode.OK,
|
||||
emoji: '🟢'
|
||||
}
|
||||
}
|
||||
|
||||
getIssues(): Collection {
|
||||
return this.issues.map((issue: Issue) => issue.getURL())
|
||||
}
|
||||
}
|
58
scripts/models/stream.ts
Normal file
58
scripts/models/stream.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
import type { StreamData } from '../types/stream'
|
||||
import { Feed, Channel } from './index'
|
||||
|
||||
export class Stream {
|
||||
name?: string
|
||||
url: string
|
||||
id?: string
|
||||
channelId?: string
|
||||
channel?: Channel
|
||||
feedId?: string
|
||||
feed?: Feed
|
||||
filepath?: string
|
||||
line?: number
|
||||
label?: string
|
||||
verticalResolution?: number
|
||||
isInterlaced?: boolean
|
||||
referrer?: string
|
||||
userAgent?: string
|
||||
groupTitle: string = 'Undefined'
|
||||
removed: boolean = false
|
||||
|
||||
constructor(data: StreamData) {
|
||||
const id = data.channel && data.feed ? [data.channel, data.feed].join('@') : data.channel
|
||||
const { verticalResolution, isInterlaced } = parseQuality(data.quality)
|
||||
|
||||
this.id = id || undefined
|
||||
this.channelId = data.channel || undefined
|
||||
this.feedId = data.feed || undefined
|
||||
this.name = data.name || undefined
|
||||
this.url = data.url
|
||||
this.referrer = data.referrer || undefined
|
||||
this.userAgent = data.user_agent || undefined
|
||||
this.verticalResolution = verticalResolution || undefined
|
||||
this.isInterlaced = isInterlaced || undefined
|
||||
this.label = data.label || undefined
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
return this.id || ''
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
return this.name || ''
|
||||
}
|
||||
}
|
||||
|
||||
function parseQuality(quality: string | null): {
|
||||
verticalResolution: number | null
|
||||
isInterlaced: boolean | null
|
||||
} {
|
||||
if (!quality) return { verticalResolution: null, isInterlaced: null }
|
||||
const [, verticalResolutionString] = quality.match(/^(\d+)/) || [null, undefined]
|
||||
const isInterlaced = /i$/i.test(quality)
|
||||
let verticalResolution = 0
|
||||
if (verticalResolutionString) verticalResolution = parseInt(verticalResolutionString)
|
||||
|
||||
return { verticalResolution, isInterlaced }
|
||||
}
|
16
scripts/templates/_config.js
Normal file
16
scripts/templates/_config.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
module.exports = {
|
||||
site: '<DOMAIN>',
|
||||
url({ channel, date }) {
|
||||
return `https://example.com/api/${channel.site_id}/${date.format('YYYY-MM-DD')}`
|
||||
},
|
||||
parser({ content }) {
|
||||
try {
|
||||
return JSON.parse(content)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
},
|
||||
channels() {
|
||||
return []
|
||||
}
|
||||
}
|
21
scripts/templates/_readme.md
Normal file
21
scripts/templates/_readme.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
# <DOMAIN>
|
||||
|
||||
https://<DOMAIN>
|
||||
|
||||
### Download the guide
|
||||
|
||||
```sh
|
||||
npm run grab --- --site=<DOMAIN>
|
||||
```
|
||||
|
||||
### Update channel list
|
||||
|
||||
```sh
|
||||
npm run channels:parse --- --config=./sites/<DOMAIN>/<DOMAIN>.config.js --output=./sites/<DOMAIN>/<DOMAIN>.channels.xml
|
||||
```
|
||||
|
||||
### Test
|
||||
|
||||
```sh
|
||||
npm test --- <DOMAIN>
|
||||
```
|
3
scripts/templates/_sites.md
Normal file
3
scripts/templates/_sites.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Sites
|
||||
|
||||
_TABLE_
|
38
scripts/templates/_test.js
Normal file
38
scripts/templates/_test.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
const { parser, url } = require('./<DOMAIN>.config.js')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
dayjs.extend(customParseFormat)
|
||||
dayjs.extend(utc)
|
||||
|
||||
const date = dayjs.utc('2025-01-12', 'YYYY-MM-DD').startOf('d')
|
||||
const channel = { site_id: 'bbc1' }
|
||||
|
||||
it('can generate valid url', () => {
|
||||
expect(url({ channel, date })).toBe('https://example.com/api/bbc1/2025-01-12')
|
||||
})
|
||||
|
||||
it('can parse response', () => {
|
||||
const content =
|
||||
'[{"title":"Program 1","start":"2025-01-12T00:00:00.000Z","stop":"2025-01-12T00:30:00.000Z"},{"title":"Program 2","start":"2025-01-12T00:30:00.000Z","stop":"2025-01-12T01:00:00.000Z"}]'
|
||||
|
||||
const results = parser({ content })
|
||||
|
||||
expect(results.length).toBe(2)
|
||||
expect(results[0]).toMatchObject({
|
||||
title: 'Program 1',
|
||||
start: '2025-01-12T00:00:00.000Z',
|
||||
stop: '2025-01-12T00:30:00.000Z'
|
||||
})
|
||||
expect(results[1]).toMatchObject({
|
||||
title: 'Program 2',
|
||||
start: '2025-01-12T00:30:00.000Z',
|
||||
stop: '2025-01-12T01:00:00.000Z'
|
||||
})
|
||||
})
|
||||
|
||||
it('can handle empty guide', () => {
|
||||
const results = parser({ content: '' })
|
||||
|
||||
expect(results).toMatchObject([])
|
||||
})
|
28
scripts/types/channel.d.ts
vendored
Normal file
28
scripts/types/channel.d.ts
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { Collection } from '@freearhey/core'
|
||||
|
||||
export type ChannelData = {
|
||||
id: string
|
||||
name: string
|
||||
alt_names: string[]
|
||||
network: string
|
||||
owners: Collection
|
||||
country: string
|
||||
subdivision: string
|
||||
city: string
|
||||
categories: Collection
|
||||
is_nsfw: boolean
|
||||
launched: string
|
||||
closed: string
|
||||
replaced_by: string
|
||||
website: string
|
||||
logo: string
|
||||
}
|
||||
|
||||
export type ChannelSearchableData = {
|
||||
id: string
|
||||
name: string
|
||||
altNames: string[]
|
||||
guideNames: string[]
|
||||
streamNames: string[]
|
||||
feedFullNames: string[]
|
||||
}
|
19
scripts/types/dataLoader.d.ts
vendored
Normal file
19
scripts/types/dataLoader.d.ts
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { Storage } from '@freearhey/core'
|
||||
|
||||
export type DataLoaderProps = {
|
||||
storage: Storage
|
||||
}
|
||||
|
||||
export type DataLoaderData = {
|
||||
countries: object | object[]
|
||||
regions: object | object[]
|
||||
subdivisions: object | object[]
|
||||
languages: object | object[]
|
||||
categories: object | object[]
|
||||
blocklist: object | object[]
|
||||
channels: object | object[]
|
||||
feeds: object | object[]
|
||||
timezones: object | object[]
|
||||
guides: object | object[]
|
||||
streams: object | object[]
|
||||
}
|
12
scripts/types/dataProcessor.d.ts
vendored
Normal file
12
scripts/types/dataProcessor.d.ts
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Collection, Dictionary } from '@freearhey/core'
|
||||
|
||||
export type DataProcessorData = {
|
||||
feedsGroupedByChannelId: Dictionary
|
||||
guidesGroupedByStreamId: Dictionary
|
||||
streamsGroupedById: Dictionary
|
||||
channelsKeyById: Dictionary
|
||||
channels: Collection
|
||||
streams: Collection
|
||||
guides: Collection
|
||||
feeds: Collection
|
||||
}
|
12
scripts/types/feed.d.ts
vendored
Normal file
12
scripts/types/feed.d.ts
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Collection } from '@freearhey/core'
|
||||
|
||||
export type FeedData = {
|
||||
channel: string
|
||||
id: string
|
||||
name: string
|
||||
is_main: boolean
|
||||
broadcast_area: Collection
|
||||
languages: Collection
|
||||
timezones: Collection
|
||||
video_format: string
|
||||
}
|
8
scripts/types/guide.d.ts
vendored
Normal file
8
scripts/types/guide.d.ts
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
export type GuideData = {
|
||||
channel: string
|
||||
feed: string
|
||||
site: string
|
||||
site_id: string
|
||||
site_name: string
|
||||
lang: string
|
||||
}
|
10
scripts/types/stream.d.ts
vendored
Normal file
10
scripts/types/stream.d.ts
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
export type StreamData = {
|
||||
channel: string | null
|
||||
feed: string | null
|
||||
name?: string
|
||||
url: string
|
||||
referrer: string | null
|
||||
user_agent: string | null
|
||||
quality: string | null
|
||||
label: string | null
|
||||
}
|
|
@ -27,7 +27,7 @@ module.exports = {
|
|||
const stop = start.add(1, 'h')
|
||||
programs.push({
|
||||
title: parseTitle($item),
|
||||
icon: parseIcon($item),
|
||||
image: parseImage($item),
|
||||
description: parseDescription($item),
|
||||
start,
|
||||
stop
|
||||
|
@ -44,7 +44,7 @@ function parseStart($item, date) {
|
|||
return dayjs.tz(`${date.format('YYYY-MM-DD')} ${time}`, 'YYYY-MM-DD HH:mm', 'Asia/Jerusalem')
|
||||
}
|
||||
|
||||
function parseIcon($item) {
|
||||
function parseImage($item) {
|
||||
const backgroundImage = $item('a > div.guide_info_group > div.guide_info_pict').css(
|
||||
'background-image'
|
||||
)
|
||||
|
|
|
@ -31,14 +31,14 @@ it('can parse response', () => {
|
|||
start: '2022-03-06T04:30:00.000Z',
|
||||
stop: '2022-03-06T07:10:00.000Z',
|
||||
title: 'Слепая',
|
||||
icon: 'https://www.9tv.co.il/download/pictures/img_id=8484.jpg',
|
||||
image: 'https://www.9tv.co.il/download/pictures/img_id=8484.jpg',
|
||||
description:
|
||||
'Она не очень любит говорить о себе или о том, кто и зачем к ней обращается. Живет уединенно, в глуши. Но тех, кто приходит -принимает. Она видит судьбы.'
|
||||
},
|
||||
{
|
||||
start: '2022-03-06T07:10:00.000Z',
|
||||
stop: '2022-03-06T08:10:00.000Z',
|
||||
icon: 'https://www.9tv.co.il/download/pictures/img_id=23694.jpg',
|
||||
image: 'https://www.9tv.co.il/download/pictures/img_id=23694.jpg',
|
||||
title: 'Орел и решка. Морской сезон',
|
||||
description: 'Орел и решка. Морской сезон. Ведущие -Алина Астровская и Коля Серга.'
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@ https://www.9tv.co.il/BroadcastSchedule
|
|||
### Download the guide
|
||||
|
||||
```sh
|
||||
npm run grab -- --site=9tv.co.il
|
||||
npm run grab --- --site=9tv.co.il
|
||||
```
|
||||
|
||||
### Test
|
||||
|
||||
```sh
|
||||
npm test -- 9tv.co.il
|
||||
npm test --- 9tv.co.il
|
||||
```
|
||||
|
|
1
sites/abc.net.au/__data__/content.json
Normal file
1
sites/abc.net.au/__data__/content.json
Normal file
File diff suppressed because one or more lines are too long
8
sites/abc.net.au/__data__/no_content.html
Normal file
8
sites/abc.net.au/__data__/no_content.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Error
|
||||
><code>NoSuchKey</code><Message>The specified key does not exist.</Message
|
||||
><Key>processed/Sydney_2026-02-04.json</Key><RequestId>A8BGG30W2N9P97Z1</RequestId
|
||||
><HostId
|
||||
>4NlYzMSR9t2HPBctGhbCKPEBuFdVxtbuyLIOA7uTL28R6/ooqneS1TTwVa7PkTt7gr9yyopqCKk=</HostId
|
||||
></Error
|
||||
>
|
|
@ -1,543 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SPREE">SPREE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#TENHD">TENHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#7HD">7HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#9Rush">9Rush</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SPREE">SPREE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#TENHD">TENHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#PrimS">PrimS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SNR">SNR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#DDT">DDT</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#SC">SC</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#7HD">7HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#10Nth">10Nth</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#NBN">NBN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#Prime">Prime</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SNR">SNR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SC">SC</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SHD7">SHD7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#TDHD">TDHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#TDT">TDT</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#7HD">7HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#9Rush">9Rush</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SPREE">SPREE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#TENHD">TENHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#7GTS">7GTS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#10Nth">10Nth</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#Imp">Imp</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#NBN">NBN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#PrimN">PrimN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#PrimS">PrimS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SNR">SNR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#7C">7C</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#Imp">Imp</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#7HD">7HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#9Rush">9Rush</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SPREE">SPREE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#TENHD">TENHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7C">7C</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7QLD">7QLD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7TWOQ">7TWOQ</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#Imp">Imp</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SNR">SNR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#7C">7C</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#7GTS">7GTS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#Imp">Imp</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SC9">SC9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SNR">SNR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#WIN9">WIN9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#WIN10">WIN10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SC">SC</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SHD7">SHD7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#TDHD">TDHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#TDT">TDT</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#Prime">Prime</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SNR">SNR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#WinSA">WinSA</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#GWN">GWN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#WDT">WDT</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="7bravoAdelaide.au" site_id="Adelaide#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="7bravoSydney.au" site_id="Sydney#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="7flixAdelaide.au" site_id="Adelaide#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="7flixSydney.au" site_id="Sydney#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="7HDAdelaide.au" site_id="Adelaide#7HD">7HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="7mateAdelaide.au" site_id="Adelaide#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="7mateSydney.au" site_id="Sydney#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="7twoAdelaide.au" site_id="Adelaide#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="7twoSydney.au" site_id="Sydney#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="9GemSydney.au" site_id="Sydney#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="9GoSydney.au" site_id="Sydney#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="9HDAdelaide.au" site_id="Adelaide#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="9LifeAdelaide.au" site_id="Adelaide#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="9LifeSydney.au" site_id="Sydney#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="9RushAdelaide.au" site_id="Adelaide#9Rush">9Rush</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="9RushSydney.au" site_id="Sydney#9Rush">9Rush</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="10BoldSydney.au" site_id="Sydney#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="10PeachSydney.au" site_id="Sydney#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="10ShakeSydney.au" site_id="Sydney#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCAustralia.au" site_id="Sydney#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCKidsSydney.au" site_id="Sydney#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCMESydney.au" site_id="Sydney#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCTVNSW.au" site_id="New South Wales#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCTVNT.au" site_id="Northern Territory#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCTVPlusSydney.au" site_id="Sydney#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCTVQLD.au" site_id="Queensland#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCTVSA.au" site_id="South Australia#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCTVSydney.au" site_id="Sydney#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCTVSydney.au" site_id="Sydney#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCTVTAS.au" site_id="Tasmania#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCTVVIC.au" site_id="Victoria#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="ABCTVWA.au" site_id="Western Australia#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="C31Melbourne.au" site_id="Melbourne#31">31</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="Channel7Adelaide.au" site_id="Adelaide#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="Channel7Sydney.au" site_id="Sydney#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="Channel7Sydney.au" site_id="Sydney#7HD">7HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="Channel9Adelaide.au" site_id="Adelaide#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="Channel9Sydney.au" site_id="Sydney#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="Channel9Sydney.au" site_id="Sydney#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="10Adelaide.au" site_id="Adelaide#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="10Sydney.au" site_id="Sydney#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="10Sydney.au" site_id="Sydney#TENHD">TENHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="Channel44.au" site_id="Adelaide#44">44</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="NITVAdelaide.au" site_id="Adelaide#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="NITVSydney.au" site_id="Sydney#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="Racingcom.au" site_id="Sydney#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="SBSAdelaide.au" site_id="Adelaide#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="SBSFoodSydney.au" site_id="Sydney#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="SBSSydney.au" site_id="Sydney#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="SBSSydney.au" site_id="Sydney#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="SBSVicelandSydney.au" site_id="Sydney#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="SBSWorldMoviesSydney.au" site_id="Sydney#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="SBSWorldWatchSydney.au" site_id="Sydney#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="SpreeTV.au" site_id="Sydney#SPREE">SPREE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="TVSN.au" site_id="Sydney#TVSN">TVSN</channel>
|
||||
</channels>
|
|
@ -19,7 +19,7 @@ module.exports = {
|
|||
url({ date, channel }) {
|
||||
const [region] = channel.site_id.split('#')
|
||||
|
||||
return `https://epg.abctv.net.au/processed/${region}_${date.format('YYYY-MM-DD')}.json`
|
||||
return `https://cdn.iview.abc.net.au/epg/processed/${region}_${date.format('YYYY-MM-DD')}.json`
|
||||
},
|
||||
parser({ content, channel }) {
|
||||
let programs = []
|
||||
|
@ -33,7 +33,7 @@ module.exports = {
|
|||
season: parseSeason(item),
|
||||
episode: parseEpisode(item),
|
||||
rating: parseRating(item),
|
||||
icon: parseIcon(item),
|
||||
image: parseImage(item),
|
||||
start: parseTime(item.start_time),
|
||||
stop: parseTime(item.end_time)
|
||||
})
|
||||
|
@ -41,42 +41,43 @@ module.exports = {
|
|||
|
||||
return programs
|
||||
},
|
||||
async channels() {
|
||||
async channels({ region = 'syd' }) {
|
||||
const now = dayjs()
|
||||
const regions = [
|
||||
'Sydney',
|
||||
'Melbourne',
|
||||
'Brisbane',
|
||||
'GoldCoast',
|
||||
'Perth',
|
||||
'Adelaide',
|
||||
'Hobart',
|
||||
'Darwin',
|
||||
'Canberra',
|
||||
'New South Wales',
|
||||
'Victoria',
|
||||
'Townsville',
|
||||
'Queensland',
|
||||
'Western Australia',
|
||||
'South Australia',
|
||||
'Tasmania',
|
||||
'Northern Territory'
|
||||
]
|
||||
const regions = {
|
||||
syd: 'Sydney',
|
||||
mel: 'Melbourne',
|
||||
bri: 'Brisbane',
|
||||
gc: 'GoldCoast',
|
||||
per: 'Perth',
|
||||
adl: 'Adelaide',
|
||||
hbr: 'Hobart',
|
||||
drw: 'Darwin',
|
||||
cbr: 'Canberra',
|
||||
nsw: 'New South Wales',
|
||||
vic: 'Victoria',
|
||||
tsv: 'Townsville',
|
||||
qld: 'Queensland',
|
||||
wa: 'Western Australia',
|
||||
sa: 'South Australia',
|
||||
tas: 'Tasmania',
|
||||
nt: 'Northern Territory'
|
||||
}
|
||||
|
||||
let channels = []
|
||||
for (let region of regions) {
|
||||
const data = await axios
|
||||
.get(`https://epg.abctv.net.au/processed/${region}_${now.format('YYYY-MM-DD')}.json`)
|
||||
.then(r => r.data)
|
||||
.catch(console.log)
|
||||
const regionName = regions[region]
|
||||
const data = await axios
|
||||
.get(
|
||||
`https://cdn.iview.abc.net.au/epg/processed/${regionName}_${now.format('YYYY-MM-DD')}.json`
|
||||
)
|
||||
.then(r => r.data)
|
||||
.catch(console.log)
|
||||
|
||||
for (let item of data.schedule) {
|
||||
channels.push({
|
||||
lang: 'en',
|
||||
site_id: `${region}#${item.channel}`,
|
||||
name: item.channel
|
||||
})
|
||||
}
|
||||
for (let item of data.schedule) {
|
||||
channels.push({
|
||||
lang: 'en',
|
||||
site_id: `${regionName}#${item.channel}`,
|
||||
name: item.channel
|
||||
})
|
||||
}
|
||||
|
||||
return channels
|
||||
|
@ -92,7 +93,7 @@ function parseItems(content, channel) {
|
|||
const [, channelId] = channel.site_id.split('#')
|
||||
const channelData = data.schedule.find(i => i.channel == channelId)
|
||||
return channelData.listing && Array.isArray(channelData.listing) ? channelData.listing : []
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +107,7 @@ function parseEpisode(item) {
|
|||
function parseTime(time) {
|
||||
return dayjs.tz(time, 'YYYY-MM-DD HH:mm', 'Australia/Sydney')
|
||||
}
|
||||
function parseIcon(item) {
|
||||
function parseImage(item) {
|
||||
return item.image_file
|
||||
? `https://www.abc.net.au/tv/common/images/publicity/${item.image_file}`
|
||||
: null
|
||||
|
|
|
@ -1,54 +1,51 @@
|
|||
const { parser, url } = require('./abc.net.au.config.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
dayjs.extend(utc)
|
||||
|
||||
const date = dayjs.utc('2022-12-22', 'YYYY-MM-DD').startOf('d')
|
||||
const channel = {
|
||||
site_id: 'Sydney#ABC1',
|
||||
xmltv_id: 'ABCTV.au'
|
||||
}
|
||||
const date = dayjs.utc('2025-02-04', 'YYYY-MM-DD').startOf('d')
|
||||
const channel = { site_id: 'Sydney#ABC1' }
|
||||
|
||||
it('can generate valid url', () => {
|
||||
expect(url({ date, channel })).toBe('https://epg.abctv.net.au/processed/Sydney_2022-12-22.json')
|
||||
expect(url({ date, channel })).toBe(
|
||||
'https://cdn.iview.abc.net.au/epg/processed/Sydney_2025-02-04.json'
|
||||
)
|
||||
})
|
||||
|
||||
it('can parse response', () => {
|
||||
const content =
|
||||
'{"date":"2022-12-22","region":"Sydney","schedule":[{"channel":"ABC1","listing":[{"consumer_advice":"Adult Themes, Drug Use, Violence","rating":"M","show_id":912747,"repeat":true,"description":"When tragedy strikes close to home, it puts head teacher Noah Taylor on a collision course with the criminals responsible. Can the Lyell team help him stop the cycle of violence?","title":"Silent Witness","crid":"ZW2178A004S00","start_time":"2022-12-22T00:46:00","series-crid":"ZW2178A","live":false,"captioning":true,"show_type":"Episode","series_num":22,"episode_title":"Lift Up Your Hearts (part Two)","length":58,"onair_title":"Silent Witness","end_time":"2022-12-22T01:44:00","genres":["Entertainment"],"image_file":"ZW2178A004S00_460.jpg","prog_slug":"silent-witness","episode_num":4}]}]}'
|
||||
|
||||
const result = parser({ content, channel }).map(p => {
|
||||
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'))
|
||||
const results = parser({ content, channel }).map(p => {
|
||||
p.start = p.start.toJSON()
|
||||
p.stop = p.stop.toJSON()
|
||||
return p
|
||||
})
|
||||
|
||||
expect(result).toMatchObject([
|
||||
{
|
||||
title: 'Silent Witness',
|
||||
sub_title: 'Lift Up Your Hearts (part Two)',
|
||||
description:
|
||||
'When tragedy strikes close to home, it puts head teacher Noah Taylor on a collision course with the criminals responsible. Can the Lyell team help him stop the cycle of violence?',
|
||||
category: ['Entertainment'],
|
||||
rating: {
|
||||
system: 'ACB',
|
||||
value: 'M'
|
||||
},
|
||||
season: 22,
|
||||
episode: 4,
|
||||
icon: 'https://www.abc.net.au/tv/common/images/publicity/ZW2178A004S00_460.jpg',
|
||||
start: '2022-12-21T13:46:00.000Z',
|
||||
stop: '2022-12-21T14:44:00.000Z'
|
||||
}
|
||||
])
|
||||
expect(results.length).toBe(30)
|
||||
expect(results[0]).toMatchObject({
|
||||
title: "Julia Zemiro's Home Delivery",
|
||||
sub_title: 'Maggie Beer',
|
||||
description:
|
||||
"The kitchen Maggie Beer made famous in The Cook and the Chef may be in the heart of the Barossa Valley, but our most beloved foodie meets up with Julia where she grew up in Sydney's Lakemba.",
|
||||
category: ['Entertainment', 'Factual'],
|
||||
rating: {
|
||||
system: 'ACB',
|
||||
value: 'G'
|
||||
},
|
||||
season: null,
|
||||
episode: null,
|
||||
image: 'https://www.abc.net.au/tv/common/images/publicity/LE1761H002S00_460.jpg',
|
||||
start: '2025-02-03T12:40:00.000Z',
|
||||
stop: '2025-02-03T13:09:00.000Z'
|
||||
})
|
||||
})
|
||||
|
||||
it('can handle empty guide', () => {
|
||||
const result = parser(
|
||||
{
|
||||
content:
|
||||
'<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>processed/Sydney_2023-01-17.json</Key><RequestId>6MRHX5TJ12X39B3Y</RequestId><HostId>59rH6XRMrmkFywg8Kv58iqpI6O1fuOCuEbKa1HRRYa4buByXMBTvAhz8zuAK7X5D+ZN9ZuWxyGs=</HostId></Error>'
|
||||
},
|
||||
const results = parser({
|
||||
content: fs.readFileSync(path.resolve(__dirname, '__data__/no_content.html')),
|
||||
channel
|
||||
)
|
||||
expect(result).toMatchObject([])
|
||||
})
|
||||
|
||||
expect(results).toMatchObject([])
|
||||
})
|
||||
|
|
38
sites/abc.net.au/abc.net.au_adl.channels.xml
Normal file
38
sites/abc.net.au/abc.net.au_adl.channels.xml
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#7HD">7HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#9Rush">9Rush</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#44">44</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#SPREE">SPREE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#TENHD">TENHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Adelaide#YOUTV">YOUTV</channel>
|
||||
</channels>
|
37
sites/abc.net.au/abc.net.au_bri.channels.xml
Normal file
37
sites/abc.net.au/abc.net.au_bri.channels.xml
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#7HD">7HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#9Rush">9Rush</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#SPREE">SPREE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#TENHD">TENHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Brisbane#YOUTV">YOUTV</channel>
|
||||
</channels>
|
35
sites/abc.net.au/abc.net.au_cbr.channels.xml
Normal file
35
sites/abc.net.au/abc.net.au_cbr.channels.xml
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#PrimS">PrimS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#SNR">SNR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Canberra#WINHD">WINHD</channel>
|
||||
</channels>
|
29
sites/abc.net.au/abc.net.au_drw.channels.xml
Normal file
29
sites/abc.net.au/abc.net.au_drw.channels.xml
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#DDT">DDT</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#SC">SC</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Darwin#VICHD">VICHD</channel>
|
||||
</channels>
|
36
sites/abc.net.au/abc.net.au_gc.channels.xml
Normal file
36
sites/abc.net.au/abc.net.au_gc.channels.xml
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#10Nth">10Nth</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#NBN">NBN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#Prime">Prime</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#SNR">SNR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="GoldCoast#YOUTV">YOUTV</channel>
|
||||
</channels>
|
35
sites/abc.net.au/abc.net.au_hbr.channels.xml
Normal file
35
sites/abc.net.au/abc.net.au_hbr.channels.xml
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SC">SC</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#SHD7">SHD7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#TDHD">TDHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#TDT">TDT</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Hobart#YOUTV">YOUTV</channel>
|
||||
</channels>
|
38
sites/abc.net.au/abc.net.au_mel.channels.xml
Normal file
38
sites/abc.net.au/abc.net.au_mel.channels.xml
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#7HD">7HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#9Rush">9Rush</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#31">31</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#SPREE">SPREE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#TENHD">TENHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Melbourne#YOUTV">YOUTV</channel>
|
||||
</channels>
|
41
sites/abc.net.au/abc.net.au_nsw.channels.xml
Normal file
41
sites/abc.net.au/abc.net.au_nsw.channels.xml
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#7GTS">7GTS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#10Nth">10Nth</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#Imp">Imp</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#NBN">NBN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#PrimN">PrimN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#PrimS">PrimS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#SNR">SNR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="New South Wales#YOUTV">YOUTV</channel>
|
||||
</channels>
|
25
sites/abc.net.au/abc.net.au_nt.channels.xml
Normal file
25
sites/abc.net.au/abc.net.au_nt.channels.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#7C">7C</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#Imp">Imp</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Northern Territory#VICHD">VICHD</channel>
|
||||
</channels>
|
37
sites/abc.net.au/abc.net.au_per.channels.xml
Normal file
37
sites/abc.net.au/abc.net.au_per.channels.xml
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#7HD">7HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#9Rush">9Rush</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#SPREE">SPREE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#TENHD">TENHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Perth#YOUTV">YOUTV</channel>
|
||||
</channels>
|
39
sites/abc.net.au/abc.net.au_qld.channels.xml
Normal file
39
sites/abc.net.au/abc.net.au_qld.channels.xml
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7C">7C</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7QLD">7QLD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#7TWOQ">7TWOQ</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#Imp">Imp</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#SNR">SNR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Queensland#WINHD">WINHD</channel>
|
||||
</channels>
|
35
sites/abc.net.au/abc.net.au_sa.channels.xml
Normal file
35
sites/abc.net.au/abc.net.au_sa.channels.xml
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#7C">7C</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#7GTS">7GTS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#Imp">Imp</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SC9">SC9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#SNR">SNR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#WIN9">WIN9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#WIN10">WIN10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="South Australia#WINHD">WINHD</channel>
|
||||
</channels>
|
37
sites/abc.net.au/abc.net.au_syd.channels.xml
Normal file
37
sites/abc.net.au/abc.net.au_syd.channels.xml
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#7HD">7HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#9">9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#9HD">9HD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#9Rush">9Rush</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#SPREE">SPREE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#TENHD">TENHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Sydney#YOUTV">YOUTV</channel>
|
||||
</channels>
|
36
sites/abc.net.au/abc.net.au_tas.channels.xml
Normal file
36
sites/abc.net.au/abc.net.au_tas.channels.xml
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SC">SC</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#SHD7">SHD7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#TDHD">TDHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#TDT">TDT</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Tasmania#YOUTV">YOUTV</channel>
|
||||
</channels>
|
34
sites/abc.net.au/abc.net.au_tsv.channels.xml
Normal file
34
sites/abc.net.au/abc.net.au_tsv.channels.xml
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#7">7</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Townsville#WINHD">WINHD</channel>
|
||||
</channels>
|
38
sites/abc.net.au/abc.net.au_vic.channels.xml
Normal file
38
sites/abc.net.au/abc.net.au_vic.channels.xml
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#7bravo">7bravo</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#7flix">7flix</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ASPIR">ASPIR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#Prime">Prime</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SCA9">SCA9</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SCHD">SCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SHAKE">SHAKE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#SNR">SNR</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#TVSN">TVSN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#WINHD">WINHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#WinSA">WinSA</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Victoria#YOUTV">YOUTV</channel>
|
||||
</channels>
|
29
sites/abc.net.au/abc.net.au_wa.channels.xml
Normal file
29
sites/abc.net.au/abc.net.au_wa.channels.xml
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#7MATE">7MATE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#7TWO">7TWO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#9Life">9Life</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#10">10</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#11">11</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ABC1">ABC1</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ABC2">ABC2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ABC3">ABC3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ABC4KIDS">ABC4KIDS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ABCHD">ABCHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ABCN">ABCN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#GEM">GEM</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#GO">GO</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#GWN">GWN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#NITV">NITV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#ONE">ONE</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#RTV">RTV</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#SBS">SBS</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#SBS2">SBS2</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#SBS3">SBS3</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#SBSHD">SBSHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#SBSWW">SBSWW</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#VICHD">VICHD</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#WDT">WDT</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#WIN">WIN</channel>
|
||||
<channel site="abc.net.au" lang="en" xmltv_id="" site_id="Western Australia#WINHD">WINHD</channel>
|
||||
</channels>
|
|
@ -2,20 +2,40 @@
|
|||
|
||||
https://www.abc.net.au/tv/epg/
|
||||
|
||||
| Region | Code |
|
||||
| ------------------ | ----- |
|
||||
| Sydney | `syd` |
|
||||
| Melbourne | `mel` |
|
||||
| Brisbane | `bri` |
|
||||
| Gold Coast | `gc` |
|
||||
| Perth | `per` |
|
||||
| Adelaide | `adl` |
|
||||
| Hobart | `hbr` |
|
||||
| Darwin | `drw` |
|
||||
| Canberra | `cbr` |
|
||||
| New South Wales | `nsw` |
|
||||
| Victoria | `vic` |
|
||||
| Townsville | `tsv` |
|
||||
| Queensland | `qld` |
|
||||
| Western Australia | `wa` |
|
||||
| South Australia | `sa` |
|
||||
| Tasmania | `tas` |
|
||||
| Northern Territory | `nt` |
|
||||
|
||||
### Download the guide
|
||||
|
||||
```sh
|
||||
npm run grab -- --site=abc.net.au
|
||||
npm run grab --- --channels=sites/abc.net.au/abc.net.au_<REGION_CODE>.channels.xml
|
||||
```
|
||||
|
||||
### Update channel list
|
||||
|
||||
```sh
|
||||
npm run channels:parse -- --config=./sites/abc.net.au/abc.net.au.config.js --output=./sites/abc.net.au/abc.net.au.channels.xml
|
||||
npm run channels:parse --- --config=./sites/abc.net.au/abc.net.au.config.js --output=./sites/abc.net.au/abc.net.au_<REGION_CODE>.channels.xml --set=region:<REGION_CODE>
|
||||
```
|
||||
|
||||
### Test
|
||||
|
||||
```sh
|
||||
npm test -- abc.net.au
|
||||
npm test --- abc.net.au
|
||||
```
|
||||
|
|
|
@ -30,23 +30,23 @@
|
|||
<channel site="allente.dk" lang="da" xmltv_id="" site_id="1033">France 24 (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="" site_id="1074">Discovery Channel HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="" site_id="1075">Eurosport 1 HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="6eren.dk" site_id="568">6'eren HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="AlJazeeraEnglish.qa" site_id="0344">Al Jazeera English -OTT</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="BBCNewsEurope.uk" site_id="0016">BBC News (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="6eren.dk" site_id="568">6'eren HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="en" xmltv_id="AlJazeera.qa@English" site_id="0344">Al Jazeera English -OTT</channel>
|
||||
<channel site="allente.dk" lang="en" xmltv_id="BBCNews.uk@Europe" site_id="0016">BBC News (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="BoomerangNordic.uk" site_id="0017">Cartoonito (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="Canal9.dk" site_id="0368">CANAL9 HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="CartoonNetworkScandinavia.uk" site_id="0028">Cartoon Network (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="CNBCEurope.uk" site_id="0032">CNBC (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="CNNInternationalEurope.us" site_id="0033">CNN (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="" site_id="0028">Cartoon Network (T)</channel>
|
||||
<channel site="allente.dk" lang="en" xmltv_id="CNBCEurope.uk" site_id="0032">CNBC (T)</channel>
|
||||
<channel site="allente.dk" lang="en" xmltv_id="CNNInternational.us@MENA" site_id="0033">CNN (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="dk4.dk" site_id="0376">dk4 (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="DR1.dk" site_id="452">DR1 HD (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="DR2.dk" site_id="0051">DR2 HD (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="DRRamasjang.dk" site_id="0048">DR Ramasjang (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="Eurosport2.dk" site_id="0367">Eurosport 2 HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="Eurosport2.fr@Denmark" site_id="0367">Eurosport 2 HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="Kanal4.dk" site_id="0064">Kanal 4 HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="Kanal5.dk" site_id="0065">Kanal 5 HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="MTV00s.uk" site_id="0246">MTV 00s (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="MTV80s.uk" site_id="604">MTV 80s (T)</channel>
|
||||
<channel site="allente.dk" lang="en" xmltv_id="MTV00s.uk" site_id="0246">MTV 00s (T)</channel>
|
||||
<channel site="allente.dk" lang="en" xmltv_id="MTV80s.uk" site_id="604">MTV 80s (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="MTVGlobal.uk" site_id="0076">MTV (Nordic) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="NationalGeographic.dk" site_id="0317">National Geographic HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="NickJrScandinavia.nl" site_id="0088">Nick Jr. (T)</channel>
|
||||
|
@ -63,7 +63,7 @@
|
|||
<channel site="allente.dk" lang="da" xmltv_id="TV3Plus.dk" site_id="0248">TV3+ HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="TV3Puls.dk" site_id="665">TV3 Puls HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="TV3Sport.dk" site_id="0200">TV3 Sport HD (D) (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="TV4.se" site_id="0227">TV4 HD (T)</channel>
|
||||
<channel site="allente.dk" lang="sv" xmltv_id="TV4.se" site_id="0227">TV4 HD (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="VFilmAction.se" site_id="0299">V film action HD (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="VFilmFamily.se" site_id="0308">V film family (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="VFilmHits.se" site_id="0322">V film hits HD (T)</channel>
|
||||
|
@ -74,4 +74,4 @@
|
|||
<channel site="allente.dk" lang="da" xmltv_id="VSportGolf.se" site_id="0364">V sport golf HD (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="VSportUltraHD.se" site_id="418">V sport ultra HD (T)</channel>
|
||||
<channel site="allente.dk" lang="da" xmltv_id="Xee.dk" site_id="707">See (D) (T)</channel>
|
||||
</channels>
|
||||
</channels>
|
|
@ -22,7 +22,7 @@ module.exports = {
|
|||
title: item.title,
|
||||
category: item.details.categories,
|
||||
description: item.details.description,
|
||||
icon: item.details.image,
|
||||
image: item.details.image,
|
||||
season: parseSeason(item),
|
||||
episode: parseEpisode(item),
|
||||
start,
|
||||
|
|
|
@ -32,7 +32,8 @@ it('can parse response', () => {
|
|||
category: ['other'],
|
||||
description:
|
||||
'Svenskt träningsprogram från 2021. Styrka. Sofia Åhman leder SVT:s hemmagympapass. Denna gång fokuserar vi på styrka.',
|
||||
icon: 'https://viasatps.api.comspace.se/PS/channeldate/image/viasat.ps/21/2022-08-22/se.cs.svt1.event.A_41214031600.jpg?size=2560x1440',
|
||||
image:
|
||||
'https://viasatps.api.comspace.se/PS/channeldate/image/viasat.ps/21/2022-08-22/se.cs.svt1.event.A_41214031600.jpg?size=2560x1440',
|
||||
season: 4,
|
||||
episode: 1
|
||||
}
|
||||
|
|
|
@ -5,17 +5,17 @@ https://www.allente.dk/tv-guide/
|
|||
### Download the guide
|
||||
|
||||
```sh
|
||||
npm run grab -- --site=allente.dk
|
||||
npm run grab --- --site=allente.dk
|
||||
```
|
||||
|
||||
### Update channel list
|
||||
|
||||
```sh
|
||||
npm run channels:parse -- --config=./sites/allente.dk/allente.dk.config.js --output=./sites/allente.dk/allente.dk.channels.xml
|
||||
npm run channels:parse --- --config=./sites/allente.dk/allente.dk.config.js --output=./sites/allente.dk/allente.dk.channels.xml
|
||||
```
|
||||
|
||||
### Test
|
||||
|
||||
```sh
|
||||
npm test -- allente.dk
|
||||
npm test --- allente.dk
|
||||
```
|
||||
|
|
|
@ -46,21 +46,21 @@
|
|||
<channel site="allente.fi" lang="fi" xmltv_id="" site_id="1086">MTV Urheilu 1 HD (F) (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="" site_id="1087">MTV Urheilu 2 HD (F) (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="" site_id="1088">Eurosport 1 HD (F) (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="BoomerangNordic.uk" site_id="0017">Cartoonito (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="CartoonNetworkScandinavia.uk" site_id="0028">Cartoon Network (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="CNBCEurope.uk" site_id="0032">CNBC (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="CNNInternationalEurope.us" site_id="0033">CNN (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="MTV00s.uk" site_id="0246">MTV 00s (T)</channel>
|
||||
<channel site="allente.fi" lang="da" xmltv_id="BoomerangNordic.uk" site_id="0017">Cartoonito (T)</channel>
|
||||
<channel site="allente.fi" lang="en" xmltv_id="" site_id="0028">Cartoon Network (T)</channel>
|
||||
<channel site="allente.fi" lang="en" xmltv_id="CNBCEurope.uk" site_id="0032">CNBC (T)</channel>
|
||||
<channel site="allente.fi" lang="en" xmltv_id="CNNInternational.us@MENA" site_id="0033">CNN (T)</channel>
|
||||
<channel site="allente.fi" lang="en" xmltv_id="MTV00s.uk" site_id="0246">MTV 00s (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="MTVGlobal.uk" site_id="0080">MTV (Nordic) (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="NationalGeographic.fi" site_id="0084">National Geographic HD (S/F) (T)</channel>
|
||||
<channel site="allente.fi" lang="sv" xmltv_id="NationalGeographic.fi" site_id="0084">National Geographic HD (S/F) (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="NickJrScandinavia.nl" site_id="0088">Nick Jr. (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VFilmAction.se" site_id="0299">V film action HD (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VFilmFamily.se" site_id="0308">V film family (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VFilmHits.se" site_id="0322">V film hits HD (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VFilmPremiere.se" site_id="0321">V film premiere HD (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VSport1.fi" site_id="0159">V sport 1 Suomi HD (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VSport1.se@Finland" site_id="0159">V sport 1 Suomi HD (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VSport1.se" site_id="0362">V sport 1 HD (S/F) (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VSport2.fi" site_id="488">V sport 2 Suomi HD (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VSport2.se@Finland" site_id="488">V sport 2 Suomi HD (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VSportFootball.se" site_id="0269">V sport football HD (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VSportGolf.se" site_id="0364">V sport golf HD (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VSportLive1.se" site_id="0255">V sport live 1 (T)</channel>
|
||||
|
@ -71,4 +71,4 @@
|
|||
<channel site="allente.fi" lang="fi" xmltv_id="VSportPremium.se" site_id="527">V sport premium HD (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VSportUltraHD.se" site_id="418">V sport ultra HD (T)</channel>
|
||||
<channel site="allente.fi" lang="fi" xmltv_id="VSportVinter.se" site_id="0363">V sport vinter HD (T)</channel>
|
||||
</channels>
|
||||
</channels>
|
|
@ -22,7 +22,7 @@ module.exports = {
|
|||
title: item.title,
|
||||
category: item.details.categories,
|
||||
description: item.details.description,
|
||||
icon: item.details.image,
|
||||
image: item.details.image,
|
||||
season: parseSeason(item),
|
||||
episode: parseEpisode(item),
|
||||
start,
|
||||
|
|
|
@ -32,7 +32,8 @@ it('can parse response', () => {
|
|||
category: ['other'],
|
||||
description:
|
||||
'Svenskt träningsprogram från 2021. Styrka. Sofia Åhman leder SVT:s hemmagympapass. Denna gång fokuserar vi på styrka.',
|
||||
icon: 'https://viasatps.api.comspace.se/PS/channeldate/image/viasat.ps/21/2022-08-22/se.cs.svt1.event.A_41214031600.jpg?size=2560x1440',
|
||||
image:
|
||||
'https://viasatps.api.comspace.se/PS/channeldate/image/viasat.ps/21/2022-08-22/se.cs.svt1.event.A_41214031600.jpg?size=2560x1440',
|
||||
season: 4,
|
||||
episode: 1
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue