Greasy Fork

ALink

Adds AniList links to mangadex manga pages

目前为 2019-03-18 提交的版本。查看 最新版本

// ==UserScript==
// @name ALink
// @namespace Morimasa
// @author Morimasa
// @description Adds AniList links to mangadex manga pages
// @match https://mangadex.org/title/*
// @match https://mangadex.org/manga/*
// @version 0.52
// ==/UserScript==

const insertAL = data => {
  const id = data.data.Media.id;
  document.getElementsByClassName("list-inline")[3].innerHTML+=`
    <li class="list-inline-item">
      <a rel="noopener noreferrer" target="_blank" href="https://anilist.co/manga/${id}">
        <img src="https://anilist.co/img/icons/icon.svg" height=16>
        AniList
      </a>
    </li>`;
}

const api = async (query, vars) => {
    const options = {
      method: 'POST',
      body: JSON.stringify({query: query, variables: vars}),
      headers: {
          'Content-Type': 'application/json'
      }
    }
    let res = await fetch('https://graphql.anilist.co', options)
    if (res.ok)
      return await res.json();
    else 
      return Promise.reject(res);
}

const searchMAL = id => {
  const query = 'query($mal:Int){Media(idMal:$mal,type:MANGA){id}}';
  const vars = {"mal": id}
  return api(query, vars);
}

const searchTitle = (title, format) => {
  const query = 'query($t:String,$f:MediaFormat){Media(search:$t,format:$f,type:MANGA){id}}';
  const vars = {"t": title, "f": format}
  return api(query, vars);
}

const getCountry = () => {
	return document.getElementsByClassName("card-header")[0].children[2].classList[2].split('-')[1]
}

const getNames = () => {
  const altNamesEL = document.getElementsByClassName('col-xl-9')[0].children[0];
  if(altNamesEL.children[0].innerText==="Alt name(s):")
    return [...altNamesEL.children[1].children[0].children].map(t => t.innerText);
  else
    return [];
}

const searchNative = (names, lang) => {
  const reg = {
    jp: /[\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f]/g,
    kr: /[\u1100-\u11FF\u3130-\u318F\uA960-\uA97F\uAC00-\uD7AF\uD7B0-\uD7FF]/g
  }
  const native = names.filter(t => t.match(reg[lang]))
  if(native.length !== 1) return false;
  else return native[0];
}

const check = err => {
  if (err===undefined || err.status===404) {
    const lang = getCountry();
    if (!["jp", "kr", "cn"].includes(lang)) return;
    const names = getNames();
    const native = searchNative(names, lang);
    const title = native ? native : document.getElementsByClassName("card-header")[0].childNodes[3].textContent;
    const isOneshot = document.querySelector('.badge[href$="/genre/21"]');
    searchTitle(title, isOneshot ? 'ONE_SHOT' : 'MANGA')
    .then(insertAL)
    .catch(err => console.info(`ALink: ${err.statusText}`))
  }
  else
    console.error(err)
}

const malURL = document.querySelector('a[href^="https://myanimelist.net"]');
if (malURL)
  searchMAL(malURL.href.split('/').pop())
  .then(insertAL)
  .catch(check)
else
  check();