import json
import random
import re
import time
from datetime import datetime
import xbmc
from lib.utils.kodi.settings import get_setting
from lib.utils.kodi.utils import action_url_run, kodilog
def is_trakt_auth():
if not get_setting("is_trakt_auth"):
kodilog("Trakt is not authenticated", level=xbmc.LOGDEBUG)
return False
kodilog("Trakt is authenticated", level=xbmc.LOGDEBUG)
return True
def _filter_trakt_actions(actions, include_add=True, include_remove=True):
filtered = []
for label, command, action_type in actions:
if action_type == "add" and not include_add:
continue
if action_type == "remove" and not include_remove:
continue
filtered.append((label, command))
return filtered
def add_trakt_watchlist_context_menu(media_type, ids, include_add=True, include_remove=True):
filtered_ids = clean_ids(
{
"tmdb": ids.get("tmdb_id") or ids.get("tmdb"),
"tvdb": ids.get("tvdb_id") or ids.get("tvdb"),
"imdb": ids.get("imdb_id") or ids.get("imdb"),
}
)
return _filter_trakt_actions(
[
(
"Add to Trakt Watchlist",
action_url_run(
"trakt_add_to_watchlist",
media_type=media_type,
ids=json.dumps(filtered_ids),
),
"add",
),
(
"Remove from Trakt Watchlist",
action_url_run(
"trakt_remove_from_watchlist",
media_type=media_type,
ids=json.dumps(filtered_ids),
),
"remove",
),
],
include_add,
include_remove,
)
def add_trakt_watched_context_menu(
media_type, season=None, episode=None, ids=None, include_add=True, include_remove=True
):
if ids is None:
ids = {}
filtered_ids = clean_ids(
{
"tmdb": ids.get("tmdb_id") or ids.get("tmdb"),
"tvdb": ids.get("tvdb_id") or ids.get("tvdb"),
"imdb": ids.get("imdb_id") or ids.get("imdb"),
}
)
return _filter_trakt_actions(
[
(
"Mark as Watched on Trakt",
action_url_run(
"trakt_mark_as_watched",
media_type=media_type,
ids=json.dumps(filtered_ids),
season=json.dumps(season),
episode=json.dumps(episode),
),
"add",
),
(
"Mark as Unwatched on Trakt",
action_url_run(
"trakt_mark_as_unwatched",
media_type=media_type,
ids=json.dumps(filtered_ids),
season=json.dumps(season),
episode=json.dumps(episode),
),
"remove",
),
],
include_add,
include_remove,
)
def add_trakt_collection_context_menu(media_type, ids, include_add=True, include_remove=True):
filtered_ids = clean_ids(
{
"tmdb": ids.get("tmdb_id") or ids.get("tmdb"),
"tvdb": ids.get("tvdb_id") or ids.get("tvdb"),
"imdb": ids.get("imdb_id") or ids.get("imdb"),
}
)
return _filter_trakt_actions(
[
(
"Add to Collection",
action_url_run(
"add_to_collection",
media_type=media_type,
ids=json.dumps(filtered_ids),
),
"add",
),
(
"Remove from Collection",
action_url_run(
"remove_from_collection",
media_type=media_type,
ids=json.dumps(filtered_ids),
),
"remove",
),
],
include_add,
include_remove,
)
def add_trakt_favorites_context_menu(media_type, ids, include_add=True, include_remove=True):
filtered_ids = clean_ids(
{
"tmdb": ids.get("tmdb_id") or ids.get("tmdb"),
"tvdb": ids.get("tvdb_id") or ids.get("tvdb"),
"imdb": ids.get("imdb_id") or ids.get("imdb"),
}
)
return _filter_trakt_actions(
[
(
"Add to Trakt Favorites",
action_url_run(
"trakt_add_to_favorites",
media_type=media_type,
ids=json.dumps(filtered_ids),
),
"add",
),
(
"Remove from Trakt Favorites",
action_url_run(
"trakt_remove_from_favorites",
media_type=media_type,
ids=json.dumps(filtered_ids),
),
"remove",
),
],
include_add,
include_remove,
)
def add_trakt_custom_list_context_menu(media_type, ids, include_add=True, include_remove=True):
filtered_ids = clean_ids(
{
"tmdb": ids.get("tmdb_id") or ids.get("tmdb"),
"tvdb": ids.get("tvdb_id") or ids.get("tvdb"),
"imdb": ids.get("imdb_id") or ids.get("imdb"),
}
)
return _filter_trakt_actions(
[
(
"Add to Trakt List",
action_url_run(
"trakt_add_item_to_list",
media_type=media_type,
ids=json.dumps(filtered_ids),
),
"add",
),
(
"Remove from Trakt List",
action_url_run(
"trakt_remove_item_from_list",
media_type=media_type,
ids=json.dumps(filtered_ids),
),
"remove",
),
],
include_add,
include_remove,
)
def clean_ids(ids_dict):
return {k: v for k, v in ids_dict.items() if v not in (None, "", "null")}
def jsondate_to_datetime(jsondate_object, resformat, remove_time=False):
if not jsondate_object:
return None
if remove_time:
datetime_object = datetime_workaround(jsondate_object, resformat).date()
else:
datetime_object = datetime_workaround(jsondate_object, resformat)
return datetime_object
def datetime_workaround(data, str_format):
try:
datetime_object = datetime.strptime(data, str_format)
except Exception:
datetime_object = datetime(*(time.strptime(data, str_format)[0:6]))
return datetime_object
def sort_list(sort_key, sort_direction, list_data):
try:
reverse = sort_direction != "asc"
if sort_key == "rank":
return sorted(list_data, key=lambda x: x["rank"], reverse=reverse)
if sort_key == "added":
return sorted(list_data, key=lambda x: x["listed_at"], reverse=reverse)
if sort_key == "title":
return sorted(
list_data,
key=lambda x: title_key(x[x["type"]].get("title")),
reverse=reverse,
)
if sort_key == "released":
return sorted(list_data, key=lambda x: released_key(x[x["type"]]), reverse=reverse)
if sort_key == "runtime":
return sorted(list_data, key=lambda x: x[x["type"]].get("runtime", 0), reverse=reverse)
if sort_key == "popularity":
return sorted(list_data, key=lambda x: x[x["type"]].get("votes", 0), reverse=reverse)
if sort_key == "percentage":
return sorted(list_data, key=lambda x: x[x["type"]].get("rating", 0), reverse=reverse)
if sort_key == "votes":
return sorted(list_data, key=lambda x: x[x["type"]].get("votes", 0), reverse=reverse)
if sort_key == "random":
return sorted(list_data, key=lambda k: random.random())
return list_data
except Exception:
return list_data
def released_key(item):
if "released" in item:
return item["released"] or "2050-01-01"
if "first_aired" in item:
return item["first_aired"] or "2050-01-01"
return "2050-01-01"
def title_key(title):
try:
if title is None:
title = ""
articles = ["the", "a", "an"]
match = re.match(r"^((\w+)\s+)", title.lower())
if match and match.group(2) in articles:
offset = len(match.group(1))
else:
offset = 0
return title[offset:]
except Exception:
return title
def sort_for_article(_list, _key):
_list.sort(key=lambda k: re.sub(r"(^the |^a |^an )", "", k[_key].lower()))
return _list