feat: delete remote images from Lsky when record/attachment is deleted (keys stored at upload, legacy URLs resolved via pathname)
This commit is contained in:
@@ -27,6 +27,53 @@ async function lskyUpload(buf, fileName, mime) {
|
||||
if (!j || j.status !== true || !url) throw new Error('LSKY ' + r.status + ': ' + (j?.message || 'no url'));
|
||||
return { url, thumb_url: sanitizeImageUrl(j?.data?.thumbnail_url) || undefined, key: j.data.key };
|
||||
}
|
||||
|
||||
async function lskyDelete(key) {
|
||||
const r = await fetch(LSKY_API + '/images/' + encodeURIComponent(key), {
|
||||
method: 'DELETE', headers: { authorization: 'Bearer ' + LSKY_TOKEN, accept: 'application/json' },
|
||||
signal: AbortSignal.timeout(30_000),
|
||||
});
|
||||
const j = await r.json().catch(() => null);
|
||||
if (!j || j.status !== true) throw new Error('LSKY delete ' + r.status + ': ' + (j?.message || ''));
|
||||
return true;
|
||||
}
|
||||
|
||||
// 历史 URL 反查 key:按 pathname 在图床相册里匹配(最多翻 5 页)
|
||||
async function lskyFindKeyByUrl(url) {
|
||||
try {
|
||||
const pathname = new URL(url).pathname.replace(/^\/i\//, '');
|
||||
for (let page = 1; page <= 5; page++) {
|
||||
const r = await fetch(LSKY_API + '/images?per_page=100&page=' + page, {
|
||||
headers: { authorization: 'Bearer ' + LSKY_TOKEN, accept: 'application/json' },
|
||||
signal: AbortSignal.timeout(30_000),
|
||||
});
|
||||
const j = await r.json().catch(() => null);
|
||||
const items = j?.data?.data || [];
|
||||
const hit = items.find(x => x.pathname === pathname);
|
||||
if (hit) return hit.key;
|
||||
if (page >= (j?.data?.last_page || 1)) break;
|
||||
}
|
||||
} catch (e) { console.log('[lsky] 反查 key 失败:', e.message); }
|
||||
return null;
|
||||
}
|
||||
|
||||
// 删除联动:记录/附件删除后清理图床(后台异步)
|
||||
function lskyCleanupRemote(items) {
|
||||
if (!LSKY_API || !LSKY_TOKEN) return;
|
||||
(async () => {
|
||||
for (const it of items) {
|
||||
try {
|
||||
let k = it.remote_key;
|
||||
if (!k && it.remote_url) k = await lskyFindKeyByUrl(it.remote_url);
|
||||
if (k) await lskyDelete(k);
|
||||
let tk = it.remote_thumb_key;
|
||||
if (!tk && it.remote_thumb) tk = await lskyFindKeyByUrl(it.remote_thumb);
|
||||
if (tk) await lskyDelete(tk);
|
||||
if (k || tk) console.log('[lsky] 图床已清理:', it.file_name || it.id);
|
||||
} catch (e) { console.log('[lsky] 图床清理失败:', it.file_name || it.id, e.message); }
|
||||
}
|
||||
})();
|
||||
}
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { getDb } from './db.mjs';
|
||||
@@ -207,7 +254,7 @@ const server = http.createServer(async (req, res) => {
|
||||
const tUp = await lskyUpload(Buffer.from(td.data_b64, 'base64'), 'thumb-' + row.file_name + '.webp', td.mime || 'image/webp');
|
||||
thumbUrl = tUp.thumb_url || tUp.url;
|
||||
}
|
||||
cmds.handleCommand('attachment_set_remote', { id: row.id, remote_url: up.url, remote_thumb: thumbUrl });
|
||||
cmds.handleCommand('attachment_set_remote', { id: row.id, remote_url: up.url, remote_thumb: thumbUrl, remote_key: up.key, remote_thumb_key: thumbKey });
|
||||
done++;
|
||||
} catch (e) { failed++; console.log('[lsky-migrate]', row.id, e.message); }
|
||||
}
|
||||
@@ -296,12 +343,13 @@ const server = http.createServer(async (req, res) => {
|
||||
(async () => {
|
||||
try {
|
||||
const up = await lskyUpload(buf, name, mime);
|
||||
let thumbUrl = null;
|
||||
let thumbUrl = null, thumbKey = null;
|
||||
if (thumbB64) {
|
||||
const tUp = await lskyUpload(Buffer.from(thumbB64, 'base64'), 'thumb-' + name + '.webp', 'image/webp');
|
||||
thumbUrl = tUp.thumb_url || tUp.url;
|
||||
thumbKey = tUp.key;
|
||||
}
|
||||
cmds.handleCommand('attachment_set_remote', { id: itemId, remote_url: up.url, remote_thumb: thumbUrl });
|
||||
cmds.handleCommand('attachment_set_remote', { id: itemId, remote_url: up.url, remote_thumb: thumbUrl, remote_key: up.key, remote_thumb_key: thumbKey });
|
||||
console.log('[lsky] 附件 #' + itemId + ' 已上图床');
|
||||
} catch (e) { console.log('[lsky] 附件 #' + itemId + ' 后台上传失败(可用 sync-lsky 补传):', e.message); }
|
||||
})();
|
||||
@@ -309,6 +357,26 @@ const server = http.createServer(async (req, res) => {
|
||||
return send(200, true, data);
|
||||
}
|
||||
|
||||
// 附件删除:本地清理 + 图床异步清理
|
||||
if (req.method === 'POST' && route === '/api/attachment_delete') {
|
||||
const body = await readJson(req);
|
||||
const cmds = commandsFor(auth.user_id);
|
||||
const row = cmds.getDb().prepare('SELECT id, file_name, remote_url, remote_thumb, remote_key, remote_thumb_key FROM attachment WHERE id=?').get(Number(body.id));
|
||||
const data = cmds.handleCommand('attachment_delete', body);
|
||||
if (row && (row.remote_key || row.remote_url || row.remote_thumb)) lskyCleanupRemote([row]);
|
||||
return send(200, true, data);
|
||||
}
|
||||
|
||||
// 记录删除:级联清理附件 + 图床
|
||||
if (req.method === 'POST' && route === '/api/footprint_delete') {
|
||||
const body = await readJson(req);
|
||||
const cmds = commandsFor(auth.user_id);
|
||||
const atts = cmds.getDb().prepare("SELECT id, file_name, remote_url, remote_thumb, remote_key, remote_thumb_key FROM attachment WHERE owner_type='footprint' AND owner_id=? AND deleted_at IS NULL AND (remote_url IS NOT NULL OR remote_key IS NOT NULL)").all(Number(body.id));
|
||||
const data = cmds.handleCommand('footprint_delete', body);
|
||||
if (atts.length) lskyCleanupRemote(atts);
|
||||
return send(200, true, data);
|
||||
}
|
||||
|
||||
// 附件直传图床(兼容旧 base64 通道):同样异步
|
||||
if (req.method === 'POST' && route === '/api/attachment_add') {
|
||||
const body = await readJson(req);
|
||||
@@ -319,13 +387,13 @@ const server = http.createServer(async (req, res) => {
|
||||
(async () => {
|
||||
try {
|
||||
const up = await lskyUpload(orig, body.file_name || ('file-' + itemId), body.mime);
|
||||
let thumbUrl = null;
|
||||
let thumbUrl = null, thumbKey = null;
|
||||
if (body.thumb_b64) {
|
||||
const tUp = await lskyUpload(Buffer.from(body.thumb_b64, 'base64'), 'thumb-' + (body.file_name || 'img') + '.webp', 'image/webp');
|
||||
thumbUrl = tUp.thumb_url || tUp.url;
|
||||
thumbKey = tUp.key;
|
||||
}
|
||||
cmds = null;
|
||||
commandsFor(auth.user_id).handleCommand('attachment_set_remote', { id: itemId, remote_url: up.url, remote_thumb: thumbUrl });
|
||||
commandsFor(auth.user_id).handleCommand('attachment_set_remote', { id: itemId, remote_url: up.url, remote_thumb: thumbUrl, remote_key: up.key, remote_thumb_key: thumbKey });
|
||||
console.log('[lsky] 附件 #' + itemId + ' 已上图床');
|
||||
} catch (e) { console.log('[lsky] 附件 #' + itemId + ' 后台上传失败:', e.message); }
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user