NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name WatchOnlineMenu // @version 4.1.9.1 // @namespace https://openuserjs.org/users/skip // @description [shikimori.org] Добавляет ссылки на сайты просмотра аниме // @author Pasha13666 // @match http://shikimori.one/* // @match https://shikimori.one/* // @match http://shikimori.org/* // @match https://shikimori.org/* // @match https://plashiki.su/* // @match https://*.shikimorilive.top/* // @updateURL https://openuserjs.org/meta/skip/WatchOnlineMenu.meta.js // @homepageURL https://github.com/GlitchSkip/AltWatcher4 // @run-at document-body // @license MIT // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_log // @grant GM_xmlhttpRequest // @connect raw.githubusercontent.com // @copyright 2019, Pasha13666 (https://openuserjs.org/users/Pasha13666) // ==/UserScript== /* div - $ph * div - $wo * a.aw4-dark-button.aw4-link - $link * a.aw4-dark-button.aw4-hider - $hider * div.clearfix - $clearfix * * div - $bar * a.aw4-dark-button.watch-online * ... * div.aw4-langs - $langs * a.aw4-dark-button.aw4-lang - $ru * a.aw4-dark-button.aw4-lang - $en */ function WatchOnlineMenu(services) { this.services = services; this.$ph = document.getElementsByClassName('watch-online')[0]; this.$rb = document.getElementsByClassName("c-info-right")[0]; this.$wo = document.createElement('div'); this.$link = document.createElement('a'); this.$hider = document.createElement('a'); this.$clearfix = document.createElement('div'); this.$bar = document.createElement('div'); this.$langs = document.createElement('div'); this.$ru = document.createElement('a'); this.$en = document.createElement('a'); this.$link.target = "_blank"; this.$ru.title = 'Искать по русскому названию'; this.$en.title = 'Искать по английскому названию'; this.$hider.innerText = "▼"; this.$ru.innerText = 'ru'; this.$en.innerText = 'en'; this.$link.classList = "aw4-dark-button aw4-link" this.$hider.classList = "aw4-dark-button aw4-hider"; this.$clearfix.classList = "clearfix"; this.$bar.classList = ""; this.$ru.classList = "aw4-dark-button aw4-lang"; this.$en.classList = "aw4-dark-button aw4-lang"; this.$langs.classList = "aw4-langs"; if (GM_getValue("searchLang", 'ru') === 'ru') this.$ru.classList.add('aw4-selected'); else this.$en.classList.add('aw4-selected'); this.isHentai = document.querySelector('a.b-tag[href*="genre/12"]') != null; if (this.$ph !== undefined) { this.$rb.removeChild(this.$ph); } this.$ph = document.createElement('div'); this.$rb.appendChild(this.$ph); for (var i = 0; i < this.services.length; i++) { var v = this.services[i]; if (this.isHentai ? v.forRx : v.forNotRx) this.$bar.appendChild(this.createPlayerButton(v, i)); } this.redrawButton(); this.$ru.addEventListener('click', () => { this.$ru.classList.add('aw4-selected'); this.$en.classList.remove('aw4-selected'); GM_setValue("searchLang", 'ru'); this.redrawButton(); }); this.$en.addEventListener('click', () => { this.$en.classList.add('aw4-selected'); this.$ru.classList.remove('aw4-selected'); GM_setValue("searchLang", 'en'); this.redrawButton(); }); this.$hider.addEventListener('click', () => { this.$bar.style.display = this.$bar.style.display === 'none' ? '' : 'none'; }); this.$langs.appendChild(this.$ru); this.$langs.appendChild(this.$en); this.$bar.appendChild(this.$langs); this.$wo.appendChild(this.$link); this.$wo.appendChild(this.$hider); this.$wo.appendChild(this.$clearfix); this.$ph.appendChild(this.$wo); this.$ph.appendChild(this.$bar); } WatchOnlineMenu.prototype.createPlayerButton = function (service, id) { var a = document.createElement('a'); a.classList = "aw4-dark-button"; a.innerText = service.description || service.name; a.addEventListener('click', (ev) => { GM_setValue(this.isHentai ? "currentRxServiceId" : "currentServiceId", id); this.redrawButton(); }); a.addEventListener('mousedown', (ev) => { if (ev.which == 2 || ev.button == 4) { ev.preventDefault(); window.open(this.createServiceUrl(service), '_blank'); return; } }); return a; } WatchOnlineMenu.prototype.redrawButton = function () { var service = this.services[GM_getValue(this.isHentai ? "currentRxServiceId" : "currentServiceId", 0)]; this.$link.innerText = 'Смотреть на ' + service.name; this.$link.href = this.createServiceUrl(service); this.$bar.style.display = 'none'; } WatchOnlineMenu.prototype.createServiceUrl = function (service) { //Поменять местами чтобы открывалась первая серия если крайняя еще не вышла //const epTotal = parseInt(this.$ph.dataset.episodes_aired); const epTotal = parseInt(this.$ph.dataset.total_episodes); const v = document.getElementsByClassName('current-episodes')[0]; const epWatched = (v ? parseInt(v.innerText) : 0) || 0; const epNext = epWatched === epTotal ? 1 : (epWatched + 1); const animeName = document.querySelector("#animes_show > section > div > header > h1").innerText.split(" / "); const isEnglish = GM_getValue("searchLang", 'ru') == 'en'; const data = { id: location.pathname.replace(/^\/animes\/[a-z]*(\d+)-.*$/, "$1"), link: location.href, nextEpisode: epNext, englishName: animeName[1], russianName: animeName[0], localezedName: animeName[+isEnglish], localizedEpisode: isEnglish ? 'episode' : 'серия' }; return location.protocol + "//" + service.url.replace(/\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g, (match, name) => encodeURIComponent(data[name])); } function checkUpdates() { const servicesCache = GM_getValue("servicesCache", null); if (servicesCache && servicesCache.date > new Date()) return Promise.resolve(servicesCache.services); GM_log("[WatchOnlineMenu] Updating services list..."); return new Promise(function (res, rej) { GM_xmlhttpRequest({ "method": "GET", "url": "https://raw.githubusercontent.com/GlitchSkip/AltWatcher4/master/services.json", "responseType": "json", "fetch": true, "onerror": function (){ if (servicesCache) res(servicesCache.services); else GM_log("[WatchOnlineMenu] Not starting WatchOnlineMenu due to network error."); }, "onload": function (obj) { if (obj.status !== 200 || !obj.response) { if (servicesCache) res(servicesCache.services); else GM_log("[WatchOnlineMenu] Not starting WatchOnlineMenu due to network error."); } else { GM_setValue("servicesCache", { services: obj.response, date: +new Date() + 1000 * 60 * 60 * 24 }); res(obj.response); } } }); }); } document.head.appendChild(GM_addStyle( ".aw4-dark-button { background-color: #456; border: 1px solid #3e4d5d; color: #fff; display: block; text-align: center; cursor: pointer; padding: 4px 0; font-size: 15px; font-weight: 600; }" + ".aw4-link {float: left; width: calc(100% - 32px); margin-bottom: 15px; }\n" + ".aw4-hider {width: 32px; float: right; }\n" + ".aw4-lang { width: 50%; float: left; }\n" + ".aw4-langs { margin-top: 5px; }\n" + ".aw4-selected { border: 5px solid #00c12a; padding: 4px 0; }\n" )); if (location.host === 'plashiki.su') { unsafeWindow.corsAjax = function () { GM_log('[WatchOnlineMenu] PlaShiki xhr:', Array.prototype.slice.call(arguments)); return GM_xmlhttpRequest.apply(this, arguments); } const us = unsafeWindow.USERSCRIPT = { name: GM_info.script.name, author: GM_info.script.author, version: "1.0.1", realVersion: GM_info.script.version } unsafeWindow.USERSCRIPT_VERSION = us.version + ' | Режим совместимости | ' + us.name + ' v' + us.realVersion; unsafeWindow.toggleGalo4ki = function (e) {}; unsafeWindow.galo4kiEnabled = function () { return Promise.resolve(function (e) { return false; }) }; } else if (location.host.substr(location.host.length - 17) === 'shikimorilive.top') { unsafeWindow.SLiveVersion = '1.5'; } else if (location.host === 'shikimori.one' || location.host === 'shikimori.org') { checkUpdates() .then(function (services) { GM_log("[WatchOnlineMenu] Starting..."); let start = function () { if (document.body && document.body.classList.contains("p-animes") && !document.getElementsByClassName('aw4-link').length) { new WatchOnlineMenu(services); } } document.addEventListener('ready', start); document.addEventListener('page:load', start); document.addEventListener('turbolinks:load', start); start(); }) }