From cefe6ffabd84dc2b8cebbadd49681ea183fda206 Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Thu, 28 May 2026 10:22:05 -0400 Subject: [PATCH] chore(config): add initial config files and docker compose setup --- .env | 6 + config/developer/left.yml | 13 + config/developer/main.yml | 22 ++ config/developer/right.yml | 6 + config/developer/widgets/graph.yml | 16 + config/finance/header.yml | 74 ++++ config/finance/left.yml | 13 + config/finance/main.yml | 10 + config/finance/right.yml | 6 + config/finance/widgets/fred.yml | 74 ++++ config/finance/widgets/youtube.yml | 94 +++++ config/glance.yml | 42 +++ config/media/movies.yml | 494 +++++++++++++++++++++++++ config/media/tv.yml | 494 +++++++++++++++++++++++++ config/today/header.yml | 11 + config/today/left.yml | 25 ++ config/today/main.yml | 10 + config/today/right.yml | 13 + config/today/widgets/alerts.yml | 28 ++ config/today/widgets/headlines.yml | 24 ++ config/today/widgets/ical-personal.yml | 76 ++++ config/today/widgets/ical-work.yml | 76 ++++ config/today/widgets/reddit.yml | 41 ++ config/today/widgets/youtube.yml | 94 +++++ docker-compose.yml | 29 ++ 25 files changed, 1791 insertions(+) create mode 100644 .env create mode 100644 config/developer/left.yml create mode 100644 config/developer/main.yml create mode 100644 config/developer/right.yml create mode 100644 config/developer/widgets/graph.yml create mode 100644 config/finance/header.yml create mode 100644 config/finance/left.yml create mode 100644 config/finance/main.yml create mode 100644 config/finance/right.yml create mode 100644 config/finance/widgets/fred.yml create mode 100644 config/finance/widgets/youtube.yml create mode 100644 config/glance.yml create mode 100644 config/media/movies.yml create mode 100644 config/media/tv.yml create mode 100644 config/today/header.yml create mode 100644 config/today/left.yml create mode 100644 config/today/main.yml create mode 100644 config/today/right.yml create mode 100644 config/today/widgets/alerts.yml create mode 100644 config/today/widgets/headlines.yml create mode 100644 config/today/widgets/ical-personal.yml create mode 100644 config/today/widgets/ical-work.yml create mode 100644 config/today/widgets/reddit.yml create mode 100644 config/today/widgets/youtube.yml create mode 100644 docker-compose.yml diff --git a/.env b/.env new file mode 100644 index 0000000..a96205c --- /dev/null +++ b/.env @@ -0,0 +1,6 @@ +# Variables defined here will be available to use anywhere in the config with the syntax ${MY_SECRET_TOKEN} +# Note: making changes to this file requires re-running docker compose up +MY_SECRET_TOKEN=123456 +JELLYFIN_URL=http://umbrel.tail51ffca.ts.net:8096 +JELLYFIN_KEY=df9e869fec0b460bb6577302f5efd049 +FRED_API_KEY=46fd446049e6ad0cbd6e019584fe36bf diff --git a/config/developer/left.yml b/config/developer/left.yml new file mode 100644 index 0000000..2aed5bc --- /dev/null +++ b/config/developer/left.yml @@ -0,0 +1,13 @@ +- size: small + widgets: + - type: twitch-top-games + limit: 20 + collapse-after: 13 + exclude: + - just-chatting + - pools-hot-tubs-and-beaches + - music + - art + - asmr + + diff --git a/config/developer/main.yml b/config/developer/main.yml new file mode 100644 index 0000000..174b89a --- /dev/null +++ b/config/developer/main.yml @@ -0,0 +1,22 @@ +- size: full + widgets: + - type: group + widgets: + - type: reddit + show-thumbnails: true + subreddit: commandline + - type: reddit + subreddit: selfhosted + - type: reddit + subreddit: tui + + - type: videos + style: grid-cards + collapse-after-rows: 3 + channels: + - UCNvzD7Z-g64bPXxGzaQaa4g # gameranx + - UCZ7AeeVbyslLM_8-nVy2B8Q # Skill Up + - UCHDxYLv8iovIbhrfl16CNyg # GameLinked + - UC9PBzalIcEQCsiIkq36PyUA # Digital Foundry + + diff --git a/config/developer/right.yml b/config/developer/right.yml new file mode 100644 index 0000000..7bbbdc7 --- /dev/null +++ b/config/developer/right.yml @@ -0,0 +1,6 @@ +- size: small + widgets: + - type: reddit + subreddit: gamingnews + limit: 7 + style: vertical-cards diff --git a/config/developer/widgets/graph.yml b/config/developer/widgets/graph.yml new file mode 100644 index 0000000..2727388 --- /dev/null +++ b/config/developer/widgets/graph.yml @@ -0,0 +1,16 @@ +- type: extension + url: http://localhost:8181/graph/prnk28 + allow-potentially-dangerous-html: true + parameters: + background-color: "#1d2025" # cell background + primary-color: "#f3afaf" # cell foreground + svg-height: 150 # height for graph svg + show-months: true # show months on the graph + show-weekdays: true # show weekdays on the graph + font-size: 9 # size of weekdays & months text on graph + + # if true, it will transition the hue from background + # to primary color per the number of commits. + # otherwise it will just use the background hue for + # 0 commits and the foreground hue for all others + transition-hue: false diff --git a/config/finance/header.yml b/config/finance/header.yml new file mode 100644 index 0000000..aeb15ff --- /dev/null +++ b/config/finance/header.yml @@ -0,0 +1,74 @@ +- type: split-column + max-columns: 5 + widgets: + - type: custom-api + title: Secured Financing Rate + cache: 12h + url: https://api.stlouisfed.org/fred/series/observations?series_id=SOFR&api_key=46fd446049e6ad0cbd6e019584fe36bf&file_type=json&sort_order=desc&limit=2 + template: | + {{ $latest := .JSON.Float "observations.0.value" }} + {{ $previous := .JSON.Float "observations.1.value" }} + {{ $lastObserve := .JSON.String "observations.0.date" }} + {{ $change := sub $latest $previous }} +
+
+ + {{ .JSON.String "observations.0.value" }}% + +
St. Louis Federal Reserve
+
+
+
+ {{ printf "%+.2f" $change }}% +
+
+
+
+
+ + - type: custom-api + title: Federal Funds Rate + cache: 12h + url: https://api.stlouisfed.org/fred/series/observations?series_id=FEDFUNDS&api_key=46fd446049e6ad0cbd6e019584fe36bf&file_type=json&sort_order=desc&limit=2 + template: | + {{ $latest := .JSON.Float "observations.0.value" }} + {{ $previous := .JSON.Float "observations.1.value" }} + {{ $lastObserve := .JSON.String "observations.0.date" }} + {{ $change := sub $latest $previous }} +
+
+ + {{ .JSON.String "observations.0.value" }}% + +
St. Louis Federal Reserve
+
+
+
+ {{ printf "%+.2f" $change }}% +
+
+
+
+
+ + - type: custom-api + title: Real GDP + cache: 12h + url: https://api.stlouisfed.org/fred/series/observations?series_id=A191RL1Q225SBEA&api_key=46fd446049e6ad0cbd6e019584fe36bf&file_type=json&sort_order=desc&limit=2 + template: | + {{ $latest := .JSON.Float "observations.0.value" }} + {{ $previous := .JSON.Float "observations.1.value" }} + {{ $lastObserve := .JSON.String "observations.0.date" }} + {{ $change := sub $latest $previous }} +
+
+ + {{ .JSON.String "observations.0.value" }}% + +
St. Louis Federal Reserve
+
+
+
+ {{ printf "%+.2f" $change }}% +
+ diff --git a/config/finance/left.yml b/config/finance/left.yml new file mode 100644 index 0000000..2aed5bc --- /dev/null +++ b/config/finance/left.yml @@ -0,0 +1,13 @@ +- size: small + widgets: + - type: twitch-top-games + limit: 20 + collapse-after: 13 + exclude: + - just-chatting + - pools-hot-tubs-and-beaches + - music + - art + - asmr + + diff --git a/config/finance/main.yml b/config/finance/main.yml new file mode 100644 index 0000000..ea79f62 --- /dev/null +++ b/config/finance/main.yml @@ -0,0 +1,10 @@ +- size: full + widgets: + - type: group + widgets: + - type: reddit + show-thumbnails: true + subreddit: technology + - type: reddit + show-thumbnails: true + subreddit: wallstreetbets diff --git a/config/finance/right.yml b/config/finance/right.yml new file mode 100644 index 0000000..7bbbdc7 --- /dev/null +++ b/config/finance/right.yml @@ -0,0 +1,6 @@ +- size: small + widgets: + - type: reddit + subreddit: gamingnews + limit: 7 + style: vertical-cards diff --git a/config/finance/widgets/fred.yml b/config/finance/widgets/fred.yml new file mode 100644 index 0000000..aeb15ff --- /dev/null +++ b/config/finance/widgets/fred.yml @@ -0,0 +1,74 @@ +- type: split-column + max-columns: 5 + widgets: + - type: custom-api + title: Secured Financing Rate + cache: 12h + url: https://api.stlouisfed.org/fred/series/observations?series_id=SOFR&api_key=46fd446049e6ad0cbd6e019584fe36bf&file_type=json&sort_order=desc&limit=2 + template: | + {{ $latest := .JSON.Float "observations.0.value" }} + {{ $previous := .JSON.Float "observations.1.value" }} + {{ $lastObserve := .JSON.String "observations.0.date" }} + {{ $change := sub $latest $previous }} +
+
+ + {{ .JSON.String "observations.0.value" }}% + +
St. Louis Federal Reserve
+
+
+
+ {{ printf "%+.2f" $change }}% +
+
+
+
+
+ + - type: custom-api + title: Federal Funds Rate + cache: 12h + url: https://api.stlouisfed.org/fred/series/observations?series_id=FEDFUNDS&api_key=46fd446049e6ad0cbd6e019584fe36bf&file_type=json&sort_order=desc&limit=2 + template: | + {{ $latest := .JSON.Float "observations.0.value" }} + {{ $previous := .JSON.Float "observations.1.value" }} + {{ $lastObserve := .JSON.String "observations.0.date" }} + {{ $change := sub $latest $previous }} +
+
+ + {{ .JSON.String "observations.0.value" }}% + +
St. Louis Federal Reserve
+
+
+
+ {{ printf "%+.2f" $change }}% +
+
+
+
+
+ + - type: custom-api + title: Real GDP + cache: 12h + url: https://api.stlouisfed.org/fred/series/observations?series_id=A191RL1Q225SBEA&api_key=46fd446049e6ad0cbd6e019584fe36bf&file_type=json&sort_order=desc&limit=2 + template: | + {{ $latest := .JSON.Float "observations.0.value" }} + {{ $previous := .JSON.Float "observations.1.value" }} + {{ $lastObserve := .JSON.String "observations.0.date" }} + {{ $change := sub $latest $previous }} +
+
+ + {{ .JSON.String "observations.0.value" }}% + +
St. Louis Federal Reserve
+
+
+
+ {{ printf "%+.2f" $change }}% +
+ diff --git a/config/finance/widgets/youtube.yml b/config/finance/widgets/youtube.yml new file mode 100644 index 0000000..f9afb48 --- /dev/null +++ b/config/finance/widgets/youtube.yml @@ -0,0 +1,94 @@ +- type: group + widgets: + # Podcasts & Commentary + - type: videos + style: grid-cards + collapse-after-rows: 2 + title: Pop-Culture + channels: + - UCzQUP1qoWDoEbmsQxvdjxgQ # PowerfulJRE + - UCJIfeSCssxSC_Dhc5s7woww # Lex Clips + - UC5PstSsGrRwj2o6asQpC4Rg # Flagrant 2 + - UCKrpnfpTwncQ050VFXcVkuQ # Network State Podcast + - UC7oPkqeHTwuOZ5CZ-R9f-6w # Triggernometry + - UCIHdDJ0tjn_3j-FS7s_X1kQ # Valuetainment + + # Programming & Tech + - type: videos + style: grid-cards + collapse-after-rows: 2 + title: Programming + channels: + - UCUyeluBRhGPCW4rPe_UvBZQ # ThePrimeTime + - UCjSEJkpGbcZhvo0lr-44X_w # TechHut + - UCXuqSBlHAE6Xw-yeJA0Tunw # Linus Tech Tips + - UCs6KfncB4OV6Vug4o_bzijg # Techlore + - UCTwxaBjziKfy6y_uWu30orAby # BugBytes + - UCYeiozh-4QwuC1sjgCmB92w # DevOps Toolbox + - UCsBjURrPoezykLs9EqgamOA # Angular Firebase + - UC-mTIBh__DzAqW495JHXy5A # The Coding Gopher + - UC2WHjPDvbE6O328n17ZGcfg # ForrestKnight + - UCsUalyRg43M8D60mtHe6YcAD # Honeypot + - UCgfe2ooZD3VJPB6aJAnuQng # cloud + - UCdjsUXJ3QawK4O5L1kqqsew # IPFS + - UC3Wn3dABlgESm8Bzn8Vamgg # Sideprojects + - UCtMVHI3AJD4Qk4hcbZnI9ZQ # SomeOrdinaryGamers + - UCNJ1Ymd5yFuUPtn21xtRbbw # AI Explained + - UCutCcajxhR33k9UR-DdLsAQ # Systems Innovation + + # Startups & Business + - type: videos + style: grid-cards + collapse-after-rows: 2 + title: Startups + channels: + - UCcefcZRL2oaA_uBNeo5UOWg # Y Combinator + - UCllx7jOjBL794FK67jtb5Og # Dalton + Michael + - UCxIJaCMEptJjxmmQgGFsnCg # How to Start a Startup + - UCQrZfl1FeCN9c71yjOzWVRw # Startup Archive + - UCtieZ1nS_tpjGEama6Kjxcg # Steve Jobs Archive + - UCm_WkN0wg49-eG4SymAQ_4g # Harvard Innovation Labs + - UCSGc7c1yKxo-Uhz5_oivrfg # The Startup Club by Slidebean + - UCGq-a57w-aPwyi3pW7XLiHw # The Diary Of A CEO + + # AI & Futurism + - type: videos + style: grid-cards + collapse-after-rows: 2 + title: Futurism + channels: + - UCawZsQWqfGSbCI5yjkdVkTA # Matthew Berman + - UCZFipeZtQM5CKUjx6grh54g # Isaac Arthur + - UCR9sFzaG9Ia_kXJhfxtFMB # melodysheep + - UCSeuZvDGosq1zC6NqgqGo-Q # merlin + # Finance + - type: videos + style: grid-cards + collapse-after-rows: 2 + title: Finance + channels: + - UCAeAB8ABXGoGMbXuYPmiu2A # The Swedish Investor + - UCvSXMi2LebwJEM1s4bz5IBA # New Money + - UCV6KDgJskWaEckne5aPA0aQ # Graham Stephan + - UCAzhpt9DmG6PnHXjmJTvRGQ # Federal Reserve + + + # Science, History & Education + - type: videos + style: grid-cards + collapse-after-rows: 2 + title: Education + channels: + - UCHnyfMqiRRG1u-2MsSQLbXA # Veritasium + - UCsXVk37bltHxD1rDPwtNM8QL # Kurzgesagt – In a Nutshell + - UCxqAWLTk1CmBvZFPzeZMd9A # Domain of Science + - UCR2uRTQ53V_egXKFflMMaaw # Artem Kirsanov + - UCeUJFQ0D9qs6aVNyUt9fkeQ # The Armchair Historian + - UC5Dw9TFdbPJoTDMSiJdIQT # Whatifalthist + - UC0NCSdGglnmdWg-qHALhu1w # History102 + - UCpCSAcbqs-sjEVfk_hMfY9w # MajorPrep + - UCmdugCMpC7BawYGwkRs5drQ # PhiloNautica + - UC4gHARRmw40kcLZgINlTK_g # Religion Camp + - UCPPrhcXtGR2aMoxrPJRKPLg # Para Bellum + - UCQUnqaW8Q33siyLYhisN7HQ # Antidote + - UCXzw-OdotBUcNA9yhuYQBw # Awesome diff --git a/config/glance.yml b/config/glance.yml new file mode 100644 index 0000000..7940191 --- /dev/null +++ b/config/glance.yml @@ -0,0 +1,42 @@ +server: + assets-path: /app/assets + +theme: + background-color: 240 27 11 + contrast-multiplier: 1.5 + primary-color: 321 100 71 + positive-color: 165 78 51 + negative-color: 360 100 71 + +pages: + - name: Today + width: wide + head-widgets: + - $include: ./today/header.yml + columns: + - $include: ./today/left.yml + - $include: ./today/main.yml + - $include: ./today/right.yml + + - name: Finance + head-widgets: + - $include: ./finance/header.yml + columns: + - $include: ./finance/left.yml + - $include: ./finance/main.yml + - $include: ./finance/right.yml + + - name: Developer + columns: + - $include: ./developer/left.yml + - $include: ./developer/main.yml + - $include: ./developer/right.yml + + - name: Movies + columns: + - $include: ./media/movies.yml + + - name: TV + columns: + - $include: ./media/tv.yml + diff --git a/config/media/movies.yml b/config/media/movies.yml new file mode 100644 index 0000000..0e0fde4 --- /dev/null +++ b/config/media/movies.yml @@ -0,0 +1,494 @@ +- size: full + widgets: + - type: custom-api + title: Latest Movies + frameless: true + cache: 5m + options: + base-url: http://umbrel.tail51ffca.ts.net: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" }} +
+
ERROR
+ + + +
+

