From 3f07f83735feaf35f254e0e9854b8c808dfdfe35 Mon Sep 17 00:00:00 2001 From: SuperSaltyGamer Date: Mon, 29 Jan 2024 22:59:02 +0200 Subject: [PATCH] [musicbrainz] Add ISWC to Enhanced Search --- dist/musicbrainz.user.js | 12 ++++++------ src/musicbrainz/main.ts | 2 +- src/musicbrainz/modules/search.ts | 9 +++++++++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/dist/musicbrainz.user.js b/dist/musicbrainz.user.js index a4a58ef..c7e554d 100644 --- a/dist/musicbrainz.user.js +++ b/dist/musicbrainz.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @namespace ame-musicbrainz // @name Ame (MusicBrainz) -// @version 1.7.0 +// @version 1.8.0 // @author SuperSaltyGamer // @run-at document-end // @match https://musicbrainz.org/* @@ -12,7 +12,7 @@ // @updateURL https://notabug.org/SuperSaltyGamer/ame/raw/main/dist/musicbrainz.user.js // ==/UserScript== -(function(ue){typeof define=="function"&&define.amd?define(ue):ue()})(function(){"use strict";function ue(k){const M=document.createElement("template");return M.innerHTML=k,M.content.firstElementChild}function Re(k){return k.trim().replace(/[\/\?<>\\:\*\|":]/g,"_").replace(/\.+$/,"_")}function Xe(k){const[M,i]=k.split(":").map(Number);return M*60+i}var ve=(k=>(k.Incompatible="incompatible",k.Deduced="deduced",k.Exact="exact",k))(ve||{});function Le(k){return k=k.toLowerCase().replace(/[^a-z+]/g,""),k.includes("digitalmedia")||k.includes("cd")||k.includes("disc")}function Pe(){return location.pathname.split("/")[2]}function xe(){var s;const k=Pe();let M=(s=document.querySelector(".barcode"))==null?void 0:s.innerText;M==="[none]"&&(M=void 0);const i=document.querySelector("dd.format").innerText,x=document.querySelector(".tabs a[href$='/discids']"),d=x&&x.textContent!=="Disc IDs (0)";return{id:k,title:document.querySelector("h1 a").innerText,artist:document.querySelector(".subheader bdi").innerText,barcode:M,catalogs:Array.from(document.querySelectorAll(".catalog-number")).map(c=>c.innerText).filter(c=>c!="[none]"),tocType:d?"exact":Le(i)?"deduced":"incompatible",trackCounts:Array.from(document.querySelectorAll("table.medium")).map(c=>c.querySelectorAll("td.pos").length)}}async function Me(k){if(k.tocType==="incompatible")return null;if(k.tocType==="deduced"){const M=Ue();if(M)return M}try{const M=await fetch(`https://musicbrainz.org/ws/2/release/${k.id}?fmt=json&inc=recordings+discids`).then(d=>d.json()),i=M.media.flatMap(d=>d.discs).filter(d=>d.offsets.length)[0];if(i)return[1,i.offsets.length,i.sectors].concat(i.offsets).join(" ");const x=M.media.filter(d=>Le(d.format))[0];if(x){let d="0",s=0;for(const c of x.tracks)s+=c.length/1e3*75,d+=`:${s}`;return d}}catch(M){console.error(M)}return Ue()}function Ue(){const k=[];let M=0;for(const i of document.querySelectorAll("table.medium")){k.push("0");for(const x of i.querySelectorAll("td.treleases"))M+=Xe(x.innerHTML)*75,k[k.length-1]+=`:${M}`}return k.length?k[0]:null}const Se=document.querySelector("form[action='/search']"),me=document.querySelector("#headerid-query"),ge=document.querySelector("#headerid-type"),Ke=document.querySelector("form[action='/search'] button");me.focus(),me.placeholder="Enhanced search",ge.options.add(ue('')),ge.options.add(ue('')),ge.options.add(ue('')),ge.options.add(ue('')),me.addEventListener("input",()=>{const k=Je(me.value);switch(k&&(me.value=k),Ne(me.value)){case"barcode":ge.value="barcode";break;case"catalog":ge.value="catalog";break;case"isrc":ge.value="isrc";break;case"toc":ge.value="toc";break}}),Se.addEventListener("dragover",k=>{k.preventDefault();const M=k.dataTransfer;M&&(M.dropEffect="link")}),Se.addEventListener("drop",async k=>{k.preventDefault();const M=k.dataTransfer;if(!M)return;const i=M.files.item(0);if(!(i!=null&&i.name.match(/\.log$/)))return;const x=new FileReader;x.readAsText(i),x.onload=()=>{me.value=x.result,me.dispatchEvent(new Event("input")),Ke.click()}}),Se.addEventListener("submit",k=>{const i=new FormData(Se).get("query").trim(),x=Ne(i);if(x!=="unknown")switch(k.preventDefault(),x){case"barcode":location.href=`https://musicbrainz.org/search?type=release&method=advanced&query=barcode:${encodeURIComponent(i)}`;break;case"catalog":location.href=`https://musicbrainz.org/search?type=release&method=advanced&query=catno:${encodeURIComponent(Qe(i))}`;break;case"isrc":location.href=`https://musicbrainz.org/search?type=recording&method=advanced&query=isrc:${encodeURIComponent(i)}`;break;case"toc":let d=`?toc=${i}`;location.pathname.startsWith("/release/")&&(d+=`&filter-release.query=${Pe()}`),location.href=`https://musicbrainz.org/cdtoc/attach${d}`;break}});function Ne(k){return/^(\d{8}|\d{12}|\d{13}|\d{14})$/.test(k)?"barcode":/^[a-zA-Z]{5}[0-9]{7}$/.test(k)?"isrc":k===k.toUpperCase()&&/\d/.test(k)&&/[a-zA-Z]/.test(k)&&/[ ~-]/.test(k)?"catalog":k.split(" ").filter(Number).length>=4?"toc":"unknown"}function Qe(k){return/^(.+)([1-9][0-9]*)~([0-9]+)$/.test(k)?k.split("~")[0]:k}function Je(k){const M=[[]];if(k.includes("Exact Audio Copy")||k.includes("X Lossless Decoder")){let d=0;for(const s of k.matchAll(/ *\d+:\d+.\d+ *\| *\d+:\d+.\d+ *\| *(\d+) *\| *(\d+)/g)){const c={startSector:Number(s[1]),endSector:Number(s[2])};c.startSector=2)for(let d=1;dd.startSector).concat([i[i.length-1].endSector+1]);return[1,x.length-1,x[x.length-1]+150].concat(x.slice(0,-1).map(d=>d+150)).join(" ")}const je=new Map;function Fe(k,M){return new Promise((i,x)=>{const d=je.get(k);if(d){i(d.clone());return}GM.xmlHttpRequest({url:k,method:(M==null?void 0:M.method)??"GET",headers:Object.fromEntries(new Headers(M==null?void 0:M.headers)),responseType:"blob",onload(s){if((s.status<200||s.status>299)&&s.status!==404){x(new Error(`Fetching "${k}" responded with an erroneous status code.`));return}const c=s.responseHeaders.split(`\r +(function(ue){typeof define=="function"&&define.amd?define(ue):ue()})(function(){"use strict";function ue(k){const M=document.createElement("template");return M.innerHTML=k,M.content.firstElementChild}function Re(k){return k.trim().replace(/[\/\?<>\\:\*\|":]/g,"_").replace(/\.+$/,"_")}function Xe(k){const[M,i]=k.split(":").map(Number);return M*60+i}var ve=(k=>(k.Incompatible="incompatible",k.Deduced="deduced",k.Exact="exact",k))(ve||{});function Le(k){return k=k.toLowerCase().replace(/[^a-z+]/g,""),k.includes("digitalmedia")||k.includes("cd")||k.includes("disc")}function Pe(){return location.pathname.split("/")[2]}function xe(){var s;const k=Pe();let M=(s=document.querySelector(".barcode"))==null?void 0:s.innerText;M==="[none]"&&(M=void 0);const i=document.querySelector("dd.format").innerText,x=document.querySelector(".tabs a[href$='/discids']"),d=x&&x.textContent!=="Disc IDs (0)";return{id:k,title:document.querySelector("h1 a").innerText,artist:document.querySelector(".subheader bdi").innerText,barcode:M,catalogs:Array.from(document.querySelectorAll(".catalog-number")).map(c=>c.innerText).filter(c=>c!="[none]"),tocType:d?"exact":Le(i)?"deduced":"incompatible",trackCounts:Array.from(document.querySelectorAll("table.medium")).map(c=>c.querySelectorAll("td.pos").length)}}async function Me(k){if(k.tocType==="incompatible")return null;if(k.tocType==="deduced"){const M=Ue();if(M)return M}try{const M=await fetch(`https://musicbrainz.org/ws/2/release/${k.id}?fmt=json&inc=recordings+discids`).then(d=>d.json()),i=M.media.flatMap(d=>d.discs).filter(d=>d.offsets.length)[0];if(i)return[1,i.offsets.length,i.sectors].concat(i.offsets).join(" ");const x=M.media.filter(d=>Le(d.format))[0];if(x){let d="0",s=0;for(const c of x.tracks)s+=c.length/1e3*75,d+=`:${s}`;return d}}catch(M){console.error(M)}return Ue()}function Ue(){const k=[];let M=0;for(const i of document.querySelectorAll("table.medium")){k.push("0");for(const x of i.querySelectorAll("td.treleases"))M+=Xe(x.innerHTML)*75,k[k.length-1]+=`:${M}`}return k.length?k[0]:null}const Se=document.querySelector("form[action='/search']"),ge=document.querySelector("#headerid-query"),fe=document.querySelector("#headerid-type"),Ke=document.querySelector("form[action='/search'] button");ge.focus(),ge.placeholder="Enhanced search",fe.options.add(ue('')),fe.options.add(ue('')),fe.options.add(ue('')),fe.options.add(ue('')),fe.options.add(ue('')),ge.addEventListener("input",()=>{const k=Je(ge.value);switch(k&&(ge.value=k),Ne(ge.value)){case"barcode":fe.value="barcode";break;case"catalog":fe.value="catalog";break;case"isrc":fe.value="isrc";break;case"iswc":fe.value="iswc";break;case"toc":fe.value="toc";break}}),Se.addEventListener("dragover",k=>{k.preventDefault();const M=k.dataTransfer;M&&(M.dropEffect="link")}),Se.addEventListener("drop",async k=>{k.preventDefault();const M=k.dataTransfer;if(!M)return;const i=M.files.item(0);if(!(i!=null&&i.name.match(/\.log$/)))return;const x=new FileReader;x.readAsText(i),x.onload=()=>{ge.value=x.result,ge.dispatchEvent(new Event("input")),Ke.click()}}),Se.addEventListener("submit",k=>{const i=new FormData(Se).get("query").trim(),x=Ne(i);if(x!=="unknown")switch(k.preventDefault(),x){case"barcode":location.href=`https://musicbrainz.org/search?type=release&method=advanced&query=barcode:${encodeURIComponent(i)}`;break;case"catalog":location.href=`https://musicbrainz.org/search?type=release&method=advanced&query=catno:${encodeURIComponent(Qe(i))}`;break;case"isrc":location.href=`https://musicbrainz.org/search?type=recording&method=advanced&query=isrc:${encodeURIComponent(i)}`;break;case"iswc":location.href=`https://musicbrainz.org/search?type=work&method=advanced&query=iswc:${encodeURIComponent(i)}`;break;case"toc":let d=`?toc=${i}`;location.pathname.startsWith("/release/")&&(d+=`&filter-release.query=${Pe()}`),location.href=`https://musicbrainz.org/cdtoc/attach${d}`;break}});function Ne(k){return/^(\d{8}|\d{12}|\d{13}|\d{14})$/.test(k)?"barcode":/^[a-zA-Z]{5}[0-9]{7}$/.test(k)?"isrc":/^T-\d{3}.\d{3}.\d{3}-\d$/.test(k)?"iswc":k===k.toUpperCase()&&/\d/.test(k)&&/[a-zA-Z]/.test(k)&&/[ ~-]/.test(k)?"catalog":k.split(" ").filter(Number).length>=4?"toc":"unknown"}function Qe(k){return/^(.+)([1-9][0-9]*)~([0-9]+)$/.test(k)?k.split("~")[0]:k}function Je(k){const M=[[]];if(k.includes("Exact Audio Copy")||k.includes("X Lossless Decoder")){let d=0;for(const s of k.matchAll(/ *\d+:\d+.\d+ *\| *\d+:\d+.\d+ *\| *(\d+) *\| *(\d+)/g)){const c={startSector:Number(s[1]),endSector:Number(s[2])};c.startSector=2)for(let d=1;dd.startSector).concat([i[i.length-1].endSector+1]);return[1,x.length-1,x[x.length-1]+150].concat(x.slice(0,-1).map(d=>d+150)).join(" ")}const je=new Map;function Fe(k,M){return new Promise((i,x)=>{const d=je.get(k);if(d){i(d.clone());return}GM.xmlHttpRequest({url:k,method:(M==null?void 0:M.method)??"GET",headers:Object.fromEntries(new Headers(M==null?void 0:M.headers)),responseType:"blob",onload(s){if((s.status<200||s.status>299)&&s.status!==404){x(new Error(`Fetching "${k}" responded with an erroneous status code.`));return}const c=s.responseHeaders.split(`\r `).slice(0,-1).map(u=>u.split(": ")),r=new Response(s.response,{headers:Object.fromEntries(c),status:s.status,statusText:s.statusText});Object.defineProperty(r,"url",{value:k}),je.set(k,r.clone()),i(r)},onerror(){x(new Error("Network request errored."))},ontimeout(){x(new Error("Network request timed out."))}})})}const _e=(unsafeWindow==null?void 0:unsafeWindow.wrappedJSObject)??unsafeWindow,$e=typeof cloneInto=="function"?cloneInto:k=>k,et=typeof exportFunction=="function"?exportFunction:k=>k;function tt(k){return $e(k,_e,{cloneFunctions:!0,wrapReflectors:!0})}function rt(k){return et(k,_e)}function nt(k,M){return M??(M=_e),function(...i){return k.call(M,...tt(i))}}const De={},it=nt(_e.history.pushState,_e.history);_e.history.pushState=rt(at);function at(k,M,i){it(k,M,i),He()}addEventListener("popstate",()=>{He()});function He(){for(const k of Object.values(De)){const M=k.pattern.test(location.pathname)?k.onCallbacks:k.offCallbacks;for(const i of M)i()}}function st(k){const M=new RegExp(`^/${k.replaceAll("/","\\/")}$`);let i=De[k];return i||(i={pattern:M,onCallbacks:[],offCallbacks:[]},De[k]=i,i)}function Te(k,M){const i=st(k),x=i.pattern.test(location.pathname);i.onCallbacks.push(M),x&&M()}const ot="release/[0-9a-f-]+",At="release/[0-9a-f-]+/cover-art",ct="release/[0-9a-f-]+/add-cover-art";function We(k){Te(ot,k)}function ut(k){Te(At,k)}function lt(k){Te(ct,k)}lt(()=>{const k=document.querySelector(".fileinput-button.buttons");if(!k)return;const M=xe();if(!M)return;const i=ue(`