您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Enhance Project Free TV viewing page with links to previous and next episodes
// ==UserScript== // @name ProjectFreeTV Episode Links // @namespace pftvepisodelinks // @include http*://projectfreetv.im/watch/* // @version 1 // @grant none // @description Enhance Project Free TV viewing page with links to previous and next episodes // ==/UserScript== (function () { "use strict"; // Global utility methods HTMLCollection.prototype.any = function() { return this.length > 0; }; HTMLCollection.prototype.first = function() { if (this == null) { throw new Error("The source is null"); } if (!this.any()) { throw new Error("The source sequence is empty"); } return this[0]; }; HTMLCollection.prototype.firstOrDefault = function(criteria) { for (var i = 0; i < this.length; i++) { if (criteria(this[i])) { return this[i]; } } return null; }; // HTTP client class var HttpClient = function() { }; HttpClient.getAsync = function(url) { return new Promise(function(resolve, reject) { var request = new XMLHttpRequest(); request.open("GET", url); request.onload = function() { if (request.status != 200) { reject(new Error("Non-success status code. Status:" + request.status + ", Text:" + request.statusText)); return; } resolve(request.response); }; request.onerror = function() { reject(new Error("Network error")); } request.send(); }); }; HttpClient.getHtmlDocAsync = function(url) { return HttpClient.getAsync(url).then(function(response) { var doc = document.implementation.createHTMLDocument("response"); doc.documentElement.innerHTML = response; return doc; }); }; // Episode class var Episode = function(series, season, episode) { this.series = series; this.season = season; this.episode = episode; }; Episode.prototype.getAdjacentEpisodesAsync = function() { return HttpClient.getHtmlDocAsync(this.getLink()).then(function(response) { var div = response.getElementsByClassName("navlinks").first(); var links = div.getElementsByTagName("a"); var prevAnchor = links.firstOrDefault(function(a) { return a.rel == "prev"; }); var nextAnchor = links.firstOrDefault(function(a) { return a.rel == "next"; }); return { previous: Episode.createFromLink(prevAnchor ? prevAnchor.href : null), next: Episode.createFromLink(nextAnchor ? nextAnchor.href : null) }; }).catch(function(error) { return { previous: null, next: null }; }); }; Episode.prototype.getNextEpisodeOrDefault = function() { return new Episode(this.series, this.season, this.episode + 1); }; Episode.prototype.getPreviousEpisodeOrDefault = function() { if (this.episode < 1) { return null; } return new Episode(this.series, this.season, this.episode - 1); }; Episode.prototype.getLink = function() { return "http://projectfreetv.im/episode/" + this.toString().toLowerCase().replace(/ /g, "-"); }; Episode.prototype.toString = function() { return this.series + " Season " + this.season + " Episode " + this.episode; }; Episode.prototype.toShortString = function() { return "S" + this.season + "E" + this.episode; } // Static helper methods Episode.createFromTitle = function(title) { var parsedEpisode = title.match(/(.+) Season (\d+) Episode (\d+)/); var series = parsedEpisode[1]; var season = Number.parseInt(parsedEpisode[2]); var episode = Number.parseInt(parsedEpisode[3]); return new Episode(series, season, episode); }; Episode.createFromLink = function(link) { if (link == null) { return null; } var parsedEpisode = link.match(/\/episode\/(\S+)/); var title = parsedEpisode[1].replace(/-|\//g, " ").trim().toLowerCase().replace(/\b[a-z]/g, String.toUpperCase); return Episode.createFromTitle(title); } function createEpisodeAnchor(episode, text, float) { var anchor = document.createElement("a"); anchor.href = episode.getLink(); anchor.innerText = text + episode.toShortString(); anchor.style.float = float; return anchor; }; function run() { try { var title = document.getElementsByClassName("title").first(); var curr = Episode.createFromTitle(title.innerText); var header = title.parentElement; title.style.margin = 0; // so that links sit flush with episode title curr.getAdjacentEpisodesAsync().then(function(episodes) { if (episodes.previous != null) { header.appendChild(createEpisodeAnchor(episodes.previous, "Previous ", "left")); } if (episodes.next != null) { header.appendChild(createEpisodeAnchor(episodes.next, "Next ", "right")); } }); } catch (err) { console.error(err); } }; run(); }) ();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址