您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Automatically opens the stream on your preferred hoster by order.
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/455253/1120097/Kamikaze%27%20Script%20Utils.js
// ==UserScript== // @name Kamikaze' Script Utils // @namespace http://greasyfork.icu/users/928242 // @description Automatically opens the stream on your preferred hoster by order. // @version 0.0.1 // @description Kamikaze' Script Utils // @author Kamikaze (https://github.com/Kamiikaze) // @license MIT // @grant none // ==/UserScript== /* jshint esversion: 11 */ /* const log = new Logger("Custom Script") log.setDev(true) */ class Logger { constructor(prefix) { this.prefix = prefix; // Name of Script this.logLevel = 4; this.defaultStyle = "background: #44adf3; color: #000; font-weight: bold; padding: 5px 15px; border-radius: 10px" this.resetStyle = "background: unset; color: unest" this.prefixStyle = this.setPrefixStyle(prefix); } setLogLevel(logLevel) { this.logLevel = logLevel } setPrefixStyle(prefix) { switch (prefix) { case "sto": return "background: #000; color: #fff" default: return this.defaultStyle } } formattedOutput(...args) { const argsArray = Array.from(args).map(arg => { if (typeof arg === "object") return JSON.stringify(arg, null, 4) return arg }) return `%c${ this.prefix }%c ` + argsArray.join(", ") } info(...args) { if (this.logLevel > 1) console.info(this.formattedOutput(...args), this.prefixStyle, this.resetStyle) } debug(...args) { if (this.logLevel > 2) console.debug(this.formattedOutput(...args), this.prefixStyle, this.resetStyle) } warn(...args) { if (this.logLevel > 3) console.warn(this.formattedOutput(...args), this.prefixStyle, this.resetStyle) } error(...args) { if (this.logLevel > 1) console.error(this.formattedOutput(...args), this.prefixStyle, this.resetStyle) } } function addGlobalStyle(css, important) { let head, style; head = document.getElementsByTagName('head')[0]; if (!head) return; style = document.createElement('style'); (important) ? style.innerHTML = css.replace(/;/g, ' !important;') : style.innerHTML = css; head.appendChild(style); } function waitForElm(selector) { return new Promise((resolve, reject) => { if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } const observer = new MutationObserver(mutations => { if (document.querySelector(selector)) { resolve(document.querySelector(selector)); observer.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); }); } function getStreamPageLocation() { const url = window.location; // "https://s.to/serie/stream/the-walking-dead" const host = url.host; // "s.to" const path = url.pathname.split("/").slice(3); // ['the-walking-dead', 'staffel-1', 'episode-1'] return { host: host, season: path[1]?.split("-")[1] || 0, episode: path[2]?.split("-")[1] || 0, } } function checkHasMovies(seasonListEl) { const seasonList = seasonListEl.children for ( let i = 0; i < seasonList.length; i++ ) if ( seasonList[i].textContent.trim() === "Filme" ) return true return false } async function getStreamDetails() { const titleEl = await waitForElm( ".series-title > h1 > span" ) const seasonListEl = await waitForElm( "#stream > ul:nth-child(1)" ) const episodeListEl = await waitForElm( "#stream > ul:nth-child(4)" ) const hasMovies = checkHasMovies(seasonListEl) const seasonsCount = seasonListEl.childElementCount - 1 - (hasMovies ? 1 : 0) const episodesCount = episodeListEl.childElementCount - 1 log.debug("Elements", titleEl,seasonListEl,episodeListEl) log.debug("Count", seasonsCount, episodesCount) return { title: titleEl.textContent.trim(), seasonsCount: seasonsCount, episodesCount: episodesCount, hasMovies: hasMovies, } } async function getStreamData() { const streamLocation = getStreamPageLocation() const streamDetails = await getStreamDetails() const data = { host: streamLocation.host, title: streamDetails.title, currentSeason: streamLocation.season, seasonsCount: streamDetails.seasonsCount, currentEpisode: streamLocation.episode, episodesCount: streamDetails.episodesCount, hasMovies: streamDetails.hasMovies, } log.debug("Data", data) return data }