NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name AnimeGoSync // @namespace https://animego.org/anime/* // @version 1.0 // @description simple script for sync anime from yummyanime to shikimori! // @author lelykmaryan // @match https://animego.org/anime/* // @icon https://www.google.com/s2/favicons?domain=animego.org // @grant none // @license MIT // ==/UserScript== let names = document.querySelector(".list-unstyled > li").innerText; let response = await fetch(`https://shikimori.one/api/animes?search=${names}`); // получаем общую информацию об аниме без токена пользователя let responseAnime = await response.json(); let anime = {}; anime.id = responseAnime[0].id; anime.episodes = responseAnime[0].episodes; anime.name = responseAnime[0].name; checkVallidToken() if (String(localStorage.getItem('access_token')) != 'undefined' && localStorage.getItem('access_token') != null ) { // токен есть в сторадже? -Да - получаем инфу по этому аниме от пользователя, обновляем статусы, Нет - показываем форму авторизации getAnime(); haveToken(); } else { let syncButton = document.createElement('div'); syncButton.innerHTML = `<br><h4>Shikimori:</h4> <div style="color: #ff6666; font-weight: bold">Без авторизации на Shikimori, добавить аниме в свой список будет невозможно! <br><br> <div class="btn-primary btn" id="authAdd">Авторизоваться</div> </div>`; document.querySelector(".dropdown").after(syncButton); ; } async function checkVallidToken() { if( Date.now()/1000 > localStorage.getItem('expired_token')) { // токен устарел? => меняем на новый (refresh токен активен 28 дней, если они пройдут, наиболее вероятно будет ошибка, исправлю позже) const formData = new FormData(); formData.append('grant_type', 'refresh_token'); formData.append('client_id', 'IGtPiT4zLudryFhJMA4yPdNtZ_3T_E4GFVrma1O4KkI'); formData.append('client_secret', 'bxTapg5D3FIoNVFwxeowYyQizqQLbN0kdITcZVOzmUo'); formData.append('refresh_token', localStorage.getItem('refresh_token')); let response = await fetch(`https://shikimori.one/oauth/token`, { method: 'POST', body: formData }); let responseJSON = await response.json(); localStorage.setItem('expired_token', responseJSON.created_at+responseJSON.expires_in); localStorage.setItem('access_token', responseJSON.access_token); localStorage.setItem('refresh_token', responseJSON.refresh_token); } } async function getAnime() { // получаем статус аниме и количество просмотреннных эпизодов let response = await fetch(`https://shikimori.one/api/v2/user_rates/?target_id=${anime.id}&target_type=Anime&user_id=${localStorage.getItem('shiki_id')}`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('access_token')}` }}); let responseJSON = await response.json(); anime.status = responseJSON[0]?.status; anime.myEpisodes = responseJSON[0]?.episodes != undefined ? responseJSON[0]?.episodes : 0; anime.rewatches = responseJSON[0]?.episodes != undefined ? responseJSON[0]?.rewatches : 0; } try { authAdd.onclick = () => { //авторизуем пользователя (oauth2.0), получаем его статус по аниме, обновляем раздел let paramsLink = `scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no, width=450,height=650`; let link = `https://shikimori.one/oauth/authorize?client_id=IGtPiT4zLudryFhJMA4yPdNtZ_3T_E4GFVrma1O4KkI&redirect_uri=https://animego.org/&response_type=code&scope=user_rates`; newWindow = open(link, 'test', paramsLink); let timerID = setTimeout(async function tick() { try { let tmppath = newWindow.location.href; let path = tmppath.slice(tmppath.indexOf('=')+1); const formData = new FormData(); formData.append('grant_type', 'authorization_code'); formData.append('client_id', 'IGtPiT4zLudryFhJMA4yPdNtZ_3T_E4GFVrma1O4KkI'); formData.append('client_secret', 'bxTapg5D3FIoNVFwxeowYyQizqQLbN0kdITcZVOzmUo'); formData.append('code', path); formData.append('redirect_uri', 'https://animego.org/'); let responseToken = await fetch(`https://shikimori.one/oauth/token`, { method: 'POST', body: formData }); let responseTokenJson = await responseToken.json(); localStorage.setItem('expired_token', responseTokenJson.created_at+86400); localStorage.setItem('access_token', responseTokenJson.access_token); localStorage.setItem('refresh_token', responseTokenJson.refresh_token); let responseID = await fetch(`https://shikimori.one/api/users/whoami`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('access_token')}` } }); let responseIdJson = await responseID.json(); localStorage.setItem('shiki_id', responseIdJson.id); newWindow.close(); getAnime(); } catch { time = setTimeout(tick, 2000); } }, 2000); } } catch { console.log(`токен шики найден, кнопки авторизации отключены`); } async function haveToken() { let timerID = setTimeout(function tick() { try { document.querySelector(".video-player-bar-series-watch").onclick = function() { let numSeries = (document.querySelector(`.video-player-bar-series-item.video-player__active`) != null) ? document.querySelector(`.video-player-bar-series-item.video-player__active`).getAttribute('data-episode') : 1; let nextSeries = document.getElementById(`video-carousel-item${+numSeries}`); (nextSeries != null) ? nextSeries.querySelector(`.video-player-bar-series-item`).click() : false; anime.status = (+numSeries === anime.episodes) ? 'completed' : 'watching'; anime.myEpisodes = +numSeries; sendStatus(anime.status, numSeries); }; } catch { time = setTimeout(tick, 1000); }}, 1000); } sendStatus = async function(statusAnime, numSeries) { //отправляем изменения в статусе/эпизоде аниме let json = { "user_rate": { "episodes": `${anime.status === 'watching' ? numSeries : anime.myEpisodes}`, "status": `${statusAnime}`, "rewatches": `${anime.rewatches}`, "target_id": `${anime.id}`, "target_type": "Anime", "user_id": `${localStorage.getItem('shiki_id')}` }}; let responsetok = await fetch(`https://shikimori.one/api/v2/user_rates`, { method: 'POST', headers: { 'Authorization': `Bearer ${localStorage.getItem('access_token')}`, 'Content-Type': 'application/json' }, body: JSON.stringify(json) }); }