5

MacOSX contextual menus allow me use Pocket [Formerly Read it later] to archive all, and also read, some of the enormous amounts of content that I come across daily on my browser of choice - Safari.

On iOS [iPad/iPhone] however, the native 'Add to Reading List' feature for Safari is the most tightly integrated option when 'long-clicking' a URL in many different apps, like Mail [all newsletters with links]. This has caused a lot of grief for me as half on my links are saved to the Safari Reading List, and half to a Read-it-later service like Pocket.

Consolidating it in a seamless way when using iOS is a challenge if you wish to avoid opening the webpage in safari first, then clicking a bookmarklet, etc.

Web-based trigger services like 'IFTTT' are only useful when the content has already made its way to Cloud services that it supports, like Pocket, Evernote etc.

One conceptual solution to this problem could be something along the lines of having a script run on my mac that is periodically looking for new items in the 'Reading List' plist file and extracting the url when it sees a new item added [since iCloud syncs iOS and MacOSX Safari]. Perhaps Alfred or some other automator service could then get it to a spreadsheet on the cloud which can then sync with IFTTT and Pocket etc.

Maybe this particular design is not technically feasible or outright wrong, but I would be really grateful if someone with more expertise or nous could suggest an implementation or similar solution.

TL;DR

How can I sync Safari's 'reading list' URLs to Pocket/Evernote etc automagically?

1
  • It's sounds good, i'm planing on using Hazel to check if plist has changed and then run script.
    – Lapaev
    Aug 11, 2013 at 23:48

4 Answers 4

5

I had this same idea a few months ago. I came up with a solution that works, using Ruby.

I use this gist to parse the Safari Reading List plist file: https://gist.github.com/andphe/3232343

Then I use the ruby Pocket gem to add each item to Pocket.

In the end, I went with Pinboard instead of Pocket, and I have a working project up on github that does exactly that, except using Pinboard.

The example code that you'd benefit from is: https://github.com/prokizzle/pinboard_tools/blob/master/lib/srl_to_pinboard.rb

What you'd ideally do to make it automatic is have Hazel monitor the Safari Reading List plist file for changes, and then run the ruby script if it's recently modified. That way, every item will make it from SRL to your read later service of choice.

Hope that helps.

3

I use the same bash command as Neglectogram above, but used it within a somewhat primitive script I wrote, which uses Pocket's "add by email" solution as outlined in the other answer to this post. I go in to detail here as there seems to be a demand for a solution to this and such I want even novice users to be able to use this (if it works properly).

My script focuses specifically on Evernote and Pocket as asked, but would work with any service which has the same "email your content in" feature.

The result is as desired, whereby the script:

  • extracts all of the links in the reading list (BUG: takes all bookmarks from Safari, so I temporarly deleted all my bookmarks and just left the reading list, not ideal I know but it works).

  • Iterates over each of these links and sends them to Pocket/Evernote/whatever service individually.

To use the script yourself:

  • Simply open it up in any text editor and replace the email addresses with your Pocket/Evernote account email address depending on which service you want to use and the recipient email addresses with Evernote or Pocket "email in to us" URLs. (Change addresses on lines 11, 13 and 14 to your own).
  • If just using Pocket, you need to send FROM your Pocket account email address TO add@getpocket.com
  • If using Evernote, you can send FROM any of your email addresses TO your specific Evernote Email Adress.

Here is the script I wrote below... (note, I am using Mac OS X, and as such this is a bash script and may not work on other OSs)

#!/bin/bash
# Script to export Safari's reading list into a text file, then import this into Pocket or Evernote (or any service with a "email in content" feature).

# First take all of Safari's Reading List items and place them in a text file.
/usr/bin/plutil -convert xml1 -o - ~/Library/Safari/Bookmarks.plist | grep -E  -o '<string>http[s]{0,1}://.*</string>' | grep -v icloud | sed -E 's/<\/{0,1}string>//g' > readinglistlinksfromsafari.txt

# Now loop over each of those URls within that text file and add them to pocket.
while IFS= read -r line
do
    echo $line
/usr/sbin/sendmail -i -f {{CHANGE THIS insert your pocket account email address here}} {{CHANGE THIS TO EITHER add@getpocket.com OR YOUR EVERNOTE EMAIL ADDRESS}} <<END
Subject: $line
From: {{ CHANGE THIS to your pocket account email if using Pocket, otherwise any of your email accounts will do.}}
To: add@getpocket.com {{ OR IF USING EVERNOTE YOUR EVERNOTE EMAIL ADDRESS}}

