Kemono助手

提供更好的Kemono使用体验

2023-06-15 يوللانغان نەشرى. ئەڭ يېڭى نەشرىنى كۆرۈش.

// ==UserScript==
// @name         Kemono助手
// @version      1.0.1
// @description  提供更好的Kemono使用体验
// @author       ZIDOUZI
// @match        https://*.kemono.party/*
// @match        https://*.kemono.su/*
// @icon         https://kemono.su/static/favicon.ico
// @grant        GM_xmlhttpRequest
// @connect   api.fanbox.cc
// @namespace https://greasyfork.org/users/448292
// ==/UserScript==

(async function () {

  var postContent = document.querySelector('.post__content');

  if (postContent) {
      replaceAsync(postContent.innerHTML, /(?<!a href="|<a [^>]+">)(https?:\/\/[^\s<]+)/g, async function (match) {
          var url = await getKemonoUrl(match);
          return `<a href="${url || match}" target="${url ? "_self" : "_blank"}">${url ? "[已替换]" : ""}${match}</a>`;
      }).then(function (result) {
          postContent.innerHTML = result
              .replace(/<a href="(https:\/\/[^\s<]+)">\1<\/a>\n?(#[^\s<]+)/g, "<a href=\"$1$2\">$1$2</a>")
              .replace(/<a href="(https:\/\/[^\s<]+)">(.*?)<\/a>\n?(#[^\s<]+)/g, "<a href=\"$1$3\">$2</a>")
      })
  }

  var prev = document.querySelector(".post__nav-link prev");
  if (prev) {
    prev.addEventListener("keydown", function (e) {
      if (e.key == "Right" || e.key == "ArrowRight") {
        prev.click();
      }
    });
  }

  var next = document.querySelector(".post__nav-link next");
  next = document.querySelector(".post__nav-link next");
  next.addEventListener("keydown", function (e) {
    if (e.key == "Left" || e.key == "ArrowLeft") {
      next.click();
    }
  });


})();

async function replaceAsync(str, regex, asyncFn) {
  const promises = [];
  str.replace(regex, (match, ...args) => {
      const promise = asyncFn(match, ...args);
      promises.push(promise);
  });
  const data = await Promise.all(promises);
  return str.replace(regex, () => data.shift());
}

async function getKemonoUrl(url) {

  function getFanbox(creatorId) {
      // 同步执行promise
      return new Promise((resolve, reject) => {
          GM_xmlhttpRequest({
              method: "GET",
              url: `https://api.fanbox.cc/creator.get?creatorId=${creatorId}`,
              headers: {
                  "Content-Type": "application/json",
                  "Accept": "application/json",
                  "Origin": "https://www.fanbox.cc",
                  "Referer": "https://www.fanbox.cc/"
              },
              onload: function (response) {
                  if (response.status == 200) {
                      resolve(JSON.parse(response.responseText))
                  } else {
                      reject({ status: response.status, statusText: response.statusText })
                  }
              },
              onerror: function (response) {
                  reject({ status: response.status, statusText: response.statusText })
              }
          })
      })
  }

  const pixiv_user = /https:\/\/www\.pixiv\.net\/users\/(\d+)/i;
  const pixiv_artworks = /https:\/\/www\.pixiv\.net\/artworks\/(\d+)/i;
  const fantia_user = /https:\/\/fantia\.jp\/fanclubs\/(\d+)(\/posts(\S+))?/i;
  const fanbox_user1 = /https:\/\/www\.fanbox\.cc\/@([^/]+)(?:\/posts\/(\d+))?/i;
  const fanbox_user2 = /https:\/\/(.+)\.fanbox\.cc(?:\/posts\/(\d+))?/i;
  const dlsite_user = /https:\/\/www.dlsite.com\/.+?\/profile\/=\/maker_id\/(RG\d+).html/i;
  const patreon_user1 = /https:\/\/www.patreon.com\/user\?u=(\d+)/i;
  const patreon_user2 = /https:\/\/www.patreon.com\/(\w+)/i;

  let service;
  let id;
  let post = null;

  if (pixiv_user.test(url)) {
      //pixiv artist
      service = "fanbox"
      id = url.match(pixiv_user)[1]
  } else if (pixiv_artworks.test(url)) {
      //pixiv artworks
      service = "fanbox";
      var artist = document.querySelector("#root > div.charcoal-token > div > div.sc-1nr368f-0.beQeCv > div > div.sc-1nr368f-3.dkdRNk > aside > section.sc-171jvz-1.sc-171jvz-3.sc-10r3j8-0.sc-f30yhg-3.fXmjBM.gOeyOH.iwVjrD.isGBrE > h2:nth-child(1) > div > a");
      if (artist) {
          id = artist.href.match(pixiv_user)[1]
      } else {
          window.alert("try get artist id failed")
          return;
      }
  } else if (fantia_user.test(url)) {
      //fantia
      service = "fantia"
      id = url.match(fantia_user)[1]
  } else if (dlsite_user.test(url)) {
      service = "dlsite"
      id = url.match(dlsite_user)[1]
  } else if (fanbox_user1.test(url) || fanbox_user2.test(url)) {
      //fanbox
      service = "fanbox"
      let matches = fanbox_user1.test(url) ? url.match(fanbox_user1) : url.match(fanbox_user2);
      id = (await getFanbox(matches[1])).body.user.userId
      post = matches[2]
  } else if (patreon_user1.test(url)) {
      // patreon
      service = "patreon"
      id = url.match(patreon_user1)[1]
  } else {
      return undefined;
  }

  return post == null ? `https://kemono.party/${service}/user/${id}` : `https://kemono.party/${service}/user/${id}/post/${post}`

}