// ==UserScript== // @name Kemono跳转 // @namespace https://github.com/ZIDOUZI/kemono-jump-js // @version 2.4.5 // @description 在一些特定网站添加跳转至kemono按钮 // @author 子斗子 // @license MIT // @match https://*.pixiv.net/* // @match https://*.dlsite.com/*/RG*.html // @match https://*.fantia.jp/fanclubs/* // @match https://*.fanbox.cc/* // @icon https://kemono.party/static/favicon.ico // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @downloadURL none // ==/UserScript== (function () { const url = window.location.href; const language = navigator.language || navigator.userLanguage; var openInNew = GM_getValue('OpenInNew', false); let openInNewId = GM_registerMenuCommand(`[${openInNew ? "✔" : "✖"}]新建标签页打开`, openInNew_callback); function openInNew_callback() { GM_unregisterMenuCommand(openInNewId); openInNew = !openInNew; GM_setValue('OpenInNew', openInNew); openInNewId = GM_registerMenuCommand(`[${openInNew ? "✔" : "✖"}]新建标签页打开`, openInNew_callback); } var domain = GM_getValue('Domain', 'kemono.party'); let domainId = GM_registerMenuCommand(`当前域名:${domain}`, domain_callback); function domain_callback() { domain = prompt(language === 'zh-CN' ? '请输入域名, 例如kemono.su' : 'Please enter the domain name, for example kemono.su', domain); if (!domain) return; GM_setValue('Domain', domain); GM_unregisterMenuCommand(domainId); domainId = GM_registerMenuCommand(`当前域名:${domain}`, domain_callback); } if (window.location.host.endsWith('kemono.party')) { var dms = document.querySelector('.user-header__dms'); if (language === 'zh-CN' && dms) { dms.innerHTML = '私信' } var postFlag = document.querySelector('.post__flag'); if (language === 'zh-CN' && postFlag) { var text = postFlag.querySelector('span:last-child'); if (text) { text.textContent = '标记重新导入'; } } var postPublished = document.querySelector('.post__published'); if (postPublished) { fetch('https://kemono.party/api' + window.location.pathname) .then(res => res.json()) .then(res => { var edited = new Date(res[0].edited).getTime(); var editedTime = document.createElement('time'); editedTime.className = 'timestamp post__edited'; editedTime.dateTime = edited; editedTime.textContent = new Date(edited).toLocaleString(); postPublished.appendChild(editedTime); // insert explain text before edited time var editedExplain = document.createElement('span'); editedExplain.className = 'post__edited-explain'; editedExplain.textContent = language === 'zh-CN' ? '编辑于:' : 'Edited at:'; postPublished.insertBefore(editedExplain, editedTime); // insert separator var separator = document.createElement('span'); separator.className = 'post__separator'; separator.textContent = ' '; postPublished.insertBefore(separator, editedExplain); // insert explain text at first var publishedExplain = document.createElement('span'); publishedExplain.className = 'post__published-explain'; publishedExplain.textContent = language === 'zh-CN' ? '发布于:' : 'Published at:'; postPublished.insertBefore(publishedExplain, postPublished.firstChild); }) .catch(err => console.log(err)) } return; } //创建容器 const item = document.createElement('item'); item.id = 'SIR'; item.innerHTML = ` `; document.body.append(item) //创建样式 const style = document.createElement('style'); style.innerHTML = ` #SIR * { box-sizing: border-box; padding: 0; margin: 0; } #SIR .SIR-button { display: inline-block; height: 22px; margin-right: 10px; opacity: 0.5; background: white; font-size: 13px; padding:0 5px; position:fixed; bottom:2px; right:2px; border: solid 2px black; z-index: 9999; } `; const button = item.querySelector('.SIR-button') button.onclick = async () => { if (openInNew) { window.open(await getKemonoUrl(url)); } else { self.location = await getKemonoUrl(url); } } document.head.append(style) })(); async function getKemonoUrl(url) { function getFanbox(creatorId) { return new Promise((resolve, reject) => { fetch(`https://api.fanbox.cc/creator.get?creatorId=${creatorId}`, { method: "get", credentials: "include" }) .then(r => { if (r.ok) { return r.json() } else { reject({ status: r.status, statusText: r.statusText }) } }) .then(data => resolve(data)) .catch(e => reject(e)) }) } 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[3] } else if (patreon_user1.test(url)) { // patreon service = "patreon" id = url.match(patreon_user1)[1] } else { window.alert("unknown") return; } return post == null ? `https://kemono.party/${service}/user/${id}` : `https://kemono.party/${service}/user/${id}/post/${post}` }