/dream api: Upload StableDiffusion image to Firestore
This commit is contained in:
		
							parent
							
								
									14c008234a
								
							
						
					
					
						commit
						b33a301e44
					
				| 
						 | 
				
			
			@ -56,9 +56,10 @@
 | 
			
		|||
    "react-expanding-textarea": "2.3.5",
 | 
			
		||||
    "react-hot-toast": "2.2.0",
 | 
			
		||||
    "react-instantsearch-hooks-web": "6.24.1",
 | 
			
		||||
    "react-masonry-css": "1.0.16",
 | 
			
		||||
    "react-query": "3.39.0",
 | 
			
		||||
    "react-twitter-embed": "4.0.4",
 | 
			
		||||
    "react-masonry-css": "1.0.16",
 | 
			
		||||
    "stability-client": "1.5.0",
 | 
			
		||||
    "string-similarity": "^4.0.4",
 | 
			
		||||
    "tippy.js": "6.3.7"
 | 
			
		||||
  },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										103
									
								
								web/pages/api/v0/dream.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								web/pages/api/v0/dream.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,103 @@
 | 
			
		|||
import { getDownloadURL, ref, uploadBytesResumable } from 'firebase/storage'
 | 
			
		||||
import { nanoid } from 'nanoid'
 | 
			
		||||
import { NextApiRequest, NextApiResponse } from 'next'
 | 
			
		||||
import { generateAsync } from 'stability-client'
 | 
			
		||||
import { storage } from 'web/lib/firebase/init'
 | 
			
		||||
import {
 | 
			
		||||
  CORS_ORIGIN_MANIFOLD,
 | 
			
		||||
  CORS_ORIGIN_LOCALHOST,
 | 
			
		||||
} from 'common/envs/constants'
 | 
			
		||||
import { applyCorsHeaders } from 'web/lib/api/cors'
 | 
			
		||||
 | 
			
		||||
export const config = { api: { bodyParser: true } }
 | 
			
		||||
 | 
			
		||||
// Highly experimental. Proxy for https://github.com/vpzomtrrfrt/stability-client
 | 
			
		||||
export default async function route(req: NextApiRequest, res: NextApiResponse) {
 | 
			
		||||
  await applyCorsHeaders(req, res, {
 | 
			
		||||
    origin: [CORS_ORIGIN_MANIFOLD, CORS_ORIGIN_LOCALHOST],
 | 
			
		||||
    methods: 'POST',
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const body = JSON.parse(req.body)
 | 
			
		||||
  // Check that prompt and apiKey are included in the body
 | 
			
		||||
  if (!body.prompt) {
 | 
			
		||||
    res.status(400).json({ message: 'Missing prompt' })
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  if (!body.apiKey) {
 | 
			
		||||
    res.status(400).json({ message: 'Missing apiKey' })
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  /** Optional params:
 | 
			
		||||
  outDir: string
 | 
			
		||||
  debug: boolean
 | 
			
		||||
  requestId: string
 | 
			
		||||
  samples: number
 | 
			
		||||
  engine: string
 | 
			
		||||
  host: string
 | 
			
		||||
  seed: number
 | 
			
		||||
  width: number
 | 
			
		||||
  height: number
 | 
			
		||||
  diffusion: keyof typeof diffusionMap
 | 
			
		||||
  steps: number
 | 
			
		||||
  cfgScale: number
 | 
			
		||||
  noStore: boolean
 | 
			
		||||
  imagePrompt: {mime: string; content: Buffer} | null
 | 
			
		||||
  stepSchedule: {start?: number; end?: number}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
 | 
			
		||||
    // @ts-ignore
 | 
			
		||||
    const { dreamResponse, images } = await generateAsync({
 | 
			
		||||
      ...body,
 | 
			
		||||
      // Don't actually write to disk, because we're going to upload it to Firestore
 | 
			
		||||
      noStore: true,
 | 
			
		||||
    })
 | 
			
		||||
    const buffer: Buffer = images[0].buffer
 | 
			
		||||
    const url = await upload(buffer)
 | 
			
		||||
 | 
			
		||||
    res.status(200).json({ url })
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    res.status(500).json({ message: `Error running code: ${e}` })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Loosely copied from web/lib/firebase/storage.ts
 | 
			
		||||
const ONE_YEAR_SECS = 60 * 60 * 24 * 365
 | 
			
		||||
 | 
			
		||||
async function upload(buffer: Buffer) {
 | 
			
		||||
  const filename = `${nanoid(10)}.png`
 | 
			
		||||
  const storageRef = ref(storage, `dream/${filename}`)
 | 
			
		||||
  const uploadTask = uploadBytesResumable(storageRef, buffer, {
 | 
			
		||||
    cacheControl: `public, max-age=${ONE_YEAR_SECS}`,
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  let resolvePromise: (url: string) => void
 | 
			
		||||
  let rejectPromise: (reason?: any) => void
 | 
			
		||||
 | 
			
		||||
  const promise = new Promise<string>((resolve, reject) => {
 | 
			
		||||
    resolvePromise = resolve
 | 
			
		||||
    rejectPromise = reject
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const unsubscribe = uploadTask.on(
 | 
			
		||||
    'state_changed',
 | 
			
		||||
    (_snapshot) => {},
 | 
			
		||||
    (error) => {
 | 
			
		||||
      // A full list of error codes is available at
 | 
			
		||||
      // https://firebase.google.com/docs/storage/web/handle-errors
 | 
			
		||||
      rejectPromise(error)
 | 
			
		||||
      unsubscribe()
 | 
			
		||||
    },
 | 
			
		||||
    () => {
 | 
			
		||||
      getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
 | 
			
		||||
        resolvePromise(downloadURL)
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      unsubscribe()
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  return await promise
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										72
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								yarn.lock
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -2380,6 +2380,18 @@
 | 
			
		|||
  resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
 | 
			
		||||
  integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
 | 
			
		||||
 | 
			
		||||
"@improbable-eng/grpc-web-node-http-transport@^0.15.0":
 | 
			
		||||
  version "0.15.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.15.0.tgz#5a064472ef43489cbd075a91fb831c2abeb09d68"
 | 
			
		||||
  integrity sha512-HLgJfVolGGpjc9DWPhmMmXJx8YGzkek7jcCFO1YYkSOoO81MWRZentPOd/JiKiZuU08wtc4BG+WNuGzsQB5jZA==
 | 
			
		||||
 | 
			
		||||
"@improbable-eng/grpc-web@^0.15.0":
 | 
			
		||||
  version "0.15.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web/-/grpc-web-0.15.0.tgz#3e47e9fdd90381a74abd4b7d26e67422a2a04bef"
 | 
			
		||||
  integrity sha512-ERft9/0/8CmYalqOVnJnpdDry28q+j+nAlFFARdjyxXDJ+Mhgv9+F600QC8BR9ygOfrXRlAk6CvST2j+JCpQPg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    browser-headers "^0.4.1"
 | 
			
		||||
 | 
			
		||||
"@jridgewell/gen-mapping@^0.1.0":
 | 
			
		||||
  version "0.1.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996"
 | 
			
		||||
| 
						 | 
				
			
			@ -4457,6 +4469,11 @@ broadcast-channel@^3.4.1:
 | 
			
		|||
    rimraf "3.0.2"
 | 
			
		||||
    unload "2.2.0"
 | 
			
		||||
 | 
			
		||||
browser-headers@^0.4.1:
 | 
			
		||||
  version "0.4.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/browser-headers/-/browser-headers-0.4.1.tgz#4308a7ad3b240f4203dbb45acedb38dc2d65dd02"
 | 
			
		||||
  integrity sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==
 | 
			
		||||
 | 
			
		||||
browser-image-compression@2.0.0:
 | 
			
		||||
  version "2.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/browser-image-compression/-/browser-image-compression-2.0.0.tgz#f421381a76d474d4da7dcd82810daf595b09bef6"
 | 
			
		||||
| 
						 | 
				
			
			@ -4854,6 +4871,11 @@ commander@^8.0.0, commander@^8.3.0:
 | 
			
		|||
  resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
 | 
			
		||||
  integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
 | 
			
		||||
 | 
			
		||||
commander@^9.4.0:
 | 
			
		||||
  version "9.4.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.0.tgz#bc4a40918fefe52e22450c111ecd6b7acce6f11c"
 | 
			
		||||
  integrity sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==
 | 
			
		||||
 | 
			
		||||
commondir@^1.0.1:
 | 
			
		||||
  version "1.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
 | 
			
		||||
| 
						 | 
				
			
			@ -5707,6 +5729,11 @@ dot-prop@^5.2.0:
 | 
			
		|||
  dependencies:
 | 
			
		||||
    is-obj "^2.0.0"
 | 
			
		||||
 | 
			
		||||
dotenv@^16.0.2:
 | 
			
		||||
  version "16.0.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.2.tgz#0b0f8652c016a3858ef795024508cddc4bffc5bf"
 | 
			
		||||
  integrity sha512-JvpYKUmzQhYoIFgK2MOnF3bciIZoItIIoryihy0rIA+H4Jy0FmgyKYAHCTN98P5ybGSJcIFbh6QKeJdtZd1qhA==
 | 
			
		||||
 | 
			
		||||
duplexer3@^0.1.4:
 | 
			
		||||
  version "0.1.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
 | 
			
		||||
| 
						 | 
				
			
			@ -6937,6 +6964,11 @@ google-p12-pem@^3.1.3:
 | 
			
		|||
  dependencies:
 | 
			
		||||
    node-forge "^1.3.1"
 | 
			
		||||
 | 
			
		||||
google-protobuf@^3.21.0:
 | 
			
		||||
  version "3.21.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.0.tgz#8dfa3fca16218618d373d414d3c1139e28034d6e"
 | 
			
		||||
  integrity sha512-byR7MBTK4tZ5PZEb+u5ZTzpt4SfrTxv5682MjPlHN16XeqgZE2/8HOIWeiXe8JKnT9OVbtBGhbq8mtvkK8cd5g==
 | 
			
		||||
 | 
			
		||||
got@^9.6.0:
 | 
			
		||||
  version "9.6.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
 | 
			
		||||
| 
						 | 
				
			
			@ -8634,6 +8666,11 @@ mkdirp@0.3.0:
 | 
			
		|||
  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e"
 | 
			
		||||
  integrity sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=
 | 
			
		||||
 | 
			
		||||
mkdirp@^1.0.4:
 | 
			
		||||
  version "1.0.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
 | 
			
		||||
  integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
 | 
			
		||||
 | 
			
		||||
module-alias@2.2.2:
 | 
			
		||||
  version "2.2.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.2.tgz#151cdcecc24e25739ff0aa6e51e1c5716974c0e0"
 | 
			
		||||
| 
						 | 
				
			
			@ -10706,6 +10743,13 @@ rxjs@^6.6.3:
 | 
			
		|||
  dependencies:
 | 
			
		||||
    tslib "^1.9.0"
 | 
			
		||||
 | 
			
		||||
rxjs@^7.5.2:
 | 
			
		||||
  version "7.5.7"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39"
 | 
			
		||||
  integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    tslib "^2.1.0"
 | 
			
		||||
 | 
			
		||||
rxjs@^7.5.4:
 | 
			
		||||
  version "7.5.5"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f"
 | 
			
		||||
| 
						 | 
				
			
			@ -11149,6 +11193,22 @@ sprintf-js@~1.0.2:
 | 
			
		|||
  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
 | 
			
		||||
  integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
 | 
			
		||||
 | 
			
		||||
stability-client@1.5.0:
 | 
			
		||||
  version "1.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/stability-client/-/stability-client-1.5.0.tgz#f221420a297c808f209c469a0df8fa2401f8f6ae"
 | 
			
		||||
  integrity sha512-hXuDK6QW/msf50pu8M4L1hTCYG4w5ZrhLgxirigUrSZEARupIPT88O7qz4YSmUbbp9nKlzS8UJ6NjYUH7qy45w==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@improbable-eng/grpc-web" "^0.15.0"
 | 
			
		||||
    "@improbable-eng/grpc-web-node-http-transport" "^0.15.0"
 | 
			
		||||
    commander "^9.4.0"
 | 
			
		||||
    dotenv "^16.0.2"
 | 
			
		||||
    google-protobuf "^3.21.0"
 | 
			
		||||
    mime "^3.0.0"
 | 
			
		||||
    mkdirp "^1.0.4"
 | 
			
		||||
    read-pkg-up "^7.0.1"
 | 
			
		||||
    typed-emitter "^2.1.0"
 | 
			
		||||
    uuid4 "^2.0.3"
 | 
			
		||||
 | 
			
		||||
stable@^0.1.8:
 | 
			
		||||
  version "0.1.8"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
 | 
			
		||||
| 
						 | 
				
			
			@ -11687,6 +11747,13 @@ type-is@~1.6.18:
 | 
			
		|||
    media-typer "0.3.0"
 | 
			
		||||
    mime-types "~2.1.24"
 | 
			
		||||
 | 
			
		||||
typed-emitter@^2.1.0:
 | 
			
		||||
  version "2.1.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/typed-emitter/-/typed-emitter-2.1.0.tgz#ca78e3d8ef1476f228f548d62e04e3d4d3fd77fb"
 | 
			
		||||
  integrity sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==
 | 
			
		||||
  optionalDependencies:
 | 
			
		||||
    rxjs "^7.5.2"
 | 
			
		||||
 | 
			
		||||
typedarray-to-buffer@^3.1.5:
 | 
			
		||||
  version "3.1.5"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
 | 
			
		||||
| 
						 | 
				
			
			@ -11985,6 +12052,11 @@ utils-merge@1.0.1:
 | 
			
		|||
  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
 | 
			
		||||
  integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
 | 
			
		||||
 | 
			
		||||
uuid4@^2.0.3:
 | 
			
		||||
  version "2.0.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/uuid4/-/uuid4-2.0.3.tgz#241e5dfe1704a79c52e2aa40e7e581a5e7b01ab4"
 | 
			
		||||
  integrity sha512-CTpAkEVXMNJl2ojgtpLXHgz23dh8z81u6/HEPiQFOvBc/c2pde6TVHmH4uwY0d/GLF3tb7+VDAj4+2eJaQSdZQ==
 | 
			
		||||
 | 
			
		||||
uuid@^8.0.0, uuid@^8.3.2:
 | 
			
		||||
  version "8.3.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user