11"""Module for live channels."""
2- from concurrent import futures
32import json
43from urllib .parse import urlencode
54
65import requests
76
8- from resources .lib .utils import save_cookies , loadCookies , log , get_iptv_channels_file
7+ from resources .lib .utils import log , get_iptv_channels_file
98from resources .lib .cbc import CBC
109from resources .lib .gemv2 import GemV2
1110
12- LIST_URL = 'https://services.radio-canada.ca/ott/catalog/v2/gem/home?device=web'
13- LIST_ELEMENT = '2415871718'
11+ LIST_URL = 'https://gem.cbc.ca/_next/data/7ByKb_CElwT2xVJeTO43g/live.json'
1412
1513class LiveChannels :
1614 """Class for live channels."""
@@ -19,9 +17,6 @@ def __init__(self):
1917 """Initialize the live channels class."""
2018 # Create requests session object
2119 self .session = requests .Session ()
22- session_cookies = loadCookies ()
23- if session_cookies is not None :
24- self .session .cookies = session_cookies
2520
2621 def get_live_channels (self ):
2722 """Get the list of live channels."""
@@ -30,25 +25,48 @@ def get_live_channels(self):
3025 if not resp .status_code == 200 :
3126 log ('ERROR: {} returns status of {}' .format (LIST_URL , resp .status_code ), True )
3227 return None
33- save_cookies (self .session .cookies )
34-
35- ret = None
36- for result in json .loads (resp .content )['lineups' ]['results' ]:
37- if result ['key' ] == LIST_ELEMENT :
38- ret = result ['items' ]
39-
40- future_to_callsign = {}
41- with futures .ThreadPoolExecutor (max_workers = 20 ) as executor :
42- for i , channel in enumerate (ret ):
43- callsign = CBC .get_callsign (channel )
44- future = executor .submit (self .get_channel_metadata , callsign )
45- future_to_callsign [future ] = i
46-
47- for future in futures .as_completed (future_to_callsign ):
48- i = future_to_callsign [future ]
49- metadata = future .result ()
50- ret [i ]['image' ] = metadata ['Metas' ]['imageHR' ]
51- return ret
28+
29+ data = json .loads (resp .content )
30+ page_data = data .get ('pageProps' , {}).get ('data' , {})
31+ streams = page_data .get ('streams' , [])
32+ free_tv_items = page_data .get ('freeTv' , {}).get ('items' , [])
33+
34+ channels = []
35+ for stream in streams :
36+ items = stream .get ('items' , [])
37+ if len (items ) == 0 :
38+ continue
39+
40+ for item in items :
41+ channel = dict (item )
42+ if 'title' not in channel or not channel ['title' ]:
43+ channel ['title' ] = stream .get ('title' )
44+ if 'genericImage' in channel and 'image' not in channel :
45+ channel ['image' ] = channel ['genericImage' ]
46+ channels .append (channel )
47+
48+ for item in free_tv_items :
49+ channel = dict (item )
50+ if 'genericImage' in channel and 'image' not in channel :
51+ channel ['image' ] = channel ['genericImage' ]
52+ channels .append (channel )
53+
54+ unique_channels = []
55+ seen_ids = set ()
56+ for channel in channels :
57+ id_media = channel .get ('idMedia' )
58+
59+ if id_media is None :
60+ unique_channels .append (channel )
61+ continue
62+
63+ if id_media in seen_ids :
64+ continue
65+
66+ seen_ids .add (id_media )
67+ unique_channels .append (channel )
68+
69+ return unique_channels
5270
5371 def get_iptv_channels (self ):
5472 """Get the channels in a IPTV Manager compatible list."""
@@ -99,7 +117,6 @@ def get_channel_metadata(self, id):
99117 if not resp .status_code == 200 :
100118 log ('ERROR: {} returns status of {}' .format (LIST_URL , resp .status_code ), True )
101119 return None
102- save_cookies (self .session .cookies )
103120 return json .loads (resp .content )
104121
105122 @staticmethod
0 commit comments