To celebrate 2013 here is Kukkaisvoima version 15. It adds optional
short URL support, which is described here. Version 15 can be downloaded
here.
For those who are interested the full
source code changes of version 15 can be inspected at github.
Date: 2013-01-01 13:49:45
Added support for animated GIFs to my reddit image viewer Pinkit for Nokia N9.
Here is the full changelog:
Have fun viewing some random nsfw gifs!
p.s. bonus website: Every animated GIF on Wikipedia
Date: 2012-12-12 21:40:54
My favorite XMPP client has been
working really nicely every day for the last couple of years. Since
releasing jj version 1, I have added some minor features and fixed
bugs.
Here is a list of most important changes for jj version 2:
- Support for MUC private messages
- Status information to contact's directory
- More precise time format for output
Writing status information every time contact's status information
changes might use excess amount of disk space. I advice to monitor
jj's disk space usage. Biggest status file found from my jj directory
was only 1.5M, but there might be a problems with some other
setups. There is also option -n to disable status output entirely if
needed.
I am using some tools with my jj setup. I will put those to tools
directory on the jj source code repository. For now there is only
fecho utility. Fecho is a wrapper around echo that prevents blocking
if one of jj's fifos does not read the input right away.
Version 2 of jj can be downloaded from jj's
home page
For those who are interested the full source code
changes of version 2 can be inspected at github.
Date: 2012-11-29 20:23:54
It is nice to have colors in modern Linux shell. Colors in bash
scripts are quite common, but coloring Python script output is just as
easy. Colors in shell are done with ANSI escape
codes. Here is an example code snippet on how to get started with
ANSI colors in Python.
#!/usr/bin/python
import sys
ansi_red = '\033[91m'
ansi_yellow = '\033[93m'
ansi_end = '\033[0m'
def apply_color(msg, color):
if sys.stdout.isatty():
return "%s%s%s" % (color, msg, ansi_end)
return msg
def apply_red(msg):
return apply_color(msg, ansi_red)
def apply_yellow(msg):
return apply_color(msg, ansi_yellow)
print "%s roses and %s submarine." % (apply_red("Red"), apply_yellow("yellow"))
Function apply_color does some minor sanity checking, so that when
redirecting output to file it will not insert the ANSI escape codes
there.
Date: 2012-11-01 22:27:51
I am adding short URLs for Kukkaisvoima. Every blog entry will have
an unique [1] five or six character base62 [2] encoded URL. Actually
crc32 checksum does not guarantee uniqueness, but since it is
calculated from the entry filename, one can always rename the entry
file, if collision should happen (not very likely). I will enable it
here while developing, so URLS will change to shorter ones (RSS feed
spam possible).
[1] calculated with crc32
checksum
[2] base64
without + and /
Date: 2012-10-06 23:23:00
Since upgrading Debian left me with broken X, I tried to use Ubuntu
for couple of days. I have to confess that Unity is a nice piece of
software. On Debian I have nice setup with awesome window manager
(framework!) that displays line of text on the panel. I wanted to
have the same on functionality with Unity. It was not that hard.
I wrote a small Python program that executes command every 37
seconds, reads that commands output and puts that on the Unity
panel. Simple task. The actual output generated by the command is more
complicated, since it displays my next calendar entry, near by weather
from the Finnish weather service and couple of mailboxes. I am not
going to describe its inner logic in detail here. But basically the
Python program is the applet
Here is the Python applet.
#!/usr/bin/env python
import sys
import gtk
import appindicator
import subprocess
PING_FREQUENCY = 37 # seconds
class PetteriApplet:
def __init__(self):
self.ind = appindicator.Indicator("petteri",
"petteri",
appindicator.CATEGORY_APPLICATION_STATUS)
self.ind.set_label("petteri")
self.ind.set_status(appindicator.STATUS_ACTIVE)
self.ind.set_attention_icon("new-messages-red")
self.menu_setup()
self.ind.set_menu(self.menu)
def menu_setup(self):
self.menu = gtk.Menu()
self.quit_item = gtk.MenuItem("Quit")
self.quit_item.connect("activate", self.quit)
self.quit_item.show()
self.menu.append(self.quit_item)
def main(self):
self.check_line()
gtk.timeout_add(PING_FREQUENCY * 1000, self.check_line)
gtk.main()
def quit(self, widget):
sys.exit(0)
def check_line(self):
line = subprocess.check_output(["/home/petteri/bin/combine"])
self.ind.set_label(line.strip())
return True
if __name__ == "__main__":
indicator = PetteriApplet()
indicator.main()
After the Python program was finished I created
~/.config/autostart/petteri-applet.desktop file with the following
content:
[Desktop Entry]
Name=Petteri
Comment=Show string in panel
Icon=Petteri
Exec=/home/petteri/bin/petteri-applet
Terminal=false
Type=Application
NoDisplay=true
NotShowIn=KDE;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=NetworkManager
X-GNOME-Bugzilla-Component=general
X-GNOME-Autostart-enabled=true
X-Ubuntu-Gettext-Domain=petteri-applet
The .desktop dictates that every time I start Unity the Python
applet (/home/petteri/bin/petteri-applet) will be also started. Works
nicely
Date: 2012-09-30 18:28:48
Some time ago I wrote superb Jabber/XMPP
client based on the ideas of even more superb IRC client ii. I named the client jj and put the source code to github. Since
then me and my friends have been using jj for our Jabber MUC
(multiuser chat room, something like channel in IRC). And it has been
serving us nicely.
Our jj bot resolves URL titles and aggregates Twitter, Google Plus
and some RSS feeds to our MUC. The process how this is done is quite
easy. Jj has outfile and input FIFO for each channel it sits on. The
bot functionality can be distinguished into two different tasks: 1)
reacting to input and 2) cron jobs:
URL resolving is done by reacting to what input is coming
in. There is one shell script that listens our mucs outfile with
inotify. When it gets notified that something is said on the MUC it
will inspect the line. If it finds URL on that line, it will call the
title resolver and write the resolved title to the MUC in file.
Here is pseudo bash for it (external tools fecho and gettitle.py
are used), note also that I divided the long greps to multiple lines
without testing the code:
nickname="botbot"
outfile="jabber.tld/mucs/conf@conference.jabber.tld/out"
infile="jabber.tld/mucs/conf@conference.jabber.tld/in"
while true; do
inotifywait -e modify $outfile
line=$(tail -1 "$outfile" |\
grep -v "^[0-9][0-9][0-9][0-9]\-[0-9][0-9]\-[0-9][0-9]\
[0-9][0-9]:[0-9][0-99][0-9] <$nickname>" |\
grep "^[0-9][0-9]"|\
grep -v "[0-9] -\!-" |\
tac|\
grep -m 1 -i -E "https?://")
if [ ! -z "$line" ]; then
url=$(echo "$line"| grep -o -i -E "https?://.*" | cut -d" " -f1)
title=$(echo "$url" | gettitle.py)
fecho "$title" $infile
fi
done
Basically this can be used for any kind of reaction tasks. For
example for the classic sed like line "s/from/to".
- Feeds (Twitter, Google Plus, RSS etc.) are done with cron
jobs. Here is pseudo bash example for that (it uses external tools
feedcheck and fecho):
feedlist=$(cat <<EOF
http://twitter.com/statuses/user_timeline/petteri_.rss
http://github.com/petteri.atom
http://23.fi/blogi/feed
EOF
)
# Set IFS to newline only. See BASH(1) manpage for details on IFS.
IFS=$'\n'
for feed in $feedlist; do
for x in $(feedcheck $feed); do
fecho "$x" jabber.tld/mucs/conf@conference.jabber.tld/in
sleep 5
done
done
Sadly I had to write the external tools fecho, gettitle.py and
feedcheck, since there we no proper ones available. Fecho is already
in jj source code repository, but the other ones are not yet. For fecho
source see here.
Hopefully these examples will illustrate how to make jj bots. I
will try to polish the instructions later and add these to jj source
code repository as examples.
Date: 2012-07-13 14:13:28