Uru Library Manager (an alternative)

Uru Library Manager (ULM) has become the default way of sharing and downloading user-created content for Uru. It basically handles a list of Ages, and a list of files for each Age with mirrors and checksums.

The main issue with ULM is the fact that it’s written using .NET 2.0. I can’t make it run on Linux.

I finally got around to writing a CLI-based Python script to download Ages from ULM into the current directory.

#! /usr/bin/env python

import pycurl
import StringIO
import sys
import re
import md5
import base64
import os

baseurl = 'http://ulm.hbyte.net/library.php'
ages = None

# We should ignore SIGPIPE when using pycurl.NOSIGNAL - see
# the libcurl tutorial for more info.
try:
    import signal
    from signal import SIGPIPE, SIG_IGN
    signal.signal(signal.SIGPIPE, signal.SIG_IGN)
except ImportError:
    pass

def getAges():
    sio = StringIO.StringIO()

    c = pycurl.Curl()
    c.setopt(c.URL, baseurl + '/LinkingBooks.txt')
    c.setopt(c.HTTPGET, True)
    c.setopt(pycurl.WRITEFUNCTION, sio.write)
    c.setopt(c.VERBOSE, 0)
    c.perform()
    c.close()

    return sio.getvalue().splitlines()

def parseVersion(lines):
    ret = {}
    lncount = 0
    version = None
    i = 0
    while i < len(lines):
        line = lines[i].strip()
        if line is '' or line.isspace():
            i += 1
            lncount += 1
            continue

        m = re.search("(?<=[[]version )\d(?=[]])", line)
        if not m is None:
            if version is None:
                version = int(m.group(0))
            else:
                i = len(lines)
                break
        else:
            (name, value) = line.split(':', 1)
            
            if name.endswith('file'):
                if name in ret:
                    ret[name].append(value)
                else:
                    ret[name] = [value,]
            else:
                ret[name] = value
        i += 1
        lncount += 1
    return (lncount, version, ret)

def parseAge(string):
    ret = {}
    lns = string.splitlines(True)
    i = 0
    while i < len(lns):
        line = lns[i].strip()
        if line is '':
            i += 1
            continue
        
        #print line

        if not line.startswith("[version"):
            try:
                (name, value) = line.split(':', 1)
            except ValueError:
                (name, value) = line.split('=', 1)
            
            ret[name] = value
            i += 1
        else:
            (c, v, r) = parseVersion(lns[i:])
            i += c
            print "We have version %d" % v
            ret[v] = r
    #print ret
    return ret

def progress(download_t, download_d, upload_t, upload_d):
    try:
        if(prog == None): print "We have some issues..."
    except NameError:
        prog = 0.0
        
    if download_t == 0:
        prog += 0.1
        if prog >= 1.0:  prog = 0.0
    else:
        prog = float(download_d) / float(download_t)
    s = int(prog*50)
    r = 50-s
    print "\r[" + "="*s + " "*r + "] %3d%%" % (int(prog*100)),

a = True
while a:
    userIn = raw_input("> ")
    
    if userIn.startswith('quit'):
        a = False
    elif userIn.startswith('help'):
        print "Plasma Content Distributor"
        print "  Darryl 'Paradox' Pogue  "
        print "=========================="
        print "Commands are as follows:"
        print "  help       - print this message"
        print "  quit       - exit the program"
        print "  lib [url]  - change the base library"
        print "  list       - download the list of Ages"
        print "  get [ID]   - download an Age from the Age list"
        print "    ver [ID] - download the specified Age version"
        print "    back     - return to the main prompt"
    elif userIn.startswith('lib '):
        gets = userIn.split(' ')
        if (len(gets) < 2):
            print "You did not provide a library URL"
        else:
            baseurl = gets[1]
    elif userIn.startswith('list'):
        ages = getAges()
        for age in ages:
            if age != '':
                print "[%02d] %s" % (ages.index(age) + 1, age)
    elif userIn.startswith('get '):
        gets = userIn.split(' ')
        if ages is None:
            print "Need a list of Ages! (Try 'list' at the prompt)"
        elif (len(gets)  len(ages)) or (int(gets[1])  maxVer:
                            maxVer = k
            b = True
            while b:
                ageIn = raw_input(">> ")
                
                if ageIn.startswith('back'):
                    b = False
                elif ageIn.startswith('quit'):
                    b = False
                    a = False
                elif ageIn.startswith('help'):
                    print "Plasma Content Distributor"
                    print "  Darryl 'Paradox' Pogue  "
                    print "=========================="
                    print "Commands are as follows:"
                    print "  help     - print this message"
                    print "  quit     - exit the program"
                    print "  ver [ID] - download the specified Age version"
                    print "  back     - return to the main prompt"
                elif ageIn.startswith('ver '):
                    ip = ageIn.split(' ')
                    if (len(ip)  maxVer) or (int(ip[1]) <= 0):
                        print "Invalid selection"
                    else:
                        print "Downloading version %d" % int(ip[1])
                        key = ret[int(ip[1])]
                        mirr = key['mirror']
                        
                        for k in key.iterkeys():
                            if k.endswith('file'):
                                filearr = key[k]
                                for fi in filearr:
                                    (name, md5hash) = fi.split('=', 1)

                                    out = open(name, 'w')
                                    d = pycurl.Curl()
                                    d.setopt(c.URL, mirr + '/' + name)
                                    d.setopt(c.HTTPGET, True)
                                    d.setopt(pycurl.FILE, out);
                                    d.setopt(c.VERBOSE, 0)
                                    d.perform()
                                    d.close()
                                    out.close()
                                    
                                    out = open(name, 'r')
                                    digest = md5.new(out.read()).digest()
                                    out.close()
                                    
                                    if(base64.encodestring(digest).strip() == md5hash):
                                        print "Saved file " + name
                                    else:
                                        print "Checksum hash failure on file " + name
                                        os.remove(name)
                        
                        b = False
                else:
                    print "Unrecognized command!"
    else:
        print "Unrecognized command!"

sys.exit()
Advertisements

One thought on “Uru Library Manager (an alternative)

  1. diafero says:

    Thanks for that script :)
    However, ULM ran great for me on Linux (till I uninstalled it), using wine and installing the .NET Framework 2 in it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s