diff --git a/docs/widgets/services/komga.md b/docs/widgets/services/komga.md
index c9edaeb2..fc76127f 100644
--- a/docs/widgets/services/komga.md
+++ b/docs/widgets/services/komga.md
@@ -9,6 +9,11 @@ Uses the same username and password used to login from the web.
Allowed fields: `["libraries", "series", "books"]`.
+| Komga API Version | Homepage Widget Version |
+| ----------------- | ----------------------- |
+| < v2 | 1 (default) |
+| >= v2 | 2 |
+
```yaml
widget:
type: komga
diff --git a/src/utils/config/service-helpers.js b/src/utils/config/service-helpers.js
index bd304df9..38e7a2bf 100644
--- a/src/utils/config/service-helpers.js
+++ b/src/utils/config/service-helpers.js
@@ -304,7 +304,7 @@ export function cleanServiceGroups(groups) {
// frigate
enableRecentEvents,
- // beszel, glances, immich, mealie, pihole, pfsense, speedtest
+ // beszel, glances, immich, komga, mealie, pihole, pfsense, speedtest
version,
// glances
@@ -482,7 +482,7 @@ export function cleanServiceGroups(groups) {
if (snapshotHost) widget.snapshotHost = snapshotHost;
if (snapshotPath) widget.snapshotPath = snapshotPath;
}
- if (["beszel", "glances", "immich", "mealie", "pfsense", "pihole", "speedtest"].includes(type)) {
+ if (["beszel", "glances", "immich", "komga", "mealie", "pfsense", "pihole", "speedtest"].includes(type)) {
if (version) widget.version = parseInt(version, 10);
}
if (type === "glances") {
diff --git a/src/utils/proxy/cookie-jar.js b/src/utils/proxy/cookie-jar.js
index 6519231c..baea21d5 100644
--- a/src/utils/proxy/cookie-jar.js
+++ b/src/utils/proxy/cookie-jar.js
@@ -8,7 +8,7 @@ export function setCookieHeader(url, params) {
const existingCookie = cookieJar.getCookieStringSync(url.toString());
if (existingCookie) {
params.headers = params.headers ?? {};
- params.headers.Cookie = existingCookie;
+ params.headers[params.cookieHeader ?? "Cookie"] = existingCookie;
}
}
diff --git a/src/widgets/komga/component.jsx b/src/widgets/komga/component.jsx
index 14af8df4..4272ddfc 100644
--- a/src/widgets/komga/component.jsx
+++ b/src/widgets/komga/component.jsx
@@ -8,16 +8,13 @@ export default function Component({ service }) {
const { t } = useTranslation();
const { widget } = service;
- const { data: libraryData, error: libraryError } = useWidgetAPI(widget, "libraries");
- const { data: seriesData, error: seriesError } = useWidgetAPI(widget, "series");
- const { data: bookData, error: bookError } = useWidgetAPI(widget, "books");
+ const { data: komgaData, error: komgaError } = useWidgetAPI(widget);
- if (libraryError || seriesError || bookError) {
- const finalError = libraryError ?? seriesError ?? bookError;
- return ;
+ if (komgaError) {
+ return ;
}
- if (!libraryData || !seriesData || !bookData) {
+ if (!komgaData) {
return (
@@ -27,9 +24,11 @@ export default function Component({ service }) {
);
}
+ const { libraries: libraryData, series: seriesData, books: bookData } = komgaData;
+
return (
-
+
diff --git a/src/widgets/komga/proxy.js b/src/widgets/komga/proxy.js
new file mode 100644
index 00000000..a827f408
--- /dev/null
+++ b/src/widgets/komga/proxy.js
@@ -0,0 +1,86 @@
+import getServiceWidget from "utils/config/service-helpers";
+import { formatApiCall } from "utils/proxy/api-helpers";
+import { httpProxy } from "utils/proxy/http";
+import widgets from "widgets/widgets";
+import createLogger from "utils/logger";
+
+const proxyName = "komgaProxyHandler";
+const logger = createLogger(proxyName);
+
+export default async function komgaProxyHandler(req, res) {
+ const { group, service, index } = req.query;
+
+ if (group && service) {
+ const widget = await getServiceWidget(group, service, index);
+
+ if (!widgets?.[widget.type]?.api) {
+ return res.status(403).json({ error: "Service does not support API calls" });
+ }
+
+ if (widget) {
+ try {
+ const data = {};
+ const headers = {
+ accept: "application/json",
+ "Content-Type": "application/json",
+ };
+ if (widget.username && widget.password) {
+ headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
+ } else if (widget.key) {
+ headers["X-API-Key"] = widget.key;
+ }
+ const librariesURL = formatApiCall(widgets?.[widget.type].api, { ...widget, endpoint: "libraries" });
+ const [librariesStatus, , librariesData] = await httpProxy(librariesURL, {
+ method: "GET",
+ headers,
+ cookieHeader: "X-Auth-Token",
+ });
+
+ if (librariesStatus !== 200) {
+ return res.status(librariesStatus).send(data);
+ }
+
+ data.libraries = JSON.parse(Buffer.from(librariesData).toString()).filter((library) => !library.unavailable);
+
+ const seriesEndpointName = widget.version === 2 ? "seriesv2" : "series";
+ const seriesEndpoint = widgets[widget.type].mappings[seriesEndpointName].endpoint;
+ const seriesURL = formatApiCall(widgets?.[widget.type].api, { ...widget, endpoint: seriesEndpoint });
+ const [seriesStatus, , seriesData] = await httpProxy(seriesURL, {
+ method: widgets[widget.type].mappings[seriesEndpointName].method || "GET",
+ headers,
+ body: "{}",
+ cookieHeader: "X-Auth-Token",
+ });
+
+ if (seriesStatus !== 200) {
+ return res.status(seriesStatus).send(data);
+ }
+
+ data.series = JSON.parse(Buffer.from(seriesData).toString());
+
+ const booksEndpointName = widget.version === 2 ? "booksv2" : "books";
+ const booksEndpoint = widgets[widget.type].mappings[booksEndpointName].endpoint;
+ const booksURL = formatApiCall(widgets?.[widget.type].api, { ...widget, endpoint: booksEndpoint });
+ const [booksStatus, , booksData] = await httpProxy(booksURL, {
+ method: widgets[widget.type].mappings[booksEndpointName].method || "GET",
+ headers,
+ body: "{}",
+ cookieHeader: "X-Auth-Token",
+ });
+
+ if (booksStatus !== 200) {
+ return res.status(booksStatus).send(data);
+ }
+
+ data.books = JSON.parse(Buffer.from(booksData).toString());
+
+ return res.send(data);
+ } catch (e) {
+ logger.error("Error communicating with Komga API: %s", e);
+ return res.status(500).json({ error: "Error communicating with Komga API" });
+ }
+ }
+ }
+
+ return res.status(400).json({ error: "Invalid proxy service type" });
+}
diff --git a/src/widgets/komga/widget.js b/src/widgets/komga/widget.js
index ee01e391..e89bd746 100644
--- a/src/widgets/komga/widget.js
+++ b/src/widgets/komga/widget.js
@@ -1,25 +1,31 @@
-import genericProxyHandler from "utils/proxy/handlers/generic";
-import { jsonArrayFilter } from "utils/proxy/api-helpers";
+import komgaProxyHandler from "./proxy";
const widget = {
api: "{url}/api/v1/{endpoint}",
- proxyHandler: genericProxyHandler,
+ proxyHandler: komgaProxyHandler,
mappings: {
libraries: {
endpoint: "libraries",
- map: (data) => ({
- total: jsonArrayFilter(data, (item) => !item.unavailable).length,
- }),
},
series: {
endpoint: "series",
validate: ["totalElements"],
},
+ seriesv2: {
+ endpoint: "series/list",
+ method: "POST",
+ validate: ["totalElements"],
+ },
books: {
endpoint: "books",
validate: ["totalElements"],
},
+ booksv2: {
+ endpoint: "books/list",
+ method: "POST",
+ validate: ["totalElements"],
+ },
},
};