add 订阅自动检查更新

This commit is contained in:
theluyuan 2023-07-22 15:56:26 +08:00
parent 573883e2d1
commit be48d26d8c
12 changed files with 193 additions and 45 deletions

Binary file not shown.

View File

@ -23,4 +23,7 @@ const videoInfo = require("./router/videoInfo.js");
app.use(videoInfo.routes()).use(videoInfo.allowedMethods()) app.use(videoInfo.routes()).use(videoInfo.allowedMethods())
app.listen(3050, "0.0.0.0"); app.listen(3050, "0.0.0.0");
// 引入定时检测更新
require("./util/Video/Update.js")
console.log("link: http://127.0.0.1:3050") console.log("link: http://127.0.0.1:3050")

View File

@ -19,6 +19,7 @@
"koa-sse-stream": "^0.2.0", "koa-sse-stream": "^0.2.0",
"koa-static": "^5.0.0", "koa-static": "^5.0.0",
"koa-websocket": "^7.0.0", "koa-websocket": "^7.0.0",
"node-schedule": "^2.1.1",
"process": "^0.11.10", "process": "^0.11.10",
"puppeteer": "^20.7.1", "puppeteer": "^20.7.1",
"sqlite3": "^5.1.6" "sqlite3": "^5.1.6"

View File

@ -28,6 +28,9 @@ dependencies:
koa-websocket: koa-websocket:
specifier: ^7.0.0 specifier: ^7.0.0
version: 7.0.0 version: 7.0.0
node-schedule:
specifier: ^2.1.1
version: 2.1.1
process: process:
specifier: ^0.11.10 specifier: ^0.11.10
version: 0.11.10 version: 0.11.10
@ -642,6 +645,13 @@ packages:
path-type: 4.0.0 path-type: 4.0.0
dev: false dev: false
/cron-parser@4.8.1:
resolution: {integrity: sha512-jbokKWGcyU4gl6jAfX97E1gDpY12DJ1cLJZmoDzaAln/shZ+S3KBFBuA2Q6WeUN4gJf/8klnV1EfvhA2lK5IRQ==}
engines: {node: '>=12.0.0'}
dependencies:
luxon: 3.3.0
dev: false
/cross-fetch@3.1.6: /cross-fetch@3.1.6:
resolution: {integrity: sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==} resolution: {integrity: sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==}
dependencies: dependencies:
@ -1424,6 +1434,10 @@ packages:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
dev: false dev: false
/long-timeout@0.1.1:
resolution: {integrity: sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==}
dev: false
/lru-cache@6.0.0: /lru-cache@6.0.0:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -1436,6 +1450,11 @@ packages:
engines: {node: '>=12'} engines: {node: '>=12'}
dev: false dev: false
/luxon@3.3.0:
resolution: {integrity: sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==}
engines: {node: '>=12'}
dev: false
/make-dir@3.1.0: /make-dir@3.1.0:
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -1627,6 +1646,15 @@ packages:
dev: false dev: false
optional: true optional: true
/node-schedule@2.1.1:
resolution: {integrity: sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==}
engines: {node: '>=6'}
dependencies:
cron-parser: 4.8.1
long-timeout: 0.1.1
sorted-array-functions: 1.3.0
dev: false
/nopt@5.0.0: /nopt@5.0.0:
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -2021,6 +2049,10 @@ packages:
smart-buffer: 4.2.0 smart-buffer: 4.2.0
dev: false dev: false
/sorted-array-functions@1.3.0:
resolution: {integrity: sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==}
dev: false
/source-map@0.6.1: /source-map@0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}

View File

