A wrapper to i3status in go

I ride my bicycle to go to work and one thing is important about it: should I put on my rain clothes? There is a service in France given by MétéoFrance that tells you for most places in France whether it will rain in the next hour.

For every 5 minutes in the next hour, a rectangle is colored whether it will rain and how strong.

Late last week, I wrote a small script in python that uses the API (not public, I just opened Firefox’network page and reverse-engineered it…) to query such piece of information. I made the simple script below where the information is cached in a temporary file and use flock() on it to protect concurrent accesses.

    #!/usr/bin/env python3
    
    import fcntl
    import json
    import os
    import requests
    import sys
    import time
    
    TMP_FILE='/tmp/pluie_dans_lheure.data'
    
    self = sys.argv[0]
    fd = open(self, 'r')
    fcntl.flock(fd, fcntl.LOCK_EX)
    
    def generate_new_file():
        BASE_URL='[REDACTED]'
        CODE='[REDACTED]
        r = requests.get(BASE_URL + CODE)
        assert r.status_code is 200
        j = r.json()['dataCadran']
        esc = chr(27)
        with open(TMP_FILE, 'w') as f:
            for p in d:
                n = p['niveauPluie']
                if n == 1:
                    f.write(u'_')
                elif n == 2:
                    # light
                    f.write(u'')
                elif n == 3:
                    # medium
                    f.write(u'')
                elif n == 4:
                    # dark
                    f.write(u'')
                elif n >= 5:
                    f.write(u'')
    
    try:
        st = os.stat(TMP_FILE)
    except FileNotFoundError:
        generate_new_file()
    else:
        t = time.localtime(st.st_ctime)
        now = time.localtime()
        if t.tm_hour != now.tm_hour or int(now.tm_min/5) != int(t.tm_min/5):
            generate_new_file()
    
    with open(TMP_FILE, 'r') as f:
        print(f.read())

The idea was to get a string of unicode characters representing the next hour and put that in my status bar on i3. That script, even when just reading the file in /tmp, was taking 1.5s. It was to be called it every 5s. That was way too much time for such a simple task.

I wanted to write something in Go for quite some time and decided it was the good opportunity to do it.

On i3status’s manpage, there is an example about prepending the i3status output with a custom command:

    #!/bin/sh
    # shell script to prepend i3status with more stuff
    
    i3status | while :
    do
            read line
            echo "mystuff | $line" || exit 1
    done

I did that but I wanted i3bar to display some colors. To do that, it uses a JSON protocol and thus this small script is not working since it’s not outputting valid JSON.

I wrote the same thing in Go and pushed it on myi3status GitHub’s repository. As expected, it takes about nothing to run but the code is 3 times larger.

Here are some screenshots of it in action, first when there is no incoming rain, then with some:

myi3status with no rain

myi3status with some incoming rain