123456789101112131415161718192021222324252627 |
- // ==UserScript==
- // @namespace ame-musicbrainz-works
- // @name Ame (MusicBrainz - Works)
- // @version 0.4.1
- // @author SuperSaltyGamer
- // @run-at document-end
- // @match https://musicbrainz.org/*
- // @match https://beta.musicbrainz.org/*
- // @match https://www.minc.or.jp/*
- // @match https://iswcnet.cisac.org/*
- // @match https://www2.jasrac.or.jp/*
- // @grant GM.addStyle
- // @grant GM.xmlHttpRequest
- // @grant GM.setValue
- // @grant GM.getValue
- // @grant GM.deleteValue
- // @downloadURL https://gitlab.com/SuperSaltyGamer/ame/-/raw/main/dist/musicbrainz-works.user.js
- // @updateURL https://gitlab.com/SuperSaltyGamer/ame/-/raw/main/dist/musicbrainz-works.user.js
- // ==/UserScript==
- (function(u){typeof define=="function"&&define.amd?define(u):u()})(function(){"use strict";function u(e){return new Promise(t=>{setTimeout(t,e)})}function H(e){const t=document.createElement("template");return t.innerHTML=e,t.content.firstElementChild}function k(e,t){return new Promise(r=>{const n=t==null?void 0:t.waitSelector,o=(t==null?void 0:t.timeout)??3e3;if(o!==0){const s=document.querySelector(e);if(s){r(s);return}}const a=setTimeout(()=>{o!==0&&(i.disconnect(),r(null))},o),i=new MutationObserver(s=>{for(const l of s)for(const c of Array.from(l.addedNodes))if(c instanceof Element&&c.matches(n??e)){o!==0&&(i.disconnect(),clearTimeout(a)),r(n?document.querySelector(e):c);return}});i.observe(document.body,{childList:!0,subtree:!0})})}function _(e,t){new MutationObserver(async n=>{for(const o of n)for(const a of o.addedNodes){if(!(a instanceof HTMLElement))continue;const i=a.matches(e)?a:a.querySelector(e);i&&await t(i)}}).observe(document.body,{childList:!0,subtree:!0})}function h(e,t){return document.evaluate(t,e,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue}function y(e,t){const r=document.evaluate(t,e,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);return Array.from({length:r.snapshotLength},(n,o)=>r.snapshotItem(o))}const w=new AudioContext,V=new Set(`[᠊᳓‾﹉-﹌__﹍-﹏︳︴‗--﹣֊᐀᭠᠆᠇‐-–︲—﹘︱―⸺⸻⁓⹃⸗⹀⹝〜゠・・𐺭,,﹐︐⸴⸲⹁⹌⹎⹏՝،؍٫٬߸᠂᠈꓾꘍꛵𖺗、﹑︑、﹅﹆𖿢;;;﹔︔؛⁏⸵꛶⹉::﹕︓⩴։؞܃-܈࠰-࠾፡፣-፦᠄᠅༔៖᭝꧇᛫-᛭꛴!!﹗︕¡⹓՜߹᥄𞥞??﹖︖⁈⁇¿⸮⹔՞؟܉፧᥅⳺⳻꘏꛷꫱𑅃𞥟‽⸘..․﹒‥︰…︙᠁۔܁܂።᠃᠉᙮᭜⳹⳾⸰⸼꓿꘎꛳𖫵𖺘𛲟。︒。··⸱⸳।॥꣎꣏᰻᰼꡶꡷᜵᜶꤯၊။។៕᪨-᪫᭞᭟꧈꧉꩝-꩟꫰꯫𐩖𐩗𑁇𑁈𑃀𑃁𑅁𑅂𑇅𑇆𑈸𑈹𑑋𑑌𑗂𑗃𑙁𑙂𑜼𑜽𑥄𑱁𑱂𑽃𑽄𖩮𖩯᱾᱿؝܀߷჻፠፨᨞᨟᭚᭛᭽᭾꧁-꧆꧊-꧍꛲꥟𐡗𐬺-𐬿𐽕-𐽙𐾆-𐾉𑂾𑂿𑅀𑇈𑇞𑇟𑊩𑜾𑥆𑻷𑻸𑽅-𑽏⁕⁖⁘-⁞⸪-⸭⸽⳼⳿⸙𐤿𐄀-𐄂𐎟𐏐𐤟𒑰-𒑴𒿱𒿲''‘-‛׳‹›""“-‟⹂〝-〟״«»((﹙⁽₍︵))﹚⁾₎︶[[﹇]]﹈{{﹛︷}}﹜︸༺-༽᚛᚜⁅⁆⌈-⌋⧼⧽⦃-⦅⦅⦆⦆⦇-⦘⟅⟆⟦-⟯❨-❵⸂-⸅⸉⸊⸌⸍⸜⸝⸠-⸩⹕-⹜〈〈︿〉〉﹀《︽》︾「﹁「」﹂」『﹃』﹄【︻】︼〔﹝︹〕﹞︺〖︗〗︘〘-〛﴾﴿‖⸾⧘-⧛§⸹¶⁋⹍⸿@@﹫**﹡⁎⁑٭꙳//\\\﹨⹊&&﹠⁊⹒##﹟%%﹪٪‰؉‱؊†‡⸶-⸸⹋•‣‧⁃⁌⁍′-‴⁗‵-‷〃‸※‿⁔⁀⁐⁁⁂⸀⸁⸆-⸈⸋⸎-⸖⸚⸛⸞⸟⹄-⹈꙾՚՛՟־׀׃׆܊-܍࡞᠀𑙠-𑙬॰꣸-꣺꣼𑬀-𑬉৽੶૰౷಄෴๏๚๛꫞꫟༄-༊࿐࿑་-༒྅࿒-࿔࿙࿚𑨿-𑩆𑪚-𑪜𑪞-𑪢𑱰𑱱᰽-᰿၌-၏៘-៚᪠-᪦᪬᪭᳀-᳇⵰꡴꡵᯼-᯿꤮꧞꧟꩜𐕯𑁉-𑁍𐩐-𐩕𐩘𑱃-𑱅𐬹𐩿𐫰-𐫶𐮙-𐮜𑂻𑂼𑅴𑅵𑇍𑇇𑇛𑇝𑈺-𑈽𑑍𑑚𑑎𑑏𑑛𑑝𑓆𑗁𑗄-𑗗𑙃𑚹𑠻𑥅𑧢𑿿𖬷-𖬻𖭄𖺙𖺚𝪇-𝪋؈𞻰𞻱℘⅁-⅄←←↚→→↛↑↑↓↓↠↣↦⇒⇏⇔⇎⇴-∂𝛛𝜕𝝏𝞉𝟃∃-∇𝛁𝛻𝜵𝝯𝞩∈-∍϶∎-∑⅀++﬩﹢⁺₊±÷×<<﹤≮==﹦⁼₌≠⩵⩶>>﹥≯¬¬||~~−⁻₋⁒∓-∕⁄∖-∛؆∜؇∝-∭⨌∮-∼≁∽-≀≂-≅≇≆≈-≍≭≎-≟≡-≤≰≥≱≦-≬≲≴≳≵≶≸≷≹≺⊀≻⊁≼⋠≽⋡≾≿⊂⊄⊃⊅⊆⊈⊇⊉-⊑⋢⊒⋣⊓-⊢⊬⊣-⊨⊭⊩⊮⊪⊫⊯-⊲⋪⊳⋫⊴⋬⊵⋭⊶-⊼⅋⊽-⋟⋤-⋩⋮-⋿⌠⌡⍼⎛-⎳⏜-⏡▷◁◸-◺◿⟀-⟄⟇-⟥⟰-⟿⤀-⤳⤶-⦂⦙-⧗⧜-⧻⧾-⨋⨍-⩳⩷-⫛⫝⫝̸⫞-⫿⬰-⭄⭇-⭌♯↔↮⤴⤵‼⁉〰〽◼◻◾◽]`.split("")),M={0:1,"0":1,1:2,"1":2,2:3,"2":3,3:4,"3":4,4:5,"4":5,5:6,"5":6,6:7,"6":7,7:8,"7":8,8:9,"8":9,9:10,"9":10,a:11,a:11,A:11,ä:11,b:12,b:12,B:12,c:13,c:13,C:13,d:14,d:14,D:14,e:15,e:15,E:15,f:16,f:16,F:16,g:17,g:17,G:17,h:18,h:18,H:18,i:19,i:19,I:19,j:20,j:20,J:20,k:21,k:21,K:21,l:22,l:22,L:22,m:23,m:23,M:23,n:24,n:24,N:24,o:25,o:25,O:25,ö:25,õ:25,p:26,p:26,P:26,q:27,q:27,Q:27,r:28,r:28,R:28,s:29,s:29,S:29,$:29,t:30,t:30,T:30,u:31,u:31,U:31,ü:31,v:32,v:32,V:32,w:33,w:33,W:33,x:34,x:34,X:34,y:35,y:35,Y:35,z:36,z:36,Z:36},j=Object.entries(M).reduce((e,[t,r])=>(r in e||(e[r]=[]),e[r].push(t),e),{});function I(e){const t=M[e];return t?j[t]??[e]:[e]}function P(e){return e=e.replace(/[\s・]+/g,"").split("").map(t=>V.has(t)?"":`[${I(t).join("")}]`).join("[\\s\\p{Pc}\\p{Pd}\\p{Pe}\\p{Pf}\\p{Pi}\\p{Po}\\p{Ps}\\p{Sm}]{0,4}"),new RegExp(`(?<!<span class="ame__mark--inner">)${e}`,"gui")}function A(e,t){e.innerHTML=e.innerHTML.replaceAll(t,r=>{const n=document.createElement("span");n.classList.add("ame__mark--inner"),n.innerText=r;const o=document.createElement("span");return o.classList.add("ame__mark"),o.appendChild(n),o.outerHTML})}function T(e){const t=e.value;return e.addEventListener("input",()=>{e.value!==t&&(e.style.backgroundColor="yellow")}),e}function g(e,t){if(e instanceof HTMLInputElement){Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,"value").set.call(e,t),e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("focusout",{bubbles:!0}));return}if(e instanceof HTMLSelectElement){Object.getOwnPropertyDescriptor(HTMLSelectElement.prototype,"value").set.call(e,t),e.dispatchEvent(new Event("change",{bubbles:!0})),e.dispatchEvent(new Event("focusout",{bubbles:!0}));return}}function N(e,t){const r=w.createOscillator(),n=w.createGain();r.connect(n),n.connect(w.destination),n.gain.value=.25,r.frequency.value=t,r.start(w.currentTime),r.stop(w.currentTime+e/1e3)}var f=(e=>(e.Work="work",e))(f||{});function W(e,t,r=!0){if(document.visibilityState==="visible")return r&&N(50,1e3),t==null?GM.deleteValue(e):(console.info("setBusValue",e,t),GM.setValue(e,{value:t,timestamp:new Date().getTime()+60*1e3}))}async function L(e){if(document.visibilityState!=="visible")return null;const t=await GM.getValue(e);return!t||(await W(e,null,!1),t.timestamp<new Date().getTime())?null:(console.info("getBusValue",e,t),t.value)}async function b(e,t){const r=await L(e);if(r)try{await t(r)}catch(n){console.error(n)}finally{await W(e,r)}}async function D(){_("a[class^='LandingPage_languageButton__']",()=>{location.href="/search"})}async function $(){let e=!1;await b(f.Work,async t=>{if(!t.iswc)return;const r=document.querySelector("#iswc"),n=document.querySelector("button[type='submit']");if(g(r,t.iswc),await u(800),n==null||n.click(),await u(500),e=await Promise.any([k("div[class^='Search_resultsContainer__'] div[class^='AlertMessage_text__']").then(()=>!0),k("[class^='Search_sectionTitle__']").then(i=>!i)]),e)return;const o=document.querySelector("[id='View More']");o.click(),await u(100);const a=h(document,"//button[.='Copy work codes']");a?(a.click(),t.codes.external=!0):o.after(H('<div style="padding: .5rem;">Install <a href="https://musicbrainz.org/doc/Guides/Userscripts#Userscripts:_Works">Bulk copy-paste work codes</a> for better integration.</div>')),t.sources.push(location.href),t.sources=Array.from(new Set(t.sources))}),e&&(location.href="/")}async function z(){return b(f.Work,async e=>{if(!(e!=null&&e.name))return;const t=document.querySelector("input[name='IN_WORKS_TITLE_NAME1']"),r=document.querySelector("button[name='CMD_SEARCH']");t.value!==e.name&&(g(t,e.name),r.click())})}async function F(){return b(f.Work,async e=>{var l,c,m,p;document.querySelector("a[href='#tab-00-07']").click(),await u(300);const r=((c=(l=h(document,"//*[contains(@class, 'baseinfo--iswc')]//strong"))==null?void 0:l.innerText)==null?void 0:c.trim())||null,n=((p=(m=h(document,"//*[contains(@class, 'baseinfo--code')]//strong"))==null?void 0:m.innerText)==null?void 0:p.trim())||null,o=y(document,"//table[contains(@class, 'detail')]//td[contains(., '作詞')]/parent::tr/*[2]").map(S).filter(Boolean).filter(d=>d!=="識別"),a=y(document,"//table[contains(@class, 'detail')]//td[contains(., '作曲')]/parent::tr/*[2]").map(S).filter(Boolean).filter(d=>d!=="識別"),i=y(document,"//table[contains(@class, 'detail')]//td[contains(., '編曲')]/parent::tr/*[2]").map(S).filter(Boolean).filter(d=>d!=="識別"),s=y(document,"//table[contains(@class, 'detail')]//td[contains(., '出版者')]/parent::tr/*[2]").map(S).filter(Boolean).filter(d=>d!=="識別");r&&(e.iswc=r),n&&(e.codes.jasrac=n),e.lyricists=Array.from(new Set(o)),e.composers=Array.from(new Set(a)),e.arrangers=Array.from(new Set(i)),e.publishers=Array.from(new Set(s)),e.sources.push(location.href),e.sources=Array.from(new Set(e.sources))})}function S(e){var t,r;return((r=(t=e.textContent)==null?void 0:t.split(`
- `)[0])==null?void 0:r.trim())??""}function G(){const e=document.querySelector(".logo > a");e&&(e.href=`${location.origin}/search`)}function U(){return b(f.Work,async e=>{if(!e.name)return;const t=document.querySelector("#kyokunm"),r=document.querySelector("#search-by-track-and-artist");t.value=e.name,r.click()})}function J(){for(const e of document.querySelectorAll(".saku-detail-link")){const t=document.createElement("a");t.target="_blank",t.href=`/saku/detail/?${e.getAttribute("data-href")}`,t.innerHTML=e.innerHTML,e.replaceWith(t)}return b(f.Work,async e=>{for(const n of e.context.tokens){const o=P(n);for(const a of document.querySelectorAll("#track-list tr td:nth-child(3), #track-list tr td:nth-child(4)"))A(a,o)}if(e.name)for(const n of document.querySelectorAll("#track-list tr td:nth-child(2)"))A(n,P(e.name));const t=document.querySelector("#kyokunm"),r=document.querySelector("#search-by-track-and-artist");!e.name||t.value===e.name||(t.value=e.name,r.click())})}function K(){return b(f.Work,async e=>{var l,c,m,p,d,B;const t=((c=(l=h(document,"//h3/text()[.!='-']"))==null?void 0:l.nodeValue)==null?void 0:c.replaceAll(" ",""))||null,r=((p=(m=h(document,"//a[@href='#jasrac']/following-sibling::*/span[2][.!='']"))==null?void 0:m.innerText)==null?void 0:p.trim())||null,n=((B=(d=h(document,"//a[@href='#nextone']/following-sibling::*/span[2][.!='']"))==null?void 0:d.innerText)==null?void 0:B.trim())||null,o=y(document,"//div[contains(@class, 'management')]//td[contains(., '作詞')]/parent::tr/*[2]").map(E).filter(Boolean),a=y(document,"//div[contains(@class, 'management')]//td[contains(., '作曲')]/parent::tr/*[2]").map(E).filter(Boolean),i=y(document,"//div[contains(@class, 'management')]//td[contains(., '編曲')]/parent::tr/*[2]").map(E).filter(Boolean),s=y(document,"//div[contains(@class, 'management')]//td[contains(., '出版者')]/parent::tr/*[2]").map(E).filter(Boolean);t&&(e.iswc=t),r&&(e.codes.jasrac=r),n&&(e.codes.nextone=n),e.lyricists=Array.from(new Set(o)),e.composers=Array.from(new Set(a)),e.arrangers=Array.from(new Set(i)),e.publishers=Array.from(new Set(s)),e.sources.push(location.href),e.sources=Array.from(new Set(e.sources))})}function E(e){var t,r,n,o;return((o=(n=(r=(t=e.firstChild)==null?void 0:t.textContent)==null?void 0:r.split(`
- `)[0])==null?void 0:n.replace(/\s*\/\s*$/,""))==null?void 0:o.trim())??""}let C=!1;function Q(){O(),_("#add-relationship-dialog",async e=>{const t=h(e,"//td[.='Work']/following-sibling::td//button");await u(100),t==null||t.click()})}async function X(){O();const e=T(document.querySelector("#id-edit-work\\.name")),t=T(document.querySelector("input[name='edit-work.iswcs.0']")),r=document.querySelector("#id-edit-work\\.edit_note"),n=await L(f.Work);if(!(n!=null&&n.sources.length)){C||await W(f.Work,{name:e.value||null,iswc:t.value||null,codes:{external:!1,jasrac:null,nextone:null},lyricists:[],composers:[],arrangers:[],publishers:[],sources:[],context:{tokens:Array.from(R(parent===window?document.body:parent.document.body))}});return}if(C=!0,n.iswc&&g(t,n.iswc),n.codes.jasrac&&q("jasrac",n.codes.jasrac),n.codes.nextone&&q("nextone",n.codes.nextone),n.sources.length&&(r.value=`Filled out with Ame (MusicBrainz - Works):
- ${n.sources.join(`
- `)}
- `),n.codes.external){const o=document.querySelector("#ROpdebee_MB_Paste_Work");o==null||o.click()}for(const o of n.lyricists)await v("artist","lyrics / lyricist",o);for(const o of n.composers)await v("artist","composed / composer",o);for(const o of n.arrangers)await v("artist","arranged / arranger",o);for(const o of n.publishers)await v("label","published / publisher",o.replace("株式会社","").trim())}function O(){_("ul[id^='relationship-target']",async e=>{new MutationObserver(async r=>{const n=r[0],o=e.style.visibility;if(o==="hidden"||o===n.oldValue)return;const a=e.firstElementChild;if(a!=null&&a.innerText.includes("Click here to try again")){await u(100),a.click();return}const s=document.getElementById(e.getAttribute("aria-labelledby")).control,l=R();s.value&&l.add(s.value);for(const c of l){const m=P(c);for(const p of e.children)A(p,m)}}).observe(e,{attributes:!0,attributeOldValue:!0,attributeFilter:["style"]})})}function R(e=document.body){return new Set(Array.from(e.querySelectorAll("a[href^='/artist/'][title]")).map(t=>t.innerText.trim()))}async function v(e,t,r){document.querySelector("button.add-relationship").click();const o=await k("#add-relationship-dialog");if(!o)return;const a=o.querySelector("select.entity-type");g(a,e);const i=o.querySelector("input.relationship-type");g(i,t),h(o,`//li[contains(@class, 'option-item') and contains(., '${t}')]`).click();const s=o.querySelector(".relationship-target input");g(s,r),await u(300),o.querySelector(".relationship-target button").click(),await new Promise(c=>{const m=o.querySelector("button.negative"),p=o.querySelector("button.positive");m.addEventListener("click",()=>c()),p.addEventListener("click",()=>c())}),await u(300)}function q(e,t){e=e.toLowerCase();const r=document.querySelector("#add-work-attribute");for(let n=0;n<2;n++){for(const o of document.querySelectorAll("#work-attributes tr:not(:last-child)")){const a=o.querySelector("select"),i=a.selectedOptions[0],s=Array.from(a.options).filter(c=>c.innerText.trim().toLowerCase().startsWith(e))[0];if(i!==s&&i.value)continue;s.selected=!0;const l=T(o.querySelector("input"));l.value=t;return}r.click(),q(e,t)}}GM.addStyle(".ame__mark{background-color:#ff0e!important;outline:2px solid #ffff00ee!important}.ame__mark--inner{color:#000!important;filter:brightness(.1)}");const x=new URLSearchParams(location.search);window.addEventListener("focus",async()=>{var e,t;await u(100),!(!window.document.hasFocus()&&!((e=window.top)!=null&&e.document.hasFocus()))&&(location.host.endsWith("musicbrainz.org")?location.pathname.startsWith("/release/")&&location.pathname.endsWith("/edit-relationships")?await Q():(location.pathname.startsWith("/work/")&&location.pathname.endsWith("/edit")||location.pathname.startsWith("/dialog")&&((t=x.get("path"))!=null&&t.startsWith("/work/create")))&&await X():location.host.endsWith("minc.or.jp")?(await G(),location.pathname.startsWith("/search")?await U():location.pathname.startsWith("/music/list")?await J():location.pathname.startsWith("/saku/detail")&&await K()):location.host.endsWith("cisac.org")?(await D(),location.pathname.startsWith("/search")&&await $()):location.host.endsWith("jasrac.or.jp")&&(x.get("trxID")==="F00100"?await z():x.get("trxID")==="F20101"&&await F()))}),window.dispatchEvent(new Event("focus"))});
|