Skip to content

Commit

Permalink
[script.plexmod] 0.7.7
Browse files Browse the repository at this point in the history
  • Loading branch information
pannal committed Apr 20, 2024
1 parent a629d88 commit 1ac7714
Show file tree
Hide file tree
Showing 75 changed files with 1,413 additions and 3,609 deletions.
7 changes: 7 additions & 0 deletions script.plexmod/LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -490,3 +490,10 @@ Library.
Fontawesome
https://fontawesome.com/license/free
CC BY 4.0 License: https://creativecommons.org/licenses/by/4.0/#

-------------------------------------------------------------------------
Play queue by Sébastien Robaszkiewicz from <a href="https://thenounproject.com/browse/icons/term/play-queue/" target="_blank" title="Play queue Icons">Noun Project</a> (CC BY 3.0)
fast forward by Adiyogi from <a href="https://thenounproject.com/browse/icons/term/fast-forward/" target="_blank" title="fast forward Icons">Noun Project</a> (CC BY 3.0)
subtitle by YANDI RS from <a href="https://thenounproject.com/browse/icons/term/subtitle/" target="_blank" title="subtitle Icons">Noun Project</a> (CC BY 3.0)

Other unlisted icons under CC BY 3.0, https://creativecommons.org/licenses/by/3.0/
10 changes: 5 additions & 5 deletions script.plexmod/addon.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.plexmod"
name="PM4K for Plex"
version="0.7.6"
version="0.7.7"
provider-name="pannal">
<requires>
<import addon="xbmc.python" version="3.0.0"/>
Expand Down Expand Up @@ -33,11 +33,11 @@
<source>https://github.com/pannal/plex-for-kodi</source>
<platform>all</platform>
<news>
- Based on 0.7.6-rev2
- Based on 0.7.7-rev3
</news>
<assets>
<icon>icon.png</icon>
<fanart>fanart.jpg</fanart>
<icon>icon2.png</icon>
<fanart>fanart.png</fanart>
</assets>
</extension>
</addon>
</addon>
45 changes: 42 additions & 3 deletions script.plexmod/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,46 @@
[-0.7.6-rev2 -]
- Core: Avoid DNS rebind protection issues for plex.direct
[-0.7.7-rev2-]
- UserSelect: When not switching user (startup), close the addon on cancel actions
- Libraries/Photos: Do autoplay when Play or Shuffle buttons are pressed in photo library view
- Libraries/Photos: Fix wonky thumbnail display on photodirectories; support dynamic backgrounds for Photo items
- SeekDialog: Fix final credits marker skipping wrongly on manual marker skip
- SeekDialog: Fix several marker issues (over-jumping, invalid markers)
- SeekDialog: Show stream transport type in video session info (smb, nfs, path mapped, http(s))
- SeekDialog: Fix empty chapters list shown when watching an episode without markers via NEXT after watching one with markers
- SeekDialog/Settings: Add option to hide all time-related information from the user when the OSD isn't open
- SeekDialog: Transcode Session Only: Don't show subtitle download option in subtitle quick actions; properly show subtitles when toggling them via subtitle quick actions
- Core: Advanced/Addon settings: Set default Plex requests timeout to 10 (was 5)
- Core/Mainloop: Make sure we were able to open the Home/UserSelect window after our BACKGROUND successfully opened, even if another modal dialog opened in the meantime
- Core: Firstrun: Refresh resources after signin and/or home user switch, otherwise the first time the addon's run the user sees no servers
- Core: UI: Fall back to black background image when we have backgrounds set but they didn't load
- Core: Finally fix and handle plex.direct mappings via advancedsettings.xml
- Core: Fix issues resulting in new devices being registered with plex.tv on every plugin start
- Core: Only use mapped file path if mapped file exists or verification is off
- Core: Backgrounds: More concise fallback handling
- Core/Player: Add optional DirectPlay path mapping via addon_data/script.plexmod/path_mapping.json (path_mapping.example.json included in addon directory). Allows for arbitrary replacements of HTTP playback with SMB, NFS, local mounts etc.
- Home: Rework and simplify section/library change logic
- Home: Never update hubs while playing a video to avoid hickups in high bitrate scenarios
- Home: Properly cache user thumbnail (by removing the ?c timestamp from the URL), increasing performance
- Home: Fix round robining on hubs (going left once before the last item, then right falsely round-robined to the start, early)
- Home: Add virtual hub 'home.VIRTUAL.movies.recentlyreleased' on index 3 if we encounter 'movie.recentlyreleased' on the home hubs
- Home/Settings: Add setting to use the modern Continue Watching hub on Home instead of the separated In Progress/On Deck hubs
- Episodes: Complete rework of the watch-state handler for TV; instantly update progress while watching
- Theme: Update assets, icon, splash
- Music: Rework music player and handler; remove plugin:// path and handle tracks directly; fixed all stability issues; massively improve performance
- Player: Add button theme support, use new modern colored theme; support custom themes
- Player: Improve handling when postplay screen is not wanted and we're at the end of a show; harden progressEvent handler
- Player: Remove all /file.xxx instances instead of just .mkv and .mp4 from non mapped stream URLs
- Musicplayer: Partially fix "dangling" playing tracks in Plex Dashboard after stopping playback
- Music: Hide spinner on prev/next button clicks as well (only with Plextuary skin 4.0.0-pm4k0.9 (omega), 3.0.10-pm4k0.8 (nexus and older))
- Settings: Add setting to toggle path mapping dynamically
- Settings: Adjust cache recommendations down from 100MB to 50MB
- AddonSettings: Add advanced setting to verify mapped files before playing them (default: on)
- Account/HomeUsers: Use new API to determine the PlexPass subscription status of the Plex Home
- Account/HomeUsers: Refresh home users once a week if we've never seen a plex home
- Home/RefreshUsers/UserSelect: Refresh subscription state


