Skip to content
Open

Wip #1803

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions addon.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.netflix" name="Netflix" version="1.23.5+matrix.1" provider-name="libdev, jojo, asciidisco, caphm, castagnait">
<addon id="plugin.video.netflix" name="Netflix" version="1.23.6+matrix" provider-name="libdev, jojo, asciidisco, caphm, castagnait">
<requires>
<import addon="xbmc.python" version="3.0.0"/>
<import addon="script.module.addon.signals" version="0.0.6+matrix.1"/>
Expand Down Expand Up @@ -86,7 +86,9 @@
<email></email>
<forum>https://forum.kodi.tv/showthread.php?tid=329767</forum>
<source>https://github.com/CastagnaIT/plugin.video.netflix</source>
<news>v1.23.5 (2025-08-24)
<news>v1.23.6 (2026-08-25)
- Fix login with E-Mail/Password, the sign in is confirmed with the code sent by Netflix
v1.23.5 (2025-08-24)
- Fix esn error on login due to website changes
- Fix Nonetype error on startup due to website changes
</news>
Expand Down
16 changes: 9 additions & 7 deletions resources/lib/common/ipc.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
from .misc_utils import run_threaded

IPC_TIMEOUT_SECS = 20
# The login can wait the user that gets the one-time code sent by Netflix
IPC_TIMEOUT_SECS_LOGIN = 600

# IPC over HTTP endpoints
IPC_ENDPOINT_CACHE = '/netflix_service/cache'
Expand Down Expand Up @@ -75,7 +77,7 @@ def _send_signal(signal, data):


@measure_exec_time_decorator()
def make_call(func_name, data=None, endpoint=IPC_ENDPOINT_NFSESSION):
def make_call(func_name, data=None, endpoint=IPC_ENDPOINT_NFSESSION, timeout=IPC_TIMEOUT_SECS):
"""
Make an IPC call
:param func_name: function name
Expand All @@ -91,11 +93,11 @@ def make_call(func_name, data=None, endpoint=IPC_ENDPOINT_NFSESSION):
# https://github.com/xbmc/xbmc/issues/19332
# https://github.com/CastagnaIT/script.module.addon.connector
if G.IPC_OVER_HTTP:
return make_http_call(endpoint, func_name, data)
return make_addonsignals_call(func_name, data)
return make_http_call(endpoint, func_name, data, timeout)
return make_addonsignals_call(func_name, data, timeout)


def make_http_call(endpoint, func_name, data=None):
def make_http_call(endpoint, func_name, data=None, timeout=IPC_TIMEOUT_SECS):
"""
Make an IPC call via HTTP and wait for it to return.
The contents of data will be expanded to kwargs and passed into the target function.
Expand All @@ -109,7 +111,7 @@ def make_http_call(endpoint, func_name, data=None):
try:
with urlopen(url=url,
data=pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL),
timeout=IPC_TIMEOUT_SECS) as f:
timeout=timeout) as f:
received_data = f.read()
if received_data:
_data = pickle.loads(received_data)
Expand All @@ -127,7 +129,7 @@ def make_http_call(endpoint, func_name, data=None):
raise exceptions.BackendNotReady(err_msg) from exc


def make_addonsignals_call(callname, data):
def make_addonsignals_call(callname, data, timeout=IPC_TIMEOUT_SECS):
"""
Make an IPC call via AddonSignals and wait for it to return.
The contents of data will be expanded to kwargs and passed into the target function.
Expand All @@ -138,7 +140,7 @@ def make_addonsignals_call(callname, data):
source_id=G.ADDON_ID,
signal=callname,
data=_data,
timeout_ms=IPC_TIMEOUT_SECS * 1000,
timeout_ms=timeout * 1000,
use_timeout_exception=True)
_result = pickle.loads(b64decode(result))
if isinstance(_result, Exception):
Expand Down
4 changes: 2 additions & 2 deletions resources/lib/common/pathops.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ def get_path(path, search_space, include_key=False):

def get_path_safe(path, search_space, include_key=False, default=None):
"""Retrieve a value from a nested dict by following the path.
Returns default if any key in the path does not exist."""
Returns default if the path is missing or cannot be traversed."""
try:
return get_path(path, search_space, include_key)
except (KeyError, IndexError):
except (KeyError, IndexError, TypeError):
return default


Expand Down
12 changes: 8 additions & 4 deletions resources/lib/database/db_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,17 @@ def movie_id_exists(self, movieid):
"""Return True if a movie id exists"""
query = 'SELECT EXISTS(SELECT 1 FROM video_lib_movies WHERE MovieID = ?)'
cur = self._execute_query(query, (movieid,))
return bool(cur.fetchone()[0])
result = cur.fetchone()
return bool(result and result[0])

