From 863716c096e87d61558ed90963b6be0fc79a0366 Mon Sep 17 00:00:00 2001 From: John Costa Date: Sat, 8 Mar 2025 15:37:10 +0000 Subject: [PATCH] feat: super basic image search --- backend/main.go | 42 +++++++++++++++++++++++--- frontend/bun.lockb | Bin 113510 -> 114257 bytes frontend/package.json | 2 ++ frontend/src/App.tsx | 60 ++++++++++++++++++++----------------- frontend/src/ImagePage.tsx | 36 ++++++++++++++++++++++ frontend/src/index.tsx | 9 +++++- 6 files changed, 117 insertions(+), 32 deletions(-) create mode 100644 frontend/src/ImagePage.tsx diff --git a/backend/main.go b/backend/main.go index 3f04e3d..56584eb 100644 --- a/backend/main.go +++ b/backend/main.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "encoding/base64" "encoding/json" "fmt" @@ -134,6 +135,10 @@ func main() { r.Get("/image", func(w http.ResponseWriter, r *http.Request) { userId := r.Header.Get("userId") + w.Header().Add("Access-Control-Allow-Origin", "*") + w.Header().Add("Access-Control-Allow-Credentials", "*") + w.Header().Add("Access-Control-Allow-Headers", "*") + images, err := models.GetUserImages(userId) if err != nil { log.Println(err) @@ -156,6 +161,10 @@ func main() { r.Get("/image/{id}", func(w http.ResponseWriter, r *http.Request) { imageId := r.PathValue("id") + w.Header().Add("Access-Control-Allow-Origin", "*") + w.Header().Add("Access-Control-Allow-Credentials", "*") + w.Header().Add("Access-Control-Allow-Headers", "*") + // TODO: really need authorization here! image, err := models.GetImage(imageId) if err != nil { @@ -188,17 +197,42 @@ func main() { return } - bodyData, err := io.ReadAll(r.Body) - // TODO: check headers - contentType := r.Header.Get("Content-Type") + log.Println(contentType) + + // TODO: length checks on body + // TODO: extract this shit out image := make([]byte, 0) if contentType == "application/base64" { - base64.StdEncoding.Decode(image, bodyData) + decoder := base64.NewDecoder(base64.StdEncoding, r.Body) + buf := &bytes.Buffer{} + + decodedIamge, err := io.Copy(buf, decoder) + if err != nil { + log.Println(err) + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "bruh, base64 aint decoding") + return + } + + fmt.Println(string(image)) + fmt.Println(decodedIamge) + + image = buf.Bytes() } else if contentType == "application/oclet-stream" { + bodyData, err := io.ReadAll(r.Body) + if err != nil { + log.Println(err) + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "bruh, binary aint binaring") + return + } + // TODO: check headers + image = bodyData } else { + log.Println("bad stuff?") w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, "Bruh, you need oclet stream or base64") return diff --git a/frontend/bun.lockb b/frontend/bun.lockb index e402c1c51e0d0e40ac66d671689f35e4d20ef6f3..e34de90cd66892fb9cd8123c6ccca40d666e1840 100755 GIT binary patch delta 18672 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�-e&d! z4@$D=Pa+9EW{lN`W8;mcqS}L>@HSPm~+RE@(7TSO>l)_BF5UXVE8G z$&s-73=1J8%Wb9+_yn3+9w4`5US%~K(vU{o$CCkuc`mmnTlDSmj60C$`NbNhL!zP^ z@fzF^wnL*k4z}}P++(28VwP{s`u5na2Fi1=6jBDiofOM%@Sp(}U5^x=Gr-K=% z!K#K=rdxDf2J=oCX8npGk~Ex$WW?%!fizT>Qijqhp}1Eejgck8FwHI-l45rh(jYmt z#c=s%jvRJKsdC&wNOCDUpAo!juvzatlGg9-!Lj;6Na?b45>lEhd5w~!6j>TyEA4~S zUyf@qT9T|J=?0AERYSX#x=ZrAmc+mw05Kk5WH|(^1F)IPSABLuOgPX0h>}zPGp2Ge z-pwT{2)mkG5Ij(l__<-83DgX@n0yhFj>(s=f5l{n?L}g|>$EUy-kRTq-BPXXK068Ngh~7cmt$TGkXM zJrkgYX90Lkk#YdK>NAac9zgb!RL%#}RmY`u5e*?uQB;|!f@!KwOa(p(P=PZ5y6Q8< z&y-^oru?&2y*`s2RZHwp>&JRgdh`^SE@EoX0)Q%B1W<qU@#eS`n9uGIgh6;dPHA)wti2uyR@S#5cJruY!V(?%2lCNDRs zcEscxabSv~uRe4UlU?^xHKIG1M0rDCo0?9=Ps7KSm zq?f4tB$zVHq)3%rz|TT&#BY!3B2OV#Q;DhH%T%41N?iq}{d9vG|L-uB^RjABOs#lD z)$4JoJo7u$g!y&on}7A-B5#ZT z%7B*B|7ZGNPc}57e?8g!^<+bS@PB*q`QwvK7p0(o`^jc^OkQ$_~u}Yzhy0$;Ll}w)iD0o5n9fTd>T9$1k(? zFHxE*hfWK6e^S$93(wlP=}@<^6pEMdy&UW0ruCD=Aj z8j*G8J-mF<_2$iIE?paUb@+gA9wNN>OUtZm2EV?{#%~B0-b+~7EWSk8`10j0 z{1<4YJYl(w_gUe>H!rucIlKniU1;emtoTm4VTFxvS?R*{E3NElp0?7)2d{GBd!fze zY?X~WuXf?ttE}u8~0l4!l$gUvgdgPv{TU9 zt+lcxykM=3PhaQ4KZeG6;5r+7k(VHRiC;jtj0df^F~R2`T+S~dT){&(*znQ#S%jwYGd1YCc^FfAi^Eob&HMd{C8xA3S%z3;zb%MIO4}#-k6o@R#;m+2{N^ zv>VWR9k8-1e8~ZL+(CF8v@dwVL3rFDc-%oNyUuH%-G!EZ$jZLr8xEm=Z=io~SlKr` z?G5zrF!~4WJI)THe@D>2!&X+w%b^{B=6=MA-yAZJpnq?of6#7o*Ei9>qv+q8R`xxw zfOZO6yQ5ZoN-j8x{=J3%LHmgZzJ>l(pnq>!*)RM8w9lYLR#@4ud`<=WcMSc5c8`Z1 zL;sGWf5)u&@$Wjc8_;?kx3UL($#L}WZS)V?BcAX!`ga2Td)umGjQ{v{2EPk6{e+b@ z;2Tb$gYTe&?^y8%7isUHgD25JXpJ~Ki4LAZ2Txj=ftN!&0L}fBl|9BYPoaaS(Lrb~ z-1Rg%cm^FjZN=XcRGhZ4X59OXjk)pygw6SBge`dByEf*=OAxyA3kW@U&{-Svu z@rww(dFVMC^Wo1T^ySwP`tg|eY^)_;f)IaUfG~h3yl-Qz_zHx9yar)w-uJwXwc#7i zf2c3SdqiViaPRb}Pc>CX-2SEKE`@;b+sFzd@{`uDI& zQy+fXee0`ROdn=b+DSh+JMqWA{aWuj0^ihN@Zs)L-wibJ$rr~o9vp~FxcamfZ39@e z`uhCvk#bRruY3zoJ{;87>wkvuQ*G#F>?x%{sihi6-%SE2BQF1XWp##5rU7akeURu; zN-?-vsgd;7S18Be@66OVx-B}?xYmfHO6g1CQvjvWXDa-oS&`#&uBR zrc)ufybvM$+Of7`dMlP(idm*VQIifM^&oHvcoU#+7e|0MfCIoTU?;E}C!0JH}>0&RgHAQgkI(BXE{Z~#AH$zPZ@B7PG|G;Gd(~l)9fRzAtCuuTJ0OSM30IlO3U?PwUM4=q| zL~H^w02?p}Fakk9cfbxzq{Wa6ArH8WjGqF1fknUqU=WZ2bO-1cnJK_jU=H8_W&?S^ zDCDOvulYbf=+6V`z;vJlm0v;G79Mr?h4Rn-&tVV zf#w0U!z=?{1nA35pAIm$uVgc`vu^@Qh@4v63`l^b*gy( zly)phS4uj88b3(|l|h}QI%#%jaHu2Ht~tO=fNZI)#AHkC0I0JBEsgp>13~?vK_NSW zDwk@)Kk#!fqM2C;JPS|*C=(S(1!#qm{wD>?u2ruhd6wu0JesXffEwUq+5kU<@HTK9 zpxYH?qS4z4(8$xsMgZb^N7mW!Xa~gYq&^tL83&A4buEtUKL9=gDgkt?R4)7mlrMqr z0L}PY$W#$EK&$K<$X^3r0kj?{&o$r@a1rByqRsaa zEu@ElC-4CH6`(1k-S{_vT0a=L58MOpih|Cph5VB_nYjRu1LO%4!4yaPauAsIY1+T3 zSlZBObEi$8ZUh9=wQ~Gc{ar&)Bf^V$3}KFhDI90rG=t2gn6@dVnZBj5h!Pq zy%+U5POm?SOi4K@&V{gW5AC#x_E*&?&SVS~=i`{0Xl7)M*)`#7WS!Zs zBFV_Y85c8*>{DOuz)`5><#sdYy80kjxG~&_K@SjlU6{A8c0#G##sBMP7ng;=Ak-LU zMBQOx0}NQ4VCk^aPD1&Xm431FyS8N! zL|_yODi-lwVfU0y`SbE2+uBsQJU#U=?4p!{UJwN^VC%&qqTOP1SM;NmxJVQrTteA+ zr7>;|L#f^f@qDOkR~8C`NKt^dg@$s4eZ{Y#tiP{zDr{5E)F~wohqXjaVa8BYCcP|1 zg(2%sQ4)r%H^h!G)}K|1-zajTa1Tdj?SxnQ=v$BOzmR!H&Kyql=80M1%sWy$>g6;z zY|y!eTTj3sQt5|w_^VTwKEK}`=Jq2}Oh~~<+!gO4tFLz2>uB(*OR?!*{a`?2j%AW6 z9)+Vt^3Z#Tz7fpCPK!AaXx3e^3gnA}Ve-L=`Hh0s_TTjSt8&&*V+=Lx{Rp;-rHYA> zu+vV8B{tplYVqRp3(1{~p~`Hmi)7)x!OfII4r8C&mtnuWwi*S6DUG}%Zc_<=Isjdb z*jd&2Oc${#kz@Tf}5nvuGw<7^ZQC!zNB7d2!)SUhF|Ws7zu z?9MxzE8S5N#oN)Wxq;l8{O>oh7?zRRNwWammm|}vt0$wx7&H{^(9Whk-E4Sn?mV_y z84L0aFY!6D`f5krwm$yJ!$&t)bmbMnFB3=m%+TcmdAZOGAT{pzc?JF52Z4ec15E$yTJBYr%6y{^W6A|wV) z($2+gDS4P5zTP*%Ngf}Xm=uvo28GxJFg1?5_h(EvHu%NOIyMY3sNeCFNQq_MDI1`| z2^?dG96z?U>3Y46J%<=~#Arw3(m%Y__R0KaLr{6NGUsPufsN7;+PLOsr`~Q(I(7gt zZis0i9#E|*P_c_T9^|rJlUpZVLe>Z+>r*1M8%AoVuoB6dhZA~wO_U-cQaiV|JwJ3$ zZgtjLWW?@5ex@DV8&l9WzWZZMqme>`imYwKIb`)!kN7zTbUC)s`^<4S7(^*`rU-_f zqB82RuXa>$C|mt`?_bxE1E?E@Vi0)^Q}Y-ae{1Z}^eb_1CBh&^*}}BLfJ5Gi8d%lu z-YukbMG9KCL#&~)wbOt1T(c)Wj5xOf2BAjuysLCYT%b1e5;uvC34I*vuWJ%02F0;3 zW#?8maBr3&-iTx2;+UCv=!{X~Rvhz-RL|}?GSfa^{pF?EI5&ZUBjxR*tumbp&RlTa zFD3^dB^*_vP4h&2Jldq4()*&(lJldl95Ts`j-jmEL;(!Ym_=mw6$&Cpkd|M4(7&{S zS+)x`M&nUQ9F1q;x{P+>=Xe&T8_`yDG^5p@ieYACzagHlBQn~GL|yX^;;NZ>MQLXT z$DaQ2hxy@Kv2n-^NAtAPg|>ueJj?ga9Ie)el$;J?rv;nVNDK4Psmed&DD9A8{Kk*^ z&WP2&Ef*7EG~ulV_iPVz=*rQ{tH+^z(uTurL|JXdfFNtei&setWY$R|Y)#TJCl< zb*dy-R3k5&FBz+up7Bk)`nTykZ{gDN-HNqNYSwu+{`u%5M(k@kaeTOu0f zee1-qU?ONc*3M3Tx2*Wb4VF7^)TLY#Bak&pJ8T)1e0JZ4rF)*NGtiD>cI~lp)c%G| zb#*D8MzOsY^YYUUa4vA#K4Fw=x9N2j@kVhC7E$V%Psgc7siOCdykm71V~xsI=5_ym z=)f~k*>x$?jl$R)z1Gf=em-|x@6ctJD(WoOi_G3w5_`l9kgs+QmB-#{le2i`f;zj) z;x!mVX$M!=`gT3^VP)3PIs<(dWe*OX=-KF}<2k+SQhd6IhiF8Ub{N*hGqG~*&Z#Hs zEVSdY+j`qa6k0m0u1gu-MIsSS%i7@PavPnat$ z??RE%2OgpwVU7M_MoN=r^DopHXop-EJ^x_!{x+^vbtzS14YEdQr((ZNXy^P(&&0Ru z4778zBTg6eO6)i5gSwQIXmN|$rJb~0I>&Fw?5V$Wth3-EpfB2`oz1m0N*h$uuo zxjWy?nemLFThuyb6^9$6q-ya!iqbVs5R+5!MDE{@`Rh^>gt;GfqlpRP1uIxh)JNiZ zXtP+<4|fzL%8UIhmJDQWjl!ak#CnP*F!%fO%E+Qw&t(HpUUpA09ER#6x>`-x-<8== zE)x%Hsqm94!Zo?Jm0E-TSi4fTSenct{Ir9%i5EA05;d{>IeA+PkHKb*ZS8Mq%tPEw zW@8#p?5*r7f9y=4T(NeBH|fjVUY#oTA5=!HUN_lh@os-i!vEIWNbOYc%^NFMKGEfP zGD=dP(zJ8K(zrL@zWqYMWjRH?&G#RGZl4w72Vi*wh*i*ZX-VRT47@AQO?O0+IFF%> z)DAM=+?Kt0?FZ}jDb1vb(vB*JFU@+gV$FIy92WLby1PiUOu??9oo(Llb>i~*^ABnN zmLGItr0pUt1=Y%LP;TAimlo|?e*W_Jo6cU4ESfQozVc^m{O1?Bx%Q%B=|{2a6Q7xZ z^wvO6QrLNASMg@Dhq*VTHfau}&O!rx&(h|Xo?0{y(5ar}TMf7MgZqxW_=9o4dY@-? z4A0on@LK7XI0C=WJQJ@^CdsM4_%RjtH0^Zt!;gyJbUb)Yd3wf6gnUoyo(2o;T=lHO zPdH*L=3l8BG^Jr)evK29=Sq(j-zIll(5FJSkZab~0@bKEzxY0l>3tWZC=UUTFYPtR zb>3%5y4pL`TG4bMHWBsEwxi{eev`7+^J#Ske_EOREUH!(K$ZP-E4dlry0|p)&Okg7 zC8vq|V0Cpxt;c(73%ZrwJHGd@)0ma$3cc^)7O$NM|E7J_rEeog&XqeUr(~yznNMJW z_7yKZ!S=EgVI2gA*_@^fO8ofqV`t9KX$$)>I0r_yT$I8fQagbD^_8@f_S-E-l7XBq zy@vb00gb5lh_Aj{Do^JAn4OeAdzP11gY1aou?+0#Y`m{_Abo1!xmnMB6L4Ft1s(Db zH`C#_OGQ8i3-{9wv=2WKe8YQIhXJtbs(eE5%@C6^FjDO^#NiC=M=JYiN7$qLov996 z<%7Gq{5Ao1Q4f0(;>ft$glk2 zzS_CQdr{h~a~=eQW3Oznm}Sm47^_ zNu5Q>5b**mqS8kwzW&X<@QGiyX@Gkz-jwOVPtuOkZ@=UbS#f6oZn9d+oDt$G^7?9r z?=2x^&N-L-zpt~{C0vJKoKA_(Am8h#!xtWNXl1rn(u+CA>+F6PqhQdu>u}}6)epnP zQ$tv9xOj1VDE{0pw_=OQywxuPoMF!ZCfjEovY%_ zb3D_VJaUV;+Qe0K8_LW+dsCJ8dC`$)+4Lq4Ta8faIe0`Y9m+N~!T;oAADdIur7(X= zadzSU@L_CppsV_kt4l~1RT8tOv3C3UOtzAVYjc_2yEX@Gl&m4jS2d9~ng#3+p3S<& F{|{p~k)= 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 function App() { - const [options, setOptions] = createSignal([]); - const [emoji, setEmoji] = createSignal(null); + const [searchResults, setSearchResults] = createSignal([]); const [images] = createResource(getUserImages); + const nav = useNavigate(); + + let fuze = new Fuse([], { keys: ["Text.ImageText"] }); + + // TODO: there's probably a better way? createEffect(() => { - console.log(images()?.map(image => image.ID)) + const userImages = images(); + if (userImages == null) { + return; + } + + fuze = new Fuse(userImages, { keys: ["Text.ImageText"] }); }); - const emojiData: Emoji[] = [ - { emoji: "😀", name: "Grinning Face" }, - { emoji: "😃", name: "Grinning Face with Big Eyes" }, - { emoji: "😄", name: "Grinning Face with Smiling Eyes" }, - { emoji: "😁", name: "Beaming Face with Smiling Eyes" }, - { emoji: "😆", name: "Grinning Squinting Face" }, - ]; - - const queryEmojiData = (query: string) => { - return emojiData.filter((emoji) => - emoji.name.toLowerCase().includes(query.toLowerCase()), - ); - }; + const onInputChange = (query: string) => { + const searched = fuze.search(query).flatMap(s => s.item).flatMap(s => s.Text ?? []); + setSearchResults(searched); + } return (
setOptions(queryEmojiData(query))} - onChange={(result) => setEmoji(result)} - optionValue="name" - optionLabel="name" + options={searchResults() ?? []} + onInputChange={onInputChange} + onChange={(item) => { + if (item?.ImageID == null) { + console.error("ImageID was null"); + return; + } + + nav(`/image/${item.ImageID}`); + }} + optionValue="ID" + optionLabel="ImageText" placeholder="Search for stuff..." itemComponent={(props) => ( - {props.item.rawValue.emoji} + {props.item.rawValue.ImageText ?? ''} )} @@ -107,7 +113,7 @@ function App() {
{(image) => ( - + )}
diff --git a/frontend/src/ImagePage.tsx b/frontend/src/ImagePage.tsx new file mode 100644 index 0000000..2173ef7 --- /dev/null +++ b/frontend/src/ImagePage.tsx @@ -0,0 +1,36 @@ +import { A, useParams } from "@solidjs/router" +import { createEffect, createResource, For, Suspense } from "solid-js" +import { getUserImages } from "./network" + +export function ImagePage() { + const { imageId } = useParams<{ imageId: string }>() + + const [image] = createResource(async () => { + const userImages = await getUserImages(); + + const currentImage = userImages.find(image => image.ID === imageId); + if (currentImage == null) { + // TODO: this error handling. + throw new Error("must be valid"); + } + + return currentImage; + }); + + createEffect(() => { + console.log(image()); + }) + + return (Loading...}> + Back +

{image()?.Image.ImageName}

+ +
+ + {(tag) => ( +
{tag.Tag}
+ )} +
+
+
) +} diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index e02db44..13e8ce0 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -2,5 +2,12 @@ import { render } from "solid-js/web"; import App from "./App"; import "./index.css"; +import { Route, Router } from "@solidjs/router"; +import { ImagePage } from "./ImagePage"; -render(() => , document.getElementById("root") as HTMLElement); +render(() => ( + + + + +), document.getElementById("root") as HTMLElement);