mirror of
https://github.com/maxdorninger/MediaManager.git
synced 2026-04-17 15:43:28 +02:00
Merge pull request #171 from maxdorninger/rework-torrent-handling
Add ability to manually mark torrent as imported and speed up eslint
This commit is contained in:
@@ -17,7 +17,7 @@ class IndexerQueryResult(BaseModel):
|
||||
title: str
|
||||
download_url: str = pydantic.Field(
|
||||
exclude=True,
|
||||
description="This can be a magnet link or URL to the .torrent file"
|
||||
description="This can be a magnet link or URL to the .torrent file",
|
||||
)
|
||||
seeders: int
|
||||
flags: list[str]
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
from fastapi.exceptions import HTTPException
|
||||
|
||||
from fastapi import APIRouter
|
||||
from fastapi import status
|
||||
from fastapi.params import Depends
|
||||
|
||||
from media_manager.auth.users import current_active_user, current_superuser
|
||||
from media_manager.torrent.dependencies import torrent_service_dep, torrent_dep
|
||||
from media_manager.torrent.schemas import Torrent
|
||||
from media_manager.torrent.dependencies import (
|
||||
torrent_service_dep,
|
||||
torrent_dep,
|
||||
torrent_repository_dep,
|
||||
)
|
||||
from media_manager.torrent.schemas import Torrent, TorrentStatus
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -53,3 +59,29 @@ def retry_torrent_download(
|
||||
):
|
||||
service.pause_download(torrent=torrent)
|
||||
service.resume_download(torrent=torrent)
|
||||
|
||||
|
||||
@router.patch(
|
||||
"/{torrent_id}/status",
|
||||
status_code=status.HTTP_200_OK,
|
||||
dependencies=[Depends(current_superuser)],
|
||||
response_model=Torrent,
|
||||
)
|
||||
def update_torrent_status(
|
||||
rep: torrent_repository_dep,
|
||||
torrent: torrent_dep,
|
||||
state: TorrentStatus | None = None,
|
||||
imported: bool | None = None,
|
||||
):
|
||||
if imported is not None:
|
||||
torrent.imported = imported
|
||||
if state is not None:
|
||||
torrent.status = state
|
||||
if state is None and imported is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="No status or imported value provided",
|
||||
)
|
||||
|
||||
rep.save_torrent(torrent=torrent)
|
||||
return torrent
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"prepare": "svelte-kit sync || echo ''",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "eslint --fix . && prettier --check .",
|
||||
"lint": "eslint --concurrency auto --fix . && prettier --check .",
|
||||
"format": "prettier --write .",
|
||||
"openapi": "npx openapi-typescript http://localhost:8000/openapi.json -o src/lib/api/api.d.ts"
|
||||
},
|
||||
|
||||
51
web/src/lib/api/api.d.ts
vendored
51
web/src/lib/api/api.d.ts
vendored
@@ -633,6 +633,23 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
'/api/v1/torrent/{torrent_id}/status': {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
/** Update Torrent Status */
|
||||
patch: operations['update_torrent_status_api_v1_torrent__torrent_id__status_patch'];
|
||||
trace?: never;
|
||||
};
|
||||
'/api/v1/movies': {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -3150,6 +3167,40 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
update_torrent_status_api_v1_torrent__torrent_id__status_patch: {
|
||||
parameters: {
|
||||
query?: {
|
||||
state?: components['schemas']['TorrentStatus'] | null;
|
||||
imported?: boolean | null;
|
||||
};
|
||||
header?: never;
|
||||
path: {
|
||||
torrent_id: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
'application/json': components['schemas']['Torrent'];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
'application/json': components['schemas']['HTTPValidationError'];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
get_all_movies_api_v1_movies_get: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
66
web/src/lib/components/edit-torrent-dialog.svelte
Normal file
66
web/src/lib/components/edit-torrent-dialog.svelte
Normal file
@@ -0,0 +1,66 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button/index.js';
|
||||
import * as Dialog from '$lib/components/ui/dialog/index.js';
|
||||
import type { components } from '$lib/api/api';
|
||||
import { Switch } from '$lib/components/ui/switch';
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
import client from '$lib/api';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { invalidateAll } from '$app/navigation';
|
||||
|
||||
let {
|
||||
torrent
|
||||
}: {
|
||||
torrent: components['schemas']['MovieTorrent'] | components['schemas']['RichSeasonTorrent'];
|
||||
} = $props();
|
||||
let dialogOpen = $state(false);
|
||||
let importedState = $state(torrent.imported || false);
|
||||
|
||||
async function closeDialog() {
|
||||
dialogOpen = false;
|
||||
importedState = torrent.imported || false;
|
||||
}
|
||||
async function saveTorrent() {
|
||||
const { error } = await client.PATCH('/api/v1/torrent/{torrent_id}/status', {
|
||||
params: {
|
||||
path: {
|
||||
torrent_id: torrent.torrent_id!
|
||||
},
|
||||
query: {
|
||||
imported: importedState
|
||||
}
|
||||
}
|
||||
});
|
||||
if (error) {
|
||||
console.error(`Failed to update torrent ${torrent.torrent_id} imported state: ${error}`);
|
||||
toast.error(`Failed to update torrent: ${error}`);
|
||||
return;
|
||||
}
|
||||
await invalidateAll();
|
||||
await closeDialog();
|
||||
}
|
||||
</script>
|
||||
|
||||
<Dialog.Root bind:open={dialogOpen}>
|
||||
<Dialog.Trigger>
|
||||
<Button class="w-full" onclick={() => (dialogOpen = true)}>Edit Torrent</Button>
|
||||
</Dialog.Trigger>
|
||||
<Dialog.Content class="w-full max-w-[600px] rounded-lg p-6 shadow-lg">
|
||||
<Dialog.Header>
|
||||
<Dialog.Title class="mb-1 text-xl font-semibold">Edit Torrent</Dialog.Title>
|
||||
<Dialog.Description class="mb-4 text-sm">
|
||||
Edit torrent "{torrent.torrent_title}".
|
||||
</Dialog.Description>
|
||||
</Dialog.Header>
|
||||
<div class="flex gap-2">
|
||||
<Switch bind:checked={importedState} id="imported-state" />
|
||||
<Label for="imported-state"
|
||||
>Change Torrent import state to: {importedState ? 'is' : 'is not'} imported.</Label
|
||||
>
|
||||
</div>
|
||||
<Dialog.Footer class="mt-8 flex justify-between gap-2">
|
||||
<Button onclick={() => closeDialog()} variant="secondary">Cancel</Button>
|
||||
<Button onclick={() => saveTorrent()}>Save Torrent</Button>
|
||||
</Dialog.Footer>
|
||||
</Dialog.Content>
|
||||
</Dialog.Root>
|
||||
@@ -12,7 +12,7 @@
|
||||
import client from '$lib/api';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import DeleteTorrentDialog from '$lib/components/delete-torrent-dialog.svelte';
|
||||
|
||||
import EditTorrentDialog from '$lib/components/edit-torrent-dialog.svelte';
|
||||
let {
|
||||
torrents,
|
||||
isShow = true
|
||||
@@ -96,6 +96,7 @@
|
||||
{/if}
|
||||
<DeleteTorrentDialog torrentName={torrent.torrent_title} torrentId={torrent.torrent_id!}
|
||||
></DeleteTorrentDialog>
|
||||
<EditTorrentDialog {torrent} />
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
</Table.Row>
|
||||
|
||||
Reference in New Issue
Block a user