164 lines
4.5 KiB
JavaScript
164 lines
4.5 KiB
JavaScript
import req from '../../util/req.js';
|
|
import { load } from 'cheerio';
|
|
|
|
const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0';
|
|
const SITE = 'https://rou.video';
|
|
|
|
async function request(reqUrl) {
|
|
const resp = await req.get(reqUrl, {
|
|
headers: {
|
|
'User-Agent': UA,
|
|
},
|
|
});
|
|
return resp.data;
|
|
}
|
|
|
|
async function home(_inReq, _outResp) {
|
|
let classes = [
|
|
{ type_id: 'https://rou.video/v', type_name: '全部' },
|
|
{ type_id: 'https://rou.video/t/國產AV', type_name: '國產' },
|
|
{ type_id: 'https://rou.video/t/探花', type_name: '探花' },
|
|
{ type_id: 'https://rou.video/t/自拍流出', type_name: '自拍' },
|
|
{ type_id: 'https://rou.video/t/OnlyFans', type_name: 'OnlyFans' },
|
|
{ type_id: 'https://rou.video/t/日本', type_name: '日本' },
|
|
];
|
|
return {
|
|
class: classes,
|
|
};
|
|
}
|
|
|
|
async function category(inReq, _outResp) {
|
|
const tid = inReq.body.id;
|
|
const pg = inReq.body.page;
|
|
// const extend = inReq.body.filters;
|
|
let page = pg || 1;
|
|
if (page == 0) page = 1;
|
|
|
|
let reqUrl = tid;
|
|
if (page > 1) {
|
|
reqUrl += `?order=createdAt&page=${page}`;
|
|
}
|
|
|
|
const html = await request(reqUrl);
|
|
const $ = load(html);
|
|
let videos = [];
|
|
$('.grid.grid-cols-2.mb-6 > div').each((_, element) => {
|
|
if ($(element).find('.relative').length == 0) return;
|
|
const href = $(element).find('.relative a').attr('href');
|
|
const vodName = $(element).find('img:last').attr('alt');
|
|
const vodPic = $(element).find('img').attr('src');
|
|
const subTitle = $(element).find('.relative a > div:eq(1)').text();
|
|
const hdinfo = $(element).find('.relative a > div:first').text();
|
|
videos.push({
|
|
vod_id: SITE + href,
|
|
vod_name: vodName,
|
|
vod_pic: vodPic,
|
|
vod_remarks: subTitle || hdinfo,
|
|
});
|
|
});
|
|
|
|
return {
|
|
page: page,
|
|
pagecount: videos.length < 12 ? page : page + 1,
|
|
list: videos,
|
|
// filter logic placeholder
|
|
filter: [],
|
|
};
|
|
}
|
|
|
|
async function detail(inReq, _outResp) {
|
|
const id = inReq.body.id;
|
|
// 获取播放链接
|
|
const html = await request(id, {
|
|
headers: {
|
|
'User-Agent': UA,
|
|
},
|
|
});
|
|
|
|
let playUrl = null;
|
|
const evMatch = html.match(/"ev"\s*:\s*(\{[\s\S]*?"d"\s*:\s*"[^"]+"\s*,\s*"k"\s*:\s*\d+[\s\S]*?\})/);
|
|
if (evMatch) {
|
|
try {
|
|
const ev = JSON.parse(evMatch[1]);
|
|
const decoded = Buffer.from(ev.d, 'base64');
|
|
const bytes = decoded.map((b) => (b - ev.k + 256) % 256);
|
|
const evData = JSON.parse(Buffer.from(bytes).toString('utf8'));
|
|
playUrl = evData.videoUrl || null;
|
|
} catch (_) {
|
|
playUrl = null;
|
|
}
|
|
}
|
|
let vod = {
|
|
vod_id: id,
|
|
vod_name: '',
|
|
vod_pic: '',
|
|
vod_play_from: '肉视频',
|
|
vod_play_url: '播放$' + playUrl,
|
|
};
|
|
|
|
return {
|
|
list: [vod],
|
|
};
|
|
}
|
|
|
|
async function play(inReq, _outResp) {
|
|
const flag = inReq.body.flag;
|
|
const id = inReq.body.id;
|
|
// 将 .jpg 替换为 .m3u8
|
|
const playUrl = id.replace('.jpg', '.m3u8');
|
|
|
|
return {
|
|
parse: 0,
|
|
url: playUrl,
|
|
header: {
|
|
'User-Agent': UA,
|
|
},
|
|
};
|
|
}
|
|
|
|
async function search(inReq, _outResp) {
|
|
const pg = inReq.body.page;
|
|
const wd = inReq.body.wd;
|
|
let page = pg || 1;
|
|
if (page == 0) page = 1;
|
|
const text = encodeURIComponent(wd);
|
|
const html = await request(`${SITE}/search?q=${text}&t=&page=${page}`);
|
|
const $ = load(html);
|
|
let videos = [];
|
|
$('.grid.grid-cols-2.mb-6 > div').each((_, element) => {
|
|
if ($(element).find('.relative').length == 0) return;
|
|
const href = $(element).find('.relative a').attr('href');
|
|
const vodName = $(element).find('img:last').attr('alt');
|
|
const vodPic = $(element).find('img').attr('src');
|
|
const subTitle = $(element).find('.relative a > div:eq(1)').text();
|
|
const hdinfo = $(element).find('.relative a > div:first').text();
|
|
videos.push({
|
|
vod_id: SITE + href,
|
|
vod_name: vodName,
|
|
vod_pic: vodPic,
|
|
vod_remarks: subTitle || hdinfo,
|
|
});
|
|
});
|
|
return {
|
|
page: page,
|
|
pagecount: videos.length < 12 ? page : page + 1,
|
|
list: videos,
|
|
};
|
|
}
|
|
|
|
export default {
|
|
meta: {
|
|
key: 'rou',
|
|
name: '肉视频',
|
|
type: 3,
|
|
},
|
|
api: async (fastify) => {
|
|
fastify.post('/init', async () => ({}));
|
|
fastify.post('/home', home);
|
|
fastify.post('/category', category);
|
|
fastify.post('/detail', detail);
|
|
fastify.post('/play', play);
|
|
fastify.post('/search', search);
|
|
},
|
|
};
|