This commit is contained in:
ponzischeme89
2026-08-27 15:50:15 +12:00
parent 6b2bf767e2
commit 2f4bd0da31
19 changed files with 456 additions and 144 deletions
+104 -2
View File
@@ -26,10 +26,21 @@ type myShowsResponse struct {
}
type notificationsResponse struct {
Notifications []store.UserNotification `json:"notifications"`
Notifications []notificationResponse `json:"notifications"`
Preferences store.NotificationPreferences `json:"preferences"`
}
type notificationAction struct {
Kind string `json:"kind"`
Label string `json:"label"`
CompletedLabel string `json:"completedLabel"`
}
type notificationResponse struct {
store.UserNotification
Action *notificationAction `json:"action,omitempty"`
}
func (s *Server) handleMyShows(w http.ResponseWriter, r *http.Request, sess store.Session) {
switch r.Method {
case http.MethodGet:
@@ -178,12 +189,73 @@ func (s *Server) handleNotifications(w http.ResponseWriter, r *http.Request, ses
writeError(w, http.StatusInternalServerError, "could not load notifications")
return
}
visible := filterStoredNotifications(notifications, prefs)
shows := []store.UserShow{}
if value, showsErr := s.store.UserShows(r.Context(), sess.EmbyUserID); showsErr == nil {
shows = value
} else {
s.loggerFor(r.Context()).Warn("My Shows unavailable for notification actions", "error", showsErr)
}
sonarrSeries := []sonarr.Series{}
if s.sonarrEnabled(r.Context()) {
if value, seriesErr := s.sonarrSeriesCatalogue(r.Context()); seriesErr == nil {
sonarrSeries = value
} else {
s.loggerFor(r.Context()).Warn("Sonarr status unavailable for notifications", "error", seriesErr)
}
}
writeJSON(w, http.StatusOK, notificationsResponse{
Notifications: filterStoredNotifications(notifications, prefs),
Notifications: notificationResponses(visible, shows, sonarrSeries),
Preferences: prefs,
})
}
func notificationResponses(
notifications []store.UserNotification, shows []store.UserShow, series []sonarr.Series,
) []notificationResponse {
showItemsBySeriesKey := map[string]string{}
for _, show := range shows {
matched := matchSonarrSeries(show, series)
if matched == nil {
continue
}
seriesKey := sonarrSeriesStatusKey(*matched)
if seriesKey == "" || strings.TrimSpace(show.ItemID) == "" {
continue
}
showItemsBySeriesKey[seriesKey] = show.ItemID
}
result := make([]notificationResponse, 0, len(notifications))
for _, notification := range notifications {
response := notificationResponse{UserNotification: notification}
if notification.Kind == "show-cancelled" {
if itemID := showItemsBySeriesKey[notificationSeriesKey(notification.SourceKey)]; itemID != "" {
response.ItemID = itemID
response.Action = &notificationAction{
Kind: "remove-my-show",
Label: "Remove from My Shows",
CompletedLabel: "Removed from My Shows",
}
}
}
result = append(result, response)
}
return result
}
func notificationSeriesKey(sourceKey string) string {
const prefix = "show-cancelled:"
if !strings.HasPrefix(sourceKey, prefix) {
return ""
}
trimmed := strings.TrimPrefix(sourceKey, prefix)
cut := strings.LastIndex(trimmed, ":")
if cut <= 0 {
return ""
}
return trimmed[:cut]
}
func (s *Server) syncReturnNotifications(
r *http.Request, sess store.Session, prefs store.NotificationPreferences,
) {
@@ -314,6 +386,8 @@ func (s *Server) handleNotificationAction(
err = s.store.MarkNotificationUnread(r.Context(), sess.EmbyUserID, id)
case "dismiss":
err = s.store.DismissNotification(r.Context(), sess.EmbyUserID, id)
case "remove-my-show":
err = s.removeMyShowFromNotification(r, sess, id)
default:
writeError(w, http.StatusNotFound, "unknown notification action")
return
@@ -325,6 +399,34 @@ func (s *Server) handleNotificationAction(
w.WriteHeader(http.StatusNoContent)
}
func (s *Server) removeMyShowFromNotification(
r *http.Request, sess store.Session, notificationID int64,
) error {
notifications, err := s.store.UserNotifications(r.Context(), sess.EmbyUserID)
if err != nil {
return err
}
shows, err := s.store.UserShows(r.Context(), sess.EmbyUserID)
if err != nil {
return err
}
series := []sonarr.Series{}
if s.sonarrEnabled(r.Context()) {
value, err := s.sonarrSeriesCatalogue(r.Context())
if err != nil {
return err
}
series = value
}
for _, notification := range notificationResponses(notifications, shows, series) {
if notification.ID != notificationID || notification.Action == nil || notification.ItemID == "" {
continue
}
return s.store.DeleteUserShow(r.Context(), sess.EmbyUserID, notification.ItemID)
}
return nil
}
func decodeJSON(w http.ResponseWriter, r *http.Request, out any) bool {
decoder := json.NewDecoder(http.MaxBytesReader(w, r.Body, 64<<10))
decoder.DisallowUnknownFields()