diff --git a/internal/database/handlers.go b/internal/database/handlers.go index eabf2c6..7417560 100644 --- a/internal/database/handlers.go +++ b/internal/database/handlers.go @@ -2,6 +2,8 @@ package database import ( "database/sql" + "errors" + "io/fs" "os" "path" @@ -223,7 +225,7 @@ func PutPost(db Queryer, boardSlug string, threadId int, body string, mediaPath func DeleteThread(db Queryer, threadId int) error { // cleanup images rows, err := db.Query(` - SELECT media_path + SELECT media_path, thumb_path FROM posts WHERE thread_id = ?`, threadId) if err != nil { @@ -231,21 +233,24 @@ func DeleteThread(db Queryer, threadId int) error { } defer rows.Close() - var pruneMediaPaths []string for rows.Next() { - var pruneMediaPath string - if err := rows.Scan(&pruneMediaPath); err != nil { + var ( + pruneMediaThumbPath string + pruneMediaFullPath string + ) + if err := rows.Scan(&pruneMediaFullPath, &pruneMediaThumbPath); err != nil { return err } - pruneMediaPaths = append(pruneMediaPaths, pruneMediaPath) - } - for _, pruneMediaPath := range pruneMediaPaths { - if err := os.Remove(path.Join(util.POST_MEDIA_FULL_PATH, pruneMediaPath)); err != nil && !os.IsNotExist(err) { - return err + if err := os.Remove(path.Join(util.POST_MEDIA_FULL_PATH, pruneMediaFullPath)); err != nil { + if !errors.Is(err, fs.ErrNotExist) { + return err + } } - if err := os.Remove(path.Join(util.POST_MEDIA_THUMB_PATH, pruneMediaPath)); err != nil && !os.IsNotExist(err) { - return err + if err := os.Remove(path.Join(util.POST_MEDIA_THUMB_PATH, pruneMediaThumbPath)); err != nil { + if !errors.Is(err, fs.ErrNotExist) { + return err + } } } diff --git a/web/main.go b/web/main.go index 60a773e..83a94c9 100644 --- a/web/main.go +++ b/web/main.go @@ -154,7 +154,7 @@ func main() { // check cooldown timeRemaining := util.GetRemainingCooldown(ip, util.ThreadCooldowns, util.THREAD_COOLDOWN) - if timeRemaining > 0 { + if timeRemaining > 0 && !isAdmin(r) { response := fmt.Sprintf("Please wait %.0f seconds", timeRemaining.Seconds()) io.Copy(io.Discard, r.Body) http.Error(w, response, http.StatusTooManyRequests) @@ -247,7 +247,7 @@ func main() { // check cooldown timeRemaining := util.GetRemainingCooldown(ip, util.PostCooldowns, util.POST_COOLDOWN) - if timeRemaining > 0 { + if timeRemaining > 0 && !isAdmin(r) { response := fmt.Sprintf("Please wait %.0f seconds", timeRemaining.Seconds()) io.Copy(io.Discard, r.Body) http.Error(w, response, http.StatusTooManyRequests) @@ -377,6 +377,7 @@ func main() { previews = append(previews, views.CatalogThreadPreview{ Subject: thread.Subject, Body: op.Body, + ThreadId: thread.Id, ThreadURL: fmt.Sprintf("/%s/threads/%d", slug, thread.Id), ThumbPath: op.ThumbPath, ReplyCount: len(posts), @@ -384,7 +385,10 @@ func main() { }) } - views.ThreadsCatalog(previews, isAdmin(r)).Render(r.Context(), w) + views.ThreadsCatalog(previews, views.CatalogContext{ + IsAdmin: isAdmin(r), + BoardSlug: slug, + }).Render(r.Context(), w) }) // THREAD POSTS @@ -498,6 +502,23 @@ func main() { Path: "/", }) }) + + r.Delete("/{slug}/threads/{threadId}", func(w http.ResponseWriter, r *http.Request) { + // slug := chi.URLParam(r, "slug") + threadIdStr := chi.URLParam(r, "threadId") + threadId, err := strconv.Atoi(threadIdStr) + if err != nil { + http.Error(w, "Invalid thread id", http.StatusBadRequest) + return + } + + err = database.DeleteThread(db, threadId) + if err != nil { + log.Println("DeleteThread: %v", err) + http.Error(w, "Error deleting thread: "+threadIdStr, http.StatusInternalServerError) + } + }) + }) // ----------------- diff --git a/web/static/index.js b/web/static/index.js index e2daebb..1ab34ad 100644 --- a/web/static/index.js +++ b/web/static/index.js @@ -95,3 +95,7 @@ function applyCatalogSearch() { } } } + +function currentBoardSlug() { + return window.location.pathname.split("/")[1] || ""; +} diff --git a/web/views/board.templ b/web/views/board.templ index 842517e..1174e58 100644 --- a/web/views/board.templ +++ b/web/views/board.templ @@ -52,13 +52,19 @@ templ Board(board database.Board, isAdmin bool) { type CatalogThreadPreview struct { Subject string Body string + ThreadId int ThreadURL string ThumbPath string ReplyCount int IpCount int } -templ ThreadsCatalog(previews []CatalogThreadPreview, isAdmin bool) { +type CatalogContext struct { + IsAdmin bool + BoardSlug string +} + +templ ThreadsCatalog(previews []CatalogThreadPreview, catalogContext CatalogContext) {
@templ.Raw(util.EnrichPost(preview.Body))
- if isAdmin { - + if catalogContext.IsAdmin { + }