// ==UserScript== // @name kemono.su links for ppixiv // @author EnergoStalin // @description Add kemono.su patreon & fanbox & fantia links into ppixiv // @license AGPL-3.0-only // @version 1.5.4 // @namespace https://pixiv.net // @match https://*.pixiv.net/* // @run-at document-body // @icon https://www.google.com/s2/favicons?sz=64&domain=pixiv.net // @connect gumroad.com // @connect www.patreon.com // @connect kemono.su // @grant GM.xmlHttpRequest // @downloadURL none // ==/UserScript== "use strict";(()=>{var L=Object.defineProperty;var n=(e,t)=>L(e,"name",{value:t,configurable:!0});var i=(e,t,o)=>new Promise((r,a)=>{var c=s=>{try{l(o.next(s))}catch(d){a(d)}},u=s=>{try{l(o.throw(s))}catch(d){a(d)}},l=s=>s.done?r(s.value):Promise.resolve(s.value).then(c,u);l((o=o.apply(e,t)).next())});function b(e){let t=e.match(/datetime="(.+) /);return t?t[1]:"Could not determine last post datetime"}n(b,"lastPostTimeFromHtml");function m(e){let t=e.trim();return t.startsWith("http")||(t=`https://${t}`),t}n(m,"normalizeUrl");function p(e){let t=new Map,o=!1;return function(r,a,...c){if(o)return;o=!0;let u=c[0];if(t.has(u))return o=!1,r(t.get(u));e.apply(this,c).then(l=>{t.set(u,l),f(a),o=!1})}}n(p,"memoize");var G=/[\W\s]((?:https?:\/\/)?(?:\w+[\.\/])+(?:\w?)+)/g,g={patreon:"patreon.com",fanbox:"Fanbox",fantia:"fantia.jp",gumroad:"gumroad.com"};function I(e){return e.map(t=>{try{let o=new URL(m(t));return{label:g[Object.keys(g).find(r=>o.host.includes(r))],url:o}}catch(o){}})}n(I,"preprocessMatches");function y(e){let o=document.body.querySelector(".description").innerText.replaceAll(/\/\s+/g,"/").replaceAll("(dot)",".");return M(I(Array.from(o.matchAll(G)).map(r=>r[1])).filter(r=>r),e)}n(y,"getLinksFromDescription");function M(e,t){let o=t.map(r=>r.label);return e.filter(r=>!o.includes(r.label))}n(M,"removeDuplicates");function f(e){unsafeWindow.ppixiv.userCache.callUserModifiedCallbacks(e)}n(f,"notifyUserUpdated");function E(e){let t=0;if(e.length===0)return t;for(let o=0;ox[r.url.toString()]===void 0).map(r=>T(r.url.toString()))).then(r=>{h.delete(o),r.length>0&&f(t.userId)}).catch(console.error));for(let r of e){let a=x[r.url.toString()];(a==null?void 0:a.redirected)===!0?(r.label+=" (Redirected)",r.disabled=!0):a===void 0?r.disabled=!0:r.label+=` (${a.lastUpdate})`}return e}n(w,"postprocessLinks");function U(e,t){e.push({url:new URL(`https://kemono.su/fanbox/user/${t}`),icon:"mat:money_off",type:`kemono_fanbox#${t}`,label:"Kemono fanbox"})}n(U,"fanbox");function R(e,t){let o=e.url.toString().split("/").pop();t.push({url:new URL(`https://kemono.su/fantia/user/${o}`),icon:"mat:money_off",type:`kemono_fantia#${o}`,label:"Kemono fantia"})}n(R,"fantia");var $=/"external_id":"(\d+)"/,z=p(e=>i(void 0,null,function*(){return GM.xmlHttpRequest({method:"GET",url:e}).then(t=>{var o,r;return(r=(o=t.responseText.match($))==null?void 0:o[1])!=null?r:"undefined"})}));function _(e,t,o){z(r=>{t.push({url:new URL(`https://kemono.su/gumroad/user/${r}`),icon:"mat:money_off",type:"kemono_gumroad#{id}",label:"Kemono gumroad"})},o,e.url.toString())}n(_,"gumroad");function S(e){typeof e.url=="string"&&(e.url=new URL(m(e.url))),e.url.protocol="https",e.url.host.startsWith("www.")||(e.url.host=`www.${e.url.host}`)}n(S,"normalizePatreonLink");var v=new RegExp('"id":\\s*"(\\d+)",[\\n\\s]*"type":\\s*"user"',"ms"),C=p(e=>i(void 0,null,function*(){return yield GM.xmlHttpRequest({method:"GET",url:e}).then(t=>{var o,r;return(r=(o=t.responseText.match(v))==null?void 0:o[1])!=null?r:"undefined"})}));function k(e,t,o){S(e);let r=e.url.toString();C(a=>{t.push({url:new URL(`https://kemono.su/patreon/user/${a}`),icon:"mat:money_off",type:`kemono_patreon#${a}`,label:"Kemono patreon"})},o,r)}n(k,"patreon");var F=n(({extraLinks:e,userInfo:t})=>{let o=[];for(let a of[...e,...y(e)])switch(a.label){case"Fanbox":U(o,t.userId);break;case"patreon.com":k(a,o,t.userId);break;case"gumroad.com":_(a,o,t.userId);break;case"fantia.jp":R(a,o);break;default:}let r=w(o,t);e.push(...r)},"addUserLinks");unsafeWindow.vviewHooks={addUserLinks:F};})();