Files
tvbox_collect/recha18/drpy_libs/live2vod4.js
T
2026-07-11 04:45:19 +00:00

495 lines
16 KiB
JavaScript

var globalHeaders = [];
var classes = [];
var categories = {}; // 修复:正确使用categories存储分类数据
var picUrl = 'http://hufa.zabc.net:8080/lib/dream.jpg';
var webPaths = {};
var sourceHeaders = {};
var sourceConfigs = {}; // 修复:统一使用sourceConfigs变量名
var vodSourceConfigs = {}; // 修复:复数形式,与引用处保持一致
var globalHostHeaders = {};
var processedHosts = new Set();
function initGlobalHeaders() {
for (var i = 0; i < globalHeaders.length; i++) {
var config = globalHeaders[i];
if (config.host && config.header) globalHostHeaders[config.host] = config.header;
}
}
function extractHostFromUrl(url) {
try {
var urlObj = new URL(url);
return urlObj.host;
} catch (error) {
var match = url.match(/:\/\/([^\/]+)/);
return match ? match[1] : null;
}
}
function addToGlobalHeaders(host, headers) {
if (!host || !headers || Object.keys(headers).length === 0) return;
var exists = false;
for (var i = 0; i < globalHeaders.length; i++) {
if (globalHeaders[i].host === host) {
exists = true;
break;
}
}
if (!exists) {
globalHeaders.push({ "host": host, "header": headers });
globalHostHeaders[host] = headers;
}
}
function getHeadersForUrl(url) {
var resultHeaders = {};
try {
var urlObj = new URL(url);
var host = urlObj.host;
if (globalHostHeaders[host]) {
resultHeaders = Object.assign({}, globalHostHeaders[host]);
} else {
for (var pattern in globalHostHeaders) {
if (pattern.includes('*') && url.includes(pattern.replace(':*', ''))) {
resultHeaders = Object.assign({}, globalHostHeaders[pattern]);
break;
} else if (url.includes(pattern)) {
resultHeaders = Object.assign({}, globalHostHeaders[pattern]);
break;
}
}
}
} catch (error) {
for (var pattern in globalHostHeaders) {
if (url.includes(pattern.replace(':*', ''))) {
resultHeaders = Object.assign({}, globalHostHeaders[pattern]);
break;
}
}
}
return resultHeaders;
}
function getPlayHeaders(playUrl, sourceConfig) {
var playHeaders = getHeadersForUrl(playUrl);
var hasGlobalHeaders = Object.keys(playHeaders).length > 0;
if (!hasGlobalHeaders && sourceConfig && sourceConfig.headers && Object.keys(sourceConfig.headers).length > 0) {
playHeaders = Object.assign({}, playHeaders, sourceConfig.headers);
}
return playHeaders;
}
function init(inputData) {
initGlobalHeaders();
try {
var parsedData = JSON.parse(inputData.trim());
var configs = extractLivesConfig(parsedData);
if (configs && configs.length > 0) {
for (var i = 0; i < configs.length; i++) {
var config = normalizeConfig(configs[i]);
if (config.host) continue;
var typeId = config.name + '$' + config.url;
var typeName = config.name;
classes.push({ 'type_id': typeId, 'type_name': typeName });
if (config.headers && Object.keys(config.headers).length > 0) {
sourceHeaders[typeId] = config.headers;
sourceConfigs[typeId] = { headers: config.headers, play_parse: config.play_parse || false };
if (config.url) {
var hostFromUrl = extractHostFromUrl(config.url);
if (hostFromUrl && !processedHosts.has(hostFromUrl)) {
addToGlobalHeaders(hostFromUrl, config.headers);
processedHosts.add(hostFromUrl);
}
}
} else {
sourceConfigs[typeId] = { headers: {}, play_parse: config.play_parse || false };
}
}
return;
}
} catch (error) {
console.error('JSON解析错误:', error);
}
var baseUrl = '';
if (inputData.indexOf('$$$') > 0) {
baseUrl = inputData.split('$$$')[0].trim();
inputData = inputData.split('$$$')[1].trim();
}
if (inputData.indexOf('&&&') > 0) {
inputData = inputData.split('&&&')[0].trim();
}
var parts = inputData.split('#');
for (var j = 0; j < parts.length; j++) {
var part = parts[j];
if (part.indexOf('$') > 0) {
var typeId = part;
var typeName = part.split('$')[0];
if (typeId.indexOf('://') < 0) {
typeId = typeId.replace('$', '$' + baseUrl);
}
classes.push({ 'type_id': typeId, 'type_name': typeName.replace('!!', '') });
} else {
var url = part;
if (url.indexOf('://') < 0) {
url = baseUrl + url;
}
var requestHeaders = getHeadersForUrl(url);
try {
var response = req(url, { 'method': 'GET', 'headers': requestHeaders });
var data = JSON.parse(response.content);
var pathPrefix = url.substring(0, url.lastIndexOf('/') + 1);
for (var k = 0; k < data.length; k++) {
var item = data[k];
var itemName = item.name;
var itemUrl = item.url;
var itemTypeId = itemName + '$' + (itemUrl.indexOf('://') < 0 ? pathPrefix : '') + itemUrl;
classes.push({ 'type_id': itemTypeId, 'type_name': itemName.replace('!!', '') });
var normalizedItem = normalizeConfig(item);
if (normalizedItem.headers && Object.keys(normalizedItem.headers).length > 0) {
sourceHeaders[itemTypeId] = normalizedItem.headers;
sourceConfigs[itemTypeId] = normalizedItem;
}
}
} catch (error) {
console.error('加载二级数据错误:', error);
}
}
}
}
function extractLivesConfig(parsedData) {
if (Array.isArray(parsedData)) {
return parsedData;
}
if (typeof parsedData === 'object' && parsedData !== null) {
var livesKey = Object.keys(parsedData).find(key => key.toLowerCase() === 'lives');
if (livesKey && Array.isArray(parsedData[livesKey])) {
return parsedData[livesKey];
}
}
return null;
}
function normalizeConfig(config) {
var normalized = Object.assign({}, config);
if (config.ua && typeof config.ua === 'string') {
if (!normalized.headers) {
normalized.headers = {};
}
normalized.headers['User-Agent'] = config.ua;
delete normalized.ua;
}
if (config.header && typeof config.header === 'object') {
if (!normalized.headers) {
normalized.headers = {};
}
Object.assign(normalized.headers, config.header);
delete normalized.header;
}
/* 保留 img 供后面取 */
if (config.img) normalized.img = config.img;
return normalized;
}
function home(param) {
return JSON.stringify({
'class': classes,
'filters': null
});
}
function homeVod(param) {
if (classes.length === 0) return JSON.stringify({ 'list': [] });
var data = getCategoryData(classes[0].type_id);
return JSON.stringify({
'list': data
});
}
function category(categoryId, page, filter, extend) {
var data = [];
if (page == 1) {
data = getCategoryData(categoryId);
}
return JSON.stringify({
'list': data
});
}
function getCategoryData(categoryId) {
var urlPart = categoryId.split('$')[1];
var namePart = categoryId.split('$')[0];
if (!categories[categoryId]) {
categories[categoryId] = [];
var requestHeaders = getHeadersForUrl(urlPart);
if (sourceHeaders[categoryId] && Object.keys(sourceHeaders[categoryId]).length > 0) {
requestHeaders = Object.assign({}, requestHeaders, sourceHeaders[categoryId]);
}
if (urlPart.indexOf('|') > 0) {
var paramsStr = decodeURIComponent(urlPart.split('|')[1]);
urlPart = urlPart.split('|')[0];
var params = paramsStr.split('&');
for (var l = 0; l < params.length; l++) {
var param = params[l];
if (param.indexOf('=') > 0) {
var key = param.split('=')[0];
var value = param.split('=')[1];
requestHeaders[key] = value;
}
}
}
try {
var response = req(urlPart, {
'method': 'GET',
'headers': requestHeaders
});
var responseContent = response.content.trim();
var parsedContent = '';
if (responseContent.indexOf('#EXTM3U') >= 0) {
parsedContent = parseM3u(responseContent, namePart);
} else if (responseContent.indexOf('"channel"') > 0 && responseContent.indexOf('"urls"') > 0) {
parsedContent = parseFm(responseContent);
} else if (responseContent.indexOf('"datalist"') > 0 && responseContent.indexOf('"urls"') > 0) {
parsedContent = parseList(responseContent);
} else {
parsedContent = responseContent;
}
parseContent(parsedContent, categoryId, namePart, picUrl);
} catch (error) {
console.error('获取分类数据失败:', error, '分类ID:', categoryId);
}
}
return categories[categoryId];
}
function parseContent(content, categoryId, typeName, imageUrl) {
var lines = (typeName + '\n' + content.replace('\r', '')).split('\n');
var currentCategory = typeName;
var currentUrls = '';
for (var m = 0; m < lines.length; m++) {
var line = lines[m].replace(/\s+/g, '');
if (line != '' && line.indexOf('://') < 0 && (line.indexOf(',') < 0 || line.indexOf('#genre#') > 0)) {
if (currentUrls != '') {
saveCategoryItem(categoryId, currentCategory, currentUrls, typeName, imageUrl);
}
currentCategory = line.split(',')[0].trim();
currentUrls = '';
} else if (line.indexOf(',') > 0 && /http|rtmp|rtsp|rsp/.test(line)) {
var parts = line.split(',');
var channelName = parts[0].trim();
var channelUrl = parts[1].trim();
if (channelUrl && sourceHeaders[categoryId] && Object.keys(sourceHeaders[categoryId]).length > 0) {
var secondaryHost = extractHostFromUrl(channelUrl);
if (secondaryHost && !processedHosts.has(secondaryHost)) {
addToGlobalHeaders(secondaryHost, sourceHeaders[categoryId]);
processedHosts.add(secondaryHost);
}
}
if (currentUrls != '') {
currentUrls += '#';
}
currentUrls += channelName + '$' + channelUrl;
}
}
if (currentUrls != '') {
saveCategoryItem(categoryId, currentCategory, currentUrls, typeName, imageUrl);
}
return lines;
}
function saveCategoryItem(categoryId, categoryName, urls, typeName, imageUrl) {
/* ★★★ 唯一改动:用当前源 img,不存在再用默认 ★★★ */
var cfg = sourceConfigs[categoryId] || {};
var processedImageUrl = cfg.img || picUrl;
var vodId = categoryId + '$$$' + categories[categoryId].length;
vodSourceConfigs[vodId] = {
sourceHeaders: sourceHeaders[categoryId] || {},
sourceConfig: sourceConfigs[categoryId] || {},
categoryId: categoryId
};
var item = {
'vod_id': vodId,
'vod_name': categoryName,
'vod_pic': processedImageUrl, // ★ 这里已换成各自 img
'vod_remarks': '',
'type_name': '',
'vod_year': '',
'vod_area': '',
'vod_actor': '',
'vod_director': '',
'vod_content': '',
'vod_play_from': typeName,
'vod_play_url': urls
};
categories[categoryId].push(item);
}
function parseM3u(content, categoryName) {
var result = {};
var regex = /(#EXTINF:.+?),([^,]+?)\s*\n(.+?)\s*\n/g;
var match;
while ((match = regex.exec(content)) !== null) {
var infTag = match[1];
var name = match[2];
var url = match[3];
if (!name || !url || name == '' || url == '') continue;
name = name.trim();
url = url.trim();
var group = categoryName;
var groupRegex = /group-title="(.*?)"/;
if (groupRegex.test(infTag)) {
group = infTag.match(groupRegex)[1];
}
if (!result[group]) result[group] = [];
result[group].push(name + ',' + url);
}
var output = '';
for (var group in result) {
if (result.hasOwnProperty(group)) {
output += group + '\n';
result[group].forEach(item => output += item + '\n');
}
}
return output;
}
function parseFm(content) {
var output = '';
try {
var data = JSON.parse(content);
data.forEach(item => {
var channelName = item.name;
var urls = item.urls;
output += channelName + ',#genre#\n';
urls.forEach(urlItem => {
var itemName = urlItem.name;
urlItem.datalist.forEach(url => {
output += itemName + ',' + url + '\n';
});
});
});
} catch (error) {
console.error('解析Fm数据错误:', error);
}
return output;
}
function parseList(content) {
var output = '';
try {
var data = JSON.parse(content).data;
data.list.forEach(item => {
var channelName = item.prov;
var programs = item.list;
output += channelName + ',#genre#\n';
programs.forEach(program => {
var programName = program.name;
program.datalist.forEach(urlItem => {
output += programName + ' ===>>> ' + urlItem.vod_play_from + ',' + urlItem.vod_play_url + '\n';
});
});
});
} catch (error) {
console.error('解析List数据错误:', error);
}
return output;
}
function detail(detailId) {
var parts = detailId.split('$$$');
var categoryId = parts[0];
var index = parseInt(parts[1]);
if (!categories[categoryId] || !categories[categoryId][index]) {
return JSON.stringify({ 'list': [] });
}
var detailData = categories[categoryId][index];
var itemId = categoryId.split('$')[0];
if (itemId.indexOf('!!') >= 0) {
itemId = itemId.replace('!!', '');
var urls = detailData.vod_play_url.split('#');
var countMap = {};
var groupMap = {};
urls.forEach(url => {
var namePart = url.split('$')[0];
var displayName = itemId;
if (namePart.indexOf(' ===>>> ') > 0) {
displayName = namePart.split(' ===>>> ')[1];
namePart = namePart.split(' ===>>> ')[0];
}
countMap[namePart] = (countMap[namePart] || 0) + 1;
displayName = itemId + (countMap[namePart] > 1 ? ' ' + countMap[namePart] : '');
if (!groupMap[displayName]) groupMap[displayName] = [];
groupMap[displayName].push(namePart + '$' + url.split('$')[1]);
});
var groupNames = Object.keys(groupMap);
var groupUrls = groupNames.map(name => groupMap[name].join('#'));
detailData.vod_play_from = groupNames.join('$$$');
detailData.vod_play_url = groupUrls.join('$$$');
}
return JSON.stringify({
'list': [detailData]
});
}
function play(playId, playUrl, param) {
var parse = 0;
var sourceConfig = null;
if (vodSourceConfigs[playId]) {
var vodConfig = vodSourceConfigs[playId];
sourceConfig = vodConfig.sourceConfig;
if (vodConfig.sourceConfig && vodConfig.sourceConfig.play_parse !== undefined) {
parse = vodConfig.sourceConfig.play_parse ? 1 : 0;
}
}
var playHeaders = getPlayHeaders(playUrl, sourceConfig);
return JSON.stringify({
'parse': parse,
'url': playUrl,
'header': playHeaders,
'js': '',
'extra': {}
});
}
function search(keyword, param) {
return JSON.stringify({ 'list': [] });
}
__JS_SPIDER__ = {
'init': init,
'home': home,
'homeVod': homeVod,
'category': category,
'detail': detail,
'play': play,
'search': search
};