Greasy Fork

Greasy Fork is available in English.

Kamikaze' Script Utils

Automatically opens the stream on your preferred hoster by order.

当前为 2022-11-22 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @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
}