Merge pull request #913 from croneter/fix-timezones

Fix PKC potentially marking a video as watched on startup; don't sync time by toggling a video watch status but use PMS epoch time
This commit is contained in:
croneter 2019-06-29 16:54:11 +02:00 committed by GitHub
commit fb4de9fb92
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 6 additions and 128 deletions

View file

@ -2,7 +2,6 @@
from __future__ import absolute_import, division, unicode_literals from __future__ import absolute_import, division, unicode_literals
from .full_sync import start from .full_sync import start
from .time import sync_pms_time
from .websocket import store_websocket_message, process_websocket_messages, \ from .websocket import store_websocket_message, process_websocket_messages, \
WEBSOCKET_MESSAGES, PLAYSTATE_SESSIONS WEBSOCKET_MESSAGES, PLAYSTATE_SESSIONS
from .common import update_kodi_library, PLAYLIST_SYNC_ENABLED from .common import update_kodi_library, PLAYLIST_SYNC_ENABLED

View file

@ -1,104 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals
from logging import getLogger
from .. import plex_functions as PF, utils, timing, variables as v, app
LOG = getLogger('PLEX.sync.time')
def sync_pms_time():
"""
PMS does not provide a means to get a server timestamp. This is a work-
around - because the PMS might be in another time zone
In general, everything saved to Kodi shall be in Kodi time.
Any info with a PMS timestamp is in Plex time, naturally
"""
LOG.info('Synching time with PMS server')
# Find a PMS item where we can toggle the view state to enforce a
# change in lastViewedAt
# Get all Plex libraries
sections = PF.get_plex_sections()
if sections is None:
LOG.error("Error download PMS views, abort sync_pms_time")
return False
plex_id = None
typus = (
(v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_MOVIE,),
(v.PLEX_TYPE_SHOW, v.PLEX_TYPE_EPISODE),
(v.PLEX_TYPE_ARTIST, v.PLEX_TYPE_SONG)
)
for section_type, plex_type in typus:
if plex_id:
break
for section in sections:
if plex_id:
break
if not section.attrib['type'] == section_type:
continue
library_id = section.attrib['key']
try:
iterator = PF.SectionItems(library_id, plex_type=plex_type)
for item in iterator:
if item.get('viewCount'):
# Don't want to mess with items that have playcount>0
continue
if item.get('viewOffset'):
# Don't mess with items with a resume point
continue
plex_id = utils.cast(int, item.get('ratingKey'))
LOG.info('Found a %s item to sync with: %s',
plex_type, plex_id)
break
except RuntimeError:
pass
if plex_id is None:
LOG.error("Could not find an item to sync time with")
LOG.error("Aborting PMS-Kodi time sync")
return False
# Get the Plex item's metadata
xml = PF.GetPlexMetadata(plex_id)
if xml in (None, 401):
LOG.error("Could not download metadata, aborting time sync")
return False
timestamp = xml[0].get('lastViewedAt')
if timestamp is None:
timestamp = xml[0].get('updatedAt')
LOG.debug('Using items updatedAt=%s', timestamp)
if timestamp is None:
timestamp = xml[0].get('addedAt')
LOG.debug('Using items addedAt=%s', timestamp)
if timestamp is None:
timestamp = 0
LOG.debug('No timestamp; using 0')
timestamp = utils.cast(int, timestamp)
# Set the timer
koditime = timing.unix_timestamp()
# Toggle watched state
PF.scrobble(plex_id, 'watched')
# Let the PMS process this first!
app.APP.monitor.waitForAbort(1)
# Get updated metadata
xml = PF.GetPlexMetadata(plex_id)
# Toggle watched state back
PF.scrobble(plex_id, 'unwatched')
try:
plextime = xml[0].attrib['lastViewedAt']
except (IndexError, TypeError, AttributeError, KeyError):
LOG.warn('Could not get lastViewedAt - aborting')
return False
# Calculate time offset Kodi-PMS
timing.KODI_PLEX_TIME_OFFSET = float(koditime) - float(plextime)
utils.settings('kodiplextimeoffset',
value=str(timing.KODI_PLEX_TIME_OFFSET))
LOG.info("Time offset Koditime - Plextime in seconds: %s",
timing.KODI_PLEX_TIME_OFFSET)
return True

View file

@ -87,8 +87,6 @@ class Service(object):
utils.window(prop, clear=True) utils.window(prop, clear=True)
clientinfo.getDeviceId() clientinfo.getDeviceId()
# Init time-offset between Kodi and Plex
timing.KODI_PLEX_TIME_OFFSET = float(utils.settings('kodiplextimeoffset') or 0.0)
self.startup_completed = False self.startup_completed = False
self.server_has_been_online = True self.server_has_been_online = True

View file

