Month: December 2022

A year of things not working out

Including working out. If only I was joking.

a foggy forest with trees on a hill

Supercharged OAuth scopes with reitit

You might be familiar with OAuth scopes from for example the Github dialog for creating a new access token. You get to choose what the token is authorized to do: can the user manage repos? Leave reviews? Push commits? There are a ton of options. Similarly Mastodon has scopes such as “see favorites” or “post on your behalf.”

padlock on black metal fence

Redis sorted sets are cool

I first saw Redis sorted sets in action reading Mastodon’s source code. Sorted sets are used to store feeds (ignore that ZREVRANGEBYSCORE is deprecated). In a use-case such as Mastodon feeds (timelines), sorted sets come handy because you can “just” add new elements and Redis will take care of the sorting.

variety of fruits displayed on wooden shelf

Configuring MPV

I used VLC for a very long time. No longer. The other day I was watching something and I noticed how dull the colors were. It did fit the theme of the video though so I just assumed that it was a thing, except then I ran into a very colorful screenshot from the same video. What gives? In 2011, when fansubbing was huge, 10bit was the “new big thing.” It encodes colors into 10 bits into the standard 8, which results in much better colors. At least it should, as it seems VLC wasn’t able to handle that.

Example of 10bit difference

Server-side rendering a ClojureScript app with Deno

タイトルは英語のままなのは、日本語にしようとしても結局全部カタカナになるので放置。さてre-frameは俺的にClojureScriptでウェブのフロントエンド作るにあたって標準装備になっているが、ものによっては完全動的に生成されるReactのアプリよりも、検索エンジンなどでも絶対拾える静的HTMLを返した方がいいという場合もある。今回は流行り言葉をいっぱい使えるように、Denoを活かしてClojureScriptアプリのサーバーサイドレンダリングを実現しようと思います。動くコードはGithubにて


Frontend/backend shared routing with reitit

Commonly frontend and backend are separate beasts. Backend written in Ruby using Rails for example, its routing written in its own DSL. Frontend written in TypeScript using Vue.js for example, its routing written in its own DSL. Of course the frontend will call some backend endpoints, so it should definitely know about those backend endpoints too, while there may be some frontend “paths” that don’t correspond to any single API endpoint, yet you might want to generate absolute URLs for those pages on the backend. This results in a nasty mess and duplication of routing and adjacent logic.

asphalt road between trees

Elasticsearch aggregation to find most popular tags over time

Finding popular keywords or tags is what twitter’s trends are (other than a means to manipulate public opinion and introduce artificial trends by paying good cash). While I think having a “trends” feature tends to introduce more problems than the value it provides for discovery, I wanted to figure out how I’d do it before deciding not to.


Suunto 9 Baro first impressions

I wrote about how I was considering getting a new watch, and a while back I actually put that into action and got a Suunto 9 Baro. I wanted to try something not Garmin to have a more reliable point of view.

Getting the Suunto 9 Baro up and running wasn’t hard, but it wasn’t seamless either. I paired the device with my phone before installing the Suunto app, after which the app wasn’t able to “pair” with it. I had to unpair the smartwatch once and redo it from the app. Weird stuff.

It’s a very different beast from the Garmin Instinct. First of all, it’s much bigger, but I don’t think it’s too heavy or so big as to get in the way. It’s a full-fledged smartwatch with a touchscreen, so my first thing to do was to get a protective film so the glass doesn’t get all scratchy and/or smudgy. It also means that it can show notifications and stuff, which can get pretty noisy if there are too many. Of course it can be configured, but it has to be configured.


Dealing with circular dependencies in Clojure

While working on stuff (of course in Clojure), I kept running into problems with namespaces having circular dependencies. For example I’d have an app.router namespace that defines the, uh, routes. I’d have an app.url namespace that contains helper functions to generate absolute URLs based on route data (so it depends on app.router). I’d have an app.views namespace that uses those URL helpers (thus depending on app.url), and these views would be referenced in the routes so app.router would require app.views.

This completes the dependency circle and is the beginning of my journey. There are a bunch of ways to deal with circular dependencies in Clojure, but I won’t go in-depth about all of them.

timelapse photography of fire

A way to extract an image from Firefox

The problem I faced: I was scrolling through a hashtag‘s timeline in Tweetdeck, when I spotted a nice image. I wanted to retweet it, but that failed: turns out the tweet was deleted in the meanwhile. This usually means that either the artist themselves deleted the tweet for some reason, or it was stolen in the first place and (by some miracle) it was moderated.

In this case it seems to have been the latter, so finding the image through the author’s profile was not an option. As Tweetdeck displays images as CSS backgrounds in the timeline, right-click “Open image in new tab” was not an option. Since the tweet was deleted, its URL was invalidated too, so I couldn’t give that to Saucenao or similar to find matches either.

However, while digging through the Firefox Dev Tools, I noticed that the context menu when right clicking the URL of the background-image had an item “Copy image data URL”. This turned out to be just what I needed.

Pasting the copied (data blob) URL to the address bar I got the image that I could magnify so that I could decipher the artist’s signature on it. (It turned out to have been a partial image so Saucenao couldn’t help either.) After a few tries I found the artist’s profile and there the original post. Yay.