Skip to content

Commit 18eb6c1

Browse files
authored
Merge pull request #4695 from rickeylohia/plugin.video.stalkervod.v1.1.0
[plugin.video.stalkervod] v1.1.0
2 parents 2132dec + 315a97f commit 18eb6c1

File tree

4 files changed

+114
-15
lines changed

4 files changed

+114
-15
lines changed

plugin.video.stalkervod/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,7 @@ v1.0.0 (2024-07-13)
55
- Major version release with refactor of the menu options. Support for portal with separate menu option for Series.
66
If using kodi Add to Favourites option, existing Favourites link would break.
77
Ability to use Portal Favorite option for both VOD and TV Channels
8-
Add support for UpNext addon.
8+
Add support for UpNext addon.
9+
10+
v1.1.0 (2025-07-26)
11+
- Add search to directory listing for TV and VOD

plugin.video.stalkervod/addon.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2-
<addon id="plugin.video.stalkervod" name="Stalker VOD Client" version="1.0.0" provider-name="rickey">
2+
<addon id="plugin.video.stalkervod" name="Stalker VOD Client" version="1.1.0" provider-name="rickey">
33
<requires>
44
<import addon="xbmc.python" version="3.0.1"/>
55
<import addon="script.module.requests" version="2.27.1"/>
@@ -30,6 +30,9 @@ v1.0.0 (2024-07-13)
3030
If using kodi Add to Favourites option, existing Favourites link would break.
3131
Ability to use Portal Favorite option for both VOD and TV Channels
3232
Add support for UpNext addon.
33+
34+
v1.1.0 (2025-07-26)
35+
- Add search to directory listing for TV and VOD
3336
</news>
3437
</extension>
3538
</addon>

plugin.video.stalkervod/lib/addon.py

Lines changed: 92 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@
99
import xbmcgui
1010
import xbmcplugin
1111
from .globals import G
12-
from .utils import ask_for_input, get_int_value
12+
from .utils import ask_for_input, get_int_value, ask_for_category_selection
1313
from .api import Api
14+
from .loggers import Logger
1415

1516

1617
class StalkerAddon:
1718
"""Stalker Addon"""
1819
@staticmethod
1920
def __toggle_favorites(video_id, add, _type):
2021
"""Remove/add favorites and refresh"""
22+
Logger.debug('Toggle Favorites video_id={}, add={}, _type={}'.format(video_id, add, _type))
2123
if add:
2224
Api.add_favorites(video_id, _type)
2325
else:
@@ -27,6 +29,7 @@ def __toggle_favorites(video_id, add, _type):
2729
@staticmethod
2830
def __play_video(params):
2931
"""Play video"""
32+
Logger.debug('Play video {}'.format(params))
3033
stream_url = Api.get_vod_stream_url(params['video_id'], params['series'], params.get('cmd', ''), params.get('use_cmd', '0'))
3134
play_item = xbmcgui.ListItem(path=stream_url)
3235
video_info = play_item.getVideoInfoTag()
@@ -45,19 +48,27 @@ def __play_video(params):
4548
@staticmethod
4649
def __play_tv(cmd):
4750
"""Play TV Channel"""
51+
Logger.debug('Play TV {}'.format(cmd))
4852
stream_url = Api.get_tv_stream_url(cmd)
4953
play_item = xbmcgui.ListItem(path=stream_url)
5054
xbmcplugin.setResolvedUrl(G.get_handle(), True, listitem=play_item)
5155

5256
@staticmethod
5357
def __list_tv_genres():
5458
"""List TV channel genres"""
59+
Logger.debug('List TV Genres')
5560
xbmcplugin.setPluginCategory(G.get_handle(), 'TV CHANNELS')
5661
xbmcplugin.setContent(G.get_handle(), 'videos')
5762
list_item = xbmcgui.ListItem(label='TV FAVORITES')
5863
url = G.get_plugin_url({'action': 'tv_favorites', 'page': 1, 'update_listing': False})
5964
xbmcplugin.addDirectoryItem(G.get_handle(), url, list_item, True)
6065

66+
# Add search option
67+
list_item = xbmcgui.ListItem(label='SEARCH')
68+
list_item.setArt({'thumb': G.get_custom_thumb_path('search.png')})
69+
url = G.get_plugin_url({'action': 'tv_search', 'fav': 0, 'isContextMenuSearch': False})
70+
xbmcplugin.addDirectoryItem(G.get_handle(), url, list_item, True)
71+
6172
genres = Api.get_tv_genres()
6273
for genre in genres:
6374
list_item = xbmcgui.ListItem(label=genre['title'].upper())
@@ -74,13 +85,20 @@ def __list_tv_genres():
7485
@staticmethod
7586
def __list_vod_categories():
7687
"""List vod categories"""
88+
Logger.debug('List VOD Categories')
7789
xbmcplugin.setPluginCategory(G.get_handle(), 'VOD')
7890
xbmcplugin.setContent(G.get_handle(), 'videos')
7991

