From bf07c18fd71d3d786385041a95931cae7ecd63b8 Mon Sep 17 00:00:00 2001 From: John Costa Date: Sat, 8 Mar 2025 12:30:16 +0000 Subject: [PATCH] feat: sending base64 image to backend This is silly, but binary is apparently hard to do???? --- backend/main.go | 20 +++- backend/models/image.go | 8 -- backend/openai.go | 5 +- frontend/src/components/ImageViewer.tsx | 8 +- frontend/src/network/index.ts | 140 ++++++++++++------------ 5 files changed, 93 insertions(+), 88 deletions(-) diff --git a/backend/main.go b/backend/main.go index c80aa1d..3f04e3d 100644 --- a/backend/main.go +++ b/backend/main.go @@ -1,6 +1,7 @@ package main import ( + "encoding/base64" "encoding/json" "fmt" "io" @@ -88,8 +89,6 @@ func main() { return } - fmt.Printf("%+v\n", image) - imageInfo, err := openAiClient.GetImageInfo(image.Image.ImageName, image.Image.Image) if err != nil { log.Println("2") @@ -189,8 +188,21 @@ func main() { return } - image, err := io.ReadAll(r.Body) - fmt.Println(image) + bodyData, err := io.ReadAll(r.Body) + // TODO: check headers + + contentType := r.Header.Get("Content-Type") + + image := make([]byte, 0) + if contentType == "application/base64" { + base64.StdEncoding.Decode(image, bodyData) + } else if contentType == "application/oclet-stream" { + image = bodyData + } else { + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "Bruh, you need oclet stream or base64") + return + } if err != nil { log.Println("First case") diff --git a/backend/models/image.go b/backend/models/image.go index db533c9..ce08240 100644 --- a/backend/models/image.go +++ b/backend/models/image.go @@ -35,8 +35,6 @@ func removeImageToProcess(imageId string) error { stmt := UserImagesToProcess.DELETE().WHERE(UserImagesToProcess.ID.EQ(UUID(id))) - fmt.Println(stmt.DebugSql()) - _, err := stmt.Exec(db) return err @@ -111,8 +109,6 @@ func GetImageToProcess(imageId string) (model.UserImagesToProcess, error) { id := uuid.MustParse(imageId) stmt := UserImagesToProcess.SELECT(UserImagesToProcess.AllColumns).WHERE(UserImagesToProcess.ID.EQ(UUID(id))) - fmt.Println(stmt.DebugSql()) - images := []model.UserImagesToProcess{} err := stmt.Query(db, &images) @@ -138,8 +134,6 @@ func GetUserImages(userId string) ([]UserImagesWithInfo, error) { id := uuid.MustParse(userId) stmt := SELECT(UserImages.ID.AS("UserImagesWithInfo.ID"), Image.ID, Image.ImageName, ImageTags.AllColumns, ImageText.AllColumns, ImageLinks.AllColumns).FROM(UserImages.INNER_JOIN(Image, Image.ID.EQ(UserImages.ImageID)).LEFT_JOIN(ImageTags, ImageTags.ImageID.EQ(UserImages.ID)).LEFT_JOIN(ImageText, ImageText.ImageID.EQ(UserImages.ID)).LEFT_JOIN(ImageLinks, ImageLinks.ImageID.EQ(UserImages.ID))).WHERE(UserImages.UserID.EQ(UUID(id))) - fmt.Println(stmt.DebugSql()) - images := []UserImagesWithInfo{} err := stmt.Query(db, &images) @@ -157,8 +151,6 @@ func SaveImageTags(imageId string, tags []string) ([]model.ImageTags, error) { stmt.RETURNING(ImageTags.AllColumns) - fmt.Println(stmt.DebugSql()) - imageTags := []model.ImageTags{} err := stmt.Query(db, &imageTags) diff --git a/backend/openai.go b/backend/openai.go index 49644ff..4a90a34 100644 --- a/backend/openai.go +++ b/backend/openai.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + "log" "net/http" "os" "path/filepath" @@ -264,6 +265,7 @@ func parseOpenAiResponse(jsonResponse []byte) (ImageInfo, error) { } if len(response.Choices) != 1 { + log.Println(string(jsonResponse)) return ImageInfo{}, errors.New("Expected exactly one choice.") } @@ -298,8 +300,6 @@ func (client OpenAiClient) GetImageInfo(imageName string, imageData []byte) (Ima return ImageInfo{}, err } - fmt.Println(string(jsonAiRequest)) - request, err := client.getRequest(jsonAiRequest) if err != nil { return ImageInfo{}, err @@ -315,6 +315,5 @@ func (client OpenAiClient) GetImageInfo(imageName string, imageData []byte) (Ima return ImageInfo{}, err } - fmt.Println(string(response)) return parseOpenAiResponse(response) } diff --git a/frontend/src/components/ImageViewer.tsx b/frontend/src/components/ImageViewer.tsx index 8efbbdb..cd1a974 100644 --- a/frontend/src/components/ImageViewer.tsx +++ b/frontend/src/components/ImageViewer.tsx @@ -9,11 +9,13 @@ export function ImageViewer() { createEffect(() => { // Listen for PNG processing events const unlisten = listen("png-processed", (event) => { - console.log("Received processed PNG"); + console.log("Received processed PNG", event); const base64Data = event.payload as string; - setLatestImage(`data:image/png;base64,${base64Data}`); - sendImage("test-image.png", base64Data); + const urlImage = `data:image/png;base64,${base64Data}`; + setLatestImage(urlImage); + + sendImage("test-image.png", urlImage); }); return () => { diff --git a/frontend/src/network/index.ts b/frontend/src/network/index.ts index 9a31eb3..a6213c3 100644 --- a/frontend/src/network/index.ts +++ b/frontend/src/network/index.ts @@ -1,97 +1,97 @@ import { - array, - InferOutput, - null as Null, - nullable, - object, - parse, - pipe, - string, - uuid, + array, + InferOutput, + null as Null, + nullable, + object, + parse, + pipe, + string, + uuid, } from "valibot"; type BaseRequestParams = Partial<{ - path: string; - body: RequestInit["body"]; - method: "GET" | "POST"; + path: string; + body: RequestInit["body"]; + method: "GET" | "POST"; }>; const getBaseRequest = ({ path, body, method }: BaseRequestParams): Request => { - return new Request(`http://localhost:3040/${path}`, { - headers: { userId: "fcc22dbb-7792-4595-be8e-d0439e13990a" }, - body, - method, - }); + return new Request(`http://localhost:3040/${path}`, { + headers: { userId: "fcc22dbb-7792-4595-be8e-d0439e13990a" }, + body, + method, + }); }; const sendImageResponseValidator = object({ - ID: pipe(string(), uuid()), - ImageID: pipe(string(), uuid()), - UserID: pipe(string(), uuid()), + ID: pipe(string(), uuid()), + ImageID: pipe(string(), uuid()), + UserID: pipe(string(), uuid()), }); export const sendImage = async ( - imageName: string, - image: BlobPart, + imageName: string, + image: BlobPart, ): Promise> => { - const data = new Blob([image]); - const request = getBaseRequest({ - path: `image/${imageName}`, - body: data, - method: "POST", - }); + const data = new Blob([image]); + const request = getBaseRequest({ + path: `image/${imageName}`, + body: data, + method: "POST", + }); - request.headers.set("Content-Type", "aplication/oclet-stream"); + request.headers.set("Content-Type", "aplication/base64"); - const res = await fetch(request).then((res) => res.json()); + const res = await fetch(request).then((res) => res.json()); - return parse(sendImageResponseValidator, res); + return parse(sendImageResponseValidator, res); }; const getUserImagesResponseValidator = array( - object({ - ID: pipe(string(), uuid()), - Image: object({ - ID: pipe(string(), uuid()), - ImageName: string(), - Image: Null(), - }), - Tags: nullable( - array( - object({ - ID: pipe(string(), uuid()), - Tag: string(), - ImageID: pipe(string(), uuid()), - }), - ), - ), - Links: nullable( - array( - object({ - ID: pipe(string(), uuid()), - Links: string(), - ImageID: pipe(string(), uuid()), - }), - ), - ), - Text: nullable( - array( - object({ - ID: pipe(string(), uuid()), - ImageText: string(), - ImageID: pipe(string(), uuid()), - }), - ), - ), - }), + object({ + ID: pipe(string(), uuid()), + Image: object({ + ID: pipe(string(), uuid()), + ImageName: string(), + Image: Null(), + }), + Tags: nullable( + array( + object({ + ID: pipe(string(), uuid()), + Tag: string(), + ImageID: pipe(string(), uuid()), + }), + ), + ), + Links: nullable( + array( + object({ + ID: pipe(string(), uuid()), + Links: string(), + ImageID: pipe(string(), uuid()), + }), + ), + ), + Text: nullable( + array( + object({ + ID: pipe(string(), uuid()), + ImageText: string(), + ImageID: pipe(string(), uuid()), + }), + ), + ), + }), ); export const getUserImages = async (): Promise< - InferOutput + InferOutput > => { - const request = getBaseRequest({ path: "image" }); + const request = getBaseRequest({ path: "image" }); - const res = await fetch(request).then((res) => res.json()); + const res = await fetch(request).then((res) => res.json()); - return parse(getUserImagesResponseValidator, res); + return parse(getUserImagesResponseValidator, res); };