forked from tangled.org/core
this repo has no description
1package notifications 2 3import ( 4 "log" 5 "net/http" 6 "strconv" 7 8 "github.com/go-chi/chi/v5" 9 "tangled.org/core/appview/db" 10 "tangled.org/core/appview/middleware" 11 "tangled.org/core/appview/oauth" 12 "tangled.org/core/appview/pages" 13 "tangled.org/core/appview/pagination" 14) 15 16type Notifications struct { 17 db *db.DB 18 oauth *oauth.OAuth 19 pages *pages.Pages 20} 21 22func New(database *db.DB, oauthHandler *oauth.OAuth, pagesHandler *pages.Pages) *Notifications { 23 return &Notifications{ 24 db: database, 25 oauth: oauthHandler, 26 pages: pagesHandler, 27 } 28} 29 30func (n *Notifications) Router(mw *middleware.Middleware) http.Handler { 31 r := chi.NewRouter() 32 33 r.Use(middleware.AuthMiddleware(n.oauth)) 34 35 r.Get("/", n.notificationsPage) 36 37 r.Get("/count", n.getUnreadCount) 38 r.Post("/{id}/read", n.markRead) 39 r.Post("/read-all", n.markAllRead) 40 r.Delete("/{id}", n.deleteNotification) 41 42 return r 43} 44 45func (n *Notifications) notificationsPage(w http.ResponseWriter, r *http.Request) { 46 userDid := n.oauth.GetDid(r) 47 48 limitStr := r.URL.Query().Get("limit") 49 offsetStr := r.URL.Query().Get("offset") 50 51 limit := 20 // default 52 if limitStr != "" { 53 if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 { 54 limit = l 55 } 56 } 57 58 offset := 0 // default 59 if offsetStr != "" { 60 if o, err := strconv.Atoi(offsetStr); err == nil && o >= 0 { 61 offset = o 62 } 63 } 64 65 page := pagination.Page{Limit: limit + 1, Offset: offset} 66 notifications, err := db.GetNotificationsWithEntities(n.db, page, db.FilterEq("recipient_did", userDid)) 67 if err != nil { 68 log.Println("failed to get notifications:", err) 69 n.pages.Error500(w) 70 return 71 } 72 73 hasMore := len(notifications) > limit 74 if hasMore { 75 notifications = notifications[:limit] 76 } 77 78 err = n.db.MarkAllNotificationsRead(r.Context(), userDid) 79 if err != nil { 80 log.Println("failed to mark notifications as read:", err) 81 } 82 83 unreadCount := 0 84 85 user := n.oauth.GetUser(r) 86 if user == nil { 87 http.Error(w, "Failed to get user", http.StatusInternalServerError) 88 return 89 } 90 91 params := pages.NotificationsParams{ 92 LoggedInUser: user, 93 Notifications: notifications, 94 UnreadCount: unreadCount, 95 HasMore: hasMore, 96 NextOffset: offset + limit, 97 Limit: limit, 98 } 99 100 err = n.pages.Notifications(w, params) 101 if err != nil { 102 log.Println("failed to load notifs:", err) 103 n.pages.Error500(w) 104 return 105 } 106} 107 108func (n *Notifications) getUnreadCount(w http.ResponseWriter, r *http.Request) { 109 userDid := n.oauth.GetDid(r) 110 111 count, err := n.db.GetUnreadNotificationCount(r.Context(), userDid) 112 if err != nil { 113 http.Error(w, "Failed to get unread count", http.StatusInternalServerError) 114 return 115 } 116 117 params := pages.NotificationCountParams{ 118 Count: count, 119 } 120 err = n.pages.NotificationCount(w, params) 121 if err != nil { 122 http.Error(w, "Failed to render count", http.StatusInternalServerError) 123 return 124 } 125} 126 127func (n *Notifications) markRead(w http.ResponseWriter, r *http.Request) { 128 userDid := n.oauth.GetDid(r) 129 130 idStr := chi.URLParam(r, "id") 131 notificationID, err := strconv.ParseInt(idStr, 10, 64) 132 if err != nil { 133 http.Error(w, "Invalid notification ID", http.StatusBadRequest) 134 return 135 } 136 137 err = n.db.MarkNotificationRead(r.Context(), notificationID, userDid) 138 if err != nil { 139 http.Error(w, "Failed to mark notification as read", http.StatusInternalServerError) 140 return 141 } 142 143 w.WriteHeader(http.StatusNoContent) 144} 145 146func (n *Notifications) markAllRead(w http.ResponseWriter, r *http.Request) { 147 userDid := n.oauth.GetDid(r) 148 149 err := n.db.MarkAllNotificationsRead(r.Context(), userDid) 150 if err != nil { 151 http.Error(w, "Failed to mark all notifications as read", http.StatusInternalServerError) 152 return 153 } 154 155 http.Redirect(w, r, "/notifications", http.StatusSeeOther) 156} 157 158func (n *Notifications) deleteNotification(w http.ResponseWriter, r *http.Request) { 159 userDid := n.oauth.GetDid(r) 160 161 idStr := chi.URLParam(r, "id") 162 notificationID, err := strconv.ParseInt(idStr, 10, 64) 163 if err != nil { 164 http.Error(w, "Invalid notification ID", http.StatusBadRequest) 165 return 166 } 167 168 err = n.db.DeleteNotification(r.Context(), notificationID, userDid) 169 if err != nil { 170 http.Error(w, "Failed to delete notification", http.StatusInternalServerError) 171 return 172 } 173 174 w.WriteHeader(http.StatusOK) 175}