diff --git a/media_manager/torrent/router.py b/media_manager/torrent/router.py
index ce90c83..2df2edd 100644
--- a/media_manager/torrent/router.py
+++ b/media_manager/torrent/router.py
@@ -2,18 +2,13 @@ from fastapi import APIRouter
from fastapi import status
from fastapi.params import Depends
-from media_manager.auth.users import current_active_user
+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
router = APIRouter()
-@router.get("/{torrent_id}", status_code=status.HTTP_200_OK, response_model=Torrent)
-def get_torrent(service: torrent_service_dep, torrent: torrent_dep):
- return service.get_torrent_by_id(torrent_id=torrent.id)
-
-
@router.get(
"",
status_code=status.HTTP_200_OK,
@@ -22,3 +17,39 @@ def get_torrent(service: torrent_service_dep, torrent: torrent_dep):
)
def get_all_torrents(service: torrent_service_dep):
return service.get_all_torrents()
+
+
+@router.get("/{torrent_id}", status_code=status.HTTP_200_OK, response_model=Torrent)
+def get_torrent(service: torrent_service_dep, torrent: torrent_dep):
+ return service.get_torrent_by_id(torrent_id=torrent.id)
+
+
+@router.delete(
+ "/{torrent_id}",
+ status_code=status.HTTP_204_NO_CONTENT,
+ dependencies=[Depends(current_superuser)],
+)
+def delete_torrent(
+ service: torrent_service_dep,
+ torrent: torrent_dep,
+ delete_files: bool = False,
+):
+ try:
+ service.cancel_download(torrent=torrent, delete_files=delete_files)
+ except RuntimeError:
+ pass
+
+ service.delete_torrent(torrent_id=torrent.id)
+
+
+@router.post(
+ "/{torrent_id}/retry",
+ status_code=status.HTTP_204_NO_CONTENT,
+ dependencies=[Depends(current_superuser)],
+)
+def retry_torrent_download(
+ service: torrent_service_dep,
+ torrent: torrent_dep,
+):
+ service.pause_download(torrent=torrent)
+ service.resume_download(torrent=torrent)
diff --git a/media_manager/torrent/service.py b/media_manager/torrent/service.py
index 751eb11..1322bca 100644
--- a/media_manager/torrent/service.py
+++ b/media_manager/torrent/service.py
@@ -105,13 +105,9 @@ class TorrentService:
self.torrent_repository.get_torrent_by_id(torrent_id=torrent_id)
)
- # TODO: extract deletion logic to tv module
- # def delete_torrent(self, torrent_id: TorrentId):
- # t = self.torrent_repository.get_torrent_by_id(torrent_id=torrent_id)
- # if not t.imported:
- # from media_manager.tv.repository import remove_season_files_by_torrent_id
- # remove_season_files_by_torrent_id(db=self.db, torrent_id=torrent_id)
- # media_manager.torrent.repository.delete_torrent(db=self.db, torrent_id=t.id)
+ def delete_torrent(self, torrent_id: TorrentId):
+ t = self.torrent_repository.get_torrent_by_id(torrent_id=torrent_id)
+ self.torrent_repository.delete_torrent(torrent_id=t.id)
def get_movie_files_of_torrent(self, torrent: Torrent):
return self.torrent_repository.get_movie_files_of_torrent(torrent_id=torrent.id)
diff --git a/web/src/lib/api/api.d.ts b/web/src/lib/api/api.d.ts
index 42a3394..9e32386 100644
--- a/web/src/lib/api/api.d.ts
+++ b/web/src/lib/api/api.d.ts
@@ -248,6 +248,43 @@ export interface paths {
patch?: never;
trace?: never;
};
+ '/api/v1/auth/oauth/authorize': {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Oauth:Oauth2.Cookie.Authorize */
+ get: operations['oauth_oauth2_cookie_authorize_api_v1_auth_oauth_authorize_get'];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ '/api/v1/auth/oauth/callback': {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Oauth:Oauth2.Cookie.Callback
+ * @description The response varies based on the authentication backend used.
+ */
+ get: operations['oauth_oauth2_cookie_callback_api_v1_auth_oauth_callback_get'];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
'/api/v1/tv/shows': {
parameters: {
query?: never;
@@ -544,23 +581,6 @@ export interface paths {
patch?: never;
trace?: never;
};
- '/api/v1/torrent/{torrent_id}': {
- parameters: {
- query?: never;
- header?: never;
- path?: never;
- cookie?: never;
- };
- /** Get Torrent */
- get: operations['get_torrent_api_v1_torrent__torrent_id__get'];
- put?: never;
- post?: never;
- delete?: never;
- options?: never;
- head?: never;
- patch?: never;
- trace?: never;
- };
'/api/v1/torrent': {
parameters: {
query?: never;
@@ -578,6 +598,41 @@ export interface paths {
patch?: never;
trace?: never;
};
+ '/api/v1/torrent/{torrent_id}': {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Get Torrent */
+ get: operations['get_torrent_api_v1_torrent__torrent_id__get'];
+ put?: never;
+ post?: never;
+ /** Delete Torrent */
+ delete: operations['delete_torrent_api_v1_torrent__torrent_id__delete'];
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ '/api/v1/torrent/{torrent_id}/retry': {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Retry Torrent Download */
+ post: operations['retry_torrent_download_api_v1_torrent__torrent_id__retry_post'];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
'/api/v1/movies': {
parameters: {
query?: never;
@@ -1221,6 +1276,11 @@ export interface components {
*/
timestamp?: string;
};
+ /** OAuth2AuthorizeResponse */
+ OAuth2AuthorizeResponse: {
+ /** Authorization Url */
+ authorization_url: string;
+ };
/** PublicMovie */
PublicMovie: {
/**
@@ -2275,6 +2335,80 @@ export interface operations {
};
};
};
+ oauth_oauth2_cookie_authorize_api_v1_auth_oauth_authorize_get: {
+ parameters: {
+ query?: {
+ scopes?: string[];
+ };
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ 'application/json': components['schemas']['OAuth2AuthorizeResponse'];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ 'application/json': components['schemas']['HTTPValidationError'];
+ };
+ };
+ };
+ };
+ oauth_oauth2_cookie_callback_api_v1_auth_oauth_callback_get: {
+ parameters: {
+ query?: {
+ code?: string | null;
+ code_verifier?: string | null;
+ state?: string | null;
+ error?: string | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ 'application/json': unknown;
+ };
+ };
+ /** @description Bad Request */
+ 400: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ 'application/json': components['schemas']['ErrorModel'];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ 'application/json': components['schemas']['HTTPValidationError'];
+ };
+ };
+ };
+ };
get_all_shows_api_v1_tv_shows_get: {
parameters: {
query?: never;
@@ -2905,6 +3039,26 @@ export interface operations {
};
};
};
+ get_all_torrents_api_v1_torrent_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ 'application/json': components['schemas']['Torrent'][];
+ };
+ };
+ };
+ };
get_torrent_api_v1_torrent__torrent_id__get: {
parameters: {
query?: never;
@@ -2936,22 +3090,62 @@ export interface operations {
};
};
};
- get_all_torrents_api_v1_torrent_get: {
+ delete_torrent_api_v1_torrent__torrent_id__delete: {
parameters: {
- query?: never;
+ query?: {
+ delete_files?: boolean;
+ };
header?: never;
- path?: never;
+ path: {
+ torrent_id: string;
+ };
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Successful Response */
- 200: {
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
headers: {
[name: string]: unknown;
};
content: {
- 'application/json': components['schemas']['Torrent'][];
+ 'application/json': components['schemas']['HTTPValidationError'];
+ };
+ };
+ };
+ };
+ retry_torrent_download_api_v1_torrent__torrent_id__retry_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ torrent_id: string;
+ };
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ 'application/json': components['schemas']['HTTPValidationError'];
};
};
};
diff --git a/web/src/lib/components/delete-torrent-dialog.svelte b/web/src/lib/components/delete-torrent-dialog.svelte
new file mode 100644
index 0000000..fec3895
--- /dev/null
+++ b/web/src/lib/components/delete-torrent-dialog.svelte
@@ -0,0 +1,61 @@
+
+
+