shvchenko commited on
Commit
69f63db
·
verified ·
1 Parent(s): a96501d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -0
app.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import json
3
+ import random
4
+ import string
5
+ import gradio as gr
6
+
7
+ # Local file paths
8
+ M3U_FILE = "daddylive-channels-events.m3u8"
9
+ CHANNELS_JSON = "channels_fixed.json"
10
+
11
+ # --- Helpers ---
12
+ def normalize(s):
13
+ return re.sub(r'[^a-z0-9]', '', s.lower())
14
+
15
+ def fuzzy_match(name, json_keys, cutoff=0.8):
16
+ from difflib import get_close_matches
17
+ matches = get_close_matches(normalize(name), [normalize(k) for k in json_keys], n=1, cutoff=cutoff)
18
+ if matches:
19
+ for k in json_keys:
20
+ if normalize(k) == matches[0]:
21
+ return k
22
+ return None
23
+
24
+ def generate_filename(upper=False):
25
+ chars = ''.join(random.choices(string.ascii_uppercase if upper else string.ascii_lowercase, k=3))
26
+ return f"{chars}.m3u"
27
+
28
+ # --- Main Processing ---
29
+ def process_playlist():
30
+ # Lazy load playlist
31
+ try:
32
+ with open(M3U_FILE, 'r', encoding='utf-8') as f:
33
+ m3u_lines = f.read().splitlines()
34
+ except Exception as e:
35
+ return f"Error reading playlist: {e}", None, None
36
+
37
+ # Load JSON reference
38
+ try:
39
+ with open(CHANNELS_JSON, 'r', encoding='utf-8') as f:
40
+ channels_ref = json.load(f)
41
+ except Exception as e:
42
+ return f"Error reading JSON: {e}", None, None
43
+
44
+ # Split 24/7 vs Events
45
+ m3u_24_7 = []
46
+ m3u_events = []
47
+ current_section = None
48
+
49
+ for line in m3u_lines:
50
+ if line.startswith('#EXTINF'):
51
+ if 'group-title="24/7 CHANNELS' in line:
52
+ current_section = '24_7'
53
+ elif 'EVENTS|' in line:
54
+ current_section = 'events'
55
+ else:
56
+ current_section = None
57
+
58
+ if current_section == '24_7':
59
+ m3u_24_7.append(line)
60
+ elif current_section == 'events':
61
+ m3u_events.append(line)
62
+ else:
63
+ # Include headers like #EXTM3U
64
+ m3u_24_7.append(line)
65
+ m3u_events.append(line)
66
+
67
+ log_lines = []
68
+
69
+ def update_tvg_id(lines):
70
+ updated = []
71
+ for line in lines:
72
+ if line.startswith('#EXTINF'):
73
+ # Extract channel name after last comma
74
+ parts = line.split(',')
75
+ ch_name = parts[-1].strip()
76
+
77
+ # Match against JSON
78
+ match_key = fuzzy_match(ch_name, channels_ref.keys())
79
+ if match_key:
80
+ new_tvg_id = channels_ref[match_key].get('tvg_id', '')
81
+ # Replace or add tvg-id
82
+ if 'tvg-id=' in line:
83
+ line = re.sub(r'tvg-id=".*?"', f'tvg-id="{new_tvg_id}"', line)
84
+ else:
85
+ line = line.replace('#EXTINF:', f'#EXTINF:-1 tvg-id="{new_tvg_id}",')
86
+ log_lines.append(f"✅ {ch_name} → {new_tvg_id}")
87
+ else:
88
+ log_lines.append(f"⚠️ {ch_name} (no match)")
89
+ updated.append(line)
90
+ return updated
91
+
92
+ updated_24_7 = update_tvg_id(m3u_24_7)
93
+ updated_events = update_tvg_id(m3u_events)
94
+
95
+ # Generate random filenames
96
+ filename_24_7 = generate_filename(upper=True)
97
+ filename_events = generate_filename(upper=False)
98
+
99
+ # Save outputs
100
+ with open(filename_24_7, 'w', encoding='utf-8') as f:
101
+ f.write('\n'.join(updated_24_7))
102
+
103
+ with open(filename_events, 'w', encoding='utf-8') as f:
104
+ f.write('\n'.join(updated_events))
105
+
106
+ log_text = '\n'.join(log_lines)
107
+ return log_text, filename_24_7, filename_events
108
+
109
+ # --- Gradio UI ---
110
+ demo = gr.Interface(
111
+ fn=process_playlist,
112
+ inputs=[],
113
+ outputs=[
114
+ gr.Textbox(label="Update Log", lines=25),
115
+ gr.File(label="Download 24/7 Channels M3U"),
116
+ gr.File(label="Download Events M3U")
117
+ ],
118
+ title="Project 1 Playlist Updater - Local",
119
+ description="Updates tvg-id for 24/7 and Events channels based on local channels_fixed.json with fuzzy matching."
120
+ )
121
+
122
+ demo.launch()