From 7a19bedc25a35cef5e5f5bfdf27f0c07b5e5bb32 Mon Sep 17 00:00:00 2001 From: Jason Fischer Date: Wed, 28 Sep 2022 15:36:08 -0700 Subject: [PATCH 001/401] Fix Prowlarr show API Error --- src/widgets/prowlarr/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/prowlarr/widget.js b/src/widgets/prowlarr/widget.js index 3b7b2787..9eb3396d 100644 --- a/src/widgets/prowlarr/widget.js +++ b/src/widgets/prowlarr/widget.js @@ -1,7 +1,7 @@ import genericProxyHandler from "utils/proxy/handlers/generic"; const widget = { - api: "{url}/api/v1/{endpoint}", + api: "{url}/api/v1/{endpoint}?apikey={key}", proxyHandler: genericProxyHandler, mappings: { From dadd501843f76720905030b8679485f34ecd9a4d Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Thu, 29 Sep 2022 11:40:09 +0300 Subject: [PATCH 002/401] fix case with empty bookmarks and widgets --- src/utils/config/api-response.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils/config/api-response.js b/src/utils/config/api-response.js index 1b4c1b5f..809927d1 100644 --- a/src/utils/config/api-response.js +++ b/src/utils/config/api-response.js @@ -14,6 +14,8 @@ export async function bookmarksResponse() { const fileContents = await fs.readFile(bookmarksYaml, "utf8"); const bookmarks = yaml.load(fileContents); + if (!bookmarks) return []; + // map easy to write YAML objects into easy to consume JS arrays const bookmarksArray = bookmarks.map((group) => ({ name: Object.keys(group)[0], @@ -33,6 +35,8 @@ export async function widgetsResponse() { const fileContents = await fs.readFile(widgetsYaml, "utf8"); const widgets = yaml.load(fileContents); + if (!widgets) return []; + // map easy to write YAML objects into easy to consume JS arrays const widgetsArray = widgets.map((group) => ({ type: Object.keys(group)[0], From 12279e9bda2a602fa7f58043054bddded76a12c8 Mon Sep 17 00:00:00 2001 From: Sascha Jelinek Date: Wed, 28 Sep 2022 18:13:13 +0000 Subject: [PATCH 003/401] Translated using Weblate (German) Currently translated at 100.0% (118 of 118 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/ --- public/locales/de/common.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/locales/de/common.json b/public/locales/de/common.json index 18c91ac2..b40fec4c 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -170,8 +170,8 @@ "transferRate": "Bewerten" }, "authentik": { - "users": "Users", - "loginsLast24H": "Logins (24h)", - "failedLoginsLast24H": "Failed Logins (24h)" + "users": "Benutzer", + "loginsLast24H": "Anmeldungen (24h)", + "failedLoginsLast24H": "fehlerhafte Anmeldungen (24h)" } } From 6b0659af1f098f6d35a0a5dc931cda812ace56f7 Mon Sep 17 00:00:00 2001 From: Nonoss117 Date: Thu, 29 Sep 2022 07:59:49 +0000 Subject: [PATCH 004/401] Translated using Weblate (French) Currently translated at 100.0% (118 of 118 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/ --- public/locales/fr/common.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json index bda5998b..a1ff63c1 100644 --- a/public/locales/fr/common.json +++ b/public/locales/fr/common.json @@ -170,8 +170,8 @@ "transferRate": "Débit" }, "authentik": { - "users": "Users", - "loginsLast24H": "Logins (24h)", - "failedLoginsLast24H": "Failed Logins (24h)" + "users": "Utilisateurs", + "loginsLast24H": "Cnx. (24h)", + "failedLoginsLast24H": "Cnx. échouées (24h)" } } From 512a6cd4b937b5c36609407c7824717e1951b7a7 Mon Sep 17 00:00:00 2001 From: C8opmBM Date: Wed, 28 Sep 2022 21:44:17 +0000 Subject: [PATCH 005/401] Translated using Weblate (Romanian) Currently translated at 100.0% (118 of 118 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ro/ --- public/locales/ro/common.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/locales/ro/common.json b/public/locales/ro/common.json index 8789cd63..ea00d35c 100644 --- a/public/locales/ro/common.json +++ b/public/locales/ro/common.json @@ -170,8 +170,8 @@ "domain_count": "Domenii" }, "authentik": { - "users": "Users", - "loginsLast24H": "Logins (24h)", - "failedLoginsLast24H": "Failed Logins (24h)" + "users": "Utilizatori", + "loginsLast24H": "Autentificări (24h)", + "failedLoginsLast24H": "Conectări eșuate (24h)" } } From 9b7d6b196fad548cbc9e4c9ee99afff6e8a4bd97 Mon Sep 17 00:00:00 2001 From: Jason Fischer Date: Thu, 29 Sep 2022 21:15:25 -0700 Subject: [PATCH 006/401] Allow widget field visibility to be configurable --- src/components/services/widget/block.jsx | 5 +++- src/components/services/widget/container.jsx | 15 ++++++++++-- src/utils/config/service-helpers.js | 2 ++ src/widgets/adguard/component.jsx | 20 ++++++++-------- src/widgets/authentik/component.jsx | 16 ++++++------- src/widgets/bazarr/component.jsx | 14 ++++++------ src/widgets/coinmarketcap/component.jsx | 6 ++--- src/widgets/docker/component.jsx | 20 ++++++++-------- src/widgets/gotify/component.jsx | 19 ++++++++++++---- src/widgets/jackett/component.jsx | 12 +++++----- src/widgets/jellyseerr/component.jsx | 16 ++++++------- src/widgets/lidarr/component.jsx | 16 ++++++------- src/widgets/mastodon/component.jsx | 16 ++++++------- src/widgets/npm/component.jsx | 16 ++++++------- src/widgets/nzbget/component.jsx | 16 ++++++------- src/widgets/ombi/component.jsx | 16 ++++++------- src/widgets/overseerr/component.jsx | 16 ++++++------- src/widgets/pihole/component.jsx | 16 ++++++------- src/widgets/portainer/component.jsx | 16 ++++++------- src/widgets/prowlarr/component.jsx | 24 ++++++++++---------- src/widgets/qbittorrent/component.jsx | 20 ++++++++-------- src/widgets/radarr/component.jsx | 16 ++++++------- src/widgets/readarr/component.jsx | 16 ++++++------- src/widgets/rutorrent/component.jsx | 16 ++++++------- src/widgets/sabnzbd/component.jsx | 16 ++++++------- src/widgets/sonarr/component.jsx | 16 ++++++------- src/widgets/speedtest/component.jsx | 16 ++++++------- src/widgets/strelaysrv/component.jsx | 16 ++++++------- src/widgets/traefik/component.jsx | 16 ++++++------- src/widgets/transmission/component.jsx | 20 ++++++++-------- 30 files changed, 246 insertions(+), 219 deletions(-) diff --git a/src/components/services/widget/block.jsx b/src/components/services/widget/block.jsx index 295330d6..00a50772 100644 --- a/src/components/services/widget/block.jsx +++ b/src/components/services/widget/block.jsx @@ -1,6 +1,9 @@ +import { useTranslation } from "next-i18next"; import classNames from "classnames"; export default function Block({ value, label }) { + const { t } = useTranslation(); + return (
{value === undefined || value === null ? "-" : value}
-
{label}
+
{t(label)}
); } diff --git a/src/components/services/widget/container.jsx b/src/components/services/widget/container.jsx index deb5fdc2..6aa9aad0 100644 --- a/src/components/services/widget/container.jsx +++ b/src/components/services/widget/container.jsx @@ -1,4 +1,4 @@ -export default function Container({ error = false, children }) { +export default function Container({ error = false, children, service }) { if (error) { return (
@@ -7,5 +7,16 @@ export default function Container({ error = false, children }) { ); } - return
{children}
; + let visibleChildren = children; + const fields = service?.widget?.fields; + const type = service?.widget?.type; + if (fields && type) { + visibleChildren = children.filter(child => fields.some(field => `${type}.${field}` === child.props?.label)); + } + + return ( +
+ {visibleChildren} +
+ ); } diff --git a/src/utils/config/service-helpers.js b/src/utils/config/service-helpers.js index f36e0a56..813972b2 100644 --- a/src/utils/config/service-helpers.js +++ b/src/utils/config/service-helpers.js @@ -113,6 +113,7 @@ export function cleanServiceGroups(groups) { // whitelisted set of keys to pass to the frontend const { type, // all widgets + fields, server, // docker widget container, currency, // coinmarketcap widget @@ -121,6 +122,7 @@ export function cleanServiceGroups(groups) { cleanedService.widget = { type, + fields: fields || null, service_name: service.name, service_group: serviceGroup.name, }; diff --git a/src/widgets/adguard/component.jsx b/src/widgets/adguard/component.jsx index dbd67644..0c78113d 100644 --- a/src/widgets/adguard/component.jsx +++ b/src/widgets/adguard/component.jsx @@ -17,11 +17,11 @@ export default function Component({ service }) { if (!adguardData) { return ( - - - - - + + + + + ); } @@ -30,12 +30,12 @@ export default function Component({ service }) { adguardData.num_replaced_safebrowsing + adguardData.num_replaced_safesearch + adguardData.num_replaced_parental; return ( - - - - + + + + diff --git a/src/widgets/authentik/component.jsx b/src/widgets/authentik/component.jsx index 7087c205..31f864d1 100644 --- a/src/widgets/authentik/component.jsx +++ b/src/widgets/authentik/component.jsx @@ -19,10 +19,10 @@ export default function Component({ service }) { if (!usersData || !loginsData || !failedLoginsData) { return ( - - - - + + + + ); } @@ -38,10 +38,10 @@ export default function Component({ service }) { ); return ( - - - - + + + + ); } diff --git a/src/widgets/bazarr/component.jsx b/src/widgets/bazarr/component.jsx index 921529da..24fef1ce 100644 --- a/src/widgets/bazarr/component.jsx +++ b/src/widgets/bazarr/component.jsx @@ -13,22 +13,22 @@ export default function Component({ service }) { const { data: moviesData, error: moviesError } = useWidgetAPI(widget, "movies"); if (episodesError || moviesError) { - return ; + return ; } if (!episodesData || !moviesData) { return ( - - - + + + ); } return ( - - - + + + ); } diff --git a/src/widgets/coinmarketcap/component.jsx b/src/widgets/coinmarketcap/component.jsx index 113eb40e..0b970b31 100644 --- a/src/widgets/coinmarketcap/component.jsx +++ b/src/widgets/coinmarketcap/component.jsx @@ -30,7 +30,7 @@ export default function Component({ service }) { if (!symbols || symbols.length === 0) { return ( - + ); @@ -42,7 +42,7 @@ export default function Component({ service }) { if (!statsData || !dateRange) { return ( - + ); @@ -51,7 +51,7 @@ export default function Component({ service }) { const { data } = statsData; return ( - +
diff --git a/src/widgets/docker/component.jsx b/src/widgets/docker/component.jsx index 015a1f25..10e55fcb 100644 --- a/src/widgets/docker/component.jsx +++ b/src/widgets/docker/component.jsx @@ -31,23 +31,23 @@ export default function Component({ service }) { if (!statsData || !statusData) { return ( - - - - - + + + + + ); } return ( - - - + + + {statsData.stats.networks && ( <> - - + + )} diff --git a/src/widgets/gotify/component.jsx b/src/widgets/gotify/component.jsx index f12b0e11..40f5793b 100644 --- a/src/widgets/gotify/component.jsx +++ b/src/widgets/gotify/component.jsx @@ -17,11 +17,22 @@ export default function Component({ service }) { return ; } + + if (!appsData || !messagesData || !clientsData) { + return ( + + + + + + ); + } + return ( - - - - + + + + ); } diff --git a/src/widgets/jackett/component.jsx b/src/widgets/jackett/component.jsx index 98f9bc46..9629e266 100644 --- a/src/widgets/jackett/component.jsx +++ b/src/widgets/jackett/component.jsx @@ -17,9 +17,9 @@ export default function Component({ service }) { if (!indexersData) { return ( - - - + + + ); } @@ -27,9 +27,9 @@ export default function Component({ service }) { const errored = indexersData.filter((indexer) => indexer.last_error); return ( - - - + + + ); } diff --git a/src/widgets/jellyseerr/component.jsx b/src/widgets/jellyseerr/component.jsx index 9e685f64..217e406e 100644 --- a/src/widgets/jellyseerr/component.jsx +++ b/src/widgets/jellyseerr/component.jsx @@ -17,19 +17,19 @@ export default function Component({ service }) { if (!statsData) { return ( - - - - + + + + ); } return ( - - - - + + + + ); } diff --git a/src/widgets/lidarr/component.jsx b/src/widgets/lidarr/component.jsx index 96df170e..343760e7 100644 --- a/src/widgets/lidarr/component.jsx +++ b/src/widgets/lidarr/component.jsx @@ -19,19 +19,19 @@ export default function Component({ service }) { if (!albumsData || !wantedData || !queueData) { return ( - - - - + + + + ); } return ( - - - - + + + + ); } diff --git a/src/widgets/mastodon/component.jsx b/src/widgets/mastodon/component.jsx index aa1dad01..ec12fca1 100644 --- a/src/widgets/mastodon/component.jsx +++ b/src/widgets/mastodon/component.jsx @@ -17,19 +17,19 @@ export default function Component({ service }) { if (!statsData) { return ( - - - - + + + + ); } return ( - - - - + + + + ); } diff --git a/src/widgets/npm/component.jsx b/src/widgets/npm/component.jsx index 518fc3eb..b35e27c8 100644 --- a/src/widgets/npm/component.jsx +++ b/src/widgets/npm/component.jsx @@ -17,10 +17,10 @@ export default function Component({ service }) { if (!infoData) { return ( - - - - + + + + ); } @@ -30,10 +30,10 @@ export default function Component({ service }) { const total = infoData.length; return ( - - - - + + + + ); } diff --git a/src/widgets/nzbget/component.jsx b/src/widgets/nzbget/component.jsx index f69f4cf0..f9ace707 100644 --- a/src/widgets/nzbget/component.jsx +++ b/src/widgets/nzbget/component.jsx @@ -17,23 +17,23 @@ export default function Component({ service }) { if (!statusData) { return ( - - - - + + + + ); } return ( - - + + diff --git a/src/widgets/ombi/component.jsx b/src/widgets/ombi/component.jsx index e7402721..60128c37 100644 --- a/src/widgets/ombi/component.jsx +++ b/src/widgets/ombi/component.jsx @@ -17,19 +17,19 @@ export default function Component({ service }) { if (!statsData) { return ( - - - - + + + + ); } return ( - - - - + + + + ); } diff --git a/src/widgets/overseerr/component.jsx b/src/widgets/overseerr/component.jsx index ad46a27e..47131f6e 100644 --- a/src/widgets/overseerr/component.jsx +++ b/src/widgets/overseerr/component.jsx @@ -17,19 +17,19 @@ export default function Component({ service }) { if (!statsData) { return ( - - - - + + + + ); } return ( - - - - + + + + ); } diff --git a/src/widgets/pihole/component.jsx b/src/widgets/pihole/component.jsx index a956594e..17a18627 100644 --- a/src/widgets/pihole/component.jsx +++ b/src/widgets/pihole/component.jsx @@ -17,19 +17,19 @@ export default function Component({ service }) { if (!piholeData) { return ( - - - - + + + + ); } return ( - - - - + + + + ); } diff --git a/src/widgets/portainer/component.jsx b/src/widgets/portainer/component.jsx index 140078bc..bd44d77e 100644 --- a/src/widgets/portainer/component.jsx +++ b/src/widgets/portainer/component.jsx @@ -19,10 +19,10 @@ export default function Component({ service }) { if (!containersData) { return ( - - - - + + + + ); } @@ -36,10 +36,10 @@ export default function Component({ service }) { const total = containersData.length; return ( - - - - + + + + ); } diff --git a/src/widgets/prowlarr/component.jsx b/src/widgets/prowlarr/component.jsx index 85c50186..bb082519 100644 --- a/src/widgets/prowlarr/component.jsx +++ b/src/widgets/prowlarr/component.jsx @@ -18,12 +18,12 @@ export default function Component({ service }) { if (!indexersData || !grabsData) { return ( - - - - - - + + + + + + ); } @@ -42,12 +42,12 @@ export default function Component({ service }) { }); return ( - - - - - - + + + + + + ); } diff --git a/src/widgets/qbittorrent/component.jsx b/src/widgets/qbittorrent/component.jsx index 28458312..4d3a3585 100644 --- a/src/widgets/qbittorrent/component.jsx +++ b/src/widgets/qbittorrent/component.jsx @@ -17,11 +17,11 @@ export default function Component({ service }) { if (!torrentData) { return ( - - - - - + + + + + ); } @@ -42,11 +42,11 @@ export default function Component({ service }) { const leech = torrentData.length - completed; return ( - - - - - + + + + + ); } diff --git a/src/widgets/radarr/component.jsx b/src/widgets/radarr/component.jsx index d6df7cf0..4b16f75f 100644 --- a/src/widgets/radarr/component.jsx +++ b/src/widgets/radarr/component.jsx @@ -18,19 +18,19 @@ export default function Component({ service }) { if (!moviesData || !queuedData) { return ( - - - - + + + + ); } return ( - - - - + + + + ); } diff --git a/src/widgets/readarr/component.jsx b/src/widgets/readarr/component.jsx index 794a6ab8..1e55d7cd 100644 --- a/src/widgets/readarr/component.jsx +++ b/src/widgets/readarr/component.jsx @@ -19,19 +19,19 @@ export default function Component({ service }) { if (!booksData || !wantedData || !queueData) { return ( - - - - + + + + ); } return ( - - - - + + + + ); } diff --git a/src/widgets/rutorrent/component.jsx b/src/widgets/rutorrent/component.jsx index cc0d03f5..279bdf0e 100644 --- a/src/widgets/rutorrent/component.jsx +++ b/src/widgets/rutorrent/component.jsx @@ -17,10 +17,10 @@ export default function Component({ service }) { if (!statusData) { return ( - - - - + + + + ); } @@ -32,10 +32,10 @@ export default function Component({ service }) { const active = statusData.filter((torrent) => torrent["d.get_state"] === "1"); return ( - - - - + + + + ); } diff --git a/src/widgets/sabnzbd/component.jsx b/src/widgets/sabnzbd/component.jsx index b38cb90f..c4e64c9a 100644 --- a/src/widgets/sabnzbd/component.jsx +++ b/src/widgets/sabnzbd/component.jsx @@ -27,19 +27,19 @@ export default function Component({ service }) { if (!queueData) { return ( - - - - + + + + ); } return ( - - - - + + + + ); } diff --git a/src/widgets/sonarr/component.jsx b/src/widgets/sonarr/component.jsx index 71aeb69c..8618b512 100644 --- a/src/widgets/sonarr/component.jsx +++ b/src/widgets/sonarr/component.jsx @@ -19,19 +19,19 @@ export default function Component({ service }) { if (!wantedData || !queuedData || !seriesData) { return ( - - - - + + + + ); } return ( - - - - + + + + ); } diff --git a/src/widgets/speedtest/component.jsx b/src/widgets/speedtest/component.jsx index edf8c66e..778d31c5 100644 --- a/src/widgets/speedtest/component.jsx +++ b/src/widgets/speedtest/component.jsx @@ -17,26 +17,26 @@ export default function Component({ service }) { if (!speedtestData) { return ( - - - - + + + + ); } return ( - + - - - + + + + ); } return ( - + - + diff --git a/src/widgets/traefik/component.jsx b/src/widgets/traefik/component.jsx index efa0e8fa..d24edb9e 100644 --- a/src/widgets/traefik/component.jsx +++ b/src/widgets/traefik/component.jsx @@ -17,19 +17,19 @@ export default function Component({ service }) { if (!traefikData) { return ( - - - - + + + + ); } return ( - - - - + + + + ); } diff --git a/src/widgets/transmission/component.jsx b/src/widgets/transmission/component.jsx index 5e471666..3c2f38ef 100644 --- a/src/widgets/transmission/component.jsx +++ b/src/widgets/transmission/component.jsx @@ -17,11 +17,11 @@ export default function Component({ service }) { if (!torrentData) { return ( - - - - - + + + + + ); } @@ -34,11 +34,11 @@ export default function Component({ service }) { const leech = torrents.length - completed || 0; return ( - - - - - + + + + + ); } From d4ad11a63fc955014df175e1361165c2bc4a41ce Mon Sep 17 00:00:00 2001 From: Jason Fischer Date: Thu, 29 Sep 2022 21:20:01 -0700 Subject: [PATCH 007/401] Slightly simplify container.jsx --- src/components/services/widget/container.jsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/components/services/widget/container.jsx b/src/components/services/widget/container.jsx index 6aa9aad0..ef2ddcfd 100644 --- a/src/components/services/widget/container.jsx +++ b/src/components/services/widget/container.jsx @@ -14,9 +14,5 @@ export default function Container({ error = false, children, service }) { visibleChildren = children.filter(child => fields.some(field => `${type}.${field}` === child.props?.label)); } - return ( -
- {visibleChildren} -
- ); + return
{visibleChildren}
; } From 000e15640ac533a26ef74989b9f111fe3a76afd4 Mon Sep 17 00:00:00 2001 From: FunsKiTo Date: Fri, 30 Sep 2022 00:19:17 +0000 Subject: [PATCH 008/401] Translated using Weblate (Spanish) Currently translated at 100.0% (118 of 118 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/ --- public/locales/es/common.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 1c4b36c3..755d7d03 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -38,17 +38,17 @@ "download": "Bajada" }, "sonarr": { - "wanted": "Más deseado", + "wanted": "Buscando", "queued": "En cola", "series": "Series" }, "radarr": { - "wanted": "Más deseado", + "wanted": "Buscando", "queued": "En cola", "movies": "Películas" }, "readarr": { - "wanted": "Más deseado", + "wanted": "Buscando", "queued": "En cola", "books": "Libros" }, @@ -143,7 +143,7 @@ }, "lidarr": { "queued": "En cola", - "wanted": "Más deseado", + "wanted": "Buscando", "albums": "Álbumes" }, "adguard": { @@ -170,8 +170,8 @@ "transferRate": "Velocidad" }, "authentik": { - "users": "Users", - "loginsLast24H": "Logins (24h)", - "failedLoginsLast24H": "Failed Logins (24h)" + "users": "Usuarios", + "loginsLast24H": "Accesos (24h)", + "failedLoginsLast24H": "Accesos Fallidos (24h)" } } From 45f39120da551cae3f022f10e29ec8d3c8fd35e6 Mon Sep 17 00:00:00 2001 From: lok Date: Thu, 29 Sep 2022 10:32:27 +0000 Subject: [PATCH 009/401] Translated using Weblate (Yue) Currently translated at 100.0% (118 of 118 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/yue/ --- public/locales/yue/common.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/locales/yue/common.json b/public/locales/yue/common.json index fb927d1f..516741f9 100644 --- a/public/locales/yue/common.json +++ b/public/locales/yue/common.json @@ -170,8 +170,8 @@ "domain_count": "域" }, "authentik": { - "users": "Users", - "loginsLast24H": "Logins (24h)", - "failedLoginsLast24H": "Failed Logins (24h)" + "users": "用戶", + "loginsLast24H": "登錄( 24小时)", + "failedLoginsLast24H": "登錄失敗( 24鐘頭)" } } From 2271cc00440d4446fb018762cecd47b69e8fffd2 Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Fri, 30 Sep 2022 21:56:22 +0300 Subject: [PATCH 010/401] cache github response for 5 min --- src/components/version.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/version.jsx b/src/components/version.jsx index 72449a7a..52211219 100644 --- a/src/components/version.jsx +++ b/src/components/version.jsx @@ -3,6 +3,8 @@ import useSWR from "swr"; import { compareVersions } from "compare-versions"; import { MdNewReleases } from "react-icons/md"; +import cachedFetch from "utils/proxy/cached-fetch"; + export default function Version() { const { t, i18n } = useTranslation(); @@ -10,7 +12,9 @@ export default function Version() { const revision = process.env.NEXT_PUBLIC_REVISION ?? "dev"; const version = process.env.NEXT_PUBLIC_VERSION ?? "dev"; - const { data: releaseData } = useSWR("https://api.github.com/repos/benphelps/homepage/releases"); + const cachedFetcher = (resource) => cachedFetch(resource, 5).then((res) => res.json()); + + const { data: releaseData } = useSWR("https://api.github.com/repos/benphelps/homepage/releases", cachedFetcher); // use Intl.DateTimeFormat to format the date const formatDate = (date) => { From f52c6f3b412ff4e676ddd26ab9f6453406a7af79 Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Fri, 30 Sep 2022 22:13:37 +0300 Subject: [PATCH 011/401] improved static styles and x-browser scrollbars --- src/pages/_document.jsx | 6 +---- src/pages/index.jsx | 49 +++++++++++++++++++++++++----------- src/styles/globals.css | 29 ++++++++++++++++----- src/utils/contexts/color.jsx | 2 +- src/utils/contexts/theme.jsx | 2 +- 5 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/pages/_document.jsx b/src/pages/_document.jsx index 9d227492..97780e21 100644 --- a/src/pages/_document.jsx +++ b/src/pages/_document.jsx @@ -9,11 +9,7 @@ export default function Document() { content="A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations." /> - +
diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 672e5641..687075b5 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -2,6 +2,7 @@ import useSWR, { SWRConfig } from "swr"; import Head from "next/head"; import dynamic from "next/dynamic"; +import classNames from "classnames"; import { useTranslation } from "next-i18next"; import { useEffect, useContext, useState } from "react"; import { BiError } from "react-icons/bi"; @@ -12,12 +13,12 @@ import BookmarksGroup from "components/bookmarks/group"; import Widget from "components/widgets/widget"; import Revalidate from "components/toggles/revalidate"; import createLogger from "utils/logger"; +import useWindowFocus from "utils/hooks/window-focus"; import { getSettings } from "utils/config/config"; import { ColorContext } from "utils/contexts/color"; import { ThemeContext } from "utils/contexts/theme"; import { SettingsContext } from "utils/contexts/settings"; import { bookmarksResponse, servicesResponse, widgetsResponse } from "utils/config/api-response"; -import useWindowFocus from "utils/hooks/window-focus"; const ThemeToggle = dynamic(() => import("components/toggles/theme"), { ssr: false, @@ -74,7 +75,7 @@ export async function getStaticProps() { } } -export default function Index({ initialSettings, fallback }) { +function Index({ initialSettings, fallback }) { const windowFocused = useWindowFocus(); const [stale, setStale] = useState(false); const { data: errorsData } = useSWR("/api/validate"); @@ -119,7 +120,7 @@ export default function Index({ initialSettings, fallback }) { if (errorsData && errorsData.length > 0) { return ( -
+
{errorsData.map((error, i) => (
{ @@ -186,12 +187,12 @@ function Home({ initialSettings }) { return ( <> - {settings.title || "Homepage"} - {settings.base && } - {settings.favicon && } + {initialSettings.title || "Homepage"} + {initialSettings.base && } + {initialSettings.favicon && } -
-
+
+
{widgets && ( <> @@ -215,7 +216,7 @@ function Home({ initialSettings }) { {services && (
{services.map((group) => ( - + ))}
)} @@ -229,9 +230,9 @@ function Home({ initialSettings }) { )}
- {!settings?.color && } + {!initialSettings?.color && } - {!settings?.theme && } + {!initialSettings?.theme && }
@@ -241,3 +242,23 @@ function Home({ initialSettings }) { ); } + +export default function Wrapper({ initialSettings, fallback }) { + return ( +
+
+ +
+
+ ); +} diff --git a/src/styles/globals.css b/src/styles/globals.css index ce1ee181..34c97333 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -9,33 +9,50 @@ padding: 0; } +html, body { font-family: Manrope, "Manrope-Fallback", Arial, sans-serif; + overflow: hidden; +} + +#page_wrapper { + width: 100vw; + height: 100vh; + margin: 0; + padding: 0; overflow: overlay; } -.light body::-webkit-scrollbar { +.light #page_container { + scrollbar-color: rgb(var(--color-300)) rgb(var(--color-200)); +} + +.dark #page_container { + scrollbar-color: rgb(var(--color-600)) rgb(var(--color-700)); +} + +.light ::-webkit-scrollbar { width: 0.75em; } -.light body::-webkit-scrollbar-track { +.light ::-webkit-scrollbar-track { background-color: rgb(var(--color-200)); } -.light body::-webkit-scrollbar-thumb { +.light ::-webkit-scrollbar-thumb { background-color: rgb(var(--color-300)); border-radius: 0.25em; } -.dark body::-webkit-scrollbar { +.dark ::-webkit-scrollbar { width: 0.75em; } -.dark body::-webkit-scrollbar-track { +.dark ::-webkit-scrollbar-track { background-color: rgb(var(--color-700)); } -.dark body::-webkit-scrollbar-thumb { +.dark ::-webkit-scrollbar-thumb { background-color: rgb(var(--color-600)); border-radius: 0.25em; } diff --git a/src/utils/contexts/color.jsx b/src/utils/contexts/color.jsx index 83aa692d..d7d985f0 100644 --- a/src/utils/contexts/color.jsx +++ b/src/utils/contexts/color.jsx @@ -20,7 +20,7 @@ export function ColorProvider({ initialTheme, children }) { const [color, setColor] = useState(getInitialColor); const rawSetColor = (rawColor) => { - const root = window.document.documentElement; + const root = window.document.getElementById("page_wrapper"); root.classList.remove(`theme-${lastColor}`); root.classList.add(`theme-${rawColor}`); diff --git a/src/utils/contexts/theme.jsx b/src/utils/contexts/theme.jsx index 89b5a57b..85d613fc 100644 --- a/src/utils/contexts/theme.jsx +++ b/src/utils/contexts/theme.jsx @@ -22,7 +22,7 @@ export function ThemeProvider({ initialTheme, children }) { const [theme, setTheme] = useState(getInitialTheme); const rawSetTheme = (rawTheme) => { - const root = window.document.documentElement; + const root = window.document.getElementById("page_wrapper"); const isDark = rawTheme === "dark"; root.classList.remove(isDark ? "light" : "dark"); From de4ce73a9af25427dd72b0c9a0b10f8cfca4b272 Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Fri, 30 Sep 2022 23:34:48 +0300 Subject: [PATCH 012/401] fix hidden scrollbars this was an adventure --- src/pages/index.jsx | 27 ++++++++++++++++-------- src/styles/globals.css | 48 +++++++++++++++++++----------------------- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 687075b5..2a1c6e7d 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -163,13 +163,6 @@ function Home({ initialSettings }) { const { data: bookmarks } = useSWR("/api/bookmarks"); const { data: widgets } = useSWR("/api/widgets"); - const wrappedStyle = {}; - if (initialSettings && initialSettings.background) { - wrappedStyle.backgroundImage = `url(${initialSettings.background})`; - wrappedStyle.backgroundSize = "cover"; - wrappedStyle.opacity = initialSettings.backgroundOpacity ?? 1; - } - useEffect(() => { if (settings.language) { i18n.changeLanguage(settings.language); @@ -191,7 +184,6 @@ function Home({ initialSettings }) { {initialSettings.base && } {initialSettings.favicon && } -
{widgets && ( @@ -244,11 +236,27 @@ function Home({ initialSettings }) { } export default function Wrapper({ initialSettings, fallback }) { + const wrappedStyle = {}; + if (initialSettings && initialSettings.background) { + // wrappedStyle.backgroundImage = `url(${initialSettings.background})`; + // wrappedStyle.backgroundSize = "cover"; + const opacity = initialSettings.backgroundOpacity ?? 1; + const opacityValue = 1 - opacity; + wrappedStyle.backgroundImage = ` + linear-gradient( + rgb(var(--bg-color) / ${opacityValue}), + rgb(var(--bg-color) / ${opacityValue}) + ), + url(${initialSettings.background})`; + wrappedStyle.backgroundPosition = "center"; + wrappedStyle.backgroundSize = "cover"; + } + return (
diff --git a/src/styles/globals.css b/src/styles/globals.css index 34c97333..cc1c56e9 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -20,39 +20,35 @@ body { height: 100vh; margin: 0; padding: 0; +} + +.light { + --bg-color: var(--color-50); + --scrollbar-thumb: rgb(var(--color-300)); + --scrollbar-track: rgb(var(--color-200)); +} + +.dark { + --bg-color: var(--color-800); + --scrollbar-thumb: rgb(var(--color-600)); + --scrollbar-track: rgb(var(--color-700)); +} + +#page_container { + overflow: auto; overflow: overlay; + scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); } -.light #page_container { - scrollbar-color: rgb(var(--color-300)) rgb(var(--color-200)); -} - -.dark #page_container { - scrollbar-color: rgb(var(--color-600)) rgb(var(--color-700)); -} - -.light ::-webkit-scrollbar { +::-webkit-scrollbar { width: 0.75em; } -.light ::-webkit-scrollbar-track { - background-color: rgb(var(--color-200)); +::-webkit-scrollbar-track { + background-color: var(--scrollbar-track); } -.light ::-webkit-scrollbar-thumb { - background-color: rgb(var(--color-300)); - border-radius: 0.25em; -} - -.dark ::-webkit-scrollbar { - width: 0.75em; -} - -.dark ::-webkit-scrollbar-track { - background-color: rgb(var(--color-700)); -} - -.dark ::-webkit-scrollbar-thumb { - background-color: rgb(var(--color-600)); +::-webkit-scrollbar-thumb { + background-color: var(--scrollbar-thumb); border-radius: 0.25em; } From 6e2197a2546b1781f0078d17ceb0f6ac4a24022f Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Sat, 1 Oct 2022 10:30:54 +0300 Subject: [PATCH 013/401] update readme --- README.md | 71 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 7d75f27c..d143964e 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,19 @@

-
-

+

+ +

+ A modern (fully static, fast), secure (fully proxied), highly customizable application dashboard with integrations for more than 25 services and s for 15 languages. Easily configured via YAML files (or discovery via docker labels). +

+ +

-
+

+ +

@@ -20,17 +27,18 @@

-Docker -Weblate + Docker + Weblate

## Features -- Fast! The entire site is statically generated at build time, so you can expect instant load times +- **Fast!** The entire site is statically generated at build time, so you can expect instant load times +- **Secure!** Every API request to backend services goes through a proxy server, so your API keys are never exposed to the frontend client. - Images built for AMD64 (x86_64), ARM64, ARMv7 and ARMv6 - Supports all Raspberry Pi's, most SBCs & Apple Silicon - Full i18n support with automatic language detection - - Translations for Chinese, Dutch, French, German, Hebrew, Hungarian, Norwegian Bokmål, Polish, Portuguese, Russian, Spanish and Swedish + - s for Chinese, Dutch, French, German, Hebrew, Hungarian, Norwegian Bokmål, Polish, Portuguese, Portuguese (Brazil), Romainian, Russian, Spanish, Swedish and Yue - Want to help translate? [Join the Weblate project](https://hosted.weblate.org/engage/homepage/) - Service & Web Bookmarks - Docker Integration @@ -39,17 +47,17 @@ - Service Integration - Sonarr, Radarr, Readarr, Prowlarr, Bazarr, Lidarr, Emby, Jellyfin, Tautulli (Plex) - Ombi, Overseerr, Jellyseerr, Jackett, NZBGet, SABnzbd, ruTorrent, Transmission, qBittorrent - - Portainer, Traefik, Speedtest Tracker, PiHole, AdGuard Home, Nginx Proxy Manager, Gotify, Syncthing Relay Server + - Portainer, Traefik, Speedtest Tracker, PiHole, AdGuard Home, Nginx Proxy Manager, Gotify, Syncthing Relay Server, Authentic - Information Providers - Coin Market Cap, Mastodon - Information & Utility Widgets - System Stats (Disk, CPU, Memory) - Weather via WeatherAPI.com or OpenWeatherMap - - Automatic location detection (with HTTPS), or manual location selection - Search Bar - Customizable - 21 theme colors with light and dark mode support - Background image support + - Column and Row layout options ## Support & Suggestions @@ -140,26 +148,41 @@ Huge thanks to the all the contributors who have helped make this project what i - [aidenpwnz](https://github.com/benphelps/homepage/commits?author=aidenpwnz) - Nginx Proxy Manager, Search Bar Widget - [AlexFullmoon](https://github.com/benphelps/homepage/commits?author=AlexFullmoon) - OpenWeatherMap Widget -- [AmadeusGraves](https://github.com/benphelps/homepage/commits?author=AmadeusGraves) - Spanish Translation - [andrii-kryvoviaz](https://github.com/benphelps/homepage/commits?author=andrii-kryvoviaz) - Background opacity option -- [boerniee](https://github.com/benphelps/homepage/commits?author=boerniee) - German Translation -- [comradekingu](https://github.com/benphelps/homepage/commits?author=comradekingu) - Norwegian Bokmål Translation -- Daniel Varga - German & Hungarian Translation -- [deffcolony](https://github.com/benphelps/homepage/commits?author=deffcolony) - Dutch Translation -- [desolaris](https://github.com/benphelps/homepage/commits?author=desolaris) - Russian Translation - [DevPGSV](https://github.com/benphelps/homepage/commits?author=DevPGSV) - Syncthing Relay Server & Mastodon widgets - [ilusi0n](https://github.com/benphelps/homepage/commits?author=ilusi0n) - Jellyseerr Integration - [ItsJustMeChris](https://github.com/benphelps/homepage/commits?author=ItsJustMeChris) - Coin Market Cap Widget -- [jackblk](https://github.com/benphelps/homepage/commits?author=jackblk) - Vietnamese Translation -- [JazzFisch](https://github.com/benphelps/homepage/commits?author=JazzFisch) - Readarr, Bazarr, Lidarr, SABnzbd, Transmission & qBittorrent Integrations -- [juanmanuelbc](https://github.com/benphelps/homepage/commits?author=juanmanuelbc) - Spanish and Catalan Translations +- [JazzFisch](https://github.com/benphelps/homepage/commits?author=JazzFisch) - Readarr, Bazarr, Lidarr, SABnzbd, Transmission, qBittorrent Integrations & countless more improvements +- [josways](https://github.com/benphelps/homepage/commits?author=josways) - Baidu search provider +- [mauricio-kalil](https://github.com/benphelps/homepage/commits?author=mauricio-kalil) - Portuguese (Brazil) - [modem7](https://github.com/benphelps/homepage/commits?author=modem7) - Impvoed Docker Image -- [nicedc](https://github.com/benphelps/homepage/commits?author=nicedc) - Chinese Translation -- [Nonoss117](https://github.com/benphelps/homepage/commits?author=Nonoss117) - French Translation -- [pacoculebras](https://github.com/benphelps/homepage/commits?author=pacoculebras) - Catalan Translation -- [psychodracon](https://github.com/benphelps/homepage/commits?author=psychodracon) - Polish Translation - [quod](https://github.com/benphelps/homepage/commits?author=quod) - Fixed Typos - [schklom](https://github.com/benphelps/homepage/commits?author=schklom) - ARM64, ARMv7 and ARMv6 -- [ShlomiPorush](https://github.com/benphelps/homepage/commits?author=ShlomiPorush) - Hebrew Translation -- [SuperDOS](https://github.com/benphelps/homepage/commits?author=SuperDOS) - Swedish Translation - [xicopitz](https://github.com/benphelps/homepage/commits?author=xicopitz) - Gotify & Prowlarr Integration + +### Translators + +- [3vilson](https://github.com/benphelps/homepage/commits?author=3vilson) - German +- [4lenz1](https://github.com/benphelps/homepage/commits?author=4lenz1) - Chinese +- [AmadeusGraves](https://github.com/benphelps/homepage/commits?author=AmadeusGraves) - Spanish +- [boerniee](https://github.com/benphelps/homepage/commits?author=boerniee) - German +- [brunoccr](https://github.com/benphelps/homepage/commits?author=brunoccr) - Portuguese (Brazil) +- [C8opmBM](https://github.com/benphelps/homepage/commits?author=C8opmBM) - Romainian +- [comradekingu](https://github.com/benphelps/homepage/commits?author=comradekingu) - Norwegian Bokmål +- Daniel Varga - German & Hungarian +- [deffcolony](https://github.com/benphelps/homepage/commits?author=deffcolony) - Dutch +- [desolaris](https://github.com/benphelps/homepage/commits?author=desolaris) - Russian +- [ericlokz](https://github.com/benphelps/homepage/commits?author=ericlokz) - Yue +- [FunsKiTo](https://github.com/benphelps/homepage/commits?author=FunsKiTo) - Spanish +- [jackblk](https://github.com/benphelps/homepage/commits?author=jackblk) - Vietnamese +- [juanmanuelbc](https://github.com/benphelps/homepage/commits?author=juanmanuelbc) - Spanish and Catalan +- [ling0412](https://github.com/benphelps/homepage/commits?author=ling0412) - Chinese +- [milotype](https://github.com/benphelps/homepage/commits?author=milotype) - Croatian +- [nicedc](https://github.com/benphelps/homepage/commits?author=nicedc) - Chinese +- [Nonoss117](https://github.com/benphelps/homepage/commits?author=Nonoss117) - French +- [pacoculebras](https://github.com/benphelps/homepage/commits?author=pacoculebras) - Catalan +- [Prilann](https://github.com/benphelps/homepage/commits?author=Prilann) - German +- [psychodracon](https://github.com/benphelps/homepage/commits?author=psychodracon) - Polish +- Sascha Jelinek - German +- [ShlomiPorush](https://github.com/benphelps/homepage/commits?author=ShlomiPorush) - Hebrew +- [SuperDOS](https://github.com/benphelps/homepage/commits?author=SuperDOS) - Swedish From e0bc45f37e6f1cea013a0db4ca479362807701ff Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Sat, 1 Oct 2022 10:31:22 +0300 Subject: [PATCH 014/401] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d143964e..cb769e03 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@

- A modern (fully static, fast), secure (fully proxied), highly customizable application dashboard with integrations for more than 25 services and s for 15 languages. Easily configured via YAML files (or discovery via docker labels). + A modern (fully static, fast), secure (fully proxied), highly customizable application dashboard with integrations for more than 25 services and s for 15 languages. Easily configured via YAML files (or discovery via docker labels).

From 82b490c524b98049948af4ae1ee2fe312a6be3a9 Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Sat, 1 Oct 2022 10:33:04 +0300 Subject: [PATCH 015/401] fix formatting typos --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cb769e03..bf32fdea 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@

- A modern (fully static, fast), secure (fully proxied), highly customizable application dashboard with integrations for more than 25 services and s for 15 languages. Easily configured via YAML files (or discovery via docker labels). + A modern (fully static, fast), secure (fully proxied), highly customizable application dashboard with integrations for more than 25 services and translations for 15 languages. Easily configured via YAML files (or discovery via docker labels).

@@ -38,7 +38,7 @@ - Images built for AMD64 (x86_64), ARM64, ARMv7 and ARMv6 - Supports all Raspberry Pi's, most SBCs & Apple Silicon - Full i18n support with automatic language detection - - s for Chinese, Dutch, French, German, Hebrew, Hungarian, Norwegian Bokmål, Polish, Portuguese, Portuguese (Brazil), Romainian, Russian, Spanish, Swedish and Yue + - Translantions for Chinese, Dutch, French, German, Hebrew, Hungarian, Norwegian Bokmål, Polish, Portuguese, Portuguese (Brazil), Romainian, Russian, Spanish, Swedish and Yue - Want to help translate? [Join the Weblate project](https://hosted.weblate.org/engage/homepage/) - Service & Web Bookmarks - Docker Integration From 09b4de08e34c86bacff7be05b3b59ee99b10b6fe Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Sat, 1 Oct 2022 15:21:13 +0300 Subject: [PATCH 016/401] hopefully improve font rendering --- src/styles/font/Manrope.ttf | Bin 0 -> 165808 bytes src/styles/globals.css | 3 +++ src/styles/manrope.css | 45 +++++------------------------------- 3 files changed, 9 insertions(+), 39 deletions(-) create mode 100644 src/styles/font/Manrope.ttf diff --git a/src/styles/font/Manrope.ttf b/src/styles/font/Manrope.ttf new file mode 100644 index 0000000000000000000000000000000000000000..42a47034ed2376e923b6b76c9f46bef555a8181b GIT binary patch literal 165808 zcmcG13t)`b^7uLD`*t@XBJV^*h_^-tF5ZGs^NyZuG{vuscK7Pzx-#;_w8nPv%7iR-(UM>U*C6T&di)SGjrz5 zA(Rl}4u3=vJ+NQ@0s6(-uLzB=gl{tjW(*(s!^j(Z2u+A4WTex;k)u-m9dA|=`b;t* zE~RN%eKLO-@#7&vcb_6es~tYFOU$+%r7Z}dXW;pQky0ON#qvcj5W4>yd|owi#`uz| z?cuWsX>|eaubRAI{G75!Q@0UX-Wz_;oicuI3B0-h{Oj=QFr|3WhDm_`>C-7Ngcf1i!XdA#o<5@Cm?!3{v z{_z{3{_6?x&M28Psia7|>1lZW1l+G9NIP+5n&Y7=$8oKbe2|j8G!*AgqJm(D`RL<4wwh=|Qj<&~WyF$}P+`&UlbyBQ>4y5XCVX~PDQ3#8Q(rr_WpvFrd~5&kZA z)0D$Y01-8p$R+VT67m1z(z!vqC&?yFDM_|^`M__CcxcpDv4Cu{d7ZHM&GNJQtZ)t5 z%m;XuR|I^Y0kGhe?jYsLReO!@sJ#L2H>+1Nye28%)t-jeqryx=@Dg(YK3u{rQf_fg z&@O|vJK4C_051Qxmm{|4aET;~8vv&T02e-s7va6>wFkbla%qOceS3+A<)tZvcK(kp zaV>Gw`H~3BOI!?aVU*gvHjqN-SKXCNGQ|H6m#z@nT>-R6fLCkR3iy68$t zu968_lwSo#{nsUcPg5`K8$M%rHGe(;f78jlpPM+Hp}%Y&*`!`;;dQYn!td5D7*FgE z;vx7G4}3LTfPd-#)g_!G5t=LYFQFRXJ|q$LF3}(Kn(1|zWFXDOY(6HF*(~VmtI#*p zt2jnM2Z}E06$0Z7X=bA9wAWx9zV5+q#blGV60RC}zX|RKx@*qjYwb@C3y6nn?E_$Hh2SG=4zSJMdi!Jf~g;Sp}L! z@IK9h-%y6|cXeC}*GPBQ!9527pZDN;pteWg75Xbi0IlZ06#(y1u9R^- zz|cP&BS0gfxyA2A{0Pbcz&yoa_g0?+S%o>t3+RmZC^DBqN;%GWKjI2wiH|A7X9p>T z_odnea4+D(+ef+}{|&sy_XY4A=r){#ke6I$R9b46!FR}i;IA2<;a<*X(3=Jxb3KhZ zAKHXDEkX;rmW_qi1kw-WB}1D<`k{W{dKP38Y0CQv^aVa-09~|ZpzhkL>3h!9KRKBQwAJa>!4fLxYp_A0ypTuU_%l{Q#z?G3i3_8R_fys!=U zT?8BuE{C}W#`a~nClhphC-`m^yq3as9bmr)pY!22cn{ZE@j5Mr*F)-64zD}l!ry*| z>omR>fPSnHc;i9}*&~1xK?(&wxR${8C*gA^_zm7S_C7jOF45j0rMfh@CIdcbbHP7+ zrDe(m?@L)UsSvxtJs(gXu!75JC4A>cD){&7NjZxnRd@+ifD2skEcA;W6#9{5T@c*+ zv3lV%>V0^R0C4fbwzWRWdyp4m_FXjf5u!mjf!>bRx`jAtCjqf>bD*z|;qD7<> zFZ?Y0#IH@_aq0tC89N5Q6$4z0?=^=(Ua!D!aOoH+2iceivV020S+3?f$Rg+$?G1Pi zPHw+F_= zk3f?J@IBZrx>R_D@qjcG*DJIVPAjjP3Q~m^_67T7{Com_zf1lF*FEGPjI}S}8UXLJ z;o2q?!0%ePa)}R)1CZ4Wof9c_l;Ar(qIt*7ac?huX;(dY$S0_@1{Lq$@@)lt%+@S{MlKUiCdl_`@ zJkZz2K>(qXQp*?@Nf-VO8$3<}&H z_(l*5(gd{*atrbd@(uD2>KK$3R1h>N^y5mQvc(ftTMPKM0>2}gB!P^0(I^^6yVE{& zFwFow%jsX456AN&yDrQFJl6o8n}w~yOTrQ1b>U-?h;79Xv4_}C1n!Dw#rys%0MBy3 z(>=f^z)!`qyNc($fE9q}t16yv8SyML;^}IJXCdH8D|Jt3Z7u5oWBn(<*7DyY=-x-PD-RW{?*PRJ>2HhdI|8x6e z`0vCW;OA}m_8+%@h1VZ%|MT{m+q2=FZ{-J-Z&&_}kjg!kM=D>e+*vudaugvq9fIxz z{ZpICrQjemc!8#|D3;CgSs|OrmatVIEEVh)t3+toEBTH5PO8Zh zN?^jFj$$j=J8Tl$ z#{S86u(K?g^<>xChinVWVU?^0&0;Ir0M?%kWMhacjM5gwi?k-5#GClRhztQa=|uXH z6w-_I2FcGN6Ts8YAu~t;%umH+Jy}hjCTqzHq=bf&Gvrlrg1kdclXK)ed7peuJ|Uly zFUe2j-{d~|5BZ4H(w3A_0me=X_BZMYBfS%hqAqj*Z9~(DJ2?y5;Rs0P+r*drowOq# z5P$L^X-nQCf#ebiBL5&=$#v41fNe#-C86XpNhJRy3FH>&j@zUgsU*qdF6lwOCj&_p z=}&$p1IRC=54lGMkq2Z5c}RwlKge+Mh@_K0Nd|dLMv@vbipWGFdNLXWc{=qV)2KU{ zNxjKj>PO~Ne=?7@BMWH&Sxke;A`0^#4J0dQ2eO<-fW`_ZJ7`a`l_rrjv@_XGlSvuv zPPWk=WEbs2_R)c4KY5v^lUHa4IYfuUY}$%!pt0mB8bVgmNRaif*-dsEB>r3WCA&s{ zVZ&$@{gpnT59#mBo&G`pWNnx)=s;KI#oU-D^JX5*hmNBKbR8W_mxGpENmtR;bO~Kb z*U%|+5}i#;>1diw$Iu*_NAu};I)P54g>*8VL+8@@bRJzm7t*KbV!DW~pik4abPFw` zTS1Hch3=%g=^pw#-Anh;BlIYJjUJ=N>0jyJ=t=rIJwxB2=jn5F7k!s*r*G2J^euXp zzD-ZjH|ROKpT0m}r6*`E-9gvW3-lTKce;VTNA}RZhvW0d74>X><`Glr3e;*dq26Xs5+&Iori{ zv$5ZFR@qIA@&*jgk5HzviI5R>@9ZY46S|og!n8fksKK9&y&xn1I!ak=qJn{ zM%qGn;v2zFm;|%KN#PsORg4$sil@bgn)aHpnys48wJzF1?IG>=IzL^W?j_w(-Fvz_ z4qAsuhfxkI9F95sw?#~gq!wdZl(yL2;`0{2I7T>*cU<83M#~m0N47lB^4~3GCqJj& zPD7mvoJyUxIvsR+)9JF)AFUi)CAON>YE!FsTYc-SarSWT=-k)2(0PgTF6ZOUpE_5y z_Gz8bdU5N&wf@Z|(Pg#Er>?%PPq|jQg}N2Gz3leHeXx7E`yU>|JkEGVc$Rpc@RYqA zy}Z1Jdp+aziMOM7ruPfpKl`Nk?DYAy&A2vi`?mEh^j+Xv=6l@ttnbaXLffuwXSChl z_KUW%UuVA(zhi#Cw2NuCpxtNwk^bZSH~H`Kzw2MsUei9T{qXin+8=3ut^IESEdx3R z3=fzaur1(k0rvv~0}}(Y0!ssT2L2c{FzEH*px|vGV#vl&&(QgyH^cgd9SiReek7u0 z#N>$gJH&U`8mWt175S*+!j5lryw|CHr?H)mbozJa_MLM(zts7!ogYR;MioW98ueqB zxGqb&T#OElUKhP3`f}G6UDLWg-}T#=-Z9U`d>Zp>?7-NQaqe-8;=YO(;=9GqiGMnN zYy8Xc@5Fx?|7rZa_$LXW3EdNl6ZRyWPWUF_*Ti;-9TIycW+u)`T$A`=;&0tLbeq`i zK(}AJ$9137{e|w|Cbdf%mvk^m-y^5Tb3Hyw)+LWh-kbbG&u%@}_53kqM9S8bfAn(h zHLln6UPpRW^^WSD*?W2KUc9)mP}-p>I~-HGMDjBmJWK74|#a z?@oWe{v-OY@Bifh?*S7Byf&bEV9vnv1D~Wtr!7zWGVPyf4+nV;N*OeL(5^x64Z1z( z$>4T_QwJ9fUO)Kg;5&nV9wH729@2lv#39p%EF7|W$myYMXvEOyp;L#>9=c-auA#3E zy*cz>L;pL>ZCLkV>xR8B>>tDK535RdP4AK3H+@L@$n;6+Gt%d$FHPT({`cVy!(E1V z8$Nva$Bc5amnVm9=GdE^# z&wM`fubFRV){Y!CvT)>*kQv$JF3s9yixN;Eg7|W z)Xq`+Mx7XSX4L(xn5?9%!mOvVwq^Y_>!Yli(TSsHjy^wH&empk%bu1!CwpV|_Uz}g zua0pWBaN9cX4jZ2Ibk_da%Sc1%-NswO3sgCgT_XVO&L32Z2H)&vH4?njQuLtKQ}CQ zV(#?Zxw%i}uFicS_vPHza^J}PJy)Nn$!n7rnAah%U*6C>DK9s#G;c-T`npjY}Q(mvPq%d<%jKrWR~1*j;eG;NJzmj87du zc>MVBd&gg&;5s2?LeYeh38fR>oKQP4YT|^6Gbff${AS{vi9Zx36)q{fSoql_?IfQ` zgC?z>R6gnE&tEbBz4`xKP_SUzf{KOh7EWGxbm6xPYf3{(2bX4- z&MsY6T3-5A>8GVXl*)_T7j<4VXwlR~XBXXF^!sAR#S<65xcH03-#;Zj<@;37Q&XP$ zbji3SbC*1|WXF=%mRwv?xuj;P=h7}qhb|qpbmr0(OE)cje(9@A&oBLaY30(IWf9AU zFUwuFV%aOpPAogKta|y-<=M*%mzOLr0j=H&tPz-;H05Bg=wRk*4YrFn*ePiDg~QC$ z1!gM}8z1Ny+QjRU*zHLZuQ_wdGBV~39z18jfO)B@^OBS2bnCVtI(km0PIDq77lee& z2?&_y>kCFR%$7vl12`kbB$md~V7S}?!wBY-1OLk`Sr%uqN=%-hgP)cMgq>n%AzD@ZLugTlh%V?DfLV-ny+t2JwN zLa(Bp>0^5K8lB#=NWada^^lY)y?Ty;U#Fxzt}urpD)>6Yajqaw>cJ5#dobPvRvYY1 zAKUQ2fOY=!ay^*x8gY-#L8TGGjF0s+?T=+&S!k(#qd63Ln+Y27niVVP5>qhZ@w!ff zrNp^ux0gb!yD0{Y_i}Wvlx(2rq=M`M{a?)CYfY$%y_6q3x?zd{h>r?Y0@?`mu=^7I38WlKX zP*0EO;QY|Gj$V(P%+OP@)BOO_6|Rgy8WhEXgS6hkVF|G@{tN^yJl0Dq*ps{4;X~3= z{X2R(rnwF4A2Af(hxs|BxefiwggKU!(?Mi)lzJ;B!hrNXW8?i3{;jMYm2KF|k zR<{x8;{#r7NF9Cb3afz&bWc4&tvO^3`n&Zd^eZz~8OBc-VB!zHb)*p!>w;<~6GbZT zf@}zA%>!#V(I9ite6+zDMqG30xW?qX4Yc4dyHP3!l*%a<5Xws7-{TUq7D2vI7xKAL znJ+BcvZDFw35T_L2gL!WEW85a16dS^0rSX_#bg;sIfH49yn5O*6 z*BQncY$HTC+CWr+P`hkrq#nCv7xRwm+#BMwI?AkSw-CNc|1T#t~skzGz>T?A@O}P|Vy#ehg8HSytKaT%HtD9gdErnKHA<7m8t-1y( z^wfnbWDO1tj7dPsh6RJ5D{q4XH?g3i6Vuidi(6hRd3V0-L@yV;GJecoa^T%(Bi3ac zT`I?D%Ey#Xo%3#ZbkrxipL#7<8n7lmfA`qT^fj5KkikTfYwu_xH0N;)Xo5mme4JZI zYz*<%g@phMnNI5lrdSBb6JhUtBi}A7qwT+`p>YY>(emSO-uitBV@n>t^$pcUXD7&) z{V&kWiVB)}L4N$5$GhJjk-vQZefiqayXQT=lOKb%$zgG;F%WnL6Omva;_omeZEp}N zw<}lJ1#N_lGc4-*SntGGU2p^79bvjHyp-$GAO^aAM~+lI-fR~I=)D}oDeVD~N*p!e ziQLMKgEz4{&g2I0ITM)N)-NWcb5|*5sFW1jzbK_a%;X>!r@jh{Lly=gJ>)wlZvPjPCx5X&cD|2%iVlq) zAGrCo;lp3s99Y;{KBXyV4&E2#&(FLifBvDjPLQ-(pQE(J!GpBLQ6H@qdI+m7;z@vr z??NG|5oZM){dVDcux#0}A=vDYBimIRYr)ssv%625duc4 zePY0Rno13(1*;5DLA@x{0CmtmHBqmd%rvU1MVWFp*DwaJ)Z`hq7X7$Gbx#^RQiB#Y zJdcz>D_qeMKnJ5%r;^&^lDbxmeKRxz^2@R26vcK_Yu>b-eyRz4x2_#^YygoA4e?n) zr~!{ooom#VxD9XGS})ZOn7O3_~@lt>UQmPQz)ZUDD~}h zeV`>w>o&Rp0b|b;3%x=6+!TvJDi*fvbNzfvT&&sV225adD01b%w6p+5he6IzPolh| zRc!*Exs}Sy1OVzkFw70j!P6)QFt)5eZO(q#ob5)~7z0As7HnoI7)|)Y1iHZnH-(R5 z8#wD~!vZ(y3;n*n1-`YebsN^Vp{oXLx$Vs<#dWO7u%?yz?7HR*R=4T%vY+SxwDPiJ zahu>P%&c#5*Zf`w!KSrs0BPW@2s+ueg=+$leQv|TH5W1q>()fuD7qHDfE8a8UAsvL zfJmOCH{6*6%;uI{kmelDR~qm>RI^b8vk@(S)og@m5=>RJY?#R2d-1`65okSrM%|J! z<9;||FdpB!J5^pmzZU2+`8WTWm#F*86?DYAf8QOn?!{N-Yutd`PPMN|ex01p$zT2z zr5^3bAn;FH!+JWgjG|#ArxEyk1aU$`EU{l>a5D{sJwD$EL=AZ2Y|;tvG+0uNL65$r zXpWZ~g_&wpH4Z14X^?X*Vci@w1~?Mo!Js!hwC;_g+j_?UZy}{r@@fob5I$}l)ULF2 zXbP=t9Cj*a1&Ac7c3)%2#lZe+3_et)WPUejmsq&haK8Z7T)Fy8C7Ayvj|q1rN!8)v-g>q|T@!Sl zA`9{cwVgUc!2}0N$_XJ40SCybLJZ0!bX);9_?~8Sn@9)NC3;=(>mx9Q&PWCW2=A-C z2KQaycsPPyR;3kg?WBM&g1hTNjYO!u0r#I(qeMU@oP97xZ*yg_y&?}@~VseS>8LQ_E{C)wuQvp+eE+Yw`-Zl*r$>Q z#LP?=9@RJ`j?3;OWdT2-HDMQ*D~z)#as^7-YO}`_Svyj{byfJvtO8N|1ThzI2H8dF zhj<_a1!1_dOY`(80-IO!2*zFpJE70eyRa&~3my)C9e=3Xy9{%>%gKiT4(QZlEYR?K2=9E+0J5EBX2>aQ8(` zQuPG!+LK7}>nD*a$I9V3Zf)>xafS)SpkH^u{eNg2VbRg4`XR{BCh!5uIn7!bsem1V zC)jnQgd{1?8L3zQX`F|F?MAQ80Fs_leL4rV4WmP6f&$_I(t`N5gj_gF${KK)sZv*8 zt+r)B;rdwN2*wzP^$4b`0ZAdn);QK0dv0Yo*TDlm$$L2dK1c%?$H6cL z_ur?Tj~D`pAeah7E(z}3E;frIT8Ar$ARz|~@gb|Qx!4$Eh_(?hz(-l~!Z@wbsxyR6 zt)oCMD~fGf16c40))*bLjfbevLG`wMO;(L~Y`_?;vw_W53O0PrPoCHaoG^rN+z>jm zjTWpAB+F|wX{r@riWi^A8^TMaQdVhlBXD{Y4a?#A4I^cTR_L@ggp(TEq!_P|zik9w zN(kdz!-yfZaQvvTjR?qAHONzFJu{_2JbzVrT0i0;zugF|tpq{dY`6;s+A6V;D98#n z^uW48s|(}Wkj#(NUf7D5eA$Su)Qh1MH{1~;FEEy(1DzZWJuz6c4Ty-4gw}4UeasX~ z*cg7cGloFN;1~j}DnJeq`u=DGH-H11SsG#&0d71uVzd}E9L9AN=xAFv1brV2jySvU zQNw~!-U!`hzyRYyf!s^2HyG-cBdm)NTU5`W?`ju2YsP*f#NRL%a|s~yjMfm{-> zk6~g(gSnwWE9OZp-QzKZYo)gx}y1X zg)!A6y8Z>mSF`9UKQLmu5u~6!CYG*YK0@ygu7qH(vcAF@We!# znCPw3QC&lxM_S4yFJZICn<*c<)Xejx=k228oAkAhaM|O-#IIdy;`}Z*tY%?dMzP~W z76v=IV8c1P1-np)^1VYL;H-X6g2f{EUGZnr!IyNy`5pXuSnc(P+#McU2@Z6HFA@?{ zAc`HPt}-(>&rWTNc8?snyQpm^PdSyIckSXca&}VE?2$fQT;)_vxu9`b_(pN@8w*`T zQGbE$5Ji{5Eh9#3DRj|5Kv0301Q0zGhzJuFnBjkb3KNzAD9_If=PTP1Ju-Yq_#pp2 z1AE3N9UUWQ(IbO5M2B}~G%=?0vOaQ_rd+P{ZynVx`Q_0gcJ@deDp%5ZeYi zuASoz5>sc#XkZg(L!1(;m#AY8F7hF&`UN4^3#T(*?Q) z0!q{tu@9HI=x+!y^4&Drt!A1nlJB`6;0y#GoS zFnaYB2DaPB#1QjPM4%D)DBi0tjv`|;#3+KcP@*wvm}Fbyurfwb8bS-G1d$cw5svKk zu(Qh|y3!zO%*_zg%4!^L=24l35QJD2jBha?BsoD@?^0uzkd76_!b773jOt?ko41a~ zVKMd1%Uk0wczQT9Hf`H~cKb@<@*B&}6(x+!36^)I&rSblGt%W9#@q6MBX?7JH{kh23W!9bfd$a+j(5vmtXUYf5*w zoR%FkR!_{^Ijy@AhY|C+oFxJEK*n$ttVvj|0D)W3R7{nyNmJ1^;)`{Pv)B3=YEOWYin%Wy{DPB$OT0M@` ztyMOOBa;>Hy}YS?P=otTW(ndAx&udMOW5&grZ-%hC{ApEszjQKyooZYY%1X)DhrzB z8^FH{*DPv4mgjkf$5XzV4zsf-1ZU&WBH&7fa#KNYNgCQIHnZ#Gg9Z6-Z=_CLUs(R; zC%(?QTt~;igI^UF9D2Hw{6qek#lQKxwvt-69RA#l{H>!k>Ga#c0VkIBTbEjMO<2}{ zO61nPJ>v%l$}Ju8Utja_9Uvjkz*-O57*@7mf`qlLKvx!`uM+3!t29F;srnR9-2)6% zya)IH7&6xQokxT;IYzlz%|25eF+9T~gU)qhUIjq2m9Z=;j~eC<HJ&gKJYX$LmvNShz|ul?;M;Xuver{A6%A3yi)r-ijO`3HVm2N)qguX9a| zyO~r?Y^BAIK;O={XjM_CHkvlJjd>3kox;^blbuqi@vXo)X_DvA%MzZ+?w-fz8-k14 z+8^N7>4y5?=s86LY_o)aioM89_O;wTTKV4rCWSxev(($ zHYv{fRTj{-Qt#3TKV6FfRNH#W;}31X<&vRU4UI=$wnWax zj-my&@#QlS#&Q&VZ$UK@Ko2uZ#3e9$Xu&SRYZ?NFcjea};Q}yPf6!WEhFE|_lZF;?4o6E#nZwN*WxJHATfStyU1RQ-IkJ2&miB>~)dhB; zVb#p6aZ$@R3m&)HbX}5|dDHdi0GiCKRUroym+WS>QDeHX1tk>wb~5l0ELQ_fkvSf; zT6QahYBpyJWj9(~C@0Cu>;}82U&dDHlk{P1hrSr30RD-P`vSFSz&chq;!1DHK?U?M zJyalvutFhOAHphXKG5$)PV)OXCm}zE+k=Lum^W~7cioc;>#RSIe1ptFgY9K#g1RX@ zD>7|GVU&405CTNJRW6}S8P+xpO|ca`WzVD`l`UosL4Ux8!u|`G?}M!fh8E~2rIYF& z=N8ivvxnaL7vR^og^cYTsyCek)U|HS^7+aPl!0@Y zpA!I(tj-410F526q4?#8bwKMU+?he7q!4%%2DHVDsCbGF4D2l|6b96s72c~kFQocw zqNJeeYndol{9Z0shKwlV6Kou+hnMS~QzWbY(V*_-R8tU_{YeRL(jExvD zK#LtQKzqp8081&=AFq3sr`?tq9|i0)YVQaiKuxw_sMdu!hDu&!3QN=_U;;VT2>@3Y zqtoE|dTTM2C?PQ+E*^Hc>i8yCFM4s=q0EtMhvk2By0gFLFXz_39GDyO&!ampg*ZE< zM|7+uuh0M6tkw>l;@`d^buAhg_mqEjnKW)`nu~io53R?$Z!cQvvvcp_qKG*O`dk{p z_8gI<{j<8Q@C(wow)J$1%O4y!Esa3mIHo-RE*z?eDI>T!__7helpmXjGv@X^zTXVQ z4R~YRI~FRRf&2oEExkqDGu#xKvuKlo2d_4@FX!qCAUp|cMxUSpE=mnlk;GVjq8fuU z@0G#dZgS7MnDh+Gef;u2^bQMUJoai{4`D~n2VA?Nv|*GHHEeU_jhjp+45y!!u4rPP zzBQod2R*emfTG!v`;Xa-Z2 zQTz|k!?-IoipSj*e?rMUZO&wFx`9=%Z&qI*?Xp=)7iE-d-3plPQR}Au4_a5qL%$4$nruHKO)_|Kc7;r5330Gh&ctI8Pbl{Bv zXY;yMhHsnVnFjWRpyJV2T; zV=WVBXNY5A;Q@?Xxp@Z1hhdpXNCk7l&9fllp-N7tcVG~YV0i~Y&?`lV4TO-F67%Be z9T@WxoEe4SpQhigFQ(7b>)e|K2^d!>YqIZP$F-xvd8k8!4HC3>U_g@pQj6i-u~Mud*xM1w){o@ z{iNS5Dn9jH*?02qrAs36SENew$9G>nUKioeVO-YSMbgpda_9H)(>gu-!K9)UeiN6c zY+W5bEK**-qAZC8!M1f}^(Go-W;_`H)`QLZ4#ko}adW0CbeX5JD1`9xVmVtbO`Z1n zb6Y=|R{Vv2x1^;jmcE)b^6<)KM@MHJ_1{H>7Y|ap{W)3Qe?Znh=MP(JPu3hySaEaX zhVPay`R>_`H&=jA@hCzSP~K008=k;vt`?ur>bw++L)u2li#JLHVfKykoj-QX==}EL z^(V8L@bO0r&veb~Tj5_u>8r0%^6ZwSK}B zV_J2uvihuTc#7tPMMM}+?X8U`41n|Ee_W+_d1-LFt}6@M{YCM#Pqsey`LwB*wk$uI zHTvkXm9J)Iy-M|3$^SVj9N16UbKB+GgD=YZT@s9=XTMvr{JRY>juM1SmJZ962)R;> z)cV1C3a>t@(LxGi3iE~}6G(1N^b*y~bfvDNE)0`f-NUIjOWFI~e8v`3?3sVPm)o*$ zo^w1wSz36w)54p(E?)lf-4CvO@qH@wO7&-J9vnFM>uScvjVu56nwFW4FK-`m=wF9l z`fW|t@1KA1KoI`??8{%oj5s^&|EGMHfp30ld5p2lk9^xDkeJ^sCvmR z3VckMVNf^z8^S|sUWQQj`lEN_v<1~pg)v|lNp7Sh*Lup8mLl; z@2~#O4r&U=fI=8bvWJ<c?~JbwbhOAf@F{scskOal=@~`Bc$ljgnc$N|WuN zrp&7L5aEy^V*&Mb(;(X)CJhgdx;|s=7NyTh6r}-Xu?Ps6q}u7VAw1Gxzj5y1kr00N zMEyueBUE|)s(XFyU}iPMVHZt-6&}n3N+lfn3wNW#s40jF92=|Nkj0g-&atok` z>~_aMN%Xzr;p{UTzIVgQf?cxVXxrCymOiyzWG$^IiXJoM*#{$$V?7N;Y1B**3U$R; z^6py;&8?`XKLIQ1H#VxKOw8I)3uaX9hE3G*oZtOww4#k-l$Z*TD%N6mESf)gfKfx=cU! ztPSf_W}T*vjhU4<i>~l?4o#!^b zC#K8mj|cp3y+WJRA66dgs*T{P{AfVVf+odtb>2?-FB(}7}uBVhzjUcE8aRXE-yceONeV^&1^;(sj6 zd}jLKu$m3&T9!QT)maJsOZSduZ+%}BHG0{L1^QE(@|xrNlRydh$J<7lfPd(U+QlXW zT1h{%3WIy38FnGnzJrkXeky<5*=$&Pwh64SVgw4$T7_sR?r0AtuO+G0n1tP7hT4qf zk|b#YR;;M5#G|SpK35JzcnBvY12wP~U%AA;S1VC+Zx)}%s2cpL)V)Kardq4qr&OZk zo~MmUl!`0x!~^fItyQWqa$EB(-*wO7<7YT4740z7ijsW4no@aE0BObQlaj>Exh2>d z_CuL5pr2^DA*N`z0j5fINyYq9V8fkQQ>8DrvTRnD99?hisHTN_r!sTs z=G7%NXxLomHwtFeC1Gb4DnaY@C9$VgYfM7dtsnbQM~m8{(8K>|(5}Fp0oJp3fI4<6 zO^Ox~ca?b1)1Tx38l=HoY{+f~EMYe-GzGQkP_{h!^%^J5UR^H90a*j{H2&2;ZCI=$ z$RGaP&mbW!u}-_`bLuEiA63=6$@ALF+-v1k3xz8Hxn8|Uzh(N%Y(ts89ENlmbI{+_ z--W-A2=E&Asq<&-)r+JT413WJOU&4o*|tNAcGd9$xERL^YzZg;c;!IvMpSOa`&fH} zwDR2o$d7k1gvW;TTKecS{;QW`Tk1e0b*!^|SCv7NQcw+p8!+JNd zTSd)5c4O1QV`TwFFXat8uw3uM`GlHL%&@E90fVOKcMb}5i86PfX5jiAsqJoEB^D--DMRd54t_^XaFYcs72bLeZr%xVBD$| zqHWA$*iS=|RJzP6WK(&v1KvPg)HPj{+TPZ31?|w=mhZC9Dq8jRk{#rb_wp`I8)t}4 zcLIKZzZmZYn}ktUX$6~X5%xqT`FHKnzNOToja5A4y`n~!snZ4bi!Zq_Dvge{g9gu? z7dyfDYHe8mGRFP5vwhUaXis=jQ&)m;Uj|Gk?qe)PEaghmTOQ zd220s<)~a+Ceha4-lV!EH#S$u4^hT3>fDLz6L-G)p{{?~hBF1k{26PoP|6?Qw-3+& z59Qp8uYOsH^ICSzxXxo8s*>DjAFi^d&`FJ4`tm*13gmjR-Fnc~D5+9FbAoLgcs$oW z8W`_`2vsMT&9Jgk0LKF)s=ga(!dZ2i!}ypr;9V3`Pl;051#g-+C|ae3WfZp_EykRC~iV>h)u^_7PWU-ASF*z0r#>$*-%6Q(7X)PAl8* zttb~mvRng@F_r={&!e)6j%i5ZZHam#WZa5Ivy8;n>tRa>!iHKWwUV4>zk{ky<9}gqL_4cKs`w87ZaIq(t06 zPMd%qthUkYhDnA(tSxE^+0?PyY`Wn9XawDMz%Xbs-FVGOv>~Fo{A0~Yh``ogf6z3Z z&sN3*{kmbgS{WYSG>gh;k%q!tlnVW@>H)_#zArWd?0;{#LzWh6Q#zy0Q>ve+XnU~i zxCdi*%(q8JG8O)`vp(FF+5!!kc}6XaaSc`H^C|;Hy84%+OM>vYnyzr#9VwhL-*Zc2UTDd>_OGqYkWC z9Ej^zNN=!&VU5z;GYr?8JY6@X`?|)p>9lBZm%cmubnoIQc9Z3xPD6bDfIx{MQe@E@&BgJ4#j;H`Kx?bzwb1+=95YH{WE1Uv(@5pnz!j zwIyHaHi;C2-_lt0E~_IktP%K`jLtiaqaN1nyDMs8T_36kK^~@BI}yuq#zRn!N1ZKe zCt|ThU()B{_0j-hNF9B{t0_P+2lta|cQWld0&U|JqA5wcqn<9W_@6kkb}Od`Qg zw2}{BM`lCyAIv>cx47(6A>_h}s-U#ZX9VM_1Joz81pz1U&DNlBrT?=%P)1moi5|{R zw7^wGlR^@9;KrJyhV-)v-=xOElTMAoqi*%XpdD>>o2pw`ZS;VPd!VXcC8^ekckA&Imlu~L+oW%#PPm0Y#>llSJ3iFtUWxqq>1}rL}Nw5j+{P*2!dLZ&=w}B zs~dxjJQK7)<55DUV)PxPQ7q^5!8(`7H*>t~N~hSzj7o2n4r!21k3WZk2X+Pbf1wpf zc%x_)uf(|;$v$NOaB9`w7x#gTIg7naQ%{)_D6$( zvU|A{_T<@UX50?78tbw>1DN+gUS%U>ai>A4NVG^NwXbVkc}dJ8%j zA3UrTY8@RltYvq)G|bEx(^6(;u+ePOho;iXht{C+w4Mg%2|uA4<_RxYPv9{mYuP>! zowQ*U2nANQNWW|i8S5!QmmAb)!p~Y|zjLgTf2`nVZNIZ^&ClYjY-$d-hNZ2Y%XjVI z32`oNrD^uEFbW<%KdB{6-UWU?#0P~PKwT|ltf;j%PspX&G@s_?$faVpnpELDm}1JE zn!|9XQ{A0Pb1^sx{qavg7JQKJ$amn$Y~e6oPc8{ZYG9i%uf?f3%%#-@8bnDo ztM1tr1XKT~)yC8yj75`%7SUF!tL`b7HcB5TuHs$m&7yIHSy>hhgH!`u09VB#g6NaM z9x`iOC_ocPw$`+20zt-_MbieH(HcQ2fTlL10>h%j@+50*D(cq?y1cfha1VF`S$;;M z24ii{Gje7Tti>!Sk~8U8X51wuT__%um`GS#z zQCFE9mP-%!rb}}4AIkwO?y$J&$$ilWLUYgye1`MVP>0d@Bx{En=5@2j5%))7rcD^z zK<*(W6gyWiHbXrW)(y632zmB6&a^4u7RN^67C--2v0m#MV~dehxn@l%JbLuVv?&8t zKn-JkM~x9BR$eN5nYDrTXQ62WmXtyM8lR_?$lO27T2Q!Z-XQ}P+=|5P!*I(KfV!U1 zSL)4}Tg?DiF%}=?nW7BZL7^XNhyJQ|&=|GDXNqLhRpyKkob(~Wf|`e{!e4kVJE$f# zTOHlPXJ!&nR~Hi#W%T3gp2JR8YwJI4kcE1cISq&KMAfyS#!iim@R0==pcK@r%t^18 z>aUwTi~EwV8y{8oZTX2=uy5-TP=I1?A$h3vfwt6KUMSQV3pJv~lx-#Tz#*k}^k* z9F;MW`IRqQ{=)vH%lD5e88ddqtTAI}qAUVA_h>MS8CPPIto3w_@dPhCm&1565_T*& zG*Ia$1i&CZ9k@wI(>u}gRt^qZx^m@G_1G{;_Aos;OcF((_ZKaG&qpHw2C(WNmU0Xr z`UF_OXQ2i#(4Z_J{7phh&0S5oawZ7>l~<%i{fV<0zlVN~S}+gqG!&=C`*~}ki?%mr zSVL>*XG43@Qq2`jdHF+r%1B17i>3hJxnZ8Zw=0~-k(l7-mI(QyuE8Kx?mz%7!-B9G zdDG+DIJ&qwIS5&W(vw|lg=P8-Z7X+Yr=T8HwBNWrZ{=*Hgt{KAJ|&;4f^Wn}Ps=s( zr{kx- zX<4_j&sMg}@|peGoF%6w6ds>BxR*x@P46LI2Tpvrd+WJA*?s=kYNk@j@VsXvNT>41c_3IgR9E+ZCM#qb~0vs*|?Q|3-f<%%kuM6RaxPuje{%% z;(74Ar(!uA?aq&C$8+6bEW`Qas$`c#ZR!@V#>cgca)vyNAG65QCiSFq`mxEGCQ2j9 zLGfCX^GpmQrW_=)1?oY*PKiZHpniI+yRoeUFcX=z!3&4u*?quuF_%llU}9)37g}>9 z;3zAtan7NrZ<5%hdHNKA&8vAtp9g`5$|am<3cpbBf%_4){}L|)_pz6lI0|ccD9ypH zfw0-oS%^p;5*6s?>f_;}6N)5#KL=-5ANN+lsdFWrTiVX0bH2JuTOWg-4qg7ky}OVUS&MFaMlmIDrt)5{BQip%==iI{`Q-qYh!aZW2SJnl-3dHAAaU zsXYfx1JBGdwh_VG0L_finFcIkbY_$LHyFl2C%~f(WU|4?4UE^~ znjI{Z!hlUc$#-VqP_I198Q%J{L`>az$(-@P|Qikp65M%lHv0EwOJ z-L=p9pLfyq^4m{K~+EHE(EIoxR zeW>tVD=BxQ>>BO|!JUl%8*YW$3vfi%7HIFo-5S(Xn)qNKAXfA-Jf+>Ssq*nb_0jTj z>7fx6e;#pj(GUe%9d5Anu~%Ou36~{(RaKP=v7icN0%?PDn|dB5Kr%ZKlh15?O-G&D zB&+k9*@2k)3l;yXK$E(zDyGFBB zuJAAUe2dS8uLPD`IQi>2(wo$GKND_Wbp9{ZoRj~0`>K2l_M9npF(2JMQ70;U&~y$! zpWa+YlG?lMGXFgd=*8etM!$er`?xDG6tg&Za0HYv--4*sCBj?gCw~w**n42@wlqm(U=I;}s0Jeg~9C*f?_m+SlXUH@g7;dS2e`N@>^Sn&Ehc-Mo`qy?{o zkmN}E9RFos(N>$c(3W2y=c0K>>w zO$j{$*G-#%>gQAL?fjj#oOb=-vQq^G=Qo#s(ZOAZgqIU$PL_X{|9iNWlu7e$mGAi= zf9bRRxA&7nKn@U&Gw1VOc&p5>s+M=R!QsmK>@By$TYk1M_o(=}%eV^M(An0j#J&21 zc2Cgdhw~*je1I-UZZga>X+TLG+CAO?9c^zO9HGI<8Yk(=UZ%}qPB}81uaQ&!@L_qm zwl|m(VbwQOTS0pP=|ji!ael?l(tz@0IlPGDmuG3SqN*o0$=~{SB>)CITXKQfXxQq(9fNPx}$FAtt zh~2>FR_0*xV*v7oozen}G_m~Y zAVYH|nFDLAw~UcwjCX-|XVO}C@b74#p%oBZ`N1jk=M@RQ0zGk5W=_>32h-TNe^>0L ze`K*27i1%hUg0$fK|6^XiB(Zv{QVUxmv6*$W`YdvOJ3;t{flo+*AU zTz$Qr*l9`su!V=0Pb=rh+>Dl?ncb%RLOZ<&9l87TZ`WSyHDI*A!V&QVwC2S70pWB` zRO-4Zi=LzBvLv}AS1tjDL$MVsV>%Rc4&?Ku31RftSE_D_!_Mj zIYkqq*$4Ga19+x@t2P8}sSs}XN*ve-*hBKvl1NeSonIa8!zFVxPm|T+~ zv1QV&@^TO%KLHr4`jwglqXfTo z!xN@Hbhr+L0tTh5)lH zba4=snO}r{a!4TxEHLZ6l}H=#Bplhm?M*O#gCW!hJMCH4eG_msck6)N75t$w1lOwH z@_OL(S9$3Nlz!kmtg69!Ul76swO{9_TIu0ww&{-DF2XRg*++m@`>QqxpoQSdv#F*s z>uI3C16eE-d(7Q+-s6a#Jt2?M*UO15zTYmZW8bIJH|Itb`pPGm9AnUFg3H}5<03)_ zMdyv|T;P2-qh&~Dcdp{(!OWp$>WV3ww|hE@b=q#C=;+ubclgwaE-eIQZqZx;{P-RL zgB)7o=4yc#D0qh~3yeTP=bK@Iyr8GeuwYU8s~`eK_*|bs#x~c9a7rggE9gjGRTrvq zD7L9-g<{1yMjAmBh$TZ|&^g~ezfY-9{P&A3S%Us!r%UJ6BE=B5{;RP_@xx2f#}AYm z#gq&H827*iP++Jw0QY{eB&a(1bDxh^@2KdP8FOaAyB|5}KV}Jz7vEcSu5(7rk1ss` z?VR}){%co-Oq==OW9ibvIYmKBw>(=*Ui)h;*$DkAhu%PJ04%A0!8^fFX@y%-FcOV+ z6v#A9#Rz!1RJY>GYqO{oKA?qP6~7n^GR9l{9$Lgm(;dxb=!F-`F^^&g!>k1?4gBFUtF06StRPNY8xMTGY5mE;>m`8*|}=8w#wh(m0(O#yvl4{<&FMqjpZ*dqOKY_Iavc<#SRFq?PN}b{yO`Z!Xs#T%Vxb0hscL z3D>7O9N0#LRUuV13H|v(#h^D1K#BIF>&h;8WVM+8?!pD9Cig$OXZz0h*S42^)HciS zH@{c5k1UZo1SAiN&7H$m&vwaucKF~mS!ol8M@FO!=~29_w9sYUZq#Uy{|~k9VBFq> zaZ1rb)o4L-t@XCxc_obSXHx(`SLP4zWRIc?jCP_v6uv-UPmWD zp7t*IM$MiE%Le)kGNI(@G$#u=#>9WBahBf!qXn{()aVF3kxSR-$Oq*E+1$Q9Uz4gn2Npa~?|?DN0##gqdru6X zu_h0Eu2$@CXcz28xc`_+?E-NHz|p`;D@1hBiw};sox?7aS3->-YyE_!0K2K|oU?cM zT&>mzau+<%c}<9i%tKrgiHBv~V91mYRKAb*hWHI%Dslge?VoE>9!QgwuGL>PD-Q&2 znonJUAolZ%u|N>J5AlFfSlyVwdyBdHe5DBcOB;=eW>uwBeW5{gfEbOz zNaY_`tH6)fIY0QUs3`|(VO4hSl{Gv!f<1G==In@}v<7ELz(k3iK%AeJaY+FQtjj`B zFs;i8P%*DTiKRJ!xw^W?F-LE@E>bvCxTmi)2KJy}94*htT!dBw{lZYtvxg2_`SVcVc z&sVRS6Vrr#*ITQNJfT4;(4pVMXGo+dT(D;Qq(Tg-=?$Se2vJvqqmCh6 z^sQCu0QIts)Pq)lL&e6==^V-|fWrNEq%Myd#8YfM5UP6t2)01KL39D_Jz2j;$jx9Y zAgU+ncLeBna5x^orS-fWSOo^S@UJcsj(9-tI&rvj`0sfCWPX3$dgyh48;W*V6ywve zx=#vSY{hAUH!v~7slTpl{i3&4g!nm1n%2Qr_e=Y~3~H^BTC@vU_0~c--6U&kPTEX= z<|b!_F6mWvo(VTNrnM{*5AImyawP#P&p{%1@Xg4?*JpJHYjW}rQ7f-MLtZYcXnah%-Vw!Pl7uCK$ zW5)Y(^{!j;iDF6WaEy{yp8n;n=~LhQarLTeFU|7jlrxN}Fu(`a9@+I;cR2+phTs1L z6bXlMP^J7Lzi#+Nvzh;rL>^fFLOuQLQhl3oPRDb!Dx0V4k$mY-N zrGwR9zU9C4;}Ure)**i;N9vw2SpMqy;WjM)x{McCLl)ra|C z-a3ODR~w`M4AYTZgT5sQlA78IpU{%Gq{Z*-%@ zR?I{>KEfrU7tul@-0v27-z#3;5rjO`0RZnUZILM17zbnJ(# z5IAR`@#q~Nqon+pE`(6X6o=oq!yz{DI3vNEIR1N#&AOHB|(~mx-qk6vl z{FJc42_b!2(K2~e+ZfNd)E={6n&S8L&o7ieSmofnuIh#TRqLe3pI)wdbm`OIg~gs7 zdQBVEb$DW{7Q#@C#wj_bV`^eT0BRicjt>DxmFTr%-s%)gIbXR?0U@kdUZUCbJdMw0 z9h=ytaD>z7sbgO(dgj`Y)b4K<&wY8@vVG+T zih!nw>>8r1E}w_Oe81W@E+cC4vUaW;*L&HDZfg$BuAig@^(ihd9^Ym0ivBqV*VzY-xOGVW zfDTv2<@WE;ap--^Qhs*g-tM(WiyV%=^D0Xwb*(vgZ))*^0n%di7`kFE>aP}kq)|@e z`uoJP58O$^*%-*d#+;}Hm%4Eew?@0>w3r*W=ChRzTz%KCZQHk~r@Dr()Nsg2B>Ol2 zV3L%gcedGj$n_b;x8PG&+1WoevfqsGpp+pV?kR)uF{^r~J|e@>=eFK9i{_qXx6=rL z+~WQ>l5!qJYehSN{YA7^oT-bJ*pa5a3o2@V>CU?$rLm8MCI|qTAtplmGPy^Lh4G4KYhLaB@Z0HNGQPG`y zm`ex{ZjJVH-aX-=b!WewTf1QTg7ih(C;jSgDU(uOcx3a519kp)46(X*8Zxr%>HMlc z|H3|WY*6Ct=#Ez^3cAewb@kR~1N%I^XzD#V{SIvGvEu%F?_a&uO-hHRS)-R#E!s8= z&B=Yp$`Yd5m{Wsl8d>y{S+q(Bj!jZE_HMy3v9=y?#q#VG2TlU>;yNv|3WMu~o1C_Z z>+vECGTg}TD5I29zgkVYm!7!y;Wvv*-rTb0l}K4(sQK8HHD(tbMUTt$yXXC-=6zn( zx%IP69Un_B+*kWyjoA;e7eI0@m26mq#ZWY86e$=JRj1hrJqB)CvTARB{|;C*+x~e> zR=*eTTJzjwDZAXUWof{$I|7I1M|QYUndfh{j#+qjO~lL6bN#(5aKYE|i}&8XeRCf5 zz2p^hkXtG%EOcOf-&lEa;fC?LK6-uS2?tt`TWC|<_F;AYuU3Ri3XvC_+xyPHyZXaz zC(oQYx%Obr*}x6o?cDnLCLgPGbWe0%-M{m@4Gw92_ibsBa>;vlpL04<8&M5k@h(T# zrv5~nCRqPC-0V|oFZU^Z_oK06B@Z<_)-niTE1PvK$+P88kr(W*wrKyII%qxdO;9zr ze#fe*{T-nr=iZaeb2oX}{NOmQY;UDXtUs9h__B!+v|2=M$=Ls}Nk{^)Lw;+v_fYLj zvYbGgVW`Ar@*6rZIv$-eF|_&W@>^Bak=45V=D*;{Tu1Jc3;bDv>#^e3h)V9#CO$BE zczJh~9tFkL19@(bJrNKep)Q@|ks0WuWtu$#n&lFE4mSwwp4#*m?2~ z4}Nmj@-=Igqct(FU&M*6br=`y0_(lz zx~ptG4SgwACftyWu{L|A^@MPW=`5#nO@%734@jnGotyB~zit1NbBFb9bGOrl%Nngr zB_ntB@3+?0D2LyDb<_5SoY9KUr$!#J2GN+u=KS1DX*Zv@KHgeVdM>Y@xOrk|&3bB- z({{+AO`UzOk$+loazIi65RX7B<9tUO`DVV~_O_?`GYtb8DfkgGol+oWb6ey(ou(fa?ohid zS5ZBR>s*gmPtmSo^!BC|2Id!Z3kVG=w8E}WAiU}L1PyG&IaEsZYYP{?R;^>+Jb9B6PnZfilNdske85Z0*U#T5a<7V#4FWfc5vFP-YWv3VP9F|Ew>WTg-y_v`ZXf&d%M5QrcHmcV*lxY zPHAdnl4C;sm8j6Ef7)657N+@}D@!2K#Hk3{$;YZCZSz8q_eMk+^2$`FmzwU_w@*en zEM335B#%3j9L_Tw660|vgd{ltz0CD%2Bz1SCg)mM)2S{MQ*m^4_bmUaMjRVe1|^@UTyJuUy`71B1 zUirZqmV1zLCTfDeCUR{ZrUcTt@g$$wSj@IUO{HY@g_SEVtXchs!Na3}Sqf5uhJ11_ z+>ii>nscy}F%VYO9nPyu`b?e&C+FtS`CH%!Cx_{Yyi!?^WIP>Zf%by}q-wgT!s|1& z4)y1)BPUF_c8K{U_WwZjEjZC+d;tOpCcbmyL`pySbK}I%*E}Eu5l%&{e6{TU2Uo5x zeqq6a7mAm!a@)4K{N&2*$A9zKW4}4R{k~_OxetGVvtL}f@x1{N-CnC+@Z{vlPcEo_ zwOii-?`>T9;%vwM9Zx*<)Dt`QtFIrp@4ox*zwf>Wz!T8lno1P6`{><_WJt6@eSpTi z-4LSV{0(uEU!Y_gOY~yW@aRMHxI{m$y`e;{M^Sq9pXxOrUFxFtl15UJgAPh5iit7ic5b@!qa_ibvVy5JH4-3L!~1wCn%-THri zLezf>7vhvv+G@DmZn%Iis(sovxFi}bSq+y}4g0}*D~BRKC)foU)m`A{FuM#fTxuIG zsVkh;P%|Ec8qI!^4VP;8Immue$c0-jhXOC?3(8t+x%3^OOUtEo3hq$y==giHvuh`f zxw}tFV18oq?AwES-Rp3y%NlpDW7>)p)9|Nl&AxA<^H|P?>=A=wA_rlk>Wk1jrexhc z&apl_Yt^(VD^^UIwu);GC)VGx9zbg)d5dI@mg5y1XtbiiO772IHEPtVY#k>oUOZv^ zk|oLl7dc0Fb8f{mYsq+7KB2mLf^*~eCEzjDs=KVB_JtI@?XmF~qk8P!o2|NQ;j^dC zzP=RBA|HEr`>Y4)`#WD_jG`gZzm*|MJ{;F$!GznV$4Lj#vNE$?0dfC^FFGv$KF zNs$v54VoS|cE!k1E62n;Mua*yCuR|+Q*NpTR0MH8d5Genu=xFMrS!+jPo0O-^_`t zMjH7!fz&WM$ynFXsWWb}m>?skI^U9`v-6Sd16gWi{W96k`E?c+PpKr_)M11q$+VG; z@rg?sOK%vPB8|a$7#D(;bsn z<|Gx|etZ8A`OfGdXJ$k~B3eWCJ>#e)Dy6QV4d^Y=r42NWN}XK>!)7acMoY|E+t?CA z*Ees8N{y?XD2JjY4o_;OB~GoWnMy5@>ZiLJjeMh(`069kZk$)kkxu6Uw3L{vtn07S zSOi)Rg4S-B4U(kHQnEP~LCm7F&*1zdXSfpTIugmPjuj(jcP zk(g`uG2(|zWBUT}2Vu^xw~-&{?X9Hz0}Q}Y(~PKaChGf{LjBbnNTpE;8UO;+NsP@o zJhEPFNRc?qB0^O*h90{bD-yM1>@QP0rm(lBW(zcXoNnD?+h<7=Zm`4#%Xlfn;Apw- z+>{{CIHM9|smgT7(l}?7Gb&D&qJP!FX8>9O+6Eo{slzwJaIJ1g!4A+tTDS9$$GPBG zERCY`RNHz6U~)hFK#b~jd(govDMLZSMR5>|fvZIrQH3x%b?xZQO{hki+Gj{J6d?qK zlSOzUoO%mSMSD*&%}VW+&h#Q>x*g~WzCePiCajp@Bq#jfm{1x@g#GwJzQ;8%J;@J> zspd1%l%jZsQww>dAK#M2M{Q_LsPWVg=2{p?XafSvzRVqHr3kJX(v%17!9laDd# z1tWc(msYc4VtsK+KqcyQ_39RUYvj6&Q7ghjgB*RL5_eAkT?6_>L=atFb8^&vgRI+f zqX*~qjPKpAUua=G$Qm3UKR9+pX8Nj#u;HU3BWGvG^&pGJW4+Cx&hcFWM0uTWp6(GD z*&`?-LWM^3=-ICy7W2@~cFFx(jFv>_XboOVzL~$O@_|$1GZ2rPFi=7CSTj+|tZ+ZkwVcHksh7X3M#YaPxg>NKi{TuhWBWtGjXQt(-r zt2xdZ$jg{aH+$!c&4YJj4PNpQgF5O5vM+jXmEJ>SU!#XyZ`snDwPI^sV=Klix)$mF zM_Y@<@5i(j<~%hrKnnur$q_l+dNS2pipLn*HL6yVz-f55xmxiX_yp_HeG<A5+ z;p|g?W36*}V-0UL4x}y`hFZfLHlrj98`fR_n(5h%^s(ZCRC07XQX%_n(~h{wUP$!H z0OuZc&Q=2nSIAIBd%C=+h80{NAAhxN!M^F!_bo`O*fl94j-09GGlGb zTIX+_&px%sxzBmB22|%DrT{%A-!SNhz_AZr@uh7GwJoW9SI(qe6-gYSb5C5293&lk zp2GH0JjHaxx$W>_=QigNkO7*~)T_2n>0~H+6(sDiu+W(Jc&uWhGxA;}#BICXpJubP zIjJU3T;hj&o3j0uOe`sh85ufsXz0k85@*_y@oImso)w5u4ji!UECXcb)vL}l zw>rmFH(D(^2zrF!2M54tyGRM=!K+tgCK9nyBV!>1_w7pWG1 zu%ViX03sk4lfA7MvV*9c>$tt7N0aCf_lS$<>;?Awf| z_1VS|zFngUy{gWFR4^Y4L;T@ZBON@!0WA^Y3b+)F9=1^W1f(a{rsA(e4zEs;0X;2) z+6_&)axm!jUW(QZOy5K&&YUovddxbVE-~0$%<>~6y5nZFqZ^}*X*5x6qFl?>PUAcw z=;IxbP|HU zl_V$hF%9LBa+zEj>2x@=O%w7-@|YHANkc8YK)erU+V*H$A)lehdT~thRD#^*EP`~l zCr)mY+aQ_g<&z*kMQMhrH3(-{YY>xO$_au-PvV^zIIAJ-$Ra+!S|>xaT+1@7TGYVj zL82ZmnU-aG8TfuL_4qR52J(q|iPcxjqf9;V%#E;bwLD7HlUxbuvXOeJ8p)?Gc0aL} zLhcIZvkknK3gLiu#N&OFEF>t{?UA(D4QWg3plP(e7@1U>fw}tN>9HY`CuMjq_8K{> zXzDGg6{)IE!i?L4^9sgzE%uu+zdT#J5ZL_|nc1a_e@acU`aE}eX0LYL0=3}*0p9Ut zGwS`;{CsqPI^h7fKr7oMBT-s(!b$S^qH1TYjBI#Vce$ECEu|sCHWyl8(rC>SngsN- z4s?#s&&QC!T-IAayT2X0Nk1}be#TD6R!DAxN6lqzQ(O0l^Q+e@i(i#po_SIFKR?E^ z&ewP`N_x@_f z?BcOGGYj9j^LNsxZkz1**225qan`Rr{Or_hx0IpjOR^kGQsak(u5*4kVs27Z_Li@n znO=VM%jNg{?S;aD(P={lE5DgJGiJ=3I(<5Ef>~IdqxIS(($s=g<}lj4BVjXM7cosS z7}I;a>e&Oi*F{o)+8hWY`QHvP4SNDSiKc*(Es$FAUu7?PEiF1mleb0ooDw;H%FId8 z^WuhYj0qX!GrH@b+e!z{8kd^hCn6xByRz9VDyO68(LwwCCiEHn!03?+Vur-Dum37$ zT5w3PRM1-bOkmpZxZ2ENn+Enx@R@LL@$9Gjb@dAg4M-0QNemC{9^T`wvFTG1x((>+ z3=AF^`1$eN{Gex(c7%`c5B7KX-WrzFS$@c|9FWmS8t90-$Rv3M^$SWe0rFeL2O?lzU9@o_Fuyk;^i5ANh|v4-Z^k zjoVTz+Jj3I3gtFLZN;3|P=i4a zfs38a#<0o>T@#MFyy4nQbLYNvZNvTF((~JU$8U^{>7jZKh<#vEY;M248D7~Pql0eE z3>#V++Uu6!;E>Xx*=a!$UXCv5f&KD_EIt3kv}sSAUwYRE^!&iXC8ql+X4xSrCFPM3 zcWfJylH}j5TXuB!;H1u-ePbdcmnEjx^cxTz-f2)s;J^``x_3W>@OQb!hv5k;VcC`l z>(|JCPs}6-QH?h*ftCjV!@NZ!t1wB>EC-&c2@Puz{r@cD^<3uM+)dDe0omtzQV$N6kxl2eNtlBD4zqn zc74`AI0TEum>a1BwwY+-?dYrozVpKuxW4pRGej=qqgJhYr0gU6j8s|9>uFAB{ZZ#v zs?_3JLzVdASG4(J`dCW$fiRufj9k>SFI>Rj;qC?|cuVudFu35YC z@^|IV+BtLP&RKUXyMzAUm6>^$`XX;<{>)u7f%!Z09L5`d|GiShL8R%19MS3odgwt1 z&$rN<8{7) z3bY|%i_2~xZnvS0J_BWDj`JNEk)xv{M@Bf`!IYm+W#qvA4M2s|U&O=d0jNJh<9DqP zZb2xuP~s0reX|ucf>9@*pOA-L)@g#JokWvh+rIBCvNVAvoe9oOmg_3hxhYPbk!Rv? z2!cwf;S-EhN0Ep75EtpmN)-F7+imUO@&H^8L0+tFNVHVjicns3V!I=>kMtFB=&`hh zfr_@IzbXM<0EAP=8*lw$@FqE3WuWSY*WS9$NDBR7b|@ z>C+#Yl0ABLcJ(Gy0(OT_Xe2TAAo_6r8qxvCBc`bDgWLUlj6v1jS@~@~Rj6r2r+((R z`|XIVe!pJ4?!Y9aoqmnJQXFz(RpKG{&EM|W{q08gLx((St8mDRJUS=@X+gW>j zQ%UL+wB!t=5g{5U5g_T|Ple9gzc_hl^^=8Uv}vR#uW?5L`EVsf0CsYTu6R(9@%KN;Z&oR%L}uyCMvPRv6Ojy~%=qt@0hR%R>hMJtW983rFsWy_~Q}ujV-Cu99Se$3k{x0)iO7aaThyw-GZ+On; z+gJ#cB$Y|CGV+dxOkwn(TDej$gpF&1#`brvmMgvcn~Jjfdpnm6SFf+EFV*(epI715 zI+R59^CkEHp}(gGipXo$#<62J=6AGe*T0UdU$31+V_Azr;Zzyu^Z*t=RD*NMqNv5tqpeuVP}lW?4#;xXLoFp zp_N`yZkEg1HV(o5sTo|+u3xuk*Qs|qu?#^mU%{@`Wn-_3a*OR#b0n0<6V=v440s$! z7A309gN~RX+qhnYl^J85iB@Lx)h=~Omm`bhwmrHGS>!BYno+x#acFs5$h+WvNrMerWbMgn}plvEl4cL@$~WYjan3?#vG$dGllFPH zISZ-fWr$0bOWLF0>=7iJ^wQ5o(EQE6Cr#iD>7PVPh!_ysuogsRi8;HUF%2L)6gJDM zk~M?V@6KPcE_8EOS!1<-?BY**$u6w`ESe^Sd5i z8DoQCCN70W{Ta9+=Byag_)8d^<#jj{X!s#Tx#Xu|v9`hT3H2C%l6B&-pBaxQCZ*Nt zTD=V)iOYJ`Ref6Dy{jhHW~-Hn_$+p0Wc}9Z^;;w9j8Oo3>jv9KIs<^6(AZ$sXnf|_ zH!|vgN^;b1Q`1M*zi#XPZ8^+k;N z#9MC%s?}fZ*!8znO8Q3*>z}rA(5ibpvOS*o*&Vz8yl3a%S5NrIn{R)mY5zR)?w2&j zsK#uUq}F~w{~yZm9R^1wYh2K#P#gUcNTEZW@|5PJ0o+Yp~g~+l^gUZ ziBpP@EaIiw>~fCA+R1h4rbQZUTHn#bSYHHpz_`p~I8A`C8g2~ao3z7@@4l9$#%R7t z6W90A$1%u{R5;OJj{gYUtQEMh;9Yoa?} z;Wx6R`mHKg^h=5DX?yoVz@j)p)M3_3 zFSu8`+<7U_y6BW~)j&^F;&v2OZQqU&18bSB@B{E^3}4{W@=z;xTiF6)CdD_NLFB$aUx(uy{-J)yBZM_R9Q3R}T#YgM+M989+*Rnc$c(ogeCHv^xyv}UzJUV$e8Yjxn*&V04 zQ+R*J7zIf6H!^N4Bg(o~ZXoL(l^vP5Vp)7jcv0Dae(}Lw68ePeJFxnGwy{Ia>#yI~ z1a?7e>H(yOGaeYBoRFmbNKUc#2*by4BvSe7(y7fZZDH6rV|mKXLY1GtWpi(TXG%)H zTc&KBvU+XO+LUPr4yG9>XH=LRh}F6^ivxqmL|ka z+W6E{8O}akq0umH-(!Ut!#5PwJ(Y^GtaEZd>e8A%ae& zh>)H=EP__SgvDZ^edA>>IbXP1TYFWGcaE6#`Bc*FUS z6M844mn_t-JI^}L*6(ia`v}J{iG93rV@N7V$eot682!wfdM>IIKCu9ITVJ?`Ne8*0 z?_6Z}P7PmJ6L4>Cs0@Xx9j9}a;VDFrT#H)9KY&etz)TvPNwy*f1@7c!m}ySk*)Ut+ zgER$`A1nA|55sK3+D9M5YzJSXy)J11e}nFcc*88QCi1aiR-yyK>wYvbNctLPi;Ewt z=qg7U?luu33k|ay=)c!6yStb@MGyIu;oi>0++GIBHw^ah;hRE{J&VnAV4lTclf`^Ii}1ceRN{R&$5{p6 zm0}Q<_WL81V)ij#%tW=$g3ozyt%SckgrV5;f&Jm?no{o@Qcj1^Ud16Y8)?r59fhEv zgyV`q{ISSEthil_6T=b12$-7Zpr2?ho(YJD=r0C!rN~87Ol=803gPB*eu_a!5Yld* zH!5W+5wkoBkVX|~orhHO5jKxYyO_%_gDId|83)sB_*=+%qq5h1l;AlFAxq((!UrM$ zRECs;Ao$noZ5;BR3HunXH_B5}%v63&G4#c|miZq5>gZ2z2d$-RQj>>EAo36&)xb<3 z(YX+Iq9X`ylx{MPIgq&uB@hI6*V3p2CDazn;aZ6lsSZl;r1n&ZRxt+QGk;Q;<~7$^ ztxp8CW-n-JQ=_<4i&3icPzMFTVhm+vpen!d*%X`k2AoO}R|DVNPHWpY{!^dBEkyiQ zDyd;P%_?ouE?&cpA@0&cddhZUrfe^smK|hA>4iesFE(OjJXF++29Xc#j6N9K{vv&4 zCv>p_*;$;Deh_~HWEa_0oR-~Wckw%U3$B~IRR&=_y^pvmgJlodQ`{y)WH0PJzAoMn zXT&vd@;7P0P4{<5Epkp0Cc#0X@h93Z2_Y#EJwyd~b2F<6+2gPffp z3gtlYE>2C}E)(TonIwnEp)y&fhzG%1Lsv%#l;Tj0Qmm;*VfmkT-m9=8NyiabB_v1|2DEWXGEjNiV@@I0h z+#>!2hB;Pll@H2oSk-(8d(ex-68W%vL~fTqhwhW5@-eYk*2%}^4!IL&xu1}`<&$!c zcpUdBJ%{G^1z5v)`3t!hBhv)A54u;c%ctdjagUfNpOMeX=i~vb(=3zEiyE;)9u&*v zFXbWm0+#T8C6CBoL)rIB@~HfcJSHZK9Qm?5E?QJ_HlCr7C_r_=ic2?q ziFAt!RJW=i6^z?Ed*ZlSFMPirrovTk)koc?`l@~^LiJaXYJiGT(JDs8syG#|64XF7 zNZqay)nJvRhNz(`S*55{m8Q~Fh8m`Zs}X9Xx&!B=N2$?jjLO275ZP*+a;WiYf|`h< z)RR??nt~bCG&Nn#P`N4(yPvaEzA8|&RiP?U#cGb4t4h>7RjSHVxw=zTs7h6(=Bov2 zp{iDk)MB+nEme1kN7OR4T-B%*YNcAGR;x8?t-4#SQ}?L#>Rwf=?o%7o{c0ml6!=0S z?+m%pA1g{-um;;rbXS|y&(vnMMQv3Ns%`2a^{{$GZC5|Xr0+3&h4Q%Cp?0cW>It=5 zJ*oDnU#Pw6DYZ{Mt@f*D#EbY2^&jFJ^(@X{NTK1($@A)<`lULAedLZ1>C1McfTt`Zk=_8lqlMht;pt5#gnN4LxGds~1IzdPyBszrnh4J2744;zZj}bxggi zj;mMH3H7QtAzsA^$Y0__#0&U_<`a^Icey3i?x{|wCC)SF4 z#d_?4tx|7@8R9dsQXE%j)SEa>{k8Q|HwC>b&~Bx**o557b4m zRs8`omoKpjaTtTl{UR8d)$u`XBX~_?7w#IQ0fdz^URs@kenUGUo@-eENHFL3}7aQh!yK)&Ht5)R#El z@;9Mu$ulbo78Ka$mlh95PfpjLDRIU#(s)K0&lvrgY(7&ByWu}M!LTPAPa}MCls$P~ z-mHqUQhRb)VOeRxT+h^5#TB#W&zoIRQ0_ZQI=O_OJ|!N zSBgPfs*zTz5qGLVTWX9)dSg6B5QChQWP7@ie7c^z@jlgaSQ8oK7C9g)%41k#G?w8r z^C~=tH}^9jJ=MrwYJz=)5$^~+UfYPO;*$IV&ymf8L=K3Kvt{PZnqO65%WTXOTvKeL zb=T1@t}(G%dTF6fVw#c5G$Si%MsCxL8b~us!>EbWbnBR+vWik8v_WXP8OrdLW|U=m zWcx8i^Ggf!D(25C$(vtgAERf-maS8j?Lt*-oNXMtdX8(6xu^jKaRbvW4iuQp;Swy4 zla7oUkZc?8($dlm`qSgA>-dV|(n8yK zt_0geo!p5{fRuRSIly>E8_!t%nQT7O47=e!d7xoWF`h>F&$AR*<)4{ zHThiXwt~jOACR765S3~ql4?YnY7mtg>rv1cfu3%PK}Sl8y}(Gfpjn?`x+9}v2YMDZ z(LrI+ccMKC8>6!nQQs+Q^5b3{QBpRm#F2f6o>Hoj)6{|XVk4zuqZbwHy=YETU_F88 zcw33yGD{kBiC&ayE7e^~U0h@0w1UQ7WaK-|$XuF{|1_gA(#-NPDkU|;TGrGm(+on> z%}|D~G^2FW2edD1)+)>N?AR)Fsw!NlijB8bva4rhi_Aq07-*@Y-c#k`J&uz^?@6)E zcWG?t2HolL*7;3zrW?7-Fmju2(rwV2p3#1OGdkxR#XjHYJ@dKu%-4I*LY>ToO=P++ zZ0tP?_1?3n>7`z$8L_rSuD!=7*NlO-#T=c-;>Px2%ZsS2j2vJqiKxmeDdGB!8NmHM zGG+kh08gEH#0=1jAtusz4mABS7lA)6k4T)t)#HgY!*lP&d!_?V<}Y}1Nx{F~m}3So zpMjnE4Bm6e;c41Uf6O=G&NUwy6J?|qWuzBn&>LmaYxs{c=!`Pxj56qnGU$sk=!!Dw zGUGSWk22_qGU+t^nRYY(W;zDFkw*NHMtYG(I+134CVfVFkx}mBE3qO|Ts3QvUXmC( zscXliCv@cJfEez?DZ{c2dt3{9atnKkY1iY4HcBkoD6wdx#IP~S@yD7qY`!;g6m8@% z)(9VKzBh6hZR9Z8$YHcmLa|0kL>u{tHA*zvD1m6xZu&DyB-$vE7$dzHBfS`d-WZc! z!+(rHXN*B-j6n}Rj^cd97<9#$beZuR>BkuK#F%uN{!F`>e={9}-dH34SR=hyBb`_? zK9fEpz1S%C`7LVL@R>ePuhHlzv&Ia2bPIcn77*Q{1w_ZU@So7aKCrnxHm$imxL%BF)iqeNo^5-dUJd90Je|IPO&DJlo#b$QVOc_ zti$r=&CBDej~*CfPcN@5E-5RuvD<*MSWfg1LMP=4;#f9_oG)LZi`*=MnEvu+lOT}MSWwD-2@<0zxzpAXXtg@Yv zB3s;$A{*Q(LH)fEziu(&WQ)g`c?E@rC-QEx{Emhv({9b<%+5qUtc8?WYkomVRi3@T z$m(Le(CB3qXSJBJI+wFr!dcacPDxdz^Hp`Ry-d%qR#8-@ze$anGrpuAx zS@?t1T1IrbQ@na6$Yc`d?P}3q8&R;OqhT?3t<;VWni?g>mvwTFenp zc|=7fFeAc~84;e$i11`ageNlwJeg78$&3L{W(;^TW5AOcOH^dM&e$S#c`q_DMQ3c0 zDMozpMtt!`eDOwn@kV^{Mtt!DRcf|QVw@3Wa-@4+X<1c4NkOsE1>)0viWZd@6_n1< z9}y+Rg?YY)Q(;9xUR6N_yLrqiLqCa_l~-BNv7mYuno54zLf!6t=lp`os^YTJMi<}m zf{Nm@e3~~xsL$t6+;}3BnL9>B4jABRBuFuO7L?}aRTi;7&w_c4<__g~6$Paw1+%O4 zgxOj_n-XmAFcWedGGo4GYtw5lvd=B3YV_c3I5c_Di)TQFPvQLHl9GaXWlf%a8=acG zv$sl2WZ>6Gl)bT2lQ+(4v|dk<(ebgi%7R%a9Zqb(fH<#`g33zQ^0wz0`I%K#zNmRL zQIRPbmi)5PLQDGm3hsb#F&cm_0l;oFycDBs^@bA_nam>;o;=dvsW-5w0kLic^UA9h zRTfm~m68(M&a7&x4R@kXud}?0in4|C%RTtXl)1B!YFal@L3DszTv41?h`O$tUs2kz z$+uojY;Pa`Hx^gc|#enI;4`*Glv@T=ihd#~1i zLrZ#J?Oh)JXzz0Rg^zamJsN(h`LFk*ZU2Q&=#%K`JAA?q{d%7dKNmjR{Pk`}zwpxV z(%wP%op1Xud;((n)a5rlyx9*_9p=1JDU>6Jlut4r#+&m7m8D4UQ3^*-{I%2n5bJFC zA)3x}EQiA>9LLi8FqIbE&-V_3599`>N7*NZrd;Ux2j+}$@je1rKL9FclFUi6+CwG#1A8e8!@CscYJ)%q~o9S5aXFG^f{dV zP2z1m2Bh^P{ogE}|2N%T^KGWvROY4&^0r+s%a-q24Uc;JSN~CZZTZ)jepdR!rhn6| z!Jvcc#Wg;1Z>TbT>-lQ3-Dqk!qq|YO{FiW}A6FMMeOI@C#oU+=O24r`z}&2V+&qPw z(Q`BRo5%FSZ(Qm7Vc)I$Xm~aqAH%fmpIJ9;^ZnC(HC%2A+pIoXxKsWcK5_AD@UteD z^mYFZKGD4H(ib$v-@55vsh58xZ0poCxi-&7lly;z3FE*GW7WSx7mahwi-;dF|4H9q zj(r?2z8PmfNAScS{p0dUG|bzL_teJdFBgA5Fy@%=DLyl9j@Jm+NDtz|7`x8-89i_O zM`6u>rr8`5$laBn(iuFmx8$?*MFRWXuD@e5`OC#0+}iTbjI#kenA0%AnQfHfqJR88 zmyL~O#qNe1n_c>;?vqd-N2m{*{ha-}^kb&Mg%3A{ZEiBlzPT&nb&0FxyOwrWzYXWp zH@AFGc2_@ChwSD;pV^k!{To94-%a!9LLave7rPnu$3D$^X&H`aZ>+m!>7=hDzpi<6 z&4+6|H!bJOO)`P2fBK@F|C!HbFTdZ?G9M=G-yf>^+t$L6n`>D#5ApA}wMN7DrQ%u- zroYzWFx{H@Pc%a`f4a86=5N|=Yb)O{W8^Y!wcndQ{+pjSY0n19t~}Va{M%a2u3=nD z;b#5I)z6PHx0a5pTVr2vk*z5Ho7J^z*tXDN`Zu3#31j+k4a2~liiqyHu)j9*8VjMv#!a1gO~2xq>0Azw*1ri zVtP6GZ4CQE0Xyj)O#kNdhl07jcManzqnmyj&ZG}*G&dh#T9uib)o(NZ$X5%y8SjsI zwj4ixOjy&e*`K-XxX{G%Sc^8)8qGJGU$y4fO!GhSY_0B0w`Q~iww}6K4z0g!n`>L< zkCYCVHI31bSLt7a(VtB^$!^lF`)ERP=RedHKX1YdnnJ*zQLmgX#l2mB>zam16TP`v zS(tRX#(guhnMTX^H*;_4@4wxCvodN)w^{aWb#LkKKW|UZ_;G2ZFV+3GeO=|p#oy$+ zwX$<V(TB{fRZPVD_-fsqDmqjfaP!A!%HUClXLYoT1z zY3+S$Ze}{Iy>oQ~-)(gc0DqvBWh^t_NejgtgVi@$#pXS!*koPW9e-@y-;gKQ$o>z_KQ4(Dnx4d`d|E~4r>Tc5N`rdT= zvCp3>tNoZh|6^(TPx$|-ZQ`ef`%mQI|4(t6ZMTu98ksZOmHGVtWS*tU=d~=UmU2Gu zWWFxd66SUEp2l*i0vk>QevaoYEEh>Ny&;#~dy1^UD{wDlccrG&KA;gw!8b-C)k}!L z*P(5P!y=`1f%{-{Pz>-%@|#jiIGmokhSZU&PLo>AHK2(**)5;w!u#_G)#ML0)1Uqh zVO`zEQtwdNjD-#711BJCPdro9Smdh@-T;LrUtk|r#>WWZ&(VN$Gdi6p9g^}bu;nrp zUcjZ4bEFQ$86##qF-f$@FD3ydE#en|+9 za-v%h@V-e#9#`hU7Fn-MVB_Z-b`2Bn$6g>ufL@1p*F!+=*Wxbe*hVZ4Eo2A7>9VMnsF#&>b^Y{2h8KO2jqsohX&0EwUWiZ9>F4nJzQM z2562ME4D&s%tY}ZbjIX}ZO|AqRXhYOF?r%)IUD+69wA*YVmq|JR6?K0I%scsOx8k6 zOC2<_Y!gq&N1=gb5A?3=6u*GpmEB@5lxXi2Pm%rECyhK`1#BZPl<+6AgT2Q_e$Dsk` zYw?Qwr~IclLHbX`tI&Vq6t6-5i4>=x`@~)Rmb9LTH%RM=coP~=0>s!VBe~*F&^?kbK85y?+2YU8IxIc%(kgl(C<3cBy1s!Y)hMT*J7UQkQqL`#Q#2cGt%! z*Ad!fRF*f6U4P-QpEF+O7?Zt$rV>eeAxU5W0nqaaq31c%1PS z#uJRMGM;37jqw!YZy8TBo?(2G@h!%;8Q)=ikMVuR3ydEy{(KC#P~7ew}etM zDn^ab!f0i*G1?j37~L5?7(E%=F}7#yz}S(|i_x3WhtZd@6JuvaKSqDXu8g-b1~CRR z_F(ME7{a)Pv5s*k<8H>ij4v=AX5`YAT+WiqS#k+WE<<^h{d~t*PpCN8igT?vr;2l` zICqM3q?lS2!2Y{1j&)8&*lfnf$OXJ~4?lmw$aIOP*u0PNX~zAG&oDmA_#EQ_#^)Ii zGX9eB5F_VLaQ?)v*yRZ0uNhxte2MWW<1uQr;$_C;jIS`BV0@MFB;#quGmLLCzQy=9 z<2#J+F}}}uf$;;zZyB#~ih7Aka*>KrW3(_@8EuSqMmI)xMh`|$#&(SD89Oj`Wb|V6 zX7pk7W$eV*nbD8YpONcIwxwn1@;=W2!aRdl_|Za+u9r z{*uewXoD>KqYYBYaBoISB=c3q?-=VDofJP>BHp4U5^~9)C6Za6J#aaoJ(5cRV;9D5 z9CkXNqP`0wix=u&F>3m(i_ywxW3)56F}gE)FnTh!V{FgZfw3c_7o#_$52G(*C&tc< zevJN%!+GX5g7N=~Ctjqo5q}_FEk0!YBjZPmEPaXp?{Y>5x5|lB+K@8|ix@XB{#3q+ zvTDXR-{;saFn-MVCFA$=QyxWr1Xm5BIMrC^Hefd6IBL<#!I;a)+*V!U_WnOyv+L2` z>BOdD)EF&{Rz@46ozacaoza8Qld&CRd&Ulo9T~kCy%~KNeHlA3c4qWr^k*C{MElLq zX-J5508oW>0N`Fm<`iNdo1bRf&-e`Evy9I%9$BxPkG0e!GSJZ)Nj?jN2IN*nKDCZpOWgTwn4q zo4H0XLQt+>W90IL97<_jVEmZzOUA40=R3xFLP#v26XOJ#xim0NkeN#W5(}9*M;IZ< z+=VfSV#92*D=?e!F^UH|0a*$YJc5Ys+@k^+V;SQZ;~6J0PG-zuoWeMjaT?=v#u<#c zjCqVR8D}x(GZrw;W-MeZVk~By!#J0*gmE5YDdU}t`dp>8SxPQ)wzYxqLB?&24>3N> z*!I!rG^h2`PQ*!M{t`Vuv&?=~`q&_!W%|7+{ z*m`#V{?Ul#TX~E_xk~Z6{Qf$->r(uO9NV86_1W5A+583L-x>eGsE<$AIIJ$CveXad z2PA7*$o)sl{yYoO=X=m)$ucj-p6zIBEb|JMc?HY7SZgA8mU#usyn-b=!IGU|nOCsP zD_F`CEc0S@mO`r!ohIkb5cLMcyab4O z3Gmm9n3uqec?s|+<1x?{0u8u?#~EK?1g&s+mGLCwX-0hi4EHw~-(q~5@g2tZ7_o8- zKUld1e!zGUYhXfrOJ?XGCRB_XqlFPG&v3`eGY~7!KsQFLJj0BYXCPLdf$bQv@(eRp zo`G0-20~H+V&xf#m1iJUo`G0-24dwIh}AhDR-S>FVb}wugJ{F5AnF&R3n6nyj4@;` z=Qdl(xRkMmv6gWI`@tLq@oeEZ>lk-3V(kN|>}5R6$YqYTHFAHAk;@Px4W-31Ir%Z0 zFLV4~viU0e{Eo4nP;n_KtOuj7aQP@MAFQX*TP_F1dBmz3xpZL+qSzqIq0S-85th=v zw<>3>V60+Xz<7z{{~toJ>Az|QgB*$xB$@tK&G4yzzfAQem{*Ed*v#u5g4aF7Np@lG zDNeEZw~YVFc=iX5f%&iaBbz^B{Fw2-ZM0*_rcJ8=p|qzf!x+OEdo%W7)K>>?Hpeno z4Nw=7#|HWRD^%#0@aa0jaee(8=3DL*bDP$$^qJOUTx$qYgJvY!F?ut0WVAC{89f=@ z89f*Uqm8ixqlHmpl#J~e-GBX+kD#S$A0-uAgw@-;_*tNI_2tm4UxB@fB)JH`q0mQv7qsgyhaUPg(n1eS`ghCqas=&Q z$Wge1a1%7=ZAIHUni&&%k z8fbKX2XUQ+CiivFpz4Z_l?lu{%6Ga7wlVXf%f(*i2Lu*+rAyU7FXqC@|x-< zABV>EAo&XR85YPBw38suKyUdP`6g*Bmv3P|;c@v6G>`9;?~&GVd5-oL9gwd65xCi4q__h+ zsF|pbUR)o&P#^OUYbkzK)Ji$xpnWBU`l%4%sG<451^D@+o|XWY;^&23r@OF!y9~dc zVmWr8JfLrUGj>R~Ku36hcm%(m&=>_@cCxxcZ~qnS8`FMP5L(ASV5aub3GL%s>s3%OBU|-q5U!o+Dx`^<6Sciw=Lj~N3@*DxPgXt&^&kt%>%77 zS6F!;%@^%-Cf?F+nlH6fDD0mn=OI+7EEOHGzgC7&<+5D3qwQAUE$y}Sq!x@&OXLzD zZdJf76wBpu_^&~iQ)tmEK<8??8gJL&eg%crcsFuKJ9O^2U*R6Oug5J53T^#9q`N_G zz^RV=<^7-^?H*;aS#Abyfs7$}FVBXy`VjK_i2ONRXkRY~{b2{pyW}q56Y>d^D(&%k z;(moE5q6LKg=jCI!o3PU=r{Y|2R#S)oO}+H9KgK_Qa&$#3G)l`1%$$V3MjW1<%_sg z=%_r3x3n|Z6@BX%O8XW03TQroyA}N8tJo#%f}0giBIZ-LS3&Y#VG!NroBiFJ^Kpk_wVxWaG`xk zcl7dqz)ZW7?&#}R5%V>94b;}ldgOw3D!pZcY`_U0bSn|cyOu$?xj~73xV-`Q8{q~A z++BoQ9IPS|_c+)^Z`|bIEcoUHJIz4eWLLGAPxO!ap6Q2?t!Ke0!9=IXl7sARrp&q;w>dt$h zy^&qi7kGvReVKSvSL|IYa09v}fqn`cDjt}Cu_BE5l$H5ZICj`3;^qVzE0n>HhzI#H z5AtR1(~-GP2j)HhxpEK`1XWj2H*KDIMiwUr1%}E^uYZtXi4H- zaTezH@RQ;kejd21E4@TU)8CJxn&IaKFn9O`f4E8G=Be5$*_r@j$a!Doq2 zNu5uL>zJ@uF{b&Wl>}f{-kW(=2=lB+=2?EsvwXm<`k=ku2Ck$rSMp@8)QP!LJLXD3 z%#~~gS8`zP(T#bNg?UqZjAzr(=V?d319Kw9_rJ8qoi9aj*ZC1~BE_7jBXgn-E}Tf` zK^?(^mLdk?L4nMJIxr8iG7s{?%`R)f3y24GGT`yMVM}EwY{9O2v2l&y$;L*g7tjv$PgCEtQ#2%NAqr`TAH(B}QfzF|<%%MV< zLrLaP{g^|w!_6;y5sLU!C-A9f5Q^@6vC4zsO;+Yj!MN?^F#Nc3sF!ed!ODEf=EA2u zaRUtQD(2G+lDU-+bF0qGtvd0^2FdrqX!0~Tmz6nJcjjE4;9O_mLMI+f&h@r@7d4B! zVc>pFod)LNgt?U`bE{ySy|97r5YOs{`)Az50J?()F2u9?G0)O)8%=w-5a;T| zoJ+&aG`Qam{L2q#3;i28*KG#pqSH(kx<>}w4L8V$K6Hl+xJ<6f1=1;v0Oo65n6Cve zU+cnrEr9u27v^gL%-6awUkhNq)`j`nt<2YMWxjSR^R-|XzUIq(Es%LxM}wDrsy+oJ zxZ#9urW9U~bBY|ou0Vc=Yn9Jo|+fw^wi== zr>8cRbb4wlNvEf_hje;sXGo`~_BE9xE;F>@lp3BE{YFEnNGmDqiZqXs`!d6Bz7I0& zff!lHU!q~3VAw+pyTy1a{b`wl_ipf?tJ}@=HIhUTkG4*KLUzDFjo$EuVLyY>16kG5 zv643{5$h~4W338EDM-ljgmk)5 z@|j4ww~@?rN>XA(B*fa25j#D5G6f1}Bz-xKq1J5cZ0lm{2I~&%A?s=Dht{ubHd|L) zge}E3!8XUX%#vo?WSL;wZ7H%Hv7NDfVp(ka#!_qdusmuHv^;B%vK+UZwOq1i*mLZq z_LcUnmaF!?_M`4T?tR@3xUF?NZGXpp$!)v+np+3A9&T}NBi*LEed1Q(cFpQx?QV^* z4#l@OqpX+xYoZhmfoZXs^ijcFyPZa3tiHD4ZW^5xkkUyvQ!Py_ATt&X`9*@7r7mV zTbwtWMJC`yz3ZG~G0dxvKJR$`;-nyq`Y_#TDZC7VtQl>~*w%-;5n^?IW} zWjks+3inKxoGRO1>qWRF7;coVvTe0(gWwduADZl|mP z&HPc=gVs;j&8Q*ETDa9&PHS5I58*Vdok03&468i~sRMu7rN*$JidJ*9gBtn{;=2|3mD+B&F3`inEr{KU;5HL( z$Jt*Ga+6iCqfgM&qy_6!QbR4#({!^eh8x1t6KWFm` z-YCrX$Ajun+{`%$&oJE2c{`rrxTP}@&)&GJ6RQQd!!t%D;dvYG?HqzzpKO=Bvv4w#LOMH zw&KRt=P)mabo~SI(|w@#sRvwWlIs7V?P>s`Dz^XJyB{pDEFU5wA|j$9A|fIpBJM5= zA|fIpA|fIZDk74fNJhI0epF`WGqo}^GBYFdnUR?pna^it{>_ZcOoGd&YU@O&Y3e4@EpTV;yx$SPuOwkH*>kqdEDpI+-ENLna6$3 z=RS4Z=S%bx7ApFAi+-|N?lXn^%;Y}lIKeJJ`pNX5pRi2R|M#Jv;7j`XDgA^ki2k3_ zi^2Jw^m7dTb&x6H|{(YKV!u{2U;_sMZH)1Ui4g}^Y8_>90inQ|Za_7<#B;K7!DSZiKSJn+QWhxa_~ndNQzhK2Oz zS4Y-ZDT%OZu*axyM3G>%;Et7p2k8U8^CJTwgXw|j-Qe8_#4kZ47{7(U=hPFuqJotz z0>zg*r?@|Ch|zc=hNR%sh;)>ZI9@x0D6v*wihG|SMc5y+oUFj_t58yLTJ*o*fqIp^ zh0{*oM#cn-CV;YJ_jAo`+f#Jey0ot*o{1)sQ5qTno6?*I60y#*y6)Jttu7D5KocUYT3 zge%iu`fEHWXDU3z12`}D{z8AF)>RXfViJnpxLao7&~h`2v6{R<*5GbxAEsqntMWd4 zSEfRF;?ZS2+1gT$;LO^#h5D>$Nie?{uYmuOTa^qFf;f{5tX119q~#ZSDzK?gUt8e= zXvtG|6WPQ`aTBdm$Z_s|{;5K6etRVtztDF};V@1IhOY}nP41R8u(X?ssqTmW-HS7c zO(h2sr)_b-=%yu(9Dog646b$qZ@hq>;<+tU_?rp4JkK9I--P0>S*Ys;@Q@Gi4~FOR z2zq}7dT$rttzx2a{<06*4Q_A){**53@jE?tJRiNf7*DUkq4X8_HUSbOO@OnSr#c7Z5`Lw-9aqhJ&>X-zDSQL_CFa&$(VnMJqPpu5ZY7 z$U45CvT;rQ^@Y&X%1IXdz_IWOi*c>R=e;i}zDUKX=m8kR-iT?d!{2axKIpr>%t&}d z4z;Ob6Rv#W|J{Us+XPQ6r5qi{Tk%~UB!3yoF7CUnZJy&VsI*yvLOHbc|2H8X00lE` z6F#Y*2eO9oLp{R(jpuOI^*+#1!{Ava7F;n4N?RxgpMcvkft3%wj|Qz4qK7lkJGtPg zW56dAT=FLn@BxnJNg0j21&#O@m1+E|0$wA67VM#y%rf8?2W|*4He-a*yZiuwzQgeL zB`3Lu_JIzEQRp7dX0n%&kqr>!l&6}QSUg9_Nmz`<%`B}FMMh;kMh&$m!nd{r2ZwRf zg92RN2ctp_m{dohw_~p){lopA1uYQIh&RiKpyv|yK+A7pcr{J;Nm$bg8VluC_gINM zaSwkNJxz+*EUk!)!snm>5`PDfq!4k<0A~u70aOYRqn%Jlj0DgDg#jl~2sB=gdzL=O z&0mrl%w%{;D4nr~A3nnj(B&|6mvC6lKf(-cfIgB1KjgRURgqLQL^NKsLUd4cL+mP! z6Bmd-6#p*iElH8QDEUHiQyL%*k&cBW^hIf@^harvmABP&t8G>vSbc4E*6Nn55A1;R zWbep6k^N~MY`w(#p!IDVg-u_ZQ8wdkX4vH0ylC^f&HFa{ZGN@+!`8(%+;*nzYqlTR z{$zX6_8++dhc~I@ljU>etK{3|-^g#1C(?INj+K*lA{`cRE!$_iQr-OhDucJJaI=swMTo%?(4hutr^8@k7I-`xElk2H_+ z9=&>O_3Z6g;91dgP|r19tXIC*cfES_%IkI7+uM7U_l@3Dd!Ohd=@Z!JsXlM?Ip5d0 zZ*<>feLw5_b>C(mf1F?Sw$HhK9{r~Fd#m3q-vr;uzOVQm^)>X5>c6c28Na@Mll=<( zjt=NQplHA)|4{!N{}TUS{cHUj2FeC@AJ}`~fPt!k2?G}oEFSpDz+VS82Y3Vw3YZWu zHDF$VF5r!Tj{+J8^&d22(3U~x1N{T@0^bNcj_{V@gBK0n9V7}$33@r`tDx&cf`;S{ z*)`}Pu5!K;7;j_bchTj>PG;+Z9#N+msY%o<)%;8IhGw6pN^@0nUDFt86=@&o64^a+KxBO6 zTaoWY9*z7p@_LkARF9}hQRz`{M!g$#HR}2(pHXR}vPR{OT0H9QQPt6I(FxHh(a%Ni zjs8CROmt=RwdlV`D@QLM{jbqGM(-PaW%OU88)5=u#>cFUc{k?Un9DIuW1Po?j!7Id zb4>1-!ZFLotRAy@%(gM##CDE#k5$G_jLnWMj@=M@B(`C!@7M)n-ygesY-OBNoLk(0 zxFK<2anHnk5ck(OGOo|Kq;aL=u8zAFZy)a(-y?o%{F?X;@!R7+jNco7ApYz4f5s0R zUo`&3@!yR2CVZ7}G~r~z zPYD+$beoViA$!823EBxSPS`M^WWt9N$|qDNc1fI@xG3?PiPjUxO-!1&apIwg$0pV$ zxg>cc%}JV{v?A%yBr+*v(#%O4CvBPZ?xgBu|K#-KSCijL{&BLy z^;GK5sg3dMV8{txsA;+J>}kX_uziPn*=LOr17sTJAL6 zw3nuBoA%MP{nP$4?T2ZB>ju@Khhhflj*k8yH1}mea`d+)0a-yO@Ds+ z%hO+-{>JpTr@uG-@bs#T9vKN4Gcx99EX~-M@m9w789!%S&A6V?G^5{)pc&(4OrG)L zjCW^zG2`%z?`NEyadAd%ra03!(={_aGdpu(X2nyZpPKd5nXH_wU0L5{UCO$a)il#~ zW~Z3}Gec*_&73$hZRYzk&(Ct2l{xF(Sr=wC%+8;^efG6%@9gyKZP`C$|24;9&Y(GA zbH>h@IA`{pf;q)=UY%1iXV0ASIp58>kTW1BF()l2H)ns&<+*lq-RBOUJ8o{$+*juw z%~j-f%k|0)${m$EId^VuQSNKGyK}$E{XX|n?kxm3+0XNs7dTHdFKOPqc^l?^KJP#C zsu1vGo7X8XGVkfUg1n-<)p_fcFoR$w>jT-YC8a7TLF?IySdEe#6f2d<$wW!k>xxyz zWyWP%QCVhYSrLDK5bjq(XXuloB3nS)GsybdwS@~)VnRGU)!f42 zMRrDeDA?b;DIXFSmzJNOpB5K4M1J!DwWi%$tA?+Y%pfl_-DfDtkL@CQU-c1~<2En~ zM)3eRh-P)^jPwV>i-nsWZ~7r31|`{W4-}a)ImY@L+R3%@MY5jBY7lC*%`Ceqr;SRB zlk;?)+^P+!F~eFYBb_1na?ld9sRQ&W@?=9B^tqm1)e1su+KXqn{L?i{P2NNd&ztgR z$GF*cw#9+$eY=_sbUeH#;mkP1dv+!@&@?xa=drGT7jZh@L9;uBs2#)RFRsnkYF`>VH??GJF<`A(xut6$Bi7&xwD$QhN6Ym(hj$> znVAbUP#Ed5Y!g|_B3HwxRyDAwA%YoBzG3Vc-94;wcgWcYb=^0BxcVY#eFlSyGU+{4 zNa&~)kQGs6=>QfrWVP^|4IRZo?L`m94!yUHabZ&LsrmufrKCKdwTtg*?Rc!tbg=By zF};~ycuNrJRRXKen|L1}pP_t2-fkC`m4NFQHB3ai$qu{4V|q2#G)N=-yAKYJh-^b_ zo}Zqj@ISIrkr&DDUB-@%e0t{O_}H;2$y09EH4X|L6`wd^%&15;81rNDUb|o&1h8RY zvFUkvd9&i95X&N3KI4`&FOsk}XmC^=POxyQHozE2}-WvD)G3 zxr4s%uVZlg{d~7GT6ZolqB;098eG&|=93EsU@PLIA<@xTCAlI_3=2!-*#gqJO2-NJ zB2gLmg6D^c^ht*sozm49!mpBz@+FbZ5_^e%|NcEYwbuw@PWNzl`J;A;uWxpCdsS(f zWy_Y|KjTctbFxI$fIfZt3?7>vh1L0b$bl_fSs^OOO-WJ`z392j_NsM}N}c-!sV7cQ z6YK6FF&WF2Ez3@K?<~Ea>SN$|b>oFQ%#L``WttWL1(ovBAx;K^!D*TXT#W&UqLajo zjv3t+GNVieN5(gOPcr{kT@mT4`$AdGHj7efW0isG{60`7_lI+y+IL`piI(v`! zwAk3#8F>qHqN1WEB?c==xlHX?zIN@}FO6<00uzRn+u!@vty}kp8-CJ~XkC%*`NJpv zTU~!sY9HX+Nf!Zw3@xwPWvRQIC@Cq4i;MHTaA>vKm`DrHkK+J~4I124Z_{;fP{7#K zlASk#GBpq(hp-GiLbh9H2Hn_Mk~%hkr0R6y=4QBY^dd*Ms_jB8;^H63fM+1KX%VG( zRR2}XaU#uBM%5ohqLLgj7XYWySOSGoN@gTd}0Z#0>J9h zr+X&{|6a~)U0vO+`r6>wM9_4InLwSJnus_lEiFy$-=m9*vrE(nKR?GNGf}w9&Frgx zKCL9*NCpq=Zzf==Aa2bB#q}TT7DRgP+`@%s!Vp#F=U18ufNx6*Am|i+y}G&fjZRNb zkM8U0*4s}>_AC6lIJs2se*N{=cm3|-7imnzkV+Pqn}?A}VK}9vczDF9h6P7v6&4m|MFxjN#3;!bMa+PC5<g0K@6yLosi z$v#o~xz<3fgt6AD3Xa1bPy?$yld2?p#U5@*9C#OPla_LC4bf;fyXo3OB{|Lp2l_`a zeaR=}HZxa;rmCpD)AUyq2BW*Kwc4lW#II=K!ehr&;GvxY`mgEZydvlPGz@X zBMReD6amFBHml(-O4=4Ixz@!1H>L3z=7&j2@)6s$vttDGnFVlx^?ww0P#fC8E|0di z_*^<@Eb;PiTReGbBt-Nbcw_HC|NlT#FlW)62+Z8CpsXZI?*jyK6q&GWN2O>7GS&Ln z<-bl>lFwXw_2@Qg#K1mYy#o9PeSi3bl|%PFzWsW3@AixmOOj{r1Ip9hLXGb}G&q_{ zfQ1en$4G_9Od$o~T zIXiX!WXGOAZZb9sI|*Z)Hg|eEARew;-3N&45ob(D62AYmB%bzNJbi1GMh%lz!uRn^ zN`J56L*4bFz9YP{=^AdG_{1;HRHb=`Q)rHo_Z%{V&b;`-*08XgIXO8w>h2^*r?b9s zwT^Uhge3ba(wJ+UWt?W5NM{rAN~kx_s-Y;BlAShFE|-@2`VQ;m*Hy~%;3~lD)XV0# zZ@w8jc5pApfBt#)+03xVfPbHfD;{ZjR@EC~Lt~z+|z&Gd5XJwuL@2bZj2*)*4W?G#&lb81x2=F?MXflN+ta8}3>yNz##0o@0Bo8P8hH-TSmEx(uWDGNn+ZORxctYmv|WGq1^j z!r3I+fRYKSUn_{z3q`GJs2@|Lo~zRhR8k^KYTvm^azV%apv8(s$0_71dAOdqhbebe z!DV=pO-o5?b(@K0ggY@(TUt)k(BD|L0O2WsCi2|jxkJy_he&#fm>bW;32Pr79VWk$ z$LPVoW;O7?Lc<|!uV2S0$*Zl<5K)mV;4lJrh&)BT@*>E4P!ZoFE3GGbckaqK(M8^ZBO6}GH-Rh@thCh5YPD?kM63X&EQ*8u3hhIR5I&Fs3rolz>RjIm z*sEIsY)`rhcvEYZ^K*-4rlm}ol{MSCSvoR$Vp_)Z$#iM`F{=NhRaFm{qI?TRQ#vI2 zIs$pP(`Ab_{R}m~R8&+%ack=hFhXnuo2`V0o!YV_27`-#N?`=t>a=VS70w==VB4%OF9CW)KvW0$&Xd&1fWuz zQ6fr(!f}HQMcJ3U2J8f%ft~n14t*Mzme||{oyW8T~s($D` zGAonb&Qw%Ha^_eca*-61Vn(Y{B1ds8a5Y&J`Tz=62-~dOUk?pkyVk>(dxWgOyPV)ACI&a|)pG6hL%r+*W)$>7RA0^< zIijJ_EZnW-AlwRpGq z8e@)@xOOUNOT9L=OhGNqsR^3lLqj4XqN;!X-Mx3<@R8xcfdOhnnry*R>cOpf_=szZ zsRl5}5jCX;S)mB6|8@7aZJ&L9@Q0?Rrt`Zv`wb5S-Lyidb5NXEwQALxbu#*DK6&J< z59n1yk>R?#lCjhN9IPbonh&InwZ>dXR6}Do)Xi6tW0If%KWbet zt3{?M#$;kJ7v3TYucWCEf`e6tg+wrekb+ynEHS^Ct(T3KLSJyVwPLjP$`uvS!o6a4 zt4*+}i@{RZT+4Y|5er*U1RMh|5hD|6IdsmFE!h6drTd#`xzd=&9F2w8ktl4W8Iey# zB4X$&xs3NWWTPl+()3BN5K5nYcEM9-6XX%gS4(O10qq}NTkZmFdE%H6K>>rp!$w{> zb*{5V|Dcee1N-+=V_CbAyl6hzEL`haigPw_W?Z3%ttD%vXU@dOn@>EGGsFUry!1&2 zOiWDh`I%1!&UIojBd0)ydXuMC=;={;K4I9shSoWKEj?{>NhY`p1Va%H-z_gmCH}8x3wM z5oWsQfQwGUDKt)xO%O*aF&~>KoTfqXc+5VLW>OA*GJ;?!!_Upz?&6_n#T!q`yNb5d zX~!ODF(>`|F1D6(a_7tmqlX9j4-5+(@$1R6o!t8c1`ip~udf=m%vZ_tPsCpj*V}kH z&j#k~v$o@vz$-pxX!@u zI#FEQ?CdD)UwIj3Q(6#@FUp=hHjWxMQ55Q^(NVs)PMtb+%NPGsV`-*Uk{5K#U7D}| zcKW}cmhPZ0f-t;<#0kNM(>tS#^I^eDM9Nu<`Y8(2yc zHC5_})^<*6OjlC*{`yr~t@f^7Ep0sHlV)}gGln1~wkKp-O6BwxDr)Xhku8j?=It)q zw=Z4{nmve&WU+3!j8gHlttC5l6k9)vhSbZY1flxD#`qiGagPC#llT_FT?n|MQgu{} zid14=5I;6()56js=yW!)lFOZfC#TBgYHFE7NqKA>+N@2@M1&hXRIe7RgWMgQ)!0Mz z19`6JFF)7&D*?Hi&(yM_EU{9pI=5ApH+NXai?FnCM79;ba+sAsj-;DlIqn;@(R=ADJA*oe}OK)_Uurc zcT@h_8xxm6<22Vweq-h|O!~rzz&k7R=5<41{cHcCtpJ856CJg5kXcJ<0DI zd+~qK3++TSbX2$St)uslmPkg7!rb{K`44>C`>_cNMTY1t>rP&S zV=`i}SL-w6pgWI<#~Ot4z0Z~1m_^^$>5w%r5>xLdun5qyS{B#O>*jyT-8R3XHm1-b zUbnt<|3RIkG7CtrN5%}Kk$9xnho)!~m3s#)ZfUij6?dkpq zC{ojKeN^RK4<(^)MkeDdZ_=YjmC8rd-V!qUNaFLjQ$LVk8+k;{yhY?uNb|MQ_z~%) zw;U%us!q;0XI`Cos8eKj&0#9lU)GWJb_>;xNM+aG$H&9r5n$T2beIQu1|XAxG%Wai zqLnY2?5t2I#0GnxM?keRl4GCj-?Oib7|EU6w;$OdTz}6q2bM$Ip~ep$8bfITNGl9L zLf3t~u0IEG#Yc~(r(51m&RX#}ZOt*Kt)1Gol`_@iG?W@7c;0-aHB`I1z4>^orD)sm z_6!k^Vl=Mrx3tErJwEelOOF|o$Ed?c#>R~Ov$Cd_-!OGl|6x*3}kD^~E_>rd}!s70J16JN)Fs-U^-WEx=l*@?TiQm3dd zV<7m1*Yb$qwG6{^O4DYiM^wN~vk$C=&ic$A8x<@L)#CWr=!YX>n(6MTisSVNT2oLE z_3f2PZr;qvd3aSV)7pdT3PoM4l%flRY{cswZoa&K6 zBq%m`C#a#xI*}Ld#o)Ze6OksG0hnmU2GzfEonC zmbCK_o$~KK#KRg-DXH!qslmkl4RX(aL*AD!i5jXJnm%>vgvbZBx@AtcZ@cT~Zq*zW zrlMvgS>EZHxtZzHb93g|v+~HeDVeioPMb1W4GsUl?KSQJMpxUr8z}C9f^iF-odz5r z@FLQfMUzA@=~x;ZA!4f8!&NP4_q|&pGx@tCK;F?9mrUEoxUl7xN4b`Spe3Tsfx)3l zY{AIC2{z0^NUR1Rcu;%5c}H{zlH~RV5HY9z>s1K;+a<^V4?*pX!R~5gq zY109vF<ks~oN0iKG6hJu3W!#a?b_per-9C5za%PHm_l3x!Wj*j;Ckl(zSpFeHr zjO#a5cX&dSdF|M-QIYzd##Y+?b!s z%QYH5H*RC}l)*o~%#7-o7IEY9KF}?@ggc-sIO%l_t*{O3di~6q)Kqn#CtcAZvR1NS zjNvy1Zj$9N`!Bb9YA}1_&JFjjUG16wW#i1+jobkZ=Xj7o!-?}#Q^snPs<_y3e^u4? z_8+c^9yN0KFuGs)J@SUFx*v1pN={CKI>6OcjR4inq)0TS0}1ei+nzg$669@Af?a)a zmXef9eEWEHU<*x}W(T0kaqCAE(>2xEN^*$x^YM;gx|0u(ifKkiia%3y6z6+=V&TEd zic;X+q4G|Y!}pgM{nc@j&eUDPdXjqGmByva_Y;-mL$*sN`v~$Wju-iz>GwaOH}ubr z;*;}~PwwvF8V}d+T-cP)GLG27??|r0y1WKQp*)ZG4y?%EMFNGFIx7)68LVr?kP>c!gJv?g6*bd_c znkz-hvTAh)BF)*@o}AF!oJ#53)yeqB#fulO+j=Az7}C`OB$qSlWUG3(~^+_UYS~d*e?BHpUD)V+ZxlF|^7#IZioraFA-G zy6VRZu08#S4i63V_oJKOUMFiha@u-;ZKYLmiVo|kGia0i(yw1`-@bkS|DC!}Uw=_; z9FC&0ey5@-G$SLUTg5vn<9Oo`#m&Y)s{)LlY- zjT$>KQADdxk{C4~nIc&d?&>UqeFNTTyQzNm|M$hkniI#q{Q9CzjFM<|wzh`G+g4rs z2PXL5+8|g*#Kq-xzh2d&pKtt7x#QH|&T{!8oPC zK)073AV`^O<9cI1QW1P|MKN?K%@~3rDhMO#z|?TZ(0oTP7Ksf8V-dS<9dJU%6!Btz z!--XDV+Jka)jt^e<|)Y*0UEW^Ir#RnyF>0c_Vb@KFQeqs+rFt0sFfz$_}Y50ul=W6 zGL}pr$*5myMgIOr&z#s6X)H8m({v#yh3qjhE`lcoS<5a=3*zmg)Jn(3o%4dR+e`qw zsm3xWGXO=jwvVsBk{ou*xnf>RTB2SogS8B>dPj{I91s@~+==Fa zZ6`RzY$SLMfwoxCPdj0^n|Yv3+PQ^&m(^78V_{SxwN9$$VF<96BH^73ulGLT~&>}WI?#3H@qPBZvkVD-Gd zh98hlhG+FvCk+0GG2EhM)~#E?%~wwYj+eWK!axjm?(SDtZF=*SH;+{R-@&6-yM=^= z1oU$MRDpQ^Dv#ATBOXHb2}|L5{1{Ci#^``!cs#4M!Gh5h!8!TM91+ z@I)K@0uZHoOgz8NB9M0l!Q((}wQI~WsHSKUi)mXxY0Kx^V3BVlg6RYU%w=Y>WrS{H zrLY(W8ucozsL0JVv(4iAdVY5u-ERht5_aJ{g5dToY$Xs&n6EerZ2W71l6=b!88jdQ z$A`kv!i;)M3Q)U&#T0ml_QLbOA(He9N#9;Qo=Gc=B;O(ii{@RfBD+P;A=_pI?0_^^ z*lJOsnRMdE+oM+h79h(>JnFGvU%E6~NxtgRzi+Q`kwg7``-cP%`}uf>WX*B7%aDA;TFufPoC56Rti3-H`3!P(5?#L~QNt**kL;0+m7daSwWpk-sj_rXcJrEO z_wK|*POZ326bdW7#Mv(>s21^QT>4g4P5!Osmld*?4qdrHf({-G;`Jx$DVJAQS6`^C zlc{HArln;@z@J<~i%yi5M$&Xzsa{udveIaS9p!nnh@L-2^g6hg`M&=bY7hr{yLBQw2WM);-eMsB3!F^vK zF4|Obs8(;bZhF@rC{7yDxw)BJMT)bMG=5m5)7aXLl6f71^nLEYj&H?wP?-6$iwYL; z8&*>%PwWu9TUIU|Npzkg_5)vz-lBq}!2#U=WQ~oDfgOT(1X66$To5lvpPer-FJ9>>W2|jB0Qz4BOL01dQb^J2URj zn3N0{mSs$81-Ct`bdhM6hsQ2q))@r|9hp5T2=(d2wKmtTT{ES)UAFkzH7@279I;8K z)xa%D%O_;Jj&bd&YmLqD2R$w1&K4neHhEwTCKll5DtFX@P}FFQ)^Y?MUS!sh9mWcJ z1^7F3Yxw>R#a&iDKK==d@_l^xnQS+^xc$f4Y#0*icwBCF1MCRK6{=h(hYW4TI{ib=s8oUDr;d{oNN_}rtXt_g6U(I1u(Vhxo7BWh zw{g-u(0h=&{%7vtBOvT?h`|jSV}W3FonpPBTrM^=H#h%wrbuO6Y+S5kwiOAwlg&%z z*XsYqZ@+$fzL?V=Q)z1-M?gJN_HwWV={plpgq%H(1x&()%RWLB@&LJ3%>_Ks>j6O_ zN^-(_asA`8uO+n7e5iEydfR+Yvbe_qZPz-P;G?FUR;}Iu_zyil;jw7{fF(ie&{(s` z!;ky|;OF9eYwzaG`V}Q03?}rL$DxnI+U2X)8N^LBRW&TD`11|(NW|kX7C5j$gSzM) zT?YjPkI&A|9zQhbk8Rtw)dXSP@GfueWS5a_onB;w^;j=~Eg7e0aY@M7Sc7R5BGR8Q zj7AJTFZt+c9qd9jn&uBQt8z}@SOS5wgY&T`64>_50%DTRmcXGShuwTLA7RIAXmDTz zjxGHRnV6n7uUW0_hn7Ii22@B`E@#gp`bM;jr-B$%KreAt74txu$RW(XTuXWT7YqAW z1h#)JCx0^|ENm&=VqgKMY^L27AjGqKca|B_$y)mTDRM$u9HgWuZ~fB5WgZSaw%Vv&8uf^hGy8P@f9-e-Uv* zzVS|H69#o5!k8aF6eGUXfY0V~ed-ttcP!5_+A*-1Sc5QWVyI)65;w1;P`X^bs=@+a zXI{H4;7@@s=^jvN!)~uxX7xH39b*x-mZARktbAsHY)`AU2n#ym9U5}-V#7R$qoa&8 zH~eK5aJuL5gT4Pg^R3*;T0&ThU@o>Crf3;2)wLv;+iqzwXim@zJxl!~yp(&KmYX(S zT8x4KeSzhzmoB4x`1nnSY~<(1O@Q5+=eo6ux_S&IXyL$aZKJE6fH$bbd#D}tak}gQ zs#BM{yNaFw+v&iTT_l16^0~DCXU3<^8agdIGtC?{oW!HMKcy}%Nl9jbptkoS3uZ%V zDN&NOGFRWMLkG?#XpkvzAKc|;!LqGN$tgT*@F-coHlWVTCh<~y747S!*zh5P0!NNe zR{rp-OAo&x!$Jc5eAQUEZ6d49L*N0u+bXWfB8;$}C3L&t6=7#+CN3Ws=_9NQ&5rcR z&4uRrs7RlAfCjk)quOJ^M5H+W-4kN;2*4a~SrFT?ZCiPHhNZC`xw(97M-**eg0Pa` z4h}nogXngnqv_$=yUG8NN~HO$pzViQ5gDy?dRbGG)WzNU@4pGnK|9_!MXY_R(!p6+ z%_gG0ySbGushC&$A6`4vF+{tgV&YWfB7*T`7GZ7*TX;kZo&pRjcXzL-**Wg+{F#f} zpiEoRlr~n7cENG|Oy^yZyA_SZDJNylnf{lMHe~bRszxMe70Wt%`3@W$LiZ3B|KXn< z36+wT_n>;NwVFK|`GEq6nkM`9P^Qcml3Ce~bGiM~mu0&?{?Ey(zx86q&{*-d+L(#J zv$?h(p1tnu<1;9rpHF9lF!SjEpB;apw-T9Lp9~FaYKM3{R5(gd`wv>mDx6#pS}#dF z`DEzGh3%hDfYDZ9 zqlL-0vhXOZ;l;P};NB8aDzkf0J%1_a;^w1`FWVO;e|J;#vADyWa zEqo?tA&owH9ddwk)p9gf;d#tdbh~i-wb)i9CRUI~)TBX8^q3=>6w3Ip$~eno`<3y$ zN%gVb>R|)@Vnzmd*x1-ODr5<>@~CmCeKg%4I6@wUH?=g0LPEkbRIpa8VnRYp8JSi* zq!FE3^VXvv!~uf%+SjEAt6H)>z1C@FM3nT~&&$gd3QyN_=gP|q3*ml~Ha2>WO&eUN zBjJ&lsi@ZuXIzr)vL)f&eb0AsYlOguA$$c-BhE%P?@ol0d}3bpHk9;cg5bD=u5cc7 zM64v)tme4fdjhN_usL0Z&)sf?-0fxov=ai@EP<1OHZtDcTv(~>;>FZdvmhx<*|g0B z#rGKXf${5AGdqlCh_DC(wROlYzujrFS*@_4QB4-rf3K~>zSX+ZERZcLP3N{NO^dL| zMJq`^6^^Za$G%|R1O?pFhDK{Ivk-7@n{mh@xX+jc*ZKaj&5u&*VSg;}dfw>4jY)dO z6X~nM8NYAa zaQmNs%;37oEW(W1O0?`Xj7&a@mJ6;Cce0O3 z!8z#2>Z!%{0-YYm^$1)-{rUKP50lI&$%{!v$T=z>%(EJ&C9z1J<&Cp~yo;1Z zmtsz4gy0$E5n?(`Ml|_D9+q<2VcQCLUZF86%nm3(#bC`Sb@)Rnu@=+-@}PQ@v>sny z6}4W7YHBhv9#WBwX_kLrO*B44WcAhHr4Ok=N{7V*pZ3DjTIQGm+1c6P^*KtimCe}@ zj4LgUBrHO3NU_p5OR$ghq>!#uU#W!~g$)l!;) z3p89A*LE=G5@oeK#$$~9Tu2&K9+>|?Xgu9p9^oL3!xOD-=89Ij%L6NE(N!GU>MEpd zz1FB#%UlQDwZaJEBeP6-qKr~T?x1AkjGqHRf~Xv@%XY7>NG^Av zw~74xh=Yy~&_EWd9Al22I}A|Z1xjtDF_UdFuwW8KdEowMTOuvmJkHU;y-f})_9RYz zYlR-4!HP$ar?LdlbU0*-AH|Rq_r<*Ntxv;{cN1Da8qYWs6oiMjA441+tzyKCSgT~j zh#J<(u>O2-KrtT;M6I`^xoE(j*QaJcVo}PBKSAM%( zd%61R<$AG=r=VSQ<1)W-j!zLQ!f9~m8DeW^=cZ`7+GEflH!U&ht&GIC_QyXRc`8XM zm1wUDeMEPg>F8m+>$#YtxUsXd3pKpF$LEXU=dx$V#UWTvP7gM4$GHaXt&cU}Pe8Q` zz$D-M0u@wQYh@0rjJhn9FgEu$4`BJp?YqWex2wY4Y9|8wH_k;6xi z1q6hKMq$5dAs-iKTxeV<&YQQOpiqqgzJ_e2XU=K)&1|c!X2&P0e4SZHbTp}0Lq8F5 zm24~!of(oiLj^;{0p8cex6O3&Z`&(xnh#Ehf#l*KJ)pmc&L_1#7+1_?=L6Qv!ebDi zI=;__19z?3s5Dk17v$;F+`da@cOhmiCi4aU>hx(PIjbd^IxRhM(2x6v|E$J8emuN} zI>Z^1mA#OUpJrNr(KRn8xfk+d+YQf{IUC2c<;@ryZC_hk86kvk$3Zq%fA#0KanbDl-#(a~e_aQmLUJ5?iI;=i}bVMyFKoe~#=b{b1+Lok{dH zfvLa_XKq_Cv-Ui4zZ13Imbvp+rPzry*!s9y@ff;NAt{{Yhtufj*?i~#?npl^&X~g_ z9V5_VAOd!#LGjEp-wMKTen7HL;8A9b1k&LV#%@@ z>aIAqQ5yl4T!*bF&x=z1hb>iNH8}_IeITjq%^xmQlWTSVh}(>=P#sTG0oRt%E};++ z(8&L4e|OAaS~DI-8?+G7NxZ}to_)d8PX5_c;aUF5N4UZ)Lf8!_FzFwW1Z36sTFGOe0ULB-COL>2Sjv0iojrF8h8dg_UR#pe`P)ycq zNuEw?x0us5*rxjRk$hXWZ{Om@IMGBa zgE92Tkt5%otI=7zj$Kj!WAdzwRGw;G>4*>{26GGyd4M^PPj?Wl0RL?UUu|Y~^OWId zaVk}4R!W@BTTgZwFA^Aaao0}z=Fg+;g++!nVObG>D|T!lUuByIcA-kXa{e*C{!Xni zxdPf8FrI|fZyN**>gL;@h4vzTRYi#|iXAg^Rum-ZYJL#|;^{=QX2!-MNKT>DjMDhr zIC=8q4IlhZiLZd*DxKaonZ6Q75A*9`FD{CrQkE;F$jG(EI?0bc_F?IVyLOpks6lT! z^r6u+(LBfI0RxebkFzuNo?T=XFN(ni#&xKpOb}q7qNa5??t`8&b5W6<`*dzXcZk65 z3HTq@kr#mnJ)m2!*I9@QU6&vqFYyudib7mM*G1qilas^$?bAnvZJ<@m!UZwNsJRx? z&R+N*Y54@Ab1n9(E?lT2Rf<_T^K#<5VZ%wcc>He`z5-Ue5s{dbR9aeOAzlJcZZq-Z zQ^3o%sk!dgGe1<{ZgOyQQ(<5FEcPq;m{E`}AE85`-oT7oO5PS1WCqAjs<6c(Q{twO zA(Bd0%ovP%kw{$ojvA96l|HZ8QLKK`6wri@bVTnG&+}@myTQws8Gt7C?BXQH#92n( z6UQiOKHaJ|F2%v+3zJj}t;PlgpZ`3t<&5JrmCzhd3Gb(^+q z<43HP*2?$y8LTzY|Dw?0zD{~qC*R?r!(uWPE?k%qGc45Y%GV$5D*f`3TWAVB{p8<- zX4UvF7~y3$g)Bs0r=^vY=pC zgI9FY*nj~8gV0c&Y{!n0t)HF#?RxVnk`N`p;18*qFWY(A5Ii9fd0_cbKNBrxoSmWb zQBuQ}E;LFJ|8vgTkDX!0E#xe8kfWj48375t2BMX%CABb3 z6zF+5ETQ}bEw2qNS~L+l3zJfMEYNzUBAV_jql!L#oVS+nPbUaZKaZPTdb+teOYYn< zIJ))d+}+j1Z|vlWsdJV-tAU7m2V&`cqPHGDHe$qx5&gUO`koG56tfe~vkq$r85^Ww}g$Qm_9Jz_-Im?%|RT3UK^Tr_MB2jyN~(&iI5 zPx!LmpkZn*az$Q$``VSSwrtt*b>%HP2i!w-kD^ZhG#lO7KmTgDjcgjuy@t5D+lr;S z?ga$}&lWC?_HNv_?_ha(ISg6h;X}y9uQ#qgOD#*VF6fG|FeV7RsnwBMp5qtcX<37;zINHtVDevj zycaE5#(eQEg<|&#HKIUJx*llqh)~wvv2Jdr>+7j`1ye>Mk&A~BIa_q1OUDB9ge)cU zxk0^a4;(l^t(m9Zh`^*q%Y0_7Q<0o)sX*{t4jh+}qfRv6tT^Tbkp29n{t5$SQV8 zZUnz#v3k!YVn*K3=IcC(cT&tKAssLVM5j)v!?|SU;CH=FuVkEYy1`B?;C2cv z>)c8kC3ti{d#Lab)jJEd1ZOLi^4cKJ@7X%O?;KjzIs{v+HXAE(`(|#j(^|5o3wQI+ zCJR@NEzh#2NhV!zXHrFgDg+!)3v-gT^_cxf%a4GGZ~*`4TQY`&8o+_6v3tRY~3vBIZiS^K2wr9)T@p)95{d zeB|kqBhY6gu(U2O|NNJmb^kO&MT`V@^W`x4$~w=t>rX<^fYxTuzaewKIraVVV<&ai zCof&B?3R_4m7e&3_0CCyhU`Z-ZKg626B%8Ow5)f8k;tuLh#?Y-ooccHOA;;7(%a}; zm@#3Gww4KND3*O-gXdc+yP0OJc97CQq#ijZ zFA~bv%ff0$D~g}s=MTSxJaeogd;P?T6IUHPV>9suz+k0ggZV5ib;598KX1Dt1-3#J z7A%_O_fK^d=E=(Y>$eLWI3<0_b5N=Blo9S8wBE!KO#N@zKlL+l2uq|6kmO_)0%Nv z99{DlPV{Z6uDU=8%VRWywp>`JqWKsy_CXV-Wh{OUnnAWY)X&oZHJcksc1gpeH~%;V zj{TW+i%+5pRZ^hSGihmU!8%n|lKX&hl7Sy5YGIsEo?-oZ*y^o2`32LYdS(B3sUh-y zL=RL{sL>M@WVy_gS}z4_AX~YiflIBYfvIvXuZc^(S1J!3>i>Y;dR+9Vzt!&;{s%~j zcuc_Q<*TWwqgcGU_)JK;3Z1)8-dH2@_K!|UNf|dBn^durB@L%+uH~27lKzJdDV5)A z1eJd-&0ldsFaD>&Ah#{%sVAlV2}^`Y);YJ9#cC>x*#fB1bmilTlSYJ5C_J^v^b}8* zLV+%HR*wS7e2&B&NR*e;ZFoEx-@#*I z3zw0dDHv8(E{6`ec&0CgNqiHx^eQDUiD!-PO_u4jw$MS}*s`_!^c76=#ZJ3-!$=Pe zQvbqB8}^=VbawajcZG#<@Oj#-Eq+rTruW=%~=o&@vlh7B7wu6y;8Uzi$$j%I*6 za|W}l)+R1qsZm+-oA?UrYhW^ybkB3QtooQGo60CV*prcg$w+{o~rHxLi$7#BCvp2kB)KRX)P z1NNgI=*pEAY695BEFw_SbUK?qoPEQ>n}7N2KxMODaplBuWA|&Gc7I)F`q=M!?K}t2{DSsvRBZk8gA~zU1`}7MK1jE+#vmdG<2C|Kr z;-h#yhZnh zTZ>tNLn1?3bnnxcLp0F6opi*hm>|Hfj(=K)rlXJ^MN{aswt zu&2CEbQ1Fdyq+imFB!PW?EX9KxqE^VobHe8K?C;dERQA=B-jp9+g$)r%f%cpbiuk0 zGLeoYqyKWA|9Q%rBwX7op|0bmy4wEA%}?jfaXVtA=gyhcA|!a=q5`dJYt0Qi;pV5s zXa&_9X@-F!n_1Hb%VYuld$_p#jnl6<%>W)=2ZspGK6Qk=qR5SMa0m$*;NjMALnf1g zl*e^ilC6R2!<%Z~wJuQJY!->d;vPOl++?p~QlAx8TQ&=n4hn1h)@z8DFq^zUd5T6j zASwWVp9qy|fd}iE0Yfr`Y#dZ=X-kIXBPs;pwo))u@0G@6JWG>Gwy{+^+zs0oB5`)L*e0vEHITl zSlPADGq2&!M*7w1H@eaKkh(U~4?c2X& z=kfPmSOxq-jq&33yDwyB>cp8d|0;h=Wt?aX)mg35e{gcw2M6{EI6n)xB4_9IU+JwC zJqHC19hCxavI?ev({K*Bxmx}3Udfh^epCb{M?t0e7=~_IcHz|br;?N5iq!JbVUs*w zVJoG6DUsAx5l>UU0Vk+MJ7JJrGDLd$eGS|Nyt#X!czdP6D^-ov7BJ_>gaTL)FQsuF zno*|HV(R573QsR#bG{)o3C%s<#(j)$tM2`F9KL02@BKFL4cz;Bt8XbhtVx)+aW@*# z7GC^^_-$>gZ_U$^`#s?~ewnnbUS1CRF4zTi{>}2z(zv+N((*UY#`USjA_hs5BcToK z6}sSEb{?W-kTBRtBx1c9zEcCk7O4%*Mq`LvKO>7b4v^D~e zI9sRujZ@d4d%^@-+dF8kFi(r}0*_tdN0lD%Wv9Q}yYuk1A5UG;OKfB}ovy4<8sn+i zITqvjC&rx_LjHlCM~_fH%9V12O-8=Qg_&fBiBm%XMJIER+qk>A`T1nf$JRq8enJ;4 zyymH;nx~HW9=ZI}Xh9l_#`;?ZJ#Bskd}=OPpLHGZ$5+hXxXx}XU|=) z8$?gH#j;6@b*=uM4Lu^dp{Gc4=rUZ=+m*&-p-utMmJ#&|U`Y4w-SOE)qqW}Q*#7g# zgzq_Qd{S6M!ZlgnBn_;1)YN~P?6S$9pBfKG|D?%ji!>mVFd^7xx@jhjOURg=8i!K_ zR@hiM)zmfF{(Zjg4x=ZdsD1dnDT>JHwKG;@_Cvr62|d&zAK!$9FrxBnH}W2{6djJaR8mu8=il2wFBVH#qe0Jp@d8+u ziq)t4k+ZLu^3lKeeRHo|Dpom-oUWo|&Gl!06OTxX?WMPYrD*beSc;5&Qlj9E{u!o_ zU+{Spw$SGG`I{6e}in$f^b?}1b2`-6(7EJRMym}XO3;7rX%5028sT7(=Fe{ zQ5>Zxt={D*6=}`WCJV6Hpni^ev7zyrSWRi3olOstJwx7-V?*1d@Sy9U_+LTOBQWuD z{l+eWT|#GNB_nl}mv7!dJRsb;(zPp(&{!@`=U@}bhY`j}n7St#pJk7c@zjLMOXZ1x zXVoBTtp5J=>C-wGKce^<1H)o1!w2WW;k zV+c48(G1{wis!3Tfv@;0lSQ0LC+W?bw=UnSi)|KV_qcgeMYfS`R?C9L_i1Bgkb7^^ zUoonwHg>W4)ak|__U?r?mStQj`s!R0y!>zhKrzCnXp&9saTWSEOJ}vW^rz-iC#o+B z<8vi2V10Yp>)GG7_|wB#`C+!Z(=%~C)C>ZX(o+GlU*3a#^|TMxuZo2*^^6Mi9XZ0s zziStWYb%y@8x&w|N9gWsT}|Lb8Ue+N=6{3rk1@^7QDBWSFeU%(OQMN^wU9dbTDii? ze;^H8`2F0u-&vko)Hd0&U&9iy$?XJul<4I7X*ysqYBgumwS^tBz-;M!UDvWp?opt) zQECfFDxAja1zX7)9q(PwpcF5V#VJX-Wo*Zt0BkPn@h#1vEp4+iz#>MMnKlbp29=MW z9>tBu))56J+4?fDk`DS(vgAql4ncS+DILpuG%k#tPolu)ma4~`+w<{tC(WLtvsBIufFa=#L>=5bMeKZ=1hq_e!>A7>a*dm`8p)5=q-#V;?@{1zypSF033)JMKmsSO{vNAC- zf_G>Xq+S#xKD|;%<}6xyS{zJWSG#$>0S$5D&|bRgz==*=`e)A9M+wejzLsLH3~p?Lxb&#jbRMhG52;lL%#|Cj6eIrtqkK-yuUBNtl+50}d$})Y64v9) zbC7UaozB*=kFT6@sB!u8%!PWry#B(OKRZ_|L~`Fgj_4c&;>ognYY^mKOAHMY41hZ?zIOrh@qlU$Vgs~({;q~q#Bwo9gp%9=|!J!3dl4$0hhB;9;=kbW!8HD zq`9HVU_=5t8a%g5bgapDiJEE@WSeM-Z_`l~T={W4RVM?pUd^ZBncBShgVW94V-azc zI@Y`S_cC~LUN8H-xwD!&s@0u~9(TNp0Rej>1f7JtI^O2$Xq&5wHdoi$T-CI>+Hbm& z0swo6NOb}X$_H9oTW1%%I^C(f?Ir`Wi59q5ei3PWR^Y)5W2Wuf6{miM1){#01eom8 z;$=7y4P%3oB8>iIkxt%x`9!pr1cUaA*8{U61P|a!Hrn$A+vdK$6{?+~Y+o=nGReQMpb?WQwh+bX0X3vS^--G*psjQL&1_ny1%JJ=2 zaQ)~c#)cX%2Ug$n!bz6^thYw?RP5OGJ?H_yD$9~xyAYrn7Z=x)oHIpbt7w1tca;>$ zC0+g1NtB~fM)~(CvhL?UlrqyGY-fOKY123Az?lZUbK@@uqI_)GgoF{%`wqZ!_SL@V z2qCf*Q8$D!8Zr4!nL?((eDKcO%nD9Qsc9d(8qS}>vVpkzXeK5#HR0qgum0GE)Z0l) zU8$v_fB+Jp)7nLQxw3T?h#LRud|h2rv8=JS^4u?{vf|?fexa*)#;uFaJ~=MHtpQO2 z26wL^O7{bMbWC8N8WxwJiJh&OZAS10l{_?{KyeJpK@x0oeKalK?!2t59- zUgjDWBb7NjYf{qErw(`RM)w5Uim=g6=YW8=f#`;w<;@&?ReUUb8gr`?`IyMyY8kl`*iz-C;WeN*8&#Bm8EZ0S2s=bMnuH6 zbr4CXMI?x**kaQ*k03#V1{IMo1X;!~sK_WW%5*i1;WNfHZp;`p8O9i5Sl2O*QKO6^ zgTxrtL4$-PNPHj?M50Jq#I}3>TUBkG(adDO{dT|QQeCfGbzkS+d(MB)IVDjv^kkp| z)5der(dpD&N?3W>FH$s>pIME+(&BOD_|eOt7;nuu)M6$b)GebjsM2MK2C9yih(@24 zl@+Zazy*nB8jhzy-r_l>ub;!p%ZA?Xy=@tDyZ8RELEC`C&sT|zg!@@RtyaJARGm)M zdk&d8*Q?TrW7_`}o%^DE6w@!fWyJm<$TP~bNvfAuXuW`PSy1lJ@p)(uc+|N}uF`}7RpY3==3fAaXDKY=WCyo*j} zx9fDRtzr?y{IJMRnMCi9OsJ|Q>4MY@TV(U&G1Q0+ZXumJ>!`^3X)~u9HtqQ&sHh7-5JTM-ZR5G!S1w(-#d8@M z`rhr*Tig+w?drz;eOLh6EnR(b9%)>rYYNoD(8yEx^w#p=)Cn^l8X)k;0{W zu=S*BIKnM6*(}=kY{1)mnwxujt{r`M?;p^KPc`?37_dNF1(E#}5ZVT_xBJYj#fI?2 zWyOWCbcofCUt%H^xDRzyU`o_#0edslH{EUB5BhI>`9VL`|i8J5#bY?OIUfxVf0TVHiWWEd|Gi>#>b z1F05^ZJLUwRMmS(SW~4v?ELWpKyR$H3$>@=%murG>dG|SS!bM@!crxAoBYOM)*tV1-L`f^0 z9H9%&Uz4Gy*NSz`;@mlI{QbSZKYujtfA{zqq@(KYxnm=?J3Za23QQ2PKLl_1Ar?gP zSHW|FPg8UE10oxy3vD=YuAjJu$3=)aoQNmEwJNQo^Hlw*4!f1gd}i*I<@w8D`)Q_L z7kru`;=)}?|G5(lp}Jw1`MaCNXIJ1^mls3b@HfnhckvoVk3wHe1q9BMl@JLJOW}R2 zRJ{N2>|b#YG0bE&?;8*>wLodT)XPmy$w-Q9WP^i)jiRQ#@^{sdLkBdbr<5k-Xs0Ca z1&AqAo+Bi{YUQri;IHXu6Wv|stk!^8`S{DqTfI6jiyqBFA}~ELNssSDNtI8TGy_8; ztA8gYk|Ml*wH0C9ASvYJfz|n0Muzpw9~_kZJ^%7@6R5%)t1vhe+984`Xn3 zm32lV3BX;pJXpLdM=p6(V3|Pi|C5@gw8En(=Y^-hRo-<-lD!rJd@nM?Ye_z%?e5BQ}6pC+RX{EmKQ124w zbe;r<%us#}Guu4mItAQEI5P&K__yR1j-xTC(r^g_*CseSUz`Acq?q(9ObjvLLB*{D z2M_Fi>n)>W3c>kf`HYH(kEE;Q*kPm8lq;r(W8+v*+Z#KtaEp$1yN3R*hYht=Oq!EXDuwZLv zIMOb2C+->OpG*cabB1^8wR<<(!^B^y+#z^IuJ5Vu(I=vyY(Zjypzep#(fDEZMsK_L zE5#S7(kUBK$;TzWd3|$y2BamfJA>@@7wJ_*V3(s6LM7B06!Dm!3#rx5I7h($t=znZ ze0oM0pP%NJUASaQK#=0X?rm`xDGD4hjv)?DM+&!Vi)9B8hgFVORB!yD{?zpVQ%ZW) z8q8see_`4BdeR03@aVU7(P2Xp|%TLw$@#ua!%+eGK`QDer%O&+@d_2>0IGHuq7wsVV;B z{M~hdKHhyNDk>^!t-ihi>VSa!yu4@KmCYYi{5BTwK?!%59sL|=)dF4l*SW$ZwfjYS zJ)5&sTvNMRl$zi%PZi3LRbE6H zIQ2+(CBv&3rTgHiJ)gnIbGTkVIpVn$Ykyr_c%Y{3hDT6xQ9PI~0sTQb<%A!$c5Thk zLx+w)`~HOmNzL}J_iy`mYv{fIKy5EWKPYBG;u6tQ-UdhbDRhGXL82R#vZ=(x^TRpS zP}GzuF?_hcz32RQ-ku7`omcA){&r&`P^CPqK08^&T*pe6y=N{fg2#u2%>@2-7VBt7 zJPHeg=FLsb>ZmzffBq&E4=HB+J5uKMl0IsCMRn7+qo+IztZF^*MhP#Tgi?B6xzcj| zi|WelK&iI9U;RaAOPnBFbi*G-B~ytmZG@b^XV0F>Js%zXtm&IR2Vq_p#H6a@xlb7H$&hjcs0YX=@4B{lF5rjA(a_k1JpA0tYvWOg z2f*nz3Ss}q;?xPMfxbT0W#GPbP+9p=k2*3fHz#}kg1q$jXsAG%$%c@1b963O8qb_* zxz=&d1MXtfBiy@>Z8Dq96&L#5LZ|Da!y^-uQ)WnX+)9XPCL@O=z(8?|3V4tIIWIf+ z4`bi~=Ra#8rDhU1pOoTd5zwWV19Ybo0F~h=m2MJ_evdjjir!g`iTf{Dhi+xF@=9i- zxhf$m{h2`X6ezbl0wDu9I|bsYf|bU)C7G#+eH9oiHU9k^(W&Jk4U`>vc+4cn!5d3F z=7BSKU+EZTTVNoR=!cCSH#R63y8h!rM#+1d&eqgGZ{civkB{cXJbVLQ@R5f8Sn9VT zH+^BWHYhMScuWx32jN$o1z!an$f73%sw|UKffJ$=78k&jreJY`J|bA7(F8~6 z<CI9P$Quf;NpWXoY26uY&AFv*sa>7bY*2JG^N;= zotIt~OZ?<{_epaFFdQd8^-$7;ubDhYi^E_RdJ&!?WLKG))QBY+BWbC@;SdBZ`YU&5 z-SHm}fv5?a_}ip9eq7&?O|r8)^v6YBgUTFcSxyeg;h}~mzD+~lu7g<-m*G$RF|9VT zIzck8jqE1=4F<#C%#cpaNF^TP4NNi?lBD|^amDqs&z^stZcoGE<{!x)8EMaZY35`m zCnvwOyeJ>ut>@2+!n%{v=u?Bm?-P!|SW-i3TmtVN0qS`p5Vy=Ek@vEBdfIyJ_Fm_{ z)UCbl>}Q>Q{R*#e-4Lwsij&n=k6hz0YL1N2d-ON88zuNy%2gI}0n2;%BHFB!}CQp4YGIdsEzcK zwyhreoE)7_PvFj_BP**zr0S)}fyyvryq`)nX1ZbitI!nXv=P$`%S;&B8ZjF-l0V8; z8uVJ=K1?xsdul2V5FFJ|4(RjVU4RW1rnlV${^xneLg?zHaixu9;<}j_E-Bp|RR#N! zBT-RD8j_M4BnlWo#|S|(LZgGztYtI>Gm-BCy0QM-pvYlj;H*Gw$3f(f#YZ%#oH=(i z+>5DPi1#d}mU)9QkO$ECX~hsu!$lmOc3GP?!%unhvsx2|`;E|QJ3u~Smr+M6@Dk4W z`%z`TP4+?Xe3|Zt?%J=`)zw|MDWlR}q;ewF4ZKFWl;Oh@Y!1J^pwD5xHm|5vNMP0$8@9s->lV-<}H=*MYv?rq*w-bT&C_Y%Znc z3m0MmO1-HpiR${I`Y-oJj*LZ*IK%zQ(NNdPGf7E23#y=eyCn|gs0W5tgRx~he4t-D zd-n2$#$Jcq;P@5e?_qHKLUuBH;U^*mY{0wy($mxC<`z5$Pw|~YQVV`DJ8i*&>=%+S z!)?K$ah>PdrAo0JU)>DcjoGzP{An{OLOh5KZPom1>@# zQiWw)i-IAJ_Wj$<@vzTLLP!*T3ovKJkDYJgx!U^A>#L|!53zB6#Z}=#Ez;{C7S#r& zGCsblDkg@+^JRVy?p$u#_jbiDFm-S=k~(kRWP4LpykmvH{J$V9UZ*j8_Ve63US98P z;K>HD&P!Yp=t2|RA_$`#;J!|{8Xlh=?_G=R#y35OW;#}j zVh*$OlAuFpmTixZccRM^@OIblzMDFgZif!>a;>(o5E6&MVPvki8yr#GrinTW&`uDC zXk;MDj#Fvv#M1ehQK5XNnH*O9rPq!#swLEM2Cne3lQU+Vv>2fNV27ZoD>c~b#W#$5 zTt6L4WK|>reo8z&@y>Rp0IT_w+i!y1Vf8FRv zc9fHY%2f{|i23<(37u-Vu;65<7}HGFn<2owv$+FaFYwV%?WxOZQv zy#DDfsbnVPjk-zPIHWi~H}BQeYx}QXbu&EoV*ZNdxtZXFI$+n^PyW+vAT9jxO`CR~ z#QI)CRaHkU81?M92@@vFm_L8S$xYJRoO~?2L$I}mHlZB_dpw1I=u!VdVB>6;y^BJL zS^(@~?QB90eDu>s0B{{K)fBxVGc7rHT>(H@szXD=wx6vocr_;(3`^p8W0W>j8)aNl z4BemNC55x68;!>4vkOa%P=PEbZ!jgOmjk@Ms%rmv+fY45sBDvI!6NKu>9}iuf{ef8 zy(357+fijQ>Fp<>Tl5t?ppJ!HIhM5#eueXscD+f;R}{hb3o+dbT$=F9Q5GLO8w1Ns zX1IGthr9JgeRX~F4eRhoowcXErKP>c>hJGi4$x{zbMtLYq$wrEq_`asF>a)bqtNkt@WVCNU}$dGj~r+Qlg)%w*PL2CQb*@~D2XZmE>c%PT5~ z24Rq0fPFt1l;!6GY9)if>n zZ37z`Pa^3fw zLct2lVC=K@gGM;M$acKQeo9TocS@}m57$XUg;sM4WkUqf4C0xhn3UOUO>bg=Vc!hS z#rIR#T&HwKWi@80%`8J4kkF%Y+Ye{5ty)Qndx?-ynkS~hI+OjU$+1hjYK(xW(j4nJ z@67YZP}$qySXt_{B*!Qx&I5FWAc?^7QMrdAY81sT zno3P2Rh<>;1+69ZS7LzJ2Y+k$6`jip_c5IKA;ocaffyQ`(CSRwB8tTfW-(aW0dk`$rvY+lQ3N#6M(u#?90HSW5ZpmTbOYH0P9Vz zg6De714i*}vB={;{AMHy|2F@RKNBd{h;ueGGX?|oD?wLf!tr(t@iL+r!u7Scw_m%` z7NR!+dm0OP(eH^L50dI75>Ez%4#zjs>~3SHrv z7muy6C~!@{TFS(dFQO^*)$R1;?A*}t`jLG-pYN+~>bTL_Hb>hB=x7D-ieiu7?mKa{ zZi%QrI`3K-eUL?Q_xkx``?Y8=vzOxg)9+%0eyb8cJL~T##5##a z+J5#yk|l&G-g%5Y+9&>AosY%E_&{t6EzGkE|2 literal 0 HcmV?d00001 diff --git a/src/styles/globals.css b/src/styles/globals.css index cc1c56e9..4e7aad46 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -13,6 +13,9 @@ html, body { font-family: Manrope, "Manrope-Fallback", Arial, sans-serif; overflow: hidden; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } #page_wrapper { diff --git a/src/styles/manrope.css b/src/styles/manrope.css index ee904188..fd870e32 100644 --- a/src/styles/manrope.css +++ b/src/styles/manrope.css @@ -13,49 +13,16 @@ @font-face { font-family: "Manrope"; - font-weight: 200; - src: local("Manrope"), url("./font/Manrope.woff2") format("woff2"); + font-weight: 200 800; + font-style: normal; + src: local("Manrope"), url("./font/Manrope.woff2") format("woff2"), url("./font/Manrope.ttf") format("ttf"); font-display: swap; } @font-face { font-family: "Manrope"; - font-weight: 300; - src: local("Manrope"), url("./font/Manrope.woff2") format("woff2"); - font-display: swap; -} - -@font-face { - font-family: "Manrope"; - font-weight: 400; - src: local("Manrope"), url("./font/Manrope.woff2") format("woff2"); - font-display: swap; -} - -@font-face { - font-family: "Manrope"; - font-weight: 500; - src: local("Manrope"), url("./font/Manrope.woff2") format("woff2"); - font-display: swap; -} - -@font-face { - font-family: "Manrope"; - font-weight: 600; - src: local("Manrope"), url("./font/Manrope.woff2") format("woff2"); - font-display: swap; -} - -@font-face { - font-family: "Manrope"; - font-weight: 700; - src: local("Manrope"), url("./font/Manrope.woff2") format("woff2"); - font-display: swap; -} - -@font-face { - font-family: "Manrope"; - font-weight: 800; - src: local("Manrope"), url("./font/Manrope.woff2") format("woff2"); + font-weight: 200 800; + fint-style: italic; + src: local("Manrope"), url("./font/Manrope.woff2") format("woff2"), url("./font/Manrope.ttf") format("ttf"); font-display: swap; } From 7052951a434bc9e8958a8ae4a2b230130fc86b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Fern=C3=A1ndez=20S=C3=A1nchez?= Date: Sat, 1 Oct 2022 08:55:28 +0000 Subject: [PATCH 017/401] Translated using Weblate (Spanish) Currently translated at 100.0% (118 of 118 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/ --- public/locales/es/common.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 755d7d03..58717230 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -14,10 +14,10 @@ "load": "Carga" }, "docker": { - "rx": "RX", - "tx": "TX", - "mem": "MEM", - "cpu": "CPU", + "rx": "RECIBIDO", + "tx": "TRANSMITIDO", + "mem": "MEMORIA", + "cpu": "PROCESADOR", "offline": "Desconectado" }, "emby": { From 76f6b3a4a7695bf0a9579147fd496faf9776bc89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Benn=C3=A0ssar=20Carretero?= Date: Fri, 30 Sep 2022 11:59:52 +0000 Subject: [PATCH 018/401] Translated using Weblate (Spanish) Currently translated at 100.0% (118 of 118 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/ --- public/locales/es/common.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 58717230..1b4777bd 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -171,7 +171,7 @@ }, "authentik": { "users": "Usuarios", - "loginsLast24H": "Accesos (24h)", - "failedLoginsLast24H": "Accesos Fallidos (24h)" + "loginsLast24H": "Inicios de sesión (24h)", + "failedLoginsLast24H": "Inicios de sesión fallidos (24h)" } } From a63f71d3ee4bc6b4de99454696a92cd85e43c397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Benn=C3=A0ssar=20Carretero?= Date: Fri, 30 Sep 2022 11:56:37 +0000 Subject: [PATCH 019/401] Translated using Weblate (Catalan) Currently translated at 100.0% (118 of 118 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/ --- public/locales/ca/common.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/locales/ca/common.json b/public/locales/ca/common.json index c5945fb8..a2496521 100644 --- a/public/locales/ca/common.json +++ b/public/locales/ca/common.json @@ -170,8 +170,8 @@ "transferRate": "Velocitat" }, "authentik": { - "users": "Users", - "loginsLast24H": "Logins (24h)", - "failedLoginsLast24H": "Failed Logins (24h)" + "users": "Usuaris", + "loginsLast24H": "Inicis de sessió (24h)", + "failedLoginsLast24H": "Errors d'inici de sessió (24h)" } } From 07e99768e6b2a3cc6f75799f851542fa8fe59f14 Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Mon, 3 Oct 2022 10:45:45 +0300 Subject: [PATCH 020/401] speedtest widget, catch api errors --- src/widgets/speedtest/component.jsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/widgets/speedtest/component.jsx b/src/widgets/speedtest/component.jsx index 778d31c5..e93c6963 100644 --- a/src/widgets/speedtest/component.jsx +++ b/src/widgets/speedtest/component.jsx @@ -11,7 +11,7 @@ export default function Component({ service }) { const { data: speedtestData, error: speedtestError } = useWidgetAPI(widget, "speedtest/latest"); - if (speedtestError) { + if (speedtestError || (speedtestData && !speedtestData.data)) { return ; } @@ -31,10 +31,7 @@ export default function Component({ service }) { label="speedtest.download" value={t("common.bitrate", { value: speedtestData.data.download * 1024 * 1024 })} /> - + Date: Sun, 2 Oct 2022 08:26:53 +0000 Subject: [PATCH 021/401] Translated using Weblate (Spanish) Currently translated at 100.0% (118 of 118 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/ --- public/locales/es/common.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 1b4777bd..1e8ba3dd 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -14,9 +14,9 @@ "load": "Carga" }, "docker": { - "rx": "RECIBIDO", - "tx": "TRANSMITIDO", - "mem": "MEMORIA", + "rx": "Recibido", + "tx": "Transmitido", + "mem": "Memoria", "cpu": "PROCESADOR", "offline": "Desconectado" }, From 4503612bf0ab1e9ba752c2d9be264f48d09086f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Fern=C3=A1ndez=20S=C3=A1nchez?= Date: Sat, 1 Oct 2022 19:44:19 +0000 Subject: [PATCH 022/401] Translated using Weblate (Spanish) Currently translated at 100.0% (118 of 118 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/ --- public/locales/es/common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 1e8ba3dd..b9146959 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -17,7 +17,7 @@ "rx": "Recibido", "tx": "Transmitido", "mem": "Memoria", - "cpu": "PROCESADOR", + "cpu": "CPU", "offline": "Desconectado" }, "emby": { From 1249724f8a000d688cabba6a8e2bce9b5ad8eeda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Benn=C3=A0ssar=20Carretero?= Date: Mon, 3 Oct 2022 15:47:46 +0200 Subject: [PATCH 023/401] Fix resources CPU label... --- public/locales/en/common.json | 1 + src/components/widgets/resources/cpu.jsx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index a652abf8..d4634e80 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -25,6 +25,7 @@ "placeholder": "Search…" }, "resources": { + "cpu": "CPU", "total": "Total", "free": "Free", "used": "Used", diff --git a/src/components/widgets/resources/cpu.jsx b/src/components/widgets/resources/cpu.jsx index 741ffefd..6b021193 100644 --- a/src/components/widgets/resources/cpu.jsx +++ b/src/components/widgets/resources/cpu.jsx @@ -30,7 +30,7 @@ export default function Cpu({ expanded }) {

-
-
{t("docker.cpu")}
+
{t("resources.cpu")}
{expanded && (
@@ -59,7 +59,7 @@ export default function Cpu({ expanded }) { maximumFractionDigits: 0, })}
-
{t("docker.cpu")}
+
{t("resources.cpu")}
{expanded && (
From c3a623c329bc65250851fcad58de1c4782186778 Mon Sep 17 00:00:00 2001 From: Jason Fischer Date: Mon, 3 Oct 2022 15:17:56 -0700 Subject: [PATCH 024/401] Remove pages/api/proxy.js as it was an open proxy - The only location pages/api/proxy was used was for icon loading in item.jsx, simply returning the icon URL instead worked just fine. There was no need to proxy icon requests. fixes: #327 --- src/components/services/item.jsx | 2 +- src/pages/api/proxy.js | 59 -------------------------------- src/widgets/bazarr/component.jsx | 2 +- 3 files changed, 2 insertions(+), 61 deletions(-) delete mode 100644 src/pages/api/proxy.js diff --git a/src/components/services/item.jsx b/src/components/services/item.jsx index abd06ffe..870eb4f4 100644 --- a/src/components/services/item.jsx +++ b/src/components/services/item.jsx @@ -10,7 +10,7 @@ import { SettingsContext } from "utils/contexts/settings"; function resolveIcon(icon) { if (icon.startsWith("http")) { - return `/api/proxy?url=${encodeURIComponent(icon)}`; + return icon; } if (icon.startsWith("/")) { diff --git a/src/pages/api/proxy.js b/src/pages/api/proxy.js deleted file mode 100644 index 7ab95edc..00000000 --- a/src/pages/api/proxy.js +++ /dev/null @@ -1,59 +0,0 @@ -import https from "https"; - -import getRawBody from "raw-body"; - -import { httpRequest, httpsRequest } from "utils/proxy/http"; - -export const config = { - api: { - bodyParser: false, - }, -}; - -export default async function handler(req, res) { - const headers = ["X-API-Key", "Authorization"].reduce((obj, key) => { - if (req.headers && Object.prototype.hasOwnProperty.call(req.headers, key.toLowerCase())) { - // eslint-disable-next-line no-param-reassign - obj[key] = req.headers[key.toLowerCase()]; - } - return obj; - }, {}); - - const url = new URL(req.query.url); - - if (url.protocol === "https:") { - // this agent allows us to bypass the certificate check - // which is required for most self-signed certificates - const httpsAgent = new https.Agent({ - rejectUnauthorized: false, - }); - - const [status, contentType, data] = await httpsRequest(url, { - agent: httpsAgent, - method: req.method, - headers, - body: - req.method === "GET" || req.method === "HEAD" - ? null - : await getRawBody(req, { - encoding: "utf8", - }), - }); - - res.setHeader("Content-Type", contentType); - return res.status(status).send(data); - } - const [status, contentType, data] = await httpRequest(url, { - method: req.method, - headers, - body: - req.method === "GET" || req.method === "HEAD" - ? null - : await getRawBody(req, { - encoding: "utf8", - }), - }); - - res.setHeader("Content-Type", contentType); - return res.status(status).send(data); -} diff --git a/src/widgets/bazarr/component.jsx b/src/widgets/bazarr/component.jsx index 24fef1ce..c339def5 100644 --- a/src/widgets/bazarr/component.jsx +++ b/src/widgets/bazarr/component.jsx @@ -13,7 +13,7 @@ export default function Component({ service }) { const { data: moviesData, error: moviesError } = useWidgetAPI(widget, "movies"); if (episodesError || moviesError) { - return ; + return ; } if (!episodesData || !moviesData) { From 84bb98b00796246e8979c0f451a694323f84192e Mon Sep 17 00:00:00 2001 From: Jason Fischer Date: Mon, 3 Oct 2022 15:20:30 -0700 Subject: [PATCH 025/401] Update component.jsx --- src/widgets/bazarr/component.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/bazarr/component.jsx b/src/widgets/bazarr/component.jsx index c339def5..24fef1ce 100644 --- a/src/widgets/bazarr/component.jsx +++ b/src/widgets/bazarr/component.jsx @@ -13,7 +13,7 @@ export default function Component({ service }) { const { data: moviesData, error: moviesError } = useWidgetAPI(widget, "movies"); if (episodesError || moviesError) { - return ; + return ; } if (!episodesData || !moviesData) { From f29154cfa4795c196e3ecce29ef1327ca3c14ca2 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:16 +0000 Subject: [PATCH 026/401] Translated using Weblate (German) Currently translated at 99.1% (118 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/ --- public/locales/de/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/de/common.json b/public/locales/de/common.json index b40fec4c..d3a7a55b 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -11,7 +11,8 @@ "total": "Gesamt", "free": "Frei", "used": "Gebraucht", - "load": "Belastung" + "load": "Belastung", + "cpu": "CPU" }, "docker": { "rx": "Rx", From 8718b4bcee2eafb24018f6bbad72528762842c7f Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:16 +0000 Subject: [PATCH 027/401] Translated using Weblate (Spanish) Currently translated at 99.1% (118 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/ --- public/locales/es/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/es/common.json b/public/locales/es/common.json index b9146959..5cfef018 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -11,7 +11,8 @@ "total": "Total", "free": "Libre", "used": "Usado", - "load": "Carga" + "load": "Carga", + "cpu": "CPU" }, "docker": { "rx": "Recibido", From ad3752650b4bbe4e530370ceee55bce78e3265f5 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:16 +0000 Subject: [PATCH 028/401] Translated using Weblate (French) Currently translated at 99.1% (118 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/ --- public/locales/fr/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json index a1ff63c1..4040e9a0 100644 --- a/public/locales/fr/common.json +++ b/public/locales/fr/common.json @@ -11,7 +11,8 @@ "total": "Total", "free": "Libre", "used": "Utilisé", - "load": "Charge" + "load": "Charge", + "cpu": "CPU" }, "docker": { "rx": "Rx", From 5643af98454be053f87d18581a3cae7464f61a31 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:16 +0000 Subject: [PATCH 029/401] Translated using Weblate (Portuguese) Currently translated at 96.6% (115 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt/ --- public/locales/pt/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/pt/common.json b/public/locales/pt/common.json index 3d795f03..36e41199 100644 --- a/public/locales/pt/common.json +++ b/public/locales/pt/common.json @@ -11,7 +11,8 @@ "total": "Total", "free": "Livre", "used": "Usado", - "load": "Carregar" + "load": "Carregar", + "cpu": "CPU" }, "docker": { "rx": "Rx", From 68b7fe2b35f546a3fca73569fd4280b3883b46a4 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:16 +0000 Subject: [PATCH 030/401] Translated using Weblate (Russian) Currently translated at 19.3% (23 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ru/ --- public/locales/ru/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/ru/common.json b/public/locales/ru/common.json index 4baa4a3a..9b9e54d4 100644 --- a/public/locales/ru/common.json +++ b/public/locales/ru/common.json @@ -11,7 +11,8 @@ "total": "Всего", "free": "Свободно", "used": "Использовано", - "load": "Load" + "load": "Load", + "cpu": "CPU" }, "docker": { "rx": "Rx", From 588ea9b04e6aefba0e1b0fe5c25e5e6714a53d5b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:16 +0000 Subject: [PATCH 031/401] Translated using Weblate (Chinese (Simplified)) Currently translated at 91.5% (109 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/ --- public/locales/zh-CN/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/zh-CN/common.json b/public/locales/zh-CN/common.json index c3e34a6b..9e35011d 100644 --- a/public/locales/zh-CN/common.json +++ b/public/locales/zh-CN/common.json @@ -11,7 +11,8 @@ "total": "共", "free": "空闲", "used": "已用", - "load": "负载" + "load": "负载", + "cpu": "CPU" }, "docker": { "rx": "接收", From 6a67873c10bfa98d263fa4c773de028045461253 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:16 +0000 Subject: [PATCH 032/401] Translated using Weblate (Italian) Currently translated at 64.7% (77 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/it/ --- public/locales/it/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/it/common.json b/public/locales/it/common.json index 68b04608..be0f3d45 100644 --- a/public/locales/it/common.json +++ b/public/locales/it/common.json @@ -45,7 +45,8 @@ "total": "Totale", "free": "Libero", "used": "In utilizzo", - "load": "Load" + "load": "Load", + "cpu": "CPU" }, "rutorrent": { "active": "Attivo", From 3e133c10d29707176ee2b6cb4a6c845082c94292 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:16 +0000 Subject: [PATCH 033/401] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegi?= =?UTF-8?q?an=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 66.3% (79 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nb_NO/ --- public/locales/nb-NO/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/nb-NO/common.json b/public/locales/nb-NO/common.json index f3822301..2fa34338 100644 --- a/public/locales/nb-NO/common.json +++ b/public/locales/nb-NO/common.json @@ -11,7 +11,8 @@ "total": "Totalt", "free": "Ledig", "used": "Brukt", - "load": "Last inn" + "load": "Last inn", + "cpu": "CPU" }, "docker": { "rx": "Mottatt", From 83983d772d599804754d834ed3a6d8b9dbb42334 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:16 +0000 Subject: [PATCH 034/401] Translated using Weblate (Vietnamese) Currently translated at 36.9% (44 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/vi/ --- public/locales/vi/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/vi/common.json b/public/locales/vi/common.json index 70d410f3..492b8545 100644 --- a/public/locales/vi/common.json +++ b/public/locales/vi/common.json @@ -11,7 +11,8 @@ "total": "Tổng", "free": "Dư", "used": "Đã dùng", - "load": "Load" + "load": "Load", + "cpu": "CPU" }, "docker": { "rx": "RX", From 5e38e71229b91e0216aa5f17b7ee74ed4cc884a9 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:17 +0000 Subject: [PATCH 035/401] Translated using Weblate (Dutch) Currently translated at 52.9% (63 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nl/ --- public/locales/nl/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/nl/common.json b/public/locales/nl/common.json index fe4e8f11..7b98ba7b 100644 --- a/public/locales/nl/common.json +++ b/public/locales/nl/common.json @@ -8,7 +8,8 @@ "total": "Totaal", "free": "Vrij", "used": "Gebruikt", - "load": "Load" + "load": "Load", + "cpu": "CPU" }, "docker": { "rx": "RX", From 1b7b6af84d590602c20923f93b4d8e909b09e44e Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:17 +0000 Subject: [PATCH 036/401] Translated using Weblate (Chinese (Traditional)) Currently translated at 7.5% (9 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hant/ --- public/locales/zh-Hant/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/zh-Hant/common.json b/public/locales/zh-Hant/common.json index d7cb7228..61317f0d 100644 --- a/public/locales/zh-Hant/common.json +++ b/public/locales/zh-Hant/common.json @@ -41,7 +41,8 @@ "total": "Total", "free": "Free", "used": "Used", - "load": "Load" + "load": "Load", + "cpu": "CPU" }, "nzbget": { "rate": "Rate", From 0f107d8648c295f2cc5b5e282550587aeefc640b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:15 +0000 Subject: [PATCH 037/401] Translated using Weblate (Catalan) Currently translated at 99.1% (118 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/ --- public/locales/ca/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/ca/common.json b/public/locales/ca/common.json index a2496521..032bd777 100644 --- a/public/locales/ca/common.json +++ b/public/locales/ca/common.json @@ -33,7 +33,8 @@ "total": "Total", "free": "Lliure", "used": "Usat", - "load": "Càrrega" + "load": "Càrrega", + "cpu": "CPU" }, "docker": { "rx": "RX", From a2c9754560f88c6008a04864be87d0acfcf6c393 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:15 +0000 Subject: [PATCH 038/401] Translated using Weblate (Polish) Currently translated at 82.3% (98 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pl/ --- public/locales/pl/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/pl/common.json b/public/locales/pl/common.json index 287a288e..27f1772d 100644 --- a/public/locales/pl/common.json +++ b/public/locales/pl/common.json @@ -12,7 +12,8 @@ "used": "Użyte", "load": "Obciążenie", "total": "Całkowite", - "free": "Wolne" + "free": "Wolne", + "cpu": "CPU" }, "emby": { "no_active": "Brak aktywnych strumieni", From dec25762f065070387a7f725fc6e7c4a06e231fc Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:15 +0000 Subject: [PATCH 039/401] Translated using Weblate (Swedish) Currently translated at 89.9% (107 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sv/ --- public/locales/sv/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/sv/common.json b/public/locales/sv/common.json index 093a57a0..96b481e2 100644 --- a/public/locales/sv/common.json +++ b/public/locales/sv/common.json @@ -14,7 +14,8 @@ "load": "Laddar", "total": "Total", "free": "Ledigt", - "used": "Använt" + "used": "Använt", + "cpu": "CPU" }, "docker": { "rx": "RX", From 933414934c944993aec375c314ac0ed4d6dfee1b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:15 +0000 Subject: [PATCH 040/401] Translated using Weblate (Croatian) Currently translated at 96.6% (115 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hr/ --- public/locales/hr/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/hr/common.json b/public/locales/hr/common.json index 51827285..74b589c5 100644 --- a/public/locales/hr/common.json +++ b/public/locales/hr/common.json @@ -12,7 +12,8 @@ "total": "Ukupno", "free": "Slobodno", "used": "Korišteno", - "load": "Opterećenje" + "load": "Opterećenje", + "cpu": "CPU" }, "sabnzbd": { "rate": "Stopa", From dd080d9a0461b7300b9773807bcce8a9b79e5954 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:15 +0000 Subject: [PATCH 041/401] Translated using Weblate (Hungarian) Currently translated at 90.7% (108 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hu/ --- public/locales/hu/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/hu/common.json b/public/locales/hu/common.json index 26aba50e..d40c2d4a 100644 --- a/public/locales/hu/common.json +++ b/public/locales/hu/common.json @@ -3,7 +3,8 @@ "total": "Összes", "free": "Szabad", "used": "Használt", - "load": "Terhelés" + "load": "Terhelés", + "cpu": "CPU" }, "docker": { "rx": "RX", From 1972f2b6db0dfab3810c04c8691cfbcfe2ea7dfc Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:15 +0000 Subject: [PATCH 042/401] Translated using Weblate (Hebrew) Currently translated at 84.8% (101 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/he/ --- public/locales/he/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/he/common.json b/public/locales/he/common.json index 6f6c0259..82186604 100644 --- a/public/locales/he/common.json +++ b/public/locales/he/common.json @@ -17,7 +17,8 @@ "total": "סה\"כ", "free": "פנוי", "used": "בשימוש", - "load": "עומס" + "load": "עומס", + "cpu": "CPU" }, "docker": { "rx": "RX", From 875eefe71fcc6f25a7011f9b811e92f3f0d7955e Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:15 +0000 Subject: [PATCH 043/401] Translated using Weblate (Romanian) Currently translated at 99.1% (118 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ro/ --- public/locales/ro/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/ro/common.json b/public/locales/ro/common.json index ea00d35c..de3ad552 100644 --- a/public/locales/ro/common.json +++ b/public/locales/ro/common.json @@ -3,7 +3,8 @@ "used": "Utilizați", "load": "Sarcină", "total": "Total", - "free": "Disponibili" + "free": "Disponibili", + "cpu": "CPU" }, "docker": { "rx": "RX", From 82f18c7cff886ae62a4debfc0d89a220ad8d95be Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:15 +0000 Subject: [PATCH 044/401] Translated using Weblate (Portuguese (Brazil)) Currently translated at 96.6% (115 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt_BR/ --- public/locales/pt-BR/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/pt-BR/common.json b/public/locales/pt-BR/common.json index b319e7a2..cbf95cfd 100644 --- a/public/locales/pt-BR/common.json +++ b/public/locales/pt-BR/common.json @@ -45,7 +45,8 @@ "total": "Total", "free": "Livre", "used": "Usado", - "load": "Carregamento" + "load": "Carregamento", + "cpu": "CPU" }, "docker": { "rx": "Rx", From 6c3489aa3dafbad1a48898c508b3c006249c016f Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 06:41:16 +0000 Subject: [PATCH 045/401] Translated using Weblate (Yue) Currently translated at 99.1% (118 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/yue/ --- public/locales/yue/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/yue/common.json b/public/locales/yue/common.json index 516741f9..848c6151 100644 --- a/public/locales/yue/common.json +++ b/public/locales/yue/common.json @@ -35,7 +35,8 @@ "total": "全部", "free": "剩餘", "used": "用咗", - "load": "負荷" + "load": "負荷", + "cpu": "CPU" }, "docker": { "rx": "接收", From 84f142683f93991cfbb2c5b36ac7eb9a497bf8a9 Mon Sep 17 00:00:00 2001 From: Kai Huuhko Date: Tue, 4 Oct 2022 14:32:32 +0200 Subject: [PATCH 046/401] Added translation using Weblate (Finnish) --- public/locales/fi/common.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 public/locales/fi/common.json diff --git a/public/locales/fi/common.json b/public/locales/fi/common.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/public/locales/fi/common.json @@ -0,0 +1 @@ +{} From 701270b020a027bad6e2baac8395ee5ca4b17242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Benn=C3=A0ssar=20Carretero?= Date: Tue, 4 Oct 2022 06:48:27 +0000 Subject: [PATCH 047/401] Translated using Weblate (Spanish) Currently translated at 100.0% (119 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/ --- public/locales/es/common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 5cfef018..01497d0f 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -18,7 +18,7 @@ "rx": "Recibido", "tx": "Transmitido", "mem": "Memoria", - "cpu": "CPU", + "cpu": "Procesador", "offline": "Desconectado" }, "emby": { From 1e7ef54c0557f3f7d2fa7ce33a515fcf65032547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Benn=C3=A0ssar=20Carretero?= Date: Tue, 4 Oct 2022 06:50:04 +0000 Subject: [PATCH 048/401] Translated using Weblate (Catalan) Currently translated at 100.0% (119 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/ --- public/locales/ca/common.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/public/locales/ca/common.json b/public/locales/ca/common.json index 032bd777..b2dea57a 100644 --- a/public/locales/ca/common.json +++ b/public/locales/ca/common.json @@ -37,10 +37,10 @@ "cpu": "CPU" }, "docker": { - "rx": "RX", - "tx": "TX", - "mem": "MEM", - "cpu": "CPU", + "rx": "Rebut", + "tx": "Transmès", + "mem": "Memòria", + "cpu": "Processador", "offline": "Fora de línia" }, "emby": { From 07a28c08415236dae968cd6bff442953a4ffe1ab Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 4 Oct 2022 12:32:34 +0000 Subject: [PATCH 049/401] Translated using Weblate (Finnish) Currently translated at 100.0% (0 of 0 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fi/ --- public/locales/fi/common.json | 179 +++++++++++++++++++++++++++++++++- 1 file changed, 178 insertions(+), 1 deletion(-) diff --git a/public/locales/fi/common.json b/public/locales/fi/common.json index 0967ef42..c2d48369 100644 --- a/public/locales/fi/common.json +++ b/public/locales/fi/common.json @@ -1 +1,178 @@ -{} +{ + "widget": { + "missing_type": "Missing Widget Type: {{type}}", + "api_error": "API Error", + "status": "Status" + }, + "weather": { + "current": "Current Location", + "allow": "Click to allow", + "updating": "Updating", + "wait": "Please wait" + }, + "search": { + "placeholder": "Search…" + }, + "resources": { + "cpu": "CPU", + "total": "Total", + "free": "Free", + "used": "Used", + "load": "Load" + }, + "docker": { + "rx": "RX", + "tx": "TX", + "mem": "MEM", + "cpu": "CPU", + "offline": "Offline" + }, + "emby": { + "playing": "Playing", + "transcoding": "Transcoding", + "bitrate": "Bitrate", + "no_active": "No Active Streams" + }, + "tautulli": { + "playing": "Playing", + "transcoding": "Transcoding", + "bitrate": "Bitrate", + "no_active": "No Active Streams" + }, + "nzbget": { + "rate": "Rate", + "remaining": "Remaining", + "downloaded": "Downloaded" + }, + "sabnzbd": { + "rate": "Rate", + "queue": "Queue", + "timeleft": "Time Left" + }, + "rutorrent": { + "active": "Active", + "upload": "Upload", + "download": "Download" + }, + "transmission": { + "download": "Download", + "upload": "Upload", + "leech": "Leech", + "seed": "Seed" + }, + "qbittorrent": { + "download": "Download", + "upload": "Upload", + "leech": "Leech", + "seed": "Seed" + }, + "sonarr": { + "wanted": "Wanted", + "queued": "Queued", + "series": "Series" + }, + "radarr": { + "wanted": "Wanted", + "queued": "Queued", + "movies": "Movies" + }, + "lidarr": { + "wanted": "Wanted", + "queued": "Queued", + "albums": "Albums" + }, + "readarr": { + "wanted": "Wanted", + "queued": "Queued", + "books": "Books" + }, + "bazarr": { + "missingEpisodes": "Missing Episodes", + "missingMovies": "Missing Movies" + }, + "ombi": { + "pending": "Pending", + "approved": "Approved", + "available": "Available" + }, + "jellyseerr": { + "pending": "Pending", + "approved": "Approved", + "available": "Available" + }, + "overseerr": { + "pending": "Pending", + "approved": "Approved", + "available": "Available" + }, + "pihole": { + "queries": "Queries", + "blocked": "Blocked", + "gravity": "Gravity" + }, + "adguard": { + "queries": "Queries", + "blocked": "Blocked", + "filtered": "Filtered", + "latency": "Latency" + }, + "speedtest": { + "upload": "Upload", + "download": "Download", + "ping": "Ping" + }, + "portainer": { + "running": "Running", + "stopped": "Stopped", + "total": "Total" + }, + "traefik": { + "routers": "Routers", + "services": "Services", + "middleware": "Middleware" + }, + "npm": { + "enabled": "Enabled", + "disabled": "Disabled", + "total": "Total" + }, + "coinmarketcap": { + "configure": "Configure one or more crypto currencies to track", + "1hour": "1 Hour", + "1day": "1 Day", + "7days": "7 Days", + "30days": "30 Days" + }, + "gotify": { + "apps": "Applications", + "clients": "Clients", + "messages": "Messages" + }, + "prowlarr": { + "enableIndexers": "Indexers", + "numberOfGrabs": "Grabs", + "numberOfQueries": "Queries", + "numberOfFailGrabs": "Fail Grabs", + "numberOfFailQueries": "Fail Queries" + }, + "jackett": { + "configured": "Configured", + "errored": "Errored" + }, + "strelaysrv": { + "numActiveSessions": "Sessions", + "numConnections": "Connections", + "dataRelayed": "Relayed", + "transferRate": "Rate" + }, + "mastodon": { + "user_count": "Users", + "status_count": "Posts", + "domain_count": "Domains" + }, + "authentik": { + "users": "Users", + "loginsLast24H": "Logins (24h)", + "failedLoginsLast24H": "Failed Logins (24h)" + } +} From 962e6e576cf933f68ac777772c54c9f357e1bc80 Mon Sep 17 00:00:00 2001 From: Jason Fischer Date: Tue, 4 Oct 2022 13:15:49 -0700 Subject: [PATCH 050/401] Add ErrorBoundary component - wrap a myriad of components in ErrorBoundary resolves #270 --- src/components/bookmarks/group.jsx | 3 ++- src/components/errorboundry.jsx | 41 ++++++++++++++++++++++++++++++ src/components/services/group.jsx | 3 ++- src/components/services/list.jsx | 3 ++- src/pages/index.jsx | 9 ++++--- 5 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 src/components/errorboundry.jsx diff --git a/src/components/bookmarks/group.jsx b/src/components/bookmarks/group.jsx index af510081..d4c05663 100644 --- a/src/components/bookmarks/group.jsx +++ b/src/components/bookmarks/group.jsx @@ -1,10 +1,11 @@ +import ErrorBoundary from "components/errorboundry"; import List from "components/bookmarks/list"; export default function BookmarksGroup({ group }) { return (

{group.name}

- +
); } diff --git a/src/components/errorboundry.jsx b/src/components/errorboundry.jsx new file mode 100644 index 00000000..ffee89ff --- /dev/null +++ b/src/components/errorboundry.jsx @@ -0,0 +1,41 @@ +import React from 'react'; + +export default class ErrorBoundary extends React.Component { + constructor(props) { + super(props); + this.state = { error: null, errorInfo: null }; + } + + componentDidCatch(error, errorInfo) { + // Catch errors in any components below and re-render with error message + this.setState({ + error, + errorInfo + }) + + // You can also log error messages to an error reporting service here + // eslint-disable-next-line no-console + console.error(error, errorInfo); + } + + render() { + const { error, errorInfo } = this.state; + if (errorInfo) { + // Error path + return ( +
+

Something went wrong.

+
+ {error && error.toString()} +
+ {errorInfo.componentStack} +
+
+ ); + } + + // Normally, just render children + const { children } = this.props; + return children; + } +} \ No newline at end of file diff --git a/src/components/services/group.jsx b/src/components/services/group.jsx index daae1909..373023c1 100644 --- a/src/components/services/group.jsx +++ b/src/components/services/group.jsx @@ -1,5 +1,6 @@ import classNames from "classnames"; +import ErrorBoundary from "components/errorboundry"; import List from "components/services/list"; export default function ServicesGroup({ services, layout }) { @@ -12,7 +13,7 @@ export default function ServicesGroup({ services, layout }) { )} >

{services.name}

- +
); } diff --git a/src/components/services/list.jsx b/src/components/services/list.jsx index 80b45592..a42a64a1 100644 --- a/src/components/services/list.jsx +++ b/src/components/services/list.jsx @@ -1,5 +1,6 @@ import classNames from "classnames"; +import ErrorBoundary from "components/errorboundry"; import Item from "components/services/item"; const columnMap = [ @@ -23,7 +24,7 @@ export default function List({ services, layout }) { )} > {services.map((service) => ( - + ))} ); diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 2a1c6e7d..c9661a07 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -8,6 +8,7 @@ import { useEffect, useContext, useState } from "react"; import { BiError } from "react-icons/bi"; import { serverSideTranslations } from "next-i18next/serverSideTranslations"; +import ErrorBoundary from "components/errorboundry"; import ServicesGroup from "components/services/group"; import BookmarksGroup from "components/bookmarks/group"; import Widget from "components/widgets/widget"; @@ -191,14 +192,14 @@ function Home({ initialSettings }) { {widgets .filter((widget) => !rightAlignedWidgets.includes(widget.type)) .map((widget, i) => ( - + ))}
{widgets .filter((widget) => rightAlignedWidgets.includes(widget.type)) .map((widget, i) => ( - + ))}
@@ -208,7 +209,7 @@ function Home({ initialSettings }) { {services && (
{services.map((group) => ( - + ))}
)} @@ -216,7 +217,7 @@ function Home({ initialSettings }) { {bookmarks && (
{bookmarks.map((group) => ( - + ))}
)} From a9fb458f19c1d3c8b40077579fd516a4f14c6379 Mon Sep 17 00:00:00 2001 From: Jason Fischer Date: Tue, 4 Oct 2022 21:46:48 -0700 Subject: [PATCH 051/401] Add Proxmox widget --- public/locales/en/common.json | 6 +++ src/utils/proxy/handlers/credentialed.js | 2 + src/widgets/components.js | 1 + src/widgets/proxmox/component.jsx | 53 ++++++++++++++++++++++++ src/widgets/proxmox/widget.js | 14 +++++++ src/widgets/widgets.js | 2 + 6 files changed, 78 insertions(+) create mode 100644 src/widgets/proxmox/component.jsx create mode 100644 src/widgets/proxmox/widget.js diff --git a/public/locales/en/common.json b/public/locales/en/common.json index d4634e80..dfc1a5ba 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -185,5 +185,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } diff --git a/src/utils/proxy/handlers/credentialed.js b/src/utils/proxy/handlers/credentialed.js index d14ef0e1..7418b68c 100644 --- a/src/utils/proxy/handlers/credentialed.js +++ b/src/utils/proxy/handlers/credentialed.js @@ -29,6 +29,8 @@ export default async function credentialedProxyHandler(req, res) { headers["X-gotify-Key"] = `${widget.key}`; } else if (widget.type === "authentik") { headers.Authorization = `Bearer ${widget.key}`; + } else if (widget.type === "proxmox") { + headers.Authorization = `PVEAPIToken=${widget.username}=${widget.password}`; } else { headers["X-API-Key"] = `${widget.key}`; } diff --git a/src/widgets/components.js b/src/widgets/components.js index fdfaa335..5357c070 100644 --- a/src/widgets/components.js +++ b/src/widgets/components.js @@ -20,6 +20,7 @@ const components = { pihole: dynamic(() => import("./pihole/component")), portainer: dynamic(() => import("./portainer/component")), prowlarr: dynamic(() => import("./prowlarr/component")), + proxmox: dynamic(() => import("./proxmox/component")), qbittorrent: dynamic(() => import("./qbittorrent/component")), radarr: dynamic(() => import("./radarr/component")), readarr: dynamic(() => import("./readarr/component")), diff --git a/src/widgets/proxmox/component.jsx b/src/widgets/proxmox/component.jsx new file mode 100644 index 00000000..9cdb26f7 --- /dev/null +++ b/src/widgets/proxmox/component.jsx @@ -0,0 +1,53 @@ +import { useTranslation } from "next-i18next"; + +import Container from "components/services/widget/container"; +import Block from "components/services/widget/block"; +import useWidgetAPI from "utils/proxy/use-widget-api"; + +function calcRunning(total, current) { + return current.status === "running" ? total + 1 : total; +} + +export default function Component({ service }) { + const { t } = useTranslation(); + + const { widget } = service; + + const { data: clusterData, error: clusterError } = useWidgetAPI(widget, "cluster/resources"); + + if (clusterError) { + return ; + } + + if (!clusterData || !clusterData.data) { + return ( + + + + + + + ); + } + + const { data } = clusterData ; + const vms = data.filter(item => item.type === "qemu") || []; + const lxc = data.filter(item => item.type === "lxc") || []; + const nodes = data.filter(item => item.type === "node") || []; + + const runningVMs = vms.reduce(calcRunning, 0); + const runningLXC = lxc.reduce(calcRunning, 0); + + // TODO: support more than one node + // TODO: better handling of cluster with zero nodes + const node = nodes.length > 0 ? nodes[0] : { cpu: 0.0, mem: 0, maxmem: 0 }; + + return ( + + + + + + + ); +} diff --git a/src/widgets/proxmox/widget.js b/src/widgets/proxmox/widget.js new file mode 100644 index 00000000..32d361e4 --- /dev/null +++ b/src/widgets/proxmox/widget.js @@ -0,0 +1,14 @@ +import credentialedProxyHandler from "utils/proxy/handlers/credentialed"; + +const widget = { + api: "{url}/api2/json/{endpoint}", + proxyHandler: credentialedProxyHandler, + + mappings: { + "cluster/resources": { + endpoint: "cluster/resources", + }, + }, +}; + +export default widget; diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js index 953b7417..04665c78 100644 --- a/src/widgets/widgets.js +++ b/src/widgets/widgets.js @@ -15,6 +15,7 @@ import overseerr from "./overseerr/widget"; import pihole from "./pihole/widget"; import portainer from "./portainer/widget"; import prowlarr from "./prowlarr/widget"; +import proxmox from "./proxmox/widget"; import qbittorrent from "./qbittorrent/widget"; import radarr from "./radarr/widget"; import readarr from "./readarr/widget"; @@ -46,6 +47,7 @@ const widgets = { pihole, portainer, prowlarr, + proxmox, qbittorrent, radarr, readarr, From ea969993771f08ff91832472bbfb49742a86d52f Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Wed, 5 Oct 2022 13:43:22 +0300 Subject: [PATCH 052/401] place error boundaries closer to the source --- src/components/errorboundry.jsx | 17 ++++++++--------- src/components/services/group.jsx | 3 +-- src/components/services/list.jsx | 3 +-- src/components/services/widget.jsx | 7 ++++++- src/components/widgets/widget.jsx | 8 +++++++- src/pages/index.jsx | 14 ++++++++------ 6 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/components/errorboundry.jsx b/src/components/errorboundry.jsx index ffee89ff..bad4b552 100644 --- a/src/components/errorboundry.jsx +++ b/src/components/errorboundry.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React from "react"; export default class ErrorBoundary extends React.Component { constructor(props) { @@ -10,8 +10,8 @@ export default class ErrorBoundary extends React.Component { // Catch errors in any components below and re-render with error message this.setState({ error, - errorInfo - }) + errorInfo, + }); // You can also log error messages to an error reporting service here // eslint-disable-next-line no-console @@ -23,11 +23,10 @@ export default class ErrorBoundary extends React.Component { if (errorInfo) { // Error path return ( -
-

Something went wrong.

-
- {error && error.toString()} -
+
+
Something went wrong.
+
+ {error && error.toString()} {errorInfo.componentStack}
@@ -38,4 +37,4 @@ export default class ErrorBoundary extends React.Component { const { children } = this.props; return children; } -} \ No newline at end of file +} diff --git a/src/components/services/group.jsx b/src/components/services/group.jsx index 373023c1..daae1909 100644 --- a/src/components/services/group.jsx +++ b/src/components/services/group.jsx @@ -1,6 +1,5 @@ import classNames from "classnames"; -import ErrorBoundary from "components/errorboundry"; import List from "components/services/list"; export default function ServicesGroup({ services, layout }) { @@ -13,7 +12,7 @@ export default function ServicesGroup({ services, layout }) { )} >

{services.name}

- +
); } diff --git a/src/components/services/list.jsx b/src/components/services/list.jsx index a42a64a1..80b45592 100644 --- a/src/components/services/list.jsx +++ b/src/components/services/list.jsx @@ -1,6 +1,5 @@ import classNames from "classnames"; -import ErrorBoundary from "components/errorboundry"; import Item from "components/services/item"; const columnMap = [ @@ -24,7 +23,7 @@ export default function List({ services, layout }) { )} > {services.map((service) => ( - + ))} ); diff --git a/src/components/services/widget.jsx b/src/components/services/widget.jsx index f6ae4204..3a7463ac 100644 --- a/src/components/services/widget.jsx +++ b/src/components/services/widget.jsx @@ -1,5 +1,6 @@ import { useTranslation } from "next-i18next"; +import ErrorBoundary from "components/errorboundry"; import components from "widgets/components"; export default function Widget({ service }) { @@ -8,7 +9,11 @@ export default function Widget({ service }) { const ServiceWidget = components[service.widget.type]; if (ServiceWidget) { - return ; + return ( + + + + ); } return ( diff --git a/src/components/widgets/widget.jsx b/src/components/widgets/widget.jsx index a5ed1eb3..de3f7a35 100644 --- a/src/components/widgets/widget.jsx +++ b/src/components/widgets/widget.jsx @@ -1,5 +1,7 @@ import dynamic from "next/dynamic"; +import ErrorBoundary from "components/errorboundry"; + const widgetMappings = { weatherapi: dynamic(() => import("components/widgets/weather/weather")), openweathermap: dynamic(() => import("components/widgets/openweathermap/weather")), @@ -13,7 +15,11 @@ export default function Widget({ widget }) { const InfoWidget = widgetMappings[widget.type]; if (InfoWidget) { - return ; + return ( + + + + ); } return ( diff --git a/src/pages/index.jsx b/src/pages/index.jsx index c9661a07..cb534813 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -8,7 +8,6 @@ import { useEffect, useContext, useState } from "react"; import { BiError } from "react-icons/bi"; import { serverSideTranslations } from "next-i18next/serverSideTranslations"; -import ErrorBoundary from "components/errorboundry"; import ServicesGroup from "components/services/group"; import BookmarksGroup from "components/bookmarks/group"; import Widget from "components/widgets/widget"; @@ -20,6 +19,7 @@ import { ColorContext } from "utils/contexts/color"; import { ThemeContext } from "utils/contexts/theme"; import { SettingsContext } from "utils/contexts/settings"; import { bookmarksResponse, servicesResponse, widgetsResponse } from "utils/config/api-response"; +import ErrorBoundary from "components/errorboundry"; const ThemeToggle = dynamic(() => import("components/toggles/theme"), { ssr: false, @@ -145,7 +145,9 @@ function Index({ initialSettings, fallback }) { return ( fetch(resource, init).then((res) => res.json()) }}> - + + + ); } @@ -192,14 +194,14 @@ function Home({ initialSettings }) { {widgets .filter((widget) => !rightAlignedWidgets.includes(widget.type)) .map((widget, i) => ( - + ))}
{widgets .filter((widget) => rightAlignedWidgets.includes(widget.type)) .map((widget, i) => ( - + ))}
@@ -209,7 +211,7 @@ function Home({ initialSettings }) { {services && (
{services.map((group) => ( - + ))}
)} @@ -217,7 +219,7 @@ function Home({ initialSettings }) { {bookmarks && (
{bookmarks.map((group) => ( - + ))}
)} From 892c68856fdcee711cf5fbde21b551d91523e964 Mon Sep 17 00:00:00 2001 From: Kai Huuhko Date: Tue, 4 Oct 2022 12:44:24 +0000 Subject: [PATCH 053/401] Translated using Weblate (Finnish) Currently translated at 100.0% (119 of 119 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fi/ --- public/locales/fi/common.json | 210 +++++++++++++++++----------------- 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/public/locales/fi/common.json b/public/locales/fi/common.json index c2d48369..c19e8546 100644 --- a/public/locales/fi/common.json +++ b/public/locales/fi/common.json @@ -1,178 +1,178 @@ { "widget": { - "missing_type": "Missing Widget Type: {{type}}", - "api_error": "API Error", - "status": "Status" + "missing_type": "Puuttuva härpäkkeen tyyppi: {{type}}", + "api_error": "API-virhe", + "status": "Tila" }, "weather": { - "current": "Current Location", - "allow": "Click to allow", - "updating": "Updating", - "wait": "Please wait" + "current": "Nykyinen sijainti", + "allow": "Klikkaa salliaksesi", + "updating": "Päivitetään", + "wait": "Odota, ole hyvä" }, "search": { - "placeholder": "Search…" + "placeholder": "Hae…" }, "resources": { "cpu": "CPU", - "total": "Total", - "free": "Free", - "used": "Used", - "load": "Load" + "total": "Yhteensä", + "free": "Vapaana", + "used": "Käytetty", + "load": "Kuorma" }, "docker": { "rx": "RX", "tx": "TX", - "mem": "MEM", + "mem": "RAM", "cpu": "CPU", "offline": "Offline" }, "emby": { - "playing": "Playing", - "transcoding": "Transcoding", - "bitrate": "Bitrate", - "no_active": "No Active Streams" + "playing": "Toistaa", + "transcoding": "Transkoodaa", + "bitrate": "Bittinopeus", + "no_active": "Ei aktiivisia striimejä" }, "tautulli": { - "playing": "Playing", - "transcoding": "Transcoding", - "bitrate": "Bitrate", - "no_active": "No Active Streams" + "playing": "Toistaa", + "transcoding": "Transkoodaa", + "bitrate": "Bittinopeus", + "no_active": "Ei aktiivisia striimejä" }, "nzbget": { - "rate": "Rate", - "remaining": "Remaining", - "downloaded": "Downloaded" + "rate": "Nopeus", + "remaining": "Jäljellä", + "downloaded": "Ladattu" }, "sabnzbd": { - "rate": "Rate", - "queue": "Queue", - "timeleft": "Time Left" + "rate": "Nopeus", + "queue": "Jono", + "timeleft": "Aikaa jäljellä" }, "rutorrent": { - "active": "Active", - "upload": "Upload", - "download": "Download" + "active": "Aktiivinen", + "upload": "Lähetys", + "download": "Lataus" }, "transmission": { - "download": "Download", - "upload": "Upload", - "leech": "Leech", - "seed": "Seed" + "download": "Lataus", + "upload": "Lähetys", + "leech": "Lataajia", + "seed": "Lähettäjiä" }, "qbittorrent": { - "download": "Download", - "upload": "Upload", - "leech": "Leech", - "seed": "Seed" + "download": "Lataus", + "upload": "Lähetys", + "leech": "Lataajia", + "seed": "Lähettäjiä" }, "sonarr": { - "wanted": "Wanted", - "queued": "Queued", - "series": "Series" + "wanted": "Haluttu", + "queued": "Jonossa", + "series": "Sarja" }, "radarr": { - "wanted": "Wanted", - "queued": "Queued", - "movies": "Movies" + "wanted": "Haluttu", + "queued": "Jonossa", + "movies": "Elokuvia" }, "lidarr": { - "wanted": "Wanted", - "queued": "Queued", - "albums": "Albums" + "wanted": "Haluttu", + "queued": "Jonossa", + "albums": "Albumeja" }, "readarr": { - "wanted": "Wanted", - "queued": "Queued", - "books": "Books" + "wanted": "Haluttu", + "queued": "Jonossa", + "books": "Kirjoja" }, "bazarr": { - "missingEpisodes": "Missing Episodes", - "missingMovies": "Missing Movies" + "missingEpisodes": "Puuttuvia jaksoja", + "missingMovies": "Puuttuvia elokuvia" }, "ombi": { - "pending": "Pending", - "approved": "Approved", - "available": "Available" + "pending": "Vireillä", + "approved": "Hyväksytty", + "available": "Saatavilla" }, "jellyseerr": { - "pending": "Pending", - "approved": "Approved", - "available": "Available" + "pending": "Vireillä", + "approved": "Hyväksytty", + "available": "Saatavilla" }, "overseerr": { - "pending": "Pending", - "approved": "Approved", - "available": "Available" + "pending": "Vireillä", + "approved": "Hyväksytty", + "available": "Saatavilla" }, "pihole": { - "queries": "Queries", - "blocked": "Blocked", - "gravity": "Gravity" + "queries": "Kyselyjä", + "blocked": "Estetty", + "gravity": "Vakavuus" }, "adguard": { - "queries": "Queries", - "blocked": "Blocked", - "filtered": "Filtered", - "latency": "Latency" + "queries": "Kyselyjä", + "blocked": "Estetty", + "filtered": "Suodatettu", + "latency": "Viive" }, "speedtest": { - "upload": "Upload", - "download": "Download", - "ping": "Ping" + "upload": "Lähetys", + "download": "Lataus", + "ping": "Viive" }, "portainer": { - "running": "Running", - "stopped": "Stopped", - "total": "Total" + "running": "Käynnissä", + "stopped": "Pysäytetty", + "total": "Yhteensä" }, "traefik": { - "routers": "Routers", - "services": "Services", - "middleware": "Middleware" + "routers": "Reitittimiä", + "services": "Palveluja", + "middleware": "Middlewareja" }, "npm": { - "enabled": "Enabled", - "disabled": "Disabled", - "total": "Total" + "enabled": "Käytössä", + "disabled": "Poissa käytöstä", + "total": "Yhteensä" }, "coinmarketcap": { - "configure": "Configure one or more crypto currencies to track", - "1hour": "1 Hour", - "1day": "1 Day", - "7days": "7 Days", - "30days": "30 Days" + "configure": "Määritä yksi tai useampi kryptovaluutta seurattavaksi", + "1hour": "1 tunti", + "1day": "1 päivä", + "7days": "7 päivää", + "30days": "30 päivää" }, "gotify": { - "apps": "Applications", - "clients": "Clients", - "messages": "Messages" + "apps": "Sovelluksia", + "clients": "Asiakasohjelmia", + "messages": "Viestejä" }, "prowlarr": { - "enableIndexers": "Indexers", - "numberOfGrabs": "Grabs", - "numberOfQueries": "Queries", - "numberOfFailGrabs": "Fail Grabs", - "numberOfFailQueries": "Fail Queries" + "enableIndexers": "Indeksoijia", + "numberOfGrabs": "Nappauksia", + "numberOfQueries": "Hakuja", + "numberOfFailGrabs": "Epäonnistuneita nappauksia", + "numberOfFailQueries": "Epäonnistuneita kyselyjä" }, "jackett": { - "configured": "Configured", - "errored": "Errored" + "configured": "Määritettyjä", + "errored": "Virheellisiä" }, "strelaysrv": { - "numActiveSessions": "Sessions", - "numConnections": "Connections", - "dataRelayed": "Relayed", - "transferRate": "Rate" + "numActiveSessions": "Istuntoja", + "numConnections": "Yhteyksiä", + "dataRelayed": "Välitetty", + "transferRate": "Nopeus" }, "mastodon": { - "user_count": "Users", - "status_count": "Posts", - "domain_count": "Domains" + "user_count": "Käyttäjiä", + "status_count": "Kirjoituksia", + "domain_count": "Verkkotunnuksia" }, "authentik": { - "users": "Users", - "loginsLast24H": "Logins (24h)", - "failedLoginsLast24H": "Failed Logins (24h)" + "users": "Käyttäjiä", + "loginsLast24H": "Kirjautumisia (24h)", + "failedLoginsLast24H": "Epäonnistuneita kirjautumisia (24h)" } } From fa71586a50ccbdae85e56c09847900ec9099d56b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:07 +0000 Subject: [PATCH 054/401] Translated using Weblate (German) Currently translated at 95.9% (118 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/ --- public/locales/de/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/de/common.json b/public/locales/de/common.json index d3a7a55b..0b84664f 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -174,5 +174,11 @@ "users": "Benutzer", "loginsLast24H": "Anmeldungen (24h)", "failedLoginsLast24H": "fehlerhafte Anmeldungen (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 6a0a87279080af040a7d2381bdc10ffbabf992f2 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:07 +0000 Subject: [PATCH 055/401] Translated using Weblate (Spanish) Currently translated at 96.7% (119 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/ --- public/locales/es/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 01497d0f..fe9a7253 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -174,5 +174,11 @@ "users": "Usuarios", "loginsLast24H": "Inicios de sesión (24h)", "failedLoginsLast24H": "Inicios de sesión fallidos (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 6dacd1bdd60d9c886f784daca973df0d2d8f3836 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:07 +0000 Subject: [PATCH 056/401] Translated using Weblate (French) Currently translated at 96.7% (119 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/ --- public/locales/fr/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json index 4040e9a0..c0a72e95 100644 --- a/public/locales/fr/common.json +++ b/public/locales/fr/common.json @@ -174,5 +174,11 @@ "users": "Utilisateurs", "loginsLast24H": "Cnx. (24h)", "failedLoginsLast24H": "Cnx. échouées (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 193b548d0b59c0d1d31daf1ceb8f24dce81bccda Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:07 +0000 Subject: [PATCH 057/401] Translated using Weblate (Portuguese) Currently translated at 93.4% (115 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt/ --- public/locales/pt/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/pt/common.json b/public/locales/pt/common.json index 36e41199..fc7b3c9c 100644 --- a/public/locales/pt/common.json +++ b/public/locales/pt/common.json @@ -185,5 +185,11 @@ "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)", "users": "Users" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 969dab9971660ce205efb00f338e3edbcdb5a039 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:07 +0000 Subject: [PATCH 058/401] Translated using Weblate (Russian) Currently translated at 18.6% (23 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ru/ --- public/locales/ru/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/ru/common.json b/public/locales/ru/common.json index 9b9e54d4..d06131fd 100644 --- a/public/locales/ru/common.json +++ b/public/locales/ru/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 935f97415f07fb4708f05470eb7c71be160831da Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:07 +0000 Subject: [PATCH 059/401] Translated using Weblate (Chinese (Simplified)) Currently translated at 88.6% (109 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/ --- public/locales/zh-CN/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/zh-CN/common.json b/public/locales/zh-CN/common.json index 9e35011d..4fcc1702 100644 --- a/public/locales/zh-CN/common.json +++ b/public/locales/zh-CN/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 40a11bd9ced275fa2f7581db3664ba1c2abb30e0 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:08 +0000 Subject: [PATCH 060/401] Translated using Weblate (Italian) Currently translated at 62.6% (77 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/it/ --- public/locales/it/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/it/common.json b/public/locales/it/common.json index be0f3d45..09f32213 100644 --- a/public/locales/it/common.json +++ b/public/locales/it/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 45fb059e712a012f3c613ee64028e2c0ee79d9dd Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:06 +0000 Subject: [PATCH 061/401] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegi?= =?UTF-8?q?an=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 64.2% (79 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nb_NO/ --- public/locales/nb-NO/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/nb-NO/common.json b/public/locales/nb-NO/common.json index 2fa34338..cea70d93 100644 --- a/public/locales/nb-NO/common.json +++ b/public/locales/nb-NO/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 01d005dbbebdf59b9bd0f72b34c078484792e155 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:08 +0000 Subject: [PATCH 062/401] Translated using Weblate (Vietnamese) Currently translated at 35.7% (44 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/vi/ --- public/locales/vi/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/vi/common.json b/public/locales/vi/common.json index 492b8545..736120cf 100644 --- a/public/locales/vi/common.json +++ b/public/locales/vi/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 8f6ea7b49f04054eac052669c1b327dc69a37a5f Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:08 +0000 Subject: [PATCH 063/401] Translated using Weblate (Dutch) Currently translated at 51.2% (63 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nl/ --- public/locales/nl/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/nl/common.json b/public/locales/nl/common.json index 7b98ba7b..b13cd912 100644 --- a/public/locales/nl/common.json +++ b/public/locales/nl/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 593d8a1cbc602240d917babd4c47d3c99c3359a2 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:08 +0000 Subject: [PATCH 064/401] Translated using Weblate (Chinese (Traditional)) Currently translated at 7.3% (9 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hant/ --- public/locales/zh-Hant/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/zh-Hant/common.json b/public/locales/zh-Hant/common.json index 61317f0d..70dba911 100644 --- a/public/locales/zh-Hant/common.json +++ b/public/locales/zh-Hant/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 528ce1a5fe65d3b00c6931b06e6b55810573477d Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:06 +0000 Subject: [PATCH 065/401] Translated using Weblate (Catalan) Currently translated at 96.7% (119 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/ --- public/locales/ca/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/ca/common.json b/public/locales/ca/common.json index b2dea57a..8ef784cb 100644 --- a/public/locales/ca/common.json +++ b/public/locales/ca/common.json @@ -174,5 +174,11 @@ "users": "Usuaris", "loginsLast24H": "Inicis de sessió (24h)", "failedLoginsLast24H": "Errors d'inici de sessió (24h)" + }, + "proxmox": { + "vms": "VMs", + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC" } } From b380fd23069073430528d4a85ce7159dd505d21c Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:06 +0000 Subject: [PATCH 066/401] Translated using Weblate (Polish) Currently translated at 79.6% (98 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pl/ --- public/locales/pl/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/pl/common.json b/public/locales/pl/common.json index 27f1772d..4eb9ffa1 100644 --- a/public/locales/pl/common.json +++ b/public/locales/pl/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From f44b564bb53d2826268c1bd9d3dccd8c25514a33 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:04 +0000 Subject: [PATCH 067/401] Translated using Weblate (Swedish) Currently translated at 86.9% (107 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sv/ --- public/locales/sv/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/sv/common.json b/public/locales/sv/common.json index 96b481e2..c42ecabb 100644 --- a/public/locales/sv/common.json +++ b/public/locales/sv/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 6f5a0ea6b861842bd25f99b4eaac003ab1f7832c Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:04 +0000 Subject: [PATCH 068/401] Translated using Weblate (Croatian) Currently translated at 93.4% (115 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hr/ --- public/locales/hr/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/hr/common.json b/public/locales/hr/common.json index 74b589c5..36b970a0 100644 --- a/public/locales/hr/common.json +++ b/public/locales/hr/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 292c6dd6b0f70bbb8753c32b54990cd6e2c09ffa Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:06 +0000 Subject: [PATCH 069/401] Translated using Weblate (Hungarian) Currently translated at 87.8% (108 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hu/ --- public/locales/hu/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/hu/common.json b/public/locales/hu/common.json index d40c2d4a..ac4d7fff 100644 --- a/public/locales/hu/common.json +++ b/public/locales/hu/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 1ffe7da9b71b8168a63e9a5a318714e5a5ac9cc8 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:04 +0000 Subject: [PATCH 070/401] Translated using Weblate (Hebrew) Currently translated at 82.1% (101 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/he/ --- public/locales/he/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/he/common.json b/public/locales/he/common.json index 82186604..9414f038 100644 --- a/public/locales/he/common.json +++ b/public/locales/he/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 031f11c5c1e9011a9860c2367c6d83c78b229552 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:05 +0000 Subject: [PATCH 071/401] Translated using Weblate (Romanian) Currently translated at 95.9% (118 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ro/ --- public/locales/ro/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/ro/common.json b/public/locales/ro/common.json index de3ad552..eaa9af3a 100644 --- a/public/locales/ro/common.json +++ b/public/locales/ro/common.json @@ -174,5 +174,11 @@ "users": "Utilizatori", "loginsLast24H": "Autentificări (24h)", "failedLoginsLast24H": "Conectări eșuate (24h)" + }, + "proxmox": { + "vms": "VMs", + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC" } } From b8d00f24f7ca51506e610946124c96f4f840a222 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:05 +0000 Subject: [PATCH 072/401] Translated using Weblate (Portuguese (Brazil)) Currently translated at 93.4% (115 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt_BR/ --- public/locales/pt-BR/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/pt-BR/common.json b/public/locales/pt-BR/common.json index cbf95cfd..5596ac64 100644 --- a/public/locales/pt-BR/common.json +++ b/public/locales/pt-BR/common.json @@ -174,5 +174,11 @@ "users": "Users", "loginsLast24H": "Logins (24h)", "failedLoginsLast24H": "Failed Logins (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From 00eb768cdf1768833b5f4571174a382ee4cc805e Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:05 +0000 Subject: [PATCH 073/401] Translated using Weblate (Yue) Currently translated at 95.9% (118 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/yue/ --- public/locales/yue/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/yue/common.json b/public/locales/yue/common.json index 848c6151..72e2ddde 100644 --- a/public/locales/yue/common.json +++ b/public/locales/yue/common.json @@ -174,5 +174,11 @@ "users": "用戶", "loginsLast24H": "登錄( 24小时)", "failedLoginsLast24H": "登錄失敗( 24鐘頭)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From adf601c572543e4582fa907f13e50f929aecdcc6 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 5 Oct 2022 15:56:06 +0000 Subject: [PATCH 074/401] Translated using Weblate (Finnish) Currently translated at 96.7% (119 of 123 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fi/ --- public/locales/fi/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/locales/fi/common.json b/public/locales/fi/common.json index c19e8546..133a0f32 100644 --- a/public/locales/fi/common.json +++ b/public/locales/fi/common.json @@ -174,5 +174,11 @@ "users": "Käyttäjiä", "loginsLast24H": "Kirjautumisia (24h)", "failedLoginsLast24H": "Epäonnistuneita kirjautumisia (24h)" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" } } From b9b9449cd33f42f86bed269babe6ead24b5f5cb9 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+shamoon@users.noreply.github.com> Date: Wed, 5 Oct 2022 21:36:43 -0700 Subject: [PATCH 075/401] Add unifi_console widget, API endpoint --- package.json | 1 + pnpm-lock.yaml | 101 ++++++++++++++++++ public/locales/en/common.json | 7 ++ .../widgets/unifi_console/unifi_console.jsx | 96 +++++++++++++++++ src/components/widgets/widget.jsx | 1 + src/pages/api/widgets/unifi.js | 53 +++++++++ 6 files changed, 259 insertions(+) create mode 100644 src/components/widgets/unifi_console/unifi_console.jsx create mode 100644 src/pages/api/widgets/unifi.js diff --git a/package.json b/package.json index 3dd2ed0d..0ee4cf2b 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "next": "^12.3.1", "next-i18next": "^12.0.1", "node-os-utils": "^1.3.7", + "node-unifi": "^2.1.0", "pretty-bytes": "^6.0.0", "raw-body": "^2.5.1", "react": "^18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49394c8e..c6cbeb98 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,6 +24,7 @@ specifiers: next: ^12.3.1 next-i18next: ^12.0.1 node-os-utils: ^1.3.7 + node-unifi: ^2.1.0 postcss: ^8.4.16 prettier: ^2.7.1 pretty-bytes: ^6.0.0 @@ -54,6 +55,7 @@ dependencies: next: 12.3.1_biqbaboplfbrettd7655fr4n2y next-i18next: 12.0.1_azq6kxkn3od7qdylwkyksrwopy node-os-utils: 1.3.7 + node-unifi: 2.1.0 pretty-bytes: 6.0.0 raw-body: 2.5.1 react: 18.2.0 @@ -458,6 +460,15 @@ packages: hasBin: true dev: true + /agent-base/6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /ajv/6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: @@ -577,6 +588,15 @@ packages: engines: {node: '>=4'} dev: true + /axios/0.27.2: + resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} + dependencies: + follow-redirects: 1.15.2 + form-data: 4.0.0 + transitivePeerDependencies: + - debug + dev: false + /axobject-query/2.2.0: resolution: {integrity: sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==} dev: true @@ -1394,6 +1414,10 @@ packages: engines: {node: '>=0.10.0'} dev: true + /eventemitter2/6.4.9: + resolution: {integrity: sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==} + dev: false + /fast-deep-equal/3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -1488,6 +1512,15 @@ packages: mime-types: 2.1.35 dev: false + /form-data/4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + /fraction.js/4.2.0: resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} dev: true @@ -1647,6 +1680,25 @@ packages: void-elements: 3.1.0 dev: false + /http-cookie-agent/4.0.2_tough-cookie@4.1.2: + resolution: {integrity: sha512-noTmxdH5CuytTnLj/Qv3Z84e/YFq8yLXAw3pqIYZ25Edhb9pQErIAC+ednw40Cic6Le/h9ryph5/TqsvkOaUCw==} + engines: {node: '>=14.18.0 <15.0.0 || >=16.0.0'} + peerDependencies: + deasync: ^0.1.26 + tough-cookie: ^4.0.0 + undici: ^5.1.1 + peerDependenciesMeta: + deasync: + optional: true + undici: + optional: true + dependencies: + agent-base: 6.0.2 + tough-cookie: 4.1.2 + transitivePeerDependencies: + - supports-color + dev: false + /http-errors/2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} @@ -2090,6 +2142,25 @@ packages: resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} dev: true + /node-unifi/2.1.0: + resolution: {integrity: sha512-vawHGIFEc5XgCXo2I98h72pykVklemI5eE1d50oRZOLpfnYLVDNWF2RfdhvaRSHtVpPjFRshqJP2zuOSWnq4+A==} + engines: {node: '>=14.18.0 <15.0.0 || >=16.0.0'} + dependencies: + axios: 0.27.2 + eventemitter2: 6.4.9 + http-cookie-agent: 4.0.2_tough-cookie@4.1.2 + tough-cookie: 4.1.2 + url: 0.11.0 + ws: 8.9.0 + transitivePeerDependencies: + - bufferutil + - deasync + - debug + - supports-color + - undici + - utf-8-validate + dev: false + /normalize-path/3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -2365,10 +2436,20 @@ packages: once: 1.4.0 dev: false + /punycode/1.3.2: + resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==} + dev: false + /punycode/2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} + /querystring/0.2.0: + resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==} + engines: {node: '>=0.4.x'} + deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. + dev: false + /querystringify/2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} dev: false @@ -2921,6 +3002,13 @@ packages: requires-port: 1.0.0 dev: false + /url/0.11.0: + resolution: {integrity: sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==} + dependencies: + punycode: 1.3.2 + querystring: 0.2.0 + dev: false + /use-sync-external-store/1.2.0_react@18.2.0: resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} peerDependencies: @@ -3000,6 +3088,19 @@ packages: /wrappy/1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + /ws/8.9.0: + resolution: {integrity: sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /xtend/4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} diff --git a/public/locales/en/common.json b/public/locales/en/common.json index dfc1a5ba..f1912008 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -31,6 +31,13 @@ "used": "Used", "load": "Load" }, + "unifi": { + "users": "Users", + "status": "Status", + "days": "Days", + "wan": "WAN", + "wait": "Please wait" + }, "docker": { "rx": "RX", "tx": "TX", diff --git a/src/components/widgets/unifi_console/unifi_console.jsx b/src/components/widgets/unifi_console/unifi_console.jsx new file mode 100644 index 00000000..7e0ff7fc --- /dev/null +++ b/src/components/widgets/unifi_console/unifi_console.jsx @@ -0,0 +1,96 @@ +import useSWR from "swr"; +import { BiError, BiWifi, BiCheckCircle } from "react-icons/bi"; +import { MdSettingsEthernet } from "react-icons/md"; +import { useTranslation } from "next-i18next"; +import { SiUbiquiti } from "react-icons/si"; + +export default function Widget({ options }) { + const { t, i18n } = useTranslation(); + + const { data, error } = useSWR( + `/api/widgets/unifi?${new URLSearchParams({ lang: i18n.language, ...options }).toString()}` + ); + + if (error || data?.error) { + return ( +
+
+
+ +
+ {t("widget.api_error")} + - +
+
+
+
+ ); + } + + if (!data) { + return ( +
+
+
+ +
+
+ {t("unifi.wait")} +
+
+
+ ); + } + + return ( +
+
+
+ +
+ {data.name} +
+
+
+
+
+ {t("common.number", { + value: data.uptime / 86400, + maximumFractionDigits: 1, + })} +
+
{t("unifi.days")}
+
+
+
{t("unifi.wan")}
+ +
+
+
+
+
+ +
+
+ {t("common.number", { + value: data.wlan.users, + maximumFractionDigits: 0, + })} +
+
+
+
+ +
+
+ {t("common.number", { + value: data.lan.users, + maximumFractionDigits: 0, + })} +
+
+
+
+
+ ); +} diff --git a/src/components/widgets/widget.jsx b/src/components/widgets/widget.jsx index de3f7a35..8daa8724 100644 --- a/src/components/widgets/widget.jsx +++ b/src/components/widgets/widget.jsx @@ -9,6 +9,7 @@ const widgetMappings = { search: dynamic(() => import("components/widgets/search/search")), greeting: dynamic(() => import("components/widgets/greeting/greeting")), datetime: dynamic(() => import("components/widgets/datetime/datetime")), + unifi_console: dynamic(() => import("components/widgets/unifi_console/unifi_console")), }; export default function Widget({ widget }) { diff --git a/src/pages/api/widgets/unifi.js b/src/pages/api/widgets/unifi.js new file mode 100644 index 00000000..f8cbcc1e --- /dev/null +++ b/src/pages/api/widgets/unifi.js @@ -0,0 +1,53 @@ +import { Controller } from "node-unifi"; + +export default async function handler(req, res) { + const { host, port, username, password } = req.query; + + if (!host) { + return res.status(400).json({ error: "Missing host" }); + } + + if (!username) { + return res.status(400).json({ error: "Missing username" }); + } + + if (!password) { + return res.status(400).json({ error: "Missing password" }); + } + + const controller = new Controller({ + host: host, + port: port, + sslverify: false + }); + + try { + //login to the controller + await controller.login(username, password); + + //retrieve sites + const sites = await controller.getSitesStats(); + const default_site = sites.find(s => s.name == "default"); + const wan = default_site.health.find(h => h.subsystem == "wan"); + const lan = default_site.health.find(h => h.subsystem == "lan"); + const wlan = default_site.health.find(h => h.subsystem == "wlan"); + + return res.status(200).json({ + name: wan.gw_name, + uptime: wan['gw_system-stats']['uptime'], + up: wan.status == 'ok', + wlan: { + users: wlan.num_user, + status: wlan.status + }, + lan: { + users: lan.num_user, + status: lan.status + } + }); + } catch (e) { + return res.status(400).json({ + error: `Error communicating with UniFi Console: ${e.message}` + }) + } +} From 5ba75bc62d80d7761791e85aa2d7bb854c6ecba4 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+shamoon@users.noreply.github.com> Date: Wed, 5 Oct 2022 21:41:39 -0700 Subject: [PATCH 076/401] support wan down too --- src/components/widgets/unifi_console/unifi_console.jsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/widgets/unifi_console/unifi_console.jsx b/src/components/widgets/unifi_console/unifi_console.jsx index 7e0ff7fc..ee8cfa45 100644 --- a/src/components/widgets/unifi_console/unifi_console.jsx +++ b/src/components/widgets/unifi_console/unifi_console.jsx @@ -1,5 +1,5 @@ import useSWR from "swr"; -import { BiError, BiWifi, BiCheckCircle } from "react-icons/bi"; +import { BiError, BiWifi, BiCheckCircle, BiXCircle } from "react-icons/bi"; import { MdSettingsEthernet } from "react-icons/md"; import { useTranslation } from "next-i18next"; import { SiUbiquiti } from "react-icons/si"; @@ -63,7 +63,10 @@ export default function Widget({ options }) {
{t("unifi.wan")}
- + { data.up + ? + : + }
From 952f0295cc69da7cbfb7b90072e8ed8692aa8a0b Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+shamoon@users.noreply.github.com> Date: Wed, 5 Oct 2022 21:44:15 -0700 Subject: [PATCH 077/401] uptime label --- public/locales/en/common.json | 2 +- src/components/widgets/unifi_console/unifi_console.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index f1912008..af8fc197 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -33,7 +33,7 @@ }, "unifi": { "users": "Users", - "status": "Status", + "uptime": "System Uptime", "days": "Days", "wan": "WAN", "wait": "Please wait" diff --git a/src/components/widgets/unifi_console/unifi_console.jsx b/src/components/widgets/unifi_console/unifi_console.jsx index ee8cfa45..484982c8 100644 --- a/src/components/widgets/unifi_console/unifi_console.jsx +++ b/src/components/widgets/unifi_console/unifi_console.jsx @@ -52,7 +52,7 @@ export default function Widget({ options }) {
-
+
{t("common.number", { value: data.uptime / 86400, From ac4dcd32222650113aac19d56c4f8261f0264ae8 Mon Sep 17 00:00:00 2001 From: Jason Fischer Date: Fri, 7 Oct 2022 17:12:29 -0700 Subject: [PATCH 078/401] Remove node-unifi package dependency - Add custom Unifi proxy built on existing cookie jar and httpProxy - Change formatApiCall to emit empty string instead of undefined on missing key --- package.json | 1 - pnpm-lock.yaml | 101 ----------------- .../widgets/unifi_console/unifi_console.jsx | 34 ++++-- src/pages/api/widgets/unifi.js | 53 --------- src/utils/proxy/api-helpers.js | 2 +- src/widgets/unifi/proxy.js | 103 ++++++++++++++++++ src/widgets/unifi/widget.js | 14 +++ src/widgets/widgets.js | 3 + 8 files changed, 148 insertions(+), 163 deletions(-) delete mode 100644 src/pages/api/widgets/unifi.js create mode 100644 src/widgets/unifi/proxy.js create mode 100644 src/widgets/unifi/widget.js diff --git a/package.json b/package.json index 0ee4cf2b..3dd2ed0d 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "next": "^12.3.1", "next-i18next": "^12.0.1", "node-os-utils": "^1.3.7", - "node-unifi": "^2.1.0", "pretty-bytes": "^6.0.0", "raw-body": "^2.5.1", "react": "^18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c6cbeb98..49394c8e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,7 +24,6 @@ specifiers: next: ^12.3.1 next-i18next: ^12.0.1 node-os-utils: ^1.3.7 - node-unifi: ^2.1.0 postcss: ^8.4.16 prettier: ^2.7.1 pretty-bytes: ^6.0.0 @@ -55,7 +54,6 @@ dependencies: next: 12.3.1_biqbaboplfbrettd7655fr4n2y next-i18next: 12.0.1_azq6kxkn3od7qdylwkyksrwopy node-os-utils: 1.3.7 - node-unifi: 2.1.0 pretty-bytes: 6.0.0 raw-body: 2.5.1 react: 18.2.0 @@ -460,15 +458,6 @@ packages: hasBin: true dev: true - /agent-base/6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: false - /ajv/6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: @@ -588,15 +577,6 @@ packages: engines: {node: '>=4'} dev: true - /axios/0.27.2: - resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} - dependencies: - follow-redirects: 1.15.2 - form-data: 4.0.0 - transitivePeerDependencies: - - debug - dev: false - /axobject-query/2.2.0: resolution: {integrity: sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==} dev: true @@ -1414,10 +1394,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /eventemitter2/6.4.9: - resolution: {integrity: sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==} - dev: false - /fast-deep-equal/3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -1512,15 +1488,6 @@ packages: mime-types: 2.1.35 dev: false - /form-data/4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: false - /fraction.js/4.2.0: resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} dev: true @@ -1680,25 +1647,6 @@ packages: void-elements: 3.1.0 dev: false - /http-cookie-agent/4.0.2_tough-cookie@4.1.2: - resolution: {integrity: sha512-noTmxdH5CuytTnLj/Qv3Z84e/YFq8yLXAw3pqIYZ25Edhb9pQErIAC+ednw40Cic6Le/h9ryph5/TqsvkOaUCw==} - engines: {node: '>=14.18.0 <15.0.0 || >=16.0.0'} - peerDependencies: - deasync: ^0.1.26 - tough-cookie: ^4.0.0 - undici: ^5.1.1 - peerDependenciesMeta: - deasync: - optional: true - undici: - optional: true - dependencies: - agent-base: 6.0.2 - tough-cookie: 4.1.2 - transitivePeerDependencies: - - supports-color - dev: false - /http-errors/2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} @@ -2142,25 +2090,6 @@ packages: resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} dev: true - /node-unifi/2.1.0: - resolution: {integrity: sha512-vawHGIFEc5XgCXo2I98h72pykVklemI5eE1d50oRZOLpfnYLVDNWF2RfdhvaRSHtVpPjFRshqJP2zuOSWnq4+A==} - engines: {node: '>=14.18.0 <15.0.0 || >=16.0.0'} - dependencies: - axios: 0.27.2 - eventemitter2: 6.4.9 - http-cookie-agent: 4.0.2_tough-cookie@4.1.2 - tough-cookie: 4.1.2 - url: 0.11.0 - ws: 8.9.0 - transitivePeerDependencies: - - bufferutil - - deasync - - debug - - supports-color - - undici - - utf-8-validate - dev: false - /normalize-path/3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -2436,20 +2365,10 @@ packages: once: 1.4.0 dev: false - /punycode/1.3.2: - resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==} - dev: false - /punycode/2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} - /querystring/0.2.0: - resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==} - engines: {node: '>=0.4.x'} - deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. - dev: false - /querystringify/2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} dev: false @@ -3002,13 +2921,6 @@ packages: requires-port: 1.0.0 dev: false - /url/0.11.0: - resolution: {integrity: sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==} - dependencies: - punycode: 1.3.2 - querystring: 0.2.0 - dev: false - /use-sync-external-store/1.2.0_react@18.2.0: resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} peerDependencies: @@ -3088,19 +3000,6 @@ packages: /wrappy/1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - /ws/8.9.0: - resolution: {integrity: sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: false - /xtend/4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} diff --git a/src/components/widgets/unifi_console/unifi_console.jsx b/src/components/widgets/unifi_console/unifi_console.jsx index 484982c8..7427bd23 100644 --- a/src/components/widgets/unifi_console/unifi_console.jsx +++ b/src/components/widgets/unifi_console/unifi_console.jsx @@ -1,17 +1,18 @@ -import useSWR from "swr"; import { BiError, BiWifi, BiCheckCircle, BiXCircle } from "react-icons/bi"; import { MdSettingsEthernet } from "react-icons/md"; import { useTranslation } from "next-i18next"; import { SiUbiquiti } from "react-icons/si"; +import useWidgetAPI from "utils/proxy/use-widget-api"; + export default function Widget({ options }) { - const { t, i18n } = useTranslation(); + const { t } = useTranslation(); - const { data, error } = useSWR( - `/api/widgets/unifi?${new URLSearchParams({ lang: i18n.language, ...options }).toString()}` - ); + // eslint-disable-next-line no-param-reassign + options.type = "unifi_console"; + const { data: statsData, error: statsError } = useWidgetAPI(options, "stat/sites"); - if (error || data?.error) { + if (statsError || statsData?.error) { return (
@@ -27,7 +28,9 @@ export default function Widget({ options }) { ); } - if (!data) { + const defaultSite = statsData?.data?.find(s => s.name === "default"); + + if (!defaultSite) { return (
@@ -42,6 +45,23 @@ export default function Widget({ options }) { ); } + const wan = defaultSite.health.find(h => h.subsystem === "wan"); + const lan = defaultSite.health.find(h => h.subsystem === "lan"); + const wlan = defaultSite.health.find(h => h.subsystem === "wlan"); + const data = { + name: wan.gw_name, + uptime: wan["gw_system-stats"].uptime, + up: wan.status === 'ok', + wlan: { + users: wlan.num_user, + status: wlan.status + }, + lan: { + users: lan.num_user, + status: lan.status + } + }; + return (
diff --git a/src/pages/api/widgets/unifi.js b/src/pages/api/widgets/unifi.js deleted file mode 100644 index f8cbcc1e..00000000 --- a/src/pages/api/widgets/unifi.js +++ /dev/null @@ -1,53 +0,0 @@ -import { Controller } from "node-unifi"; - -export default async function handler(req, res) { - const { host, port, username, password } = req.query; - - if (!host) { - return res.status(400).json({ error: "Missing host" }); - } - - if (!username) { - return res.status(400).json({ error: "Missing username" }); - } - - if (!password) { - return res.status(400).json({ error: "Missing password" }); - } - - const controller = new Controller({ - host: host, - port: port, - sslverify: false - }); - - try { - //login to the controller - await controller.login(username, password); - - //retrieve sites - const sites = await controller.getSitesStats(); - const default_site = sites.find(s => s.name == "default"); - const wan = default_site.health.find(h => h.subsystem == "wan"); - const lan = default_site.health.find(h => h.subsystem == "lan"); - const wlan = default_site.health.find(h => h.subsystem == "wlan"); - - return res.status(200).json({ - name: wan.gw_name, - uptime: wan['gw_system-stats']['uptime'], - up: wan.status == 'ok', - wlan: { - users: wlan.num_user, - status: wlan.status - }, - lan: { - users: lan.num_user, - status: lan.status - } - }); - } catch (e) { - return res.status(400).json({ - error: `Error communicating with UniFi Console: ${e.message}` - }) - } -} diff --git a/src/utils/proxy/api-helpers.js b/src/utils/proxy/api-helpers.js index 55cd333c..904c9e96 100644 --- a/src/utils/proxy/api-helpers.js +++ b/src/utils/proxy/api-helpers.js @@ -2,7 +2,7 @@ export function formatApiCall(url, args) { const find = /\{.*?\}/g; const replace = (match) => { const key = match.replace(/\{|\}/g, ""); - return args[key]; + return args[key] || ""; }; return url.replace(/\/+$/, "").replace(find, replace); diff --git a/src/widgets/unifi/proxy.js b/src/widgets/unifi/proxy.js new file mode 100644 index 00000000..d4d50e0d --- /dev/null +++ b/src/widgets/unifi/proxy.js @@ -0,0 +1,103 @@ +import { formatApiCall } from "utils/proxy/api-helpers"; +import { httpProxy } from "utils/proxy/http"; +import { addCookieToJar, setCookieHeader } from "utils/proxy/cookie-jar"; +import { getSettings } from "utils/config/config"; +import getServiceWidget from "utils/config/service-helpers"; +import createLogger from "utils/logger"; +import widgets from "widgets/widgets"; + +const logger = createLogger("unifiProxyHandler"); + +async function getWidget(req) { + const { group, service, type } = req.query; + + let widget = null; + if (type === 'unifi_console') { + const settings = getSettings(); + widget = settings.unifi_console; + if (!widget) { + logger.debug("There is no unifi_console section in settings.yaml"); + return null; + } + widget.type = "unifi"; + } else { + if (!group || !service) { + logger.debug("Invalid or missing service '%s' or group '%s'", service, group); + return null; + } + + widget = await getServiceWidget(group, service); + + if (!widget) { + logger.debug("Invalid or missing widget for service '%s' in group '%s'", service, group); + return null; + } + } + + return widget; +} + +async function login(widget) { + logger.debug("Unifi isn't logged in or is rejecting the reqeust, logging in."); + + const loginBody = { username: widget.username, password: widget.password, remember: true }; + let loginUrl = `${widget.url}/api`; + if (widget.version === "udm-pro") { + loginUrl += "/auth" + } + loginUrl += "/login"; + + const loginParams = { method: "POST", body: JSON.stringify(loginBody) }; + const [status, contentType, data, responseHeaders] = await httpProxy(loginUrl, loginParams); + return [status, contentType, data, responseHeaders]; +} + +export default async function unifiProxyHandler(req, res) { + const widget = await getWidget(req); + if (!widget) { + return res.status(400).json({ error: "Invalid proxy service type" }); + } + + const api = widgets?.[widget.type]?.api; + if (!api) { + return res.status(403).json({ error: "Service does not support API calls" }); + } + + widget.prefx = ""; + if (widget.version === "udm-pro") { + widget.prefix = "/proxy/network" + } + + const { endpoint } = req.query; + const url = new URL(formatApiCall(api, { endpoint, ...widget })); + const params = { method: "GET", headers: {} }; + setCookieHeader(url, params); + + let [status, contentType, data, responseHeaders] = await httpProxy(url, params); + if (status === 401) { + [status, contentType, data, responseHeaders] = await login(widget); + + if (status !== 200) { + logger.error("HTTP %d logging in to Unifi. Data: %s", status, data); + return res.status(status).end(data); + } + + const json = JSON.parse(data.toString()); + if (json?.meta?.rc !== "ok") { + logger.error("Error logging in to Unifi: Data: %s", data); + return res.status(401).end(data); + } + + addCookieToJar(url, responseHeaders); + setCookieHeader(url, params); + } + + [status, contentType, data] = await httpProxy(url, params); + + if (status !== 200) { + logger.error("HTTP %d getting data from Unifi. Data: %s", status, data); + } + + if (contentType) res.setHeader("Content-Type", contentType); + return res.status(status).send(data); +} diff --git a/src/widgets/unifi/widget.js b/src/widgets/unifi/widget.js new file mode 100644 index 00000000..928ebd76 --- /dev/null +++ b/src/widgets/unifi/widget.js @@ -0,0 +1,14 @@ +import unifiProxyHandler from "./proxy"; + +const widget = { + api: "{url}{prefix}/api/{endpoint}", + proxyHandler: unifiProxyHandler, + + mappings: { + "stat/sites": { + endpoint: "stat/sites", + }, + } +}; + +export default widget; diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js index 04665c78..a4cab76b 100644 --- a/src/widgets/widgets.js +++ b/src/widgets/widgets.js @@ -27,6 +27,7 @@ import strelaysrv from "./strelaysrv/widget"; import tautulli from "./tautulli/widget"; import traefik from "./traefik/widget"; import transmission from "./transmission/widget"; +import unifi from "./unifi/widget"; const widgets = { adguard, @@ -59,6 +60,8 @@ const widgets = { tautulli, traefik, transmission, + unifi, + unifi_console: unifi }; export default widgets; From ad1d1e751dd9edf54c951b0cb93953892443b9cb Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 7 Oct 2022 23:26:16 -0700 Subject: [PATCH 079/401] Refactor unifi proxy for udm-pro compatibility --- src/widgets/unifi/proxy.js | 51 ++++++++++++++++++++++++++----------- src/widgets/unifi/widget.js | 2 +- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/widgets/unifi/proxy.js b/src/widgets/unifi/proxy.js index d4d50e0d..91446051 100644 --- a/src/widgets/unifi/proxy.js +++ b/src/widgets/unifi/proxy.js @@ -38,17 +38,22 @@ async function getWidget(req) { } async function login(widget) { - logger.debug("Unifi isn't logged in or is rejecting the reqeust, logging in."); + let endpoint = widget.udmp ? "auth/login" : "login"; + widget.prefix = ""; // never use prefix for login + const api = widgets?.[widget.type]?.api; + const loginUrl = new URL(formatApiCall(api, { endpoint, ...widget })); const loginBody = { username: widget.username, password: widget.password, remember: true }; - let loginUrl = `${widget.url}/api`; - if (widget.version === "udm-pro") { - loginUrl += "/auth" - } - loginUrl += "/login"; - const loginParams = { method: "POST", body: JSON.stringify(loginBody) }; - const [status, contentType, data, responseHeaders] = await httpProxy(loginUrl, loginParams); + const headers = { + "Content-Type": "application/json" + }; + + const [status, contentType, data, responseHeaders] = await httpProxy(loginUrl, { + method: "POST", + body: JSON.stringify(loginBody), + headers + }); return [status, contentType, data, responseHeaders]; } @@ -62,9 +67,22 @@ export default async function unifiProxyHandler(req, res) { if (!api) { return res.status(403).json({ error: "Service does not support API calls" }); } + + // determine if udm-pro from base url + let [status, contentType, data, responseHeaders] = await httpProxy(`https://${widget.host}`); + if (responseHeaders['x-csrf-token']) { + widget.udmp = true + } - widget.prefx = ""; - if (widget.version === "udm-pro") { + if (!widget.port) { + widget.port = 8443; + if (widget.udmp) { + widget.port = 443 + } + } + + widget.prefix = ""; + if (widget.udmp) { widget.prefix = "/proxy/network" } @@ -73,29 +91,32 @@ export default async function unifiProxyHandler(req, res) { const params = { method: "GET", headers: {} }; setCookieHeader(url, params); - let [status, contentType, data, responseHeaders] = await httpProxy(url, params); + [status, contentType, data, responseHeaders] = await httpProxy(url, params); if (status === 401) { + logger.debug("Unifi isn't logged in or rejected the reqeust, attempting login."); [status, contentType, data, responseHeaders] = await login(widget); if (status !== 200) { - logger.error("HTTP %d logging in to Unifi. Data: %s", status, data); + logger.error("HTTP %d logging in to Unifi. Data: %s", status, data); return res.status(status).end(data); } const json = JSON.parse(data.toString()); - if (json?.meta?.rc !== "ok") { + if (!(json?.meta?.rc === "ok" || json.login_time)) { logger.error("Error logging in to Unifi: Data: %s", data); return res.status(401).end(data); } addCookieToJar(url, responseHeaders); setCookieHeader(url, params); + + logger.debug("Retrying Unifi reqeust after login."); + [status, contentType, data, responseHeaders] = await httpProxy(url, params); } - [status, contentType, data] = await httpProxy(url, params); if (status !== 200) { - logger.error("HTTP %d getting data from Unifi. Data: %s", status, data); + logger.error("HTTP %d getting data from Unifi endpoint %s. Data: %s", status, url.href, data); } if (contentType) res.setHeader("Content-Type", contentType); diff --git a/src/widgets/unifi/widget.js b/src/widgets/unifi/widget.js index 928ebd76..f4b1366f 100644 --- a/src/widgets/unifi/widget.js +++ b/src/widgets/unifi/widget.js @@ -1,7 +1,7 @@ import unifiProxyHandler from "./proxy"; const widget = { - api: "{url}{prefix}/api/{endpoint}", + api: "https://{host}:{port}{prefix}/api/{endpoint}", proxyHandler: unifiProxyHandler, mappings: { From e03822df6eabc2ab98272c656112cb9823e0e5a4 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 8 Oct 2022 00:45:00 -0700 Subject: [PATCH 080/401] Add UniFI console service widget --- public/locales/en/common.json | 4 +++ src/widgets/components.js | 1 + src/widgets/unifi/component.jsx | 56 +++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 src/widgets/unifi/component.jsx diff --git a/public/locales/en/common.json b/public/locales/en/common.json index af8fc197..669ebd27 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -36,6 +36,10 @@ "uptime": "System Uptime", "days": "Days", "wan": "WAN", + "lan": "LAN", + "wlan": "WLAN", + "up": "UP", + "down": "DOWN", "wait": "Please wait" }, "docker": { diff --git a/src/widgets/components.js b/src/widgets/components.js index 5357c070..0ff197af 100644 --- a/src/widgets/components.js +++ b/src/widgets/components.js @@ -32,6 +32,7 @@ const components = { tautulli: dynamic(() => import("./tautulli/component")), traefik: dynamic(() => import("./traefik/component")), transmission: dynamic(() => import("./transmission/component")), + unifi_console: dynamic(() => import("./unifi/component")), }; export default components; diff --git a/src/widgets/unifi/component.jsx b/src/widgets/unifi/component.jsx new file mode 100644 index 00000000..82b33941 --- /dev/null +++ b/src/widgets/unifi/component.jsx @@ -0,0 +1,56 @@ +import { useTranslation } from "next-i18next"; + +import Container from "components/services/widget/container"; +import Block from "components/services/widget/block"; +import useWidgetAPI from "utils/proxy/use-widget-api"; + +export default function Component({ service }) { + const { t } = useTranslation(); + + const { widget } = service; + + const { data: statsData, error: statsError } = useWidgetAPI(widget, "stat/sites"); + + if (statsError || statsData?.error) { + return ; + } + + const defaultSite = statsData?.data?.find(s => s.name === "default"); + + if (!defaultSite) { + return ( + + + + + + + ); + } + + const wan = defaultSite.health.find(h => h.subsystem === "wan"); + const lan = defaultSite.health.find(h => h.subsystem === "lan"); + const wlan = defaultSite.health.find(h => h.subsystem === "wlan"); + const data = { + name: wan.gw_name, + uptime: wan["gw_system-stats"].uptime, + up: wan.status === 'ok', + wlan: { + users: wlan.num_user, + status: wlan.status + }, + lan: { + users: lan.num_user, + status: lan.status + } + }; + + return ( + + + + + + + ); +} From e56dccc7f17144a53b97a315c2e4f622fa07e58d Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Sat, 8 Oct 2022 16:04:24 +0300 Subject: [PATCH 081/401] new logo and styling tweaks --- README.md | 8 +- images/banner_dark@2x.png | Bin 0 -> 31649 bytes images/banner_light@2x.png | Bin 0 -> 30470 bytes images/homepage-dark.png | Bin 14937 -> 0 bytes images/homepage-light.png | Bin 15054 -> 0 bytes public/android-chrome-192x192.png | Bin 0 -> 2258 bytes public/android-chrome-512x512.png | Bin 0 -> 7077 bytes public/apple-touch-icon.png | Bin 0 -> 1407 bytes public/favicon-16x16.png | Bin 0 -> 465 bytes public/favicon-32x32.png | Bin 0 -> 595 bytes public/favicon.ico | Bin 15086 -> 0 bytes public/homepage.ico | Bin 0 -> 15086 bytes public/mstile-144x144.png | Bin 0 -> 1184 bytes public/mstile-150x150.png | Bin 0 -> 1231 bytes public/mstile-310x150.png | Bin 0 -> 1365 bytes public/mstile-310x310.png | Bin 0 -> 2800 bytes public/mstile-70x70.png | Bin 0 -> 958 bytes public/safari-pinned-tab.svg | 23 +++ src/components/bookmarks/group.jsx | 6 +- src/components/favicon.jsx | 114 ++++++++++++++ src/components/widgets/logo/logo.jsx | 56 +++++++ .../widgets/openweathermap/weather.jsx | 20 ++- .../widgets/resources/resources.jsx | 2 +- src/components/widgets/search/search.jsx | 2 +- src/components/widgets/widget.jsx | 1 + src/pages/_document.jsx | 5 + src/pages/api/theme.js | 14 ++ src/pages/browserconfig.xml.jsx | 29 ++++ src/pages/index.jsx | 20 ++- src/pages/site.webmanifest.jsx | 42 ++++++ src/styles/globals.css | 1 - src/styles/theme.css | 69 +++++++++ src/utils/styles/themes.js | 142 ++++++++++++++++++ 33 files changed, 533 insertions(+), 21 deletions(-) create mode 100644 images/banner_dark@2x.png create mode 100644 images/banner_light@2x.png delete mode 100644 images/homepage-dark.png delete mode 100644 images/homepage-light.png create mode 100644 public/android-chrome-192x192.png create mode 100644 public/android-chrome-512x512.png create mode 100644 public/apple-touch-icon.png create mode 100644 public/favicon-16x16.png create mode 100644 public/favicon-32x32.png delete mode 100644 public/favicon.ico create mode 100644 public/homepage.ico create mode 100644 public/mstile-144x144.png create mode 100644 public/mstile-150x150.png create mode 100644 public/mstile-310x150.png create mode 100644 public/mstile-310x310.png create mode 100644 public/mstile-70x70.png create mode 100644 public/safari-pinned-tab.svg create mode 100644 src/components/favicon.jsx create mode 100644 src/components/widgets/logo/logo.jsx create mode 100644 src/pages/api/theme.js create mode 100644 src/pages/browserconfig.xml.jsx create mode 100644 src/pages/site.webmanifest.jsx create mode 100644 src/utils/styles/themes.js diff --git a/README.md b/README.md index bf32fdea..303a5751 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

- - + +

@@ -38,7 +38,7 @@ - Images built for AMD64 (x86_64), ARM64, ARMv7 and ARMv6 - Supports all Raspberry Pi's, most SBCs & Apple Silicon - Full i18n support with automatic language detection - - Translantions for Chinese, Dutch, French, German, Hebrew, Hungarian, Norwegian Bokmål, Polish, Portuguese, Portuguese (Brazil), Romainian, Russian, Spanish, Swedish and Yue + - Translantions for Chinese, Dutch, Finnish, French, German, Hebrew, Hungarian, Norwegian Bokmål, Polish, Portuguese, Portuguese (Brazil), Romainian, Russian, Spanish, Swedish and Yue - Want to help translate? [Join the Weblate project](https://hosted.weblate.org/engage/homepage/) - Service & Web Bookmarks - Docker Integration @@ -156,6 +156,7 @@ Huge thanks to the all the contributors who have helped make this project what i - [josways](https://github.com/benphelps/homepage/commits?author=josways) - Baidu search provider - [mauricio-kalil](https://github.com/benphelps/homepage/commits?author=mauricio-kalil) - Portuguese (Brazil) - [modem7](https://github.com/benphelps/homepage/commits?author=modem7) - Impvoed Docker Image +- [MountainGod2](https://github.com/benphelps/homepage/discussions/243) - Homepage Logo - [quod](https://github.com/benphelps/homepage/commits?author=quod) - Fixed Typos - [schklom](https://github.com/benphelps/homepage/commits?author=schklom) - ARM64, ARMv7 and ARMv6 - [xicopitz](https://github.com/benphelps/homepage/commits?author=xicopitz) - Gotify & Prowlarr Integration @@ -186,3 +187,4 @@ Huge thanks to the all the contributors who have helped make this project what i - Sascha Jelinek - German - [ShlomiPorush](https://github.com/benphelps/homepage/commits?author=ShlomiPorush) - Hebrew - [SuperDOS](https://github.com/benphelps/homepage/commits?author=SuperDOS) - Swedish +- [kaihu](https://github.com/benphelps/homepage/commits?author=kaihu) - Finnish diff --git a/images/banner_dark@2x.png b/images/banner_dark@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..87bcd0a7772d96fcd95040f2964f74f569e49023 GIT binary patch literal 31649 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 b10Kbi|GjXZXvfp$Em$w<8tas5JKg;sZD(cY literal 0 HcmV?d00001 diff --git a/images/banner_light@2x.png b/images/banner_light@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..721446b811452813ed6e918a83c1c314ad8dc16d GIT binary patch literal 30470 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 literal 0 HcmV?d00001 diff --git a/images/homepage-dark.png b/images/homepage-dark.png deleted file mode 100644 index 7c9e882ca1e69dcc255b96f5113a980b5636feb4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14937 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 z znjtKv36Up`dl{o_38q$w7cMKmh1uP#i>Rdx6OH>btSeXnU zXo%WvaDSzW%~H*Ke*41e&}BO+WfHmyTa>zheATW8t;himTK7(k#C`@y+A{xfv;%a9 zxI60Ecuoi*Q-ahqD}0=*RNud7CNTbr>DcBdC!qAF3>{1k5B`)-E#6{<*KWe%^A6ny zw7m2gom-acCh~btSMgZK@$iJYt7&2s$!uqvLv0OO+#1Y9mSbVI!9DAVhf}tYs;MwQ z;!QR;TIQ zue?@G@<vYS_%c?h)p~oyp(cI*Iqfx;cj0+g^IKE{C%({F#tIbrfmByu# zb5`5yCgHt%_?Xh`6-1+ot?iiICiIvIDUh48&{Wv((j9cyRPoPI$|!Jpv7K_3!Rc71I!)GG zky%XR>hW3)glJ=qv+HeDjxR>L2jX#VimQNVM3bgXKEwYq&1c-TuwkovWLLtCfqI4b&6Ia+UQINCmiSrV;j=NQ z=Ug0O9Ao0ku8*Ow8}aq)zAAi$bV&L&QphX ztM0lnVzE}2Z|EXGVl0>ZFXhi4Zl}ezg)7g2;FQQLBGhZwXM`To!P}AzWBhFj`!?|+ zbnZr0v}p#l?Z5HRs)Fe@Ut2(u%fetn)DX|EzQr`^Rl&Wvz^YA=@j0LS^7p)Byuh!O z=zIH$c66WpbMS`B{qAcpC1}S5qQb_Q5+c7->R#=Xe~$L}AbdN;GR>)bqiz$*3S&Eu z*-GdTrh(19?{wec3?*JN?8O4`R5*uW2le`RkJp4?);LK#U@`<*qPtaGrhSD$tQ#k= zPYCgp1n(W<3#_0=B=NRB87gc4+7_B~NPu9oVn&B}`vBqJ>$MQTw$Ms1 ztb~swxU|Yj(^6G6b(m<%`d8ixUJPjHoiMPnFS39Ibm*jrhtxmcx1G{L%fkcYLOVS# zvao>}*zmr{2@Z5=eAHR~J<9emkXf#$wVJ z6A8LyQ5IVX1pS{(1ca`RS1D+OkIBy#E=?_8ktUCrxZO zG>IeH5@>1vR0t!YkRF)G6A&ua&3WQ{q&&*<%l~uA`{9-*B6G%~Qwg|jV$FTJ`#B&v z4HIJWkDcvs#T@-zkvei+NPL)>tb#jz{Wv720)nfV-fc?SkO-W4z>XvVRrXMr5)IPi z0Vm)D3lOQPdY_kiX7Tv4uTA|<4KYDT84sgEzJzfpO2wdGJP*y=etms8>~+PY95wp% zQMe9*KvtO#_zMD`@G3M`{t1>~;{$LaNT6pEA#xRDom{{K{yzg#P*BBrTIG}$_zG_Qt z`A-IRF03m65g<|@yP4oIY@z<19)8E1*q<57dI$m zDk_j8@DeTf{>kA3T*6@YqnQtGWh=1}sdqK+S(h_B)|qZ0W&V( zH#p{WUn0CS!JXv&so58Bzg=maSqn1Ob#45fJ~FPz^h1$rZ$M7U*n1 z>WKFYFX)TYs#HqR_9AQz%_wyqtQ?g$MS*l%1TFL@&^#H_~*B-awoh`z_-`p1= zgcdJC0ZG%n@sLo~#e#DH3=P(q&gbsN5o04Tx(B0ft}xXu#z|JRe7Dmd#2N{<0tNDSHf;P)!y&F@5vz&Jkfr@R1+E%Rz!d#f zvgs)=I$%_)vNd+W|Hv^*t(|1PaZxUr@0%o61}q3D0hdyhP$poIC^!WZC&=+Ah!bdT zcyHCs^L6uF4m)Vn`dE;Q9VmToRi>dGFJGX~WsFlke@tSuUHwa&fEp>5f>1-mbA&45 zt1!B804{fLO&M5L=^o_1V)p5RW|S4zS7I7f|Gn$V><~H=LEjM9ISk_YkAWB?Ufml_ zK=X-DcwFB=~+?tpE65z{ez#!G}o*3PEb@Gfw%fm2SEaN zLAaP<`s#e4K)$y=`ylm#Z|B!orSl_?7aMsK-e=gf_wL7%ola-!|Jwf~+-k&0IDUr! z)l(-!qZH-knDeUjKDgoPd~Q5MGTV2X^%sK63HBn#tB$PnU-x$27C*7vIewJQ1>`Jm z?>r!N^L_-9uHY1&GoS)UPjD({Srpin=KgEDE3oyW7kpxa$R2zYuV0%?oaz$uQpbR1 ze1FG~p|>OgXXDo^i!W?#n<78}H(Ja%7R!C;ts{<>2zF3v$1?K{UchcRgb!bJot+(4 zE;M-8vfv~)HHSld_ev%~M(7u>Rp&R*`@b@^WnU8TNs#*wg$u^b)x;4ZD!;IKa8PBd zB#>{R@D&OpnDyz7dSbHjHS>7m_lRU^9Tk{|qg$3aF*2eVxo!ZXL%PFyaSlhhW>PWX zd)n8?3Tdp2h^({hsLhnmW%oit*rXj5}hLXYZ4 zU&w(UW{=zY+4)eD1JA>(Cab~{QfxlH0J5k7Z4cbI;A0<#FXO)hLltb}L=Np>b!JbJ z+OPmxm%Ysr@cr~~m=0;R%L3+9DOl-jr#A<{-M}})NS(Q~>no2Qv4f4HvA<#g5@xq= zTB!jXI5WVcKBV{P?kzuJ{2PH+#C|)msse^kDBB>^R2;!&M8WNeSL|0_f~6T|g%}PC zX3w*%^?Dk1r{>{12wpBkJ-?!!BT~1RYorIlk}IX_@c`DUU!l!#X@@xZvC7?|;kxAL~br>Em+`ZEtoh z@eqD6L7i&MTLOvH-V(4Fa0Fgk*YSgj4htdfGkR8Q>M&S#w^lgIX7r)*thAg6#`q{WSTi7cxAjlFPzKrdr0aQE~**!9p)HlTi3D_@GiC#SrK`pBA#bCQpu?U!;|MM85+Jg`)j zyxpCudJD!*$fv&<=nhAJo6V-*&`;D;ou~z${N@FZqPE%}TeJvw!vZ`}0H3;>wzTdgs&eTJ2wG?l42U(6O|NaLuqgc@N2p)lz#6YdVLm^%@2yT-`t# zU}|1DGHdCf?z=}yR+TjT=%_BR6izSOTAkaI(QgRS9)#r+4Tpo`p~8t#-}NMzI*B1C z>b?uKcbJGFyB}4F_d6itfUOG;B7KaSrzm9MJ%4^KzLyZOZg9gjkX`Um7)OD`M{Mr3@>K zR^8r)C2JeV9_%^2pl7lAKv$0FqGY3|R+fvEDMwgD>ioW%GOry-B%(CelhUON@OL+z z9tuUsRksJE@QCvw{|@}%X^*|U8BP~OW|kv_-nTC`q^{L5eI$gN134}&du}xQ8WDMs zK2%G*QV9d3wBqu-kP}wtQ^iEWTww%5vVGRCOD-A|kr5CQqJ}j@brqu;snc|0@zvat zSD~NVSThA7y>OBbU6GK{1gI1_BcmcafAkrUhN#$h)Ee#m&lW9vWyAA}HAR z#lsB-GP?F}!iHxf-FGA3s@D9CfK`P*ABBl+Ktl4;STvWvMKlDFXu@to!K2XbOl}%z zB4Y2|qun2!9#V0hNz|*46JO}wjGtV{ERErwJdNqbe^XregJ8t)^N$jhkVwK?roRG3 zc%84&l$nU3Kd*@5760SBnF20+B}(y{)iD&K7{3SKbEPl~B4xw!C7_=+)xk6<96_YB zdx~FZgHzA@?Nq@DHjBr%*=S>Z()3K+(i?k_(dWqP_+k;n&%>&L7v_ z^w3oEQR3gp69NBK98t-*`rS+Gc33k~ksp%Zrt%xJq&f-8)$u%^!){r#t=CQHR>0I1 zlZeH7+fyC2FdwEi<5vZhL^gkt@3FiUM0ORZc(lp%u(WK4>>2|_DrH;8!~RaYf(3F7 zLqmTxGkQ|@9wIO@L>#!m0HzXa-%{1nIEsQ)_{kf^u7_u8OdCc3dW9_|ycN7Fz46eD zyvu!3E@>KK`hC-$y+Qdc_MS*e1$vv_#MVz|zb-_DC&>Yi0~j-@Jd}YSX}R^e!>0IEy3e&Jok781zaivN&@YaL9(?}QJhTMQ0^$E@o5wJ&ZhKze_r%btpP~e znpvH+fV5>17L!;0D*082d$q{m-xG`rS}FI&04VvuOtm*+B!q)htvQ(CKz!%vHErDh zgHzdMpE2DPM!|(ez3Zdz$wG|G)UqtXN;jI;vC=cR=*~blbY5yO|6 zpkQ#evc>E~IG!k1 z=Z@*>Ffrtde9gEqAf{JfI_6rQk{Q3aV8V~q!cowxp7{)_VH>&;#Yv=DMo*A?7LB(d zrdVucuq8``_BYAUg9dprg{no8V{G?N(_GK|{-J1Ea34(=w3XIR8JIIV&LUrK5lKqG zBH6CyHc7$4^`j;F@K1&UC6xuCVr@Dxc1u-{S|t$+Hepl&?oC#5!eA>x;2~JCC1GCo z$a^t#QGM;}jV1~8UHS!9#UU1)SN=ZlK7<=`xxD?B7pWvF7x?=FAqy3>Zeqa2o2XA* zJ+Nx9zhytU_;Cwup!^Sax5v-;^%%Sg5-q&6f%X^5M2e!27~=Z6)6cW@Z~Et@+S7G+ zZvDQW*!w5GQv4&-E#Ag9&b3PpX1!B8e;uRq&WWNk?xP&&q~I8(s{MsBzNB3PPBz`(0Aw zWax6*qE9oDw-(X=VSeV%h3|4jYV7(X%w!Qcw{pvUDlJrI`UQT? zsp%)YNrWtPC}f4rg$JeiAdsl^ag<{0FW+Kh8r7{OV5rDJp<^U1aJJI=9&7}R2qJeQ zgD<8wiEkTK?u&pag50>x0CSx7XJKNWIE?W+$qoqUWEIEYVX4>=I;($}#P@uqY1#>I z{YIv5S65OAE%kt=qd=}>@~mt8Ka)dFcaRS7MB~|4KRTG&<5kW6tfO`#v^|R>-wM&5 zcM~}c>a$GUJ4%Z7Z;)!XZ|TqTT=A(;kj>{3jh!6&qjEQ93Xfqb4sXzVB2~&p8|3@YiogJ1 znc;1;>+pBXZODxr7e+}(G}0GzOniTzGwLpJu#%7}?)y5eVvOuZax&>ha$o!)A!bhA z43+@}^S=+9BSl@u98g5*-PRb8L<$bfYL?Sd??X8Phvx9yrvX2x<4Dwo_wDw2 z(ok=3LF|j&H-`d7c659Fs%(NtCP9dd3ZCE*UdltX`gpH+3I}>p>_1YB&0?l>EtxL6 zd4T!TgXJMVTES$hSrtSq;Vl+TJ97b+jq^)0OuYhY0SIh<{v+#rM5krT_E8+P_Hu_1 zAq3%Il3*aC7W86y66*<~L6Ok3a~EJm1Yo3Ra0nu~Mw;u%2|}#_m!dGABO$k}PpTfs z>NJcEV%37hfXB5>qzQzUk&0G;^)tE>ZyJ=oCkuxPWK{@F)qip=Awt#SGbV;i&t|~w zzfe3 zhzpJ~CRAoPe(e;W2Fmxf$&|tYtr1jEhuE^>V^-R-{q!+x?2I~JOC^?9iCiVgS{_TKC4;H3@gURn7X4p-9wyiQn`C-)ffw~Gku-srtne(p3dm@ml| zA}*4}-E4B*Ye_Do#v8R0xIhjfrbAWWXc9cM3N8Gi`rK<}Tj`yinnBq#%5!^4iZdek zJ?+wrX={VYHKTXkNZD_P;!fp)*5itgOWEL@1BD7`|$4=}p zD~H!`t9ci15L>hK+?OgDh?8FN7Z9IKV`ttNf>IX{GiUt6(qs67%ocYJsI zsZsghtj-!tw;fZ+&ly?!4TpdK%L&`xeTVX7KCKxNUh5-8cA>a-A@>n@h0*3|0p`6GCfLPG8 zU8z`)xB;(>{|-)_;iQOUSebuKjImGXC;>Fv5P=~}iF}lA>_2HO55ms1nEE4xM$g+Z zi+t7Hx5~05iI0Ur?L&yI;was-e4m|ODJqyQ>@vK0kvl-YhxCCPye!WB~fpIPa6MTXVPY#M{^VK}@+A{|Mc`&K^z?O6U{p?0Fc_sK zZNu8)0gP8l-(Wden4wi`A%tGAlJHHEhAd+|q(VZ+WbVqF zd`KmZL0JS)p1RA~eHUGd+Ml4;yuepxilhFK@pld)px5lc*KZrS{$ls8iTJt&SjD`+ zjMivOC$lX#DSMlk?=g3q8$CXZUpl&|h6;IGm(`l`%$~x~Kp6AktT(ay@e2}`17gh?@w`2dDBt&5Ow-tZ1eO%RX7VEKiOtx)#- zu(g!y<@ZohPu%dl8AiDs4uutFxom8(2)061Ng~TZN}dbA`CSPBIj{r%+Vxf1<4vx= zQ+d4pjk8AUUED|)F7}16rgab!OtbS+iF*S5qP{f*p)vSS_g8G!C|^x$$tJJf6j1p` zm_rNF>)m9T;`cDQ?ks$0uwkI|@vop(_uoB4exXzpNX*h!RjHEuhgPW83N}iRF$I#c zv{gf?OX=m=0VCT>7}n=_7@b#iYs;Q$``l#hZ#ubUj4?IzM!)`*+2NydGVSZx0eCGz z=psIp!%*JtV6o!LVK!%H(bq!WP6uS9fq0&^;bk%BbL8P+dBL{@CG~`cTWL)VnC{7d z!mXAY`rM$Tp|Gyjg4nX(oh-kWvEk*C4f|_UARkI(L$=5t^P^OZ@(dWAV)>PKBI9FlQk0pQqv|@2YL|tpzhl5&#bFAh`t|k zExrHs(G)Z2gG6L2-1z+S4(&}MMrfD_M}OM>U1h0}9q~FQhvSu0bPk1pntqkHJy=z)o(^^WDGk(_Yy#*DFQ)2 zI!HfskRTceyz#!DXTHDR`{&JM=A4za*0rux_C7P&NrI`d9xW9Y6$k{PHPF{K1A)jf zAP`X+1(@*3M{jCg!sUtST?-w;l}}9N|H1oB%m@o1*fp4$u{j8W=s99Y<1dmKd$?Tt z+;m8>|Aicr_nV#dj-VBH_P^E??6M4rAdu2818u0qi@CiSC{@%$me_IYi*%jGnz1@D z?N>Uw(MSf-Yk$bLKKvY2ZzCdL|6jc%-4$3svYq~7`y{SC388`0uqqr1gqT&p%kPW4 z4h}r~KAoP71j}C2!|=C9T~=1jyIZk-p-=`1k%S>__`3(8En^NCA`U^|s%3CutVY_8 z5w^6qnB+Yt3yQn1Wnd;PmJ`ST2>d*Y7`pfNx+SxB#(So?{1c|4%$Xh{CK7z~>Vwwf z60M;mBsfg~h;YyyJO7i~LS@4U0}-^T0ZK{MT`?aB0V$&{=V6^s)-3bVSfS(sP>jim z7I#LuplB2wkdqLq?&UGk(03!<^ds5hssgu%}35L#X(Aoi$`sfdi8viiKxUduL zg?+|>f~MCw z{XV8*-g3{`YBSTHV4ZPDk27zpX*0kix$uU($z0MRfB5DHZ~Tu+Zj!L}`N4xZc=(Bu zEy1!ek|fM_6gL?f@NL(;6A3Cdwt*r0D9g7mDvp7EN!34?Vhs|Bq5+AM>(Q3PK%zh6EJQ775-`oi}+AJ2Tg|m$Z8dHqNnW?f`ryw zJUVntn~Ot%64ec|H+pP=`0tUX`w{68qzKnN6aP-W`=zGZ<<3=#}_cmw!aGFLSpAMzh%8FF{&&a%Uz z2%{hX0&!5m&vk+=&PD%6!r?#f8{-F*pyZ%lGt9|!1K9qD+7_-{vNZ(0mj92p*gxJH3(fxx(i7lsa5u?Yw`FLg zxk1e+`cjJ*D=QKli_}oAPR@vspLJT4K39&Z?6Qpg8FstlXGz`#N5`${*m0A@ysK?F zg&5NiBgM>U>&Dw53hwrYd6+E4I9c4%+)=@adQ8n8v*wzpUDEPtIE_|t33Up(eNkwH z4PQ8WpjdZ2LAJP`sB0bZ+L{7a4>cK`7Thb^G7YiwJkQAtJ0cw|*{Ax>Em*J9J2(=zdZHO0B9-qe0k?6L~O_5IWP$^rE+n)V~p4V%Kl zKV_70KT<8nw|96p%xw8BgjnrX*MhV}W@fMj9N3G~@*5Xx?*gN0XyH3~C`mdswn_h3#bBoIboc?IdUG;ezeUKcfu7Q}=YTw0&TS349w@=Qh;He0K&Riw6( zOJ3;mYEXQlRx9`>%H83KY@}=MB|U0hN`QOI?eCFA{)!_YrP(UHg8lZug*zQlZjOZ? zcm=upC-_I)j?YG}y zl$tM9-WGhnV#7(SIBC2C8K^PRE>Pn|GuD9*ZPW+K@dxifi!z(+$HPSf0wMeRqK;|tO&xzSVNYd_&DBgwL zn0qp2O$-X$dcYVPv(eR?W`cUJp$Zq3 z%j`pry4sp{#F*LK77NrhSg%)f_{s%bkGu<h=9@vdLGL~I+iwSq@^A+FdZv650Mxvw7 zcWb}Dj}77P*}&Q&vQc?D1`!t~*Hsj3xvQgbwABjs{if6og5l@M=0!G5Kgwjdb1h}B z;|sKlpyTcWIuT>>1p{Py*V*AUH*7smxuKrXTOudHfEg)f&oKhcigHm`#IbK{>eByQ z4-_BP2xTp^w*+k&Ah%DumbIK4SDpGS`FA#+dq3@8Vn04D^{8GH$7^JEzApm_rCR~0 zlD}*o@E+chNVgEvJZyzjc9pICW2}-;spQj)iU^6XQ_TvB4Afyd%G*Y3{RP_ZHCHd5 zEHsiIqL{btst@)+QF;?xMp>%7UXE^(uU_MLJ_MMgOUT}f5&=#Z&e%E~xaT~dg+!D+ z6LY*p`?;jq=EsduXT=;u`iv;dL;r2sTKGhnA%b`C+`eigDeR)$wz`IJFVVhy)7R^P zA62O)J*(G6c$+O^$30V2~e4ef6;LhXwMp5#)u>y3n^(G^wmfbVWwP&d{ zlVLmpFs`B;5Qn#aY{|IgNy5p6#nJlpnDC`7quzY~ zkb3tz7L%E%Ps9}M><+ssJh$Axip8Mcv)ZODy4&3e<#)+vzcbFcIxua{^z%oJ%HG-- zot$=rS$T&M)14OAn@)*BFWf;TL6mBTV@Sq(wMlnkYTU>3KoH@^fTlMuI<}fTVGy8g z%mgg?Y9wJ^9aj}cYbq@|>SG1CV>yZ;$6rCaAMY4_W?|I(5-XoZhu&4syN!O@aW0y< zUEOEYIzF@vQK<`n1Kl_sR4+RCfqLqF2Bu%Z> zXHo8~YVL|0<@vB2Lndd7m;>jX zWCp)y(z`*!X`|cR1tf{Yx)dw(;n$fc!bpo`E9kAv?yhey`CPsJNGMGtX7NpY$cJ0e zW_pU3L{OWd@9E=;D%D%VD2mLjMWWk`wJmp4E+PXKrC@nv4v!ANr&NI?8O}HrQWjq_ zrafe+%&a%cy{*-^ zuA|te%-(DKe(%pQ`&dVm%-X?ZcGJon8|*hmQQ0i~md$#b%JUpYl-|Xr0WPNb!A<)1 zvx~$w;u;5F36xs!eQD$^T$hFex?L-sl&NX`SsMRZ^8>bCn5&qXh7&W~8*sKDie-JH zIcb6sF=`Vi#wS~6$ggB4Hwqo5IiANHjFhrlJgU4azLx595K9M~#jeC~T7a{Kez=eBso>)6&Psng7t z-@I_jtq(R6fVrMt#NT|!TFN6OO?kXR311nzJ>5YYhPOi_(FHsLtplk>-|^d&cum@l zP+`3E7~o}xlSPpe-8`PrHPOJM7osri-8nxe&A-PC!b(u)N4L+>klBK>-}^=2NcxA| z=bc>Cio<-a7tyu8-`b>Ey#{Rf zi!CiiVLYc2=aZfTtfF6xxji0O+kja(SpY z&Dp#aU`T>U{yNtXZldsrWGgbrRk~PTur@${Q?%R5SnB@yNZI?4)~rBom5rlIeg;!; z`xWk2PS#FiH|7diY8=4a;&z#@tv zwF>I)9XCdMm%!x=%Ww5!wsf^M1WH~-)7L(kckF2bLWJOZArR`~pc(O&))|MzRrWDH z(jS&r-{j|)1#kD=M#?FhI4O89TB%@awHJiqWh|*DG(M|G7H;9ZYWQmh7gb|rzb9s+ zf2)+I#CzR7I!==eBo6m@k-3ef zK=N1eTgC&+>}O4p;RoqLKuE21!=?Srk$Fulom=L}?IOf|@~d`rL?iV;qV(1hl+&Qm z_bUfxKQGm6Qdy`fM`J-u(b!j6r0f|vJkaZ&9j7rOY!y-gq*qzrI$Qa4y+T1}`R;e9 zk?ZgSX`K_w(fb)YU%DG}b$MB%9Spz`u^&DRO8yGUDi(h+@dXyJulR z6GsYLX#6Iw!n*Dwq0^ty=#tj?j0Ap&-+1tfMGzN31RLa2Dv42XTu}19@obiMqnMgg z5)4cKZo1qY{P<_#$bGH;hd-IXKe&8#-3BxD?|&G0ltxVSGC57@PtksZX$){hiCKiN zUz8*{o=^F?0VjavtF(P`QZ00ar0vS@s>A5i!#H0UL<*R^%@|8-S$=jp*RF~4nHhM7Ln(j0MkG8fKTK6?3 za@X?eSpwYL$#G-3SRt=edvui~n|Ni)*YPGXCYC8GmyWM9&mWe55wafjIF5IlQK2qZ zkl^8xb9Aa3XS7diJZIW&hR9sv1>FNWbUMIzc7NHf2)_H}Jq+Nf5b;OFA3n}&H|S}@ zRZo4?mXe?Y=r4h=y+$RX>xWDL$!QUBlv`lS0rT%aKa0|-4UrZ4X}jHUMvUlOWO%jQ z+xQKyeqpj}6d0YvYs~Vm_ZZU=YqL0-A{2^xY&|`;o#^ZX=OR^PuZX&Y%V8S2c6aE_ zlmv-U=`>N;dtt>A{jCEQHC|-I{czv*YaHE9tcft^-s%-dqn>>Ez}p(8eY=)45rsMu z;2QJOU&PTyp^Dlj4>}RKZjXmvM<6ca+v%<#N9o0@_X3g2Ae_PH^GlcNDSTYHPcg97 zUcV|7{JDIoT{Z~$>i1?Hc{vus5EeE;BmJTGCzHgZgXh>$F&>60xtncwgS4&3 z(u!?hJR4@r7jAx_7M`Z}5?HE@5C5cjWUvu*>hZ^uFID*syM)$EqCXjh%(o zqwm(sPRe(Ce2nbAr2aT49@GRz69G<{M(FB4W|9`3u6Mq>^lK*dv3w63C(-rzeZ26@ zhd!^`aaI38!~`O@%T!{pUeHPYi5>rhgfHqA*Nb-1O4%{urm))&fZ!w)u z^+i%TgM|Y~FL{7e%d~k+4wt|(MYT0)$(8;@k|znD z$lE6o`?euLrHy){C{|#+Cw|S4lj=ROkLNSc7h=m$qJr(82oST+d*7e~sD7vJaYgb00`k|klTA5asX7O|;+t?we_?-J2>~gZ zb$k42(2u->4)9rZS`ix`S!kUCCm=tWp7vOgx9fl|s-p!%ko-4PzZyyDcZe|XtQn&f z4sP6z^1bGlOGX2L3p(Gjgt4h$EFl`})_A><_qX7_`M#$*ymhWZb^{K=TIW9sYohT& z6}re&9=?s(TfcN8Z>&i-{1T}>c;`dnBIuXeklPY$eq*!4vp2s{eV0IP8%p7p@qL0D33Z!p&BcQBd=& z6_r}7p@jU(W3>ZO+IJyMU5{}eZq|LI8FJNMuXvd-=_OcpzkOoIEigcebv`fSS4 zB1yp@Jqtc}TE9E>xMMR)#gBNT_SLArMq1N|=;J*7euoDS^rUqilg?Z*dRC-P;0_2E zGQzboJdPSu5M8r9oH3HYHd7+?TiN|(jXkEekI%Q>ByqWPxwz2nj0o-CT)jnwkt-v@ zx#Q*vA0Q5RvCQK7^^Pw=Ax-^HmLRbHsHI{nWQ3kk>$A(}UBBR6wLe0ccZH-_kz?s9zFS9l>XI6 z9uh={d!4Klo|$5txb&!OT=2h6y8bAMy71?=@0k0P#g7%7Joy@FJyn+V#6$RqI{Yyr z1&s4*O%)11`S2K7O>1#r^4GUZ8lk2w=cg%;`LZs?J}+0@qphsnsUw*B;Q2JW?*SpM)p@;2nmfd0#H71NOY?+UZ zd<9E&h|SerVX~-{_X`A1^)g7NE&6YM|0;E+T-|b`XGI{-<@5a~3KrFN|0=EV9yh{9 zulJN)LWB~-AN^|i2sZY};U(L`^Yy#wP`@9$w(J3QBE3|~wQRvVP-(~+E!=pMhyEJ= zcx~l&kRY%_jfI8p^|1EYGN_>xExTUPi-+Ok49Qg$4SC&v>g$B_DQQ`m%m8#$iA=-iwCO#ijSDxmvG_ud|RXUwQ~t9|Ay_gScUyJ zR+R8L79 zP{`R#uqY1Q(p4_ad6+qfGl_jtSL0Ld1-sz?mRg7ELGg@YDc--FP6*Z?_pqSEC;EBvL+9&>KWZx67zz_wWPJPdum6%|g z^=ylUo1;N532lTU_>et}zzz}i_tbPz5PL`k{%7rrhu&}hQ6sQ$k6fyVU`9reW1OCu zC)K#?s_jM5{;#SqLr^cO`@_;NJe0rU6u7IrrJ7jEf^7U3{p#VNanM2xN|uH{Z_4@n zzU7YN>B5zcl>_Rv;GkGxs9X0L+4WomKMffLE-7k>N|!{97FJsp5PQPLvD7q%4>vYb}lj{RtWC|{l2~LDil(;JLFwCkr2Ug%X zPC3BwAV)X+-$CEMGzyUXDL?pHQ6v~GrYJ{du5-c1OWNY|{@W8^BJ^2X08`RGjBYjx z+;S-8L~V&7NNsz0ZvLiEP6ls4f4BPS?>j(r*CqvAGU}B=6d!#lMXkCJ;5pmlCdK)c zxMT6;$-z3|7*X#jF)uDVKa)_HF)$8UuN(Oi>0?KObSX5s_myZLvW+~uJrb|$C-20K zo9^BixWdo@yfke-C=N`e?!9uNpMCYbL{Va6+9rM512(O1Sb81fC!j zNz}A{@0wLFRVQL{IkCj$?J2Y{z*=ig2q3|0V}_LsI_1)sunJC}{!W(iEV0*l$44(! z(KCt30i<{R3us~Mq#6eQ`ppGwFhDSe(c$f`S_tG>%f9R+d|}dH>3WID!(BiG z@a#rxTiendzU&Lk?wBgsfd+o1SH4WCTq0Bc6;)I!3%#0a{jJUjvzvv={CqukjN^^! z-joT-Vq}0#Kx-#T%5@!)_k}D;-_0D*T5Npyd5@9>8}u5ZjY$ziEKzH6d0huQFa4}J zd6(E_3tV^tdf@5o1}+5q2mAO4nIP-UF$lC)rT#1uIscUoev?F=YlM+dkzQ;S40G?* zi^bZVbpaYoQPt`QHbJ>B^-`ZO9$UnVRpLvZZ>Po;LNGyB>xfYHVyXBh@?8FS%w&h1 zgiPi<5$}}^>9I+ldkDi!nN1{AorG7oWC+0iQ3j=4sZq5OTO#+YNvy=3nF z2bXWhivHD_59nv8^Z$iF9$tMhPKprBik|1GXv=7!g!2l!w2Wf;A(^qA zNcI!sPX&>gNFTpH6SaLj3tpLuDGFb%r~YjBRr?lGvHFYzy_G^(nV2dvbezb;EfQ|1 z#vcWr7bO9Y=ng(q>YkK~9B`^Bnmjx{-1J_{yX~V*SO9owpg(`$yGJ3C|KhFru|G$A zi&EVAp{QM91pY#=H^c{UJtu@Ra2TB`VUCQO2h`;nd74@vbf;+H0cLl4Q6?R%G0&D6v&c}q*NirM(+fD_c9zEp~XB6p(8IJ6B&ZN;< zlj$VJf6HUgdsj0oJIP!}{3r555Gz;>$_gb8g5VIg$_N&KlmM=>I=jJ@!vdIK-QsEb zq$+zdO?=T0n*!95BKbJpCuYDA2lYFOYlLzD8xSYZnDqHvVF^UzWb<>Y>Sz6;lHRvu zE=S5=B8?@?SlxGtl&fEE^cjm`Sb-qof?N9IN1-8!R9Jr>^^jq?Z;)E*Z(AZulqFT% z1jb-XUsXlKD>RHm45M)hN9w)1<}UHfLP zs3kfq_yAV1)zC$Z_u<@I#BpJKjhCdNo_-`7PgQRN12MjTL;FL$G~3+Sk=;g-HIN=w zpm6+B_&u2jDGrRDrG+I|StNL{VNayAWqCRg-5+U^LJmmalf$blfESt%XhPu)tfZe> zBQ?hJ(2&7g|DdR>2QL}br%ACSa$ALOA@PpNG5?y$3wT7ljvc0=!ji*J;$P==aR4`@ zkXqmW)>Dj|uSz$PzEL8br-qFof`(tP(|##~SR%2zfoW`0pZ*zA$MAG2R%Np;hU!F*jNYVGo|r z3O-qG?i9;^!1h?O#%&-4gE(j>FoN=k=r7R25*dtYb@cLHKBIz>;;JF35CezRhS$XS z$R){*XkVp9$xrsn7I?aGIAE@UVHR4@$gBk|KD1!3Jl}f@Sp3(?3E_P*)J$O?DUB^B z`sMalt4VL7fuglP*jnboFX;Vg}i*q_d-9qF(RweYl*_*4abvKGLs^0&5#n9LsGbA z@cLJ4=Tb;c2(y?@?eAi{Y~Jv>na+VAiU4!_heViuh4#Je2r&m(GkJ$mor1DW4zWXI zxEuz}-5uL9L2E>XrSl=?wVQ!EEhB*9q@K@rI{eTM#LBZP!QS0mo&76D@lSjR6J7?n zs!0&!JEc%y;ibaz`4CTjFsZR?3>YS+=^&rB2Vp!t<7$c2QbzrQx~Z@r|5H;m@|{Q! zDO~FetR~yHuxoX1gavR|BJoJ4GSmndrW?4&5)pqs^C^3bJ<>S%nfLahD>5TC!MfE* z*WzDlWXd{Zz};N&mn^{8iJSkSmu(<6z*m=V>21C9QJ;0BdJ3<_n|7&_7`>B;GTX?1 zS!rOvsYOXu<=nX}KvImiu zVx%~e{$tm<9i~81+~oGXm%^Jr6N`Hr)}G7x4$fq8|EV~$A;w-h1^4`rAzFm=RjJdb zN)Wal!k+m)Zeje)=ZX-^yjC&Z=eBmzT4Gdh!{_IXu-Q?%c)b^zn z6l+d37O0+=ROnmpLL^oG;yWVWVSK2={Lj2_4`OkAD0k<@n2-$at-5F(nlsA9PAKit zmLn>IR9UD&l9?x>R5OBz6{nbus=XrXUbR3mOI=xcS>+gvsT;7q7GBKXJ1cQKOQvJO z#iZ)5c%yt&UvR1&)9n5c$FiHEu7LWnwn{gH*d+m2(V(#rnd;h#W=@W4mzrE%YHrY} z${E#Sr(o*PClFcPr(Vu?eV