feat: add HuggingFace storage channel support

- Add HuggingFace API wrapper class (huggingfaceAPI.js)
- Support upload, download, delete operations via HuggingFace Hub API
- Support public repos (unlimited storage) and private repos (100GB limit)
- Private repos: server proxies requests with Authorization header
- Auto-create repo if not exists (with write token)
- Add HuggingFace to auto-retry channel list
- Environment variables: HF_TOKEN, HF_REPO, HF_PRIVATE
- Support load balancing for multiple HuggingFace channels
This commit is contained in:
axibayuit
2025-12-30 17:46:11 +08:00
parent 5393e04631
commit 7ef6fd48ac
6 changed files with 474 additions and 3 deletions

View File

@@ -3,6 +3,7 @@ import { purgeCFCache } from "../../../utils/purgeCache";
import { removeFileFromIndex, batchRemoveFilesFromIndex } from "../../../utils/indexManager.js";
import { getDatabase } from '../../../utils/databaseAdapter.js';
import { DiscordAPI } from '../../../utils/discordAPI.js';
import { HuggingFaceAPI } from '../../../utils/huggingfaceAPI.js';
// CORS 跨域响应头
const corsHeaders = {
@@ -148,6 +149,11 @@ async function deleteFile(env, fileId, cdnUrl, url) {
await deleteDiscordFile(img);
}
// HuggingFace 渠道的图片,需要删除 HuggingFace 中对应的文件
if (img.metadata?.Channel === 'HuggingFace') {
await deleteHuggingFaceFile(img);
}
// 删除数据库中的记录
// 注意:容量统计现在由索引自动维护,删除文件后索引更新时会自动重新计算
await db.delete(fileId);
@@ -224,4 +230,30 @@ async function deleteDiscordFile(img) {
console.error("Discord Delete Failed:", error);
return false;
}
}
}
// 删除 HuggingFace 渠道的图片
async function deleteHuggingFaceFile(img) {
const token = img.metadata?.HfToken;
const repo = img.metadata?.HfRepo;
const filePath = img.metadata?.HfFilePath;
const isPrivate = img.metadata?.HfIsPrivate || false;
if (!token || !repo || !filePath) {
console.warn('HuggingFace file missing required metadata for deletion');
return false;
}
try {
const huggingfaceAPI = new HuggingFaceAPI(token, repo, isPrivate);
const success = await huggingfaceAPI.deleteFile(filePath, `Delete ${filePath}`);
if (!success) {
console.error('HuggingFace Delete Failed: API returned false');
}
return success;
} catch (error) {
console.error("HuggingFace Delete Failed:", error);
return false;
}
}