@db_base_mysql.handle_connection
@db_base_sqlite.handle_connection
def tvshow_id_exists(self, tvshowid):
"""Return True if a tvshow id exists"""
query = 'SELECT EXISTS(SELECT 1 FROM video_lib_tvshows WHERE TvShowID = ?)'
cur = self._execute_query(query, (tvshowid,))
return bool(cur.fetchone()[0])
result = cur.fetchone()
return bool(result and result[0])

@db_base_mysql.handle_connection
@db_base_sqlite.handle_connection
Expand All @@ -231,7 +233,8 @@ def season_id_exists(self, tvshowid, seasonid):
'ON video_lib_seasons.TvShowID = video_lib_tvshows.TvShowID '
'WHERE video_lib_tvshows.TvShowID = ? AND video_lib_seasons.SeasonID = ?)')
cur = self._execute_query(query, (tvshowid, seasonid))
return bool(cur.fetchone()[0])
result = cur.fetchone()
return bool(result and result[0])

@db_base_mysql.handle_connection
@db_base_sqlite.handle_connection
Expand All @@ -248,7 +251,8 @@ def episode_id_exists(self, tvshowid, seasonid, episodeid):
'video_lib_seasons.SeasonID = ? AND '
'video_lib_episodes.EpisodeID = ?)')
cur = self._execute_query(query, (tvshowid, seasonid, episodeid))
return bool(cur.fetchone()[0])
result = cur.fetchone()
return bool(result and result[0])

@db_base_mysql.handle_connection
@db_base_sqlite.handle_connection
Expand Down
32 changes: 20 additions & 12 deletions resources/lib/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,28 @@
'request_context_name': 'mylist',
'view': VIEW_MYLIST,
'has_sort_setting': True,
'query_without_reference': True}),
'query_without_reference': True,
'label_id': 30167,
'description_id': None,
'icon': 'DefaultVideoPlaylists.png'}),
('continueWatching', {'path': ['video_list', 'continueWatching'],
'loco_contexts': ['continueWatching'],
'loco_known': True}),
'loco_known': True,
'label_id': 30168,
'description_id': 30093,
'icon': 'DefaultInProgressShows.png'}),
('newAndPopular', {'path': ['category_list', 'newAndPopular'],
'loco_contexts': ['comingSoon'],
'loco_known': False,
'label_id': 30700,
'description_id': 30146,
'icon': 'DefaultRecentlyAddedMovies.png'}),

Check failure on line 91 in resources/lib/globals.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal 'DefaultRecentlyAddedMovies.png' 3 times.

See more on https://sonarcloud.io/project/issues?id=CastagnaIT_plugin.video.netflix&issues=AaBEwmo0UyLjMDBX0q8v&open=AaBEwmo0UyLjMDBX0q8v&pullRequest=1803
('chosenForYou', {'path': ['video_list', 'chosenForYou'],
'loco_contexts': ['topTen'],
'loco_known': True}),
'loco_known': True,
'label_id': 30169,
'description_id': 30094,
'icon': 'DefaultUser.png'}),
('recentlyAdded', {'path': ['video_list_sorted', 'recentlyAdded', '1592210'],
'loco_contexts': None,
'loco_known': False,
Expand All @@ -102,10 +111,16 @@
'query_without_reference': True}),
('currentTitles', {'path': ['video_list', 'currentTitles'],
'loco_contexts': ['trendingNow'],
'loco_known': True}),
'loco_known': True,
'label_id': 30150,
'description_id': 30146,
'icon': 'DefaultRecentlyAddedMovies.png'}),
('mostViewed', {'path': ['video_list', 'mostViewed'],
'loco_contexts': ['popularTitles'],
'loco_known': True}),
'loco_known': True,
'label_id': 30001,
'description_id': 30094,
'icon': 'DefaultUser.png'}),
('netflixOriginals', {'path': ['video_list_sorted', 'netflixOriginals', '839338'],
'loco_contexts': ['netflixOriginals'],
'loco_known': True,
Expand All @@ -120,13 +135,6 @@
'icon': 'DefaultTVShows.png',
'has_sort_setting': True,
'query_without_reference': True}),
('recommendations', {'path': ['recommendations', 'recommendations'],
'loco_contexts': ['similars', 'becauseYouAdded', 'becauseYouLiked', 'watchAgain',
'bigRow'],
'loco_known': False,
'label_id': 30001,
'description_id': 30094,
'icon': 'DefaultUser.png'}),
('tvshowsGenres', {'path': ['subgenres', 'tvshowsGenres', '83'],
'loco_contexts': None,
'loco_known': False,
Expand Down
Loading