11import time
22import json
3- from re import sub
4- from urllib .parse import quote
3+ import re
4+ from urllib .parse import quote , unquote
55from requests import get
66from xbmcaddon import Addon
77from xbmcvfs import translatePath
1010
1111from lib .authentication import authenticated_request
1212from lib .history import set_watch_history , mark_as_watched , mark_as_unwatched
13+ from lib .blacklist import blacklist_load , blacklist_add , blacklist_remove
1314from lib .utils import get_component , human_format
1415
1516addon = Addon ()
1920def home () -> None :
2021 folders : list = list ()
2122 if addon .getSettingBool ('use_login' ):
22- folders .append (('feed' , addon .getLocalizedString (30001 )))
23- folders .append (('subscriptions' , addon .getLocalizedString (30002 )))
24- folders .append (('playlists' ,addon .getLocalizedString (30003 )))
25- if addon .getSettingBool ('watch_history_enable' ) and len (addon .getSettingString ('watch_history_playlist' )) > 0 :
23+ if addon .getSettingBool ('menu_show_feed' ):
24+ folders .append (('feed' , addon .getLocalizedString (30001 )))
25+ if addon .getSettingBool ('menu_show_feed_update' ):
26+ folders .append (('updatefeed' , addon .getLocalizedString (30020 )))
27+ if addon .getSettingBool ('menu_show_subscriptions' ):
28+ folders .append (('subscriptions' , addon .getLocalizedString (30002 )))
29+ if addon .getSettingBool ('menu_show_playlists' ):
30+ folders .append (('playlists' ,addon .getLocalizedString (30003 )))
31+ if addon .getSettingBool ('menu_show_watch_history' ) and addon .getSettingBool ('watch_history_enable' ) and len (addon .getSettingString ('watch_history_playlist' )) > 0 :
2632 folders .append (('watch_history' , addon .getLocalizedString (30004 )))
27-
28- folders .append (('trending' , addon .getLocalizedString (30005 )))
29- folders .append (('search_select' , addon .getLocalizedString (30006 )))
30- folders .append (('settings' , addon .getLocalizedString (30007 )))
33+
34+ if addon .getSettingBool ('menu_show_watch_trending' ):
35+ folders .append (('trending' , addon .getLocalizedString (30005 )))
36+ if addon .getSettingBool ('menu_show_watch_blacklist' ) and addon .getSettingBool ('blacklist_channels_enable' ):
37+ folders .append (('blacklist_section' , addon .getLocalizedString (30600 )))
38+ if addon .getSettingBool ('menu_show_watch_search' ):
39+ folders .append (('search_select' , addon .getLocalizedString (30006 )))
40+ if addon .getSettingBool ('menu_show_watch_settings' ):
41+ folders .append (('settings' , addon .getLocalizedString (30007 )))
3142
3243 for folder in folders :
3344 xbmcplugin .addDirectoryItem (handle = addon_handle , url = f"{ addon_url } /{ folder [0 ]} " , listitem = xbmcgui .ListItem (folder [1 ]), isFolder = True )
@@ -39,7 +50,6 @@ def watch(video_id: str) -> None:
3950 path = f'http://localhost:{ addon .getSettingInt ("http_port" )} /watch?v={ video_id } ' ,
4051 )
4152 listitem .setProperty ('inputstream' , 'inputstream.adaptive' )
42- listitem .setProperty ('inputstream.adaptive.manifest_type' , 'mpd' )
4353 listitem .setProperty ('piped_video_id' , video_id )
4454
4555 xbmcplugin .setResolvedUrl (handle = addon_handle , succeeded = True , listitem = listitem )
@@ -49,32 +59,53 @@ def list_videos(videos: list, hide_watched: bool=False, nextpage: str='') -> Non
4959 watch_history_enabled : bool = addon .getSettingBool ('watch_history_enable' ) and len (addon .getSettingString ('watch_history_playlist' )) > 0
5060 if watch_history_enabled :
5161 try :
52- with open (f'{ translatePath (addon .getAddonInfo ("profile" ))} /watch_history.json' , 'r' ) as f :
62+ with open (f'{ translatePath (addon .getAddonInfo ("profile" ))} /watch_history.json' , 'r' ) as f :
5363 history = json .load (f )
5464 except :
5565 pass
5666
67+ blacklist_channels_enabled : bool = addon .getSettingBool ('blacklist_channels_enable' )
68+ if blacklist_channels_enabled :
69+ blacklist_channels_list = blacklist_load ()
70+
71+ blacklist_titles_enabled : bool = addon .getSettingBool ('blacklist_titles_enable' )
72+ if blacklist_titles_enabled :
73+ blacklist_titles_regex_str : str = addon .getSettingString ('blacklist_titles_regex' )
74+ if len (blacklist_titles_regex_str ) > 0 :
75+ blacklist_titles_regex = re .compile (rf"{ blacklist_titles_regex_str } " , re .IGNORECASE if addon .getSettingBool ('blacklist_titles_case_insensitive' ) else re .NOFLAG )
76+ else :
77+ blacklist_titles_enabled = False
78+
5779 for video in videos :
80+ if blacklist_titles_enabled and 'title' in video and re .match (blacklist_titles_regex , video ['title' ]):
81+ continue
82+
5883 plugin_url : str = f"{ addon_url } { video ['url' ].replace ('?v=' , '/' )} "
5984 video_id : str = get_component (video ['url' ])['params' ]['v' ]
60- if hide_watched and video_id in history : continue
85+ channel_id : str = video ['uploaderUrl' ][9 :] if ('uploaderUrl' in video and len (str (video ['uploaderUrl' ])) > 8 ) else ''
86+
87+ if (hide_watched and video_id in history ) or (blacklist_channels_enabled and channel_id in blacklist_channels_list ):
88+ continue
89+
6190 if 'uploadedDate' in video and video ['uploadedDate' ] is not None : date : str = video ['uploadedDate' ]
6291 elif video ['uploaded' ] > 0 : date : str = time .strftime ('%Y-%m-%d %H:%M:%S' , time .localtime (video ['uploaded' ] / 1000 ))
6392 else : date : str = ''
6493 info : str = f"{ video ['title' ]} \n \n { video ['uploaderName' ]} \n \n "
94+ if addon .getSettingBool ('show_description' ) and 'shortDescription' in video and video ['shortDescription' ] is not None : info += video ['shortDescription' ] + "\n \n "
6595 if video ['views' ] >= 0 : info += f"{ addon .getLocalizedString (30008 )} : { human_format (video ['views' ])} \n "
6696 if len (date ) > 2 : info += f"{ addon .getLocalizedString (30009 )} : { date } "
6797 listitem = xbmcgui .ListItem (label = video ['title' ], path = plugin_url )
6898 listitem .setProperty ('isplayable' , 'true' )
6999 listitem .setArt (dict (
70100 thumb = video ['thumbnail' ],
71- fanart = video ['uploaderAvatar' ]
101+ fanart = video ['thumbnail' ]. replace ( 'hqdefault.jpg' , 'maxresdefault.jpg' )
72102 ))
73103
74104 tag = listitem .getVideoInfoTag ()
75105 tag .setTitle (video ['title' ])
76106 tag .setPlot (info )
77107 tag .setDuration (video ['duration' ])
108+ if 'uploaded' in video and video ['uploaded' ] > 0 : tag .setFirstAired (time .strftime ('%Y-%m-%d' , time .localtime (video ['uploaded' ] / 1000 )))
78109 tag .setFilenameAndPath (plugin_url )
79110 tag .setPath (plugin_url )
80111
@@ -84,6 +115,13 @@ def list_videos(videos: list, hide_watched: bool=False, nextpage: str='') -> Non
84115 context_menu_items .append ((addon .getLocalizedString (30011 ), f"RunPlugin({ addon_url } /mark_as_unwatched?id={ video_id } )" ))
85116 else :
86117 context_menu_items .append ((addon .getLocalizedString (30012 ), f"RunPlugin({ addon_url } /mark_as_watched?id={ video_id } )" ))
118+
119+ if blacklist_channels_enabled :
120+ if channel_id in blacklist_channels_list :
121+ context_menu_items .append ((addon .getLocalizedString (30023 ), f"RunPlugin({ addon_url } /blacklist_remove?id={ channel_id } )" ))
122+ else :
123+ context_menu_items .append ((addon .getLocalizedString (30022 ), f"RunPlugin({ addon_url } /blacklist_add?id={ channel_id } &name={ quote (video ['uploaderName' ])} )" ))
124+
87125 listitem .addContextMenuItems (context_menu_items , replaceItems = True )
88126
89127 xbmcplugin .addDirectoryItem (addon_handle , plugin_url , listitem , False )
@@ -96,6 +134,22 @@ def list_videos(videos: list, hide_watched: bool=False, nextpage: str='') -> Non
96134def feed () -> None :
97135 list_videos (authenticated_request ('/feed?authToken=' , True ), addon .getSettingBool ('watch_history_hide_watched_feed' ))
98136
137+ def updatefeed () -> None :
138+ instance : str = addon .getSettingString ('instance' )
139+
140+ channels : list = authenticated_request ('/subscriptions' )
141+ channelcount : int = len (channels )
142+
143+ progressbar = xbmcgui .DialogProgress ()
144+ progressbar .create (addon .getLocalizedString (30021 ))
145+
146+ for i in range (channelcount ):
147+ channel = channels [i ]
148+ progressbar .update (int ((i + 1 ) / channelcount * 100 ), f"{ i + 1 } /{ channelcount } | { channel ['name' ]} " )
149+ authenticated_request (channel ['url' ])
150+
151+ feed ()
152+
99153def list_channels (channels : list , nextpage : str = '' ) -> None :
100154 for channel in channels :
101155 info : str = ''
@@ -136,10 +190,11 @@ def list_playlists(playlists: list, nextpage: str='') -> None:
136190
137191 if 'id' not in playlist :
138192 playlist ['id' ] = get_component (playlist ['url' ])['params' ]['list' ]
139-
193+
140194 listitem = xbmcgui .ListItem (playlist ['name' ])
141195 listitem .setArt (dict (
142- thumb = playlist ['thumbnail' ]
196+ thumb = playlist ['thumbnail' ],
197+ fanart = playlist ['thumbnail' ].replace ('hqdefault.jpg' , 'maxresdefault.jpg' )
143198 ))
144199
145200 tag = listitem .getVideoInfoTag ()
@@ -169,6 +224,19 @@ def playlist(playlist_id: str, hide_watched=None) -> None:
169224def watch_history () -> None :
170225 playlist (addon .getSettingString ('watch_history_playlist' ), False )
171226
227+ def blacklist_section () -> None :
228+ blacklist : dict = dict (sorted (blacklist_load ().items (), key = lambda x : x [1 ]['name' ].lower ()))
229+
230+ for channel_id in blacklist .keys ():
231+ listitem = xbmcgui .ListItem (blacklist [channel_id ]['name' ])
232+
233+ tag = listitem .getVideoInfoTag ()
234+ tag .setTitle (blacklist [channel_id ]['name' ])
235+
236+ xbmcplugin .addDirectoryItem (addon_handle , f"{ addon_url } /blacklist_remove?id={ channel_id } &prompt=true" , listitem , False )
237+
238+ xbmcplugin .endOfDirectory (addon_handle )
239+
172240def channel (channel_id : str , nextpage : str = "" ) -> None :
173241 instance : str = addon .getSettingString ('instance' )
174242
@@ -235,9 +303,11 @@ def router(argv: list) -> None:
235303 routes : dict = {
236304 'home' : {},
237305 'feed' : {},
306+ 'updatefeed' : {},
238307 'settings' : {},
239308 'subscriptions' : {},
240309 'playlists' : {},
310+ 'blacklist_section' : {},
241311 'search_select' : {},
242312 'search' : {
243313 'search_filter' : component ['params' ]['search_filter' ] if 'search_filter' in component ['params' ] else '' ,
@@ -258,17 +328,25 @@ def router(argv: list) -> None:
258328 'mark_as_unwatched' : {
259329 'video_id' : component ['params' ]['id' ] if 'id' in component ['params' ] else ''
260330 },
331+ 'blacklist_add' : {
332+ 'channel_id' : component ['params' ]['id' ] if 'id' in component ['params' ] else '' ,
333+ 'channel_name' : unquote (component ['params' ]['name' ]) if 'name' in component ['params' ] else ''
334+ },
335+ 'blacklist_remove' : {
336+ 'channel_id' : component ['params' ]['id' ] if 'id' in component ['params' ] else '' ,
337+ 'prompt' : True if 'prompt' in component ['params' ] and component ['params' ]['prompt' ] == 'true' else False
338+ },
261339 'watch' : {
262- 'video_id' : sub (r'.*\/' , '' , component ['path' ])
340+ 'video_id' : re . sub (r'.*\/' , '' , component ['path' ])
263341 },
264342 'channel' : {
265- 'channel_id' : sub (r'.*\/' , '' , component ['path' ]),
343+ 'channel_id' : re . sub (r'.*\/' , '' , component ['path' ]),
266344 'nextpage' : component ['params' ]['nextpage' ] if 'nextpage' in component ['params' ] else ''
267345 },
268346 }
269347
270- route : str = sub (r'\/.*' , '' , component ['path' ][1 :])
348+ route : str = re . sub (r'\/.*' , '' , component ['path' ][1 :])
271349 if route == '' : route = 'home'
272350
273351 if route in routes :
274- globals ()[route ](** routes [route ])
352+ globals ()[route ](** routes [route ])
0 commit comments