8092
list_item = xbmcgui.ListItem(label='VOD FAVORITES')
8193
url = G.get_plugin_url({'action': 'vod_favorites', 'page': 1, 'update_listing': False})
8294
xbmcplugin.addDirectoryItem(G.get_handle(), url, list_item, True)
8395

96+
# Add search option
97+
list_item = xbmcgui.ListItem(label='SEARCH')
98+
list_item.setArt({'thumb': G.get_custom_thumb_path('search.png')})
99+
url = G.get_plugin_url({'action': 'vod_search', 'fav': 0, 'isContextMenuSearch': False})
100+
xbmcplugin.addDirectoryItem(G.get_handle(), url, list_item, True)
101+
84102
categories = Api.get_vod_categories()
85103
for category in categories:
86104
list_item = xbmcgui.ListItem(label=category['title'])
@@ -96,13 +114,20 @@ def __list_vod_categories():
96114
@staticmethod
97115
def __list_series_categories():
98116
"""List series categories"""
117+
Logger.debug('List Series Categories')
99118
xbmcplugin.setPluginCategory(G.get_handle(), 'SERIES')
100119
xbmcplugin.setContent(G.get_handle(), 'videos')
101120

102121
list_item = xbmcgui.ListItem(label='SERIES FAVORITES')
103122
url = G.get_plugin_url({'action': 'series_favorites', 'page': 1, 'update_listing': False})
104123
xbmcplugin.addDirectoryItem(G.get_handle(), url, list_item, True)
105124

125+
# Add search option
126+
list_item = xbmcgui.ListItem(label='SEARCH')
127+
list_item.setArt({'thumb': G.get_custom_thumb_path('search.png')})
128+
url = G.get_plugin_url({'action': 'series_search', 'fav': 0, 'isContextMenuSearch': False})
129+
xbmcplugin.addDirectoryItem(G.get_handle(), url, list_item, True)
130+
106131
categories = Api.get_series_categories()
107132
for category in categories:
108133
list_item = xbmcgui.ListItem(label=category['title'])
@@ -118,6 +143,7 @@ def __list_series_categories():
118143
@staticmethod
119144
def __list_channels(params):
120145
"""List TV Channels"""
146+
Logger.debug('List Channels {}'.format(params))
121147
search_term = params.get('search_term', '')
122148
page = params['page']
123149
plugin_category = 'TV - ' + params['category'] if params.get('fav', '0') != '1' else 'TV - ' + params['category'] + ' - FAVORITES'
@@ -159,6 +185,7 @@ def __create_tv_listing(videos, params):
159185
@staticmethod
160186
def __list_vod(params):
161187
"""List videos for a category"""
188+
Logger.debug('List VOD {}'.format(params))
162189
search_term = params.get('search_term', '')
163190
plugin_category = 'VOD - ' + params['category'] if params.get('fav', '0') != '1' else 'VOD - ' + params['category'] + ' - FAVORITES'
164191
xbmcplugin.setPluginCategory(G.get_handle(), plugin_category)
@@ -169,6 +196,7 @@ def __list_vod(params):
169196
@staticmethod
170197
def __list_vod_favorites(params):
171198
"""List Favorites Channels"""
199+
Logger.debug('List VOD Favorites {}'.format(params))
172200
xbmcplugin.setPluginCategory(G.get_handle(), 'VOD FAVORITES')
173201
xbmcplugin.setContent(G.get_handle(), 'videos')
174202
videos = Api.get_vod_favorites(params['page'])
@@ -185,14 +213,16 @@ def __list_series_favorites(params):
185213
@staticmethod
186214
def __list_tv_favorites(params):
187215
"""List Favorites Channels"""
216+
Logger.debug('List TV favorites {}'.format(params))
188217
xbmcplugin.setPluginCategory(G.get_handle(), 'TV FAVORITES')
189218
xbmcplugin.setContent(G.get_handle(), 'videos')
190219
videos = Api.get_tv_favorites(params['page'])
191220
StalkerAddon.__create_tv_listing(videos, params)
192221

193222
@staticmethod
194223
def __list_series(params):
195-
"""List videos for a category"""
224+
"""List series"""
225+
Logger.debug('List TV favorites {}'.format(params))
196226
search_term = params.get('search_term', '')
197227
plugin_category = 'SERIES - ' + params['category'] if params.get('fav', '0') != '1' else 'SERIES - ' + params['category'] + ' - FAVORITES'
198228
xbmcplugin.setPluginCategory(G.get_handle(), plugin_category)
@@ -202,7 +232,7 @@ def __list_series(params):
202232

