Detailed Guide: Using the Pocket API with a Custom Script
Let me elaborate on Method 2, which gives you the most control over the synchronization process between Firefox Pocket and ArchiveBox.
Step 1: Set Up Pocket API Access
-
Create a Pocket API application:
- Go to https://getpocket.com/developer/apps/new
- Fill in the application details:
- Application name: “PocketToArchiveBox”
- Application description: “Sync Pocket items to ArchiveBox”
- Permissions: Check “Retrieve” (we only need to read your list)
- Platforms: Check “Web”
- Click “Create Application”
- You’ll receive a Consumer Key - save this for later use
-
Obtain an Access Token:
- This is a bit tricky as it requires a three-step OAuth process
- Let’s create a simple script to handle this authentication:
import requests
import webbrowser
import time
CONSUMER_KEY = "114230-e320d22731d275a71b062c1"
REDIRECT_URI = "http://localhost" # This can be any URL, we'll intercept the redirect
# Step 1: Get a request token
request_data = {
"consumer_key": CONSUMER_KEY,
"redirect_uri": REDIRECT_URI
}
response = requests.post("https://getpocket.com/v3/oauth/request", json=request_data)
request_token = response.json()["code"]
print(f"Request token: {request_token}")
# Step 2: Redirect user to authorization page
auth_url = f"https://getpocket.com/auth/authorize?request_token={request_token}&redirect_uri={REDIRECT_URI}"
print(f"Opening browser to authorize application: {auth_url}")
webbrowser.open(auth_url)
# Wait for user to authorize
input("Please authorize the app in your browser, then press Enter to continue...")
# Step 3: Convert request token to access token
auth_data = {
"consumer_key": CONSUMER_KEY,
"code": request_token
}
response = requests.post("https://getpocket.com/v3/oauth/authorize", json=auth_data)
access_token = response.json()["access_token"]
print(f"Your access token is: {access_token}")
print("Save this token for future use with your script.")Run this script once to get your access token. Save both the Consumer Key and Access Token securely.
Step 2: Create the Synchronization Script
Now, let’s create a more comprehensive script that:
- Retrieves items from Pocket
- Filters them if needed (e.g., only unarchived items)
- Keeps track of already processed items to avoid duplicates
- Adds new URLs to ArchiveBox
#!/usr/bin/env python3
import requests
import subprocess
import json
import os
import logging
from datetime import datetime
# Setup logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='pocket_to_archivebox.log'
)
# Configuration
CONSUMER_KEY = "your_consumer_key"
ACCESS_TOKEN = "your_access_token"
ARCHIVEBOX_PATH = "/path/to/your/archivebox" # Change this to your ArchiveBox directory
STATE_FILE = os.path.expanduser("~/.pocket_archivebox_state.json")
# Options: 'unread', 'archive', or 'all'
POCKET_STATE = "all" # Change to 'unread' if you only want unread items
# Options: newest, oldest, title, site
POCKET_SORT = "newest"
# Maximum number of items to retrieve (0 for all)
MAX_ITEMS = 50
def load_state():
"""Load the state file containing previously processed items"""
if os.path.exists(STATE_FILE):
with open(STATE_FILE, 'r') as f:
return json.load(f)
return {"processed_items": [], "last_run": None}
def save_state(state):
"""Save the state to keep track of processed items"""
with open(STATE_FILE, 'w') as f:
json.dump(state, f, indent=2)
def get_pocket_items():
"""Retrieve items from Pocket API"""
logging.info("Retrieving items from Pocket")
payload = {
"consumer_key": CONSUMER_KEY,
"access_token": ACCESS_TOKEN,
"state": POCKET_STATE,
"sort": POCKET_SORT,
"detailType": "simple",
"count": MAX_ITEMS if MAX_ITEMS > 0 else None
}
try:
response = requests.post("https://getpocket.com/v3/get", json=payload)
response.raise_for_status()
data = response.json()
# Extract URLs and item IDs
items = []
for item_id, item in data.get("list", {}).items():
url = item.get("resolved_url") or item.get("given_url")
if url:
items.append({
"id": item_id,
"url": url,
"title": item.get("given_title", ""),
"time_added": item.get("time_added", "")
})
logging.info(f"Retrieved {len(items)} items from Pocket")
return items
except Exception as e:
logging.error(f"Error retrieving Pocket items: {e}")
return []
def add_to_archivebox(urls):
"""Add URLs to ArchiveBox"""
if not urls:
logging.info("No new URLs to add to ArchiveBox")
return True
try:
# Change to ArchiveBox directory
os.chdir(ARCHIVEBOX_PATH)
# Create a temporary file with URLs
temp_file = os.path.join(ARCHIVEBOX_PATH, "pocket_urls.txt")
with open(temp_file, 'w') as f:
for url in urls:
f.write(f"{url}\n")
# Add URLs to ArchiveBox using the file
cmd = f"archivebox add --depth=1 < {temp_file}"
logging.info(f"Running: {cmd}")
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
# Clean up
os.remove(temp_file)
if result.returncode != 0:
logging.error(f"ArchiveBox error: {result.stderr}")
return False
logging.info(f"Successfully added {len(urls)} URLs to ArchiveBox")
return True
except Exception as e:
logging.error(f"Error adding to ArchiveBox: {e}")
return False
def main():
"""Main function to sync Pocket to ArchiveBox"""
logging.info("Starting Pocket to ArchiveBox sync")
# Load state
state = load_state()
processed_ids = set(state["processed_items"])
# Get items from Pocket
items = get_pocket_items()
# Filter out already processed items
new_items = [item for item in items if item["id"] not in processed_ids]
logging.info(f"Found {len(new_items)} new items to process")
if new_items:
# Extract URLs from new items
urls = [item["url"] for item in new_items]
# Add to ArchiveBox
if add_to_archivebox(urls):
# Update state with successfully processed items
for item in new_items:
processed_ids.add(item["id"])
# Update and save state
state["processed_items"] = list(processed_ids)
state["last_run"] = datetime.now().isoformat()
save_state(state)
logging.info("Sync completed")
if __name__ == "__main__":
main()Step 3: Make the Script Executable and Test It
-
Save the script to a file named
pocket_to_archivebox.py -
Make it executable:
chmod +x pocket_to_archivebox.py -
Run it manually to test:
./pocket_to_archivebox.py -
Check the logs to verify it’s working correctly:
cat pocket_to_archivebox.log
Step 4: Set Up a Cron Job for Automation
-
Edit your crontab:
crontab -e -
Add a scheduled task (this example runs daily at 3 AM):
0 3 * * * /full/path/to/pocket_to_archivebox.py -
For more frequent syncing (every 4 hours):
0 */4 * * * /full/path/to/pocket_to_archivebox.py
Additional Customization Options
Filtering Options
You can modify the script to filter items based on specific criteria:
# Add this inside get_pocket_items() function after retrieving the data
filtered_items = []
for item_id, item in data.get("list", {}).items():
# Only include items with specific tags
if 'tags' in item and 'archive-this' in item['tags']:
# Process item...
# Only include items from specific sites
if 'given_url' in item and 'github.com' in item['given_url']:
# Process item...Adding Tags in ArchiveBox
You can pass additional metadata to ArchiveBox:
# Modify the add_to_archivebox function
def add_to_archivebox(items):
for item in items:
url = item["url"]
title = item["title"]
tag = "pocket"
cmd = f'archivebox add "{url}" --tag "{tag}" --title "{title}"'
# Run command...Archiving After Syncing
You might want to archive items in Pocket after they’ve been added to ArchiveBox:
def archive_pocket_items(item_ids):
"""Archive items in Pocket after they've been added to ArchiveBox"""
payload = {
"consumer_key": CONSUMER_KEY,
"access_token": ACCESS_TOKEN,
"actions": [{"action": "archive", "item_id": item_id} for item_id in item_ids]
}
try:
response = requests.post("https://getpocket.com/v3/send", json=payload)
response.raise_for_status()
return True
except Exception as e:
logging.error(f"Error archiving Pocket items: {e}")
return FalseThis script provides a solid foundation that you can customize based on your specific needs. Let me know if you need any clarification or have specific requirements you’d like to incorporate!