/*** Thanks to & modified from 1. https://gist.githubusercontent.com/Hyseen/b06e911a41036ebc36acf04ddebe7b9a/raw/nf_check.js 2. https://github.com/AtlantisGawrGura/Quantumult-X-Scripts/blob/main/media.js 3. https://github.com/CoiaPrant/MediaUnlock_Test/blob/main/check.sh For Quantumult-X 598+ ONLY!! [task_local] event-interaction https://raw.githubusercontent.com/KOP-XIAO/QuantumultX/master/Scripts/streaming-ui-check.js, tag=流媒体-解锁查询, img-url=checkmark.seal.system, enabled=true @XIAO_KOP **/ const BASE_URL = 'https://www.netflix.com/title/'; const BASE_URL_YTB = "https://www.youtube.com/premium"; const BASE_URL_DISNEY = 'https://www.disneyplus.com'; const BASE_URL_Dazn = "https://startup.core.indazn.com/misl/v5/Startup"; const FILM_ID = 81215567 const link = { "media-url": "https://raw.githubusercontent.com/KOP-XIAO/QuantumultX/master/img/southpark/7.png" } const policy_name = "Netflix" //填入你的 netflix 策略组名 const arrow = " ➟ " const UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36' // 即将登陆 const STATUS_COMING = 2 // 支持解锁 const STATUS_AVAILABLE = 1 // 不支持解锁 const STATUS_NOT_AVAILABLE = 0 // 检测超时 const STATUS_TIMEOUT = -1 // 检测异常 const STATUS_ERROR = -2 var opts = { policy: $environment.params }; var opts1 = { policy: $environment.params, redirection: false }; var flags = new Map([[ "AC" , "🇦🇨" ] ,["AE","🇦🇪"], [ "AF" , "🇦🇫" ] , [ "AI" , "🇦🇮" ] , [ "AL" , "🇦🇱" ] , [ "AM" , "🇦🇲" ] , [ "AQ" , "🇦🇶" ] , [ "AR" , "🇦🇷" ] , [ "AS" , "🇦🇸" ] , [ "AT" , "🇦🇹" ] , [ "AU" , "🇦🇺" ] , [ "AW" , "🇦🇼" ] , [ "AX" , "🇦🇽" ] , [ "AZ" , "🇦🇿" ] , ["BA", "🇧🇦"], [ "BB" , "🇧🇧" ] , [ "BD" , "🇧🇩" ] , [ "BE" , "🇧🇪" ] , [ "BF" , "🇧🇫" ] , [ "BG" , "🇧🇬" ] , [ "BH" , "🇧🇭" ] , [ "BI" , "🇧🇮" ] , [ "BJ" , "🇧🇯" ] , [ "BM" , "🇧🇲" ] , [ "BN" , "🇧🇳" ] , [ "BO" , "🇧🇴" ] , [ "BR" , "🇧🇷" ] , [ "BS" , "🇧🇸" ] , [ "BT" , "🇧🇹" ] , [ "BV" , "🇧🇻" ] , [ "BW" , "🇧🇼" ] , [ "BY" , "🇧🇾" ] , [ "BZ" , "🇧🇿" ] , [ "CA" , "🇨🇦" ] , [ "CF" , "🇨🇫" ] , [ "CH" , "🇨🇭" ] , [ "CK" , "🇨🇰" ] , [ "CL" , "🇨🇱" ] , [ "CM" , "🇨🇲" ] , [ "CN" , "🇨🇳" ] , [ "CO" , "🇨🇴" ] , [ "CP" , "🇨🇵" ] , [ "CR" , "🇨🇷" ] , [ "CU" , "🇨🇺" ] , [ "CV" , "🇨🇻" ] , [ "CW" , "🇨🇼" ] , [ "CX" , "🇨🇽" ] , [ "CY" , "🇨🇾" ] , [ "CZ" , "🇨🇿" ] , [ "DE" , "🇩🇪" ] , [ "DG" , "🇩🇬" ] , [ "DJ" , "🇩🇯" ] , [ "DK" , "🇩🇰" ] , [ "DM" , "🇩🇲" ] , [ "DO" , "🇩🇴" ] , [ "DZ" , "🇩🇿" ] , [ "EA" , "🇪🇦" ] , [ "EC" , "🇪🇨" ] , [ "EE" , "🇪🇪" ] , [ "EG" , "🇪🇬" ] , [ "EH" , "🇪🇭" ] , [ "ER" , "🇪🇷" ] , [ "ES" , "🇪🇸" ] , [ "ET" , "🇪🇹" ] , [ "EU" , "🇪🇺" ] , [ "FI" , "🇫🇮" ] , [ "FJ" , "🇫🇯" ] , [ "FK" , "🇫🇰" ] , [ "FM" , "🇫🇲" ] , [ "FO" , "🇫🇴" ] , [ "FR" , "🇫🇷" ] , [ "GA" , "🇬🇦" ] , [ "GB" , "🇬🇧" ] , [ "HK" , "🇭🇰" ] ,["HU","🇭🇺"], [ "ID" , "🇮🇩" ] , [ "IE" , "🇮🇪" ] , [ "IL" , "🇮🇱" ] , [ "IM" , "🇮🇲" ] , [ "IN" , "🇮🇳" ] , [ "IS" , "🇮🇸" ] , [ "IT" , "🇮🇹" ] , [ "JP" , "🇯🇵" ] , [ "KR" , "🇰🇷" ] , [ "LU" , "🇱🇺" ] , [ "MO" , "🇲🇴" ] , [ "MX" , "🇲🇽" ] , [ "MY" , "🇲🇾" ] , [ "NL" , "🇳🇱" ] , [ "PH" , "🇵🇭" ] , [ "RO" , "🇷🇴" ] , [ "RS" , "🇷🇸" ] , [ "RU" , "🇷🇺" ] , [ "RW" , "🇷🇼" ] , [ "SA" , "🇸🇦" ] , [ "SB" , "🇸🇧" ] , [ "SC" , "🇸🇨" ] , [ "SD" , "🇸🇩" ] , [ "SE" , "🇸🇪" ] , [ "SG" , "🇸🇬" ] , [ "TH" , "🇹🇭" ] , [ "TN" , "🇹🇳" ] , [ "TO" , "🇹🇴" ] , [ "TR" , "🇹🇷" ] , [ "TV" , "🇹🇻" ] , [ "TW" , "🇨🇳" ] , [ "UK" , "🇬🇧" ] , [ "UM" , "🇺🇲" ] , [ "US" , "🇺🇸" ] , [ "UY" , "🇺🇾" ] , [ "UZ" , "🇺🇿" ] , [ "VA" , "🇻🇦" ] , [ "VE" , "🇻🇪" ] , [ "VG" , "🇻🇬" ] , [ "VI" , "🇻🇮" ] , [ "VN" , "🇻🇳" ] , [ "ZA" , "🇿🇦"]]) let result = { "title": ' 📺 流媒体服务查询', "YouTube": 'YouTube: 检测失败,请重试', "Netflix": 'Netflix: 检测失败,请重试', "Dazn": "Dazn: 检测失败,请重试", "Disney": "Disney⁺: 检测失败,请重试", //"Google": "Google 定位: 检测失败,请重试" } const message = { action: "get_policy_state", content: $environment.params }; ;(async () => { testYTB() testDazn() let [{ region, status }] = await Promise.all([testDisneyPlus(),testNf(FILM_ID)]) console.log(result["Netflix"]) console.log(`testDisneyPlus: region=${region}, status=${status}`) if (status==STATUS_COMING) { //console.log(1) result["Disney"] = "Disney⁺: 即将登陆 ➟ "+'⟦'+flags.get(region.toUpperCase())+"⟧" } else if (status==STATUS_AVAILABLE){ //console.log(2) result["Disney"] = "Disney⁺: 已支持 ➟ "+'⟦'+flags.get(region.toUpperCase())+"⟧" console.log(result["Disney"]) } else if (status==STATUS_NOT_AVAILABLE) { //console.log(3) result["Disney"] = "Disney⁺: 未支持 " } else if (status==STATUS_TIMEOUT) { result["Disney"] = "Disney⁺: 测试超时 " } let content = "------------------------------"+"
"+([result["YouTube"],result["Netflix"],result["Disney"],result["Dazn"]]).join("

") content = content + "
------------------------------
"+""+"节点 ➟ " + $environment.params+ "" content =`

` + content + `

` // cnt = `

` +'----------------------

'+result["Disney"]+'

----------------------
'+$environment.params + `

` $configuration.sendMessage(message).then(resolve => { if (resolve.error) { console.log(resolve.error); $done() } if (resolve.ret) { let output=JSON.stringify(resolve.ret[message.content])? JSON.stringify(resolve.ret[message.content]).replace(/\"|\[|\]/g,"").replace(/\,/g," ➟ ") : $environment.params let content = "------------------------------"+"
"+([result["YouTube"],result["Netflix"],result["Disney"],result["Dazn"]]).join("

") content = content + "
------------------------------
"+""+"节点 ➟ " + output+ "" content =`

` + content + `

` //$notify(typeof(output),output) console.log(output); $done({"title":result["title"],"htmlMessage":content}) } //$done();| }, reject => { // Normally will never happen. $done(); }); //$done({"title":result["title"],"htmlMessage":content}) })() .finally(() => { $configuration.sendMessage(message).then(resolve => { if (resolve.error) { console.log(resolve.error); $done() } if (resolve.ret) { let output=JSON.stringify(resolve.ret[message.content])? JSON.stringify(resolve.ret[message.content]).replace(/\"|\[|\]/g,"").replace(/\,/g," ➟ ") : $environment.params let content = "------------------------------"+"
"+([result["YouTube"],result["Netflix"],result["Disney"],result["Dazn"]]).join("

") content = content + "
------------------------------
"+""+"节点 ➟ " + output+ "" content =`

