Skip to content

Commit cd539bf

Browse files
Spacetechcroneter
authored andcommitted
Add/Remove Watchlist context menu commands
lint lint lint
1 parent 9f4ff5d commit cd539bf

File tree

7 files changed

+136
-2
lines changed

7 files changed

+136
-2
lines changed

addon.xml

+10
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414
</extension>
1515
<extension point="kodi.context.item">
1616
<menu id="kodi.core.main">
17+
<item library="context_watchlist_add.py">
18+
<!-- Add to Plex Watchlist -->
19+
<label>30402</label>
20+
<visible>[[[String.IsEqual(ListItem.DBTYPE,movie) | String.IsEqual(ListItem.DBTYPE,tvshow) | String.IsEqual(ListItem.DBTYPE,season) | String.IsEqual(ListItem.DBTYPE,episode)] + !String.IsEmpty(ListItem.DBID)] + !String.IsEqual(ListItem.Property(LISTINGKEY),watchlist)]</visible>
21+
</item>
22+
<item library="context_watchlist_remove.py">
23+
<!-- Remove from Plex Watchlist -->
24+
<label>30403</label>
25+
<visible>[[[String.IsEqual(ListItem.DBTYPE,movie) | String.IsEqual(ListItem.DBTYPE,tvshow)] + !String.IsEmpty(ListItem.DBID)] + String.IsEqual(ListItem.Property(LISTINGKEY),watchlist)]</visible>
26+
</item>
1727
<item library="context_extras.py">
1828
<!-- Extras -->
1929
<label>30235</label>

context_watchlist_add.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Grabs kodi_id and kodi_type for the Kodi item the context menu was called for
4+
and sends a request to our main Python instance
5+
"""
6+
from urllib.parse import urlencode
7+
8+
from xbmc import sleep
9+
from xbmcgui import Window
10+
11+
from resources.lib.contextmenu.common import kodi_item_from_listitem
12+
13+
14+
def main():
15+
kodi_id, kodi_type = kodi_item_from_listitem()
16+
args = {
17+
'kodi_id': kodi_id,
18+
'kodi_type': kodi_type
19+
}
20+
window = Window(10000)
21+
while window.getProperty('plexkodiconnect.command'):
22+
sleep(20)
23+
window.setProperty('plexkodiconnect.command',
24+
'WATCHLIST_ADD?%s' % urlencode(args))
25+
26+
27+
if __name__ == "__main__":
28+
main()

context_watchlist_remove.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Grabs kodi_id and kodi_type for the Kodi item the context menu was called for
4+
and sends a request to our main Python instance
5+
"""
6+
from urllib.parse import urlencode
7+
8+
from xbmc import sleep
9+
from xbmcgui import Window
10+
11+
from resources.lib.contextmenu.common import kodi_item_from_listitem
12+
13+
14+
def main():
15+
kodi_id, kodi_type = kodi_item_from_listitem()
16+
args = {
17+
'kodi_id': kodi_id,
18+
'kodi_type': kodi_type
19+
}
20+
window = Window(10000)
21+
while window.getProperty('plexkodiconnect.command'):
22+
sleep(20)
23+
window.setProperty('plexkodiconnect.command',
24+
'WATCHLIST_REMOVE?%s' % urlencode(args))
25+
26+
27+
if __name__ == "__main__":
28+
main()

resources/language/resource.language.en_gb/strings.po

+10
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,16 @@ msgctxt "#30401"
409409
msgid "Plex options"
410410
msgstr ""
411411

412+
# contextmenu entry
413+
msgctxt "#30402"
414+
msgid "Add to Plex Watchlist"
415+
msgstr ""
416+
417+
# contextmenu entry
418+
msgctxt "#30403"
419+
msgid "Remove from Plex Watchlist"
420+
msgstr ""
421+
412422
# contextmenu entry
413423
msgctxt "#30405"
414424
msgid "Add to Plex favorites"

resources/lib/entrypoint.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def show_listing(xml, plex_type=None, section_id=None, synched=True, key=None):
262262
all_items = [item for item in all_items if item.section_id == utils.cast(int, section_id)]
263263

264264
all_items = [widgets.generate_item(api) for api in all_items]
265-
all_items = [widgets.prepare_listitem(item) for item in all_items]
265+
all_items = [widgets.prepare_listitem(item, key) for item in all_items]
266266
# fill that listing...
267267
all_items = [widgets.create_listitem(item) for item in all_items]
268268
xbmcplugin.addDirectoryItems(int(sys.argv[1]), all_items, len(all_items))