[-0.7.6-]
- Core: Avoid DNS rebind protection issues for plex.direct
- Core: Support ipv6 plex.direct hosts when checking for locality/LAN
- Core: Network: Massively speed up local connection checks
- Core: Network: Skip local connection checks for plex.tv
Expand All @@ -25,7 +65,6 @@
- SeekDialog: Autoscroll episode/movie title lines for too long titles
- SeekDialog: Hide non-autoskipping marker into the OSD using NAV_BACK/PREVIOUS_MENU
- SeekDialog: Apply positive marker endtime offset to manually skipping markers as well (unifying with the autoskip handling), to avoid re-showing the marker occasionally after seeking
- SeekDialog: Fix final credits marker skipping wrongly on manual marker skip
- Library: Show current total item count in title
- Settings: Add description for Direct Stream

Expand Down
Binary file removed script.plexmod/fanart.jpg
Binary file not shown.
Binary file removed script.plexmod/icon.png
Binary file not shown.
4 changes: 2 additions & 2 deletions script.plexmod/lib/_included_packages/plexnet/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def tracks(self, watched=None):
leavesKey = '/library/metadata/%s/allLeaves' % self.ratingKey
return plexobjects.listItems(self.server, leavesKey, watched=watched)

def all(self):
def all(self, *args, **kwargs):
return self.tracks()

def track(self, title):
Expand Down Expand Up @@ -93,7 +93,7 @@ def track(self, title):
path = '%s/children' % self.key
return plexobjects.findItem(self.server, path, title)

def all(self):
def all(self, *args, **kwargs):
return self.tracks()

def isFullObject(self):
Expand Down
8 changes: 4 additions & 4 deletions script.plexmod/lib/_included_packages/plexnet/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

DEFAULT_TIMEOUT = asyncadapter.AsyncTimeout(util.TIMEOUT).setConnectTimeout(util.TIMEOUT)

KNOWN_HOSTS = {}
RESOLVED_PD_HOSTS = {}

_getaddrinfo = socket.getaddrinfo

