diff --git a/entry.go b/entry.go index 0856e78..7932d68 100644 --- a/entry.go +++ b/entry.go @@ -28,26 +28,31 @@ type Entry struct { Username string `json:"username"` } -func handleFeed(w http.ResponseWriter, r *http.Request) { - page, _ := strconv.Atoi(chi.URLParam(r, "page")) +// feedPage liefert eine Feed-Seite (20 Beiträge, neueste zuerst). Ist uid != 0, +// werden nur die Beiträge dieses Nutzers geliefert. +func feedPage(page int, uid int64) ([]Entry, error) { if page < 0 { page = 0 } if page > 100 { page = 100 } - const count = 20 - offset := page * count - rows, err := db.Query(` + query := ` SELECT e.pid, e.uid, e.created_at, e.content, e.filepath, u.username - FROM entry e JOIN user u ON u.uid = e.uid - ORDER BY e.created_at DESC - LIMIT ? OFFSET ?`, count, offset) + FROM entry e JOIN user u ON u.uid = e.uid` + args := []any{} + if uid != 0 { + query += ` WHERE e.uid = ?` + args = append(args, uid) + } + query += ` ORDER BY e.created_at DESC LIMIT ? OFFSET ?` + args = append(args, count, page*count) + + rows, err := db.Query(query, args...) if err != nil { - writeError(w, http.StatusInternalServerError, "Datenbankfehler") - return + return nil, err } defer rows.Close() @@ -59,6 +64,33 @@ func handleFeed(w http.ResponseWriter, r *http.Request) { } entries = append(entries, e) } + return entries, rows.Err() +} + +func handleFeed(w http.ResponseWriter, r *http.Request) { + page, _ := strconv.Atoi(chi.URLParam(r, "page")) + entries, err := feedPage(page, 0) + if err != nil { + writeError(w, http.StatusInternalServerError, "Datenbankfehler") + return + } + writeJSON(w, http.StatusOK, entries) +} + +// handleUserFeed liefert den Feed eines einzelnen Nutzers (öffentlich). +func handleUserFeed(w http.ResponseWriter, r *http.Request) { + var uid int64 + if err := db.QueryRow(`SELECT uid FROM user WHERE username = ?`, chi.URLParam(r, "username")).Scan(&uid); err != nil { + writeError(w, http.StatusNotFound, "Nutzer nicht gefunden") + return + } + + page, _ := strconv.Atoi(chi.URLParam(r, "page")) + entries, err := feedPage(page, uid) + if err != nil { + writeError(w, http.StatusInternalServerError, "Datenbankfehler") + return + } writeJSON(w, http.StatusOK, entries) } diff --git a/main.go b/main.go index 7498861..bd1999f 100644 --- a/main.go +++ b/main.go @@ -39,7 +39,9 @@ func routes() http.Handler { r.Get("/entry/{pid}/votes", handleVotes) // --- User (öffentlich) --- - r.Get("/u/{username}", handleUserPage) + r.Get("/u/{username}", serveUserPage) + r.Get("/u/{username}/info", handleUserPage) + r.Get("/u/{username}/feed/{page}", handleUserFeed) // --- Geschützt (Session erforderlich) --- r.Group(func(r chi.Router) { diff --git a/user.go b/user.go index dd3c36f..51f8063 100644 --- a/user.go +++ b/user.go @@ -36,6 +36,12 @@ func idFromUsername(username string) int64 { return id } +// serveUserPage liefert die statische Profilseite; das Frontend lädt die Daten +// dann über /u/{username}/info und /u/{username}/feed/{page}. +func serveUserPage(w http.ResponseWriter, r *http.Request) { + http.ServeFile(w, r, "web/user.html") +} + func handleUserPage(w http.ResponseWriter, r *http.Request) { username := chi.URLParam(r, "username") diff --git a/web/index.html b/web/index.html index e483566..2680fbe 100644 --- a/web/index.html +++ b/web/index.html @@ -46,25 +46,12 @@
- -