mirror of
https://github.com/DI0IK/homepage-plus.git
synced 2025-07-16 09:49:49 +00:00
Add the Jackett widget
- add the follow-redirect package - add the tough-cookie package Jackett API uses a redirect mechanism to set a CSRF token. This CSRF token is stored in a cookie that is required to be present or the API won't work.
This commit is contained in:
parent
945ed854a4
commit
f750876425
8 changed files with 135 additions and 5 deletions
|
@ -22,6 +22,7 @@ import Tautulli from "./widgets/service/tautulli";
|
|||
import CoinMarketCap from "./widgets/service/coinmarketcap";
|
||||
import Gotify from "./widgets/service/gotify";
|
||||
import Prowlarr from "./widgets/service/prowlarr";
|
||||
import Jackett from "./widgets/service/jackett";
|
||||
|
||||
const widgetMappings = {
|
||||
docker: Docker,
|
||||
|
@ -45,7 +46,8 @@ const widgetMappings = {
|
|||
npm: Npm,
|
||||
tautulli: Tautulli,
|
||||
gotify: Gotify,
|
||||
prowlarr: Prowlarr
|
||||
prowlarr: Prowlarr,
|
||||
jackett: Jackett
|
||||
};
|
||||
|
||||
export default function Widget({ service }) {
|
||||
|
|
37
src/components/services/widgets/service/jackett.jsx
Normal file
37
src/components/services/widgets/service/jackett.jsx
Normal file
|
@ -0,0 +1,37 @@
|
|||
import useSWR from "swr";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import Widget from "../widget";
|
||||
import Block from "../block";
|
||||
|
||||
import { formatApiUrl } from "utils/api-helpers";
|
||||
|
||||
export default function Jackett({ service }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const config = service.widget;
|
||||
|
||||
const { data: indexersData, error: indexersError } = useSWR(formatApiUrl(config, "indexers"));
|
||||
|
||||
if (indexersError) {
|
||||
return <Widget error={t("widget.api_error")} />;
|
||||
}
|
||||
|
||||
if (!indexersData) {
|
||||
return (
|
||||
<Widget>
|
||||
<Block label={t("jackett.configured")} />
|
||||
<Block label={t("jackett.errored")} />
|
||||
</Widget>
|
||||
);
|
||||
}
|
||||
|
||||
const errored = indexersData.filter((indexer) => indexer.last_error);
|
||||
|
||||
return (
|
||||
<Widget>
|
||||
<Block label={t("jackett.configured")} value={indexersData.length} />
|
||||
<Block label={t("jackett.errored")} value={errored.length} />
|
||||
</Widget>
|
||||
);
|
||||
}
|
|
@ -17,6 +17,7 @@ const serviceProxyHandlers = {
|
|||
tautulli: genericProxyHandler,
|
||||
traefik: genericProxyHandler,
|
||||
sabnzbd: genericProxyHandler,
|
||||
jackett: genericProxyHandler,
|
||||
// uses X-API-Key (or similar) header auth
|
||||
gotify: credentialedProxyHandler,
|
||||
portainer: credentialedProxyHandler,
|
||||
|
|
|
@ -19,6 +19,7 @@ const formats = {
|
|||
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`
|
||||
};
|
||||
|
||||
export function formatApiCall(api, args) {
|
||||
|
|
|
@ -1,9 +1,44 @@
|
|||
/* eslint-disable prefer-promise-reject-errors */
|
||||
import https from "https";
|
||||
import http from "http";
|
||||
/* eslint-disable no-param-reassign */
|
||||
import { http, https } from "follow-redirects";
|
||||
import { Cookie, CookieJar } from 'tough-cookie';
|
||||
|
||||
const cookieJar = new CookieJar();
|
||||
|
||||
function addCookieHandler(url, params) {
|
||||
// add cookie header, if we have one in the jar
|
||||
const existingCookie = cookieJar.getCookieStringSync(url.toString());
|
||||
if (existingCookie) {
|
||||
params.headers = params.headers ?? {};
|
||||
params.headers.Cookie = existingCookie;
|
||||
}
|
||||
|
||||
// handle cookies during redirects
|
||||
params.beforeRedirect = (options, responseInfo) => {
|
||||
const cookieHeader = responseInfo.headers['set-cookie'];
|
||||
if (!cookieHeader || cookieHeader.length === 0) return;
|
||||
|
||||
let cookies = null;
|
||||
if (cookieHeader instanceof Array) {
|
||||
cookies = cookieHeader.map(Cookie.parse);
|
||||
}
|
||||
else {
|
||||
cookies = [Cookie.parse(cookieHeader)];
|
||||
}
|
||||
|
||||
for (let i = 0; i < cookies.length; i += 1) {
|
||||
cookieJar.setCookieSync(cookies[i], options.href);
|
||||
}
|
||||
|
||||
const cookie = cookieJar.getCookieStringSync(options.href);
|
||||
options.headers = options.headers ?? {};
|
||||
options.headers.Cookie = cookie;
|
||||
};
|
||||
}
|
||||
|
||||
export function httpsRequest(url, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
addCookieHandler(url, params);
|
||||
const request = https.request(url, params, (response) => {
|
||||
const data = [];
|
||||
|
||||
|
@ -30,6 +65,7 @@ export function httpsRequest(url, params) {
|
|||
|
||||
export function httpRequest(url, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
addCookieHandler(url, params);
|
||||
const request = http.request(url, params, (response) => {
|
||||
const data = [];
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue