diff --git a/app.js b/app.js index 1974cf3..be667d9 100644 --- a/app.js +++ b/app.js @@ -9,8 +9,10 @@ require("dotenv") .config(); // 引入一个个路由模块 -const danmakuRouter = require("./routes/danmaku"); +const danmakuRouter = require("./routes/danmaku.mjs").default; const app = express(); +// 加载路由 +app.use("/", danmakuRouter); // 启用gzip压缩 app.use(compression()); @@ -33,8 +35,7 @@ app.use("/assets", [ express.static(__dirname + "/node_modules/leancloud-storage/dist",{maxAge: 86400*1000}), ]); -// 加载路由 -app.use("/", danmakuRouter); + // catch 404 and forward to error handler app.use(function (req, res, next) { diff --git a/routes/api/base.js b/routes/api/base.js deleted file mode 100644 index 4fc9f19..0000000 --- a/routes/api/base.js +++ /dev/null @@ -1,16 +0,0 @@ -//引入API组件 -const Bilibili = require("./bilibili"); -const Mgtv = require("./mgtv"); -const Tencentvideo = require("./tencentvideo"); -const Youku = require("./youku"); -const Iqiyi = require("./iqiyi"); -const Gamer = require("./gamer"); -// 实例化API组件 -const bilibili = new Bilibili(); -const mgtv = new Mgtv(); -const tencentvideo = new Tencentvideo(); -const youku = new Youku(); -const iqiyi = new Iqiyi(); -const gamer = new Gamer(); -//TODO 优化代码 -module.exports = { bilibili, mgtv, tencentvideo, youku, iqiyi, gamer }; diff --git a/routes/api/base.mjs b/routes/api/base.mjs new file mode 100644 index 0000000..d27c92c --- /dev/null +++ b/routes/api/base.mjs @@ -0,0 +1,54 @@ +export default class BaseSource { + // 构造函数,初始化通用配置 + constructor() { + this.name = ""; + this.domain = ""; + this.example_urls = []; + } + + content_template = { + timepoint: 0, // 弹幕发送时间(秒) + ct: 1, // 弹幕类型,1-3 为滚动弹幕、4 为底部、5 为顶端、6 为逆向、7 为精确、8 为高级 + size: 25, //字体大小,25 为中,18 为小 + color: 16777215, //弹幕颜色,RGB 颜色转为十进制后的值,16777215 为白色 + unixtime: Math.floor(Date.now() / 1000), //Unix 时间戳格式 + uid: 0, //发送人的 id + content: "", + } + + 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; + } + + // 解析传入的视频网址,获取弹幕请求地址(Promise数组) + async resolve(url) { + throw new Error("Method 'resolve()' must be implemented."); + } + + // 请求弹幕资源,返回标准化弹幕内容 + async parse(promises) { + throw new Error("Method 'parse()' must be implemented."); + } + + // 综合处理入口,返回最终弹幕内容 + async work(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" + }; + } + +} \ No newline at end of file diff --git a/routes/api/bilibili.js b/routes/api/bilibili.mjs similarity index 69% rename from routes/api/bilibili.js rename to routes/api/bilibili.mjs index 576a4fd..9638be6 100644 --- a/routes/api/bilibili.js +++ b/routes/api/bilibili.mjs @@ -1,17 +1,21 @@ -const urlmodule = require("url"); -const axios = require("axios"); +import urlmodule from "url"; +import axios from "axios"; +import BaseSource from "./base.mjs"; -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" - ]; +export default class BilibiliSource extends BaseSource { + constructor() { + super(); + 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) => { + async resolve(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"; @@ -60,7 +64,7 @@ function Bilibili() { }; - this.work = async (url) => { + async work(url) { const urls = await this.resolve(url); if (!this.error_msg) { this.url = urls[0]; @@ -73,12 +77,16 @@ function Bilibili() { }; } -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); - }); -} +// if(!module.parent) { +// const b = new Bilibili(); +// b.work(b.example_urls[0]).then(() => { +// console.log(b.content); +// console.log(b.title); +// }); +// } +// 判断是否直接运行当前文件(跨平台) +// if (fileURLToPath(import.meta.url) === process.argv[1]) { +// console.log("单独运行") +// } \ No newline at end of file diff --git a/routes/api/gamer.js b/routes/api/gamer.mjs similarity index 58% rename from routes/api/gamer.js rename to routes/api/gamer.mjs index 523833c..30bb396 100644 --- a/routes/api/gamer.js +++ b/routes/api/gamer.mjs @@ -1,16 +1,20 @@ -const urlmodule = require("url"); -const axios = require("axios"); -const {time_to_second, content_template} = require("./utils"); +import urlmodule from "url"; +import axios from "axios"; +import BaseSource from "./base.mjs"; -function Gamer() { - this.name = "巴哈姆特動畫瘋"; - this.domain = "gamer.com.tw"; - this.example_urls = [ - "https://ani.gamer.com.tw/animeVideo.php?sn=41645", - "https://ani.gamer.com.tw/animeVideo.php?sn=41889" - ]; +export default class GamerSource extends BaseSource { - this.resolve = async (url) => { + constructor() { + super(); + this.name = "巴哈姆特動畫瘋"; + this.domain = "gamer.com.tw"; + this.example_urls = [ + "https://ani.gamer.com.tw/animeVideo.php?sn=41645", + "https://ani.gamer.com.tw/animeVideo.php?sn=41889" + ]; + } + + async resolve(url) { // 相关API const api_video_info = "https://api.gamer.com.tw/anime/v1/video.php"; const api_danmu = "https://api.gamer.com.tw/anime/v1/danmu.php"; @@ -42,7 +46,7 @@ function Gamer() { }; - this.parse = async (promises) => { + async parse(promises) { //筛选出成功的请求 let datas = (await Promise.allSettled(promises)) .filter(x => x.status === "fulfilled") @@ -51,7 +55,7 @@ function Gamer() { for (let i = 0; i < datas.length; i++) { const data = datas[i].data; for (const item of data.danmu) { - const content = JSON.parse(JSON.stringify(content_template)); + const content = JSON.parse(JSON.stringify(this.content_template)); content.timepoint = item.time / 10; content.content = item.text; content.uid = item.userid; @@ -63,23 +67,13 @@ function Gamer() { 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: this.error_msg? this.error_msg: "ok" - }; - }; } -module.exports = Gamer; +// module.exports = Gamer; -if(!module.parent) { - const g = new Gamer(); - g.work(g.example_urls[0]).then(res=>{ - console.log(res) - }); -} +// if(!module.parent) { +// const g = new Gamer(); +// g.work(g.example_urls[0]).then(res=>{ +// console.log(res) +// }); +// } diff --git a/routes/api/iqiyi.js b/routes/api/iqiyi.mjs similarity index 68% rename from routes/api/iqiyi.js rename to routes/api/iqiyi.mjs index 8643cde..110d8e4 100644 --- a/routes/api/iqiyi.js +++ b/routes/api/iqiyi.mjs @@ -1,21 +1,21 @@ -const axios = require("axios"); -const pako = require("pako"); -const { - time_to_second, - content_template, -} = require("./utils"); -const memory = require("../../utils/memory"); +import axios from "axios"; +import BaseSource from "./base.mjs"; +import pako from "pako"; +import memory from "../../utils/memory.js"; -function Iqiyi() { - this.name = "爱奇艺"; - this.domain = "iqiyi.com"; - this.example_urls = [ - "https://www.iqiyi.com/v_bb6gsxzz78.html", - "https://www.iqiyi.com/v_19rr1lm35o.html", - ]; +export default class IqiyiSource extends BaseSource { + constructor() { + super(); + this.name = "爱奇艺"; + this.domain = "iqiyi.com"; + this.example_urls = [ + "https://www.iqiyi.com/v_bb6gsxzz78.html", + "https://www.iqiyi.com/v_19rr1lm35o.html", + ]; + } // 新的tvid获取方法 - this.get_tvid = async (url) => { + async get_tvid(url) { const id = /v_(\w+)/.exec(url)[1]; const api = `https://pcw-api.iq.com/api/decode/${id}?platformId=3&modeCode=intl&langCode=sg`; const response = await axios.get(api); @@ -23,13 +23,13 @@ function Iqiyi() { }; // 获取视频基础信息 - this.get_video_info = async (tvid) => { + async get_video_info(tvid) { const api = `https://pcw-api.iqiyi.com/video/video/baseinfo/${tvid}`; const response = await axios.get(api); return response.data.data; }; - this.resolve = async (url) => { + async resolve(url) { // 1. 获取tvid const tvid = await this.get_tvid(url); @@ -68,21 +68,21 @@ function Iqiyi() { return promises; }; - function extract(xml, tag) { + extract(xml, tag) { const reg = new RegExp(`<${tag}>(.*?)`, "g"); const res = xml.match(reg) ?.map(x => x.substring(tag.length + 2, x.length - tag.length - 3)); return res || []; } - this.xml2json = (xml, contents, length) => { - const danmaku = extract(xml, "content"); - const showTime = extract(xml, "showTime"); - const color = extract(xml, "color"); + xml2json(xml, contents, length) { + const danmaku = this.extract(xml, "content"); + const showTime = this.extract(xml, "showTime"); + const color = this.extract(xml, "color"); const step = Math.ceil(danmaku.length * length / 10000); for (let i = 0; i < danmaku.length; i += step) { - const content = JSON.parse(JSON.stringify(content_template)); + const content = JSON.parse(JSON.stringify(this.content_template)); content.timepoint = showTime[i]; content.color = parseInt(color[i], 16); content.content = danmaku[i]; @@ -91,7 +91,7 @@ function Iqiyi() { } }; - this.parse = async (promises) => { + async parse(promises) { memory(); let datas = (await Promise.allSettled(promises)) .filter(x => x.status === "fulfilled") @@ -110,25 +110,15 @@ function Iqiyi() { 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" - }; - }; } -module.exports = Iqiyi; +// module.exports = Iqiyi; -if (!module.parent) { - const m = new Iqiyi(); - m.work(m.example_urls[0]) - .then(() => { - console.log(m.title); - memory(); - }); -} \ No newline at end of file +// if (!module.parent) { +// const m = new Iqiyi(); +// m.work(m.example_urls[0]) +// .then(() => { +// console.log(m.title); +// memory(); +// }); +// } \ No newline at end of file diff --git a/routes/api/mgtv.js b/routes/api/mgtv.mjs similarity index 55% rename from routes/api/mgtv.js rename to routes/api/mgtv.mjs index e6cf1e6..f4ddfab 100644 --- a/routes/api/mgtv.js +++ b/routes/api/mgtv.mjs @@ -1,16 +1,20 @@ -const urlmodule = require("url"); -const axios = require("axios"); -const {time_to_second, content_template} = require("./utils"); +import urlmodule from "url"; +import axios from "axios"; +import BaseSource from "./base.mjs"; -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.resolve = async (url) => { +export default class MgtvSource extends BaseSource { + constructor() { + super(); + 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 + ]; + } + + async resolve(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); @@ -22,15 +26,15 @@ function Mgtv() { const time = res.data.data.info.time; const step = 60 * 1000; - const end_time = time_to_second(time) * 1000; + const end_time = this.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) => { + async parse(promises) { let contents = []; const results = await Promise.allSettled(promises); let datas = results.filter(result => result.status === 'fulfilled') @@ -39,7 +43,7 @@ function Mgtv() { if (data.data.items === null) continue; for (const item of data.data.items) { - const content = JSON.parse(JSON.stringify(content_template)); + const content = JSON.parse(JSON.stringify(this.content_template)); content.timepoint = item.time / 1000; content.content = item.content; content.uid = item.uid; @@ -48,29 +52,17 @@ function Mgtv() { } // 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" - }; - }; - + } } -module.exports = Mgtv; +// module.exports = Mgtv; -if (!module.parent) { - const m = new Mgtv(); +// if (!module.parent) { +// 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); +// }); +// } diff --git a/routes/api/tencentvideo.js b/routes/api/tencentvideo.mjs similarity index 55% rename from routes/api/tencentvideo.js rename to routes/api/tencentvideo.mjs index 801ebc2..ba357e6 100644 --- a/routes/api/tencentvideo.js +++ b/routes/api/tencentvideo.mjs @@ -1,19 +1,22 @@ -const urlmodule = require("url"); -const axios = require("axios"); -const whacko = require("whacko"); -const {content_template} = require("./utils"); +import urlmodule from "url"; +import axios from "axios"; +import BaseSource from "./base.mjs"; +import whacko from "whacko"; -function Tencentvideo() { - this.name = "腾讯视频"; - this.domain = "v.qq.com"; - this.example_urls = [ - "https://v.qq.com/x/cover/53q0eh78q97e4d1/x00174aq5no.html",//api lens 50 - "https://v.qq.com/x/cover/mzc00200fph94nw/l00448ijvve.html",//api lens 91 - "https://v.qq.com/x/cover/mzc00200fhhxx8d/h0046u6z1iu.html",//api lens 215 OOM - "https://v.qq.com/x/cover/0s4fa14ciz3ohd0/p0047w54ncc.html",//api lens 297 OOM - ]; +export default class TencentvideoSource extends BaseSource { + constructor() { + super(); + this.name = "腾讯视频"; + this.domain = "v.qq.com"; + this.example_urls = [ + "https://v.qq.com/x/cover/53q0eh78q97e4d1/x00174aq5no.html",//api lens 50 + "https://v.qq.com/x/cover/mzc00200fph94nw/l00448ijvve.html",//api lens 91 + "https://v.qq.com/x/cover/mzc00200fhhxx8d/h0046u6z1iu.html",//api lens 215 OOM + "https://v.qq.com/x/cover/0s4fa14ciz3ohd0/p0047w54ncc.html",//api lens 297 OOM + ]; + } - this.resolve = async (url) => { + async resolve(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); @@ -43,9 +46,9 @@ function Tencentvideo() { promises.push(axios.get(`${api_danmaku_segment}${vid}/${item.segment_name}`)); } return promises; - }; + } - this.parse = async (promises) => { + async parse(promises) { let contents = []; const results = await Promise.allSettled(promises); let datas = results.filter(result => result.status === 'fulfilled') @@ -53,7 +56,7 @@ function Tencentvideo() { for (const data of datas) { for (const item of data.barrage_list) { - const content = JSON.parse(JSON.stringify(content_template)); + const content = JSON.parse(JSON.stringify(this.content_template)); content.timepoint = item.time_offset / 1000; if (item.content_style.color) { const content_style = JSON.stringify(item.content_style.color); @@ -65,30 +68,17 @@ function Tencentvideo() { } // 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" - }; - }; + } } -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); - }); -} +// 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); +// }); +// } diff --git a/routes/api/utils.js b/routes/api/utils.js deleted file mode 100644 index d845fb0..0000000 --- a/routes/api/utils.js +++ /dev/null @@ -1,22 +0,0 @@ -const content_template = { - timepoint: 0, // 弹幕发送时间(秒) - ct: 1, // 弹幕类型,1-3 为滚动弹幕、4 为底部、5 为顶端、6 为逆向、7 为精确、8 为高级 - size: 25, //字体大小,25 为中,18 为小 - color: 16777215, //弹幕颜色,RGB 颜色转为十进制后的值,16777215 为白色 - unixtime: Math.floor(Date.now() / 1000), //Unix 时间戳格式 - uid: 0, //发送人的 id - content: "", -}; - -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; -} - -module.exports = {time_to_second, content_template}; diff --git a/routes/api/youku.js b/routes/api/youku.mjs similarity index 73% rename from routes/api/youku.js rename to routes/api/youku.mjs index 2ae6fa2..3c26dde 100644 --- a/routes/api/youku.js +++ b/routes/api/youku.mjs @@ -1,19 +1,22 @@ -const urlmodule = require('url'); -const axios = require('axios'); -const cookie = require('cookie'); -const crypto = require('crypto'); -const { content_template } = require('./utils'); +import urlmodule from "url"; +import axios from "axios"; +import BaseSource from "./base.mjs"; +import cookie from "cookie"; +import crypto from "crypto"; -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' - ]; +export default class YoukuSource extends BaseSource { + constructor() { + super(); + 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 () => { + async get_tk_enc() { const api_url = 'https://acs.youku.com/h5/mtop.com.youku.aplatform.weakget/1.0/?jsv=2.5.1&appKey=24679788'; let cookies = undefined; // 服务端可能报错:"x-retcode": "FAIL_SYS_INTERNAL_FAULT" @@ -26,8 +29,8 @@ function Youku() { targetCookie = Object.assign(targetCookie, cookie.parse(cookieStr)); } return targetCookie; - }; - this.get_cna = async () => { + } + async get_cna() { const api_url = 'https://log.mmstat.com/eg.js'; const res = await axios.get(api_url); const cookies = res.headers['set-cookie']; @@ -36,22 +39,22 @@ function Youku() { targetCookie = Object.assign(targetCookie, cookie.parse(cookieStr)); } return targetCookie['cna']; - }; + } - const yk_msg_sign = (msg) => { + yk_msg_sign(msg) { const md5 = crypto.createHash('md5'); return md5.update(msg + 'MkmC9SoIw6xCkSKHhJ7b5D2r51kBiREr') .digest('hex'); - }; + } - const yk_t_sign = (token, t, appkey, data) => { + 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) => { + async get_vinfos_by_video_id(url) { const q = urlmodule.parse(url, true); const path = q.pathname.split('/'); const video_id = path.slice(-1)[0].split('.')[0].slice(3); @@ -70,9 +73,9 @@ function Youku() { console.log('video_id:', video_id, 'duration:', duration, 'title:', this.title); return [video_id, duration]; } - }; + } - this.resolve = async (url) => { + async resolve(url) { const cna = await this.get_cna(); const tk_enc = await this.get_tk_enc(); const headers = { @@ -81,7 +84,7 @@ function Youku() { '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 [vid, duration] = await this.get_vinfos_by_video_id(url); const max_mat = Math.floor(duration / 60) + 1; let promises = []; @@ -104,14 +107,14 @@ function Youku() { const buff = Buffer.from(str, 'utf-8'); const msg_b64encode = buff.toString('base64'); msg['msg'] = msg_b64encode; - msg['sign'] = yk_msg_sign(msg_b64encode); + msg['sign'] = this.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), + 'sign': this.yk_t_sign(tk_enc['_m_h5_tk'].slice(0, 32), t, '24679788', data), 'api': 'mopen.youku.danmu.list', 'v': '1.0', 'type': 'originaljson', @@ -125,9 +128,9 @@ function Youku() { })); } return promises; - }; + } - this.parse = async (promises) => { + async parse(promises) { let contents = []; const results = await Promise.allSettled(promises); let datas = results.filter(result => result.status === 'fulfilled') @@ -142,7 +145,7 @@ function Youku() { // 接口请求情况 // console.log(i, res.ret[0]) for (const danmu of danmus) { - const content = JSON.parse(JSON.stringify(content_template)); + const content = JSON.parse(JSON.stringify(this.content_template)); content.timepoint = danmu['playat'] / 1000; if (danmu.propertis.color) { content.color = JSON.parse(danmu.propertis).color; @@ -153,27 +156,17 @@ function Youku() { } // 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' - }; - }; } -module.exports = Youku; +// module.exports = Youku; -if (!module.parent) { - const b = new Youku(); - b.work(b.example_urls[2]) - .then(() => { - // console.log(b.content); - console.log(b.title); - }); -} +// if (!module.parent) { +// const b = new Youku(); +// b.work(b.example_urls[2]) +// .then(() => { +// // console.log(b.content); +// console.log(b.title); +// }); +// } diff --git a/routes/danmaku.js b/routes/danmaku.mjs similarity index 87% rename from routes/danmaku.js rename to routes/danmaku.mjs index e47ddaf..9bf526e 100644 --- a/routes/danmaku.js +++ b/routes/danmaku.mjs @@ -1,18 +1,13 @@ -const express = require("express"); -const axios = require("axios"); +import express from "express"; +import axios from "axios"; +import { createSourceList } from "./sources.mjs"; +import memory from "../utils/memory.js"; +import db from "../utils/db.js"; +import { inflateRawSync } from "zlib"; + + const router = express.Router(); -const URL = require("url"); -const { - bilibili, - mgtv, - tencentvideo, - youku, - iqiyi, - gamer, -} = require("./api/base"); -const list = [bilibili, mgtv, tencentvideo, youku, iqiyi, gamer]; -const memory = require("../utils/memory"); -const db = require("../utils/db"); +const list = createSourceList(); const UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"; // 返回对象{msg: "ok", title: "标题", content: []} @@ -81,10 +76,10 @@ async function resolve(req, res) { // 记录视频信息 db.videoInfoInsert({url,title:ret.title}) //B站视频,直接重定向 - if (ret.url) + if (ret.url) { res.redirect(ret.url); - else { - res.set('Cache-Control', 'public, max-age=86400'); // one year + } else { + res.set('Cache-Control', 'public, max-age=86400'); // 缓存一天 res.render("danmaku-xml", { contents: ret.content }); } } @@ -131,4 +126,5 @@ router.get("/delete", async function (req, res) { res.send(`成功请求删除三个月以前的记录,删除情况请查看日志`); }); -module.exports = router; +// module.exports = router; +export default router; \ No newline at end of file diff --git a/routes/sources.mjs b/routes/sources.mjs new file mode 100644 index 0000000..c60778f --- /dev/null +++ b/routes/sources.mjs @@ -0,0 +1,19 @@ +import BilibiliSource from "./api/bilibili.mjs"; +import MgtvSource from "./api/mgtv.mjs"; +import TencentvideoSource from "./api/tencentvideo.mjs"; +import YoukuSource from "./api/youku.mjs"; +import IqiyiSource from "./api/iqiyi.mjs"; +import GamerSource from "./api/gamer.mjs"; + +export function createSourceList() { + const sourceClasses = [ + BilibiliSource, + MgtvSource, + TencentvideoSource, + YoukuSource, + IqiyiSource, + GamerSource + ]; + + return sourceClasses.map(SourceClass => new SourceClass()); +} diff --git a/test/App.test.js b/test/App.test.js index b74c922..d40009a 100644 --- a/test/App.test.js +++ b/test/App.test.js @@ -1,8 +1,9 @@ -let chai = require("chai"); -let chaiHttp = require("chai-http"); -let app = require("../app"); -const { bilibili, mgtv, tencentvideo, youku, iqiyi, gamer } = require("../routes/api/base"); -const list = [bilibili, mgtv, tencentvideo, youku, iqiyi, gamer]; +import chai from "chai"; +import chaiHttp from "chai-http"; +import app from "../app.js"; +import { createSourceList } from "../routes/sources.mjs"; + +const list = createSourceList(); chai.should(); chai.use(chaiHttp); @@ -43,14 +44,15 @@ describe("App", () => { chai.request(app) .get("/") .query({url}) + .redirects(0) .end((err, res) => { - if (err) { - //B站弹幕获取会遇到解压错误 - err.code.should.equal("Z_DATA_ERROR") - } if (res) { - res.should.have.status(200); - res.header["content-type"].should.equal("application/xml; charset=utf-8"); + if (name === "B站") { + res.should.redirect; + } else { + res.should.have.status(200); + res.header["content-type"].should.equal("application/xml; charset=utf-8"); + } } done(); }); diff --git a/utils/db.js b/utils/db.js index 3925838..1a7244f 100644 --- a/utils/db.js +++ b/utils/db.js @@ -125,24 +125,24 @@ async function deleteAccess() { } } -async function main() { - const ret = await deleteAccess(); - console.log(ret); -} +// async function main() { +// const ret = await deleteAccess(); +// console.log(ret); +// } -if (!module.parent) { - accessInsert({ - 'ip': '127.0.0.1', - 'url': 'https://www.mgtv.com/b/336727/8087768.html', - 'UA': 'PostmanRuntime/7.37.3' - }); +// if (!module.parent) { +// accessInsert({ +// 'ip': '127.0.0.1', +// 'url': 'https://www.mgtv.com/b/336727/8087768.html', +// 'UA': 'PostmanRuntime/7.37.3' +// }); - videoInfoInsert({ - 'url': 'https://www.mgtv.com/b/336727/8087768.html', - 'title': '婚前21天' - }); +// videoInfoInsert({ +// 'url': 'https://www.mgtv.com/b/336727/8087768.html', +// 'title': '婚前21天' +// }); - main(); -} +// main(); +// } module.exports = { errorInsert, accessInsert, accessCountQuery, videoInfoInsert, hotlistQuery, deleteAccess };