Script/Disney/DisneyRating.js

254 lines
17 KiB
JavaScript
Raw Normal View History

2024-05-04 14:09:02 +08:00
/*********************************
Disney+ 显示IMDb评分 / 烂番茄评分 / 豆瓣评分
脚本作者: @NobyDa
脚本兼容: SurgeQuantumultXLoon
系统兼容: iOS14+
更新时间: 2024/05/04
脚本参考: https://github.com/yichahucha/surge/blob/master/nf_rating.js
Surge模块:
https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/DisneyRating.sgmodule
QuantumultX重写引用:
https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/DisneyRating.snippet
*********************************/
const $tool = new Tool();
const consoleLog = false;
let obj = $response.body;
let IMDbApikeys = IMDbApikeyList();
let IMDbApikey = $tool.read("ImdbApikeyCacheKey");
if (!IMDbApikey) {
updateIMDbApikey();
}
const requestRatings = async () => {
if (consoleLog) console.log("Disney Original Body:\n" + obj);
obj = JSON.parse(obj);
const sliced = obj?.data?.page?.actions?.[0]?.internalTitle?.split(' - ');
let title = sliced?.[0] || obj?.data?.page?.visuals?.title;
if (title) {
title = title.replace(/.+?:\s|\s?\(.+?\)\s?/g,'');
} else {
throw 'NO TITLE';
}
const year = obj?.data?.page?.visuals?.metastringParts?.releaseYearRange?.startYear;
const type = (sliced?.[1]?.startsWith('s') && 'series') || (sliced?.[1] == 'movie' && 'movie');
const IMDb = await requestIMDbRating(title, year, type);
const Douban = await requestDoubanRating(IMDb.id);
const IMDbrating = IMDb.msg.rating;
const tomatoes = IMDb.msg.tomatoes;
const country = IMDb.msg.country;
// const awards = IMDb.msg.awards;
const doubanRating = Douban.rating;
// const message = `${awards.length > 0 ? awards + "\n" : ""}${country}\n${IMDbrating}\n${doubanRating}${tomatoes.length > 0 ? "\n" + tomatoes + "\n" : "\n"}`;
return { country, tomatoes, IMDbrating, doubanRating };
}
requestRatings()
.then(data => {
if (obj?.data?.page?.visuals) {
obj.data.page.visuals.promoLabel = {
promoLabelType: "generic",
header: `${data.country}${data.tomatoes ? `\n${data.tomatoes}` : ``}`,
subheader: `${data.IMDbrating}${data.doubanRating ? `\n${data.doubanRating}` : ``}`
}
}
if (consoleLog) console.log("Disney Modified Body:\n" + JSON.stringify(obj));
})
.catch(error => console.log(`ERROR: ${error}`))
.finally(() => $done({ body: typeof obj == 'object' ? JSON.stringify(obj) : obj }));
function requestDoubanRating(imdbId) {
return new Promise(function (resolve, reject) {
const url = `https://www.douban.com/search?cat=1002&q=${imdbId}`;
if (consoleLog) console.log("Disney Douban Rating URL:\n" + url);
$tool.get(url, function (error, response, data) {
if (!error) {
if (consoleLog) console.log("Disney Douban Rating Data:\n" + data);
if (response.status == 200) {
const rating = get_douban_rating_message(data);
resolve({ rating });
} else {
resolve({});
}
} else {
console.log("Disney Douban Rating Error: " + error);
resolve({});
}
});
});
}
function requestIMDbRating(title, year, type) {
return new Promise(function (resolve, reject) {
let url = "https://www.omdbapi.com/?t=" + encodeURIComponent(title) + "&apikey=" + IMDbApikey;
if (year) url += "&y=" + year;
if (type) url += "&type=" + type;
if (consoleLog) console.log("Disney IMDb Rating URL:\n" + url);
$tool.get(url, function (error, response, data) {
if (!error) {
if (consoleLog) console.log("Disney IMDb Rating Data:\n" + data);
if (response.status == 200) {
const obj = JSON.parse(data);
if (obj.Response == "True") {
const id = obj.imdbID;
const msg = get_IMDb_message(obj);
resolve({ id, msg });
} else {
reject(`Title [${title}] IMDb data not found`);
}
} else if (response.status == 401) {
if (IMDbApikeys.length > 1) {
updateIMDbApikey();
requestIMDbRating(title, year, type);
} else {
reject(`IMDb Key invalid`);
}
} else {
reject(`Unknown status: ${response.status}, Data: ${data}`);
}
} else {
reject(`IMDB data response failed: ${error}`);
}
});
});
}
function updateIMDbApikey() {
if (IMDbApikey) IMDbApikeys.splice(IMDbApikeys.indexOf(IMDbApikey), 1);
const index = Math.floor(Math.random() * IMDbApikeys.length);
IMDbApikey = IMDbApikeys[index];
$tool.write(IMDbApikey, "ImdbApikeyCacheKey");
}
function get_IMDb_message(data) {
let rating_message = "IMDb: ⭐️ N/A";
let tomatoes_message = "";
let country_message = "";
let ratings = data.Ratings;
let awards_message = "";
if (data.Awards && data.Awards != "N/A") {
awards_message = "🏆 " + data.Awards;
}
if (ratings.length > 0) {
const imdb_source = ratings[0]["Source"];
if (imdb_source == "Internet Movie Database") {
const imdb_votes = data.imdbVotes;
const imdb_rating = ratings[0]["Value"];
rating_message = "IMDb: ⭐️ " + imdb_rating + " " + imdb_votes;
if (data.Type == "movie") {
if (ratings.length > 1) {
const source = ratings[1]["Source"];
if (source == "Rotten Tomatoes") {
const tomatoes = ratings[1]["Value"];
tomatoes_message = "Tomatoes: 🍅 " + tomatoes;
}
}
}
}
}
country_message = get_country_message(data.Country);
return { rating: rating_message, tomatoes: tomatoes_message, country: country_message, awards: awards_message }
}
function get_douban_rating_message(data) {
const s = data.replace(/\n| |&#\d{2}/g, '')
.match(/\[(\u7535\u5f71|\u7535\u89c6\u5267)\].+?subject-cast\">.+?<\/span>/g);
const average = s ? s[0].split(/">(\d\.\d)</)[1] || '' : '';
const numRaters = s ? s[0].split(/(\d+)\u4eba\u8bc4\u4ef7/)[1] || '' : '';
const rating_message = `Douban: ⭐️ ${average ? average + "/10" : "N/A"} ${!numRaters ? "" : parseFloat(numRaters).toLocaleString()}`;
return average && rating_message;
}
function get_country_message(data) {
const country = data;
const countrys = country.split(", ");
let emoji_country = "";
countrys.forEach(item => {
emoji_country += countryEmoji(item) + " " + item + ", ";
});
return emoji_country.slice(0, -2);
}
// function errorTip() {
// return { noData: "⭐️ N/A", error: "❌ N/A" }
// }
function IMDbApikeyList() {
const apikeys = [
"f75e0253", "d8bb2d6b",
"ae64ce8d", "7218d678",
"b2650e38", "8c4a29ab",
"9bd135c2", "953dbabe",
"1a66ef12", "3e7ea721",
"457fc4ff", "d2131426",
"9cc1a9b7", "e53c2c11",
"f6dfce0e", "b9db622f",
"e6bde2b9", "d324dbab",
"d7904fa3", "aeaf88b9",
"4e89234e",];
return apikeys;
}
function countryEmoji(name) { const emojiMap = { "Chequered": "🏁", "Triangular": "🚩", "Crossed": "🎌", "Black": "🏴", "White": "🏳", "Rainbow": "🏳️‍🌈", "Pirate": "🏴‍☠️", "Ascension Island": "🇦🇨", "Andorra": "🇦🇩", "United Arab Emirates": "🇦🇪", "Afghanistan": "🇦🇫", "Antigua & Barbuda": "🇦🇬", "Anguilla": "🇦🇮", "Albania": "🇦🇱", "Armenia": "🇦🇲", "Angola": "🇦🇴", "Antarctica": "🇦🇶", "Argentina": "🇦🇷", "American Samoa": "🇦🇸", "Austria": "🇦🇹", "Australia": "🇦🇺", "Aruba": "🇦🇼", "Åland Islands": "🇦🇽", "Azerbaijan": "🇦🇿", "Bosnia & Herzegovina": "🇧🇦", "Barbados": "🇧🇧", "Bangladesh": "🇧🇩", "Belgium": "🇧🇪", "Burkina Faso": "🇧🇫", "Bulgaria": "🇧🇬", "Bahrain": "🇧🇭", "Burundi": "🇧🇮", "Benin": "🇧🇯", "St. Barthélemy": "🇧🇱", "Bermuda": "🇧🇲", "Brunei": "🇧🇳", "Bolivia": "🇧🇴", "Caribbean Netherlands": "🇧🇶", "Brazil": "🇧🇷", "Bahamas": "🇧🇸", "Bhutan": "🇧🇹", "Bouvet Island": "🇧🇻", "Botswana": "🇧🇼", "Belarus": "🇧🇾", "Belize": "🇧🇿", "Canada": "🇨🇦", "Cocos (Keeling) Islands": "🇨🇨", "Congo - Kinshasa": "🇨🇩", "Congo": "🇨🇩", "Central African Republic": "🇨🇫", "Congo - Brazzaville": "🇨🇬", "Switzerland": "🇨🇭", "Côte dIvoire": "🇨🇮", "Cook Islands": "🇨🇰", "Chile": "🇨🇱", "Cameroon": "🇨🇲", "China": "🇨🇳", "Colombia": "🇨🇴", "Clipperton Island": "🇨🇵", "Costa Rica": "🇨🇷", "Cuba": "🇨🇺", "Cape Verde": "🇨🇻", "Curaçao": "🇨🇼", "Christmas Island": "🇨🇽", "Cyprus": "🇨🇾", "Czechia": "🇨🇿", "Czech Republic": "🇨🇿", "Germany": "🇩🇪", "Diego Garcia": "🇩🇬", "Djibouti": "🇩🇯", "Denmark": "🇩🇰", "Dominica": "🇩🇲", "Dominican Republic": "🇩🇴", "Algeria": "🇩🇿", "Ceuta & Melilla": "🇪🇦", "Ecuador": "🇪🇨", "Estonia": "🇪🇪", "Egypt": "🇪🇬", "Western Sahara": "🇪🇭", "Eritrea": "🇪🇷", "Spain": "🇪🇸", "Ethiopia": "🇪🇹", "European Union": "🇪🇺", "Finland": "🇫🇮", "Fiji": "🇫🇯", "Falkland Islands": "🇫🇰", "Micronesia": "🇫🇲", "Faroe Islands": "🇫🇴", "France": "🇫🇷", "Gabon": "🇬🇦", "United Kingdom": "🇬🇧", "UK": "🇬🇧", "Grenada": "🇬🇩", "Georgia": "🇬🇪", "French Guiana": "🇬🇫", "Guernsey": "🇬🇬", "Ghana": "🇬🇭", "Gibraltar": "🇬🇮", "Greenland": "🇬🇱", "Gambia": "🇬🇲", "Guinea": "🇬🇳", "Guadeloupe": "🇬🇵", "Equatorial Guinea": "🇬🇶", "Greece": "🇬🇷", "South Georgia & South Sandwich Is lands": "🇬🇸", "Guatemala": "🇬🇹", "Guam": "🇬🇺", "Guinea-Bissau": "🇬🇼", "Guyana": "🇬🇾", "Hong Kong SAR China": "🇭🇰", "Hong Kong": "🇭🇰", "Heard & McDonald Islands": "🇭🇲", "Honduras": "🇭🇳", "Croatia": "🇭🇷", "Haiti": "🇭🇹", "Hungary": "🇭🇺", "Canary Islands": "🇮🇨", "Indonesia": "🇮🇩", "Ireland": "🇮🇪", "Israel": "🇮🇱", "Isle of Man": "🇮🇲", "India": "🇮🇳", "British Indian Ocean Territory": "🇮🇴", "Iraq": "🇮🇶", "Iran": "🇮🇷", "Iceland": "🇮🇸", "Italy": "🇮🇹", "Jersey": "🇯🇪", "Jamaica": "🇯🇲", "Jordan": "🇯🇴", "Japan": "🇯🇵", "Kenya": "🇰🇪", "Kyrgyzstan": "🇰🇬", "Cambodia": "🇰🇭", "Kiribati": "🇰🇮", "Comoros": "🇰🇲", "St. Kitts & Nevis": "🇰🇳", "North Korea": "🇰🇵", "South Korea": "🇰🇷", "Kuwait": "🇰🇼", "Cayman Islands": "🇰🇾", "Kazakhstan": "🇰🇿", "Laos": "🇱🇦", "Lebanon": "🇱🇧", "St. Lucia": "🇱🇨", "Liechtenstein": "🇱🇮", "Sri Lanka": "🇱🇰", "Liberia": "🇱🇷", "Lesotho": "🇱🇸", "Lithuania": "🇱🇹", "Luxembourg": "🇱🇺", "Latvia": "🇱🇻", "Libya": "🇱🇾", "Morocco": "🇲🇦", "Monaco": "🇲🇨", "Moldova": "🇲🇩", "Montenegro": "🇲🇪", "St. Martin": "🇲🇫", "Madagascar": "🇲<EFBFBD>
function Tool() {
_node = (() => {
if (typeof require == "function") {
const request = require('request')
return ({ request })
} else {
return (null)
}
})()
_isSurge = typeof $httpClient != "undefined"
_isQuanX = typeof $task != "undefined"
this.isSurge = _isSurge
this.isQuanX = _isQuanX
this.isResponse = typeof $response != "undefined"
this.notify = (title, subtitle, message) => {
if (_isQuanX) $notify(title, subtitle, message)
if (_isSurge) $notification.post(title, subtitle, message)
if (_node) console.log(JSON.stringify({ title, subtitle, message }));
}
this.write = (value, key) => {
if (_isQuanX) return $prefs.setValueForKey(value, key)
if (_isSurge) return $persistentStore.write(value, key)
}
this.read = (key) => {
if (_isQuanX) return $prefs.valueForKey(key)
if (_isSurge) return $persistentStore.read(key)
}
this.get = (options, callback) => {
if (_isQuanX) {
if (typeof options == "string") options = { url: options }
options["method"] = "GET"
$task.fetch(options).then(response => { callback(null, _status(response), response.body) }, reason => callback(reason.error, null, null))
}
if (_isSurge) $httpClient.get(options, (error, response, body) => { callback(error, _status(response), body) })
if (_node) _node.request(options, (error, response, body) => { callback(error, _status(response), body) })
}
this.post = (options, callback) => {
if (_isQuanX) {
if (typeof options == "string") options = { url: options }
options["method"] = "POST"
$task.fetch(options).then(response => { callback(null, _status(response), response.body) }, reason => callback(reason.error, null, null))
}
if (_isSurge) $httpClient.post(options, (error, response, body) => { callback(error, _status(response), body) })
if (_node) _node.request.post(options, (error, response, body) => { callback(error, _status(response), body) })
}
_status = (response) => {
if (response) {
if (response.status) {
response["statusCode"] = response.status
} else if (response.statusCode) {
response["status"] = response.statusCode
}
}
return response
}
}