add missing kodi lib folder to remote

This commit is contained in:
mhdzumair
2024-06-29 22:05:29 +05:30
parent d72f321367
commit 12bbb089b2
4 changed files with 397 additions and 1 deletions
+2 -1
View File
@@ -142,4 +142,5 @@ config/
mediafusion.local*
.lock
kodi/build/
kodi/*.zip
kodi/*.zip
!kodi/**/lib/
+301
View File
@@ -0,0 +1,301 @@
import sys
from urllib import parse
import xbmc
import xbmcgui
import xbmcplugin
from .utils import (
fetch_data,
build_url,
ADDON_HANDLE,
BASE_URL,
SECRET_STR,
add_context_menu_items,
log,
)
def list_categories():
manifest_data = fetch_data(f"{BASE_URL}/{SECRET_STR}/manifest.json")
if not manifest_data:
return
catalogs = manifest_data.get("catalogs", [])
if not catalogs:
log("No catalogs enabled. Make sure to configure correctly", xbmc.LOGERROR)
xbmcgui.Dialog().notification(
"MediaFusion",
"No catalogs enabled. Make sure to configure correctly",
xbmcgui.NOTIFICATION_ERROR,
)
return
for catalog in catalogs:
if any(extra["name"] == "search" for extra in catalog.get("extra", [])):
continue
url = build_url(
"list_catalog", catalog_type=catalog["type"], catalog_id=catalog["id"]
)
li = xbmcgui.ListItem(label=catalog["name"])
xbmcplugin.addDirectoryItem(
handle=ADDON_HANDLE, url=url, listitem=li, isFolder=True
)
xbmcplugin.endOfDirectory(ADDON_HANDLE)
def list_catalogs(params):
log(f"Loading {params['catalog_type']} videos...", xbmc.LOGINFO)
skip = int(params.get("skip", 0))
url = f"{BASE_URL}/{SECRET_STR}/catalog/{params['catalog_type']}/{params['catalog_id']}/skip={skip}.json"
response = fetch_data(url)
if not response:
return
videos = response.get("metas", [])
if not videos:
xbmcgui.Dialog().notification(
"MediaFusion", "No videos available", xbmcgui.NOTIFICATION_ERROR
)
return
content_type = "movies" if params["catalog_type"] == "movie" else "tvshows"
xbmcplugin.setContent(ADDON_HANDLE, content_type)
for video in videos:
if params["catalog_type"] == "series":
url = build_url(
"list_seasons",
catalog_type=params["catalog_type"],
video_id=video["id"],
)
else:
url = build_url(
"get_streams", video_id=video["id"], catalog_type=params["catalog_type"]
)
li = xbmcgui.ListItem(label=video["name"])
tags = li.getVideoInfoTag()
tags.setUniqueID(
video["id"], type="imdb" if video["id"].startswith("tt") else "mf"
)
tags.setTitle(video["name"])
tags.setPlot(video.get("description", ""))
tags.setRating(float(video.get("imdbRating", 0)))
if video.get("releaseInfo"):
tags.setYear(int(video.get("releaseInfo").strip("--")))
tags.setGenres(video.get("genres", []))
li.setArt(
{
"thumb": video.get("poster", ""),
"poster": video.get("poster", ""),
"fanart": video.get("poster", ""),
"icon": video.get("poster", ""),
"banner": video.get("background", ""),
"landscape": video.get("background", ""),
}
)
add_context_menu_items(
li, video["id"], params["catalog_type"], params["catalog_id"]
)
xbmcplugin.addDirectoryItem(
handle=ADDON_HANDLE, url=url, listitem=li, isFolder=True
)
next_url = build_url(
"list_catalog",
catalog_type=params["catalog_type"],
catalog_id=params["catalog_id"],
skip=skip + len(videos),
)
li = xbmcgui.ListItem(label="Next Page")
xbmcplugin.addDirectoryItem(
handle=ADDON_HANDLE, url=next_url, listitem=li, isFolder=True
)
xbmcplugin.endOfDirectory(ADDON_HANDLE)
def list_seasons(params):
url = f"{BASE_URL}/{SECRET_STR}/meta/{params['catalog_type']}/{params['video_id']}.json"
response = fetch_data(url)
if not response:
return
meta_data = response.get("meta", {})
videos = meta_data.get("videos", [])
if not videos:
xbmcgui.Dialog().notification(
"MediaFusion", "No seasons available", xbmcgui.NOTIFICATION_ERROR
)
return
available_seasons = set(video["season"] for video in videos)
for season in available_seasons:
url = build_url(
"list_episodes",
catalog_type=params["catalog_type"],
video_id=params["video_id"],
season=season,
)
li = xbmcgui.ListItem(label=f"Season {season}")
tags = li.getVideoInfoTag()
tags.setUniqueID(
meta_data["id"], type="imdb" if meta_data["id"].startswith("tt") else "mf"
)
tags.setTitle(meta_data["name"])
tags.setPlot(meta_data.get("description", ""))
tags.setRating(float(meta_data.get("imdbRating", 0)))
if meta_data.get("releaseInfo"):
tags.setYear(int(meta_data.get("releaseInfo").strip("--")))
tags.setGenres(meta_data.get("genres", []))
tags.setTvShowTitle(meta_data["name"])
tags.setSeason(season)
li.setArt(
{
"thumb": meta_data.get("poster", ""),
"poster": meta_data.get("poster", ""),
"fanart": meta_data.get("poster", ""),
"icon": meta_data.get("poster", ""),
"banner": meta_data.get("background", ""),
"landscape": meta_data.get("background", ""),
}
)
add_context_menu_items(li, params["video_id"], params["catalog_type"])
xbmcplugin.addDirectoryItem(
handle=ADDON_HANDLE, url=url, listitem=li, isFolder=True
)
xbmcplugin.endOfDirectory(ADDON_HANDLE)
def list_episodes(params):
url = f"{BASE_URL}/{SECRET_STR}/meta/{params['catalog_type']}/{params['video_id']}.json"
response = fetch_data(url)
if not response:
return
meta_data = response.get("meta", {})
videos = meta_data.get("videos", [])
if not videos:
xbmcgui.Dialog().notification(
"MediaFusion", "No episodes available", xbmcgui.NOTIFICATION_ERROR
)
return
for video in videos:
if video["season"] != int(params["season"]):
continue
url = build_url(
"get_streams",
video_id=f"{params['video_id']}:{video['season']}:{video['episode']}",
catalog_type=params["catalog_type"],
)
li = xbmcgui.ListItem(label=video["title"])
tags = li.getVideoInfoTag()
tags.setUniqueID(
meta_data["id"], type="imdb" if meta_data["id"].startswith("tt") else "mf"
)
tags.setTitle(video["title"])
tags.setPlot(meta_data.get("description", ""))
tags.setRating(float(meta_data.get("imdbRating", 0)))
if meta_data.get("releaseInfo"):
tags.setYear(int(meta_data.get("releaseInfo").strip("--")))
tags.setGenres(meta_data.get("genres", []))
tags.setTvShowTitle(video["title"])
tags.setSeason(int(video["season"]))
tags.setEpisode(int(video["episode"]))
li.setArt(
{
"thumb": meta_data.get("poster", ""),
"poster": meta_data.get("poster", ""),
"fanart": meta_data.get("poster", ""),
"icon": meta_data.get("poster", ""),
"banner": meta_data.get("background", ""),
"landscape": meta_data.get("background", ""),
}
)
add_context_menu_items(li, params["video_id"], params["catalog_type"])
xbmcplugin.addDirectoryItem(
handle=ADDON_HANDLE, url=url, listitem=li, isFolder=True
)
xbmcplugin.endOfDirectory(ADDON_HANDLE)
def get_streams(params):
url = f"{BASE_URL}/{SECRET_STR}/stream/{params['catalog_type']}/{params['video_id']}.json"
response = fetch_data(url)
if not response:
return
streams = response.get("streams", [])
if not streams:
xbmcgui.Dialog().notification(
"MediaFusion", "No streams available", xbmcgui.NOTIFICATION_ERROR
)
return
for stream in streams:
li = xbmcgui.ListItem(label=stream["name"], offscreen=True)
tags = li.getVideoInfoTag()
tags.setTitle(stream["name"])
tags.setPlot(stream.get("description", ""))
li.setProperty("IsPlayable", "true")
xbmcplugin.addDirectoryItem(
handle=ADDON_HANDLE,
url=build_url(
"play_video",
video_url=stream["url"],
headers=parse.urlencode(
stream.get("behaviorHints", {})
.get("proxyHeaders", {})
.get("request", {})
),
),
listitem=li,
isFolder=False,
totalItems=len(streams),
)
xbmcplugin.endOfDirectory(ADDON_HANDLE)
def play_video(params):
video_url = params["video_url"]
li = xbmcgui.ListItem(path=video_url)
if "headers" in params:
li.setProperty("inputstream.adaptive.stream_headers", params["headers"])
xbmcplugin.setResolvedUrl(ADDON_HANDLE, True, li)
def addon_router():
param_string = sys.argv[2][1:]
if param_string:
params = dict(parse.parse_qsl(param_string))
action = params.get("action")
if action == "list_catalog":
list_catalogs(params)
elif action == "get_streams":
get_streams(params)
elif action == "list_seasons":
list_seasons(params)
elif action == "list_episodes":
list_episodes(params)
elif action == "play_video":
play_video(params)
else:
list_categories()
else:
list_categories()
@@ -0,0 +1,94 @@
import os
import sys
from urllib import parse
import requests
import xbmc
import xbmcaddon
import xbmcgui
ADDON_HANDLE = int(sys.argv[1])
ADDON = xbmcaddon.Addon()
ADDON_PATH = sys.argv[0]
MANIFEST_URL = ADDON.getSetting("manifest_url")
ADDON_ID = ADDON.getAddonInfo("id")
if not MANIFEST_URL:
xbmcgui.Dialog().notification(
"MediaFusion",
"Manifest URL is not set. Please configure the addon",
xbmcgui.NOTIFICATION_INFO,
)
xbmc.executebuiltin(f"Addon.OpenSettings({ADDON_ID})")
sys.exit(0)
parsed_url = parse.urlparse(MANIFEST_URL)
BASE_URL = f"{parsed_url.scheme}://{parsed_url.netloc}"
try:
SECRET_STR = parsed_url.path.split("/")[1]
except IndexError:
xbmcgui.Dialog().notification(
"MediaFusion",
"Invalid manifest URL. Please configure the addon",
xbmcgui.NOTIFICATION_ERROR,
)
xbmc.executebuiltin(f"Addon.OpenSettings({ADDON_ID})")
sys.exit(0)
def fetch_data(url):
try:
response = requests.get(url)
response.raise_for_status()
return response.json()
except requests.RequestException as e:
if e.response.status_code == 401:
xbmc.log("Unauthorized request", xbmc.LOGERROR)
xbmcgui.Dialog().notification(
"MediaFusion", "Unauthorized request", xbmcgui.NOTIFICATION_ERROR
)
elif e.response.status_code == 429:
xbmc.log("Too many requests, Try again in few seconds", xbmc.LOGERROR)
xbmcgui.Dialog().notification(
"MediaFusion",
"Too many requests, Try again in few seconds",
xbmcgui.NOTIFICATION_ERROR,
)
else:
xbmc.log(f"Request failed: {e}", xbmc.LOGERROR)
xbmcgui.Dialog().notification(
"MediaFusion", "Request failed", xbmcgui.NOTIFICATION_ERROR
)
return None
def build_url(action, **params):
query = parse.urlencode(params)
return f"{ADDON_PATH}?action={action}&{query}"
def add_context_menu_items(li, video_id, catalog_type, catalog_id=None):
context_menu = [
(
"Mark as Watched",
f"RunPlugin({build_url('mark_watched', video_id=video_id)})",
),
(
"Mark as Unwatched",
f"RunPlugin({build_url('mark_unwatched', video_id=video_id)})",
),
]
if catalog_id:
context_menu.insert(
0,
(
"Refresh",
f"Container.Refresh({build_url('list_catalog', catalog_type=catalog_type, catalog_id=catalog_id)})",
),
)
li.addContextMenuItems(context_menu)
def log(message, level=xbmc.LOGINFO):
xbmc.log(f"[MediaFusion] {message}", level)