karakeep-python-api 1.6.0__tar.gz → 1.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (18) hide show
  1. {karakeep_python_api-1.6.0/karakeep_python_api.egg-info → karakeep_python_api-1.7.0}/PKG-INFO +1 -1
  2. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/karakeep_python_api/datatypes.py +4 -0
  3. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/karakeep_python_api/karakeep_api.py +53 -5
  4. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/karakeep_python_api/openapi_reference.json +61 -0
  5. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0/karakeep_python_api.egg-info}/PKG-INFO +1 -1
  6. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/setup.py +1 -1
  7. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/LICENSE +0 -0
  8. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/MANIFEST.in +0 -0
  9. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/README.md +0 -0
  10. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/karakeep_python_api/__init__.py +0 -0
  11. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/karakeep_python_api/__main__.py +0 -0
  12. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/karakeep_python_api.egg-info/SOURCES.txt +0 -0
  13. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/karakeep_python_api.egg-info/dependency_links.txt +0 -0
  14. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/karakeep_python_api.egg-info/entry_points.txt +0 -0
  15. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/karakeep_python_api.egg-info/requires.txt +0 -0
  16. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/karakeep_python_api.egg-info/top_level.txt +0 -0
  17. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/setup.cfg +0 -0
  18. {karakeep_python_api-1.6.0 → karakeep_python_api-1.7.0}/tests/test_karakeep_api.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: karakeep_python_api
3
- Version: 1.6.0
3
+ Version: 1.7.0
4
4
  Summary: Community python client for the Karakeep API.
5
5
  Home-page: https://github.com/thiswillbeyourgithub/karakeep_python_api/
6
6
  Keywords: rss,karakeep,hoarder,data-hoarding,python,api,feeds,openapi
@@ -136,6 +136,10 @@ class PaginatedBookmarks(BaseModel):
136
136
  nextCursor: Optional[str] = ""
137
137
 
138
138
 
139
+ class CheckUrlResponse(BaseModel):
140
+ bookmarkId: Optional[str]
141
+
142
+
139
143
  class ListModel(BaseModel):
140
144
  id: str
141
145
  name: str
@@ -85,7 +85,7 @@ class KarakeepAPI:
85
85
  """
86
86
 
87
87
  # Version reflects the client library version, updated by bumpver
88
- VERSION: str = "1.6.0"
88
+ VERSION: str = "1.7.0"
89
89
 
90
90
  def __init__(
91
91
  self,
@@ -930,6 +930,38 @@ class KarakeepAPI:
930
930
  # Response should match PaginatedBookmarks schema
931
931
  return datatypes.PaginatedBookmarks.model_validate(response_data)
932
932
 
933
+ @optional_typecheck
934
+ def check_url(
935
+ self,
936
+ url: str,
937
+ ) -> Union[datatypes.CheckUrlResponse, Dict[str, Any], List[Any]]:
938
+ """
939
+ Check if a URL is already bookmarked. Corresponds to GET /bookmarks/check-url.
940
+ Uses substring matching to find candidates, then normalizes URLs (ignoring hash fragments and trailing slashes) for exact comparison.
941
+
942
+ Args:
943
+ url: The URL to check.
944
+
945
+ Returns:
946
+ datatypes.CheckUrlResponse: Object indicating whether the URL is bookmarked. bookmarkId is null if not found.
947
+ If response validation is disabled, returns the raw API response (dict/list).
948
+
949
+ Raises:
950
+ APIError: If the API request fails.
951
+ pydantic.ValidationError: If response validation fails (and is not disabled).
952
+ """
953
+ params = {
954
+ "url": url,
955
+ }
956
+ response_data = self._call("GET", "bookmarks/check-url", params=params)
957
+
958
+ if self.disable_response_validation:
959
+ logger.debug("Skipping response validation as requested.")
960
+ return response_data
961
+ else:
962
+ # Response should match CheckUrlResponse schema
963
+ return datatypes.CheckUrlResponse.model_validate(response_data)
964
+
933
965
  @optional_typecheck
934
966
  def get_a_single_bookmark(
935
967
  self,
@@ -1048,6 +1080,7 @@ class KarakeepAPI:
1048
1080
  bookmark_id: str,
1049
1081
  tag_ids: Optional[List[str]] = None,
1050
1082
  tag_names: Optional[List[str]] = None,
1083
+ attached_by: Optional[Literal["ai", "human"]] = "human",
1051
1084
  ) -> Dict[str, Any]:
1052
1085
  """
1053
1086
  Attach one or more tags to a bookmark. Corresponds to POST /bookmarks/{bookmarkId}/tags.
@@ -1056,6 +1089,7 @@ class KarakeepAPI:
1056
1089
  bookmark_id: The ID (string) of the bookmark.
1057
1090
  tag_ids: List of existing tag IDs to attach (optional).
1058
1091
  tag_names: List of tag names to attach (will create tags if they don't exist) (optional).
1092
+ attached_by: Who attached the tag, either "ai" or "human" (default: "human").
1059
1093
 
1060
1094
  Returns:
1061
1095
  dict: A dictionary containing the list of attached tag IDs under the key "attached".
@@ -1097,11 +1131,17 @@ class KarakeepAPI:
1097
1131
 
1098
1132
  if tag_ids:
1099
1133
  for tag_id in tag_ids:
1100
- tags_list.append({"tagId": tag_id.strip()})
1134
+ tag_entry: Dict[str, Any] = {"tagId": tag_id.strip()}
1135
+ if attached_by is not None:
1136
+ tag_entry["attachedBy"] = attached_by
1137
+ tags_list.append(tag_entry)
1101
1138
 
1102
1139
  if tag_names:
1103
1140
  for tag_name in tag_names:
1104
- tags_list.append({"tagName": tag_name.strip()})
1141
+ tag_entry = {"tagName": tag_name.strip()}
1142
+ if attached_by is not None:
1143
+ tag_entry["attachedBy"] = attached_by
1144
+ tags_list.append(tag_entry)
1105
1145
 
1106
1146
  tags_data = {"tags": tags_list}
1107
1147
 
@@ -1123,6 +1163,7 @@ class KarakeepAPI:
1123
1163
  bookmark_id: str,
1124
1164
  tag_ids: Optional[List[str]] = None,
1125
1165
  tag_names: Optional[List[str]] = None,
1166
+ attached_by: Optional[Literal["ai", "human"]] = "human",
1126
1167
  ) -> Dict[str, Any]:
1127
1168
  """
1128
1169
  Detach one or more tags from a bookmark. Corresponds to DELETE /bookmarks/{bookmarkId}/tags.
@@ -1131,6 +1172,7 @@ class KarakeepAPI:
1131
1172
  bookmark_id: The ID (string) of the bookmark.
1132
1173
  tag_ids: List of existing tag IDs to detach (optional).
1133
1174
  tag_names: List of tag names to detach (optional).
1175
+ attached_by: Who attached the tag, either "ai" or "human" (default: "human").
1134
1176
 
1135
1177
  Returns:
1136
1178
  dict: A dictionary containing the list of detached tag IDs under the key "detached".
@@ -1172,11 +1214,17 @@ class KarakeepAPI:
1172
1214
 
1173
1215
  if tag_ids:
1174
1216
  for tag_id in tag_ids:
1175
- tags_list.append({"tagId": tag_id.strip()})
1217
+ tag_entry: Dict[str, Any] = {"tagId": tag_id.strip()}
1218
+ if attached_by is not None:
1219
+ tag_entry["attachedBy"] = attached_by
1220
+ tags_list.append(tag_entry)
1176
1221
 
1177
1222
  if tag_names:
1178
1223
  for tag_name in tag_names:
1179
- tags_list.append({"tagName": tag_name.strip()})
1224
+ tag_entry = {"tagName": tag_name.strip()}
1225
+ if attached_by is not None:
1226
+ tag_entry["attachedBy"] = attached_by
1227
+ tags_list.append(tag_entry)
1180
1228
 
1181
1229
  tags_data = {"tags": tags_list}
1182
1230
 
@@ -983,6 +983,51 @@
983
983
  }
984
984
  }
985
985
  },
986
+ "/bookmarks/check-url": {
987
+ "get": {
988
+ "description": "Check if a URL is already bookmarked. Uses substring matching to find candidates, then normalizes URLs (ignoring hash fragments and trailing slashes) for exact comparison.",
989
+ "summary": "Check if a URL exists in bookmarks",
990
+ "tags": [
991
+ "Bookmarks"
992
+ ],
993
+ "security": [
994
+ {
995
+ "bearerAuth": []
996
+ }
997
+ ],
998
+ "parameters": [
999
+ {
1000
+ "schema": {
1001
+ "type": "string"
1002
+ },
1003
+ "required": true,
1004
+ "name": "url",
1005
+ "in": "query"
1006
+ }
1007
+ ],
1008
+ "responses": {
1009
+ "200": {
1010
+ "description": "Object indicating whether the URL is bookmarked. bookmarkId is null if not found.",
1011
+ "content": {
1012
+ "application/json": {
1013
+ "schema": {
1014
+ "type": "object",
1015
+ "properties": {
1016
+ "bookmarkId": {
1017
+ "type": "string",
1018
+ "nullable": true
1019
+ }
1020
+ },
1021
+ "required": [
1022
+ "bookmarkId"
1023
+ ]
1024
+ }
1025
+ }
1026
+ }
1027
+ }
1028
+ }
1029
+ }
1030
+ },
986
1031
  "/bookmarks/{bookmarkId}": {
987
1032
  "get": {
988
1033
  "description": "Get bookmark by its id",
@@ -1445,6 +1490,14 @@
1445
1490
  },
1446
1491
  "tagName": {
1447
1492
  "type": "string"
1493
+ },
1494
+ "attachedBy": {
1495
+ "type": "string",
1496
+ "enum": [
1497
+ "ai",
1498
+ "human"
1499
+ ],
1500
+ "default": "human"
1448
1501
  }
1449
1502
  }
1450
1503
  }
@@ -1536,6 +1589,14 @@
1536
1589
  },
1537
1590
  "tagName": {
1538
1591
  "type": "string"
1592
+ },
1593
+ "attachedBy": {
1594
+ "type": "string",
1595
+ "enum": [
1596
+ "ai",
1597
+ "human"
1598
+ ],
1599
+ "default": "human"
1539
1600
  }
1540
1601
  }
1541
1602
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: karakeep_python_api
3
- Version: 1.6.0
3
+ Version: 1.7.0
4
4
  Summary: Community python client for the Karakeep API.
5
5
  Home-page: https://github.com/thiswillbeyourgithub/karakeep_python_api/
6
6
  Keywords: rss,karakeep,hoarder,data-hoarding,python,api,feeds,openapi
@@ -7,7 +7,7 @@ with open("README.md", "r") as readme:
7
7
 
8
8
  setup(
9
9
  name="karakeep_python_api",
10
- version="1.6.0",
10
+ version="1.7.0",
11
11
  description="Community python client for the Karakeep API.", # Simplified description
12
12
  long_description=long_description,
13
13
  long_description_content_type="text/markdown",