implement plexamp headless claim endpoint
This commit is contained in:
parent
45f0756191
commit
a7492c152d
@ -5,9 +5,13 @@ subscription.
|
||||
|
||||
### Requirements
|
||||
|
||||
- A router that can redirect traffic (i.e. OPNsense, pfSense, DD-WRT...)
|
||||
- (alternative) a DNS server that can redirect traffic *(some apps won't work due to DNS pinning)*
|
||||
- A router that **can redirect traffic** (i.e. OPNsense, pfSense, DD-WRT...)
|
||||
- _(alternative) a DNS server that can redirect traffic (some apps won't work due to DNS pinning)_
|
||||
- A reverse proxy (i.e. Traefik, Nginx, Caddy...)
|
||||
- A Plex server (self-hosted)
|
||||
|
||||
### What works?
|
||||
- PlexAmp mobile (download mode)
|
||||
|
||||
## How to setup ?
|
||||
|
||||
|
108
const.py
108
const.py
@ -1,4 +1,5 @@
|
||||
from datetime import datetime, timezone, timedelta
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
OFFICIAL_API = "https://clients.plex.tv"
|
||||
|
||||
@ -299,6 +300,113 @@ PLEXAMP_FEATURES = [
|
||||
"webhooks"
|
||||
]
|
||||
|
||||
PLEXAMP_SUBSCRIPTION_XML = ET.fromstring("""
|
||||
<subscription active="1" status="Active" plan="">
|
||||
<feature id="guided-upgrade" />
|
||||
<feature id="increase-password-complexity" />
|
||||
<feature id="upgrade-3ds2" />
|
||||
<feature id="ad-countdown-timer" />
|
||||
<feature id="adaptive_bitrate" />
|
||||
<feature id="amazon-loop-debug" />
|
||||
<feature id="Android - Dolby Vision" />
|
||||
<feature id="Android - PiP" />
|
||||
<feature id="avod-ad-analysis" />
|
||||
<feature id="avod-new-media" />
|
||||
<feature id="blacklist_get_signin" />
|
||||
<feature id="camera_upload" />
|
||||
<feature id="CU Sunset" />
|
||||
<feature id="client-radio-stations" />
|
||||
<feature id="cloudsync" />
|
||||
<feature id="cloudflare-turnstile-required" />
|
||||
<feature id="common-sense-media-ratings-premium" />
|
||||
<feature id="comments_and_replies_push_notifications" />
|
||||
<feature id="friend_request_push_notifications" />
|
||||
<feature id="community_access_plex_tv" />
|
||||
<feature id="community_friends_group_notifications" />
|
||||
<feature id="companions_sonos" />
|
||||
<feature id="content_filter" />
|
||||
<feature id="custom-home-removal" />
|
||||
<feature id="grandfather-sync" />
|
||||
<feature id="disable-facebook-auth" />
|
||||
<feature id="disable_home_user_friendships" />
|
||||
<feature id="disable_sharing_friendships" />
|
||||
<feature id="downloads-gating" />
|
||||
<feature id="drm_support" />
|
||||
<feature id="dvr" />
|
||||
<feature id="dvr-block-unsupported-countries" />
|
||||
<feature id="le_isrg_root_x1" />
|
||||
<feature id="epg-recent-channels" />
|
||||
<feature id="federated-auth" />
|
||||
<feature id="global-continue-watching" />
|
||||
<feature id="hwtranscode" />
|
||||
<feature id="hardware_transcoding" />
|
||||
<feature id="home" />
|
||||
<feature id="HRK_enable_EUR" />
|
||||
<feature id="imagga-v2" />
|
||||
<feature id="ios14-privacy-banner" />
|
||||
<feature id="item_clusters" />
|
||||
<feature id="iterable-notification-tokens" />
|
||||
<feature id="keep-payment-method" />
|
||||
<feature id="kevin-bacon" />
|
||||
<feature id="lets_encrypt" />
|
||||
<feature id="lightning-dvr-pivot" />
|
||||
<feature id="livetv" />
|
||||
<feature id="allow_dvr" />
|
||||
<feature id="live-tv-support-incomplete-segments" />
|
||||
<feature id="tuner-sharing" />
|
||||
<feature id="lyrics" />
|
||||
<feature id="metadata_search" />
|
||||
<feature id="vod_cloudflare" />
|
||||
<feature id="music_videos" />
|
||||
<feature id="new_plex_pass_prices" />
|
||||
<feature id="news-provider-sunset-modal" />
|
||||
<feature id="nominatim" />
|
||||
<feature id="pass" />
|
||||
<feature id="photos-favorites" />
|
||||
<feature id="photos-metadata-edition" />
|
||||
<feature id="photosV6-edit" />
|
||||
<feature id="photosV6-tv-albums" />
|
||||
<feature id="pms_health" />
|
||||
<feature id="premium-dashboard" />
|
||||
<feature id="premium_music_metadata" />
|
||||
<feature id="rate-limit-client-token" />
|
||||
<feature id="reactions_push_notifications_settings" />
|
||||
<feature id="shared_server_notification" />
|
||||
<feature id="shared_source_notification" />
|
||||
<feature id="redirect-subscription-to-account-page" />
|
||||
<feature id="scrobbling-service-plex-tv" />
|
||||
<feature id="album-types" />
|
||||
<feature id="collections" />
|
||||
<feature id="music-analysis" />
|
||||
<feature id="radio" />
|
||||
<feature id="session_bandwidth_restrictions" />
|
||||
<feature id="session_kick" />
|
||||
<feature id="exclude restrictions" />
|
||||
<feature id="signin_notification" />
|
||||
<feature id="signin_with_apple" />
|
||||
<feature id="skip-data-licensing-consent" />
|
||||
<feature id="sleep-timer" />
|
||||
<feature id="spring_serve_ad_provider" />
|
||||
<feature id="sync" />
|
||||
<feature id="trailers" />
|
||||
<feature id="transcoder_cache" />
|
||||
<feature id="boost-voices" />
|
||||
<feature id="TREBLE-show-features" />
|
||||
<feature id="silence-removal" />
|
||||
<feature id="sweet-fades" />
|
||||
<feature id="visualizers" />
|
||||
<feature id="volume-leveling" />
|
||||
<feature id="two-factor-authentication" />
|
||||
<feature id="unsupportedtuners" />
|
||||
<feature id="plexpass_from_billing_context" />
|
||||
<feature id="vod-schema" />
|
||||
<feature id="watch-together-invite" />
|
||||
<feature id="watchlist-rss" />
|
||||
<feature id="web_server_dashboard" />
|
||||
<feature id="webhooks" />
|
||||
</subscription>
|
||||
""")
|
||||
|
||||
ENTITLEMENTS = ["deprecated_google_iap_activation", "all", "roku", "android", "xbox_one", "xbox_360", "windows",
|
||||
"windows_phone", "ios"]
|
||||
|
||||
|
39
main_app.py
39
main_app.py
@ -8,7 +8,7 @@ from starlette.responses import JSONResponse
|
||||
from client import AsyncCustomHost, NameSolver
|
||||
from const import OFFICIAL_API, FEATURES_DICT, ENTITLEMENTS, CURRENT_DATE_MINUS_ONE_DAY, FEATURES, \
|
||||
CURRENT_DATE_MINUS_ONE_DAY_Z, NEXT_MONTH_DATE_Z, PLEXAMP_FEATURES, TIMESTAMP_CURRENT_PLUS_30DAYS, \
|
||||
TIMESTAMP_CURRENT_MINUS_30MIN
|
||||
TIMESTAMP_CURRENT_MINUS_30MIN, PLEXAMP_SUBSCRIPTION_XML
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@ -266,6 +266,7 @@ async def fake_user_signin(request: Request):
|
||||
|
||||
return await return_edited_response(upstream_response, data_override)
|
||||
|
||||
|
||||
@app.get("/api/v2/user.json")
|
||||
async def fake_get_user_json(request: Request):
|
||||
upstream_response = await call_official(request, request.url.path.lstrip("/"))
|
||||
@ -317,6 +318,42 @@ async def fake_get_user_json(request: Request):
|
||||
return await return_edited_response(upstream_response, data_override)
|
||||
|
||||
|
||||
@app.post("/api/claim/exchange")
|
||||
async def fake_claim_exchange(request: Request):
|
||||
upstream_response = await call_official(request, request.url.path.lstrip("/"))
|
||||
|
||||
data_override = None
|
||||
|
||||
content_type = upstream_response.headers.get("content-type", "")
|
||||
if content_type.startswith("application/xml"):
|
||||
data = ET.fromstring(upstream_response.content)
|
||||
|
||||
subscription = data.find("subscription")
|
||||
if subscription is not None:
|
||||
parent = data
|
||||
parent.remove(subscription)
|
||||
parent.append(PLEXAMP_SUBSCRIPTION_XML)
|
||||
|
||||
# --- Replace <entitlements> ---
|
||||
for ents in data.findall("entitlements"):
|
||||
data.remove(ents)
|
||||
entitlements = ET.SubElement(data, "entitlements", {"all": "1"})
|
||||
for entitlement in ENTITLEMENTS:
|
||||
ET.SubElement(entitlements, "entitlement", {"id": entitlement})
|
||||
|
||||
# --- Replace <roles> ---
|
||||
for roles in data.findall("roles"):
|
||||
data.remove(roles)
|
||||
roles = ET.SubElement(data, "roles")
|
||||
ET.SubElement(roles, "role", {"id": "plexpass"})
|
||||
|
||||
# Pretty print XML
|
||||
ET.indent(data)
|
||||
|
||||
data_override = ET.tostring(data, encoding="utf-8", method="xml")
|
||||
|
||||
return await return_edited_response(upstream_response, data_override)
|
||||
|
||||
|
||||
@app.get("/api/hack")
|
||||
async def hack_endpoint():
|
||||
|
Loading…
x
Reference in New Issue
Block a user