Sync ownCloud bookmarks to Pinboard

import os
import requests
from bs4 import BeautifulSoup
from termcolor import cprint
from dotenv import load_dotenv
class Hydrator(object):
def __init__(self):
self.soups = {}
def title(self, url):
soup = self._get_soup(url)
title = soup.title.string
if title == "":
cprint(f"Url provided as title for {url}", "white", "on_blue")
title = url
return title
def description(self, url):
soup = self._get_soup(url)
meta = soup.find_all("meta")
for tag in meta:
if (
"name" in tag.attrs.keys()
and tag.attrs["name"].strip().lower() == "description"
):
content = tag.attrs.get("content")
if content is None:
content = tag.attrs.get("value")
if content is None:
cprint(f"No content found", "red")
print(tag.attrs.keys())
else:
return content
cprint(f"No description found for {url}", "white", "on_blue")
return ""
def _get_soup(self, url):
soup = self.soups.get(url)
if soup is None:
response = requests.get(url)
soup = self.soups[url] = BeautifulSoup(response.content, "lxml")
return soup
hydrate = Hydrator()
def get_bookmark_from_pinboard(url):
response = requests.get(
url="https://api.pinboard.in/v1/posts/get",
params={
"url": url,
"auth_token": os.getenv("PINBOARD_AUTH_TOKEN"),
"format": "json",
},
)
posts = response.json()["posts"]
return posts[0] if len(posts) == 1 else None
def hydrate_bookmark(bookmark):
title = bookmark["title"]
url = bookmark["url"]
description = bookmark["description"]
if title == url or title == "":
title = hydrate.title(url)
if description == url or description == "":
description = hydrate.description(url)
return {
"url": url,
"title": title,
"description": description,
"tags": bookmark["tags"],
}
def add_bookmark_to_pinboard(bookmark):
response = requests.get(
url="https://api.pinboard.in/v1/posts/add",
params={
"auth_token": os.getenv("PINBOARD_AUTH_TOKEN"),
"format": "json",
"url": bookmark["url"],
# actually title
"description": bookmark["title"],
# actually description
"extended": bookmark["description"],
"tags": ",".join(bookmark["tags"]),
},
)
body = response.json()
return body["result_code"] == "done"
def process_bookmark(bookmark):
url = bookmark["url"]
pinboard_bookmark = get_bookmark_from_pinboard(url)
# Add only if we don't find the bookmark in pinboard.
if pinboard_bookmark is None:
hydrated = hydrate_bookmark(bookmark)
success = add_bookmark_to_pinboard(hydrated)
if success:
cprint(f"Successfully added {url} to pinboard", "green")
else:
cprint(f"Error adding {url} to pinboard", "red")
else:
cprint(f"Url {url} found in Pinboard. Skipping.", "yellow")
def send_request(page=0):
try:
response = requests.get(
url=f'https://{os.getenv("OWNCLOUD_DOMAIN")}/index.php/apps/bookmarks/bookmark',
params={"type": "bookmark", "page": page},
headers={
"Cookie": os.getenv("OWNCLOUD_COOKIE"),
"requesttoken": os.getenv("OWNCLOUD_REQUEST_TOKEN"),
},
)
body = response.json()
status = body["status"]
if status == "success":
data = body["data"]
for bookmark in data:
process_bookmark(bookmark)
if len(data) != 0:
send_request(page + 1)
except requests.exceptions.RequestException as err:
cprint(f"Request failed: {err.request.url}", "red")
if __name__ == "__main__":
load_dotenv()
send_request()
__main__.py
PINBOARD_AUTH_TOKEN=username:token
OWNCLOUD_DOMAIN=your.owncloud.domain.com
OWNCLOUD_COOKIE=Get this from the network tab of the bookmarks page
OWNCLOUD_REQUEST_TOKEN=Also from the network tab
.env