fix: 提升代码质量,增加测试用例

This commit is contained in:
lyz05
2022-11-09 18:28:35 +08:00
parent 709b94cf0c
commit 20a790c2bc
20 changed files with 158 additions and 119 deletions

20
app.js
View File

@@ -1,19 +1,19 @@
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
// 引入环境变量
require('dotenv').config();
// 引入一个个路由模块
var danmakuRouter = require('./routes/danmaku');
var usersRouter = require('./routes/users');
var ipinfoRouter = require('./routes/ipinfo');
var airportsubRouter = require('./routes/airportsub');
const danmakuRouter = require('./routes/danmaku');
const usersRouter = require('./routes/users');
const ipinfoRouter = require('./routes/ipinfo');
const airportsubRouter = require('./routes/airportsub');
var app = express();
const app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));

21
bin/www
View File

@@ -3,23 +3,20 @@
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('danmaku:server');
var http = require('http');
const app = require('../app');
const debug = require('debug')('danmaku:server');
const http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
const port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
const server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
@@ -34,7 +31,7 @@ server.on('listening', onListening);
*/
function normalizePort(val) {
var port = parseInt(val, 10);
const port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
@@ -58,7 +55,7 @@ function onError(error) {
throw error;
}
var bind = typeof port === 'string'
const bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
@@ -82,8 +79,8 @@ function onError(error) {
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
const addr = server.address();
const bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);

31
package-lock.json generated
View File

@@ -10,6 +10,7 @@
"dependencies": {
"ali-oss": "^6.17.1",
"axios": "^1.1.3",
"cookie": "^0.5.0",
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"dotenv": "^16.0.3",
@@ -25,7 +26,8 @@
"morgan": "~1.9.1",
"pako": "^1.0.11",
"whacko": "^0.19.1",
"xml-js": "^1.6.11"
"xml-js": "^1.6.11",
"xml2js": "^0.4.23"
},
"devDependencies": {
"chai": "^4.3.6",
@@ -1602,9 +1604,9 @@
"dev": true
},
"node_modules/cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
"engines": {
"node": ">= 0.6"
}
@@ -1621,6 +1623,14 @@
"node": ">= 0.8.0"
}
},
"node_modules/cookie-parser/node_modules/cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
@@ -7260,9 +7270,9 @@
"dev": true
},
"cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
},
"cookie-parser": {
"version": "1.4.6",
@@ -7271,6 +7281,13 @@
"requires": {
"cookie": "0.4.1",
"cookie-signature": "1.0.6"
},
"dependencies": {
"cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
}
}
},
"cookie-signature": {

View File

@@ -11,6 +11,7 @@
"dependencies": {
"ali-oss": "^6.17.1",
"axios": "^1.1.3",
"cookie": "^0.5.0",
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"dotenv": "^16.0.3",
@@ -26,7 +27,8 @@
"morgan": "~1.9.1",
"pako": "^1.0.11",
"whacko": "^0.19.1",
"xml-js": "^1.6.11"
"xml-js": "^1.6.11",
"xml2js": "^0.4.23"
},
"devDependencies": {
"chai": "^4.3.6",

View File

@@ -18,7 +18,7 @@ function getuserinfo(headers) {
if (str === undefined) {
return undefined
}
var dic = cookie.parse(str);
const dic = cookie.parse(str);
dic['total_use'] = 1 * dic.upload + 1 * dic.download
dic['use_percent'] = (100.0 * dic.total_use / dic.total).toFixed(2)
const now_time = Math.floor(Date.now() / 1000)
@@ -87,6 +87,7 @@ router.get('/', async function (req, res, next) {
}
});
// TODO: 定时任务
router.get('/cache', async function (req, res, next) {
const database = await updateDatabase();
let messages = [];
@@ -107,7 +108,7 @@ router.get('/cache', async function (req, res, next) {
const userinfo = res.headers['subscription-userinfo']
const base64userinfo = Buffer.from(userinfo).toString('base64')
// 设置强制下载并设置文件名
headers = {
const headers = {
'Content-type': 'text/plain; charset=utf-8',
'content-disposition': `attachment; filename=${key}`,
'x-oss-persistent-headers': "Subscription-Userinfo:" + base64userinfo

View File

@@ -1,3 +1,5 @@
// noinspection EqualityComparisonWithCoercionJS
const urlmodule = require('url');
const axios = require('axios');
const got = require('got');
@@ -17,14 +19,14 @@ function Bilibili() {
// 相关API
const api_video_info = "https://api.bilibili.com/x/web-interface/view"
const api_epid_cid = "https://api.bilibili.com/pgc/view/web/season"
var q = urlmodule.parse(url, true);
var path = q.pathname.split('/');
const q = urlmodule.parse(url, true);
const path = q.pathname.split('/');
// 普通投稿视频
if (url.indexOf('video/') !== -1) {
// 获取视频分P信息
const p = q.query.p || 1;
// 判断是否为旧版av号
var params;
let params;
if (url.indexOf('BV') !== -1) {
params = {'bvid': path.slice(-1)[0]};
} else {
@@ -49,7 +51,7 @@ function Bilibili() {
this.error_msg = '获取番剧视频信息失败!'
return
}
for (var i = 0; i < response.data.result.episodes.length; i++) {
for (let i = 0; i < response.data.result.episodes.length; i++) {
if (response.data.result.episodes[i].id == params.ep_id) {
this.title = response.data.result.episodes[i].share_copy;
const cid = response.data.result.episodes[i].cid;

View File

@@ -1,6 +1,6 @@
const axios = require('axios');
const pako = require('pako');
var xml2js = require('xml2js');
const xml2js = require('xml2js');
const {time_to_second, make_response, content_template} = require('./utils');
const memory = require('../../utils/memory')
@@ -35,7 +35,7 @@ function Iqiyi() {
console.log('tvid', tvid)
let promises = []
for (let i = 0; i < page; i++) {
const api_url = `http://cmts.iqiyi.com/bullet/${tvid.slice(-4, -2)}/${tvid.slice(-2)}/${tvid}_300_${i + 1}.z`
const api_url = `https://cmts.iqiyi.com/bullet/${tvid.slice(-4, -2)}/${tvid.slice(-2)}/${tvid}_300_${i + 1}.z`
const params = {
rn: '0.0123456789123456',
business: 'danmu',
@@ -67,7 +67,7 @@ function Iqiyi() {
continue
for (const bulletInfo of entry.list[0].bulletInfo){
// console.log(bulletInfo)
var content = JSON.parse(JSON.stringify(content_template));
const content = JSON.parse(JSON.stringify(content_template));
content.timepoint = bulletInfo['showTime'][0]//showTime
content.color = parseInt(bulletInfo['color'][0], 16)//color
content.content = bulletInfo['content'][0] //content

View File

@@ -38,7 +38,7 @@ function Mgtv() {
if (data.data.items === null)
continue;
for (const item of data.data.items) {
var content = JSON.parse(JSON.stringify(content_template));
const content = JSON.parse(JSON.stringify(content_template));
content.timepoint = item.time / 1000;
content.content = item.content;
content.uid = item.uid;

View File

@@ -45,7 +45,7 @@ function Tencentvideo() {
for (const data of datas) {
for (const item of data.barrage_list) {
var content = JSON.parse(JSON.stringify(content_template));
const content = JSON.parse(JSON.stringify(content_template));
content.timepoint = item.time_offset / 1000;
if (item.content_style.color) {
const content_style = JSON.stringify(item.content_style.color)

View File

@@ -11,9 +11,9 @@ const content_template = {
};
function time_to_second(time) {
var t = time.split(':');
var s = 0;
var m = 1;
const t = time.split(':');
let s = 0;
let m = 1;
while (t.length > 0) {
s += m * parseInt(t.pop(), 10);
m *= 60;

View File

@@ -35,13 +35,13 @@ function Youku() {
}
const yk_msg_sign = (msg) => {
var md5 = crypto.createHash('md5');
const md5 = crypto.createHash('md5');
return md5.update(msg + "MkmC9SoIw6xCkSKHhJ7b5D2r51kBiREr").digest('hex');
}
const yk_t_sign = (token, t, appkey, data) => {
const text = [token, t, appkey, data].join('&');
var md5 = crypto.createHash('md5');
const md5 = crypto.createHash('md5');
return md5.update(text).digest('hex')
}
@@ -101,7 +101,7 @@ function Youku() {
msg['sign'] = yk_msg_sign(msg_b64encode)
const data = JSON.stringify(msg)
const t = Date.now()
params = {
const params = {
"jsv": "2.5.6",
"appKey": "24679788",
"t": t,
@@ -130,7 +130,7 @@ function Youku() {
// 接口请求情况
// console.log(i, res.ret[0])
for (danmu of danmus) {
var content = JSON.parse(JSON.stringify(content_template));
const content = JSON.parse(JSON.stringify(content_template));
content.timepoint = danmu["playat"] / 1000
if (danmu.propertis.color) {
content.color = JSON.parse(danmu.propertis).color

View File

@@ -24,8 +24,8 @@ async function build_response(url,req) {
console.log(e)
return {msg: '传入的链接非法!请检查链接是否能在浏览器正常打开'}
}
var fc = undefined
for (var item of list) {
let fc = undefined;
for (let item of list) {
if (url.indexOf(item.domain) !== -1) {
fc = item
}
@@ -49,13 +49,13 @@ router.get('/', async function (req, res, next) {
leancloud.danmakuAccessAdd({ip: getClientIp(req), url: req.query.url, ua: req.headers['user-agent']})
//检查是否包含URL参数
if (!req.query.url) {
var urls = [mgtv.example_urls[0], bilibili.example_urls[0], tencentvideo.example_urls[0], youku.example_urls[0], iqiyi.example_urls[0]];
const urls = [mgtv.example_urls[0], bilibili.example_urls[0], tencentvideo.example_urls[0], youku.example_urls[0], iqiyi.example_urls[0]];
const path = getscheme(req) + '://' + req.headers.host + req.originalUrl;
res.render('danmaku', {path, urls});
} else {
url = req.query.url;
download = (req.query.download === 'on');
ret = await build_response(url,req)
const url = req.query.url;
const download = (req.query.download === 'on');
const ret = await build_response(url,req)
memory() //显示内存使用量
if (ret.msg !== 'ok') {
res.status(403).send(ret.msg)

View File

@@ -1,8 +1,8 @@
var express = require('express');
var router = express.Router();
var libqqwry = require('lib-qqwry');
var dns = require('dns');
var qqwry = libqqwry() //初始化IP库解析器
const express = require('express');
const router = express.Router();
const libqqwry = require('lib-qqwry');
const dns = require('dns');
const qqwry = libqqwry(); //初始化IP库解析器
function getClientIp(req) {
return req.headers['x-forwarded-for'] ||
@@ -13,14 +13,15 @@ function getClientIp(req) {
/* GET home page. */
router.get('/', function (req, res, next) {
var ip = req.query.name || getClientIp(req);
let ip = req.query.name || getClientIp(req);
dns.lookup(ip, (err, address, family) => {
let ipL;
if (err) {
ipL = { 'ip': ip, 'msg': '域名解析IP失败' };
} else {
ip = address
try {
var ipL = qqwry.searchIP(ip); //查询IP信息
ipL = qqwry.searchIP(ip); //查询IP信息
} catch (e) {
ipL = { 'ip': ip, 'msg': e };
}

View File

@@ -1,5 +1,5 @@
var express = require('express');
var router = express.Router();
const express = require('express');
const router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {

26
test.js
View File

@@ -1,26 +0,0 @@
function main() {
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p1');
}, 500);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p2');
}, 300);
});
const Promises = [p1,p2];
let count = 0;
p1.then((value) => {
count ++;
console.log(value)
})
p2.then((value) => {
count ++;
console.log(value)
})
while (count<2) ;
console.log('All promise done');
}
main()

View File

@@ -7,6 +7,7 @@ const list = [bilibili, mgtv, tencentvideo, youku, iqiyi];
let should = chai.should();
chai.use(chaiHttp);
//TODO: add more test cases
describe('App', () => {
describe('弹幕解析模块测试', function () {
@@ -19,7 +20,30 @@ describe('App', () => {
done();
});
});
it('页面统计计数测试', (done) => {
chai.request(app)
.get('/pageinfo')
.end((err, res) => {
res.should.have.status(200);
done();
});
});
it('传入无法打开的url测试', (done) => {
chai.request(app)
.get('/?url=ababa')
.end((err, res) => {
res.should.have.status(403);
done();
});
});
it('传入不支持的网址', (done) => {
chai.request(app)
.get('/?url=https://tv.sohu.com/v/MjAyMDA2MjYvbjYwMDg3NDcwOS5zaHRtbA==.html')
.end((err, res) => {
res.should.have.status(403);
done();
});
});
for (const item of list) {
const name = item.name;
const example_urls = item.example_urls;
@@ -119,6 +143,32 @@ describe('App', () => {
done();
});
});
it('接口带user与错误ctype参数测试', (done) =>{
chai.request(app)
.get('/sub?user=congcong&ctype=abaaba')
.end((err,res) => {
res.should.have.status(404);
done();
});
});
it('接口带user与ctype参数测试带Mozilla UA', (done) =>{
chai.request(app)
.get('/sub?user=congcong&ctype=v2ray')
.set('User-Agent','Mozilla/5.0 ')
.end((err,res) => {
res.should.have.status(200);
done();
});
});
it('接口带user,订阅过期测试', (done) =>{
chai.request(app)
.get('/sub?user=test&ctype=v2ray')
.set('User-Agent','Mozilla/5.0 ')
.end((err,res) => {
res.should.have.status(200);
done();
});
});
it('缓存测试', (done) =>{
chai.request(app)
.get('/sub/cache')

View File

@@ -9,15 +9,6 @@ AV.init({
serverURL: "https://dbvunek8.lc-cn-e1-shared.com"
});
function test() {
const TestObject = AV.Object.extend('TestObject');
const testObject = new TestObject();
testObject.set('words', 'Hello world!');
testObject.set('number', 123);
testObject.save().then((testObject) => {
console.log('保存成功。')
})
}
function danmakuAccessAdd(obj) {
const {ip, url, ua} = obj;
@@ -44,9 +35,9 @@ function lastDay() {
}
function currentMonth() {
var date = new Date(), y = date.getFullYear(), m = date.getMonth();
var firstDay = new Date(y, m, 1);
var lastDay = new Date(y, m + 1, 0);
const date = new Date(), y = date.getFullYear(), m = date.getMonth();
const firstDay = new Date(y, m, 1);
const lastDay = new Date(y, m + 1, 0);
return [firstDay, lastDay]
}
@@ -65,6 +56,7 @@ function danmakuErrorAdd(obj) {
const record = new DanmakuErrorObject();
record.set('remoteIP', ip);
record.set('url', url);
//TODO: 转换成object
record.set('error', JSON.stringify(error));
record.save().then()
}

View File

@@ -11,18 +11,19 @@
<div class="container">
<h3>温馨提示:</h3>
<p>
带filter的是过滤无效节点并精选的结果建议优先使用。强烈建议使用clash作为客户端具有自动测试节点的功能和完善的规则。</p>
带filter的是过滤无效节点并精选的结果建议优先使用。强烈建议使用clash作为客户端具有自动测试节点的功能和完善的规则。
</p>
<p>
相关软件<a href="/sub/download">下载链接</a><br>
</p>
<p>
<p class="card-heading">Telegram 代理</p>
<p>
<a href="tg://proxy?server=vipserv.ccloud.live&amp;port=443&amp;secret=dddd561961fea026e517764b084bd64072">域名</a>
<a href="tg://proxy?server=167.235.77.32&amp;port=443&amp;secret=dddd561961fea026e517764b084bd64072">IPV4</a>
<a href="tg://proxy?server=2a01:4f8:1c1e:eeb6::1&amp;port=443&amp;secret=dddd561961fea026e517764b084bd64072">IPV6</a>
</p>
</p>
<h3>Your Subscribe:</h3>
<p>
当前账户过期时间:<%= expire %><br>
@@ -34,11 +35,12 @@
<br>
<% if (ret[index]) { %>
过去已用:<%= ret[index].total_use %> 总量:<%= ret[index].total %> 过期时间:<%= ret[index].expire %> 用量比:<%= ret[index].use_percent %>%
过去已用:<%= ret[index].total_use %> 总量:<%= ret[index].total %> 过期时间:<%= ret[index].expire %>
用量比:<%= ret[index].use_percent %>%
日期比:<%= ret[index].date_percent %>%<br>
<% } %>
<% }; %>
<% } %>
</p>
</div>
</body>

View File

@@ -54,6 +54,7 @@
<div class="form-group">
<label class="col-sm-1 control-label">视频网址</label>
<div class="col-sm-5">
<!--suppress HtmlFormInputWithoutLabel -->
<input type="text" class="form-control" placeholder="URL" name="url">
</div>
</div>

View File

@@ -1,4 +1,4 @@
<html>
<html lang="zh">
<head>
<title><%= error.status %> <%= message %></title>