Signal Desktop (Update)

My weekend adventures got me as far as a running Election branch. Something was obviously a little weird as it was opening with a javascript debugger taking up the right third of the app window. Not ideal, but easy to close.

And then i tried to link it to the account on my phone… no dice.

What i’d built was the development version, which defaults to connecting to the test / staging servers. For any of this experiment to be useful it needs to connect to the production servers.

These are all defined in the /config directory, but it wasn’t obvious to me how to change to another config. In the package.json there were references to ${env.SIGNAL_ENV} but exporting that to the shell with a value of ‘production’ didn’t help.

A little reading about my new friend ‘yarn’ showed that there was a ‘–production=true’ CLI option. Passing that along with ‘yarn install’ broke things.. but the command:

$ yarn start --production=true

Moves things along and makes it possible to link to a phone account. The process is actually pretty smooth – you just take a picture of a QRCode, give the client a name and you’re done.

What i’ve still not worked out is how to tell my other new friend ‘electron-packager’ to package the production version. Until that is worked out i’m stuck with the Muon version… which isn’t a bad place – it has been very stable thus far.

Edit: It seems ‘electron-packager’ was not my friend after all, ‘yarn’ however i’m starting to like! The ‘package.json’ contains a ‘scripts’ section defining a bunch of targets, one of which ‘pack-prod’ is ‘SIGNAL_ENV=production npm run dist’ which seems exactly what i need. And, indeed:

$ yarn pack-prod

spat out a ‘dist’ dir containing a working ‘production’ Signal.app.

The end.

Advertisements

Flickr Local Backup?

Flickr is dead / dying. Yahoo! is owned by someone like CBS… i’m not even sure i want to know. Time to get out. Maybe not completely, but that’s a different story.

My plan is to make a local backup / archive of everything that i’ve uploaded. In theory there is a copy of everything elsewhere, but as previous discussed, my organisational skills leave a little to be desired.

Pick a tool. There is a Python Flickr API kit thing, so presumably someone will have written a backup tool. Checkout GitHub and see what is there. The most recently updated / highly rated choice is Flickrmirrorer. Lets give that a go:

$ git clone --recursive https://github.com/markdoliner/flickrmirrorer.git
Cloning into 'flickrmirrorer'...
remote: Counting objects: 483, done.
remote: Total 483 (delta 0), reused 0 (delta 0), pack-reused 483
Receiving objects: 100% (483/483), 104.01 KiB | 0 bytes/s, done.
Resolving deltas: 100% (225/225), done.
$ cd flickrmirrorer/
$ ./flickrmirrorer.py --help
Traceback (most recent call last):
 File "./flickrmirrorer.py", line 49, in <module>
 import requests
ImportError: No module named requests

Ah, fun… Python libraries. This always ends well. According to the README.md we need:

  • python 2.something or python 3.anything
  • python dateutil
    • Ubuntu: apt-get install python-dateutil
  • python flickrapi library 2.0 or newer.
  • python requests

I’ve not done any Python dev on this machine, and it’s macOS not Linux, so no apt-get here. The first thing to try is installing pip… with easy_install. Sometimes it’s pip, sometimes it’s easy_install. They might well be equivalent… no idea!

$ sudo easy_install pip
...
$ sudo pip install requests
...
$ sudo pip install dateutils
...
$ sudo easy_install flickrapi

Might have just as easily been able to install flickrapi with pip, but they said they wanted easy_install. And now:

$ ./flickrmirrorer.py --help
usage: flickrmirrorer.py [-h] [-v] [-q] [-s] [--ignore-views]
 [--ignore-photos] [--ignore-videos]
 [--delete-unknown]
 destdir

Create a local mirror of your flickr data.

positional arguments:
 destdir the path to where the mirror shall be stored

optional arguments:
 -h, --help show this help message and exit
 -v, --verbose print progress information to stdout
 -q, --quiet print nothing to stdout if the mirror succeeds
 -s, --statistics print transfer-statistics at the end
 --ignore-views do not include views-counter in metadata
 --ignore-photos do not mirror photos
 --ignore-videos do not mirror videos
 --delete-unknown delete unrecognized files in the destination directory.
 Warning: if you choose to ignore photos or videos, they
 will be deleted!

Cool. Now all we need to do is setup a disk to keep all this stuff and kick it off:

$ ./flickrmirrorer.py /Volumes/FlickrDump/backup/
0:121: execution error: "https://www.flickr.com/services/oauth/authorize?oauth_token=<token>&perms=read" doesn’t understand the “open location” message. (-1708)

Please authorize Flickr Mirrorer to read your photos, titles, tags, etc.

1. Visit https://www.flickr.com/services/oauth/authorize?oauth_token=<token>&perms=read
2. Click "OK, I'LL AUTHORIZE IT"
3. Copy and paste the code here and press 'return'

XYZ-ABC-123

Fetching 33991776973.jpg
Updated metadata for 33991776973.jpg
Fetching 32923862986.jpg
Updated metadata for 32923862986.jpg
Fetching 31996362424.jpg
...

This will presumably take a while. An hour or so in:

$ ls -1 *.jpg | wc -l
 900

Edit: of course it died right after this was posted…

Traceback (most recent call last):
 File "./flickrmirrorer.py", line 812, in <module>
 main()
 File "./flickrmirrorer.py", line 807, in main
 mirrorer.run()
 File "./flickrmirrorer.py", line 195, in run
 self._run_helper()
 File "./flickrmirrorer.py", line 237, in _run_helper
 self._download_all_photos()
 File "./flickrmirrorer.py", line 288, in _download_all_photos
 new_files |= self._download_photo(photo)
 File "./flickrmirrorer.py", line 398, in _download_photo
 photo_datetime = get_photo_datetime(photo)
 File "./flickrmirrorer.py", line 147, in get_photo_datetime
 return dateutil.parser.parse(photo['datetaken'])
 File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/dateutil/parser.py", line 697, in parse
 return DEFAULTPARSER.parse(timestr, **kwargs)
 File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/dateutil/parser.py", line 310, in parse
 ret = default.replace(**repl)
ValueError: month must be in 1..12

<sigh>

It seems that some of the images in Flickr has no date taken data at all. Isn’t that fun. Time for a little hackery:

$ git diff flickrmirrorer.py 
diff --git a/flickrmirrorer.py b/flickrmirrorer.py
index ef9aa85..29df9a2 100755
--- a/flickrmirrorer.py
+++ b/flickrmirrorer.py
@@ -144,7 +144,11 @@ def get_photo_datetime(photo):
 datetime.datetime
 """
 if photo['datetakenunknown'] == "0":
- return dateutil.parser.parse(photo['datetaken'])
+ try:
+ return dateutil.parser.parse(photo['datetaken'])
+ except ValueError:
+ # now what?
+ return datetime.datetime(1970,1,1,0,0,0,0)
 
 try:
 parsed = datetime.datetime.strptime(photo['title'], '%Y%m%d_%H%M%S')

Which is to say:

  • wrap the parsing of ‘datetaken’ in a try / catch
  • return the beginning of unix time and move on

Suppose it might have been easier to edit the metadata on flickr… but where is the fun in that!

Signal Desktop (without Chrome)

As unfathomable as i’m sure this is, i’m not a fan of the Chrome browser – don’t think i’ve ever used it. One of those ‘on principle’ things of which i seem to be so fond. Unfortunately the Signal Desktop application runs as a Chrome App… imagine their surprise when Big G declared that it would stop supporting Chrome Apps in the near future. Sorry, getting distracted.

If you want to run a Signal Desktop App there are now options. They most revolve around frameworks that provide a browser platform to applications without actually being a browser, and have names like Electron and Muon.

After a few failed attempts to create a working development environment for Election, and build the official Signal Desktop Electron branch i stumbled upon a Muon branch. This is obviously not at all official, and completely unsupported, but it works really well! If nothing else it will get me by until an official Electron build is produced by Whisper Systems.

My build environment for this was:

  • Xcode (think that’s where my git binaries come from…)
  • macports
    • nodejs7
    • npm4

As usual it was more of a pain to get the environment setup than it was to follow the build instructions. Make sure you install nodejs7 before npm4 otherwise you get stuck with an old version… i should probably move to Brew, etc.

The end result was a OS X Signal.app that paired perfectly with the account on my phone, and has been completely stable / trouble free for the last week. It doesn’t look like the branch is going to be maintained – at least nothing has been merged to it from upstream for nearly two weeks, so this isn’t a long term solution. However, if like me you’re moving more and more of your communications away from mail to signal, it’s a good way to save yourself from typing on a phone!

Edit: i’m an idiot. Building the Electron branch is simple.

$ git clone --recursive https://github.com/WhisperSystems/Signal-Desktop.git
Cloning into 'Signal-Desktop'...
remote: Counting objects: 22939, done.
remote: Compressing objects: 100% (241/241), done.
remote: Total 22939 (delta 333), reused 546 (delta 324), pack-reused 22373
Receiving objects: 100% (22939/22939), 49.29 MiB | 1.04 MiB/s, done.
Resolving deltas: 100% (13362/13362), done.
$ cd Signal-Desktop/
$ git checkout electron
Branch electron set up to track remote branch electron from origin.
Switched to a new branch 'electron'
$ npm install

Now wait for a while… and eventually:

$ npm start

> signal-desktop@1.0.10 start /Users/<redacted>/src/Signal-Desktop
> electron .

Wait for app ready
setting AUMID
reading package.json
configuring
NODE_ENV development
NODE_CONFIG_DIR /Users/<redacted>/src/Signal-Desktop/config
NODE_CONFIG {}
ALLOW_CONFIG_MUTATIONS undefined
HOSTNAME undefined
NODE_APP_INSTANCE undefined
SUPPRESS_NO_CONFIG_WARNING undefined
userData /Users/<redacted>/Library/Application Support/Signal-development
app ready

signal desktop

Edit 2: Sven educated me further, and now i can package an application. This requires another exciting adventure with npm, and installing another tool, the ‘electron-packager‘:

$ npm install electron-packager -g

This let me run:

$ ~/.local/lib/npm/bin/electron-packager .
Packaging app for platform darwin x64 using electron v1.6.7
Wrote new app to /Users/<redacted>/src/Signal-Desktop/Signal-darwin-x64

Which outputs a macOS application bundle ‘Signal.app’. It is a little “heavy”:

$ du -sh Signal.app
156M Signal.app

But that’s the end of the trail. From git to a usable Signal Desktop application… it’s probably time i went outside.

Signal?

Time for another “old man shakes fist at sky” moment.

4593531893_f67a757fa1

[several deleted attempts to justify why this time you should engage with safe guarding your privacy, and how i’m moving personal communications away from mail]

How about you get it installed:

Trust is in short supply these days. Trust that you can express yourself freely.

Photo Archiving?

I have a problem… yes, yes, i know. This is different.

One of my photography projects (lets call it IWTFY) is quite popular. This means that periodically there are requests for sets of images. When this happens i end up trolling through Lightroom libraries on several machines looking for images, exporting them at an appropriate size / dpi, gathering them into one place, packaging them for distribution, uploading them to be downloaded. Bleugh!

What i need is a place that i can:

  • archive / upload a full-sized processed image
  • tag / label all images
  • search / select subsets
  • define an export size
  • have everything processed into a download bundle

Does such a thing exist? Is it worth paying for? Should i just get my shit together and import everything into a new Lightroom library on one machine?

Help?

Chorba / شوربا‎‎ / ሾርባ / شوروا‎ / शोरबा

Recently i’ve been making a simple lentil soup and telling everyone it’s “chorba”. Truth be told… the term is so generic that it’d be hard for that not to be the case.

  • brown lentils (soak over night, wash well)
  • medium onion
  • 4 – 8 cloves of garlic
  • 1 tsp ground coriander seeds
  • 1/4 tsp cumin
  • bayleaf

Thinly slice the onion and fry in oil with the bayleaf, add salt, and cover until they are soft. Add the garlic, roughly chopped, and cook until the raw garlic smell is gone. Add the coriander powder and cumin, let it cook for a minute, then add the lentils, and cover with water. Add more salt as needed. Bring to the boil and simmer on a low heat for 20 to 30 mins, or until the lentils are soft / losing shape. Remove the bayleaf and puree with a hand blender until creamy.

In a food processor, make a smooth, thin, paste from:

  • cilantro / coriander leaves
  • juice of half a lemon
  • 1 – 2 tbsp of olive oil

Serve the soup with spoonfuls of the sauce – the sour / bitterness balances the creaminess of the lentils… and it’s a really pretty colour. Feels like it cures colds!

Perfidious Albion II

Was a little rushed this morning, and skipped over a few things.

The direction of travel suggests to me that the question of triggering Article 50 is going to be the major issue of the 2020 election.

There is a little more to this statement than the perpetually pushed back triggering of Article 50. The largest of which is the future of the currently dysfunctional United Kingdom of Great Britain and Northern Ireland.

One of Mrs. May’s first official visits was to Holyrood Palace for an audience with the Queen of the North, the Great Nicola of Dreghorn. The reported content of their conversation was that there would be no invocation of Article 50 until there was agreement on a negotiating position within the Union.

Right. That’s going to happen in short order. Or, more likely, never.

It’s another one of those “evil genius, purely evil, or extremely shrewd” moments for the press to consider. Is the Queen of the North now on the hook to absorb the heaped opprobrium of little england as she valiantly saves them from their idiotic impulses?

Is it an excuse to moan, “If it wasn’t for that stubborn Scot we’d have taken back our country by now!” Or, more of a “Oh please Brer Fox, whatever you do, please don’t throw me into the briar patch”?

It’s pretty obvious that it puts another checkpoint in front of any call from the swivel eyed brigade – “we must respect the view of our partners in the Union… or are you prepared to be responsible for it’s destruction?!”

We may never know for sure one way or the other, but it’s very hard to see it as anything other than a delaying tactic.

Following on from Scotland is a report today that:

there will be no return to border checks for people entering the UK from the Republic of Ireland despite Britain’s vote to leave the EU.

That’s generations worth of clusterfuckery to be resolved! It’s not clear to me how it’s possible to have an open border between Ireland and Northern Ireland when one is part of the EU, with freedom of movement, and the other is fortress england. The obvious solution would be to introduce a hard border between Northern Ireland and little england… you can imagine how well that would be received in the Union.

In a lot of ways the unknown fate of Northern Ireland is one of the hardest parts of the referendum result to accept. It seems impossible to me that Cameron could ever gambled with the fragile peace in that region. The Good Friday agreement relies on Ireland and the UK being members of the EU to facilitate freedom of movement over the border. Is the potential resumption of The Troubles a reasonable outcome of internal Tory party spats really a price worth paying? Earlier when i referred to Cameron as “a political midget” i meant no offence to midgets…

And Wales? Well, Wales is fucked. As the song goes, “if you go to bed with the pigs, you wake up with the pigs”.