$line
END
done < readinglistlinksfromsafari.txt

Above is the template for you to change, and below is the exact script I used, complete with email addresses for Pocket, to act as an example. (On Mavericks, this send to pocket ALL element in Bookmarks.plist, then also Bookmark)

#!/bin/bash
# Script to export Safari's reading list into a text file, then import this into Pocket or Evernote (or any service with a "email in content" feature).

# First take all of Safari's Reading List items and place them in a text file.
/usr/bin/plutil -convert xml1 -o - ~/Library/Safari/Bookmarks.plist | grep -E  -o '<string>http[s]{0,1}://.*</string>' | grep -v icloud | sed -E 's/<\/{0,1}string>//g' > readinglistlinksfromsafari.txt

# Now loop over each of those URls within that text file and add them to pocket.
while IFS= read -r line
do
    echo $line
/usr/sbin/sendmail -i -f myemailaddress@gmail.com add@getpocket.com <<END
Subject: $line
From: myemailaddress@gmail.com
To: add@getpocket.com

$line
END
done < readinglistlinksfromsafari.txt

I hope this works for you all, and you find it helpful as this is one of my first public scripts etc. Any question just let me know! Here is a link to the GitHub Gist for this also.

https://gist.github.com/arcadia168/0bade46a6bb720395f56

Enjoy!

1

Also, this link may help a little. It's not perfect but it's an option. http://help.getpocket.com/customer/portal/articles/482759

1
  • Links rot. We prefer answers that copy out the relevant, useful data behind a link in to the answer body. For more information on link rot and Stack Exchange please see this article. Thanks!
    – Ian C.
    Jul 20, 2015 at 21:48
0

Perhaps the plist structure has changed since this posting but I found grepping for https to be a bit noisy and returned a significant number of URLs that were not legitimate reading list items. I wrote this little script to import all items into Pocket

#!/usr/bin/env python3

import logging
import os
import plistlib
import requests
import sys
import webbrowser


CONSUMER_KEY = os.environ["POCKET_CONSUMER_KEY"]
BASE_URL = "https://getpocket.com"
REDIRECT_URL = "localhost"

logger = logging.getLogger(__name__)
urls = []


def extract_urls(node):
    children = node.get("Children", [])
    url = node.get("URLString")
    if url:
        urls.append(url)
    for child in children:
        extract_urls(child)


def read_plist():
    filename = os.path.expanduser("~/Library/Safari/Bookmarks.plist")
    with open(filename, 'rb') as handler:
        plist = plistlib.load(handler)
        extract_urls(plist)


def post(url, data):
    headers = {
        "x-accept": "application/json",
    }
    response = requests.post(url, data=data, headers=headers)
    error = response.headers.get("X-Error")
    if error:
        logger.error(f"{response.status_code}, {error}")
        response.raise_for_status()
    else:
        return response.json()


def request_code():
    payload = {
        "consumer_key": CONSUMER_KEY,
        "redirect_uri": REDIRECT_URL,
    }
    response = post(f"{BASE_URL}/v3/oauth/request", payload)
    return response["code"]


def request_access_token(code):
    payload = {
        "consumer_key": CONSUMER_KEY,
        "code": code,
    }
    response = post(f"{BASE_URL}/v3/oauth/authorize", payload)
    return response["access_token"]


def request_authorization(code):
    url = f"{BASE_URL}/auth/authorize?request_token={code}&redirect_uri={REDIRECT_URL}"
    webbrowser.open(url, new=2)


def authenticate_pocket():
    code = request_code()
    request_authorization(code)
    input("Press any key after authorizing app...")
    return request_access_token(code)


def add_item(url, token):
    payload = {
        "url": url,
        "consumer_key": CONSUMER_KEY,
        "access_token": token,
    }
    return post("https://getpocket.com/v3/add", payload)


def main():
    read_plist()
    access_token = authenticate_pocket()
    logger.info("Successfully authenticated with Pocket")
    for url in urls:
        add_item(url, access_token)
    logger.info(f"Added {len(urls)} urls to Pocket!")


if __name__ == '__main__':
    sys.exit(main())

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .