NetNewsWire 5 - Send to Instapaper?

Hi, all. NetNewsWire 5 is out - right now, you can only share things via Safari extension/share sheet. I would like to be able to share the current article, but there’s no Instapaper sharing extension on the Mac.

I should be able to use Keyboard Maestro (or even simple Applescript) to trigger on a keyboard shortcut, grab the current article’s URL from NetNewsWire, and run my Send to Instapaper bookmarklet’s code against it. NetNewsWire is Applescriptable, but I haven’t written Applescript in at least a decade, and not much of it then.

Anyone have any pointers? Thanks in advance…

Many years ago I wrote a script to send a NNW item to BibDesk - still available here

http://dfay.fastmail.fm/bibdesk/

Have you tried this?

Yup, doesn’t work. That extension provides a toolbar button in Safari and some Greasemonkey-like rewriting of a few websites to add inline Instapaper links, but it does not provide a sharing extension.

Well, I have this one 99% solved. But the last 1% keeps it from working at all.

Using Automator, I was able to create a “Quick Action” (neé “Service”) that will add a given URL to Instapaper by creating a shell script .

That part works great.

However:

  1. there is no “Copy URL of the Article That You Are Reading” in NetNewsWire, so there’s no easy way to trigger this.

  2. And it apparently has to be a URL. If it is is a link such as

<a href=http://google.com>Search Here</a>

and you right click on that link, then choose “Services” and use one of the actions which takes a URL, it appears that NNW is sending “Search Here” rather than the URL.

I don’t know how to get around that.


FWIW, here’s a shell script which will take some input, look for a URL, and if it finds one, will try to add it to Instapaper.

It requires that you put in your Instapaper username and password into variables (or you can use keychain, as I explain below).

Maybe someone else can use this to come up with a working solution.

Although it might look complex, the real “meat” of it is just this part:

curl --dump-header - --location --silent \
--basic --user "${INSTAPAPER_USERNAME}:${INSTAPAPER_PASSWORD}" \
--data-urlencode "url=$URL" https://www.instapaper.com/api/add

That assumes you have 3 variables defined:

  • INSTAPAPER_USERNAME
  • INSTAPAPER_PASSWORD
  • URL

The rest is just error checking. It will also use terminal-notifier or growlnotify (if found) to tell the user what is happening, because otherwise there is no way to know if it worked or not if you are using it from a service.

#!/usr/bin/env zsh -f
# Purpose: Send a URL to Instapaper
#
# From:	Timothy J. Luoma
# Mail:	luomat at gmail dot com
# Date:	2019-08-30

NAME="$0:t:r"

if [ -e "$HOME/.path" ]
then
	source "$HOME/.path"
else
	PATH=/usr/local/scripts:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin
fi

function msg {

echo "$NAME: $@"

if (( $+commands[terminal-notifier] ))
then

	terminal-notifier -appIcon https://images.luo.ma/appicons/terminal-notifier/instapaper.png -message "$@" -title "$NAME"

elif (( $+commands[growlnotify] ))
then

	growlnotify  \
	--appIcon "NetNewsWire" \
	--identifier "$NAME" \
	--message "$@" \
	--title "$NAME"

fi

}

if [[ "$#" == "0" ]]
then
	msg "$NAME: No Arguments given!"
	exit 1
fi

	# This is my attempt at parsing the input. It's not very complicated or smart.
	# All it does it take all of the info given to it and replaces every space with
	# a newline, and then looks for a 'http' at the start of the newline. If it finds
	# more than one, it will just use the first one.
URL=$(echo "$@" | tr ' ' '\012' | egrep -i '^http' | head -1)

	# if no URLs are found, complain and quit immediately
if [[ "$URL" == "" ]]
then
	msg "$NAME: No URL found in input: ($@)!"
	exit 1
fi


############################################################################################################################################################
# The easy way to store your Instapaper credentials is to put them in a plain text file with this format:
#
#	INSTAPAPER_USERNAME='you@example.com'
#	INSTAPAPER_PASSWORD='Su8ers3kr3t'
#
# but that's obviously not the most secure idea ever. You could fetch them from your Keychain using these lines instead:
#
# 	INSTAPAPER_USERNAME=$(security find-internet-password -s www.instapaper.com 2>&1 | awk -F'"' '/acct/{print $4}')
# 	INSTAPAPER_PASSWORD=$(security find-internet-password -gs www.instapaper.com 2>&1 | awk -F'"' '/^password/{print $2}')
#
# the first time you run the script you will see a prompt which says something like
# 'security wants to use your confidential information stored in "www.instapaper.com" in your keychain'

INSTAPAPER_USERNAME='you@example.com'
INSTAPAPER_PASSWORD='Su8ers3kr3t'

STATUS=$(curl --location --silent --basic \
		--user "${INSTAPAPER_USERNAME}:${INSTAPAPER_PASSWORD}" \
			https://www.instapaper.com/api/authenticate)

if [[ "$STATUS" == "200" ]]
then

	msg "$NAME: Verified login, now adding $URL..."

	IFS=$'\n' RESULT=($(curl --dump-header - --location --silent \
						--basic --user "${INSTAPAPER_USERNAME}:${INSTAPAPER_PASSWORD}" \
						--data-urlencode "url=$URL" https://www.instapaper.com/api/add \
						| tr -d '\r' \
						| egrep '^(Content-Location|X-Instapaper-Title): '))

	FINAL_URL=$(echo "$RESULT[1]" | sed 's#^Content-Location: ##g')

	FINAL_TITLE=$(echo "$RESULT[2]" | sed 's#^X-Instapaper-Title: ##g')

	if [ "$FINAL_URL" = "" -o "$FINAL_TITLE" = "" ]
	then
			msg "Error! Either FINAL_URL or FINAL_TITLE is empty!"
			exit 1
	else
			msg "Success: '${FINAL_TITLE}'"
			exit 0
	fi


else
		msg "FATAL ERROR: Status = $STATUS"
		exit 1
fi

exit 0

Take that file, save it as /usr/local/bin/send-to-instapaper.sh (creating /usr/local/bin/ if necessary) and then make it executable:

chmod 700 /usr/local/bin/send-to-instapaper.sh

Then add your Instapaper username and password to it where shown.

Once you’ve done that, using it is simply a matter of:

/usr/local/bin/send-to-instapaper.sh https://arstechnica.com/information-technology/2019/06/microsoft-says-mandatory-password-changing-is-ancient-and-obsolete/

and it will tell you if it worked or not.

Hmm, I’ll have to play with that. You can get the URL of the current article from NNW via Applescript, so that may be the missing bit. It’s something like

tell application “NetNewsWire”
set article_url to (url of current article)
end tell

Oooooh! Well, that ought to be do-able then. Let me take a crack at it.

Boom! Got it!

Keyboard Maestro macro posted to the Keyboard Maestro forum.

You’ll have to either edit the script to add your Instapaper username (email) and password, or add it to Keychain. There are instructions in the macro.

The Keyboard Maestro macro is two steps. The first is AppleScript which has a slightly different syntax to the example above:

tell application "NetNewsWire"
    set articleUrl to the url of the current article
end tell

return articleUrl

which gets saved to a variable NNW_URL

The second is the shell script which will use $KMVAR_ NNW_URL and do all the behind-the-scenes work to connect to the Instapaper API.

I chose ⌘ + ⇧ + I (capital i) because ⌘+I was already in use by NNW. It’s also available through the Keyboard Maestro menu bar item.

1 Like

That did it, after I installed terminal-notifier with Homebrew. Thanks!