@bonginkan/maria 4.3.12 → 4.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/dist/READY.manifest.json +1 -1
- package/dist/bin/maria.cjs +4410 -1053
- package/dist/bin/maria.cjs.map +1 -1
- package/dist/cli.cjs +4411 -1054
- package/dist/cli.cjs.map +1 -1
- package/dist/server/express-server.cjs +28 -18
- package/dist/server/express-server.js +28 -18
- package/dist/server-express.cjs +28 -18
- package/dist/server-express.cjs.map +1 -1
- package/package.json +2 -2
- package/src/slash-commands/READY.manifest.json +1 -1
|
@@ -6913,7 +6913,7 @@ function startRateLimitCleanup() {
|
|
|
6913
6913
|
});
|
|
6914
6914
|
}, 10 * 60 * 1e3);
|
|
6915
6915
|
}
|
|
6916
|
-
async function getFirestorePlan(
|
|
6916
|
+
async function getFirestorePlan(uid2) {
|
|
6917
6917
|
try {
|
|
6918
6918
|
const admin = await import('firebase-admin');
|
|
6919
6919
|
if (!admin.apps?.length) {
|
|
@@ -6924,7 +6924,7 @@ async function getFirestorePlan(uid) {
|
|
|
6924
6924
|
}
|
|
6925
6925
|
const { getFirestore } = await import('firebase-admin/firestore');
|
|
6926
6926
|
const db = getFirestore();
|
|
6927
|
-
const doc = await db.doc(`projects/default/users/${
|
|
6927
|
+
const doc = await db.doc(`projects/default/users/${uid2}`).get();
|
|
6928
6928
|
const plan = doc.exists && doc.data()?.plan || "FREE";
|
|
6929
6929
|
return String(plan).toUpperCase();
|
|
6930
6930
|
} catch {
|
|
@@ -8608,7 +8608,7 @@ app.get("/api/user/profile", async (req, res) => {
|
|
|
8608
8608
|
if (!decoded) {
|
|
8609
8609
|
return res.status(401).json({ error: "invalid_token" });
|
|
8610
8610
|
}
|
|
8611
|
-
const
|
|
8611
|
+
const uid2 = decoded.uid || decoded.sub || "unknown";
|
|
8612
8612
|
const email = decoded.email || "";
|
|
8613
8613
|
const displayName = decoded.name || decoded.displayName || (email ? String(email).split("@")[0] : "User");
|
|
8614
8614
|
let provider = decoded.firebase?.sign_in_provider;
|
|
@@ -8619,7 +8619,7 @@ app.get("/api/user/profile", async (req, res) => {
|
|
|
8619
8619
|
}
|
|
8620
8620
|
const plan = "FREE";
|
|
8621
8621
|
const response2 = {
|
|
8622
|
-
id:
|
|
8622
|
+
id: uid2,
|
|
8623
8623
|
email,
|
|
8624
8624
|
name: displayName,
|
|
8625
8625
|
provider: provider || "unknown",
|
|
@@ -8703,6 +8703,9 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8703
8703
|
await loadProviderKeys();
|
|
8704
8704
|
const auth = req.headers.authorization;
|
|
8705
8705
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8706
|
+
const idToken = auth.substring("Bearer ".length).trim();
|
|
8707
|
+
const decoded = await decodeFirebaseToken(idToken).catch(() => null);
|
|
8708
|
+
const uid2 = decoded?.uid || decoded?.sub || "current";
|
|
8706
8709
|
const { prompt, model, size = "1024x1024", format = "png", count = 1, seed } = req.body || {};
|
|
8707
8710
|
if (!prompt) return res.status(400).json({ error: "bad_request", message: "prompt required" });
|
|
8708
8711
|
const m2 = /^(\d{2,4})x(\d{2,4})$/.exec(String(size));
|
|
@@ -8730,10 +8733,11 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8730
8733
|
kind: "image",
|
|
8731
8734
|
manifestPath: saved.manifestPath,
|
|
8732
8735
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8733
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8736
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8737
|
+
uid: uid2
|
|
8734
8738
|
});
|
|
8735
8739
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
8736
|
-
await recordConsumption(
|
|
8740
|
+
await recordConsumption(uid2, { requests: 1, image: Math.max(1, buffers.length) }, idemKey);
|
|
8737
8741
|
return res.json({ success: true, data: { url: saved.manifestPath, jobId: manifest.trace } });
|
|
8738
8742
|
} catch (error) {
|
|
8739
8743
|
console.error("[Image API] Error:", error);
|
|
@@ -8779,14 +8783,15 @@ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
|
8779
8783
|
saved = await saveArtifacts({ root: process.cwd(), kind: "video" }, items, manifest);
|
|
8780
8784
|
}
|
|
8781
8785
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
8782
|
-
await recordConsumption(
|
|
8786
|
+
await recordConsumption(uid, { requests: 1, video: 1 }, idemKey);
|
|
8783
8787
|
jobIndex.set(String(manifest.trace), {
|
|
8784
8788
|
id: String(manifest.trace),
|
|
8785
8789
|
status: "completed",
|
|
8786
8790
|
kind: "video",
|
|
8787
8791
|
manifestPath: saved.manifestPath,
|
|
8788
8792
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8789
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8793
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8794
|
+
uid
|
|
8790
8795
|
});
|
|
8791
8796
|
return res.json({ success: true, data: { url: saved.manifestPath, jobId: manifest.trace } });
|
|
8792
8797
|
} catch (error) {
|
|
@@ -8799,10 +8804,15 @@ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
|
8799
8804
|
});
|
|
8800
8805
|
app.get("/api/v1/jobs/:id", async (req, res) => {
|
|
8801
8806
|
try {
|
|
8807
|
+
const auth = req.headers.authorization;
|
|
8808
|
+
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8809
|
+
const idToken = auth.substring("Bearer ".length).trim();
|
|
8810
|
+
const decoded = await decodeFirebaseToken(idToken).catch(() => null);
|
|
8811
|
+
const uid2 = decoded?.uid || decoded?.sub || "current";
|
|
8802
8812
|
const id = String(req.params.id || "").trim();
|
|
8803
8813
|
if (!id) return res.status(400).json({ error: "bad_request", message: "id required" });
|
|
8804
8814
|
const info = jobIndex.get(id);
|
|
8805
|
-
if (!info) return res.status(404).json({ error: "not_found", message: "job not found" });
|
|
8815
|
+
if (!info || info.uid && info.uid !== uid2) return res.status(404).json({ error: "not_found", message: "job not found" });
|
|
8806
8816
|
let manifest;
|
|
8807
8817
|
if (info.manifestPath) {
|
|
8808
8818
|
try {
|
|
@@ -8981,14 +8991,14 @@ function calcNextReset() {
|
|
|
8981
8991
|
d.setUTCHours(0, 0, 0, 0);
|
|
8982
8992
|
return d.toISOString();
|
|
8983
8993
|
}
|
|
8984
|
-
async function recordConsumption(
|
|
8994
|
+
async function recordConsumption(uid2, consumption, idempotencyKey) {
|
|
8985
8995
|
const db = await getFirestoreSafe();
|
|
8986
8996
|
if (!db) return;
|
|
8987
|
-
const docPath = `projects/default/usage/${
|
|
8997
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
8988
8998
|
const usageRef = db.doc(docPath);
|
|
8989
8999
|
const nowISO = (/* @__PURE__ */ new Date()).toISOString();
|
|
8990
9000
|
if (idempotencyKey) {
|
|
8991
|
-
const idemRef = db.doc(`projects/default/usage/${
|
|
9001
|
+
const idemRef = db.doc(`projects/default/usage/${uid2}/consumptions/${idempotencyKey}`);
|
|
8992
9002
|
const idemSnap = await idemRef.get();
|
|
8993
9003
|
if (idemSnap.exists) return;
|
|
8994
9004
|
await idemRef.set({ createdAt: nowISO, consumption });
|
|
@@ -9022,8 +9032,8 @@ app.get("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
9022
9032
|
const auth = req.headers.authorization;
|
|
9023
9033
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
9024
9034
|
const db = await getFirestoreSafe();
|
|
9025
|
-
const
|
|
9026
|
-
const docPath = `projects/default/usage/${
|
|
9035
|
+
const uid2 = "current";
|
|
9036
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
9027
9037
|
let data = null;
|
|
9028
9038
|
if (db) {
|
|
9029
9039
|
const snap = await db.doc(docPath).get();
|
|
@@ -9042,7 +9052,7 @@ app.get("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
9042
9052
|
};
|
|
9043
9053
|
await db.doc(docPath).set(data);
|
|
9044
9054
|
}
|
|
9045
|
-
const historySnap = await db.collection(`projects/default/usage/${
|
|
9055
|
+
const historySnap = await db.collection(`projects/default/usage/${uid2}/consumptions`).orderBy("createdAt", "desc").limit(20).get();
|
|
9046
9056
|
const history = historySnap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
9047
9057
|
data.history = history;
|
|
9048
9058
|
} else {
|
|
@@ -9070,11 +9080,11 @@ app.post("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
9070
9080
|
const { consumption } = req.body || {};
|
|
9071
9081
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
9072
9082
|
const db = await getFirestoreSafe();
|
|
9073
|
-
const
|
|
9074
|
-
const docPath = `projects/default/usage/${
|
|
9083
|
+
const uid2 = "current";
|
|
9084
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
9075
9085
|
let data = null;
|
|
9076
9086
|
if (db) {
|
|
9077
|
-
await recordConsumption(
|
|
9087
|
+
await recordConsumption(uid2, consumption || {}, idemKey);
|
|
9078
9088
|
const snap = await db.doc(docPath).get();
|
|
9079
9089
|
data = snap.exists ? snap.data() : { ok: true };
|
|
9080
9090
|
} else {
|
|
@@ -6913,7 +6913,7 @@ function startRateLimitCleanup() {
|
|
|
6913
6913
|
});
|
|
6914
6914
|
}, 10 * 60 * 1e3);
|
|
6915
6915
|
}
|
|
6916
|
-
async function getFirestorePlan(
|
|
6916
|
+
async function getFirestorePlan(uid2) {
|
|
6917
6917
|
try {
|
|
6918
6918
|
const admin = await import('firebase-admin');
|
|
6919
6919
|
if (!admin.apps?.length) {
|
|
@@ -6924,7 +6924,7 @@ async function getFirestorePlan(uid) {
|
|
|
6924
6924
|
}
|
|
6925
6925
|
const { getFirestore } = await import('firebase-admin/firestore');
|
|
6926
6926
|
const db = getFirestore();
|
|
6927
|
-
const doc = await db.doc(`projects/default/users/${
|
|
6927
|
+
const doc = await db.doc(`projects/default/users/${uid2}`).get();
|
|
6928
6928
|
const plan = doc.exists && doc.data()?.plan || "FREE";
|
|
6929
6929
|
return String(plan).toUpperCase();
|
|
6930
6930
|
} catch {
|
|
@@ -8608,7 +8608,7 @@ app.get("/api/user/profile", async (req, res) => {
|
|
|
8608
8608
|
if (!decoded) {
|
|
8609
8609
|
return res.status(401).json({ error: "invalid_token" });
|
|
8610
8610
|
}
|
|
8611
|
-
const
|
|
8611
|
+
const uid2 = decoded.uid || decoded.sub || "unknown";
|
|
8612
8612
|
const email = decoded.email || "";
|
|
8613
8613
|
const displayName = decoded.name || decoded.displayName || (email ? String(email).split("@")[0] : "User");
|
|
8614
8614
|
let provider = decoded.firebase?.sign_in_provider;
|
|
@@ -8619,7 +8619,7 @@ app.get("/api/user/profile", async (req, res) => {
|
|
|
8619
8619
|
}
|
|
8620
8620
|
const plan = "FREE";
|
|
8621
8621
|
const response2 = {
|
|
8622
|
-
id:
|
|
8622
|
+
id: uid2,
|
|
8623
8623
|
email,
|
|
8624
8624
|
name: displayName,
|
|
8625
8625
|
provider: provider || "unknown",
|
|
@@ -8703,6 +8703,9 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8703
8703
|
await loadProviderKeys();
|
|
8704
8704
|
const auth = req.headers.authorization;
|
|
8705
8705
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8706
|
+
const idToken = auth.substring("Bearer ".length).trim();
|
|
8707
|
+
const decoded = await decodeFirebaseToken(idToken).catch(() => null);
|
|
8708
|
+
const uid2 = decoded?.uid || decoded?.sub || "current";
|
|
8706
8709
|
const { prompt, model, size = "1024x1024", format = "png", count = 1, seed } = req.body || {};
|
|
8707
8710
|
if (!prompt) return res.status(400).json({ error: "bad_request", message: "prompt required" });
|
|
8708
8711
|
const m2 = /^(\d{2,4})x(\d{2,4})$/.exec(String(size));
|
|
@@ -8730,10 +8733,11 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8730
8733
|
kind: "image",
|
|
8731
8734
|
manifestPath: saved.manifestPath,
|
|
8732
8735
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8733
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8736
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8737
|
+
uid: uid2
|
|
8734
8738
|
});
|
|
8735
8739
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
8736
|
-
await recordConsumption(
|
|
8740
|
+
await recordConsumption(uid2, { requests: 1, image: Math.max(1, buffers.length) }, idemKey);
|
|
8737
8741
|
return res.json({ success: true, data: { url: saved.manifestPath, jobId: manifest.trace } });
|
|
8738
8742
|
} catch (error) {
|
|
8739
8743
|
console.error("[Image API] Error:", error);
|
|
@@ -8779,14 +8783,15 @@ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
|
8779
8783
|
saved = await saveArtifacts({ root: process.cwd(), kind: "video" }, items, manifest);
|
|
8780
8784
|
}
|
|
8781
8785
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
8782
|
-
await recordConsumption(
|
|
8786
|
+
await recordConsumption(uid, { requests: 1, video: 1 }, idemKey);
|
|
8783
8787
|
jobIndex.set(String(manifest.trace), {
|
|
8784
8788
|
id: String(manifest.trace),
|
|
8785
8789
|
status: "completed",
|
|
8786
8790
|
kind: "video",
|
|
8787
8791
|
manifestPath: saved.manifestPath,
|
|
8788
8792
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8789
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8793
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8794
|
+
uid
|
|
8790
8795
|
});
|
|
8791
8796
|
return res.json({ success: true, data: { url: saved.manifestPath, jobId: manifest.trace } });
|
|
8792
8797
|
} catch (error) {
|
|
@@ -8799,10 +8804,15 @@ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
|
8799
8804
|
});
|
|
8800
8805
|
app.get("/api/v1/jobs/:id", async (req, res) => {
|
|
8801
8806
|
try {
|
|
8807
|
+
const auth = req.headers.authorization;
|
|
8808
|
+
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8809
|
+
const idToken = auth.substring("Bearer ".length).trim();
|
|
8810
|
+
const decoded = await decodeFirebaseToken(idToken).catch(() => null);
|
|
8811
|
+
const uid2 = decoded?.uid || decoded?.sub || "current";
|
|
8802
8812
|
const id = String(req.params.id || "").trim();
|
|
8803
8813
|
if (!id) return res.status(400).json({ error: "bad_request", message: "id required" });
|
|
8804
8814
|
const info = jobIndex.get(id);
|
|
8805
|
-
if (!info) return res.status(404).json({ error: "not_found", message: "job not found" });
|
|
8815
|
+
if (!info || info.uid && info.uid !== uid2) return res.status(404).json({ error: "not_found", message: "job not found" });
|
|
8806
8816
|
let manifest;
|
|
8807
8817
|
if (info.manifestPath) {
|
|
8808
8818
|
try {
|
|
@@ -8981,14 +8991,14 @@ function calcNextReset() {
|
|
|
8981
8991
|
d.setUTCHours(0, 0, 0, 0);
|
|
8982
8992
|
return d.toISOString();
|
|
8983
8993
|
}
|
|
8984
|
-
async function recordConsumption(
|
|
8994
|
+
async function recordConsumption(uid2, consumption, idempotencyKey) {
|
|
8985
8995
|
const db = await getFirestoreSafe();
|
|
8986
8996
|
if (!db) return;
|
|
8987
|
-
const docPath = `projects/default/usage/${
|
|
8997
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
8988
8998
|
const usageRef = db.doc(docPath);
|
|
8989
8999
|
const nowISO = (/* @__PURE__ */ new Date()).toISOString();
|
|
8990
9000
|
if (idempotencyKey) {
|
|
8991
|
-
const idemRef = db.doc(`projects/default/usage/${
|
|
9001
|
+
const idemRef = db.doc(`projects/default/usage/${uid2}/consumptions/${idempotencyKey}`);
|
|
8992
9002
|
const idemSnap = await idemRef.get();
|
|
8993
9003
|
if (idemSnap.exists) return;
|
|
8994
9004
|
await idemRef.set({ createdAt: nowISO, consumption });
|
|
@@ -9022,8 +9032,8 @@ app.get("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
9022
9032
|
const auth = req.headers.authorization;
|
|
9023
9033
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
9024
9034
|
const db = await getFirestoreSafe();
|
|
9025
|
-
const
|
|
9026
|
-
const docPath = `projects/default/usage/${
|
|
9035
|
+
const uid2 = "current";
|
|
9036
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
9027
9037
|
let data = null;
|
|
9028
9038
|
if (db) {
|
|
9029
9039
|
const snap = await db.doc(docPath).get();
|
|
@@ -9042,7 +9052,7 @@ app.get("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
9042
9052
|
};
|
|
9043
9053
|
await db.doc(docPath).set(data);
|
|
9044
9054
|
}
|
|
9045
|
-
const historySnap = await db.collection(`projects/default/usage/${
|
|
9055
|
+
const historySnap = await db.collection(`projects/default/usage/${uid2}/consumptions`).orderBy("createdAt", "desc").limit(20).get();
|
|
9046
9056
|
const history = historySnap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
9047
9057
|
data.history = history;
|
|
9048
9058
|
} else {
|
|
@@ -9070,11 +9080,11 @@ app.post("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
9070
9080
|
const { consumption } = req.body || {};
|
|
9071
9081
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
9072
9082
|
const db = await getFirestoreSafe();
|
|
9073
|
-
const
|
|
9074
|
-
const docPath = `projects/default/usage/${
|
|
9083
|
+
const uid2 = "current";
|
|
9084
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
9075
9085
|
let data = null;
|
|
9076
9086
|
if (db) {
|
|
9077
|
-
await recordConsumption(
|
|
9087
|
+
await recordConsumption(uid2, consumption || {}, idemKey);
|
|
9078
9088
|
const snap = await db.doc(docPath).get();
|
|
9079
9089
|
data = snap.exists ? snap.data() : { ok: true };
|
|
9080
9090
|
} else {
|
package/dist/server-express.cjs
CHANGED
|
@@ -6913,7 +6913,7 @@ function startRateLimitCleanup() {
|
|
|
6913
6913
|
});
|
|
6914
6914
|
}, 10 * 60 * 1e3);
|
|
6915
6915
|
}
|
|
6916
|
-
async function getFirestorePlan(
|
|
6916
|
+
async function getFirestorePlan(uid2) {
|
|
6917
6917
|
try {
|
|
6918
6918
|
const admin = await import('firebase-admin');
|
|
6919
6919
|
if (!admin.apps?.length) {
|
|
@@ -6924,7 +6924,7 @@ async function getFirestorePlan(uid) {
|
|
|
6924
6924
|
}
|
|
6925
6925
|
const { getFirestore } = await import('firebase-admin/firestore');
|
|
6926
6926
|
const db = getFirestore();
|
|
6927
|
-
const doc = await db.doc(`projects/default/users/${
|
|
6927
|
+
const doc = await db.doc(`projects/default/users/${uid2}`).get();
|
|
6928
6928
|
const plan = doc.exists && doc.data()?.plan || "FREE";
|
|
6929
6929
|
return String(plan).toUpperCase();
|
|
6930
6930
|
} catch {
|
|
@@ -8608,7 +8608,7 @@ app.get("/api/user/profile", async (req, res) => {
|
|
|
8608
8608
|
if (!decoded) {
|
|
8609
8609
|
return res.status(401).json({ error: "invalid_token" });
|
|
8610
8610
|
}
|
|
8611
|
-
const
|
|
8611
|
+
const uid2 = decoded.uid || decoded.sub || "unknown";
|
|
8612
8612
|
const email = decoded.email || "";
|
|
8613
8613
|
const displayName = decoded.name || decoded.displayName || (email ? String(email).split("@")[0] : "User");
|
|
8614
8614
|
let provider = decoded.firebase?.sign_in_provider;
|
|
@@ -8619,7 +8619,7 @@ app.get("/api/user/profile", async (req, res) => {
|
|
|
8619
8619
|
}
|
|
8620
8620
|
const plan = "FREE";
|
|
8621
8621
|
const response2 = {
|
|
8622
|
-
id:
|
|
8622
|
+
id: uid2,
|
|
8623
8623
|
email,
|
|
8624
8624
|
name: displayName,
|
|
8625
8625
|
provider: provider || "unknown",
|
|
@@ -8703,6 +8703,9 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8703
8703
|
await loadProviderKeys();
|
|
8704
8704
|
const auth = req.headers.authorization;
|
|
8705
8705
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8706
|
+
const idToken = auth.substring("Bearer ".length).trim();
|
|
8707
|
+
const decoded = await decodeFirebaseToken(idToken).catch(() => null);
|
|
8708
|
+
const uid2 = decoded?.uid || decoded?.sub || "current";
|
|
8706
8709
|
const { prompt, model, size = "1024x1024", format = "png", count = 1, seed } = req.body || {};
|
|
8707
8710
|
if (!prompt) return res.status(400).json({ error: "bad_request", message: "prompt required" });
|
|
8708
8711
|
const m2 = /^(\d{2,4})x(\d{2,4})$/.exec(String(size));
|
|
@@ -8730,10 +8733,11 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8730
8733
|
kind: "image",
|
|
8731
8734
|
manifestPath: saved.manifestPath,
|
|
8732
8735
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8733
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8736
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8737
|
+
uid: uid2
|
|
8734
8738
|
});
|
|
8735
8739
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
8736
|
-
await recordConsumption(
|
|
8740
|
+
await recordConsumption(uid2, { requests: 1, image: Math.max(1, buffers.length) }, idemKey);
|
|
8737
8741
|
return res.json({ success: true, data: { url: saved.manifestPath, jobId: manifest.trace } });
|
|
8738
8742
|
} catch (error) {
|
|
8739
8743
|
console.error("[Image API] Error:", error);
|
|
@@ -8779,14 +8783,15 @@ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
|
8779
8783
|
saved = await saveArtifacts({ root: process.cwd(), kind: "video" }, items, manifest);
|
|
8780
8784
|
}
|
|
8781
8785
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
8782
|
-
await recordConsumption(
|
|
8786
|
+
await recordConsumption(uid, { requests: 1, video: 1 }, idemKey);
|
|
8783
8787
|
jobIndex.set(String(manifest.trace), {
|
|
8784
8788
|
id: String(manifest.trace),
|
|
8785
8789
|
status: "completed",
|
|
8786
8790
|
kind: "video",
|
|
8787
8791
|
manifestPath: saved.manifestPath,
|
|
8788
8792
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8789
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8793
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8794
|
+
uid
|
|
8790
8795
|
});
|
|
8791
8796
|
return res.json({ success: true, data: { url: saved.manifestPath, jobId: manifest.trace } });
|
|
8792
8797
|
} catch (error) {
|
|
@@ -8799,10 +8804,15 @@ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
|
8799
8804
|
});
|
|
8800
8805
|
app.get("/api/v1/jobs/:id", async (req, res) => {
|
|
8801
8806
|
try {
|
|
8807
|
+
const auth = req.headers.authorization;
|
|
8808
|
+
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8809
|
+
const idToken = auth.substring("Bearer ".length).trim();
|
|
8810
|
+
const decoded = await decodeFirebaseToken(idToken).catch(() => null);
|
|
8811
|
+
const uid2 = decoded?.uid || decoded?.sub || "current";
|
|
8802
8812
|
const id = String(req.params.id || "").trim();
|
|
8803
8813
|
if (!id) return res.status(400).json({ error: "bad_request", message: "id required" });
|
|
8804
8814
|
const info = jobIndex.get(id);
|
|
8805
|
-
if (!info) return res.status(404).json({ error: "not_found", message: "job not found" });
|
|
8815
|
+
if (!info || info.uid && info.uid !== uid2) return res.status(404).json({ error: "not_found", message: "job not found" });
|
|
8806
8816
|
let manifest;
|
|
8807
8817
|
if (info.manifestPath) {
|
|
8808
8818
|
try {
|
|
@@ -8981,14 +8991,14 @@ function calcNextReset() {
|
|
|
8981
8991
|
d.setUTCHours(0, 0, 0, 0);
|
|
8982
8992
|
return d.toISOString();
|
|
8983
8993
|
}
|
|
8984
|
-
async function recordConsumption(
|
|
8994
|
+
async function recordConsumption(uid2, consumption, idempotencyKey) {
|
|
8985
8995
|
const db = await getFirestoreSafe();
|
|
8986
8996
|
if (!db) return;
|
|
8987
|
-
const docPath = `projects/default/usage/${
|
|
8997
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
8988
8998
|
const usageRef = db.doc(docPath);
|
|
8989
8999
|
const nowISO = (/* @__PURE__ */ new Date()).toISOString();
|
|
8990
9000
|
if (idempotencyKey) {
|
|
8991
|
-
const idemRef = db.doc(`projects/default/usage/${
|
|
9001
|
+
const idemRef = db.doc(`projects/default/usage/${uid2}/consumptions/${idempotencyKey}`);
|
|
8992
9002
|
const idemSnap = await idemRef.get();
|
|
8993
9003
|
if (idemSnap.exists) return;
|
|
8994
9004
|
await idemRef.set({ createdAt: nowISO, consumption });
|
|
@@ -9022,8 +9032,8 @@ app.get("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
9022
9032
|
const auth = req.headers.authorization;
|
|
9023
9033
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
9024
9034
|
const db = await getFirestoreSafe();
|
|
9025
|
-
const
|
|
9026
|
-
const docPath = `projects/default/usage/${
|
|
9035
|
+
const uid2 = "current";
|
|
9036
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
9027
9037
|
let data = null;
|
|
9028
9038
|
if (db) {
|
|
9029
9039
|
const snap = await db.doc(docPath).get();
|
|
@@ -9042,7 +9052,7 @@ app.get("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
9042
9052
|
};
|
|
9043
9053
|
await db.doc(docPath).set(data);
|
|
9044
9054
|
}
|
|
9045
|
-
const historySnap = await db.collection(`projects/default/usage/${
|
|
9055
|
+
const historySnap = await db.collection(`projects/default/usage/${uid2}/consumptions`).orderBy("createdAt", "desc").limit(20).get();
|
|
9046
9056
|
const history = historySnap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
9047
9057
|
data.history = history;
|
|
9048
9058
|
} else {
|
|
@@ -9070,11 +9080,11 @@ app.post("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
9070
9080
|
const { consumption } = req.body || {};
|
|
9071
9081
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
9072
9082
|
const db = await getFirestoreSafe();
|
|
9073
|
-
const
|
|
9074
|
-
const docPath = `projects/default/usage/${
|
|
9083
|
+
const uid2 = "current";
|
|
9084
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
9075
9085
|
let data = null;
|
|
9076
9086
|
if (db) {
|
|
9077
|
-
await recordConsumption(
|
|
9087
|
+
await recordConsumption(uid2, consumption || {}, idemKey);
|
|
9078
9088
|
const snap = await db.doc(docPath).get();
|
|
9079
9089
|
data = snap.exists ? snap.data() : { ok: true };
|
|
9080
9090
|
} else {
|