- // ==UserScript==
- // @name shikiPlus
- // @author chsa13
- // @description script add viewer and playeer on shikimori
- // @namespace http://shikimori.me/
- // @version 2.1.2
- // @match *://shikimori.org/*
- // @match *://shikimori.one/*
- // @match *://shikimori.me/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=shikimori.me
- // @license MIT
- // @copyright Copyright © 2024 chsa13. All rights reserved.
- // ==/UserScript==
- let RonobeLibLink = "https://ranobelib.me/ru/"
- let MangaLibLink = "https://test-front.mangalib.me/ru/"
- let AnimeLibLink = "https://anilib.me/ru/anime/"
- let LibSocialApiLink = 'https://api.lib.social/api'
-
- function launchFullScreen(element) {
- if (element.requestFullScreen) {
- element.requestFullScreen();
- }
- else if (element.webkitRequestFullScreen) {
- element.webkitRequestFullScreen();
- }
- else if (element.mozRequestFullScreen) {
- element.mozRequestFullScreen();
- }
- }
- function addStyles(){
- $(document.body).append($("<style>").prop("type", "text/css").html(`
- .shiki-plus .iframe{
- width: 100%;
- height: unset;
- aspect-ratio: 1.36;
- min-height: 650px;
- border: none;
- }
- .shiki-plus .black-div {
- position: absolute;
- background-color: black;
- width: 100%;
- height: unset;
- aspect-ratio: 1.36;
- min-height: 650px;
- border: none;
- }
- .shiki-plus .options {
- margin-bottom: 10px;
- width: 100%;
- height: 40px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
- .shiki-plus .options .sweatcher {
- opacity: 1;
- display: flex;
- align-items: center;
- font-size: 20px;
- color: var(--color-text-primary, --font-main, #F8F8F2);
- white-space: nowrap;
- }
- .shiki-plus .options .sweatcher span {
- margin-right: 10px;
- color: var(--color-text-primary, --font-main, #112233);
- }
- .shiki-plus .options .sweatcher .variant {
- min-width: unset;
- margin-bottom: unset;
- margin-right: 10px;
- }
- .shiki-plus .options .sweatcher .variant.selected {
- opacity: 0.85;
- }
- @media (max-width: 768px) {
- .shiki-plus .hide-on-mobile-text {
- display: none !important;
- }
- }
- `))
- }
- function ready(fn) {
- document.addEventListener('page:load', fn);
- document.addEventListener('turbolinks:load', fn);
- if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") fn();
- else document.addEventListener('DOMContentLoaded', fn);
- }
-
- async function sleep(timeMs) {
- await new Promise(resolve => setTimeout(resolve, timeMs));
- }
-
- async function GetResourceAsync(uri, config = {}) {
- return await new Promise((resolve, reject) => {
- $.ajax(Object.assign({
- url: uri,
- dataType: 'json',
- async: true,
- cache: false,
- headers: {
- 'Accept': 'application/json, text/javascript, */*; q=0.01',
- 'Accept-Language': 'en-US,en;q=0.9',
- },
- success: function(res) {
- resolve(res);
- },
- error: function(xhr) {
- reject(xhr);
- }
- }, config));
- });
- }
-
-
- async function createReader(hrefs, type) {
- let shikiPlus = $("<div>").addClass("shiki-plus")
- let options = $("<div>").addClass("options");
- let link
- if (type == "manga") {
- link = MangaLibLink + hrefs[0] + "/read/v01/c01";
- } else if (type == "ranobe") {
- link = RonobeLibLink + hrefs[0] + "/read/v01/c01";
- }
- let iframe = $("<iframe>").addClass("iframe").attr({
- 'allowFullScreen': 'allowfullscreen',
- "src": link,
- });
- let blackdiv = $("<div>").addClass("black-div");
- iframe.on("load", ()=>{
- blackdiv.remove();
- })
- shikiPlus.append(options).append(blackdiv).append(iframe)
- let currentVal = 0
- let variants = []
- let sweatcher = $("<div>").addClass("sweatcher");
- sweatcher.append($("<span>").text("Выбрать версию:").addClass("hide-on-mobile-text"))
- for (let i in hrefs) {
- let variant = $("<div>").addClass("b-link_button").addClass("dark").addClass("variant").text((String(Number(i) + 1)));
- variant.on("click", ()=>{
- if (i == currentVal) return
- let link
- if (type == "manga") {
- link = MangaLibLink + hrefs[i] + "/read/v01/c01";
- } else if (type == "ranobe") {
- link = RonobeLibLink + hrefs[i] + "/read/v01/c01";
- }
- for (let i of variants){
- i.removeClass("selected")
- }
- variant.addClass("selected")
- currentVal = i
- iframe.attr("src", link)
- })
- sweatcher.append(variant);
- variants.push(variant)
- }
- variants[0].addClass("selected")
-
- if (hrefs.length >= 2) options.append(sweatcher);
- let fullScreenBtn = $("<div>").addClass("full-screen-btn").addClass("b-link_button").addClass("dark").text("Полноэкранный режим");
-
-
- fullScreenBtn.on("click", ()=>{
- // fullScreenBtn.removeClass("touched")
- launchFullScreen(iframe[0]);
- })
- options.append(fullScreenBtn);
-
- let container = $('.b-db_entry');
- let aboutSection = container.find('.c-about');
- let descriptionSection = $('.c-description');
- let imageSection = container.find('.c-image');
-
- // Проверка на мобильную версию
- if ($(window).width() <= 768) {
- if (imageSection.length) {
- imageSection.append(shikiPlus);
- }
- } else if (aboutSection.length && descriptionSection.length) {
- shikiPlus.insertBefore(descriptionSection);
- }
- }
-
-
- function createWatcher(href) {
- let shikiPlus = $("<div>").addClass("shiki-plus")
- let iframe = $("<iframe>").addClass("iframe").attr({
- "src": AnimeLibLink + href.split("?")[0] + "/watch",
- "allowFullScreen": "allowfullscreen"
- });
-
- let blackdiv = $("<div>").addClass("black-div");
- shikiPlus.append(blackdiv).append(iframe)
- // Находим контейнер
- let container = $('.b-db_entry');
- let descriptionSection = $('.c-description');
-
- // Проверяем, существует ли нужный элемент
- if (descriptionSection.length) {
- // Если это мобильное устройство
- if ($(window).width() <= 768) {
- let cImageElement = container.find('.c-image');
- if (cImageElement.length) {
- cImageElement.append(shikiPlus);
- }
- } else {
- shikiPlus.insertBefore(descriptionSection);
- }
- }
- iframe.on("load", ()=>{
- blackdiv.remove();
- })
- }
-
-
- async function addBtn() {
- if (document.querySelector('.shikiPlus')) return
- let lic = false
- let btn = $("<div>").addClass("shikiPlus").addClass("b-link_button").addClass("dark")
- let href = ""
- let type
- if (location.href.includes("/animes/")) {
- type = "anime"
- let id = document.querySelector('.b-user_rate').getAttribute('data-target_id')
- let title = document.querySelector("meta[property='og:title']").getAttribute('content')
- try {
- title = title.split(" ")[0]
- }
- catch {return}
- let response = await GetResourceAsync(LibSocialApiLink + "/anime?q=" + title)
- href = ""
- for (let i in response.data) {
- if (id == response.data[i].shikimori_href.split("/")[4]) {
- lic = response.data.is_licensed
- href = response.data[i].slug_url
- }
- }
- btn.text("Смотреть")
- }
- else if (location.href.includes("/mangas/")) {
- let links = document.querySelectorAll(".mangalib > a")
- type = "manga"
- btn.text("Читать")
- await findInLinks(links)
- }
- else if (location.href.includes("/ranobe/")) {
- let links = document.querySelectorAll(".ranobelib > a")
- type = "ranobe"
- btn.text("Читать")
- await findInLinks(links)
- }
- async function findInLinks(as) {
- href = []
- for (let i in as) {
- if (as[i].href) {
- i = (as[i].href.split("?")[0].replace("https://ranobelib.me/", "").replace("https://mangalib.me/", "").replace("ru/", "").replace("book/", "").replace("ranobes/", "").replace("ranobe/", "").replace("manga/", "").replace("mangas/", ""))
- let response = await GetResourceAsync(LibSocialApiLink + "/manga/" + i)
- lic = response.data.is_licensed
- href.push(response.data.slug_url)
- }
- }
- }
- btn.on("click", ()=>{
- btn.remove();
- document.querySelector('.c-description').style.cssText = `
- margin-left:0;
- `
- if (type == "anime"){
- createWatcher(href)
- }
- else if (type == "manga" || type == "ranobe"){
- createReader(href, type)
- }
- })
- if (!lic && (href || href.length))
- document.querySelectorAll('.c-image').forEach(e => e.appendChild(btn[0]))
- }
- ready(addStyles)
- ready(addBtn)