203233
@staticmethod
204234
def __list_season(params):
205-
"""List videos for a category"""
235+
"""List season"""
206236
xbmcplugin.setPluginCategory(G.get_handle(), params['name'])
207237
xbmcplugin.setContent(G.get_handle(), 'videos')
208238
seasons = Api.get_seasons(params['video_id'])
@@ -412,35 +442,84 @@ def __list_episodes(params):
412442
xbmcplugin.addDirectoryItem(G.get_handle(), url, list_item, False)
413443
xbmcplugin.endOfDirectory(G.get_handle(), succeeded=True, updateListing=False, cacheToDisc=False)
414444

415-
@staticmethod
416-
def __search_vod(params):
445+
def __search_vod(self, params):
417446
"""Search for videos"""
447+
Logger.debug('Search VOD {}'.format(params))
448+
449+
# If category is missing, show category selection popup
450+
if not params.get('category'):
451+
categories = Api.get_vod_categories()
452+
selected_category = ask_for_category_selection(categories, 'VOD')
453+
if not selected_category:
454+
# User cancelled category selection - end directory properly
455+
xbmcplugin.endOfDirectory(G.get_handle(), succeeded=False, updateListing=False, cacheToDisc=False)
456+
return
457+
params.update({
458+
'category': selected_category['title'],
459+
'category_id': selected_category['id']
460+
})
461+
418462
search_term = ask_for_input(params['category'])
419463
if search_term:
420464
params.update({'action': 'vod_listing', 'update_listing': False, 'search_term': search_term, 'page': 1})
421-
url = G.get_plugin_url(params)
422-
func_str = f'Container.Update({url})'
423-
xbmc.executebuiltin(func_str)
465+
is_context = str(params.get('isContextMenuSearch', 'true')).lower() == 'true'
466+
if is_context:
467+
url = G.get_plugin_url(params)
468+
func_str = f'Container.Update({url})'
469+
xbmc.executebuiltin(func_str)
470+
else:
471+
self.__list_vod(params)
424472

425473
@staticmethod
426474
def __search_series(params):
427475
"""Search for videos"""
476+
477+
# If category is missing, show category selection popup
478+
if not params.get('category'):
479+
categories = Api.get_series_categories()
480+
selected_category = ask_for_category_selection(categories, 'Series')
481+
if not selected_category:
482+
# User cancelled category selection - end directory properly
483+
xbmcplugin.endOfDirectory(G.get_handle(), succeeded=False, updateListing=False, cacheToDisc=False)
484+
return
485+
params.update({
486+
'category': selected_category['title'],
487+
'category_id': selected_category['id']
488+
})
489+
428490
search_term = ask_for_input(params['category'])
429491
if search_term:
430492
params.update({'action': 'series_listing', 'update_listing': False, 'search_term': search_term, 'page': 1})
431493
url = G.get_plugin_url(params)
432494
func_str = f'Container.Update({url})'
433495
xbmc.executebuiltin(func_str)
434496

435-
@staticmethod
436-
def __search_tv(params):
497+
def __search_tv(self, params):
437498
"""Search for videos"""
499+
500+
# If category is missing, show category selection popup
501+
if not params.get('category'):
502+
genres = Api.get_tv_genres()
503+
selected_genre = ask_for_category_selection(genres, 'TV')
504+
if not selected_genre:
505+
# User cancelled category selection - end directory properly
506+
xbmcplugin.endOfDirectory(G.get_handle(), succeeded=False, updateListing=False, cacheToDisc=False)
507+
return
508+
params.update({
509+
'category': selected_genre['title'],
510+
'category_id': selected_genre['id']
511+
})
512+
438513
search_term = ask_for_input(params['category'])
439514
if search_term:
440515
params.update({'action': 'tv_listing', 'update_listing': False, 'search_term': search_term, 'page': 1})
441-
url = G.get_plugin_url(params)
442-
func_str = f'Container.Update({url})'
443-
xbmc.executebuiltin(func_str)
516+
is_context = str(params.get('isContextMenuSearch', 'true')).lower() == 'true'
517+
if is_context:
518+
url = G.get_plugin_url(params)
519+
func_str = f'Container.Update({url})'
520+
xbmc.executebuiltin(func_str)
521+
else:
522+
self.__list_channels(params)
444523

445524
@staticmethod
446525
def __list_main_menu():

plugin.video.stalkervod/lib/utils.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,20 @@ def ask_for_input(category):
1616
type=xbmcgui.INPUT_ALPHANUM) or None
1717

1818

19+
def ask_for_category_selection(categories, content_type):
20+
"""Category selection dialog box"""
21+
if not categories:
22+
return None
23+
24+
category_titles = [category['title'] for category in categories]
25+
dialog = xbmcgui.Dialog()
26+
selected_index = dialog.select(f'Select {content_type} Category', category_titles)
27+
28+
if selected_index >= 0:
29+
return categories[selected_index]
30+
return None
31+
32+
1933
def get_int_value(dictionary, key):
2034
"""Helper method to get int value"""
2135
if key in dictionary:

0 commit comments

Comments
 (0)