diff --git a/.dockerignore b/.dockerignore index d0a20b9..8c2a330 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,6 @@ -/.git -/node_modules -/.workflow +.git +node_modules +.workflow *.bak +.github +.gitignore diff --git a/.workflow/fetch.yml b/.workflow/update.yml similarity index 56% rename from .workflow/fetch.yml rename to .workflow/update.yml index 2414f01..cc297d3 100644 --- a/.workflow/fetch.yml +++ b/.workflow/update.yml @@ -1,47 +1,39 @@ version: '1.0' -name: fetch -displayName: fetch +name: update +displayName: update triggers: trigger: auto - pr: - branches: - precise: - - main schedule: - - cron: '* 0 */2 * * ? *' + - cron: '* 0 */6 * * ? *' variables: global: - - GITHUB_TOKEN - TOKEN stages: - - name: fetchurl - displayName: fetchurl + - name: update + displayName: 更新 strategy: naturally trigger: auto + executor: [] steps: - step: build@nodejs - name: fetchurl - displayName: fetchurl + name: update_files + displayName: 更新文件 nodeVersion: 21.5.0 commands: - git clone https://dream-deve:${TOKEN}@gitee.com/dream-deve/migu_video.git - - '# git clone https://develop202:${GITHUB_TOKEN}@github.com/develop202/migu_video.git' - cd migu_video - '# 设置NPM源,提升安装速度' - npm config set registry https://registry.npmmirror.com - '# 执行编译命令 ' - - '# npm install && node fetchURLByWasm.js' - - '# npm install && node fetchURLByAndroid.js' - - '# npm install && node fetchURLByAndroidV2.js' - npm install && node fetchURLByAndroid720p.js - - '# npm install && node fetchURLByWasmV2.js' - git config user.name "Gitee流水线" - git config user.email "actions@githee.com" - git add . - '# gitee流水线提交 ' - git diff --quiet && git diff --staged --quiet || git commit -m "Update by Gitee流水线" - - '# git push -f https://dream-deve:${TOKEN}@gitee.com/dream-deve/migu_video.git main:main' - git push + caches: [] + notify: [] strategy: retry: '0' - timeout: 2 + timeout: 4 diff --git a/README.md b/README.md index 181bb9d..a3d6899 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,7 @@ https://gh-proxy.com/https://raw.githubusercontent.com/develop202/migu_video/ref # 本地部署 -使用node自带的http模块实现。 - +> [!warning] > 注意事项 > > 1. 登录后使用不保证安全,请谨慎使用 @@ -29,21 +28,21 @@ https://gh-proxy.com/https://raw.githubusercontent.com/develop202/migu_video/ref ## 配置 -配置信息如下,默认仅本机可用 +配置信息如下,默认本机和局域网可用 -| 变量名 | 默认值 | 类型 | 介绍 | -| --------- | ----------------------- | ------ | ------------------------------------------ | -| muserId | | string | 用户id,可在网页端登录获取 | -| mtoken | | string | 用户token,可在网页端登录获取 | -| mport | 1234 | number | 服务本地启动端口 | -| mhost | | string | 访问地址,用于节目和epg地址生成 | -| mrateType | 3 | number | 画质 2:标清 3:高清 4:蓝光(需要登录且有VIP) | +| 变量名 | 默认值 | 类型 | 介绍 | +| --------- | ------ | ------ | -------------------------------------------- | +| muserId | | string | 用户id,可在网页端登录获取 | +| mtoken | | string | 用户token,可在网页端登录获取 | +| mport | 1234 | number | 本地运行端口号 | +| mhost | | string | 公网/自定义访问地址 格式 | +| mrateType | 3 | number | 画质 2:标清 3:高清 4:蓝光(需登录且有VIP) | ## node ### 环境要求 -需要 NodeJS 15+ 环境 +需要 NodeJS 18+ 环境 ### 安装 diff --git a/app.js b/app.js index 9d61665..8bf8b3f 100644 --- a/app.js +++ b/app.js @@ -16,6 +16,7 @@ let loading = false const server = http.createServer(async (req, res) => { + // console.dir(req, { depth: null }) while (loading) { await delay(50) } @@ -25,7 +26,7 @@ const server = http.createServer(async (req, res) => { // 获取请求方法、URL 和请求头 const { method, url, headers } = req; - console.log() + // printGreen("") printMagenta("请求地址:" + url) if (method != "GET") { @@ -40,13 +41,27 @@ const server = http.createServer(async (req, res) => { } // 响应接口内容 - if (url == "/" || url == "/interface.txt") { + if (url == "/" || url == "/interface.txt" || url == "/m3u") { try { // 读取文件内容 - const data = readFileSync(process.cwd() + "/interface.txt"); + let data = readFileSync(process.cwd() + "/interface.txt"); + let replaceHost = `http://${headers.host}` + + if (host != "" && (headers["x-real-ip"] || headers["x-forwarded-for"] || host.indexOf(headers.host) != -1)) { + replaceHost = host + } + + data = `${data}`.replaceAll("${replace}", replaceHost); + + let contentType = 'text/plain;charset=UTF-8' + if (url == "/m3u") { + // contentType = "audio/mpegurl;charset=UTF-8" + contentType = "audio/x-mpegurl; charset=utf-8" + res.setHeader('content-disposition', "inline; filename=\"interface.m3u\""); + } // 设置响应头 - res.setHeader('Content-Type', 'text/plain;charset=UTF-8'); + res.setHeader('Content-Type', contentType); res.statusCode = 200; res.end(data); // 发送文件内容 @@ -91,7 +106,6 @@ const server = http.createServer(async (req, res) => { let pid = urlSplit let params = "" - if (urlSplit.match(/\?/)) { // 回放 printGreen("处理传入参数") @@ -103,7 +117,6 @@ const server = http.createServer(async (req, res) => { printGrey("无参数传入") } - if (isNaN(pid)) { res.writeHead(200, { "Content-Type": "application/json;charset=UTF-8" }) res.end("地址错误") @@ -168,13 +181,43 @@ const server = http.createServer(async (req, res) => { return } + // 直接访问g开头的域名链接时概率会302到不能播放的地址,目前不清楚原因,在这重定向正确地址 + // printRed(resObj.url) + if (resObj.url != "") { + let z = 1 + while (z <= 6) { + if (z >= 2) { + printYellow(`获取失败,正在第${z - 1}次重试`) + } + axio + const obj = await fetch(`${resObj.url}`, { + method: "GET", + redirect: "manual" + }) + + const location = obj.headers.get("Location") + if (location.startsWith("http://hlsz")) { + resObj.url = location + break + } + if (z == 6) { + printRed(`获取失败`) + resObj.url = "" + } else { + await delay(150) + } + z++ + } + } + printGreen(`添加节目缓存 ${pid}`) // 加入缓存 urlCache[pid] = { - // 有效期2小时 节目调整改为2分钟 - valTime: Date.now() + (resObj.url == "" ? 2 * 60 * 1000 : 2 * 60 * 60 * 1000), + // 有效期3小时 节目调整时改为1分钟 + valTime: Date.now() + (resObj.url == "" ? 1 * 60 * 1000 : 3 * 60 * 60 * 1000), url: resObj.url } + // console.log(resObj.url) if (resObj.url == "") { printRed(`${pid} 节目调整,暂不提供服务`) @@ -186,7 +229,6 @@ const server = http.createServer(async (req, res) => { } let playURL = resObj.url - // console.dir(playURL, { depth: null }) // 添加回放参数 @@ -199,7 +241,6 @@ const server = http.createServer(async (req, res) => { printGreen("链接获取成功") - res.writeHead(302, { 'Content-Type': 'application/json;charset=UTF-8', location: playURL @@ -212,10 +253,10 @@ const server = http.createServer(async (req, res) => { server.listen(port, async () => { - // 设置定时器,3小时更新一次 + // 设置定时器,6小时更新一次 setInterval(async () => { printBlue(`\n准备更新文件 ${getDateTimeStr(new Date())}\n`) - hours += 3 + hours += 6 try { await update(hours) } catch (error) { @@ -224,7 +265,7 @@ server.listen(port, async () => { } printBlue(`\n当前已运行${hours}小时`) - }, 3 * 60 * 60 * 1000); + }, 6 * 60 * 60 * 1000); try { // 初始化数据 @@ -234,10 +275,11 @@ server.listen(port, async () => { console.log(error) } - console.log() + printYellow("每6小时更新一次") - printYellow("定时器设置完毕 每3小时更新一次") - printYellow("Server running at port " + port) - printYellow("访问地址: " + host) + printGreen(`本地地址: http://localhost:${port}`) + if (host != "") { + printGreen(`自定义地址: ${host}`) + } }) diff --git a/config.js b/config.js index 63537a6..146f01a 100644 --- a/config.js +++ b/config.js @@ -4,13 +4,14 @@ const userId = process.env.muserId || "" const token = process.env.mtoken || "" // 本地运行端口号 const port = process.env.mport || 1234 -// 访问地址,用于epg和节目访问。 -// 部署后访问地址是什么就填什么,默认只可本机使用 -const host = process.env.mhost || "http://localhost:1234" +// 公网/自定义访问地址 +const host = process.env.mhost || "" // 画质 // 4蓝光(需要登录且账号有VIP) // 3高清 // 2标清 const rateType = process.env.mrateType || 3 +// 是否刷新token,可能是导致封号的原因 +// const refreshToken = process.env.mrefreshToken || true -export { userId, token, port, host, rateType } +export { userId, token, port, host, rateType/* , refreshToken */ } diff --git a/fetchURLByAndroid720p.js b/fetchURLByAndroid720p.js index 4a629e0..df0aadf 100644 --- a/fetchURLByAndroid720p.js +++ b/fetchURLByAndroid720p.js @@ -1,8 +1,8 @@ -import { dataList } from "./utils/fetchList.js" +import { dataList, delay } from "./utils/fetchList.js" import { getAndroidURL720p } from "./utils/androidURL.js" import { appendFile, appendFileSync, renameFileSync, writeFile } from "./utils/fileUtil.js" import { updatePlaybackData } from "./utils/playback.js" -import { printBlue, printGreen, printMagenta, printRed, printYellow } from "./utils/colorOut.js" +import { printBlue, printGreen, printRed, printYellow } from "./utils/colorOut.js" async function fetchURLByAndroid720p() { @@ -10,11 +10,14 @@ async function fetchURLByAndroid720p() { // 获取数据 const datas = await dataList() + + printGreen("数据获取成功!") // 必须绝对路径 const path = process.cwd() + '/interface.txt.bak' // 创建写入空内容 writeFile(path, "") + printYellow("正在更新...") // 回放 const playbackFile = process.cwd() + '/playback.xml.bak' writeFile(playbackFile, @@ -26,30 +29,50 @@ async function fetchURLByAndroid720p() { // 分类列表 for (let i = 0; i < datas.length; i++) { - printBlue(`分类###:${datas[i].name}`) const data = datas[i].dataList + + printBlue(`开始更新分类###: ${datas[i].name}`) // 写入节目 for (let j = 0; j < data.length; j++) { - printMagenta(`${data[j].name}:`) - const res = await updatePlaybackData(data[j], playbackFile) - if (res) { - printGreen(` 节目单更新成功`) - } else { - printRed(` 节目单更新失败`) - } + await updatePlaybackData(data[j], playbackFile) // 获取链接 const resObj = await getAndroidURL720p(data[j].pID) - if (resObj.url == "") { - printRed(` 节目调整,暂不提供服务`) - continue + + if (resObj.url != "") { + let z = 1 + while (z <= 6) { + if (z >= 2) { + printYellow(`${data[j].name} 获取失败,正在第${z - 1}次重试`) + } + const obj = await fetch(`${resObj.url}`, { + method: "GET", + redirect: "manual" + }) + + const location = obj.headers.get("Location") + if (location.startsWith("http://hlsz")) { + resObj.url = location + break + } + if (z == 6) { + resObj.url = "" + } else { + await delay(150) + } + z++ + } } + if (resObj.url == "") { + printRed(`${data[j].name} 更新失败`) + continue + } // 写入节目 appendFile(path, `#EXTINF:-1 tvg-id="${data[j].name}" tvg-name="${data[j].name}" tvg-logo="${data[j].pics.highResolutionH}" group-title="${datas[i].name}",${data[j].name}\n${resObj.url}\n`) - printGreen(` 节目链接更新成功`) + printGreen(`${data[j].name} 更新成功!`) } } @@ -58,7 +81,7 @@ async function fetchURLByAndroid720p() { renameFileSync(playbackFile, playbackFile.replace(".bak", "")) renameFileSync(path, path.replace(".bak", "")) const end = Date.now() - printYellow(`本次耗时:${(end - start) / 1000}秒`) + printYellow(`本次耗时: ${(end - start) / 1000}秒`) } fetchURLByAndroid720p() diff --git a/fetchURLByAndroidV2.js b/fetchURLByAndroidV2.js deleted file mode 100644 index 380c649..0000000 --- a/fetchURLByAndroidV2.js +++ /dev/null @@ -1,77 +0,0 @@ -import { dataList } from "./utils/fetchList.js" -import { getAndroidURL } from "./utils/androidURL.js" -import refreshToken from "./utils/refreshToken.js" -import { appendFile, appendFileSync, renameFileSync, writeFile } from "./utils/fileUtil.js" -import { updatePlaybackData } from "./utils/playback.js" -import { printBlue, printGreen, printMagenta, printRed, printYellow } from "./utils/colorOut.js" -import { token as config_token, userId as config_userId } from "./config.js" - -async function fetchURLByAndroid() { - - const userId = process.env.USERID || config_userId - const token = process.env.MIGU_TOKEN || config_token - - const date = new Date() - const start = date.getTime() - - // 获取数据 - const datas = await dataList() - - // 必须绝对路径 - const path = process.cwd() + '/interface.txt.bak' - // 创建写入空内容 - writeFile(path, "") - - // 回放 - const playbackFile = process.cwd() + '/playback.xml.bak' - writeFile(playbackFile, - `\n` + - `\n`) - - if (!date.getHours()) { - // 0点刷新token - await refreshToken(userId, token) ? printGreen("token刷新成功") : printRed("token刷新失败") - } - - // 写入开头 - // appendFile(aptvPath, `#EXTM3U x-tvg-url="https://gitee.com/dream-deve/migu_video/raw/main/playback.xml" catchup="append" catchup-source="&playbackbegin=\${(b)yyyyMMddHHmmss}&playbackend=\${(e)yyyyMMddHHmmss}"\n`) - appendFile(path, `#EXTM3U x-tvg-url="https://develop202.github.io/migu_video/playback.xml,https://raw.githubusercontent.com/develop202/migu_video/refs/heads/main/playback.xml,https://gh-proxy.com/https://raw.githubusercontent.com/develop202/migu_video/refs/heads/main/playback.xml" catchup="append" catchup-source="&playbackbegin=\${(b)yyyyMMddHHmmss}&playbackend=\${(e)yyyyMMddHHmmss}"\n`) - - // 分类列表 - for (let i = 0; i < datas.length; i++) { - printBlue(`分类###:${datas[i].name}`) - - const data = datas[i].dataList - // 写入节目 - for (let j = 0; j < data.length; j++) { - - printMagenta(`${data[j].name}:`) - const res = await updatePlaybackData(data[j], playbackFile) - if (res) { - printGreen(` 节目单更新成功`) - } else { - printRed(` 节目单更新失败`) - } - - // 获取链接 - const resObj = await getAndroidURL(userId, token, data[j].pID, 4) - if (resObj.url == "") { - printRed(` 节目调整,暂不提供服务`) - continue - } - - // 写入节目 - appendFile(path, `#EXTINF:-1 svg-id="${data[j].name}" svg-name="${data[j].name}" tvg-logo="${data[j].pics.highResolutionH}" group-title="${datas[i].name}",${data[j].name}\n${resObj.url}\n`) - printGreen(` 节目链接更新成功`) - } - } - - appendFileSync(playbackFile, `\n`) - - renameFileSync(playbackFile, playbackFile.replace(".bak", "")) - renameFileSync(path, path.replace(".bak", "")) - const end = Date.now() - printYellow(`本次耗时:${(end - start) / 1000}秒`) -} - -fetchURLByAndroid() diff --git a/updateData.js b/updateData.js index a2c24cc..a3dd511 100644 --- a/updateData.js +++ b/updateData.js @@ -1,9 +1,9 @@ import { dataList } from "./utils/fetchList.js" import { appendFile, appendFileSync, renameFileSync, writeFile } from "./utils/fileUtil.js" import { updatePlaybackData } from "./utils/playback.js" -import { host, token, userId } from "./config.js" +import { /* refreshToken as mrefreshToken, */ host, token, userId } from "./config.js" import refreshToken from "./utils/refreshToken.js" -import { printBlue, printGreen, printMagenta, printRed, printYellow } from "./utils/colorOut.js" +import { printGreen, printRed, printYellow } from "./utils/colorOut.js" async function update(hours) { @@ -12,6 +12,7 @@ async function update(hours) { let interfacePath = "" // 获取数据 const datas = await dataList() + printGreen("数据获取成功!") if (!(hours % 24)) { // 必须绝对路径 @@ -22,10 +23,14 @@ async function update(hours) { if (!(hours % 24)) { // 每24小时刷新token - if (!(userId == "" || token == "")) { + if (userId != "" && token != "") { + // if (mrefreshToken) { await refreshToken(userId, token) ? printGreen("token刷新成功") : printRed("token刷新失败") + // } else { + // printGreen(`跳过token刷新`) + // } } - appendFile(interfacePath, `#EXTM3U x-tvg-url="${host}/playback.xml" catchup="append" catchup-source="?playbackbegin=\${(b)yyyyMMddHHmmss}&playbackend=\${(e)yyyyMMddHHmmss}"\n`) + appendFile(interfacePath, `#EXTM3U x-tvg-url="\${replace}/playback.xml" catchup="append" catchup-source="?playbackbegin=\${(b)yyyyMMddHHmmss}&playbackend=\${(e)yyyyMMddHHmmss}"\n`) } printYellow("正在更新...") // 回放 @@ -36,26 +41,22 @@ async function update(hours) { // 分类列表 for (let i = 0; i < datas.length; i++) { - if (!(hours % 24)) { - printBlue(`分类###:${datas[i].name}`) - } + const data = datas[i].dataList // 写入节目 for (let j = 0; j < data.length; j++) { - printMagenta(`${data[j].name}:`) - const res = await updatePlaybackData(data[j], playbackFile) - if (res) { - printGreen(` 节目单更新成功`) - } else { - printRed(` 节目单更新失败`) - } + + await updatePlaybackData(data[j], playbackFile) if (!(hours % 24)) { // 写入节目 - appendFile(interfacePath, `#EXTINF:-1 svg-id="${data[j].name}" svg-name="${data[j].name}" tvg-logo="${data[j].pics.highResolutionH}" group-title="${datas[i].name}",${data[j].name}\n${host}/${data[j].pID}\n`) - printGreen(` 节目链接更新成功`) + appendFile(interfacePath, `#EXTINF:-1 tvg-id="${data[j].name}" tvg-name="${data[j].name}" tvg-logo="${data[j].pics.highResolutionH}" group-title="${datas[i].name}",${data[j].name}\n\${replace}/${data[j].pID}\n`) + // printGreen(` 节目链接更新成功`) } } + if (!(hours % 24)) { + printGreen(`分类###:${datas[i].name} 更新完成!`) + } } appendFileSync(playbackFile, `\n`) @@ -65,9 +66,9 @@ async function update(hours) { if (!(hours % 24)) { renameFileSync(interfacePath, interfacePath.replace(".bak", "")) } - printYellow("更新完成") + printYellow("更新完成!") const end = Date.now() - printYellow(`本次耗时:${(end - start) / 1000}秒`) + printYellow(`本次耗时: ${(end - start) / 1000}秒`) } diff --git a/utils/androidURL.js b/utils/androidURL.js index 2e9eac0..13485f6 100644 --- a/utils/androidURL.js +++ b/utils/androidURL.js @@ -206,7 +206,8 @@ async function getAndroidURL(userId, token, pid, rateType) { return { url: resURL, - rateType: parseInt(rateType) + rateType: parseInt(rateType), + content: respData } } @@ -265,7 +266,8 @@ async function getAndroidURL720p(pid) { return { url: resURL, - rateType: parseInt(rateType) + rateType: parseInt(rateType), + content: respData } } diff --git a/utils/colorOut.js b/utils/colorOut.js index b91e867..38d6bc5 100644 --- a/utils/colorOut.js +++ b/utils/colorOut.js @@ -1,26 +1,31 @@ +import { getLogDateTime } from "./time.js" + +function basePrint(color, msg) { + console.log(`${color}%s %s\x1B[0m`, `[${getLogDateTime(new Date())}]`, msg) +} function printRed(msg) { - console.log('\x1B[31m%s\x1B[0m', msg) + basePrint("\x1B[31m", msg) } function printGreen(msg) { - console.log('\x1B[32m%s\x1B[0m', msg) + basePrint("\x1B[32m", msg) } function printYellow(msg) { - console.log('\x1B[33m%s\x1B[0m', msg) + basePrint("\x1B[33m", msg) } function printBlue(msg) { - console.log('\x1B[34m%s\x1B[0m', msg) + basePrint("\x1B[33m", msg) } function printMagenta(msg) { - console.log('\x1B[35m%s\x1B[0m', msg) + basePrint("\x1B[35m", msg) } function printGrey(msg) { - console.log('\x1B[2m%s\x1B[0m', msg) + basePrint("\x1B[2m", msg) } export { diff --git a/utils/fetchList.js b/utils/fetchList.js index 2a85e4c..f2895d8 100644 --- a/utils/fetchList.js +++ b/utils/fetchList.js @@ -9,64 +9,41 @@ function delay(ms) { // 获取分类集合 async function cateList() { - try { - const resp = await axios.get("https://program-sc.miguvideo.com/live/v2/tv-data/1ff892f2b5ab4a79be6e25b69d2f5d05") - let liveList = resp.data.body.liveList - // 热门内容重复 - liveList = liveList.filter((item) => { - return item.name != "热门" - }) + const resp = await axios.get("https://program-sc.miguvideo.com/live/v2/tv-data/1ff892f2b5ab4a79be6e25b69d2f5d05") + let liveList = resp.data.body.liveList + // 热门内容重复 + liveList = liveList.filter((item) => { + return item.name != "热门" + }) - // 央视作为首个分类 - liveList.sort((a, b) => { - if (a.name === "央视") return -1; - if (b.name === "央视") return 1 - return 0 - }) + // 央视作为首个分类 + liveList.sort((a, b) => { + if (a.name === "央视") return -1; + if (b.name === "央视") return 1 + return 0 + }) - return liveList - } catch (error) { - throw error - } + return liveList } // 所有数据 async function dataList() { - try { - let cates = await cateList() + let cates = await cateList() - for (let cate in cates) { - try { - const resp = await axios.get("https://program-sc.miguvideo.com/live/v2/tv-data/" + cates[cate].vomsID) - cates[cate].dataList = resp.data.body.dataList - } catch (error) { - cates[cate].dataList = []; - } + for (let cate in cates) { + try { + const resp = await axios.get("https://program-sc.miguvideo.com/live/v2/tv-data/" + cates[cate].vomsID) + cates[cate].dataList = resp.data.body.dataList + } catch (error) { + cates[cate].dataList = []; } - - // 去除重复节目 - cates = uniqueData(cates) - // console.dir(cates, { depth: null }) - // console.log(cates) - return cates - } catch (error) { - throw error } -} -// 获取电视链接 -async function getUrlInfo(contId) { - try { - const resp = await axios.get(`https://webapi.miguvideo.com/gateway/playurl/v2/play/playurlh5?contId=${contId}&rateType=999&clientId=-&startPlay=true&xh265=false&channelId=0131_200300220100002`) - // console.log(resp.data.body.urlInfo.url) - // console.log(resp.data) - if (resp.data?.body?.urlInfo?.url) { - return resp.data.body.urlInfo.url - } - return "" - } catch (error) { - throw error - } + // 去除重复节目 + cates = uniqueData(cates) + // console.dir(cates, { depth: null }) + // console.log(cates) + return cates } // 对data的dataList去重 @@ -120,4 +97,4 @@ function uniqueData(liveList) { return liveList } -export { cateList, dataList, getUrlInfo, delay } +export { cateList, dataList, delay } diff --git a/utils/getURL.js b/utils/getURL.js deleted file mode 100644 index eb3b130..0000000 --- a/utils/getURL.js +++ /dev/null @@ -1,38 +0,0 @@ -import puppeteer from 'puppeteer'; - -// 打开浏览器 -async function get_browser(path) { - return await puppeteer.launch({ - args: [ - "--no-sandbox" - ] - }); -} - -// 创建页面 -async function get_page(browser) { - return await browser.newPage(); -} - -// 获取url -async function get_url(page, video_id) { - let url = "" - let base_url = "" - page.on("requestfinished", request => { - if (request.url().startsWith("https://hlszymgsplive.miguvideo.com/")) { - url = request.url() - } - if (request.url().startsWith("https://h5live.gslb.cmvideo.cn/")) { - base_url = request.url() - } - }) - await page.goto('https://m.miguvideo.com/m/liveDetail/' + video_id, { waitUntil: "networkidle2" }); - return url, base_url -} - -// 关闭浏览器 -async function close_browser(browser) { - await browser.close() -} - -export { get_browser, get_page, get_url, close_browser } diff --git a/utils/net.js b/utils/net.js new file mode 100644 index 0000000..ab6dcc4 --- /dev/null +++ b/utils/net.js @@ -0,0 +1,27 @@ +import os from "os" + +function getLocalIPv(ver = 4) { + const ips = [] + const inter = os.networkInterfaces() + // console.dir(inter, { depth: null }) + for (let net in inter) { + + // console.dir(net, { depth: null }) + // console.log() + for (let netPort of inter[net]) { + // netPort = inter[net][netPort] + // console.dir(netPort, { depth: null }) + if (netPort.family === `IPv${ver}`) { + // console.dir(netPort, { depth: null }) + ips.push(netPort.address) + } + } + } + // console.log() + // console.dir(ips, { depth: null }) + return ips +} + +export { + getLocalIPv +} diff --git a/utils/time.js b/utils/time.js index cd41822..750eba3 100644 --- a/utils/time.js +++ b/utils/time.js @@ -16,4 +16,8 @@ function getDateTimeStr(date) { `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}:${String(date.getSeconds()).padStart(2, "0")}` } -export { getDateString, getTimeString, getDateTimeString, getDateTimeStr } +function getLogDateTime(date) { + return `${getDateTimeStr(date)}:${String(date.getMilliseconds()).padStart(3, "0")}` +} + +export { getDateString, getTimeString, getDateTimeString, getDateTimeStr, getLogDateTime }