mirror of
https://github.com/gethomepage/homepage.git
synced 2025-12-05 21:47:48 +01:00
Compare commits
3 Commits
b87d64b42f
...
dfd2b8bb9f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfd2b8bb9f | ||
|
|
5b50e8ff81 | ||
|
|
c36c6a9012 |
@@ -14,4 +14,6 @@ widget:
|
||||
type: frigate
|
||||
url: http://frigate.host.or.ip:port
|
||||
enableRecentEvents: true # Optional, defaults to false
|
||||
username: username # optional
|
||||
password: password # optional
|
||||
```
|
||||
|
||||
@@ -12,11 +12,17 @@ Learn more about [Gluetun](https://github.com/qdm12/gluetun).
|
||||
Allowed fields: `["public_ip", "region", "country", "port_forwarded"]`.
|
||||
Default fields: `["public_ip", "region", "country"]`.
|
||||
|
||||
To setup authentication, follow [the official Gluetun documentation](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication). Note that to use the api key method, you must add the route `GET /v1/publicip/ip` to the `routes` array in your Gluetun config.toml. Similarly, if you want to include the `port_forwarded` field, you must add the route `GET /v1/openvpn/portforwarded` to your Gluetun config.toml.
|
||||
To setup authentication, follow [the official Gluetun documentation](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication). Note that to use the api key method, you must add the route `GET /v1/publicip/ip` to the `routes` array in your Gluetun config.toml. Similarly, if you want to include the `port_forwarded` field, you must add the route `GET /v1/openvpn/portforwarded` (or `/v1/portforward`) to your Gluetun config.toml.
|
||||
|
||||
| Gluetun Version | Homepage Widget Version |
|
||||
| --------------- | ----------------------- |
|
||||
| < 3.40.1 | 1 (default) |
|
||||
| >= 3.40.1 | 2 |
|
||||
|
||||
```yaml
|
||||
widget:
|
||||
type: gluetun
|
||||
url: http://gluetun.host.or.ip:port
|
||||
key: gluetunkey # Not required if /v1/publicip/ip endpoint is configured with `auth = none`
|
||||
version: 2 # optional, default is 1
|
||||
```
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Vandag",
|
||||
"gross_percent_1y": "Een jaar",
|
||||
"gross_percent_max": "Alle tyd"
|
||||
"gross_percent_max": "Alle tyd",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podsendinge",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "سنة",
|
||||
"gross_percent_max": "كل الوقت"
|
||||
"gross_percent_max": "كل الوقت",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "بودكاست",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Една година",
|
||||
"gross_percent_max": "All time"
|
||||
"gross_percent_max": "All time",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Подкасти",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Un any",
|
||||
"gross_percent_max": "Sempre"
|
||||
"gross_percent_max": "Sempre",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Pòdcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Jeden rok",
|
||||
"gross_percent_max": "Za celou dobu"
|
||||
"gross_percent_max": "Za celou dobu",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasty",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Et År",
|
||||
"gross_percent_max": "Altid"
|
||||
"gross_percent_max": "Altid",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Heute",
|
||||
"gross_percent_1y": "Ein Jahr",
|
||||
"gross_percent_max": "Gesamt"
|
||||
"gross_percent_max": "Gesamt",
|
||||
"net_worth": ""
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Ένας χρόνος",
|
||||
"gross_percent_max": "Διαχρονικά"
|
||||
"gross_percent_max": "Διαχρονικά",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "One year",
|
||||
"gross_percent_max": "All time"
|
||||
"gross_percent_max": "All time",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Hoy",
|
||||
"gross_percent_1y": "Un año",
|
||||
"gross_percent_max": "Todo el tiempo"
|
||||
"gross_percent_max": "Todo el tiempo",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "One year",
|
||||
"gross_percent_max": "All time"
|
||||
"gross_percent_max": "All time",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "One year",
|
||||
"gross_percent_max": "All time"
|
||||
"gross_percent_max": "All time",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -142,8 +142,8 @@
|
||||
"connectionStatusDisconnected": "Déconnecté",
|
||||
"connectionStatusConnected": "Connecté",
|
||||
"uptime": "Démarré depuis",
|
||||
"maxDown": "Réception max.",
|
||||
"maxUp": "Envoi max.",
|
||||
"maxDown": "Réception max",
|
||||
"maxUp": "Envoi max",
|
||||
"down": "Réception",
|
||||
"up": "Envoi",
|
||||
"received": "Reçu",
|
||||
@@ -229,7 +229,7 @@
|
||||
"seed": "En partage"
|
||||
},
|
||||
"develancacheui": {
|
||||
"cachehitbytes": "Cache Hit (B)",
|
||||
"cachehitbytes": "Octets acquis du cache",
|
||||
"cachemissbytes": "Cache Miss (B)"
|
||||
},
|
||||
"downloadstation": {
|
||||
@@ -294,7 +294,7 @@
|
||||
"queries": "Requêtes",
|
||||
"blocked": "Bloqué",
|
||||
"blocked_percent": "% bloqué",
|
||||
"gravity": "Listes dom. bloqués"
|
||||
"gravity": "Listes dom. Bloqués"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Requêtes",
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Aujourd'hui",
|
||||
"gross_percent_1y": "Un an",
|
||||
"gross_percent_max": "Depuis le début"
|
||||
"gross_percent_max": "Depuis le début",
|
||||
"net_worth": "Patrimoine net"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
@@ -1091,7 +1092,7 @@
|
||||
"NEW_ARRAY": "Nouveau tableau",
|
||||
"RECON_DISK": "Reconstruction du disque",
|
||||
"DISABLE_DISK": "Disque désactivé",
|
||||
"SWAP_DSBL": "Swap Disable",
|
||||
"SWAP_DSBL": "Désactiver le swap",
|
||||
"INVALID_EXPANSION": "Extension invalide",
|
||||
"PARITY_NOT_BIGGEST": "La parité n'est pas la plus grande",
|
||||
"TOO_MANY_MISSING_DISKS": "Trop de disques manquants",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "היום",
|
||||
"gross_percent_1y": "שנה",
|
||||
"gross_percent_max": "כל הזמן"
|
||||
"gross_percent_max": "כל הזמן",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "פודקאסטים",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "One year",
|
||||
"gross_percent_max": "All time"
|
||||
"gross_percent_max": "All time",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Danas",
|
||||
"gross_percent_1y": "Jedna godina",
|
||||
"gross_percent_max": "Svo vrijeme"
|
||||
"gross_percent_max": "Svo vrijeme",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasti",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Egy év",
|
||||
"gross_percent_max": "Mindig"
|
||||
"gross_percent_max": "Mindig",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcast",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Satu Tahun",
|
||||
"gross_percent_max": "Sepanjang Masa"
|
||||
"gross_percent_max": "Sepanjang Masa",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcast",
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
"passes": "Tessere"
|
||||
},
|
||||
"tautulli": {
|
||||
"playing": "Playing",
|
||||
"playing": "In riproduzione",
|
||||
"transcoding": "Transcoding",
|
||||
"bitrate": "Bitrate",
|
||||
"no_active": "No Active Streams",
|
||||
@@ -313,7 +313,7 @@
|
||||
"total": "Total"
|
||||
},
|
||||
"suwayomi": {
|
||||
"download": "Downloaded",
|
||||
"download": "Scaricati",
|
||||
"nondownload": "Non Scaricato",
|
||||
"read": "Read",
|
||||
"unread": "Unread",
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Un anno",
|
||||
"gross_percent_max": "Sempre"
|
||||
"gross_percent_max": "Sempre",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcast",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "1年",
|
||||
"gross_percent_max": "全期間"
|
||||
"gross_percent_max": "全期間",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "ポッドキャスト",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "오늘",
|
||||
"gross_percent_1y": "1년",
|
||||
"gross_percent_max": "전체 기간"
|
||||
"gross_percent_max": "전체 기간",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "팟캐스트",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "One year",
|
||||
"gross_percent_max": "All time"
|
||||
"gross_percent_max": "All time",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Satu tahun",
|
||||
"gross_percent_max": "Sepanjang masa"
|
||||
"gross_percent_max": "Sepanjang masa",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podkas",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Vandaag",
|
||||
"gross_percent_1y": "Een jaar",
|
||||
"gross_percent_max": "Altijd"
|
||||
"gross_percent_max": "Altijd",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Ett år",
|
||||
"gross_percent_max": "Gjennom tidene"
|
||||
"gross_percent_max": "Gjennom tidene",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podkaster",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Dzisiaj",
|
||||
"gross_percent_1y": "Rok",
|
||||
"gross_percent_max": "Od początku"
|
||||
"gross_percent_max": "Od początku",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasty",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Um ano",
|
||||
"gross_percent_max": "Desde Sempre"
|
||||
"gross_percent_max": "Desde Sempre",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Hoje",
|
||||
"gross_percent_1y": "Um ano",
|
||||
"gross_percent_max": "Todo o tempo"
|
||||
"gross_percent_max": "Todo o tempo",
|
||||
"net_worth": "Patrimônio Líquido"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Un an",
|
||||
"gross_percent_max": "Tot timpul"
|
||||
"gross_percent_max": "Tot timpul",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasturi",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Сегодня",
|
||||
"gross_percent_1y": "Один год",
|
||||
"gross_percent_max": "Все время"
|
||||
"gross_percent_max": "Все время",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Подкасты",
|
||||
|
||||
@@ -362,8 +362,8 @@
|
||||
},
|
||||
"trilium": {
|
||||
"version": "Verzia",
|
||||
"notesCount": "Notes",
|
||||
"dbSize": "Database Size",
|
||||
"notesCount": "Poznámky",
|
||||
"dbSize": "Veľkosť databázy",
|
||||
"unknown": "Neznáme"
|
||||
},
|
||||
"navidrome": {
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Dnes",
|
||||
"gross_percent_1y": "Jeden rok",
|
||||
"gross_percent_max": "Za celý čas"
|
||||
"gross_percent_max": "Za celý čas",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasty",
|
||||
@@ -786,7 +787,7 @@
|
||||
"downloadCount": "Poradie",
|
||||
"downloadBytesRemaining": "Zostávajúce",
|
||||
"downloadTotalBytes": "Veľkosť",
|
||||
"downloadSpeed": "Speed"
|
||||
"downloadSpeed": "Rýchlosť"
|
||||
},
|
||||
"kavita": {
|
||||
"seriesCount": "Series",
|
||||
@@ -952,7 +953,7 @@
|
||||
"loading": "Načítava sa",
|
||||
"open": "Open - US Market",
|
||||
"closed": "Closed - US Market",
|
||||
"invalidConfiguration": "Invalid Configuration"
|
||||
"invalidConfiguration": "Neplatná konfigurácia"
|
||||
},
|
||||
"frigate": {
|
||||
"cameras": "Kamery",
|
||||
@@ -1022,10 +1023,10 @@
|
||||
"loading": "Načítava sa"
|
||||
},
|
||||
"gitlab": {
|
||||
"groups": "Groups",
|
||||
"issues": "Issues",
|
||||
"groups": "Skupiny",
|
||||
"issues": "Problémy",
|
||||
"merges": "Merge Requests",
|
||||
"projects": "Projects"
|
||||
"projects": "Projekty"
|
||||
},
|
||||
"apcups": {
|
||||
"status": "Stav",
|
||||
@@ -1035,7 +1036,7 @@
|
||||
},
|
||||
"karakeep": {
|
||||
"bookmarks": "Bookmarks",
|
||||
"favorites": "Favorites",
|
||||
"favorites": "Obľúbené",
|
||||
"archived": "Archived",
|
||||
"highlights": "Highlights",
|
||||
"lists": "Zoznamy",
|
||||
@@ -1065,13 +1066,13 @@
|
||||
"komodo": {
|
||||
"total": "Celkom",
|
||||
"running": "Beží",
|
||||
"stopped": "Stopped",
|
||||
"stopped": "Zastavené",
|
||||
"down": "Down",
|
||||
"unhealthy": "Nezdravý",
|
||||
"unknown": "Neznáme",
|
||||
"servers": "Servers",
|
||||
"servers": "Servery",
|
||||
"stacks": "Stacks",
|
||||
"containers": "Containers"
|
||||
"containers": "Kontajnery"
|
||||
},
|
||||
"filebrowser": {
|
||||
"available": "Dostupné",
|
||||
@@ -1080,8 +1081,8 @@
|
||||
},
|
||||
"wallos": {
|
||||
"activeSubscriptions": "Subscriptions",
|
||||
"thisMonthlyCost": "This Month",
|
||||
"nextMonthlyCost": "Next Month",
|
||||
"thisMonthlyCost": "Tento mesiac",
|
||||
"nextMonthlyCost": "Ďalší mesiac",
|
||||
"previousMonthlyCost": "Prev. Month",
|
||||
"nextRenewingSubscription": "Next Payment"
|
||||
},
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Eno leto",
|
||||
"gross_percent_max": "Celoten čas"
|
||||
"gross_percent_max": "Celoten čas",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasti",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Данас",
|
||||
"gross_percent_1y": "Једна година",
|
||||
"gross_percent_max": "Све време"
|
||||
"gross_percent_max": "Све време",
|
||||
"net_worth": "Нето вредност"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Подкасти",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "One year",
|
||||
"gross_percent_max": "All time"
|
||||
"gross_percent_max": "All time",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "One year",
|
||||
"gross_percent_max": "All time"
|
||||
"gross_percent_max": "All time",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "One year",
|
||||
"gross_percent_max": "All time"
|
||||
"gross_percent_max": "All time",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Bugün",
|
||||
"gross_percent_1y": "Bir yıl",
|
||||
"gross_percent_max": "Tüm zaman"
|
||||
"gross_percent_max": "Tüm zaman",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcast",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "Один рік",
|
||||
"gross_percent_max": "Весь час"
|
||||
"gross_percent_max": "Весь час",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Подкасти",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "One year",
|
||||
"gross_percent_max": "All time"
|
||||
"gross_percent_max": "All time",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "一年",
|
||||
"gross_percent_max": "所有時間"
|
||||
"gross_percent_max": "所有時間",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "播客",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "一年",
|
||||
"gross_percent_max": "所有时间"
|
||||
"gross_percent_max": "所有时间",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "播客",
|
||||
|
||||
@@ -759,7 +759,8 @@
|
||||
"ghostfolio": {
|
||||
"gross_percent_today": "Today",
|
||||
"gross_percent_1y": "一年",
|
||||
"gross_percent_max": "所有時間"
|
||||
"gross_percent_max": "所有時間",
|
||||
"net_worth": "Net Worth"
|
||||
},
|
||||
"audiobookshelf": {
|
||||
"podcasts": "Podcasts",
|
||||
|
||||
@@ -563,6 +563,7 @@ export function cleanServiceGroups(groups) {
|
||||
"speedtest",
|
||||
"wgeasy",
|
||||
"grafana",
|
||||
"gluetun",
|
||||
].includes(type)
|
||||
) {
|
||||
if (version) widget.version = parseInt(version, 10);
|
||||
|
||||
95
src/widgets/frigate/proxy.js
Normal file
95
src/widgets/frigate/proxy.js
Normal file
@@ -0,0 +1,95 @@
|
||||
import getServiceWidget from "utils/config/service-helpers";
|
||||
import createLogger from "utils/logger";
|
||||
import { asJson, formatApiCall, sanitizeErrorURL } from "utils/proxy/api-helpers";
|
||||
import { addCookieToJar } from "utils/proxy/cookie-jar";
|
||||
import { httpProxy } from "utils/proxy/http";
|
||||
import widgets from "widgets/widgets";
|
||||
|
||||
const proxyName = "frigateProxyHandler";
|
||||
const logger = createLogger(proxyName);
|
||||
|
||||
export default async function frigateProxyHandler(req, res, map) {
|
||||
const { group, service, endpoint, index } = req.query;
|
||||
|
||||
if (group && service) {
|
||||
const widget = await getServiceWidget(group, service, index);
|
||||
|
||||
if (!widgets?.[widget.type]?.api) {
|
||||
return res.status(403).json({ error: "Service does not support API calls" });
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
const url = formatApiCall(widgets[widget.type].api, { endpoint, ...widget });
|
||||
|
||||
const params = {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
};
|
||||
|
||||
let [status, , data] = await httpProxy(url, params);
|
||||
|
||||
if (status === 401 && widget.username && widget.password) {
|
||||
const loginUrl = `${widget.url}/api/login`;
|
||||
logger.debug("Attempting login to Frigate at %s", loginUrl);
|
||||
const [loginStatus, , , loginResponseHeaders] = await httpProxy(loginUrl, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ user: widget.username, password: widget.password }),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (loginStatus !== 200) {
|
||||
logger.error("HTTP Error %d calling %s", loginStatus, sanitizeErrorURL(loginUrl));
|
||||
return res.status(status).json({
|
||||
error: {
|
||||
message: `HTTP Error ${status} while trying to login to Frigate`,
|
||||
url: sanitizeErrorURL(url),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
addCookieToJar(url, loginResponseHeaders);
|
||||
// Retry original request with cookie set
|
||||
[status, , data] = await httpProxy(url, params);
|
||||
}
|
||||
|
||||
if (status >= 400) {
|
||||
logger.error("HTTP Error %d calling %s", status, sanitizeErrorURL(url));
|
||||
return res.status(status).json({
|
||||
error: {
|
||||
message: `HTTP Error ${status} from Frigate`,
|
||||
url: sanitizeErrorURL(url),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
data = asJson(data);
|
||||
|
||||
if (endpoint == "stats") {
|
||||
res.status(status).send({
|
||||
num_cameras: data?.cameras !== undefined ? Object.keys(data?.cameras).length : 0,
|
||||
uptime: data?.service?.uptime,
|
||||
version: data?.service.version,
|
||||
});
|
||||
} else if (endpoint == "events") {
|
||||
return res.status(status).send(
|
||||
data.slice(0, 5).map((event) => ({
|
||||
id: event.id,
|
||||
camera: event.camera,
|
||||
label: event.label,
|
||||
start_time: new Date(event.start_time * 1000),
|
||||
thumbnail: event.thumbnail,
|
||||
score: event.data.score,
|
||||
type: event.data.type,
|
||||
})),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("Invalid or missing proxy service type '%s' in group '%s'", service, group);
|
||||
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||
}
|
||||
@@ -1,37 +1,12 @@
|
||||
import { asJson } from "utils/proxy/api-helpers";
|
||||
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||
import frigateProxyHandler from "./proxy";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/api/{endpoint}",
|
||||
proxyHandler: genericProxyHandler,
|
||||
proxyHandler: frigateProxyHandler,
|
||||
|
||||
mappings: {
|
||||
stats: {
|
||||
endpoint: "stats",
|
||||
map: (data) => {
|
||||
const jsonData = asJson(data);
|
||||
return {
|
||||
num_cameras: jsonData?.cameras !== undefined ? Object.keys(jsonData?.cameras).length : 0,
|
||||
uptime: jsonData?.service?.uptime,
|
||||
version: jsonData?.service.version,
|
||||
};
|
||||
},
|
||||
},
|
||||
events: {
|
||||
endpoint: "events",
|
||||
map: (data) =>
|
||||
asJson(data)
|
||||
.slice(0, 5)
|
||||
.map((event) => ({
|
||||
id: event.id,
|
||||
camera: event.camera,
|
||||
label: event.label,
|
||||
start_time: new Date(event.start_time * 1000),
|
||||
thumbnail: event.thumbnail,
|
||||
score: event.data.score,
|
||||
type: event.data.type,
|
||||
})),
|
||||
},
|
||||
stats: { endpoint: "stats" },
|
||||
events: { endpoint: "events" },
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -12,10 +12,8 @@ export default function Component({ service }) {
|
||||
|
||||
const { data: gluetunData, error: gluetunError } = useWidgetAPI(widget, "ip");
|
||||
const includePF = widget.fields.includes("port_forwarded");
|
||||
const { data: portForwardedData, error: portForwardedError } = useWidgetAPI(
|
||||
widget,
|
||||
includePF ? "port_forwarded" : "",
|
||||
);
|
||||
const pfEndpoint = widget.version > 1 ? "port_forwarded_v2" : "port_forwarded";
|
||||
const { data: portForwardedData, error: portForwardedError } = useWidgetAPI(widget, includePF ? pfEndpoint : "");
|
||||
|
||||
if (gluetunError || (includePF && portForwardedError)) {
|
||||
return <Container service={service} error={gluetunError || portForwardedError} />;
|
||||
|
||||
@@ -13,6 +13,10 @@ const widget = {
|
||||
endpoint: "openvpn/portforwarded",
|
||||
validate: ["port"],
|
||||
},
|
||||
port_forwarded_v2: {
|
||||
endpoint: "portforward",
|
||||
validate: ["port"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user