Merge pull request #1016 from croneter/beta-version

Bump master
This commit is contained in:
croneter 2019-10-12 12:56:25 +02:00 committed by GitHub
commit 45cd1aa0fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 203 additions and 92 deletions

View file

@ -1,5 +1,5 @@
[![stable version](https://img.shields.io/badge/stable_version-2.9.9-blue.svg?maxAge=60&style=flat) ](https://github.com/croneter/binary_repo/raw/master/stable/repository.plexkodiconnect/repository.plexkodiconnect-1.0.2.zip) [![stable version](https://img.shields.io/badge/stable_version-2.9.11-blue.svg?maxAge=60&style=flat) ](https://github.com/croneter/binary_repo/raw/master/stable/repository.plexkodiconnect/repository.plexkodiconnect-1.0.2.zip)
[![beta version](https://img.shields.io/badge/beta_version-2.9.9-red.svg?maxAge=60&style=flat) ](https://github.com/croneter/binary_repo/raw/master/beta/repository.plexkodiconnectbeta/repository.plexkodiconnectbeta-1.0.2.zip) [![beta version](https://img.shields.io/badge/beta_version-2.9.11-red.svg?maxAge=60&style=flat) ](https://github.com/croneter/binary_repo/raw/master/beta/repository.plexkodiconnectbeta/repository.plexkodiconnectbeta-1.0.2.zip)
[![Installation](https://img.shields.io/badge/wiki-installation-brightgreen.svg?maxAge=60&style=flat)](https://github.com/croneter/PlexKodiConnect/wiki/Installation) [![Installation](https://img.shields.io/badge/wiki-installation-brightgreen.svg?maxAge=60&style=flat)](https://github.com/croneter/PlexKodiConnect/wiki/Installation)
[![FAQ](https://img.shields.io/badge/wiki-FAQ-brightgreen.svg?maxAge=60&style=flat)](https://github.com/croneter/PlexKodiConnect/wiki/faq) [![FAQ](https://img.shields.io/badge/wiki-FAQ-brightgreen.svg?maxAge=60&style=flat)](https://github.com/croneter/PlexKodiConnect/wiki/faq)

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="2.9.9" provider-name="croneter"> <addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="2.9.11" provider-name="croneter">
<requires> <requires>
<import addon="xbmc.python" version="2.1.0"/> <import addon="xbmc.python" version="2.1.0"/>
<import addon="script.module.requests" version="2.9.1" /> <import addon="script.module.requests" version="2.9.1" />
@ -83,7 +83,18 @@
<summary lang="lt_LT">Natūralioji „Plex“ integracija į „Kodi“</summary> <summary lang="lt_LT">Natūralioji „Plex“ integracija į „Kodi“</summary>
<description lang="lt_LT">Prijunkite „Kodi“ prie „Plex Medija Serverio“. Šiame papildinyje daroma prielaida, kad valdote visus savo vaizdo įrašus naudodami „Plex“ (ir nė vieno su „Kodi“). Galite prarasti jau saugomus „Kodi“ vaizdo įrašų ir muzikos duomenų bazių duomenis (kadangi šis papildinys juos tiesiogiai pakeičia). Naudokite savo pačių rizika!</description> <description lang="lt_LT">Prijunkite „Kodi“ prie „Plex Medija Serverio“. Šiame papildinyje daroma prielaida, kad valdote visus savo vaizdo įrašus naudodami „Plex“ (ir nė vieno su „Kodi“). Galite prarasti jau saugomus „Kodi“ vaizdo įrašų ir muzikos duomenų bazių duomenis (kadangi šis papildinys juos tiesiogiai pakeičia). Naudokite savo pačių rizika!</description>
<disclaimer lang="lt_LT">Naudokite savo pačių rizika</disclaimer> <disclaimer lang="lt_LT">Naudokite savo pačių rizika</disclaimer>
<news>version 2.9.9: <news>version 2.9.11:
- version 2.9.10 for everyone
version 2.9.10 (beta only):
- Add tmdb provider sync
- Fix external subtitles not being available
- Fix PKC increasing the Plex watch count by 2 instead of 1
- Improve subtitle naming
- Delete temporary subtitles on playback stop
- Fix a missleading string
version 2.9.9:
- Versions 2.9.6 - 2.9.8 for everyone - Versions 2.9.6 - 2.9.8 for everyone
version 2.9.8 (beta only): version 2.9.8 (beta only):

View file

@ -1,3 +1,14 @@
version 2.9.11:
- version 2.9.10 for everyone
version 2.9.10 (beta only):
- Add tmdb provider sync
- Fix external subtitles not being available
- Fix PKC increasing the Plex watch count by 2 instead of 1
- Improve subtitle naming
- Delete temporary subtitles on playback stop
- Fix a missleading string
version 2.9.9: version 2.9.9:
- Versions 2.9.6 - 2.9.8 for everyone - Versions 2.9.6 - 2.9.8 for everyone

View file

@ -1164,7 +1164,7 @@ msgid "Enter your Plex Media Server's IP or URL, Examples are:"
msgstr "" msgstr ""
msgctxt "#39217" msgctxt "#39217"
msgid "Use HTTPS (SSL) connections? With Kodi 18 or later, HTTPS will likely not work!" msgid "Use HTTPS (SSL) connections? Answer should probably be yes."
msgstr "" msgstr ""
msgctxt "#39218" msgctxt "#39218"

View file

@ -53,6 +53,9 @@ class PlayState(object):
} }
self.played_info = {} self.played_info = {}
# Currently playing PKC item, a PlaylistItem()
self.item = None
# Set by SpecialMonitor - did user choose to resume playback or start from the # Set by SpecialMonitor - did user choose to resume playback or start from the
# beginning? # beginning?
# Set to None if resume dialog has not been shown # Set to None if resume dialog has not been shown

View file

@ -85,8 +85,7 @@ class InitialSetup(object):
if not port: if not port:
return False return False
url = '%s:%s' % (address, port) url = '%s:%s' % (address, port)
# "Use HTTPS (SSL) connections? With Kodi 18 or later, HTTPS will likely # "Use HTTPS (SSL) connections? Answer should probably be yes."
# not work!"
https = utils.yesno_dialog(utils.lang(29999), utils.lang(39217)) https = utils.yesno_dialog(utils.lang(29999), utils.lang(39217))
if https: if https:
url = 'https://%s' % url url = 'https://%s' % url

View file

@ -91,6 +91,14 @@ class Movie(ItemBase):
api.provider('imdb'), api.provider('imdb'),
"imdb", "imdb",
uniqueid) uniqueid)
elif api.provider('tmdb') is not None:
uniqueid = self.kodidb.get_uniqueid(kodi_id,
v.KODI_TYPE_MOVIE)
self.kodidb.update_uniqueid(kodi_id,
v.KODI_TYPE_MOVIE,
api.provider('tmdb'),
"tmdb",
uniqueid)
else: else:
self.kodidb.remove_uniqueid(kodi_id, v.KODI_TYPE_MOVIE) self.kodidb.remove_uniqueid(kodi_id, v.KODI_TYPE_MOVIE)
uniqueid = -1 uniqueid = -1
@ -120,6 +128,13 @@ class Movie(ItemBase):
v.KODI_TYPE_MOVIE, v.KODI_TYPE_MOVIE,
api.provider('imdb'), api.provider('imdb'),
"imdb") "imdb")
elif api.provider('tmdb') is not None:
uniqueid = self.kodidb.add_uniqueid_id()
self.kodidb.add_uniqueid(uniqueid,
kodi_id,
v.KODI_TYPE_MOVIE,
api.provider('tmdb'),
"tmdb")
else: else:
uniqueid = -1 uniqueid = -1
self.kodidb.add_people(kodi_id, self.kodidb.add_people(kodi_id,

View file

@ -204,6 +204,14 @@ class Show(TvShowMixin, ItemBase):
api.provider('tvdb'), api.provider('tvdb'),
'tvdb', 'tvdb',
uniqueid) uniqueid)
elif api.provider('tmdb') is not None:
uniqueid = self.kodidb.get_uniqueid(kodi_id,
v.KODI_TYPE_SHOW)
self.kodidb.update_uniqueid(kodi_id,
v.KODI_TYPE_SHOW,
api.provider('tmdb'),
'tmdb',
uniqueid)
else: else:
self.kodidb.remove_uniqueid(kodi_id, v.KODI_TYPE_SHOW) self.kodidb.remove_uniqueid(kodi_id, v.KODI_TYPE_SHOW)
uniqueid = -1 uniqueid = -1
@ -245,6 +253,13 @@ class Show(TvShowMixin, ItemBase):
v.KODI_TYPE_SHOW, v.KODI_TYPE_SHOW,
api.provider('tvdb'), api.provider('tvdb'),
'tvdb') 'tvdb')
if api.provider('tmdb'):
uniqueid = self.kodidb.add_uniqueid_id()
self.kodidb.add_uniqueid(uniqueid,
kodi_id,
v.KODI_TYPE_SHOW,
api.provider('tmdb'),
'tmdb')
else: else:
uniqueid = -1 uniqueid = -1
self.kodidb.add_people(kodi_id, self.kodidb.add_people(kodi_id,
@ -490,6 +505,14 @@ class Episode(TvShowMixin, ItemBase):
api.provider('tvdb'), api.provider('tvdb'),
"tvdb", "tvdb",
uniqueid) uniqueid)
elif api.provider('tmdb'):
uniqueid = self.kodidb.get_uniqueid(kodi_id,
v.KODI_TYPE_EPISODE)
self.kodidb.update_uniqueid(kodi_id,
v.KODI_TYPE_EPISODE,
api.provider('tmdb'),
"tmdb",
uniqueid)
else: else:
self.kodidb.remove_uniqueid(kodi_id, v.KODI_TYPE_EPISODE) self.kodidb.remove_uniqueid(kodi_id, v.KODI_TYPE_EPISODE)
uniqueid = -1 uniqueid = -1
@ -568,6 +591,15 @@ class Episode(TvShowMixin, ItemBase):
v.KODI_TYPE_EPISODE, v.KODI_TYPE_EPISODE,
api.provider('tvdb'), api.provider('tvdb'),
"tvdb") "tvdb")
elif api.provider('tmdb'):
uniqueid = self.kodidb.add_uniqueid_id()
self.kodidb.add_uniqueid(uniqueid,
kodi_id,
v.KODI_TYPE_EPISODE,
api.provider('tmdb'),
"tmdb")
else:
uniqueid = -1
self.kodidb.add_people(kodi_id, self.kodidb.add_people(kodi_id,
v.KODI_TYPE_EPISODE, v.KODI_TYPE_EPISODE,
api.people()) api.people())

View file

@ -24,8 +24,7 @@ from . import backgroundthread, app, variables as v
LOG = getLogger('PLEX.kodimonitor') LOG = getLogger('PLEX.kodimonitor')
# "Start from beginning", "Play from beginning" # "Start from beginning", "Play from beginning"
STRINGS = (utils.try_encode(utils.lang(12021)), STRINGS = (utils.lang(12021).encode('utf-8'), utils.lang(12023).encode('utf-8'))
utils.try_encode(utils.lang(12023)))
class KodiMonitor(xbmc.Monitor): class KodiMonitor(xbmc.Monitor):
@ -107,29 +106,7 @@ class KodiMonitor(xbmc.Monitor):
with app.APP.lock_playqueues: with app.APP.lock_playqueues:
self._playlist_onclear(data) self._playlist_onclear(data)
elif method == "VideoLibrary.OnUpdate": elif method == "VideoLibrary.OnUpdate":
# Manually marking as watched/unwatched _videolibrary_onupdate(data)
playcount = data.get('playcount')
item = data.get('item')
if playcount is None or item is None:
return
try:
kodi_id = item['id']
kodi_type = item['type']
except (KeyError, TypeError):
LOG.info("Item is invalid for playstate update.")
return
# Send notification to the server.
with PlexDB() as plexdb:
db_item = plexdb.item_by_kodi_id(kodi_id, kodi_type)
if not db_item:
LOG.error("Could not find plex_id in plex database for a "
"video library update")
else:
# notify the server
if playcount > 0:
PF.scrobble(db_item['plex_id'], 'watched')
else:
PF.scrobble(db_item['plex_id'], 'unwatched')
elif method == "VideoLibrary.OnRemove": elif method == "VideoLibrary.OnRemove":
pass pass
elif method == "System.OnSleep": elif method == "System.OnSleep":
@ -423,6 +400,8 @@ class KodiMonitor(xbmc.Monitor):
container_key = '/playQueues/%s' % playqueue.id container_key = '/playQueues/%s' % playqueue.id
else: else:
container_key = '/library/metadata/%s' % plex_id container_key = '/library/metadata/%s' % plex_id
# Remember the currently playing item
app.PLAYSTATE.item = item
# Remember that this player has been active # Remember that this player has been active
app.PLAYSTATE.active_players.add(playerid) app.PLAYSTATE.active_players.add(playerid)
status.update(info) status.update(info)
@ -456,7 +435,7 @@ def _playback_cleanup(ended=False):
# Remember the last played item later # Remember the last played item later
app.PLAYSTATE.old_player_states[playerid] = copy.deepcopy(status) app.PLAYSTATE.old_player_states[playerid] = copy.deepcopy(status)
# Stop transcoding # Stop transcoding
if status['playmethod'] == 'Transcode': if status['playmethod'] == v.PLAYBACK_METHOD_TRANSCODE:
LOG.debug('Tell the PMS to stop transcoding') LOG.debug('Tell the PMS to stop transcoding')
DU().downloadUrl( DU().downloadUrl(
'{server}/video/:/transcode/universal/stop', '{server}/video/:/transcode/universal/stop',
@ -470,6 +449,8 @@ def _playback_cleanup(ended=False):
app.PLAYSTATE.player_states[playerid] = copy.deepcopy(app.PLAYSTATE.template) app.PLAYSTATE.player_states[playerid] = copy.deepcopy(app.PLAYSTATE.template)
# As all playback has halted, reset the players that have been active # As all playback has halted, reset the players that have been active
app.PLAYSTATE.active_players = set() app.PLAYSTATE.active_players = set()
app.PLAYSTATE.item = None
utils.delete_temporary_subtitles()
LOG.info('Finished PKC playback cleanup') LOG.info('Finished PKC playback cleanup')
@ -639,6 +620,41 @@ def _notify_upnext(item):
xbmc.executebuiltin('NotifyAll(%s, %s, %s)' % (sender, method, data)) xbmc.executebuiltin('NotifyAll(%s, %s, %s)' % (sender, method, data))
def _videolibrary_onupdate(data):
"""
A specific Kodi library item has been updated. This seems to happen if the
user marks an item as watched/unwatched or if playback of the item just
stopped
"""
playcount = data.get('playcount')
item = data.get('item')
if playcount is None or item is None:
return
try:
kodi_id = item['id']
kodi_type = item['type']
except (KeyError, TypeError):
LOG.info("Item is invalid for playstate update.")
return
if app.PLAYSTATE.item and kodi_id == app.PLAYSTATE.item.kodi_id and \
kodi_type == app.PLAYSTATE.item.kodi_type:
# Kodi updates an item immediately after playback. Hence we do NOT
# increase or decrease the viewcount
return
# Send notification to the server.
with PlexDB(lock=False) as plexdb:
db_item = plexdb.item_by_kodi_id(kodi_id, kodi_type)
if not db_item:
LOG.error("Could not find plex_id in plex database for a "
"video library update")
return
# notify the server
if playcount > 0:
PF.scrobble(db_item['plex_id'], 'watched')
else:
PF.scrobble(db_item['plex_id'], 'unwatched')
class ContextMonitor(backgroundthread.KillableThread): class ContextMonitor(backgroundthread.KillableThread):
""" """
Detect the resume dialog for widgets. Could also be used to detect Detect the resume dialog for widgets. Could also be used to detect

View file

@ -19,6 +19,8 @@ import shutil
import os import os
from os import path # allows to use path_ops.path.join, for example from os import path # allows to use path_ops.path.join, for example
from distutils import dir_util from distutils import dir_util
import re
import xbmc import xbmc
import xbmcvfs import xbmcvfs
@ -26,6 +28,7 @@ from .tools import unicode_paths
# Kodi seems to encode in utf-8 in ALL cases (unlike e.g. the OS filesystem) # Kodi seems to encode in utf-8 in ALL cases (unlike e.g. the OS filesystem)
KODI_ENCODING = 'utf-8' KODI_ENCODING = 'utf-8'
REGEX_FILE_NUMBERING = re.compile(r'''_(\d\d)\.\w+$''')
def encode_path(path): def encode_path(path):
@ -216,3 +219,25 @@ def basename(path):
return path.rsplit('\\', 1)[1] return path.rsplit('\\', 1)[1]
except IndexError: except IndexError:
return '' return ''
def create_unique_path(directory, filename, extension):
"""
Checks whether 'directory/filename.extension' exists. If so, will start
numbering the filename until the file does not exist yet (up to 99)
"""
res = path.join(directory, '.'.join((filename, extension)))
while exists(res):
occurance = REGEX_FILE_NUMBERING.search(res)
if not occurance:
filename = '{}_00'.format(filename[:min(len(filename),
251 - len(extension))])
res = path.join(directory, '.'.join((filename, extension)))
else:
number = int(occurance.group(1)) + 1
if number > 99:
raise RuntimeError('Could not create unique file: {} {} {}'.format(
directory, filename, extension))
basename = re.sub(REGEX_FILE_NUMBERING, '', res)
res = '{}_{:02d}.{}'.format(basename, number, extension)
return res

View file

@ -19,7 +19,7 @@ from . import playlist_func as PL
from . import playqueue as PQ from . import playqueue as PQ
from . import json_rpc as js from . import json_rpc as js
from . import transfer from . import transfer
from .playback_decision import set_playurl from .playback_decision import set_playurl, audio_subtitle_prefs
from . import variables as v from . import variables as v
from . import app from . import app
@ -473,10 +473,11 @@ def _conclude_playback(playqueue, pos):
_ensure_resolve() _ensure_resolve()
return return
listitem.setPath(item.file.encode('utf-8')) listitem.setPath(item.file.encode('utf-8'))
if item.playmethod == 'DirectStream': if item.playmethod == v.PLAYBACK_METHOD_DIRECT_PLAY:
listitem.setSubtitles(api.cache_external_subs()) listitem.setSubtitles(api.cache_external_subs())
elif item.playmethod == 'Transcode': elif item.playmethod in (v.PLAYBACK_METHOD_DIRECT_STREAM,
playutils.audio_subtitle_prefs(listitem) v.PLAYBACK_METHOD_TRANSCODE):
audio_subtitle_prefs(api, listitem)
_set_resume(listitem, item, api) _set_resume(listitem, item, api)
transfer.send(listitem) transfer.send(listitem)
LOG.info('Done concluding playback') LOG.info('Done concluding playback')
@ -518,7 +519,7 @@ def process_indirect(key, offset, resolve=True):
playqueue.clear() playqueue.clear()
item = PL.playlist_item_from_xml(xml[0]) item = PL.playlist_item_from_xml(xml[0])
item.offset = offset item.offset = offset
item.playmethod = 'DirectStream' item.playmethod = v.PLAYBACK_METHOD_DIRECT_PLAY
# Need to get yet another xml to get the final playback url # Need to get yet another xml to get the final playback url
try: try:

View file

@ -351,12 +351,12 @@ def audio_subtitle_prefs(api, listitem):
for stream in mediastreams: for stream in mediastreams:
# Since Plex returns all possible tracks together, have to sort # Since Plex returns all possible tracks together, have to sort
# them. # them.
index = stream.attrib.get('id') index = stream.get('id')
typus = stream.attrib.get('streamType') typus = stream.get('streamType')
# Audio # Audio
if typus == "2": if typus == "2":
codec = stream.attrib.get('codec') codec = stream.get('codec')
channellayout = stream.attrib.get('audioChannelLayout', "") channellayout = stream.get('audioChannelLayout', "")
try: try:
track = "%s %s - %s %s" % (audio_numb + 1, track = "%s %s - %s %s" % (audio_numb + 1,
stream.attrib['language'], stream.attrib['language'],
@ -368,48 +368,42 @@ def audio_subtitle_prefs(api, listitem):
codec, codec,
channellayout) channellayout)
audio_streams_list.append(index) audio_streams_list.append(index)
audio_streams.append(utils.try_encode(track)) audio_streams.append(track.encode('utf-8'))
audio_numb += 1 audio_numb += 1
# Subtitles # Subtitles
elif typus == "3": elif typus == "3":
try: try:
track = "%s %s" % (sub_num + 1, stream.attrib['language']) track = '{} {}'.format(sub_num, stream.attrib['displayTitle'])
except KeyError: except KeyError:
track = "%s %s (%s)" % (sub_num + 1, track = '{} {} ({})'.format(sub_num + 1,
utils.lang(39707), # unknown utils.lang(39707), # unknown
stream.attrib.get('codec')) stream.get('codec'))
default = stream.attrib.get('default') default = stream.get('default')
forced = stream.attrib.get('forced') forced = stream.get('forced')
downloadable = stream.attrib.get('key') downloadable = stream.get('key')
if default: if default:
track = "%s - %s" % (track, utils.lang(39708)) # Default track = "%s - %s" % (track, utils.lang(39708)) # Default
if forced: if forced:
track = "%s - %s" % (track, utils.lang(39709)) # Forced track = "%s - %s" % (track, utils.lang(39709)) # Forced
if downloadable: if downloadable:
# We do know the language - temporarily download path = api.download_external_subtitles(
if 'language' in stream.attrib: '{{server}}{}'.format(stream.get('key')),
path = api.download_external_subtitles( stream.get('displayTitle'),
'{server}%s' % stream.attrib['key'], stream.get('codec'))
"subtitle.%s.%s" % (stream.attrib['languageCode'], if path:
stream.attrib['codec'])) downloadable_streams.append(index)
# We don't know the language - no need to download download_subs.append(path.encode('utf-8'))
else:
path = api.attach_plex_token_to_url(
"%s%s" % (app.CONN.server,
stream.attrib['key']))
downloadable_streams.append(index)
download_subs.append(utils.try_encode(path))
else: else:
track = "%s (%s)" % (track, utils.lang(39710)) # burn-in track = "%s (%s)" % (track, utils.lang(39710)) # burn-in
if stream.attrib.get('selected') == '1' and downloadable: if stream.get('selected') == '1' and downloadable:
# Only show subs without asking user if they can be # Only show subs without asking user if they can be
# turned off # turned off
default_sub = index default_sub = index
subtitle_streams_list.append(index) subtitle_streams_list.append(index)
subtitle_streams.append(utils.try_encode(track)) subtitle_streams.append(track.encode('utf-8'))
sub_num += 1 sub_num += 1
if audio_numb > 1: if audio_numb > 1:

View file

@ -552,6 +552,9 @@ class Base(object):
elif providername == 'tvdb': elif providername == 'tvdb':
# originally e.g. com.plexapp.agents.thetvdb://276564?lang=en # originally e.g. com.plexapp.agents.thetvdb://276564?lang=en
regex = utils.REGEX_TVDB regex = utils.REGEX_TVDB
elif providername == 'tmdb':
# originally e.g. com.plexapp.agents.themoviedb://603?lang=en
regex = utils.REGEX_TMDB
else: else:
raise NotImplementedError('Not implemented: %s' % providername) raise NotImplementedError('Not implemented: %s' % providername)

View file

@ -254,46 +254,33 @@ class Media(object):
try: try:
mediastreams = self.xml[0][self.part] mediastreams = self.xml[0][self.part]
except (TypeError, KeyError, IndexError): except (TypeError, KeyError, IndexError):
return return externalsubs
kodiindex = 0
fileindex = 0
for stream in mediastreams: for stream in mediastreams:
# Since plex returns all possible tracks together, have to pull # Since plex returns all possible tracks together, have to pull
# only external subtitles - only for these a 'key' exists # only external subtitles - only for these a 'key' exists
if cast(int, stream.get('streamType')) != 3: if int(stream.get('streamType')) != 3 or 'key' not in stream.attrib:
# Not a subtitle # Not a subtitle or not not an external subtitle
continue continue
# Only set for additional external subtitles NOT lying beside video path = self.download_external_subtitles(
key = stream.get('key') '{server}%s' % stream.get('key'),
# Only set for dedicated subtitle files lying beside video stream.get('displayTitle'),
# ext = stream.attrib.get('format') stream.get('codec'))
if key: if path:
# We do know the language - temporarily download
if stream.get('languageCode') is not None:
language = stream.get('languageCode')
codec = stream.get('codec')
path = self.download_external_subtitles(
"{server}%s" % key,
"subtitle%02d.%s.%s" % (fileindex, language, codec))
fileindex += 1
# We don't know the language - no need to download
else:
path = self.attach_plex_token_to_url(
"%s%s" % (app.CONN.server, key))
externalsubs.append(path) externalsubs.append(path)
kodiindex += 1
LOG.info('Found external subs: %s', externalsubs) LOG.info('Found external subs: %s', externalsubs)
return externalsubs return externalsubs
@staticmethod @staticmethod
def download_external_subtitles(url, filename): def download_external_subtitles(url, filename, extension):
""" """
One cannot pass the subtitle language for ListItems. Workaround; will One cannot pass the subtitle language for ListItems. Workaround; will
download the subtitle at url to the Kodi PKC directory in a temp dir download the subtitle at url to the Kodi PKC directory in a temp dir
Returns the path to the downloaded subtitle or None Returns the path to the downloaded subtitle or None
""" """
path = path_ops.path.join(v.EXTERNAL_SUBTITLE_TEMP_PATH, filename) path = path_ops.create_unique_path(v.EXTERNAL_SUBTITLE_TEMP_PATH,
filename,
extension)
response = DU().downloadUrl(url, return_response=True) response = DU().downloadUrl(url, return_response=True)
try: try:
response.status_code response.status_code
@ -302,8 +289,8 @@ class Media(object):
return return
else: else:
LOG.debug('Writing temp subtitle to %s', path) LOG.debug('Writing temp subtitle to %s', path)
with open(path_ops.encode_path(path), 'wb') as filer: with open(path_ops.encode_path(path), 'wb') as f:
filer.write(response.content) f.write(response.content)
return path return path
def validate_playurl(self, path, typus, force_check=False, folder=False, def validate_playurl(self, path, typus, force_check=False, folder=False,

View file

@ -49,6 +49,7 @@ REGEX_PLEX_DIRECT = re.compile(r'''\.plex\.direct:\d+$''')
# Plex API # Plex API
REGEX_IMDB = re.compile(r'''/(tt\d+)''') REGEX_IMDB = re.compile(r'''/(tt\d+)''')
REGEX_TVDB = re.compile(r'''thetvdb:\/\/(.+?)\?''') REGEX_TVDB = re.compile(r'''thetvdb:\/\/(.+?)\?''')
REGEX_TMDB = re.compile(r'''themoviedb:\/\/(.+?)\?''')
# Plex music # Plex music
REGEX_MUSICPATH = re.compile(r'''^\^(.+)\$$''') REGEX_MUSICPATH = re.compile(r'''^\^(.+)\$$''')
# Grab Plex id from an URL-encoded string # Grab Plex id from an URL-encoded string
@ -511,6 +512,19 @@ def escape_html(string):
return string return string
def delete_temporary_subtitles():
"""
Permanently deletes all temporary subtitle files
"""
for root, _, files in path_ops.walk(v.EXTERNAL_SUBTITLE_TEMP_PATH):
for file in files:
try:
path_ops.remove(path_ops.path.join(root, file))
except (OSError, IOError) as err:
LOG.error('Could not delete temporary subtitle: %s, %s: %s',
root, file, err)
def kodi_sql(media_type=None): def kodi_sql(media_type=None):
""" """
Open a connection to the Kodi database. Open a connection to the Kodi database.