-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbartv_handler.js
More file actions
234 lines (208 loc) · 10.5 KB
/
bartv_handler.js
File metadata and controls
234 lines (208 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
const BARTV_API_HOST = "core.bartv.es";
const BARTV_USER_AGENT = "Mozilla/5.0 (SMART-TV; Linux; Tizen 4.0) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/56.0.2924.0 TV Safari/537.36";
const BARTV_ORIGIN = "https://samsung.bartv.es";
const BARTV_REFERER = "https://samsung.bartv.es/";
const BARTV_LOGIN_URL = "https://core.bartv.es/v1/auth/login?partner=bares";
const BARTV_MEDIA_URL_TEMPLATE = "https://core.bartv.es/v1/media/{mediaId}?drm=widevine&token={token}&device=tv&appv=311&ll=true&partner=bares";
const CHANNEL_NAMES_BARTV = {
"24h-live": {"nombre": "LaLiga TV BAR", "logo": "https://www.movistarplus.es/recorte/m-NEO/canal/LIGBAR.png"},
"ppv-02": {"nombre": "LaLiga TV BAR 2", "logo": "https://www.movistarplus.es/recorte/m-NEO/canal/LIGBA1.png"},
"ppv-03": {"nombre": "LaLiga TV BAR 3", "logo": "https://www.movistarplus.es/recorte/m-NEO/canal/LIGBA2.png"},
"ppv-04": {"nombre": "LALIGA +", "logo": "https://ver.clictv.es/RTEFacade/images/attachments/LALIGA_PLUS_BARES.png"},
"24h-live-golstadium": {"nombre": "GOLSTADIUM", "logo": "https://pbs.twimg.com/profile_images/1814029026840793088/GPf672XK_400x400.jpg"},
"24h-live-gol": {"nombre": "GOLPLAY", "logo": "https://storage.googleapis.com/laligatvbar/assets/img/taquillas/bg-gol-black.jpg"},
"smb-24h": {"nombre": "LALIGA TV HYPERMOTION", "logo": "https://estatico.emisiondof6.com/recorte/m-NEONEGR/canal/MLIGS"},
"smb-02": {"nombre": "LALIGA TV HYPERMOTION 2", "logo": "https://estatico.emisiondof6.com/recorte/m-NEONEGR/canal/MLIGS2"},
"smb-03": {"nombre": "LALIGA TV HYPERMOTION 3", "logo": "https://estatico.emisiondof6.com/recorte/m-NEONEGR/canal/MLIGS3"},
"dazn-00": {"nombre": "DAZN F1", "logo": "https://ver.clictv.es/RTEFacade/images/attachments/DAZN F1.png"},
"dazn-01": {"nombre": "DAZN 1", "logo": "https://ver.clictv.es/RTEFacade/images/attachments/DAZN1.png"},
"dazn-02": {"nombre": "DAZN 2", "logo": "https://ver.clictv.es/RTEFacade/images/attachments/DAZN2.png"},
"euro-01": {"nombre": "EUROSPORT 1", "logo": "https://storage.googleapis.com/laligatvbar/assets/img/taquillas/eurosport-1.jpg"},
"euro-02": {"nombre": "EUROSPORT 2", "logo": "https://storage.googleapis.com/laligatvbar/assets/img/taquillas/eurosport-2.jpg"},
};
async function setDynamicHeadersBarTv(specificHeadersArray) {
if (!chrome.runtime?.id) return false;
try {
await new Promise((resolve, reject) => {
chrome.runtime.sendMessage({
cmd: "updateHeadersRules",
requestHeaders: specificHeadersArray,
urlFilter: `*://${BARTV_API_HOST}/*`,
initiatorDomain: chrome.runtime.id
}, (response) => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
} else if (response && response.success) {
resolve(response);
} else {
reject(response ? response.error : 'Fallo al actualizar reglas DNR para BarTV.');
}
});
});
await new Promise(resolve => setTimeout(resolve, 200));
return true;
} catch (error) {
console.error("[BarTV] Error estableciendo cabeceras dinámicas globales:", error);
if (typeof showNotification === 'function') showNotification("Error configurando cabeceras de red para BarTV.", "error");
return false;
}
}
async function clearDynamicHeadersBarTv() {
if (!chrome.runtime?.id) return;
try {
await new Promise((resolve, reject) => {
chrome.runtime.sendMessage({ cmd: "clearAllDnrHeaders" }, (response) => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
} else if (response && response.success) {
resolve(response);
} else {
reject(response ? response.error : 'Fallo al limpiar reglas DNR tras BarTV.');
}
});
});
} catch (error) {
console.error("[BarTV] Error limpiando cabeceras dinámicas globales:", error);
}
}
async function loginBarTv(email, password) {
const loginHeaders = {
"Content-Type": "application/json; charset=UTF-8",
"Host": BARTV_API_HOST,
"Origin": BARTV_ORIGIN,
"Referer": BARTV_REFERER,
"User-Agent": BARTV_USER_AGENT
};
const dnrHeaders = Object.entries(loginHeaders).map(([key, value]) => ({ header: key, value: value }));
if (!await setDynamicHeadersBarTv(dnrHeaders)) {
throw new Error("No se pudieron establecer cabeceras para login BarTV.");
}
try {
const response = await fetch(BARTV_LOGIN_URL, {
method: 'POST',
body: JSON.stringify({ email, password })
});
if (!response.ok) {
throw new Error(`HTTP error en login BarTV: ${response.status}`);
}
const data = await response.json();
if (data && data.success && data.success.token) {
return data.success.token;
} else {
throw new Error("Login BarTV fallido o formato de respuesta inesperado.");
}
} finally {
}
}
async function fetchBarTvChannelDetails(mediaId, token) {
const url = BARTV_MEDIA_URL_TEMPLATE.replace("{mediaId}", mediaId).replace("{token}", token);
const fetchHeaders = {
"Host": BARTV_API_HOST,
"Origin": BARTV_ORIGIN,
"Referer": BARTV_REFERER,
"User-Agent": BARTV_USER_AGENT
};
const dnrHeaders = Object.entries(fetchHeaders).map(([key, value]) => ({ header: key, value: value }));
if (!await setDynamicHeadersBarTv(dnrHeaders)) {
throw new Error(`No se pudieron establecer cabeceras para obtener detalles del canal ${mediaId}.`);
}
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error ${response.status} para ${mediaId}`);
}
const data = await response.json();
if (data.manifestUrl && data.protData && data.protData.licenseUrl) {
return {
manifestUrl: data.manifestUrl,
licenseUrl: data.protData.licenseUrl
};
} else {
throw new Error(`Datos incompletos para ${mediaId}`);
}
} finally {
}
}
async function generateM3uBarTv() {
if (typeof showLoading === 'function') showLoading(true, "Cargando canales de BarTV...");
const barTvSourceName = "BarTV";
let headersSetSuccessfully = false;
try {
const email = userSettings.barTvEmail;
const password = userSettings.barTvPassword;
if (!email || !password) {
if (typeof showNotification === 'function') showNotification("Credenciales de BarTV no configuradas en Ajustes.", "warning");
throw new Error("Credenciales BarTV no configuradas.");
}
const token = await loginBarTv(email, password);
headersSetSuccessfully = true;
if (typeof showNotification === 'function') showNotification("Login en BarTV exitoso.", "success");
const channelDetailsPromises = [];
for (const mediaId in CHANNEL_NAMES_BARTV) {
channelDetailsPromises.push(
fetchBarTvChannelDetails(mediaId, token)
.then(details => ({ ...details, mediaId, ...CHANNEL_NAMES_BARTV[mediaId] }))
.catch(e => {
console.warn(`Error obteniendo detalles para ${CHANNEL_NAMES_BARTV[mediaId].nombre}: ${e.message}`);
return null;
})
);
await new Promise(resolve => setTimeout(resolve, 300));
}
const allChannelData = (await Promise.all(channelDetailsPromises)).filter(Boolean);
if (allChannelData.length === 0) {
throw new Error("No se pudieron obtener detalles para ningún canal de BarTV.");
}
if (typeof showNotification === 'function') showNotification(`Obtenidos ${allChannelData.length} canales de BarTV.`, "info");
let globalLicenseJwt = null;
if (allChannelData.length > 0) {
try {
const lastLicenseUrl = allChannelData[allChannelData.length - 1].licenseUrl;
const parsedUrl = new URL(lastLicenseUrl);
globalLicenseJwt = parsedUrl.searchParams.get("license");
} catch (e) {
console.warn("No se pudo extraer JWT global de la última licencia:", e);
}
}
if (!globalLicenseJwt) {
console.warn("No se pudo obtener un JWT de licencia global. Las licencias podrían no funcionar.");
}
const m3uLines = ["#EXTM3U"];
allChannelData.forEach(ch => {
m3uLines.push(`#EXTINF:-1 tvg-logo="${ch.logo}" group-title="BAR TV",${ch.nombre}`);
m3uLines.push(`#EXTVLCOPT:http-user-agent=${BARTV_USER_AGENT}`);
m3uLines.push("#KODIPROP:inputstream.adaptive.manifest_type=mpd");
m3uLines.push("#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha");
let finalLicenseUrl = ch.licenseUrl;
if (globalLicenseJwt) {
try {
const parsedOriginalLicense = new URL(ch.licenseUrl);
parsedOriginalLicense.searchParams.set("license", globalLicenseJwt);
finalLicenseUrl = parsedOriginalLicense.toString();
} catch (e) {
console.warn(`Error reemplazando JWT en licencia para ${ch.nombre}, usando original: ${e}`);
}
}
m3uLines.push(`#KODIPROP:inputstream.adaptive.license_key=${finalLicenseUrl}`);
m3uLines.push(ch.manifestUrl);
});
const m3uString = m3uLines.join("\n") + "\n\n";
if (typeof removeChannelsBySourceOrigin === 'function') {
removeChannelsBySourceOrigin(barTvSourceName);
}
if (typeof appendM3UContent === 'function') {
appendM3UContent(m3uString, barTvSourceName);
} else {
console.error("appendM3UContent no encontrada. Usando fallback processM3UContent.");
processM3UContent(m3uString, barTvSourceName, true);
}
} catch (error) {
console.error("Error generando M3U de BarTV:", error);
if (typeof showNotification === 'function') showNotification(`Error cargando BarTV: ${error.message}`, 'error');
} finally {
if (headersSetSuccessfully) {
await clearDynamicHeadersBarTv();
}
if (typeof showLoading === 'function') showLoading(false);
}
}