docs: 使用eslint进行代码检查

This commit is contained in:
lyz05
2022-11-11 15:13:07 +08:00
parent d71ee113a0
commit cd572bafb2
24 changed files with 3314 additions and 1355 deletions

32
.eslintrc.js Normal file
View File

@@ -0,0 +1,32 @@
module.exports = {
"env": {
"node": true,
"commonjs": true,
"es2021": true,
"jest": true
},
"extends": "eslint:recommended",
"overrides": [
],
"parserOptions": {
"ecmaVersion": "latest"
},
"rules": {
"indent": [
"error",
"tab"
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"double"
],
"semi": [
"error",
"always"
]
}
};

View File

@@ -1,4 +1,10 @@
FROM node:14.21.0-alpine3.16
ENV TZ Asia/Shanghai
RUN apk add tzdata && cp /usr/share/zoneinfo/${TZ} /etc/localtime \
&& echo ${TZ} > /etc/timezone \
&& apk del tzdata
LABEL fly_launch_runtime="nodejs"
COPY . /app

62
app.js
View File

@@ -1,57 +1,57 @@
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const 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();
require("dotenv").config();
// 引入一个个路由模块
const danmakuRouter = require('./routes/danmaku');
const ipinfoRouter = require('./routes/ipinfo');
const airportsubRouter = require('./routes/airportsub');
const danmakuRouter = require("./routes/danmaku");
const ipinfoRouter = require("./routes/ipinfo");
const airportsubRouter = require("./routes/airportsub");
const DEBUG = process.env.DEBUG==="true" || false;
if (!DEBUG) {
console.log("PRODUCTION MODE!该模式下TG机器人与定时任务正常运行");
// 引入定时任务模块
const schedule = require('./schedule/schedule');
// 引入TG机器人
const tgbot = require('./tgbot/bot');
console.log("PRODUCTION MODE!该模式下TG机器人与定时任务正常运行");
// 引入定时任务模块
require("./schedule/schedule");
// 引入TG机器人
require("./tgbot/bot");
} else
console.log("DEBUG MODE!该模式下将关闭TG机器人和定时任务");
console.log("DEBUG MODE!该模式下将关闭TG机器人和定时任务");
const app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.set('trust proxy', true)
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");
app.set("trust proxy", true);
app.use(logger('dev'));
app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, "public")));
app.use('/', danmakuRouter);
app.use('/ipinfo', ipinfoRouter);
app.use('/sub', airportsubRouter);
app.use("/", danmakuRouter);
app.use("/ipinfo", ipinfoRouter);
app.use("/sub", airportsubRouter);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
app.use(function (err, req, res) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get("env") === "development" ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
// render the error page
res.status(err.status || 500);
res.render("error");
});
module.exports = app;

