150 lines
6.7 KiB
JavaScript
150 lines
6.7 KiB
JavaScript
let host = 'https://a123tv.com';
|
|
let headers = {
|
|
'User-Agent': 'Mozilla/5.0 (Linux; Android 13; M2102J2SC Build/TKQ1.221114.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/144.0.7559.31 Mobile Safari/537.36',
|
|
'Referer': host
|
|
};
|
|
|
|
function getList(html) {
|
|
let videos = [];
|
|
pdfa(html, '.w4-item-wrap').forEach(it => {
|
|
const id = pdfh(it, 'a.w4-item&&href') || '',
|
|
name = pdfh(it, 'img&&alt') || '',
|
|
pic = pdfh(it, 'img&&data-src') || pdfh(it, 'img&&src') || '',
|
|
remark = pdfh(it, '.w4-item-cover .s span&&Text') || '';
|
|
if (id && name) {
|
|
let vod_pic = pic.startsWith('//') ? `https:${pic}` : pic.startsWith('/') ? `${host}${pic}` : pic;
|
|
vod_pic = vod_pic || 'data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=';
|
|
videos.push({
|
|
vod_id: id.replace(host, '').replace(/^\//, ''),
|
|
vod_name: name.trim(),
|
|
vod_pic,
|
|
vod_remarks: remark.trim()
|
|
});
|
|
}
|
|
});
|
|
return videos;
|
|
}
|
|
|
|
async function init(cfg) {}
|
|
async function home(filter) {
|
|
return JSON.stringify({
|
|
class: [{ "type_id": "10", "type_name": "电影" }, { "type_id": "11", "type_name": "连续剧" },
|
|
{ "type_id": "12", "type_name": "综艺" }, { "type_id": "13", "type_name": "动漫" },
|
|
{ "type_id": "15", "type_name": "福利" }],
|
|
filters: {}
|
|
});
|
|
}
|
|
async function homeVod() {
|
|
let resp = await req(host, { headers });
|
|
return JSON.stringify({ list: getList(resp.content) });
|
|
}
|
|
async function category(tid, pg, filter, extend) {
|
|
let p = parseInt(pg) || 1;
|
|
let resp = await req(`${host}/t/${tid}/p${p}.html`, { headers });
|
|
return JSON.stringify({ list: getList(resp.content), page: p, pagecount: p + 5, limit: 20 });
|
|
}
|
|
|
|
async function detail(id) {
|
|
const playFrom = [], playList = [];
|
|
let detailUrl = id.startsWith('http') ? id : `${host}/${id.replace(/^\//, '')}`;
|
|
let { content: html = '' } = await req(detailUrl, { headers });
|
|
|
|
// 基础信息
|
|
let vod_name = (pdfh(html, 'li.on h1&&Text') || pdfh(html, 'h1.title&&Text') || '未知片名').trim();
|
|
let vod_pic = pdfh(html, '#awp1&&data-poster') || '';
|
|
vod_pic = vod_pic.startsWith('//') ? `https:${vod_pic}` : vod_pic.startsWith('/') ? `${host}${vod_pic}` : vod_pic;
|
|
let vod_remarks = pdfh(html, '.w4-line-cover .i&&Text')?.split(' / ')[1] || '720p';
|
|
|
|
// 解析meta中的导演/演员/地区/年代/类型/简介
|
|
let vod_area = '', vod_year = '', type_name = '', vod_actor = '', vod_director = '', vod_content = '';
|
|
// 提取description
|
|
const descMatch = html.match(/<meta name="description" content="([^"]+)"[^>]*>/i);
|
|
const descText = descMatch ? descMatch[1] : '';
|
|
// 从标题提取类型和年代
|
|
const titleMatch = html.match(/《[^》]+》\s*-\s*([^-]+)\s*-\s*(\d+)年/i);
|
|
if (titleMatch) {
|
|
type_name = titleMatch[1].trim();
|
|
vod_year = titleMatch[2].trim();
|
|
}
|
|
// 解析描述中的地区、导演、演员、剧情
|
|
if (descText) {
|
|
const areaMatch = descText.match(/地区:([^。]+)。/);
|
|
const dirMatch = descText.match(/导演:([^。]+)。/);
|
|
const actorMatch = descText.match(/演员:([^。]+)。/);
|
|
const contentMatch = descText.match(/剧情:([\s\S]+)/);
|
|
|
|
vod_area = areaMatch ? areaMatch[1].trim() : '';
|
|
vod_director = dirMatch ? dirMatch[1].trim().replace(/、/g, '/') : '';
|
|
vod_actor = actorMatch ? actorMatch[1].trim().replace(/、/g, '/') : '';
|
|
vod_content = contentMatch ? contentMatch[1].trim() : descText;
|
|
}
|
|
|
|
const ppMatch = html.match(/var\s+pp\s*=\s*({[\s\S]*?});/);
|
|
if (ppMatch) {
|
|
const { la = [] } = JSON.parse(ppMatch[1]);
|
|
const episodeNames = pdfa(html, '.w4-episode-list .w a').map((a, i) =>
|
|
(pdfh(a, 'a&&Text') || pdfh(a, 'a&&title') || `第${i+1}集`).trim()
|
|
);
|
|
|
|
la.forEach((item, index) => {
|
|
if (Array.isArray(item) && item.length >= 5) {
|
|
const [, , episodeNum, , m3u8] = item;
|
|
const realEpNum = parseInt(episodeNum) || episodeNames.length;
|
|
const lineEpisodes = [];
|
|
for (let i = 0; i < realEpNum; i++) {
|
|
let epName = episodeNames[i] || `第${i+1}集`;
|
|
let realM3u8 = m3u8.startsWith('//') ? `https:${m3u8}` : m3u8;
|
|
lineEpisodes.push(`${epName}$${realM3u8}`);
|
|
}
|
|
playFrom.push(`✨推荐✨${index + 1}`);
|
|
playList.push(lineEpisodes.join('#'));
|
|
}
|
|
});
|
|
}
|
|
|
|
return JSON.stringify({
|
|
list: [{
|
|
vod_id: id, vod_name, vod_pic, vod_remarks, vod_year, vod_area,
|
|
type_name, vod_actor, vod_director, vod_content,
|
|
vod_play_from: playFrom.join('$$$'), vod_play_url: playList.join('$$$')
|
|
}]
|
|
});
|
|
}
|
|
|
|
async function search(wd, quick, pg) {
|
|
let p = parseInt(pg) || 1;
|
|
let resp = await req(`${host}/s/${encodeURIComponent(wd)}/p${p}.html`, { headers });
|
|
return JSON.stringify({ list: getList(resp.content), page: p, pagecount: p + 5, limit: 20 });
|
|
}
|
|
|
|
async function play(flag, id, flags) {
|
|
let url = id.startsWith('http') ? id : `${host}/${id.replace(/^\//, '')}`;
|
|
let { content: html = '' } = await req(url, { headers });
|
|
|
|
const playerVarMatch = html.match(/var\s+player_aaaa\s*=\s*({[^;]+});/);
|
|
if (playerVarMatch) {
|
|
let jsonStr = playerVarMatch[1].replace(/(\w+):/g, '"$1":').replace(/\\/g, '');
|
|
let { url: playUrl } = JSON.parse(jsonStr);
|
|
if (playUrl) return JSON.stringify({ parse: playUrl.includes('.m3u8') ? 0 : 1, url: playUrl, header: headers });
|
|
}
|
|
|
|
let m3u8Match = html.match(/"url":"([^"]+\.m3u8(\?[^"]*)?)"/) || html.match(/'url':'([^']+\.m3u8(\?[^']*)?)'/) ||
|
|
html.match(/"(https?:\/\/[^"]+\.m3u8[^"]*)"/) || html.match(/'(https?:\/\/[^']+\.m3u8[^']*)'/) ||
|
|
html.match(/https?:\/\/[^\s"]+\.m3u8[^\s"]*/);
|
|
if (m3u8Match) {
|
|
let playUrl = m3u8Match[1] || m3u8Match[0];
|
|
return JSON.stringify({ parse: 0, url: playUrl.replace(/\\/g, ""), header: headers });
|
|
}
|
|
|
|
let iframeMatch = html.match(/<iframe[^>]*src="([^"]+)"[^>]*>/i) || html.match(/<video[^>]*src="([^"]+)"[^>]*>/i);
|
|
if (iframeMatch) {
|
|
let iframeUrl = iframeMatch[1];
|
|
iframeUrl = iframeUrl.startsWith('//') ? `https:${iframeUrl}` : !iframeUrl.startsWith('http') ? `${host}${iframeUrl.startsWith('/') ? '' : '/'}${iframeUrl}` : iframeUrl;
|
|
return JSON.stringify({ parse: 1, url: iframeUrl, header: headers });
|
|
}
|
|
|
|
return JSON.stringify({ parse: 1, url: url, header: headers });
|
|
}
|
|
|
|
export default { init, home, homeVod, category, detail, search, play };
|