diff --git a/assets/js/uploader.js b/assets/js/uploader.js index 7f87ef9a..d686ec78 100644 --- a/assets/js/uploader.js +++ b/assets/js/uploader.js @@ -37,6 +37,19 @@ throw new Error("The demozoo-submission element is null."); } + const introM = document.getElementById("uploader-intro"); + if (introM == null) { + throw new Error("The uploader-intro element is null."); + } + introM.addEventListener("shown.bs.modal", function () { + introInput.focus(); + }); + const introModal = new bootstrap.Modal(introM); + const introInput = document.getElementById("uploader-intro-file"); + if (introInput == null) { + throw new Error("The uploader-intro-file element is null."); + } + const txtM = document.getElementById("uploaderText"); const imgM = document.getElementById("uploaderImg"); const magM = document.getElementById("uploaderMag"); @@ -99,7 +112,7 @@ pouetModal.show(); break; case intro: - demozooModal.show(); + introModal.show(); break; case nfo: txtModal.show(); diff --git a/handler/htmx/htmx.go b/handler/htmx/htmx.go index 0697a475..6f1a1473 100644 --- a/handler/htmx/htmx.go +++ b/handler/htmx/htmx.go @@ -2,15 +2,23 @@ package htmx import ( + "context" + "crypto/sha512" "embed" "errors" + "fmt" "html/template" + "io" + "net/http" + "os" "strings" "github.com/Defacto2/releaser" "github.com/Defacto2/releaser/initialism" "github.com/Defacto2/releaser/name" "github.com/Defacto2/server/handler/app" + "github.com/Defacto2/server/internal/postgres" + "github.com/Defacto2/server/model" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "go.uber.org/zap" @@ -40,9 +48,68 @@ func Routes(logr *zap.SugaredLogger, e *echo.Echo) *echo.Echo { submit.POST("/search/releaser", func(x echo.Context) error { return SearchReleaser(logr, x) }) + submit.POST("/uploader/intro", func(x echo.Context) error { + return holder(x) + }) return e } +func holder(c echo.Context) error { + // Source + input, err := c.FormFile("uploader-intro-file") + if err != nil { + return err + } + src, err := input.Open() + if err != nil { + return err + } + defer src.Close() + + hasher := sha512.New384() + if _, err := io.Copy(hasher, src); err != nil { + return err + } + sum := hasher.Sum(nil) + fmt.Printf("%x; %s\n", sum, input.Filename) + + db, err := postgres.ConnectDB() + if err != nil { + return ErrDB + } + defer db.Close() + ctx := context.Background() + + if exist, err := model.ExistsHash(ctx, db, sum); err != nil { + return err + } else if exist { + return c.HTML(http.StatusOK, fmt.Sprintf("

File %s already exists.

", input.Filename)) + } + + // reopen the file + src, err = input.Open() + if err != nil { + return err + } + defer src.Close() + // Destination + dst, err := os.CreateTemp("tmp", "upload-*.zip") + //dst, err := os.Create(file.Filename) + if err != nil { + return err + } + defer dst.Close() + + // Copy + if _, err = io.Copy(dst, src); err != nil { + return err + } + + return c.HTML(http.StatusOK, + fmt.Sprintf("

File %s uploaded successfully with fields.

%s

", input.Filename, dst.Name())) + +} + // GlobTo returns the path to the template file. func GlobTo(name string) string { const pathSeparator = "/" diff --git a/model/file.go b/model/file.go index c8402588..8ef38b17 100644 --- a/model/file.go +++ b/model/file.go @@ -26,6 +26,17 @@ func ExistFile(ctx context.Context, db *sql.DB, id int64) (bool, error) { return models.Files(models.FileWhere.ID.EQ(id), qm.WithDeleted()).Exists(ctx, db) } +// ExistsHash returns true if the file record exists in the database using a SHA-384 hash. +func ExistsHash(ctx context.Context, db *sql.DB, sha384 []byte) (bool, error) { + if db == nil { + return false, ErrDB + } + hash := fmt.Sprintf("%x", sha384) + // todo validate sha384 is not empty, is valid + strong := null.String{String: hash, Valid: true} + return models.Files(models.FileWhere.FileIntegrityStrong.EQ(strong), qm.WithDeleted()).Exists(ctx, db) +} + // FindFile retrieves a single file record from the database using the record key. // This function will also return records that have been marked as deleted. func FindFile(ctx context.Context, db *sql.DB, id int64) (*models.File, error) { diff --git a/public/js/uploader.min.js b/public/js/uploader.min.js index eea4929f..37ecb498 100644 --- a/public/js/uploader.min.js +++ b/public/js/uploader.min.js @@ -1,2 +1,2 @@ /* uploader.min.js © Defacto2 2024 */ -(()=>{"use strict";const t="is-invalid",r=document.getElementById("uploader-pouet");if(r==null)throw new Error("The uploader-pouet element is null.");r.addEventListener("shown.bs.modal",function(){$.focus()});const ce=new bootstrap.Modal(r),$=document.getElementById("pouet-submission");if($==null)throw new Error("The pouet-submission element is null.");const u=document.getElementById("uploader-demozoo");if(u==null)throw new Error("The uploader-demozoo element is null.");u.addEventListener("shown.bs.modal",function(){J.focus()});const j=new bootstrap.Modal(u),J=document.getElementById("demozoo-submission");if(J==null)throw new Error("The demozoo-submission element is null.");const me=document.getElementById("uploaderText"),re=document.getElementById("uploaderImg"),ue=document.getElementById("uploaderMag"),fe=document.getElementById("uploaderAdv"),ge=document.getElementById("termsModal"),ve=new bootstrap.Modal(me),Ee=new bootstrap.Modal(re),Le=new bootstrap.Modal(ue),ye=new bootstrap.Modal(fe),pe=new bootstrap.Modal(ge),q=document.getElementById("paginationStart"),G=document.getElementById("paginationPrev"),H=document.getElementById("paginationPrev2"),Q=document.getElementById("paginationNext"),V=document.getElementById("paginationNext2"),W=document.getElementById("paginationEnd"),n=document.getElementById("paginationRange");if(typeof n<"u"&&n!=null){n.addEventListener("change",function(){const s=n.value,d=new URL(window.location.href);let a=d.pathname.split("/");const m=a[a.length-1];!isNaN(m)&&typeof Number(m)=="number"?a[a.length-1]=s:a.push(s),d.pathname=a.join("/"),window.location.href=d.href});const e=document.getElementById("paginationRangeLabel");n.addEventListener("input",function(){e.textContent="Jump to page "+n.value})}document.addEventListener("keydown",function(e){const s="d",d="p",ie="i",a="n",m="g",Ie="m",Be="a",he="t";if(e.ctrlKey&&e.altKey)switch(e.key){case s:j.show();break;case d:ce.show();break;case ie:j.show();break;case a:ve.show();break;case m:Ee.show();break;case Ie:Le.show();break;case Be:ye.show();break;case he:pe.show();break}const P="ArrowRight",O="ArrowLeft";if(e.ctrlKey&&e.key==O){q?.click();return}if(e.ctrlKey&&e.key==P){W?.click();return}if(e.shiftKey&&e.key==O){H?.click();return}if(e.shiftKey&&e.key==P){V?.click();return}if(e.key==O){G?.click();return}if(e.key==P){Q?.click();return}});function l(e){if(`${e}`=="")return!0;const s=new Date().getFullYear();return!(e<1980||e>s)}function o(e){return`${e}`==""?!0:!(e<1||e>12)}function X(e){return`${e}`==""?!0:!(e<1||e>31)}const Z=document.getElementById("introUploader"),_=document.getElementById("textUploader"),ee=document.getElementById("imageUploader"),te=document.getElementById("magUploader"),se=document.getElementById("advancedUploader"),f=document.getElementById("introFile"),g=document.getElementById("releaseTitle"),v=document.getElementById("introReleasers"),E=document.getElementById("introYear"),L=document.getElementById("introMonth");function ae(){f.classList.remove(t),g.classList.remove(t),v.classList.remove(t),E.classList.remove(t),L.classList.remove(t)}document.getElementById("introSubmit").addEventListener("click",function(){let e=!0;ae(),f.value==""&&(f.classList.add(t),e=!1),g.value==""&&(g.classList.add(t),e=!1),v.value==""&&(v.classList.add(t),e=!1),l(E.value)==!1&&(E.classList.add(t),e=!1),o(L.value)==!1&&(L.classList.add(t),e=!1),e==!0&&Z.submit()}),Z.addEventListener("reset",ae);const y=document.getElementById("textFile"),p=document.getElementById("textTitle"),I=document.getElementById("textReleasers"),B=document.getElementById("textYear"),h=document.getElementById("textMonth");function ne(){y.classList.remove(t),p.classList.remove(t),I.classList.remove(t),B.classList.remove(t),h.classList.remove(t)}document.getElementById("textSubmit").addEventListener("click",function(){let e=!0;ne(),y.value==""&&(y.classList.add(t),e=!1),p.value==""&&(p.classList.add(t),e=!1),I.value==""&&(I.classList.add(t),e=!1),l(B.value)==!1&&(B.classList.add(t),e=!1),o(h.value)==!1&&(h.classList.add(t),e=!1),e==!0&&_.submit()}),_.addEventListener("reset",ne);const b=document.getElementById("imageFile"),w=document.getElementById("imageTitle"),M=document.getElementById("imageReleasers"),k=document.getElementById("imageYear"),x=document.getElementById("imageMonth");function le(){b.classList.remove(t),w.classList.remove(t),M.classList.remove(t),k.classList.remove(t),x.classList.remove(t)}document.getElementById("imageSubmit").addEventListener("click",function(){let e=!0;le(),b.value==""&&(b.classList.add(t),e=!1),w.value==""&&(w.classList.add(t),e=!1),M.value==""&&(M.classList.add(t),e=!1),l(k.value)==!1&&(k.classList.add(t),e=!1),o(x.value)==!1&&(x.classList.add(t),e=!1),e==!0&&ee.submit()}),ee.addEventListener("reset",le);const R=document.getElementById("magFile"),F=document.getElementById("magTitle"),T=document.getElementById("magIssue"),Y=document.getElementById("magYear"),S=document.getElementById("magMonth"),z=document.getElementById("magDay");function oe(){R.classList.remove(t),F.classList.remove(t),T.classList.remove(t),Y.classList.remove(t),S.classList.remove(t),z.classList.remove(t)}document.getElementById("magSubmit").addEventListener("click",function(){let e=!0;oe(),R.value==""&&(R.classList.add(t),e=!1),F.value==""&&(F.classList.add(t),e=!1),T.value==""&&(T.classList.add(t),e=!1),l(Y.value)==!1&&(Y.classList.add(t),e=!1),o(S.value)==!1&&(S.classList.add(t),e=!1),X(z.value)==!1&&(z.classList.add(t),e=!1),e==!0&&te.submit()}),te.addEventListener("reset",oe);const N=document.getElementById("advFile"),i=document.getElementById("advSelOS"),c=document.getElementById("advSelCat"),D=document.getElementById("advTitle"),K=document.getElementById("releasersAdv"),U=document.getElementById("advYear"),A=document.getElementById("advMonth"),C=document.getElementById("advDay");function de(){N.classList.remove(t),i.classList.remove(t),c.classList.remove(t),D.classList.remove(t),K.classList.remove(t),U.classList.remove(t),A.classList.remove(t),C.classList.remove(t)}document.getElementById("advSubmit").addEventListener("click",function(){const e="Choose...";let s=!0;de(),N.value==""&&(N.classList.add(t),s=!1),(i.value==""||i.value==e)&&(i.classList.add(t),s=!1),(c.value==""||c.value==e)&&(c.classList.add(t),s=!1),D.value==""&&(D.classList.add(t),s=!1),K.value==""&&(K.classList.add(t),s=!1),l(U.value)==!1&&(U.classList.add(t),s=!1),o(A.value)==!1&&(A.classList.add(t),s=!1),X(C.value)==!1&&(C.classList.add(t),s=!1),s==!0&&se.submit()}),se.addEventListener("reset",de)})(); +(()=>{"use strict";const t="is-invalid",r=document.getElementById("uploader-pouet");if(r==null)throw new Error("The uploader-pouet element is null.");r.addEventListener("shown.bs.modal",function(){j.focus()});const me=new bootstrap.Modal(r),j=document.getElementById("pouet-submission");if(j==null)throw new Error("The pouet-submission element is null.");const u=document.getElementById("uploader-demozoo");if(u==null)throw new Error("The uploader-demozoo element is null.");u.addEventListener("shown.bs.modal",function(){J.focus()});const re=new bootstrap.Modal(u),J=document.getElementById("demozoo-submission");if(J==null)throw new Error("The demozoo-submission element is null.");const f=document.getElementById("uploader-intro");if(f==null)throw new Error("The uploader-intro element is null.");f.addEventListener("shown.bs.modal",function(){q.focus()});const ue=new bootstrap.Modal(f),q=document.getElementById("uploader-intro-file");if(q==null)throw new Error("The uploader-intro-file element is null.");const fe=document.getElementById("uploaderText"),ge=document.getElementById("uploaderImg"),ve=document.getElementById("uploaderMag"),Ee=document.getElementById("uploaderAdv"),Le=document.getElementById("termsModal"),ye=new bootstrap.Modal(fe),pe=new bootstrap.Modal(ge),Ie=new bootstrap.Modal(ve),Be=new bootstrap.Modal(Ee),he=new bootstrap.Modal(Le),G=document.getElementById("paginationStart"),H=document.getElementById("paginationPrev"),Q=document.getElementById("paginationPrev2"),V=document.getElementById("paginationNext"),W=document.getElementById("paginationNext2"),X=document.getElementById("paginationEnd"),a=document.getElementById("paginationRange");if(typeof a<"u"&&a!=null){a.addEventListener("change",function(){const s=a.value,i=new URL(window.location.href);let n=i.pathname.split("/");const m=n[n.length-1];!isNaN(m)&&typeof Number(m)=="number"?n[n.length-1]=s:n.push(s),i.pathname=n.join("/"),window.location.href=i.href});const e=document.getElementById("paginationRangeLabel");a.addEventListener("input",function(){e.textContent="Jump to page "+a.value})}document.addEventListener("keydown",function(e){const s="d",i="p",ce="i",n="n",m="g",we="m",be="a",Me="t";if(e.ctrlKey&&e.altKey)switch(e.key){case s:re.show();break;case i:me.show();break;case ce:ue.show();break;case n:ye.show();break;case m:pe.show();break;case we:Ie.show();break;case be:Be.show();break;case Me:he.show();break}const O="ArrowRight",$="ArrowLeft";if(e.ctrlKey&&e.key==$){G?.click();return}if(e.ctrlKey&&e.key==O){X?.click();return}if(e.shiftKey&&e.key==$){Q?.click();return}if(e.shiftKey&&e.key==O){W?.click();return}if(e.key==$){H?.click();return}if(e.key==O){V?.click();return}});function o(e){if(`${e}`=="")return!0;const s=new Date().getFullYear();return!(e<1980||e>s)}function l(e){return`${e}`==""?!0:!(e<1||e>12)}function Z(e){return`${e}`==""?!0:!(e<1||e>31)}const _=document.getElementById("introUploader"),ee=document.getElementById("textUploader"),te=document.getElementById("imageUploader"),se=document.getElementById("magUploader"),ne=document.getElementById("advancedUploader"),g=document.getElementById("introFile"),v=document.getElementById("releaseTitle"),E=document.getElementById("introReleasers"),L=document.getElementById("introYear"),y=document.getElementById("introMonth");function ae(){g.classList.remove(t),v.classList.remove(t),E.classList.remove(t),L.classList.remove(t),y.classList.remove(t)}document.getElementById("introSubmit").addEventListener("click",function(){let e=!0;ae(),g.value==""&&(g.classList.add(t),e=!1),v.value==""&&(v.classList.add(t),e=!1),E.value==""&&(E.classList.add(t),e=!1),o(L.value)==!1&&(L.classList.add(t),e=!1),l(y.value)==!1&&(y.classList.add(t),e=!1),e==!0&&_.submit()}),_.addEventListener("reset",ae);const p=document.getElementById("textFile"),I=document.getElementById("textTitle"),B=document.getElementById("textReleasers"),h=document.getElementById("textYear"),w=document.getElementById("textMonth");function oe(){p.classList.remove(t),I.classList.remove(t),B.classList.remove(t),h.classList.remove(t),w.classList.remove(t)}document.getElementById("textSubmit").addEventListener("click",function(){let e=!0;oe(),p.value==""&&(p.classList.add(t),e=!1),I.value==""&&(I.classList.add(t),e=!1),B.value==""&&(B.classList.add(t),e=!1),o(h.value)==!1&&(h.classList.add(t),e=!1),l(w.value)==!1&&(w.classList.add(t),e=!1),e==!0&&ee.submit()}),ee.addEventListener("reset",oe);const b=document.getElementById("imageFile"),M=document.getElementById("imageTitle"),k=document.getElementById("imageReleasers"),x=document.getElementById("imageYear"),R=document.getElementById("imageMonth");function le(){b.classList.remove(t),M.classList.remove(t),k.classList.remove(t),x.classList.remove(t),R.classList.remove(t)}document.getElementById("imageSubmit").addEventListener("click",function(){let e=!0;le(),b.value==""&&(b.classList.add(t),e=!1),M.value==""&&(M.classList.add(t),e=!1),k.value==""&&(k.classList.add(t),e=!1),o(x.value)==!1&&(x.classList.add(t),e=!1),l(R.value)==!1&&(R.classList.add(t),e=!1),e==!0&&te.submit()}),te.addEventListener("reset",le);const T=document.getElementById("magFile"),F=document.getElementById("magTitle"),Y=document.getElementById("magIssue"),S=document.getElementById("magYear"),z=document.getElementById("magMonth"),N=document.getElementById("magDay");function ie(){T.classList.remove(t),F.classList.remove(t),Y.classList.remove(t),S.classList.remove(t),z.classList.remove(t),N.classList.remove(t)}document.getElementById("magSubmit").addEventListener("click",function(){let e=!0;ie(),T.value==""&&(T.classList.add(t),e=!1),F.value==""&&(F.classList.add(t),e=!1),Y.value==""&&(Y.classList.add(t),e=!1),o(S.value)==!1&&(S.classList.add(t),e=!1),l(z.value)==!1&&(z.classList.add(t),e=!1),Z(N.value)==!1&&(N.classList.add(t),e=!1),e==!0&&se.submit()}),se.addEventListener("reset",ie);const D=document.getElementById("advFile"),d=document.getElementById("advSelOS"),c=document.getElementById("advSelCat"),K=document.getElementById("advTitle"),U=document.getElementById("releasersAdv"),A=document.getElementById("advYear"),C=document.getElementById("advMonth"),P=document.getElementById("advDay");function de(){D.classList.remove(t),d.classList.remove(t),c.classList.remove(t),K.classList.remove(t),U.classList.remove(t),A.classList.remove(t),C.classList.remove(t),P.classList.remove(t)}document.getElementById("advSubmit").addEventListener("click",function(){const e="Choose...";let s=!0;de(),D.value==""&&(D.classList.add(t),s=!1),(d.value==""||d.value==e)&&(d.classList.add(t),s=!1),(c.value==""||c.value==e)&&(c.classList.add(t),s=!1),K.value==""&&(K.classList.add(t),s=!1),U.value==""&&(U.classList.add(t),s=!1),o(A.value)==!1&&(A.classList.add(t),s=!1),l(C.value)==!1&&(C.classList.add(t),s=!1),Z(P.value)==!1&&(P.classList.add(t),s=!1),s==!0&&ne.submit()}),ne.addEventListener("reset",de)})(); diff --git a/view/app/layout_uploader.tmpl b/view/app/layout_uploader.tmpl index b8643a14..a0c0ce4b 100644 --- a/view/app/layout_uploader.tmpl +++ b/view/app/layout_uploader.tmpl @@ -10,7 +10,7 @@
  • Pouët
  • -
  • Intro, cracktro, bbstro
  • +
  • Intro, cracktro, bbstro
  • Text, ANSI or NFO
  • Image or photo
  • Magazine
  • diff --git a/view/app/uploaderHtmx.tmpl b/view/app/uploaderHtmx.tmpl index 399334c6..91078e75 100644 --- a/view/app/uploaderHtmx.tmpl +++ b/view/app/uploaderHtmx.tmpl @@ -79,7 +79,102 @@ + + +