Spaces:
Sleeping
Sleeping
File size: 4,457 Bytes
33f687c a86efc3 33f687c a484614 a86efc3 a484614 2fa53e9 f62bcf0 b2a321b a86efc3 2fa53e9 a484614 a86efc3 a484614 a86efc3 2fa53e9 a484614 2fa53e9 2b2a93b 2fa53e9 2b2a93b a484614 2b2a93b 33f687c a86efc3 144f7f2 9ad973a 2fa53e9 9f32484 2fa53e9 9f32484 9ad973a a484614 2fa53e9 9ad973a 9f32484 9ad973a a484614 2fa53e9 9ad973a 222e54f 9ad973a 2fa53e9 9ad973a 2fa53e9 9ad973a a484614 9ad973a 60c1a52 9ad973a a86efc3 2fa53e9 a484614 2fa53e9 a86efc3 33f687c e502e8d 33f687c 2fa53e9 289ca2d 2fa53e9 a484614 a86efc3 e6a8780 2fa53e9 e6a8780 a86efc3 e6a8780 33f687c a86efc3 2fa53e9 a86efc3 2fa53e9 9ad973a 2fa53e9 9ad973a 2fa53e9 33f687c a86efc3 2fa53e9 a484614 2fa53e9 a484614 a86efc3 9ad973a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | import path from "node:path";
import { listFiles, downloadFile } from "@huggingface/hub";
import { sha256 } from "../utils/sha256";
import { Mod } from "./mod";
import { Server } from "../server/server";
import { Logger } from "../logger/logger";
export class ModManager {
private server: Server;
private logger: Logger;
private bucketId = "buckets/NSMP/NSMP-Server-Storage";
private bucketFolder = "mods";
private modCache: Mod[] = [];
private refreshIntervalMs = 60_000; // 1 minute
constructor(server: Server, logger: Logger) {
this.server = server;
this.logger = logger;
}
public async createModEndpoints(): Promise<void> {
await this.refreshModCache();
setInterval(() => {
this.refreshModCache().catch(err => {
this.logger.error("Failed to refresh mod cache:", err);
});
}, this.refreshIntervalMs);
this.server.get("/mods/", async (_req, res) => {
try {
res.send(JSON.stringify(this.modCache));
} catch (err) {
this.logger.error("Failed to list mods:", err);
res.status(500).send("Failed to list mods");
}
});
this.server.get("/files/mods/:filename", async (req, res) => {
try {
const filename = req.params.filename;
const mod = this.modCache.find(
m => m.filename === filename
);
if (!mod) {
res.status(404).send("Mod not found");
return;
}
this.logger.time(`download:${filename}`);
const blob = await downloadFile({
repo: this.bucketId,
path: mod.path,
accessToken: process.env.HF_TOKEN
});
this.logger.timeEnd(`download:${filename}`);
if (!blob) {
res.status(404).send("Mod not found");
return;
}
const buffer = Buffer.from(
await blob.arrayBuffer()
);
res.setHeader(
"Content-Disposition",
`attachment; filename="${filename}"`
);
res.setHeader(
"Content-Type",
"application/java-archive"
);
res.send(buffer);
} catch (err) {
this.logger.error(err as string);
res.status(500).send("Failed to fetch mod from bucket");
}
});
}
private async refreshModCache(): Promise<void> {
this.logger.time("refreshModCache");
const existing = new Map(
this.modCache.map(mod => [mod.path, mod])
);
const updated: Mod[] = [];
for await (const item of listFiles({
repo: this.bucketId,
path: this.bucketFolder,
recursive: true,
accessToken: process.env.HF_TOKEN
})) {
if (
item.type !== "file" ||
!item.path.toLowerCase().endsWith(".jar")
) {
continue;
}
const cached = existing.get(item.path);
if (cached) {
updated.push(cached);
continue;
}
this.logger.info(`New mod detected: ${item.path}`);
const jarBlob = await downloadFile({
repo: this.bucketId,
path: item.path,
accessToken: process.env.HF_TOKEN
});
if (!jarBlob) {
continue;
}
const jarBuffer = Buffer.from(
await jarBlob.arrayBuffer()
);
const filename = path.basename(item.path);
updated.push({
name: filename.replace(/\.jar$/i, ""),
filename,
path: item.path,
sha256: sha256(jarBuffer),
url: `https://NSMP-NSMP-Server.hf.space/files/mods/${encodeURIComponent(
filename
)}`
});
}
this.modCache = updated;
this.logger.timeEnd("refreshModCache");
this.logger.info(`Cached ${this.modCache.length} mods`);
}
} |