mirror of
https://gitlab.com/upRootNutrition/dotfiles.git
synced 2025-06-16 10:05:13 -05:00
feat: refactored glance
This commit is contained in:
parent
3c230de4fd
commit
8d4ce8d2f9
17 changed files with 571 additions and 149 deletions
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
type = "calendar";
|
||||
title = "Calendar";
|
||||
style = "vertical-cards";
|
||||
}
|
22
modules/nixos/services/glance/config/widgets/clock.nix
Normal file
22
modules/nixos/services/glance/config/widgets/clock.nix
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
type = "clock";
|
||||
hour-format = "12h";
|
||||
timezones = [
|
||||
{
|
||||
timezone = "America/Winnipeg";
|
||||
label = "Winnipeg, MB";
|
||||
}
|
||||
{
|
||||
timezone = "Europe/Berlin";
|
||||
label = "Berlin, DE";
|
||||
}
|
||||
{
|
||||
timezone = "Asia/Kolkata";
|
||||
label = "Kolkata, IN";
|
||||
}
|
||||
{
|
||||
timezone = "Asia/Tokyo";
|
||||
label = "Tokyo, JP";
|
||||
}
|
||||
];
|
||||
}
|
|
@ -0,0 +1,326 @@
|
|||
''
|
||||
{{ $mediaServer := .Options.StringOr "media-server" "" }}
|
||||
{{ $baseURL := .Options.StringOr "base-url" "" }}
|
||||
{{ $apiKey := .Options.StringOr "api-key" "" }}
|
||||
{{ $userName := .Options.StringOr "user-name" "" }}
|
||||
|
||||
{{ define "errorMsg" }}
|
||||
<div class="widget-error-header">
|
||||
<div class="color-negative size-h3">ERROR</div>
|
||||
<svg class="widget-error-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<p class="break-all">{{ . }}</p>
|
||||
{{ end }}
|
||||
|
||||
{{ if or
|
||||
(eq $mediaServer "")
|
||||
(eq $baseURL "")
|
||||
(eq $apiKey "")
|
||||
(and (eq $mediaServer "jellyfin") (eq $userName ""))
|
||||
}}
|
||||
{{ template "errorMsg" "Some required options are not set" }}
|
||||
{{ else }}
|
||||
|
||||
{{ $historyLength := .Options.StringOr "history-length" "10" }}
|
||||
{{ $mediaTypes := .Options.StringOr "media-types" "" }}
|
||||
{{ if eq $mediaServer "tautulli" }}
|
||||
{{ $mediaTypes = .Options.StringOr "media-types" "movie,episode,track" }}
|
||||
{{ else if or (eq $mediaServer "jellyfin") (eq $mediaServer "emby") }}
|
||||
{{ $mediaTypes = .Options.StringOr "media-types" "Movie,Episode,Audio" }}
|
||||
{{ end }}
|
||||
{{ $isSmallColumn := .Options.BoolOr "small-column" false }}
|
||||
{{ $isCompact := .Options.BoolOr "compact" true }}
|
||||
{{ $showThumbnail := .Options.BoolOr "show-thumbnail" false }}
|
||||
{{ $thumbAspectRatio := .Options.StringOr "thumbnail-aspect-ratio" "" }}
|
||||
{{ $showUser := .Options.BoolOr "show-user" true }}
|
||||
{{ $timeAbsolute := .Options.BoolOr "time-absolute" false }}
|
||||
{{ $timeFormat := .Options.StringOr "time-format" "Jan 02 15:04" }}
|
||||
|
||||
{{ $userID := "" }}
|
||||
{{ $historyRequestURL := "" }}
|
||||
{{ $usersRequestURL := "" }}
|
||||
{{ $historyCall := "" }}
|
||||
{{ $usersCall := "" }}
|
||||
{{ $history := "" }}
|
||||
{{ $users := "" }}
|
||||
|
||||
{{ if eq $mediaServer "plex" }}
|
||||
{{ $historyRequestURL = concat $baseURL "/status/sessions/history/all" }}
|
||||
{{ $historyCall = newRequest $historyRequestURL
|
||||
| withParameter "limit" $historyLength
|
||||
| withParameter "sort" "viewedAt:desc"
|
||||
| withHeader "Accept" "application/json"
|
||||
| withHeader "X-Plex-Token" $apiKey
|
||||
| getResponse }}
|
||||
|
||||
{{ if $historyCall.JSON.Exists "MediaContainer" }}
|
||||
{{ $history = $historyCall.JSON.Array "MediaContainer.Metadata" }}
|
||||
{{ else }}
|
||||
{{ template "errorMsg" (concat "Could not fetch " $mediaServer " API.") }}
|
||||
{{ end }}
|
||||
|
||||
{{ $usersRequestURL = concat $baseURL "/accounts" }}
|
||||
{{ $usersCall = newRequest $usersRequestURL
|
||||
| withHeader "Accept" "application/json"
|
||||
| withHeader "X-Plex-Token" $apiKey
|
||||
| getResponse }}
|
||||
{{ $users = $usersCall.JSON.Array "MediaContainer.Account" }}
|
||||
|
||||
{{ else if eq $mediaServer "tautulli" }}
|
||||
{{ $historyRequestURL = concat $baseURL "/api/v2" }}
|
||||
{{ $historyCall = newRequest $historyRequestURL
|
||||
| withParameter "apikey" $apiKey
|
||||
| withParameter "cmd" "get_history"
|
||||
| withParameter "length" $historyLength
|
||||
| withParameter "media_type" $mediaTypes
|
||||
| withHeader "Accept" "application/json"
|
||||
| getResponse }}
|
||||
|
||||
{{ if eq $historyCall.Response.StatusCode 200 }}
|
||||
{{ $history = $historyCall.JSON.Array "response.data.data" }}
|
||||
{{ else }}
|
||||
{{ template "errorMsg" (concat "Could not fetch " $mediaServer " API.") }}
|
||||
{{ end }}
|
||||
|
||||
{{ else if or (eq $mediaServer "jellyfin") (eq $mediaServer "emby") }}
|
||||
{{ $usersRequestURL = concat $baseURL "/Users" }}
|
||||
{{ $usersCall = newRequest $usersRequestURL
|
||||
| withParameter "api_key" $apiKey
|
||||
| withHeader "Accept" "application/json"
|
||||
| getResponse }}
|
||||
|
||||
{{ $usersList := $usersCall.JSON.Array "" }}
|
||||
{{ range $i, $user := $usersList }}
|
||||
{{ if eq ($user.String "Name") $userName }}
|
||||
{{ $userID = $user.String "Id" }}
|
||||
{{ break }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ if eq $userID "" }}
|
||||
{{ template "errorMsg" (concat "User '" $userName "' not found.") }}
|
||||
{{ end }}
|
||||
|
||||
{{ $historyRequestURL = concat $baseURL "/Users/" $userID "/Items" }}
|
||||
{{ $historyCall = newRequest $historyRequestURL
|
||||
| withParameter "api_key" $apiKey
|
||||
| withParameter "Limit" $historyLength
|
||||
| withParameter "IncludeItemTypes" $mediaTypes
|
||||
| withParameter "Recursive" "true"
|
||||
| withParameter "isPlayed" "true"
|
||||
| withParameter "sortBy" "DatePlayed"
|
||||
| withParameter "sortOrder" "Descending"
|
||||
| withParameter "Fields" "UserDataLastPlayedDate"
|
||||
| withHeader "Accept" "application/json"
|
||||
| getResponse }}
|
||||
|
||||
{{ $history = $historyCall.JSON.Array "Items" }}
|
||||
{{ end }}
|
||||
|
||||
{{ if and (eq $historyCall.Response.StatusCode 200) (eq (len $history) 0) }}
|
||||
<p>Nothing has been played. Start streaming something!</p>
|
||||
{{ else }}
|
||||
<div class="carousel-container show-right-cutoff">
|
||||
<div class="cards-horizontal carousel-items-container">
|
||||
{{ range $n, $item := $history }}
|
||||
{{ $mediaType := "" }}
|
||||
{{ $isMovie := false }}
|
||||
{{ $isShows := false }}
|
||||
{{ $isMusic := false }}
|
||||
{{ $title := "" }}
|
||||
{{ $showTitle := "" }}
|
||||
{{ $showSeason := "" }}
|
||||
{{ $showEpisode := "" }}
|
||||
{{ $artist := "" }}
|
||||
{{ $albumTitle := "" }}
|
||||
{{ $thumbURL := "" }}
|
||||
{{ $playedAt := "" }}
|
||||
|
||||
{{ if eq $mediaServer "plex" }}
|
||||
{{ $userID = $item.Int "accountID" }}
|
||||
{{ range $n, $u := $users }}
|
||||
{{ if eq $userID ($u.Int "id") }}
|
||||
{{ $userName = $u.String "name" }}
|
||||
{{ break }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ $mediaType = $item.String "type" }}
|
||||
{{ $isMovie = eq $mediaType "movie" }}
|
||||
{{ $isShows = eq $mediaType "episode" }}
|
||||
{{ $isMusic = eq $mediaType "track" }}
|
||||
|
||||
{{ $title = $item.String "title" }}
|
||||
{{ if $isShows }}
|
||||
{{ $showTitle = $item.String "grandparentTitle" }}
|
||||
{{ $showSeason = $item.String "parentIndex" }}
|
||||
{{ $showEpisode = $item.String "index" }}
|
||||
{{ else if $isMusic }}
|
||||
{{ $artist = $item.String "grandparentTitle" }}
|
||||
{{ $albumTitle = $item.String "parentTitle" }}
|
||||
{{ end }}
|
||||
|
||||
{{ $thumbID := $item.String "thumb" }}
|
||||
{{ if or $isShows $isMusic}}
|
||||
{{ $thumbID = $item.String "parentThumb" }}
|
||||
{{ end }}
|
||||
{{ $thumbURL = concat $baseURL $thumbID "?X-Plex-Token=" $apiKey }}
|
||||
|
||||
{{ $time := $item.String "viewedAt" }}
|
||||
{{ if $timeAbsolute }}
|
||||
{{ $playedAt = $time | parseLocalTime "unix" | formatTime $timeFormat }}
|
||||
{{ else }}
|
||||
{{ $playedAt = $time | parseRelativeTime "unix" }}
|
||||
{{ end }}
|
||||
|
||||
{{ else if eq $mediaServer "tautulli" }}
|
||||
{{ $userName = $item.String "user" }}
|
||||
{{ $mediaType = $item.String "media_type" }}
|
||||
{{ $isMovie = eq $mediaType "movie" }}
|
||||
{{ $isShows = eq $mediaType "episode" }}
|
||||
{{ $isMusic = eq $mediaType "track" }}
|
||||
|
||||
{{ $title = $item.String "title" }}
|
||||
{{ if $isShows }}
|
||||
{{ $showTitle = $item.String "grandparent_title" }}
|
||||
{{ $showSeason = $item.String "parent_media_index" }}
|
||||
{{ $showEpisode = $item.String "media_index" }}
|
||||
{{ else if $isMusic }}
|
||||
{{ $artist = $item.String "grandparent_title" }}
|
||||
{{ $albumTitle = $item.String "parent_title" }}
|
||||
{{ end }}
|
||||
|
||||
{{ $thumbID := $item.String "thumb" }}
|
||||
{{ $thumbURL = concat $baseURL "/api/v2?apikey=" $apiKey "&cmd=pms_image_proxy&img=" $thumbID }}
|
||||
|
||||
{{ $time := $item.String "date" }}
|
||||
{{ if $timeAbsolute }}
|
||||
{{ $playedAt = $time | parseLocalTime "unix" | formatTime $timeFormat }}
|
||||
{{ else }}
|
||||
{{ $playedAt = $time | parseRelativeTime "unix" }}
|
||||
{{ end }}
|
||||
|
||||
{{ else if or (eq $mediaServer "jellyfin") (eq $mediaServer "emby") }}
|
||||
{{ $mediaType = $item.String "Type" }}
|
||||
{{ $isMovie = eq $mediaType "Movie" }}
|
||||
{{ $isShows = eq $mediaType "Episode" }}
|
||||
{{ $isMusic = eq $mediaType "Audio" }}
|
||||
|
||||
{{ $title = $item.String "Name" }}
|
||||
{{ if $isShows }}
|
||||
{{ $showTitle = $item.String "SeriesName" }}
|
||||
{{ $showSeason = $item.String "ParentIndexNumber" }}
|
||||
{{ $showEpisode = $item.String "IndexNumber" }}
|
||||
{{ else if $isMusic }}
|
||||
{{ $artist = $item.String "AlbumArtist" }}
|
||||
{{ $albumTitle = $item.String "Album" }}
|
||||
{{ end }}
|
||||
|
||||
{{ $thumbID := $item.String "Id" }}
|
||||
{{ if $isShows }}
|
||||
{{ $thumbID = $item.String "SeasonId" }}
|
||||
{{ end }}
|
||||
{{ $thumbURL = concat $baseURL "/Items/" $thumbID "/Images/Primary?api_key=" $apiKey }}
|
||||
|
||||
{{ $time := $item.String "UserData.LastPlayedDate" }}
|
||||
{{ if $timeAbsolute }}
|
||||
{{ $playedAt = $time | parseLocalTime "rfc3339" | formatTime $timeFormat }}
|
||||
{{ else }}
|
||||
{{ $playedAt = $time | parseRelativeTime "rfc3339" }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ $showInfoFormat := concat "Season " $showSeason " Episode " $showEpisode}}
|
||||
{{ if $isCompact }}
|
||||
{{ $showInfoFormat = concat "S" $showSeason "E" $showEpisode}}
|
||||
{{ end }}
|
||||
|
||||
<div class="card widget-content-frame">
|
||||
{{ if $showThumbnail }}
|
||||
<img src="{{ $thumbURL | safeURL }}"
|
||||
alt="{{ $title }} thumbnail"
|
||||
loading="lazy"
|
||||
class="media-server-thumbnail shrink-0"
|
||||
style="
|
||||
object-fit: cover;
|
||||
border-radius: var(--border-radius) var(--border-radius) 0 0;
|
||||
{{ if eq $thumbAspectRatio "square" }}
|
||||
aspect-ratio: 1;
|
||||
{{ else if eq $thumbAspectRatio "portrait" }}
|
||||
aspect-ratio: 3/4;
|
||||
{{ else if eq $thumbAspectRatio "landscape" }}
|
||||
aspect-ratio: 4/3;
|
||||
{{ else }}
|
||||
aspect-ratio: initial;
|
||||
{{ end }}
|
||||
"
|
||||
/>
|
||||
{{ end }}
|
||||
|
||||
<div class="grow padding-inline-widget margin-top-10 margin-bottom-10">
|
||||
<ul class="flex flex-column justify-evenly margin-bottom-3 {{if $isSmallColumn}}size-h6{{end}}" style="height: 100%;">
|
||||
{{ if $isCompact }}
|
||||
<ul class="list-horizontal-text flex-nowrap">
|
||||
{{ if $showUser }}
|
||||
<li class="color-primary text-truncate">{{ $userName }}</li>
|
||||
{{ end }}
|
||||
|
||||
{{ if $timeAbsolute }}
|
||||
<li class="text-truncate">{{ $playedAt }}</li>
|
||||
{{ else }}
|
||||
<li class="shrink-0">
|
||||
<span {{ $playedAt }}></span>
|
||||
{{ if not $showUser }}
|
||||
<span> ago</span>
|
||||
{{ end }}
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
|
||||
{{ if $isShows }}
|
||||
<ul class="list-horizontal-text flex-nowrap">
|
||||
<li class="text-truncate">{{ $showInfoFormat }}</li>
|
||||
<li class="text-truncate">{{ $showTitle }}</li>
|
||||
</ul>
|
||||
{{ else if $isMusic }}
|
||||
<ul class="list-horizontal-text flex-nowrap">
|
||||
<li class="text-truncate">{{ $artist }}</li>
|
||||
<li class="text-truncate">{{ $albumTitle }}</li>
|
||||
</ul>
|
||||
{{ end }}
|
||||
|
||||
<li class="text-truncate">{{ $title }}</li>
|
||||
{{ else }}
|
||||
{{ if $showUser }}
|
||||
<li class="color-primary text-truncate">{{ $userName }}</li>
|
||||
{{ end }}
|
||||
|
||||
{{ if $timeAbsolute }}
|
||||
<li class="text-truncate">{{ $playedAt }}</li>
|
||||
{{ else }}
|
||||
<li class="text-truncate">
|
||||
<span {{ $playedAt }}></span>
|
||||
<span> ago</span>
|
||||
</li>
|
||||
{{ end }}
|
||||
|
||||
{{ if $isShows }}
|
||||
<li class="text-truncate">{{ $showTitle }}</li>
|
||||
<li class="text-truncate">{{ $showInfoFormat }}</li>
|
||||
{{ else if $isMusic }}
|
||||
<li class="text-truncate">{{ $artist }}</li>
|
||||
<li class="text-truncate">{{ $albumTitle }}</li>
|
||||
{{ end }}
|
||||
|
||||
<li class="text-truncate">{{ $title }}</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
''
|
|
@ -0,0 +1,30 @@
|
|||
{ config, flake, ... }:
|
||||
let
|
||||
inherit (flake.config.people) user0;
|
||||
inherit (flake.config.people.users.${user0}) name;
|
||||
inherit (flake.config.services.instances) glance jellyfin web;
|
||||
service = glance;
|
||||
jellyfinUserName = name;
|
||||
jellyfinHost = "https://${jellyfin.subdomain}.${web.domains.url0}";
|
||||
in
|
||||
{
|
||||
type = "custom-api";
|
||||
title = "Jellyfin History";
|
||||
frameless = true;
|
||||
cache = "5m";
|
||||
options = {
|
||||
media-server = "jellyfin";
|
||||
base-url = jellyfinHost;
|
||||
api-key = config.sops.secrets."${service.name}-${jellyfin.name}".path;
|
||||
user-name = jellyfinUserName;
|
||||
history-length = "10";
|
||||
small-column = true;
|
||||
compact = true;
|
||||
show-thumbnail = false;
|
||||
thumbnail-aspect-ratio = "default";
|
||||
show-user = true;
|
||||
time-absolute = false;
|
||||
time-format = "Jan 02 15:04";
|
||||
};
|
||||
template = import ./config;
|
||||
}
|
20
modules/nixos/services/glance/config/widgets/podcasts.nix
Normal file
20
modules/nixos/services/glance/config/widgets/podcasts.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
type = "rss";
|
||||
title = "Podcasts";
|
||||
style = "detailed-list";
|
||||
collapse-after = 6;
|
||||
feeds = [
|
||||
{
|
||||
url = "https://sigmanutrition.libsyn.com/rss/";
|
||||
title = "Sigma Nutrition Radio";
|
||||
}
|
||||
{
|
||||
url = "https://wakingup.libsyn.com/rss";
|
||||
title = "Making Sense with Sam Harris";
|
||||
}
|
||||
{
|
||||
url = "https://feeds.simplecast.com/uNKL_XD_";
|
||||
title = "Docs Who Lift";
|
||||
}
|
||||
];
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
''
|
||||
<ul class="list list-gap-10 collapsible-container" data-collapse-after="5">
|
||||
{{ range .JSON.Array "specials.items" }}
|
||||
<li>
|
||||
<a class="size-h4 color-highlight block text-truncate" href="https://store.steampowered.com/app/{{ .Int "id" }}/">{{ .String "name" }}</a>
|
||||
<ul class="list-horizontal-text">
|
||||
<li>{{ .Int "final_price" | toFloat | mul 0.01 | printf "$%.2f" }}</li>
|
||||
{{ $discount := .Int "discount_percent" }}
|
||||
<li{{ if ge $discount 40 }} class="color-positive"{{ end }}>{{ $discount }}% off</li>
|
||||
</ul>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
''
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
type = "custom-api";
|
||||
title = "Steam Specials";
|
||||
cache = "12h";
|
||||
url = "https://store.steampowered.com/api/featuredcategories?cc=ca";
|
||||
template = import ./config;
|
||||
}
|
7
modules/nixos/services/glance/config/widgets/weather.nix
Normal file
7
modules/nixos/services/glance/config/widgets/weather.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
type = "weather";
|
||||
title = "Weather";
|
||||
units = "metric";
|
||||
hour-format = "12h";
|
||||
location = "Winnipeg, Manitoba, Canada";
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue