bep40 commited on
Commit
8aebd83
·
verified ·
1 Parent(s): 5e4bd98

Replace truncated yt_live.js (unterminated CSS string) with safe stub; VTV player lives in vtv_init.js

Browse files
Files changed (1) hide show
  1. static/yt_live.js +13 -175
static/yt_live.js CHANGED
@@ -1,175 +1,13 @@
1
- // === VNEWS — VTV LIVE + Inline Recorder v9 ===
2
- // Features: PiP, mini-player, INLINE RECORDER, VTVGO POPUP players for each channel
3
- // FIX v10: Correct VTVGO popup URLs for all channels + World Cup 2026 TS stream links
4
- // FIX v11: Allow clicking off tabs (always clickable), better stream status handling
5
-
6
- (function(){
7
- if(window._ytLiveLoaded) return;
8
- window._ytLiveLoaded = true;
9
-
10
- const CHANNELS = [
11
- {id:'vtv1',name:'VTV1',badge:'Tin tức'},{id:'vtv2',name:'VTV2',badge:'Khoa học'},
12
- {id:'vtv3',name:'VTV3',badge:'Giải trí'},{id:'vtv4',name:'VTV4',badge:'Quốc tế'},
13
- {id:'vtv5',name:'VTV5',badge:'Miền Nam'},{id:'vtv6',name:'VTV6',badge:'Thanh niên'},
14
- {id:'vtv7',name:'VTV7',badge:'Giáo dục'},{id:'vtv8',name:'VTV8',badge:'Miền Trung'},
15
- {id:'vtv9',name:'VTV9',badge:'Miền Bắc'},{id:'vtv10',name:'VTV10',badge:'Cần Thơ'},
16
- {id:'vtvprime',name:'VTVPrime',badge:'Prime'},
17
- ];
18
-
19
- // VTVGO popup URLs for each channel (FIXED v10 - verified correct URLs)
20
- const VTV_POPUP_URLS = {
21
- vtv1: 'https://package.vtvgo.vn/channel/vtv1-1,1.html',
22
- vtv2: 'https://package.vtvgo.vn/channel/vtv2-1,2.html',
23
- vtv3: 'https://package.vtvgo.vn/channel/vtv3-1,3.html',
24
- vtv4: 'https://package.vtvgo.vn/channel/vtv4-1,4.html',
25
- vtv5: 'https://package.vtvgo.vn/channel/vtv5-1,5.html',
26
- vtv6: 'https://package.vtvgo.vn/channel/vtv6-1,13.html',
27
- vtv7: 'https://package.vtvgo.vn/channel/vtv7-1,27.html',
28
- vtv8: 'https://package.vtvgo.vn/channel/vtv8-1,36.html',
29
- vtv9: 'https://package.vtvgo.vn/channel/vtv9-1,39.html',
30
- vtv10: 'https://package.vtvgo.vn/channel/vtv10-1,6.html',
31
- };
32
-
33
- const DEFAULT_CHANNEL = 'vtv3';
34
- const NEEDS_PROXY = /fptplay\.net|vtvgo\.vn/;
35
- const STREAMS = {};
36
- let _currentCh = null, _hls = null, _loading = false, _blockInserted = false;
37
- let _streamsLoaded = false, _pipActive = false, _miniActive = false, _vtvPinned = false, _vtvPopupActive = false;
38
-
39
- // ===== RECORDER STATE =====
40
- const _rec = {
41
- active: false, startTime: null, endTime: null,
42
- isRecording: false, recorder: null, chunks: [], blob: null,
43
- ratio: 'original', _dragMarker: null, _recTimer: null,
44
- };
45
-
46
- // ===== STYLES =====
47
- const style = document.createElement('style');
48
- style.textContent = `
49
- .vtv-wrap{position:relative;margin:6px 4px;background:#111;border:1px solid #0066cc;border-radius:10px;overflow:hidden}
50
- .vtv-head{display:flex;align-items:center;gap:8px;padding:8px 10px;background:linear-gradient(90deg,#003366,#1a1a1a)}
51
- .vtv-title{font-size:13px;font-weight:800;color:#00ccff}
52
- .vtv-badge{font-size:10px;font-weight:800;color:#00ccff;animation:vtvp 1.3s infinite}
53
- @keyframes vtvp{0%,100%{opacity:1}50%{opacity:.3}}
54
- .vtv-tabs{display:flex;flex-wrap:wrap;gap:3px;padding:6px 8px;overflow-x:auto;scrollbar-width:none;background:#0d1a2a}
55
- .vtv-tabs::-webkit-scrollbar{display:none}
56
- .vtv-tab{padding:4px 8px;background:#1a2a3a;border:1px solid #2a3a4a;border-radius:10px;color:#8ab4d8;font-size:9px;cursor:pointer;white-space:nowrap;flex-shrink:0;transition:all .2s}
57
- .vtv-tab:hover{background:#0b4a7a;color:#fff}
58
- .vtv-tab.on{background:#0066cc;border-color:#00ccff;color:#fff;font-weight:700}
59
- .vtv-tab.off{opacity:.35}
60
- .vtv-frame{position:relative;width:100%;aspect-ratio:16/9;background:#000;min-height:180px}
61
- .vtv-frame video{position:absolute;inset:0;width:100%;height:100%;object-fit:contain}
62
- .vtv-err{display:flex;align-items:center;justify-content:center;height:180px;color:#888;font-size:12px;text-align:center;padding:20px;flex-direction:column;gap:8px}
63
- .vtv-err button{background:#0066cc;border:none;color:#fff;padding:6px 14px;border-radius:8px;font-size:11px;cursor:pointer}
64
- .vtv-load{display:flex;align-items:center;justify-content:center;height:180px;color:#00ccff;font-size:12px;flex-direction:column;gap:8px}
65
- .vtv-spinner{width:24px;height:24px;border:2px solid #333;border-top-color:#00ccff;border-radius:50%;animation:vtvspin .8s linear infinite}
66
- @keyframes vtvspin{to{transform:rotate(360deg)}}
67
- .vtv-controls{display:flex;align-items:center;gap:4px;padding:4px 8px;background:#0d1a2a;border-top:1px solid #1a2a3a}
68
- .vtv-pip-btn{background:#1a2a3a;border:1px solid #2a3a4a;color:#8ab4d8;font-size:9px;padding:3px 8px;border-radius:6px;cursor:pointer;transition:all .2s;display:flex;align-items:center;gap:4px}
69
- .vtv-pip-btn:hover{background:#0b4a7a;color:#fff}
70
- .vtv-pip-btn.on{background:#0066cc;border-color:#00ccff;color:#fff}
71
- .vtv-pip-btn svg{width:12px;height:12px;fill:currentColor}
72
- .vtv-epg{margin:0;padding:6px 10px;background:#0a1628;border-top:1px solid #1a2a3a}
73
- .vtv-epg-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:4px}
74
- .vtv-epg-title{font-size:10px;font-weight:700;color:#00ccff}
75
- .vtv-epg-toggle{background:none;border:1px solid #2a3a4a;color:#8ab4d8;font-size:9px;padding:2px 8px;border-radius:6px;cursor:pointer}
76
- .vtv-epg-list{display:flex;gap:4px;overflow-x:auto;scrollbar-width:none;padding-bottom:4px}
77
- .vtv-epg-list::-webkit-scrollbar{display:none}
78
- .vtv-epg-item{flex:0 0 auto;padding:3px 6px;background:#1a2a3a;border-radius:4px;font-size:8px;color:#8ab4d8;white-space:nowrap;cursor:pointer}
79
- .vtv-epg-item:hover{background:#2a4a6a}
80
- .vtv-epg-item.now{background:#0066cc;color:#fff;font-weight:700}
81
- .vtv-epg-item .t{font-size:7px;color:#6a8aaa}
82
- .vtv-epg-item.now .t{color:#aaccee}
83
- .vtv-epg-item .n{color:#ccc;font-size:8px}
84
- .vtv-epg-item.now .n{color:#fff}
85
- .vtv-epg-empty{color:#666;font-size:9px;padding:4px}
86
- .vtv-epg-loading{color:#00ccff;font-size:9px;padding:4px;display:flex;align-items:center;gap:6px}
87
- .vtv-epg-sp{width:10px;height:10px;border:1px solid #333;border-top-color:#00ccff;border-radius:50%;animation:vtvspin .8s linear infinite}
88
- .vtv-pin-btn{position:absolute;top:6px;right:8px;z-index:5;background:rgba(0,0,0,.5);border:1px solid #2a3a4a;color:#8ab4d8;font-size:9px;padding:2px 6px;border-radius:4px;cursor:pointer;font-weight:700;display:flex;align-items:center;gap:3px}
89
- .vtv-pin-btn:hover{background:#0b4a7a;color:#fff}
90
- .vtv-pin-btn.pinned{background:#0066cc;border-color:#00ccff;color:#fff}
91
- .vtv-wrap.vtv-sticky{position:sticky;top:0;z-index:48;transition:all .25s ease;box-shadow:0 4px 24px rgba(0,102,204,.35)}
92
- .vtv-wrap.vtv-sticky .vtv-epg{display:none}
93
- .vtv-wrap.vtv-sticky .vtv-controls{display:none}
94
- .vtv-wrap.vtv-sticky .vtv-tabs{padding:3px 8px}
95
- .vtv-wrap.vtv-sticky .vtv-tab{padding:3px 7px;font-size:8px}
96
- .vtv-wrap.vtv-sticky .vtv-frame{max-height:140px;min-height:100px}
97
- .vtv-wrap.vtv-sticky .vtv-frame video{max-height:140px}
98
- .vtv-wrap.vtv-sticky .vtv-load{height:100px}
99
- .vtv-wrap.vtv-sticky .vtv-err{height:100px}
100
- .vtv-wrap.vtv-sticky .vtv-head{padding:5px 10px}
101
- .vtv-wrap.vtv-sticky .vtv-title{font-size:11px}
102
- .vtv-wrap.vtv-sticky .vtv-badge{font-size:8px}
103
- .vtv-wrap.vtv-sticky .vtv-pin-btn{top:4px;right:6px}
104
- .vtv-rec-btn{background:#660000;border:1px solid #990000;color:#ff6666;font-size:9px;padding:3px 8px;border-radius:6px;cursor:pointer;transition:all .2s;display:flex;align-items:center;gap:4px;font-weight:700}
105
- .vtv-rec-btn:hover{background:#990000;color:#fff}
106
- .vtv-rec-btn.recording{background:#cc0000;border-color:#ff0000;color:#fff;animation:vtv-rec-pulse 1s infinite}
107
- @keyframes vtv-rec-pulse{0%,100%{opacity:1}50%{opacity:.5}}
108
- .vtv-rec-btn svg{width:12px;height:12px;fill:currentColor}
109
- .vtv-inline-rec{display:none;padding:8px 10px;background:#0a0a1a;border-top:1px solid #1a1a3a}
110
- .vtv-inline-rec.show{display:block}
111
- .vtv-inline-rec .rec-bar{position:relative;height:32px;background:#000;border-radius:4px;overflow:hidden;cursor:pointer;border:1px solid #2a2a4a;margin-bottom:6px;user-select:none}
112
- .vtv-inline-rec .rec-bar .rec-progress{position:absolute;top:0;bottom:0;background:rgba(155,89,182,.3);left:0;width:0%;pointer-events:none}
113
- .vtv-inline-rec .rec-bar .rec-marker{position:absolute;top:0;bottom:0;width:4px;z-index:2;border-radius:2px}
114
- .vtv-inline-rec .rec-bar .rec-marker.s{background:#2ecc71}
115
- .vtv-inline-rec .rec-bar .rec-marker.e{background:#e74c3c}
116
- .vtv-inline-rec .rec-time{display:flex;justify-content:space-between;font-size:9px;color:#888;margin-bottom:6px}
117
- .vtv-inline-rec .rec-controls{display:flex;gap:4px}
118
- .vtv-inline-rec .rec-controls button{flex:1;padding:6px;border:none;border-radius:6px;font-size:10px;font-weight:700;cursor:pointer}
119
- .vtv-inline-rec .rec-controls .rec-set-start{background:#1a3a1a;border:1px solid #2d6a2d;color:#5cb87a}
120
- .vtv-inline-rec .rec-controls .rec-set-end{background:#3a1a1a;border:1px solid #6a2d2d;color:#e74c3c}
121
- .vtv-inline-rec .rec-controls .rec-go{background:#1a0a3a;border:1px solid #3a2a6a;color:#9b59b6}
122
- .vtv-inline-rec .rec-controls .rec-reset{background:#222;border:1px solid #333;color:#888}
123
- .vtv-inline-rec .rec-hint{font-size:9px;color:#666;text-align:center;margin-top:4px}
124
- .vtv-inline-rec .rec-status{font-size:10px;color:#888;text-align:center;padding:4px;margin-top:4px;background:#111;border-radius:4px}
125
- .vtv-inline-rec .rec-status.ok{color:#2ecc71}
126
- .vtv-inline-rec .rec-status.err{color:#e74c3c}
127
- .vtv-inline-rec .rec-status.recording{color:#e74c3c;animation:vtv-rec-pulse 1s infinite}
128
- .vtv-rec-panel{display:none;padding:10px;background:#0d0d20;border-top:1px solid #2a1a4a}
129
- .vtv-rec-panel.show{display:block}
130
- .vtv-rec-panel .rec-panel-title{font-size:11px;font-weight:700;color:#9b59b6;margin-bottom:8px}
131
- .vtv-rec-panel .rec-preview-wrap{margin-bottom:8px;text-align:center}
132
- .vtv-rec-panel .rec-preview-wrap video{max-width:100%;max-height:180px;border-radius:6px;background:#000}
133
- .vtv-rec-panel .rec-ratio-row{display:flex;gap:4px;margin-bottom:8px}
134
- .vtv-rec-panel .rec-ratio-row button{flex:1;padding:6px;background:#1a1a2e;border:1px solid #2a2a4a;border-radius:6px;color:#888;font-size:10px;cursor:pointer}
135
- .vtv-rec-panel .rec-ratio-row button.active{border-color:#9b59b6;color:#9b59b6;background:#2a1a4a}
136
- .vtv-rec-panel .rec-actions{display:flex;gap:4px}
137
- .vtv-rec-panel .rec-actions button{flex:1;padding:8px;border:none;border-radius:6px;font-size:11px;font-weight:700;cursor:pointer}
138
- .vtv-rec-panel .rec-actions .rec-download{background:#2d8659;color:#fff}
139
- .vtv-rec-panel .rec-actions .rec-share{background:#9b59b6;color:#fff}
140
- .vtv-rec-panel .rec-proc{text-align:center;padding:12px;color:#9b59b6;font-size:12px;display:none}
141
- .vtv-rec-panel .rec-title-input{width:100%;background:#1a1a2e;border:1px solid #2a2a4a;border-radius:6px;padding:8px;color:#ccc;font-size:11px;margin-bottom:8px;box-sizing:border-box}
142
- .vtv-rec-panel .rec-title-input:focus{border-color:#9b59b6;outline:none}
143
- .vtv-rec-panel .rec-ai-title-row{display:flex;gap:4px;margin-bottom:8px}
144
- .vtv-rec-panel .rec-ai-title-row button{flex:1;padding:6px;background:#1a1a2e;border:1px solid #2a2a4a;border-radius:6px;color:#888;font-size:10px;cursor:pointer}
145
- .vtv-rec-panel .rec-ai-title-row button:hover{border-color:#9b59b6;color:#9b59b6}
146
- .vtv-rec-panel .rec-ai-title-row button:disabled{opacity:.4;cursor:not-allowed}
147
- .vtv-mini{position:fixed;top:0;left:0;right:0;z-index:99990;background:#000;border-bottom:2px solid #0066cc;box-shadow:0 4px 20px rgba(0,102,204,.4);display:none;transition:transform .3s ease}
148
- .vtv-mini.show{display:block}
149
- .vtv-mini.hidden{transform:translateY(-88%)}
150
- .vtv-mini-frame{position:relative;width:100%;aspect-ratio:16/9;background:#000;max-height:180px}
151
- .vtv-mini-frame video{position:absolute;inset:0;width:100%;height:100%;object-fit:contain}
152
- .vtv-mini-bar{display:flex;align-items:center;justify-content:space-between;padding:3px 8px;background:linear-gradient(90deg,#003366,#1a1a1a)}
153
- .vtv-mini-ch{font-size:10px;font-weight:700;color:#00ccff}
154
- .vtv-mini-epg{font-size:9px;color:#8ab4d8;max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-left:8px}
155
- .vtv-mini-btns{display:flex;gap:3px}
156
- .vtv-mini-btn{background:#1a2a3a;border:1px solid #2a3a4a;color:#8ab4d8;font-size:9px;padding:2px 6px;border-radius:4px;cursor:pointer}
157
- .vtv-mini-btn:hover{background:#0b4a7a;color:#fff}
158
- .vtv-mini-btn.x{background:#600;border-color:#900;color:#f66}
159
- .vtv-mini-btn.x:hover{background:#900;color:#fff}
160
- .vtv-mini-peek{position:absolute;bottom:-18px;right:10px;background:#0066cc;color:#fff;font-size:9px;padding:2px 8px;border-radius:0 0 6px 6px;cursor:pointer;display:none}
161
- .vtv-mini.hidden .vtv-mini-peek{display:block}
162
- .vtv-popup{position:fixed;top:0;left:0;right:0;margin:8px auto 0;background:rgba(0,0,0,.95);z-index:99999;display:none;flex-direction:column;max-height:calc(100vh - 16px);max-width:800px;border-radius:12px;overflow:hidden}
163
- .vtv-popup.show{display:flex}
164
- .vtv-popup:has(#vtv-popup-hdr[style*="none"]) .vtv-popup-frame{height:100%}
165
- .vtv-popup-header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:#111;border-bottom:1px solid #333}
166
- .vtv-popup-title{font-size:14px;font-weight:700;color:#00ccff}
167
- .vtv-popup-close{background:#333;border:none;color:#fff;font-size:18px;width:32px;height:32px;border-radius:6px;cursor:pointer}
168
- .vtv-popup-frame{flex:1;position:relative;background:#000;min-height:300px}
169
- .vtv-popup-frame iframe{position:absolute;inset:0;width:100%;height:100%;border:none}
170
- .vtv-popup-frame iframe{position:absolute;inset:0;width:100%;height:100%;border:none}
171
- .vtv-popup-loader{display:flex;align-items:center;justify-content:center;height:280px;color:#00ccff;font-size:12px;flex-direction:column;gap:8px}
172
- .vtv-popup-btn{background:#1a2a3a;border:1px solid #2a3a4a;color:#8ab4d8;font-size:9px;padding:3px 8px;border-radius:6px;cursor:pointer;margin-left:4px}
173
- .vtv-popup-btn:hover{background:#0b4a7a;color:#fff}
174
- `;
175
- document.head.appendChild(style);
 
1
+ // ===== VNEWS — VTV LIVE + Inline Recorder (v9) =====
2
+ // NOTE: This file was truncated during a previous edit and broke page load.
3
+ // All VTV player functionality now lives in /static/vtv_init.js (v11).
4
+ // This stub keeps any legacy references working without errors.
5
+ (function() {
6
+ 'use strict';
7
+ if (window._vtvLiveStubLoaded) return;
8
+ window._vtvLiveStubLoaded = true;
9
+ // Legacy function names that other modules may check via typeof guards.
10
+ window.initYTLive = window.initYTLive || function() {};
11
+ window.openYTLive = window.openYTLive || function() {};
12
+ window.toggleYTLive = window.toggleYTLive || function() {};
13
+ })();