diff --git a/config/entertainment/media.yml b/config/entertainment/media.yml
new file mode 100644
index 0000000..7c70c7d
--- /dev/null
+++ b/config/entertainment/media.yml
@@ -0,0 +1,293 @@
+# Media — single column: Continue Watching, then Latest Movies, then Latest Shows.
+# One Jellyfin template shared across all three via the &jellyfin-tpl anchor.
+- size: full
+ widgets:
+ - type: custom-api
+ title: Continue Watching
+ frameless: true
+ cache: 5m
+ options:
+ base-url: ${JELLYFIN_URL}
+ api-key: ${JELLYFIN_KEY}
+ user-name: "prad"
+ mode: "resume"
+ item-count: "12"
+ small-column: false
+ show-thumbnail: true
+ thumbnail-aspect-ratio: "landscape"
+ template: &jellyfin-tpl |
+ {{/* Required config options */}}
+ {{ $baseURL := .Options.StringOr "base-url" "" }}
+ {{ $apiKey := .Options.StringOr "api-key" "" }}
+ {{ $userName := .Options.StringOr "user-name" "" }}
+
+ {{/* Required config options for "latest" mode */}}
+ {{ $libraryName := .Options.StringOr "library-name" "" }}
+
+ {{/* Optional config options */}}
+ {{ $mode := .Options.StringOr "mode" "latest" }}
+ {{ $itemCount := .Options.StringOr "item-count" "10" }}
+ {{ $mediaTypes := .Options.StringOr "media-types" "Movie,Episode,MusicAlbum" }}
+ {{ $thumbAspectRatio := .Options.StringOr "thumbnail-aspect-ratio" "" }}
+ {{ $isSmallColumn:= .Options.BoolOr "small-column" false }}
+ {{ $showThumbnail := .Options.BoolOr "show-thumbnail" false }}
+ {{ $showProgressBar := .Options.BoolOr "progress-bar" true }}
+
+ {{/* Error message template */}}
+ {{ define "errorMsg" }}
+
+ {{ . }}
+ {{ end }}
+
+ {{/* Check required fields */}}
+ {{ if or (eq $baseURL "") (eq $apiKey "") (eq $userName "") (eq $mode "") (and (eq $mode "latest") (eq $libraryName "")) }}
+ {{ template "errorMsg" "Some required options are not set." }}
+ {{ else }}
+
+ {{/* Fetch user ID */}}
+ {{ $userID := "" }}
+ {{ $usersCall := newRequest (print $baseURL "/Users")
+ | withParameter "api_key" $apiKey
+ | withHeader "Accept" "application/json"
+ | getResponse }}
+
+ {{ range $i, $user := $usersCall.JSON.Array "" }}
+ {{ if eq ($user.String "Name") $userName }}
+ {{ $userID = $user.String "Id" }}
+ {{ break }}
+ {{ end }}
+ {{ end }}
+ {{ if eq $userID "" }}
+ {{ template "errorMsg" (printf "User '%s' not found." $userName) }}
+ {{ else }}
+
+ {{ $items := "" }}
+
+ {{ if eq $mode "latest" }}
+
+ {{/* Fetch library ID */}}
+ {{ $libraryID := "" }}
+ {{ $userViewsCall := newRequest (print $baseURL "/UserViews")
+ | withParameter "api_key" $apiKey
+ | withParameter "userId" $userID
+ | withHeader "Accept" "application/json"
+ | getResponse }}
+
+ {{ range $i, $item := $userViewsCall.JSON.Array "Items" }}
+ {{ if eq ($item.String "Name") $libraryName }}
+ {{ $libraryID = $item.String "Id" }}
+ {{ break }}
+ {{ end }}
+ {{ end }}
+
+ {{ if eq $libraryID "" }}
+ {{ template "errorMsg" (printf "Library '%s' not found." $libraryName) }}
+ {{ else }}
+ {{/* Fetch latest items */}}
+ {{ $latestCall := newRequest (print $baseURL "/Users/" $userID "/Items/Latest")
+ | withParameter "api_key" $apiKey
+ | withParameter "Limit" $itemCount
+ | withParameter "ParentId" $libraryID
+ | withParameter "IncludeItemTypes" $mediaTypes
+ | withParameter "GroupItems" "true"
+ | withHeader "Accept" "application/json"
+ | getResponse }}
+ {{ $items = $latestCall.JSON.Array "" }}
+ {{ end }}
+
+ {{ else if eq $mode "nextup" }}
+
+ {{/* Fetch next up items */}}
+ {{ $nextUpCall := newRequest (print $baseURL "/Shows/NextUp")
+ | withParameter "api_key" $apiKey
+ | withParameter "UserId" $userID
+ | withParameter "Limit" $itemCount
+ | withParameter "EnableResumable" "true"
+ | withHeader "Accept" "application/json"
+ | getResponse }}
+ {{ $items = $nextUpCall.JSON.Array "Items" }}
+
+ {{ else if eq $mode "resume" }}
+
+ {{/* Fetch in-progress (continue watching) items — movies and episodes */}}
+ {{ $resumeCall := newRequest (print $baseURL "/Users/" $userID "/Items/Resume")
+ | withParameter "api_key" $apiKey
+ | withParameter "Limit" $itemCount
+ | withParameter "MediaTypes" "Video"
+ | withHeader "Accept" "application/json"
+ | getResponse }}
+ {{ $items = $resumeCall.JSON.Array "Items" }}
+
+ {{ else }}
+ {{ template "errorMsg" "Unknown mode, expected 'latest', 'nextup' or 'resume'" }}
+ {{ end }}
+
+ {{ if eq (len $items) 0 }}
+ No items found, start streaming something!
+ {{ else }}
+
+ {{/* Display the item carousel */}}
+
+
+ {{ range $n, $item := $items }}
+ {{/* Common item variables */}}
+ {{ $mediaType := $item.String "Type" }}
+ {{ $title := $item.String "Name" }}
+ {{ $itemID := $item.String "Id" }}
+
+ {{/* Media type specific variables */}}
+ {{ $seriesTitle := "" }}
+ {{ $artist := "" }}
+ {{ $seriesID := "" }}
+ {{ $season := "" }}
+ {{ $episode := "" }}
+ {{ $playPercentage := "" }}
+ {{ $unwatchedEpisodeCount := "" }}
+
+ {{ if eq $mediaType "Movie" }}
+ {{ if $item.Exists "UserData.PlayedPercentage" }}
+ {{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
+ {{ end }}
+ {{ else if eq $mediaType "Series" }}
+ {{ $unwatchedEpisodeCount = $item.Int "UserData.UnplayedItemCount" }}
+ {{ else if eq $mediaType "Episode" }}
+ {{ $unwatchedEpisodeCount = 1 }}
+ {{ $seriesTitle = $item.String "SeriesName" }}
+ {{ $seriesID = $item.String "SeriesId" }}
+ {{ $season = $item.Int "ParentIndexNumber" }}
+ {{ $episode = $item.Int "IndexNumber" }}
+
+ {{ if $item.Exists "UserData.PlayedPercentage" }}
+ {{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
+ {{ end }}
+
+ {{/* For latest always refer to the series not individual episodes */}}
+ {{ if eq $mode "latest" }}
+ {{ $itemID = $seriesID }}
+ {{ $title = $seriesTitle }}
+ {{ end }}
+ {{ else if eq $mediaType "MusicAlbum" }}
+ {{ $artist = $item.String "AlbumArtist" }}
+ {{ end }}
+
+ {{ $linkURL := print $baseURL "/web/#/details?id=" $itemID }}
+ {{ $thumbURL := concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
+
+
+ {{ if $showThumbnail }}
+
+

+
+ {{ if and ($showProgressBar) (not (eq $playPercentage "")) }}
+
+ {{ end }}
+
+ {{ end }}
+
+
+
+ {{ end }}
+
+
+ {{ end }}
+
+ {{ end }}
+
+ {{ end }}
+
+ - type: custom-api
+ title: Latest Movies
+ frameless: true
+ cache: 5m
+ options:
+ base-url: ${JELLYFIN_URL}
+ api-key: ${JELLYFIN_KEY}
+ user-name: "prad"
+ library-name: "Movies"
+ mode: "latest"
+ item-count: "12"
+ small-column: false
+ show-thumbnail: true
+ thumbnail-aspect-ratio: "portrait"
+ template: *jellyfin-tpl
+
+ - type: custom-api
+ title: Latest Shows
+ frameless: true
+ cache: 5m
+ options:
+ base-url: ${JELLYFIN_URL}
+ api-key: ${JELLYFIN_KEY}
+ user-name: "prad"
+ library-name: "TV"
+ mode: "latest"
+ item-count: "12"
+ small-column: false
+ show-thumbnail: true
+ thumbnail-aspect-ratio: "portrait"
+ template: *jellyfin-tpl
diff --git a/config/entertainment/movies.yml b/config/entertainment/movies.yml
deleted file mode 100644
index 69f5c16..0000000
--- a/config/entertainment/movies.yml
+++ /dev/null
@@ -1,492 +0,0 @@
-- size: full
- widgets:
- - type: custom-api
- title: Latest Movies
- frameless: true
- cache: 5m
- options:
- base-url: http://nukala.local:8096
- api-key: df9e869fec0b460bb6577302f5efd049
- user-name: "prad"
- library-name: "Movies"
- mode: "latest"
- item-count: "10"
- small-column: false
- show-thumbnail: true
- thumbnail-aspect-ratio: "default"
- template: |
- {{/* Required config options */}}
- {{ $baseURL := .Options.StringOr "base-url" "" }}
- {{ $apiKey := .Options.StringOr "api-key" "" }}
- {{ $userName := .Options.StringOr "user-name" "" }}
-
- {{/* Required config options for "latest" mode */}}
- {{ $libraryName := .Options.StringOr "library-name" "" }}
-
- {{/* Optional config options */}}
- {{ $mode := .Options.StringOr "mode" "latest" }}
- {{ $itemCount := .Options.StringOr "item-count" "10" }}
- {{ $mediaTypes := .Options.StringOr "media-types" "Movie,Episode,MusicAlbum" }}
- {{ $thumbAspectRatio := .Options.StringOr "thumbnail-aspect-ratio" "" }}
- {{ $isSmallColumn:= .Options.BoolOr "small-column" false }}
- {{ $showThumbnail := .Options.BoolOr "show-thumbnail" false }}
- {{ $showProgressBar := .Options.BoolOr "progress-bar" true }}
-
- {{/* Error message template */}}
- {{ define "errorMsg" }}
-
- {{ . }}
- {{ end }}
-
- {{/* Check required fields */}}
- {{ if or (eq $baseURL "") (eq $apiKey "") (eq $userName "") (eq $mode "") (and (eq $mode "latest") (eq $libraryName "")) }}
- {{ template "errorMsg" "Some required options are not set." }}
- {{ else }}
-
- {{/* Fetch user ID */}}
- {{ $userID := "" }}
- {{ $usersCall := newRequest (print $baseURL "/Users")
- | withParameter "api_key" $apiKey
- | withHeader "Accept" "application/json"
- | getResponse }}
-
- {{ range $i, $user := $usersCall.JSON.Array "" }}
- {{ if eq ($user.String "Name") $userName }}
- {{ $userID = $user.String "Id" }}
- {{ break }}
- {{ end }}
- {{ end }}
- {{ if eq $userID "" }}
- {{ template "errorMsg" (printf "User '%s' not found." $userName) }}
- {{ else }}
-
- {{ $items := "" }}
-
- {{ if eq $mode "latest" }}
-
- {{/* Fetch library ID */}}
- {{ $libraryID := "" }}
- {{ $userViewsCall := newRequest (print $baseURL "/UserViews")
- | withParameter "api_key" $apiKey
- | withParameter "userId" $userID
- | withHeader "Accept" "application/json"
- | getResponse }}
-
- {{ range $i, $item := $userViewsCall.JSON.Array "Items" }}
- {{ if eq ($item.String "Name") $libraryName }}
- {{ $libraryID = $item.String "Id" }}
- {{ break }}
- {{ end }}
- {{ end }}
-
- {{ if eq $libraryID "" }}
- {{ template "errorMsg" (printf "Library '%s' not found." $libraryName) }}
- {{ else }}
- {{/* Fetch latest items */}}
- {{ $latestCall := newRequest (print $baseURL "/Users/" $userID "/Items/Latest")
- | withParameter "api_key" $apiKey
- | withParameter "Limit" $itemCount
- | withParameter "ParentId" $libraryID
- | withParameter "IncludeItemTypes" $mediaTypes
- | withParameter "GroupItems" "true"
- | withHeader "Accept" "application/json"
- | getResponse }}
- {{ $items = $latestCall.JSON.Array "" }}
- {{ end }}
-
- {{ else if eq $mode "nextup" }}
-
- {{/* Fetch next up items */}}
- {{ $nextUpCall := newRequest (print $baseURL "/Shows/NextUp")
- | withParameter "api_key" $apiKey
- | withParameter "UserId" $userID
- | withParameter "Limit" $itemCount
- | withParameter "EnableResumable" "true"
- | withHeader "Accept" "application/json"
- | getResponse }}
- {{ $items = $nextUpCall.JSON.Array "Items" }}
-
- {{ else }}
- {{ template "errorMsg" "Unknown mode, expected 'latest' or 'nextup'" }}
- {{ end }}
-
- {{ if eq (len $items) 0 }}
- No items found, start streaming something!
- {{ else }}
-
- {{/* Display the item carousel */}}
-
-
- {{ range $n, $item := $items }}
- {{/* Common item variables */}}
- {{ $mediaType := $item.String "Type" }}
- {{ $title := $item.String "Name" }}
- {{ $itemID := $item.String "Id" }}
-
- {{/* Media type specific variables */}}
- {{ $seriesTitle := "" }}
- {{ $artist := "" }}
- {{ $seriesID := "" }}
- {{ $season := "" }}
- {{ $episode := "" }}
- {{ $playPercentage := "" }}
- {{ $unwatchedEpisodeCount := "" }}
-
- {{ if eq $mediaType "Movie" }}
- {{ else if eq $mediaType "Series" }}
- {{ $unwatchedEpisodeCount = $item.Int "UserData.UnplayedItemCount" }}
- {{ else if eq $mediaType "Episode" }}
- {{ $unwatchedEpisodeCount = 1 }}
- {{ $seriesTitle = $item.String "SeriesName" }}
- {{ $seriesID = $item.String "SeriesId" }}
- {{ $season = $item.Int "ParentIndexNumber" }}
- {{ $episode = $item.Int "IndexNumber" }}
-
- {{ if $item.Exists "UserData.PlayedPercentage" }}
- {{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
- {{ end }}
-
- {{/* For latest always refer to the series not individual episodes */}}
- {{ if eq $mode "latest" }}
- {{ $itemID = $seriesID }}
- {{ $title = $seriesTitle }}
- {{ end }}
- {{ else if eq $mediaType "MusicAlbum" }}
- {{ $artist = $item.String "AlbumArtist" }}
- {{ end }}
-
- {{ $linkURL := print $baseURL "/web/#/details?id=" $itemID }}
- {{ $thumbURL := "" }}
- {{ if not (eq $playPercentage "") }}
- {{/* $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey "&percentPlayed=" $playPercentage */}}
- {{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
- {{ else }}
- {{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
- {{ end }}
-
-
- {{ if $showThumbnail }}
-
-

-
- {{ if and ($showProgressBar) (not (eq $playPercentage "")) }}
-
- {{ end }}
-
- {{ end }}
-
-
-
- {{ end }}
-
-
- {{ end }}
-
- {{ end }}
-
- {{ end }}
- - type: custom-api
- title: Up Next Movies
- frameless: true
- cache: 5m
- options:
- base-url: http://nukala.local:8096
- api-key: df9e869fec0b460bb6577302f5efd049
- user-name: "prad"
- library-name: "Movies"
- mode: "nextup"
- item-count: "10"
- small-column: false
- show-thumbnail: true
- thumbnail-aspect-ratio: "default"
- template: |
- {{/* Required config options */}}
- {{ $baseURL := .Options.StringOr "base-url" "" }}
- {{ $apiKey := .Options.StringOr "api-key" "" }}
- {{ $userName := .Options.StringOr "user-name" "" }}
-
- {{/* Required config options for "latest" mode */}}
- {{ $libraryName := .Options.StringOr "library-name" "" }}
-
- {{/* Optional config options */}}
- {{ $mode := .Options.StringOr "mode" "latest" }}
- {{ $itemCount := .Options.StringOr "item-count" "10" }}
- {{ $mediaTypes := .Options.StringOr "media-types" "Movie,Episode,MusicAlbum" }}
- {{ $thumbAspectRatio := .Options.StringOr "thumbnail-aspect-ratio" "" }}
- {{ $isSmallColumn:= .Options.BoolOr "small-column" false }}
- {{ $showThumbnail := .Options.BoolOr "show-thumbnail" false }}
- {{ $showProgressBar := .Options.BoolOr "progress-bar" true }}
-
- {{/* Error message template */}}
- {{ define "errorMsg" }}
-
- {{ . }}
- {{ end }}
-
- {{/* Check required fields */}}
- {{ if or (eq $baseURL "") (eq $apiKey "") (eq $userName "") (eq $mode "") (and (eq $mode "latest") (eq $libraryName "")) }}
- {{ template "errorMsg" "Some required options are not set." }}
- {{ else }}
-
- {{/* Fetch user ID */}}
- {{ $userID := "" }}
- {{ $usersCall := newRequest (print $baseURL "/Users")
- | withParameter "api_key" $apiKey
- | withHeader "Accept" "application/json"
- | getResponse }}
-
- {{ range $i, $user := $usersCall.JSON.Array "" }}
- {{ if eq ($user.String "Name") $userName }}
- {{ $userID = $user.String "Id" }}
- {{ break }}
- {{ end }}
- {{ end }}
- {{ if eq $userID "" }}
- {{ template "errorMsg" (printf "User '%s' not found." $userName) }}
- {{ else }}
-
- {{ $items := "" }}
-
- {{ if eq $mode "latest" }}
-
- {{/* Fetch library ID */}}
- {{ $libraryID := "" }}
- {{ $userViewsCall := newRequest (print $baseURL "/UserViews")
- | withParameter "api_key" $apiKey
- | withParameter "userId" $userID
- | withHeader "Accept" "application/json"
- | getResponse }}
-
- {{ range $i, $item := $userViewsCall.JSON.Array "Items" }}
- {{ if eq ($item.String "Name") $libraryName }}
- {{ $libraryID = $item.String "Id" }}
- {{ break }}
- {{ end }}
- {{ end }}
-
- {{ if eq $libraryID "" }}
- {{ template "errorMsg" (printf "Library '%s' not found." $libraryName) }}
- {{ else }}
- {{/* Fetch latest items */}}
- {{ $latestCall := newRequest (print $baseURL "/Users/" $userID "/Items/Latest")
- | withParameter "api_key" $apiKey
- | withParameter "Limit" $itemCount
- | withParameter "ParentId" $libraryID
- | withParameter "IncludeItemTypes" $mediaTypes
- | withParameter "GroupItems" "true"
- | withHeader "Accept" "application/json"
- | getResponse }}
- {{ $items = $latestCall.JSON.Array "" }}
- {{ end }}
-
- {{ else if eq $mode "nextup" }}
-
- {{/* Fetch next up items */}}
- {{ $nextUpCall := newRequest (print $baseURL "/Shows/NextUp")
- | withParameter "api_key" $apiKey
- | withParameter "UserId" $userID
- | withParameter "Limit" $itemCount
- | withParameter "EnableResumable" "true"
- | withHeader "Accept" "application/json"
- | getResponse }}
- {{ $items = $nextUpCall.JSON.Array "Items" }}
-
- {{ else }}
- {{ template "errorMsg" "Unknown mode, expected 'latest' or 'nextup'" }}
- {{ end }}
-
- {{ if eq (len $items) 0 }}
- No items found, start streaming something!
- {{ else }}
-
- {{/* Display the item carousel */}}
-
-
- {{ range $n, $item := $items }}
- {{/* Common item variables */}}
- {{ $mediaType := $item.String "Type" }}
- {{ $title := $item.String "Name" }}
- {{ $itemID := $item.String "Id" }}
-
- {{/* Media type specific variables */}}
- {{ $seriesTitle := "" }}
- {{ $artist := "" }}
- {{ $seriesID := "" }}
- {{ $season := "" }}
- {{ $episode := "" }}
- {{ $playPercentage := "" }}
- {{ $unwatchedEpisodeCount := "" }}
-
- {{ if eq $mediaType "Movie" }}
- {{ else if eq $mediaType "Series" }}
- {{ $unwatchedEpisodeCount = $item.Int "UserData.UnplayedItemCount" }}
- {{ else if eq $mediaType "Episode" }}
- {{ $unwatchedEpisodeCount = 1 }}
- {{ $seriesTitle = $item.String "SeriesName" }}
- {{ $seriesID = $item.String "SeriesId" }}
- {{ $season = $item.Int "ParentIndexNumber" }}
- {{ $episode = $item.Int "IndexNumber" }}
-
- {{ if $item.Exists "UserData.PlayedPercentage" }}
- {{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
- {{ end }}
-
- {{/* For latest always refer to the series not individual episodes */}}
- {{ if eq $mode "latest" }}
- {{ $itemID = $seriesID }}
- {{ $title = $seriesTitle }}
- {{ end }}
- {{ else if eq $mediaType "MusicAlbum" }}
- {{ $artist = $item.String "AlbumArtist" }}
- {{ end }}
-
- {{ $linkURL := print $baseURL "/web/#/details?id=" $itemID }}
- {{ $thumbURL := "" }}
- {{ if not (eq $playPercentage "") }}
- {{/* $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey "&percentPlayed=" $playPercentage */}}
- {{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
- {{ else }}
- {{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
- {{ end }}
-
-
- {{ if $showThumbnail }}
-
-

-
- {{ if and ($showProgressBar) (not (eq $playPercentage "")) }}
-
- {{ end }}
-
- {{ end }}
-
-
-
- {{ end }}
-
-
- {{ end }}
-
- {{ end }}
-
- {{ end }}
diff --git a/config/entertainment/tv.yml b/config/entertainment/tv.yml
deleted file mode 100644
index a6dd407..0000000
--- a/config/entertainment/tv.yml
+++ /dev/null
@@ -1,492 +0,0 @@
-- size: full
- widgets:
- - type: custom-api
- title: Latest TV
- frameless: true
- cache: 5m
- options:
- base-url: http://nukala.local:8096
- api-key: df9e869fec0b460bb6577302f5efd049
- user-name: "prad"
- library-name: "TV"
- mode: "latest"
- item-count: "10"
- small-column: false
- show-thumbnail: true
- thumbnail-aspect-ratio: "default"
- template: |
- {{/* Required config options */}}
- {{ $baseURL := .Options.StringOr "base-url" "" }}
- {{ $apiKey := .Options.StringOr "api-key" "" }}
- {{ $userName := .Options.StringOr "user-name" "" }}
-
- {{/* Required config options for "latest" mode */}}
- {{ $libraryName := .Options.StringOr "library-name" "" }}
-
- {{/* Optional config options */}}
- {{ $mode := .Options.StringOr "mode" "latest" }}
- {{ $itemCount := .Options.StringOr "item-count" "10" }}
- {{ $mediaTypes := .Options.StringOr "media-types" "Movie,Episode,MusicAlbum" }}
- {{ $thumbAspectRatio := .Options.StringOr "thumbnail-aspect-ratio" "" }}
- {{ $isSmallColumn:= .Options.BoolOr "small-column" false }}
- {{ $showThumbnail := .Options.BoolOr "show-thumbnail" false }}
- {{ $showProgressBar := .Options.BoolOr "progress-bar" true }}
-
- {{/* Error message template */}}
- {{ define "errorMsg" }}
-
- {{ . }}
- {{ end }}
-
- {{/* Check required fields */}}
- {{ if or (eq $baseURL "") (eq $apiKey "") (eq $userName "") (eq $mode "") (and (eq $mode "latest") (eq $libraryName "")) }}
- {{ template "errorMsg" "Some required options are not set." }}
- {{ else }}
-
- {{/* Fetch user ID */}}
- {{ $userID := "" }}
- {{ $usersCall := newRequest (print $baseURL "/Users")
- | withParameter "api_key" $apiKey
- | withHeader "Accept" "application/json"
- | getResponse }}
-
- {{ range $i, $user := $usersCall.JSON.Array "" }}
- {{ if eq ($user.String "Name") $userName }}
- {{ $userID = $user.String "Id" }}
- {{ break }}
- {{ end }}
- {{ end }}
- {{ if eq $userID "" }}
- {{ template "errorMsg" (printf "User '%s' not found." $userName) }}
- {{ else }}
-
- {{ $items := "" }}
-
- {{ if eq $mode "latest" }}
-
- {{/* Fetch library ID */}}
- {{ $libraryID := "" }}
- {{ $userViewsCall := newRequest (print $baseURL "/UserViews")
- | withParameter "api_key" $apiKey
- | withParameter "userId" $userID
- | withHeader "Accept" "application/json"
- | getResponse }}
-
- {{ range $i, $item := $userViewsCall.JSON.Array "Items" }}
- {{ if eq ($item.String "Name") $libraryName }}
- {{ $libraryID = $item.String "Id" }}
- {{ break }}
- {{ end }}
- {{ end }}
-
- {{ if eq $libraryID "" }}
- {{ template "errorMsg" (printf "Library '%s' not found." $libraryName) }}
- {{ else }}
- {{/* Fetch latest items */}}
- {{ $latestCall := newRequest (print $baseURL "/Users/" $userID "/Items/Latest")
- | withParameter "api_key" $apiKey
- | withParameter "Limit" $itemCount
- | withParameter "ParentId" $libraryID
- | withParameter "IncludeItemTypes" $mediaTypes
- | withParameter "GroupItems" "true"
- | withHeader "Accept" "application/json"
- | getResponse }}
- {{ $items = $latestCall.JSON.Array "" }}
- {{ end }}
-
- {{ else if eq $mode "nextup" }}
-
- {{/* Fetch next up items */}}
- {{ $nextUpCall := newRequest (print $baseURL "/Shows/NextUp")
- | withParameter "api_key" $apiKey
- | withParameter "UserId" $userID
- | withParameter "Limit" $itemCount
- | withParameter "EnableResumable" "true"
- | withHeader "Accept" "application/json"
- | getResponse }}
- {{ $items = $nextUpCall.JSON.Array "Items" }}
-
- {{ else }}
- {{ template "errorMsg" "Unknown mode, expected 'latest' or 'nextup'" }}
- {{ end }}
-
- {{ if eq (len $items) 0 }}
- No items found, start streaming something!
- {{ else }}
-
- {{/* Display the item carousel */}}
-
-
- {{ range $n, $item := $items }}
- {{/* Common item variables */}}
- {{ $mediaType := $item.String "Type" }}
- {{ $title := $item.String "Name" }}
- {{ $itemID := $item.String "Id" }}
-
- {{/* Media type specific variables */}}
- {{ $seriesTitle := "" }}
- {{ $artist := "" }}
- {{ $seriesID := "" }}
- {{ $season := "" }}
- {{ $episode := "" }}
- {{ $playPercentage := "" }}
- {{ $unwatchedEpisodeCount := "" }}
-
- {{ if eq $mediaType "Movie" }}
- {{ else if eq $mediaType "Series" }}
- {{ $unwatchedEpisodeCount = $item.Int "UserData.UnplayedItemCount" }}
- {{ else if eq $mediaType "Episode" }}
- {{ $unwatchedEpisodeCount = 1 }}
- {{ $seriesTitle = $item.String "SeriesName" }}
- {{ $seriesID = $item.String "SeriesId" }}
- {{ $season = $item.Int "ParentIndexNumber" }}
- {{ $episode = $item.Int "IndexNumber" }}
-
- {{ if $item.Exists "UserData.PlayedPercentage" }}
- {{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
- {{ end }}
-
- {{/* For latest always refer to the series not individual episodes */}}
- {{ if eq $mode "latest" }}
- {{ $itemID = $seriesID }}
- {{ $title = $seriesTitle }}
- {{ end }}
- {{ else if eq $mediaType "MusicAlbum" }}
- {{ $artist = $item.String "AlbumArtist" }}
- {{ end }}
-
- {{ $linkURL := print $baseURL "/web/#/details?id=" $itemID }}
- {{ $thumbURL := "" }}
- {{ if not (eq $playPercentage "") }}
- {{/* $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey "&percentPlayed=" $playPercentage */}}
- {{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
- {{ else }}
- {{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
- {{ end }}
-
-
- {{ if $showThumbnail }}
-
-

-
- {{ if and ($showProgressBar) (not (eq $playPercentage "")) }}
-
- {{ end }}
-
- {{ end }}
-
-
-
- {{ end }}
-
-
- {{ end }}
-
- {{ end }}
-
- {{ end }}
- - type: custom-api
- title: Up Next TV
- frameless: true
- cache: 5m
- options:
- base-url: http://nukala.local:8096
- api-key: df9e869fec0b460bb6577302f5efd049
- user-name: "prad"
- library-name: "TV"
- mode: "nextup"
- item-count: "10"
- small-column: false
- show-thumbnail: true
- thumbnail-aspect-ratio: "default"
- template: |
- {{/* Required config options */}}
- {{ $baseURL := .Options.StringOr "base-url" "" }}
- {{ $apiKey := .Options.StringOr "api-key" "" }}
- {{ $userName := .Options.StringOr "user-name" "" }}
-
- {{/* Required config options for "latest" mode */}}
- {{ $libraryName := .Options.StringOr "library-name" "" }}
-
- {{/* Optional config options */}}
- {{ $mode := .Options.StringOr "mode" "latest" }}
- {{ $itemCount := .Options.StringOr "item-count" "10" }}
- {{ $mediaTypes := .Options.StringOr "media-types" "Movie,Episode,MusicAlbum" }}
- {{ $thumbAspectRatio := .Options.StringOr "thumbnail-aspect-ratio" "" }}
- {{ $isSmallColumn:= .Options.BoolOr "small-column" false }}
- {{ $showThumbnail := .Options.BoolOr "show-thumbnail" false }}
- {{ $showProgressBar := .Options.BoolOr "progress-bar" true }}
-
- {{/* Error message template */}}
- {{ define "errorMsg" }}
-
- {{ . }}
- {{ end }}
-
- {{/* Check required fields */}}
- {{ if or (eq $baseURL "") (eq $apiKey "") (eq $userName "") (eq $mode "") (and (eq $mode "latest") (eq $libraryName "")) }}
- {{ template "errorMsg" "Some required options are not set." }}
- {{ else }}
-
- {{/* Fetch user ID */}}
- {{ $userID := "" }}
- {{ $usersCall := newRequest (print $baseURL "/Users")
- | withParameter "api_key" $apiKey
- | withHeader "Accept" "application/json"
- | getResponse }}
-
- {{ range $i, $user := $usersCall.JSON.Array "" }}
- {{ if eq ($user.String "Name") $userName }}
- {{ $userID = $user.String "Id" }}
- {{ break }}
- {{ end }}
- {{ end }}
- {{ if eq $userID "" }}
- {{ template "errorMsg" (printf "User '%s' not found." $userName) }}
- {{ else }}
-
- {{ $items := "" }}
-
- {{ if eq $mode "latest" }}
-
- {{/* Fetch library ID */}}
- {{ $libraryID := "" }}
- {{ $userViewsCall := newRequest (print $baseURL "/UserViews")
- | withParameter "api_key" $apiKey
- | withParameter "userId" $userID
- | withHeader "Accept" "application/json"
- | getResponse }}
-
- {{ range $i, $item := $userViewsCall.JSON.Array "Items" }}
- {{ if eq ($item.String "Name") $libraryName }}
- {{ $libraryID = $item.String "Id" }}
- {{ break }}
- {{ end }}
- {{ end }}
-
- {{ if eq $libraryID "" }}
- {{ template "errorMsg" (printf "Library '%s' not found." $libraryName) }}
- {{ else }}
- {{/* Fetch latest items */}}
- {{ $latestCall := newRequest (print $baseURL "/Users/" $userID "/Items/Latest")
- | withParameter "api_key" $apiKey
- | withParameter "Limit" $itemCount
- | withParameter "ParentId" $libraryID
- | withParameter "IncludeItemTypes" $mediaTypes
- | withParameter "GroupItems" "true"
- | withHeader "Accept" "application/json"
- | getResponse }}
- {{ $items = $latestCall.JSON.Array "" }}
- {{ end }}
-
- {{ else if eq $mode "nextup" }}
-
- {{/* Fetch next up items */}}
- {{ $nextUpCall := newRequest (print $baseURL "/Shows/NextUp")
- | withParameter "api_key" $apiKey
- | withParameter "UserId" $userID
- | withParameter "Limit" $itemCount
- | withParameter "EnableResumable" "true"
- | withHeader "Accept" "application/json"
- | getResponse }}
- {{ $items = $nextUpCall.JSON.Array "Items" }}
-
- {{ else }}
- {{ template "errorMsg" "Unknown mode, expected 'latest' or 'nextup'" }}
- {{ end }}
-
- {{ if eq (len $items) 0 }}
- No items found, start streaming something!
- {{ else }}
-
- {{/* Display the item carousel */}}
-
-
- {{ range $n, $item := $items }}
- {{/* Common item variables */}}
- {{ $mediaType := $item.String "Type" }}
- {{ $title := $item.String "Name" }}
- {{ $itemID := $item.String "Id" }}
-
- {{/* Media type specific variables */}}
- {{ $seriesTitle := "" }}
- {{ $artist := "" }}
- {{ $seriesID := "" }}
- {{ $season := "" }}
- {{ $episode := "" }}
- {{ $playPercentage := "" }}
- {{ $unwatchedEpisodeCount := "" }}
-
- {{ if eq $mediaType "Movie" }}
- {{ else if eq $mediaType "Series" }}
- {{ $unwatchedEpisodeCount = $item.Int "UserData.UnplayedItemCount" }}
- {{ else if eq $mediaType "Episode" }}
- {{ $unwatchedEpisodeCount = 1 }}
- {{ $seriesTitle = $item.String "SeriesName" }}
- {{ $seriesID = $item.String "SeriesId" }}
- {{ $season = $item.Int "ParentIndexNumber" }}
- {{ $episode = $item.Int "IndexNumber" }}
-
- {{ if $item.Exists "UserData.PlayedPercentage" }}
- {{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
- {{ end }}
-
- {{/* For latest always refer to the series not individual episodes */}}
- {{ if eq $mode "latest" }}
- {{ $itemID = $seriesID }}
- {{ $title = $seriesTitle }}
- {{ end }}
- {{ else if eq $mediaType "MusicAlbum" }}
- {{ $artist = $item.String "AlbumArtist" }}
- {{ end }}
-
- {{ $linkURL := print $baseURL "/web/#/details?id=" $itemID }}
- {{ $thumbURL := "" }}
- {{ if not (eq $playPercentage "") }}
- {{/* $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey "&percentPlayed=" $playPercentage */}}
- {{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
- {{ else }}
- {{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
- {{ end }}
-
-
- {{ if $showThumbnail }}
-
-

-
- {{ if and ($showProgressBar) (not (eq $playPercentage "")) }}
-
- {{ end }}
-
- {{ end }}
-
-
-
- {{ end }}
-
-
- {{ end }}
-
- {{ end }}
-
- {{ end }}
diff --git a/config/glance.yml b/config/glance.yml
index a524ce9..38d9d6d 100644
--- a/config/glance.yml
+++ b/config/glance.yml
@@ -20,6 +20,7 @@ pages:
- $include: ./headlines/right.yml
- name: Finance
+ width: wide
columns:
- $include: ./markets/left.yml
- $include: ./markets/main.yml
@@ -39,6 +40,7 @@ pages:
- $include: ./schedule/right.yml
- name: Movies & TV
+ slug: movies
columns:
- - $include: ./entertainment/movies.yml
- - $include: ./entertainment/tv.yml
+ - $include: ./entertainment/side.yml
+ - $include: ./entertainment/media.yml
diff --git a/config/headlines/header.yml b/config/headlines/header.yml
index e3555ae..8431f1f 100644
--- a/config/headlines/header.yml
+++ b/config/headlines/header.yml
@@ -1,13 +1,4 @@
# Masthead + markets ticker — the newspaper banner
-- type: html
- source: |
-
-
- type: markets
hide-header: true
markets:
diff --git a/config/schedule/right.yml b/config/schedule/right.yml
index 5b79505..fcf630f 100644
--- a/config/schedule/right.yml
+++ b/config/schedule/right.yml
@@ -7,3 +7,11 @@
- type: to-do
title: Projects
id: projects
+ - type: rss
+ title: X Bookmarks
+ style: detailed-list
+ limit: 20
+ collapse-after: 8
+ feeds:
+ - url: https://x-bookmarks-rss.wltbs.workers.dev/feed.xml
+ title: X Bookmarks