From badf76fde509776c980c03d32955474fd6eec49e Mon Sep 17 00:00:00 2001 From: SuperSaltyGamer Date: Tue, 6 Feb 2024 23:24:02 +0200 Subject: [PATCH] [musicbrainz-works] Fixes --- dist/musicbrainz-works.user.js | 8 +++---- src/musicbrainz-works/main.ts | 4 ++-- src/musicbrainz-works/modules/iswcnet.ts | 25 ++++++++++++-------- src/musicbrainz-works/modules/minc.ts | 1 + src/musicbrainz-works/modules/musicbrainz.ts | 17 ++++++++++--- 5 files changed, 36 insertions(+), 19 deletions(-) diff --git a/dist/musicbrainz-works.user.js b/dist/musicbrainz-works.user.js index fe3e885..66e8dae 100644 --- a/dist/musicbrainz-works.user.js +++ b/dist/musicbrainz-works.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @namespace ame-musicbrainz-works // @name Ame (MusicBrainz - Works) -// @version 0.1.1 +// @version 0.1.2 // @author SuperSaltyGamer // @run-at document-end // @match https://musicbrainz.org/* @@ -17,7 +17,7 @@ // @updateURL https://notabug.org/SuperSaltyGamer/ame/raw/main/dist/musicbrainz-works.user.js // ==/UserScript== -(function(l){typeof define=="function"&&define.amd?define(l):l()})(function(){"use strict";function l(e){return new Promise(t=>{setTimeout(t,e)})}function L(e){const t=document.createElement("template");return t.innerHTML=e,t.content.firstElementChild}function k(e,t){return new Promise(n=>{const o=t==null?void 0:t.waitSelector,i=(t==null?void 0:t.timeout)??3e3;if(i!==0){const s=document.querySelector(e);if(s){n(s);return}}const r=setTimeout(()=>{i!==0&&(a.disconnect(),n(null))},i),a=new MutationObserver(s=>{for(const m of s)for(const c of Array.from(m.addedNodes))if(c instanceof Element&&c.matches(o??e)){i!==0&&(a.disconnect(),clearTimeout(r)),n(o?document.querySelector(e):c);return}});a.observe(document.body,{childList:!0,subtree:!0})})}function h(e,t){new MutationObserver(async o=>{for(const i of o)for(const r of i.addedNodes){if(!(r instanceof HTMLElement))continue;const a=r.matches(e)?r:r.querySelector(e);a&&await t(a)}}).observe(document.body,{childList:!0,subtree:!0})}function d(e,t){return document.evaluate(t,e,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue}function b(e,t){const n=document.evaluate(t,e,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);return Array.from({length:n.snapshotLength},(o,i)=>n.snapshotItem(i))}var u=(e=>(e.Work="work",e))(u||{});function E(e,t){if(document.visibilityState==="visible")return t==null?GM.deleteValue(e):(console.info("setBusValue",e,t),GM.setValue(e,{value:t,timestamp:new Date().getTime()+60*1e3}))}async function v(e){if(document.visibilityState!=="visible")return null;const t=await GM.getValue(e);return!t||(await E(e,null),t.timestamp":44,">":44,"?":45,"?":45,"⁇":45,"!":46,"!":46,"‼":46},R=Object.entries(T).reduce((e,[t,n])=>(n in e||(e[n]=[]),e[n].push(t),e),{});function A(e){const t=T[e];return t?R[t]??[e]:[e]}function x(e){return e=e.replace(/[\\^$*+?.()|[\]{}]/g,"\\$&").replace(/[\s・]+/g,"").split("").map(t=>`[${A(t).join("")}]`).join("\\s{0,4}"),new RegExp(e,"gi")}function $(e){return e}function w(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}}async function O(){h("a[class^='LandingPage_languageButton__']",()=>{location.href="/search"}),h("div[class^='Search_resultsContainer__'] div[class^='AlertMessage_text__']",()=>{location.href="/"})}function H(){return p(u.Work,async e=>{if(!e.iswc)return;const t=document.querySelector("#iswc"),n=document.querySelector("button[type='submit']");if(t.value===e.iswc)return;w(t,e.iswc),n==null||n.click(),await k("[class^='Search_sectionTitle__']");const o=document.querySelector("[id='View More']");o.click(),await l(100);const i=d(document,"//button[.='Copy work codes']");i?(i.click(),e.workCodes=!0):o.after(L('
Install Bulk copy-paste work codes for better integration.
'))})}function B(){const e=document.querySelector(".logo > a");e&&(e.href=`${location.origin}/search`)}function V(){return p(u.Work,async e=>{if(!e.name)return;const t=document.querySelector("#kyokunm"),n=document.querySelector("#search-by-track-and-artist");t.value=e.name,n.click()})}function C(){for(const e of document.querySelectorAll(".saku-detail-link")){const t=document.createElement("a");t.href=`/saku/detail/?${e.getAttribute("data-href")}`,t.innerHTML=e.innerHTML,e.replaceWith(t)}return p(u.Work,async e=>{const t=document.querySelector("#kyokunm"),n=document.querySelector("#search-by-track-and-artist");!e.name||t.value===e.name||(t.value=e.name,n.click())})}function D(){return p(u.Work,async e=>{var m,c,y,g,M,q,_,P;const t=((c=(m=d(document,"//h2/text()"))==null?void 0:m.nodeValue)==null?void 0:c.trim())||null,n=((g=(y=d(document,"//h3/text()[.!='-']"))==null?void 0:y.nodeValue)==null?void 0:g.replaceAll(" ",""))||null,o=((q=(M=d(document,"//a[@href='#jasrac']/following-sibling::*/span[2][.!='']"))==null?void 0:M.innerText)==null?void 0:q.trim())||null,i=((P=(_=d(document,"//a[@href='#nextone']/following-sibling::*/span[2][.!='']"))==null?void 0:_.innerText)==null?void 0:P.trim())||null,r=new Set(b(document,"//td[contains(., '作詞')]/parent::tr/*[2]").map(f=>f.innerText.trim()).filter(Boolean)),a=new Set(b(document,"//td[contains(., '作曲')]/parent::tr/*[2]").map(f=>f.innerText.trim()).filter(Boolean)),s=new Set(b(document,"//td[contains(., '出版者')]/parent::tr/*[2]").map(f=>f.innerText.trim()).filter(Boolean));n&&(e.iswc=n),e.lyricists=Array.from(r),e.composers=Array.from(a),e.publishers=Array.from(s)})}let W=!1;function N(){h("#add-relationship-dialog",e=>{const t=d(e,"//td[.='Work']/following-sibling::td//button");setTimeout(()=>{t==null||t.click()},100)}),h("ul[role='listbox'][id^='relationship-target'] > li:first-child",e=>{if(e.innerText.includes("Click here to try again")){setTimeout(()=>{e.click()},100);return}for(const t of I())e.innerHTML=e.innerHTML.replaceAll(x(t),n=>{const o=document.createElement("mark");return o.innerText=n,o.outerHTML})})}async function z(){const e=document.querySelector("#id-edit-work\\.name"),t=document.querySelector("input[name='edit-work.iswcs.0']"),n=document.querySelector("#id-edit-work\\.edit_note"),o=await v(u.Work);if(!o){W||await E(u.Work,{name:e.value||null,iswc:t.value||null,lyricists:[],composers:[],publishers:[],sources:[],workCodes:!1});return}if(W=!0,o.workCodes){const i=document.querySelector("#ROpdebee_MB_Paste_Work");i==null||i.click()}o.iswc&&(t.value=o.iswc),o.sources.length&&(n.value=`Filled out with of Ame (MusicBrainz - Works): -${o.sources.join(` +(function(l){typeof define=="function"&&define.amd?define(l):l()})(function(){"use strict";function l(e){return new Promise(t=>{setTimeout(t,e)})}function L(e){const t=document.createElement("template");return t.innerHTML=e,t.content.firstElementChild}function b(e,t){return new Promise(n=>{const i=t==null?void 0:t.waitSelector,o=(t==null?void 0:t.timeout)??3e3;if(o!==0){const s=document.querySelector(e);if(s){n(s);return}}const r=setTimeout(()=>{o!==0&&(a.disconnect(),n(null))},o),a=new MutationObserver(s=>{for(const f of s)for(const c of Array.from(f.addedNodes))if(c instanceof Element&&c.matches(i??e)){o!==0&&(a.disconnect(),clearTimeout(r)),n(i?document.querySelector(e):c);return}});a.observe(document.body,{childList:!0,subtree:!0})})}function p(e,t){new MutationObserver(async i=>{for(const o of i)for(const r of o.addedNodes){if(!(r instanceof HTMLElement))continue;const a=r.matches(e)?r:r.querySelector(e);a&&await t(a)}}).observe(document.body,{childList:!0,subtree:!0})}function d(e,t){return document.evaluate(t,e,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue}function E(e,t){const n=document.evaluate(t,e,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);return Array.from({length:n.snapshotLength},(i,o)=>n.snapshotItem(o))}var u=(e=>(e.Work="work",e))(u||{});function S(e,t){if(document.visibilityState==="visible")return t==null?GM.deleteValue(e):(console.info("setBusValue",e,t),GM.setValue(e,{value:t,timestamp:new Date().getTime()+60*1e3}))}async function v(e){if(document.visibilityState!=="visible")return null;const t=await GM.getValue(e);return!t||(await S(e,null),t.timestamp":44,">":44,"?":45,"?":45,"⁇":45,"!":46,"!":46,"‼":46},R=Object.entries(T).reduce((e,[t,n])=>(n in e||(e[n]=[]),e[n].push(t),e),{});function A(e){const t=T[e];return t?R[t]??[e]:[e]}function x(e){return e=e.replace(/[\\^$*+?.()|[\]{}]/g,"\\$&").replace(/[\s・]+/g,"").split("").map(t=>`[${A(t).join("")}]`).join("\\s{0,4}"),new RegExp(e,"gi")}function $(e){return e}function m(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}}async function O(){p("a[class^='LandingPage_languageButton__']",()=>{location.href="/search"})}async function B(){await w(u.Work,async e=>{if(!e.iswc)return;const t=document.querySelector("#iswc"),n=document.querySelector("button[type='submit']");if(m(t,e.iswc),n==null||n.click(),await Promise.any([b("div[class^='Search_resultsContainer__'] div[class^='AlertMessage_text__']").then(()=>!1),b("[class^='Search_sectionTitle__']").then(a=>!!a)]))return;const o=document.querySelector("[id='View More']");o.click(),await l(100);const r=d(document,"//button[.='Copy work codes']");r?(r.click(),e.workCodes=!0):o.after(L('
Install Bulk copy-paste work codes for better integration.
')),e.sources.push(location.href)})}function H(){const e=document.querySelector(".logo > a");e&&(e.href=`${location.origin}/search`)}function V(){return w(u.Work,async e=>{if(!e.name)return;const t=document.querySelector("#kyokunm"),n=document.querySelector("#search-by-track-and-artist");t.value=e.name,n.click()})}function D(){for(const e of document.querySelectorAll(".saku-detail-link")){const t=document.createElement("a");t.href=`/saku/detail/?${e.getAttribute("data-href")}`,t.innerHTML=e.innerHTML,e.replaceWith(t)}return w(u.Work,async e=>{const t=document.querySelector("#kyokunm"),n=document.querySelector("#search-by-track-and-artist");!e.name||t.value===e.name||(t.value=e.name,n.click())})}function C(){return w(u.Work,async e=>{var f,c,y,g,M,q,P,_;const t=((c=(f=d(document,"//h2/text()"))==null?void 0:f.nodeValue)==null?void 0:c.trim())||null,n=((g=(y=d(document,"//h3/text()[.!='-']"))==null?void 0:y.nodeValue)==null?void 0:g.replaceAll(" ",""))||null,i=((q=(M=d(document,"//a[@href='#jasrac']/following-sibling::*/span[2][.!='']"))==null?void 0:M.innerText)==null?void 0:q.trim())||null,o=((_=(P=d(document,"//a[@href='#nextone']/following-sibling::*/span[2][.!='']"))==null?void 0:P.innerText)==null?void 0:_.trim())||null,r=new Set(E(document,"//td[contains(., '作詞')]/parent::tr/*[2]").map(h=>h.innerText.trim()).filter(Boolean)),a=new Set(E(document,"//td[contains(., '作曲')]/parent::tr/*[2]").map(h=>h.innerText.trim()).filter(Boolean)),s=new Set(E(document,"//td[contains(., '出版者')]/parent::tr/*[2]").map(h=>h.innerText.trim()).filter(Boolean));n&&(e.iswc=n),e.lyricists=Array.from(r),e.composers=Array.from(a),e.publishers=Array.from(s),e.sources.push(location.href)})}let W=!1;function N(){p("#add-relationship-dialog",e=>{const t=d(e,"//td[.='Work']/following-sibling::td//button");setTimeout(()=>{t==null||t.click()},100)}),p("ul[role='listbox'][id^='relationship-target'] > li:first-child",e=>{if(e.innerText.includes("Click here to try again")){setTimeout(()=>{e.click()},100);return}for(const t of I())e.innerHTML=e.innerHTML.replaceAll(x(t),n=>{const i=document.createElement("mark");return i.innerText=n,i.outerHTML})}),p("iframe[src^='/dialog']",e=>{const t=new ResizeObserver(n=>{e.style.height=`${n[0].contentRect.height+100}px`});e.addEventListener("load",()=>{t.observe(e.contentDocument.body)})})}async function z(){const e=document.querySelector("#id-edit-work\\.name"),t=document.querySelector("input[name='edit-work.iswcs.0']"),n=document.querySelector("#id-edit-work\\.edit_note"),i=await v(u.Work);if(!(i!=null&&i.sources.length)){W||await S(u.Work,{name:e.value||null,iswc:t.value||null,lyricists:[],composers:[],publishers:[],sources:[],workCodes:!1});return}if(W=!0,i.iswc&&m(t,i.iswc),i.sources.length&&(n.value=`Filled out with Ame (MusicBrainz - Works): +${i.sources.join(` `)} -`);for(const i of o.composers)await S("artist","composed / composer",i);for(const i of o.lyricists)await S("artist","lyrics / lyricist",i);for(const i of o.publishers)await S("label","published / publisher",i)}function I(){return new Set(Array.from(document.body.querySelectorAll("a[href^='/artist/'][title]")).map(e=>e.innerText.trim()))}async function S(e,t,n){document.querySelector("button.add-relationship").click();const i=await k("#add-relationship-dialog");if(!i)return;const r=i.querySelector("select.entity-type");w(r,e);const a=i.querySelector("input.relationship-type");w(a,t),i.querySelector("li.option-item").click();const s=i.querySelector(".relationship-target input");w(s,n),await l(300),i.querySelector(".relationship-target button").click(),await new Promise(c=>{const y=i.querySelector("button.negative"),g=i.querySelector("button.positive");y.addEventListener("click",()=>c()),g.addEventListener("click",()=>c())}),await l(300)}const j="";GM.addStyle(j);const G=new URLSearchParams(location.search);window.addEventListener("focus",async()=>{var e;await l(100),document.hasFocus()&&(location.host.endsWith("musicbrainz.org")?location.pathname.startsWith("/release/")&&location.pathname.endsWith("/edit-relationships")?await N():(location.pathname.startsWith("/work/")&&location.pathname.endsWith("/edit")||location.pathname.startsWith("/dialog")&&((e=G.get("path"))!=null&&e.startsWith("/work/create")))&&await z():location.host.endsWith("minc.or.jp")?(await B(),location.pathname.startsWith("/search")?await V():location.pathname.startsWith("/music/list")?await C():location.pathname.startsWith("/saku/detail")&&await D()):location.host.endsWith("cisac.org")&&(await O(),location.pathname.startsWith("/search")&&await H()))}),window.dispatchEvent(new Event("focus"))}); +`),i.workCodes){const o=document.querySelector("#ROpdebee_MB_Paste_Work");o==null||o.click()}for(const o of i.composers)await k("artist","composed / composer",o);for(const o of i.lyricists)await k("artist","lyrics / lyricist",o);for(const o of i.publishers)await k("label","published / publisher",o)}function I(){return new Set(Array.from(document.body.querySelectorAll("a[href^='/artist/'][title]")).map(e=>e.innerText.trim()))}async function k(e,t,n){document.querySelector("button.add-relationship").click();const o=await b("#add-relationship-dialog");if(!o)return;const r=o.querySelector("select.entity-type");m(r,e);const a=o.querySelector("input.relationship-type");m(a,t),o.querySelector("li.option-item").click();const s=o.querySelector(".relationship-target input");m(s,n),await l(300),o.querySelector(".relationship-target button").click(),await new Promise(c=>{const y=o.querySelector("button.negative"),g=o.querySelector("button.positive");y.addEventListener("click",()=>c()),g.addEventListener("click",()=>c())}),await l(300)}const j="";GM.addStyle(j);const G=new URLSearchParams(location.search);window.addEventListener("focus",async()=>{var e,t;await l(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 N():(location.pathname.startsWith("/work/")&&location.pathname.endsWith("/edit")||location.pathname.startsWith("/dialog")&&((t=G.get("path"))!=null&&t.startsWith("/work/create")))&&await z():location.host.endsWith("minc.or.jp")?(await H(),location.pathname.startsWith("/search")?await V():location.pathname.startsWith("/music/list")?await D():location.pathname.startsWith("/saku/detail")&&await C()):location.host.endsWith("cisac.org")&&(await O(),location.pathname.startsWith("/search")&&await B()))}),window.dispatchEvent(new Event("focus"))}); diff --git a/src/musicbrainz-works/main.ts b/src/musicbrainz-works/main.ts index b21b2d0..11a9ff1 100644 --- a/src/musicbrainz-works/main.ts +++ b/src/musicbrainz-works/main.ts @@ -1,7 +1,7 @@ // ==UserScript== // @namespace ame-musicbrainz-works // @name Ame (MusicBrainz - Works) -// @version 0.1.1 +// @version 0.1.2 // @author SuperSaltyGamer // @run-at document-end // @match https://musicbrainz.org/* @@ -27,7 +27,7 @@ const queryParams = new URLSearchParams(location.search); window.addEventListener("focus", async () => { await sleep(100); - if (!document.hasFocus()) return; + if (!window.document.hasFocus() && !window.top?.document.hasFocus()) return; if (location.host.endsWith("musicbrainz.org")) { if (location.pathname.startsWith("/release/") && location.pathname.endsWith("/edit-relationships")) { diff --git a/src/musicbrainz-works/modules/iswcnet.ts b/src/musicbrainz-works/modules/iswcnet.ts index a61fdbb..591ec91 100644 --- a/src/musicbrainz-works/modules/iswcnet.ts +++ b/src/musicbrainz-works/modules/iswcnet.ts @@ -8,26 +8,26 @@ export async function onIswcNetPages() { observeQuerySelector("a[class^='LandingPage_languageButton__']", () => { location.href = "/search"; }); - - // Skip to captcha on error. - observeQuerySelector("div[class^='Search_resultsContainer__'] div[class^='AlertMessage_text__']", () => { - location.href = "/"; - }); } -export function onIswcNetSearchPage() { - return updateBusValue(MessageType.Work, async (work) => { +export async function onIswcNetSearchPage() { + let captcha = false; + + await updateBusValue(MessageType.Work, async (work) => { if (!work.iswc) return; const iswcEl = document.querySelector("#iswc")!; const searchEl = document.querySelector("button[type='submit']")!; - if (iswcEl.value === work.iswc) return; - setReactInputValue(iswcEl, work.iswc); searchEl?.click(); - await waitQuerySelector("[class^='Search_sectionTitle__']"); + const success = await Promise.any([ + waitQuerySelector("div[class^='Search_resultsContainer__'] div[class^='AlertMessage_text__']").then(() => false), + waitQuerySelector("[class^='Search_sectionTitle__']").then((el) => Boolean(el)) + ]); + + if (success) return; const moreEl = document.querySelector("[id='View More']")!; moreEl.click(); @@ -41,5 +41,10 @@ export function onIswcNetSearchPage() { copyEl.click(); work.workCodes = true; } + + work.sources.push(location.href); }); + + // Skip to captcha on error. + if (captcha) location.href = "/"; } diff --git a/src/musicbrainz-works/modules/minc.ts b/src/musicbrainz-works/modules/minc.ts index 46278f2..f76c313 100644 --- a/src/musicbrainz-works/modules/minc.ts +++ b/src/musicbrainz-works/modules/minc.ts @@ -51,5 +51,6 @@ export function onMincWorkPage() { work.lyricists = Array.from(lyricists); work.composers = Array.from(composers); work.publishers = Array.from(publishers); + work.sources.push(location.href); }); } diff --git a/src/musicbrainz-works/modules/musicbrainz.ts b/src/musicbrainz-works/modules/musicbrainz.ts index c1011b5..3dde709 100644 --- a/src/musicbrainz-works/modules/musicbrainz.ts +++ b/src/musicbrainz-works/modules/musicbrainz.ts @@ -30,6 +30,16 @@ export function onMusicBrainzEditRelationshipsPage() { }); } }); + + observeQuerySelector("iframe[src^='/dialog']", (el) => { + const observer = new ResizeObserver((entries) => { + el.style.height = `${entries[0].contentRect.height + 100}px`; + }); + + el.addEventListener("load", () => { + observer.observe(el.contentDocument!.body); + }); + }); } export async function onMusicBrainzEditWorkPage() { @@ -38,7 +48,7 @@ export async function onMusicBrainzEditWorkPage() { const noteEl = markChange(document.querySelector("#id-edit-work\\.edit_note")!); const work = await getBusValue(MessageType.Work); - if (!work) { + if (!work?.sources.length) { if (!done) { await setBusValue(MessageType.Work, { name: nameEl.value || null, @@ -56,13 +66,14 @@ export async function onMusicBrainzEditWorkPage() { done = true; + if (work.iswc) setReactInputValue(iswcEl, work.iswc); + if (work.sources.length) noteEl.value = `Filled out with Ame (MusicBrainz - Works):\n${work.sources.join("\n")}\n`; + if (work.workCodes) { const pasteWorkCodesEl = document.querySelector("#ROpdebee_MB_Paste_Work"); pasteWorkCodesEl?.click(); } - if (work.iswc) iswcEl.value = work.iswc; - if (work.sources.length) noteEl.value = `Filled out with of Ame (MusicBrainz - Works):\n${work.sources.join("\n")}\n`; for (const composer of work.composers) await addRelationship("artist", "composed / composer", composer); for (const lyricist of work.lyricists) await addRelationship("artist", "lyrics / lyricist", lyricist); for (const publisher of work.publishers) await addRelationship("label", "published / publisher", publisher);