{{ . }}

+ {{ 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 */}} + + {{ end }} + + {{ end }} + + {{ end }} + - type: custom-api + title: Up Next Movies + frameless: true + cache: 5m + options: + base-url: http://umbrel.tail51ffca.ts.net: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" }} +
+
ERROR
+ + + +
+

{{ . }}

+ {{ 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 */}} + + {{ end }} + + {{ end }} + + {{ end }} + + diff --git a/config/media/tv.yml b/config/media/tv.yml new file mode 100644 index 0000000..c29ef1a --- /dev/null +++ b/config/media/tv.yml @@ -0,0 +1,494 @@ +- size: full + widgets: + - type: custom-api + title: Latest TV + frameless: true + cache: 5m + options: + base-url: http://umbrel.tail51ffca.ts.net: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" }} +
+
ERROR
+ + + +
+

{{ . }}

+ {{ 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 */}} + + {{ end }} + + {{ end }} + + {{ end }} + - type: custom-api + title: Up Next TV + frameless: true + cache: 5m + options: + base-url: http://umbrel.tail51ffca.ts.net: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" }} +
+
ERROR
+ + + +
+

{{ . }}

+ {{ 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 */}} + + {{ end }} + + {{ end }} + + {{ end }} + + diff --git a/config/today/header.yml b/config/today/header.yml new file mode 100644 index 0000000..dff5119 --- /dev/null +++ b/config/today/header.yml @@ -0,0 +1,11 @@ +- type: markets + hide-header: true + markets: + - symbol: BTC-USD + name: Bitcoin + - symbol: ETH-USD + name: Ethereum + - symbol: MAGS + name: Mag7 + - symbol: QQQ + name: Nasdaq diff --git a/config/today/left.yml b/config/today/left.yml new file mode 100644 index 0000000..546919d --- /dev/null +++ b/config/today/left.yml @@ -0,0 +1,25 @@ +- size: small + widgets: + - type: weather + location: Ashburn, Virginia, United States + units: imperial # alternatively "metric" + hour-format: 12h # alternatively "24h" + - $include: ./widgets/ical-work.yml + - type: clock + hour-format: 12h + timezones: + - timezone: America/Los_Angeles + label: Los Angeles + - timezone: Asia/Singapore + label: Singapore + - timezone: Europe/London + label: London + - type: rss + title: Deals + limit: 10 + collapse-after: 2 + feeds: + - url: https://rss.app/feeds/rb0smDdeyhIkusel.xml + title: Crypto Fundraising + + diff --git a/config/today/main.yml b/config/today/main.yml new file mode 100644 index 0000000..0aa9123 --- /dev/null +++ b/config/today/main.yml @@ -0,0 +1,10 @@ +- size: full + widgets: + # Top Headlines + - $include: ./widgets/headlines.yml + # Community Discussions + - $include: ./widgets/reddit.yml + # Videos + - $include: ./widgets/youtube.yml + + diff --git a/config/today/right.yml b/config/today/right.yml new file mode 100644 index 0000000..0dbc535 --- /dev/null +++ b/config/today/right.yml @@ -0,0 +1,13 @@ +- size: small + widgets: + - type: to-do + - type: calendar + first-day-of-week: sunday + - $include: ./widgets/ical-personal.yml + - type: rss + title: Crypto + limit: 20 + collapse-after: 5 + feeds: + - url: https://rss.app/feeds/wiGtpLZuOjLgKlC4.xml + title: WatcherGuru diff --git a/config/today/widgets/alerts.yml b/config/today/widgets/alerts.yml new file mode 100644 index 0000000..ec15bfe --- /dev/null +++ b/config/today/widgets/alerts.yml @@ -0,0 +1,28 @@ +- type: group + widgets: + - type: rss + title: Crypto + limit: 30 + collapse-after: 13 + feeds: + - url: https://rss.app/feeds/wiGtpLZuOjLgKlC4.xml + title: WatcherGuru + + - type: rss + title: Deals + limit: 30 + collapse-after: 13 + feeds: + - url: https://rss.app/feeds/rb0smDdeyhIkusel.xml + title: Crypto Fundraising + + + - type: rss + title: Finance + limit: 30 + collapse-after: 13 + feeds: + - url: https://www.ft.com/technology?format=rss + title: Financial Times + - url: https://feeds.a.dj.com/rss/RSSMarketsMain.xml + title: Wall Street Journal diff --git a/config/today/widgets/headlines.yml b/config/today/widgets/headlines.yml new file mode 100644 index 0000000..2c34665 --- /dev/null +++ b/config/today/widgets/headlines.yml @@ -0,0 +1,24 @@ +- type: group + widgets: + - type: rss + title: Techmeme + style: horizontal-cards + feeds: + - url: https://www.techmeme.com/feed.xml + title: TechMeme + + - type: rss + title: ProductHunt + style: horizontal-cards + feeds: + - url: https://rss.app/feeds/_tBKt0Q2vzII4baWl.xml + title: ProductHunt + + - type: rss + title: TerminalTrove + style: horizontal-cards + feeds: + - url: https://terminaltrove.com/new.xml + title: TerminalTrove + + diff --git a/config/today/widgets/ical-personal.yml b/config/today/widgets/ical-personal.yml new file mode 100644 index 0000000..a0572aa --- /dev/null +++ b/config/today/widgets/ical-personal.yml @@ -0,0 +1,76 @@ +- type: custom-api + title: Personal Events + cache: 15m + url: http://glances-ical-api:8076/events + parameters: + url: https://calendar.google.com/calendar/ical/prnk28%40gmail.com/public/basic.ics + limit: 5 + template: | + {{ $events := .JSON.Array "events" }} + {{ $count := len $events }} + {{ $limit := 3 }} + + {{ if eq $count 0 }} +
+ No entries found. +
+ {{ end }} + + +
    + {{ range $i, $e := $events }} + {{ $ongoing := $e.Bool "ongoing" }} + {{ if $ongoing }} + {{ $start := $e.String "start" | parseTime "rfc3339" }} + {{ $end := $e.String "end" | parseTime "rfc3339" }} + {{ $name := $e.String "name" }} + {{ $url := $e.String "url" }} +
  • +
    + +
    + {{ if $url }} + {{ $name }} + {{ else }} + {{ $name }} + {{ end }} +
    {{ $start | formatTime "Mon, 02 Jan 2006" }}
    +
    + +
    + ends +
    +
    +
  • + {{ end }} + {{ end }} +
