def post(self, url, hidden=False, **kwargs):
     kodi.log("LOADING: %s" % url)
     if kwargs and not hidden:
         kodi.log("Payload: %s" % kwargs)
     req = self.session.post(url, timeout=30, **kwargs)
     req.soup = MethodType(self.soup, req)
     return req
 def func_mapper(task):
     '''Stores indication of whether function errored'''
     try:
         task.func(task.obj)
     except Exception as exc:
         kodi.log("Error removing %s:\n%s" % (task.obj, traceback.format_exc().decode(sys.getfilesystemencoding())))
         task.exception = exc
 def tap(self, keycode, character, press_bool):
     """get single key then stop keyboardevent"""
     if press_bool:
         self.keycode = keycode
         self.character = character
         kodi.log(keycode)
         kodi.log(character)
         self.stop()
 def run(self, player):
     self.player = player
     funcmap = {button.code: button.func for button in self.mapping if button.code}
     self.listener = PlaybackListener(funcmap)
     self.listener.run()
     missing_keys = [button.name for button in self.mapping if button.code not in funcmap]
     if missing_keys:
         kodi.log("Note, following actions are not mapped to remote: %s" % missing_keys)
 def monitor_movie_progress(self, playingfile):
     kodi.log("starting monitoring")
     movie = MediaItem(name=playingfile["label"], kodiid=playingfile["id"], playcount=playingfile["playcount"],
                       runtime=dt.timedelta(seconds=playingfile["runtime"]))
     started_watching_at = dt.datetime.now()
     self.stop_event.wait()
     self.mark_watched(movie, started_watching_at)
     kodi.log("finished monitoring")
def _getapiurl(contextdata):
    kodi.log("setting api url")
    try:
        shakti_api_root = contextdata["serverDefs"]["data"]["SHAKTI_API_ROOT"]
        build_identifier = contextdata["serverDefs"]["data"]["BUILD_IDENTIFIER"]
    except KeyError:
        kodi.log(contextdata)
        raise
    api = shakti_api_root + "/" + build_identifier
    return api
    def setup(self):
        self.load_cookies()
        kodi.log("Checking login")
        page = self.get("https://www.netflix.com/login")
        if page.url != "https://www.netflix.com/browse":
            raise Exception("Login failed. Ensure chrome is logged in")
        contextdata = _extract_contextdata(page.text)

        if kodi.settings["geolocation"] and kodi.settings["geolocation"] != "Any country":
            _check_location(contextdata)
        self.endpoints = contextdata["serverDefs"]["data"]["endpointIdentifiers"]
        self.authurl = contextdata["userInfo"]["data"]["authURL"]
 def mark_watched(self, mediaitem, started_watching_at):
     finished_watching_at = dt.datetime.now()
     watch_duration = finished_watching_at - started_watching_at
     if 0 in (mediaitem.runtime.seconds, watch_duration.seconds):
         return
     if watch_duration.seconds / mediaitem.runtime.seconds >= 0.9:
         kodi.rpc("VideoLibrary.SetEpisodeDetails", episodeid=mediaitem.kodiid,
                  playcount=mediaitem.playcount + 1, lastplayed=finished_watching_at.strftime("%d-%m-%Y %H:%M:%S"))
         kodi.log("%s: Marked as watched" % mediaitem.name)
     else:
         kodi.log("%s: Skipped, only partially watched (%s vs. %s)" %
                  (mediaitem.name, mediaitem.runtime.seconds, watch_duration.seconds))
 def coro_mapper(task):
     '''Executes next step in coroutine sent as arg,
        Prints traceback otherwise swallowed due to multithreading
        Stores indication of whether coroutine is finished (stopiteration), errored (exception), or unfinished
        '''
     try:
         next(task.coroutine)
     except StopIteration:
         task.finished = True
     except Exception as exc:
         kodi.log("Error adding/updating %s:\n%s" % (task.obj, traceback.format_exc().decode(sys.getfilesystemencoding())))
         task.exception = exc
         task.finished = True
    def connect(self):
        try:
            self.browser = Chromote(host="localhost", port=9222)
        except requests.exceptions.ConnectionError:
            self.browser = Chromote(host="localhost", port=9222, internet_explorer=True)
        kodi.log("connected to %s: %s" % (self.browser.browsertype, self.browser))

        while not self.stop_event.check():
            try:
                self.tab = next(tab for tab, title, url in self.browser.tabs if url != "about:blank" and "file://" not in url)
                break
            except StopIteration:
                xbmc.sleep(200)
        self.tab.connect_websocket()
        kodi.log("websocket connected: %s" % self.tab.url)
def run_schedule():
    timeout = minutes_to_next_rounded_update_time()
    kodi.log("Starting update scheduler, next update at %s" %
             (dt.datetime.now() + dt.timedelta(seconds=timeout)).strftime("%H:%M"))
    while True:
        abort = xbmc.Monitor().waitForAbort(timeout)
        if abort:
            kodi.log("Closing background service")
            break
        timeout = {
            "15 min": 900,
            "30 min": 1800,
            "1 hour": 3600,
            "2 hours": 7200
        }[kodi.settings["schedule frequency"]]

        scheduler_enabled = kodi.settings["enable schedule"]
        player_active = kodi.rpc("Player.GetActivePlayers")
        koala_active = xbmcgui.Window(10000).getProperty("%s running" % const.addonname) == "true"
        if player_active or koala_active or not scheduler_enabled:
            continue

        kodi.log("Starting scheduled update next update at %s" %
                 (dt.datetime.now() + dt.timedelta(seconds=timeout)).strftime("%H:%M"))
        xbmc.executebuiltin("RunScript(%s, mode=library, action=schedule)" % const.addonid)
    def setup(self):
        playingfile = self.get_playing_file()
        if not playingfile["file"].startswith((utils.uni_join(const.libpath, const.provider),
                                               utils.uni_join(const.addonpath, "resources"))):
            return
        try:
            kodi.log("Start playback setup")

            self.player = Player(stop_event=self.stop_event)

            if kodi.settings["remote"]:
                self.remote = remote.Remote()
                self.remote.run(player=self.player)

            self.player.connect()

            if playingfile["type"] == "episode":
                Thread(target=self.monitor_episodes_progress, args=[playingfile]).start()
            elif playingfile["type"] == "movie":
                Thread(target=self.monitor_movie_progress, args=[playingfile]).start()

            kodi.log("Finished playback setup")

        except self.player.exceptions:
            pass

        except:
            kodi.log("Exception occured during playback\n%s" % traceback.format_exc().decode(sys.getfilesystemencoding()))

        finally:
            self.stop_event.wait()

            kodi.log("Start playback cleanup")
            if self.remote:
                self.remote.close()
            if self.player:
                self.player.disconnect()
            kodi.log("Finish playback cleanup")
def library_mode(action):
    if xbmcgui.Window(10000).getProperty("%s running" % const.addonname) == "true":
        if action in ["startup", "schedule"]:
            return
        run = kodi.Dialog.yesno(heading="Running", line1="Koala is running. ",
                                line2="Running multiple instances may cause instablity.", line3="Continue?")
        if not run:
            return
    koalasetup()
    if not is_libpath_added():
        kodi.Dialog.ok(heading="Koala path not in video sources",
                       line1="Koala library paths have not been added to Kodi video sources:",
                       line2=utils.uni_join(const.libpath, "%s shows" % const.provider),
                       line3=utils.uni_join(const.libpath, "%s movies" % const.provider))
        return

    starttime = dt.datetime.now()
    kodi.log("Starting %s" % action)
    xbmcgui.Window(10000).setProperty("%s running" % const.addonname, "true")
    try:
        library.main(action)
    finally:
        xbmcgui.Window(10000).setProperty("%s running" % const.addonname, "false")
        kodi.log("Finished %s in %s" % (action, str(dt.datetime.now() - starttime)))
def remove_show(show):
    kodi.log("Removing show: %s" % show.title)
    koala_stored_episodes = show.get_koala_stored_eps()
    for lib_entry in koala_stored_episodes:
        lib_entry.save_playcount()
        lib_entry.delete_htm()
        lib_entry.remove_from_lib()
    databases.stored_shows.remove(show)
    kodi.log("Removed episodes: %s, %s" % (show.title, sorted(koala_stored_episodes)))
    kodi.log("Finished removing show: %s" % show.title)
def get_watchlist_changes(session, tasks):
    available_movies, available_shows = session.get_watchlist()

    unav_movies = databases.stored_movies - available_movies
    kodi.log("unavailable_movies:\n %s" % unav_movies)
    tasks["removals"].extend([Task(movie, remove_movie) for movie in unav_movies])

    unav_shows = databases.stored_shows - available_shows
    kodi.log("unavailable_shows:\n %s" % unav_shows)
    tasks["removals"].extend([Task(show, remove_show) for show in unav_shows])

    new_movies = available_movies - (databases.stored_movies | databases.excluded_movies)
    kodi.log("new_movies:\n %s" % new_movies)
    tasks["updates"].extend([Task(movie, add_movie) for movie in new_movies])

    new_shows = available_shows - (databases.stored_shows | databases.excluded_shows)
    kodi.log("new_shows:\n %s" % new_shows)
    tasks["updates"].extend([Task(show, update_add_show) for show in new_shows])
def remove_movie(movie):
    kodi.log("Removing movie: %s" % movie)
    lib_entry = movie.get_lib_entry()
    if lib_entry:
        lib_entry.save_playcount()
        lib_entry.remove_from_lib()
        lib_entry.delete_htm()
    else:
        kodi.log("Couldn't find in library: %s" % (movie))
    if kodi.settings["added_notifications"]:
        kodi.Dialog.notification(heading="%s movie removed:" % const.provider, message=movie.title)
    databases.stored_movies.remove(movie)
    kodi.log("Finished removing movie: %s" % movie)
