From 04a9be5c93682d1e6f9cbe24f975585c0758221b Mon Sep 17 00:00:00 2001
From: Robonau <30987265+Robonau@users.noreply.github>
Date: Tue, 12 Nov 2024 01:33:45 +0000
Subject: [PATCH] resolve review issues
---
docs/widgets/services/suwayomi.md | 30 ++----
src/widgets/suwayomi/component.jsx | 41 ++------
src/widgets/suwayomi/proxy.js | 145 ++++++-----------------------
3 files changed, 43 insertions(+), 173 deletions(-)
diff --git a/docs/widgets/services/suwayomi.md b/docs/widgets/services/suwayomi.md
index 52753474..c4a7b416 100644
--- a/docs/widgets/services/suwayomi.md
+++ b/docs/widgets/services/suwayomi.md
@@ -5,28 +5,16 @@ description: Suwayomi Widget Configuration
Learn more about [Suwayomi](https://github.com/Suwayomi/Suwayomi-Server).
-all supported fields shown in example yaml, though a max of 4 will show at one time.
-The default fields are download, nondownload, read and unread.
-category defaults to "all" if left unset or set to not a number.
-The category ID can be obtained from the url when navigating to it, `?tab={categoryID}`.
-username and password are available if you have basic auth setup for Suwayomi.
+Allowed fields:["download", "nondownload", "read", "unread", "downloadedread", "downloadedunread", "nondownloadedread", "nondownloadedunread"]
+
+The widget defaults to the first four above. If more than four fields are provided, only the first 4 are displayed.
+Category IDs can be obtained from the url when navigating to it, `?tab={categoryID}`.
```yaml
widget:
- icon: https://raw.githubusercontent.com/Suwayomi/Suwayomi-Server/refs/heads/master/server/src/main/resources/icon/faviconlogo-128.png
- widget:
- type: suwayomi
- url: http://suwayomi.host.or.ip
- username: username
- password: password
- category: 0
- fields:
- - download
- - nondownload
- - read
- - unread
- - downloadedRead
- - downloadedunread
- - nondownloadedread
- - nondownloadedunread
+ type: suwayomi
+ url: http://suwayomi.host.or.ip
+ username: username #optional
+ password: password #optional
+ category: 0 #optional, defaults to all categories
```
diff --git a/src/widgets/suwayomi/component.jsx b/src/widgets/suwayomi/component.jsx
index 28bfc951..fa753917 100644
--- a/src/widgets/suwayomi/component.jsx
+++ b/src/widgets/suwayomi/component.jsx
@@ -4,43 +4,11 @@ import Container from "components/services/widget/container";
import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
-/**
- * @param {string[]|null} Fields
- * @returns {string[]}
- */
-function makeFields(Fields = []) {
- let fields = Fields ?? [];
- if (fields.length === 0) {
- fields = ["download", "nonDownload", "read", "unRead"];
- }
- if (fields.length > 4) {
- fields.length = 4;
- }
- fields = fields.map((field) => field.toLowerCase());
-
- return fields;
-}
-
export default function Component({ service }) {
const { t } = useTranslation();
- /**
- * @type {{
- * widget: {
- * fields: string[]|null
- * }
- * }}
- */
const { widget } = service;
- /**
- * @type {{
- * error: unknown
- * data: ({
- * label: string, count: number
- * }[]),
- * }}
- */
const { data: suwayomiData, error: suwayomiError } = useWidgetAPI(widget);
if (suwayomiError) {
@@ -48,10 +16,15 @@ export default function Component({ service }) {
}
if (!suwayomiData) {
- const fields = makeFields(widget.fields);
+ if (!widget.fields || widget.fields.length === 0) {
+ widget.fields = ["download", "nondownload", "read", "unread"];
+ } else if (widget.fields.length > 4) {
+ widget.fields = widget.fields.slice(0, 4);
+ widget.fields = widget.fields.map((field) => field.toLowerCase());
+ }
return (
- {fields.map((field) => (
+ {widget.fields.map((field) => (
))}
diff --git a/src/widgets/suwayomi/proxy.js b/src/widgets/suwayomi/proxy.js
index 324ae291..eb19f388 100644
--- a/src/widgets/suwayomi/proxy.js
+++ b/src/widgets/suwayomi/proxy.js
@@ -7,69 +7,6 @@ import widgets from "widgets/widgets";
const proxyName = "suwayomiProxyHandler";
const logger = createLogger(proxyName);
-/**
- * @typedef {object} countsToExtractItem
- * @property {(chapter: chapter) => boolean} condition
- * @property {string} gqlCondition
- */
-
-/**
- * @typedef totalCount
- * @type {object}
- * @property {string} totalCount - count
- */
-
-/**
- * @typedef ResponseJSON
- * @type {{
- * data: {
- * download: totalCount,
- * nondownload: totalCount,
- * read: totalCount,
- * unread: totalCount,
- * downloadedRead: totalCount,
- * downloadedunread: totalCount,
- * nondownloadedread: totalCount,
- * nondownloadedunread: totalCount,
- * }
- * }}
- */
-
-/**
- * @typedef chapter
- * @type {{
- * isRead: boolean,
- * isDownloaded: boolean
- * }}
- */
-
-/**
- * @typedef ResponseJSONcategory
- * @type {{
- * data: {
- * category: {
- * mangas: {
- * nodes: {
- * chapters: {
- * nodes: chapter[]
- * }
- * }[]
- * }
- * }
- * }
- * }}
- */
-
-/**
- * @typedef {object} widget
- * @property {string} username
- * @property {string} password
- * @property {string[]|null} fields
- * @property {string|number|undefined} category
- * @property {keyof typeof widgets} type
- */
-
-/** @type {Record} */
const countsToExtract = {
download: {
condition: (c) => c.isDownloaded,
@@ -79,9 +16,18 @@ const countsToExtract = {
condition: (c) => !c.isDownloaded,
gqlCondition: "isDownloaded: false",
},
- read: { condition: (c) => c.isRead, gqlCondition: "isRead: true" },
- unread: { condition: (c) => !c.isRead, gqlCondition: "isRead: false" },
- downloadedread: { condition: (c) => c.isDownloaded && c.isRead, gqlCondition: "isDownloaded: true, isRead: true" },
+ read: {
+ condition: (c) => c.isRead,
+ gqlCondition: "isRead: true",
+ },
+ unread: {
+ condition: (c) => !c.isRead,
+ gqlCondition: "isRead: false",
+ },
+ downloadedread: {
+ condition: (c) => c.isDownloaded && c.isRead,
+ gqlCondition: "isDownloaded: true, isRead: true",
+ },
downloadedunread: {
condition: (c) => c.isDownloaded && !c.isRead,
gqlCondition: "isDownloaded: true, isRead: false",
@@ -96,13 +42,6 @@ const countsToExtract = {
},
};
-/**
- * Makes a GraphQL query body based on the provided fieldsSet and category.
- *
- * @param {string[]} fields - Array of field names.
- * @param {string|number|undefined} [category="all"] - Category ID or "all" for general counts.
- * @returns {string} - The JSON stringified query body.
- */
function makeBody(fields, category = "all") {
if (Number.isNaN(Number(category))) {
let query = "";
@@ -148,13 +87,6 @@ function makeBody(fields, category = "all") {
});
}
-/**
- * Extracts the counts from the response JSON object based on the provided fields.
- *
- * @param {ResponseJSON|ResponseJSONcategory} responseJSON - The response JSON object.
- * @param {string[]} fields - Array of field names.
- * @returns
- */
function extractCounts(responseJSON, fields) {
if (!("category" in responseJSON.data)) {
return fields.map((field) => ({
@@ -181,38 +113,6 @@ function extractCounts(responseJSON, fields) {
}));
}
-/**
- * @param {string[]|null} Fields
- * @returns {string[]}
- */
-function makeFields(Fields = []) {
- let fields = Fields ?? [];
- if (fields.length === 0) {
- fields = ["download", "nonDownload", "read", "unRead"];
- }
- if (fields.length > 4) {
- fields.length = 4;
- }
- fields = fields.map((f) => f.toLowerCase());
-
- return fields;
-}
-
-/**
- * @param {widget} widget
- * @returns {{ "Content-Type": string, Authorization?: string }}
- */
-function makeHeaders(widget) {
- const headers = {
- "Content-Type": "application/json",
- };
-
- if (widget.username && widget.password) {
- headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
- }
- return headers;
-}
-
export default async function suwayomiProxyHandler(req, res) {
const { group, service, endpoint } = req.query;
@@ -221,7 +121,6 @@ export default async function suwayomiProxyHandler(req, res) {
return res.status(400).json({ error: "Invalid proxy service type" });
}
- /** @type {widget} */
const widget = await getServiceWidget(group, service);
if (!widget) {
@@ -229,13 +128,24 @@ export default async function suwayomiProxyHandler(req, res) {
return res.status(400).json({ error: "Invalid proxy service type" });
}
- const fields = makeFields(widget.fields);
+ if (!widget.fields || widget.fields.length === 0) {
+ widget.fields = ["download", "nondownload", "read", "unread"];
+ } else if (widget.fields.length > 4) {
+ widget.fields = widget.fields.slice(0, 4);
+ widget.fields = widget.fields.map((field) => field.toLowerCase());
+ }
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
- const body = makeBody(fields, widget.category);
+ const body = makeBody(widget.fields, widget.category);
- const headers = makeHeaders(widget);
+ const headers = {
+ "Content-Type": "application/json",
+ };
+
+ if (widget.username && widget.password) {
+ headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
+ }
const [status, contentType, data] = await httpProxy(url, {
method: "POST",
@@ -259,10 +169,9 @@ export default async function suwayomiProxyHandler(req, res) {
return res.status(status).send({ error: { message: "Error getting data. body: %s, data: %s", body, data } });
}
- /** @type {ResponseJSON|ResponseJSONcategory} */
const responseJSON = JSON.parse(data);
- const returnData = extractCounts(responseJSON, fields);
+ const returnData = extractCounts(responseJSON, widget.fields);
if (contentType) res.setHeader("Content-Type", contentType);
return res.status(status).send(returnData);