@ -95,28 +95,28 @@ router.get('/msg', KoaSSEStream(SSE_CONF), ctx => {
} }
}) })
let start = false let start = false
// 下载检测
function startDown(data) { // function startDown(data) {
start = true // start = true
dowload(data, async (data2, isok) => { // dowload(data, async (data2, isok) => {
let name = data2.title // let name = data2.title
clientList.forEach((i) => { // clientList.forEach((i) => {
i.send(isok ? `${name}下载完成` : data2) // i.send(isok ? `${name}下载完成` : data2)
}) // })
if (isok) { // if (isok) {
// dowloadlist.shift() // // dowloadlist.shift()
await setDownState(data.id, 1) // await setDownState(data.id, 1)
start = false // start = false
} // }
}) // })
} // }
// 定时检测下载地址
setInterval(async () => { // setInterval(async () => {
let dowloadlist = await getDownList() // let dowloadlist = await getDownList()
if (dowloadlist.length !== 0 && !start) { // if (dowloadlist.length !== 0 && !start) {
startDown(dowloadlist[0]) // startDown(dowloadlist[0])
} else if (dowloadlist.length === 0) { // } else if (dowloadlist.length === 0) {
start = false // start = false
} // }
}, 1000) // }, 1000)
module.exports = router module.exports = router

38
util/Video/Update.js Normal file
View File

@ -0,0 +1,38 @@
const schedule = require('node-schedule');
const { getSub,updateSkip } = require('../sql/video');
const { getQqListData } = require("../getList/qq.js")
const { addDownList } = require("../sql/download.js")
// 检查更新并将更新推送下载
async function addDown(i) {
// 判断视频网站
if (i.url.indexOf("v.qq.com") != -1) {
let cid = i.url.split("/")[5].replace(".html")
let list = await getQqListData(cid)
list = list.item_datas
for (let j = i.skip - 1; j < list.length; j++) {
let v = list[j]
await addDownList(v.item_params.title, `https://v.qq.com/x/cover/${cid}/${v.item_params.vid}.html`, `d:/aaa/${i.sid}`, new Date().getTime(), 0, i.sid)
}
await updateSkip(list.length + 1,i.id)
// console.log(JSON.stringify(list))
}
}
async function CheckUpdate() {
let date = new Date()
let hours = date.getHours()
let minutes = date.getMinutes()
let all = await getSub()
for (let i of all) {
let time = i.time.split(":")
if (hours == time[0] && minutes == time[1]) {
addDown(i)
}
}
}
console.log("开始定时检测更新")
// 设置定时器 每分钟检测更新
let job = schedule.scheduleJob('0 * * * * *', () => {
CheckUpdate()
});

View File

