Skip to content

Instantly share code, notes, and snippets.

@Roardom
Created December 7, 2021 15:55
Show Gist options
  • Save Roardom/d3b188a3e4be7d9da4ce9a2239878605 to your computer and use it in GitHub Desktop.
Save Roardom/d3b188a3e4be7d9da4ce9a2239878605 to your computer and use it in GitHub Desktop.
Replace paths easily in qBittorrent .fastresume (useful when switching from windows to linux)
import os
import re
# Insert the path where you keep your fast resume files here.
# Make a backup first!!!
torrentsDir = r'/torrents/'
# Insert paths to be replaced here. Dictionary key is current path. Dictionary value is new path
# If left empty, the script will only detect paths
fastresumePaths = {}
if not fastresumePaths:
print('Finding paths...\n')
detectedPaths = []
# Loop through torrents directory
for file in os.listdir(torrentsDir):
if file.endswith('.fastresume'):
with open(torrentsDir + file, 'rb') as fastresumeFile:
filedata = fastresumeFile.read()
query = re.search(b'save_path(\d+):', filedata)
if query is None:
print(f'Could not find path in {file}')
else:
pathLen = int(query.group(1))
path = filedata[query.end():query.end() + pathLen]
# check if user entered paths to change or not
if fastresumePaths:
if path in fastresumePaths:
newPath = fastresumePaths[path]
filedata = filedata.replace(
bytes(str(pathLen), 'utf-8') + b':' + path,
bytes(str(len(newPath)), 'utf-8') + b':' + newPath
)
print(f"Replaced {path} with {newPath}")
with open(torrentsDir + file, 'wb') as fastresumeFile:
fastresumeFile.write(filedata)
else:
if path not in detectedPaths:
detectedPaths.append(path)
if fastresumePaths is None or not fastresumePaths:
if not detectedPaths:
print('No paths were found')
else:
print('The following paths were found\n')
for path in detectedPaths:
print(path)
print('\nCopy the following code into the "fastresumePaths" variable to replace paths.\n')
maxPathLength = len(max(detectedPaths, key=len)) + 4
print(f"# {'Original Path'.ljust(maxPathLength)} New Path")
print(f"# {'-'*(maxPathLength)} {'-'*(maxPathLength)}\n")
print('fastresumePaths = {')
for path in detectedPaths:
print(f" {str(path).ljust(maxPathLength)}: {str(path).ljust(maxPathLength)},")
print('}\n')
@mpeter50
Copy link

Also very useful when qbittorrent decides to ignore that I moved the torrent! Thanks for your tool!

A little note: in my experience both the keys and the values of the fastresumePaths dict need to be a "byte literal", like this: b"D:\\my\\path".
This is crucial when your path contains non-english characters (you can get a copy of the value you need when running the script with a debugger in PyCharm, but probably print()ing it could also work), but also python complained when the dict value was not a byte literal, because it didnt know how to concat it.. just put the b before the string and now qbittorrent finally finds the torrents where they actually are.

@escape0707
Copy link

escape0707 commented Nov 14, 2024

I just want to mention that, there is another project called qbt_migrate which is also available through PyPI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment