Skip to content

Commit

Permalink
feat: add komga integration
Browse files Browse the repository at this point in the history
  • Loading branch information
oae committed Nov 3, 2022
1 parent 5cb4457 commit 04c521d
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Box, Container, createStyles, Group, Header, Title, UnstyledButton } fr
import Image from 'next/image';
import Link from 'next/link';
import { SearchControl } from './headerSearch';
import { SettingsMenuButton } from './settingsMenu';

const useStyles = createStyles((theme) => ({
header: {
Expand Down Expand Up @@ -44,8 +45,9 @@ export function KaizokuHeader() {
</UnstyledButton>
</Link>

<Group spacing={5}>
<Group position="center" spacing={5}>
<SearchControl />
<SettingsMenuButton />
</Group>
</Box>
</Container>
Expand Down
2 changes: 2 additions & 0 deletions src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import next from 'next';
import { logger } from '../utils/logging';
import { checkChaptersQueue, scheduleAll } from './queue/checkChapters';
import { downloadQueue } from './queue/download';
import { integrationQueue } from './queue/integration';
import { notificationQueue } from './queue/notify';
import { updateMetadataQueue } from './queue/updateMetadata';

Expand All @@ -23,6 +24,7 @@ createBullBoard({
new BullAdapter(checkChaptersQueue),
new BullAdapter(notificationQueue),
new BullAdapter(updateMetadataQueue),
new BullAdapter(integrationQueue),
],
serverAdapter,
});
Expand Down
2 changes: 2 additions & 0 deletions src/server/queue/download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { sanitizer } from '../../utils';
import { logger } from '../../utils/logging';
import { prisma } from '../db/client';
import { downloadChapter, getChapterFromLocal, getMangaPath, removeManga } from '../utils/mangal';
import { integrationQueue } from './integration';
import { notificationQueue } from './notify';

const mangaWithLibraryAndMetadata = Prisma.validator<Prisma.MangaArgs>()({
Expand Down Expand Up @@ -61,6 +62,7 @@ export const downloadWorker = new Worker(
source: manga.source,
url: manga.metadata.urls.find((url) => url.includes('anilist')),
});
await integrationQueue.add('run_integrations', null);
await job.updateProgress(100);
} catch (err) {
await job.log(`${err}`);
Expand Down
41 changes: 41 additions & 0 deletions src/server/queue/integration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Job, Queue, Worker } from 'bullmq';
import { runIntegrations } from '../utils/integration';

export const integrationWorker = new Worker(
'integrationQueue',
async (job: Job) => {
try {
await runIntegrations();
await job.updateProgress(100);
} catch (err) {
await job.log(`${err}`);
throw err;
}
},
{
connection: {
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT || '6379', 10),
},
concurrency: 30,
limiter: {
max: 30,
duration: 1000 * 2,
},
},
);

export const integrationQueue = new Queue('integrationQueue', {
connection: {
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT || '6379', 10),
},
defaultJobOptions: {
removeOnComplete: true,
attempts: 20,
backoff: {
type: 'fixed',
delay: 1000 * 60 * 2,
},
},
});
2 changes: 2 additions & 0 deletions src/server/queue/updateMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Job, Queue, Worker } from 'bullmq';
import { refreshMetadata } from '../utils/integration';

import { getMangaPath, updateExistingMangaMetadata } from '../utils/mangal';

Expand All @@ -13,6 +14,7 @@ export const updateMetadataWorker = new Worker(
const { libraryPath, mangaTitle }: IUpdateMetadataWorkerData = job.data;
try {
await updateExistingMangaMetadata(libraryPath, mangaTitle);
await refreshMetadata(mangaTitle);
await job.updateProgress(100);
} catch (err) {
await job.log(`${err}`);
Expand Down
2 changes: 2 additions & 0 deletions src/server/trpc/router/manga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { isCronValid, sanitizer } from '../../../utils';
import { checkChaptersQueue, removeJob, schedule } from '../../queue/checkChapters';
import { downloadQueue, downloadWorker, removeDownloadJobs } from '../../queue/download';
import { scheduleUpdateMetadata } from '../../queue/updateMetadata';
import { scanLibrary } from '../../utils/integration';
import { bindTitleToAnilistId, getAvailableSources, getMangaDetail, removeManga, search } from '../../utils/mangal';
import { t } from '../trpc';

Expand Down Expand Up @@ -106,6 +107,7 @@ export const mangaRouter = t.router({
if (shouldRemoveFiles === true) {
const mangaPath = path.resolve(removed.library.path, sanitizer(removed.title));
await removeManga(mangaPath);
await scanLibrary();
}
downloadWorker.resume();
}),
Expand Down
81 changes: 81 additions & 0 deletions src/server/utils/integration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { sanitizer } from '../../utils';
import { prisma } from '../db/client';

interface Library {
id: string;
}

interface Series {
content: SeriesContent[];
}

interface SeriesContent {
id: string;
name: string;
}

export const scanLibrary = async () => {
const settings = await prisma.settings.findFirstOrThrow();

if (settings.komgaEnabled && settings.komgaHost && settings.komgaUser && settings.komgaPassword) {
const baseKomgaUrl = settings.komgaHost.toLowerCase().startsWith('http')
? settings.komgaHost
: `http://${settings.komgaHost}`;
const headers = {
Authorization: `Basic ${Buffer.from(`${settings.komgaUser}:${settings.komgaPassword}`).toString('base64')}`,
};
const komgaLibrariesUrl = new URL('/api/v1/libraries', baseKomgaUrl).href;

const libraries: Library[] = await (
await fetch(komgaLibrariesUrl, {
headers,
})
).json();

await Promise.all(
libraries.map(async (library) => {
const komgaLibraryUrl = new URL(`/api/v1/libraries/${library.id}/scan`, baseKomgaUrl).href;
await fetch(komgaLibraryUrl, {
method: 'POST',
headers,
});
}),
);
}
};

export const refreshMetadata = async (mangaName: string) => {
const settings = await prisma.settings.findFirstOrThrow();

if (settings.komgaEnabled && settings.komgaHost && settings.komgaUser && settings.komgaPassword) {
const baseKomgaUrl = settings.komgaHost.toLowerCase().startsWith('http')
? settings.komgaHost
: `http://${settings.komgaHost}`;
const headers = {
Authorization: `Basic ${Buffer.from(`${settings.komgaUser}:${settings.komgaPassword}`).toString('base64')}`,
};
const komgaSeriesUrl = new URL('/api/v1/series?size=1000', baseKomgaUrl).href;

const series: Series = await (
await fetch(komgaSeriesUrl, {
headers,
})
).json();

const content = series.content.find((c) => c.name === sanitizer(mangaName));

if (!content) {
return;
}

const komgaSeriesRefreshUrl = new URL(`/api/v1/series/${content.id}/metadata/refresh`, baseKomgaUrl).href;
await fetch(komgaSeriesRefreshUrl, {
method: 'POST',
headers,
});
}
};

export const runIntegrations = async () => {
await scanLibrary();
};

0 comments on commit 04c521d

Please sign in to comment.