Fix seeding field overwrite bug and hardcode NocoDB field names
NocoDB returns records keyed by field titles, but the code was looking up values by field IDs, always getting None. This caused every update to overwrite existing seeders instead of appending. Hardcode "Id" and "Seeding Users" field names as class constants and remove the --id-field and --seeding-field CLI args.
This commit is contained in:
@@ -16,12 +16,10 @@ Requirements:
|
||||
|
||||
Usage:
|
||||
python seed_tracker.py --id-folder ./torrents --bt-backup /path/to/BT_backup \\
|
||||
--nocodb-url https://noco.example.com --table-id tblXXX --api-token xc-xxx \\
|
||||
--id-field cXXX --seeding-field cYYY
|
||||
--nocodb-url https://noco.example.com --table-id tblXXX --api-token xc-xxx
|
||||
|
||||
To find NocoDB IDs:
|
||||
- Table ID: Click ... next to table name → Copy Table ID
|
||||
- Field IDs: Click field header dropdown → Copy Field ID
|
||||
"""
|
||||
|
||||
import argparse
|
||||
@@ -209,18 +207,20 @@ def get_bt_backup_data(bt_backup_path: Path) -> tuple[set[str], dict[tuple[str,
|
||||
class NocoDBClient:
|
||||
"""Simple NocoDB API client."""
|
||||
|
||||
ID_FIELD = "Id"
|
||||
SEEDING_FIELD = "Seeding Users"
|
||||
|
||||
def __init__(self, base_url: str, table_id: str, api_token: str,
|
||||
id_field: str, seeding_field: str, debug: bool = False):
|
||||
debug: bool = False):
|
||||
self.base_url = base_url.rstrip('/')
|
||||
self.table_id = table_id
|
||||
self.api_token = api_token
|
||||
self.id_field = id_field
|
||||
self.seeding_field = seeding_field
|
||||
self.debug = debug
|
||||
self.endpoint = f"{self.base_url}/api/v2/tables/{table_id}/records"
|
||||
|
||||
def _request(self, method: str, data: dict | None = None, params: dict | None = None) -> dict:
|
||||
def _request(self, method: str, url: str | None = None, data: dict | None = None, params: dict | None = None) -> dict:
|
||||
"""Make an API request."""
|
||||
if url is None:
|
||||
url = self.endpoint
|
||||
if params:
|
||||
query = "&".join(f"{k}={urllib.request.quote(str(v))}" for k, v in params.items())
|
||||
@@ -254,7 +254,7 @@ class NocoDBClient:
|
||||
def get_record(self, record_id: int | str) -> dict | None:
|
||||
"""Get a single record by ID."""
|
||||
try:
|
||||
params = {"where": f"({self.id_field},eq,{record_id})", "limit": "1"}
|
||||
params = {"where": f"({self.ID_FIELD},eq,{record_id})", "limit": "1"}
|
||||
result = self._request("GET", params=params)
|
||||
records = result.get("list", [])
|
||||
return records[0] if records else None
|
||||
@@ -266,7 +266,7 @@ class NocoDBClient:
|
||||
def update_record(self, row_id: int, value: str) -> bool:
|
||||
"""Update the seeding_users field on a record."""
|
||||
try:
|
||||
data = {"Id": row_id, self.seeding_field: value}
|
||||
data = {"Id": row_id, self.SEEDING_FIELD: value}
|
||||
self._request("PATCH", data=data)
|
||||
return True
|
||||
except Exception as e:
|
||||
@@ -302,13 +302,10 @@ def main():
|
||||
Examples:
|
||||
# API mode - update NocoDB directly:
|
||||
%(prog)s --id-folder ./torrents --bt-backup ~/.local/share/qBittorrent/BT_backup \\
|
||||
--nocodb-url https://noco.example.com --table-id tblXXXXX --api-token xc-xxxx \\
|
||||
--id-field cXXXXX --seeding-field cYYYYY
|
||||
--nocodb-url https://noco.example.com --table-id tblXXXXX --api-token xc-xxxx
|
||||
|
||||
# CSV mode - just output a file:
|
||||
%(prog)s --id-folder ./torrents --bt-backup /path/to/BT_backup --csv-only
|
||||
|
||||
To find field IDs in NocoDB: click field header dropdown → Copy Field ID (starts with "c")
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -324,12 +321,7 @@ To find field IDs in NocoDB: click field header dropdown → Copy Field ID (star
|
||||
help='NocoDB table ID (starts with "tbl")')
|
||||
parser.add_argument('--api-token', type=str, default=None,
|
||||
help='NocoDB API token (xc-token)')
|
||||
parser.add_argument('--id-field', type=str, default=None,
|
||||
help='Field ID for the Id column (starts with "c")')
|
||||
parser.add_argument('--seeding-field', type=str, default=None,
|
||||
help='Field ID for the seeding_users column (starts with "c")')
|
||||
|
||||
# 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'),
|
||||
@@ -357,13 +349,13 @@ To find field IDs in NocoDB: click field header dropdown → Copy Field ID (star
|
||||
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, args.id_field, args.seeding_field]):
|
||||
print("Error: API mode requires --nocodb-url, --table-id, --api-token, --id-field, and --seeding-field", file=sys.stderr)
|
||||
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)
|
||||
print(" Use --csv-only to skip API and just output CSV", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
noco = NocoDBClient(
|
||||
args.nocodb_url, args.table_id, args.api_token,
|
||||
args.id_field, args.seeding_field, args.debug
|
||||
args.debug
|
||||
)
|
||||
|
||||
# Test connection
|
||||
@@ -446,7 +438,7 @@ To find field IDs in NocoDB: click field header dropdown → Copy Field ID (star
|
||||
continue
|
||||
|
||||
# Parse current seeders
|
||||
current_seeders = parse_multiselect(record.get(noco.seeding_field))
|
||||
current_seeders = parse_multiselect(record.get(noco.SEEDING_FIELD))
|
||||
|
||||
if username in current_seeders:
|
||||
print(f" = {torrent_id}: already listed")
|
||||
|
||||
Reference in New Issue
Block a user