Usenet and Torrent downloads in 1 widget. sabNZBd, NzbGet, Deluge, qBitTorrent, and transmission support. Columns can be reordered in Edit mode. Sorting enabled. Time uses Dayjs with auto translation. Can pause/resume single items, clients, or all. Can delete items (With option to delete assossiated files). Clients list and details. Include all filtering and processing for ratio from oldmarr torrent widget. Invalidation of old data (older than 30 seconds) to show an integration is not responding anymore. Misc (So many miscs): Fixed validation error with multiText. Fixed translation application for multiSelect to behave the same as select. Added background to gitignore (I needed to add a background to visually test opacity, probably will in the future too) Added setOptions to frontend components so potential updates made from the Dashboard can be saved. Extracted background and border color to use in widgets. humanFileSize function based on the si format (powers of 1024, not 1000). Improved integrationCreatorByKind by @Meierschlumpf. Changed integrationCreatorByKind to integrationCreator so it functions directly from the integration. Added integrationCreatorFromSecrets to directly work with secrets from db. Added getIntegrationKindsByCategory to get a list of integrations sharing categories. Added IntegrationKindByCategory type to get the types possible for a category (Great to cast on integration.kind that isn't already properly limited/typed but for which we know the limitation) Added a common AtLeastOneOf type. Applied to TKind and IntegrationSecretKind[] where it was already being used and Added to the getIntegrationKindsByCategory's output to be more freely used. Added the Modify type, instead of omiting to then add again just to change a parameters type, use the modify instead. Applied code wide already. Hook to get list of integration depending on permission level of user. (By @Meierschlumpf)
172 lines
6.0 KiB
TypeScript
172 lines
6.0 KiB
TypeScript
import { objectKeys } from "@homarr/common";
|
|
import type { AtLeastOneOf } from "@homarr/common/types";
|
|
|
|
export const integrationSecretKindObject = {
|
|
apiKey: { isPublic: false },
|
|
username: { isPublic: true },
|
|
password: { isPublic: false },
|
|
} satisfies Record<string, { isPublic: boolean }>;
|
|
|
|
export const integrationSecretKinds = objectKeys(integrationSecretKindObject);
|
|
|
|
interface integrationDefinition {
|
|
name: string;
|
|
iconUrl: string;
|
|
secretKinds: AtLeastOneOf<IntegrationSecretKind[]>; // at least one secret kind set is required
|
|
category: AtLeastOneOf<IntegrationCategory>;
|
|
}
|
|
|
|
export const integrationDefs = {
|
|
sabNzbd: {
|
|
name: "SABnzbd",
|
|
secretKinds: [["apiKey"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/sabnzbd.png",
|
|
category: ["downloadClient", "usenet"],
|
|
},
|
|
nzbGet: {
|
|
name: "NZBGet",
|
|
secretKinds: [["username", "password"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/nzbget.png",
|
|
category: ["downloadClient", "usenet"],
|
|
},
|
|
deluge: {
|
|
name: "Deluge",
|
|
secretKinds: [["password"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/deluge.png",
|
|
category: ["downloadClient", "torrent"],
|
|
},
|
|
transmission: {
|
|
name: "Transmission",
|
|
secretKinds: [["username", "password"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/transmission.png",
|
|
category: ["downloadClient", "torrent"],
|
|
},
|
|
qBittorrent: {
|
|
name: "qBittorrent",
|
|
secretKinds: [["username", "password"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/qbittorrent.png",
|
|
category: ["downloadClient", "torrent"],
|
|
},
|
|
sonarr: {
|
|
name: "Sonarr",
|
|
secretKinds: [["apiKey"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/sonarr.png",
|
|
category: ["calendar"],
|
|
},
|
|
radarr: {
|
|
name: "Radarr",
|
|
secretKinds: [["apiKey"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/radarr.png",
|
|
category: ["calendar"],
|
|
},
|
|
lidarr: {
|
|
name: "Lidarr",
|
|
secretKinds: [["apiKey"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/lidarr.png",
|
|
category: ["calendar"],
|
|
},
|
|
readarr: {
|
|
name: "Readarr",
|
|
secretKinds: [["apiKey"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/readarr.png",
|
|
category: ["calendar"],
|
|
},
|
|
prowlarr: {
|
|
name: "Prowlarr",
|
|
secretKinds: [["apiKey"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/prowlarr.png",
|
|
category: ["indexerManager"],
|
|
},
|
|
jellyfin: {
|
|
name: "Jellyfin",
|
|
secretKinds: [["username", "password"], ["apiKey"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/jellyfin.png",
|
|
category: ["mediaService"],
|
|
},
|
|
plex: {
|
|
name: "Plex",
|
|
secretKinds: [["apiKey"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/plex.png",
|
|
category: ["mediaService"],
|
|
},
|
|
jellyseerr: {
|
|
name: "Jellyseerr",
|
|
secretKinds: [["apiKey"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/jellyseerr.png",
|
|
category: ["mediaSearch", "mediaRequest"],
|
|
},
|
|
overseerr: {
|
|
name: "Overseerr",
|
|
secretKinds: [["apiKey"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/overseerr.png",
|
|
category: ["mediaSearch", "mediaRequest"],
|
|
},
|
|
piHole: {
|
|
name: "Pi-hole",
|
|
secretKinds: [["apiKey"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/pi-hole.png",
|
|
category: ["dnsHole"],
|
|
},
|
|
adGuardHome: {
|
|
name: "AdGuard Home",
|
|
secretKinds: [["username", "password"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/adguard-home.png",
|
|
category: ["dnsHole"],
|
|
},
|
|
homeAssistant: {
|
|
name: "Home Assistant",
|
|
secretKinds: [["apiKey"]],
|
|
iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/home-assistant.png",
|
|
category: ["smartHomeServer"],
|
|
},
|
|
} as const satisfies Record<string, integrationDefinition>;
|
|
|
|
export const integrationKinds = objectKeys(integrationDefs) as AtLeastOneOf<IntegrationKind>;
|
|
|
|
export const getIconUrl = (integration: IntegrationKind) => integrationDefs[integration].iconUrl;
|
|
|
|
export const getIntegrationName = (integration: IntegrationKind) => integrationDefs[integration].name;
|
|
|
|
export const getDefaultSecretKinds = (integration: IntegrationKind): IntegrationSecretKind[] =>
|
|
integrationDefs[integration].secretKinds[0];
|
|
|
|
export const getAllSecretKindOptions = (integration: IntegrationKind): AtLeastOneOf<IntegrationSecretKind[]> =>
|
|
integrationDefs[integration].secretKinds;
|
|
|
|
/**
|
|
* Get all integration kinds that share a category, typed only by the kinds belonging to the category
|
|
* @param category Category to filter by, belonging to IntegrationCategory
|
|
* @returns Partial list of integration kinds
|
|
*/
|
|
export const getIntegrationKindsByCategory = <TCategory extends IntegrationCategory>(category: TCategory) => {
|
|
return objectKeys(integrationDefs).filter((integration) =>
|
|
integrationDefs[integration].category.some((defCategory) => defCategory === category),
|
|
) as AtLeastOneOf<IntegrationKindByCategory<TCategory>>;
|
|
};
|
|
|
|
/**
|
|
* Directly get the types of the list returned by getIntegrationKindsByCategory
|
|
*/
|
|
export type IntegrationKindByCategory<TCategory extends IntegrationCategory> = {
|
|
[Key in keyof typeof integrationDefs]: TCategory extends (typeof integrationDefs)[Key]["category"][number]
|
|
? Key
|
|
: never;
|
|
}[keyof typeof integrationDefs] extends infer U
|
|
? //Needed to simplify the type when using it
|
|
U
|
|
: never;
|
|
|
|
export type IntegrationSecretKind = keyof typeof integrationSecretKindObject;
|
|
export type IntegrationKind = keyof typeof integrationDefs;
|
|
export type IntegrationCategory =
|
|
| "dnsHole"
|
|
| "mediaService"
|
|
| "calendar"
|
|
| "mediaSearch"
|
|
| "mediaRequest"
|
|
| "downloadClient"
|
|
| "usenet"
|
|
| "torrent"
|
|
| "smartHomeServer"
|
|
| "indexerManager";
|