diff --git a/.gitignore b/.gitignore index fc3697b..c43d48b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ access.log node_modules package-lock.json data +config.json diff --git a/main.js b/main.js index d34f858..d859240 100644 --- a/main.js +++ b/main.js @@ -1,9 +1,7 @@ import fs from 'fs' import { Tail } from 'tail' +import { updateDatabase } from './put_database.js' -const tail = new Tail('/opt/log/caddy/access.log') - -// 指标(日榜, 周榜, 月榜, 总榜) const 作品 = new Map() const 游戏 = new Map() const 截图 = new Map() @@ -15,7 +13,6 @@ const imagesRegex = /\/api\/images\?similar=(\d+)/ var 当前日期 = 格式.format(new Date()).replace(/\//g, '-') var 正在存档 = false - const 存档 = async (message = '存档中..') => { if (正在存档) return 正在存档 = true @@ -28,72 +25,77 @@ const 存档 = async (message = '存档中..') => { 正在存档 = false } - -if (fs.existsSync(`./data/${当前日期}.json`)) { - console.log(当前日期, '启动时读入数据..') - const file = fs.readFileSync(`./data/${当前日期}.json`, 'utf8') - if (file) { - const data = JSON.parse(file) - Object.entries(data.作品).forEach(([key, value]) => 作品.set(key, value)) - Object.entries(data.游戏).forEach(([key, value]) => 游戏.set(key, value)) - Object.entries(data.截图).forEach(([key, value]) => 截图.set(key, value)) - } -} - - -console.log(当前日期, '开始收集日志..') -setInterval(() => 存档('10 分钟存档一次..'), 600000) - -tail.on('line', async (line) => { - const item = JSON.parse(line) - if (item.level !== 'debug') return - if (item.msg !== 'upstream roundtrip') return - - const 日志日期 = 格式.format(new Date(item.ts * 1000)).replace(/\//g, '-') - if (当前日期 !== 日志日期) { - await 存档('跨日期存档..') - 作品.clear() - 游戏.clear() - 截图.clear() - 当前日期 = 日志日期 - } - - if (item.request.uri.startsWith('/web/v1/article/get')) { - const [uri, id, user_id] = item.request.uri.match(articleRegex) ?? [] - if (uri && id && user_id && item.request.headers.Referer) { - if (item.request.headers.Referer[0].includes('/articleDetails/')) { - 作品.set(id, 作品.has(id) ? 作品.get(id) + 1 : 1) - return - } - if (item.request.headers.Referer[0].includes('/inspirationInfo/')) { - 游戏.set(id, 游戏.has(id) ? 游戏.get(id) + 1 : 1) - return - } - if (item.request.headers.Referer[0].includes('/game/')) { - 游戏.set(id, 游戏.has(id) ? 游戏.get(id) + 1 : 1) - return - } - console.log('未处理 Referer:', item.request.headers.Referer) +export default function () { + if (fs.existsSync(`./data/${当前日期}.json`)) { + console.log(当前日期, '启动时读入数据..') + const file = fs.readFileSync(`./data/${当前日期}.json`, 'utf8') + if (file) { + const data = JSON.parse(file) + Object.entries(data.作品).forEach(([key, value]) => 作品.set(key, value)) + Object.entries(data.游戏).forEach(([key, value]) => 游戏.set(key, value)) + Object.entries(data.截图).forEach(([key, value]) => 截图.set(key, value)) } - return } - if (item.request.uri.startsWith('/api/images')) { - if (item.request.uri.includes('page=')) { + + console.log(当前日期, '开始收集日志..') + setInterval(() => { + 存档('10 分钟存档一次..') + updateDatabase(Object.fromEntries(截图)) + }, 600000) + + const tail = new Tail('/opt/log/caddy/access.log') + tail.on('line', async (line) => { + const item = JSON.parse(line) + if (item.level !== 'debug') return + if (item.msg !== 'upstream roundtrip') return + + const 日志日期 = 格式.format(new Date(item.ts * 1000)).replace(/\//g, '-') + if (当前日期 !== 日志日期) { + await 存档('跨日期存档..') + 作品.clear() + 游戏.clear() + 截图.clear() + 当前日期 = 日志日期 + } + + if (item.request.uri.startsWith('/web/v1/article/get')) { + const [uri, id, user_id] = item.request.uri.match(articleRegex) ?? [] + if (uri && id && user_id && item.request.headers.Referer) { + if (item.request.headers.Referer[0].includes('/articleDetails/')) { + 作品.set(id, 作品.has(id) ? 作品.get(id) + 1 : 1) + return + } + if (item.request.headers.Referer[0].includes('/inspirationInfo/')) { + 游戏.set(id, 游戏.has(id) ? 游戏.get(id) + 1 : 1) + return + } + if (item.request.headers.Referer[0].includes('/game/')) { + 游戏.set(id, 游戏.has(id) ? 游戏.get(id) + 1 : 1) + return + } + console.log('未处理 Referer:', item.request.headers.Referer) + } return } - const [uri, id] = item.request.uri.match(imagesRegex) ?? [] - if (uri && id) { - 截图.set(id, 截图.has(id) ? 截图.get(id) + 1 : 1) + if (item.request.uri.startsWith('/api/images')) { + if (item.request.uri.includes('page=')) { + return + } + const [uri, id] = item.request.uri.match(imagesRegex) ?? [] + if (uri && id) { + 截图.set(id, 截图.has(id) ? 截图.get(id) + 1 : 1) + } + return } - return - } -}) + }) -tail.on('end', () => console.log('没有更多内容,结束读取')) -tail.on('error', (error) => console.error('错误:', error)) + tail.on('end', () => console.log('没有更多内容,结束读取')) + tail.on('error', (error) => console.error('错误:', error)) -process.on('SIGINT', async () => { - tail.unwatch() - await 存档('退出前储存数据..') - process.exit() -}) + process.on('SIGINT', async () => { + tail.unwatch() + await 存档('退出前储存数据..') + process.exit() + }) + +} diff --git a/package.json b/package.json index 0bb57c4..bbfd075 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,13 @@ "type": "module", "main": "main.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "start": "node server.js" }, "author": "satori", "license": "GPL-3.0-only", "dependencies": { "express": "^4.21.1", + "mysql2": "^3.11.4", "tail": "^2.2.6" } } diff --git a/put_database.js b/put_database.js new file mode 100644 index 0000000..18fe0fc --- /dev/null +++ b/put_database.js @@ -0,0 +1,19 @@ +import mysql from 'mysql2/promise' +import fs from 'fs' + +export async function updateDatabase(list, field) { + const { mysql: config } = JSON.parse(fs.readFileSync('config.json', 'utf8')) + const conn = await mysql.createConnection(config) + + await conn.query(`CREATE TEMPORARY TABLE temp_updates (id INT PRIMARY KEY, ${field} INT)`) + + for (let i = 0; i < list.length; i += 10000) { + const values = list.slice(i, i + 10000).map(({ id, ...rest }) => [id, rest[field]]) + await conn.query(`INSERT INTO temp_updates (id, ${field}) VALUES ?`, [values]) + } + + await conn.query(`UPDATE web_images t JOIN temp_updates tu ON t.id = tu.id SET t.${field} = tu.${field}`) + console.log('更新完成') + await conn.end() +} + diff --git a/server.js b/server.js index a9979b3..5454b44 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,6 @@ import fs from 'fs' import express from 'express' +import main from './main.js' const app = express() @@ -41,3 +42,4 @@ app.get('/api', (req, res) => { }) app.listen(6005, () => console.log('http://localhost:6005')) +main()