mirror of
https://github.com/gethomepage/homepage.git
synced 2025-12-07 09:35:54 -08:00
Merge branch 'main' into kubernetes
This commit is contained in:
@@ -12,9 +12,9 @@ export default function Component({ service }) {
|
||||
const { data: adguardData, error: adguardError } = useWidgetAPI(widget, "stats");
|
||||
|
||||
if (adguardError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={adguardError} />;
|
||||
}
|
||||
|
||||
|
||||
if (!adguardData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
|
||||
@@ -14,7 +14,8 @@ export default function Component({ service }) {
|
||||
const { data: failedLoginsData, error: failedLoginsError } = useWidgetAPI(widget, "login_failed");
|
||||
|
||||
if (usersError || loginsError || failedLoginsError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
const finalError = usersError ?? loginsError ?? failedLoginsError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!usersData || !loginsData || !failedLoginsData) {
|
||||
|
||||
@@ -14,7 +14,8 @@ export default function Component({ service }) {
|
||||
const { data: indexersData, error: indexersError } = useWidgetAPI(widget, "indexers");
|
||||
|
||||
if (statsError || filtersError || indexersError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
const finalError = statsError ?? filtersError ?? indexersError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!statsData || !filtersData || !indexersData) {
|
||||
|
||||
@@ -7,6 +7,10 @@ const widget = {
|
||||
mappings: {
|
||||
stats: {
|
||||
endpoint: "release/stats",
|
||||
validate: [
|
||||
"push_approved_count",
|
||||
"push_rejected_count"
|
||||
]
|
||||
},
|
||||
filters: {
|
||||
endpoint: "filters",
|
||||
|
||||
@@ -12,8 +12,9 @@ export default function Component({ service }) {
|
||||
const { data: episodesData, error: episodesError } = useWidgetAPI(widget, "episodes");
|
||||
const { data: moviesData, error: moviesError } = useWidgetAPI(widget, "movies");
|
||||
|
||||
if (episodesError || moviesError) {
|
||||
return <Container error="widget.api_error" />;
|
||||
if (moviesError || episodesError) {
|
||||
const finalError = moviesError ?? episodesError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!episodesData || !moviesData) {
|
||||
|
||||
@@ -9,12 +9,11 @@ export default function Component({ service }) {
|
||||
|
||||
const { widget } = service;
|
||||
|
||||
const { data } = useWidgetAPI(widget, "info");
|
||||
const { data, error } = useWidgetAPI(widget, "info");
|
||||
|
||||
if (!data) {
|
||||
return <Container error="widget.api_error" />;
|
||||
if (error) {
|
||||
return <Container error={error} />;
|
||||
}
|
||||
|
||||
const totalObserved = Object.keys(data).length;
|
||||
let diffsDetected = 0;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function Component({ service }) {
|
||||
}
|
||||
|
||||
if (statsError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={statsError} />;
|
||||
}
|
||||
|
||||
if (!statsData || !dateRange) {
|
||||
|
||||
@@ -12,6 +12,7 @@ const components = {
|
||||
emby: dynamic(() => import("./emby/component")),
|
||||
gluetun: dynamic(() => import("./gluetun/component")),
|
||||
gotify: dynamic(() => import("./gotify/component")),
|
||||
hdhomerun: dynamic(() => import("./hdhomerun/component")),
|
||||
homebridge: dynamic(() => import("./homebridge/component")),
|
||||
jackett: dynamic(() => import("./jackett/component")),
|
||||
jellyfin: dynamic(() => import("./emby/component")),
|
||||
|
||||
@@ -17,8 +17,9 @@ export default function Component({ service }) {
|
||||
|
||||
const { data: statsData, error: statsError } = useSWR(`/api/docker/stats/${widget.container}/${widget.server || ""}`);
|
||||
|
||||
if (statsError || statusError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
if (statsError || statsData?.error || statusError || statusData?.error) {
|
||||
const finalError = statsError ?? statsData?.error ?? statusError ?? statusData?.error;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (statusData && statusData.status !== "running") {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import useSWR from "swr";
|
||||
import { useTranslation } from "next-i18next";
|
||||
import { BsVolumeMuteFill, BsFillPlayFill, BsPauseFill, BsCpu, BsFillCpuFill } from "react-icons/bs";
|
||||
import { MdOutlineSmartDisplay } from "react-icons/md";
|
||||
|
||||
import Container from "components/services/widget/container";
|
||||
import { formatProxyUrl, formatProxyUrlWithSegments } from "utils/proxy/api-helpers";
|
||||
import { formatProxyUrlWithSegments } from "utils/proxy/api-helpers";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
function ticksToTime(ticks) {
|
||||
const milliseconds = ticks / 10000;
|
||||
@@ -157,7 +157,7 @@ export default function Component({ service }) {
|
||||
data: sessionsData,
|
||||
error: sessionsError,
|
||||
mutate: sessionMutate,
|
||||
} = useSWR(formatProxyUrl(widget, "Sessions"), {
|
||||
} = useWidgetAPI(widget, "Sessions", {
|
||||
refreshInterval: 5000,
|
||||
});
|
||||
|
||||
@@ -171,8 +171,8 @@ export default function Component({ service }) {
|
||||
});
|
||||
}
|
||||
|
||||
if (sessionsError || sessionsData?.error) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
if (sessionsError) {
|
||||
return <Container error={sessionsError} />;
|
||||
}
|
||||
|
||||
if (!sessionsData) {
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
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: gluetunData, error: gluetunError } = useWidgetAPI(widget, "ip");
|
||||
|
||||
if (gluetunError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={gluetunError} />;
|
||||
}
|
||||
|
||||
if (!gluetunData) {
|
||||
|
||||
@@ -7,6 +7,11 @@ const widget = {
|
||||
mappings: {
|
||||
ip: {
|
||||
endpoint: "publicip/ip",
|
||||
validate: [
|
||||
"public_ip",
|
||||
"region",
|
||||
"country"
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
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: appsData, error: appsError } = useWidgetAPI(widget, "application");
|
||||
@@ -14,7 +10,8 @@ export default function Component({ service }) {
|
||||
const { data: clientsData, error: clientsError } = useWidgetAPI(widget, "client");
|
||||
|
||||
if (appsError || messagesError || clientsError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
const finalError = appsError ?? messagesError ?? clientsError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
|
||||
|
||||
32
src/widgets/hdhomerun/component.jsx
Normal file
32
src/widgets/hdhomerun/component.jsx
Normal file
@@ -0,0 +1,32 @@
|
||||
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 { widget } = service;
|
||||
|
||||
const { data: channelsData, error: channelsError } = useWidgetAPI(widget, "lineup");
|
||||
|
||||
if (channelsError) {
|
||||
return <Container error={channelsError} />;
|
||||
}
|
||||
|
||||
if (!channelsData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="hdhomerun.channels" />
|
||||
<Block label="hdhomerun.hd" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
const hdChannels = channelsData?.filter((channel) => channel.HD === 1);
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="hdhomerun.channels" value={channelsData.length } />
|
||||
<Block label="hdhomerun.hd" value={hdChannels.length} />
|
||||
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
14
src/widgets/hdhomerun/widget.js
Normal file
14
src/widgets/hdhomerun/widget.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/{endpoint}",
|
||||
proxyHandler: genericProxyHandler,
|
||||
|
||||
mappings: {
|
||||
"lineup": {
|
||||
endpoint: "lineup.json",
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default widget;
|
||||
@@ -11,8 +11,8 @@ export default function Component({ service }) {
|
||||
|
||||
const { data: homebridgeData, error: homebridgeError } = useWidgetAPI(widget, "info");
|
||||
|
||||
if (homebridgeError || homebridgeData?.error) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
if (homebridgeError) {
|
||||
return <Container error={homebridgeError} />;
|
||||
}
|
||||
|
||||
if (!homebridgeData) {
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function Component({ service }) {
|
||||
const { data: indexersData, error: indexersError } = useWidgetAPI(widget, "indexers");
|
||||
|
||||
if (indexersError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={indexersError} />;
|
||||
}
|
||||
|
||||
if (!indexersData) {
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
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, "request/count");
|
||||
|
||||
if (statsError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={statsError} />;
|
||||
}
|
||||
|
||||
if (!statsData) {
|
||||
|
||||
@@ -7,6 +7,11 @@ const widget = {
|
||||
mappings: {
|
||||
"request/count": {
|
||||
endpoint: "request/count",
|
||||
validate: [
|
||||
"pending",
|
||||
"approved",
|
||||
"available"
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,7 +14,8 @@ export default function Component({ service }) {
|
||||
const { data: queueData, error: queueError } = useWidgetAPI(widget, "queue/status");
|
||||
|
||||
if (albumsError || wantedError || queueError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
const finalError = albumsError ?? wantedError ?? queueError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!albumsData || !wantedData || !queueData) {
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function Component({ service }) {
|
||||
const { data: statsData, error: statsError } = useWidgetAPI(widget, "instance");
|
||||
|
||||
if (statsError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={statsError} />;
|
||||
}
|
||||
|
||||
if (!statsData) {
|
||||
|
||||
@@ -26,8 +26,8 @@ export default function Component({ service }) {
|
||||
|
||||
const { data: navidromeData, error: navidromeError } = useWidgetAPI(widget, "getNowPlaying");
|
||||
|
||||
if (navidromeError || navidromeData?.error || navidromeData?.["subsonic-response"]?.error) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
if (navidromeError || navidromeData?.["subsonic-response"]?.error) {
|
||||
return <Container error={navidromeError ?? navidromeData?.["subsonic-response"]?.error} />;
|
||||
}
|
||||
|
||||
if (!navidromeData) {
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
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: infoData, error: infoError } = useWidgetAPI(widget, "nginx/proxy-hosts");
|
||||
|
||||
if (infoError || infoData?.error) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
if (infoError) {
|
||||
return <Container error={infoError} />;
|
||||
}
|
||||
|
||||
if (!infoData) {
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function Component({ service }) {
|
||||
const { data: statusData, error: statusError } = useWidgetAPI(widget, "status");
|
||||
|
||||
if (statusError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={statusError} />;
|
||||
}
|
||||
|
||||
if (!statusData) {
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
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, "Request/count");
|
||||
|
||||
if (statsError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={statsError} />;
|
||||
}
|
||||
|
||||
if (!statsData) {
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
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, "request/count");
|
||||
|
||||
if (statsError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={statsError} />;
|
||||
}
|
||||
|
||||
if (!statsData) {
|
||||
|
||||
@@ -7,6 +7,11 @@ const widget = {
|
||||
mappings: {
|
||||
"request/count": {
|
||||
endpoint: "request/count",
|
||||
validate: [
|
||||
"pending",
|
||||
"approved",
|
||||
"available",
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function Component({ service }) {
|
||||
const { data: piholeData, error: piholeError } = useWidgetAPI(widget, "api.php");
|
||||
|
||||
if (piholeError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={piholeError} />;
|
||||
}
|
||||
|
||||
if (!piholeData) {
|
||||
|
||||
@@ -7,6 +7,11 @@ const widget = {
|
||||
mappings: {
|
||||
"api.php": {
|
||||
endpoint: "api.php",
|
||||
validate: [
|
||||
"dns_queries_today",
|
||||
"ads_blocked_today",
|
||||
"domains_being_blocked"
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
import useSWR from "swr";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Block from "components/services/widget/block";
|
||||
import Container from "components/services/widget/container";
|
||||
import { formatProxyUrl } from "utils/proxy/api-helpers";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { widget } = service;
|
||||
|
||||
const { data: plexData, error: plexAPIError } = useSWR(formatProxyUrl(widget, "unified"), {
|
||||
const { data: plexData, error: plexAPIError } = useWidgetAPI(widget, "unified", {
|
||||
refreshInterval: 5000,
|
||||
});
|
||||
|
||||
if (plexAPIError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={plexAPIError} />;
|
||||
}
|
||||
|
||||
if (!plexData) {
|
||||
|
||||
@@ -44,7 +44,7 @@ async function fetchFromPlexAPI(endpoint, widget) {
|
||||
|
||||
if (status !== 200) {
|
||||
logger.error("HTTP %d communicating with Plex. Data: %s", status, data.toString());
|
||||
return [status, data.toString()];
|
||||
return [status, data];
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -65,6 +65,11 @@ export default async function plexProxyHandler(req, res) {
|
||||
logger.debug("Getting streams from Plex API");
|
||||
let streams;
|
||||
let [status, apiData] = await fetchFromPlexAPI("/status/sessions", widget);
|
||||
|
||||
if (status !== 200) {
|
||||
return res.status(status).json({error: {message: "HTTP error communicating with Plex API", data: Buffer.from(apiData).toString()}});
|
||||
}
|
||||
|
||||
if (apiData && apiData.MediaContainer) {
|
||||
streams = apiData.MediaContainer._attributes.size;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ export default function Component({ service }) {
|
||||
});
|
||||
|
||||
if (containersError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={containersError} />;
|
||||
}
|
||||
|
||||
if (!containersData) {
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
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: indexersData, error: indexersError } = useWidgetAPI(widget, "indexer");
|
||||
const { data: grabsData, error: grabsError } = useWidgetAPI(widget, "indexerstats");
|
||||
|
||||
if (indexersError || grabsError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
const finalError = indexersError ?? grabsError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!indexersData || !grabsData) {
|
||||
|
||||
@@ -16,7 +16,7 @@ export default function Component({ service }) {
|
||||
const { data: clusterData, error: clusterError } = useWidgetAPI(widget, "cluster/resources");
|
||||
|
||||
if (clusterError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={clusterError} />;
|
||||
}
|
||||
|
||||
if (!clusterData || !clusterData.data) {
|
||||
|
||||
@@ -9,8 +9,8 @@ export default function Component({ service }) {
|
||||
const { widget } = service;
|
||||
const { data: pyloadData, error: pyloadError } = useWidgetAPI(widget, "status");
|
||||
|
||||
if (pyloadError || pyloadData?.error) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
if (pyloadError) {
|
||||
return <Container error={pyloadError} />;
|
||||
}
|
||||
|
||||
if (!pyloadData) {
|
||||
|
||||
@@ -84,9 +84,9 @@ export default async function pyloadProxyHandler(req, res) {
|
||||
|
||||
if (data?.error || status !== 200) {
|
||||
try {
|
||||
return res.status(status).send(Buffer.from(data).toString());
|
||||
return res.status(status).send({error: {message: "HTTP error communicating with Plex API", data: Buffer.from(data).toString()}});
|
||||
} catch (e) {
|
||||
return res.status(status).send(data);
|
||||
return res.status(status).send({error: {message: "HTTP error communicating with Plex API", data}});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ export default async function pyloadProxyHandler(req, res) {
|
||||
}
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
return res.status(500).send(e.toString());
|
||||
return res.status(500).send({error: {message: `Error communicating with Plex API: ${e.toString()}`}});
|
||||
}
|
||||
|
||||
return res.status(400).json({ error: 'Invalid proxy service type' });
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function Component({ service }) {
|
||||
const { data: torrentData, error: torrentError } = useWidgetAPI(widget, "torrents/info");
|
||||
|
||||
if (torrentError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={torrentError} />;
|
||||
}
|
||||
|
||||
if (!torrentData) {
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
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: moviesData, error: moviesError } = useWidgetAPI(widget, "movie");
|
||||
const { data: queuedData, error: queuedError } = useWidgetAPI(widget, "queue/status");
|
||||
|
||||
if (moviesError || queuedError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
const finalError = moviesError ?? queuedError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!moviesData || !queuedData) {
|
||||
|
||||
@@ -16,6 +16,9 @@ const widget = {
|
||||
},
|
||||
"queue/status": {
|
||||
endpoint: "queue/status",
|
||||
validate: [
|
||||
"totalCount"
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,7 +14,8 @@ export default function Component({ service }) {
|
||||
const { data: queueData, error: queueError } = useWidgetAPI(widget, "queue/status");
|
||||
|
||||
if (booksError || wantedError || queueError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
const finalError = booksError ?? wantedError ?? queueError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!booksData || !wantedData || !queueData) {
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function Component({ service }) {
|
||||
const { data: statusData, error: statusError } = useWidgetAPI(widget);
|
||||
|
||||
if (statusError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={statusError} />;
|
||||
}
|
||||
|
||||
if (!statusData) {
|
||||
|
||||
@@ -22,7 +22,7 @@ export default function Component({ service }) {
|
||||
const { data: queueData, error: queueError } = useWidgetAPI(widget, "queue");
|
||||
|
||||
if (queueError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={queueError} />;
|
||||
}
|
||||
|
||||
if (!queueData) {
|
||||
|
||||
@@ -7,6 +7,9 @@ const widget = {
|
||||
mappings: {
|
||||
queue: {
|
||||
endpoint: "queue",
|
||||
validate: [
|
||||
"queue"
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
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: wantedData, error: wantedError } = useWidgetAPI(widget, "wanted/missing");
|
||||
@@ -14,7 +10,8 @@ export default function Component({ service }) {
|
||||
const { data: seriesData, error: seriesError } = useWidgetAPI(widget, "series");
|
||||
|
||||
if (wantedError || queuedError || seriesError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
const finalError = wantedError ?? queuedError ?? seriesError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!wantedData || !queuedData || !seriesData) {
|
||||
|
||||
@@ -10,13 +10,19 @@ const widget = {
|
||||
endpoint: "series",
|
||||
map: (data) => ({
|
||||
total: asJson(data).length,
|
||||
}),
|
||||
})
|
||||
},
|
||||
queue: {
|
||||
endpoint: "queue",
|
||||
validate: [
|
||||
"totalRecords"
|
||||
]
|
||||
},
|
||||
"wanted/missing": {
|
||||
endpoint: "wanted/missing",
|
||||
validate: [
|
||||
"totalRecords"
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -11,8 +11,8 @@ export default function Component({ service }) {
|
||||
|
||||
const { data: speedtestData, error: speedtestError } = useWidgetAPI(widget, "speedtest/latest");
|
||||
|
||||
if (speedtestError || (speedtestData && !speedtestData.data)) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
if (speedtestError) {
|
||||
return <Container error={speedtestError} />;
|
||||
}
|
||||
|
||||
if (!speedtestData) {
|
||||
|
||||
@@ -7,6 +7,9 @@ const widget = {
|
||||
mappings: {
|
||||
"speedtest/latest": {
|
||||
endpoint: "speedtest/latest",
|
||||
validate: [
|
||||
"data"
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function Component({ service }) {
|
||||
const { data: statsData, error: statsError } = useWidgetAPI(widget, "status");
|
||||
|
||||
if (statsError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={statsError} />;
|
||||
}
|
||||
|
||||
if (!statsData) {
|
||||
|
||||
@@ -7,6 +7,11 @@ const widget = {
|
||||
mappings: {
|
||||
status: {
|
||||
endpoint: "status",
|
||||
validate: [
|
||||
"numActiveSessions",
|
||||
"numConnections",
|
||||
"bytesProxied"
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
/* eslint-disable camelcase */
|
||||
import useSWR from "swr";
|
||||
import { useTranslation } from "next-i18next";
|
||||
import { BsFillPlayFill, BsPauseFill, BsCpu, BsFillCpuFill } from "react-icons/bs";
|
||||
import { MdOutlineSmartDisplay, MdSmartDisplay } from "react-icons/md";
|
||||
|
||||
import Container from "components/services/widget/container";
|
||||
import { formatProxyUrl } from "utils/proxy/api-helpers";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
function millisecondsToTime(milliseconds) {
|
||||
const seconds = Math.floor((milliseconds / 1000) % 60);
|
||||
@@ -119,12 +118,12 @@ export default function Component({ service }) {
|
||||
|
||||
const { widget } = service;
|
||||
|
||||
const { data: activityData, error: activityError } = useSWR(formatProxyUrl(widget, "get_activity"), {
|
||||
const { data: activityData, error: activityError } = useWidgetAPI(widget, "get_activity", {
|
||||
refreshInterval: 5000,
|
||||
});
|
||||
|
||||
if (activityError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={activityError} />;
|
||||
}
|
||||
|
||||
if (!activityData) {
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
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: traefikData, error: traefikError } = useWidgetAPI(widget, "overview");
|
||||
|
||||
if (traefikError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={traefikError} />;
|
||||
}
|
||||
|
||||
if (!traefikData) {
|
||||
|
||||
@@ -7,6 +7,9 @@ const widget = {
|
||||
mappings: {
|
||||
overview: {
|
||||
endpoint: "overview",
|
||||
validate: [
|
||||
"http"
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function Component({ service }) {
|
||||
const { data: torrentData, error: torrentError } = useWidgetAPI(widget);
|
||||
|
||||
if (torrentError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
return <Container error={torrentError} />;
|
||||
}
|
||||
|
||||
if (!torrentData) {
|
||||
|
||||
@@ -68,6 +68,7 @@ export default async function transmissionProxyHandler(req, res) {
|
||||
|
||||
if (status !== 200) {
|
||||
logger.error("Error getting data from Transmission: %d. Data: %s", status, data);
|
||||
return res.status(500).send({error: {message:"Error getting data from Transmission", url, data}});
|
||||
}
|
||||
|
||||
if (contentType) res.setHeader("Content-Type", contentType);
|
||||
|
||||
@@ -42,7 +42,8 @@ export default function Component({ service }) {
|
||||
const { data: statusData, error: statusError } = useWidgetAPI(widget, "status");
|
||||
|
||||
if (alertError || statusError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
const finalError = alertError ?? statusError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!alertData || !statusData) {
|
||||
|
||||
@@ -14,6 +14,10 @@ const widget = {
|
||||
},
|
||||
status: {
|
||||
endpoint: "system/info",
|
||||
validate: [
|
||||
"loadavg",
|
||||
"uptime_seconds"
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -15,7 +15,8 @@ export default function Component({ service }) {
|
||||
const { data: playlistsData, error: playlistsError } = useWidgetAPI(widget, "playlists");
|
||||
|
||||
if (downloadsError || videosError || channelsError || playlistsError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
const finalError = downloadsError ?? videosError ?? channelsError ?? playlistsError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!downloadsData || !videosData || !channelsData || !playlistsData) {
|
||||
|
||||
@@ -7,15 +7,27 @@ const widget = {
|
||||
mappings: {
|
||||
downloads: {
|
||||
endpoint: "download",
|
||||
validate: [
|
||||
"paginate",
|
||||
]
|
||||
},
|
||||
videos: {
|
||||
endpoint: "video",
|
||||
validate: [
|
||||
"paginate",
|
||||
]
|
||||
},
|
||||
channels: {
|
||||
endpoint: "channel",
|
||||
validate: [
|
||||
"paginate",
|
||||
]
|
||||
},
|
||||
playlists: {
|
||||
endpoint: "playlist",
|
||||
validate: [
|
||||
"paginate",
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -11,8 +11,8 @@ export default function Component({ service }) {
|
||||
|
||||
const { data: statsData, error: statsError } = useWidgetAPI(widget, "stat/sites");
|
||||
|
||||
if (statsError || statsData?.error) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
if (statsError) {
|
||||
return <Container error={statsError} />;
|
||||
}
|
||||
|
||||
const defaultSite = statsData?.data?.find(s => s.name === "default");
|
||||
|
||||
@@ -74,7 +74,7 @@ export default async function unifiProxyHandler(req, res) {
|
||||
// don't make two requests each time data from Unifi is required
|
||||
[status, contentType, data, responseHeaders] = await httpProxy(widget.url);
|
||||
prefix = "";
|
||||
if (responseHeaders["x-csrf-token"]) {
|
||||
if (responseHeaders?.["x-csrf-token"]) {
|
||||
prefix = udmpPrefix;
|
||||
}
|
||||
cache.put(prefixCacheKey, prefix);
|
||||
@@ -88,13 +88,14 @@ export default async function unifiProxyHandler(req, res) {
|
||||
setCookieHeader(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);
|
||||
return res.status(status).end(data);
|
||||
return res.status(status).json({error: {message: `HTTP Error ${status}`, url, data}});
|
||||
}
|
||||
|
||||
const json = JSON.parse(data.toString());
|
||||
@@ -112,6 +113,7 @@ export default async function unifiProxyHandler(req, res) {
|
||||
|
||||
if (status !== 200) {
|
||||
logger.error("HTTP %d getting data from Unifi endpoint %s. Data: %s", status, url.href, data);
|
||||
return res.status(status).json({error: {message: `HTTP Error ${status}`, url, data}});
|
||||
}
|
||||
|
||||
if (contentType) res.setHeader("Content-Type", contentType);
|
||||
|
||||
@@ -12,8 +12,8 @@ export default function Component({ service }) {
|
||||
|
||||
const { data: watchData, error: watchError } = useWidgetAPI(widget, "watchtower");
|
||||
|
||||
if (watchError || !watchData) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
if (watchError) {
|
||||
return <Container error={watchError} />;
|
||||
}
|
||||
|
||||
if (!watchData) {
|
||||
|
||||
@@ -33,15 +33,16 @@ export default async function watchtowerProxyHandler(req, res) {
|
||||
|
||||
if (status !== 200 || !data) {
|
||||
logger.error("Error getting data from WatchTower: %d. Data: %s", status, data);
|
||||
return res.status(status).json({error: {message: `HTTP Error ${status}`, url, data}});
|
||||
}
|
||||
|
||||
const cleanData = data.toString().split("\n").filter(s => s.startsWith("watchtower"))
|
||||
const cleanData = data.toString().split("\n").filter(s => s.startsWith("watchtower"));
|
||||
const jsonRes = {}
|
||||
|
||||
cleanData.map(e => e.split(" ")).forEach(strArray => {
|
||||
const [key, value] = strArray
|
||||
jsonRes[key] = value
|
||||
})
|
||||
});
|
||||
|
||||
if (contentType) res.setHeader("Content-Type", contentType);
|
||||
return res.status(status).send(jsonRes);
|
||||
|
||||
@@ -7,6 +7,7 @@ import coinmarketcap from "./coinmarketcap/widget";
|
||||
import emby from "./emby/widget";
|
||||
import gluetun from "./gluetun/widget";
|
||||
import gotify from "./gotify/widget";
|
||||
import hdhomerun from "./hdhomerun/widget";
|
||||
import homebridge from "./homebridge/widget";
|
||||
import jackett from "./jackett/widget";
|
||||
import jellyseerr from "./jellyseerr/widget";
|
||||
@@ -49,6 +50,7 @@ const widgets = {
|
||||
emby,
|
||||
gluetun,
|
||||
gotify,
|
||||
hdhomerun,
|
||||
homebridge,
|
||||
jackett,
|
||||
jellyfin: emby,
|
||||
|
||||
Reference in New Issue
Block a user