1909
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -36,6 +36,8 @@
"xml2js": "^0.4.23"
},
"devDependencies": {
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.26.0",
"mocha": "^10.1.0",
"nodemon": "^2.0.20",
"nyc": "^15.1.0"

View File

@@ -1,164 +1,162 @@
const express = require('express');
const express = require("express");
const router = express.Router();
const oss = require('../utils/oss');
const yaml = require('js-yaml');
const cookie = require('cookie');
const {filesize} = require('filesize');
const moment = require('moment');
const axios = require('axios');
const leancloud = require('../utils/leancloud')
const oss = require("../utils/oss");
const yaml = require("js-yaml");
const cookie = require("cookie");
const {filesize} = require("filesize");
const moment = require("moment");
const axios = require("axios");
const leancloud = require("../utils/leancloud");
// TODO 迁移到leancloud
function getuserinfo(headers) {
if (!headers)
return undefined
const str = headers["subscription-userinfo"]
if (str === undefined) {
return undefined
}
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)
const end_time = dic.expire
dic['date_percent'] = (100.0 * (now_time - end_time + 3600 * 24 * 365.0) / (3600 * 24 * 365.0)).toFixed(2)
if (!headers)
return undefined;
const str = headers["subscription-userinfo"];
if (str === undefined) {
return undefined;
}
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);
const end_time = dic.expire;
dic["date_percent"] = (100.0 * (now_time - end_time + 3600 * 24 * 365.0) / (3600 * 24 * 365.0)).toFixed(2);
dic['total_use'] = filesize(dic['total_use'], {base: 2, standard: "jedec"})
dic.total = filesize(dic.total, {base: 2, standard: "jedec"})
dic.expire = moment(dic.expire * 1000).format('YYYY-MM-DD')
return dic
dic["total_use"] = filesize(dic["total_use"], {base: 2, standard: "jedec"});
dic.total = filesize(dic.total, {base: 2, standard: "jedec"});
dic.expire = moment(dic.expire * 1000).format("YYYY-MM-DD");
return dic;
}
async function updateDatabase() {
const database = await oss.get('SUB/database.yaml');
try {
const doc = yaml.load(database);
return doc
} catch (e) {
console.log(e);
}
const database = await oss.get("SUB/database.yaml");
try {
return yaml.load(database);
} catch (e) {
console.log(e);
}
}
/* GET users listing. */
router.get('/', async function (req, res, next) {
const database = await updateDatabase();
leancloud.add('SubAccess', {
ip: req.ip,
ua: req.headers['user-agent'],
user: req.query.user,
ctype: req.query.ctype
})
if (req.query.user) {
const userinfo = database.user[req.query.user]
if (userinfo) {
const expireDate = new Date(userinfo.expire);
const now = new Date();
if (now < expireDate) {
if (req.query.ctype) {
const subinfo = database.suburl[req.query.ctype]
//返回指定订阅信息
if (subinfo) {
const ua = req.headers['user-agent'];
if (ua.indexOf('Mozilla') === -1) {
const url = await oss.signurl('SUB/' + req.query.ctype, true)
res.redirect(url)
} else {
const ret = await oss.get('SUB/' + req.query.ctype)
res.type('text/plain').end(ret);
}
} else {
res.status(404).send('Not Found 找不到这种订阅类型');
}
} else {
const path = req.protocol + '://' + req.headers.host + req.originalUrl;
const tgproxys = database.telegram;
const ctypes = Object.keys(database.suburl)
let ret = {}
for (key of ctypes) {
const headers = await oss.head('SUB/' + key)
ret[key] = getuserinfo(headers)
// ret[key] = getuserinfotxt(getuserinfo(headers))
}
res.render('airportsub', {ret, path, tgproxys, expire: userinfo.expire});
}
} else {
res.send('您的订阅已过期,请联系管理员');
}
} else {
res.status(404).send('Not Found 找不到这个用户');
}
} else {
res.status(400).send('Bad Request 缺少参数');
}
router.get("/", async function (req, res) {
const database = await updateDatabase();
leancloud.add("SubAccess", {
ip: req.ip,
ua: req.headers["user-agent"],
user: req.query.user,
ctype: req.query.ctype
});
if (req.query.user) {
const userinfo = database.user[req.query.user];
if (userinfo) {
const expireDate = new Date(userinfo.expire);
const now = new Date();
if (now < expireDate) {
if (req.query.ctype) {
const subinfo = database.suburl[req.query.ctype];
//返回指定订阅信息
if (subinfo) {
const ua = req.headers["user-agent"];
if (ua.indexOf("Mozilla") === -1) {
const url = await oss.signurl("SUB/" + req.query.ctype, true);
res.redirect(url);
} else {
const ret = await oss.get("SUB/" + req.query.ctype);
res.type("text/plain").end(ret);
}
} else {
res.status(404).send("Not Found 找不到这种订阅类型");
}
} else {
const path = req.protocol + "://" + req.headers.host + req.originalUrl;
const tgproxys = database.telegram;
const ctypes = Object.keys(database.suburl);
let ret = {};
for (const key of ctypes) {
const headers = await oss.head("SUB/" + key);
ret[key] = getuserinfo(headers);
// ret[key] = getuserinfotxt(getuserinfo(headers))
}
res.render("airportsub", {ret, path, tgproxys, expire: userinfo.expire});
}
} else {
res.send("您的订阅已过期,请联系管理员");
}
} else {
res.status(404).send("Not Found 找不到这个用户");
}
} else {
res.status(400).send("Bad Request 缺少参数");
}
});
router.get('/cache', async function (req, res, next) {
const database = await updateDatabase();
let messages = [];
// 缓存所有的协程
let promises = [];
for (let key in database.suburl) {
const url = database.suburl[key].url
const params = database.suburl[key].params
if (!url) continue
promises.push(axios.get(url, {params}));
}
Promise.all(promises).then(values => {
promises = [];
for (let i = 0; i < values.length; i++) {
const res = values[i];
const key = Object.keys(database.suburl)[i]
messages.push({title: 'Download', key, status: res.status})
const userinfo = res.headers['subscription-userinfo']
const base64userinfo = Buffer.from(userinfo).toString('base64')
// 设置强制下载并设置文件名
const headers = {
'Content-type': 'text/plain; charset=utf-8',
'content-disposition': `attachment; filename=${key}`,
'x-oss-persistent-headers': "Subscription-Userinfo:" + base64userinfo
}
promises.push(oss.put('SUB/' + key, res.data, headers))
}
Promise.all(promises).then(values => {
for (let i = 0; i < values.length; i++) {
const res = values[i];
const key = Object.keys(database.suburl)[i]
messages.push({title: 'Upload', key, status: res.res.status})
}
res.json(messages);
})
});
router.get("/cache", async function (req, res) {
const database = await updateDatabase();
let messages = [];
// 缓存所有的协程
let promises = [];
for (let key in database.suburl) {
const url = database.suburl[key].url;
const params = database.suburl[key].params;
if (!url) continue;
promises.push(axios.get(url, {params}));
}
Promise.all(promises).then(values => {
promises = [];
for (let i = 0; i < values.length; i++) {
const res = values[i];
const key = Object.keys(database.suburl)[i];
messages.push({title: "Download", key, status: res.status});
const userinfo = res.headers["subscription-userinfo"];
const base64userinfo = Buffer.from(userinfo).toString("base64");
// 设置强制下载并设置文件名
const headers = {
"Content-type": "text/plain; charset=utf-8",
"content-disposition": `attachment; filename=${key}`,
"x-oss-persistent-headers": "Subscription-Userinfo:" + base64userinfo
};
promises.push(oss.put("SUB/" + key, res.data, headers));
}
Promise.all(promises).then(values => {
for (let i = 0; i < values.length; i++) {
const res = values[i];
const key = Object.keys(database.suburl)[i];
messages.push({title: "Upload", key, status: res.res.status});
}
res.json(messages);
});
});
});
router.get('/download', async function (req, res, next) {
const repos = ['Dreamacro/clash', 'Fndroid/clash_for_windows_pkg', 'Kr328/ClashForAndroid',
'shadowsocks/shadowsocks-android', 'XTLS/Xray-core', '2dust/v2rayN', 'NetchX/Netch', '2dust/v2rayNG',
'yichengchen/clashX', 'shadowsocks/shadowsocks-windows',
'shadowsocksrr/shadowsocksr-csharp', 'FelisCatus/SwitchyOmega']
const auth = {
'username': process.env.GITHUB_USERNAME,
'password': process.env.GITHUB_TOKEN
}
const api = 'https://api.github.com/repos/{}/releases/latest'
const promises = repos.map(repo => axios.get(api.replace('{}', repo), {auth}))
Promise.all(promises).then(values => {
let datas = values.map(value => value.data)
for (let i = 0; i < datas.length; i++) {
datas[i].repo = repos[i]
for (asset of datas[i].assets) {
asset.size = filesize(asset.size, {base: 2, standard: "jedec"})
asset['fastgit_url'] = asset['browser_download_url'].replace('github.com', 'download.fastgit.org')
asset['ghproxy_url'] = 'https://mirror.ghproxy.com?q=' + asset['browser_download_url']
}
}
res.render('airportdownload', {datas});
});
router.get("/download", async function (req, res) {
const repos = ["Dreamacro/clash", "Fndroid/clash_for_windows_pkg", "Kr328/ClashForAndroid",
"shadowsocks/shadowsocks-android", "XTLS/Xray-core", "2dust/v2rayN", "NetchX/Netch", "2dust/v2rayNG",
"yichengchen/clashX", "shadowsocks/shadowsocks-windows",
"shadowsocksrr/shadowsocksr-csharp", "FelisCatus/SwitchyOmega"];
const auth = {
"username": process.env.GITHUB_USERNAME,
"password": process.env.GITHUB_TOKEN
};
const api = "https://api.github.com/repos/{}/releases/latest";
const promises = repos.map(repo => axios.get(api.replace("{}", repo), {auth}));
Promise.all(promises).then(values => {
let datas = values.map(value => value.data);
for (let i = 0; i < datas.length; i++) {
datas[i].repo = repos[i];
for (const asset of datas[i].assets) {
asset.size = filesize(asset.size, {base: 2, standard: "jedec"});
asset["fastgit_url"] = asset["browser_download_url"].replace("github.com", "download.fastgit.org");
asset["ghproxy_url"] = "https://mirror.ghproxy.com?q=" + asset["browser_download_url"];
}
}
res.render("airportdownload", {datas});
});
});
module.exports = router;
if (!module.parent) {
updateDatabase();
}
updateDatabase();
}

View File

@@ -1,9 +1,9 @@
//引入API组件
const Bilibili = require('./bilibili');
const Mgtv = require('./mgtv');
const Tencentvideo = require('./tencentvideo');
const Youku = require('./youku');
const Iqiyi = require('./iqiyi');
const Bilibili = require("./bilibili");
const Mgtv = require("./mgtv");
const Tencentvideo = require("./tencentvideo");
const Youku = require("./youku");
const Iqiyi = require("./iqiyi");
// 实例化API组件
const bilibili = new Bilibili();
const mgtv = new Mgtv();
@@ -12,4 +12,4 @@ const youku = new Youku();
const iqiyi = new Iqiyi();
//TODO 优化代码
module.exports = { bilibili, mgtv, tencentvideo, youku, iqiyi };
module.exports = { bilibili, mgtv, tencentvideo, youku, iqiyi };

View File

@@ -1,99 +1,97 @@
// noinspection EqualityComparisonWithCoercionJS
const urlmodule = require('url');
const axios = require('axios');
const got = require('got');
const {inflateRawSync} = require('zlib');
const urlmodule = require("url");
const axios = require("axios");
const got = require("got");
const {inflateRawSync} = require("zlib");
function Bilibili() {
this.name = 'B站';
this.domain = 'bilibili.com';
this.example_urls = [
'https://www.bilibili.com/video/av170001',
'https://www.bilibili.com/video/av170001?p=2',
'https://www.bilibili.com/video/BV17x411w7KC?p=3',
'https://www.bilibili.com/bangumi/play/ep691614'
];
this.name = "B站";
this.domain = "bilibili.com";
this.example_urls = [
"https://www.bilibili.com/video/av170001",
"https://www.bilibili.com/video/av170001?p=2",
"https://www.bilibili.com/video/BV17x411w7KC?p=3",
"https://www.bilibili.com/bangumi/play/ep691614"
];
this.resolve = async (url) => {
// 相关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"
const q = urlmodule.parse(url, true);
const path = q.pathname.split('/');
// 普通投稿视频
if (url.indexOf('video/') !== -1) {
// 获取视频分P信息
const p = q.query.p || 1;
// 判断是否为旧版av号
let params;
if (url.indexOf('BV') !== -1) {
params = {'bvid': path.slice(-1)[0]};
} else {
params = {'aid': path.slice(-1)[0].substring(2)};
}
const response = await axios.get(api_video_info, {params})
if (response.data.code !== 0) {
this.error_msg = '获取普通投稿视频信息失败!'
return
}
this.title = response.data.data.title;
const subtitle = response.data.data.pages[p - 1].part;
this.title = this.title + '-' + subtitle;
const cid = response.data.data.pages[p - 1].cid;
return [`https://comment.bilibili.com/${cid}.xml`];
} // 番剧
else if (url.indexOf('bangumi/') !== -1) {
const epid = path.slice(-1)[0];
const params = {'ep_id': epid.slice(2)};
const response = await axios.get(api_epid_cid, {params})
if (response.data.code !== 0) {
this.error_msg = '获取番剧视频信息失败!'
return
}
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;
return [`https://comment.bilibili.com/${cid}.xml`];
}
}
} else {
this.error_msg = '不支持的B站视频网址仅支持普通视频(av,bv)、剧集视频(ep)';
}
this.resolve = async (url) => {
// 相关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";
const q = urlmodule.parse(url, true);
const path = q.pathname.split("/");
// 普通投稿视频
if (url.indexOf("video/") !== -1) {
// 获取视频分P信息
const p = q.query.p || 1;
// 判断是否为旧版av号
let params;
if (url.indexOf("BV") !== -1) {
params = {"bvid": path.slice(-1)[0]};
} else {
params = {"aid": path.slice(-1)[0].substring(2)};
}
const response = await axios.get(api_video_info, {params});
if (response.data.code !== 0) {
this.error_msg = "获取普通投稿视频信息失败!";
return;
}
this.title = response.data.data.title;
const subtitle = response.data.data.pages[p - 1].part;
this.title = this.title + "-" + subtitle;
const cid = response.data.data.pages[p - 1].cid;
return [`https://comment.bilibili.com/${cid}.xml`];
} // 番剧
else if (url.indexOf("bangumi/") !== -1) {
const epid = path.slice(-1)[0];
const params = {"ep_id": epid.slice(2)};
const response = await axios.get(api_epid_cid, {params});
if (response.data.code !== 0) {
this.error_msg = "获取番剧视频信息失败!";
return;
}
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;
return [`https://comment.bilibili.com/${cid}.xml`];
}
}
} else {
this.error_msg = "不支持的B站视频网址仅支持普通视频(av,bv)、剧集视频(ep)";
}
}
};
this.parse = async (urls) => {
// B站使用特殊的压缩方法需要使用got模块
const bufferData = await got(urls[0], {
decompress: false
}).buffer();
const content = inflateRawSync(bufferData).toString();
return content
}
this.parse = async (urls) => {
// B站使用特殊的压缩方法需要使用got模块
const bufferData = await got(urls[0], {
decompress: false
}).buffer();
const content = inflateRawSync(bufferData).toString();
return content;
};
this.work = async (url) => {
const urls = await this.resolve(url);
console.log(this.name,'api lens:',urls.length);
if (!this.error_msg)
this.content = await this.parse(urls);
return {
title: this.title,
content: this.content,
msg: this.error_msg? this.error_msg: 'ok'
}
}
this.work = async (url) => {
const urls = await this.resolve(url);
console.log(this.name,"api lens:",urls.length);
if (!this.error_msg)
this.content = await this.parse(urls);
return {
title: this.title,
content: this.content,
msg: this.error_msg? this.error_msg: "ok"
};
};
}
module.exports = Bilibili
module.exports = Bilibili;
if(!module.parent) {
const b = new Bilibili();
b.work(b.example_urls[0]).then(() => {
console.log(b.content);
console.log(b.title);
});
const b = new Bilibili();
b.work(b.example_urls[0]).then(() => {
console.log(b.content);
console.log(b.title);
});
}

View File

@@ -1,106 +1,106 @@
const axios = require('axios');
const pako = require('pako');
const xml2js = require('xml2js');
const {time_to_second, make_response, content_template} = require('./utils');
const memory = require('../../utils/memory')
const axios = require("axios");
const pako = require("pako");
const xml2js = require("xml2js");
const {time_to_second, make_response, content_template} = require("./utils");
const memory = require("../../utils/memory");
//资源消耗大 256M内存扛不住
function Iqiyi() {
this.name = '爱奇艺'
this.domain = 'iqiyi.com'
this.example_urls = [
'https://www.iqiyi.com/v_19rr1lm35o.html', //api lens 11
'https://www.iqiyi.com/v_1wozsa91cfs.html', //api lens 9
'https://www.iqiyi.com/v_1zzwhiozqww.html', //api lens 10
'http://www.iqiyi.com/v_2ga8zts86ys.html'
];
this.name = "爱奇艺";
this.domain = "iqiyi.com";
this.example_urls = [
"https://www.iqiyi.com/v_19rr1lm35o.html", //api lens 11
"https://www.iqiyi.com/v_1wozsa91cfs.html", //api lens 9
"https://www.iqiyi.com/v_1zzwhiozqww.html", //api lens 10
"http://www.iqiyi.com/v_2ga8zts86ys.html"
];
this.resolve = async (url) => {
const res = await axios({
method: 'get',
url: "https://proxy-fc-python-fdssfsqzaa.cn-shenzhen.fcapp.run/",
params: {url},
auth: {username: 'proxy', password: 'proxy'}
});
const data = res.data
const result = data.match(/window.Q.PageInfo.playPageInfo=(.*);/)
const page_info = JSON.parse(result[1])
// console.log('page_info:', page_info)
this.resolve = async (url) => {
const res = await axios({
method: "get",
url: "https://proxy-fc-python-fdssfsqzaa.cn-shenzhen.fcapp.run/",
params: {url},
auth: {username: "proxy", password: "proxy"}
});
const data = res.data;
const result = data.match(/window.Q.PageInfo.playPageInfo=(.*);/);
const page_info = JSON.parse(result[1]);
// console.log('page_info:', page_info)
const duration = time_to_second(page_info.duration)
this.title = page_info.tvName ? page_info.tvName : page_info.name
const albumid = page_info.albumId
const tvid = page_info.tvId.toString()
const categoryid = page_info.cid
const page = Math.round(duration / (60 * 5))
console.log('tvid', tvid)
let promises = []
for (let i = 0; i < page; i++) {
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',
is_iqiyi: 'true',
is_video_page: 'true',
tvid: tvid,
albumid: albumid,
categoryid: categoryid,
qypid: '01010021010000000000'
}
promises.push(axios({method: 'get', url: api_url, params: params, responseType: 'arraybuffer'}))
}
return promises
}
const duration = time_to_second(page_info.duration);
this.title = page_info.tvName ? page_info.tvName : page_info.name;
const albumid = page_info.albumId;
const tvid = page_info.tvId.toString();
const categoryid = page_info.cid;
const page = Math.round(duration / (60 * 5));
console.log("tvid", tvid);
let promises = [];
for (let i = 0; i < page; i++) {
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",
is_iqiyi: "true",
is_video_page: "true",
tvid: tvid,
albumid: albumid,
categoryid: categoryid,
qypid: "01010021010000000000"
};
promises.push(axios({method: "get", url: api_url, params: params, responseType: "arraybuffer"}));
}
return promises;
};
this.parse = async (promises) => {
let contents = [];
const values = await Promise.all(promises)
const datas = values
.map(value => value.data)
.map(value => pako.inflate(value, {to: 'string'}));
this.parse = async (promises) => {
let contents = [];
const values = await Promise.all(promises);
const datas = values
.map(value => value.data)
.map(value => pako.inflate(value, {to: "string"}));
for (const xml of datas) {
const json = await xml2js.parseStringPromise(xml)
// console.log(json)
global.gc()
for (const entry of json.danmu.data[0].entry??[]) {
for (const bulletInfo of entry.list[0].bulletInfo??[]){
// console.log(bulletInfo)
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
content.size = bulletInfo['font'][0]//font
contents.push(content);
}
}
memory()
}
contents = make_response(contents)
return contents
}
for (const xml of datas) {
const json = await xml2js.parseStringPromise(xml);
// console.log(json)
global.gc();
for (const entry of json.danmu.data[0].entry??[]) {
for (const bulletInfo of entry.list[0].bulletInfo??[]){
// console.log(bulletInfo)
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
content.size = bulletInfo["font"][0];//font
contents.push(content);
}
}
memory();
}
contents = make_response(contents);
return contents;
};
this.work = async (url) => {
const promises = await this.resolve(url);
console.log(this.name, 'api lens:', promises.length)
this.content = await this.parse(promises);
return {
title: this.title,
content: this.content,
msg: 'ok'
}
}
this.work = async (url) => {
const promises = await this.resolve(url);
console.log(this.name, "api lens:", promises.length);
this.content = await this.parse(promises);
return {
title: this.title,
content: this.content,
msg: "ok"
};
};
}
module.exports = Iqiyi
module.exports = Iqiyi;
if (!module.parent) {
const m = new Iqiyi();
const m = new Iqiyi();
m.work(m.example_urls[2]).then(() => {
// console.log(m.content);
console.log(m.title);
memory();
});
}
m.work(m.example_urls[2]).then(() => {
// console.log(m.content);
console.log(m.title);
memory();
});
}

View File

@@ -1,75 +1,75 @@
const urlmodule = require('url');
const axios = require('axios');
const {time_to_second, make_response, content_template} = require('./utils');
const urlmodule = require("url");
const axios = require("axios");
const {time_to_second, make_response, content_template} = require("./utils");
function Mgtv() {
this.name = '芒果TV'
this.domain = 'mgtv.com'
this.example_urls = [
'https://www.mgtv.com/b/336727/8087768.html',
'https://www.mgtv.com/b/459529/17730031.html' //api lens 90
];
this.name = "芒果TV";
this.domain = "mgtv.com";
this.example_urls = [
"https://www.mgtv.com/b/336727/8087768.html",
"https://www.mgtv.com/b/459529/17730031.html" //api lens 90
];
this.resolve = async (url) => {
const api_video_info = "https://pcweb.api.mgtv.com/video/info"
const api_danmaku = 'https://galaxy.bz.mgtv.com/rdbarrage'
const q = urlmodule.parse(url, true);
const path = q.pathname.split('/');
const cid = path.slice(-2)[0];
const vid = path.slice(-1)[0].split('.')[0];
const res = await axios.get(api_video_info, {params: {cid, vid}});
this.title = res.data.data.info.videoName;
const time = res.data.data.info.time;
this.resolve = async (url) => {
const api_video_info = "https://pcweb.api.mgtv.com/video/info";
const api_danmaku = "https://galaxy.bz.mgtv.com/rdbarrage";
const q = urlmodule.parse(url, true);
const path = q.pathname.split("/");
const cid = path.slice(-2)[0];
const vid = path.slice(-1)[0].split(".")[0];
const res = await axios.get(api_video_info, {params: {cid, vid}});
this.title = res.data.data.info.videoName;
const time = res.data.data.info.time;
const step = 60 * 1000;
const end_time = time_to_second(time) * 1000;
let promises = [];
for (let i = 0; i < end_time; i += step) {
promises.push(axios({method: 'get', url: api_danmaku, params: {vid, cid, time: i}}));
}
return promises
}
const step = 60 * 1000;
const end_time = time_to_second(time) * 1000;
let promises = [];
for (let i = 0; i < end_time; i += step) {
promises.push(axios({method: "get", url: api_danmaku, params: {vid, cid, time: i}}));
}
return promises;
};
this.parse = async (promises) => {
let contents = [];
const values = await Promise.all(promises)
let datas = values.map(value => value.data)
for (const data of datas) {
if (data.data.items === null)
continue;
for (const item of data.data.items) {
const content = JSON.parse(JSON.stringify(content_template));
content.timepoint = item.time / 1000;
content.content = item.content;
content.uid = item.uid;
contents.push(content);
}
}
contents = make_response(contents)
return contents
}
this.parse = async (promises) => {
let contents = [];
const values = await Promise.all(promises);
let datas = values.map(value => value.data);
for (const data of datas) {
if (data.data.items === null)
continue;
for (const item of data.data.items) {
const content = JSON.parse(JSON.stringify(content_template));
content.timepoint = item.time / 1000;
content.content = item.content;
content.uid = item.uid;
contents.push(content);
}
}
contents = make_response(contents);
return contents;
};
this.work = async (url) => {
const promises = await this.resolve(url);
console.log(this.name,'api lens:', promises.length)
this.content = await this.parse(promises);
return {
title: this.title,
content: this.content,
msg: 'ok'
}
}
this.work = async (url) => {
const promises = await this.resolve(url);
console.log(this.name,"api lens:", promises.length);
this.content = await this.parse(promises);
return {
title: this.title,
content: this.content,
msg: "ok"
};
};
}
module.exports = Mgtv
module.exports = Mgtv;
if (!module.parent) {
const m = new Mgtv();
const m = new Mgtv();
m.work(m.example_urls[0]).then(() => {
console.log(m.content);
console.log(m.title);
});
m.work(m.example_urls[0]).then(() => {
console.log(m.content);
console.log(m.title);
});
}

View File

@@ -1,93 +1,92 @@
const urlmodule = require('url');
const axios = require('axios');
const urlmodule = require("url");
const axios = require("axios");
const whacko = require("whacko");
const {make_response, content_template} = require('./utils');
const {make_response, content_template} = require("./utils");
function Tencentvideo() {
this.name = '腾讯视频'
this.domain = 'v.qq.com'
this.example_urls = [
'https://v.qq.com/x/cover/mzc002003pn34qk/u3319i5s3jt.html',
'https://v.qq.com/x/cover/53q0eh78q97e4d1/x00174aq5no.html',//api lens 50
'https://v.qq.com/x/cover/mzc00200fph94nw/l00448ijvve.html',//api lens 91
];
this.name = "腾讯视频";
this.domain = "v.qq.com";
this.example_urls = [
"https://v.qq.com/x/cover/mzc002003pn34qk/u3319i5s3jt.html",
"https://v.qq.com/x/cover/53q0eh78q97e4d1/x00174aq5no.html",//api lens 50
"https://v.qq.com/x/cover/mzc00200fph94nw/l00448ijvve.html",//api lens 91
];
this.resolve = async (url) => {
const api_danmaku_base = "https://dm.video.qq.com/barrage/base/"
const api_danmaku_segment = "https://dm.video.qq.com/barrage/segment/"
const q = urlmodule.parse(url, true);
const path = q.pathname.split('/');
let vid;
if (q.query.vid) {
vid = q.query.vid
} else {
vid = path.slice(-1)[0].split('.')[0];
}
let res = await axios.get(url);
const $ = whacko.load(res.data, null, false);
this.title = $("title")[0].children[0].data.split('_')[0];
console.log('vid:', vid,'title:', this.title)
try {
res = await axios.get(api_danmaku_base + vid);
} catch (e) {
if (e.response.status === 404) {
this.error_msg = '好像没有弹幕哦'
return
} else throw e
}
this.resolve = async (url) => {
const api_danmaku_base = "https://dm.video.qq.com/barrage/base/";
const api_danmaku_segment = "https://dm.video.qq.com/barrage/segment/";
const q = urlmodule.parse(url, true);
const path = q.pathname.split("/");
let vid;
if (q.query.vid) {
vid = q.query.vid;
} else {
vid = path.slice(-1)[0].split(".")[0];
}
let res = await axios.get(url);
const $ = whacko.load(res.data, null, false);
this.title = $("title")[0].children[0].data.split("_")[0];
console.log("vid:", vid,"title:", this.title);
try {
res = await axios.get(api_danmaku_base + vid);
} catch (e) {
if (e.response.status === 404) {
this.error_msg = "好像没有弹幕哦";
return;
} else throw e;
}
let promises = []
let list = Object.values(res.data.segment_index)
for (item of list) {
promises.push(axios.get(`${api_danmaku_segment}${vid}/${item.segment_name}`))
}
return promises
}
let promises = [];
let list = Object.values(res.data.segment_index);
for (const item of list) {
promises.push(axios.get(`${api_danmaku_segment}${vid}/${item.segment_name}`));
}
return promises;
};
this.parse = async (promises) => {
let contents = [];
const values = await Promise.all(promises)
let datas = values.map(value => value.data)
this.parse = async (promises) => {
let contents = [];
const values = await Promise.all(promises);
let datas = values.map(value => value.data);
for (const data of datas) {
for (const item of data.barrage_list) {
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)
console.log("有颜色", content_style);
}
content.content = item.content;
contents.push(content);
}
}
contents = make_response(contents)
return contents
}
for (const data of datas) {
for (const item of data.barrage_list) {
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);
console.log("有颜色", content_style);
}
content.content = item.content;
contents.push(content);
}
}
contents = make_response(contents);
return contents;
};
this.work = async (url) => {
const promises = await this.resolve(url);
if (!this.error_msg) {
console.log(this.name, 'api lens:', promises.length)
this.content = await this.parse(promises)
}
return {
title: this.title,
content: this.content,
msg: this.error_msg ? this.error_msg : 'ok'
}
}
this.work = async (url) => {
const promises = await this.resolve(url);
if (!this.error_msg) {
console.log(this.name, "api lens:", promises.length);
this.content = await this.parse(promises);
}
return {
title: this.title,
content: this.content,
msg: this.error_msg ? this.error_msg : "ok"
};
};
}
module.exports = Tencentvideo
module.exports = Tencentvideo;
if (!module.parent) {
console.log('main')
const t = new Tencentvideo()
t.work(t.example_urls[0]).then(() => {
console.log(t.content)
console.log(t.title)
});
}
console.log("main");
const t = new Tencentvideo();
t.work(t.example_urls[0]).then(() => {
console.log(t.content);
console.log(t.title);
});
}

View File

@@ -1,50 +1,50 @@
const convert = require("xml-js");
const content_template = {
timepoint: 0,
content: '',
ct: 1,
size: 20,
color: 16777215,
unixtime: Math.floor(Date.now() / 1000),
uid: 0,
timepoint: 0,
content: "",
ct: 1,
size: 20,
color: 16777215,
unixtime: Math.floor(Date.now() / 1000),
uid: 0,
};
function time_to_second(time) {
const t = time.split(':');
let s = 0;
let m = 1;
while (t.length > 0) {
s += m * parseInt(t.pop(), 10);
m *= 60;
}
return s;
const t = time.split(":");
let s = 0;
let m = 1;
while (t.length > 0) {
s += m * parseInt(t.pop(), 10);
m *= 60;
}
return s;
}
function make_response(contents) {
let xml = {
_declaration: {
_attributes: {
version: '1.0',
encoding: 'utf-8'
}
},
i: {
d: []
}
}
for (let content of contents) {
xml.i.d.push({
_attributes: {
p: `${content.timepoint},${content.ct},${content.size},${content.color},${content.unixtime},${content.uid},26732601000067074`
},
_text: content.content
});
}
let xml = {
_declaration: {
_attributes: {
version: "1.0",
encoding: "utf-8"
}
},
i: {
d: []
}
};
for (let content of contents) {
xml.i.d.push({
_attributes: {
p: `${content.timepoint},${content.ct},${content.size},${content.color},${content.unixtime},${content.uid},26732601000067074`
},
_text: content.content
});
}
const res = convert.js2xml(xml, {compact: true, spaces: 4})
return res
const res = convert.js2xml(xml, {compact: true, spaces: 4});
return res;
}
module.exports = {time_to_second, make_response, content_template};
module.exports = {time_to_second, make_response, content_template};

View File

@@ -1,166 +1,173 @@
const urlmodule = require('url');
const axios = require('axios');
const cookie = require('cookie');
const crypto = require('crypto');
const {make_response, content_template} = require('./utils');
const urlmodule = require("url");
const axios = require("axios");
const cookie = require("cookie");
const crypto = require("crypto");
const {
make_response,
content_template
} = require("./utils");
function Youku() {
this.name = '优酷'
this.domain = 'v.youku.com'
this.example_urls = [
'https://v.youku.com/v_show/id_XNTE5NjUxNjUyOA==.html',
'https://v.youku.com/v_show/id_XMTc1OTE4ODI5Ng==.html',
'https://v.youku.com/v_show/id_XNTkxNDY2Nzg2MA==.html'
];
this.name = "优酷";
this.domain = "v.youku.com";
this.example_urls = [
"https://v.youku.com/v_show/id_XNTE5NjUxNjUyOA==.html",
"https://v.youku.com/v_show/id_XMTc1OTE4ODI5Ng==.html",
"https://v.youku.com/v_show/id_XNTkxNDY2Nzg2MA==.html"
];
this.get_tk_enc = async () => {
const api_url = "https://acs.youku.com/h5/mtop.com.youku.aplatform.weakget/1.0/?jsv=2.5.1&appKey=24679788"
const res = await axios.get(api_url);
const cookies = res.headers['set-cookie']
let targetCookie = {};
for (let cookieStr of cookies) {
targetCookie = Object.assign(targetCookie, cookie.parse(cookieStr));
}
return targetCookie
}
this.get_cna = async () => {
const api_url = "https://log.mmstat.com/eg.js"
const res = await axios.get(api_url);
const cookies = res.headers['set-cookie']
let targetCookie = {};
for (let cookieStr of cookies) {
targetCookie = Object.assign(targetCookie, cookie.parse(cookieStr));
}
return targetCookie['cna']
}
this.get_tk_enc = async () => {
const api_url = "https://acs.youku.com/h5/mtop.com.youku.aplatform.weakget/1.0/?jsv=2.5.1&appKey=24679788";
const res = await axios.get(api_url);
const cookies = res.headers["set-cookie"];
let targetCookie = {};
for (let cookieStr of cookies) {
targetCookie = Object.assign(targetCookie, cookie.parse(cookieStr));
}
return targetCookie;
};
this.get_cna = async () => {
const api_url = "https://log.mmstat.com/eg.js";
const res = await axios.get(api_url);
const cookies = res.headers["set-cookie"];
let targetCookie = {};
for (let cookieStr of cookies) {
targetCookie = Object.assign(targetCookie, cookie.parse(cookieStr));
}
return targetCookie["cna"];
};
const yk_msg_sign = (msg) => {
const md5 = crypto.createHash('md5');
return md5.update(msg + "MkmC9SoIw6xCkSKHhJ7b5D2r51kBiREr").digest('hex');
}
const yk_msg_sign = (msg) => {
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('&');
const md5 = crypto.createHash('md5');
return md5.update(text).digest('hex')
}
const yk_t_sign = (token, t, appkey, data) => {
const text = [token, t, appkey, data].join("&");
const md5 = crypto.createHash("md5");
return md5.update(text)
.digest("hex");
};
const get_vinfos_by_video_id = async (url) => {
const q = urlmodule.parse(url, true);
const path = q.pathname.split('/');
const video_id = path.slice(-1)[0].split('.')[0].slice(3);
if (video_id) {
// "?client_id=53e6cc67237fc59a&package=com.huawei.hwvplayer.youku&ext=show&video_id={}"
const api_url = "https://openapi.youku.com/v2/videos/show.json"
const params = {
client_id: "53e6cc67237fc59a",
video_id: video_id,
package: "com.huawei.hwvplayer.youku",
ext: "show"
}
const res = await axios.get(api_url, {params: params})
const duration = res.data.duration
this.title = res.data.title
console.log("video_id:", video_id, 'duration:', duration, 'title:', this.title)
return [video_id, duration]
}
}
const get_vinfos_by_video_id = async (url) => {
const q = urlmodule.parse(url, true);
const path = q.pathname.split("/");
const video_id = path.slice(-1)[0].split(".")[0].slice(3);
if (video_id) {
// "?client_id=53e6cc67237fc59a&package=com.huawei.hwvplayer.youku&ext=show&video_id={}"
const api_url = "https://openapi.youku.com/v2/videos/show.json";
const params = {
client_id: "53e6cc67237fc59a",
video_id: video_id,
package: "com.huawei.hwvplayer.youku",
ext: "show"
};
const res = await axios.get(api_url, { params: params });
const duration = res.data.duration;
this.title = res.data.title;
console.log("video_id:", video_id, "duration:", duration, "title:", this.title);
return [video_id, duration];
}
};
this.resolve = async (url) => {
const cna = await this.get_cna()
const tk_enc = await this.get_tk_enc()
const headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Cookie": '_m_h5_tk=' + tk_enc['_m_h5_tk'] + ';_m_h5_tk_enc=' + tk_enc['_m_h5_tk_enc'] + ';',
"Referer": "https://v.youku.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36",
}
const [vid, duration] = await get_vinfos_by_video_id(url)
this.resolve = async (url) => {
const cna = await this.get_cna();
const tk_enc = await this.get_tk_enc();
const headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Cookie": "_m_h5_tk=" + tk_enc["_m_h5_tk"] + ";_m_h5_tk_enc=" + tk_enc["_m_h5_tk_enc"] + ";",
"Referer": "https://v.youku.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36",
};
const [vid, duration] = await get_vinfos_by_video_id(url);
const max_mat = Math.floor(duration / 60) + 1
let promises = []
for (let mat = 0; mat < max_mat; mat++) {
const api_url = "https://acs.youku.com/h5/mopen.youku.danmu.list/1.0/"
const msg = {
"ctime": Date.now(),
"ctype": 10004,
"cver": "v1.0",
"guid": cna,
"mat": mat,
"mcount": 1,
"pid": 0,
"sver": "3.1.0",
"type": 1,
"vid": vid
}
// plain-text string
const str = JSON.stringify(msg);
const buff = Buffer.from(str, 'utf-8');
const msg_b64encode = buff.toString('base64');
msg['msg'] = msg_b64encode
msg['sign'] = yk_msg_sign(msg_b64encode)
const data = JSON.stringify(msg)
const t = Date.now()
const params = {
"jsv": "2.5.6",
"appKey": "24679788",
"t": t,
"sign": yk_t_sign(tk_enc["_m_h5_tk"].slice(0, 32), t, "24679788", data),
"api": "mopen.youku.danmu.list",
"v": "1.0",
"type": "originaljson",
"dataType": "jsonp",
"timeout": "20000",
"jsonpIncPrefix": "utility"
}
promises.push(axios.post(api_url, {data}, {headers: headers, params: params}))
}
return promises
}
const max_mat = Math.floor(duration / 60) + 1;
let promises = [];
for (let mat = 0; mat < max_mat; mat++) {
const api_url = "https://acs.youku.com/h5/mopen.youku.danmu.list/1.0/";
const msg = {
"ctime": Date.now(),
"ctype": 10004,
"cver": "v1.0",
"guid": cna,
"mat": mat,
"mcount": 1,
"pid": 0,
"sver": "3.1.0",
"type": 1,
"vid": vid
};
// plain-text string
const str = JSON.stringify(msg);
const buff = Buffer.from(str, "utf-8");
const msg_b64encode = buff.toString("base64");
msg["msg"] = msg_b64encode;
msg["sign"] = yk_msg_sign(msg_b64encode);
const data = JSON.stringify(msg);
const t = Date.now();
const params = {
"jsv": "2.5.6",
"appKey": "24679788",
"t": t,
"sign": yk_t_sign(tk_enc["_m_h5_tk"].slice(0, 32), t, "24679788", data),
"api": "mopen.youku.danmu.list",
"v": "1.0",
"type": "originaljson",
"dataType": "jsonp",
"timeout": "20000",
"jsonpIncPrefix": "utility"
};
promises.push(axios.post(api_url, { data }, {
headers: headers,
params: params
}));
}
return promises;
};
this.parse = async (promises) => {
let contents = [];
const values = await Promise.all(promises)
let datas = values.map(value => value.data)
this.parse = async (promises) => {
let contents = [];
const values = await Promise.all(promises);
let datas = values.map(value => value.data);
let i = 0;
for (const res of datas) {
i ++;
const danmus = JSON.parse(res.data.result).data.result
// 接口请求情况
// console.log(i, res.ret[0])
for (danmu of danmus) {
const content = JSON.parse(JSON.stringify(content_template));
content.timepoint = danmu["playat"] / 1000
if (danmu.propertis.color) {
content.color = JSON.parse(danmu.propertis).color
}
content.content = danmu.content
contents.push(content)
}
}
contents = make_response(contents)
return contents
}
for (const res of datas) {
const danmus = JSON.parse(res.data.result).data.result;
// 接口请求情况
// console.log(i, res.ret[0])
for (const danmu of danmus) {
const content = JSON.parse(JSON.stringify(content_template));
content.timepoint = danmu["playat"] / 1000;
if (danmu.propertis.color) {
content.color = JSON.parse(danmu.propertis).color;
}
content.content = danmu.content;
contents.push(content);
}
}
contents = make_response(contents);
return contents;
};
this.work = async (url) => {
const promises = await this.resolve(url);
console.log(this.name, 'api lens:', promises.length)
this.content = await this.parse(promises);
return {
title: this.title,
content: this.content,
msg: 'ok'
}
}
this.work = async (url) => {
const promises = await this.resolve(url);
console.log(this.name, "api lens:", promises.length);
this.content = await this.parse(promises);
return {
title: this.title,
content: this.content,
msg: "ok"
};
};
}
module.exports = Youku
module.exports = Youku;
if (!module.parent) {
const b = new Youku();
b.work(b.example_urls[0]).then(() => {
console.log(b.content);
console.log(b.title);
});
const b = new Youku();
b.work(b.example_urls[0])
.then(() => {
console.log(b.content);
console.log(b.title);
});
}

View File

@@ -1,73 +1,73 @@
const express = require('express');
const axios = require('axios');
const express = require("express");
const axios = require("axios");
const router = express.Router();
const {bilibili, mgtv, tencentvideo, youku, iqiyi} = require('./api/base');
const {bilibili, mgtv, tencentvideo, youku, iqiyi} = require("./api/base");
const list = [bilibili, mgtv, tencentvideo, youku, iqiyi];
const memory = require('../utils/memory')
const leancloud = require('../utils/leancloud')
const memory = require("../utils/memory");
const leancloud = require("../utils/leancloud");
async function build_response(url, req) {
try {
await axios.get(url)
} catch (e) {
console.log(e)
return {msg: '传入的链接非法!请检查链接是否能在浏览器正常打开'}
}
let fc = undefined;
for (let item of list) {
if (url.indexOf(item.domain) !== -1) {
fc = item
}
}
if (fc === undefined) {
return {'msg': '不支持的视频网址'}
}
let ret;
try {
ret = await fc.work(url)
} catch (e) {
console.log(e)
let err = JSON.stringify(e, Object.getOwnPropertyNames(e))
err = JSON.parse(err)
leancloud.add('DanmakuError', {ip: req.ip, url, err})
return {msg: '弹幕解析过程中程序报错退出,请等待管理员修复!或者换条链接试试!'}
}
return ret
try {
await axios.get(url);
} catch (e) {
console.log(e);
return {msg: "传入的链接非法!请检查链接是否能在浏览器正常打开"};
}
let fc = undefined;
for (let item of list) {
if (url.indexOf(item.domain) !== -1) {
fc = item;
}
}
if (fc === undefined) {
return {"msg": "不支持的视频网址"};
}
let ret;
try {
ret = await fc.work(url);
} catch (e) {
console.log(e);
let err = JSON.stringify(e, Object.getOwnPropertyNames(e));
err = JSON.parse(err);
leancloud.add("DanmakuError", {ip: req.ip, url, err});
return {msg: "弹幕解析过程中程序报错退出,请等待管理员修复!或者换条链接试试!"};
}
return ret;
}
/* GET home page. */
router.get('/', async function (req, res, next) {
leancloud.add('DanmakuAccess', {remoteIP: req.ip, url: req.query.url, UA: req.headers['user-agent']})
//检查是否包含URL参数
if (!req.query.url) {
const urls = [mgtv.example_urls[0], bilibili.example_urls[0], tencentvideo.example_urls[0], youku.example_urls[0], iqiyi.example_urls[0]];
const path = req.protocol + '://' + req.headers.host + req.originalUrl;
res.render('danmaku', {path, urls});
} else {
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)
} else if (download) {
res.attachment(ret.title + '.xml');
res.end(ret.content);
} else {
res.type('application/xml');
res.end(ret.content);
}
}
router.get("/", async function (req, res) {
leancloud.add("DanmakuAccess", {remoteIP: req.ip, url: req.query.url, UA: req.headers["user-agent"]});
//检查是否包含URL参数
if (!req.query.url) {
const urls = [mgtv.example_urls[0], bilibili.example_urls[0], tencentvideo.example_urls[0], youku.example_urls[0], iqiyi.example_urls[0]];
const path = req.protocol + "://" + req.headers.host + req.originalUrl;
res.render("danmaku", {path, urls});
} else {
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);
} else if (download) {
res.attachment(ret.title + ".xml");
res.end(ret.content);
} else {
res.type("application/xml");
res.end(ret.content);
}
}
});
router.get('/pageinfo', async function (req, res, next) {
const promises = [
leancloud.danmakuQuery(leancloud.currentDay()),
leancloud.danmakuQuery(leancloud.lastDay()),
leancloud.danmakuQuery(leancloud.currentMonth())
]
const [today_visited, lastday_visited, month_visited] = await Promise.all(promises)
res.json({today_visited, lastday_visited, month_visited})
router.get("/pageinfo", async function (req, res) {
const promises = [
leancloud.danmakuQuery(leancloud.currentDay()),
leancloud.danmakuQuery(leancloud.lastDay()),
leancloud.danmakuQuery(leancloud.currentMonth())
];
const [today_visited, lastday_visited, month_visited] = await Promise.all(promises);
res.json({today_visited, lastday_visited, month_visited});
});
module.exports = router;

View File

@@ -1,26 +1,26 @@
const express = require('express');
const express = require("express");
const router = express.Router();
const libqqwry = require('lib-qqwry');
const dns = require('dns');
const libqqwry = require("lib-qqwry");
const dns = require("dns");
const qqwry = libqqwry(); //初始化IP库解析器
/* GET home page. */
router.get('/', function (req, res, next) {
let ip = req.query.name || req.ip;
dns.lookup(ip, (err, address, family) => {
let ipL;
if (err) {
ipL = { 'ip': ip, 'msg': '域名解析IP失败' };
} else {
ip = address
try {
ipL = qqwry.searchIP(ip); //查询IP信息
} catch (e) {
ipL = { 'ip': ip, 'msg': e };
}
}
res.json(ipL);
});
router.get("/", function (req, res) {
let ip = req.query.name || req.ip;
dns.lookup(ip, (err, address) => {
let ipL;
if (err) {
ipL = { "ip": ip, "msg": "域名解析IP失败" };
} else {
ip = address;
try {
ipL = qqwry.searchIP(ip); //查询IP信息
} catch (e) {
ipL = { "ip": ip, "msg": e };
}
}
res.json(ipL);
});
});
module.exports = router;

View File

@@ -4,23 +4,22 @@ const chai = require("chai");
const chaiHttp = require("chai-http");
const app = require("../app");
function subcache() {
console.log("Running Cron Jobsubcache");
chai.use(chaiHttp);
chai.request(app)
.get('/sub/cache')
.end((err, res) => {
leancloud.add('Schedule', {name: 'subcache', result: res.text});
console.log(res.text);
});
console.log("Running Cron Jobsubcache");
chai.use(chaiHttp);
chai.request(app)
.get("/sub/cache")
.end((err, res) => {
leancloud.add("Schedule", {name: "subcache", result: res.text});
console.log(res.text);
});
}
cron.schedule('0 12/3 * * *', () => {
subcache();
cron.schedule("0 * * * *", () => {
subcache();
});
//TODO 添加自动删除一个月前的日志
console.log('schedule.js loaded');
if (!module.parent) {
subcache();
}
console.log("schedule.js loaded");
// if (!module.parent) {
// subcache();
// }

View File

@@ -1,180 +1,179 @@
let chai = require('chai');
let chaiHttp = require('chai-http');
let app = require('../app');
const { bilibili, mgtv, tencentvideo, youku, iqiyi } = require('../routes/api/base');
let chai = require("chai");
let chaiHttp = require("chai-http");
let app = require("../app");
const { bilibili, mgtv, tencentvideo, youku, iqiyi } = require("../routes/api/base");
const list = [bilibili, mgtv, tencentvideo, youku, iqiyi];
let should = chai.should();
chai.should();
chai.use(chaiHttp);
//TODO: add more test cases
describe('App', () => {
describe("App", () => {
describe('弹幕解析模块测试', function () {
this.timeout(1000*10);
it('主页测试', (done) => {
chai.request(app)
.get('/')
.end((err, res) => {
res.should.have.status(200);
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;
for (const i in example_urls) {
const url = example_urls[i];
it(name+'视频测试#'+i, (done) => {
chai.request(app)
.get('/')
.query({url})
.end((err, res) => {
res.should.have.status(200);
res.header['content-type'].should.equal('application/xml');
done();
});
});
}
}
describe("弹幕解析模块测试", function () {
this.timeout(1000*10);
it("主页测试", (done) => {
chai.request(app)
.get("/")
.end((err, res) => {
res.should.have.status(200);
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;
for (const i in example_urls) {
const url = example_urls[i];
it(name+"视频测试#"+i, (done) => {
chai.request(app)
.get("/")
.query({url})
.end((err, res) => {
res.should.have.status(200);
res.header["content-type"].should.equal("application/xml");
done();
});
});
}
}
});
it('should respond status 404', (done) => {
chai.request(app)
.get('/wrongUrl')
.end((err, res) => {
res.should.have.status(404);
done();
});
});
describe('ipinfo modules', () => {
it('GET the ipinfo response', (done) => {
chai.request(app)
.get('/ipinfo')
.end((err, res) => {
res.should.have.status(200);
done();
});
});
it('GET the ipinfo with name', (done) => {
chai.request(app)
.get('/ipinfo?name=home999.cc')
.end((err, res) => {
res.should.have.status(200);
done();
});
});
});
describe('机场订阅模块',function (){
this.timeout(1000*5);
it('接口不带参数测试', (done) =>{
chai.request(app)
.get('/sub')
.end((err,res) => {
res.should.have.status(400);
done();
});
});
it('接口错误参数测试', (done) =>{
chai.request(app)
.get('/sub?abc=123')
.end((err,res) => {
res.should.have.status(400);
done();
});
});
it('接口带user参数测试', (done) =>{
chai.request(app)
.get('/sub?user=congcong')
.end((err,res) => {
res.should.have.status(200);
done();
});
});
it('接口错误user参数测试', (done) =>{
chai.request(app)
.get('/sub?user=123')
.end((err,res) => {
res.should.have.status(404);
done();
});
});
it('接口带user与ctype参数测试', (done) =>{
chai.request(app)
.get('/sub?user=congcong&ctype=v2ray')
.end((err,res) => {
res.should.have.status(200);
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')
.end((err,res) => {
res.should.have.status(200);
done();
});
});
it('软件下载测试', (done) =>{
chai.request(app)
.get('/sub/download')
.end((err,res) => {
res.should.have.status(200);
res.text.should.have.string('clash');
res.text.should.have.string('v2ray');
res.text.should.have.string('shadowsocks');
done();
});
});
});
});
});
it("should respond status 404", (done) => {
chai.request(app)
.get("/wrongUrl")
.end((err, res) => {
res.should.have.status(404);
done();
});
});
describe("ipinfo modules", () => {
it("GET the ipinfo response", (done) => {
chai.request(app)
.get("/ipinfo")
.end((err, res) => {
res.should.have.status(200);
done();
});
});
it("GET the ipinfo with name", (done) => {
chai.request(app)
.get("/ipinfo?name=home999.cc")
.end((err, res) => {
res.should.have.status(200);
done();
});
});
});
describe("机场订阅模块",function (){
this.timeout(1000*5);
it("接口不带参数测试", (done) =>{
chai.request(app)
.get("/sub")
.end((err,res) => {
res.should.have.status(400);
done();
});
});
it("接口错误参数测试", (done) =>{
chai.request(app)
.get("/sub?abc=123")
.end((err,res) => {
res.should.have.status(400);
done();
});
});
it("接口带user参数测试", (done) =>{
chai.request(app)
.get("/sub?user=congcong")
.end((err,res) => {
res.should.have.status(200);
done();
});
});
it("接口错误user参数测试", (done) =>{
chai.request(app)
.get("/sub?user=123")
.end((err,res) => {
res.should.have.status(404);
done();
});
});
it("接口带user与ctype参数测试", (done) =>{
chai.request(app)
.get("/sub?user=congcong&ctype=v2ray")
.end((err,res) => {
res.should.have.status(200);
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")
.end((err,res) => {
res.should.have.status(200);
done();
});
});
it("软件下载测试", (done) =>{
chai.request(app)
.get("/sub/download")
.end((err,res) => {
res.should.have.status(200);
res.text.should.have.string("clash");
res.text.should.have.string("v2ray");
res.text.should.have.string("shadowsocks");
done();
});
});
});
});

View File

@@ -1,19 +1,20 @@
require('dotenv').config({path: '../.env'});
const memory = require('../utils/memory');
const hkaliyun = require('./bot/hkaliyun.js');
const airportsub = require('./bot/airportsub.js');
require("dotenv").config({path: "../.env"});
const memory = require("../utils/memory");
const hkaliyun = require("./bot/hkaliyun.js");
const airportsub = require("./bot/airportsub.js");
bots = [
hkaliyun(process.env.TELEGRAM_TOKEN_HKALIYUN),
airportsub(process.env.TELEGRAM_TOKEN_AIRPORTSUB),
const bots = [
hkaliyun(process.env.TELEGRAM_TOKEN_HKALIYUN),
airportsub(process.env.TELEGRAM_TOKEN_AIRPORTSUB),
];
console.log('bot.js loaded');
memory()
console.log("bot.js loaded");
memory();
for (const bot of bots) {
bot.getMe().then((botInfo) => {
console.log('Bot info:', botInfo);
});
// bot.getWebHookInfo().then((webhookInfo) => {
// console.log('Webhook info:', webhookInfo);
// });
}
bot.getMe().then((botInfo) => {
console.log("Bot info:", botInfo);
});
bot.deleteWebHook();
// bot.getWebHookInfo().then((webhookInfo) => {
// console.log('Webhook info:', webhookInfo);
// });
}

View File

@@ -1,215 +1,223 @@
// Import modules
const whacko = require('whacko');
const yaml = require('js-yaml');
const TelegramBot = require('node-telegram-bot-api');
const goindex = require('./goindex');
const axios = require('axios');
const OSS = require('ali-oss');
const whacko = require("whacko");
const yaml = require("js-yaml");
const TelegramBot = require("node-telegram-bot-api");
const axios = require("axios");
const OSS = require("ali-oss");
const goindex = require("./goindex");
// Environment variables
const OSS_OPTIONS = {
region: 'oss-cn-hongkong',
accessKeyId: process.env.OSS_ACCESS_KEY,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
bucket: 'hkosslog'
region: "oss-cn-hongkong",
accessKeyId: process.env.OSS_ACCESS_KEY,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
bucket: "hkosslog",
};
// function sleep(ms) {
// return new Promise((resolve) => setTimeout(resolve, ms));
// }
module.exports = (TOKEN) => {
let game = {};
const bot = new TelegramBot(TOKEN, {polling: true});
const client = new OSS(OSS_OPTIONS);
const game = {};
let setu = {};
const bot = new TelegramBot(TOKEN, { polling: true });
const client = new OSS(OSS_OPTIONS);
function sendSetu(chatId, i) {
const href = setu[i];
const prev = { text: "上一张", callback_data: i - 1 };
const next = { text: "下一张", callback_data: i + 1 };
let replyMarkup = { inline_keyboard: [[prev, next]] };
if (i === 0) {
replyMarkup = { inline_keyboard: [[next]] };
} else if (i+1 === setu.length) {
replyMarkup = { inline_keyboard: [[prev]] };
}
bot.sendMessage(chatId, href, { reply_markup: replyMarkup });
}
// Just to ping!
bot.on('message', msg => {
if (!msg.text) {
bot.sendMessage(msg.chat.id, 'I can only understand text messages!');
}
});
// Just to ping!
bot.on("message", (msg) => {
if (!msg.text) {
bot.sendMessage(msg.chat.id, "I can only understand text messages!");
}
});
// 智能聊天机器人
bot.on('text', msg => {
if (msg.text.indexOf('/') === -1) {
bot.sendMessage(msg.chat.id, 'you said: ' + msg.text);
axios.get('https://api.qingyunke.com/api.php?key=free&appid=0&msg=' + encodeURI(msg.text)).then(res => {
console.log(res.data);
bot.sendMessage(msg.chat.id, res.data.content);
});
}
});
// 智能聊天机器人
bot.on("text", (msg) => {
if (msg.text.indexOf("/") === -1) {
bot.sendMessage(msg.chat.id, `you said: ${msg.text}`);
axios.get(`https://api.qingyunke.com/api.php?key=free&appid=0&msg=${encodeURI(msg.text)}`).then((res) => {
console.log(res.data);
bot.sendMessage(msg.chat.id, res.data.content);
});
}
});
// 欢迎页面
bot.onText(/\/start/, (msg) => {
let name = [msg.from.first_name];
if (msg.from.last_name) {
name.push(msg.from.last_name);
}
name = name.join(" ");
bot.sendMessage(msg.chat.id, `Welcome, ${name}!`);
bot.sendMessage(msg.chat.id, `You can send me any message and I will repeat it back to you.`);
bot.sendMessage(msg.chat.id, `You can also send me commands like /start, /help.`);
});
// 欢迎页面
bot.onText(/\/start/, (msg) => {
let name = [msg.from.first_name];
if (msg.from.last_name) {
name.push(msg.from.last_name);
}
name = name.join(" ");
bot.sendMessage(msg.chat.id, `Welcome, ${name}!`);
bot.sendMessage(msg.chat.id, "你可以给我发送消息,我会回复你.");
bot.sendMessage(msg.chat.id, "你可以发送类似这样的指令 /start, /help.");
});
// 发送用户头像
bot.onText(/\/sendpic/, (msg) => {
bot.getUserProfilePhotos(msg.chat.id).then(photos => {
const photo = photos.photos[0][0];
bot.sendPhoto(msg.chat.id, photo.file_id, {
caption: "This is a picture of You!"
});
});
// bot.sendPhoto(msg.chat.id, "https://blog.home999.cc/images/avatar.jpg");
});
// 发送用户头像
bot.onText(/\/sendpic/, (msg) => {
bot.getUserProfilePhotos(msg.chat.id).then((photos) => {
const photo = photos.photos[0][0];
bot.sendPhoto(msg.chat.id, photo.file_id, {
caption: "This is a picture of You!",
});
});
// bot.sendPhoto(msg.chat.id, "https://blog.home999.cc/images/avatar.jpg");
});
bot.onText(/\/register/, (msg) => {
bot.sendMessage(msg.chat.id, `Chat id: ${msg.chat.id}\n请把该id告诉管理员用于注册。`);
});
bot.onText(/\/register/, (msg) => {
bot.sendMessage(msg.chat.id, `Chat id: ${msg.chat.id}\n请把该id告诉管理员用于注册。`);
});
bot.onText(/\/sub/, async (msg) => {
const database = await (await client.get("SUB/database.yaml")).content.toString();
const data = yaml.load(database);
const users = data.user;
for (let user in users) {
if (users[user].chatID == msg.chat.id) {
bot.sendMessage(msg.chat.id, `您已经注册过了,请勿重复注册。`);
bot.sendMessage(msg.chat.id, `你好,${user}`);
const url = `https://fc.home999.cc/sub?user=${user}`;
bot.sendMessage(msg.chat.id, `您的订阅链接为:${url}`);
return;
}
}
bot.sendMessage(msg.chat.id, `您已经成功注册,请等待管理员审核`);
});
bot.onText(/\/sub/, async (msg) => {
const database = await (await client.get("SUB/database.yaml")).content.toString();
const data = yaml.load(database);
const users = data.user;
// eslint-disable-next-line no-restricted-syntax
for (const user in users) {
if (users[user].chatID === msg.chat.id) {
bot.sendMessage(msg.chat.id, "您已经注册过了,请勿重复注册。");
bot.sendMessage(msg.chat.id, `你好,${user}`);
const url = `https://fc.home999.cc/sub?user=${user}`;
bot.sendMessage(msg.chat.id, `您的订阅链接为:${url}`);
return;
}
}
bot.sendMessage(msg.chat.id, "您已经成功注册,请等待管理员审核");
});
//猜数游戏
bot.onText(/\/game/, (msg) => {
const chatID = msg.chat.id;
const guess = parseInt(msg.text.replace("/game", ""));
if (game[chatID] == undefined) {
game[chatID] = {
num: Math.floor(Math.random() * 100),
limit: 10,
}
bot.sendMessage(chatID, `我们来玩猜数游戏吧!`);
bot.sendMessage(chatID, `猜一个数字你有10次机会。范围:[0, 100)`);
bot.sendMessage(chatID, `请输入你的猜测:(例:/game 50)`);
return;
}
let {num, limit} = game[chatID];
if (limit <= 0) {
bot.sendMessage(chatID, `游戏结束!未猜出正确答案,正确答案为:${num}`);
game[chatID] = undefined;
return;
}
game[chatID].limit--;
if (guess == num) {
bot.sendMessage(chatID, `恭喜你猜对了!`);
game[chatID] = undefined;
} else if (guess > num) {
bot.sendMessage(chatID, `你猜的数字太大了!`);
} else {
bot.sendMessage(chatID, `你猜的数字太小了!`);
}
});
// 猜数游戏
bot.onText(/\/game/, async (msg) => {
const chatID = msg.chat.id;
const guess = parseInt(msg.text.replace("/game", ""), 10);
if (game[chatID] === undefined) {
game[chatID] = {
num: Math.floor(Math.random() * 100),
limit: 10,
};
await bot.sendMessage(chatID, "我们来玩猜数游戏吧!");
await bot.sendMessage(chatID, "猜一个数字你有10次机会。范围:[0, 100)");
await bot.sendMessage(chatID, "请输入你的猜测:(例:/game 50)");
return;
}
const { num, limit } = game[chatID];
if (limit <= 0) {
bot.sendMessage(chatID, `游戏结束!未猜出正确答案,正确答案为:${num}`);
game[chatID] = undefined;
return;
}
game[chatID].limit -= 1;
if (guess === num) {
bot.sendMessage(chatID, "恭喜你猜对了!");
game[chatID] = undefined;
} else if (guess > num) {
bot.sendMessage(chatID, "你猜的数字太大了!");
} else {
bot.sendMessage(chatID, "你猜的数字太小了!");
}
});
bot.onText(/\/help/, (msg) => {
const helpMsg = [
{command: 'start', description: '欢迎界面'},
{command: 'game', description: '猜数游戏'},
{command: 'sub', description: '订阅链接'},
{command: 'register', description: '注册'},
{command: 'sendpic', description: '发送你的头像'},
{command: 'setu', description: '随机色图,可加编号'},
{command: 'goindex', description: '查询GoIndex上的文件'},
{command: 'help', description: '帮助'},
];
const helpMsgText = helpMsg.map(item => {
return `/${item.command} - ${item.description}`;
}).join("\n");
bot.sendMessage(msg.chat.id, helpMsgText, {parse_mode: "HTML"});
bot.setMyCommands(helpMsg);
});
bot.onText(/\/help/, (msg) => {
const helpMsg = [
{ command: "start", description: "欢迎界面" },
{ command: "game", description: "猜数游戏" },
{ command: "sub", description: "订阅链接" },
{ command: "register", description: "注册" },
{ command: "sendpic", description: "发送你的头像" },
{ command: "setu", description: "随机色图,可加编号" },
{ command: "goindex", description: "查询GoIndex上的文件" },
{ command: "help", description: "帮助" },
];
const helpMsgText = helpMsg.map((item) => `/${item.command} - ${item.description}`).join("\n");
bot.sendMessage(msg.chat.id, helpMsgText, { parse_mode: "HTML" });
bot.setMyCommands(helpMsg);
});
bot.onText(/\/setu/, (msg) => {
const index = parseInt(msg.text.replace("/setu", ""));
bot.sendMessage(msg.chat.id, `色图模式`);
axios.get('https://asiantolick.com/ajax/buscar_posts.php', {params: {index}})
.then(res => {
const $ = whacko.load(res.data);
$('.miniatura').each((i, e) => {
const href = $(e).attr('href');
setTimeout(() => {
bot.sendMessage(msg.chat.id, href, {
reply_markup: {
inline_keyboard: [
[{text: '带我去看图', url: href}],
]
}
});
}, i * 250);
});
});
});
bot.onText(/\/setu/, async (msg) => {
const index = parseInt(msg.text.replace("/setu", ""), 10);
bot.sendMessage(msg.chat.id, "色图模式");
const res = await axios.get("https://asiantolick.com/ajax/buscar_posts.php", { params: { index } });
const $ = whacko.load(res.data);
setu = Object.values($(".miniatura")).map((item) => $(item).attr("href"));
sendSetu(msg.chat.id, 0);
});
bot.onText(/\/goindex/, (msg) => {
const q = msg.text.replace("/goindex ", "")
bot.sendMessage(msg.chat.id, `正在搜寻“${q}”...`);
goindex.query(q).then(res => {
//筛选符合条件的文件
videos = res.filter(e => e.mimeType === "video/mp4").filter(e => e.size < 50 * 1024 * 1024);
images = res.filter(e => e.mimeType === "image/jpeg");
audios = res.filter(e => e.mimeType === "audio/mp3").filter(e => e.size < 50 * 1024 * 1024);
folders = res.filter(e => e.mimeType === "application/vnd.google-apps.folder");
bot.on("callback_query", async (query) => {
const i = parseInt(query.data, 10);
const queryId = query.id;
sendSetu(query.message.chat.id, i);
bot.answerCallbackQuery(queryId);
});
bot.sendMessage(msg.chat.id, `共有${images.length}个图片结果,${videos.length}个视频,${audios.length}个音乐,${folders.length}个目录,搜索结果:`);
bot.sendChatAction(msg.chat.id, "upload_photo");
images = goindex.group(images, 10);
images.forEach((e, i) => {
setTimeout(() => {
bot.sendMediaGroup(msg.chat.id, e.map(e => {
return {
type: "photo",
media: e.thumbnailLink.replace('=s220', '=s0'),
caption: e.name,
}
}));
}, i * 2000);
});
bot.sendChatAction(msg.chat.id, 'upload_video');
videos.forEach((e, i) => {
setTimeout(() => {
goindex.id2path(e.id).then(path => {
console.log(path);
bot.sendVideo(msg.chat.id, encodeURI(path), {
caption: `${e.name}`,
reply_markup: {
inline_keyboard: [
[{text: '带我去看片', url: encodeURI(path)}],
]
}
});
});
}, i * 2000);
});
bot.sendChatAction(msg.chat.id, 'upload_voice');
audios.forEach((e, i) => {
setTimeout(() => {
goindex.id2path(e.id).then(path => {
console.log(path);
bot.sendAudio(msg.chat.id, path, {caption: `${e.name}`});
});
}, i * 2000);
});
})
});
bot.onText(/\/goindex/, (msg) => {
const q = msg.text.replace("/goindex ", "");
bot.sendMessage(msg.chat.id, `正在搜寻“${q}”...`);
goindex.query(q).then((res) => {
// 筛选符合条件的文件
const videos = res.filter((e) => e.mimeType === "video/mp4").filter((e) => e.size < 50 * 1024 * 1024);
let images = res.filter((e) => e.mimeType === "image/jpeg");
const audios = res.filter((e) => e.mimeType === "audio/mp3").filter((e) => e.size < 50 * 1024 * 1024);
const folders = res.filter((e) => e.mimeType === "application/vnd.google-apps.folder");
bot.onText(/\/senddice/, (msg) => {
bot.sendDice(msg.chat.id, {emoji: "🎲"});
});
bot.sendMessage(msg.chat.id, `共有${images.length}个图片结果,${videos.length}个视频,${audios.length}个音乐,${folders.length}个目录,搜索结果:`);
bot.sendChatAction(msg.chat.id, "upload_photo");
images = goindex.group(images, 10);
images.forEach((e, i) => {
setTimeout(() => {
bot.sendMediaGroup(msg.chat.id, e.map((el) => ({
type: "photo",
media: el.thumbnailLink.replace("=s220", "=s0"),
caption: el.name,
})));
}, i * 2000);
});
bot.sendChatAction(msg.chat.id, "upload_video");
videos.forEach((e, i) => {
setTimeout(() => {
goindex.id2path(e.id).then((path) => {
console.log(path);
bot.sendVideo(msg.chat.id, encodeURI(path), {
caption: `${e.name}`,
reply_markup: {
inline_keyboard: [
[{ text: "带我去看片", url: encodeURI(path) }],
],
},
});
});
}, i * 2000);
});
bot.sendChatAction(msg.chat.id, "upload_voice");
audios.forEach((e, i) => {
setTimeout(() => {
goindex.id2path(e.id).then((path) => {
console.log(path);
bot.sendAudio(msg.chat.id, path, { caption: `${e.name}` });
});
}, i * 2000);
});
});
});
bot.on('polling_error', (error) => {
console.log(error.code); // => 'EFATAL'
})
return bot;
}
bot.onText(/\/senddice/, (msg) => {
bot.sendDice(msg.chat.id, { emoji: "🎲" });
});
bot.on("polling_error", (error) => {
console.log(error.message); // => 'EFATAL'
});
return bot;
};

View File

@@ -1,83 +1,85 @@
const axios = require("axios")
const BASE_URL = 'https://gd.lyz05.workers.dev'
const axios = require("axios");
module.exports = {
query,
id2path,
group,
}
const BASE_URL = "https://gd.lyz05.workers.dev";
function group(array, subGroupLength) {
var index = 0;
var newArray = [];
let index = 0;
const newArray = [];
while(index < array.length) {
newArray.push(array.slice(index, index += subGroupLength));
}
while (index < array.length) {
newArray.push(array.slice(index, index += subGroupLength));
}
return newArray;
return newArray;
}
async function id2path(id) {
url = BASE_URL+'/0:id2path'
const ret = await axios.post(url, { id: id })
return BASE_URL+'/0:'+ret.data;
const url = `${BASE_URL}/0:id2path`;
const ret = await axios.post(url, { id });
return `${BASE_URL}/0:${ret.data}`;
}
async function query(q) {
url = BASE_URL+'/0:search'
files = [];
let page_token = null;
while (true) {
data = {
'q': q,
'page_index': 1,
'page_token': page_token,
}
const ret = await axios.post(url, data)
files = files.concat(ret.data.data.files);
// console.log(ret.data.data.files)
page_token = ret.data.nextPageToken
if (page_token === null) {
break;
}
}
// console.log('files:',files);
return files;
const url = `${BASE_URL}/0:search`;
let files = [];
let page_token = null;
// eslint-disable-next-line no-constant-condition
while (true) {
const data = {
q,
page_index: 1,
page_token,
};
const ret = await axios.post(url, data);
files = files.concat(ret.data.data.files);
// console.log(ret.data.data.files)
page_token = ret.data.nextPageToken;
if (page_token === null) {
break;
}
}
// console.log('files:',files);
return files;
}
async function queryData(path = '') {
url = BASE_URL+'/0:/Inbox/seer/%E5%86%99%E7%9C%9F/Miho%20Kaneko%20Complete%20Photo%20Collection/' + path
data = {
'q': '',
'page_index': 0,
'page_token': null,
'password': null,
}
const response = await axios.post(url, data)
return response.data
}
// async function queryData(path = "") {
// const url = `${BASE_URL}/0:/Inbox/seer/%E5%86%99%E7%9C%9F/Miho%20Kaneko%20Complete%20Photo%20Collection/${path}`;
// const data = {
// q: "",
// page_index: 0,
// page_token: null,
// password: null,
// };
// const response = await axios.post(url, data);
// return response.data;
// }
async function dfs(path) {
let l = [];
const res = await queryData(path);
for (const item of res.data.files) {
if (item.mimeType === 'application/vnd.google-apps.folder') {
l = l.concat(await dfs(path + item.name + '/'));
} else {
l.push(item.name)
}
}
return l;
}
// async function dfs(path) {
// let l = [];
// const res = await queryData(path);
// for (const item of res.data.files) {
// if (item.mimeType === "application/vnd.google-apps.folder") {
// l = l.concat(await dfs(`${path + item.name}/`));
// } else {
// l.push(item.name);
// }
// }
// return l;
// }
async function main(num) {
// const res = await dfs('');
// console.log(res);
const files = await query();
link = files[num].thumbnailLink;
console.log(link)
}
// async function main(num) {
// // const res = await dfs('');
// // console.log(res);
// const files = await query();
// const link = files[num].thumbnailLink;
// console.log(link);
// }
module.exports = {
query,
id2path,
group,
};
// main(12);
// console.log(response.data.data.files)
// console.log(response.data.data.files)

View File

@@ -1,46 +1,46 @@
const TelegramBot = require('node-telegram-bot-api');
const TelegramBot = require("node-telegram-bot-api");
module.exports = (TOKEN) => {
const bot = new TelegramBot(TOKEN, {polling: true});
const bot = new TelegramBot(TOKEN, {polling: true});
// Just to ping!
bot.on('message', msg => {
if (msg.text) {
bot.sendMessage(msg.chat.id, msg.text);
} else {
bot.sendMessage(msg.chat.id, 'I can only understand text messages!');
}
});
bot.on('video', msg => {
bot.sendMessage(msg.chat.id, 'I reveive video message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.video));
});
bot.on('photo', msg => {
bot.sendMessage(msg.chat.id, 'I reveive photo message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.photo));
});
bot.on('audio', msg => {
bot.sendMessage(msg.chat.id, 'I reveive audio message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.audio));
});
bot.on('document', msg => {
bot.sendMessage(msg.chat.id, 'I reveive document message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.document));
});
bot.on('sticker', msg => {
bot.sendMessage(msg.chat.id, 'I reveive sticker message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.sticker));
});
bot.on('location', msg => {
bot.sendMessage(msg.chat.id, 'I reveive location message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.location));
});
bot.on('contact', msg => {
bot.sendMessage(msg.chat.id, 'I reveive contact message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.contact));
});
bot.on('polling_error', (error) => {
console.log(error.code); // => 'EFATAL'
})
return bot;
}
// Just to ping!
bot.on("message", msg => {
if (msg.text) {
bot.sendMessage(msg.chat.id, msg.text);
} else {
bot.sendMessage(msg.chat.id, "I can only understand text messages!");
}
});
bot.on("video", msg => {
bot.sendMessage(msg.chat.id, "I reveive video message!");
bot.sendMessage(msg.chat.id, JSON.stringify(msg.video));
});
bot.on("photo", msg => {
bot.sendMessage(msg.chat.id, "I reveive photo message!");
bot.sendMessage(msg.chat.id, JSON.stringify(msg.photo));
});
bot.on("audio", msg => {
bot.sendMessage(msg.chat.id, "I reveive audio message!");
bot.sendMessage(msg.chat.id, JSON.stringify(msg.audio));
});
bot.on("document", msg => {
bot.sendMessage(msg.chat.id, "I reveive document message!");
bot.sendMessage(msg.chat.id, JSON.stringify(msg.document));
});
bot.on("sticker", msg => {
bot.sendMessage(msg.chat.id, "I reveive sticker message!");
bot.sendMessage(msg.chat.id, JSON.stringify(msg.sticker));
});
bot.on("location", msg => {
bot.sendMessage(msg.chat.id, "I reveive location message!");
bot.sendMessage(msg.chat.id, JSON.stringify(msg.location));
});
bot.on("contact", msg => {
bot.sendMessage(msg.chat.id, "I reveive contact message!");
bot.sendMessage(msg.chat.id, JSON.stringify(msg.contact));
});
bot.on("polling_error", (error) => {
console.log(error.code); // => 'EFATAL'
});
return bot;
};

View File

@@ -1,54 +1,53 @@
const AV = require('leancloud-storage');
const {Query, User} = AV;
const AV = require("leancloud-storage");
// 引入环境变量
require('dotenv').config({path: '../.env'});
require("dotenv").config({path: "../.env"});
AV.init({
appId: process.env.LEANCLOUD_APP_ID,
appKey: process.env.LEANCLOUD_APP_KEY,
serverURL: "https://dbvunek8.lc-cn-e1-shared.com"
appId: process.env.LEANCLOUD_APP_ID,
appKey: process.env.LEANCLOUD_APP_KEY,
serverURL: "https://dbvunek8.lc-cn-e1-shared.com"
});
function currentDay() {
const date = new Date();
const start = new Date(date.setHours(0, 0, 0, 0))
const end = new Date(date.setHours(23, 59, 59, 999))
return [start, end]
const date = new Date();
const start = new Date(date.setHours(0, 0, 0, 0));
const end = new Date(date.setHours(23, 59, 59, 999));
return [start, end];
}
function lastDay() {
const currentday = currentDay();
currentday[0].setDate(currentday[0].getDate() - 1);
currentday[1].setDate(currentday[1].getDate() - 1);
return currentday
const currentday = currentDay();
currentday[0].setDate(currentday[0].getDate() - 1);
currentday[1].setDate(currentday[1].getDate() - 1);
return currentday;
}
function currentMonth() {
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]
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];
}
async function danmakuQuery(date) {
const query = new AV.Query('DanmakuAccess');
query.greaterThanOrEqualTo('createdAt', date[0]);
query.lessThan('createdAt', date[1]);
const query = new AV.Query("DanmakuAccess");
query.greaterThanOrEqualTo("createdAt", date[0]);
query.lessThan("createdAt", date[1]);
query.exists('url');
return await query.count()
query.exists("url");
return await query.count();
}
function add(className,obj) {
const classInstance = AV.Object.extend(className);
const record = new classInstance();
for (const key of Object.keys(obj)){
record.set(key, obj[key]);
}
record.save().then((obj) => {
// 成功保存之后,执行其他逻辑
console.log(`${className}添加一条记录。objectId${obj.id}`);
});
const classInstance = AV.Object.extend(className);
const record = new classInstance();
for (const key of Object.keys(obj)){
record.set(key, obj[key]);
}
record.save().then((obj) => {
// 成功保存之后,执行其他逻辑
console.log(`${className}添加一条记录。objectId${obj.id}`);
});
}
module.exports = {danmakuQuery, currentDay, currentMonth, lastDay, add};

View File

@@ -1,14 +1,14 @@
const {filesize} = require('filesize')
const {filesize} = require("filesize");
const print = function () {
const memoryUsage = process.memoryUsage();
const memoryUsage = process.memoryUsage();
console.log(JSON.stringify({
rss: filesize(memoryUsage.rss),//RAM 中保存的进程占用的内存部分,包括代码本身、栈、堆。
heapTotal: filesize(memoryUsage.heapTotal),//堆中总共申请到的内存量。
heapUsed: filesize(memoryUsage.heapUsed),//堆中目前用到的内存量,判断内存泄漏我们主要以这个字段为准。
external: filesize(memoryUsage.external),// V8 引擎内部的 C++ 对象占用的内存。
}));
}
console.log(JSON.stringify({
rss: filesize(memoryUsage.rss),//RAM 中保存的进程占用的内存部分,包括代码本身、栈、堆。
heapTotal: filesize(memoryUsage.heapTotal),//堆中总共申请到的内存量。
heapUsed: filesize(memoryUsage.heapUsed),//堆中目前用到的内存量,判断内存泄漏我们主要以这个字段为准。
external: filesize(memoryUsage.external),// V8 引擎内部的 C++ 对象占用的内存。
}));
};
module.exports = print
module.exports = print;

View File

@@ -1,61 +1,61 @@
const OSS = require('ali-oss');
const normalendpoint = 'oss-cn-hongkong.aliyuncs.com';
const fastendpoint = 'oss-accelerate.aliyuncs.com';
const OSS = require("ali-oss");
const normalendpoint = "oss-cn-hongkong.aliyuncs.com";
const fastendpoint = "oss-accelerate.aliyuncs.com";
// 引入环境变量
require('dotenv').config({path: '../.env'});
require("dotenv").config({path: "../.env"});
let client = new OSS({
region: process.env.OSS_REGION,
accessKeyId: process.env.OSS_ACCESS_KEY,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
bucket: process.env.OSS_BUCKET,
region: process.env.OSS_REGION,
accessKeyId: process.env.OSS_ACCESS_KEY,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
bucket: process.env.OSS_BUCKET,
});
async function get(objname) {
try {
const result = await client.get(objname);
return result.content.toString()
} catch (e) {
console.log(e);
}
try {
const result = await client.get(objname);
return result.content.toString();
} catch (e) {
console.log(e);
}
}
async function put(objname, content, headers) {
try {
const result = await client.put(objname, new Buffer.from(content), {headers});
return result
} catch (e) {
console.log(e);
}
try {
const result = await client.put(objname, new Buffer.from(content), {headers});
return result;
} catch (e) {
console.log(e);
}
}
async function head(objname) {
try {
const result = await client.head(objname);
return result.res.headers
} catch (e) {
console.log(e);
}
try {
const result = await client.head(objname);
return result.res.headers;
} catch (e) {
console.log(e);
}
}
async function signurl(objname, isFast) {
try {
let result = await client.signatureUrl(objname);
if (isFast) {
result = result.replace("http://","//").replace(normalendpoint, fastendpoint)
}
return result
} catch (e) {
console.log(e);
}
try {
let result = await client.signatureUrl(objname);
if (isFast) {
result = result.replace("http://","//").replace(normalendpoint, fastendpoint);
}
return result;
} catch (e) {
console.log(e);
}
}
module.exports = {get, put, head, signurl};
if (!module.parent) {
get('SUB/database.yaml');
put('SUB/test.txt', '中文');
head('SUB/database.yaml');
signurl('SUB/database.yaml',true);
}
get("SUB/database.yaml");
put("SUB/test.txt", "中文");
head("SUB/database.yaml");
signurl("SUB/database.yaml",true);
}