+ + + {{ $shown := 0 }} +
    + {{ range $i, $e := $events }} + {{ $ongoing := $e.Bool "ongoing" }} + {{ if not $ongoing }} + {{ $start := $e.String "start" | parseTime "rfc3339" }} + {{ $name := $e.String "name" }} + {{ $url := $e.String "url" }} +
  • +
    + +
    + {{ if $url }} + {{ $name }} + {{ else }} + {{ $name }} + {{ end }} +
    {{ $start | formatTime "Mon, 02 Jan 2006" }}
    +
    + +
    +
    +
  • + {{ $shown = add $shown 1 }} + {{ end }} + {{ end }} +
diff --git a/config/today/widgets/ical-work.yml b/config/today/widgets/ical-work.yml new file mode 100644 index 0000000..1e4eb7c --- /dev/null +++ b/config/today/widgets/ical-work.yml @@ -0,0 +1,76 @@ +- type: custom-api + title: Work Schedule + cache: 15m + url: http://glances-ical-api:8076/events + parameters: + url: https://calendar.google.com/calendar/ical/prad%40sonr.io/public/basic.ics + limit: 5 + template: | + {{ $events := .JSON.Array "events" }} + {{ $count := len $events }} + {{ $limit := 3 }} + + {{ if eq $count 0 }} +
+ No entries found. +
+ {{ end }} + + +
    + {{ range $i, $e := $events }} + {{ $ongoing := $e.Bool "ongoing" }} + {{ if $ongoing }} + {{ $start := $e.String "start" | parseTime "rfc3339" }} + {{ $end := $e.String "end" | parseTime "rfc3339" }} + {{ $name := $e.String "name" }} + {{ $url := $e.String "url" }} +
  • +
    + +
    + {{ if $url }} + {{ $name }} + {{ else }} + {{ $name }} + {{ end }} +
    {{ $start | formatTime "Mon, 02 Jan 2006" }}
    +
    + +
    + ends +
    +
    +
  • + {{ end }} + {{ end }} +
