feat: change onRequest to onCall

This commit is contained in:
Zitao Xiong
2023-12-12 14:55:04 +08:00
parent fde1898f2d
commit 78000d3cd7
3 changed files with 88 additions and 102 deletions

View File

@@ -1,11 +1,84 @@
import { CloudFunctionsTypeWithUid } from "./handlersType";
import { getStorage } from "firebase-admin/storage";
import { nanoid } from "nanoid";
import got from "got-cjs";
import { OpenAI } from "openai";
const openai = new OpenAI({
apiKey: "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",
});
export const generateImage: CloudFunctionsTypeWithUid["generateImage"] = async (
prompt,
uid,
uid
) => {
return {
url: "hello",
finalPrompt: "world" + prompt,
};
if (prompt == null || prompt.length === 0) {
throw new Error("prompt is required");
}
const generateImageResponse = await openai.images.generate({
model: "dall-e-3",
prompt: prompt,
n: 1,
size: "1792x1024",
});
const imageUrl = generateImageResponse.data[0].url;
const revised_prompt = generateImageResponse.data[0].revised_prompt;
const bucket = getStorage().bucket("storytime-ai-images");
// response.send(generateImageResponse);
// Validate imageUrl
if (!imageUrl) {
throw new Error("No image URL provided.");
}
try {
const response = await fetch(imageUrl);
// Check if image fetch was successful
if (!response.ok)
throw new Error(`Unable to fetch image: ${response.statusText}`);
// Create a reference in Firebase Storage
const fileName = `images/${Date.now()}-${nanoid()}.png`;
const file = bucket.file(fileName);
const writeStream = file.createWriteStream();
return new Promise((resolve, reject) => {
got
.stream(imageUrl)
.on("error", (error) => {
throw new Error(`Error downloading image: ${error.message}`);
})
.pipe(writeStream)
.on("finish", () => {
file
.getSignedUrl({
action: "read",
expires: "03-09-2491", // You can provide an expiry date for the URL
})
.then((signedUrls) => {
// signedUrls[0] contains the file's public URL
resolve({
image_url: signedUrls[0],
revised_prompt: revised_prompt ?? "",
});
})
.catch((error) => {
reject(new Error(`Error getting signed URL: ${error.message}`));
});
})
.on("error", (error) => {
reject(
new Error(
`Error uploading image to Firebase Storage: ${error.message}`
)
);
});
});
} catch (error) {
throw new Error(`Error downloading image: ${error}`);
}
};

View File

@@ -7,27 +7,27 @@
* See a full list of supported triggers at https://firebase.google.com/docs/functions
*/
import { onCall, onRequest, Request, HttpsError } from "firebase-functions/v2/https";
import {HttpsError, onCall} from "firebase-functions/v2/https";
import * as logger from "firebase-functions/logger";
import { OpenAI } from "openai";
import * as express from "express";
import {generateImage} from './generateImage'
import admin from "firebase-admin";
import { getStorage } from "firebase-admin/storage";
import got from "got-cjs";
import { nanoid } from "nanoid";
import adminKey from "./credentials/admin-key.json";
import {CloudFunctionsTypeWithUid} from "./handlersType";
admin.initializeApp({
credential: admin.credential.cert(adminKey as any),
});
// Start writing functions
// https://firebase.google.com/docs/functions/typescript
const handlers: CloudFunctionsTypeWithUid = {
generateImage,
};
export const execute = onCall({ region: "asia-east1" }, (request) => {
export const execute = onCall({region: "asia-east1", memory: "8GiB", invoker: "public"}, async ({data, auth}) => {
const uid = auth?.uid;
logger.info(data, { context: uid });
logger.info(data, {context: uid});
if (!(data.type in handlers)) {
throw new HttpsError(
"invalid-argument",
@@ -36,91 +36,4 @@ export const execute = onCall({ region: "asia-east1" }, (request) => {
}
return await (handlers as any)[data.type](...data.args, uid);
});
const openai = new OpenAI({
apiKey: "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",
});
const generateImage = async (req: Request, resp: express.Response) => {
const prompt = req.body.prompt;
if (prompt == null || prompt.length === 0) {
throw new Error("prompt is required");
}
const generateImageResponse = await openai.images.generate({
model: "dall-e-3",
prompt: prompt,
n: 1,
size: "1792x1024",
});
const imageUrl = generateImageResponse.data[0].url;
const revised_prompt = generateImageResponse.data[0].revised_prompt;
const bucket = getStorage().bucket("storytime-ai-images");
// response.send(generateImageResponse);
// Validate imageUrl
if (!imageUrl) {
resp.status(400).send("No image URL provided.");
return;
}
try {
const response = await fetch(imageUrl);
// Check if image fetch was successful
if (!response.ok)
throw new Error(`Unable to fetch image: ${response.statusText}`);
// Create a reference in Firebase Storage
const fileName = `images/${Date.now()}-${nanoid()}.png`;
const file = bucket.file(fileName);
const writeStream = file.createWriteStream();
got
.stream(imageUrl)
.on("error", (error) => {
resp.status(500).send(`Error downloading image: ${error.message}`);
})
.pipe(writeStream)
.on("finish", () => {
file
.getSignedUrl({
action: "read",
expires: "03-09-2491", // You can provide an expiry date for the URL
})
.then((signedUrls) => {
// signedUrls[0] contains the file's public URL
resp.status(200).send({ image_url: signedUrls[0], revised_prompt });
})
.catch((error) => {
resp.status(500).send(`Error getting signed URL: ${error.message}`);
});
})
.on("error", (error) => {
resp
.status(500)
.send(`Error uploading image to Firebase Storage: ${error.message}`);
});
} catch (error) {
resp.status(500).send(`Error downloading image: ${error}`);
}
};
export const request = onRequest(
{
memory: "4GiB",
region: "asia-east1",
invoker: "public",
minInstances: 1,
timeoutSeconds: 3600,
},
(request, response) => {
if (request.path === "/generate-image") {
generateImage(request, response);
} else {
response.status(200).send({
routes: ["/generate-image"],
});
}
}
);