// ==UserScript==
// @name Advanced Streaming | aniworld.to & s.to
// @name:de Erweitertes Streaming | aniworld.to & s.to
// @namespace https://greasyfork.org/users/928242
// @version 3.5.2
// @description Minimizing page elements to fit smaller screens and adding some usability improvements.
// @description:de Minimierung der Seitenelemente zur Anpassung an kleinere Bildschirme und Verbesserung der Benutzerfreundlichkeit.
// @author Kamikaze (https://github.com/Kamiikaze)
// @supportURL https://github.com/Kamiikaze/Tampermonkey/issues
// @iconURL https://s.to/favicon.ico
// @match https://s.to/serie/stream/*
// @match https://s.to/serienkalender*
// @match https://s.to/serien*
// @match https://s.to/account/subscribed
// @match https://aniworld.to/anime/stream/*
// @match https://aniworld.to/animekalender*
// @match https://aniworld.to/animes*
// @match https://aniworld.to/account/subscribed
// @require https://greasyfork.org/scripts/455253-kamikaze-script-utils/code/Kamikaze'%20Script%20Utils.js
// @require https://cdnjs.cloudflare.com/ajax/libs/toastify-js/1.12.0/toastify.min.js
// @resource toastifyCss https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css
// @license MIT
// @grant GM_getResourceText
// @grant GM_addStyle
// @downloadURL none
// ==/UserScript==
// Load Toastify CSS
// # # # # # #
// CONFIG
// You can disable features by replacing the value true with false.
// # # # # # #
// Enables shorter Window Tab Title
// Example: S3E8 - Black Clover | AniWorld.to
const enableShortWindowTitle = true
// Hides the section of Season Suggestions below the video
const enableHideSeasonSuggestions = true
// Closing the dropdown menu when mouse leaves (fix the perma-open menu)
const enableCloseMenuOnHoverLeave = true
// Adding a Link below "Watch Trailer" to search for it on YT (Because sometimes there is a Homepage linked to the Anime)
const enableAddTrailerSearchLink = true
// Adding a small box at bottom left to search the Anime on sites like MyAnimeList, Crunchyroll & more
const enableAddAnimeSearchBox = true
// Enable/Disable search providers by changing the value either to true or false
// If you want to add your own provider let me know
const animeSearchProviderList = {
'Crunchyroll': false,
'aniSearch': false,
'AnimePlanet': false,
'MyAnimeList': true,
'Amazon Video': true,
}
// Adding a small box at bottom left to search the Series on sites like Amazon, Netflix & more
const enableAddSeriesSearchBox = true
// Enable/Disable search providers by changing the value either to true or false
// If you want to add your own provider let me know
const seriesSearchProviderList = {
'AmazonVideo': true,
'Netflix': true,
}
// Adding a small button at the right corner of the video frame to get to the next episode
const enableEpisodeNavButtons = true
// Allows filtering the Series Calendar by subscribed series
// To use this feature you need to go to https://s.to/account/subscribed and wait for the script to save the
// subscribed series. After that you can go to https://s.to/serienkalender and use the filter.
const enableFilterSeriesCalendar = true
// Adds a link to search series in the release calendar
const enableAddCalendarSearch = true
// Enable improved Search Box
// When pressing a key, search box will be automatically focused. Clicking the search box will select all input.
// By clicking outside the search box and pressing a key, the search box will be focused and cleared for new input.
const enableImprovedSearchBox = true
// Enables Notebox (Beta)
// Allows you to save notes to each Series/Animes
const enableNoteBox = false
// # # # # # #
// Styling
// Some adjustments to layout.
// You can disable features by replacing the value true with false.
// # # # # # #
// Set the height of the video player. (in pixel)
// Set to 0 to disabled it. Default: 480
const reducePlayerHeight = 150
// Hides the text to show/edit the description of the episode below episode title
const hideDescriptionEdit = true
// Hides the language box above the video player
const hideLanguageBox = true
// Hides seen episodes (marked green) from the Episode-List (You can still see them in the season overview
const hideSeenEpisodes = true
// Use Scrollbar for Episode-List (good for seasons with a large amount of episodes)
const useScrollbarForEpisodeList = true
/*** DO NOT CHANGE BELOW ***/
/* global Logger getStreamData waitForElm addGlobalStyle searchSeries GM_getResourceText */
const log = new Logger("Advanced Streaming");
let streamData = null;
let streamDetails = null;
(async () => {
generateStyles()
await getSubscribedSeries()
hideSeen()
if (enableFilterSeriesCalendar) filterSeriesCalendar()
if (enableImprovedSearchBox) improvedSearchBox()
streamData = await getStreamData()
streamDetails = await getStreamDetails()
await toggleSubscribedSeries()
if (hideSeenEpisodes) {
if (streamData.currentEpisode !== 0) {
addGlobalStyle(`
#stream > ul:nth-child(4) li .seen {
display: none;
}
`)
}
}
/**
{
"host": "aniworld.to",
"title": "Komi Can’t Communicate",
"currentSeason": 2,
"seasonsCount": 2,
"currentEpisode": 1,
"episodesCount": 12,
"episodeTitle": {
"de": "Es ist nur der Winteranfang. Und mehr.",
"en": "It's just the arrival of winter. Plus more."
},
"hasMovies": false
}
**/
console.log("streamData:", streamData)
/**
{
"title": "Komi Can’t Communicate",
"seasonsCount": 2,
"episodesCount": 12,
"episodeTitle": {
"de": "Es ist nur der Winteranfang. Und mehr.",
"en": "It's just the arrival of winter. Plus more."
},
"hasMovies": false
}
**/
console.log("streamDetails:", streamDetails)
// Features
if (enableShortWindowTitle) shortWindowTitle()
if (enableHideSeasonSuggestions) hideSeasonSuggestions()
if (enableCloseMenuOnHoverLeave) closeMenuOnHoverLeave()
if (enableAddTrailerSearchLink) addTrailerSearchLink()
if (enableAddAnimeSearchBox) addAnimeSearchBox()
if (enableAddSeriesSearchBox) addSeriesSearchBox()
if (enableEpisodeNavButtons) addEpisodeNavButtons()
if (enableAddCalendarSearch) addCalendarSearch()
if (enableNoteBox) addNotesBox()
fixAnimeTrailerWatchButton()
})();
function hideSeen() {
const subscribedSeries = localStorage.subscribedSeries
let animeList = document.querySelector(".seriesListContainer");
if (!animeList || !subscribedSeries) return
animeList = animeList.children
for (let i = 0; i < animeList.length; i++) {
let anime = animeList[i];
let title = anime.querySelector("h3")?.innerText
if (subscribedSeries.includes(title)) {
log.debug(title, "found")
anime.querySelector("a").classList.add("subbed")
}
}
addGlobalStyle(`
.seriesListContainer a.subbed {filter: blur(1px) grayscale(1) opacity(0.5);}
.seriesListContainer a.subbed:hover {filter: unset;}
.seriesListContainer>div>a:hover h3 {white-space: break-spaces;}
`)
}
async function addNotesBox() {
//const container = await waitForElm("#series > section > div.container.row")
const container = document.querySelector("#series > section > div.container.row")
const notesVisible = (localStorage.getItem(`notes-visible`) === "true")
console.error("notesVisible", notesVisible)
if (!container) return
const notesEl = document.createElement("div")
notesEl.id = "notes-box"
notesEl.innerHTML = `