diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index 80ba5357e..6466727f9 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -192,6 +192,12 @@
"stopped": "Stopped",
"total": "Total"
},
+ "tdarr": {
+ "queue": "Queue",
+ "processed": "Processed",
+ "errored": "Errored",
+ "saved": "Saved"
+ },
"traefik": {
"routers": "Routers",
"services": "Services",
diff --git a/src/widgets/components.js b/src/widgets/components.js
index b0752b62f..e6021f17d 100644
--- a/src/widgets/components.js
+++ b/src/widgets/components.js
@@ -43,6 +43,7 @@ const components = {
speedtest: dynamic(() => import("./speedtest/component")),
strelaysrv: dynamic(() => import("./strelaysrv/component")),
tautulli: dynamic(() => import("./tautulli/component")),
+ tdarr: dynamic(() => import("./tdarr/component")),
traefik: dynamic(() => import("./traefik/component")),
transmission: dynamic(() => import("./transmission/component")),
tubearchivist: dynamic(() => import("./tubearchivist/component")),
diff --git a/src/widgets/tdarr/component.jsx b/src/widgets/tdarr/component.jsx
new file mode 100644
index 000000000..34e18a978
--- /dev/null
+++ b/src/widgets/tdarr/component.jsx
@@ -0,0 +1,45 @@
+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: tdarrData, error: tdarrError } = useWidgetAPI(widget);
+
+ if (tdarrError) {
+ return ;
+ }
+
+ if (!tdarrData) {
+ return (
+
+
+
+
+
+
+ );
+ }
+
+ // const { torrents } = tdarrData.arguments;
+
+ const queue = parseInt(tdarrData.table1Count) + parseInt(tdarrData.table4Count);
+ const processed = parseInt(tdarrData.table2Count) + parseInt(tdarrData.table5Count);
+ const errored = parseInt(tdarrData.table3Count) + parseInt(tdarrData.table6Count);
+
+ const saved = parseFloat(tdarrData.sizeDiff) * 1000000000;
+
+ return (
+
+
+
+
+
+
+ );
+}
diff --git a/src/widgets/tdarr/proxy.js b/src/widgets/tdarr/proxy.js
new file mode 100644
index 000000000..161d76296
--- /dev/null
+++ b/src/widgets/tdarr/proxy.js
@@ -0,0 +1,58 @@
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
+import getServiceWidget from "utils/config/service-helpers";
+import createLogger from "utils/logger";
+import widgets from "widgets/widgets";
+
+const proxyName = "tdarrProxyHandler";
+const logger = createLogger(proxyName);
+
+export default async function tdarrProxyHandler(req, res) {
+ const { group, service, endpoint } = req.query;
+
+ if (!group || !service) {
+ logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
+ return res.status(400).json({ error: "Invalid proxy service type" });
+ }
+
+ const widget = await getServiceWidget(group, service);
+
+ if (!widget) {
+ logger.debug("Invalid or missing widget for service '%s' in group '%s'", service, group);
+ return res.status(400).json({ error: "Invalid proxy service type" });
+ }
+
+
+
+
+ const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
+
+ const method = "POST";
+
+ const headers = {
+ "content-type": "application/json",
+ };
+
+ const body = JSON.stringify({
+ "data": {
+ "collection": "StatisticsJSONDB",
+ "mode": "getById",
+ "docID": "statistics"
+ }
+ });
+
+ let [status, contentType, data, responseHeaders] = await httpProxy(url, {
+ method,
+ body,
+ headers,
+ });
+
+
+ if (status !== 200) {
+ logger.error("Error getting data from Tdarr: %d. Data: %s", status, data);
+ return res.status(500).send({error: {message:"Error getting data from Tdarr", url, data}});
+ }
+
+ if (contentType) res.setHeader("Content-Type", contentType);
+ return res.status(status).send(data);
+}
diff --git a/src/widgets/tdarr/widget.js b/src/widgets/tdarr/widget.js
new file mode 100644
index 000000000..f26713f21
--- /dev/null
+++ b/src/widgets/tdarr/widget.js
@@ -0,0 +1,8 @@
+import tdarrProxyHandler from "./proxy";
+
+const widget = {
+ api: "{url}/api/v2/cruddb",
+ proxyHandler: tdarrProxyHandler,
+};
+
+export default widget;
diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js
index b3eaa8855..cda52cc04 100644
--- a/src/widgets/widgets.js
+++ b/src/widgets/widgets.js
@@ -38,6 +38,7 @@ import sonarr from "./sonarr/widget";
import speedtest from "./speedtest/widget";
import strelaysrv from "./strelaysrv/widget";
import tautulli from "./tautulli/widget";
+import tdarr from "./tdarr/widget";
import traefik from "./traefik/widget";
import transmission from "./transmission/widget";
import tubearchivist from "./tubearchivist/widget";
@@ -87,6 +88,7 @@ const widgets = {
speedtest,
strelaysrv,
tautulli,
+ tdarr,
traefik,
transmission,
tubearchivist,