resources/lib/service_entry.py

+55
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from . import kodimonitor
1212
from . import sync, library_sync
1313
from . import websocket_client
14+
from . import plex_db
1415
from . import plex_companion
1516
from . import plex_functions as PF
1617
from . import playback_starter
@@ -19,6 +20,7 @@
1920
from . import loghandler
2021
from . import backgroundthread
2122
from . import skip_plex_markers
23+
from . import downloadutils
2224
from .windows import userselect
2325

2426
###############################################################################
@@ -240,6 +242,53 @@ def toggle_plex_tv(self):
240242
# Enable the main loop to continue
241243
app.APP.suspend = False
242244

245+
def watchlist_add(self, raw_params):
246+
return self.watchlist_modify('addToWatchlist', raw_params)
247+
248+
def watchlist_remove(self, raw_params):
249+
return self.watchlist_modify('removeFromWatchlist', raw_params)
250+
251+
def watchlist_modify(self, api_type, raw_params):
252+
params = dict(utils.parse_qsl(raw_params))
253+
kodi_id = params.get('kodi_id')
254+
kodi_type = params.get('kodi_type')
255+
256+
LOG.info('watchlist_modify %s %s %s', api_type, kodi_id, kodi_type)
257+
258+
watchlist_plex_guid = None
259+
260+
with plex_db.PlexDB(lock=False) as plexdb:
261+
plex_item = plexdb.item_by_kodi_id(kodi_id, kodi_type)
262+
if not plex_item:
263+
return False
264+
265+
plex_guid = plex_item['plex_guid']
266+
if not plex_guid:
267+
return False
268+
269+
plex_type = plex_item['plex_type']
270+
271+
if plex_type == v.PLEX_TYPE_MOVIE or plex_type == v.PLEX_TYPE_SHOW:
272+
watchlist_plex_guid = plex_guid
273+
274+
elif plex_type == v.PLEX_TYPE_SEASON or plex_type == v.PLEX_TYPE_EPISODE:
275+
plex_show_item = plexdb.item_by_id(plex_item['show_id'], v.PLEX_TYPE_SHOW)
276+
if plex_show_item:
277+
watchlist_plex_guid = plex_show_item['plex_guid']
278+
279+
if watchlist_plex_guid is None:
280+
return False
281+
282+
# ratingKey query param accepts the last section in the plex_guid
283+
watchlist_rating_key = watchlist_plex_guid.split('/')[-1]
284+
285+
downloadutils.DownloadUtils().downloadUrl('https://discover.provider.plex.tv/actions/%s?ratingKey=%s' % (api_type, watchlist_rating_key),
286+
action_type = 'PUT',
287+
authenticate=False,
288+
headerOptions={'X-Plex-Token': utils.window('plex_token')})
289+
290+
xbmc.executebuiltin('UpdateLibrary(video)')
291+
243292
def authenticate(self):
244293
"""
245294
Authenticate the current user or prompt to log-in
@@ -473,6 +522,12 @@ def ServiceEntryPoint(self):
473522
task = playback_starter.PlaybackTask(
474523
'dummy?mode=context_menu&%s'
475524
% plex_command.replace('CONTEXT_menu?', ''))
525+
elif plex_command.startswith('WATCHLIST_ADD?'):
526+
task = backgroundthread.FunctionAsTask(
527+
self.watchlist_add, None, plex_command.replace('WATCHLIST_ADD?', ''))
528+
elif plex_command.startswith('WATCHLIST_REMOVE?'):
529+
task = backgroundthread.FunctionAsTask(
530+
self.watchlist_remove, None, plex_command.replace('WATCHLIST_REMOVE?', ''))
476531
elif plex_command == 'choose_pms_server':
477532
task = backgroundthread.FunctionAsTask(
478533
self.choose_pms_server, None)

resources/lib/widgets.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ def _generate_content(api):
249249
return item
250250

251251

252-
def prepare_listitem(item):
252+
def prepare_listitem(item, listing_key = None):
253253
"""helper to convert kodi output from json api to compatible format for
254254
listitems"""
255255
try:
@@ -316,6 +316,9 @@ def prepare_listitem(item):
316316
properties["type"] = item["type"]
317317
properties["path"] = item.get("file")
318318

319+
if listing_key is not None:
320+
properties["LISTINGKEY"] = listing_key
321+
319322
# cast
320323
list_cast = []
321324
list_castandrole = []

0 commit comments

Comments
 (0)