Skip to content

Commit 1ffb7e7

Browse files
committed
purstream: expose factual stream metadata before Core presentation
1 parent 35508fc commit 1ffb7e7

1 file changed

Lines changed: 41 additions & 0 deletions

File tree

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env python3
2+
"""Expose Purstream stream facts without owning their final presentation.
3+
4+
The upstream bundle already encodes quality/language/codec/audio/runtime in its
5+
legacy multiline labels but historically publishes empty ``quality`` and
6+
``language`` fields. This adapter projects those existing facts into explicit
7+
fields while preserving URL, headers and the legacy text for downstream identity
8+
checks. The global Core presentation layer owns the user-facing description.
9+
"""
10+
from __future__ import annotations
11+
12+
import hashlib
13+
from typing import Any
14+
15+
MARKER = "NUVIO_PURSTREAM_STREAM_FACTS_V1"
16+
17+
18+
def apply(text: str, options: dict[str, Any] | None = None, **_kwargs: Any) -> str:
19+
marker = f"{MARKER}:{hashlib.sha256(b'facts-v1').hexdigest()[:12]}"
20+
if marker in text:
21+
return text
22+
wrapper = r'''
23+
/* MARKER_PLACEHOLDER */
24+
;(function(g){"use strict";
25+
function s(v){return String(v==null?"":v).trim()}
26+
function meaningful(v){var x=s(v);return x&&!/^(?:unknown|inconnue?|n\/?a|null|undefined|none|-+)$/i.test(x)}
27+
function slot(v){if(Array.isArray(v))return{key:null,list:v};if(v&&typeof v==="object"){for(var i=0;i<3;i++){var k=["streams","results","data"][i];if(Array.isArray(v[k]))return{key:k,list:v[k]}}}return null}
28+
function rebuild(v,x,list){if(x.key===null)return list;var o=Object.assign({},v);o[x.key]=list;return o}
29+
function blob(row){return [row&&row.name,row&&row.title,row&&row.size,row&&row.description].map(s).join(" ")}
30+
function quality(row,b){if(meaningful(row.quality)){var v=s(row.quality);return /^(?:4k|2160p)$/i.test(v)?"2160p":v}var u=b.toUpperCase();if(/(?:\b4K\b|\b2160P?\b)/.test(u))return"2160p";var m=u.match(/\b(1440|1080|720|576|540|480|360)P?\b/);return m?m[1]+"p":""}
31+
function language(row,b){if(meaningful(row.language))return s(row.language);var u=b.toUpperCase();if(/\bDUAL(?:[- ]?AUDIO)?\b/.test(u))return"Dual Audio";if(/\bVOSTFR\b/.test(u))return"VOSTFR";if(/\bVFQ\b/.test(u))return"VFQ";if(/\bVFF\b/.test(u))return"VFF";if(/\bVF\b/.test(u))return"VF";if(/\bVO\b/.test(u))return"VO";return""}
32+
function codec(row,b){if(meaningful(row.codec))return s(row.codec);var u=b.toUpperCase();if(/\b(?:HEVC|H\.?265|X265)\b/.test(u))return"HEVC";if(/\bAV1\b/.test(u))return"AV1";if(/\bVP9\b/.test(u))return"VP9";if(/\b(?:AVC|H\.?264|X264)\b/.test(u))return"H.264";return""}
33+
function audio(row,b){if(meaningful(row.audio))return s(row.audio);var u=b.toUpperCase(),ch="",m=u.match(/\b(7\.1|5\.1|2\.1|2\.0)\b/);if(m)ch=" "+m[1];if(/\b(?:ATMOS|DOLBY ATMOS)\b/.test(u))return"ATMOS"+ch;if(/\b(?:E-?AC-?3|DDP|DD\+)\b/.test(u))return"E-AC3"+ch;if(/\bAC-?3\b/.test(u))return"AC3"+ch;if(/\bDTS(?:-HD)?\b/.test(u))return(/\bDTS-HD\b/.test(u)?"DTS-HD":"DTS")+ch;if(/\bAAC\b/.test(u))return"AAC"+ch;return""}
34+
function duration(row,b){if(typeof row.duration==="number"&&Number.isFinite(row.duration)&&row.duration>0)return row.duration>600?Math.round(row.duration/60):Math.round(row.duration);var direct=s(row.duration),m=direct.match(/(\d{1,4})\s*(?:min|minutes?)\b/i);if(m)return Number(m[1]);var x=b.match(/\b(\d{1,3})\s*(?:min|minutes?)\b/i);return x?Number(x[1]):0}
35+
function sourceType(row,b){if(meaningful(row.sourceType))return s(row.sourceType);var u=b.toUpperCase();if(/\b(?:BLU[- ]?RAY|BDRIP|BRRIP|BDREMUX|REMUX)\b/.test(u))return"BLU-RAY";if(/\bWEB[- .]?DL\b/.test(u))return"WEB-DL";if(/\bWEB[- .]?RIP\b/.test(u))return"WEBRIP";return""}
36+
function facts(row){if(!row||typeof row!=="object")return row;var out=Object.assign({},row),b=blob(row),q=quality(row,b),l=language(row,b),c=codec(row,b),a=audio(row,b),d=duration(row,b),st=sourceType(row,b);if(q)out.quality=q;if(l)out.language=l;if(c)out.codec=c;if(a)out.audio=a;if(d)out.duration=d;if(st)out.sourceType=st;return out}
37+
function install(o,k){if(!o||typeof o[k]!=="function"||o[k].__nuvioPurstreamStreamFactsV1)return false;var native=o[k];var wrap=async function(){var v=await native.apply(this,arguments),x=slot(v);return x?rebuild(v,x,x.list.map(facts)):v};wrap.__nuvioPurstreamStreamFactsV1=true;o[k]=wrap;return true}
38+
var ok=false;try{if(typeof module!=="undefined"&&module.exports)ok=install(module.exports,"getStreams")}catch(_e){}try{if(g&&typeof g.getStreams==="function"){if(ok&&typeof module!=="undefined"&&module.exports)g.getStreams=module.exports.getStreams;else install(g,"getStreams")}}catch(_e){}
39+
})(typeof globalThis!=="undefined"?globalThis:this);
40+
'''.replace("MARKER_PLACEHOLDER", marker)
41+
return text.rstrip() + "\n" + wrapper.lstrip()

0 commit comments

Comments
 (0)