I can haz mp4?

Let’s Encrypt was so ridiculously easy to install on my private web server that I wondered whether I could switch to mp4s for gifs. I mean, video snippets. I can’t do those directly on wordpress.com, because wordpress.com does not support controlling where mp4 videos appear in email posts.

So let’s try!

Did it work? Huh? Huh?

[Edit: It does seem to kinda work, but not in Chromium? And the snippets don’t autoplay, even if the WordPress pages says that’s supported. So once again, like for the nine thousandth time, I’m struggling with wordpress.com. I should move my blog off of this site and host it myself… *sigh*]

Innovations in Web Scraping

I added event descriptions to my Concerts in Oslo a few months back. It mostly worked kinda OK, but it’s using heuristics to find out what “the text” is, so it sometimes includes less-than-useful information.

In particular, those fucking “YES IT KNOW IT”S A FUCKING COOKIE!” texts that all fucking web sites slather their pages with now fucking get in the way, because those texts are often a significant portion of the text on any random page. (Fucking.)

But I added filtering for the those bits, and things looked fine.

Yesterday I was told that all Facebook events are basically nothing but that cookie warning (in Norwegian), and that’s because the Facebook event pages now contain nothing but that text, plus some scaffolding to load the rest as JSON:

To build the Facebook event page, about 85 HTTP calls are done and 6MB worth of data is loaded.

I contemplated reverse-engineering the calls to get the event description via the graphql calls (since Facebook has closed all access to public events via their API), but then it struck me: The browser is showing me all this data, so perhaps I could just point a headless browser towards the site, and then ask it to dump its DOM, and then I can parse that?

Which I’ve now done.

I know, it’s probably a common technique, but I’d just not considered it at all. A mental block of some kind, I guess. I’m so embarrassed. Of course, it now takes 1000x longer to scrape a Facebook event than something that just puts the event descriptions in the HTML, but whatevs. That’s what you have caches for.

I’m using PhantomJS, and it seems to work well (even if development has been discontinued). PhantomJS is so easy and pleasant to work with that I think I’ll try to stick with it until it disappears completely. Is there another headless browser that’s as good? All the other ones I’ve seen are more… enterprisey.

Let It Snow

I wanted to make the Carpenter series of posts look ridiculously romantic, so I got the swashiest font I could find.  But it’s not enough: I wanted to make it snow, too.

Now, this blog is on WordPress.com, which adds limitations to what is easy or even possible to do.  I wanted a CSS-only snowing solution that didn’t involve adding any new HTML elements, and that turns out not to be the common thing to do?  There are approximately five hundred thousand blog articles out there about making web pages snow, but they are either snowing in the background, or is a mess of <div> <div> <div>s to make it snow in front of an image.

Looking at this pretty snowing effect, I wanted to do the same, but by just adding a class: snow to the <a> element already surrounding the <img>s in this blog.

Presto:

This, as anybody who’s done CSS knows, took way too long and went down many blind alleys before I got it to work properly.  (So it’s a good thing I did it while I was on holiday.)  Here’s the CSS I ended up with:

.snow {
  display: inline-block;
  position: relative;
}
.snow::after {
  content: '';
  position: absolute;
  display: block;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
  background-image: url('https://larsmagne23.files.wordpress.com/2017/11/pl2.png'), url('https://larsmagne23.files.wordpress.com/2017/11/pm2.png'), url('https://larsmagne23.files.wordpress.com/2017/11/pm2.png'), url('https://larsmagne23.files.wordpress.com/2017/11/ps2.png'), url('https://larsmagne23.files.wordpress.com/2017/11/ps2.png');
  animation: snow-fall 5s linear infinite;
}
@keyframes snow-fall {
  0% { background-position: 0 0, 0 0, 30px 40px, 0 0, 10px 0;}
  33% { background-position: 0 137px, 0 70px, 45px 100px, 0 30px, 20px 30px; }
  66% { background-position: 0 274px, 0 140px, 35px 200px, 0 60px, 20px 60px; }
  100% { background-position: 0 413px, 0 200px, 30px 240px, 0 100px, 10px 100px; }
}

So: What’s going on here is that I’m adding an :after element to the <a> element, and that element has en empty content, but several background images.  (Five of them, to be precise.)  These images are mostly transparent, but has snowflakes of various sizes and blurrinesses.  In the original version, all these “layers” are of the same size but animated in different speeds so that the closest layer is fastest.  That’s not possible with the :after thing, because there can only be one :after, and therefore only one animation speed.

So instead I chopped the different layer images into different sizes, and then I can animate one from 0px to 100px while I animate a closer, faster layer from 0px to 200px, and so on.  The important thing is that the animations have to be the same sizes as the images, because otherwise you’ll get a shuddering effect when the animations restart.

And then you can do any number of things, like adding some slight wobble and windiness to the scene.

The more layers you add, the more CPU intensive the result will be.  Depending on whether the user’s browser uses hardware acceleration for the CSS animation, of course.  But think of it this way: It makes the computer nice and toasty warm: Perfect for winter.

(One complication to getting this to work on this blog is that I had called the animation “snow”, so the CSS read “animation: snow 5s linear infinite”.  WordPress.com helpfully auto-translated this to “animation: #fffafa 5s linear infinite”.  Presumably because “snow” is a colour name.  And that doesn’t work.  Thank you, WordPress.com.)

So when I grow up, my job is definitely going to be for restaurants that specialise in weddings in December.  I’ve already got the CSS and the font!

Responsive Comics

The other month I was staring at the Diamonds Previews interface that I hacked up last year. Its main purpose is to allow me (and anybody else) to go through the monthly listings rapidly, without all that clicking and stuff.

I was wondering: Has CSS Flexbox technology progressed to the point where the interface could be transformed “responsively” (i.e., via CSS selectors) from the wide design above to something that fits on a cell phone. It would require a completely different layout; shifting from the three column layout with many sub-boxes into a single column where some of the boxes would move up and some down and some become a line of buttons here and and and…

The answer seems to be: Nope. While googling for this stuff, everybody seemed to be saying “just add a div outside the other div and then div it up and then you can sort of move some bits around. If that div is placed before that div”.

CSS still, after 20 years, sucks at layout.

*sigh*

But once I had started tinkering with this, I couldn’t just give up, so I just wrote a bunch of JS to transform the layout, and presto:

So purdy! So UX!

And so I started wondering whether this might make sense as an app, so I wrapped it up in Cordova and shipped it over to Google…

Who rejected it outright because of copyright violations. “But,” I said, “this is like a sales catalogue and isn’t it fair use to show covers in a sales catalogue, man? Man?” And they said “nope; go away”.

While waiting for them to reject the app, I started thinking about… sharing… “Wouldn’t it be nice to make it possible for people to ‘curate’ lists and share these with others?”, so I read up on Firebase and presto: “Curate” button.

Firebase is surprisingly nice, and has a lot of documentation. The main problem is that Firebase covers so many, many use cases that trying to find the correct approach for Goshenite entailed scratching my head for a few hours.

But when the app rejection arrived I just thought, “eh, whatevs”, so it’s a bit lacking in features that are probably not going to be implemented, so it’s more of a toy than anything.

The source code can be found on Github, as usual.

“Concerts in Oslo” App Updated

I took a short holiday to sit in the garden and update the Concerts in Oslo app.  I mainly wanted to make navigation more intuitive by having the “back” button do what you’d expect it to do, but I also wanted to play with the Google Map API and see whether that’s any fun.
And it is.  Results to the right.  I’ve also added a method to list concerts in descending proximity.  You know.  For those days when you’re thinking “I want to go to a concert; I don’t care which one, but it has to be close.  Because I’m too tired to walk far.”
THIS MAKES SENSE!
The Android version is out now; the IOS version will follow once I’ve tested it on the phone I forgot to bring with me.  So a couple of days plus the nine weeks Apple will use to approve the update.
But one can’t post a blog post like this without bitching about Google, can one?  I don’t think so.  First of all, the Google Play Console defaults to the dominant language of the IP address you’re connecting from, which relegates all developers from non-English-speaking countries to third class status: We’re presented with awkwardly translated tech speak that barely made sense in English in the first place.  And it’s impossible to google for any of these messages and errors you’re inevitably presented with to find out what they mean, because all those questions and answers are in English.
And there’s no way to switch to English…  until you notice that the URL itself has a parameter that says “hl=no”, and you can edit that to “hl=en”, and then the interface will behave and become marginally more understandable.
Not very, though: I seem to have pushed an API version of 23, which excludes all pre-version-5 Android users from using the app.  And there seems to be no way to go back to API version 14, SDK 23, which I was using.  Play Console gives me errors, at least, when I try.
*sigh*
I’ll just leave you all with this unrelated screen that Android displays when I plug my phone into the laptop:
If you press “Cancel” here…  is it going to cancel the charging?  Or not?  I’ll leave that as an exercise for the class.

Face Your Problems

I maintain a web site (and a gaggle of apps) that scrape event lists of all the clubs and concert venues in Oslo.  The other day, I was told that it missed a bob hund concert and I was all whaaa?

It turned out that the reason was that Facebook is now blocking all non-logged-in access to their event lists.

Because nobody who has a venue wants anybody but people on Facebook to show up when they have a concert.  I guess that’s what you get when you’re gardening in a walled garden.

This made about a dozen sites disappear off of CSID, so I had to get real and figure out how to deal with the Facebook “Graph” API.  And it turned out to be really easy to work with.  After I read “howto” web sites for half an hour, implementing it was just a matter of connecting app secrets with app IDs with client tokens with access tokens with long-lived access tokens.

It all makes sense.

It’s all on github as usual, but it’s trivial, really.  And I guess it’ll work until Facebook feels like they should cut off more access to the data, whenever they feel like that’ll make more sense for their quarterly outlook.

Blackest Night

Previously: I bought an HDMI OLED screen and determined that its black pixels emitted light.

This made me start wondering: Do all OLED screens emit light from “black” pixels?

So I did the simplest thing possible to test this: I made a little app that displays a black screen. It’s on Google Play and everything. It’s called “Blacker Than Black” if you just want to search for it on your phone.

So I loaded it up on my Blackberry Priv AMOLED (that’s short for “armored led”, I think), and went into the unmentionable room, and took a picture:

OK, that’s kinda… black… let me twiddle the camera settings… er… f2.8… ISO6400… two second exposure…

That’s still very black! Although now the camera can see my fingers in the very, very dim room. Very dim.

OK, let’s test another phone. That’s a Samsung Galaxy S6…  (Which is also AMMO LED.) Very black indeed.

OK, I’m convinced. That SmallHD AC7 OLED screen sucks, but other black OLED screens are blacker than very black.

For kicks, I loaded the app onto my Sony Xperia z4 tablet, which has an IPS screen. And dialed the exposure settings waaaay down.

Yeah. It’s not very black.

Galaxy S6 in front to compare.

So there you have it: The OLED blackness myth… IS CONFIRMED!

Shocking. But that just means that I have to find a different 7″ OLED screen from somebody that makes a better screen, and things will be perfect!

Unfortunately, after googling for an hour or two, that doesn’t seem to exist. There are other OLED screens, and a couple of them even have HDMI, but they’re all really, really ugly, and isn’t really something that I want in my bedroom.

Oh, well. I’ll have to wait a few more years for perfection…