Merge csv_uploader into xb_seed_status as --upload-csv mode
This commit is contained in:
@@ -306,14 +306,18 @@ Examples:
|
||||
|
||||
# CSV mode - just output a file:
|
||||
%(prog)s --id-folder ./torrents --bt-backup /path/to/BT_backup --csv-only
|
||||
|
||||
# Upload a CSV generated by someone else:
|
||||
%(prog)s --upload-csv seeds.csv --nocodb-url https://noco.example.com \\
|
||||
--table-id tblXXXXX --api-token xc-xxxx
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument('--id-folder', required=True, type=Path,
|
||||
|
||||
parser.add_argument('--id-folder', type=Path,
|
||||
help='Path to folder containing {id}.torrent files')
|
||||
parser.add_argument('--bt-backup', required=True, type=Path,
|
||||
parser.add_argument('--bt-backup', type=Path,
|
||||
help="Path to qBittorrent's BT_backup folder")
|
||||
|
||||
|
||||
# NocoDB API options
|
||||
parser.add_argument('--nocodb-url', type=str, default=None,
|
||||
help='NocoDB base URL (e.g., http://localhost:8080)')
|
||||
@@ -321,33 +325,115 @@ Examples:
|
||||
help='NocoDB table ID (starts with "tbl")')
|
||||
parser.add_argument('--api-token', type=str, default=None,
|
||||
help='NocoDB API token (xc-token)')
|
||||
# CSV fallback
|
||||
# CSV fallback
|
||||
parser.add_argument('--csv-only', action='store_true',
|
||||
help='Skip API, just output CSV')
|
||||
parser.add_argument('--output', type=Path, default=Path('seeding_update.csv'),
|
||||
help='Output CSV path (default: seeding_update.csv)')
|
||||
parser.add_argument('--upload-csv', type=Path, default=None,
|
||||
help='Upload a CSV file to NocoDB (skip torrent scanning)')
|
||||
parser.add_argument('--debug', action='store_true',
|
||||
help='Print debug info for API calls')
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validate paths
|
||||
if not args.id_folder.exists():
|
||||
print(f"Error: ID folder does not exist: {args.id_folder}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if not args.bt_backup.exists():
|
||||
print(f"Error: BT_backup folder does not exist: {args.bt_backup}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Validate args based on mode
|
||||
if args.upload_csv:
|
||||
if not args.upload_csv.exists():
|
||||
print(f"Error: CSV file not found: {args.upload_csv}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if not all([args.nocodb_url, args.table_id, args.api_token]):
|
||||
print("Error: --upload-csv requires --nocodb-url, --table-id, and --api-token", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
else:
|
||||
if not args.id_folder or not args.bt_backup:
|
||||
print("Error: --id-folder and --bt-backup are required (unless using --upload-csv)", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if not args.id_folder.exists():
|
||||
print(f"Error: ID folder does not exist: {args.id_folder}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if not args.bt_backup.exists():
|
||||
print(f"Error: BT_backup folder does not exist: {args.bt_backup}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Determine mode
|
||||
use_api = not args.csv_only
|
||||
|
||||
# --- Upload CSV mode ---
|
||||
if args.upload_csv:
|
||||
print("=" * 50)
|
||||
print("Seed Tracker — CSV Upload")
|
||||
print("=" * 50)
|
||||
|
||||
# Read CSV
|
||||
with open(args.upload_csv, 'r', newline='', encoding='utf-8') as f:
|
||||
reader = csv.DictReader(f)
|
||||
rows = list(reader)
|
||||
|
||||
print(f"Loaded {len(rows)} rows from {args.upload_csv}")
|
||||
|
||||
noco = NocoDBClient(
|
||||
args.nocodb_url, args.table_id, args.api_token,
|
||||
args.debug
|
||||
)
|
||||
|
||||
print("Testing connection...")
|
||||
try:
|
||||
noco._request("GET", params={"limit": "1"})
|
||||
print(" ✓ Connected!")
|
||||
except Exception as e:
|
||||
print(f" ✗ Connection failed: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print(f"\nUpdating records...")
|
||||
stats = {'updated': 0, 'already': 0, 'not_found': 0, 'failed': 0}
|
||||
|
||||
for i, row in enumerate(rows, 1):
|
||||
record_id = row.get('Id') or row.get('id')
|
||||
username = row.get('seeding_users') or row.get('Seeding_Users')
|
||||
|
||||
if not record_id or not username:
|
||||
continue
|
||||
|
||||
record = noco.get_record(record_id)
|
||||
|
||||
if record is None:
|
||||
print(f" ? {record_id}: not found")
|
||||
stats['not_found'] += 1
|
||||
continue
|
||||
|
||||
current = parse_multiselect(record.get(noco.SEEDING_FIELD))
|
||||
|
||||
if username in current:
|
||||
print(f" = {record_id}: already listed")
|
||||
stats['already'] += 1
|
||||
continue
|
||||
|
||||
current.add(username)
|
||||
|
||||
if noco.update_record(record["Id"], format_multiselect(current)):
|
||||
print(f" + {record_id}: added {username}")
|
||||
stats['updated'] += 1
|
||||
else:
|
||||
print(f" ! {record_id}: failed")
|
||||
stats['failed'] += 1
|
||||
|
||||
if i % 3 == 0:
|
||||
time.sleep(1)
|
||||
|
||||
print(f"\nDone!")
|
||||
print(f" Updated: {stats['updated']}")
|
||||
print(f" Already: {stats['already']}")
|
||||
print(f" Not found: {stats['not_found']}")
|
||||
print(f" Failed: {stats['failed']}")
|
||||
return
|
||||
|
||||
# Show banner
|
||||
print("=" * 50)
|
||||
print("Seed Tracker")
|
||||
print("=" * 50)
|
||||
print(f"Mode: {'NocoDB API' if use_api else 'CSV output'}")
|
||||
|
||||
|
||||
if use_api:
|
||||
if not all([args.nocodb_url, args.table_id, args.api_token]):
|
||||
print("Error: API mode requires --nocodb-url, --table-id, and --api-token", file=sys.stderr)
|
||||
|
||||
Reference in New Issue
Block a user