#!/usr/bin/env python3 # -*- coding: utf-8 -*- import pymysql import bencodepy from openpyxl import Workbook from openpyxl.utils import get_column_letter # ============================================================ # DB CONFIG # ============================================================ DB_CONFIG = { "host": "192.168.1.50", "user": "root", "password": "Vlado9674+", "database": "torrents", "charset": "utf8mb4", "cursorclass": pymysql.cursors.SSCursor } OUTPUT_FILE = "torrent_report.xlsx" # ============================================================ # HELPERS # ============================================================ def decode_if_bytes(value): if isinstance(value, bytes): return value.decode("utf-8", errors="replace") return value def get_root_name(info): # prefer UTF-8 variant if b"name.utf-8" in info: return decode_if_bytes(info[b"name.utf-8"]) return decode_if_bytes(info[b"name"]) def get_file_parts(file_entry): # prefer UTF-8 variant if b"path.utf-8" in file_entry: return [decode_if_bytes(p) for p in file_entry[b"path.utf-8"]] return [decode_if_bytes(p) for p in file_entry[b"path"]] def parse_torrent(blob): data = bencodepy.decode(blob) info = data[b"info"] root_name = get_root_name(info) files = [] # ===================== # MULTI FILE TORRENT # ===================== if b"files" in info: for f in info[b"files"]: parts = get_file_parts(f) # ochrana proti root/root duplicite if parts and parts[0] == root_name: full_path = "/".join(parts) else: full_path = root_name + "/" + "/".join(parts) files.append(full_path) # ===================== # SINGLE FILE TORRENT # ===================== else: files.append(root_name) return files # ============================================================ # MAIN # ============================================================ def main(): conn = pymysql.connect(**DB_CONFIG) wb = Workbook() ws = wb.active ws.title = "Torrent report" ws.append(["QB Status", "Title", "Torrent Path"]) with conn.cursor() as cursor: cursor.execute(""" SELECT qb_state, title_visible, torrent_content FROM torrents WHERE torrent_content IS NOT NULL """) for qb_state, title_visible, blob in cursor: qb_state = qb_state or "UNKNOWN" title_visible = title_visible or "" try: files = parse_torrent(blob) for f in files: ws.append([qb_state, title_visible, f]) except Exception as e: ws.append([qb_state, title_visible, f"ERROR: {e}"]) # autosize for col in ws.columns: max_len = 0 col_letter = get_column_letter(col[0].column) for cell in col: if cell.value: max_len = max(max_len, len(str(cell.value))) ws.column_dimensions[col_letter].width = min(max_len + 2, 90) wb.save(OUTPUT_FILE) conn.close() print("DONE ->", OUTPUT_FILE) if __name__ == "__main__": main()