mirror of
https://github.com/rembo10/headphones.git
synced 2026-04-11 23:49:27 +01:00
Qbittorrent
- Postprocessing get folder from hash - Postprocessing allow for single file - Rutracker fix up
This commit is contained in:
@@ -306,9 +306,10 @@ def initialize_scheduler():
|
||||
minutes=minutes)
|
||||
|
||||
# Remove Torrent + data if Post Processed and finished Seeding
|
||||
minutes = CONFIG.TORRENT_REMOVAL_INTERVAL
|
||||
schedule_job(torrentfinished.checkTorrentFinished, 'Torrent removal check', hours=0,
|
||||
minutes=minutes)
|
||||
if headphones.CONFIG.TORRENT_DOWNLOADER != 0:
|
||||
minutes = CONFIG.TORRENT_REMOVAL_INTERVAL
|
||||
schedule_job(torrentfinished.checkTorrentFinished, 'Torrent removal check', hours=0,
|
||||
minutes=minutes)
|
||||
|
||||
# Start scheduler
|
||||
if start_jobs and len(SCHED.get_jobs()):
|
||||
@@ -376,7 +377,7 @@ def dbcheck():
|
||||
c.execute(
|
||||
'CREATE TABLE IF NOT EXISTS alltracks (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, AlbumID TEXT, TrackTitle TEXT, TrackDuration, TrackID TEXT, TrackNumber INTEGER, Location TEXT, BitRate INTEGER, CleanName TEXT, Format TEXT, ReleaseID TEXT)')
|
||||
c.execute(
|
||||
'CREATE TABLE IF NOT EXISTS snatched (AlbumID TEXT, Title TEXT, Size INTEGER, URL TEXT, DateAdded TEXT, Status TEXT, FolderName TEXT, Kind TEXT)')
|
||||
'CREATE TABLE IF NOT EXISTS snatched (AlbumID TEXT, Title TEXT, Size INTEGER, URL TEXT, DateAdded TEXT, Status TEXT, FolderName TEXT, Kind TEXT, TorrentHash TEXT)')
|
||||
# Matched is a temporary value used to see if there was a match found in
|
||||
# alltracks
|
||||
c.execute(
|
||||
@@ -613,6 +614,12 @@ def dbcheck():
|
||||
except sqlite3.OperationalError:
|
||||
c.execute('ALTER TABLE artists ADD COLUMN MetaCritic TEXT DEFAULT NULL')
|
||||
|
||||
try:
|
||||
c.execute('SELECT TorrentHash from snatched')
|
||||
except sqlite3.OperationalError:
|
||||
c.execute('ALTER TABLE snatched ADD COLUMN TorrentHash TEXT')
|
||||
c.execute('UPDATE snatched SET TorrentHash = FolderName WHERE Status LIKE "Seed_%"')
|
||||
|
||||
conn.commit()
|
||||
c.close()
|
||||
|
||||
|
||||
@@ -623,7 +623,7 @@ def get_downloaded_track_list(albumpath):
|
||||
return downloaded_track_list
|
||||
|
||||
|
||||
def preserve_torrent_directory(albumpath, forced=False):
|
||||
def preserve_torrent_directory(albumpath, forced=False, single=False):
|
||||
"""
|
||||
Copy torrent directory to temp headphones_ directory to keep files for seeding.
|
||||
"""
|
||||
@@ -639,7 +639,11 @@ def preserve_torrent_directory(albumpath, forced=False):
|
||||
headphones.SYS_ENCODING, 'replace'))
|
||||
|
||||
try:
|
||||
prefix = "headphones_" + os.path.basename(os.path.normpath(albumpath)) + "_"
|
||||
file_name = os.path.basename(os.path.normpath(albumpath))
|
||||
if not single:
|
||||
prefix = "headphones_" + file_name + "_"
|
||||
else:
|
||||
prefix = "headphones_" + os.path.splitext(file_name)[0] + "_"
|
||||
new_folder = tempfile.mkdtemp(prefix=prefix, dir=tempdir)
|
||||
except Exception as e:
|
||||
logger.error("Cannot create temp directory: " + tempdir.decode(
|
||||
@@ -665,7 +669,11 @@ def preserve_torrent_directory(albumpath, forced=False):
|
||||
try:
|
||||
subdir = os.path.join(new_folder, "headphones")
|
||||
logger.info("Copying files to " + subdir.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
shutil.copytree(albumpath, subdir)
|
||||
if not single:
|
||||
shutil.copytree(albumpath, subdir)
|
||||
else:
|
||||
os.makedirs(subdir)
|
||||
shutil.copy(albumpath, subdir)
|
||||
# Update the album path with the new location
|
||||
return subdir
|
||||
except Exception as e:
|
||||
|
||||
@@ -43,6 +43,8 @@ def checkFolder():
|
||||
|
||||
for album in snatched:
|
||||
if album['FolderName']:
|
||||
folder_name = album['FolderName']
|
||||
single = False
|
||||
if album['Kind'] == 'nzb':
|
||||
download_dir = headphones.CONFIG.DOWNLOAD_DIR
|
||||
else:
|
||||
@@ -51,21 +53,29 @@ def checkFolder():
|
||||
else:
|
||||
download_dir = headphones.CONFIG.DOWNLOAD_TORRENT_DIR
|
||||
|
||||
album_path = os.path.join(download_dir, album['FolderName']).encode(
|
||||
headphones.SYS_ENCODING, 'replace')
|
||||
logger.debug("Checking if %s exists" % album_path)
|
||||
# Qbittorrent - get folder from torrent hash
|
||||
if album['TorrentHash']:
|
||||
if headphones.CONFIG.TORRENT_DOWNLOADER == 4:
|
||||
folder_name, single = qbittorrent.getFolder(album['TorrentHash'])
|
||||
if not folder_name:
|
||||
logger.debug("Could not get folder name from torrent hash for " + album['Title'])
|
||||
|
||||
if os.path.exists(album_path):
|
||||
logger.info('Found "' + album['FolderName'] + '" in ' + album[
|
||||
'Kind'] + ' download folder. Verifying....')
|
||||
verify(album['AlbumID'], album_path, album['Kind'])
|
||||
if folder_name:
|
||||
album_path = os.path.join(download_dir, folder_name).encode(
|
||||
headphones.SYS_ENCODING, 'replace')
|
||||
logger.debug("Checking if %s exists" % album_path)
|
||||
|
||||
if os.path.exists(album_path):
|
||||
logger.info('Found "' + folder_name + '" in ' + album[
|
||||
'Kind'] + ' download folder. Verifying....')
|
||||
verify(album['AlbumID'], album_path, album['Kind'],single=single)
|
||||
else:
|
||||
logger.info("No folder name found for " + album['Title'])
|
||||
|
||||
logger.debug("Checking download folder finished.")
|
||||
|
||||
|
||||
def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=False):
|
||||
def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=False, single=False):
|
||||
myDB = db.DBConnection()
|
||||
release = myDB.action('SELECT * from albums WHERE AlbumID=?', [albumid]).fetchone()
|
||||
tracks = myDB.select('SELECT * from tracks WHERE AlbumID=?', [albumid])
|
||||
@@ -206,6 +216,10 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
'replace') + " isn't complete yet. Will try again on the next run")
|
||||
return
|
||||
|
||||
# Force single file through
|
||||
if single and not downloaded_track_list:
|
||||
downloaded_track_list.append(albumpath)
|
||||
|
||||
# Check to see if we're preserving the torrent dir
|
||||
if (headphones.CONFIG.KEEP_TORRENT_FILES and Kind == "torrent") or headphones.CONFIG.KEEP_ORIGINAL_FOLDER:
|
||||
keep_original_folder = True
|
||||
@@ -263,7 +277,7 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
|
||||
if metaartist == dbartist and metaalbum == dbalbum:
|
||||
doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, Kind,
|
||||
keep_original_folder, forced)
|
||||
keep_original_folder, forced, single)
|
||||
return
|
||||
|
||||
# test #2: filenames
|
||||
@@ -282,7 +296,7 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
|
||||
if dbtrack in filetrack:
|
||||
doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, Kind,
|
||||
keep_original_folder, forced)
|
||||
keep_original_folder, forced, single)
|
||||
return
|
||||
|
||||
# test #3: number of songs and duration
|
||||
@@ -315,7 +329,7 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
delta = abs(downloaded_track_duration - db_track_duration)
|
||||
if delta < 240:
|
||||
doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, Kind,
|
||||
keep_original_folder, forced)
|
||||
keep_original_folder, forced, single)
|
||||
return
|
||||
|
||||
logger.warn(u'Could not identify album: %s. It may not be the intended album.',
|
||||
@@ -337,13 +351,13 @@ def markAsUnprocessed(albumid, albumpath, keep_original_folder=False):
|
||||
|
||||
|
||||
def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, Kind=None,
|
||||
keep_original_folder=False, forced=False):
|
||||
keep_original_folder=False, forced=False, single=False):
|
||||
logger.info('Starting post-processing for: %s - %s' % (release['ArtistName'], release['AlbumTitle']))
|
||||
new_folder = None
|
||||
|
||||
# Preserve the torrent dir
|
||||
if keep_original_folder:
|
||||
temp_path = helpers.preserve_torrent_directory(albumpath, forced)
|
||||
if keep_original_folder or single:
|
||||
temp_path = helpers.preserve_torrent_directory(albumpath, forced, single)
|
||||
if not temp_path:
|
||||
markAsUnprocessed(albumid, albumpath, keep_original_folder)
|
||||
return
|
||||
@@ -467,7 +481,7 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
|
||||
'SELECT * from snatched WHERE Status="Seed_Snatched" and AlbumID=?',
|
||||
[albumid]).fetchone()
|
||||
if seed_snatched:
|
||||
hash = seed_snatched['FolderName']
|
||||
hash = seed_snatched['TorrentHash']
|
||||
torrent_removed = False
|
||||
logger.info(u'%s - %s. Checking if torrent has finished seeding and can be removed' % (
|
||||
release['ArtistName'], release['AlbumTitle']))
|
||||
|
||||
@@ -21,6 +21,7 @@ import time
|
||||
import mimetypes
|
||||
import random
|
||||
import string
|
||||
import os
|
||||
|
||||
import headphones
|
||||
|
||||
@@ -197,25 +198,47 @@ def addFile(data):
|
||||
return qbclient._command('command/upload', filelist=files)
|
||||
|
||||
|
||||
def getFolder(hash):
|
||||
logger.debug('getFolder(%s)' % hash)
|
||||
def getName(hash):
|
||||
logger.debug('getName(%s)' % hash)
|
||||
|
||||
qbclient = qbittorrentclient()
|
||||
|
||||
tries = 1
|
||||
while tries <= 10:
|
||||
status, torrentList = qbclient._get_list()
|
||||
for torrent in torrentList:
|
||||
if torrent['hash'].upper() == hash.upper():
|
||||
if torrent['state'] == 'metaDL':
|
||||
tries += 1
|
||||
time.sleep(6)
|
||||
else:
|
||||
return torrent['name']
|
||||
while tries <= 5:
|
||||
status, torrentlist = qbclient._get_list()
|
||||
for torrent in torrentlist:
|
||||
if torrent['hash'].lower() == hash.lower():
|
||||
return torrent['name']
|
||||
tries += 1
|
||||
time.sleep(1)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def getFolder(hash):
|
||||
logger.debug('getFolder(%s)' % hash)
|
||||
|
||||
torrent_folder = None
|
||||
single_file = False
|
||||
|
||||
qbclient = qbittorrentclient()
|
||||
|
||||
try:
|
||||
status, torrent_files = qbclient.getfiles(hash.lower())
|
||||
if torrent_files:
|
||||
if len(torrent_files) == 1:
|
||||
torrent_folder = torrent_files[0]['name']
|
||||
single_file = True
|
||||
else:
|
||||
torrent_folder = os.path.split(torrent_files[0]['name'])[0]
|
||||
single_file = False
|
||||
except:
|
||||
torrent_folder = None
|
||||
single_file = False
|
||||
|
||||
return torrent_folder, single_file
|
||||
|
||||
|
||||
_BOUNDARY_CHARS = string.digits + string.ascii_letters
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ from urlparse import urlparse
|
||||
import re
|
||||
|
||||
import requests as requests
|
||||
#from requests.auth import HTTPDigestAuth
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
import headphones
|
||||
@@ -216,3 +217,34 @@ class Rutracker(object):
|
||||
self.session.post(url, params={'action': 'add-file'}, files=files)
|
||||
except Exception as e:
|
||||
logger.exception('Error adding file to utorrent %s', e)
|
||||
|
||||
|
||||
# TODO get this working in qbittorrent.py
|
||||
def qbittorrent_add_file(self, data):
|
||||
host = headphones.CONFIG.QBITTORRENT_HOST
|
||||
if not host.startswith('http'):
|
||||
host = 'http://' + host
|
||||
if host.endswith('/'):
|
||||
host = host[:-1]
|
||||
if host.endswith('/gui'):
|
||||
host = host[:-4]
|
||||
base_url = host
|
||||
|
||||
#self.session.auth = HTTPDigestAuth(headphones.CONFIG.QBITTORRENT_USERNAME, headphones.CONFIG.QBITTORRENT_PASSWORD)
|
||||
|
||||
url = base_url + '/login'
|
||||
r = self.session.post(url, data={'username': headphones.CONFIG.QBITTORRENT_USERNAME,
|
||||
'password': headphones.CONFIG.QBITTORRENT_PASSWORD})
|
||||
|
||||
url = base_url + '/command/upload'
|
||||
|
||||
args = {'savepath': headphones.CONFIG.DOWNLOAD_TORRENT_DIR}
|
||||
if headphones.CONFIG.QBITTORRENT_LABEL:
|
||||
args['category'] = headphones.CONFIG.QBITTORRENT_LABEL
|
||||
|
||||
torrent_files = {'torrents': data}
|
||||
|
||||
try:
|
||||
self.session.post(url, data=args, files=torrent_files)
|
||||
except Exception as e:
|
||||
logger.exception('Error adding file to qbittorrent %s', e)
|
||||
|
||||
@@ -1018,36 +1018,37 @@ def send_to_downloader(data, bestqual, album):
|
||||
|
||||
# Add torrent
|
||||
if bestqual[3] == 'rutracker.org':
|
||||
qbittorrent.addFile(data)
|
||||
ruobj.qbittorrent_add_file(data)
|
||||
else:
|
||||
qbittorrent.addTorrent(bestqual[2])
|
||||
|
||||
# Get hash
|
||||
torrentid = calculate_torrent_hash(bestqual[2], data)
|
||||
torrentid = torrentid.lower()
|
||||
if not torrentid:
|
||||
logger.error('Torrent id could not be determined')
|
||||
return
|
||||
|
||||
# Get folder
|
||||
folder_name = qbittorrent.getFolder(torrentid)
|
||||
# Get name
|
||||
folder_name = qbittorrent.getName(torrentid)
|
||||
if folder_name:
|
||||
logger.info('Torrent folder name: %s' % folder_name)
|
||||
logger.info('Torrent name: %s' % folder_name)
|
||||
else:
|
||||
logger.error('Torrent folder name could not be determined')
|
||||
logger.error('Torrent name could not be determined')
|
||||
return
|
||||
|
||||
myDB = db.DBConnection()
|
||||
myDB.action('UPDATE albums SET status = "Snatched" WHERE AlbumID=?', [album['AlbumID']])
|
||||
myDB.action('INSERT INTO snatched VALUES( ?, ?, ?, ?, DATETIME("NOW", "localtime"), ?, ?, ?)',
|
||||
myDB.action('INSERT INTO snatched VALUES( ?, ?, ?, ?, DATETIME("NOW", "localtime"), ?, ?, ?, ?)',
|
||||
[album['AlbumID'], bestqual[0], bestqual[1], bestqual[2], "Snatched", folder_name,
|
||||
kind])
|
||||
kind, torrentid])
|
||||
|
||||
# Store the torrent id so we can check later if it's finished seeding and can be removed
|
||||
if seed_ratio is not None and seed_ratio != 0 and torrentid:
|
||||
myDB.action(
|
||||
'INSERT INTO snatched VALUES( ?, ?, ?, ?, DATETIME("NOW", "localtime"), ?, ?, ?)',
|
||||
[album['AlbumID'], bestqual[0], bestqual[1], bestqual[2], "Seed_Snatched", torrentid,
|
||||
kind])
|
||||
'INSERT INTO snatched VALUES( ?, ?, ?, ?, DATETIME("NOW", "localtime"), ?, ?, ?, ?)',
|
||||
[album['AlbumID'], bestqual[0], bestqual[1], bestqual[2], "Seed_Snatched", folder_name,
|
||||
kind, torrentid])
|
||||
|
||||
# notify
|
||||
artist = album[1]
|
||||
|
||||
@@ -18,8 +18,6 @@ import threading
|
||||
from headphones import db, utorrent, transmission, deluge, qbittorrent, logger
|
||||
import headphones
|
||||
|
||||
postprocessor_lock = threading.Lock()
|
||||
|
||||
|
||||
def checkTorrentFinished():
|
||||
"""
|
||||
@@ -28,26 +26,25 @@ def checkTorrentFinished():
|
||||
|
||||
logger.info("Checking if any torrents have finished seeding and can be removed")
|
||||
|
||||
with postprocessor_lock:
|
||||
myDB = db.DBConnection()
|
||||
results = myDB.select('SELECT * from snatched WHERE Status="Seed_Processed"')
|
||||
myDB = db.DBConnection()
|
||||
results = myDB.select('SELECT * from snatched WHERE Status="Seed_Processed"')
|
||||
|
||||
for album in results:
|
||||
hash = album['FolderName']
|
||||
albumid = album['AlbumID']
|
||||
torrent_removed = False
|
||||
for album in results:
|
||||
hash = album['TorrentHash']
|
||||
albumid = album['AlbumID']
|
||||
torrent_removed = False
|
||||
|
||||
if headphones.CONFIG.TORRENT_DOWNLOADER == 1:
|
||||
torrent_removed = transmission.removeTorrent(hash, True)
|
||||
elif headphones.CONFIG.TORRENT_DOWNLOADER == 2:
|
||||
torrent_removed = utorrent.removeTorrent(hash, True)
|
||||
elif headphones.CONFIG.TORRENT_DOWNLOADER == 3:
|
||||
torrent_removed = deluge.removeTorrent(hash, True)
|
||||
else:
|
||||
torrent_removed = qbittorrent.removeTorrent(hash, True)
|
||||
if headphones.CONFIG.TORRENT_DOWNLOADER == 1:
|
||||
torrent_removed = transmission.removeTorrent(hash, True)
|
||||
elif headphones.CONFIG.TORRENT_DOWNLOADER == 2:
|
||||
torrent_removed = utorrent.removeTorrent(hash, True)
|
||||
elif headphones.CONFIG.TORRENT_DOWNLOADER == 3:
|
||||
torrent_removed = deluge.removeTorrent(hash, True)
|
||||
else:
|
||||
torrent_removed = qbittorrent.removeTorrent(hash, True)
|
||||
|
||||
if torrent_removed:
|
||||
myDB.action('DELETE from snatched WHERE status = "Seed_Processed" and AlbumID=?',
|
||||
[albumid])
|
||||
if torrent_removed:
|
||||
myDB.action('DELETE from snatched WHERE status = "Seed_Processed" and AlbumID=?',
|
||||
[albumid])
|
||||
|
||||
logger.info("Checking finished torrents completed")
|
||||
|
||||
Reference in New Issue
Block a user