您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
adds a link to myanimelist and anilist on Kitsu entries
- // ==UserScript==
- // @name Kitsu External Links
- // @namespace https://greasyfork.org/users/649
- // @version 1.0.1
- // @description adds a link to myanimelist and anilist on Kitsu entries
- // @author Adrien Pyke
- // @match *://kitsu.io/*
- // @grant none
- // @require https://cdn.jsdelivr.net/gh/fuzetsu/userscripts@ec863aa92cea78a20431f92e80ac0e93262136df/wait-for-elements/wait-for-elements.js
- // ==/UserScript==
- (() => {
- 'use strict';
- const Api = {
- cache: {},
- getId: () =>
- document
- .querySelector('.cover-photo')
- .getAttribute('style')
- .match(/cover_images\/(?<id>\d+)/iu).groups.id,
- getType: () =>
- location.href.match(/kitsu\.io\/(?<type>anime|manga)/iu).groups.type,
- getLinks: async (id, type) => {
- const endpoint = `https://kitsu.io/api/edge/${type}/${id}?include=mappings`;
- if (Api.cache[endpoint]) return Api.cache[endpoint];
- const response = await fetch(endpoint);
- const json = await response.json();
- const mappings = json.included
- .filter(i =>
- i.attributes.externalSite.match(
- /^(myanimelist|anilist)\/(anime|manga)$/iu
- )
- )
- .map(i => i.attributes);
- Api.cache[endpoint] = mappings;
- return mappings;
- }
- };
- const getLinksContainer = container => {
- const node = document.createElement('div');
- node.classList.add('where-to-watch-widget');
- const links = document.createElement('ul');
- links.classList.add('nav');
- node.appendChild(links);
- container.appendChild(node);
- return links;
- };
- const getLinkNode = mapping => {
- const { site, type } = mapping.externalSite.match(
- /^(?<site>myanimelist|anilist)\/(?<type>anime|manga)$/iu
- ).groups;
- const webSite =
- site === 'anilist' ? 'https://anilist.co' : 'https://myanimelist.net';
- const href = `${webSite}/${type}/${mapping.externalId}`;
- const node = document.createElement('li');
- const link = document.createElement('a');
- link.classList.add('hint--top', 'hint--bounce', 'hint--rounded');
- Object.assign(link, { href, target: '_blank', rel: 'noopener noreferrer' });
- link.setAttribute('aria-label', site);
- node.appendChild(link);
- const logo = document.createElement('img');
- Object.assign(logo, {
- src:
- site === 'anilist'
- ? 'https://anilist.co/img/icons/android-chrome-512x512.png'
- : 'https://upload.wikimedia.org/wikipedia/commons/7/7a/MyAnimeList_Logo.png',
- width: '20',
- height: '20'
- });
- link.appendChild(logo);
- return node;
- };
- waitForElems({
- sel: '.media-sidebar',
- onmatch(container) {
- const links = getLinksContainer(container);
- const id = Api.getId();
- const type = Api.getType();
- Api.getLinks(id, type).then(list =>
- list.forEach(m => links.appendChild(getLinkNode(m)))
- );
- }
- });
- })();