1
0
Files
scripts/bin/tclean
T
mark b2277e54f6 adds tclean
For cleaning torrent files from transmission. Needs some more work.
2024-12-18 19:53:24 +01:00

179 lines
6.1 KiB
Python
Executable File

#!/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()