def add_movie(movie, session):
    kodi.log("Adding movie: %s" % movie)
    movie.write_htm()
    yield

    lib_entry = movie.get_lib_entry()
    if not lib_entry:
        metadata = session.get_movie_metadata(movie)
        movie.write_nfo(metadata)
        movie.write_htm()
        kodi.log("NFO created, waiting for second lib update: %s" % movie.title)
        yield

        lib_entry = movie.get_lib_entry()
        if not lib_entry:
            kodi.log("Failed to add movie: %s" % movie)
            return
    lib_entry.load_playcount()
    if kodi.settings["added_notifications"]:
        kodi.Dialog.notification(heading="%s movie added:" % const.provider, message=movie.title)
    databases.stored_movies.add(movie)
    kodi.log("Finished adding movie: %s" % movie)
    def monitor_episodes_progress(self, playingfile):
        kodi.log("starting monitoring")
        first_urlid, stored_episodes = self.get_episodes(playingfile)

        current_urlid = first_urlid
        episode_watching = stored_episodes[current_urlid]
        started_watching_at = dt.datetime.now()
        while not self.stop_event.is_set:
            new_urlid = self.player.wait_for_new_episode(starting_urlid=current_urlid)
            if new_urlid is None:
                break  # browser closed
            if episode_watching:
                self.mark_watched(episode_watching, started_watching_at)

            kodi.log("new urlid: %s" % new_urlid)
            current_urlid = new_urlid
            episode_watching = stored_episodes.get(current_urlid)
            started_watching_at = dt.datetime.now()

        self.mark_watched(episode_watching, started_watching_at)
        kodi.log("finished monitoring")
def exclude_show(show):
    kodi.log("Excluding show: %s" % show.title)
    remove_show(show)
    databases.excluded_shows.add(show)
    kodi.log("Finished excluding show: %s" % show.title)
def readd_movie(movie, session):
    kodi.log("Readding movie: %s" % movie.title)
    for step in add_movie(movie, session):
        yield
    databases.excluded_movies.remove(movie)
    kodi.log("Finished readding movie: %s" % movie.title)
def exclude_movie(movie):
    kodi.log("Excluding movie: %s" % movie.title)
    remove_movie(movie)
    databases.excluded_movies.add(movie)
    kodi.log("Finished excluding movie: %s" % movie.title)
 def cont(self):
     kodi.log("Remote: cont triggered")
     self.player.cont()
 def playpause(self):
     kodi.log("Remote: playpause triggered")
     self.player.playpause()
def readd_show(show, session):
    kodi.log("Readding show: %s" % show.title)
    for step in update_add_show(show, session):
        yield
    databases.excluded_shows.remove(show)
    kodi.log("Finished readding show: %s" % show.title)
 def stop(self):
     PyKeyboardEvent.stop(self)
     kodi.log("keygetter stopped")
 def next(self):
     kodi.log("Remote: next triggered")
     self.player.next()
 def forward(self):
     kodi.log("Remote: forward triggered")
     self.player.forward()
def update_add_show(show, session):
    kodi.log("Updating show: %s" % show.title)
    show_metadata, available_episodes = session.get_showdata_episodes(show)
    unav_episodes, new_episodes = show.get_episode_availability(available_episodes)
    if unav_episodes:
        for lib_entry in unav_episodes:
            lib_entry.save_playcount()
            lib_entry.delete_htm()
            lib_entry.remove_from_lib()
        kodi.log("Removed episodes: %s, %s" % (show, sorted(unav_episodes)))
    if new_episodes:
        for episode in new_episodes:
            episode.write_htm()
        kodi.log("htms created, waiting for lib update: %s %s" %
                 (show, sorted(new_episodes)))
        yield

        koala_stored_episodes = show.get_koala_stored_eps()
        nonadded_episodes = new_episodes - koala_stored_episodes
        if nonadded_episodes:
            if not koala_stored_episodes:
                show.write_nfo(show_metadata)
            for episode in nonadded_episodes:
                episode.write_nfo()
                episode.write_htm()
            kodi.log("NFOs created, waiting for second lib update: %s, %s" %
                     (show, sorted(nonadded_episodes)))
            yield

            koala_stored_episodes = show.get_koala_stored_eps()
            nonadded_episodes = new_episodes - koala_stored_episodes
            if nonadded_episodes:
                kodi.log("Failed to add episodes: %s, %s" % (show, sorted(nonadded_episodes)))

        added_episodes = koala_stored_episodes - nonadded_episodes
        for lib_entry in added_episodes:
            lib_entry.load_playcount()

        if kodi.settings["added_notifications"]:
            if len(new_episodes) == 1:
                message = "Added episode: %s" % list(new_episodes)[0].code
            elif len(new_episodes) <= 3:
                message = "Added episodes: %s" % ", ".join(sorted([ep.code for ep in new_episodes]))
            else:
                message = "Added %s episodes" % len(new_episodes)
            kodi.Dialog.notification(heading=show.title, message=message)
        kodi.log("Added episodes: %s, %s" % (show, sorted(added_episodes)))
    databases.stored_shows.upsert(show)
    kodi.log("Finished updating show: %s" % show)
 def stop(self):
     kodi.log("Remote: stop triggered")
     self.player.stop()
 def rewind(self):
     kodi.log("Remote: rewind triggered")
     self.player.rewind()