Skip to content

Commit bfc9a4c

Browse files
authored
Merge pull request wishonia#135 from mikepsinn/2-10-34
Upload images
2 parents 0639059 + 1a673b6 commit bfc9a4c

File tree

5 files changed

+106
-97
lines changed

5 files changed

+106
-97
lines changed

app/researcher/researcherActions.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
writeArticle
1111
} from "@/lib/agents/researcher/researcher";
1212
import OpenAI from "openai";
13+
import {uploadImageToVercel} from "@/lib/imageUploader";
1314
const openai = new OpenAI({
1415
apiKey: process.env.OPENAI_API_KEY,
1516
})
@@ -98,13 +99,20 @@ export async function generateImage(topic: string, articleId: string) {
9899
})
99100

100101
const imageUrl = response.data[0].url
102+
if (!imageUrl) {
103+
throw new Error("Failed to generate image")
104+
}
105+
const imgPath = 'articles/' + articleId + '/featured-image'
106+
// get the buffer from the imageUrl
107+
const buffer = await fetch(imageUrl).then(res => res.arrayBuffer())
108+
const vercelUrl = await uploadImageToVercel(Buffer.from(buffer), imgPath)
101109
if (imageUrl && articleId) {
102110
await prisma.article.update({
103111
where: {
104112
id: articleId,
105113
},
106114
data: {
107-
featuredImage: imageUrl,
115+
featuredImage: vercelUrl,
108116
},
109117
})
110118
}

lib/imageLister.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { list } from "@vercel/blob";
2+
import { getRedisClient } from "@/lib/utils/redis"
3+
4+
export async function listImagesOnVercel() {
5+
const cacheKey = "vercelImages"
6+
const cachedImages = await getRedisClient().get(cacheKey)
7+
if (cachedImages) {
8+
return JSON.parse(cachedImages)
9+
}
10+
const listBlobResult = await list()
11+
const blobs = listBlobResult.blobs
12+
const urls = []
13+
for (const blob of blobs) {
14+
urls.push(blob.url)
15+
}
16+
await getRedisClient().set(cacheKey, JSON.stringify(urls))
17+
return urls
18+
}
19+
20+
export async function getVercelImageUrlFromPath(pathFromPublic: string) {
21+
const vercelImages = await listImagesOnVercel()
22+
for (const url of vercelImages) {
23+
if (url.includes(pathFromPublic)) {
24+
return url
25+
}
26+
}
27+
return null
28+
}

lib/imageUploader.ts

Lines changed: 1 addition & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
1-
import fs from "fs"
2-
import { list, put } from "@vercel/blob"
3-
4-
import {
5-
absPathFromPublic,
6-
getNonIgnoredFiles,
7-
relativePathFromPublic,
8-
} from "@/lib/fileHelper"
9-
import { getRedisClient } from "@/lib/utils/redis"
10-
1+
import { put } from "@vercel/blob"
112
export async function uploadImageToVercel(
123
buffer: Buffer,
134
pathFromPublic: string
@@ -34,85 +25,3 @@ function generateImageUrl(pathFromPublic: string) {
3425
}
3526
return `https://pcpfoetqkuq7jmso.public.blob.vercel-storage.com/${pathFromPublic}`
3627
}
37-
38-
export async function uploadPublicImagesToVercel() {
39-
const urls = []
40-
const imageFiles = getImagesFromPublic()
41-
for (const pathFromPublic of imageFiles) {
42-
let url = await uploadImageToVercelIfNecessary(pathFromPublic)
43-
urls.push(url)
44-
}
45-
return urls
46-
}
47-
48-
function getImagesFromPublic() {
49-
const allFiles = getNonIgnoredFiles(absPathFromPublic(""))
50-
const imageFiles = []
51-
for (const file of allFiles) {
52-
if (
53-
file.endsWith(".png") ||
54-
file.endsWith(".jpg") ||
55-
file.endsWith(".jpeg")
56-
) {
57-
imageFiles.push(file)
58-
}
59-
}
60-
return imageFiles.map(relativePathFromPublic)
61-
}
62-
63-
export async function uploadImageToVercelIfNecessary(pathFromPublic: string) {
64-
let url = await vercelImageExists(pathFromPublic)
65-
if (url) {
66-
console.log(`Image already uploaded: ${pathFromPublic}`)
67-
return
68-
}
69-
const buffer = fs.readFileSync(absPathFromPublic(pathFromPublic))
70-
url = await uploadImageToVercel(buffer, pathFromPublic)
71-
console.log(`Uploaded: ${url}`)
72-
return url
73-
}
74-
75-
export async function downloadAllBlobImages() {
76-
const listBlobResult = await list()
77-
const blobs = listBlobResult.blobs
78-
// Loop through array of blobs
79-
for (const blob of blobs) {
80-
const url = blob.url
81-
// Download image from url
82-
const response = await fetch(url)
83-
const buffer = await response.text()
84-
let pathname = relativePathFromPublic(blob.pathname)
85-
const absPath = absPathFromPublic(pathname)
86-
if (fs.existsSync(absPath)) {
87-
console.log(`Image already exists: ${absPath}`)
88-
continue
89-
}
90-
fs.writeFileSync(absPath, buffer)
91-
}
92-
}
93-
94-
export async function listImagesOnVercel() {
95-
const cacheKey = "vercelImages"
96-
const cachedImages = await getRedisClient().get(cacheKey)
97-
if (cachedImages) {
98-
return JSON.parse(cachedImages)
99-
}
100-
const listBlobResult = await list()
101-
const blobs = listBlobResult.blobs
102-
const urls = []
103-
for (const blob of blobs) {
104-
urls.push(blob.url)
105-
}
106-
await getRedisClient().set(cacheKey, JSON.stringify(urls))
107-
return urls
108-
}
109-
110-
export async function getVercelImageUrlFromPath(pathFromPublic: string) {
111-
const vercelImages = await listImagesOnVercel()
112-
for (const url of vercelImages) {
113-
if (url.includes(pathFromPublic)) {
114-
return url
115-
}
116-
}
117-
return null
118-
}

lib/images/localImages.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import fs from "fs";
2+
import { list } from "@vercel/blob";
3+
4+
5+
6+
import { absPathFromPublic, getNonIgnoredFiles, relativePathFromPublic } from "@/lib/fileHelper";
7+
import { uploadImageToVercel, vercelImageExists } from "@/lib/imageUploader";
8+
9+
10+
11+
12+
13+
export async function uploadImageToVercelIfNecessary(pathFromPublic: string) {
14+
let url = await vercelImageExists(pathFromPublic)
15+
if (url) {
16+
console.log(`Image already uploaded: ${pathFromPublic}`)
17+
return
18+
}
19+
const buffer = fs.readFileSync(absPathFromPublic(pathFromPublic))
20+
url = await uploadImageToVercel(buffer, pathFromPublic)
21+
console.log(`Uploaded: ${url}`)
22+
return url
23+
}
24+
25+
export async function uploadPublicImagesToVercel() {
26+
const urls = []
27+
const imageFiles = getImagesFromPublic()
28+
for (const pathFromPublic of imageFiles) {
29+
let url = await uploadImageToVercelIfNecessary(pathFromPublic)
30+
urls.push(url)
31+
}
32+
return urls
33+
}
34+
35+
function getImagesFromPublic() {
36+
const allFiles = getNonIgnoredFiles(absPathFromPublic(""))
37+
const imageFiles = []
38+
for (const file of allFiles) {
39+
if (
40+
file.endsWith(".png") ||
41+
file.endsWith(".jpg") ||
42+
file.endsWith(".jpeg")
43+
) {
44+
imageFiles.push(file)
45+
}
46+
}
47+
return imageFiles.map(relativePathFromPublic)
48+
}
49+
50+
export async function downloadAllBlobImages() {
51+
const listBlobResult = await list()
52+
const blobs = listBlobResult.blobs
53+
// Loop through array of blobs
54+
for (const blob of blobs) {
55+
const url = blob.url
56+
// Download image from url
57+
const response = await fetch(url)
58+
const buffer = await response.text()
59+
let pathname = relativePathFromPublic(blob.pathname)
60+
const absPath = absPathFromPublic(pathname)
61+
if (fs.existsSync(absPath)) {
62+
console.log(`Image already exists: ${absPath}`)
63+
continue
64+
}
65+
fs.writeFileSync(absPath, buffer)
66+
}
67+
}

tests/images.test.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
*/
44
import { generateGlobalSolutionImages } from "@/lib/globalSolutionsGenerator"
55
import { convertLargeImagesToJpg } from "@/lib/imageGenerator"
6-
import {
7-
downloadAllBlobImages,
8-
uploadPublicImagesToVercel,
9-
} from "@/lib/imageUploader"
6+
import {downloadAllBlobImages, uploadPublicImagesToVercel} from "@/lib/images/localImages";
107

118
describe("Test Images", () => {
129
it("should upload all images", async () => {

0 commit comments

Comments
 (0)