mirror of
https://github.com/DI0IK/homepage-plus.git
synced 2025-07-10 15:28:47 +00:00
starting of widget refactoring
This commit is contained in:
parent
d6f6ea9dba
commit
562235f828
42 changed files with 337 additions and 301 deletions
|
@ -1,44 +1,44 @@
|
|||
const formats = {
|
||||
emby: `{url}/emby/{endpoint}?api_key={key}`,
|
||||
jellyfin: `{url}/emby/{endpoint}?api_key={key}`,
|
||||
pihole: `{url}/admin/{endpoint}`,
|
||||
radarr: `{url}/api/v3/{endpoint}?apikey={key}`,
|
||||
sonarr: `{url}/api/v3/{endpoint}?apikey={key}`,
|
||||
speedtest: `{url}/api/{endpoint}`,
|
||||
tautulli: `{url}/api/v2?apikey={key}&cmd={endpoint}`,
|
||||
traefik: `{url}/api/{endpoint}`,
|
||||
portainer: `{url}/api/endpoints/{env}/{endpoint}`,
|
||||
rutorrent: `{url}/plugins/httprpc/action.php`,
|
||||
transmission: `{url}/transmission/rpc`,
|
||||
qbittorrent: `{url}/api/v2/{endpoint}`,
|
||||
jellyseerr: `{url}/api/v1/{endpoint}`,
|
||||
overseerr: `{url}/api/v1/{endpoint}`,
|
||||
ombi: `{url}/api/v1/{endpoint}`,
|
||||
npm: `{url}/api/{endpoint}`,
|
||||
lidarr: `{url}/api/v1/{endpoint}?apikey={key}`,
|
||||
readarr: `{url}/api/v1/{endpoint}?apikey={key}`,
|
||||
bazarr: `{url}/api/{endpoint}/wanted?apikey={key}`,
|
||||
sabnzbd: `{url}/api/?apikey={key}&output=json&mode={endpoint}`,
|
||||
coinmarketcap: `https://pro-api.coinmarketcap.com/{endpoint}`,
|
||||
gotify: `{url}/{endpoint}`,
|
||||
prowlarr: `{url}/api/v1/{endpoint}`,
|
||||
jackett: `{url}/api/v2.0/{endpoint}?apikey={key}&configured=true`,
|
||||
adguard: `{url}/control/{endpoint}`,
|
||||
strelaysrv: `{url}/{endpoint}`,
|
||||
mastodon: `{url}/api/v1/{endpoint}`,
|
||||
};
|
||||
// const formats = {
|
||||
// emby: `{url}/emby/{endpoint}?api_key={key}`,
|
||||
// jellyfin: `{url}/emby/{endpoint}?api_key={key}`,
|
||||
// pihole: `{url}/admin/{endpoint}`,
|
||||
// radarr: `{url}/api/v3/{endpoint}?apikey={key}`,
|
||||
// sonarr: `{url}/api/v3/{endpoint}?apikey={key}`,
|
||||
// speedtest: `{url}/api/{endpoint}`,
|
||||
// tautulli: `{url}/api/v2?apikey={key}&cmd={endpoint}`,
|
||||
// traefik: `{url}/api/{endpoint}`,
|
||||
// portainer: `{url}/api/endpoints/{env}/{endpoint}`,
|
||||
// rutorrent: `{url}/plugins/httprpc/action.php`,
|
||||
// transmission: `{url}/transmission/rpc`,
|
||||
// qbittorrent: `{url}/api/v2/{endpoint}`,
|
||||
// jellyseerr: `{url}/api/v1/{endpoint}`,
|
||||
// overseerr: `{url}/api/v1/{endpoint}`,
|
||||
// ombi: `{url}/api/v1/{endpoint}`,
|
||||
// npm: `{url}/api/{endpoint}`,
|
||||
// lidarr: `{url}/api/v1/{endpoint}?apikey={key}`,
|
||||
// readarr: `{url}/api/v1/{endpoint}?apikey={key}`,
|
||||
// bazarr: `{url}/api/{endpoint}/wanted?apikey={key}`,
|
||||
// sabnzbd: `{url}/api/?apikey={key}&output=json&mode={endpoint}`,
|
||||
// coinmarketcap: `https://pro-api.coinmarketcap.com/{endpoint}`,
|
||||
// gotify: `{url}/{endpoint}`,
|
||||
// prowlarr: `{url}/api/v1/{endpoint}`,
|
||||
// jackett: `{url}/api/v2.0/{endpoint}?apikey={key}&configured=true`,
|
||||
// adguard: `{url}/control/{endpoint}`,
|
||||
// strelaysrv: `{url}/{endpoint}`,
|
||||
// mastodon: `{url}/api/v1/{endpoint}`,
|
||||
// };
|
||||
|
||||
export function formatApiCall(api, args) {
|
||||
export function formatApiCall(url, args) {
|
||||
const find = /\{.*?\}/g;
|
||||
const replace = (match) => {
|
||||
const key = match.replace(/\{|\}/g, "");
|
||||
return args[key];
|
||||
};
|
||||
|
||||
return formats[api].replace(find, replace);
|
||||
return url.replace(find, replace);
|
||||
}
|
||||
|
||||
export function formatApiUrl(widget, endpoint) {
|
||||
export function formatProxyUrl(widget, endpoint) {
|
||||
const params = new URLSearchParams({
|
||||
type: widget.type,
|
||||
group: widget.service_group,
|
||||
|
@ -47,3 +47,23 @@ export function formatApiUrl(widget, endpoint) {
|
|||
});
|
||||
return `/api/services/proxy?${params.toString()}`;
|
||||
}
|
||||
|
||||
export function asJson(data) {
|
||||
if (data?.length > 0) {
|
||||
const json = JSON.parse(data.toString());
|
||||
return json;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
export function jsonArrayTransform(data, transform) {
|
||||
const json = asJson(data);
|
||||
if (json instanceof Array) {
|
||||
return transform(json);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
export function jsonArrayFilter(data, filter) {
|
||||
return jsonArrayTransform(data, (items) => items.filter(filter));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import getServiceWidget from "utils/service-helpers";
|
||||
import { formatApiCall } from "utils/api-helpers";
|
||||
import { httpProxy } from "utils/http";
|
||||
import widgets from "widgets/widgets";
|
||||
|
||||
export default async function credentialedProxyHandler(req, res) {
|
||||
const { group, service, endpoint } = req.query;
|
||||
|
@ -8,8 +9,12 @@ export default async function credentialedProxyHandler(req, res) {
|
|||
if (group && service) {
|
||||
const widget = await getServiceWidget(group, service);
|
||||
|
||||
if (!widgets?.[widget.type]?.api) {
|
||||
return res.status(403).json({ error: "Service does not support API calls" });
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
const url = new URL(formatApiCall(widget.type, { endpoint, ...widget }));
|
||||
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
|
||||
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
|
|
|
@ -2,17 +2,22 @@ import getServiceWidget from "utils/service-helpers";
|
|||
import { formatApiCall } from "utils/api-helpers";
|
||||
import { httpProxy } from "utils/http";
|
||||
import createLogger from "utils/logger";
|
||||
import widgets from "widgets/widgets";
|
||||
|
||||
const logger = createLogger('genericProxyHandler');
|
||||
const logger = createLogger("genericProxyHandler");
|
||||
|
||||
export default async function genericProxyHandler(req, res, maps) {
|
||||
export default async function genericProxyHandler(req, res, map) {
|
||||
const { group, service, endpoint } = req.query;
|
||||
|
||||
if (group && service) {
|
||||
const widget = await getServiceWidget(group, service);
|
||||
|
||||
if (!widgets?.[widget.type]?.api) {
|
||||
return res.status(403).json({ error: "Service does not support API calls" });
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
const url = new URL(formatApiCall(widget.type, { endpoint, ...widget }));
|
||||
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
|
||||
|
||||
let headers;
|
||||
if (widget.username && widget.password) {
|
||||
|
@ -27,8 +32,8 @@ export default async function genericProxyHandler(req, res, maps) {
|
|||
});
|
||||
|
||||
let resultData = data;
|
||||
if ((status === 200) && (maps?.[endpoint])) {
|
||||
resultData = maps[endpoint](data);
|
||||
if (status === 200 && map) {
|
||||
resultData = map(data);
|
||||
}
|
||||
|
||||
if (contentType) res.setHeader("Content-Type", contentType);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import getServiceWidget from "utils/service-helpers";
|
||||
import { formatApiCall } from "utils/api-helpers";
|
||||
import widgets from "widgets/widgets";
|
||||
|
||||
export default async function npmProxyHandler(req, res) {
|
||||
const { group, service, endpoint } = req.query;
|
||||
|
@ -7,8 +8,12 @@ export default async function npmProxyHandler(req, res) {
|
|||
if (group && service) {
|
||||
const widget = await getServiceWidget(group, service);
|
||||
|
||||
if (!widgets?.[widget.type]?.api) {
|
||||
return res.status(403).json({ error: "Service does not support API calls" });
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
const url = new URL(formatApiCall(widget.type, { endpoint, ...widget }));
|
||||
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
|
||||
|
||||
const loginUrl = `${widget.url}/api/tokens`;
|
||||
const body = { identity: widget.username, secret: widget.password };
|
||||
|
|
|
@ -12,15 +12,15 @@ async function login(widget, params) {
|
|||
return fetch(loginUrl, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
body: loginBody
|
||||
body: loginBody,
|
||||
})
|
||||
.then(async response => {
|
||||
addCookieToJar(loginUrl, response.headers);
|
||||
setCookieHeader(loginUrl, params);
|
||||
const data = await response.text();
|
||||
return ([response.status, data]);
|
||||
})
|
||||
.catch(err => ([500, err]));
|
||||
.then(async (response) => {
|
||||
addCookieToJar(loginUrl, response.headers);
|
||||
setCookieHeader(loginUrl, params);
|
||||
const data = await response.text();
|
||||
return [response.status, data];
|
||||
})
|
||||
.catch((err) => [500, err]);
|
||||
}
|
||||
|
||||
export default async function qbittorrentProxyHandler(req, res) {
|
||||
|
@ -46,7 +46,7 @@ export default async function qbittorrentProxyHandler(req, res) {
|
|||
if (status !== 200) {
|
||||
return res.status(status).end(data);
|
||||
}
|
||||
if (data.toString() !== 'Ok.') {
|
||||
if (data.toString() !== "Ok.") {
|
||||
return res.status(401).end(data);
|
||||
}
|
||||
}
|
||||
|
@ -55,4 +55,4 @@ export default async function qbittorrentProxyHandler(req, res) {
|
|||
|
||||
if (contentType) res.setHeader("Content-Type", contentType);
|
||||
return res.status(status).send(data);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue