Trudy commited on
Commit
e1a68dd
·
1 Parent(s): bf39892

cycled API key + shortened docker files

Browse files
Files changed (5) hide show
  1. .gitignore +3 -0
  2. Dockerfile +0 -8
  3. docker-compose.yml +1 -2
  4. pages/api/generate.js +15 -4
  5. pages/index.js +91 -5
.gitignore CHANGED
@@ -39,3 +39,6 @@ yarn-error.log*
39
  # typescript
40
  *.tsbuildinfo
41
  next-env.d.ts
 
 
 
 
39
  # typescript
40
  *.tsbuildinfo
41
  next-env.d.ts
42
+
43
+ # app.yaml (Google Cloud deployment config)
44
+ app.yaml
Dockerfile CHANGED
@@ -32,10 +32,6 @@ RUN if [ -f next.config.js ]; then \
32
  echo "/** @type {import('next').NextConfig} */\nconst nextConfig = {\n output: 'standalone'\n};\n\nmodule.exports = nextConfig;" > next.config.js; \
33
  fi
34
 
35
- # Set environment variables from app.yaml
36
- ENV GEMINI_API_KEY="AIzaSyBZqvjHhfLn_XzGYkNCWRA0PNQ6r2CUy_Y"
37
- ENV GCP_CLIENT_EMAIL="[email protected]"
38
-
39
  # Build the application
40
  RUN npm run build
41
 
@@ -55,10 +51,6 @@ COPY --from=builder --chown=nextjs:nodejs /app/public ./public
55
  COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
56
  COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
57
 
58
- # Set environment variables from app.yaml
59
- ENV GEMINI_API_KEY="AIzaSyBZqvjHhfLn_XzGYkNCWRA0PNQ6r2CUy_Y"
60
- ENV GCP_CLIENT_EMAIL="[email protected]"
61
-
62
  # Switch to non-root user
63
  USER nextjs
64
 
 
32
  echo "/** @type {import('next').NextConfig} */\nconst nextConfig = {\n output: 'standalone'\n};\n\nmodule.exports = nextConfig;" > next.config.js; \
33
  fi
34
 
 
 
 
 
35
  # Build the application
36
  RUN npm run build
37
 
 
51
  COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
52
  COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
53
 
 
 
 
 
54
  # Switch to non-root user
55
  USER nextjs
56
 
docker-compose.yml CHANGED
@@ -9,8 +9,7 @@ services:
9
  - "3000:3000"
10
  environment:
11
  - NODE_ENV=production
12
- - GEMINI_API_KEY=${GEMINI_API_KEY:-AIzaSyBZqvjHhfLn_XzGYkNCWRA0PNQ6r2CUy_Y}
13
- - GCP_CLIENT_EMAIL=${GCP_CLIENT_EMAIL:[email protected]}
14
  restart: unless-stopped
15
  healthcheck:
16
  test: ["CMD", "wget", "--spider", "http://localhost:3000"]
 
9
  - "3000:3000"
10
  environment:
11
  - NODE_ENV=production
12
+ - GEMINI_API_KEY=${GEMINI_API_KEY}
 
13
  restart: unless-stopped
14
  healthcheck:
15
  test: ["CMD", "wget", "--spider", "http://localhost:3000"]
pages/api/generate.js CHANGED
@@ -6,22 +6,33 @@ export default async function handler(req, res) {
6
  return res.status(405).json({ error: 'Method not allowed' });
7
  }
8
 
9
- // Get prompt and drawing from request body
10
- const { prompt, drawingData } = req.body;
11
 
12
  // Log request details (truncating drawingData for brevity)
13
  console.log("API Request:", {
14
  prompt,
15
  hasDrawingData: !!drawingData,
16
  drawingDataLength: drawingData ? drawingData.length : 0,
17
- drawingDataSample: drawingData ? `${drawingData.substring(0, 50)}... (truncated)` : null
 
18
  });
19
 
20
  if (!prompt) {
21
  return res.status(400).json({ error: 'Prompt is required' });
22
  }
23
 