` + content + `

` //$notify(typeof(output),output) console.log(output); $done({"title":result["title"],"htmlMessage":content}) } //$done();| }, reject => { // Normally will never happen. $done(); }); $done({"title":result["title"],"htmlMessage":`

`+'----------------------

'+"🚥 检测异常"+'

----------------------
'+ output + `

`}) } ); async function testDisneyPlus() { try { let { region, cnbl } = await Promise.race([testHomePage(), timeout(7000)]) console.log(`homepage: region=${region}, cnbl=${cnbl}`) // 即将登陆 if (cnbl == 2) { return { region, status: STATUS_COMING } } let { countryCode, inSupportedLocation } = await Promise.race([getLocationInfo(), timeout(7000)]) console.log(`getLocationInfo: countryCode=${countryCode}, inSupportedLocation=${inSupportedLocation}`) region = countryCode ?? region console.log( "region:"+region) // 即将登陆 if (inSupportedLocation === false || inSupportedLocation === 'false') { return { region, status: STATUS_COMING } } else { // 支持解锁 return { region, status: STATUS_AVAILABLE } } } catch (error) { console.log("error:"+error) // 不支持解锁 if (error === 'Not Available') { console.log("不支持") return { status: STATUS_NOT_AVAILABLE } } // 检测超时 if (error === 'Timeout') { return { status: STATUS_TIMEOUT } } return { status: STATUS_ERROR } } } function getLocationInfo() { return new Promise((resolve, reject) => { let opts0 = { url: 'https://disney.api.edge.bamgrid.com/graph/v1/device/graphql', method: "POST", opts: opts, headers: { 'Accept-Language': 'en', "Authorization": 'ZGlzbmV5JmJyb3dzZXImMS4wLjA.Cu56AgSfBTDag5NiRA81oLHkDZfu5L3CKadnefEAY84', 'Content-Type': 'application/json', 'User-Agent': UA, }, body: JSON.stringify({ query: 'mutation registerDevice($input: RegisterDeviceInput!) { registerDevice(registerDevice: $input) { grant { grantType assertion } } }', variables: { input: { applicationRuntime: 'chrome', attributes: { browserName: 'chrome', browserVersion: '94.0.4606', manufacturer: 'microsoft', model: null, operatingSystem: 'windows', operatingSystemVersion: '10.0', osDeviceIds: [], }, deviceFamily: 'browser', deviceLanguage: 'en', deviceProfile: 'windows', }, }, }), } $task.fetch(opts0).then(response => { let data = response.body console.log("locationinfo:"+response.statusCode) if (response.statusCode !== 200) { console.log('getLocationInfo: ' + data) reject('Not Available') return } else {let { inSupportedLocation, location: { countryCode }, } = JSON.parse(data)?.extensions?.sdk?.session resolve({ inSupportedLocation, countryCode }) } }, reason => { reject('Error') return }) }) } function testHomePage() { return new Promise((resolve, reject) => { let opts0 = { url: 'https://www.disneyplus.com/', opts: opts, headers: { 'Accept-Language': 'en', 'User-Agent': UA, }, } $task.fetch(opts0).then(response => { let data = response.body console.log("homepage"+response.statusCode) if (response.statusCode !== 200 || data.indexOf('unavailable') !== -1) { reject('Not Available') return } else { let match = data.match(/Region: ([A-Za-z]{2})[\s\S]*?CNBL: ([12])/) if (!match) { resolve({ region: '', cnbl: '' }) return } else { let region = match[1] let cnbl = match[2] //console.log("homepage"+region+cnbl) resolve({ region, cnbl }) } } }, reason => { reject('Error') return }) }) } function timeout(delay = 5000) { return new Promise((resolve, reject) => { setTimeout(() => { reject('Timeout') }, delay) }) } function testNf(filmId) { return new Promise((resolve, reject) =>{ let option = { url: BASE_URL + filmId, opts: opts, timeout: 3200, headers: { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36', }, } $task.fetch(option).then(response => { //$notify("nf:"+response.statusCode) console.log("nf:"+response.statusCode) if (response.statusCode === 404) { result["Netflix"] = "Netflix: 支持自制剧集" console.log("nf:"+result["Netflix"]) resolve('Not Found') return } else if (response.statusCode === 403) { //console.log("nfnf") result["Netflix"] = "Netflix: 未支持" console.log("nf:"+result["Netflix"]) // $notify("nf:"+result["Netflix"]) resolve('Not Available') return } else if (response.statusCode === 200) { let url = response.headers['X-Originating-URL'] let region = url.split('/')[3] region = region.split('-')[0] if (region == 'title') { region = 'us' } console.log("nf:"+region) result["Netflix"] = "Netflix: 完整支持"+ "⟦"+flags.get(region.toUpperCase())+"⟧" //$notify("nf:"+result["Netflix"]) resolve("nf:"+result["Netflix"]) return } }, reason => { result["Netflix"] = "Netflix: 检测超时" console.log(result["Netflix"]) resolve("timeout") } ) } ) } function testYTB() { let option = { url: BASE_URL_YTB, opts: opts, timeout: 2800, headers: { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36' }, } $task.fetch(option).then(response=> { let data = response.body console.log("ytb:"+response.statusCode) if (response.statusCode !== 200) { //reject('Error') result["YouTube"] = "YouTube Premium: 检测失败" } else if (data.indexOf('Premium is not available in your country') !== -1) { //resolve('Not Available') result["YouTube"] = "YouTube Premium: 未支持" } else if (data.indexOf('Premium is not available in your country') == -1) {//console.log(data.split("countryCode")[1]) let region = '' let re = new RegExp('"GL":"(.*?)"', 'gm') let ret = re.exec(data) if (ret != null && ret.length === 2) { region = ret[1] } else if (data.indexOf('www.google.cn') !== -1) { region = 'CN' } else { region = 'US' } //resolve(region) result["YouTube"] = "YouTube Premium: 支持"+ "⟦"+flags.get(region.toUpperCase())+"⟧" console.log("ytb:"+region+ result["YouTube"]) } }, reason => { result["YouTube"] = "YouTube Premium: 检测超时" //resolve("timeout") }) } function testDazn() { const extra =`{ "LandingPageKey":"generic", "Platform":"web", "PlatformAttributes":{}, "Manufacturer":"", "PromoCode":"", "Version":"2" }` let option = { url: BASE_URL_Dazn, method: "POST", opts: opts, timeout: 2800, headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36', "Content-Type": "application/json" }, body: extra } $task.fetch(option).then(response=> { let data = response.body //data = extra let header = JSON.stringify(response.headers) console.log("Dazn:"+response.statusCode) //console.log("Dazn:"+data) //$done(data) if (response.statusCode !== 200) { //reject('Error') result["Dazn"] = "Dazn: 检测失败" } else if (response.statusCode == 200) {//console.log(data.split("countryCode")[1]) //console.log(data) let region = '' let re = new RegExp('"GeolocatedCountry":"(.*?)"', 'gm') let ret = re.exec(data) if (ret != null && ret.length === 2) { region = ret[1] result["Dazn"] = "Dazn: 支持"+ "⟦"+flags.get(region.toUpperCase())+"⟧" } else { result["Dazn"] = "Dazn: 未支持" } //resolve(region) console.log("Dazn:"+region+ result["Dazn"]) } }, reason => { result["Dazn"] = "Dazn: 检测超时" //resolve("timeout") }) }