Skip to content

Instantly share code, notes, and snippets.

@Klaster1
Last active February 27, 2022 07:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Klaster1/b26153ad86d3e62ec6069c9bc06ddc0e to your computer and use it in GitHub Desktop.
Save Klaster1/b26153ad86d3e62ec6069c9bc06ddc0e to your computer and use it in GitHub Desktop.
Discogs paste release
// ==UserScript==
// @name Bandcamp (paste release data)
// @version 1.2
// @author Klaster_1
// @match https://www.discogs.com/release/edit/*
// @match https://www.discogs.com/release/add
// @grant unsafeWindow
// @icon https://www.discogs.com/favicon.ico
// @downloadURL https://gist.github.com/Klaster1/b26153ad86d3e62ec6069c9bc06ddc0e/raw/discogs-paste-release.user.js
// @updateURL https://gist.github.com/Klaster1/b26153ad86d3e62ec6069c9bc06ddc0e/raw/discogs-paste-release.user.js
// ==/UserScript==
// Known issues: the "Paste release" button appears only after reloading the release edit page. Save the draft and hit F5.
const script = () => {
let win = window
const prompForData = () => JSON.parse(prompt())
const getAddTrackButton = () => Array.from(document.querySelectorAll('button')).filter(b=>b.textContent === 'Add Tracks').pop()
const getTrackRowByIndex = (index) => win.document.querySelectorAll(`table.subform_tracklist tbody`)[index]
const getPositionInput = (row) => row.querySelector('[data-ref-overview="track_pos"] input')
const getTitleInput = (row) => row.querySelector('[data-ref-overview="track_title"] input')
const getDurationInput = (row) => row.querySelector('[data-ref-overview="track_duration"] input')
const getAddArtistButton = (row) => row.querySelector('[data-ref-overview="track_artist"] button')
const getAddArtistInputByIndex = (row, index) => row.querySelectorAll('[data-ref-overview="track_artist"] input[placeholder="Name"]')[index]
const wait = (duration) => new Promise(res => setTimeout(() => res(), duration))
const findInstance = (el, fn) => {
let owner = el?._reactInternalComponent?._currentElement?._owner
while (owner) {
if (fn(owner._instance)) return owner._instance
owner = owner._currentElement._owner
}
}
const setValue = async (input, value) => {
if (value === undefined || input === undefined) {
console.warn('no value or input', input, value)
return Promise.resolve(true)
}
const instance = findInstance(input, instance => {
return instance.state
})
if (!instance) return Promise.resolve(true)
input.focus()
await wait(100)
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
win.HTMLInputElement.prototype,
"value"
).set
const event = new Event('change', {
bubbles: true,
cancelable: true
});
nativeInputValueSetter.call(input, value.toString())
input.dispatchEvent(event)
instance?.handleChange(event)
await wait(100)
try {
if (instance?.state && 'value' in instance.state) instance.setState(state => ({value: value.toString()}))
if (instance?.state && 'data' in instance.state) instance.setState(state => ({
data: state.data.setIn(['value'], value).setIn(['changed'], true)
}))
} catch (e) {
win.console.log(e)
}
input.blur()
await wait(100)
}
const fillInData = async (data) => {
for (const [index, track] of data.entries()) {
let row = getTrackRowByIndex(index)
if (!row) {
getAddTrackButton().click()
await wait(100)
}
row = getTrackRowByIndex(index)
if (!row) {
throw new Error(`Row for index not found: ${index}`)
}
for (const [index, artist] of track.artists.entries()) {
if (!getAddArtistInputByIndex(row, index)) getAddArtistButton(row).click()
await wait(300)
await setValue(getAddArtistInputByIndex(row, index), artist)
}
await setValue(getPositionInput(row), track.number)
await setValue(getTitleInput(row), track.title)
await setValue(getDurationInput(row), track.time)
}
}
const addButton = () => {
const button = document.createElement('button')
Object.assign(button.style, {
position: 'fixed',
bottom: '20px',
right: '20px'
})
button.classList.add('button', 'button-small')
button.textContent = 'Paste Bandcamp release'
button.onclick = () => fillInData(prompForData())
document.body.appendChild(button)
}
addButton()
}
const el = document.createElement('script')
el.type = 'text/javascript';
el.innerHTML = `(${script.toString()})()`
setTimeout(() => document.body.appendChild(el))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment