#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ DIGI Online - Manual Token Extractor Generează playlist folosind token extras manual din browser """ import requests import json import sys from datetime import datetime class DigiOnlineManual: def __init__(self, token): self.base_url = "https://www.digionline.ro" self.api_url = "https://www.digionline.ro/api" self.token = token self.session = requests.Session() self.session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'ro-RO,ro;q=0.9,en-US;q=0.8,en;q=0.7', 'Authorization': f'Bearer {token}', 'Origin': 'https://www.digionline.ro', 'Referer': 'https://www.digionline.ro/' }) self.channels = [] def get_channels(self): """Obține lista de canale disponibile""" print("\n📺 Obținere listă canale...") channels_url = f"{self.api_url}/channel/list" try: response = self.session.get(channels_url, timeout=10) if response.status_code == 200: data = response.json() if 'data' in data: self.channels = data['data'] print(f"✅ {len(self.channels)} canale găsite!") return True else: print("❌ Răspuns invalid de la server") return False elif response.status_code == 401: print("❌ Token invalid sau expirat!") print("💡 Extrage un token nou din browser.") return False else: print(f"❌ Eroare la obținere canale! Status: {response.status_code}") return False except Exception as e: print(f"❌ Eroare la obținere canale: {e}") return False def get_stream_url(self, channel_id): """Obține URL-ul de stream pentru un canal""" stream_url = f"{self.api_url}/stream/start/{channel_id}" try: response = self.session.get(stream_url, timeout=10) if response.status_code == 200: data = response.json() if 'data' in data and 'stream_url' in data['data']: return data['data']['stream_url'] elif 'data' in data and 'url' in data['data']: return data['data']['url'] return None except Exception as e: return None def generate_playlist(self, output_file="digi_authenticated.m3u"): """Generează playlist M3U cu URL-uri autentificate""" print(f"\n📝 Generare playlist: {output_file}") if not self.channels: print("❌ Nu există canale disponibile!") return False try: with open(output_file, 'w', encoding='utf-8') as f: # Header M3U f.write("#EXTM3U\n\n") f.write("# ========================================\n") f.write("# PLAYLIST DIGI ONLINE - AUTENTIFICAT\n") f.write(f"# Generat: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") f.write(f"# Canale: {len(self.channels)}\n") f.write("# ========================================\n\n") # Procesează fiecare canal processed = 0 for channel in self.channels: channel_id = channel.get('id') channel_name = channel.get('name', 'Unknown') channel_logo = channel.get('logo', '') category = channel.get('category', 'General') print(f" 📡 Procesare: {channel_name}...", end='') # Obține URL-ul de stream stream_url = self.get_stream_url(channel_id) if stream_url: # Scrie în playlist f.write(f'#EXTINF:-1 tvg-id="{channel_id}" tvg-name="{channel_name}" ') f.write(f'tvg-logo="{channel_logo}" group-title="{category}",{channel_name}\n') f.write(f'{stream_url}\n\n') processed += 1 print(" ✅") else: print(" ❌") # Footer f.write("# ========================================\n") f.write(f"# Total canale procesate: {processed}/{len(self.channels)}\n") f.write("# ========================================\n") print(f"\n✅ Playlist generat cu succes!") print(f"📁 Fișier: {output_file}") print(f"📺 Canale funcționale: {processed}/{len(self.channels)}") return True except Exception as e: print(f"❌ Eroare la generare playlist: {e}") return False def print_instructions(): """Afișează instrucțiuni pentru extragere token""" print("\n" + "=" * 70) print("📖 CUM SĂ EXTRAGI TOKEN-UL DIN BROWSER") print("=" * 70) print(""" 1. Deschide browser (Chrome/Edge/Firefox) 2. Mergi pe: https://www.digionline.ro 3. Autentifică-te cu email și parolă 4. Deschide Developer Tools: - Chrome/Edge: F12 sau Ctrl+Shift+I - Firefox: F12 sau Ctrl+Shift+K 5. Mergi la tab-ul "Network" (Rețea) 6. Filtrează după "XHR" sau "Fetch" 7. Reîmprospătează pagina (F5) 8. Caută cererea "login" sau "user" în lista de cereri 9. Click pe cerere → Headers → Request Headers 10. Caută "Authorization: Bearer ..." și copiază token-ul (partea după "Bearer ") SAU 10. Mergi la tab-ul "Application" (Aplicație) → Storage → Local Storage → https://www.digionline.ro → Caută "token" sau "auth_token" și copiază valoarea 11. Lipește token-ul când scriptul îl cere """) print("=" * 70) def main(): """Funcția principală""" print("=" * 70) print("🎬 DIGI ONLINE - MANUAL TOKEN EXTRACTOR") print("=" * 70) # Afișează instrucțiuni print_instructions() print("\n📋 Introdu token-ul extras din browser:") print("⚠️ Token-ul arată așa: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...") print() token = input("🔑 Token: ").strip() if not token: print("❌ Token-ul este obligatoriu!") sys.exit(1) if len(token) < 20: print("❌ Token-ul pare prea scurt! Verifică că ai copiat tot token-ul.") sys.exit(1) print("\n" + "=" * 70) # Creează instanța cu token-ul digi = DigiOnlineManual(token) # Obține lista de canale if not digi.get_channels(): print("\n❌ Nu s-au putut obține canalele!") print("💡 Verifică că token-ul este valid și nu a expirat.") sys.exit(1) # Generează playlist-ul output_file = "digi_authenticated.m3u" if digi.generate_playlist(output_file): print("\n" + "=" * 70) print("🎉 SUCCES!") print("=" * 70) print(f"\n📁 Playlist generat: {output_file}") print(f"📺 Folosește acest fișier în Dispatcharr/Jellyfin/VLC") print(f"\n💡 TIP: Token-ul expiră după câteva ore.") print(f" Rulează din nou scriptul cu un token nou când expiră.\n") else: print("\n❌ Eroare la generare playlist!") sys.exit(1) if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\n\n⚠️ Întrerupt de utilizator!") sys.exit(0) except Exception as e: print(f"\n❌ Eroare neașteptată: {e}") import traceback traceback.print_exc() sys.exit(1)