239 lines
8.0 KiB
Python
239 lines
8.0 KiB
Python
#!/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)
|
|
|