Implements Sonarr callbacks
This commit is contained in:
6
package-lock.json
generated
6
package-lock.json
generated
@@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
|
"humanize-duration-ts": "^2.1.1",
|
||||||
"ip-range-check": "^0.2.0",
|
"ip-range-check": "^0.2.0",
|
||||||
"js-yaml": "^4.1.0"
|
"js-yaml": "^4.1.0"
|
||||||
},
|
},
|
||||||
@@ -2521,6 +2522,11 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/humanize-duration-ts": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/humanize-duration-ts/-/humanize-duration-ts-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-TibNF2/fkypjAfHdGpWL/dmWUS0G6Qi+3mKyiB6LDCowbMy+PtzbgPTnFMNTOVAJXDau01jYrJ3tFoz5AJSqhA=="
|
||||||
|
},
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.2.4",
|
"version": "5.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
|
"humanize-duration-ts": "^2.1.1",
|
||||||
"ip-range-check": "^0.2.0",
|
"ip-range-check": "^0.2.0",
|
||||||
"js-yaml": "^4.1.0"
|
"js-yaml": "^4.1.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
const radius = 40;
|
const radius = 40;
|
||||||
$: circumference = 2.0 * radius * Math.PI;
|
$: circumference = 2.0 * radius * Math.PI;
|
||||||
$: offset = (1.0 - Math.min(Math.max(ratio, 0.0), 1.0)) * circumference;
|
$: offset = (1.0 - Math.min(Math.max(ratio, 0.0), 1.0)) * circumference;
|
||||||
$: console.log(offset);
|
|
||||||
$: console.log(circumference);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
8
src/lib/humanize.ts
Normal file
8
src/lib/humanize.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { HumanizeDurationLanguage, HumanizeDuration } from 'humanize-duration-ts';
|
||||||
|
|
||||||
|
const langService: HumanizeDurationLanguage = new HumanizeDurationLanguage();
|
||||||
|
const humanizer: HumanizeDuration = new HumanizeDuration(langService);
|
||||||
|
|
||||||
|
export function humanizeRelativeTime(date: Date): string {
|
||||||
|
return humanizer.humanize(date.getTime() - Date.now(), { largest: 1 });
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
import type { ServiceData } from '../service';
|
import type { ServiceData } from '../service';
|
||||||
|
|
||||||
export let data: ServiceData;
|
export let data: ServiceData;
|
||||||
console.log(data.data);
|
|
||||||
$: missingClasses = data.data == undefined ? 'animate-pulse' : '';
|
$: missingClasses = data.data == undefined ? 'animate-pulse' : '';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
28
src/lib/services/sonarr/+content.svelte
Normal file
28
src/lib/services/sonarr/+content.svelte
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { humanizeRelativeTime } from '$lib/humanize';
|
||||||
|
import type { ServiceData } from '../service';
|
||||||
|
|
||||||
|
export let data: ServiceData;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-row justify-start gap-4 whitespace-nowrap">
|
||||||
|
{#if data.health?.errors > 0}
|
||||||
|
<span>
|
||||||
|
<i class="fa fa-circle-exclamation text-error-400" />: {data.health?.errors}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
{#if data.health?.warnings > 0}
|
||||||
|
<span>
|
||||||
|
<i class="fa fa-triangle-exclamation text-warning-400" />: {data.health?.warnings}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
{#if data.queue?.total > 0}
|
||||||
|
<span>
|
||||||
|
<i class="fa fa-bars" />: {data.queue?.total}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if data.queue?.nextDate}
|
||||||
|
<span> in ~{humanizeRelativeTime(data.queue?.nextDate)}</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
@@ -1,5 +1,85 @@
|
|||||||
|
import type { ServiceConfig } from '$lib/config';
|
||||||
import type { ServiceHandler } from '../service';
|
import type { ServiceHandler } from '../service';
|
||||||
|
|
||||||
export const handle: ServiceHandler = () => {
|
interface Status {
|
||||||
return { logo: 'https://cdn.rawgit.com/Sonarr/Sonarr/develop/Logo/Sonarr.svg' };
|
warnings: number;
|
||||||
|
errors: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildStatus(statuses: any[]): Status {
|
||||||
|
let warnings = 0;
|
||||||
|
let errors = 0;
|
||||||
|
for (const status of statuses) {
|
||||||
|
switch (status.type) {
|
||||||
|
case 'warning':
|
||||||
|
warnings += 1;
|
||||||
|
break;
|
||||||
|
case 'error':
|
||||||
|
errors += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { warnings, errors };
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Queue {
|
||||||
|
nextDate?: Date;
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
function recordEstimatedCompletionTime(record: any): number {
|
||||||
|
if (record.estimatedCompletionTime == undefined) {
|
||||||
|
return Infinity;
|
||||||
|
}
|
||||||
|
return new Date(record.estimatedCompletionTime).getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildQueue(queue: any): Queue {
|
||||||
|
if (queue?.records?.length === 0) {
|
||||||
|
return { total: 0 };
|
||||||
|
}
|
||||||
|
let nextTime: number = recordEstimatedCompletionTime(queue.records[0]);
|
||||||
|
for (let i = 1; i < queue.records.length; i++) {
|
||||||
|
const recordTime = recordEstimatedCompletionTime(queue.records[i]);
|
||||||
|
if (recordTime < nextTime) {
|
||||||
|
nextTime = recordTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
total: queue.records.length,
|
||||||
|
nextDate: nextTime != Infinity ? new Date(nextTime) : undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const handle: ServiceHandler = async (config: ServiceConfig) => {
|
||||||
|
const res = {
|
||||||
|
logo: 'https://cdn.rawgit.com/Sonarr/Sonarr/develop/Logo/Sonarr.svg',
|
||||||
|
subtitle: 'TV Show tracker'
|
||||||
|
};
|
||||||
|
|
||||||
|
const params = '?apikey=' + config.api_key;
|
||||||
|
|
||||||
|
const requests = [
|
||||||
|
fetch(config.url + '/api/v3/health' + params),
|
||||||
|
fetch(config.url + '/api/v3/queue' + params + '&includeUnknownSeriesItems=true')
|
||||||
|
];
|
||||||
|
|
||||||
|
const [health, queue] = await Promise.allSettled(requests);
|
||||||
|
res.status = 'online';
|
||||||
|
|
||||||
|
if (health.status != 'fulfilled') {
|
||||||
|
console.warn("Could not fetch '" + config.url + "' status: " + health.value);
|
||||||
|
res.status = 'offline';
|
||||||
|
} else if (health.value.ok == true) {
|
||||||
|
res.health = buildStatus(await health.value.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queue.status != 'fulfilled') {
|
||||||
|
console.warn("Could not fetch '" + config.url + "' queue: " + queue.value);
|
||||||
|
res.status = 'offline';
|
||||||
|
} else if (queue.value.ok == true) {
|
||||||
|
res.queue = buildQueue(await queue.value.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user