diff --git a/src/khoj/database/adapters/__init__.py b/src/khoj/database/adapters/__init__.py index ae979a8a..33e879aa 100644 --- a/src/khoj/database/adapters/__init__.py +++ b/src/khoj/database/adapters/__init__.py @@ -1683,6 +1683,15 @@ class EntryAdapters: .values_list("file_path", flat=True) ) + @staticmethod + @require_valid_user + def get_all_filenames_by_type(user: KhojUser, file_type: str): + return ( + Entry.objects.filter(user=user, file_type=file_type) + .distinct("file_path") + .values_list("file_path", flat=True) + ) + @staticmethod @require_valid_user def get_size_of_indexed_data_in_mb(user: KhojUser): diff --git a/src/khoj/routers/api_content.py b/src/khoj/routers/api_content.py index 8762681f..90e4b498 100644 --- a/src/khoj/routers/api_content.py +++ b/src/khoj/routers/api_content.py @@ -401,6 +401,36 @@ async def get_file_object( ) +@api_content.delete("/type/{content_type}", status_code=200) +@requires(["authenticated"]) +async def delete_content_type( + request: Request, + content_type: str, + client: Optional[str] = None, +): + user = request.user.object + if content_type not in {s.value for s in SearchType}: + raise ValueError(f"Unsupported content type: {content_type}") + if content_type == "all": + await EntryAdapters.adelete_all_entries(user) + else: + # Delete file objects of the given type + file_list = await sync_to_async(list)(EntryAdapters.get_all_filenames_by_type(user, content_type)) # type: ignore[call-arg] + await FileObjectAdapters.adelete_file_objects_by_names(user, file_list) + # Delete entries of the given type + await EntryAdapters.adelete_all_entries(user, file_type=content_type) + + update_telemetry_state( + request=request, + telemetry_type="api", + api="delete_content_config", + client=client, + metadata={"content_type": content_type}, + ) + + return {"status": "ok"} + + @api_content.get("/{content_source}", response_model=List[str]) @requires(["authenticated"]) async def get_content_source(