// ==UserScript==
// @name douban-info-for-pt
// @namespace https://github.com/techmovie/DouBan-Info-for-PT
// @version 1.7.0
// @description 在PT站电影详情页展示部分中文信息
// @author birdplane
// @require https://cdn.staticfile.org/jquery/1.7.1/jquery.min.js
// @match https://passthepopcorn.me/torrents.php?id=*
// @match https://passthepopcorn.me/requests.php?action=view&id=*
// @match https://beyond-hd.me/torrents/*
// @match https://beyond-hd.me/library/title/*
// @match https://blutopia.xyz/torrents/*
// @match https://asiancinema.me/torrents/*
// @match https://hdbits.org/details.php?id=*
// @match https://hdbits.org/requests/show_request?id=*
// @match https://uhdbits.org/torrents.php?id=*
// @match https://filelist.io/details.php?id=*
// @match https://hd-torrents.org/details.php?id=*
// @match https://karagarga.in/details.php?id=*
// @match https://privatehd.to/torrent/*
// @match https://www.rarbgmirror.com/torrent/*
// @match http://rarbggo.org/torrent/*
// @match http://rarbggo.to/torrent/*
// @match https://rarbgprx.org/torrent/*
// @match https://proxyrarbg.org/torrent/*
// @match https://broadcasthe.net/series.php?id=*
// @match https://iptorrents.com/torrent.php?id=*
// @match https://www.iptorrents.com/torrent.php?id=*
// @match https://www.torrentleech.org/torrent/*
// @match https://avistaz.to/torrent/*
// @match https://secret-cinema.pw/torrents.php?id=*
// @match https://aither.cc/torrents/*
// @match http://shadowthein.net/details.php?id=*
// @match https://shadowthein.net/details.php?id=*
// @match https://baconbits.org/torrents.php?id=*
// @match https://broadcity.in/details.php?id=*
// @match https://www.morethantv.me/torrents.php?id=*
// @match https://www.morethantv.me/show/*
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// @grant GM_openInTab
// @grant GM_getValue
// @grant GM_setValue
// @license MIT
// @downloadURL none
// ==/UserScript==
(() => {
var __assign = Object.assign;
// src/config.json
var PT_SITE = {
"aither.cc": {
url: "https://aither.cc",
host: "aither.cc",
siteName: "Aither",
poster: "#meta-poster",
imdb: '.badge-user a[href*="imdb.com/title"]:nth-child(1)',
insertDomSelector: ".torrent-buttons",
doubanContainerDom: '
\u7535\u5F71\u4FE1\u606F
\u5BFC\u6F14: ${data.director}
\u7C7B\u578B: ${data.genre}
\u5236\u7247\u56FD\u5BB6/\u5730\u533A: ${data.region}
\u8BED\u8A00: ${data.language}
\u65F6\u957F: ${data.runtime}
\u53C8\u540D: ${data.aka}
\u83B7\u5956\u60C5\u51B5: ${data.awards}
`);
if (data.average) {
$("#movie-ratings-table tr").prepend(`
\u8C46
\u8C46\u74E3\u8BC4\u5206
|
${data.average}
/
10
(${data.votes} votes) | `);
}
};
var getImdbId = () => {
var _a4, _b3;
let imdbLink = "";
const imdbConfig = CURRENT_SITE_INFO.imdb;
if (typeof imdbConfig === "object") {
try {
Object.keys(imdbConfig).forEach((key) => {
if ($(`${imdbConfig[key]}`)[0]) {
imdbLink = $(imdbConfig[key]).attr("href");
throw new Error("end loop");
}
});
} catch (error) {
if (error.message !== "end loop") {
console.log(error);
}
}
} else {
imdbLink = $(imdbConfig).attr("href");
}
console.log(imdbLink);
return (_b3 = (_a4 = /tt\d+/.exec(imdbLink)) == null ? void 0 : _a4[0]) != null ? _b3 : "";
};
var getTvSeasonData = async (data) => {
var _a4, _b3;
const torrentTitle = getTorrentTitle();
const {episodes = "", chineseTitle} = data;
if (episodes) {
const seasonNumber = (_b3 = (_a4 = torrentTitle.match(/S(?!eason)\s*?0?(\d+)\.?(EP?\d+)?/i)) == null ? void 0 : _a4[1]) != null ? _b3 : 1;
if (parseInt(seasonNumber) === 1) {
return data;
} else {
const query = `${chineseTitle} \u7B2C${seasonNumber}\u5B63`;
const params = encodeURI("apikey=0ab215a8b1977939201640fa14c66bab");
const searchData = await fetch(`${DOUBAN_API_URL}/search?q=${query}`, {
data: params,
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
});
if (searchData.count > 0) {
return {id: searchData.subjects[0].id};
}
}
}
};
var getDoubanInfo = async (doubanId, imdbId) => {
try {
const url = DOUBAN_SUBJECT_URL.replace("{doubanId}", doubanId);
const data = await fetch(url, {
responseType: "text"
});
if (data) {
const doubanInfo = await formatDoubanInfo(data);
const savedIds = GM_getValue("ids") || {};
savedIds[imdbId] = __assign({
doubanId,
updateTime: Date.now()
}, doubanInfo);
GM_setValue("ids", savedIds);
return doubanInfo;
} else {
console.log("\u8C46\u74E3\u6570\u636E\u83B7\u53D6\u5931\u8D25");
}
} catch (error) {
console.log(error);
}
};
var getDoubanInfoByIMDB = async (imdbId) => {
var _a4, _b3, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
try {
const params = encodeURI("apikey=0ab215a8b1977939201640fa14c66bab");
const doubanData = await fetch(`${DOUBAN_API_URL}/imdb/${imdbId}`, {
data: params,
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
});
const {attrs = {}, image, summary, rating, alt_title: altTitle, mobile_link: mobileLink} = doubanData;
const subjectLink = mobileLink.replace("m.douban.com/movie", "movie.douban.com").replace(/\/$/, "");
const doubanId = (_b3 = (_a4 = subjectLink.match(/subject\/(\d+)/)) == null ? void 0 : _a4[1]) != null ? _b3 : "";
const awards = await getAwardInfo(subjectLink);
const doubanInfo = {
director: (_c = attrs.director) == null ? void 0 : _c.join(" / "),
runtime: (_d = attrs.movie_duration) == null ? void 0 : _d.join(" / "),
language: (_e = attrs.language) == null ? void 0 : _e.join(" / "),
genre: (_g = (_f = attrs.movie_type) == null ? void 0 : _f.join(" / ")) != null ? _g : "",
aka: altTitle || "",
region: (_h = attrs.country) == null ? void 0 : _h.join(" / "),
link: subjectLink,
poster: image,
summary,
chineseTitle: altTitle.split("/")[0].trim(),
votes: rating.numRaters,
average: rating.average,
awards,
id: (_j = (_i = subjectLink.match(/subject\/(\d+)/)) == null ? void 0 : _i[1]) != null ? _j : "",
episodes: (_l = (_k = attrs.episodes) == null ? void 0 : _k.join(" / ")) != null ? _l : ""
};
if (!attrs.episodes) {
const savedIds = GM_getValue("ids") || {};
savedIds[imdbId] = __assign({
doubanId,
updateTime: Date.now()
}, doubanInfo);
GM_setValue("ids", savedIds);
}
return doubanInfo;
} catch (error) {
console.log(error);
}
};
var getAwardInfo = async (doubanLink) => {
var _a4;
const awardsPage = await fetch(`${doubanLink}/awards/`, {
responseType: "text"
});
const awardsDoc = new DOMParser().parseFromString(awardsPage, "text/html");
const awards = $("#content > div > div.article", awardsDoc).html().replace(/[ \n]/g, "").replace(/<\/li>
/g, " ").replace(/<\/a> ]*>/g, "\n").replace(/<[^>]+>/g, "").replace(/ /g, " ").replace(/ +\n/g, "\n").trim();
return (_a4 = awards == null ? void 0 : awards.replace(/\n/g, "
")) != null ? _a4 : "";
};
var formatDoubanInfo = async (domString) => {
var _a4, _b3;
const dom = new DOMParser().parseFromString(domString, "text/html");
const chineseTitle = $("title", dom).text().replace("(\u8C46\u74E3)", "").trim();
const jsonData = JSON.parse($('head > script[type="application/ld+json"]', dom).html().replace(/(\r\n|\n|\r|\t)/gm, ""));
const fetchAnchor = function(anchor) {
var _a5, _b4, _c, _d;
return (_d = (_c = (_b4 = (_a5 = anchor == null ? void 0 : anchor[0]) == null ? void 0 : _a5.nextSibling) == null ? void 0 : _b4.nodeValue) == null ? void 0 : _c.trim()) != null ? _d : "";
};
const rating = jsonData.aggregateRating ? jsonData.aggregateRating.ratingValue : 0;
const votes = jsonData.aggregateRating ? jsonData.aggregateRating.ratingCount : 0;
const director = jsonData.director ? jsonData.director : [];
const poster = jsonData.image.replace(/s(_ratio_poster|pic)/g, "l$1").replace(/img\d/, "img9");
const link = `https://movie.douban.com${jsonData.url}`;
const introductionDom = $('#link-report > span.all.hidden,#link-report-intra > [property="v:summary"], #link-report > [property="v:summary"]', dom);
const summary = (introductionDom.length > 0 ? introductionDom.text() : "\u6682\u65E0\u76F8\u5173\u5267\u60C5\u4ECB\u7ECD").split("\n").map((a) => a.trim()).filter((a) => a.length > 0).join("\n");
const genre = $('#info span[property="v:genre"]', dom).map(function() {
return $(this).text().trim();
}).toArray();
const language = fetchAnchor($('#info span.pl:contains("\u8BED\u8A00")', dom));
const region = fetchAnchor($('#info span.pl:contains("\u5236\u7247\u56FD\u5BB6/\u5730\u533A")', dom));
const runtimeAnchor = $('#info span.pl:contains("\u5355\u96C6\u7247\u957F")', dom);
const runtime = runtimeAnchor[0] ? fetchAnchor(runtimeAnchor) : $('#info span[property="v:runtime"]', dom).text().trim();
const akaAnchor = $('#info span.pl:contains("\u53C8\u540D")', dom);
let aka = [];
if (akaAnchor.length > 0) {
aka = fetchAnchor(akaAnchor).split(" / ").sort(function(a, b) {
return a.localeCompare(b);
}).join("/");
aka = aka.split("/");
}
const awards = await getAwardInfo(link);
return {
director: director.map((item) => item.name),
runtime,
language,
genre: (_a4 = genre == null ? void 0 : genre.join(" / ")) != null ? _a4 : "",
aka: (_b3 = aka == null ? void 0 : aka.join(" / ")) != null ? _b3 : "",
region,
link,
poster,
summary,
chineseTitle,
votes,
average: rating,
awards
};
};
var getTorrentTitle = () => {
let {titleDom} = CURRENT_SITE_INFO;
if (!titleDom) {
if (CURRENT_SITE_NAME === "BHD") {
titleDom = $(".dotborder").find("td:contains(Name)").next("td");
} else if (CURRENT_SITE_NAME.match(/ACM|BLU/)) {
const keyMap = {
Name: "Name",
\u540D\u79F0: "Name",
\u540D\u7A31: "Name"
};
$("#vue+.panel table tr").each((index, element) => {
const key = $(element).find("td:first").text().replace(/\s|\n/g, "");
if (keyMap[key]) {
titleDom = $(element).find("td:last");
}
});
} else if (CURRENT_SITE_NAME === "UHD") {
const torrentId = getUrlParam("torrentid");
const torrentFilePathDom = $(`#files_${torrentId} .filelist_path`);
const torrentFileDom = $(`#files_${torrentId} .filelist_table>tbody>tr:nth-child(2) td`).eq(0);
titleDom = torrentFilePathDom || torrentFileDom;
} else if (CURRENT_SITE_NAME === "HDT") {
return document.title.replace(/HD-Torrents.org\s*-/ig, "").trim();
}
}
return $(titleDom).text();
};
var getUrlParam = (key) => {
const reg = new RegExp("(^|&)" + key + "=([^&]*)(&|$)");
const regArray = location.search.substr(1).match(reg);
if (regArray) {
return unescape(regArray[2]);
}
return "";
};
var createDoubanDom = async (doubanId, imdbId, doubanInfo) => {
const div = document.createElement("div");
let {doubanContainerDom, insertDomSelector, siteName, poster} = CURRENT_SITE_INFO;
if (siteName.match(/(HDT|RARBG)$/)) {
insertDomSelector = $(insertDomSelector).parent();
}
$(insertDomSelector).before(doubanContainerDom);
const doubanLink = `https://movie.douban.com/subject/${doubanId}`;
let htmlData = await fetch(`${doubanLink}/output_card`, {
responseType: "text"
});
htmlData = htmlData.replace(/wrapper/g, "douban-wrapper").replace(//g, "");
htmlData = htmlData.replace(/(html,)body,/, "$1");
htmlData = htmlData.replace(/url\(.+?output_card\/border.png\)/g, `url(${PIC_URLS.border})`);
htmlData = htmlData.replace(/src=.+?output_card\/line\.png/g, `src="${PIC_URLS.line}`);
htmlData = htmlData.replace(/url\(.+?output_card\/ic_rating_m\.png\)/g, `url(${PIC_URLS.icon})`);
htmlData = htmlData.replace(/(1x,\s+)url\(.+?output_card\/ic_rating_m@2x\.png\)/g, `$1url(${PIC_URLS.icon2x})`);
let headDom = htmlData.match(/((.|\n)+)<\/head>/)[1];
headDom = headDom.replace(//g, "");
const bodyDom = htmlData.match(/((.|\n)+)<\/body>/)[1];
div.insertAdjacentHTML("beforeend", headDom);
div.insertAdjacentHTML("beforeend", bodyDom);
$(".douban-dom").append(div).attr("douban-link", doubanLink);
$(".douban-dom .grid-col4").after(`
`);
const doubanData = doubanInfo || await getDoubanInfo(doubanId, imdbId);
$(".douban-dom .grid-col5").html(`${doubanData.summary || "\u6682\u65E0\u7B80\u4ECB"}
`);
let posterStyle = $(".picture-douban-wrapper").attr("style");
const posterImg = siteName === "MTV" ? $(poster).attr("src") : doubanData.poster;
posterStyle = posterStyle == null ? void 0 : posterStyle.replace(/\(.+\)/, `(${posterImg})`);
$(".picture-douban-wrapper").attr("style", posterStyle);
$(".douban-dom").click(() => {
GM_openInTab(doubanLink);
});
};
function fetch(url, options = {}) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest(__assign(__assign({
method: "GET",
url,
responseType: "json"
}, options), {
onload: (res) => {
const {statusText, status, response} = res;
if (status !== 200) {
reject(new Error(statusText || status));
} else {
resolve(response);
}
},
ontimeout: () => {
reject(new Error("timeout"));
},
onerror: (error) => {
reject(error);
}
}));
});
}
// src/style.js
var style_default = GM_addStyle(`
.contentlayout.douban-info {
display: flex;
justify-content: space-around;
}
.contentlayout.douban-info .detail{
flex:1;
}
.detail .title{
font-size: 26px;
font-weight: 600;
margin-bottom: 20px;
}
.detail .title a{
text-decoration: none;
}
.movie-detail{
display: flex;
justify-content: space-between;
}
.movie-detail .synopsis {
width: 60%;
}
.movie-detail .movieinfo {
margin-right: 20px;
max-width: 30%;
}
.icon-pt1{
font-size: 14px;
display: inline-block;
text-align: center;
border: 1px solid #41be57;
background-color: #41be57;
color: white;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
width: 24px;
height: 24px;
line-height: 24px;
}
.icon-pt2{
display: inline-block;
text-align: center;
border: 1px solid #41be57;
color: #3ba94d;
background: #ffffff;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
width: 69px;
height: 24px;
line-height: 24px;
font-size: 14px;
}
.douban-dom {
display: flex;
cursor: pointer;
}
.douban-dom {
text-align: left;
}
#douban-wrapper *{
box-sizing: content-box;
}
#douban-wrapper .clearfix:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden
}
#douban-wrapper .clearfix {
zoom: 1;
display: inline-block;
_height: 1px;
}
#douban-wrapper .clearfix {
height: 1%
}
#douban-wrapper .clearfix {
display: block
}
#douban-wrapper .rating_per{
color: #111;
}
#douban-wrapper .grid{
overflow: initial;
}
.content-rounded #douban-wrapper div{
margin-left: 0;
}
#douban-wrapper #content .douban-icon .icon-pt1 {
background-image:none;
}
#douban-wrapper h2,#douban-wrapper h1{
border:none;
background-image: none;
background-color: transparent;
text-shadow: none;
}
#douban-wrapper .grid-col5 {
font-size: 14px;
padding: 27px 14px 0 12px;
width: 190px;
overflow-y: auto;
height: 277px;
width: calc(100% - 225px - 254px - 36px - 280px);
}
#douban-wrapper .summary{
padding-top: 10px;
color: #000000;
line-height: 25px;
letter-spacing: 1px;
word-break: break-all;
font-weight: 400;
}
#douban-wrapper {
width: 100% !important;
}
.douban-dom>div{
width: 100%;
}
#douban-wrapper #content{
background-image:none !important;
background: #fff;
width: calc(100% - 20px) !important;
}
#douban-wrapper #content .grid{
width: 100% !important;
}
.bhd #douban-wrapper ::-webkit-scrollbar-track{
background-color: #fff;
}
.bhd #douban-wrapper ::-webkit-scrollbar-thumb{
background-color: #ddd;
}
.btn #douban-wrapper .grid-col1 {
display: none;
}
.hdb #douban-wrapper .grid-col1 {
display: none;
}
.hdt #douban-wrapper .grid-col1 {
display: none;
}
.sc #douban-wrapper .grid-col1 {
display: none;
}
.its #douban-wrapper .grid-col1 {
display: none;
}
.bb #douban-wrapper .grid-col1 {
display: none;
}
.btn #douban-wrapper .grid-col5 {
width: calc(100% - 254px - 36px - 280px);
}
.hdt #douban-wrapper .grid-col5 {
width: calc(100% - 254px - 36px - 280px);
}
.hdb #douban-wrapper .grid-col5 {
width: calc(100% - 254px - 36px - 280px);
}
.sc #douban-wrapper .grid-col5 {
width: calc(100% - 254px - 36px - 280px);
}
.its #douban-wrapper .grid-col5 {
width: calc(100% - 254px - 36px - 280px);
}
.bb #douban-wrapper .grid-col5 {
width: calc(100% - 254px - 36px - 280px);
}
.its #douban-wrapper {
background-color: #131313;
color: #fff;
}
`);
// src/index.js
(async () => {
if (CURRENT_SITE_INFO) {
const imdbId = getImdbId();
if (!imdbId) {
return;
}
try {
const savedIds = GM_getValue("ids") || {};
if (!savedIds[imdbId] || savedIds[imdbId] && savedIds[imdbId].updateTime && Date.now() - savedIds[imdbId].updateTime >= 30 * 24 * 60 * 60 * 1e3) {
let doubanId = "";
const movieData = await getDoubanInfoByIMDB(imdbId);
if (!movieData) {
throw new Error("\u6CA1\u6709\u627E\u5230\u8C46\u74E3\u6761\u76EE");
}
const {id = "", episodes = ""} = movieData;
doubanId = id;
if (episodes) {
const tvData = await getTvSeasonData(movieData);
doubanId = tvData.id;
}
if (CURRENT_SITE_NAME === "PTP") {
addToPtpPage(movieData);
} else {
createDoubanDom(doubanId, imdbId);
}
} else {
const savedData = savedIds[imdbId];
if (CURRENT_SITE_NAME === "PTP") {
addToPtpPage(savedData);
} else {
createDoubanDom(savedData.doubanId, imdbId, savedData);
}
}
} catch (error) {
console.log(error);
}
}
})();
})();