From 2fafd17cdb723a6ba1ae3b76d4298584c2c5e67a Mon Sep 17 00:00:00 2001 From: zramsay Date: Fri, 20 Dec 2024 16:18:49 -0500 Subject: [PATCH] sweet --- src/app/api/flux/route.ts | 55 ++++++++++ src/app/page.tsx | 211 +++++++++++------------------------- src/services/fluxService.ts | 53 +++++++-- 3 files changed, 164 insertions(+), 155 deletions(-) create mode 100644 src/app/api/flux/route.ts diff --git a/src/app/api/flux/route.ts b/src/app/api/flux/route.ts new file mode 100644 index 0000000..a7d737d --- /dev/null +++ b/src/app/api/flux/route.ts @@ -0,0 +1,55 @@ +import { NextRequest, NextResponse } from 'next/server' +import { fal } from "@fal-ai/client" + +if (!process.env.FAL_AI_KEY) { + throw new Error('FAL_AI_KEY is not configured in environment variables') +} + +// Configure fal client +fal.config({ + credentials: process.env.FAL_AI_KEY +}) + +export async function POST(req: NextRequest): Promise { + try { + const { prompt, modelId } = await req.json() + + if (!prompt || !modelId) { + return NextResponse.json( + { error: 'Prompt and modelId are required' }, + { status: 400 } + ) + } + + console.log('Generating with Flux model:', modelId) + console.log('Prompt:', prompt) + + const result = await fal.subscribe(modelId, { + input: { + prompt: prompt, + }, + logs: true, + onQueueUpdate: (update) => { + if (update.status === "IN_PROGRESS") { + console.log('Generation progress:', update.logs.map((log) => log.message)) + } + }, + }) + + console.log('Flux generation result:', result) + + if (!result.data?.images?.[0]?.url) { + throw new Error('No image URL in response') + } + + return NextResponse.json({ imageUrl: result.data.images[0].url }) + } catch (error) { + console.error('Flux generation error:', error) + return NextResponse.json( + { error: error instanceof Error ? error.message : 'Failed to generate image' }, + { status: 500 } + ) + } +} + +export const dynamic = 'force-dynamic' diff --git a/src/app/page.tsx b/src/app/page.tsx index 45cadd2..21a1d98 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -3,12 +3,7 @@ import React, { useState } from 'react' import WalletHeader from '../components/WalletHeader' import AIServiceCard from '../components/AIServiceCard' -import TextGenerationCard from '../components/TextGenerationCard' -import { generateWithFlux, FluxGenerationResult } from '../services/fluxService' -import { generateWithAdobe, AdobeGenerationResult } from '../services/adobeService' -import { generateWithGrok, GrokGenerationResult } from '../services/grokService' -import { generateWithOllama, OllamaGenerationResult } from '../services/ollamaService' -import { generateWithGemini, GeminiGenerationResult } from '../services/geminiService' +import { generateWithFlux, FluxGenerationResult, FLUX_MODELS } from '../services/fluxService' import { processMTMPayment } from '../services/paymentService' interface WalletState { @@ -48,100 +43,26 @@ const Page: React.FC = (): React.ReactElement => { } } - const handleFluxGeneration = async (prompt: string): Promise => { - if (!walletState.connected || !walletState.publicKey || !window.solflare) { - return { error: 'Wallet not connected' } + const handleFluxGeneration = (modelId: string, cost: number) => { + return async (prompt: string): Promise => { + if (!walletState.connected || !walletState.publicKey || !window.solflare) { + return { error: 'Wallet not connected' } + } + + // Process payment first + const paymentResult = await processMTMPayment( + walletState.publicKey, + cost, + window.solflare + ) + + if (!paymentResult.success) { + return { error: paymentResult.error } + } + + // Then generate image with specified model + return generateWithFlux(prompt, modelId) } - - // First process payment - const paymentResult = await processMTMPayment( - walletState.publicKey, - 1, // 1 MTM token - window.solflare - ) - - if (!paymentResult.success) { - return { error: paymentResult.error } - } - - // Then generate image - return generateWithFlux(prompt) - } - - const handleGrokGeneration = async (prompt: string): Promise => { - if (!walletState.connected || !walletState.publicKey || !window.solflare) { - return { error: 'Wallet not connected' } - } - - const paymentResult = await processMTMPayment( - walletState.publicKey, - 5, // 5 MTM tokens for Grok premium service - window.solflare - ) - - if (!paymentResult.success) { - return { error: paymentResult.error } - } - - return generateWithGrok(prompt) - } - -const handleAdobeGeneration = async (prompt: string): Promise => { - if (!walletState.connected || !walletState.publicKey || !window.solflare) { - return { error: 'Wallet not connected' } - } - - const paymentResult = await processMTMPayment( - walletState.publicKey, - 4, // 4 MTM tokens for Adobe premium service - window.solflare - ) - - if (!paymentResult.success) { - return { error: paymentResult.error } - } - - return generateWithAdobe(prompt) - } - - const handleOllamaGeneration = async (prompt: string): Promise => { - if (!walletState.connected || !walletState.publicKey || !window.solflare) { - return { error: 'Wallet not connected' } - } - - // First process payment - const paymentResult = await processMTMPayment( - walletState.publicKey, - 2, // 2 MTM tokens for text generation - window.solflare - ) - - if (!paymentResult.success) { - return { error: paymentResult.error } - } - - // Then generate text - return generateWithOllama(prompt) - } - -const handleGeminiGeneration = async (prompt: string): Promise => { - if (!walletState.connected || !walletState.publicKey || !window.solflare) { - return { error: 'Wallet not connected' } - } - - // First process payment - const paymentResult = await processMTMPayment( - walletState.publicKey, - 3, // 3 MTM tokens for Gemini - window.solflare - ) - - if (!paymentResult.success) { - return { error: paymentResult.error } - } - - // Then generate text - return generateWithGemini(prompt) } return ( @@ -150,10 +71,10 @@ const handleGeminiGeneration = async (prompt: string): Promise

- Mark's Meme Market + AI Image Generator

- Generate memes using various AI models + Generate amazing images using different Flux AI models

- {/* AI Services Grid */} -
- + {/* Flux Models Grid */} +
+ {FLUX_MODELS.map((model) => ( + + ))} - - - {/* - */} - - - {/* for another app - - - */} + {/* Coming Soon Card */} +
+
+
+
+

+ Coming Soon +

+

+ New AI model integration in development. Stay tuned for more amazing features! +

+
+ Future Release +
+
+ +
+ +
+
+
{/* Info Section */}

- Powered by Mark • Requires MTM tokens + Powered by Flux AI • Different models have different costs and capabilities +

+

+ Each generation requires MTM tokens • Higher quality models cost more tokens

diff --git a/src/services/fluxService.ts b/src/services/fluxService.ts index f08f12b..ae6f0f4 100644 --- a/src/services/fluxService.ts +++ b/src/services/fluxService.ts @@ -1,18 +1,51 @@ -import { fal } from "@fal-ai/client" - export interface FluxGenerationResult { imageUrl?: string error?: string } -export async function generateWithFlux(prompt: string): Promise { +export interface FluxModelConfig { + modelId: string + name: string + description: string + cost: number +} + +// Available Flux/fal-ai models +export const FLUX_MODELS: FluxModelConfig[] = [ + { + modelId: "fal-ai/flux/schnell", + name: "Schnell", + description: "Fast meme generator", + cost: 5 // update to 500 MTM + }, + { + modelId: "fal-ai/recraft-v3", + name: "Recraft", + description: "Advanced meme generator", + cost: 6 // update to ? + }, + { + modelId: "fal-ai/stable-diffusion-v35-large", + name: "Marquee", + description: "Best meme generator", + cost: 10 //update to more + } +] + +export async function generateWithFlux( + prompt: string, + modelId: string +): Promise { try { - const response = await fetch('/api/generate', { + const response = await fetch('/api/flux', { method: 'POST', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ prompt }), + body: JSON.stringify({ + prompt, + modelId + }), }) if (!response.ok) { @@ -21,16 +54,16 @@ export async function generateWithFlux(prompt: string): Promise