You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bhmb/TVBoxOSC/cctvnews.js

152 lines
5.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

const CryptoJS = require("crypto");
function main(item) {
// 重试机制
for (let attempt = 0; attempt < 3; attempt++) {
try {
const id = item.id || 'cctv1';
const n = {
'cctv1': '11200132825562653886',
'cctv2': '12030532124776958103',
'cctv4': '10620168294224708952',
'cctv7': '8516529981177953694',
'cctv9': '7252237247689203957',
'cctv10': '14589146016461298119',
'cctv12': '13180385922471124325',
'cctv13': '16265686808730585228',
'cctv17': '4496917190172866934',
'cctv4k': '2127841942201075403',
};
const articleId = n[id];
if (!articleId) {
return {
url: null,
error: `不支持的频道ID: ${id}`,
success: false
};
}
const t = Math.floor(Date.now() / 1000);
const sail = ku9.md5(`articleId=${articleId}&scene_type=6`);
const w = `&&&20000009&${sail}&${t}&emas.feed.article.live.detail&1.0.0&&&&&`;
const k = "emasgatewayh5";
const sign = CryptoJS.HmacSHA256(w, k).toString();
const url = `https://emas-api.cctvnews.cctv.com/h5/emas.feed.article.live.detail/1.0.0?articleId=${articleId}&scene_type=6`;
const client_id = ku9.md5(t.toString());
const headers = {
'cookieuid': client_id,
'from-client': 'h5',
'referer': 'https://m-live.cctvnews.cctv.com/',
'x-emas-gw-appkey': '20000009',
'x-emas-gw-pv': '6.1',
'x-emas-gw-sign': sign,
'x-emas-gw-t': t,
'x-req-ts': t * 1000
};
const res = ku9.get(url, headers);
if (!res) {
if (attempt < 2) continue; // 重试
return {
url: null,
error: '网络请求失败',
success: false
};
}
const responseData = JSON.parse(res);
if (!responseData || !responseData.response) {
if (attempt < 2) continue; // 重试
return {
url: null,
error: 'API返回数据格式错误',
success: false
};
}
const decodedData = JSON.parse(ku9.decodeBase64(responseData.response));
if (!decodedData || !decodedData.data) {
if (attempt < 2) continue; // 重试
return {
url: null,
error: '解码后的数据格式错误',
success: false
};
}
const data = decodedData.data;
// 使用安全访问函数避免直接访问可能为null的属性
const getSafeValue = (obj, path, defaultValue = null) => {
const keys = path.split('.');
let result = obj;
for (const key of keys) {
if (result === null || result === undefined) return defaultValue;
// 处理数组索引
if (key.includes('[') && key.includes(']')) {
const arrayKey = key.split('[')[0];
const index = parseInt(key.split('[')[1].split(']')[0]);
if (!Array.isArray(result[arrayKey]) || index >= result[arrayKey].length) {
return defaultValue;
}
result = result[arrayKey][index];
} else {
result = result[key];
}
}
return result === null || result === undefined ? defaultValue : result;
};
// 安全获取认证URL
const authUrl = getSafeValue(data, 'live_room.liveCameraList[0].pullUrlList[0].authResultUrl[0].authUrl');
if (!authUrl) {
if (attempt < 2) continue; // 重试
return {
url: null,
error: '无法获取认证URL可能该频道当前无直播',
success: false
};
}
const dk = getSafeValue(data, 'dk');
if (!dk) {
if (attempt < 2) continue; // 重试
return {
url: null,
error: '缺少解密密钥(dk)',
success: false
};
}
const key = dk.substring(0, 8) + t.toString().substring(t.toString().length - 8);
const iv = dk.substring(dk.length - 8) + t.toString().substring(0, 8);
const decrypted = ku9.opensslDecrypt(authUrl, "AES-128-CBC", key, 0, iv);
if (!decrypted) {
if (attempt < 2) continue; // 重试
return {
url: null,
error: 'URL解密失败',
success: false
};
}
return {
url: decrypted,
success: true
};
} catch (error) {
// 最后一次尝试仍然失败,返回错误
if (attempt === 2) {
return {
url: null,
error: `执行错误: ${error.message}`,
success: false
};
}
// 否则继续重试
}
}
}