Advertisement
Chryses

zzz

Mar 27th, 2025
284
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 20.03 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. import requests
  4. import json
  5. from datetime import datetime
  6. import sys
  7. import time
  8.  
  9. # Parametri di connessione
  10. RADARR_HOST = "http://10.0.0.100:7878"
  11. RADARR_API_KEY = "d3ddde8fcfe74bf99f81cba41d4f13f7"
  12.  
  13. def format_bytes(size_bytes):
  14.     """Formatta i byte in una rappresentazione leggibile (KB, MB, GB)"""
  15.     if size_bytes == 0:
  16.         return "0B"
  17.     size_names = ("B", "KB", "MB", "GB", "TB", "PB")
  18.     i = 0
  19.     while size_bytes >= 1024 and i < len(size_names) - 1:
  20.         size_bytes /= 1024.0
  21.         i += 1
  22.     return f"{size_bytes:.2f} {size_names[i]}"
  23.  
  24. def format_datetime(date_string):
  25.     """Formatta una data ISO in un formato più leggibile"""
  26.     if not date_string:
  27.         return "N/A"
  28.     try:
  29.         dt = datetime.fromisoformat(date_string.replace('Z', '+00:00'))
  30.         return dt.strftime("%Y-%m-%d %H:%M:%S")
  31.     except:
  32.         return date_string
  33.  
  34. def normalize_hash(hash_value, client=""):
  35.     """
  36.    Normalizza un hash per EMule/altri client per permettere i confronti
  37.    
  38.    Args:
  39.        hash_value: Il valore dell'hash da normalizzare
  40.        client: Il nome del client (per determinare il formato)
  41.    
  42.    Returns:
  43.        Hash normalizzato
  44.    """
  45.     if not hash_value:
  46.         return hash_value
  47.    
  48.     is_emule = client and ('emule' in client.lower() or 'emulerr' in client.lower())
  49.    
  50.     # Per client EMule, gestisci i formati a 32 e 40 caratteri
  51.     if is_emule:
  52.         if len(hash_value) == 32:
  53.             return hash_value + '0' * 8  # Aggiungi 8 zeri per arrivare a 40 caratteri
  54.         elif len(hash_value) == 40:
  55.             return hash_value
  56.    
  57.     return hash_value
  58.  
  59. def get_movie_history(movie_id):
  60.     """
  61.    Ottiene la cronologia specifica per un film
  62.    
  63.    Args:
  64.        movie_id: L'ID del film in Radarr
  65.    
  66.    Returns:
  67.        Lista di record della cronologia per quel film
  68.    """
  69.     url = f"{RADARR_HOST}/api/v3/history/movie"
  70.    
  71.     params = {
  72.         "movieId": movie_id,
  73.         "apikey": RADARR_API_KEY
  74.     }
  75.    
  76.     try:
  77.         response = requests.get(url, params=params)
  78.        
  79.         if response.status_code == 200:
  80.             records = response.json()
  81.             return records
  82.         else:
  83.             print(f"Errore nel recuperare la cronologia per il film {movie_id}: {response.status_code}")
  84.             return []
  85.     except Exception as e:
  86.         print(f"Errore durante la connessione: {str(e)}")
  87.         return []
  88.  
  89. def get_history_for_file(filename, all_history=None):
  90.     """
  91.    Cerca nella cronologia globale per un nome file specifico
  92.    """
  93.     if not all_history:
  94.         # Se non è stata fornita una cronologia, recuperala
  95.         url = f"{RADARR_HOST}/api/v3/history"
  96.         params = {
  97.             "pageSize": 500,
  98.             "page": 1,
  99.             "sortKey": "date",
  100.             "sortDirection": "descending",
  101.             "apikey": RADARR_API_KEY
  102.         }
  103.        
  104.         try:
  105.             response = requests.get(url, params=params)
  106.             if response.status_code == 200:
  107.                 data = response.json()
  108.                 all_history = data.get('records', [])
  109.             else:
  110.                 return None
  111.         except:
  112.             return None
  113.    
  114.     # Normalizza il nome file per il confronto
  115.     norm_filename = filename.lower()
  116.    
  117.     # Cerca nella cronologia per il nome file
  118.     for record in all_history:
  119.         source_title = record.get('sourceTitle', '').lower()
  120.         if norm_filename == source_title or norm_filename in source_title or source_title in norm_filename:
  121.             return record
  122.    
  123.     return None
  124.  
  125. def get_movie_details(movie_id):
  126.     """
  127.    Recupera i dettagli di un film specifico
  128.    
  129.    Args:
  130.        movie_id: L'ID del film in Radarr
  131.        
  132.    Returns:
  133.        Dizionario con i dettagli del film
  134.    """
  135.     url = f"{RADARR_HOST}/api/v3/movie/{movie_id}"
  136.    
  137.     params = {
  138.         "apikey": RADARR_API_KEY
  139.     }
  140.    
  141.     try:
  142.         response = requests.get(url, params=params)
  143.        
  144.         if response.status_code == 200:
  145.             movie = response.json()
  146.             return movie
  147.         else:
  148.             print(f"Errore nel recuperare i dettagli del film {movie_id}: {response.status_code}")
  149.             return None
  150.     except Exception as e:
  151.         print(f"Errore durante la connessione: {str(e)}")
  152.         return None
  153.  
  154. def get_queue_items(page=1):
  155.     """Recupera gli elementi della coda di download da Radarr"""
  156.     # Costruzione dell'URL con tutti i parametri possibili
  157.     url = (
  158.         f"{RADARR_HOST}/api/v3/queue?"
  159.         f"page={page}"
  160.         f"&pageSize=10"
  161.         f"&sortKey=timeleft"
  162.         f"&sortDirection=ascending"
  163.         f"&includeUnknownMovieItems=true"
  164.         f"&includeMovie=true"
  165.     )
  166.    
  167.     # Aggiunta dell'API key come parametro
  168.     params = {
  169.         "apikey": RADARR_API_KEY
  170.     }
  171.    
  172.     try:
  173.         # Ottieni prima la cronologia globale (ultimi 500 elementi)
  174.         print("Recupero la cronologia globale...")
  175.         history_url = f"{RADARR_HOST}/api/v3/history"
  176.         history_params = {
  177.             "pageSize": 500,
  178.             "page": 1,
  179.             "sortKey": "date",
  180.             "sortDirection": "descending",
  181.             "apikey": RADARR_API_KEY
  182.         }
  183.        
  184.         history_response = requests.get(history_url, params=history_params)
  185.         global_history = []
  186.        
  187.         if history_response.status_code == 200:
  188.             history_data = history_response.json()
  189.             global_history = history_data.get('records', [])
  190.             print(f"Recuperati {len(global_history)} elementi dalla cronologia globale")
  191.         else:
  192.             print(f"Errore nel recupero della cronologia globale: {history_response.status_code}")
  193.        
  194.         # Ora recupera gli elementi della coda
  195.         print(f"Recupero elementi della coda Radarr, pagina {page}...")
  196.         response = requests.get(url, params=params)
  197.        
  198.         if response.status_code == 200:
  199.             queue_data = response.json()
  200.            
  201.             # Stampare informazioni sulla coda
  202.             print("\n" + "="*90)
  203.            
  204.             # Verifica la presenza dei campi di paginazione, altrimenti usa valori di default
  205.             current_page = queue_data.get('page', 1)
  206.             total_pages = queue_data.get('totalPages', 1)
  207.             total_records = queue_data.get('totalRecords', 0)
  208.            
  209.             print(f"INFORMAZIONI SULLA CODA DI DOWNLOAD - PAGINA {current_page}/{total_pages}")
  210.             print("="*90)
  211.             print(f"Record totali: {total_records}")
  212.            
  213.             # Se 'records' non è presente, potrebbe essere una risposta diretta con gli elementi
  214.             records = queue_data.get('records', [])
  215.             if not records and isinstance(queue_data, list):
  216.                 records = queue_data
  217.                
  218.             print(f"Record in questa pagina: {len(records)}")
  219.            
  220.             # Cache per i risultati dei grab
  221.             grab_results = {}
  222.            
  223.             # Analisi dettagliata degli elementi in coda
  224.             for i, item in enumerate(records):
  225.                 print("\n" + "-"*90)
  226.                 print(f"ELEMENTO #{i+1}: {item.get('title', 'N/A')}")
  227.                 print("-"*90)
  228.                
  229.                 # Informazioni di base
  230.                 print("\n[INFO DI BASE]")
  231.                 print(f"ID Coda: {item.get('id', 'N/A')}")
  232.                
  233.                 # Determina il Movie ID
  234.                 movie_id = None
  235.                 if 'movieId' in item:
  236.                     movie_id = item['movieId']
  237.                 elif 'movie' in item and item['movie'] and 'id' in item['movie']:
  238.                     movie_id = item['movie']['id']
  239.                
  240.                 if movie_id:
  241.                     print(f"Movie ID: {movie_id}")
  242.                 else:
  243.                     print("Movie ID: N/A")
  244.                
  245.                 # Ottieni il client di download e il download ID
  246.                 download_client = item.get('downloadClient', '')
  247.                 download_id = item.get('downloadId', '')
  248.                
  249.                 print(f"Stato: {item.get('status', 'N/A')}")
  250.                 print(f"Protocollo: {item.get('protocol', 'N/A')}")
  251.                 print(f"Download ID: {download_id}")
  252.                 print(f"Client di download: {download_client}")
  253.                
  254.                 # Normalizza l'hash per EMuleRR
  255.                 normalized_download_id = normalize_hash(download_id, download_client)
  256.                 if normalized_download_id != download_id:
  257.                     print(f"Download ID (Normalizzato): {normalized_download_id}")
  258.                
  259.                 print(f"Indice: {item.get('indexer', 'N/A')}")
  260.                
  261.                 # Ottieni il titolo dell'item
  262.                 item_title = item.get('title', '')
  263.                
  264.                 # PRIMA STRATEGIA: Cerca nella cronologia specifica del film se abbiamo un movie_id
  265.                 movie_history = []
  266.                 if movie_id:
  267.                     print(f"Cerco nella cronologia specifica del film (ID: {movie_id})...")
  268.                     movie_history = get_movie_history(movie_id)
  269.                     print(f"Trovati {len(movie_history)} record nella cronologia del film")
  270.                
  271.                 # Cerca gli eventi "grabbed" nella cronologia del film
  272.                 grabbed_records = [r for r in movie_history if r.get('eventType') == 'grabbed']
  273.                
  274.                 # FALLBACK STRATEGIA 1: Cerca nella cronologia globale per nome file
  275.                 if not grabbed_records:
  276.                     print(f"Nessun record 'grabbed' trovato nella cronologia del film. Cerco nella cronologia globale per nome file...")
  277.                     file_history = get_history_for_file(item_title, global_history)
  278.                     if file_history and file_history.get('eventType') == 'grabbed':
  279.                         grabbed_records = [file_history]
  280.                         print(f"Trovato 1 record 'grabbed' nella cronologia globale")
  281.                
  282.                 # FALLBACK STRATEGIA 2: Cerca nella cronologia globale per hash
  283.                 if not grabbed_records and download_id:
  284.                     print(f"Cerco nella cronologia globale per hash...")
  285.                     # Entrambe le versioni dell'hash (con e senza zeri finali per EMule)
  286.                     hash_to_search = [download_id]
  287.                     if 'emule' in download_client.lower() or 'emulerr' in download_client.lower():
  288.                         if len(download_id) == 32:
  289.                             hash_to_search.append(download_id + '00000000')
  290.                         elif len(download_id) == 40 and download_id.endswith('00000000'):
  291.                             hash_to_search.append(download_id[:-8])
  292.                    
  293.                     # Cerca match diretti per qualsiasi versione dell'hash
  294.                     for h in hash_to_search:
  295.                         matching_records = [r for r in global_history if r.get('downloadId') == h]
  296.                         if matching_records:
  297.                             grabbed_records = [r for r in matching_records if r.get('eventType') == 'grabbed']
  298.                             if grabbed_records:
  299.                                 print(f"Trovati {len(grabbed_records)} record 'grabbed' nella cronologia globale tramite hash")
  300.                                 break
  301.                
  302.                 # FALLBACK STRATEGIA 3: Cerca nella cronologia globale per movie_id
  303.                 if not grabbed_records and movie_id:
  304.                     print(f"Cerco nella cronologia globale per movie_id...")
  305.                     movie_records = [r for r in global_history if r.get('movieId') == movie_id]
  306.                     grabbed_records = [r for r in movie_records if r.get('eventType') == 'grabbed']
  307.                     if grabbed_records:
  308.                         print(f"Trovati {len(grabbed_records)} record 'grabbed' nella cronologia globale tramite movie_id")
  309.                
  310.                 # Se abbiamo trovato eventi "grabbed", usa il più recente
  311.                 grab_record = None
  312.                 if grabbed_records:
  313.                     # Ordina per data (i più recenti prima)
  314.                     sorted_records = sorted(grabbed_records,
  315.                                          key=lambda r: r.get('date', ''),
  316.                                          reverse=True)
  317.                     grab_record = sorted_records[0]
  318.                
  319.                 # NUOVO: Recupera il movie_id dal grab record se non era disponibile nell'item
  320.                 if not movie_id and grab_record and 'movieId' in grab_record:
  321.                     movie_id = grab_record['movieId']
  322.                     print(f"Movie ID recuperato dalla cronologia: {movie_id}")
  323.                    
  324.                     # Se abbiamo recuperato un movie_id, ottieni dettagli aggiuntivi
  325.                     movie_details = get_movie_details(movie_id)
  326.                     if movie_details:
  327.                         # Aggiungi i dettagli del film all'elemento in coda
  328.                         if 'movie' not in item:
  329.                             item['movie'] = movie_details
  330.                        
  331.                         print(f"Titolo film: {movie_details.get('title', 'N/A')}")
  332.                         print(f"Anno: {movie_details.get('year', 'N/A')}")
  333.                
  334.                 # Se abbiamo trovato un record grabbed corrispondente
  335.                 if grab_record:
  336.                     grab_id = grab_record.get('downloadId', 'N/A')
  337.                    
  338.                     # Memorizza il risultato
  339.                     grab_results[i] = grab_record
  340.                    
  341.                     print(f"Grab ID (dalla cronologia): {grab_id}")
  342.                    
  343.                     # Normalizza l'hash per EMuleRR
  344.                     normalized_grab_id = normalize_hash(grab_id, download_client)
  345.                     if normalized_grab_id != grab_id:
  346.                         print(f"Grab ID (Normalizzato): {normalized_grab_id}")
  347.                    
  348.                     print(f"Titolo sorgente: {grab_record.get('sourceTitle', 'N/A')}")
  349.                     print(f"Data grab: {format_datetime(grab_record.get('date', ''))}")
  350.                    
  351.                     # Confronta se il grab_id corrisponde al download_id
  352.                     if normalized_grab_id == normalized_download_id or grab_id == download_id:
  353.                         print("CORRISPONDENZA: Il Grab ID è identico al Download ID")
  354.                     else:
  355.                         print("NOTA: Il Grab ID è diverso dal Download ID")
  356.                 else:
  357.                     grab_results[i] = None
  358.                     print("Grab ID: Non trovato nella cronologia")
  359.                
  360.                 # Informazioni sul download
  361.                 print("\n[DETTAGLI DOWNLOAD]")
  362.                 print(f"Dimensione totale: {format_bytes(item.get('size', 0))}")
  363.                 if 'sizeleft' in item and item.get('size', 0) > 0:
  364.                     progress = 100 - (item['sizeleft'] / item['size'] * 100)
  365.                     print(f"Dimensione rimanente: {format_bytes(item.get('sizeleft', 0))}")
  366.                     print(f"Progresso: {progress:.2f}%")
  367.                 print(f"Tempo rimanente: {item.get('timeleft', 'N/A')}")
  368.                 print(f"Priorità di download: {item.get('downloadForced', False)}")
  369.                 if 'outputPath' in item:
  370.                     print(f"Percorso output: {item['outputPath']}")
  371.                
  372.                 # Informazioni temporali
  373.                 print("\n[INFORMAZIONI TEMPORALI]")
  374.                 print(f"Aggiunto: {format_datetime(item.get('added', ''))}")
  375.                 print(f"Data pubblicazione: {format_datetime(item.get('publishDate', ''))}")
  376.  
  377.                 # Errori e avvisi
  378.                 if item.get('errorMessage'):
  379.                     print("\n[ERRORI]")
  380.                     print(f"Messaggio di errore: {item['errorMessage']}")
  381.                
  382.                 if item.get('statusMessages'):
  383.                     print("\n[MESSAGGI DI STATO]")
  384.                     for msg in item['statusMessages']:
  385.                         print(f"- Titolo: {msg.get('title', 'N/A')}")
  386.                         for message in msg.get('messages', []):
  387.                             print(f"  • {message}")
  388.                
  389.                 # Informazioni sul film
  390.                 if 'movie' in item and item['movie']:
  391.                     movie = item['movie']
  392.                     print("\n[INFORMAZIONI FILM]")
  393.                     print(f"Movie ID: {movie.get('id', 'N/A')}")
  394.                     print(f"Titolo: {movie.get('title', 'N/A')}")
  395.                     print(f"Titolo originale: {movie.get('originalTitle', 'N/A')}")
  396.                     print(f"Anno: {movie.get('year', 'N/A')}")
  397.                     print(f"TMDb ID: {movie.get('tmdbId', 'N/A')}")
  398.                     print(f"IMDb ID: {movie.get('imdbId', 'N/A') or 'N/A'}")
  399.                
  400.                 # Dettagli qualità
  401.                 if 'quality' in item:
  402.                     print("\n[QUALITÀ]")
  403.                     quality = item['quality']
  404.                     if 'quality' in quality:
  405.                         q_details = quality['quality']
  406.                         print(f"Nome qualità: {q_details.get('name', 'N/A')}")
  407.                         print(f"Sorgente: {q_details.get('source', 'N/A')}")
  408.                         print(f"Risoluzione: {q_details.get('resolution', 'N/A')}")
  409.            
  410.             # Riepilogo dei Grab ID
  411.             print("\n" + "="*110)
  412.             print("RIEPILOGO GRAB ID DALLA CRONOLOGIA")
  413.             print("="*110)
  414.             print(f"{'#':<3} {'MOVIE ID':<8} {'CLIENT':<10} {'GRAB ID':<40} {'TITOLO'}")
  415.             print("-"*110)
  416.            
  417.             for i, item in enumerate(records):
  418.                 # Determina il Movie ID (potenzialmente dal record del grab)
  419.                 movie_id = "N/A"
  420.                 if 'movieId' in item:
  421.                     movie_id = item['movieId']
  422.                 elif 'movie' in item and item['movie'] and 'id' in item['movie']:
  423.                     movie_id = item['movie']['id']
  424.                 elif grab_results.get(i) and 'movieId' in grab_results[i]:
  425.                     # Recupera il movie_id dal record del grab
  426.                     movie_id = grab_results[i]['movieId']
  427.                
  428.                 client = item.get('downloadClient', 'N/A')
  429.                 grab_record = grab_results.get(i)
  430.                 grab_id = "N/A"
  431.                
  432.                 if grab_record:
  433.                     grab_id = grab_record.get('downloadId', 'N/A')
  434.                     if 'emule' in client.lower() or 'emulerr' in client.lower():
  435.                         grab_id = normalize_hash(grab_id, client)
  436.                
  437.                 title = item.get('title', 'N/A')
  438.                 if len(title) > 30:
  439.                     title = title[:27] + "..."
  440.                
  441.                 print(f"{i+1:<3} {movie_id:<8} {client[:10]:<10} {grab_id:<40} {title}")
  442.            
  443.             return queue_data
  444.         else:
  445.             print(f"Errore nella richiesta: {response.status_code}")
  446.             print(response.text)
  447.             return None
  448.            
  449.     except Exception as e:
  450.         print(f"Errore durante la connessione: {str(e)}")
  451.         # Debug dell'errore
  452.         import traceback
  453.         print("\nTraceback completo dell'errore:")
  454.         traceback.print_exc()
  455.         return None
  456.  
  457. # Esegue la funzione per la pagina specificata (default: 1)
  458. if __name__ == "__main__":
  459.     page = 1
  460.     if len(sys.argv) > 1:
  461.         try:
  462.             page = int(sys.argv[1])
  463.         except:
  464.             pass
  465.    
  466.     print(f"Recupero elementi della coda Radarr, pagina {page}...")
  467.     result = get_queue_items(page=page)
  468.    
  469.     # Per salvare il risultato completo in un file JSON:
  470.     if result:
  471.         filename = f"radarr_queue_page{page}.json"
  472.         with open(filename, "w") as f:
  473.             json.dump(result, f, indent=2)
  474.         print(f"\nRisultati salvati in {filename}")
  475.     else:
  476.         print("Nessun risultato da salvare.")
  477.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement