mirror of
https://github.com/gethomepage/homepage.git
synced 2025-12-26 15:42:11 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51ae55e25e |
2
.github/workflows/docker-publish.yml
vendored
2
.github/workflows/docker-publish.yml
vendored
@@ -84,7 +84,7 @@ jobs:
|
||||
latest=auto
|
||||
|
||||
- name: Next.js build cache
|
||||
uses: actions/cache@v5
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .next/cache
|
||||
key: nextjs-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('**/*.js', '**/*.jsx') }}
|
||||
|
||||
4
.github/workflows/docs-publish.yml
vendored
4
.github/workflows/docs-publish.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
with:
|
||||
python-version: 3.x
|
||||
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
|
||||
- uses: actions/cache@v5
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
key: mkdocs-material-${{ env.cache_id }}
|
||||
path: .cache
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
with:
|
||||
python-version: 3.x
|
||||
- run: echo "cache_id=${{github.sha}}" >> $GITHUB_ENV
|
||||
- uses: actions/cache@v5
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
key: mkdocs-material-${{ env.cache_id }}
|
||||
path: .cache
|
||||
|
||||
2
.github/workflows/repo-maintenance.yml
vendored
2
.github/workflows/repo-maintenance.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
name: 'Lock Old Threads'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v6
|
||||
- uses: dessant/lock-threads@v5
|
||||
with:
|
||||
issue-inactive-days: '30'
|
||||
pr-inactive-days: '30'
|
||||
|
||||
@@ -189,8 +189,6 @@ labels: ...
|
||||
- homepage.widgets[1].slug=youreventslughere
|
||||
```
|
||||
|
||||
To pass custom HTTP headers with a widget request when using labels, use the same dot-notation: `homepage.widget.headers.X-Auth-Key=secret` (or `homepage.widgets[0].headers.X-Auth-Key=secret` when multiple widgets are present).
|
||||
|
||||
You can add specify fields for e.g. the [CustomAPI](../widgets/services/customapi.md) widget by using array-style dot notation:
|
||||
|
||||
```yaml
|
||||
|
||||
@@ -94,7 +94,6 @@ metadata:
|
||||
gethomepage.dev/name: Emby
|
||||
gethomepage.dev/widget.type: "emby"
|
||||
gethomepage.dev/widget.url: "https://emby.example.com"
|
||||
gethomepage.dev/widget.headers.X-Auth-Key: "your-secret-here"
|
||||
gethomepage.dev/pod-selector: ""
|
||||
gethomepage.dev/weight: 10 # optional
|
||||
gethomepage.dev/instance: "public" # optional
|
||||
|
||||
@@ -101,25 +101,6 @@ Each service can have multiple widgets attached to it, for example:
|
||||
|
||||
Multiple widgets per service are not yet supported with Kubernetes ingress annotations.
|
||||
|
||||
#### Custom HTTP headers
|
||||
|
||||
Widgets that make HTTP calls support extra request headers via `headers`. This is useful when a reverse proxy expects a secret header.
|
||||
|
||||
```yaml
|
||||
- UptimeRobot:
|
||||
icon: uptimekuma.png
|
||||
href: https://uptimerobot.com/
|
||||
widget:
|
||||
type: uptimerobot
|
||||
url: https://api.uptimerobot.com
|
||||
key: ${UPTIMEROBOT_API_KEY}
|
||||
headers:
|
||||
User-Agent: homepage
|
||||
X-Auth-Key: your-secret-here
|
||||
```
|
||||
|
||||
If you define services via Docker labels or Kubernetes annotations, use the same key with dot-notation (for example `homepage.widget.headers.X-Auth-Key=secret` or `gethomepage.dev/widget.headers.X-Auth-Key: "secret"`).
|
||||
|
||||
#### Field Visibility
|
||||
|
||||
Each widget can optionally provide a list of which fields should be visible via the `fields` widget property. If no fields are specified, then all fields will be displayed. The `fields` property must be a valid YAML array of strings. As an example, here is the entry for Sonarr showing only a couple of fields.
|
||||
|
||||
@@ -12,7 +12,6 @@ hide:
|
||||
- Check config/logs/homepage.log, on docker simply e.g. `docker logs homepage`. This may provide some insight into the reason for an error.
|
||||
- Check the browser error console, this can also sometimes provide useful information.
|
||||
- Consider setting the `ENV` variable `LOG_LEVEL` to `debug`.
|
||||
- If certain widgets are failing when connecting to public APIs, consider [disabling IPv6](#disabling-ipv6).
|
||||
|
||||
## Service Widget Errors
|
||||
|
||||
@@ -67,17 +66,3 @@ All service widgets work essentially the same, that is, homepage makes a proxied
|
||||
## Missing custom icons
|
||||
|
||||
If, after correctly adding and mapping your custom icons via the [Icons](../configs/services.md#icons) instructions, you are still unable to see your icons please try recreating your container.
|
||||
|
||||
## Disabling IPv6 for http requests {#disabling-ipv6}
|
||||
|
||||
If you are having issues with certain widgets that are unable to reach public APIs (e.g. weather), in certain setups you may need to disable IPv6. You can set the environment variable `HOMEPAGE_PROXY_DISABLE_IPV6` to `true` to disable IPv6 for the homepage proxy.
|
||||
|
||||
Alternatively, you can use the `sysctls` option in your docker-compose file to disable IPv6 for the homepage container completely:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
homepage:
|
||||
...
|
||||
sysctls:
|
||||
- net.ipv6.conf.all.disable_ipv6=1
|
||||
```
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"luxon": "^3.6.1",
|
||||
"memory-cache": "^0.2.0",
|
||||
"minecraftstatuspinger": "^1.2.2",
|
||||
"next": "^15.5.9",
|
||||
"next": "^15.5.7",
|
||||
"next-i18next": "^12.1.0",
|
||||
"ping": "^0.4.4",
|
||||
"pretty-bytes": "^7.1.0",
|
||||
|
||||
32
pnpm-lock.yaml
generated
32
pnpm-lock.yaml
generated
@@ -51,11 +51,11 @@ importers:
|
||||
specifier: ^1.2.2
|
||||
version: 1.2.2
|
||||
next:
|
||||
specifier: ^15.5.9
|
||||
version: 15.5.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
specifier: ^15.5.7
|
||||
version: 15.5.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
next-i18next:
|
||||
specifier: ^12.1.0
|
||||
version: 12.1.0(next@15.5.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
version: 12.1.0(next@15.5.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
ping:
|
||||
specifier: ^0.4.4
|
||||
version: 0.4.4
|
||||
@@ -466,8 +466,8 @@ packages:
|
||||
'@napi-rs/wasm-runtime@0.2.8':
|
||||
resolution: {integrity: sha512-OBlgKdX7gin7OIq4fadsjpg+cp2ZphvAIKucHsNfTdJiqdOmOEwQd/bHi0VwNrcw5xpBJyUw6cK/QilCqy1BSg==}
|
||||
|
||||
'@next/env@15.5.9':
|
||||
resolution: {integrity: sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg==}
|
||||
'@next/env@15.5.7':
|
||||
resolution: {integrity: sha512-4h6Y2NyEkIEN7Z8YxkA27pq6zTkS09bUSYC0xjd0NpwFxjnIKeZEeH591o5WECSmjpUhLn3H2QLJcDye3Uzcvg==}
|
||||
|
||||
'@next/eslint-plugin-next@15.2.4':
|
||||
resolution: {integrity: sha512-O8ScvKtnxkp8kL9TpJTTKnMqlkZnS+QxwoQnJwPGBxjBbzd6OVVPEJ5/pMNrktSyXQD/chEfzfFzYLM6JANOOQ==}
|
||||
@@ -1120,8 +1120,8 @@ packages:
|
||||
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
caniuse-lite@1.0.30001760:
|
||||
resolution: {integrity: sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==}
|
||||
caniuse-lite@1.0.30001759:
|
||||
resolution: {integrity: sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==}
|
||||
|
||||
chalk@4.1.2:
|
||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||
@@ -2212,8 +2212,8 @@ packages:
|
||||
next: '>= 10.0.0'
|
||||
react: '>= 16.8.0'
|
||||
|
||||
next@15.5.9:
|
||||
resolution: {integrity: sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==}
|
||||
next@15.5.7:
|
||||
resolution: {integrity: sha512-+t2/0jIJ48kUpGKkdlhgkv+zPTEOoXyr60qXe68eB/pl3CMJaLeIGjzp5D6Oqt25hCBiBTt8wEeeAzfJvUKnPQ==}
|
||||
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@@ -3374,7 +3374,7 @@ snapshots:
|
||||
'@tybys/wasm-util': 0.9.0
|
||||
optional: true
|
||||
|
||||
'@next/env@15.5.9': {}
|
||||
'@next/env@15.5.7': {}
|
||||
|
||||
'@next/eslint-plugin-next@15.2.4':
|
||||
dependencies:
|
||||
@@ -4024,7 +4024,7 @@ snapshots:
|
||||
|
||||
callsites@3.1.0: {}
|
||||
|
||||
caniuse-lite@1.0.30001760: {}
|
||||
caniuse-lite@1.0.30001759: {}
|
||||
|
||||
chalk@4.1.2:
|
||||
dependencies:
|
||||
@@ -5259,7 +5259,7 @@ snapshots:
|
||||
|
||||
net@1.0.2: {}
|
||||
|
||||
next-i18next@12.1.0(next@15.5.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
next-i18next@12.1.0(next@15.5.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.9
|
||||
'@types/hoist-non-react-statics': 3.3.6
|
||||
@@ -5267,18 +5267,18 @@ snapshots:
|
||||
hoist-non-react-statics: 3.3.2
|
||||
i18next: 21.10.0
|
||||
i18next-fs-backend: 1.2.0
|
||||
next: 15.5.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
next: 15.5.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-i18next: 11.18.6(i18next@21.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
transitivePeerDependencies:
|
||||
- react-dom
|
||||
- react-native
|
||||
|
||||
next@15.5.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
next@15.5.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
'@next/env': 15.5.9
|
||||
'@next/env': 15.5.7
|
||||
'@swc/helpers': 0.5.15
|
||||
caniuse-lite: 1.0.30001760
|
||||
caniuse-lite: 1.0.30001759
|
||||
postcss: 8.4.31
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
"wlan_users": "WLAN Потребители",
|
||||
"up": "UP",
|
||||
"down": "DOWN",
|
||||
"wait": "Моля изчакайте",
|
||||
"wait": "Please wait",
|
||||
"empty_data": "Неизвестен статус на подсистема"
|
||||
},
|
||||
"docker": {
|
||||
@@ -83,7 +83,7 @@
|
||||
"partial": "Частично"
|
||||
},
|
||||
"ping": {
|
||||
"error": "Грешка",
|
||||
"error": "Error",
|
||||
"ping": "Пинг",
|
||||
"down": "Down",
|
||||
"up": "Up",
|
||||
@@ -91,11 +91,11 @@
|
||||
},
|
||||
"siteMonitor": {
|
||||
"http_status": "HTTP статус",
|
||||
"error": "Грешка",
|
||||
"error": "Error",
|
||||
"response": "Отговор",
|
||||
"down": "Down",
|
||||
"up": "Up",
|
||||
"not_available": "Не е налично"
|
||||
"not_available": "Not Available"
|
||||
},
|
||||
"emby": {
|
||||
"playing": "Възпроизвежда",
|
||||
@@ -111,7 +111,7 @@
|
||||
"offline": "Offline",
|
||||
"offline_alt": "Offline",
|
||||
"online": "Онлайн",
|
||||
"total": "Общо",
|
||||
"total": "Total",
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
"evcc": {
|
||||
@@ -133,7 +133,7 @@
|
||||
"unread": "Непрочетени"
|
||||
},
|
||||
"fritzbox": {
|
||||
"connectionStatus": "Статус",
|
||||
"connectionStatus": "Status",
|
||||
"connectionStatusUnconfigured": "Неконфигуриран",
|
||||
"connectionStatusConnecting": "Свързване",
|
||||
"connectionStatusAuthenticating": "Удостоверяване",
|
||||
@@ -141,7 +141,7 @@
|
||||
"connectionStatusDisconnecting": "Прекъсване на връзката",
|
||||
"connectionStatusDisconnected": "Не е свързан",
|
||||
"connectionStatusConnected": "Свързан",
|
||||
"uptime": "Време на работа",
|
||||
"uptime": "Uptime",
|
||||
"maxDown": "Макс сваляне",
|
||||
"maxUp": "Макс качване",
|
||||
"down": "Down",
|
||||
@@ -170,8 +170,8 @@
|
||||
"tautulli": {
|
||||
"playing": "Playing",
|
||||
"transcoding": "Transcoding",
|
||||
"bitrate": "Битрейт",
|
||||
"no_active": "Няма активни потоци",
|
||||
"bitrate": "Bitrate",
|
||||
"no_active": "No Active Streams",
|
||||
"plex_connection_error": "Провери връзка с Plex"
|
||||
},
|
||||
"omada": {
|
||||
@@ -189,7 +189,7 @@
|
||||
"plex": {
|
||||
"streams": "Активни Потоци",
|
||||
"albums": "Албуми",
|
||||
"movies": "Филми",
|
||||
"movies": "Movies",
|
||||
"tv": "Сериали"
|
||||
},
|
||||
"sabnzbd": {
|
||||
@@ -362,8 +362,8 @@
|
||||
},
|
||||
"trilium": {
|
||||
"version": "Version",
|
||||
"notesCount": "Бележки",
|
||||
"dbSize": "Размер на базата данни",
|
||||
"notesCount": "Notes",
|
||||
"dbSize": "Database Size",
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
"navidrome": {
|
||||
@@ -373,7 +373,7 @@
|
||||
"npm": {
|
||||
"enabled": "Активирано",
|
||||
"disabled": "Деактивирано",
|
||||
"total": "Общо"
|
||||
"total": "Total"
|
||||
},
|
||||
"coinmarketcap": {
|
||||
"configure": "Настрой за следене една или повече крипто валути",
|
||||
@@ -384,7 +384,7 @@
|
||||
},
|
||||
"gotify": {
|
||||
"apps": "Приложения",
|
||||
"clients": "Клиенти",
|
||||
"clients": "Clients",
|
||||
"messages": "Съобщения"
|
||||
},
|
||||
"prowlarr": {
|
||||
@@ -405,7 +405,7 @@
|
||||
"transferRate": "Rate"
|
||||
},
|
||||
"mastodon": {
|
||||
"user_count": "Потребители",
|
||||
"user_count": "Users",
|
||||
"status_count": "Posts",
|
||||
"domain_count": "Domains"
|
||||
},
|
||||
@@ -416,17 +416,17 @@
|
||||
},
|
||||
"minecraft": {
|
||||
"players": "Играчи",
|
||||
"version": "Версия",
|
||||
"status": "Статус",
|
||||
"up": "Онлайн",
|
||||
"down": "Офлайн"
|
||||
"version": "Version",
|
||||
"status": "Status",
|
||||
"up": "Online",
|
||||
"down": "Offline"
|
||||
},
|
||||
"miniflux": {
|
||||
"read": "Read",
|
||||
"unread": "Unread"
|
||||
},
|
||||
"authentik": {
|
||||
"users": "Потребители",
|
||||
"users": "Users",
|
||||
"loginsLast24H": "Logins (24h)",
|
||||
"failedLoginsLast24H": "Failed Logins (24h)"
|
||||
},
|
||||
|
||||
@@ -45,9 +45,9 @@
|
||||
"free": "Frei",
|
||||
"used": "In Benutzung",
|
||||
"load": "Last",
|
||||
"temp": "Temp",
|
||||
"temp": "TEMP",
|
||||
"max": "Max",
|
||||
"uptime": "Betriebszeit"
|
||||
"uptime": "BETRIEBSZEIT"
|
||||
},
|
||||
"unifi": {
|
||||
"users": "Benutzer",
|
||||
@@ -602,7 +602,7 @@
|
||||
"pangolin": {
|
||||
"orgs": "Orgs",
|
||||
"sites": "Sites",
|
||||
"resources": "Ressourcen",
|
||||
"resources": "Resources",
|
||||
"targets": "Targets",
|
||||
"traffic": "Traffic",
|
||||
"in": "In",
|
||||
|
||||
@@ -601,12 +601,12 @@
|
||||
},
|
||||
"pangolin": {
|
||||
"orgs": "Orgs",
|
||||
"sites": "Sitios",
|
||||
"resources": "Recursos",
|
||||
"targets": "Destinos",
|
||||
"traffic": "Tráfico",
|
||||
"in": "Entrante",
|
||||
"out": "Saliente"
|
||||
"sites": "Sites",
|
||||
"resources": "Resources",
|
||||
"targets": "Targets",
|
||||
"traffic": "Traffic",
|
||||
"in": "In",
|
||||
"out": "Out"
|
||||
},
|
||||
"peanut": {
|
||||
"battery_charge": "Carga de la batería",
|
||||
@@ -769,7 +769,7 @@
|
||||
"gross_percent_today": "Hoy",
|
||||
"gross_percent_1y": "Un año",
|
||||
"gross_percent_max": "Todo el tiempo",
|
||||
"net_worth": "Patrimonio neto"
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -600,13 +600,13 @@
|
||||
"total": "Укупно"
|
||||
},
|
||||
"pangolin": {
|
||||
"orgs": "Организације",
|
||||
"sites": "Сајтови",
|
||||
"resources": "Ресурси",
|
||||
"targets": "Циљеви",
|
||||
"traffic": "Саобраћај",
|
||||
"in": "Улазак",
|
||||
"out": "Излазак"
|
||||
"orgs": "Orgs",
|
||||
"sites": "Sites",
|
||||
"resources": "Resources",
|
||||
"targets": "Targets",
|
||||
"traffic": "Traffic",
|
||||
"in": "In",
|
||||
"out": "Out"
|
||||
},
|
||||
"peanut": {
|
||||
"battery_charge": "Напуњеност батерије",
|
||||
|
||||
@@ -364,7 +364,7 @@
|
||||
"version": "版本",
|
||||
"notesCount": "笔记",
|
||||
"dbSize": "数据库大小",
|
||||
"unknown": "未知"
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
"navidrome": {
|
||||
"nothing_streaming": "",
|
||||
@@ -800,7 +800,7 @@
|
||||
},
|
||||
"kavita": {
|
||||
"seriesCount": "系列",
|
||||
"totalFiles": "文件"
|
||||
"totalFiles": "Files"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -1097,7 +1097,7 @@
|
||||
},
|
||||
"unraid": {
|
||||
"STARTED": "Started",
|
||||
"STOPPED": "已停止",
|
||||
"STOPPED": "Stopped",
|
||||
"NEW_ARRAY": "New Array",
|
||||
"RECON_DISK": "Reconstructing Disk",
|
||||
"DISABLE_DISK": "Disk Disabled",
|
||||
|
||||
@@ -59,7 +59,7 @@ export default async function handler(req, res) {
|
||||
}
|
||||
|
||||
if (type === "network") {
|
||||
let networkData = await si.networkStats("*");
|
||||
let networkData = await si.networkStats();
|
||||
let interfaceDefault;
|
||||
logger.debug("networkData:", JSON.stringify(networkData));
|
||||
if (interfaceName && interfaceName !== "default") {
|
||||
|
||||
@@ -27,9 +27,6 @@ export default async function credentialedProxyHandler(req, res, map) {
|
||||
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
...(widgets[widget.type].headers ?? {}),
|
||||
...(widget.headers ?? {}),
|
||||
...(req.extraHeaders ?? {}),
|
||||
};
|
||||
|
||||
if (widget.type === "stocks") {
|
||||
|
||||
@@ -25,11 +25,7 @@ export default async function genericProxyHandler(req, res, map) {
|
||||
}
|
||||
const url = new URL(urlString);
|
||||
|
||||
const headers = {
|
||||
...(widgets[widget.type].headers ?? {}),
|
||||
...(widget.headers ?? {}),
|
||||
...(req.extraHeaders ?? {}),
|
||||
};
|
||||
const headers = req.extraHeaders ?? widget.headers ?? widgets[widget.type].headers ?? {};
|
||||
|
||||
if (widget.username && widget.password) {
|
||||
headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
|
||||
|
||||
@@ -65,7 +65,7 @@ async function fetchFromPlexAPI(endpoint, widget) {
|
||||
export default async function plexProxyHandler(req, res) {
|
||||
const widget = await getWidget(req);
|
||||
|
||||
const { service, index } = req.query;
|
||||
const { service } = req.query;
|
||||
|
||||
if (!widget) {
|
||||
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||
@@ -85,19 +85,19 @@ export default async function plexProxyHandler(req, res) {
|
||||
streams = apiData.MediaContainer._attributes.size;
|
||||
}
|
||||
|
||||
let libraries = cache.get(`${librariesCacheKey}.${service}.${index}`);
|
||||
let libraries = cache.get(`${librariesCacheKey}.${service}`);
|
||||
if (libraries === null) {
|
||||
logger.debug("Getting libraries from Plex API");
|
||||
[status, apiData] = await fetchFromPlexAPI("/library/sections", widget);
|
||||
if (apiData && apiData.MediaContainer) {
|
||||
libraries = [].concat(apiData.MediaContainer.Directory);
|
||||
cache.put(`${librariesCacheKey}.${service}.${index}`, libraries, 1000 * 60 * 60 * 6);
|
||||
cache.put(`${librariesCacheKey}.${service}`, libraries, 1000 * 60 * 60 * 6);
|
||||
}
|
||||
}
|
||||
|
||||
let albums = cache.get(`${albumsCacheKey}.${service}.${index}`);
|
||||
let movies = cache.get(`${moviesCacheKey}.${service}.${index}`);
|
||||
let tv = cache.get(`${tvCacheKey}.${service}.${index}`);
|
||||
let albums = cache.get(`${albumsCacheKey}.${service}`);
|
||||
let movies = cache.get(`${moviesCacheKey}.${service}`);
|
||||
let tv = cache.get(`${tvCacheKey}.${service}`);
|
||||
if (albums === null || movies === null || tv === null) {
|
||||
albums = 0;
|
||||
movies = 0;
|
||||
@@ -123,9 +123,9 @@ export default async function plexProxyHandler(req, res) {
|
||||
}
|
||||
}),
|
||||
);
|
||||
cache.put(`${albumsCacheKey}.${service}.${index}`, albums, 1000 * 60 * 10);
|
||||
cache.put(`${tvCacheKey}.${service}.${index}`, tv, 1000 * 60 * 10);
|
||||
cache.put(`${moviesCacheKey}.${service}.${index}`, movies, 1000 * 60 * 10);
|
||||
cache.put(`${albumsCacheKey}.${service}`, albums, 1000 * 60 * 10);
|
||||
cache.put(`${tvCacheKey}.${service}`, tv, 1000 * 60 * 10);
|
||||
cache.put(`${moviesCacheKey}.${service}`, movies, 1000 * 60 * 10);
|
||||
}
|
||||
|
||||
const data = {
|
||||
|
||||
@@ -49,12 +49,10 @@ export default function Component({ service }) {
|
||||
|
||||
// single monitor
|
||||
const monitor = uptimerobotData.monitors[0];
|
||||
const logs = Array.isArray(monitor.logs) ? monitor.logs : [];
|
||||
const lastUpLog = logs.find((log) => log.type === 2);
|
||||
const lastDownLog = logs.find((log) => log.type === 1);
|
||||
|
||||
let status;
|
||||
let uptime = 0;
|
||||
let logIndex = 0;
|
||||
const hasLogs = Array.isArray(monitor.logs) && monitor.logs.length > 0;
|
||||
|
||||
switch (monitor.status) {
|
||||
case 0:
|
||||
@@ -65,7 +63,8 @@ export default function Component({ service }) {
|
||||
break;
|
||||
case 2:
|
||||
status = t("uptimerobot.up");
|
||||
uptime = t("common.duration", { value: lastUpLog?.duration ?? 0 });
|
||||
uptime = t("common.duration", { value: hasLogs ? monitor.logs[0].duration : 0 });
|
||||
logIndex = 1;
|
||||
break;
|
||||
case 8:
|
||||
status = t("uptimerobot.seemsdown");
|
||||
@@ -78,14 +77,14 @@ export default function Component({ service }) {
|
||||
break;
|
||||
}
|
||||
|
||||
const lastDown = lastDownLog ? new Date(lastDownLog.datetime * 1000).toLocaleString() : "";
|
||||
const downDuration = t("common.duration", { value: lastDownLog?.duration ?? 0 });
|
||||
const hideDown = !lastDownLog;
|
||||
const lastDown = hasLogs ? new Date(monitor.logs[logIndex].datetime * 1000).toLocaleString() : "";
|
||||
const downDuration = t("common.duration", { value: hasLogs ? monitor.logs[logIndex].duration : 0 });
|
||||
const hideDown = !hasLogs || (logIndex === 1 && monitor.logs[logIndex].type !== 1);
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="uptimerobot.status" value={status} />
|
||||
<Block label="uptimerobot.uptime" value={uptime} />
|
||||
{hasLogs && <Block label="uptimerobot.uptime" value={uptime} />}
|
||||
{!hideDown && <Block label="uptimerobot.lastDown" value={lastDown} />}
|
||||
{!hideDown && <Block label="uptimerobot.downDuration" value={downDuration} />}
|
||||
</Container>
|
||||
|
||||
Reference in New Issue
Block a user