+ + + {{ $shown := 0 }} +
    + {{ range $i, $e := $events }} + {{ $ongoing := $e.Bool "ongoing" }} + {{ if not $ongoing }} + {{ $start := $e.String "start" | parseTime "rfc3339" }} + {{ $name := $e.String "name" }} + {{ $url := $e.String "url" }} +
  • +
    + +
    + {{ if $url }} + {{ $name }} + {{ else }} + {{ $name }} + {{ end }} +
    {{ $start | formatTime "Mon, 02 Jan 2006" }}
    +
    + +
    +
    +
  • + {{ $shown = add $shown 1 }} + {{ end }} + {{ end }} +
diff --git a/config/today/widgets/reddit.yml b/config/today/widgets/reddit.yml new file mode 100644 index 0000000..a606e5d --- /dev/null +++ b/config/today/widgets/reddit.yml @@ -0,0 +1,41 @@ +# Community Discussions +- type: split-column + max-columns: 3 + widgets: + - type: reddit + show-thumbnails: true + subreddit: commandline + - type: reddit + show-thumbnails: true + subreddit: ethereum + - type: reddit + show-thumbnails: true + subreddit: golang + - type: reddit + show-thumbnails: true + subreddit: hyprland + - type: reddit + show-thumbnails: true + subreddit: ipfs + - type: reddit + show-thumbnails: true + subreddit: libp2p + - type: reddit + show-thumbnails: true + subreddit: LinuxCirclejerk + - type: reddit + show-thumbnails: true + subreddit: niri + - type: reddit + show-thumbnails: true + subreddit: omarchy + - type: reddit + show-thumbnails: true + subreddit: selfhosted + - type: reddit + show-thumbnails: true + subreddit: termux + - type: reddit + show-thumbnails: true + subreddit: unixporn + diff --git a/config/today/widgets/youtube.yml b/config/today/widgets/youtube.yml new file mode 100644 index 0000000..f9afb48 --- /dev/null +++ b/config/today/widgets/youtube.yml @@ -0,0 +1,94 @@ +- type: group + widgets: + # Podcasts & Commentary + - type: videos + style: grid-cards + collapse-after-rows: 2 + title: Pop-Culture + channels: + - UCzQUP1qoWDoEbmsQxvdjxgQ # PowerfulJRE + - UCJIfeSCssxSC_Dhc5s7woww # Lex Clips + - UC5PstSsGrRwj2o6asQpC4Rg # Flagrant 2 + - UCKrpnfpTwncQ050VFXcVkuQ # Network State Podcast + - UC7oPkqeHTwuOZ5CZ-R9f-6w # Triggernometry + - UCIHdDJ0tjn_3j-FS7s_X1kQ # Valuetainment + + # Programming & Tech + - type: videos + style: grid-cards + collapse-after-rows: 2 + title: Programming + channels: + - UCUyeluBRhGPCW4rPe_UvBZQ # ThePrimeTime + - UCjSEJkpGbcZhvo0lr-44X_w # TechHut + - UCXuqSBlHAE6Xw-yeJA0Tunw # Linus Tech Tips + - UCs6KfncB4OV6Vug4o_bzijg # Techlore + - UCTwxaBjziKfy6y_uWu30orAby # BugBytes + - UCYeiozh-4QwuC1sjgCmB92w # DevOps Toolbox + - UCsBjURrPoezykLs9EqgamOA # Angular Firebase + - UC-mTIBh__DzAqW495JHXy5A # The Coding Gopher + - UC2WHjPDvbE6O328n17ZGcfg # ForrestKnight + - UCsUalyRg43M8D60mtHe6YcAD # Honeypot + - UCgfe2ooZD3VJPB6aJAnuQng # cloud + - UCdjsUXJ3QawK4O5L1kqqsew # IPFS + - UC3Wn3dABlgESm8Bzn8Vamgg # Sideprojects + - UCtMVHI3AJD4Qk4hcbZnI9ZQ # SomeOrdinaryGamers + - UCNJ1Ymd5yFuUPtn21xtRbbw # AI Explained + - UCutCcajxhR33k9UR-DdLsAQ # Systems Innovation + + # Startups & Business + - type: videos + style: grid-cards + collapse-after-rows: 2 + title: Startups + channels: + - UCcefcZRL2oaA_uBNeo5UOWg # Y Combinator + - UCllx7jOjBL794FK67jtb5Og # Dalton + Michael + - UCxIJaCMEptJjxmmQgGFsnCg # How to Start a Startup + - UCQrZfl1FeCN9c71yjOzWVRw # Startup Archive + - UCtieZ1nS_tpjGEama6Kjxcg # Steve Jobs Archive + - UCm_WkN0wg49-eG4SymAQ_4g # Harvard Innovation Labs + - UCSGc7c1yKxo-Uhz5_oivrfg # The Startup Club by Slidebean + - UCGq-a57w-aPwyi3pW7XLiHw # The Diary Of A CEO + + # AI & Futurism + - type: videos + style: grid-cards + collapse-after-rows: 2 + title: Futurism + channels: + - UCawZsQWqfGSbCI5yjkdVkTA # Matthew Berman + - UCZFipeZtQM5CKUjx6grh54g # Isaac Arthur + - UCR9sFzaG9Ia_kXJhfxtFMB # melodysheep + - UCSeuZvDGosq1zC6NqgqGo-Q # merlin + # Finance + - type: videos + style: grid-cards + collapse-after-rows: 2 + title: Finance + channels: + - UCAeAB8ABXGoGMbXuYPmiu2A # The Swedish Investor + - UCvSXMi2LebwJEM1s4bz5IBA # New Money + - UCV6KDgJskWaEckne5aPA0aQ # Graham Stephan + - UCAzhpt9DmG6PnHXjmJTvRGQ # Federal Reserve + + + # Science, History & Education + - type: videos + style: grid-cards + collapse-after-rows: 2 + title: Education + channels: + - UCHnyfMqiRRG1u-2MsSQLbXA # Veritasium + - UCsXVk37bltHxD1rDPwtNM8QL # Kurzgesagt – In a Nutshell + - UCxqAWLTk1CmBvZFPzeZMd9A # Domain of Science + - UCR2uRTQ53V_egXKFflMMaaw # Artem Kirsanov + - UCeUJFQ0D9qs6aVNyUt9fkeQ # The Armchair Historian + - UC5Dw9TFdbPJoTDMSiJdIQT # Whatifalthist + - UC0NCSdGglnmdWg-qHALhu1w # History102 + - UCpCSAcbqs-sjEVfk_hMfY9w # MajorPrep + - UCmdugCMpC7BawYGwkRs5drQ # PhiloNautica + - UC4gHARRmw40kcLZgINlTK_g # Religion Camp + - UCPPrhcXtGR2aMoxrPJRKPLg # Para Bellum + - UCQUnqaW8Q33siyLYhisN7HQ # Antidote + - UCXzw-OdotBUcNA9yhuYQBw # Awesome diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2e03f52 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,29 @@ +services: + glance: + env_file: + - .env + container_name: glance + image: glanceapp/glance + restart: unless-stopped + volumes: + - ./config:/app/config + - ./assets:/app/assets + - /etc/localtime:/etc/localtime:ro + - /var/run/docker.sock:/var/run/docker.sock:ro + ports: + - 6969:8080 + + glance-github-graph: + image: haumea/glance-github-graph:latest + ports: + - 8181:8080 + environment: + - CACHE_ENABLED=true + - CACHE_TYPE=memory + - CACHE_DURATION_SECS=3600 + + glances-ical-api: + image: ghcr.io/awildleon/glance-ical-events:latest + restart: always + ports: + - "8076:8072"