@@ -527,7 +527,7 @@ def build_menu_from_page(self, url, path):
527527            except  Exception :
528528                pass 
529529
530-     def  build_episode_menu (self , video_id , include_segments = True ,
530+     def  build_episode_menu (self , video_id_or_urn , include_segments = True ,
531531                           segment_option = False , audio = False ):
532532        """ 
533533        Builds a list entry for a episode by a given video id. 
@@ -536,7 +536,7 @@ def build_episode_menu(self, video_id, include_segments=True,
536536        entry for the segment will be created. 
537537
538538        Keyword arguments: 
539-         video_id          -- the id of  the video  
539+         video_id_or_urn   -- the video  id or  the urn  
540540        include_segments -- indicates if the segments (if available) of the 
541541                            video should be included in the list 
542542                            (default: True) 
@@ -545,25 +545,30 @@ def build_episode_menu(self, video_id, include_segments=True,
545545        audio            -- boolean value to indicate if the episode is a 
546546                            radio show (default: False) 
547547        """ 
548-         self .log (f'build_episode_menu, video_id  = { video_id }  )
548+         self .log (f'build_episode_menu, video_id_or_urn  = { video_id_or_urn }  )
549549        content_type  =  'audio'  if  audio  else  'video' 
550-         json_url  =  f'https://il.srgssr.ch/integrationlayer/2.0/{ self .bu }   \
551-             f'mediaComposition/{ content_type } { video_id }  
550+         if  ':'  in  video_id_or_urn :
551+             json_url  =  'https://il.srgssr.ch/integrationlayer/2.0/'  \
552+                        f'mediaComposition/byUrn/{ video_id_or_urn }  
553+             video_id  =  video_id_or_urn .split (':' )[- 1 ]
554+         else :
555+             json_url  =  f'https://il.srgssr.ch/integrationlayer/2.0/{ self .bu }   \
556+                        f'/mediaComposition/{ content_type } { video_id_or_urn }   \
557+                         '.json' 
558+             video_id  =  video_id_or_urn 
552559        self .log (f'build_episode_menu. Open URL { json_url }  )
553560        try :
554561            json_response  =  json .loads (self .open_url (json_url ))
555562        except  Exception :
556-             self .log (f'build_episode_menu: Cannot open json for { video_id }  )
563+             self .log (
564+                 f'build_episode_menu: Cannot open json for { video_id_or_urn }  )
557565            return 
558566
559567        chapter_urn  =  utils .try_get (json_response , 'chapterUrn' )
560568        segment_urn  =  utils .try_get (json_response , 'segmentUrn' )
561569
562-         id_regex  =  r'[a-z]+:[a-z]+:[a-z]+:(?P<id>.+)' 
563-         match_chapter_id  =  re .match (id_regex , chapter_urn )
564-         match_segment_id  =  re .match (id_regex , segment_urn )
565-         chapter_id  =  match_chapter_id .group ('id' ) if  match_chapter_id  else  None 
566-         segment_id  =  match_segment_id .group ('id' ) if  match_segment_id  else  None 
570+         chapter_id  =  chapter_urn .split (':' )[- 1 ] if  chapter_urn  else  None 
571+         segment_id  =  segment_urn .split (':' )[- 1 ] if  segment_urn  else  None 
567572
568573        if  not  chapter_id :
569574            self .log (f'build_episode_menu: No valid chapter URN \  
@@ -588,6 +593,7 @@ def build_episode_menu(self, video_id, include_segments=True,
588593{ video_id } 
589594            return 
590595
596+         # TODO: Simplify 
591597        json_segment_list  =  utils .try_get (
592598            json_chapter , 'segmentList' , data_type = list , default = [])
593599        if  video_id  ==  chapter_id :
@@ -690,20 +696,9 @@ def build_entry_apiv3(self, data, is_show=False, whitelist_ids=None):
690696        url  =  self .build_url (mode = 100 , name = urn )
691697        is_folder  =  True 
692698
693-         # Prevent upcoming live events from being played: 
694-         if  'swisstxt'  in  urn :
695-             url  =  self .build_url (mode = 500 , name = urn )
696-             is_folder  =  False 
697- 
698699        xbmcplugin .addDirectoryItem (
699700            self .handle , url , list_item , isFolder = is_folder )
700701
701-     def  playback_not_supported_dialog (self , urn ):
702-         heading  =  self .language (30500 )
703-         message  =  self .language (30501 ) +  f' { urn }   +  self .language (30502 )
704-         dialog  =  xbmcgui .Dialog ()
705-         dialog .notification (heading , message )
706- 
707702    def  build_menu_by_urn (self , urn ):
708703        """ 
709704        Builds a menu from an urn. 
@@ -714,6 +709,10 @@ def build_menu_by_urn(self, urn):
714709        id  =  urn .split (':' )[- 1 ]
715710        if  'show'  in  urn :
716711            self .build_menu_apiv3 (f'videos-by-show-id?showId={ id }  )
712+         elif  'swisstxt'  in  urn :
713+             # Do not include segments for livestreams, 
714+             # they fail to play. 
715+             self .build_episode_menu (urn , include_segments = False )
717716        elif  'video'  in  urn :
718717            self .build_episode_menu (id )
719718        elif  'topic'  in  urn :
@@ -811,7 +810,11 @@ def build_entry(self, json_entry, is_folder=False, audio=False,
811810            url  =  self .build_url (mode = 21 , name = name )
812811        else :
813812            list_item .setProperty ('IsPlayable' , 'true' )
814-             url  =  self .build_url (mode = 50 , name = name )
813+             # TODO: Simplify this, use URN instead of video id everywhere 
814+             if  'swisstxt'  in  urn :
815+                 url  =  self .build_url (mode = 50 , name = urn )
816+             else :
817+                 url  =  self .build_url (mode = 50 , name = name )
815818        xbmcplugin .addDirectoryItem (
816819            self .handle , url , list_item , isFolder = is_folder )
817820
@@ -1329,74 +1332,6 @@ def write_search(self, filename, name, max_entries=10):
13291332    #             continue 
13301333    #         self.build_entry(json_entry) 
13311334
1332-     def  build_live_menu (self , extract_srf3 = False ):
1333-         """ 
1334-         Builds the menu listing the currently available livestreams. 
1335-         """ 
1336-         def  get_live_ids ():
1337-             """ 
1338-             Downloads the main webpage and scrapes it for 
1339-             possible livestreams. If some live events were found, a list 
1340-             of live ids will be returned, otherwise an empty list. 
1341-             """ 
1342-             live_ids  =  []
1343-             webpage  =  self .open_url (self .host_url , use_cache = False )
1344-             event_id_regex  =  r'(?:data-sport-id=\"|eventId=)(?P<live_id>\d+)' 
1345-             try :
1346-                 for  match  in  re .finditer (event_id_regex , webpage ):
1347-                     live_ids .append (match .group ('live_id' ))
1348-             except  StopIteration :
1349-                 pass 
1350-             return  live_ids 
1351- 
1352-         def  get_srf3_live_ids ():
1353-             """ 
1354-             Returns a list of Radio SRF 3 video streams. 
1355-             """ 
1356-             url  =  'https://www.srf.ch/radio-srf-3' 
1357-             webpage  =  self .open_url (url , use_cache = False )
1358-             video_id_regex  =  r'''(?x) 
1359-                                    popupvideoplayer\?id= 
1360-                                    (?P<video_id> 
1361-                                        [a-f0-9]{8}- 
1362-                                        [a-f0-9]{4}- 
1363-                                        [a-f0-9]{4}- 
1364-                                        [a-f0-9]{4}- 
1365-                                        [a-f0-9]{12} 
1366-                                     ) 
1367-                                 ''' 
1368-             live_ids  =  []
1369-             try :
1370-                 for  match  in  re .finditer (video_id_regex , webpage ):
1371-                     live_ids .append (match .group ('video_id' ))
1372-             except  StopIteration :
1373-                 pass 
1374-             return  live_ids 
1375-         live_ids  =  get_live_ids ()
1376-         for  lid  in  live_ids :
1377-             api_url  =  ('https://event.api.swisstxt.ch/v1/events/' 
1378-                        f'{ self .bu } { lid }  )
1379-             live_json  =  json .loads (self .open_url (api_url ))
1380-             entry  =  utils .try_get (live_json , 0 , data_type = dict , default = {})
1381-             if  not  entry :
1382-                 self .log ('build_live_menu: No entry found for live id {lid}.' )
1383-                 continue 
1384-             if  utils .try_get (entry , 'streamType' ) ==  'noStream' :
1385-                 continue 
1386-             title  =  utils .try_get (entry , 'title' )
1387-             stream_url  =  utils .try_get (entry , 'hls' )
1388-             image  =  utils .try_get (entry , 'imageUrl' )
1389-             item  =  xbmcgui .ListItem (label = title )
1390-             item .setProperty ('IsPlayable' , 'true' )
1391-             item .setArt ({'thumb' : image })
1392-             purl  =  self .build_url (mode = 51 , name = stream_url )
1393-             xbmcplugin .addDirectoryItem (
1394-                 self .handle , purl , item , isFolder = False )
1395-         if  extract_srf3 :
1396-             srf3_ids  =  get_srf3_live_ids ()
1397-             for  vid  in  srf3_ids :
1398-                 self .build_episode_menu (vid , include_segments = False )
1399- 
14001335    def  _read_youtube_channels (self , fname ):
14011336        """ 
14021337        Reads YouTube channel IDs from a specified file and returns a list 
0 commit comments