Skip to content

Instantly share code, notes, and snippets.

@OpenGG
Last active April 16, 2023 17:59
Show Gist options
  • Save OpenGG/47d142f1d04b921822e60972fe3f7423 to your computer and use it in GitHub Desktop.
Save OpenGG/47d142f1d04b921822e60972fe3f7423 to your computer and use it in GitHub Desktop.
qbittorrent bulkEditTracker
// See more on https://github.com/qbittorrent/qBittorrent/issues/11868
/**
* The old tracker URL, which could be a string or regex.
*/
const OLD_TRACKER = ''
/**
* The new tracker URL.
*/
const NEW_TRACKER = ''
/**
* The API endpoints for the torrent info and tracker edit requests.
*/
const Api = {
torrentsInfo: '/api/v2/torrents/info',
editTracker: '/api/v2/torrents/editTracker',
}
/**
* Gets information about all available torrents.
*
* @returns {Promise} A promise that resolves to the JSON response from the server.
*/
const getTorrentsInfo = async () => {
const res = await fetch(Api.torrentsInfo)
if (res.status !== 200) {
const text = await res.text()
console.error(`Request error with status: ${res.status}`, text)
throw new Error(`Request error with status: ${res.status}`)
}
const body = await res.json()
return body
}
/**
* Edits the tracker URL of a given torrent.
*
* @param {string} torrentHash - The hash of the torrent to be edited.
* @param {string} oldTracker - The old tracker URL, which could be a string or regex.
* @param {string} newTracker - The new tracker URL.
* @returns {Promise} A promise that resolves to the text response from the server.
*/
const editTracker = async (torrentHash, oldTracker, newTracker) => {
const res = await fetch(Api.editTracker, {
body: new URLSearchParams({
hash: torrentHash,
origUrl: oldTracker,
newUrl: newTracker,
}),
method: 'POST'
})
const text = await res.text()
if (res.status !== 200) {
console.error(`Request error with status: ${res.status}`, text)
throw new Error(`Request error with status: ${res.status}`)
}
return text
}
/**
* Edits the tracker URL of all torrents matching the specified old tracker URL.
*
* @param {string|RegExp} oldTracker - The old tracker URL, which could be a string or regex.
* @param {string} newTracker - The new tracker URL.
* @returns {Promise} A promise that resolves when all the tracker edits are complete.
*/
const bulkEditTracker = async (oldTracker, newTracker) => {
const torrents = await getTorrentsInfo()
console.debug('All torrents', torrents)
const isRegExp = Object.prototype.toString.call(oldTracker) === '[object RegExp]'
const filterFn = isRegExp ?
({ tracker }) => oldTracker.test(tracker) :
({ tracker }) => `${oldTracker}` === tracker
const targets = torrents.filter(filterFn)
console.debug('Target torrents', targets)
const proceed = confirm(`Confirm to update tracker of ${targets.length} torrents?`)
if (!proceed) {
return
}
for (const torrent of targets) {
const r = await editTracker(torrent.hash, torrent.tracker, newTracker)
console.debug('Edit result', torrent.hash, torrent.tracker, newTracker, r)
}
}
bulkEditTracker(OLD_TRACKER, NEW_TRACKER)
.then(() => {
console.log('Finish')
}, err => {
console.error(err)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment