Here are various things I’ve found over time that aren’t obvious, or that aren’t found anywhere else online. It’s a list of things that are too small to merit their own post (and bugging people about), but they took me long enough to figure out that I want to save the next person the time.

The items in this list aren’t easy to be notified about, but it doesn’t really matter, because they’re things you won’t care about unless you search for them. Hopefully, when you do, Google will be kind enough to point you here.


Automatically use CloudFlare’s HTTP/2 Push with Django

Since CloudFlare supports an easy way of using HTTP/2 Push, I figured I’d write a quick middleware function to automatically push all static media on a page to the client.

How to properly level your 3D printer

If you’re having adhesion issues with your 3D printer, I have an illustrated guide on what the filament should look like on the bed.

How to make minidlna rescan your media reliably

Do you have minidlna scanning a directory of… uh… completely legally downloaded media, and you’re seeing new subdirectories but they don’t have any files in them? This is for you.

MicroPython Ultrasonic Sensor code

This is some code you can use for the HC-SR04 sensor with MicroPython, adapted from this GitHub repository:

from utime import sleep_us
from machine import Pin, time_pulse_us

class Ultrasonic:
    def __init__(self, tPin, ePin):
        # Init trigger pin (out)
        self.trigger = Pin(tPin, Pin.OUT)

        # Init echo pin (in)
        self.echo = Pin(ePin, Pin.IN)

    def distance_in_cm(self):
        # Send a 10us pulse.

            time = time_pulse_us(self.echo, 1, 29000)
        except OSError:
            return None

        # Calc the duration of the recieved pulse, divide the result by
        # 2 (round-trip) and divide it by 29 (the speed of sound is
        # 340 m/s and that is 29 us/cm).
        dist_in_cm = (time / 2.0) / 29

        return dist_in_cm

Fixing GPG’s stub keys

I have a Yubikey and imported my GPG keys onto it, but then my computer wouldn’t let me sign without the Yubikey any more. It would give me things like:

gpg: public key decryption failed: Card error
gpg: decryption failed: No secret key


gpg: deleting secret subkey failed: Not possible with a card based key

When I was trying to delete it and reimport it from a backup. The only thing that worked is something mentioned in the mailing list, namely deleting my private key from the /.gnupg/private-keys-v1.d directory.

The way I found which one it was was that I ran:

grep shadowed *

and the key stub that had been moved on the smart card (Yubikey) was the one that matched. I deleted that one and reimported it and now it works fine.

Turn Django models into dictionaries

Here’s a mixin that adds an as_dict method that will try to convert a model into a dictionary:

class ModelSerializationMixin(object):
    def as_dict(self, fields=None, exclude=None):
        Return this model as a dictionary, replacing ForeignKey values with
        their pks.

        fields - The fields to return. If omitted, returns all fields (minus
        exclude - The fields to return. If omitted, returns the fields from
        data = {}
        for field in self._meta.fields:
            if exclude and in exclude:

            if fields is not None and not in fields:

            if hasattr(field, "get_foreign_related_value"):
                # If the field is a FK or such, get the foreign ID.
                value = field.get_foreign_related_value(self)[0]
                value = getattr(self,
            data[] = value
        return data

Inherit from it and call as_dict() on your instance:

class MyModel(models.Model, ModelSerializationMixin):
    my_field = models.CharField(max_length=100)
    my_fk = models.ForeignKey(OtherModel)

>>> mymodel_instance.as_dict()
{"my_field": "test", "my_fk": 4}

Migrate your TOTP codes from FreeOTP to andOTP

I recently discovered the fantastic andOTP Android app for storing TOTP codes, and I wanted to migrate my codes from FreeOTP, so I wrote a short script for it.

Migrate Namecheap’s DNS record to Cloudflare using Terraform

I needed to migrate from Namecheap’s DNS to Cloudflare’s, as I like it more, it propagates faster and Terraform supports it natively. The following script will talk to Namecheap’s API and print all your records in a Terraform-compatible format.

#!/usr/bin/env python

import random
import string
import sys
from collections import OrderedDict

from namecheap import Api

def random_id():
    return "".join([random.choice(string.ascii_lowercase) for _ in range(8)])

def main():
    if len(sys.argv) != 2:
        print("Usage:\n <domain>")

    username = input("Enter your Namecheap username: ")
    api_key = input("Enter your Namecheap API key: ")
    api = Api(username, api_key, username, "", sandbox=False, debug=False)

    records = api.domains_dns_getHosts(sys.argv[1])

    for record in records:
        info = OrderedDict()

        info["domain"] = "${var.domain}"
        info["proxied"] = "false"
        info["type"] = record["Type"]
        info["name"] = record["Name"]
        info["value"] = record["Address"].rstrip(".")

        if info["type"] == "MX":
            info["priority"] = record["MXPref"]

        fields = "\n".join(["    %s = \"%s\"" % (key, value) for key, value in info.items()])

        entry = """resource "cloudflare_record" "%s" {\n%s\n}\n""" % (random_id(), fields)

if __name__ == "__main__":