Files
Sukka d82847f541 style/chore(eslint): enforce new rules (#8040)
* style: prefer object shorthand syntax
* refactor: prefer Array#map over Array#forEach
* style: prefer arrow callback
* chore(eslint): update rules
* style: auto fix by eslint
2021-08-17 22:23:23 +08:00

154 lines
5.3 KiB
JavaScript

const cheerio = require('cheerio');
const got = require('@/utils/got');
const iconv = require('iconv-lite');
const url = require('url');
const base = 'http://www.t66y.com';
const got_ins = got.extend({
headers: {
Referer: base,
},
responseType: 'buffer',
});
function killViidii(originUrl) {
const decodeStr = /.*\?http/g;
const decodeSig = /______/g;
const jsSuffix = '&z';
const htmlSuffix = '&z';
const returnSuffix = 'return false';
if (originUrl.indexOf('viidii') !== -1) {
return originUrl.replace(decodeStr, 'http').replace(decodeSig, '.').replace(jsSuffix, '').replace(htmlSuffix, '').replace(returnSuffix, '');
} else {
return originUrl;
}
}
const sourceTimezoneOffset = -8;
function parseContent(htmlString) {
let $ = cheerio.load(htmlString, { decodeEntities: false });
let time = $('.tipad').text();
const regex = /\d{4}-\d{2}-\d{2} \d{2}:\d{2}/;
const regRes = regex.exec(time);
time = regRes === null ? new Date() : new Date(regRes[0]);
time.setTime(time.getTime() + (sourceTimezoneOffset - time.getTimezoneOffset() / 60) * 60 * 60 * 1000);
const author = $('th.r_two > b').text();
const content = $('.tpc_content').html();
// Change the image tag to display image in rss reader
try {
$ = cheerio.load(content, { decodeEntities: false }); // 修复无发进行filter与filterout的问题
} catch (error) {
return null;
}
// Handle video
const video = $('a:nth-of-type(2)');
if (video) {
const videoScript = video.attr('onclick');
const regVideo = /https?:\/\/.*'/;
const videoRes = regVideo.exec(videoScript);
if (videoRes && videoRes.length !== 0) {
let link = videoRes[0];
link = link.slice(0, link.length - 1);
$('iframe').attr('src', link);
}
}
// Handle img tag
let images = $('img');
for (let k = 0; k < images.length; k++) {
$(images[k]).replaceWith(`<img src="${$(images[k]).attr('data-src')}" />`);
}
// Handle input tag
images = $('input');
for (let k = 0; k < images.length; k++) {
$(images[k]).replaceWith(`<img src="${$(images[k]).attr('data-src')}" />`);
}
// Handle links
const links = $('a[href*="viidii"]');
for (let k = 0; k < links.length; k++) {
$(links[k]).attr('href', killViidii($(links[k]).attr('href')));
}
return {
author,
description: $('body').html(),
pubDate: time.toUTCString(),
};
}
module.exports = async (ctx) => {
const tid = ctx.params.tid;
let response = await got_ins.get(url.resolve(base, `/read.php?tid=${tid}`));
let html = iconv.decode(response.data, 'gbk');
// 跟踪重定向
let $ = cheerio.load(html);
const redirect = $('a:last-child').attr('href');
response = await got_ins.get(url.resolve(base, redirect));
html = iconv.decode(response.data, 'gbk');
$ = cheerio.load(html, { decodeEntities: false });
// 获取楼主id、末页
const uid = /uid=(\d+)/.exec($('.t.t2').first().find('.tiptop>a:first-child').attr('href'))[1];
const lasturl = $('.pages:first-child>a:last-child').attr('href');
const lastpage = lasturl ? /page=(\d+)/.exec(lasturl)[1] : 1;
// 从缓存中获取上次读取的页吗
let page = 0;
const cachePage = await ctx.cache.tryGet(`/t66y/post/${tid}`, () => ({ page }));
page = cachePage.page + 1;
if (page > lastpage) {
page = lastpage;
}
// 记录重试次数
let retry = 0;
// 请求帖子
const load = async (page) => {
const link = url.resolve(base, `/read.php?tid=${tid}&page=${page}`);
if (page > 1) {
// 只有第二页开始需要重新读取
html = await ctx.cache.tryGet(link, async () => {
const response = await got_ins.get(link, {
headers: {
Referer: url.resolve(base, redirect),
},
});
return iconv.decode(response.data, 'gbk');
});
$ = cheerio.load(html, { decodeEntities: false });
}
const title = /本頁主題: (.+)\n?/.exec($('#main div.t .h:first-child').text())[1];
const items = $('.t.t2')
.get()
.filter((item) => {
const matchs = /uid=(\d+)/.exec($('.tiptop>a:first-child', item).attr('href'));
return matchs.length === 2 && uid === matchs[1];
})
.map((item, index) => {
const single = {
title: `P${page}#${index + 1} ${title}`,
link: `${link}#${index + 1}`,
guid: `${link}#${index + 1}`,
};
const result = parseContent($(item).html());
return Object.assign(single, result);
});
// 记录读取的最后页码
ctx.cache.set(`/t66y/post/${tid}`, JSON.stringify({ page }));
// 如果没有读到内容,则读取下一页,最多读取3页
if (items.length === 0 && retry < 3) {
retry++; // 记录重试次数
return load(page + 1);
} else {
return { title, link: url.resolve(base, `/read.php?tid=${tid}`), item: items };
}
};
ctx.state.data = await load(page);
};