Esempio n. 1
0
from resources.lib.MSLHttpRequestHandler import MSLHttpRequestHandler
from resources.lib.NetflixHttpRequestHandler import NetflixHttpRequestHandler

# helper function to select an unused port on the host machine
def select_unused_port():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('127.0.0.1', 0))
    addr, port = sock.getsockname()
    sock.close()
    return port

kodi_helper = KodiHelper()

# pick & store a port for the MSL service
msl_port = select_unused_port()
kodi_helper.set_setting('msl_service_port', str(msl_port))
kodi_helper.log(msg='[MSL] Picked Port: ' + str(msl_port))

# pick & store a port for the internal Netflix HTTP proxy service
ns_port = select_unused_port()
kodi_helper.set_setting('netflix_service_port', str(ns_port))
kodi_helper.log(msg='[NS] Picked Port: ' + str(ns_port))

# server defaults
SocketServer.TCPServer.allow_reuse_address = True

# configure the MSL Server
msl_server = SocketServer.TCPServer(('127.0.0.1', msl_port), MSLHttpRequestHandler)
msl_server.server_activate()
msl_server.timeout = 1
Esempio n. 2
0
class NetflixService(object):
    """
    Netflix addon service
    """
    def __init__(self):
        # init kodi helper (for logging)
        self.kodi_helper = KodiHelper()

        self.last_schedule_check = datetime.now()
        self.schedule_check_interval = int(
            self.kodi_helper.get_setting('schedule_check_interval'))
        self.startidle = 0
        self.freq = int('0' + self.kodi_helper.get_setting('auto_update'))

        # pick & store a port for the MSL service
        msl_port = select_unused_port()
        self.kodi_helper.set_setting('msl_service_port', str(msl_port))
        self.kodi_helper.log(msg='[MSL] Picked Port: ' + str(msl_port))

        # pick & store a port for the internal Netflix HTTP proxy service
        ns_port = select_unused_port()
        self.kodi_helper.set_setting('netflix_service_port', str(ns_port))
        self.kodi_helper.log(msg='[NS] Picked Port: ' + str(ns_port))

        # server defaults
        TCPServer.allow_reuse_address = True

        # configure the MSL Server
        self.msl_server = TCPServer(('127.0.0.1', msl_port),
                                    MSLHttpRequestHandler)
        self.msl_server.server_activate()
        self.msl_server.timeout = 1

        # configure the Netflix Data Server
        self.ns_server = TCPServer(('127.0.0.1', ns_port),
                                   NetflixHttpRequestHandler)
        self.ns_server.server_activate()
        self.ns_server.timeout = 1

    def _start_servers(self):
        # start thread for MLS servie
        msl_thread = threading.Thread(target=self.msl_server.serve_forever)
        msl_thread.daemon = True
        msl_thread.start()

        # start thread for Netflix HTTP service
        ns_thread = threading.Thread(target=self.ns_server.serve_forever)
        ns_thread.daemon = True
        ns_thread.start()

    def _shutdown(self):
        # MSL service shutdown sequence
        self.msl_server.server_close()
        self.msl_server.socket.close()
        self.msl_server.shutdown()
        self.kodi_helper.log(msg='Stopped MSL Service')

        # Netflix service shutdown sequence
        self.ns_server.server_close()
        self.ns_server.socket.close()
        self.ns_server.shutdown()
        self.kodi_helper.log(msg='Stopped HTTP Service')

    def _is_idle(self):
        if self.kodi_helper.get_setting('wait_idle') != 'true':
            return True

        lastidle = xbmc.getGlobalIdleTime()
        if xbmc.Player().isPlaying():
            self.startidle = lastidle
        if lastidle < self.startidle:
            self.startidle = 0
        idletime = lastidle - self.startidle
        return idletime >= 300

    def _update_running(self):
        update = self.kodi_helper.get_setting('update_running') or 'false'
        if update != 'false':
            starttime = strp(update, '%Y-%m-%d %H:%M')
            if (starttime + timedelta(hours=6)) <= datetime.now():
                self.kodi_helper.set_setting('update_running', 'false')
                self.kodi_helper.log(
                    'Canceling previous library update - duration > 6 hours',
                    xbmc.LOGWARNING)
            else:
                self.kodi_helper.log('DB Update already running')
                return True
        return False

    def run(self):
        """
        Main loop. Runs until xbmc.Monitor requests abort
        """
        self._start_servers()
        monitor = xbmc.Monitor()
        while not monitor.abortRequested():
            try:
                if self.library_update_scheduled() and self._is_idle():
                    self.update_library()
            except RuntimeError as exc:
                self.kodi_helper.log('RuntimeError: {}'.format(exc),
                                     xbmc.LOGERROR)
            if monitor.waitForAbort(5):
                break
        self._shutdown()

    def library_update_scheduled(self):
        """
        Checks if the scheduled time for a library update has been reached
        """
        now = datetime.now()
        next_schedule_check = (self.last_schedule_check +
                               timedelta(minutes=self.schedule_check_interval))

        if not self.freq or now <= next_schedule_check:
            self.kodi_helper.log('Auto-update disabled or schedule check '
                                 'interval not complete yet ({} / {}).'.format(
                                     now, next_schedule_check))
            return False

        self.last_schedule_check = now
        time = self.kodi_helper.get_setting('update_time') or '00:00'
        lastrun_date = (self.kodi_helper.get_setting('last_update')
                        or '1970-01-01')

        lastrun_full = lastrun_date + ' ' + time[0:5]
        lastrun = strp(lastrun_full, '%Y-%m-%d %H:%M')
        freqdays = [0, 1, 2, 5, 7][self.freq]
        nextrun = lastrun + timedelta(days=freqdays)

        self.kodi_helper.log(
            'It\'s currently {}, next run is scheduled for {}'.format(
                now, nextrun))

        return now >= nextrun

    def update_library(self):
        """
        Triggers an update of the local Kodi library
        """
        if not self._update_running():
            self.kodi_helper.log('Triggering library update', xbmc.LOGNOTICE)
            xbmc.executebuiltin(
                ('XBMC.RunPlugin(plugin://{}/?action=export-new-episodes'
                 '&inbackground=True)').format(
                     self.kodi_helper.get_addon().getAddonInfo('id')))
Esempio n. 3
0
    :return: int - Free port
    """
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('127.0.0.1', 0))
    _, port = sock.getsockname()
    sock.close()
    return port


# init kodi helper (for logging)
KODI_HELPER = KodiHelper()

# pick & store a port for the MSL service
MSL_PORT = select_unused_port()
KODI_HELPER.set_setting('msl_service_port', str(MSL_PORT))
KODI_HELPER.log(msg='[MSL] Picked Port: ' + str(MSL_PORT))

# pick & store a port for the internal Netflix HTTP proxy service
NS_PORT = select_unused_port()
KODI_HELPER.set_setting('netflix_service_port', str(NS_PORT))
KODI_HELPER.log(msg='[NS] Picked Port: ' + str(NS_PORT))

# server defaults
TCPServer.allow_reuse_address = True

# configure the MSL Server
MSL_SERVER = TCPServer(('127.0.0.1', MSL_PORT), MSLHttpRequestHandler)
MSL_SERVER.server_activate()
MSL_SERVER.timeout = 1