Initial commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/data
|
||||||
|
/config/media
|
||||||
97
config/monitoring/glance/glance.yml
Normal file
97
config/monitoring/glance/glance.yml
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
# Glance – main config
|
||||||
|
# See: https://github.com/glanceapp/glance/blob/main/docs/configuration.md
|
||||||
|
|
||||||
|
server:
|
||||||
|
assets-path: /app/assets
|
||||||
|
proxied: true
|
||||||
|
|
||||||
|
theme:
|
||||||
|
custom-css-file: /assets/user.css
|
||||||
|
|
||||||
|
pages:
|
||||||
|
- name: Home
|
||||||
|
columns:
|
||||||
|
- size: small
|
||||||
|
widgets:
|
||||||
|
- type: clock
|
||||||
|
- type: calendar
|
||||||
|
first-day-of-week: monday
|
||||||
|
- type: releases
|
||||||
|
cache: 1d
|
||||||
|
repositories:
|
||||||
|
- glanceapp/glance
|
||||||
|
- immich-app/immich
|
||||||
|
- size: full
|
||||||
|
widgets:
|
||||||
|
- type: hacker-news
|
||||||
|
limit: 15
|
||||||
|
collapse-after: 5
|
||||||
|
- type: lobsters
|
||||||
|
sort-by: hot
|
||||||
|
limit: 15
|
||||||
|
collapse-after: 5
|
||||||
|
- type: reddit
|
||||||
|
subreddit: unixporn
|
||||||
|
limit: 15
|
||||||
|
collapse-after: 5
|
||||||
|
- size: small
|
||||||
|
widgets:
|
||||||
|
- type: bookmarks
|
||||||
|
title: Services
|
||||||
|
groups:
|
||||||
|
- same-tab: true
|
||||||
|
links:
|
||||||
|
- title: Jellyfin
|
||||||
|
url: https://jellyfin.home
|
||||||
|
icon: mdi:television-play
|
||||||
|
- title: Seer
|
||||||
|
url: https://jellyseerr.home
|
||||||
|
icon: mdi:movie-search
|
||||||
|
- title: Radarr
|
||||||
|
url: https://radarr.home
|
||||||
|
icon: mdi:film
|
||||||
|
- title: Sonarr
|
||||||
|
url: https://sonarr.home
|
||||||
|
icon: mdi:television
|
||||||
|
- title: Lidarr
|
||||||
|
url: https://lidarr.home
|
||||||
|
icon: mdi:music
|
||||||
|
- title: Prowlarr
|
||||||
|
url: https://prowlarr.home
|
||||||
|
icon: mdi:radar
|
||||||
|
- title: qBittorrent
|
||||||
|
url: https://qbit.home
|
||||||
|
icon: mdi:download
|
||||||
|
- title: Portainer
|
||||||
|
url: https://portainer.home
|
||||||
|
icon: mdi:docker
|
||||||
|
- title: Immich
|
||||||
|
url: https://photo.home
|
||||||
|
icon: mdi:image-multiple
|
||||||
|
- title: Navidrome
|
||||||
|
url: https://music.home
|
||||||
|
icon: mdi:music-box-multiple
|
||||||
|
- title: CopyParty
|
||||||
|
url: https://copyparty.home
|
||||||
|
icon: mdi:folder-multiple
|
||||||
|
- title: Gitea
|
||||||
|
url: https://git.home
|
||||||
|
icon: mdi:git
|
||||||
|
- title: Grafana
|
||||||
|
url: https://grafana.home
|
||||||
|
icon: mdi:chart-line
|
||||||
|
- name: Media
|
||||||
|
columns:
|
||||||
|
- size: full
|
||||||
|
widgets:
|
||||||
|
- type: group
|
||||||
|
widgets:
|
||||||
|
- $include: widgets/arr-radarr-upcoming.yml
|
||||||
|
- $include: widgets/arr-radarr-recent.yml
|
||||||
|
- $include: widgets/arr-radarr-missing.yml
|
||||||
|
- $include: widgets/arr-sonarr-upcoming.yml
|
||||||
|
- $include: widgets/arr-sonarr-recent.yml
|
||||||
|
- $include: widgets/arr-sonarr-missing.yml
|
||||||
|
- $include: widgets/monitor-media.yml
|
||||||
|
- $include: pages/services.yml
|
||||||
|
- $include: pages/gaming.yml
|
||||||
39
config/monitoring/glance/pages/gaming.yml
Normal file
39
config/monitoring/glance/pages/gaming.yml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
- name: Gaming
|
||||||
|
columns:
|
||||||
|
- size: small
|
||||||
|
widgets:
|
||||||
|
- type: twitch-top-games
|
||||||
|
limit: 20
|
||||||
|
collapse-after: 13
|
||||||
|
exclude:
|
||||||
|
- just-chatting
|
||||||
|
- pools-hot-tubs-and-beaches
|
||||||
|
- music
|
||||||
|
- art
|
||||||
|
- asmr
|
||||||
|
|
||||||
|
- size: full
|
||||||
|
widgets:
|
||||||
|
- type: group
|
||||||
|
widgets:
|
||||||
|
- type: reddit
|
||||||
|
show-thumbnails: true
|
||||||
|
subreddit: pcgaming
|
||||||
|
- type: reddit
|
||||||
|
subreddit: games
|
||||||
|
|
||||||
|
- type: videos
|
||||||
|
style: grid-cards
|
||||||
|
collapse-after-rows: 3
|
||||||
|
channels:
|
||||||
|
- UCNvzD7Z-g64bPXxGzaQaa4g # gameranx
|
||||||
|
- UCZ7AeeVbyslLM_8-nVy2B8Q # Skill Up
|
||||||
|
- UCHDxYLv8iovIbhrfl16CNyg # GameLinked
|
||||||
|
- UC9PBzalIcEQCsiIkq36PyUA # Digital Foundry
|
||||||
|
|
||||||
|
- size: small
|
||||||
|
widgets:
|
||||||
|
- type: reddit
|
||||||
|
subreddit: gamingnews
|
||||||
|
limit: 7
|
||||||
|
style: vertical-cards
|
||||||
16
config/monitoring/glance/pages/home.yml
Normal file
16
config/monitoring/glance/pages/home.yml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Home: clock, calendar, quick links to all services
|
||||||
|
name: Home
|
||||||
|
columns:
|
||||||
|
- size: small
|
||||||
|
widgets:
|
||||||
|
- type: clock
|
||||||
|
- type: calendar
|
||||||
|
first-day-of-week: monday
|
||||||
|
- $include: ../widgets/bookmarks-services.yml
|
||||||
|
- size: full
|
||||||
|
widgets:
|
||||||
|
- type: releases
|
||||||
|
cache: 1d
|
||||||
|
repositories:
|
||||||
|
- glanceapp/glance
|
||||||
|
- immich-app/immich
|
||||||
15
config/monitoring/glance/pages/media.yml
Normal file
15
config/monitoring/glance/pages/media.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Media: Jellyfin (next up + latest), *arr wanted, status
|
||||||
|
name: Media
|
||||||
|
columns:
|
||||||
|
- size: full
|
||||||
|
widgets:
|
||||||
|
- type: group
|
||||||
|
widgets:
|
||||||
|
- $include: ../widgets/arr-radarr-upcoming.yml
|
||||||
|
- $include: ../widgets/arr-radarr-recent.yml
|
||||||
|
- $include: ../widgets/arr-radarr-missing.yml
|
||||||
|
- $include: ../widgets/arr-sonarr-upcoming.yml
|
||||||
|
- $include: ../widgets/arr-sonarr-recent.yml
|
||||||
|
- $include: ../widgets/arr-sonarr-missing.yml
|
||||||
|
- $include: ../widgets/jellyfin.yml
|
||||||
|
- $include: ../widgets/monitor-media.yml
|
||||||
83
config/monitoring/glance/pages/services.yml
Normal file
83
config/monitoring/glance/pages/services.yml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# Services: status monitor, Docker containers, Portainer
|
||||||
|
- name: Services
|
||||||
|
columns:
|
||||||
|
- size: full
|
||||||
|
widgets:
|
||||||
|
- type: server-stats
|
||||||
|
title: Server
|
||||||
|
servers:
|
||||||
|
- type: local
|
||||||
|
name: Services
|
||||||
|
mountpoints:
|
||||||
|
"/":
|
||||||
|
name: Root
|
||||||
|
"/srv/media":
|
||||||
|
name: Media
|
||||||
|
"/backup":
|
||||||
|
name: Backup
|
||||||
|
- type: monitor
|
||||||
|
title: Service status
|
||||||
|
sites:
|
||||||
|
- title: Jellyfin
|
||||||
|
url: https://jellyfin.home
|
||||||
|
icon: mdi:television-play
|
||||||
|
- title: Seer
|
||||||
|
url: https://jellyseerr.home
|
||||||
|
icon: mdi:movie-search
|
||||||
|
- title: Radarr
|
||||||
|
url: https://radarr.home
|
||||||
|
icon: mdi:film
|
||||||
|
- title: Sonarr
|
||||||
|
url: https://sonarr.home
|
||||||
|
icon: mdi:television
|
||||||
|
- title: Lidarr
|
||||||
|
url: https://lidarr.home
|
||||||
|
icon: mdi:music
|
||||||
|
- title: Prowlarr
|
||||||
|
url: https://prowlarr.home
|
||||||
|
icon: mdi:radar
|
||||||
|
- title: qBittorrent
|
||||||
|
url: https://qbit.home
|
||||||
|
icon: mdi:download
|
||||||
|
- title: Portainer
|
||||||
|
url: https://portainer.home
|
||||||
|
icon: mdi:docker
|
||||||
|
- title: Immich
|
||||||
|
url: https://photo.home
|
||||||
|
icon: mdi:image-multiple
|
||||||
|
- title: Navidrome
|
||||||
|
url: https://music.home
|
||||||
|
icon: mdi:music-box-multiple
|
||||||
|
- title: CopyParty
|
||||||
|
url: https://copyparty.home
|
||||||
|
icon: mdi:folder-multiple
|
||||||
|
- title: Gitea
|
||||||
|
url: https://git.home
|
||||||
|
icon: mdi:git
|
||||||
|
- title: Grafana
|
||||||
|
url: https://grafana.home
|
||||||
|
icon: mdi:chart-line
|
||||||
|
- type: docker-containers
|
||||||
|
title: Docker
|
||||||
|
show-stats: true
|
||||||
|
- type: custom-api
|
||||||
|
title: Portainer
|
||||||
|
title-url: https://portainer.home
|
||||||
|
cache: 1h
|
||||||
|
url: ${PORTAINER_URL}/api/endpoints/${PORTAINER_ENDPOINT_ID}
|
||||||
|
headers:
|
||||||
|
X-API-Key: ${PORTAINER_API_KEY}
|
||||||
|
template: |
|
||||||
|
<style>.list-horizontal-text.no-bullets > *:not(:last-child)::after { content: none !important; } .list-horizontal-text.no-bullets > *:not(:last-child) { margin-right: 1em; }</style>
|
||||||
|
<div class="list list-horizontal-text no-bullets">
|
||||||
|
<span><strong>{{ .JSON.String "Name" }}</strong></span>
|
||||||
|
<span>Containers: {{ .JSON.Int "Snapshots.0.ContainerCount" }}</span>
|
||||||
|
<span>Volumes: {{ .JSON.Int "Snapshots.0.VolumeCount" }}</span>
|
||||||
|
<span>Networks: {{ .JSON.Int "Snapshots.0.DockerSnapshotRaw.Networks.#" }}</span>
|
||||||
|
</div>
|
||||||
|
<ul class="list list-gap-4 margin-top-10">
|
||||||
|
<li>Running <strong>{{ .JSON.Int "Snapshots.0.RunningContainerCount" }}</strong></li>
|
||||||
|
<li>Healthy <strong>{{ .JSON.Int "Snapshots.0.HealthyContainerCount" }}</strong></li>
|
||||||
|
<li>Stopped <strong>{{ .JSON.Int "Snapshots.0.StoppedContainerCount" }}</strong></li>
|
||||||
|
<li>Unhealthy <strong>{{ .JSON.Int "Snapshots.0.DockerSnapshotRaw.Containers.#(Health=\"unhealthy\").#" }}</strong></li>
|
||||||
|
</ul>
|
||||||
450
config/monitoring/glance/widgets/arr-radarr-missing.yml
Normal file
450
config/monitoring/glance/widgets/arr-radarr-missing.yml
Normal file
@@ -0,0 +1,450 @@
|
|||||||
|
# *arr community widget: Radarr wanted movies
|
||||||
|
- type: custom-api
|
||||||
|
title: Wanted Movies
|
||||||
|
title-url: ${RADARR_URL}
|
||||||
|
cache: 30m
|
||||||
|
options:
|
||||||
|
service: radarr
|
||||||
|
type: missing
|
||||||
|
size: medium
|
||||||
|
collapse-after: 5
|
||||||
|
show-grabbed: false
|
||||||
|
interval: 20
|
||||||
|
api-base-url: ${RADARR_API_URL}
|
||||||
|
key: ${RADARR_KEY}
|
||||||
|
url: ${RADARR_URL}
|
||||||
|
template: |
|
||||||
|
{{ $collapseAfter := .Options.IntOr "collapse-after" 5 }}
|
||||||
|
{{ $showGrabbed := .Options.BoolOr "show-grabbed" false }}
|
||||||
|
{{ $sortTime := .Options.StringOr "sort-time" "desc" }}
|
||||||
|
{{ $coverProxy := .Options.StringOr "cover-proxy" "" }}
|
||||||
|
{{ $size := .Options.StringOr "size" "medium" }}
|
||||||
|
{{ $service := .Options.StringOr "service" "" }}
|
||||||
|
{{ $type := .Options.StringOr "type" "" }}
|
||||||
|
{{ $intervalH := .Options.IntOr "interval" 0 | mul 24 }}
|
||||||
|
|
||||||
|
{{ $now := now | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $posInterval := (offsetNow (printf "+%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $negInterval := (offsetNow (printf "-%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
|
||||||
|
{{ $apiBaseUrl := .Options.StringOr "api-base-url" "" }}
|
||||||
|
{{ $key := .Options.StringOr "key" "" }}
|
||||||
|
{{ $url := .Options.StringOr "url" $apiBaseUrl }}
|
||||||
|
|
||||||
|
{{ if or (and (ne $service "sonarr") (ne $service "radarr") (ne $service "lidarr"))
|
||||||
|
(and (ne $type "upcoming") (ne $type "recent") (ne $type "missing"))
|
||||||
|
(eq $apiBaseUrl "") (eq $key "") (eq $url "") }}
|
||||||
|
<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">
|
||||||
|
Some options are not set or malformed
|
||||||
|
<table style="border-spacing: 1rem;">
|
||||||
|
<tr><td>service</td><td>{{ $service }}</td><td>must be sonarr, radarr, or lidarr</td></tr>
|
||||||
|
<tr><td>type</td><td>{{ $type }}</td><td>must be upcoming, recent, or missing</td></tr>
|
||||||
|
<tr><td>api-base-url</td><td>{{ $apiBaseUrl }}</td><td>should include http(s):// and port if needed</td></tr>
|
||||||
|
<tr><td>key</td><td>{{ $key }}</td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
{{ else }}
|
||||||
|
{{ $requestUrl := "" }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeSeries=true&includeEpisode=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50&includeSeries=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?includeSeries=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeMovie=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/history/since?includeArtist=true&includeAlbum=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/wanted/missing?page=1&pageSize=50&includeArtist=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/calendar?includeArtist=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ $data := newRequest $requestUrl
|
||||||
|
| withHeader "Accept" "application/json"
|
||||||
|
| withHeader "X-Api-Key" $key
|
||||||
|
| getResponse }}
|
||||||
|
|
||||||
|
<ul class="list list-gap-14 collapsible-container single-line-titles" data-collapse-after="{{ $collapseAfter }}">
|
||||||
|
{{ $array := "" }}
|
||||||
|
{{ $sortByField := "" }}
|
||||||
|
{{ $itemDisplayed := false }}
|
||||||
|
{{ $itemDate := "" }}
|
||||||
|
{{ $isAvailable := false }}
|
||||||
|
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $array = "records" }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "recent" }}
|
||||||
|
{{ $sortByField = "date" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ range $data.JSON.Array $array | sortByTime $sortByField "rfc3339" $sortTime }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $itemDate = .String "airDateUtc" | parseTime "RFC3339" }}
|
||||||
|
{{ $itemDate = $itemDate.In now.Location | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ else if eq $service "radarr"}}
|
||||||
|
{{ $isAvailable = .Bool "isAvailable" }}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ else if eq $service "lidarr"}}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if or (eq $type "upcoming") (eq $type "recent") (and (or (and (gt $itemDate $negInterval) ((lt $itemDate $now ))) (eq $intervalH 0)) $isAvailable) }}
|
||||||
|
{{ $itemDisplayed = true }}
|
||||||
|
{{ $title := "" }}
|
||||||
|
{{ $subtitle := "" }}
|
||||||
|
{{ $coverUrl := "" }}
|
||||||
|
{{ $status := "" }}
|
||||||
|
{{ $coverBase := "" }}
|
||||||
|
{{ $height := "" }}
|
||||||
|
{{ $width := "" }}
|
||||||
|
{{ $popoverTitle := "" }}
|
||||||
|
{{ $popoverSubtitle := "" }}
|
||||||
|
{{ $popoverSummary := "" }}
|
||||||
|
{{ $summary := "" }}
|
||||||
|
{{ $link := "" }}
|
||||||
|
{{ $grabbed := false }}
|
||||||
|
{{ $date := now }}
|
||||||
|
{{ $datetype := "" }}
|
||||||
|
{{ $seString := "" }}
|
||||||
|
{{ $genres := "" }}
|
||||||
|
{{ $buttonJustify := "left" }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $series := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "seriesId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "seriesId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "series.title" }}
|
||||||
|
{{ $link = printf "%s/series/%s#" $url (.String "series.titleSlug") }}
|
||||||
|
{{ $series = .Get "series" }}
|
||||||
|
{{ $genres = $series.Get "genres" }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $date = .String "date" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "episode.title" }}
|
||||||
|
{{ $summary = .String "episode.overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "episode.seasonNumber") (.Int "episode.episodeNumber") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "episode.title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "episode.overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Aired" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Airs" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ $movie := "" }}
|
||||||
|
{{ $status = .String "status" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $status "announced"}}
|
||||||
|
{{ if ne (.String "inCinemas") "" }}
|
||||||
|
{{ $date = (.String "inCinemas" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "In Cinemas" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $status "inCinemas"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ else if eq $status "released"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "movie.id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "movie.id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "movie.title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "movie.overview" }}
|
||||||
|
{{ $popoverTitle = .String "movie.title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "movie.overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "movie.titleSlug") }}
|
||||||
|
{{ $movie = .Get "movie" }}
|
||||||
|
{{ $genres = $movie.Get "genres" }}
|
||||||
|
{{ if and $showGrabbed (gt (.Int "movie.movieFileId") 0) }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "titleSlug") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ $genres = .Get "genres" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ if and $showGrabbed (.Bool "movie.hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if and $showGrabbed (.Bool "hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ $artist := "" }}
|
||||||
|
{{ $album := "" }}
|
||||||
|
{{ $albumId := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v1/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ $artist = $album.Get "artist" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase (.String "albumId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase (.String "albumId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ $title = $album.String "title" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $popoverTitle = $album.String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = $artist.String "overview" }}
|
||||||
|
|
||||||
|
{{ else }}
|
||||||
|
{{ $artist = .Get "artist" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ range .Array "releases" }}
|
||||||
|
{{ $albumId = .String "albumId" }}
|
||||||
|
{{ break }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase $albumId $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase $albumId }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "artist.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $size "small" }}
|
||||||
|
{{ $buttonJustify = "right" }}
|
||||||
|
{{ $height = "9rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "9rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "6rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "medium" }}
|
||||||
|
{{ $height = "12rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "8rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "large" }}
|
||||||
|
{{ $height = "15rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "15rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "10rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "huge" }}
|
||||||
|
{{ $height = "18rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "18rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<li style="position: relative;">
|
||||||
|
<div class="flex gap-10 items-start thumbnail-container thumbnail-parent">
|
||||||
|
<div>
|
||||||
|
<div data-popover-type="html" data-popover-position="above" data-popover-show-delay="500" style="width: {{ $width }}; height: {{ $height }}; align-content: center;">
|
||||||
|
<div data-popover-html>
|
||||||
|
<div style="margin: 5px;">
|
||||||
|
<strong class="size-h4 color-primary" title="{{ $popoverTitle }}">{{ $popoverTitle }}</strong>
|
||||||
|
<div class="size-h4 text-truncate text-very-compact color-subdue" title="{{ $popoverSubtitle }}">{{ $popoverSubtitle }}</div>
|
||||||
|
<p class="margin-top-20" style="overflow-y: auto; text-align: justify; max-height: 20rem;">
|
||||||
|
{{ if ne $popoverSummary "" }}
|
||||||
|
{{ $popoverSummary }}
|
||||||
|
{{ else }}
|
||||||
|
TBA
|
||||||
|
{{ end }}
|
||||||
|
</p>
|
||||||
|
{{ if gt (len ($genres.Array "")) 0 }}
|
||||||
|
<ul class="attachments margin-top-20">
|
||||||
|
{{ range $genres.Array "" }}
|
||||||
|
<li>{{ .String "" }}</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img class="thumbnail" src="{{ $coverUrl }}" alt="Cover for {{ .String "title" }}" loading="lazy" style="width: 100%; height: 100%; box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); object-fit: cover; border-radius: 0.5rem;">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="shrink min-width-0" style="height: 9rem; position: relative; padding-top: 5px; padding-right: 5px;">
|
||||||
|
<strong class="size-h4 block text-truncate color-primary" title="{{ $title }}">{{ $title }}</strong>
|
||||||
|
<div class="text-truncate text-very-compact" title="{{ $subtitle }}">{{ $subtitle }}</div>
|
||||||
|
<div class="text-very-compact text-truncate">
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
<div>{{ $seString }} - {{ $datetype }} {{ $date.Format "1/2 03:04PM" }}</div>
|
||||||
|
{{ else }}
|
||||||
|
<span>{{ $datetype }} {{ $date.Format "1/2" }}</span>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ if eq $buttonJustify "right" }}
|
||||||
|
</div>
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="position: absolute; bottom: 1rem; right: 1rem;
|
||||||
|
{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
<div class="{{ if eq $size "small" }}text-truncate{{ if eq $service "radarr" }} margin-top-5{{ end }}{{ else }}text-truncate-2-lines margin-top-5{{ end }}">
|
||||||
|
{{ $summary }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if not $itemDisplayed }}
|
||||||
|
<li>No items found.</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
449
config/monitoring/glance/widgets/arr-radarr-recent.yml
Normal file
449
config/monitoring/glance/widgets/arr-radarr-recent.yml
Normal file
@@ -0,0 +1,449 @@
|
|||||||
|
# *arr community widget: Radarr recent movies
|
||||||
|
- type: custom-api
|
||||||
|
title: Recent Movies
|
||||||
|
title-url: ${RADARR_URL}
|
||||||
|
cache: 30m
|
||||||
|
options:
|
||||||
|
service: radarr
|
||||||
|
type: recent
|
||||||
|
size: medium
|
||||||
|
collapse-after: 5
|
||||||
|
show-grabbed: false
|
||||||
|
interval: 20
|
||||||
|
api-base-url: ${RADARR_API_URL}
|
||||||
|
key: ${RADARR_KEY}
|
||||||
|
url: ${RADARR_URL}
|
||||||
|
template: |
|
||||||
|
{{ $collapseAfter := .Options.IntOr "collapse-after" 5 }}
|
||||||
|
{{ $showGrabbed := .Options.BoolOr "show-grabbed" false }}
|
||||||
|
{{ $sortTime := .Options.StringOr "sort-time" "desc" }}
|
||||||
|
{{ $coverProxy := .Options.StringOr "cover-proxy" "" }}
|
||||||
|
{{ $size := .Options.StringOr "size" "medium" }}
|
||||||
|
{{ $service := .Options.StringOr "service" "" }}
|
||||||
|
{{ $type := .Options.StringOr "type" "" }}
|
||||||
|
{{ $intervalH := .Options.IntOr "interval" 0 | mul 24 }}
|
||||||
|
|
||||||
|
{{ $now := now | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $posInterval := (offsetNow (printf "+%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $negInterval := (offsetNow (printf "-%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
|
||||||
|
{{ $apiBaseUrl := .Options.StringOr "api-base-url" "" }}
|
||||||
|
{{ $key := .Options.StringOr "key" "" }}
|
||||||
|
{{ $url := .Options.StringOr "url" $apiBaseUrl }}
|
||||||
|
|
||||||
|
{{ if or (and (ne $service "sonarr") (ne $service "radarr") (ne $service "lidarr"))
|
||||||
|
(and (ne $type "upcoming") (ne $type "recent") (ne $type "missing"))
|
||||||
|
(eq $apiBaseUrl "") (eq $key "") (eq $url "") }}
|
||||||
|
<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">
|
||||||
|
Some options are not set or malformed
|
||||||
|
<table style="border-spacing: 1rem;">
|
||||||
|
<tr><td>service</td><td>{{ $service }}</td><td>must be sonarr, radarr, or lidarr</td></tr>
|
||||||
|
<tr><td>type</td><td>{{ $type }}</td><td>must be upcoming, recent, or missing</td></tr>
|
||||||
|
<tr><td>api-base-url</td><td>{{ $apiBaseUrl }}</td><td>should include http(s):// and port if needed</td></tr>
|
||||||
|
<tr><td>key</td><td>{{ $key }}</td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
{{ else }}
|
||||||
|
{{ $requestUrl := "" }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeSeries=true&includeEpisode=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50&includeSeries=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?includeSeries=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeMovie=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/history/since?includeArtist=true&includeAlbum=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/wanted/missing?page=1&pageSize=50&includeArtist=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/calendar?includeArtist=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ $data := newRequest $requestUrl
|
||||||
|
| withHeader "Accept" "application/json"
|
||||||
|
| withHeader "X-Api-Key" $key
|
||||||
|
| getResponse }}
|
||||||
|
|
||||||
|
<ul class="list list-gap-14 collapsible-container single-line-titles" data-collapse-after="{{ $collapseAfter }}">
|
||||||
|
{{ $array := "" }}
|
||||||
|
{{ $sortByField := "" }}
|
||||||
|
{{ $itemDisplayed := false }}
|
||||||
|
{{ $itemDate := "" }}
|
||||||
|
{{ $isAvailable := false }}
|
||||||
|
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $array = "records" }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "recent" }}
|
||||||
|
{{ $sortByField = "date" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ range $data.JSON.Array $array | sortByTime $sortByField "rfc3339" $sortTime }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $itemDate = .String "airDateUtc" | parseTime "RFC3339" }}
|
||||||
|
{{ $itemDate = $itemDate.In now.Location | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ else if eq $service "radarr"}}
|
||||||
|
{{ $isAvailable = .Bool "isAvailable" }}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ else if eq $service "lidarr"}}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if or (eq $type "upcoming") (eq $type "recent") (and (or (and (gt $itemDate $negInterval) ((lt $itemDate $now ))) (eq $intervalH 0)) $isAvailable) }}
|
||||||
|
{{ $itemDisplayed = true }}
|
||||||
|
{{ $title := "" }}
|
||||||
|
{{ $subtitle := "" }}
|
||||||
|
{{ $coverUrl := "" }}
|
||||||
|
{{ $status := "" }}
|
||||||
|
{{ $coverBase := "" }}
|
||||||
|
{{ $height := "" }}
|
||||||
|
{{ $width := "" }}
|
||||||
|
{{ $popoverTitle := "" }}
|
||||||
|
{{ $popoverSubtitle := "" }}
|
||||||
|
{{ $popoverSummary := "" }}
|
||||||
|
{{ $summary := "" }}
|
||||||
|
{{ $link := "" }}
|
||||||
|
{{ $grabbed := false }}
|
||||||
|
{{ $date := now }}
|
||||||
|
{{ $datetype := "" }}
|
||||||
|
{{ $seString := "" }}
|
||||||
|
{{ $genres := "" }}
|
||||||
|
{{ $buttonJustify := "left" }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $series := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "seriesId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "seriesId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "series.title" }}
|
||||||
|
{{ $link = printf "%s/series/%s#" $url (.String "series.titleSlug") }}
|
||||||
|
{{ $series = .Get "series" }}
|
||||||
|
{{ $genres = $series.Get "genres" }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $date = .String "date" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "episode.title" }}
|
||||||
|
{{ $summary = .String "episode.overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "episode.seasonNumber") (.Int "episode.episodeNumber") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "episode.title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "episode.overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Aired" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Airs" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ $movie := "" }}
|
||||||
|
{{ $status = .String "status" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $status "announced"}}
|
||||||
|
{{ if ne (.String "inCinemas") "" }}
|
||||||
|
{{ $date = (.String "inCinemas" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "In Cinemas" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $status "inCinemas"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ else if eq $status "released"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "movie.id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "movie.id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "movie.title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "movie.overview" }}
|
||||||
|
{{ $popoverTitle = .String "movie.title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "movie.overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "movie.titleSlug") }}
|
||||||
|
{{ $movie = .Get "movie" }}
|
||||||
|
{{ $genres = $movie.Get "genres" }}
|
||||||
|
{{ if and $showGrabbed (gt (.Int "movie.movieFileId") 0) }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "titleSlug") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ $genres = .Get "genres" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ if and $showGrabbed (.Bool "movie.hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if and $showGrabbed (.Bool "hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ $artist := "" }}
|
||||||
|
{{ $album := "" }}
|
||||||
|
{{ $albumId := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v1/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ $artist = $album.Get "artist" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase (.String "albumId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase (.String "albumId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ $title = $album.String "title" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $popoverTitle = $album.String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = $artist.String "overview" }}
|
||||||
|
|
||||||
|
{{ else }}
|
||||||
|
{{ $artist = .Get "artist" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ range .Array "releases" }}
|
||||||
|
{{ $albumId = .String "albumId" }}
|
||||||
|
{{ break }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase $albumId $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase $albumId }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "artist.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $size "small" }}
|
||||||
|
{{ $buttonJustify = "right" }}
|
||||||
|
{{ $height = "9rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "9rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "6rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "medium" }}
|
||||||
|
{{ $height = "12rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "8rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "large" }}
|
||||||
|
{{ $height = "15rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "15rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "10rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "huge" }}
|
||||||
|
{{ $height = "18rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "18rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<li style="position: relative;">
|
||||||
|
<div class="flex gap-10 items-start thumbnail-container thumbnail-parent">
|
||||||
|
<div>
|
||||||
|
<div data-popover-type="html" data-popover-position="above" data-popover-show-delay="500" style="width: {{ $width }}; height: {{ $height }}; align-content: center;">
|
||||||
|
<div data-popover-html>
|
||||||
|
<div style="margin: 5px;">
|
||||||
|
<strong class="size-h4 color-primary" title="{{ $popoverTitle }}">{{ $popoverTitle }}</strong>
|
||||||
|
<div class="size-h4 text-truncate text-very-compact color-subdue" title="{{ $popoverSubtitle }}">{{ $popoverSubtitle }}</div>
|
||||||
|
<p class="margin-top-20" style="overflow-y: auto; text-align: justify; max-height: 20rem;">
|
||||||
|
{{ if ne $popoverSummary "" }}
|
||||||
|
{{ $popoverSummary }}
|
||||||
|
{{ else }}
|
||||||
|
TBA
|
||||||
|
{{ end }}
|
||||||
|
</p>
|
||||||
|
{{ if gt (len ($genres.Array "")) 0 }}
|
||||||
|
<ul class="attachments margin-top-20">
|
||||||
|
{{ range $genres.Array "" }}
|
||||||
|
<li>{{ .String "" }}</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img class="thumbnail" src="{{ $coverUrl }}" alt="Cover for {{ .String "title" }}" loading="lazy" style="width: 100%; height: 100%; box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); object-fit: cover; border-radius: 0.5rem;">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="shrink min-width-0" style="height: 9rem; position: relative; padding-top: 5px; padding-right: 5px;">
|
||||||
|
<strong class="size-h4 block text-truncate color-primary" title="{{ $title }}">{{ $title }}</strong>
|
||||||
|
<div class="text-truncate text-very-compact" title="{{ $subtitle }}">{{ $subtitle }}</div>
|
||||||
|
<div class="text-very-compact text-truncate">
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
<div>{{ $seString }} - {{ $datetype }} {{ $date.Format "1/2 03:04PM" }}</div>
|
||||||
|
{{ else }}
|
||||||
|
<span>{{ $datetype }} {{ $date.Format "1/2" }}</span>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ if eq $buttonJustify "right" }}
|
||||||
|
</div>
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="position: absolute; bottom: 1rem; right: 1rem;
|
||||||
|
{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
<div class="{{ if eq $size "small" }}text-truncate{{ if eq $service "radarr" }} margin-top-5{{ end }}{{ else }}text-truncate-2-lines margin-top-5{{ end }}">
|
||||||
|
{{ $summary }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if not $itemDisplayed }}
|
||||||
|
<li>No items found.</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
449
config/monitoring/glance/widgets/arr-radarr-upcoming.yml
Normal file
449
config/monitoring/glance/widgets/arr-radarr-upcoming.yml
Normal file
@@ -0,0 +1,449 @@
|
|||||||
|
# *arr community widget: Radarr upcoming movies
|
||||||
|
- type: custom-api
|
||||||
|
title: Upcoming Movies
|
||||||
|
title-url: ${RADARR_URL}
|
||||||
|
cache: 30m
|
||||||
|
options:
|
||||||
|
service: radarr
|
||||||
|
type: upcoming
|
||||||
|
size: medium
|
||||||
|
collapse-after: 5
|
||||||
|
show-grabbed: false
|
||||||
|
interval: 20
|
||||||
|
api-base-url: ${RADARR_API_URL}
|
||||||
|
key: ${RADARR_KEY}
|
||||||
|
url: ${RADARR_URL}
|
||||||
|
template: |
|
||||||
|
{{ $collapseAfter := .Options.IntOr "collapse-after" 5 }}
|
||||||
|
{{ $showGrabbed := .Options.BoolOr "show-grabbed" false }}
|
||||||
|
{{ $sortTime := .Options.StringOr "sort-time" "desc" }}
|
||||||
|
{{ $coverProxy := .Options.StringOr "cover-proxy" "" }}
|
||||||
|
{{ $size := .Options.StringOr "size" "medium" }}
|
||||||
|
{{ $service := .Options.StringOr "service" "" }}
|
||||||
|
{{ $type := .Options.StringOr "type" "" }}
|
||||||
|
{{ $intervalH := .Options.IntOr "interval" 0 | mul 24 }}
|
||||||
|
|
||||||
|
{{ $now := now | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $posInterval := (offsetNow (printf "+%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $negInterval := (offsetNow (printf "-%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
|
||||||
|
{{ $apiBaseUrl := .Options.StringOr "api-base-url" "" }}
|
||||||
|
{{ $key := .Options.StringOr "key" "" }}
|
||||||
|
{{ $url := .Options.StringOr "url" $apiBaseUrl }}
|
||||||
|
|
||||||
|
{{ if or (and (ne $service "sonarr") (ne $service "radarr") (ne $service "lidarr"))
|
||||||
|
(and (ne $type "upcoming") (ne $type "recent") (ne $type "missing"))
|
||||||
|
(eq $apiBaseUrl "") (eq $key "") (eq $url "") }}
|
||||||
|
<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">
|
||||||
|
Some options are not set or malformed
|
||||||
|
<table style="border-spacing: 1rem;">
|
||||||
|
<tr><td>service</td><td>{{ $service }}</td><td>must be sonarr, radarr, or lidarr</td></tr>
|
||||||
|
<tr><td>type</td><td>{{ $type }}</td><td>must be upcoming, recent, or missing</td></tr>
|
||||||
|
<tr><td>api-base-url</td><td>{{ $apiBaseUrl }}</td><td>should include http(s):// and port if needed</td></tr>
|
||||||
|
<tr><td>key</td><td>{{ $key }}</td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
{{ else }}
|
||||||
|
{{ $requestUrl := "" }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeSeries=true&includeEpisode=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50&includeSeries=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?includeSeries=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeMovie=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/history/since?includeArtist=true&includeAlbum=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/wanted/missing?page=1&pageSize=50&includeArtist=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/calendar?includeArtist=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ $data := newRequest $requestUrl
|
||||||
|
| withHeader "Accept" "application/json"
|
||||||
|
| withHeader "X-Api-Key" $key
|
||||||
|
| getResponse }}
|
||||||
|
|
||||||
|
<ul class="list list-gap-14 collapsible-container single-line-titles" data-collapse-after="{{ $collapseAfter }}">
|
||||||
|
{{ $array := "" }}
|
||||||
|
{{ $sortByField := "" }}
|
||||||
|
{{ $itemDisplayed := false }}
|
||||||
|
{{ $itemDate := "" }}
|
||||||
|
{{ $isAvailable := false }}
|
||||||
|
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $array = "records" }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "recent" }}
|
||||||
|
{{ $sortByField = "date" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ range $data.JSON.Array $array | sortByTime $sortByField "rfc3339" $sortTime }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $itemDate = .String "airDateUtc" | parseTime "RFC3339" }}
|
||||||
|
{{ $itemDate = $itemDate.In now.Location | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ else if eq $service "radarr"}}
|
||||||
|
{{ $isAvailable = .Bool "isAvailable" }}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ else if eq $service "lidarr"}}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if or (eq $type "upcoming") (eq $type "recent") (and (or (and (gt $itemDate $negInterval) ((lt $itemDate $now ))) (eq $intervalH 0)) $isAvailable) }}
|
||||||
|
{{ $itemDisplayed = true }}
|
||||||
|
{{ $title := "" }}
|
||||||
|
{{ $subtitle := "" }}
|
||||||
|
{{ $coverUrl := "" }}
|
||||||
|
{{ $status := "" }}
|
||||||
|
{{ $coverBase := "" }}
|
||||||
|
{{ $height := "" }}
|
||||||
|
{{ $width := "" }}
|
||||||
|
{{ $popoverTitle := "" }}
|
||||||
|
{{ $popoverSubtitle := "" }}
|
||||||
|
{{ $popoverSummary := "" }}
|
||||||
|
{{ $summary := "" }}
|
||||||
|
{{ $link := "" }}
|
||||||
|
{{ $grabbed := false }}
|
||||||
|
{{ $date := now }}
|
||||||
|
{{ $datetype := "" }}
|
||||||
|
{{ $seString := "" }}
|
||||||
|
{{ $genres := "" }}
|
||||||
|
{{ $buttonJustify := "left" }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $series := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "seriesId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "seriesId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "series.title" }}
|
||||||
|
{{ $link = printf "%s/series/%s#" $url (.String "series.titleSlug") }}
|
||||||
|
{{ $series = .Get "series" }}
|
||||||
|
{{ $genres = $series.Get "genres" }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $date = .String "date" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "episode.title" }}
|
||||||
|
{{ $summary = .String "episode.overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "episode.seasonNumber") (.Int "episode.episodeNumber") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "episode.title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "episode.overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Aired" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Airs" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ $movie := "" }}
|
||||||
|
{{ $status = .String "status" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $status "announced"}}
|
||||||
|
{{ if ne (.String "inCinemas") "" }}
|
||||||
|
{{ $date = (.String "inCinemas" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "In Cinemas" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $status "inCinemas"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ else if eq $status "released"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "movie.id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "movie.id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "movie.title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "movie.overview" }}
|
||||||
|
{{ $popoverTitle = .String "movie.title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "movie.overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "movie.titleSlug") }}
|
||||||
|
{{ $movie = .Get "movie" }}
|
||||||
|
{{ $genres = $movie.Get "genres" }}
|
||||||
|
{{ if and $showGrabbed (gt (.Int "movie.movieFileId") 0) }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "titleSlug") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ $genres = .Get "genres" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ if and $showGrabbed (.Bool "movie.hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if and $showGrabbed (.Bool "hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ $artist := "" }}
|
||||||
|
{{ $album := "" }}
|
||||||
|
{{ $albumId := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v1/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ $artist = $album.Get "artist" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase (.String "albumId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase (.String "albumId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ $title = $album.String "title" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $popoverTitle = $album.String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = $artist.String "overview" }}
|
||||||
|
|
||||||
|
{{ else }}
|
||||||
|
{{ $artist = .Get "artist" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ range .Array "releases" }}
|
||||||
|
{{ $albumId = .String "albumId" }}
|
||||||
|
{{ break }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase $albumId $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase $albumId }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "artist.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $size "small" }}
|
||||||
|
{{ $buttonJustify = "right" }}
|
||||||
|
{{ $height = "9rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "9rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "6rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "medium" }}
|
||||||
|
{{ $height = "12rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "8rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "large" }}
|
||||||
|
{{ $height = "15rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "15rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "10rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "huge" }}
|
||||||
|
{{ $height = "18rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "18rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<li style="position: relative;">
|
||||||
|
<div class="flex gap-10 items-start thumbnail-container thumbnail-parent">
|
||||||
|
<div>
|
||||||
|
<div data-popover-type="html" data-popover-position="above" data-popover-show-delay="500" style="width: {{ $width }}; height: {{ $height }}; align-content: center;">
|
||||||
|
<div data-popover-html>
|
||||||
|
<div style="margin: 5px;">
|
||||||
|
<strong class="size-h4 color-primary" title="{{ $popoverTitle }}">{{ $popoverTitle }}</strong>
|
||||||
|
<div class="size-h4 text-truncate text-very-compact color-subdue" title="{{ $popoverSubtitle }}">{{ $popoverSubtitle }}</div>
|
||||||
|
<p class="margin-top-20" style="overflow-y: auto; text-align: justify; max-height: 20rem;">
|
||||||
|
{{ if ne $popoverSummary "" }}
|
||||||
|
{{ $popoverSummary }}
|
||||||
|
{{ else }}
|
||||||
|
TBA
|
||||||
|
{{ end }}
|
||||||
|
</p>
|
||||||
|
{{ if gt (len ($genres.Array "")) 0 }}
|
||||||
|
<ul class="attachments margin-top-20">
|
||||||
|
{{ range $genres.Array "" }}
|
||||||
|
<li>{{ .String "" }}</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img class="thumbnail" src="{{ $coverUrl }}" alt="Cover for {{ .String "title" }}" loading="lazy" style="width: 100%; height: 100%; box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); object-fit: cover; border-radius: 0.5rem;">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="shrink min-width-0" style="height: 9rem; position: relative; padding-top: 5px; padding-right: 5px;">
|
||||||
|
<strong class="size-h4 block text-truncate color-primary" title="{{ $title }}">{{ $title }}</strong>
|
||||||
|
<div class="text-truncate text-very-compact" title="{{ $subtitle }}">{{ $subtitle }}</div>
|
||||||
|
<div class="text-very-compact text-truncate">
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
<div>{{ $seString }} - {{ $datetype }} {{ $date.Format "1/2 03:04PM" }}</div>
|
||||||
|
{{ else }}
|
||||||
|
<span>{{ $datetype }} {{ $date.Format "1/2" }}</span>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ if eq $buttonJustify "right" }}
|
||||||
|
</div>
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="position: absolute; bottom: 1rem; right: 1rem;
|
||||||
|
{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
<div class="{{ if eq $size "small" }}text-truncate{{ if eq $service "radarr" }} margin-top-5{{ end }}{{ else }}text-truncate-2-lines margin-top-5{{ end }}">
|
||||||
|
{{ $summary }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if not $itemDisplayed }}
|
||||||
|
<li>No items found.</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
450
config/monitoring/glance/widgets/arr-sonarr-missing.yml
Normal file
450
config/monitoring/glance/widgets/arr-sonarr-missing.yml
Normal file
@@ -0,0 +1,450 @@
|
|||||||
|
# *arr community widget: Sonarr wanted episodes
|
||||||
|
- type: custom-api
|
||||||
|
title: Wanted Episodes
|
||||||
|
title-url: ${SONARR_URL}
|
||||||
|
cache: 30m
|
||||||
|
options:
|
||||||
|
service: sonarr
|
||||||
|
type: missing
|
||||||
|
size: medium
|
||||||
|
collapse-after: 5
|
||||||
|
show-grabbed: false
|
||||||
|
interval: 20
|
||||||
|
api-base-url: ${SONARR_API_URL}
|
||||||
|
key: ${SONARR_KEY}
|
||||||
|
url: ${SONARR_URL}
|
||||||
|
template: |
|
||||||
|
{{ $collapseAfter := .Options.IntOr "collapse-after" 5 }}
|
||||||
|
{{ $showGrabbed := .Options.BoolOr "show-grabbed" false }}
|
||||||
|
{{ $sortTime := .Options.StringOr "sort-time" "desc" }}
|
||||||
|
{{ $coverProxy := .Options.StringOr "cover-proxy" "" }}
|
||||||
|
{{ $size := .Options.StringOr "size" "medium" }}
|
||||||
|
{{ $service := .Options.StringOr "service" "" }}
|
||||||
|
{{ $type := .Options.StringOr "type" "" }}
|
||||||
|
{{ $intervalH := .Options.IntOr "interval" 0 | mul 24 }}
|
||||||
|
|
||||||
|
{{ $now := now | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $posInterval := (offsetNow (printf "+%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $negInterval := (offsetNow (printf "-%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
|
||||||
|
{{ $apiBaseUrl := .Options.StringOr "api-base-url" "" }}
|
||||||
|
{{ $key := .Options.StringOr "key" "" }}
|
||||||
|
{{ $url := .Options.StringOr "url" $apiBaseUrl }}
|
||||||
|
|
||||||
|
{{ if or (and (ne $service "sonarr") (ne $service "radarr") (ne $service "lidarr"))
|
||||||
|
(and (ne $type "upcoming") (ne $type "recent") (ne $type "missing"))
|
||||||
|
(eq $apiBaseUrl "") (eq $key "") (eq $url "") }}
|
||||||
|
<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">
|
||||||
|
Some options are not set or malformed
|
||||||
|
<table style="border-spacing: 1rem;">
|
||||||
|
<tr><td>service</td><td>{{ $service }}</td><td>must be sonarr, radarr, or lidarr</td></tr>
|
||||||
|
<tr><td>type</td><td>{{ $type }}</td><td>must be upcoming, recent, or missing</td></tr>
|
||||||
|
<tr><td>api-base-url</td><td>{{ $apiBaseUrl }}</td><td>should include http(s):// and port if needed</td></tr>
|
||||||
|
<tr><td>key</td><td>{{ $key }}</td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
{{ else }}
|
||||||
|
{{ $requestUrl := "" }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeSeries=true&includeEpisode=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50&includeSeries=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?includeSeries=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeMovie=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/history/since?includeArtist=true&includeAlbum=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/wanted/missing?page=1&pageSize=50&includeArtist=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/calendar?includeArtist=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ $data := newRequest $requestUrl
|
||||||
|
| withHeader "Accept" "application/json"
|
||||||
|
| withHeader "X-Api-Key" $key
|
||||||
|
| getResponse }}
|
||||||
|
|
||||||
|
<ul class="list list-gap-14 collapsible-container single-line-titles" data-collapse-after="{{ $collapseAfter }}">
|
||||||
|
{{ $array := "" }}
|
||||||
|
{{ $sortByField := "" }}
|
||||||
|
{{ $itemDisplayed := false }}
|
||||||
|
{{ $itemDate := "" }}
|
||||||
|
{{ $isAvailable := false }}
|
||||||
|
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $array = "records" }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "recent" }}
|
||||||
|
{{ $sortByField = "date" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ range $data.JSON.Array $array | sortByTime $sortByField "rfc3339" $sortTime }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $itemDate = .String "airDateUtc" | parseTime "RFC3339" }}
|
||||||
|
{{ $itemDate = $itemDate.In now.Location | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ else if eq $service "radarr"}}
|
||||||
|
{{ $isAvailable = .Bool "isAvailable" }}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ else if eq $service "lidarr"}}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if or (eq $type "upcoming") (eq $type "recent") (and (or (and (gt $itemDate $negInterval) ((lt $itemDate $now ))) (eq $intervalH 0)) $isAvailable) }}
|
||||||
|
{{ $itemDisplayed = true }}
|
||||||
|
{{ $title := "" }}
|
||||||
|
{{ $subtitle := "" }}
|
||||||
|
{{ $coverUrl := "" }}
|
||||||
|
{{ $status := "" }}
|
||||||
|
{{ $coverBase := "" }}
|
||||||
|
{{ $height := "" }}
|
||||||
|
{{ $width := "" }}
|
||||||
|
{{ $popoverTitle := "" }}
|
||||||
|
{{ $popoverSubtitle := "" }}
|
||||||
|
{{ $popoverSummary := "" }}
|
||||||
|
{{ $summary := "" }}
|
||||||
|
{{ $link := "" }}
|
||||||
|
{{ $grabbed := false }}
|
||||||
|
{{ $date := now }}
|
||||||
|
{{ $datetype := "" }}
|
||||||
|
{{ $seString := "" }}
|
||||||
|
{{ $genres := "" }}
|
||||||
|
{{ $buttonJustify := "left" }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $series := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "seriesId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "seriesId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "series.title" }}
|
||||||
|
{{ $link = printf "%s/series/%s#" $url (.String "series.titleSlug") }}
|
||||||
|
{{ $series = .Get "series" }}
|
||||||
|
{{ $genres = $series.Get "genres" }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $date = .String "date" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "episode.title" }}
|
||||||
|
{{ $summary = .String "episode.overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "episode.seasonNumber") (.Int "episode.episodeNumber") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "episode.title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "episode.overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Aired" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Airs" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ $movie := "" }}
|
||||||
|
{{ $status = .String "status" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $status "announced"}}
|
||||||
|
{{ if ne (.String "inCinemas") "" }}
|
||||||
|
{{ $date = (.String "inCinemas" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "In Cinemas" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $status "inCinemas"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ else if eq $status "released"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "movie.id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "movie.id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "movie.title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "movie.overview" }}
|
||||||
|
{{ $popoverTitle = .String "movie.title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "movie.overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "movie.titleSlug") }}
|
||||||
|
{{ $movie = .Get "movie" }}
|
||||||
|
{{ $genres = $movie.Get "genres" }}
|
||||||
|
{{ if and $showGrabbed (gt (.Int "movie.movieFileId") 0) }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "titleSlug") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ $genres = .Get "genres" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ if and $showGrabbed (.Bool "movie.hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if and $showGrabbed (.Bool "hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ $artist := "" }}
|
||||||
|
{{ $album := "" }}
|
||||||
|
{{ $albumId := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v1/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ $artist = $album.Get "artist" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase (.String "albumId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase (.String "albumId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ $title = $album.String "title" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $popoverTitle = $album.String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = $artist.String "overview" }}
|
||||||
|
|
||||||
|
{{ else }}
|
||||||
|
{{ $artist = .Get "artist" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ range .Array "releases" }}
|
||||||
|
{{ $albumId = .String "albumId" }}
|
||||||
|
{{ break }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase $albumId $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase $albumId }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "artist.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $size "small" }}
|
||||||
|
{{ $buttonJustify = "right" }}
|
||||||
|
{{ $height = "9rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "9rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "6rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "medium" }}
|
||||||
|
{{ $height = "12rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "8rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "large" }}
|
||||||
|
{{ $height = "15rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "15rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "10rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "huge" }}
|
||||||
|
{{ $height = "18rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "18rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<li style="position: relative;">
|
||||||
|
<div class="flex gap-10 items-start thumbnail-container thumbnail-parent">
|
||||||
|
<div>
|
||||||
|
<div data-popover-type="html" data-popover-position="above" data-popover-show-delay="500" style="width: {{ $width }}; height: {{ $height }}; align-content: center;">
|
||||||
|
<div data-popover-html>
|
||||||
|
<div style="margin: 5px;">
|
||||||
|
<strong class="size-h4 color-primary" title="{{ $popoverTitle }}">{{ $popoverTitle }}</strong>
|
||||||
|
<div class="size-h4 text-truncate text-very-compact color-subdue" title="{{ $popoverSubtitle }}">{{ $popoverSubtitle }}</div>
|
||||||
|
<p class="margin-top-20" style="overflow-y: auto; text-align: justify; max-height: 20rem;">
|
||||||
|
{{ if ne $popoverSummary "" }}
|
||||||
|
{{ $popoverSummary }}
|
||||||
|
{{ else }}
|
||||||
|
TBA
|
||||||
|
{{ end }}
|
||||||
|
</p>
|
||||||
|
{{ if gt (len ($genres.Array "")) 0 }}
|
||||||
|
<ul class="attachments margin-top-20">
|
||||||
|
{{ range $genres.Array "" }}
|
||||||
|
<li>{{ .String "" }}</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img class="thumbnail" src="{{ $coverUrl }}" alt="Cover for {{ .String "title" }}" loading="lazy" style="width: 100%; height: 100%; box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); object-fit: cover; border-radius: 0.5rem;">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="shrink min-width-0" style="height: 9rem; position: relative; padding-top: 5px; padding-right: 5px;">
|
||||||
|
<strong class="size-h4 block text-truncate color-primary" title="{{ $title }}">{{ $title }}</strong>
|
||||||
|
<div class="text-truncate text-very-compact" title="{{ $subtitle }}">{{ $subtitle }}</div>
|
||||||
|
<div class="text-very-compact text-truncate">
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
<div>{{ $seString }} - {{ $datetype }} {{ $date.Format "1/2 03:04PM" }}</div>
|
||||||
|
{{ else }}
|
||||||
|
<span>{{ $datetype }} {{ $date.Format "1/2" }}</span>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ if eq $buttonJustify "right" }}
|
||||||
|
</div>
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="position: absolute; bottom: 1rem; right: 1rem;
|
||||||
|
{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
<div class="{{ if eq $size "small" }}text-truncate{{ if eq $service "radarr" }} margin-top-5{{ end }}{{ else }}text-truncate-2-lines margin-top-5{{ end }}">
|
||||||
|
{{ $summary }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if not $itemDisplayed }}
|
||||||
|
<li>No items found.</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
450
config/monitoring/glance/widgets/arr-sonarr-recent.yml
Normal file
450
config/monitoring/glance/widgets/arr-sonarr-recent.yml
Normal file
@@ -0,0 +1,450 @@
|
|||||||
|
# *arr community widget: Sonarr recent episodes
|
||||||
|
- type: custom-api
|
||||||
|
title: Recent Episodes
|
||||||
|
title-url: ${SONARR_URL}
|
||||||
|
cache: 30m
|
||||||
|
options:
|
||||||
|
service: sonarr
|
||||||
|
type: recent
|
||||||
|
size: medium
|
||||||
|
collapse-after: 5
|
||||||
|
show-grabbed: false
|
||||||
|
interval: 20
|
||||||
|
api-base-url: ${SONARR_API_URL}
|
||||||
|
key: ${SONARR_KEY}
|
||||||
|
url: ${SONARR_URL}
|
||||||
|
template: |
|
||||||
|
{{ $collapseAfter := .Options.IntOr "collapse-after" 5 }}
|
||||||
|
{{ $showGrabbed := .Options.BoolOr "show-grabbed" false }}
|
||||||
|
{{ $sortTime := .Options.StringOr "sort-time" "desc" }}
|
||||||
|
{{ $coverProxy := .Options.StringOr "cover-proxy" "" }}
|
||||||
|
{{ $size := .Options.StringOr "size" "medium" }}
|
||||||
|
{{ $service := .Options.StringOr "service" "" }}
|
||||||
|
{{ $type := .Options.StringOr "type" "" }}
|
||||||
|
{{ $intervalH := .Options.IntOr "interval" 0 | mul 24 }}
|
||||||
|
|
||||||
|
{{ $now := now | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $posInterval := (offsetNow (printf "+%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $negInterval := (offsetNow (printf "-%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
|
||||||
|
{{ $apiBaseUrl := .Options.StringOr "api-base-url" "" }}
|
||||||
|
{{ $key := .Options.StringOr "key" "" }}
|
||||||
|
{{ $url := .Options.StringOr "url" $apiBaseUrl }}
|
||||||
|
|
||||||
|
{{ if or (and (ne $service "sonarr") (ne $service "radarr") (ne $service "lidarr"))
|
||||||
|
(and (ne $type "upcoming") (ne $type "recent") (ne $type "missing"))
|
||||||
|
(eq $apiBaseUrl "") (eq $key "") (eq $url "") }}
|
||||||
|
<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">
|
||||||
|
Some options are not set or malformed
|
||||||
|
<table style="border-spacing: 1rem;">
|
||||||
|
<tr><td>service</td><td>{{ $service }}</td><td>must be sonarr, radarr, or lidarr</td></tr>
|
||||||
|
<tr><td>type</td><td>{{ $type }}</td><td>must be upcoming, recent, or missing</td></tr>
|
||||||
|
<tr><td>api-base-url</td><td>{{ $apiBaseUrl }}</td><td>should include http(s):// and port if needed</td></tr>
|
||||||
|
<tr><td>key</td><td>{{ $key }}</td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
{{ else }}
|
||||||
|
{{ $requestUrl := "" }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeSeries=true&includeEpisode=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50&includeSeries=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?includeSeries=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeMovie=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/history/since?includeArtist=true&includeAlbum=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/wanted/missing?page=1&pageSize=50&includeArtist=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/calendar?includeArtist=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ $data := newRequest $requestUrl
|
||||||
|
| withHeader "Accept" "application/json"
|
||||||
|
| withHeader "X-Api-Key" $key
|
||||||
|
| getResponse }}
|
||||||
|
|
||||||
|
<ul class="list list-gap-14 collapsible-container single-line-titles" data-collapse-after="{{ $collapseAfter }}">
|
||||||
|
{{ $array := "" }}
|
||||||
|
{{ $sortByField := "" }}
|
||||||
|
{{ $itemDisplayed := false }}
|
||||||
|
{{ $itemDate := "" }}
|
||||||
|
{{ $isAvailable := false }}
|
||||||
|
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $array = "records" }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "recent" }}
|
||||||
|
{{ $sortByField = "date" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ range $data.JSON.Array $array | sortByTime $sortByField "rfc3339" $sortTime }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $itemDate = .String "airDateUtc" | parseTime "RFC3339" }}
|
||||||
|
{{ $itemDate = $itemDate.In now.Location | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ else if eq $service "radarr"}}
|
||||||
|
{{ $isAvailable = .Bool "isAvailable" }}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ else if eq $service "lidarr"}}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if or (eq $type "upcoming") (eq $type "recent") (and (or (and (gt $itemDate $negInterval) ((lt $itemDate $now ))) (eq $intervalH 0)) $isAvailable) }}
|
||||||
|
{{ $itemDisplayed = true }}
|
||||||
|
{{ $title := "" }}
|
||||||
|
{{ $subtitle := "" }}
|
||||||
|
{{ $coverUrl := "" }}
|
||||||
|
{{ $status := "" }}
|
||||||
|
{{ $coverBase := "" }}
|
||||||
|
{{ $height := "" }}
|
||||||
|
{{ $width := "" }}
|
||||||
|
{{ $popoverTitle := "" }}
|
||||||
|
{{ $popoverSubtitle := "" }}
|
||||||
|
{{ $popoverSummary := "" }}
|
||||||
|
{{ $summary := "" }}
|
||||||
|
{{ $link := "" }}
|
||||||
|
{{ $grabbed := false }}
|
||||||
|
{{ $date := now }}
|
||||||
|
{{ $datetype := "" }}
|
||||||
|
{{ $seString := "" }}
|
||||||
|
{{ $genres := "" }}
|
||||||
|
{{ $buttonJustify := "left" }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $series := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "seriesId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "seriesId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "series.title" }}
|
||||||
|
{{ $link = printf "%s/series/%s#" $url (.String "series.titleSlug") }}
|
||||||
|
{{ $series = .Get "series" }}
|
||||||
|
{{ $genres = $series.Get "genres" }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $date = .String "date" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "episode.title" }}
|
||||||
|
{{ $summary = .String "episode.overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "episode.seasonNumber") (.Int "episode.episodeNumber") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "episode.title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "episode.overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Aired" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Airs" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ $movie := "" }}
|
||||||
|
{{ $status = .String "status" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $status "announced"}}
|
||||||
|
{{ if ne (.String "inCinemas") "" }}
|
||||||
|
{{ $date = (.String "inCinemas" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "In Cinemas" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $status "inCinemas"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ else if eq $status "released"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "movie.id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "movie.id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "movie.title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "movie.overview" }}
|
||||||
|
{{ $popoverTitle = .String "movie.title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "movie.overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "movie.titleSlug") }}
|
||||||
|
{{ $movie = .Get "movie" }}
|
||||||
|
{{ $genres = $movie.Get "genres" }}
|
||||||
|
{{ if and $showGrabbed (gt (.Int "movie.movieFileId") 0) }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "titleSlug") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ $genres = .Get "genres" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ if and $showGrabbed (.Bool "movie.hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if and $showGrabbed (.Bool "hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ $artist := "" }}
|
||||||
|
{{ $album := "" }}
|
||||||
|
{{ $albumId := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v1/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ $artist = $album.Get "artist" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase (.String "albumId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase (.String "albumId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ $title = $album.String "title" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $popoverTitle = $album.String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = $artist.String "overview" }}
|
||||||
|
|
||||||
|
{{ else }}
|
||||||
|
{{ $artist = .Get "artist" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ range .Array "releases" }}
|
||||||
|
{{ $albumId = .String "albumId" }}
|
||||||
|
{{ break }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase $albumId $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase $albumId }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "artist.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $size "small" }}
|
||||||
|
{{ $buttonJustify = "right" }}
|
||||||
|
{{ $height = "9rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "9rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "6rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "medium" }}
|
||||||
|
{{ $height = "12rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "8rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "large" }}
|
||||||
|
{{ $height = "15rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "15rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "10rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "huge" }}
|
||||||
|
{{ $height = "18rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "18rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<li style="position: relative;">
|
||||||
|
<div class="flex gap-10 items-start thumbnail-container thumbnail-parent">
|
||||||
|
<div>
|
||||||
|
<div data-popover-type="html" data-popover-position="above" data-popover-show-delay="500" style="width: {{ $width }}; height: {{ $height }}; align-content: center;">
|
||||||
|
<div data-popover-html>
|
||||||
|
<div style="margin: 5px;">
|
||||||
|
<strong class="size-h4 color-primary" title="{{ $popoverTitle }}">{{ $popoverTitle }}</strong>
|
||||||
|
<div class="size-h4 text-truncate text-very-compact color-subdue" title="{{ $popoverSubtitle }}">{{ $popoverSubtitle }}</div>
|
||||||
|
<p class="margin-top-20" style="overflow-y: auto; text-align: justify; max-height: 20rem;">
|
||||||
|
{{ if ne $popoverSummary "" }}
|
||||||
|
{{ $popoverSummary }}
|
||||||
|
{{ else }}
|
||||||
|
TBA
|
||||||
|
{{ end }}
|
||||||
|
</p>
|
||||||
|
{{ if gt (len ($genres.Array "")) 0 }}
|
||||||
|
<ul class="attachments margin-top-20">
|
||||||
|
{{ range $genres.Array "" }}
|
||||||
|
<li>{{ .String "" }}</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img class="thumbnail" src="{{ $coverUrl }}" alt="Cover for {{ .String "title" }}" loading="lazy" style="width: 100%; height: 100%; box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); object-fit: cover; border-radius: 0.5rem;">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="shrink min-width-0" style="height: 9rem; position: relative; padding-top: 5px; padding-right: 5px;">
|
||||||
|
<strong class="size-h4 block text-truncate color-primary" title="{{ $title }}">{{ $title }}</strong>
|
||||||
|
<div class="text-truncate text-very-compact" title="{{ $subtitle }}">{{ $subtitle }}</div>
|
||||||
|
<div class="text-very-compact text-truncate">
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
<div>{{ $seString }} - {{ $datetype }} {{ $date.Format "1/2 03:04PM" }}</div>
|
||||||
|
{{ else }}
|
||||||
|
<span>{{ $datetype }} {{ $date.Format "1/2" }}</span>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ if eq $buttonJustify "right" }}
|
||||||
|
</div>
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="position: absolute; bottom: 1rem; right: 1rem;
|
||||||
|
{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
<div class="{{ if eq $size "small" }}text-truncate{{ if eq $service "radarr" }} margin-top-5{{ end }}{{ else }}text-truncate-2-lines margin-top-5{{ end }}">
|
||||||
|
{{ $summary }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if not $itemDisplayed }}
|
||||||
|
<li>No items found.</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
450
config/monitoring/glance/widgets/arr-sonarr-upcoming.yml
Normal file
450
config/monitoring/glance/widgets/arr-sonarr-upcoming.yml
Normal file
@@ -0,0 +1,450 @@
|
|||||||
|
# *arr community widget: Sonarr upcoming episodes
|
||||||
|
- type: custom-api
|
||||||
|
title: Upcoming Episodes
|
||||||
|
title-url: ${SONARR_URL}
|
||||||
|
cache: 30m
|
||||||
|
options:
|
||||||
|
service: sonarr
|
||||||
|
type: upcoming
|
||||||
|
size: medium
|
||||||
|
collapse-after: 5
|
||||||
|
show-grabbed: false
|
||||||
|
interval: 20
|
||||||
|
api-base-url: ${SONARR_API_URL}
|
||||||
|
key: ${SONARR_KEY}
|
||||||
|
url: ${SONARR_URL}
|
||||||
|
template: |
|
||||||
|
{{ $collapseAfter := .Options.IntOr "collapse-after" 5 }}
|
||||||
|
{{ $showGrabbed := .Options.BoolOr "show-grabbed" false }}
|
||||||
|
{{ $sortTime := .Options.StringOr "sort-time" "desc" }}
|
||||||
|
{{ $coverProxy := .Options.StringOr "cover-proxy" "" }}
|
||||||
|
{{ $size := .Options.StringOr "size" "medium" }}
|
||||||
|
{{ $service := .Options.StringOr "service" "" }}
|
||||||
|
{{ $type := .Options.StringOr "type" "" }}
|
||||||
|
{{ $intervalH := .Options.IntOr "interval" 0 | mul 24 }}
|
||||||
|
|
||||||
|
{{ $now := now | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $posInterval := (offsetNow (printf "+%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $negInterval := (offsetNow (printf "-%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
|
||||||
|
{{ $apiBaseUrl := .Options.StringOr "api-base-url" "" }}
|
||||||
|
{{ $key := .Options.StringOr "key" "" }}
|
||||||
|
{{ $url := .Options.StringOr "url" $apiBaseUrl }}
|
||||||
|
|
||||||
|
{{ if or (and (ne $service "sonarr") (ne $service "radarr") (ne $service "lidarr"))
|
||||||
|
(and (ne $type "upcoming") (ne $type "recent") (ne $type "missing"))
|
||||||
|
(eq $apiBaseUrl "") (eq $key "") (eq $url "") }}
|
||||||
|
<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">
|
||||||
|
Some options are not set or malformed
|
||||||
|
<table style="border-spacing: 1rem;">
|
||||||
|
<tr><td>service</td><td>{{ $service }}</td><td>must be sonarr, radarr, or lidarr</td></tr>
|
||||||
|
<tr><td>type</td><td>{{ $type }}</td><td>must be upcoming, recent, or missing</td></tr>
|
||||||
|
<tr><td>api-base-url</td><td>{{ $apiBaseUrl }}</td><td>should include http(s):// and port if needed</td></tr>
|
||||||
|
<tr><td>key</td><td>{{ $key }}</td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
{{ else }}
|
||||||
|
{{ $requestUrl := "" }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeSeries=true&includeEpisode=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50&includeSeries=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?includeSeries=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeMovie=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/history/since?includeArtist=true&includeAlbum=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/wanted/missing?page=1&pageSize=50&includeArtist=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/calendar?includeArtist=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ $data := newRequest $requestUrl
|
||||||
|
| withHeader "Accept" "application/json"
|
||||||
|
| withHeader "X-Api-Key" $key
|
||||||
|
| getResponse }}
|
||||||
|
|
||||||
|
<ul class="list list-gap-14 collapsible-container single-line-titles" data-collapse-after="{{ $collapseAfter }}">
|
||||||
|
{{ $array := "" }}
|
||||||
|
{{ $sortByField := "" }}
|
||||||
|
{{ $itemDisplayed := false }}
|
||||||
|
{{ $itemDate := "" }}
|
||||||
|
{{ $isAvailable := false }}
|
||||||
|
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $array = "records" }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "recent" }}
|
||||||
|
{{ $sortByField = "date" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ range $data.JSON.Array $array | sortByTime $sortByField "rfc3339" $sortTime }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $itemDate = .String "airDateUtc" | parseTime "RFC3339" }}
|
||||||
|
{{ $itemDate = $itemDate.In now.Location | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ else if eq $service "radarr"}}
|
||||||
|
{{ $isAvailable = .Bool "isAvailable" }}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ else if eq $service "lidarr"}}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if or (eq $type "upcoming") (eq $type "recent") (and (or (and (gt $itemDate $negInterval) ((lt $itemDate $now ))) (eq $intervalH 0)) $isAvailable) }}
|
||||||
|
{{ $itemDisplayed = true }}
|
||||||
|
{{ $title := "" }}
|
||||||
|
{{ $subtitle := "" }}
|
||||||
|
{{ $coverUrl := "" }}
|
||||||
|
{{ $status := "" }}
|
||||||
|
{{ $coverBase := "" }}
|
||||||
|
{{ $height := "" }}
|
||||||
|
{{ $width := "" }}
|
||||||
|
{{ $popoverTitle := "" }}
|
||||||
|
{{ $popoverSubtitle := "" }}
|
||||||
|
{{ $popoverSummary := "" }}
|
||||||
|
{{ $summary := "" }}
|
||||||
|
{{ $link := "" }}
|
||||||
|
{{ $grabbed := false }}
|
||||||
|
{{ $date := now }}
|
||||||
|
{{ $datetype := "" }}
|
||||||
|
{{ $seString := "" }}
|
||||||
|
{{ $genres := "" }}
|
||||||
|
{{ $buttonJustify := "left" }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $series := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "seriesId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "seriesId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "series.title" }}
|
||||||
|
{{ $link = printf "%s/series/%s#" $url (.String "series.titleSlug") }}
|
||||||
|
{{ $series = .Get "series" }}
|
||||||
|
{{ $genres = $series.Get "genres" }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $date = .String "date" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "episode.title" }}
|
||||||
|
{{ $summary = .String "episode.overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "episode.seasonNumber") (.Int "episode.episodeNumber") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "episode.title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "episode.overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Aired" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Airs" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ $movie := "" }}
|
||||||
|
{{ $status = .String "status" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $status "announced"}}
|
||||||
|
{{ if ne (.String "inCinemas") "" }}
|
||||||
|
{{ $date = (.String "inCinemas" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "In Cinemas" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $status "inCinemas"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ else if eq $status "released"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "movie.id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "movie.id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "movie.title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "movie.overview" }}
|
||||||
|
{{ $popoverTitle = .String "movie.title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "movie.overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "movie.titleSlug") }}
|
||||||
|
{{ $movie = .Get "movie" }}
|
||||||
|
{{ $genres = $movie.Get "genres" }}
|
||||||
|
{{ if and $showGrabbed (gt (.Int "movie.movieFileId") 0) }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "titleSlug") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ $genres = .Get "genres" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ if and $showGrabbed (.Bool "movie.hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if and $showGrabbed (.Bool "hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ $artist := "" }}
|
||||||
|
{{ $album := "" }}
|
||||||
|
{{ $albumId := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v1/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ $artist = $album.Get "artist" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase (.String "albumId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase (.String "albumId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ $title = $album.String "title" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $popoverTitle = $album.String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = $artist.String "overview" }}
|
||||||
|
|
||||||
|
{{ else }}
|
||||||
|
{{ $artist = .Get "artist" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ range .Array "releases" }}
|
||||||
|
{{ $albumId = .String "albumId" }}
|
||||||
|
{{ break }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase $albumId $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase $albumId }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "artist.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $size "small" }}
|
||||||
|
{{ $buttonJustify = "right" }}
|
||||||
|
{{ $height = "9rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "9rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "6rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "medium" }}
|
||||||
|
{{ $height = "12rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "8rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "large" }}
|
||||||
|
{{ $height = "15rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "15rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "10rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "huge" }}
|
||||||
|
{{ $height = "18rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "18rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<li style="position: relative;">
|
||||||
|
<div class="flex gap-10 items-start thumbnail-container thumbnail-parent">
|
||||||
|
<div>
|
||||||
|
<div data-popover-type="html" data-popover-position="above" data-popover-show-delay="500" style="width: {{ $width }}; height: {{ $height }}; align-content: center;">
|
||||||
|
<div data-popover-html>
|
||||||
|
<div style="margin: 5px;">
|
||||||
|
<strong class="size-h4 color-primary" title="{{ $popoverTitle }}">{{ $popoverTitle }}</strong>
|
||||||
|
<div class="size-h4 text-truncate text-very-compact color-subdue" title="{{ $popoverSubtitle }}">{{ $popoverSubtitle }}</div>
|
||||||
|
<p class="margin-top-20" style="overflow-y: auto; text-align: justify; max-height: 20rem;">
|
||||||
|
{{ if ne $popoverSummary "" }}
|
||||||
|
{{ $popoverSummary }}
|
||||||
|
{{ else }}
|
||||||
|
TBA
|
||||||
|
{{ end }}
|
||||||
|
</p>
|
||||||
|
{{ if gt (len ($genres.Array "")) 0 }}
|
||||||
|
<ul class="attachments margin-top-20">
|
||||||
|
{{ range $genres.Array "" }}
|
||||||
|
<li>{{ .String "" }}</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img class="thumbnail" src="{{ $coverUrl }}" alt="Cover for {{ .String "title" }}" loading="lazy" style="width: 100%; height: 100%; box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); object-fit: cover; border-radius: 0.5rem;">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="shrink min-width-0" style="height: 9rem; position: relative; padding-top: 5px; padding-right: 5px;">
|
||||||
|
<strong class="size-h4 block text-truncate color-primary" title="{{ $title }}">{{ $title }}</strong>
|
||||||
|
<div class="text-truncate text-very-compact" title="{{ $subtitle }}">{{ $subtitle }}</div>
|
||||||
|
<div class="text-very-compact text-truncate">
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
<div>{{ $seString }} - {{ $datetype }} {{ $date.Format "1/2 03:04PM" }}</div>
|
||||||
|
{{ else }}
|
||||||
|
<span>{{ $datetype }} {{ $date.Format "1/2" }}</span>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ if eq $buttonJustify "right" }}
|
||||||
|
</div>
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="position: absolute; bottom: 1rem; right: 1rem;
|
||||||
|
{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
<div class="{{ if eq $size "small" }}text-truncate{{ if eq $service "radarr" }} margin-top-5{{ end }}{{ else }}text-truncate-2-lines margin-top-5{{ end }}">
|
||||||
|
{{ $summary }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if not $itemDisplayed }}
|
||||||
|
<li>No items found.</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
433
config/monitoring/glance/widgets/arr-template.txt
Normal file
433
config/monitoring/glance/widgets/arr-template.txt
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
{{ $collapseAfter := .Options.IntOr "collapse-after" 5 }}
|
||||||
|
{{ $showGrabbed := .Options.BoolOr "show-grabbed" false }}
|
||||||
|
{{ $sortTime := .Options.StringOr "sort-time" "desc" }}
|
||||||
|
{{ $coverProxy := .Options.StringOr "cover-proxy" "" }}
|
||||||
|
{{ $size := .Options.StringOr "size" "medium" }}
|
||||||
|
{{ $service := .Options.StringOr "service" "" }}
|
||||||
|
{{ $type := .Options.StringOr "type" "" }}
|
||||||
|
{{ $intervalH := .Options.IntOr "interval" 0 | mul 24 }}
|
||||||
|
|
||||||
|
{{ $now := now | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $posInterval := (offsetNow (printf "+%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $negInterval := (offsetNow (printf "-%dh" $intervalH)) | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
|
||||||
|
{{ $apiBaseUrl := .Options.StringOr "api-base-url" "" }}
|
||||||
|
{{ $key := .Options.StringOr "key" "" }}
|
||||||
|
{{ $url := .Options.StringOr "url" $apiBaseUrl }}
|
||||||
|
|
||||||
|
{{ if or (and (ne $service "sonarr") (ne $service "radarr") (ne $service "lidarr"))
|
||||||
|
(and (ne $type "upcoming") (ne $type "recent") (ne $type "missing"))
|
||||||
|
(eq $apiBaseUrl "") (eq $key "") (eq $url "") }}
|
||||||
|
<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">
|
||||||
|
Some options are not set or malformed
|
||||||
|
<table style="border-spacing: 1rem;">
|
||||||
|
<tr><td>service</td><td>{{ $service }}</td><td>must be sonarr, radarr, or lidarr</td></tr>
|
||||||
|
<tr><td>type</td><td>{{ $type }}</td><td>must be upcoming, recent, or missing</td></tr>
|
||||||
|
<tr><td>api-base-url</td><td>{{ $apiBaseUrl }}</td><td>should include http(s):// and port if needed</td></tr>
|
||||||
|
<tr><td>key</td><td>{{ $key }}</td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
{{ else }}
|
||||||
|
{{ $requestUrl := "" }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeSeries=true&includeEpisode=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50&includeSeries=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?includeSeries=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/history/since?includeMovie=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/wanted/missing?page=1&pageSize=50" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v3/calendar?start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/history/since?includeArtist=true&includeAlbum=true&eventType=grabbed&date=%s" $apiBaseUrl $negInterval }}
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/wanted/missing?page=1&pageSize=50&includeArtist=true" $apiBaseUrl }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $requestUrl = printf "%s/api/v1/calendar?includeArtist=true&start=%s&end=%s" $apiBaseUrl $now $posInterval }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ $data := newRequest $requestUrl
|
||||||
|
| withHeader "Accept" "application/json"
|
||||||
|
| withHeader "X-Api-Key" $key
|
||||||
|
| getResponse }}
|
||||||
|
|
||||||
|
<ul class="list list-gap-14 collapsible-container single-line-titles" data-collapse-after="{{ $collapseAfter }}">
|
||||||
|
{{ $array := "" }}
|
||||||
|
{{ $sortByField := "" }}
|
||||||
|
{{ $itemDisplayed := false }}
|
||||||
|
{{ $itemDate := "" }}
|
||||||
|
{{ $isAvailable := false }}
|
||||||
|
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $array = "records" }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "recent" }}
|
||||||
|
{{ $sortByField = "date" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $sortByField = "airDateUtc" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $sortByField = "releaseDate" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ range $data.JSON.Array $array | sortByTime $sortByField "rfc3339" $sortTime }}
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $itemDate = .String "airDateUtc" | parseTime "RFC3339" }}
|
||||||
|
{{ $itemDate = $itemDate.In now.Location | formatTime "2006-01-02T15:04:05" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ else if eq $service "radarr"}}
|
||||||
|
{{ $isAvailable = .Bool "isAvailable" }}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ else if eq $service "lidarr"}}
|
||||||
|
{{ $itemDate = .String "releaseDate" }}
|
||||||
|
{{ $isAvailable = true }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if or (eq $type "upcoming") (eq $type "recent") (and (or (and (gt $itemDate $negInterval) ((lt $itemDate $now ))) (eq $intervalH 0)) $isAvailable) }}
|
||||||
|
{{ $itemDisplayed = true }}
|
||||||
|
{{ $title := "" }}
|
||||||
|
{{ $subtitle := "" }}
|
||||||
|
{{ $coverUrl := "" }}
|
||||||
|
{{ $status := "" }}
|
||||||
|
{{ $coverBase := "" }}
|
||||||
|
{{ $height := "" }}
|
||||||
|
{{ $width := "" }}
|
||||||
|
{{ $popoverTitle := "" }}
|
||||||
|
{{ $popoverSubtitle := "" }}
|
||||||
|
{{ $popoverSummary := "" }}
|
||||||
|
{{ $summary := "" }}
|
||||||
|
{{ $link := "" }}
|
||||||
|
{{ $grabbed := false }}
|
||||||
|
{{ $date := now }}
|
||||||
|
{{ $datetype := "" }}
|
||||||
|
{{ $seString := "" }}
|
||||||
|
{{ $genres := "" }}
|
||||||
|
{{ $buttonJustify := "left" }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
{{ $series := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "seriesId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "seriesId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "series.title" }}
|
||||||
|
{{ $link = printf "%s/series/%s#" $url (.String "series.titleSlug") }}
|
||||||
|
{{ $series = .Get "series" }}
|
||||||
|
{{ $genres = $series.Get "genres" }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $date = .String "date" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "episode.title" }}
|
||||||
|
{{ $summary = .String "episode.overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "episode.seasonNumber") (.Int "episode.episodeNumber") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "episode.title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "episode.overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ else if eq $type "missing" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Aired" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "episode.hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $type "upcoming" }}
|
||||||
|
{{ $date = .String "airDateUtc" | parseLocalTime "RFC3339" }}
|
||||||
|
{{ $date = $date.In now.Location }}
|
||||||
|
{{ $subtitle = .String "title" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $seString = printf "S%02dE%02d" (.Int "seasonNumber") (.Int "episodeNumber") }}
|
||||||
|
{{ $datetype = "Airs" }}
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = $seString }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ if .Bool "hasFile" }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $popoverTitle = .String "series.title" }}
|
||||||
|
{{ $popoverSummary = .String "series.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "radarr" }}
|
||||||
|
{{ $movie := "" }}
|
||||||
|
{{ $status = .String "status" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v3/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $status "announced"}}
|
||||||
|
{{ if ne (.String "inCinemas") "" }}
|
||||||
|
{{ $date = (.String "inCinemas" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "In Cinemas" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $status "inCinemas"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ else if eq $status "released"}}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "movie.id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "movie.id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "movie.title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "movie.overview" }}
|
||||||
|
{{ $popoverTitle = .String "movie.title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "movie.overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "movie.titleSlug") }}
|
||||||
|
{{ $movie = .Get "movie" }}
|
||||||
|
{{ $genres = $movie.Get "genres" }}
|
||||||
|
{{ if and $showGrabbed (gt (.Int "movie.movieFileId") 0) }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg?apikey=%s" $coverBase (.String "id") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/%s/poster-500.jpg" $coverBase (.String "id") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = "" }}
|
||||||
|
{{ $summary = .String "overview" }}
|
||||||
|
{{ $link = printf "%s/movie/%s#" $url (.String "titleSlug") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "overview" }}
|
||||||
|
{{ $genres = .Get "genres" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ if and $showGrabbed (.Bool "movie.hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if and $showGrabbed (.Bool "hasFile") }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ else if eq $service "lidarr" }}
|
||||||
|
{{ $artist := "" }}
|
||||||
|
{{ $album := "" }}
|
||||||
|
{{ $albumId := "" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverBase = printf "%s/api/v1/mediacover" $apiBaseUrl }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverBase = $coverProxy }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $type "recent" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ $artist = $album.Get "artist" }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase (.String "albumId") $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase (.String "albumId") }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $grabbed = true }}
|
||||||
|
{{ $title = $album.String "title" }}
|
||||||
|
{{ $date = (.String "date" | parseTime "RFC3339") }}
|
||||||
|
{{ $datetype = "Downloaded" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $popoverTitle = $album.String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = $artist.String "overview" }}
|
||||||
|
|
||||||
|
{{ else }}
|
||||||
|
{{ $artist = .Get "artist" }}
|
||||||
|
{{ $album = .Get "album" }}
|
||||||
|
{{ if eq $type "missing" }}
|
||||||
|
{{ $datetype = "Released" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $datetype = "Releases" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ range .Array "releases" }}
|
||||||
|
{{ $albumId = .String "albumId" }}
|
||||||
|
{{ break }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if eq $coverProxy "" }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg?apikey=%s" $coverBase $albumId $key }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $coverUrl = printf "%s/album/%s/cover-500.jpg" $coverBase $albumId }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $date = (.String "releaseDate" | parseTime "RFC3339") }}
|
||||||
|
{{ $title = .String "title" }}
|
||||||
|
{{ $subtitle = $artist.String "artistName" }}
|
||||||
|
{{ $summary = $album.String "overview" }}
|
||||||
|
{{ $genres = $artist.Get "genres" }}
|
||||||
|
{{ $link = printf "%s/artist/%s#" $url ($artist.String "foreignArtistId") }}
|
||||||
|
{{ $popoverTitle = .String "title" }}
|
||||||
|
{{ $popoverSubtitle = printf "%s %s" $datetype ($date | formatTime "1/2/2006") }}
|
||||||
|
{{ $popoverSummary = .String "artist.overview" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if eq $size "small" }}
|
||||||
|
{{ $buttonJustify = "right" }}
|
||||||
|
{{ $height = "9rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "9rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "6rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "medium" }}
|
||||||
|
{{ $height = "12rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "8rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "large" }}
|
||||||
|
{{ $height = "15rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "15rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "10rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else if eq $size "huge" }}
|
||||||
|
{{ $height = "18rem" }}
|
||||||
|
{{ if eq $service "lidarr" }}
|
||||||
|
{{ $width = "18rem" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $width = "12rem" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<li style="position: relative;">
|
||||||
|
<div class="flex gap-10 items-start thumbnail-container thumbnail-parent">
|
||||||
|
<div>
|
||||||
|
<div data-popover-type="html" data-popover-position="above" data-popover-show-delay="500" style="width: {{ $width }}; height: {{ $height }}; align-content: center;">
|
||||||
|
<div data-popover-html>
|
||||||
|
<div style="margin: 5px;">
|
||||||
|
<strong class="size-h4 color-primary" title="{{ $popoverTitle }}">{{ $popoverTitle }}</strong>
|
||||||
|
<div class="size-h4 text-truncate text-very-compact color-subdue" title="{{ $popoverSubtitle }}">{{ $popoverSubtitle }}</div>
|
||||||
|
<p class="margin-top-20" style="overflow-y: auto; text-align: justify; max-height: 20rem;">
|
||||||
|
{{ if ne $popoverSummary "" }}
|
||||||
|
{{ $popoverSummary }}
|
||||||
|
{{ else }}
|
||||||
|
TBA
|
||||||
|
{{ end }}
|
||||||
|
</p>
|
||||||
|
{{ if gt (len ($genres.Array "")) 0 }}
|
||||||
|
<ul class="attachments margin-top-20">
|
||||||
|
{{ range $genres.Array "" }}
|
||||||
|
<li>{{ .String "" }}</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img class="thumbnail" src="{{ $coverUrl }}" alt="Cover for {{ .String "title" }}" loading="lazy" style="width: 100%; height: 100%; box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); object-fit: cover; border-radius: 0.5rem;">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="shrink min-width-0" style="height: 9rem; position: relative; padding-top: 5px; padding-right: 5px;">
|
||||||
|
<strong class="size-h4 block text-truncate color-primary" title="{{ $title }}">{{ $title }}</strong>
|
||||||
|
<div class="text-truncate text-very-compact" title="{{ $subtitle }}">{{ $subtitle }}</div>
|
||||||
|
<div class="text-very-compact text-truncate">
|
||||||
|
{{ if eq $service "sonarr" }}
|
||||||
|
<div>{{ $seString }} - {{ $datetype }} {{ $date.Format "1/2 03:04PM" }}</div>
|
||||||
|
{{ else }}
|
||||||
|
<span>{{ $datetype }} {{ $date.Format "1/2" }}</span>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if $showGrabbed }}
|
||||||
|
{{ if eq $buttonJustify "right" }}
|
||||||
|
</div>
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="position: absolute; bottom: 1rem; right: 1rem;
|
||||||
|
{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<a href="{{ $link }}" class="bookmarks-link size-h4 color-primary" target="_blank" rel="noreferrer"
|
||||||
|
style="{{ if $grabbed }} color: var(--color-positive); border: 1px solid var(--color-positive); {{ else }} color: var(--color-negative); border: 1px solid var(--color-negative); {{ end }}
|
||||||
|
font-weight: bold; padding: 2px 5px; border-radius: 3px; display: inline-block; margin-top: 5px; text-decoration: none;">
|
||||||
|
{{ if $grabbed }}Grabbed{{ else }}Missing{{ end }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
<div class="{{ if eq $size "small" }}text-truncate{{ if eq $service "radarr" }} margin-top-5{{ end }}{{ else }}text-truncate-2-lines margin-top-5{{ end }}">
|
||||||
|
{{ $summary }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if not $itemDisplayed }}
|
||||||
|
<li>No items found.</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
27
config/monitoring/glance/widgets/monitor-media.yml
Normal file
27
config/monitoring/glance/widgets/monitor-media.yml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
- type: monitor
|
||||||
|
title: Media
|
||||||
|
sites:
|
||||||
|
- title: Jellyfin
|
||||||
|
url: https://jellyfin.home
|
||||||
|
icon: mdi:television-play
|
||||||
|
- title: Jellyseerr
|
||||||
|
url: https://jellyseerr.home
|
||||||
|
icon: mdi:movie-search
|
||||||
|
- title: Radarr
|
||||||
|
url: https://radarr.home
|
||||||
|
icon: mdi:film
|
||||||
|
- title: Sonarr
|
||||||
|
url: https://sonarr.home
|
||||||
|
icon: mdi:television
|
||||||
|
- title: Lidarr
|
||||||
|
url: https://lidarr.home
|
||||||
|
icon: mdi:music
|
||||||
|
- title: Prowlarr
|
||||||
|
url: https://prowlarr.home
|
||||||
|
icon: mdi:radar
|
||||||
|
- title: qBittorrent
|
||||||
|
url: https://qbit.home
|
||||||
|
icon: mdi:download
|
||||||
|
- title: TorrServe
|
||||||
|
url: https://torrserve.home
|
||||||
|
icon: mdi:server-network
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
providers:
|
||||||
|
- name: homelab
|
||||||
|
folder: Homelab
|
||||||
|
type: file
|
||||||
|
disableDeletion: false
|
||||||
|
editable: true
|
||||||
|
options:
|
||||||
|
path: /etc/grafana/provisioning/dashboards/json
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
datasources:
|
||||||
|
- name: Prometheus
|
||||||
|
type: prometheus
|
||||||
|
access: proxy
|
||||||
|
url: http://prometheus:9090
|
||||||
|
isDefault: false
|
||||||
|
editable: true
|
||||||
|
|
||||||
|
- name: Loki
|
||||||
|
type: loki
|
||||||
|
access: proxy
|
||||||
|
url: http://loki:3100
|
||||||
|
isDefault: true
|
||||||
|
editable: true
|
||||||
49
config/monitoring/loki-config.yaml
Normal file
49
config/monitoring/loki-config.yaml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
auth_enabled: false
|
||||||
|
|
||||||
|
server:
|
||||||
|
http_listen_port: 3100
|
||||||
|
log_level: info
|
||||||
|
|
||||||
|
ingester:
|
||||||
|
wal:
|
||||||
|
dir: /loki/wal
|
||||||
|
lifecycler:
|
||||||
|
ring:
|
||||||
|
kvstore:
|
||||||
|
store: inmemory
|
||||||
|
replication_factor: 1
|
||||||
|
chunk_idle_period: 5m
|
||||||
|
chunk_target_size: 1048576
|
||||||
|
max_transfer_retries: 0
|
||||||
|
|
||||||
|
schema_config:
|
||||||
|
configs:
|
||||||
|
- from: 2020-10-24
|
||||||
|
store: boltdb
|
||||||
|
object_store: filesystem
|
||||||
|
schema: v11
|
||||||
|
index:
|
||||||
|
prefix: index_
|
||||||
|
period: 168h
|
||||||
|
|
||||||
|
storage_config:
|
||||||
|
boltdb:
|
||||||
|
directory: /loki/index
|
||||||
|
filesystem:
|
||||||
|
directory: /loki/chunks
|
||||||
|
|
||||||
|
limits_config:
|
||||||
|
enforce_metric_name: false
|
||||||
|
reject_old_samples: true
|
||||||
|
reject_old_samples_max_age: 168h
|
||||||
|
split_queries_by_interval: 15m
|
||||||
|
|
||||||
|
querier:
|
||||||
|
max_outstanding_per_tenant: 4096
|
||||||
|
|
||||||
|
chunk_store_config:
|
||||||
|
max_look_back_period: 0s
|
||||||
|
|
||||||
|
table_manager:
|
||||||
|
retention_deletes_enabled: true
|
||||||
|
retention_period: 168h
|
||||||
24
config/monitoring/prometheus.yml
Normal file
24
config/monitoring/prometheus.yml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
global:
|
||||||
|
scrape_interval: 15s
|
||||||
|
evaluation_interval: 15s
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: "node"
|
||||||
|
static_configs:
|
||||||
|
- targets: ["192.168.1.70:9100"]
|
||||||
|
|
||||||
|
- job_name: "cadvisor"
|
||||||
|
static_configs:
|
||||||
|
- targets: ["cadvisor:8080"]
|
||||||
|
|
||||||
|
- job_name: "prometheus"
|
||||||
|
static_configs:
|
||||||
|
- targets: ["localhost:9090"]
|
||||||
|
|
||||||
|
- job_name: "caddy"
|
||||||
|
scheme: https
|
||||||
|
metrics_path: /metrics
|
||||||
|
tls_config:
|
||||||
|
insecure_skip_verify: true
|
||||||
|
static_configs:
|
||||||
|
- targets: ["metrics.home:443"]
|
||||||
48
config/monitoring/promtail-config.yaml
Normal file
48
config/monitoring/promtail-config.yaml
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
server:
|
||||||
|
http_listen_port: 9080
|
||||||
|
grpc_listen_port: 0
|
||||||
|
|
||||||
|
positions:
|
||||||
|
filename: /tmp/positions.yaml
|
||||||
|
|
||||||
|
clients:
|
||||||
|
- url: http://loki:3100/loki/api/v1/push
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: varlogs
|
||||||
|
static_configs:
|
||||||
|
- targets: [localhost]
|
||||||
|
labels:
|
||||||
|
job: varlogs
|
||||||
|
host: cyberdeck
|
||||||
|
__path__: /var/log/**/*.log
|
||||||
|
|
||||||
|
- job_name: docker
|
||||||
|
static_configs:
|
||||||
|
- targets: [localhost]
|
||||||
|
labels:
|
||||||
|
job: docker
|
||||||
|
host: cyberdeck
|
||||||
|
__path__: /var/lib/docker/containers/*/*-json.log
|
||||||
|
pipeline_stages:
|
||||||
|
- docker: {}
|
||||||
|
relabel_configs:
|
||||||
|
- source_labels: [__path__]
|
||||||
|
regex: "/var/lib/docker/containers/([^/]+)/.*"
|
||||||
|
target_label: container
|
||||||
|
replacement: "$1"
|
||||||
|
|
||||||
|
- job_name: journald
|
||||||
|
journal:
|
||||||
|
path: /var/log/journal
|
||||||
|
max_age: 12h
|
||||||
|
labels:
|
||||||
|
job: journald
|
||||||
|
host: cyberdeck
|
||||||
|
relabel_configs:
|
||||||
|
- source_labels: [__journal__systemd_unit]
|
||||||
|
target_label: unit
|
||||||
|
- source_labels: [__journal__hostname]
|
||||||
|
target_label: host
|
||||||
|
- source_labels: [__journal__priority_keyword]
|
||||||
|
target_label: level
|
||||||
14
config/storage/copyparty/copyparty.conf
Normal file
14
config/storage/copyparty/copyparty.conf
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[global]
|
||||||
|
i: 0.0.0.0
|
||||||
|
rproxy: -1
|
||||||
|
xff-src: 172.20.0.0/16
|
||||||
|
|
||||||
|
[accounts]
|
||||||
|
dan: 44435777
|
||||||
|
|
||||||
|
[/]
|
||||||
|
/srv/media/share
|
||||||
|
accs:
|
||||||
|
r: * # everyone gets read-access, but
|
||||||
|
rw: dan # the user "ed" gets read-write
|
||||||
|
d: dan
|
||||||
1
config/storage/copyparty/initcfg
Normal file
1
config/storage/copyparty/initcfg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Override image default to avoid duplicate [/] volume (see copyparty.conf for volume definition).
|
||||||
83
stacks/media/arr.yaml
Normal file
83
stacks/media/arr.yaml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# When *arr apps connect to Prowlarr, use HTTP and Docker service names:
|
||||||
|
# Lidarr: http://lidarr:8686 Radarr: http://radarr:7878
|
||||||
|
# Sonarr: http://sonarr:8989 Prowlarr: http://prowlarr:9696
|
||||||
|
services:
|
||||||
|
sonarr:
|
||||||
|
image: lscr.io/linuxserver/sonarr:latest
|
||||||
|
container_name: sonarr
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Europe/Moscow
|
||||||
|
ports:
|
||||||
|
- "8989:8989"
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/config/media/sonarr:/config
|
||||||
|
- /srv/media:/srv/media
|
||||||
|
- /srv/media/downloads:/downloads
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
|
||||||
|
radarr:
|
||||||
|
image: lscr.io/linuxserver/radarr:latest
|
||||||
|
container_name: radarr
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Europe/Moscow
|
||||||
|
ports:
|
||||||
|
- "7878:7878"
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/config/media/radarr:/config
|
||||||
|
- /srv/media:/srv/media
|
||||||
|
- /srv/media/downloads:/downloads
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
|
||||||
|
lidarr:
|
||||||
|
image: lscr.io/linuxserver/lidarr:latest
|
||||||
|
container_name: lidarr
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Europe/Moscow
|
||||||
|
ports:
|
||||||
|
- "8686:8686"
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/config/media/lidarr:/config
|
||||||
|
- /srv/media:/srv/media
|
||||||
|
- /srv/media/downloads:/downloads
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
|
||||||
|
prowlarr:
|
||||||
|
image: lscr.io/linuxserver/prowlarr:latest
|
||||||
|
container_name: prowlarr
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Europe/Moscow
|
||||||
|
ports:
|
||||||
|
- "9696:9696"
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/config/media/prowlarr:/config
|
||||||
|
- /srv/media:/srv/media
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
|
||||||
9
stacks/media/compose.yaml
Normal file
9
stacks/media/compose.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
name: media
|
||||||
|
|
||||||
|
include:
|
||||||
|
- ./arr.yaml
|
||||||
|
- ./qbittorrent.yaml
|
||||||
|
- ./jellyfin.yaml
|
||||||
|
- ./seer.yaml
|
||||||
|
- ./navidrome.yaml
|
||||||
|
- ./immich.yaml
|
||||||
10
stacks/media/immich.env
Normal file
10
stacks/media/immich.env
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
TZ=Europe/Moscow
|
||||||
|
IMMICH_VERSION=v2
|
||||||
|
DB_HOSTNAME=immich-postgres
|
||||||
|
REDIS_HOSTNAME=immich-redis
|
||||||
|
DB_PASSWORD=change_me
|
||||||
|
DB_USERNAME=postgres
|
||||||
|
DB_DATABASE_NAME=immich
|
||||||
|
POSTGRES_PASSWORD=change_me
|
||||||
|
POSTGRES_USER=postgres
|
||||||
|
POSTGRES_DB=immich
|
||||||
67
stacks/media/immich.yaml
Normal file
67
stacks/media/immich.yaml
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
services:
|
||||||
|
immich-server:
|
||||||
|
container_name: immich_server
|
||||||
|
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-v2}
|
||||||
|
volumes:
|
||||||
|
- /srv/media/immich:/data
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
env_file:
|
||||||
|
- ./immich.env
|
||||||
|
ports:
|
||||||
|
- "2283:2283"
|
||||||
|
depends_on:
|
||||||
|
- immich-redis
|
||||||
|
- immich-postgres
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
disable: false
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
|
||||||
|
immich-machine-learning:
|
||||||
|
container_name: immich_machine_learning
|
||||||
|
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-v2}
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/data/media/immich/model-cache:/cache
|
||||||
|
env_file:
|
||||||
|
- ./immich.env
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
disable: false
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
|
||||||
|
immich-redis:
|
||||||
|
container_name: immich_redis
|
||||||
|
image: docker.io/valkey/valkey:9@sha256:546304417feac0874c3dd576e0952c6bb8f06bb4093ea0c9ca303c73cf458f63
|
||||||
|
healthcheck:
|
||||||
|
test: redis-cli ping || exit 1
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
|
||||||
|
immich-postgres:
|
||||||
|
container_name: immich_postgres
|
||||||
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
|
||||||
|
env_file:
|
||||||
|
- ./immich.env
|
||||||
|
shm_size: 128mb
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/data/media/immich/postgres:/var/lib/postgresql/data
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
disable: false
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
21
stacks/media/jellyfin.yaml
Normal file
21
stacks/media/jellyfin.yaml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
services:
|
||||||
|
jellyfin:
|
||||||
|
image: lscr.io/linuxserver/jellyfin:latest
|
||||||
|
container_name: jellyfin
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Europe/Moscow
|
||||||
|
ports:
|
||||||
|
- "8096:8096"
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/config/media/jellyfin:/config
|
||||||
|
- /srv/homelab/data/media/jellyfin/cache:/cache
|
||||||
|
- /srv/media:/srv/media
|
||||||
|
- /srv/media:/media
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
16
stacks/media/navidrome.yaml
Normal file
16
stacks/media/navidrome.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
services:
|
||||||
|
navidrome:
|
||||||
|
image: deluan/navidrome:latest
|
||||||
|
container_name: navidrome
|
||||||
|
user: "1000:1000"
|
||||||
|
ports:
|
||||||
|
- "4533:4533"
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/data/media/navidrome:/data
|
||||||
|
- /srv/media/music:/music:ro
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
24
stacks/media/qbittorrent.yaml
Normal file
24
stacks/media/qbittorrent.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
services:
|
||||||
|
qbittorrent:
|
||||||
|
image: lscr.io/linuxserver/qbittorrent:latest
|
||||||
|
container_name: qbittorrent
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Europe/Moscow
|
||||||
|
- WEBUI_PORT=8081
|
||||||
|
ports:
|
||||||
|
- "8081:8081"
|
||||||
|
- "6881:6881"
|
||||||
|
- "6881:6881/udp"
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/config/media/qbittorrent:/config
|
||||||
|
- /srv/media/downloads:/downloads
|
||||||
|
- /srv/media/movies:/movies
|
||||||
|
- /srv/media/shows:/shows
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
18
stacks/media/seer.yaml
Normal file
18
stacks/media/seer.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
services:
|
||||||
|
seer:
|
||||||
|
image: ghcr.io/seerr-team/seerr:latest
|
||||||
|
container_name: seer
|
||||||
|
environment:
|
||||||
|
- LOG_LEVEL=info
|
||||||
|
- TZ=Europe/Moscow
|
||||||
|
- PORT=5055
|
||||||
|
ports:
|
||||||
|
- "5055:5055"
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/config/media/seer:/app/config
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
6
stacks/monitoring/compose.yaml
Normal file
6
stacks/monitoring/compose.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
name: monitoring
|
||||||
|
|
||||||
|
include:
|
||||||
|
- ./grafana.yaml
|
||||||
|
- ./glance.yaml
|
||||||
|
- ./portainer.yaml
|
||||||
22
stacks/monitoring/glance.env
Normal file
22
stacks/monitoring/glance.env
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Variables for config (re-run docker compose up after changes).
|
||||||
|
|
||||||
|
# Auth (optional)
|
||||||
|
MY_SECRET_TOKEN=123456
|
||||||
|
|
||||||
|
# *arr stack – API base URL and key (http from container)
|
||||||
|
RADARR_URL=http://radarr.home
|
||||||
|
RADARR_API_URL=http://radarr.home
|
||||||
|
RADARR_KEY=512cab3acfe84420957a9c8585560f8f
|
||||||
|
|
||||||
|
SONARR_URL=http://sonarr.home
|
||||||
|
SONARR_API_URL=http://sonarr.home
|
||||||
|
SONARR_KEY=b3a84ef407ca42d99f5bc22fb8afc401
|
||||||
|
|
||||||
|
LIDARR_URL=http://lidarr.home
|
||||||
|
LIDARR_API_URL=http://lidarr.home
|
||||||
|
LIDARR_KEY=e0862cb9aa8c4c0f8115ec794c5bebc1
|
||||||
|
|
||||||
|
# Portainer (Settings → API → Enable API; endpoint ID from URL e.g. !#/2/docker → 2)
|
||||||
|
PORTAINER_URL=http://portainer.home
|
||||||
|
PORTAINER_ENDPOINT_ID=3
|
||||||
|
PORTAINER_API_KEY=ptr_zmLlSaAbw8nQRoJlDRb006IDVtJLojneToSVNWJxo3c=
|
||||||
13
stacks/monitoring/glance.env.example
Normal file
13
stacks/monitoring/glance.env.example
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
MY_SECRET_TOKEN=change_me
|
||||||
|
RADARR_URL=http://radarr.home
|
||||||
|
RADARR_API_URL=http://radarr.home
|
||||||
|
RADARR_KEY=change_me
|
||||||
|
SONARR_URL=http://sonarr.home
|
||||||
|
SONARR_API_URL=http://sonarr.home
|
||||||
|
SONARR_KEY=change_me
|
||||||
|
LIDARR_URL=http://lidarr.home
|
||||||
|
LIDARR_API_URL=http://lidarr.home
|
||||||
|
LIDARR_KEY=change_me
|
||||||
|
PORTAINER_URL=http://portainer.home
|
||||||
|
PORTAINER_ENDPOINT_ID=1
|
||||||
|
PORTAINER_API_KEY=change_me
|
||||||
24
stacks/monitoring/glance.yaml
Normal file
24
stacks/monitoring/glance.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
services:
|
||||||
|
glance:
|
||||||
|
container_name: glance
|
||||||
|
image: glanceapp/glance
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/config/monitoring/glance:/app/config
|
||||||
|
- /srv/homelab/data/monitoring/glance/assets:/app/assets
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
- /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/custom-ca.crt:ro
|
||||||
|
- /srv/media:/srv/media:ro
|
||||||
|
- /backup:/backup:ro
|
||||||
|
ports:
|
||||||
|
- "9090:8080"
|
||||||
|
env_file:
|
||||||
|
- ./glance.env
|
||||||
|
environment:
|
||||||
|
- SSL_CERT_FILE=/etc/ssl/certs/custom-ca.crt
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
98
stacks/monitoring/grafana.yaml
Normal file
98
stacks/monitoring/grafana.yaml
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
# One-time permissions (run on host):
|
||||||
|
# sudo chown -R 65534:65534 /srv/homelab/data/monitoring/prometheus
|
||||||
|
# sudo chown -R 10001:10001 /srv/homelab/data/monitoring/loki
|
||||||
|
# sudo chown -R 472:472 /srv/homelab/data/monitoring/grafana
|
||||||
|
#
|
||||||
|
services:
|
||||||
|
cadvisor:
|
||||||
|
image: gcr.io/cadvisor/cadvisor:latest
|
||||||
|
container_name: cadvisor
|
||||||
|
ports:
|
||||||
|
- "8088:8080"
|
||||||
|
volumes:
|
||||||
|
- /:/rootfs:ro
|
||||||
|
- /var/run:/var/run:ro
|
||||||
|
- /sys:/sys:ro
|
||||||
|
- /var/lib/docker:/var/lib/docker:ro
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
|
||||||
|
prometheus:
|
||||||
|
image: prom/prometheus:latest
|
||||||
|
container_name: prometheus
|
||||||
|
extra_hosts:
|
||||||
|
- "metrics.home:192.168.1.70"
|
||||||
|
ports:
|
||||||
|
- "9094:9090"
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/config/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||||
|
- /srv/homelab/data/monitoring/prometheus:/prometheus
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
|
||||||
|
grafana:
|
||||||
|
image: grafana/grafana:latest
|
||||||
|
container_name: grafana
|
||||||
|
user: "472:65534"
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
environment:
|
||||||
|
- GF_FEATURE_TOGGLES_KUBERNETESDASHBOARDS=false
|
||||||
|
depends_on:
|
||||||
|
- loki
|
||||||
|
- prometheus
|
||||||
|
ports:
|
||||||
|
- "3034:3000"
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/data/monitoring/grafana:/var/lib/grafana
|
||||||
|
- /srv/homelab/config/monitoring/grafana/provisioning:/etc/grafana/provisioning:ro
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
|
||||||
|
loki:
|
||||||
|
image: grafana/loki:2.9.0
|
||||||
|
container_name: loki
|
||||||
|
ports:
|
||||||
|
- "3100:3100"
|
||||||
|
command: -config.file=/etc/loki/config.yaml
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/config/monitoring/loki-config.yaml:/etc/loki/config.yaml:ro
|
||||||
|
- /srv/homelab/data/monitoring/loki:/loki
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
|
||||||
|
promtail:
|
||||||
|
image: grafana/promtail:2.9.0
|
||||||
|
container_name: promtail
|
||||||
|
command: -config.file=/etc/promtail/config.yaml
|
||||||
|
depends_on:
|
||||||
|
- loki
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/config/monitoring/promtail-config.yaml:/etc/promtail/config.yaml:ro
|
||||||
|
- /var/log:/var/log:ro
|
||||||
|
- /etc/machine-id:/etc/machine-id:ro
|
||||||
|
- /var/lib/docker/containers:/var/lib/docker/containers:ro
|
||||||
|
- /run/log/journal:/run/log/journal:ro
|
||||||
|
- /var/log/journal:/var/log/journal:ro
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
18
stacks/monitoring/portainer.yaml
Normal file
18
stacks/monitoring/portainer.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
services:
|
||||||
|
portainer:
|
||||||
|
container_name: portainer
|
||||||
|
image: portainer/portainer-ce:lts
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- /srv/homelab/data/portainer/data:/data
|
||||||
|
ports:
|
||||||
|
- "9443:9443"
|
||||||
|
- "8000:8000"
|
||||||
|
environment:
|
||||||
|
- TRUSTED_ORIGINS=portainer.home
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
5
stacks/storage/compose.yaml
Normal file
5
stacks/storage/compose.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
name: storage
|
||||||
|
|
||||||
|
include:
|
||||||
|
- ./copyparty.yaml
|
||||||
|
- ./gitea.yaml
|
||||||
18
stacks/storage/copyparty.yaml
Normal file
18
stacks/storage/copyparty.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
services:
|
||||||
|
copyparty:
|
||||||
|
image: copyparty/ac:latest
|
||||||
|
container_name: copyparty
|
||||||
|
command: ["-c", "/cfg/copyparty.conf"]
|
||||||
|
ports:
|
||||||
|
- "3923:3923"
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/config/storage/copyparty:/cfg
|
||||||
|
- /srv/homelab/config/storage/copyparty/initcfg:/z/initcfg:ro
|
||||||
|
- /srv/media:/srv/media
|
||||||
|
- /srv/homelab/data/storage/copyparty:/w
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
21
stacks/storage/gitea.yaml
Normal file
21
stacks/storage/gitea.yaml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
networks:
|
||||||
|
gitea:
|
||||||
|
external: false
|
||||||
|
|
||||||
|
services:
|
||||||
|
server:
|
||||||
|
image: docker.gitea.com/gitea:1.25.4
|
||||||
|
container_name: gitea
|
||||||
|
environment:
|
||||||
|
- USER_UID=1000
|
||||||
|
- USER_GID=1000
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- gitea
|
||||||
|
volumes:
|
||||||
|
- /srv/homelab/data/storage/gitea:/data
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
- "222:22"
|
||||||
Reference in New Issue
Block a user