@ -137,7 +137,6 @@ class Sync(backgroundthread.KillableThread):
playlist_monitor = None playlist_monitor = None
initial_sync_done = False initial_sync_done = False
last_websocket_processing = 0 last_websocket_processing = 0
last_time_sync = 0
one_day_in_seconds = 60 * 60 * 24 one_day_in_seconds = 60 * 60 * 24
# Link to Websocket queue # Link to Websocket queue
queue = app.APP.websocket_queue queue = app.APP.websocket_queue
@ -171,8 +170,6 @@ class Sync(backgroundthread.KillableThread):
return return
if not install_sync_done: if not install_sync_done:
# Very FIRST sync ever upon installation or reset of Kodi DB # Very FIRST sync ever upon installation or reset of Kodi DB
# Initialize time offset Kodi - PMS
library_sync.sync_pms_time()
last_time_sync = timing.unix_timestamp() last_time_sync = timing.unix_timestamp()
LOG.info('Initial start-up full sync starting') LOG.info('Initial start-up full sync starting')
xbmc.executebuiltin('InhibitIdleShutdown(true)') xbmc.executebuiltin('InhibitIdleShutdown(true)')
@ -227,10 +224,6 @@ class Sync(backgroundthread.KillableThread):
not app.APP.is_playing_video): not app.APP.is_playing_video):
LOG.info('Doing scheduled full library scan') LOG.info('Doing scheduled full library scan')
self.start_library_sync() self.start_library_sync()
elif now - last_time_sync > one_day_in_seconds:
LOG.info('Starting daily time sync')
library_sync.sync_pms_time()
last_time_sync = now
elif not app.SYNC.background_sync_disabled: elif not app.SYNC.background_sync_disabled:
# Check back whether we should process something Only do # Check back whether we should process something Only do
# this once a while (otherwise, potentially many screen # this once a while (otherwise, potentially many screen

View file

@ -6,9 +6,6 @@ from time import localtime, strftime
EPOCH = datetime.utcfromtimestamp(0) EPOCH = datetime.utcfromtimestamp(0)
# What's the time offset between the PMS and Kodi?
KODI_PLEX_TIME_OFFSET = 0.0
def unix_timestamp(seconds_into_the_future=None): def unix_timestamp(seconds_into_the_future=None):
""" """
@ -37,27 +34,23 @@ def unix_date_to_kodi(unix_kodi_time):
def plex_date_to_kodi(plex_timestamp): def plex_date_to_kodi(plex_timestamp):
""" """
converts a Unix time stamp (seconds passed sinceJanuary 1 1970) to a converts a PMS epoch time stamp (seconds passed since January 1 1970, Plex
propper, human-readable time stamp used by Kodi sends timezone-independent epoch) to a propper, human-readable time stamp
used by Kodi (varies per time-zone!)
Output: Y-m-d h:m:s = 2009-04-05 23:16:04 Output: Y-m-d h:m:s = 2009-04-05 23:16:04
Returns None if plex_timestamp is not valid (e.g. -1)) Returns None if plex_timestamp is not valid (e.g. -1))
""" """
try: try:
return strftime('%Y-%m-%d %H:%M:%S', return unix_date_to_kodi(plex_timestamp)
localtime(float(plex_timestamp) + KODI_PLEX_TIME_OFFSET))
except ValueError: except ValueError:
# the PMS can return -1 as plex_timestamp - great! # the PMS can return -1 as plex_timestamp - great!
return pass
def kodi_date_to_plex(kodi_timestamp):
return float(kodi_timestamp) - KODI_PLEX_TIME_OFFSET
def plex_now(): def plex_now():
return kodi_date_to_plex(unix_timestamp()) return unix_timestamp()
def kodi_timestamp(plex_timestamp): def kodi_timestamp(plex_timestamp):

View file

@ -82,7 +82,6 @@
<setting label="[COLOR yellow]$ADDON[plugin.video.plexkodiconnect 30517][/COLOR]" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect?mode=passwords)" option="close" /><!-- Set network credentials for Direct Paths and direct play --> <setting label="[COLOR yellow]$ADDON[plugin.video.plexkodiconnect 30517][/COLOR]" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect?mode=passwords)" option="close" /><!-- Set network credentials for Direct Paths and direct play -->
<setting id="streamMusic" type="bool" label="30510" default="false" visible="false" subsetting="true"/> <!-- Direct stream Music library --> <setting id="streamMusic" type="bool" label="30510" default="false" visible="false" subsetting="true"/> <!-- Direct stream Music library -->
<setting id="kodiplextimeoffset" type="number" label="Time difference in seconds (Koditime - Plextime)" default="0" visible="false" option="int" />
<setting id="themoviedbAPIKey" type="text" default="19c90103adb9e98f2172c6a6a3d85dc4" visible="false"/> <setting id="themoviedbAPIKey" type="text" default="19c90103adb9e98f2172c6a6a3d85dc4" visible="false"/>
<setting id="FanArtTVAPIKey" type="text" default="639191cb0774661597f28a47e7e2bad5" visible="false"/> <setting id="FanArtTVAPIKey" type="text" default="639191cb0774661597f28a47e7e2bad5" visible="false"/>
<setting id="syncEmptyShows" type="bool" label="30508" default="false" visible="false"/> <setting id="syncEmptyShows" type="bool" label="30508" default="false" visible="false"/>