adds tclean
For cleaning torrent files from transmission. Needs some more work.
This commit is contained in:
Executable
+178
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
|
||||
torrents = []
|
||||
|
||||
def get_torrent_list(args):
|
||||
try:
|
||||
process = subprocess.run(['transmission-remote', f'{args.host}:{args.port}', '-l'], capture_output=True, text=True, check=True)
|
||||
return process.stdout.splitlines()
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Command failed with return code {e.returncode}")
|
||||
print(f"Error output: {e.stderr}")
|
||||
exit()
|
||||
|
||||
def parse_torrent_list(list):
|
||||
id = 0
|
||||
for line in list:
|
||||
if id == 0:
|
||||
id += 1
|
||||
continue
|
||||
data = [x.strip() for x in line.split(" ") if x]
|
||||
print(line)
|
||||
|
||||
if "Sum" in data[0]:
|
||||
continue
|
||||
|
||||
torrent = {
|
||||
"id": id,
|
||||
"size": data[2],
|
||||
"ratio": data[6],
|
||||
"name": data[8]
|
||||
}
|
||||
print(torrent)
|
||||
torrents.append(torrent)
|
||||
id += 1
|
||||
|
||||
def add_torrent_info(args):
|
||||
try:
|
||||
process = subprocess.run(['transmission-remote', f'{args.host}:{args.port}', '-t', 'all', '-i'], capture_output=True, text=True, check=True)
|
||||
torrent_info = process.stdout.splitlines()
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Command failed with return code {e.returncode}")
|
||||
print(f"Error output: {e.stderr}")
|
||||
exit()
|
||||
|
||||
id = 1 # Will be read from output.
|
||||
current_torrent = None
|
||||
for info in torrent_info:
|
||||
try:
|
||||
if "Id: " in info:
|
||||
print(info)
|
||||
id = int(info.split(": ")[1].strip())
|
||||
print(id)
|
||||
if 0 <= id-1 < len(torrents):
|
||||
current_torrent = torrents[id-1]
|
||||
else:
|
||||
current_torrent = None
|
||||
continue
|
||||
|
||||
if current_torrent is None:
|
||||
continue
|
||||
|
||||
if "Date added" in info:
|
||||
date_str = info.split(": ")[1].strip()
|
||||
current_torrent["date_added"] = datetime.strptime(date_str, "%a %b %d %H:%M:%S %Y")
|
||||
elif "Latest activity" in info:
|
||||
date_str = info.split(": ")[1].strip()
|
||||
current_torrent["latest_activity"] = datetime.strptime(date_str, "%a %b %d %H:%M:%S %Y")
|
||||
elif "Source" in info:
|
||||
current_torrent["source"] = info.split(": ")[1].strip()
|
||||
except (IndexError, ValueError, KeyError) as e:
|
||||
print(f"Error processing torrent info: {e}")
|
||||
continue
|
||||
|
||||
def calculate_deletion_score(torrent):
|
||||
"""
|
||||
Calculate a deletion score where higher scores indicate better deletion candidates.
|
||||
Factors considered:
|
||||
- Size (larger = higher score)
|
||||
- Age (older = higher score)
|
||||
- Inactivity period (longer inactive = higher score)
|
||||
- Ratio (lower = higher score, but with diminishing returns after 1.0)
|
||||
"""
|
||||
now = datetime.now()
|
||||
#print(torrent)
|
||||
# Convert size to GB for scoring (assuming size is in format like "1.5 GB" or "700 MB")
|
||||
try:
|
||||
size_str = torrent.get('size', '0 GB')
|
||||
size_num = float(size_str.split()[0])
|
||||
if 'MB' in size_str:
|
||||
size_gb = size_num / 1024
|
||||
else:
|
||||
size_gb = size_num
|
||||
except (ValueError, IndexError):
|
||||
size_gb = 0
|
||||
|
||||
# Calculate age in days
|
||||
try:
|
||||
age_days = (now - torrent.get('date_added', now)).days
|
||||
except (TypeError, AttributeError):
|
||||
age_days = 0
|
||||
|
||||
# Calculate days since last activity
|
||||
try:
|
||||
inactive_days = (now - torrent.get('latest_activity', now)).days
|
||||
except (TypeError, AttributeError):
|
||||
inactive_days = 0
|
||||
|
||||
try:
|
||||
ratio = float(torrent.get('ratio', '0'))
|
||||
except ValueError:
|
||||
ratio = 0
|
||||
|
||||
# Calculate individual scores
|
||||
size_score = size_gb * 10 # points per GB
|
||||
age_score = min(age_days / 7, 52) * 1 # 1 points per week, max 1 year
|
||||
inactive_score = min(inactive_days / 7, 12) * 8 # 8 points per week inactive, max 12 weeks
|
||||
ratio_score = 1000 * (1 - min(ratio, 1.0)) # 100 points at ratio 0, 0 points at ratio >= 1
|
||||
|
||||
# Combine scores
|
||||
total_score = size_score + age_score + inactive_score + ratio_score
|
||||
|
||||
return total_score
|
||||
|
||||
|
||||
def get_deletion_candidates(torrents, limit=10):
|
||||
"""
|
||||
Sort torrents by deletion score and return the top candidates.
|
||||
"""
|
||||
scored_torrents = [(t, calculate_deletion_score(t)) for t in torrents]
|
||||
sorted_torrents = sorted(scored_torrents, key=lambda x: x[1], reverse=True)
|
||||
|
||||
# Print results
|
||||
print("\nTop deletion candidates:")
|
||||
print("-" * 120)
|
||||
print(f"{'Score':>8} {'Size':>10} {'Ratio':>6} {'Age(d)':>7} {'Inactive(d)':>11} {'Size_pts':>9} {'Age_pts':>8} {'Inact_pts':>9} {'Ratio_pts':>9} {'Name':<30}")
|
||||
print("-" * 120)
|
||||
|
||||
for torrent, score in sorted_torrents[:limit]:
|
||||
now = datetime.now()
|
||||
age_days = (now - torrent['date_added']).days
|
||||
inactive_days = (now - torrent['latest_activity']).days
|
||||
|
||||
size_str = torrent['size']
|
||||
size_num = float(size_str.split()[0])
|
||||
if 'MB' in size_str:
|
||||
size_gb = size_num / 1024
|
||||
else:
|
||||
size_gb = size_num
|
||||
|
||||
size_score = size_gb * 10
|
||||
age_score = min(age_days / 7, 52) * 1
|
||||
inactive_score = min(inactive_days / 7, 12) * 8
|
||||
ratio = float(torrent['ratio'])
|
||||
ratio_score = 100 * (1 - min(ratio, 1.0))
|
||||
|
||||
print(f"{score:8.1f} {torrent['size']:>10} {torrent['ratio']:>6} {age_days:>7d} {inactive_days:>11d} {size_score:>9.1f} {age_score:>8.1f} {inactive_score:>9.1f} {ratio_score:>9.1f} {torrent['name'][:30]}")
|
||||
|
||||
return [t[0] for t in sorted_torrents]
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--host', default='localhost', help='Transmission host')
|
||||
parser.add_argument('--port', default='9091', help='Transmission port')
|
||||
parser.add_argument('--num', default='10', help='Amount of candidates to show')
|
||||
args = parser.parse_args()
|
||||
|
||||
torrent_list = get_torrent_list(args)
|
||||
parse_torrent_list(torrent_list)
|
||||
add_torrent_info(args)
|
||||
#print(torrents)
|
||||
candidates = get_deletion_candidates(torrents, int(args.num))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user