Expand All @@ -34,11 +34,11 @@ def pgetaddrinfo(host, port, *args, **kwargs):
"""
if host.endswith("plex.direct"):
v6 = host.count("-") > 3
if host in KNOWN_HOSTS:
ip = KNOWN_HOSTS[host]
if host in RESOLVED_PD_HOSTS:
ip = RESOLVED_PD_HOSTS[host]
else:
base = host.split(".", 1)[0]
ip = KNOWN_HOSTS[host] = v6 and base.replace("-", ":") or base.replace("-", ".")
ip = RESOLVED_PD_HOSTS[host] = v6 and base.replace("-", ":") or base.replace("-", ".")
util.DEBUG_LOG("Dynamically resolving {} to {}".format(host, ip))

fam = v6 and socket.AF_INET6 or socket.AF_INET
Expand Down
3 changes: 3 additions & 0 deletions script.plexmod/lib/_included_packages/plexnet/media.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ class Marker(MediaTag):
TYPE = 'Marker'
FILTER = 'Marker'

def __repr__(self):
return '<%s:%s:%s:%s>' % (self.__class__.__name__, self.id, self.type, self.final and "final" or "")


class Review(MediaTag):
TYPE = 'Review'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ def __init__(self):

def chooseMedia(self, item, forceUpdate=False):
# If we've already evaluated this item, use our previous choice.
if not forceUpdate and item.mediaChoice is not None and item.mediaChoice.media is not None and not item.mediaChoice.media.isIndirect():
if not forceUpdate and item.mediaChoice is not None and item.mediaChoice.media is not None and \
not item.mediaChoice.media.isIndirect():
return item.mediaChoice

# See if we're missing media/stream details for this item.
Expand Down
55 changes: 47 additions & 8 deletions script.plexmod/lib/_included_packages/plexnet/myplexaccount.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@


class HomeUser(util.AttributeDict):
pass
def __repr__(self):
return '<{0}:{1}:{2} (admin: {3})>'.format(self.__class__.__name__, self.id,
self.get('title', 'None').encode('utf8'), self.get('admin', 0))


class MyPlexAccount(object):
Expand Down Expand Up @@ -48,6 +50,7 @@ def __init__(self):
self.adminHasPlexPass = False

self.lastHomeUserUpdate = None
self.revalidatePlexPass = False
self.homeUsers = []

def init(self):
Expand Down Expand Up @@ -128,6 +131,26 @@ def logState(self):
util.LOG("Admin: {0}".format(self.isAdmin))
util.LOG("AdminPlexPass: {0}".format(self.adminHasPlexPass))

def getHomeSubscription(self):
"""
This gets the state of the plex home subscription, which is easier to determine than using a combination of
isAdmin and adminHasPlexPass, especially when caching home users.
"""
try:
req = myplexrequest.MyPlexRequest("/api/v2/home")
xml = req.getToStringWithTimeout(seconds=util.LONG_TIMEOUT)
data = ElementTree.fromstring(xml)
return data.attrib.get('subscription') == '1'
except:
util.LOG("Couldn't get Plex Home info")
return
return False

def refreshSubscription(self):
ret = self.getHomeSubscription()
if isinstance(ret, bool):
self.isPlexPass = ret

def onAccountResponse(self, request, response, context):
oldId = self.ID

Expand All @@ -141,9 +164,11 @@ def onAccountResponse(self, request, response, context):
self.title = data.attrib.get('title')
self.username = data.attrib.get('username')
self.email = data.attrib.get('email')
self.thumb = data.attrib.get('thumb')
self.thumb = data.attrib.get('thumb').split("?")[0]
self.authToken = data.attrib.get('authenticationToken')
self.isPlexPass = (data.find('subscription') is not None and data.find('subscription').attrib.get('active') == '1')
self.isPlexPass = self.isPlexPass or \
(data.find('subscription') is not None and
data.find('subscription').attrib.get('active') == '1')
self.isManaged = data.attrib.get('restricted') == '1'
self.isSecure = data.attrib.get('secure') == '1'
self.hasQueue = bool(data.attrib.get('queueEmail'))
Expand All @@ -159,12 +184,20 @@ def onAccountResponse(self, request, response, context):
# Cache home users forever
epoch = time.time()

if self.lastHomeUserUpdate:
# never automatically update home users if we have some.
# if we've never seen any, check once a week
if (self.lastHomeUserUpdate and self.homeUsers) or \
(self.lastHomeUserUpdate and not self.homeUsers and epoch - self.lastHomeUserUpdate < 604800):
util.DEBUG_LOG(
"Skipping home user update (updated {0} seconds ago)".format(epoch - self.lastHomeUserUpdate))
else:
self.updateHomeUsers(use_async=bool(self.homeUsers))

# revalidate plex home subscription state after switching home user
if self.revalidatePlexPass and self.homeUsers:
self.refreshSubscription()
self.revalidatePlexPass = False

if self.isAdmin and self.isPlexPass:
self.adminHasPlexPass = True

Expand Down Expand Up @@ -221,8 +254,8 @@ def signOut(self, expired=False):

# Booleans
self.isSignedIn = False
self.isPlexPass = False
self.adminHasPlexPass = False
#self.isPlexPass = False
#self.adminHasPlexPass = False
self.isManaged = False
self.isSecure = False
self.isExpired = expired
Expand Down Expand Up @@ -260,7 +293,7 @@ def refreshAccount(self):
return
self.validateToken(self.authToken, False)

def updateHomeUsers(self, use_async=False):
def updateHomeUsers(self, use_async=False, refreshSubscription=False):
# Ignore request and clear any home users we are not signed in
if not self.isSignedIn:
self.homeUsers = []
Expand All @@ -280,6 +313,11 @@ def updateHomeUsers(self, use_async=False):
else:
self.onHomeUsersUpdateResponse(req, None, None)

if refreshSubscription:
self.refreshSubscription()
self.logState()
self.saveState()

def onHomeUsersUpdateResponse(self, request, response, context):
"""
this can either be called with a given request, which will lead to a synchronous request, or as a
Expand Down Expand Up @@ -331,7 +369,7 @@ def switchHomeUser(self, userId, pin=''):
self.validateToken(self.authToken, True)
return True
else:
# build path and post to myplex to swith the user
# build path and post to myplex to switch the user
path = '/api/home/users/{0}/switch'.format(userId)
req = myplexrequest.MyPlexRequest(path)
xml = req.postToStringWithTimeout({'pin': pin}, seconds=util.LONG_TIMEOUT)
Expand All @@ -344,6 +382,7 @@ def switchHomeUser(self, userId, pin=''):
self.isAuthenticated = True
# validate the token (trigger change:user) on user change or channel startup
if userId != self.ID or not locks.LOCKS.isLocked("idleLock"):
self.revalidatePlexPass = True
self.validateToken(data.attrib.get('authenticationToken'), True,
force_resource_refresh=plexapp.SERVERMANAGER.reachabilityNeverTested)
return True
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@


class MyPlexManager(object):
gotResources = False

def __init__(self):
self.gotResources = False

def publish(self):
util.LOG('MyPlexManager().publish() - NOT IMPLEMENTED')
return # TODO: ----------------------------------------------------------------------------------------------------------------------------- IMPLEMENT?
Expand Down Expand Up @@ -53,6 +58,7 @@ def onResourcesResponse(self, request, response, context):
response.parseFakeXMLResponse(data)
util.DEBUG_LOG("Using cached resources")

hosts = []
if response.container:
for resource in response.container:
util.DEBUG_LOG(
Expand All @@ -67,13 +73,16 @@ def onResourcesResponse(self, request, response, context):

for conn in resource.connections:
util.DEBUG_LOG(' {0}'.format(conn))
hosts.append(conn.address)

if 'server' in resource.provides:
server = plexserver.createPlexServerForResource(resource)
util.DEBUG_LOG(' {0}'.format(server))
servers.append(server)

self.gotResources = True
plexapp.SERVERMANAGER.updateFromConnectionType(servers, plexconnection.PlexConnection.SOURCE_MYPLEX)
util.APP.trigger("loaded:myplex_servers", hosts=hosts, source="myplex")


MANAGER = MyPlexManager()
Loading

0 comments on commit 1ac7714

Please sign in to comment.