Torrent seed ratio part 2

Set scheduled job to remove torrent when post processed and finished
seeding
This commit is contained in:
Ade
2014-08-11 20:32:37 +12:00
parent ba552bd1f8
commit e224ad1a6a
9 changed files with 130 additions and 24 deletions
+6 -6
View File
@@ -395,7 +395,7 @@
</div>
<div class="row">
<label>Seed Ratio: </label>
<input type="text" class="override-float" name="piratebay_ratio" value="${config['piratebay_ratio']}" size="10" title="Stop seeding when ratio met, 0 = unlimited">
<input type="text" class="override-float" name="piratebay_ratio" value="${config['piratebay_ratio']}" size="10" title="Stop seeding when ratio met, 0 = unlimited. Scheduled job will remove torrent when post processed and finished seeding">
</div>
</div>
</fieldset>
@@ -412,7 +412,7 @@
</div>
<div class="row">
<label>Seed Ratio: </label>
<input type="text" class="override-float" name="kat_ratio" value="${config['kat_ratio']}" size="10" title="Stop seeding when ratio met, 0 = unlimited">
<input type="text" class="override-float" name="kat_ratio" value="${config['kat_ratio']}" size="10" title="Stop seeding when ratio met, 0 = unlimited. Scheduled job will remove torrent when post processed and finished seeding">
</div>
</div>
</fieldset>
@@ -433,7 +433,7 @@
</div>
<div class="row">
<label>Seed Ratio: </label>
<input type="text" class="override-float" name="waffles_ratio" value="${config['waffles_ratio']}" size="10" title="Stop seeding when ratio met, 0 = unlimited">
<input type="text" class="override-float" name="waffles_ratio" value="${config['waffles_ratio']}" size="10" title="Stop seeding when ratio met, 0 = unlimited. Scheduled job will remove torrent when post processed and finished seeding">
</div>
</div>
</fieldset>
@@ -454,7 +454,7 @@
</div>
<div class="row">
<label>Seed Ratio: </label>
<input type="text" class="override-float" name="rutracker_ratio" value="${config['rutracker_ratio']}" size="10" title="Stop seeding when ratio met, 0 = unlimited">
<input type="text" class="override-float" name="rutracker_ratio" value="${config['rutracker_ratio']}" size="10" title="Stop seeding when ratio met, 0 = unlimited. Scheduled job will remove torrent when post processed and finished seeding">
</div>
</div>
</fieldset>
@@ -475,7 +475,7 @@
</div>
<div class="row">
<label>Seed Ratio: </label>
<input type="text" class="override-float" name="whatcd_ratio" value="${config['whatcd_ratio']}" size="10" title="Stop seeding when ratio met, 0 = unlimited">
<input type="text" class="override-float" name="whatcd_ratio" value="${config['whatcd_ratio']}" size="10" title="Stop seeding when ratio met, 0 = unlimited. Scheduled job will remove torrent when post processed and finished seeding">
</div>
</div>
</fieldset>
@@ -488,7 +488,7 @@
<div class="config">
<div class="row">
<label>Seed Ratio: </label>
<input type="text" class="override-float" name="mininova_ratio" value="${config['mininova_ratio']}" size="10" title="Stop seeding when ratio met, 0 = unlimited">
<input type="text" class="override-float" name="mininova_ratio" value="${config['mininova_ratio']}" size="10" title="Stop seeding when ratio met, 0 = unlimited. Scheduled job will remove torrent when post processed and finished seeding">
</div>
</div>
</fieldset>
+4 -2
View File
@@ -514,7 +514,6 @@ def initialize():
WHATCD_USERNAME = check_setting_str(CFG, 'What.cd', 'whatcd_username', '')
WHATCD_PASSWORD = check_setting_str(CFG, 'What.cd', 'whatcd_password', '')
WHATCD_RATIO = check_setting_str(CFG, 'What.cd', 'whatcd_ratio', '')
WHATCD_PASSWORD = check_setting_str(CFG, 'What.cd', 'whatcd_password', '')
SAB_HOST = check_setting_str(CFG, 'SABnzbd', 'sab_host', '')
SAB_USERNAME = check_setting_str(CFG, 'SABnzbd', 'sab_username', '')
@@ -1135,7 +1134,7 @@ def start():
if __INITIALIZED__:
# Start our scheduled background tasks
from headphones import updater, searcher, librarysync, postprocessor
from headphones import updater, searcher, librarysync, postprocessor, torrentfinished
SCHED.add_interval_job(updater.dbUpdate, hours=UPDATE_DB_INTERVAL)
SCHED.add_interval_job(searcher.searchforalbum, minutes=SEARCH_INTERVAL)
@@ -1147,6 +1146,9 @@ def start():
if DOWNLOAD_SCAN_INTERVAL > 0:
SCHED.add_interval_job(postprocessor.checkFolder, minutes=DOWNLOAD_SCAN_INTERVAL)
# Remove Torrent + data if Post Processed and finished Seeding
SCHED.add_interval_job(torrentfinished.checkTorrentFinished, hours=12)
SCHED.start()
started = True
+1 -1
View File
@@ -145,7 +145,7 @@ class Api(object):
return
def _getHistory(self, **kwargs):
self.data = self._dic_from_query('SELECT * from snatched order by DateAdded DESC')
self.data = self._dic_from_query('SELECT * from snatched WHERE status NOT LIKE "Seed%" order by DateAdded DESC')
return
def _getUpcoming(self, **kwargs):
+20 -3
View File
@@ -24,7 +24,7 @@ import headphones
from beets import autotag
from beets.mediafile import MediaFile, FileTypeError, UnreadableFileError
from headphones import notifiers
from headphones import notifiers, utorrent, transmission
from headphones import db, albumart, librarysync, lyrics
from headphones import logger, helpers, request, mb, music_encoder
@@ -305,7 +305,7 @@ def verify(albumid, albumpath, Kind=None, forced=False):
return
logger.warn(u'Could not identify album: %s. It may not be the intended album.' % albumpath.decode(headphones.SYS_ENCODING, 'replace'))
myDB.action('UPDATE snatched SET status = "Unprocessed" WHERE AlbumID=?', [albumid])
myDB.action('UPDATE snatched SET status = "Unprocessed" WHERE status NOT LIKE "Seed%" and AlbumID=?', [albumid])
processed = re.search(r' \(Unprocessed\)(?:\[\d+\])?', albumpath)
if not processed:
renameUnprocessedFolder(albumpath)
@@ -416,7 +416,24 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
myDB = db.DBConnection()
myDB.action('UPDATE albums SET status = "Downloaded" WHERE AlbumID=?', [albumid])
myDB.action('UPDATE snatched SET status = "Processed" WHERE AlbumID=?', [albumid])
myDB.action('UPDATE snatched SET status = "Processed" WHERE Status NOT LIKE "Seed%" and AlbumID=?', [albumid])
# Check if torrent has finished seeding
if headphones.TORRENT_DOWNLOADER == (1 or 2):
seed_snatched = myDB.action('SELECT * from snatched WHERE Status="Seed_Snatched" and AlbumID=?', [albumid]).fetchone()
if seed_snatched:
hash = seed_snatched['FolderName']
torrent_removed = False
if headphones.TORRENT_DOWNLOADER == 1:
torrent_removed = transmission.removeTorrent(hash, True)
else:
torrent_removed = utorrent.removeTorrent(hash, True)
# Torrent removed, delete the snatched record, else update Status for scheduled job to check
if torrent_removed:
myDB.action('DELETE from snatched WHERE status = "Seed_Snatched" and AlbumID=?', [albumid])
else:
myDB.action('UPDATE snatched SET status = "Seed_Processed" WHERE status = "Seed_Snatched" and AlbumID=?', [albumid])
# Update the have tracks for all created dirs:
for albumpath in albumpaths:
+13 -7
View File
@@ -569,6 +569,8 @@ def send_to_downloader(data, bestqual, album):
logger.info(u'Found best result from %s: <a href="%s">%s</a> - %s', bestqual[3], bestqual[2], bestqual[0], helpers.bytes_to_mb(bestqual[1]))
# Get rid of any dodgy chars here so we can prevent sab from renaming our downloads
kind = bestqual[4]
seed_ratio = None
torrentid = None
if kind == 'nzb':
folder_name = helpers.sab_sanitize_foldername(bestqual[0])
@@ -674,7 +676,7 @@ def send_to_downloader(data, bestqual, album):
# rutracker needs cookies to be set, pass the .torrent file instead of url
if bestqual[3] == 'rutracker.org':
file_or_url, _hash = rutracker.get_torrent(bestqual[2])
file_or_url, torrentid = rutracker.get_torrent(bestqual[2])
else:
file_or_url = bestqual[2]
@@ -708,14 +710,14 @@ def send_to_downloader(data, bestqual, album):
# rutracker needs cookies to be set, pass the .torrent file instead of url
if bestqual[3] == 'rutracker.org':
file_or_url, _hash = rutracker.get_torrent(bestqual[2])
folder_name, cacheid = utorrent.dirTorrent(_hash)
file_or_url, torrentid = rutracker.get_torrent(bestqual[2])
folder_name, cacheid = utorrent.dirTorrent(torrentid)
folder_name = os.path.basename(os.path.normpath(folder_name))
utorrent.labelTorrent(_hash)
utorrent.labelTorrent(torrentid)
else:
file_or_url = bestqual[2]
_hash = CalculateTorrentHash(file_or_url, data)
folder_name = utorrent.addTorrent(file_or_url, _hash)
torrentid = CalculateTorrentHash(file_or_url, data)
folder_name = utorrent.addTorrent(file_or_url, torrentid)
if folder_name:
logger.info('Torrent folder name: %s' % folder_name)
@@ -733,12 +735,16 @@ def send_to_downloader(data, bestqual, album):
# Set Seed Ratio
seed_ratio = getSeedRatio(bestqual[3])
if seed_ratio != None:
utorrent.setSeedRatio(_hash, seed_ratio)
utorrent.setSeedRatio(torrentid, seed_ratio)
myDB = db.DBConnection()
myDB.action('UPDATE albums SET status = "Snatched" WHERE AlbumID=?', [album['AlbumID']])
myDB.action('INSERT INTO snatched VALUES( ?, ?, ?, ?, DATETIME("NOW", "localtime"), ?, ?, ?)', [album['AlbumID'], bestqual[0], bestqual[1], bestqual[2], "Snatched", folder_name, kind])
# Store the torrent id so we can check later if it's finished seeding and can be removed
if seed_ratio != 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])
# notify
artist = album[1]
albumname = album[2]
+40
View File
@@ -0,0 +1,40 @@
# This file is part of Headphones.
#
# Headphones is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Headphones is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Headphones. If not, see <http://www.gnu.org/licenses/>.
import threading
import headphones
from headphones import db, utorrent, transmission, logger
postprocessor_lock = threading.Lock()
# Remove Torrent + data if Post Processed and finished Seeding
def checkTorrentFinished():
with postprocessor_lock:
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
if headphones.TORRENT_DOWNLOADER == 1:
torrent_removed = transmission.removeTorrent(hash, True)
else:
torrent_removed = utorrent.removeTorrent(hash, True)
if torrent_removed:
myDB.action('DELETE from snatched WHERE status = "Seed_Processed" and AlbumID=?', [albumid])
+24 -2
View File
@@ -47,10 +47,10 @@ def addTorrent(link):
if response['result'] == 'success':
if 'torrent-added' in response['arguments']:
name = response['arguments']['torrent-added']['name']
retid = response['arguments']['torrent-added']['id']
retid = response['arguments']['torrent-added']['hashString']
elif 'torrent-duplicate' in response['arguments']:
name = response['arguments']['torrent-duplicate']['name']
retid = response['arguments']['torrent-duplicate']['id']
retid = response['arguments']['torrent-duplicate']['hashString']
else:
name = link
retid = False
@@ -93,6 +93,28 @@ def setSeedRatio(torrentid, ratio):
if not response:
return False
def removeTorrent(torrentid, remove_data = False):
method = 'torrent-get'
arguments = { 'ids': torrentid, 'fields': ['isFinished', 'name']}
response = torrentAction(method, arguments)
finished = response['arguments']['torrents'][0]['isFinished']
name = response['arguments']['torrents'][0]['name']
if finished:
logger.info('%s has finished seeding, removing torrent and data' % name)
method = 'torrent-remove'
if remove_data:
arguments = {'delete-local-data': True, 'ids': torrentid}
else:
arguments = {'ids': torrentid}
response = torrentAction(method, arguments)
return True
return False
def torrentAction(method, arguments):
host = headphones.TRANSMISSION_HOST
+19
View File
@@ -132,6 +132,13 @@ class utorrentclient(object):
return settings[key]
return settings
def remove(self, hash, remove_data = False):
if remove_data:
params = [('action', 'removedata'), ('hash', hash)]
else:
params = [('action', 'remove'), ('hash', hash)]
return self._action(params)
def _action(self, params, body=None, content_type=None):
url = self.base_url + '/gui/' + '?token=' + self.token + '&' + urllib.urlencode(params)
request = urllib2.Request(url)
@@ -155,6 +162,17 @@ def labelTorrent(hash):
if label:
uTorrentClient.setprops(hash,'label',label)
def removeTorrent(hash):
uTorrentClient = utorrentclient()
status, torrentList = uTorrentClient.list()
torrents = torrentList['torrents']
for torrent in torrents:
if torrent[0].lower() == hash and torrent[21] == 'Finished':
logger.info('%s has finished seeding, removing torrent and data' % torrent[2])
uTorrentClient.remove(hash, True)
return True
return False
def setSeedRatio(hash, ratio):
uTorrentClient = utorrentclient()
uTorrentClient.setprops(hash, 'seed_override', '1')
@@ -215,6 +233,7 @@ def addTorrent(link, hash):
if torrent_folder == active_dir or not torrent_folder:
torrent_folder, cacheid = dirTorrent(hash, cacheid, return_name=True)
labelTorrent(hash)
return torrent_folder
else:
labelTorrent(hash)
+3 -3
View File
@@ -735,7 +735,7 @@ class WebInterface(object):
def history(self):
myDB = db.DBConnection()
history = myDB.select('''SELECT * from snatched order by DateAdded DESC''')
history = myDB.select('''SELECT * from snatched WHERE Status NOT LIKE "Seed%" order by DateAdded DESC''')
return serve_template(templatename="history.html", title="History", history=history)
history.exposed = True
@@ -901,13 +901,13 @@ class WebInterface(object):
if type:
if type == 'all':
logger.info(u"Clearing all history")
myDB.action('DELETE from snatched')
myDB.action('DELETE from snatched WHERE Status NOT LIKE "Seed%"')
else:
logger.info(u"Clearing history where status is %s" % type)
myDB.action('DELETE from snatched WHERE Status=?', [type])
else:
logger.info(u"Deleting '%s' from history" % title)
myDB.action('DELETE from snatched WHERE Title=? AND DateAdded=?', [title, date_added])
myDB.action('DELETE from snatched WHERE Status NOT LIKE "Seed%" AND Title=? AND DateAdded=?', [title, date_added])
raise cherrypy.HTTPRedirect("history")
clearhistory.exposed = True