NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Shiki List Comparison // @namespace https://shikimori.me/ // @version 1.0.4 // @description Показывает какое аниме или какая манга, есть у вас в списке вместе с каким-то пользователем, зайдя в список аниме или манги в профиле пользователя. // @match *://shikimori.org/* // @match *://shikimori.one/* // @match *://shikimori.me/* // @icon https://shikimori.me/favicon.ico // @author neutron6663 // @updateURL https://openuserjs.org/meta/neutron6663/Shiki_List_Comparison.meta.js // @downloadURL https://openuserjs.org/install/neutron6663/Shiki_List_Comparison.user.js // @copyright 2023, neutron6663 (https://openuserjs.org/users/neutron6663) // @license MIT // ==/UserScript== function getUserId(myId = true) { let id; if (myId) { id = $('body').data('user').id; } else { if ($('#profiles_show').length) { id = $('#profiles_show .profile-head').data('userId'); } else { const rate_url = $('.user_rate').data('rate_url'); $.ajax({ url: `https://shikimori.me/api/v2/user_rates/${rate_url.substring(rate_url.lastIndexOf('/')+1)}`, success: function (result) { if (result.isOk == false) console.log('Что-то пошло не так, при попытке получить id пользователя.'); id = result.user_id; }, async: false }); } } return id; } function getList(userId) { let path = location.pathname.split('/'); let titleType = path[3] == 'anime' ? 'Anime' : 'Manga'; let allEntries = []; $.ajax({ url: `https://shikimori.me/api/v2/user_rates?target_type=${titleType}&user_id=${userId}`, success: function (result) { if (result.isOk == false) console.log('Что-то пошло не так, при попытке получить список пользователя.'); else { allEntries = result; } }, async: false }); return allEntries; } function compareList(aId, bId) { const aList = getList(aId); const bList = getList(bId); const comparedList = []; $.each(aList, function (index, aEntry) { const cEntry = bList.find(bEntry => bEntry.target_id == aEntry.target_id); if (!cEntry) return; cEntry.my_status = aEntry.status; cEntry.my_score = aEntry.score; comparedList.push(cEntry); }); return comparedList; } function getVisibleEntries(list) { const visibleEntries = [] $.each(list, function (index, entry) { const visibleEntryEl = $(".entries").find("[data-target_id='" + entry.target_id + "']")[0]; if (!visibleEntryEl) return; entry.element = visibleEntryEl; visibleEntries.push(entry); }); return visibleEntries; } function addVisibilityDifference(entry) { const element = $(entry.element); if (element.hasClass('compared-' + entry.my_status)) return; element.addClass('compared-' + entry.my_status); const my_status = $('<span>', { class: 'my-status', html: $('.b-options-floated.mylist').find(`[data-id=${entry.my_status}]`).text().split(String.fromCharCode(160))[0] }); element.find('.rewatches').after(my_status); const my_score = $('<span>', { html: `${entry.my_score === 0 ? '–' : entry.my_score}` }); element.find('.num [data-field="score"]').before(my_score); my_score.after($('<span>', { class: 'b-separator inline', html: '|' })); } function property(key, value) { return `\t${key}: ${value};`; } function getCustomStyle(selectors, ...properties) { return selectors.join(', ') + ' {\n' + properties.join('\n') + '\n}' } function addCustomCss(id, ...styles) { $('#custom_css').before($('<style id="' + id + '">' + styles.join('\n\n') + '</style>')); } function getComparedStyle() { const styles = [] styles.push(getCustomStyle(['.compared-planned .my-status', '.compared-watching .my-status', '.compared-rewatching .my-status', '.compared-completed .my-status', '.compared-on_hold .my-status', '.compared-dropped .my-status'], property('display', 'inline-block'), property('vertical-align', 'top'), property('padding', '0 6px'), property('margin', '0.0625rem 0 0 0.5rem'), property('border-radius', '2px'), property('box-shadow', 'inset 0 0 0 1px'), property('font-size', '11px'), property('white-space', 'nowrap'), property('text-transform', 'lowercase'), property('float', 'right') ), getCustomStyle(['.compared-planned .my-status'], property('color', '#ef8d50') ), getCustomStyle(['.compared-watching .my-status'], property('color', '#4f91e8') ), getCustomStyle(['.compared-rewatching .my-status'], property('color', '#4f91e8') ), getCustomStyle(['.compared-completed .my-status'], property('color', '#66bb6a') ), getCustomStyle(['.compared-on_hold .my-status'], property('color', '#549db3') ), getCustomStyle(['.compared-dropped .my-status'], property('color', '#ef5350') ) ); return styles; } function initialize() { if (!$('#user_rates_index').length || getUserId() == getUserId(false) || !getUserId()) return; const list = compareList(getUserId(), getUserId(false)); $.each(getVisibleEntries(list), function (index, entry) { addVisibilityDifference(entry); }); $('.list-groups').on("DOMNodeInserted", function (event) { if (!$(event.target).hasClass('entries') && !$(event.target).hasClass('list-lines')) return; $.each(getVisibleEntries(list), function (index, entry) { addVisibilityDifference(entry); }); }); addCustomCss('compared_style', ...getComparedStyle()); if ($('style#custom_css').text().includes('shiki-theme.web.app//main.css')) { const shikiThemeByGrin3671 = () => { return getCustomStyle(['.compared-planned .my-status', '.compared-watching .my-status', '.compared-rewatching .my-status', '.compared-completed .my-status', '.compared-on_hold .my-status', '.compared-dropped .my-status'], property('display', 'inline-block'), property('vertical-align', 'top'), property('padding', '2px 6px'), property('margin', '0.0625rem 0 0 0.5rem'), property('border-radius', '2px'), property('box-shadow', 'inset 0 0 0 1px'), property('font-size', '12px'), property('font-weight', 'bold'), property('white-space', 'nowrap'), property('text-transform', 'capitalize'), ); } addCustomCss('compared_style_shikiTheme', shikiThemeByGrin3671()); } } 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); } ready(initialize);