@ -1,7 +1,7 @@
const puppeteer = require("puppeteer") const puppeteer = require("puppeteer")
const { seep } = require("../utils.js"); const { seep, spawn } = require("../utils.js");
// 无头浏览器模式 暂时禁用
async function getQqListData(url) { async function getQqListDataBack(url) {
const browser = await puppeteer.launch({ const browser = await puppeteer.launch({
// 关闭无头模式,方便我们看到这个无头浏览器执行的过程 // 关闭无头模式,方便我们看到这个无头浏览器执行的过程
headless: false, headless: false,
@ -85,6 +85,24 @@ async function getQqListData(url) {
} }
function getQqListData(cid){
return new Promise((resolve) => {
const lux = spawn("getTencentVideoPlayList", [cid, 'vversion_name=8.2.95;', 1])
lux.stdout.on('data', (data) => {
resolve(JSON.parse(String(data)))
});
lux.stderr.on("data",(a)=>{
console.log(a)
})
lux.stdout.on("error",(err)=>{
console.log(err)
})
lux.stderr.on("error",(err)=>{
console.log(err)
})
})
}
module.exports = { module.exports = {
getQqListData getQqListData
} }

View File

@ -1,8 +1,9 @@
const { run, getAll } = require("./base"); const { run, getAll } = require("./base");
function addDownList(title,url,save,downDate,isOk,vid){ // state 0未下载 1下载完成 2已发种
let sql = `insert into download(title,url,save,downDate,isOk,vid) values(?,?,?,?,?,?)` function addDownList(title,url,save,downDate,state,vid){
run(sql,title,url,save,downDate,isOk,vid) let sql = `insert into download(title,url,save,downDate,state,vid) values(?,?,?,?,?,?)`
run(sql,title,url,save,downDate,state,vid)
} }
async function getDownList(){ async function getDownList(){

View File

@ -12,20 +12,29 @@ async function addSub(info){
await run(sql,info.name,info.rename,info.skip,info.desc,info.url,info.subtitle,info.img,info.year,info.time,info.season,info.sid,info.count) await run(sql,info.name,info.rename,info.skip,info.desc,info.url,info.subtitle,info.img,info.year,info.time,info.season,info.sid,info.count)
} }
// 获取所有订阅 (不包括已完成)
async function getSub(){ async function getSub(){
let sql = `select * from VideoInfo` let sql = `select * from VideoInfo where enable=1`
let list = await getAll(sql) let list = await getAll(sql)
return list return list
} }
async function delSub(id){ async function delSub(id){
let sql = `delete from VideoInfo where id=${id}` let sql = `delete from VideoInfo where id=${id}`
await run(sql) await run(sql)
} }
async function updateSkip(num,id){
let sql = `update VideoInfo set skip=${num} where id=${id}`
await run(sql)
}
module.exports = { module.exports = {
addSub, addSub,
getSub, getSub,
delSub delSub,
updateSkip
} }

View File

@ -1,10 +1,22 @@
const { spawn } = require('child_process'); const { spawn: spawn2 } = require('child_process');
const path = require('path'); const path = require('path');
const { cwd } = require('process'); const { cwd } = require('process');
const { readFile, createReadStream } = require("fs"); const { readFile, createReadStream } = require("fs");
const { post } = require("axios"); const { post } = require("axios");
const https = require('https') const https = require('https')
// 设置环境变量为自带的bin
function spawn(exe, arg, config) {
if (!config) {
config = {}
}
config.env = {
path: [path.join(cwd(), '/bin'), path.join(cwd(), '/bin/MediaInfoCLI'), path.join(cwd(), '/bin/Transmission')].join(";")
}
return spawn2(exe, arg, config)
}
function seep(time) { function seep(time) {
return new Promise((res) => { return new Promise((res) => {
setTimeout(() => { setTimeout(() => {
@ -22,16 +34,16 @@ async function uploadImg(filePath) {
console.log(data) console.log(data)
try { try {
let res = await post('https://image.zmpt.cc/upload/localhost', { let res = await post('https://image.zmpt.cc/upload/localhost', {
file:data file: data
},{ }, {
proxy: false, proxy: false,
headers:{ headers: {
'Content-Type': 'multipart/form-data' 'Content-Type': 'multipart/form-data'
} }
}) })
console.log(res) console.log(res)
return res.data return res.data
}catch(err){ } catch (err) {
console.error(err) console.error(err)
return err return err
} }
@ -45,7 +57,7 @@ async function uploadImg(filePath) {
*/ */
function getTencentVideoPlayList(cid) { function getTencentVideoPlayList(cid) {
return new Promise((resolve) => { return new Promise((resolve) => {
const lux = spawn("./bin/getTencentVideoPlayList.exe", [cid, 'vversion_name=8.2.95;', 1]) const lux = spawn("getTencentVideoPlayList.exe", [cid, 'vversion_name=8.2.95;', 1])
lux.stdout.on('data', (data) => { lux.stdout.on('data', (data) => {
resolve(JSON.parse(String(data))) resolve(JSON.parse(String(data)))
}); });
@ -89,7 +101,7 @@ function getVideoSpecifyTimeImage(filePath, seconds, save) {
*/ */
function getMediaInfo(filePath) { function getMediaInfo(filePath) {
return new Promise((resolve) => { return new Promise((resolve) => {
const lux = spawn("./bin/MediaInfoCLI/MediaInfo.exe", ['--output=JSON', filePath]) const lux = spawn("MediaInfo.exe", ['--output=JSON', filePath])
lux.stdout.on('data', (data) => { lux.stdout.on('data', (data) => {
resolve(JSON.parse(data)) resolve(JSON.parse(data))
}); });
@ -104,7 +116,7 @@ function getMediaInfo(filePath) {
*/ */
function createTorrent(filePath, save) { function createTorrent(filePath, save) {
return new Promise((resolve) => { return new Promise((resolve) => {
const lux = spawn("./bin/Transmission/transmission-create", [filePath, '-p', '-t https://zmpt.cc/announce.php', '-o', save]) const lux = spawn("transmission-create", [filePath, '-p', '-t https://zmpt.cc/announce.php', '-o', save])
let response = ''; let response = '';
lux.stdout.on('data', (data) => { lux.stdout.on('data', (data) => {
response += data response += data
@ -176,5 +188,6 @@ module.exports = {
getMediaInfo, getMediaInfo,
createTorrent, createTorrent,
getTencentVideoPlayList, getTencentVideoPlayList,
uploadImg uploadImg,
spawn
} }

View File

@ -12,6 +12,7 @@
"@element-plus/icons-vue": "^2.1.0", "@element-plus/icons-vue": "^2.1.0",
"axios": "^1.4.0", "axios": "^1.4.0",
"element-plus": "^2.3.6", "element-plus": "^2.3.6",
"node-schedule": "^2.1.1",
"sass": "^1.63.3", "sass": "^1.63.3",
"vue": "^3.2.47", "vue": "^3.2.47",
"vue-router": "4" "vue-router": "4"

View File

@ -1,9 +1,5 @@
lockfileVersion: '6.0' lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies: dependencies:
'@element-plus/icons-vue': '@element-plus/icons-vue':
specifier: ^2.1.0 specifier: ^2.1.0
@ -14,6 +10,9 @@ dependencies:
element-plus: element-plus:
specifier: ^2.3.6 specifier: ^2.3.6
version: 2.3.6(vue@3.2.47) version: 2.3.6(vue@3.2.47)
node-schedule:
specifier: ^2.1.1
version: 2.1.1
sass: sass:
specifier: ^1.63.3 specifier: ^1.63.3
version: 1.63.3 version: 1.63.3
@ -465,6 +464,13 @@ packages:
delayed-stream: 1.0.0 delayed-stream: 1.0.0
dev: false dev: false
/cron-parser@4.8.1:
resolution: {integrity: sha512-jbokKWGcyU4gl6jAfX97E1gDpY12DJ1cLJZmoDzaAln/shZ+S3KBFBuA2Q6WeUN4gJf/8klnV1EfvhA2lK5IRQ==}
engines: {node: '>=12.0.0'}
dependencies:
luxon: 3.3.0
dev: false
/csstype@2.6.21: /csstype@2.6.21:
resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==} resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==}
@ -620,6 +626,15 @@ packages:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
dev: false dev: false
/long-timeout@0.1.1:
resolution: {integrity: sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==}
dev: false
/luxon@3.3.0:
resolution: {integrity: sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==}
engines: {node: '>=12'}
dev: false
/magic-string@0.25.9: /magic-string@0.25.9:
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
dependencies: dependencies:
@ -646,6 +661,15 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true hasBin: true
/node-schedule@2.1.1:
resolution: {integrity: sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==}
engines: {node: '>=6'}
dependencies:
cron-parser: 4.8.1
long-timeout: 0.1.1
sorted-array-functions: 1.3.0
dev: false
/normalize-path@3.0.0: /normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -696,6 +720,10 @@ packages:
immutable: 4.3.0 immutable: 4.3.0
source-map-js: 1.0.2 source-map-js: 1.0.2
/sorted-array-functions@1.3.0:
resolution: {integrity: sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==}
dev: false
/source-map-js@1.0.2: /source-map-js@1.0.2:
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -783,3 +811,7 @@ packages:
'@vue/runtime-dom': 3.2.47 '@vue/runtime-dom': 3.2.47
'@vue/server-renderer': 3.2.47(vue@3.2.47) '@vue/server-renderer': 3.2.47(vue@3.2.47)
'@vue/shared': 3.2.47 '@vue/shared': 3.2.47
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false