Spaces:
Sleeping
Sleeping
File size: 7,068 Bytes
0c1aa19 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
from typing import Any
import os
import httpx
# Constants
RAINDROP_API_BASE = "https://api.raindrop.io/rest/v1"
RAINDROP_TOKEN = os.environ.get("RAINDROP_TOKEN")
async def make_raindrop_request(url: str, token: str, method: str = "GET", data: dict = None) -> dict[str, Any] | None:
"""Make a request to the Raindrop.io API with proper error handling."""
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
async with httpx.AsyncClient() as client:
try:
if method.upper() == "GET":
response = await client.get(url, headers=headers, timeout=30.0)
elif method.upper() == "POST":
response = await client.post(url, headers=headers, json=data, timeout=30.0)
else:
print(f"Unsupported method: {method}")
return None
response.raise_for_status()
return response.json()
except Exception as e:
print(f"Error making Raindrop request: {e}")
return None
def format_bookmark(item: dict) -> str:
"""Format a Raindrop bookmark into a readable string."""
return f"""
Title: {item.get('title', 'Untitled')}
URL: {item.get('link', 'No URL')}
Tags: {', '.join(item.get('tags', [])) or 'No tags'}
Created: {item.get('created', 'Unknown date')}
Description: {item.get('excerpt', 'No description available')}
"""
async def get_latest_feed(count: int = 10) -> str:
"""Get latest bookmarks from Raindrop.io feed.
Args:
count: Number of bookmarks to fetch (default: 10)
"""
url = f"{RAINDROP_API_BASE}/raindrops/0?perpage={count}&sort=-created"
data = await make_raindrop_request(url, RAINDROP_TOKEN)
if not data or "items" not in data:
return "Unable to fetch bookmarks or no bookmarks found."
if not data["items"]:
return "No bookmarks found in your collection."
bookmarks = [format_bookmark(item) for item in data["items"]]
return "\n---\n".join(bookmarks)
async def add_bookmark(url: str, title: str = "", description: str = "", tags: str = "", collection_id: int = 0) -> str:
"""Add a new bookmark to Raindrop.io
Args:
url: The URL to bookmark (required)
title: Title for the bookmark (optional, will be extracted from URL if not provided)
description: Description/excerpt for the bookmark (optional)
tags: Comma-separated tags to apply to the bookmark (optional)
collection_id: ID of the collection to add the bookmark to (default: 0 for Unsorted)
"""
if not url:
return "Error: URL is required"
raindrop_data = {
"link": url,
"collection": {"$id": collection_id}
}
if title:
raindrop_data["title"] = title
if description:
raindrop_data["excerpt"] = description
if tags:
# Convert comma-separated string to list
tag_list = [tag.strip() for tag in tags.split(",") if tag.strip()]
raindrop_data["tags"] = tag_list
endpoint = f"{RAINDROP_API_BASE}/raindrop"
response = await make_raindrop_request(endpoint, RAINDROP_TOKEN, method="POST", data=raindrop_data)
if not response or "item" not in response:
return "Failed to add bookmark. Please check the URL and try again."
return f"Bookmark successfully added:\n{format_bookmark(response['item'])}"
async def search_by_tag(tag: str, collection_id: int = 0, count: int = 10, from_date: str = "", to_date: str = "") -> str:
"""Search for bookmarks with a specific tag in Raindrop.io with optional date range filtering
Args:
tag: The tag to search for (required)
collection_id: ID of the collection to search in (default: 0 for all collections)
count: Maximum number of bookmarks to return (default: 10)
from_date: Start date in YYYY-MM-DD format (optional)
to_date: End date in YYYY-MM-DD format (optional)
"""
if not tag:
return "Error: Tag is required"
# Build search filters
search_filters = [f"-tags:\"{tag}\""]
# Add date range filters if provided
if from_date and from_date.strip():
search_filters.append(f"created>={from_date.strip()}")
if to_date and to_date.strip():
search_filters.append(f"created<={to_date.strip()}")
# Combine all search filters
search_query = " ".join(search_filters)
url = f"{RAINDROP_API_BASE}/raindrops/{collection_id}?perpage={count}&search={search_query}&sort=-created"
data = await make_raindrop_request(url, RAINDROP_TOKEN)
if not data or "items" not in data:
return "Unable to fetch bookmarks or no bookmarks found with this tag."
if not data["items"]:
return f"No bookmarks found with tag '{tag}' within the specified criteria."
bookmarks = [format_bookmark(item) for item in data["items"]]
result_msg = f"Found {len(data['items'])} bookmarks with tag '{tag}'"
if from_date or to_date:
date_range = f" (Date range: {from_date or 'any'} to {to_date or 'any'})"
result_msg += date_range
return result_msg + ":\n\n" + "\n---\n".join(bookmarks)
async def search_bookmarks(query: str, collection_id: int = 0, count: int = 10, from_date: str = "", to_date: str = "") -> str:
"""Search for bookmarks by keyword/text in Raindrop.io with optional date range filtering
Args:
query: The search term to look for in bookmarks (required)
collection_id: ID of the collection to search in (default: 0 for all collections)
count: Maximum number of bookmarks to return (default: 10)
from_date: Start date in YYYY-MM-DD format (optional)
to_date: End date in YYYY-MM-DD format (optional)
"""
if not query:
return "Error: Search query is required"
# Build search filters
search_filters = [f"\"{query}\""]
# Add date range filters if provided
if from_date and from_date.strip():
search_filters.append(f"created>={from_date.strip()}")
if to_date and to_date.strip():
search_filters.append(f"created<={to_date.strip()}")
# Combine all search filters
search_query = " ".join(search_filters)
url = f"{RAINDROP_API_BASE}/raindrops/{collection_id}?perpage={count}&search={search_query}&sort=-created"
data = await make_raindrop_request(url, RAINDROP_TOKEN)
if not data or "items" not in data:
return "Unable to fetch bookmarks or no bookmarks found for your search."
if not data["items"]:
return f"No bookmarks found matching '{query}' within the specified criteria."
bookmarks = [format_bookmark(item) for item in data["items"]]
result_msg = f"Found {len(data['items'])} bookmarks matching '{query}'"
if from_date or to_date:
date_range = f" (Date range: {from_date or 'any'} to {to_date or 'any'})"
result_msg += date_range
return result_msg + ":\n\n" + "\n---\n".join(bookmarks)
|