Skip to content

Commit

Permalink
Revert to previous Inputstream Adaptive version
Browse files Browse the repository at this point in the history
First tests with OQEE by Free
  • Loading branch information
f-lawe committed Dec 5, 2024
1 parent 3d82248 commit 805a182
Show file tree
Hide file tree
Showing 12 changed files with 168 additions and 21 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ If you need the latest update, you can download the latest ZIP archive from the
## Available providers
| Country | Provider | |
|:---------:|:------------------|:-|
| 🇫🇷 | OQEE by Free | Not working, under developpement |
| 🇫🇷 | Orange | |
| 🇫🇷 | Orange Caraïbe | |
| 🇫🇷 | Orange Réunion | thanks to [@starmate](https://github.com/starmate) and [@sae-gfc](https://github.com/sae-gfc) |
Expand Down
1 change: 1 addition & 0 deletions doc/README.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Si vous avez besoin de la dernière version, vous pouvez toujours télécharger
## Fournisseurs disponibles
| Pays | Fournisseur | |
|:---------:|:------------------|:-|
| 🇫🇷 | OQEE by Free | ne fonctionne pas, développement en cours |
| 🇫🇷 | Orange | |
| 🇫🇷 | Orange Caraïbe | |
| 🇫🇷 | Orange Réunion | merci à [@starmate](https://github.com/starmate) et [@sae-gfc](https://github.com/sae-gfc)
Expand Down
2 changes: 1 addition & 1 deletion resources/language/resource.language.en_gb/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ msgstr ""
# Integration settings (from 30100 to 30199)

msgctxt "#30100"
msgid "TV Integration"
msgid "IPTV Integration"
msgstr ""

msgctxt "#30101"
Expand Down
4 changes: 2 additions & 2 deletions resources/language/resource.language.fr_fr/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ msgstr ""
# Integration settings (from 30100 to 30199)

msgctxt "#30100"
msgid "TV Integration"
msgstr "Intégration TV"
msgid "IPTV Integration"
msgstr "Intégration IPTV"

msgctxt "#30101"
msgid "Install IPTV Manager…"
Expand Down
13 changes: 8 additions & 5 deletions resources/lib/managers/stream_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,15 @@ def _load_stream(self, stream_getter: Callable[[str], dict], stream_id: str) ->
xbmcplugin.setResolvedUrl(router.handle, False, create_play_item())
return

is_helper = inputstreamhelper.Helper(stream_info["protocol"], drm=stream_info["drm_config"]["drm"])
drm = stream_info.get("drm_config", {}).get("license_type")

if is_helper.check_inputstream():
play_item = create_play_item(stream_info, is_helper.inputstream_addon)
xbmcplugin.setResolvedUrl(router.handle, True, play_item)
return
if drm:
is_helper = inputstreamhelper.Helper(stream_info["protocol"], drm=stream_info["drm_config"]["license_type"])

if is_helper.check_inputstream():
play_item = create_play_item(stream_info, is_helper.inputstream_addon)
xbmcplugin.setResolvedUrl(router.handle, True, play_item)
return

log("Cannot load InputStream", xbmc.LOGERROR)
ok_dialog(localize(30901))
Expand Down
3 changes: 2 additions & 1 deletion resources/lib/providers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
from lib.utils.kodi import get_addon_setting, log

from .abstract_provider import AbstractProvider
from .fr import OrangeCaraibeProvider, OrangeFranceProvider, OrangeReunionProvider
from .fr import FreeOqeeProvider, OrangeCaraibeProvider, OrangeFranceProvider, OrangeReunionProvider

_PROVIDERS = {
"France.OQEE by Free": FreeOqeeProvider,
"France.Orange": OrangeFranceProvider,
"France.Orange Caraïbe": OrangeCaraibeProvider,
"France.Orange Réunion": OrangeReunionProvider,
Expand Down
22 changes: 14 additions & 8 deletions resources/lib/providers/abstract_orange_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,15 +277,21 @@ def _compute_stream_info(self, stream: dict, tv_token: str, wassup: str) -> dict
"path": stream.get("url"),
"protocol": "mpd",
"mime_type": "application/xml+dash",
"drm_config": { # Keeping items in order
"drm": get_drm(),
"license_server_url": license_server_url,
"headers": urlencode(
"drm_config": {
"license_type": get_drm(),
"license_key": "|".join(
{
"tv_token": f"Bearer {tv_token}",
"Content-Type": "",
"Cookie": f"wassup={wassup}",
}
"licence_server_url": license_server_url,
"headers": urlencode(
{
"tv_token": f"Bearer {tv_token}",
"Content-Type": "",
"Cookie": f"wassup={wassup}",
}
),
"post_data": "R{SSM}",
"response_data": "",
}.values()
),
},
}
Expand Down
1 change: 1 addition & 0 deletions resources/lib/providers/fr/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""."""

from .free_oqee import FreeOqeeProvider as FreeOqeeProvider
from .orange_caraibe import OrangeCaraibeProvider as OrangeCaraibeProvider
from .orange_france import OrangeFranceProvider as OrangeFranceProvider
from .orange_reunion import OrangeReunionProvider as OrangeReunionProvider
128 changes: 128 additions & 0 deletions resources/lib/providers/fr/free_oqee.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
"""OQEE by Free. WIP."""

import json
from typing import List
from urllib.parse import urlencode

import xbmc
from requests.exceptions import RequestException

from lib.exceptions import AuthenticationRequired
from lib.providers.abstract_provider import AbstractProvider
from lib.utils.kodi import build_addon_url, get_drm, log
from lib.utils.request import get_random_ua, request, request_json

_SERVICE_PLAN_ENDPOINT = "https://api.oqee.net/api/v5/service_plan"
_LOGIN_ENDPOINT = "https://api.oqee.net/api/v5/user/login"

_STREAM_LOGO_URL = "https://img1.dc2.oqee.net/channel_pictures/{stream_id}/w200"


class FreeOqeeProvider(AbstractProvider):
"""OQEE by Free provider."""

def get_live_stream_info(self, stream_id: str) -> dict:
"""Get live stream information (MPD address, Widewine key) for the specified id. Returned keys: path, mime_type, manifest_type, drm, license_type, license_key.""" # noqa: E501
try:
res = request(
"POST", _LOGIN_ENDPOINT, headers={"Content-Type": "application/json"}, data=json.dumps({"type": "ip"})
)
except RequestException as e:
log(e, xbmc.LOGWARNING)
raise AuthenticationRequired() from e

login = res.json()

if login.get("result", False) is False:
log("Failed to login to OQEE", xbmc.LOGWARNING)
raise AuthenticationRequired()

# token = login["result"]["token"]

# log(token)

stream_info = {
"path": "https://api-proxad.dc2.oqee.net/playlist/v1/live/612/1/live.mpd",
"protocol": "mpd",
"mime_type": "application/xml+dash",
"drm_config": {
"license_type": get_drm(),
"license_key": "|".join(
{
"license_server_url": "https://license.oqee.net/api/v1/live/license/widevine",
"headers": urlencode(
{
"Host": "license.oqee.net",
"User-Agent": get_random_ua(),
"Accept": "*/*",
"Accept-Language": "fr-FR,fr;q=0.8,en-GB;q=0.5,en;q=0.3",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Referer": "https://oqee.tv/",
"content-type": "application/json",
"x-oqee-account-provider": "free",
"x-oqee-customization": "1",
"x-oqee-platform": "web",
"x-oqee-profile": "qYyeeAzNbuWNxByv",
"Content-Length": "25",
"Origin": "https://oqee.tv",
"DNT": "1",
"Connection": "keep-alive",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "cross-site",
"Priority": "u=4",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
"TE": "trailers",
}
),
"post_data": "R{SSM}",
"response_data": "J[result.license]",
}.values()
),
},
}

return stream_info

def get_catchup_stream_info(self, stream_id: str) -> dict:
"""Get catchup stream information (MPD address, Widewine key) for the specified id. Returned keys: path, mime_type, manifest_type, drm, license_type, license_key.""" # noqa: E501
pass

def get_streams(self) -> list:
"""Load stream data from OQEE and convert it to JSON-STREAMS format."""
service_plan = {"channels": {}, "channel_list": []}
service_plan = request_json(_SERVICE_PLAN_ENDPOINT, default={"result": service_plan})["result"]
# channel_list = service_plan["channel_list"].sort(key=lambda channel: channel["number"])
channel_list = service_plan["channel_list"]

log(f"{len(channel_list)} channels found", xbmc.LOGINFO)

return [
{
"preset": str(channel["number"]),
**self._extract_channel_info(channel["channel_id"], service_plan["channels"]),
}
for channel in channel_list
]

def get_epg(self) -> list:
"""Load EPG data from OQEE and convert it to JSON-EPG format."""
return []

def get_catchup_items(self, levels: List[str]) -> list:
"""Return a list of directory items for the specified levels."""
pass

def _extract_channel_info(self, channel_id: dict, channels: dict, icon_type: str = "icon_dark") -> dict:
"""."""
for channel in channels.values():
if channel["id"] == channel_id and channel.get("freebox_id") is not None:
return {
"id": str(channel["freebox_id"]),
"name": channel["name"],
"logo": channel[icon_type].replace("%d", "200"),
"stream": build_addon_url(f"/stream/live/{channel['freebox_id']}"),
}

return {}
2 changes: 1 addition & 1 deletion resources/lib/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def index():


@router.route("/catchup/<path:levels>")
def catchup_(levels: str):
def catchup_directory(levels: str):
"""Display catchup service directory."""
log(f"Display catchup directory {levels}", xbmc.LOGINFO)
CatchupManager().build_directory(levels)
Expand Down
8 changes: 7 additions & 1 deletion resources/lib/utils/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ def create_play_item(stream_info: dict = None, inputstream_addon: str = "") -> L
play_item.setMimeType(stream_info.get("mime_type"))

play_item.setProperty("inputstream", inputstream_addon)
play_item.setProperty("inputstream.adaptive.drm_legacy", "|".join(stream_info.get("drm_config", {}).values()))

drm_config = stream_info.get("drm_config", {})
keys = ["license_type", "license_key", "license_data", "server_certificate", "license_flags", "pre_init_data"]

for key in keys:
if drm_config.get(key) is not None:
play_item.setProperty(f"inputstream.adaptive.{key}", drm_config.get(key))

return play_item
4 changes: 2 additions & 2 deletions resources/settings.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings>
<!-- TV Integration -->
<!-- IPTV Integration -->
<category label="30100">
<setting id="iptv.channels_uri">
<level>4</level>
Expand All @@ -22,7 +22,7 @@
<setting id="provider.country" label="30201" help="30202" type="select" values="France">
<default>France</default>
</setting>
<setting id="provider.name" visible="eq(-1,France)" label="30203" help="30204" type="labelenum" values="Orange|Orange Caraïbe|Orange Réunion">
<setting id="provider.name" visible="eq(-1,France)" label="30203" help="30204" type="labelenum" values="OQEE by Free|Orange|Orange Caraïbe|Orange Réunion">
<default>Orange</default>
</setting>
<setting type="lsep"/>
Expand Down

0 comments on commit 805a182

Please sign in to comment.