24
- const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
 
 
 
 
 
 
 
 
 
 
25
 
26
  // Set responseModalities to include "Image" so the model can generate an image
27
  const model = genAI.getGenerativeModel({
 
6
  return res.status(405).json({ error: 'Method not allowed' });
7
  }
8
 
9
+ // Get prompt, drawing, and custom API key from request body
10
+ const { prompt, drawingData, customApiKey } = req.body;
11
 
12
  // Log request details (truncating drawingData for brevity)
13
  console.log("API Request:", {
14
  prompt,
15
  hasDrawingData: !!drawingData,
16
  drawingDataLength: drawingData ? drawingData.length : 0,
17
+ drawingDataSample: drawingData ? `${drawingData.substring(0, 50)}... (truncated)` : null,
18
+ hasCustomApiKey: !!customApiKey
19
  });
20
 
21
  if (!prompt) {
22
  return res.status(400).json({ error: 'Prompt is required' });
23
  }
24
 
25
+ // Use custom API key if provided, otherwise use the one from environment variables
26
+ const apiKey = customApiKey || process.env.GEMINI_API_KEY;
27
+
28
+ if (!apiKey) {
29
+ return res.status(400).json({
30
+ success: false,
31
+ error: 'No API key available. Please provide a valid Gemini API key.'
32
+ });
33
+ }
34
+
35
+ const genAI = new GoogleGenerativeAI(apiKey);
36
 
37
  // Set responseModalities to include "Image" so the model can generate an image
38
  const model = genAI.getGenerativeModel({
pages/index.js CHANGED
@@ -1,5 +1,5 @@
1
  import { useState, useRef, useEffect } from "react";
2
- import { SendHorizontal, LoaderCircle, Trash2 } from "lucide-react";
3
  import Head from "next/head";
4
 
5
  export default function Home() {
@@ -11,6 +11,9 @@ export default function Home() {
11
  const [prompt, setPrompt] = useState("");
12
  const [generatedImage, setGeneratedImage] = useState(null);
13
  const [isLoading, setIsLoading] = useState(false);
 
 
 
14
 
15
  // Load background image when generatedImage changes
16
  useEffect(() => {
@@ -173,13 +176,15 @@ export default function Home() {
173
  // Create request payload
174
  const requestPayload = {
175
  prompt,
176
- drawingData
 
177
  };
178
 
179
  // Log the request payload (without the full image data for brevity)
180
  console.log("Request payload:", {
181
  ...requestPayload,
182
- drawingData: drawingData ? `${drawingData.substring(0, 50)}... (truncated)` : null
 
183
  });
184
 
185
  // Send the drawing and prompt to the API
@@ -204,16 +209,41 @@ export default function Home() {
204
  setGeneratedImage(imageUrl);
205
  } else {
206
  console.error("Failed to generate image:", data.error);
207
- alert("Failed to generate image. Please try again.");
 
 
 
 
 
 
 
 
 
 
 
 
208
  }
209
  } catch (error) {
210
  console.error("Error submitting drawing:", error);
211
- alert("An error occurred. Please try again.");
 
212
  } finally {
213
  setIsLoading(false);
214
  }
215
  };
216
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  // Add touch event prevention function
218
  useEffect(() => {
219
  // Function to prevent default touch behavior on canvas
@@ -343,6 +373,62 @@ export default function Home() {
343
  </div>
344
  </form>
345
  </main>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  </div>
347
  </>
348
  );
 
1
  import { useState, useRef, useEffect } from "react";
2
+ import { SendHorizontal, LoaderCircle, Trash2, X } from "lucide-react";
3
  import Head from "next/head";
4
 
5
  export default function Home() {
 
11
  const [prompt, setPrompt] = useState("");
12
  const [generatedImage, setGeneratedImage] = useState(null);
13
  const [isLoading, setIsLoading] = useState(false);
14
+ const [showErrorModal, setShowErrorModal] = useState(false);
15
+ const [errorMessage, setErrorMessage] = useState("");
16
+ const [customApiKey, setCustomApiKey] = useState("");
17
 
18
  // Load background image when generatedImage changes
19
  useEffect(() => {
 
176
  // Create request payload
177
  const requestPayload = {
178
  prompt,
179
+ drawingData,
180
+ customApiKey // Add the custom API key to the payload if it exists
181
  };
182
 
183
  // Log the request payload (without the full image data for brevity)
184
  console.log("Request payload:", {
185
  ...requestPayload,
186
+ drawingData: drawingData ? `${drawingData.substring(0, 50)}... (truncated)` : null,
187
+ customApiKey: customApiKey ? "**********" : null
188
  });
189
 
190
  // Send the drawing and prompt to the API
 
209
  setGeneratedImage(imageUrl);
210
  } else {
211
  console.error("Failed to generate image:", data.error);
212
+
213
+ // Check if the error is related to quota exhaustion or other API errors
214
+ if (data.error && (
215
+ data.error.includes("Resource has been exhausted") ||
216
+ data.error.includes("quota") ||
217
+ response.status === 429 ||
218
+ response.status === 500
219
+ )) {
220
+ setErrorMessage(data.error);
221
+ setShowErrorModal(true);
222
+ } else {
223
+ alert("Failed to generate image. Please try again.");
224
+ }
225
  }
226
  } catch (error) {
227
  console.error("Error submitting drawing:", error);
228
+ setErrorMessage(error.message || "An unexpected error occurred.");
229
+ setShowErrorModal(true);
230
  } finally {
231
  setIsLoading(false);
232
  }
233
  };
234
 
235
+ // Close the error modal
236
+ const closeErrorModal = () => {
237
+ setShowErrorModal(false);
238
+ };
239
+
240
+ // Handle the custom API key submission
241
+ const handleApiKeySubmit = (e) => {
242
+ e.preventDefault();
243
+ setShowErrorModal(false);
244
+ // Will use the customApiKey state in the next API call
245
+ };
246
+
247
  // Add touch event prevention function
248
  useEffect(() => {
249
  // Function to prevent default touch behavior on canvas
 
373
  </div>
374
  </form>
375
  </main>
376
+
377
+ {/* Error Modal */}
378
+ {showErrorModal && (
379
+ <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
380
+ <div className="bg-white rounded-lg shadow-xl max-w-md w-full p-6">
381
+ <div className="flex justify-between items-start mb-4">
382
+ <h3 className="text-xl font-bold text-gray-700">Failed to generate</h3>
383
+ <button
384
+ onClick={closeErrorModal}
385
+ className="text-gray-400 hover:text-gray-500"
386
+ >
387
+ <X className="w-5 h-5" />
388
+ </button>
389
+ </div>
390
+
391
+
392
+ <form onSubmit={handleApiKeySubmit} className="mb-4">
393
+ <label className="block text-sm font-medium text-gray-600 mb-2">
394
+ This space is pretty popular... add your own Gemini API key from <a
395
+ href="https://ai.google.dev/"
396
+ target="_blank"
397
+ rel="noopener noreferrer"
398
+ className="underline"
399
+ >
400
+ Google AI Studio
401
+ </a>:
402
+
403
+
404
+ </label>
405
+ <input
406
+ type="text"
407
+ value={customApiKey}
408
+ onChange={(e) => setCustomApiKey(e.target.value)}
409
+ placeholder="API Key..."
410
+ className="w-full p-3 border border-gray-300 rounded mb-4 font-mono text-sm"
411
+ required
412
+ />
413
+ <div className="flex justify-end gap-2">
414
+ <button
415
+ type="button"
416
+ onClick={closeErrorModal}
417
+ className="px-4 py-2 text-sm border border-gray-300 rounded hover:bg-gray-50"
418
+ >
419
+ Cancel
420
+ </button>
421
+ <button
422
+ type="submit"
423
+ className="px-4 py-2 text-sm bg-black text-white rounded hover:bg-gray-800"
424
+ >
425
+ Use My API Key
426
+ </button>
427
+ </div>
428
+ </form>
429
+ </div>
430
+ </div>
431
+ )}
432
  </div>
433
  </>
434
  );