feat: 初始化慧遇书院官网一期
This commit is contained in:
28
scripts/purge-media-trash.sh
Executable file
28
scripts/purge-media-trash.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
retention_days="${MEDIA_TRASH_RETENTION_DAYS:-30}"
|
||||
case "$retention_days" in *[!0-9]*|'') echo "MEDIA_TRASH_RETENTION_DAYS 必须是非负整数" >&2; exit 2 ;; esac
|
||||
|
||||
docker compose exec -T -e RETENTION_DAYS="$retention_days" web node - <<'NODE'
|
||||
const Database = require('better-sqlite3')
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
const db = new Database('/app/data/db/huiyu.sqlite')
|
||||
const cutoff = new Date(Date.now() - Number(process.env.RETENTION_DAYS) * 86400000).toISOString()
|
||||
const rows = db.prepare("SELECT id, asset_key, original_path, derived_path, thumbnail_path FROM media_assets WHERE status = 'trash' AND deleted_at <= ?").all(cutoff)
|
||||
const root = path.resolve('/app/data/uploads/trash')
|
||||
const remove = relative => {
|
||||
const target = path.resolve(root, relative)
|
||||
if (!target.startsWith(root + path.sep)) throw new Error('unsafe media path')
|
||||
try { fs.unlinkSync(target) } catch (error) { if (error.code !== 'ENOENT') throw error }
|
||||
}
|
||||
const finish = db.transaction(row => {
|
||||
for (const relative of [row.original_path, row.derived_path, row.thumbnail_path]) remove(relative)
|
||||
db.prepare("UPDATE media_assets SET status = 'deleted', updated_at = ? WHERE id = ?").run(new Date().toISOString(), row.id)
|
||||
db.prepare("INSERT INTO audit_logs (action, entity_type, entity_key, metadata_json, created_at) VALUES ('media.purge', 'media', ?, '{}', ?)").run(row.asset_key, new Date().toISOString())
|
||||
})
|
||||
for (const row of rows) finish(row)
|
||||
db.close()
|
||||
console.log(`已物理清理 ${rows.length} 个回收站素材`)
|
||||
NODE
|
||||
Reference in New Issue
Block a user