茶蜂 danger: high entropy

On Code

A script for keeping go up to date on Linux

I use the following script to keep go up to date on my local machine without using a package manager. This is by no means elegant or efficient, but it gets the job done. It finds the current version of go by scraping the go.dev website with a very naive match, and then plops the resulting tarball onto my filesystem.

Raw link: getgoer.sh

#!/bin/zsh

## Usage:
## getgoer [install]
## getgoer alone will output the current and remote versions
## getgoer install will upgrade if the current vesrsion is different than the remote version

arch="linux-amd64"

function getLinks() {
    curl https://go.dev/dl/ 2>/dev/null | awk '/download downloadBox(.*)/ {match($0, /href="(\/dl\/go([0-9]+\.[0-9]+\.[0-9]+)\.([^.]+)\..+)"/, arr); print arr[1]}'
}

links=$(getLinks)

function remoteVersion() {
    echo $links | awk -v arch="${arch}" '$0~arch {match($1, /\/dl\/go([0-9]+\.[0-9]+\.[0-9]+)/, arr); print arr[1]}'
}

function installedVersion() {
    go version | awk '{match($0, /go([0-9]+\.[0-9]+\.[0-9]+)/, arr); print arr[1]}'
}

function checkVersion() {
    [[ "$(remoteVersion)" == "$(installedVersion)" ]]
    return
}

function getDownloadLink() {
    echo "https://go.dev$(echo $links | awk -v arch="${arch}" '$0~arch {print $1}')"
}

function upgrade() {
    if checkVersion; then
        echo "Current version $(installedVersion) is the same as upstream. Not doing anything"
        return
    fi
    echo "current version is $(installedVersion). Downloading new version $(remoteVersion)."
    fpath=/usr/local
    sudo rm -r "${fpath}/go"
    curl -L $(getDownloadLink) 2>/dev/null | sudo tar -C $fpath -vxz
}

if [[ "${1}" == "install" ]]; then
    upgrade
else
    echo "Current version: $(installedVersion)\nRemote version:  $(remoteVersion)\nDownload link:   $(getDownloadLink)"
    checkVersion
fi

Unmarshalling a Unix timestamp to time.Time from JSON in go

Sometimes when working with remote APIs, you will come across dates formatted as Unix timestamps (an integer number of seconds since the epoch1). Go has a very nice native type for dealing with times, though, and it would be nice to be able to directly unmarshal2 to that type without doing the type conversions later. Fortunately, we can do easily do this by overriding the UnmarshalJSON method.

To do this, we will create a custom type that embeds time.Time:

Go For a Loop

Go, like many languages, has a for loop. The snippet below can help to understand the versatility of these loops. This mechanism goes well beyond simply counting integers, but can be used to implement any number of looping patterns. The important thing to remember is that the second expression in the for loop definition controls the loop, and can be used with any function or method that returns a bool, or any expression that evaluates to a bool. Also remember that the three expressions are all optional1.

Attaching StringIO Data to a Mailgun Message

Recently I started using Mailgun for our outgoing messages. They have a very nice API, and take a lot of the heavy lifting out of creating multipart messages.

If you are using requests (or treq) to send the messages through their REST API, however, you may have noticed that you must specify “attachment” as the key, and an open file handle as the value. This works great if you are sending files from the filesystem, but if you need to send generated or in memory data as a file attachment, it just doesn’t work. Adding a name attribute to the StringIO class does the trick:

A Picture is worth how many words?

i was playing around with some imaging code, and started wondering what it would look like to create some images out of text. I have worked with stenography in the past, but this time I didn’t want to hide the text, I wanted to pack the image with it.

First things first, I need some text. Time to turn to trusty Project Gutenberg. I will be using the text of Moby Dick for this project.