List Unfinished Tasks in Moodle (ucilnica.*.uni-lj.si)

If you hate Moodle, often miss homework deadlines or if you're constantly checking if there are any tasks you haven't finished, this is just the thing for you! :)

After installing, just type "todo" in your terminal, and your unfinished tasks will be listed for you.

Example output moodle-todo

Source: https://github.com/hamax/moodle-todo

Quick start:

  • install Python - Beautiful Soup (>= 3.1)
  • download one and only source file: https://github.com/hamax/moodle-todo/raw/master/todo.py
  • set your username and password in todo.py (or make a config file ~/.moodle-todo.conf)
  • (optional) add it to PATH (I recommend making a link in /usr/bin)
  • run it

Surviving without Apache (with Nginx, mod_wsgi and php-cgi)

This tutorial is very simple, anyone with basic understanding of linux should be able to get it up and running. (this blog and everything else on hamsworld.net is running on this configuration)

Side note: If you don't want to compile nginx and/or want a more stable solution consider gunicorn.

  1. Download nginx and mod_wsgi from the web and extract them
    wget http://nginx.org/download/nginx-0.8.53.tar.gz
    whet http://bitbucket.org/lifeeth/mod_wsgi/get/6975f0ec7eeb.gz
    tar xvzf nginx-0.8.53.tar.gz 6975f0ec7eeb.gz
    
  2. Make sure there are folders nginx-0.8.53 and mod_wsgi
  3. Install nginx (you will need gcc, libssl-dev and libpcre3-dev packages installed, you can just apt-get install them)
    cd nginx-0.8.53
    ./configure --sbin-path=/usr/sbin --conf-path=/etc/nginx/nginx.conf --add-module=../mod_wsgi/ --with-debug
    make
    sudo make install
    cd ..
    
  4. Install mod_wsgi
    cd mod_wsgi
    sudo python setup.py install --sbin-path=/usr/sbin --conf-path=/etc/nginx
    cd ..
    
  5. Configure nginx Go to /etc/nginx/ and create a directory sites or something like that for per virtual server configs and then edit your nginx.conf to something like that:
    user    www-data;
    worker_processes  1;
    events {
        worker_connections  1024;
    }
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        #tcp_nopush     on;
        #keepalive_timeout  0;
        keepalive_timeout  65;
        tcp_nodelay        on;
        #gzip  on;
        wsgi_python_optimize 0;
        #wsgi_python_executable /usr/bin/python;
        #wsgi_python_home /usr/;
        wsgi_enable_subinterpreters on;
        include /etc/nginx/sites/*;
    }
    
  6. If you need php, follow this few simple steps to get php-cgi up and running (skip "Install nginx" and test): http://davidwinter.me/articles/2009/06/13/php-and-nginx-the-easy-way/
  7. Now all that is left are per-site configurations. For every site create a file in /etc/nginx/sites/ and paste something like that in it:

Django or other wsgi (you'll need django.wsgi file from here http://docs.djangoproject.com/en/1.2/howto/deployment/modwsgi/):

server {
    listen       80;
    server_name  www.example.com; #change this
    location /media/ {
        root   /path/to/django/project/; #change this; without media at the end
    }
    location / {
        wsgi_pass /path/to/django/project/django.wsgi; #change this
        include wsgi_vars;
        wsgi_pass_authorization off;
        wsgi_script_reloading on;
        wsgi_use_main_interpreter on;
    }
}
Wordpress:
server {
    listen 80;
    server_name www.example.com; #change this
    root /path/to/wordpress/; #change this
    index index.php;
    try_files $uri $uri/ /index.php?q=$uri&$args;
    location ~ .php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

Other PHP: Same as wordpress, just delete the try_files if you don't want it (it redirects everything that doesn't exist to index).

IRC Scripts and Bots and stuff and things

Some neat IRC stuff that I made during this weekend:

XChat script, that lowercases "caps-lock retard" messages: ShikiScript

You can place it in ~/.xchat2/ for automatic loading on every start or just load it with the xchat GUI: Window -> Plugins and Scripts

Modules for pyfibot - IRC bot written in python:

  • module_joke: gets a random joke (.joke)
  • module_wiki: does a google search (.search/.s - they are not the same thing) or displays the first paragraph of wiki article (.wiki/.w - they are the same thing)

If you want to see it in action, you can join #hamsworld@irc.freenode.net:8001 (you can use this webchat).

APE-Project How To: Build Server-Side Module in C to use with Javascript

Building a server-side javascript module is documented here, while building server-side modules in C is considered deprecated or at least not the best idea (it is not documented at all!). Programing in javascript is all fancy and stuff, but what are you supposed to do if you need Postgres, Memcached or something like that? For C (and C++) there is tons of libraries available, APE-Project is based on C, so maybe we could do something about that.

We are going to make a javascript (mootools) class in C, like for example mysql class that is already there. For this example I'm going to create "Memcached" class.

First we need some structures:

struct _ape_memcached_data {
    memcached_st server;
    JSObject jsmemcached;
    JSContext *cx;
};
static JSClass memcached_class = {
    "Memcached", JSCLASS_HAS_PRIVATE,
        JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
        JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
        JSCLASS_NO_OPTIONAL_MEMBERS
};
static JSFunctionSpec apememcached_funcs[] = {
    JS_FS("get", apememcached_sm_get, 2, 0, 0),
    JS_FS_END
};
static JSFunctionSpec apememcached_funcs_static[] = {
    JS_FS_END
};

We also need the actual functions that are going to be called from javascript:

APE_JS_NATIVE(ape_sm_memcached_constructor)
//{
    char host;
    int port;
    struct _ape_memcached_data myhandle;
    if (!JS_ConvertArguments(cx, argc, argv, "si", &host, &port)) {
        return JS_TRUE;
    }
    myhandle = xmalloc(sizeof(myhandle));
    memcached_st server = memcached_create(NULL);
    memcached_server_add (server, host, port);
    myhandle->server = server;
    myhandle->jsmemcached = obj;
    myhandle->cx = cx;
    JS_SetPrivate(cx, obj, myhandle);
    return JS_TRUE;
}
APE_JS_NATIVE(apememcached_sm_get)
//{
    JSString query;
    struct _ape_memcached_data myhandle;
    jsval callback;
    if ((myhandle = JS_GetPrivate(cx, obj)) == NULL) {
        return JS_TRUE;
    }
    if (!JS_ConvertArguments(cx, 1, argv, "S", &query)) {
        return JS_TRUE;
    }
    size_t value_length;
    uint32_t flags;
    memcached_return_t error;
    char value = memcached_get(myhandle->server, JS_GetStringBytes(query), JS_GetStringLength(query), &value_length, &flags, &error);
    rval = STRING_TO_JSVAL(JS_NewStringCopyN(cx, value, value_length));
    free(value);
    return JS_TRUE;
}

Finally, we need to link this together. You need to find function called "ape_sm_define_ape" and add this:

JSObject *jsmemcached;
jsmemcached = JS_InitClass(asc->cx, obj, NULL, &memcached_class, ape_sm_memcached_constructor, 2, NULL, NULL, NULL, apememcached_funcs_static);
JS_DefineFunctions(asc->cx, jsmemcached, apememcached_funcs);

In your javascript code, you can use the newly created class like this:

var cache = new Ape.Memcached("localhost", 11211);
cache.get('test');

Thats all, I'm sorry for the lack of explanation.

Reboot to Windows shortcut for Ubuntu 9.10+ (Grub 2)

If you're dual booting Ubuntu and Windows, a simple shortcut "reboot to windows" might come in handy, so you don't have to stare at the screen waiting for the boot loader to show up.

This shortcut sets Windows as default grub option only for one reboot, so next time you start up the pc or reboot it from windows the default is back to Ubuntu.

Step By Step:

  1. List item
  2. Open terminal (Applications -> Accessories -> Terminal)
  3. Type "sudo gedit /etc/default/grub" and hit return
  4. Change "GRUB_DEFAULT=0" (or whatever the value is) to "GRUB_DEFAULT=saved" (you might also want to lower the GRUB_TIMEOUT value)
  5. Save & Close gedit
  6. Type "gedit ~/win-reboot.sh" and paste the following code into gedit (change "Windows 7 (loader) (on /dev/sda1)"  to the name or number of your Windows option in grub, you can check that by serching for windows keyword in /boot/grub/grub.cfg)
    #!/bin/bash
    grub-reboot "Windows 7 (loader) (on /dev/sda1)"
    reboot
    
  7. Save & close gedit
  8. Type "chmod +x ~/win-reboot.sh" to allow execution of this file
  9. Type "sudo update-grub" to apply changes to grub configuration
  10. Type exit or hit Ctrl+D to close the terminal

If you are using Gnome (default Ubuntu desktop) you can proceed to create the shortcut, but ~/win-reboot.sh should work already.

  1. Right click on a gnome panel and select "Add to panel"
  2. Select "Custom Application Launcher" and click "Add"
  3. Fill out the form like this (replace "/home/ziga/" with your home directory, you can find that out by opening terminal and typing "cd;pwd"):

    Launcher properties

  4. Click the shortcut, type your password and let it work

Please comment if you encounter any problems or have any additional questions.

EDIT (Thanks to Arttu): added update-grub step and changed the script to use grub-reboot

Replacing LCD on Asus Eee 1000H

Yeah, I broke my eee's LCD panel.

I've ordered one from ebay two weeks ago and got it today. They've charged me extra 17€ for vat and some other unknown expenses. But anyway, here it is:

New display

Next step, of course, is to disassemble eee immediately!

Disassembled eee

kaboom

PCB

motherboard (PCB MADE IN CHINA)

Throw the old lcd away, connect the new one... and...

Lid doesn't fit

this lid is too small!

Lid does fit

false alarm :)

And thats all. Pretty simple. Just connect the keyboard back with fancy connectors, screw back some screws...

Assembled eee

whoa, looks like eee again (got the keyboard working in the 2nd try). Now I only hope that this one will stay in one piece for a while (current record is less than 1 year).