Jump to content


Photo

XKCD update/Server Error


  • Please log in to reply
8 replies to this topic

#1 Sengian

Sengian

    Member

  • Members
  • PipPip
  • 28 posts

Posted 12 October 2012 - 09:04 PM

Hello,
I am trying to update the XKCD plugin. I did it ok using the old structure, but I ran in timeout problems due to the large amount of pictures.
So I decided to rewrite it using the object structure. Here is the code:
from urlparse import urljoin
from math import ceil

NAME    = 'xkcd'
PLUGIN_PREFIX   = '/photos/xkcd'
ART      = 'art-default.jpg'
ICON     = 'icon-default.png'
NB_IMAGES = 200
CACHE_1YEAR = 365 * CACHE_1DAY
####################################################################################################
def Start():
    Plugin.AddViewGroup("List", viewMode="List", mediaType="items")
    Plugin.AddViewGroup("Pictures", viewMode="Pictures", mediaType="photos")

    # Set the default ObjectContainer attributes
    ObjectContainer.art = R(ART)
    ObjectContainer.title1 = NAME
    ObjectContainer.view_group = "List"

    # Default icons for DirectoryObject
    DirectoryObject.thumb = R(ICON)
    DirectoryObject.art = R(ART)

    # Set the default cache time
    HTTP.CacheTime = CACHE_1HOUR

####################################################################################################
@handler(PLUGIN_PREFIX, NAME, art = ART, thumb = ICON)
def XKCDMenu():
    archiveURL = 'http://xkcd.com/archive/'
    archiveXPath = '//div[@id="middleContainer"]/a'
    
    oc = ObjectContainer()
    # Get all the elements needed to determine the number of entries and how to sectionize them
    StripsMainPage = HTML.ElementFromURL(archiveURL).xpath(archiveXPath)
    StripsList = [(comic.text, urljoin(archiveURL, comic.get('href'))) for comic in StripsMainPage]
    StripsList.reverse()

    if len(StripsList) < NB_IMAGES:
        #will never happen but will be implemented later on
        pass
    else:
        #Create subdirectories containing a fixed number of images
        nbdir = ceil(float(len(StripsList))/NB_IMAGES)
        for i in xrange(1,nbdir+1):
            firstelt = (i-1)*NB_IMAGES
            lastelt = i*NB_IMAGES
            refs = StripsList[firstelt:lastelt]
            if i == nbdir:
                refs = StripsList[firstelt:]
                lastelt = len(StripsList)
            name = '%d - %d' % (firstelt+1, lastelt)
            img = GetDirectoryIcon(StripsList[firstelt])
            oc.add(DirectoryObject(key = Callback(StripDirectory, id = i, stripsdata = refs), title = name, thumb = img))
    return oc

####################################################################################################
@route('%s/dir-{id}' % PLUGIN_PREFIX, method='POST')
def StripDirectory(id, stripsdata, sender = None):
    imgXpath = '//div[@id="comic"]//img'
    # oc = ObjectContainer(view_group = 'Pictures')
    oc = ObjectContainer(view_group = 'List')

    for (title,comicURL) in stripsdata:
        imgs = HTML.ElementFromURL(comicURL, cacheTime=CACHE_1YEAR).xpath(imgXpath)
        if len(imgs):
            img = imgs[0].get('src')
            resume = imgs[0].get('title')
            oc.add(PhotoObject(url=img, title=title, thumb=img, summary=resume))
    return oc

####################################################################################################
def GetDirectoryIcon(stripdata):
    imgXpath = '//div[@id="comic"]//img'
    imgs = HTML.ElementFromURL(stripdata[1], cacheTime=CACHE_1YEAR).xpath(imgXpath)
    img = R(ICON)
    if len(imgs):
        img = imgs[0].get('src')
    return img

It is in fact quite simple. My problem is that when I introduce the line to add the photoobject, I run into an internal server error:

2012-10-12 22:46:58,453 (1f88) : INFO (core:336) - Starting framework core - Version: 2.2.1.3, Build: 437c0ba (Wed Sep 05 20:31:40 UTC 2012)
2012-10-12 22:46:58,453 (1f88) : DEBUG (core:348) - Using the standard policy
2012-10-12 22:46:58,453 (1f88) : DEBUG (core:437) - Starting runtime component.
2012-10-12 22:46:58,456 (1f88) : DEBUG (core:437) - Starting caching component.
2012-10-12 22:46:58,457 (1f88) : DEBUG (core:437) - Starting data component.
2012-10-12 22:46:58,457 (1f88) : DEBUG (core:437) - Starting networking component.
2012-10-12 22:46:58,457 (1f88) : DEBUG (networking:306) - Loaded HTTP cookies
2012-10-12 22:46:58,477 (1f88) : DEBUG (networking:492) - Setting the default network timeout to 20.0
2012-10-12 22:46:58,477 (1f88) : DEBUG (core:437) - Starting localization component.
2012-10-12 22:46:58,479 (1f88) : INFO (localization:408) - Setting the default locale to en-us
2012-10-12 22:46:58,479 (1f88) : DEBUG (core:437) - Starting messaging component.
2012-10-12 22:46:58,480 (1f88) : DEBUG (core:437) - Starting debugging component.
2012-10-12 22:46:58,480 (1c0c) : DEBUG (networking:160) - Requesting 'http://127.0.0.1:324...pp.plugins.xkcd'
2012-10-12 22:46:58,480 (1f88) : DEBUG (core:437) - Starting services component.
2012-10-12 22:46:58,480 (1f88) : DEBUG (core:437) - Starting myplex component.
2012-10-12 22:46:58,482 (1f88) : DEBUG (core:437) - Starting notifications component.
2012-10-12 22:46:58,578 (1f88) : DEBUG (accessor:68) - Creating a new model access point for provider com.plexapp.plugins.xkcd in namespace 'metadata'
2012-10-12 22:46:58,586 (1f88) : DEBUG (runtime:1036) - Created a thread named 'load_all_services'
2012-10-12 22:46:58,586 (1fb4) : DEBUG (services:263) - Plug-in is not daemonized - loading services from system
2012-10-12 22:46:58,588 (1f88) : DEBUG (runtime:1036) - Created a thread named 'get_server_info'
2012-10-12 22:46:58,588 (e2c) : DEBUG (networking:160) - Requesting 'http://127.0.0.1:32400'
2012-10-12 22:46:58,589 (1fb4) : DEBUG (networking:160) - Requesting 'http://127.0.0.1:324...mRpY3QKMApyMAo_'
2012-10-12 22:46:58,589 (1f88) : DEBUG (core:149) - Finished starting framework core
2012-10-12 22:46:58,591 (1f88) : DEBUG (core:547) - Loading plug-in code
2012-10-12 22:46:58,598 (e2c) : DEBUG (core:525) - Machine identifier is 22520e1d0b5e0509ab5507a66b6777d3e9bacf1c
2012-10-12 22:46:58,598 (e2c) : DEBUG (core:526) - Server version is 0.9.6.9-8fd9c6a
2012-10-12 22:46:58,617 (1f88) : DEBUG (core:553) - Finished loading plug-in code
2012-10-12 22:46:58,618 (1f88) : DEBUG (runtime:604) - Adding a prefix handler for 'xkcd' ('/photos/xkcd')
2012-10-12 22:46:58,619 (1f88) : INFO (core:598) - Started plug-in
2012-10-12 22:46:58,619 (1f88) : DEBUG (socketinterface:141) - Starting socket server
2012-10-12 22:46:58,621 (1f88) : DEBUG (runtime:1036) - Created a thread named 'start'
2012-10-12 22:46:58,621 (1f88) : INFO (socketinterface:165) - Socket server started on port 58925
2012-10-12 22:46:58,621 (1f88) : INFO (pipeinterface:25) - Entering run loop
2012-10-12 22:46:58,621 (1f88) : DEBUG (runtime:654) - Handling request GET /:/prefixes
2012-10-12 22:46:58,622 (1f88) : DEBUG (runtime:750) - Found route matching /:/prefixes
2012-10-12 22:46:58,625 (1f88) : DEBUG (runtime:843) - Response: [200] MediaContainer, 425 bytes
2012-10-12 22:46:58,690 (1fb4) : DEBUG (services:357) - Loaded services
2012-10-12 22:46:58,693 (16fc) : DEBUG (services:433) - No shared code to load
2012-10-12 22:46:59,798 (1e04) : DEBUG (runtime:654) - Handling request GET /photos/xkcd
2012-10-12 22:46:59,799 (1e04) : DEBUG (runtime:750) - Found route matching /photos/xkcd
2012-10-12 22:46:59,848 (1e04) : DEBUG (networking:155) - Fetching 'http://xkcd.com/archive/' from the HTTP cache
2012-10-12 22:46:59,931 (1e04) : DEBUG (networking:155) - Fetching 'http://xkcd.com/1/' from the HTTP cache
2012-10-12 22:46:59,960 (1e04) : WARNING (runtime:984) - Generating a callback path for a function with no route: <function StripDirectory at 0x034208B0>
2012-10-12 22:46:59,996 (1e04) : DEBUG (networking:155) - Fetching 'http://xkcd.com/201/' from the HTTP cache
2012-10-12 22:47:00,026 (1e04) : WARNING (runtime:984) - Generating a callback path for a function with no route: <function StripDirectory at 0x034208B0>
2012-10-12 22:47:00,061 (1e04) : DEBUG (networking:155) - Fetching 'http://xkcd.com/401/' from the HTTP cache
2012-10-12 22:47:00,089 (1e04) : WARNING (runtime:984) - Generating a callback path for a function with no route: <function StripDirectory at 0x034208B0>
2012-10-12 22:47:00,125 (1e04) : DEBUG (networking:155) - Fetching 'http://xkcd.com/602/' from the HTTP cache
2012-10-12 22:47:00,154 (1e04) : WARNING (runtime:984) - Generating a callback path for a function with no route: <function StripDirectory at 0x034208B0>
2012-10-12 22:47:00,188 (1e04) : DEBUG (networking:155) - Fetching 'http://xkcd.com/802/' from the HTTP cache
2012-10-12 22:47:00,219 (1e04) : WARNING (runtime:984) - Generating a callback path for a function with no route: <function StripDirectory at 0x034208B0>
2012-10-12 22:47:00,253 (1e04) : DEBUG (networking:155) - Fetching 'http://xkcd.com/1002/' from the HTTP cache
2012-10-12 22:47:00,283 (1e04) : WARNING (runtime:984) - Generating a callback path for a function with no route: <function StripDirectory at 0x034208B0>
2012-10-12 22:47:00,289 (1e04) : DEBUG (runtime:843) - Response: [200] MediaContainer, 79890 bytes
2012-10-12 22:47:00,924 (b80) : DEBUG (runtime:654) - Handling request GET /photos/xkcd
2012-10-12 22:47:00,927 (b80) : DEBUG (runtime:750) - Found route matching /photos/xkcd
2012-10-12 22:47:00,967 (b80) : DEBUG (networking:155) - Fetching 'http://xkcd.com/archive/' from the HTTP cache
2012-10-12 22:47:01,049 (b80) : DEBUG (networking:155) - Fetching 'http://xkcd.com/1/' from the HTTP cache
2012-10-12 22:47:01,078 (b80) : WARNING (runtime:984) - Generating a callback path for a function with no route: <function StripDirectory at 0x034208B0>
2012-10-12 22:47:01,112 (b80) : DEBUG (networking:155) - Fetching 'http://xkcd.com/201/' from the HTTP cache
2012-10-12 22:47:01,141 (b80) : WARNING (runtime:984) - Generating a callback path for a function with no route: <function StripDirectory at 0x034208B0>
2012-10-12 22:47:01,177 (b80) : DEBUG (networking:155) - Fetching 'http://xkcd.com/401/' from the HTTP cache
2012-10-12 22:47:01,206 (b80) : WARNING (runtime:984) - Generating a callback path for a function with no route: <function StripDirectory at 0x034208B0>
2012-10-12 22:47:01,240 (b80) : DEBUG (networking:155) - Fetching 'http://xkcd.com/602/' from the HTTP cache
2012-10-12 22:47:01,269 (b80) : WARNING (runtime:984) - Generating a callback path for a function with no route: <function StripDirectory at 0x034208B0>
2012-10-12 22:47:01,305 (b80) : DEBUG (networking:155) - Fetching 'http://xkcd.com/802/' from the HTTP cache
2012-10-12 22:47:01,334 (b80) : WARNING (runtime:984) - Generating a callback path for a function with no route: <function StripDirectory at 0x034208B0>
2012-10-12 22:47:01,368 (b80) : DEBUG (networking:155) - Fetching 'http://xkcd.com/1002/' from the HTTP cache
2012-10-12 22:47:01,398 (b80) : WARNING (runtime:984) - Generating a callback path for a function with no route: <function StripDirectory at 0x034208B0>
2012-10-12 22:47:01,404 (b80) : DEBUG (runtime:843) - Response: [200] MediaContainer, 79890 bytes
2012-10-12 22:47:03,651 (1e08) : DEBUG (runtime:654) - Handling request GET /photos/xkcd/:/function/StripDirectory?function_args=Y2VyZWFsMQoyMDIKZGljdApsaXN0CnR1cGxlCjIKczE1CkJhcnJlbCAtIFBhcnQgMXMxOApodHRwOi8veGtjZC5jb20vMS90dXBsZQoyCnMyMApQZXRpdCBUcmVlcyAoc2tldGNoKXMxOApodHRwOi8veGtjZC5jb20vMi90dXBsZQoyCnMxNQpJc2xhbmQgKHNrZXRjaClzMTgKaHR0cDovL3hrY2QuY29tLzMvdHVwbGUKMgpzMTgKTGFuZHNjYXBlIChza2V0Y2gpczE4Cmh0dHA6Ly94a2NkLmNvbS80L3R1cGxlCjIKczExCkJsb3duIGFwYXJ0czE4Cmh0dHA6Ly94a2NkLmNvbS81L3R1cGxlCjIKczUKSXJvbnlzMTgKaHR0cDovL3hrY2QuY29tLzYvdHVwbGUKMgpzNTAKR2lybCBzbGVlcGluZyAoU2tldGNoIC0tIDExdGggZ3JhZGUgU3BhbmlzaCBjbGFzcylzMTgKaHR0cDovL3hrY2QuY29tLzcvdHVwbGUKMgpzMTEKUmVkIHNwaWRlcnNzMTgKaHR0cDovL3hrY2QuY29tLzgvdHVwbGUKMgpzMzEKU2VyZW5pdHkgaXMgY29taW5nIG91dCB0b21vcnJvd3MxOApodHRwOi8veGtjZC5jb20vOS90dXBsZQoyCnM5ClBpIEVxdWFsc3MxOQpodHRwOi8veGtjZC5jb20vMTAvdHVwbGUKMgpzMTUKQmFycmVsIC0gUGFydCAyczE5Cmh0dHA6Ly94a2NkLmNvbS8xMS90dXBsZQoyCnM3ClBvaXNzb25zMTkKaHR0cDovL3hrY2QuY29tLzEyL3R1cGxlCjIKczYKQ2FueW9uczE5Cmh0dHA6Ly94a2NkLmNvbS8xMy90dXBsZQoyCnM5CkNvcHlyaWdodHMxOQpodHRwOi8veGtjZC5jb20vMTQvdHVwbGUKMgpzMTcKSnVzdCBBbGVydGluZyBZb3VzMTkKaHR0cDovL3hrY2QuY29tLzE1L3R1cGxlCjIKczIyCk1vbnR5IFB5dGhvbiAtLSBFbm91Z2hzMTkKaHR0cDovL3hrY2QuY29tLzE2L3R1cGxlCjIKczcKV2hhdCBJZnMxOQpodHRwOi8veGtjZC5jb20vMTcvdHVwbGUKMgpzNwpTbmFwcGxlczE5Cmh0dHA6Ly94a2NkLmNvbS8xOC90dXBsZQoyCnMxNApHZW9yZ2UgQ2xpbnRvbnMxOQpodHRwOi8veGtjZC5jb20vMTkvdHVwbGUKMgpzNgpGZXJyZXRzMTkKaHR0cDovL3hrY2QuY29tLzIwL3R1cGxlCjIKczYKS2VwbGVyczE5Cmh0dHA6Ly94a2NkLmNvbS8yMS90dXBsZQoyCnMxNQpCYXJyZWwgLSBQYXJ0IDNzMTkKaHR0cDovL3hrY2QuY29tLzIyL3R1cGxlCjIKczgKVC1zaGlydHNzMTkKaHR0cDovL3hrY2QuY29tLzIzL3R1cGxlCjIKczI2CkdvZGVsLCBFc2NoZXIsIEt1cnQgSGFsc2V5czE5Cmh0dHA6Ly94a2NkLmNvbS8yNC90dXBsZQoyCnMxNQpCYXJyZWwgLSBQYXJ0IDRzMTkKaHR0cDovL3hrY2QuY29tLzI1L3R1cGxlCjIKczcKRm91cmllcnMxOQpodHRwOi8veGtjZC5jb20vMjYvdHVwbGUKMgpzMTIKTWVhdCBDZXJlYWxzczE5Cmh0dHA6Ly94a2NkLmNvbS8yNy90dXBsZQoyCnM3CkVsZWZpbm9zMTkKaHR0cDovL3hrY2QuY29tLzI4L3R1cGxlCjIKczYKSGl0bGVyczE5Cmh0dHA6Ly94a2NkLmNvbS8yOS90dXBsZQoyCnM2CkRvbm5lcnMxOQpodHRwOi8veGtjZC5jb20vMzAvdHVwbGUKMgpzMTUKQmFycmVsIC0gUGFydCA1czE5Cmh0dHA6Ly94a2NkLmNvbS8zMS90dXBsZQoyCnM2ClBpbGxhcnMxOQpodHRwOi8veGtjZC5jb20vMzIvdHVwbGUKMgpzMTQKU2VsZi1yZWZlcmVuY2VzMTkKaHR0cDovL3hrY2QuY29tLzMzL3R1cGxlCjIKczcKRmxvd2Vyc3MxOQpodHRwOi8veGtjZC5jb20vMzQvdHVwbGUKMgpzNQpTaGVlcHMxOQpodHRwOi8veGtjZC5jb20vMzUvdHVwbGUKMgpzMTAKU2NpZW50aXN0c3MxOQpodHRwOi8veGtjZC5jb20vMzYvdHVwbGUKMgpzNgpIeXBoZW5zMTkKaHR0cDovL3hrY2QuY29tLzM3L3R1cGxlCjIKczExCkFwcGxlIEphY2tzczE5Cmh0dHA6Ly94a2NkLmNvbS8zOC90dXBsZQoyCnM0CkJvd2xzMTkKaHR0cDovL3hrY2QuY29tLzM5L3R1cGxlCjIKczUKTGlnaHRzMTkKaHR0cDovL3hrY2QuY29tLzQwL3R1cGxlCjIKczExCk9sZCBEcmF3aW5nczE5Cmh0dHA6Ly94a2NkLmNvbS80MS90dXBsZQoyCnM1CkdlaWNvczE5Cmh0dHA6Ly94a2NkLmNvbS80Mi90dXBsZQoyCnMxMwpSZWQgU3BpZGVycyAyczE5Cmh0dHA6Ly94a2NkLmNvbS80My90dXBsZQoyCnM0CkxvdmVzMTkKaHR0cDovL3hrY2QuY29tLzQ0L3R1cGxlCjIKczExClNjaHJvZGluZ2VyczE5Cmh0dHA6Ly94a2NkLmNvbS80NS90dXBsZQoyCnM3ClNlY3JldHNzMTkKaHR0cDovL3hrY2QuY29tLzQ2L3R1cGxlCjIKczE5CkNvdW50ZXItUmVkIFNwaWRlcnNzMTkKaHR0cDovL3hrY2QuY29tLzQ3L3R1cGxlCjIKczUKRm91bmRzMTkKaHR0cDovL3hrY2QuY29tLzQ4L3R1cGxlCjIKczQKV2FudHMxOQpodHRwOi8veGtjZC5jb20vNDkvdHVwbGUKMgpzMTIKUGVubnkgQXJjYWRlczE5Cmh0dHA6Ly94a2NkLmNvbS81MC90dXBsZQoyCnM3Ck1hbGFyaWFzMTkKaHR0cDovL3hrY2QuY29tLzUxL3R1cGxlCjIKczEzClNlY3JldCBXb3JsZHNzMTkKaHR0cDovL3hrY2QuY29tLzUyL3R1cGxlCjIKczUKSG9iYnlzMTkKaHR0cDovL3hrY2QuY29tLzUzL3R1cGxlCjIKczcKU2NpZW5jZXMxOQpodHRwOi8veGtjZC5jb20vNTQvdHVwbGUKMgpzNwpVc2VsZXNzczE5Cmh0dHA6Ly94a2NkLmNvbS81NS90dXBsZQoyCnM4ClRoZSBDdXJlczE5Cmh0dHA6Ly94a2NkLmNvbS81Ni90dXBsZQoyCnMxMQpXYWl0IEZvciBNZXMxOQpodHRwOi8veGtjZC5jb20vNTcvdHVwbGUKMgpzMTkKV2h5IERvIFlvdSBMb3ZlIE1lP3MxOQpodHRwOi8veGtjZC5jb20vNTgvdHVwbGUKMgpzMTAKR3JhZHVhdGlvbnMxOQpodHRwOi8veGtjZC5jb20vNTkvdHVwbGUKMgpzMTAKU3VwZXIgQm93bHMxOQpodHRwOi8veGtjZC5jb20vNjAvdHVwbGUKMgpzMTIKU3RhY2V5J3MgRGFkczE5Cmh0dHA6Ly94a2NkLmNvbS82MS90dXBsZQoyCnMyMApWYWxlbnRpbmUgLSBLYXJuYXVnaHMxOQpodHRwOi8veGtjZC5jb20vNjIvdHVwbGUKMgpzMTcKVmFsZW50aW5lIC0gSGVhcnRzMTkKaHR0cDovL3hrY2QuY29tLzYzL3R1cGxlCjIKczEyClNvbGFyIFBsZXh1c3MxOQpodHRwOi8veGtjZC5jb20vNjQvdHVwbGUKMgpzNgpCYW50ZXJzMTkKaHR0cDovL3hrY2QuY29tLzY1L3R1cGxlCjIKczE3CkFidXNpdmUgQXN0cm9ub215czE5Cmh0dHA6Ly94a2NkLmNvbS82Ni90dXBsZQoyCnMxMApOZXJkIEdpcmxzczE5Cmh0dHA6Ly94a2NkLmNvbS82Ny90dXBsZQoyCnMxMQpGaXZlIFRoaXJ0eXMxOQpodHRwOi8veGtjZC5jb20vNjgvdHVwbGUKMgpzMTEKUGlsbG93IFRhbGtzMTkKaHR0cDovL3hrY2QuY29tLzY5L3R1cGxlCjIKczExCkd1aXRhciBIZXJvczE5Cmh0dHA6Ly94a2NkLmNvbS83MC90dXBsZQoyCnMxMgpJbiB0aGUgVHJlZXNzMTkKaHR0cDovL3hrY2QuY29tLzcxL3R1cGxlCjIKczkKQ2xhc3Nob2xlczE5Cmh0dHA6Ly94a2NkLmNvbS83Mi90dXBsZQoyCnM4ClplcHBlbGluczE5Cmh0dHA6Ly94a2NkLmNvbS83My90dXBsZQoyCnM3ClN1IERva3VzMTkKaHR0cDovL3hrY2QuY29tLzc0L3R1cGxlCjIKczEyCkN1cnNlIExldmVsc3MxOQpodHRwOi8veGtjZC5jb20vNzUvdHVwbGUKMgpzOApGYW1pbGlhcnMxOQpodHRwOi8veGtjZC5jb20vNzYvdHVwbGUKMgpzMjMKQm9yZWQgd2l0aCB0aGUgSW50ZXJuZXRzMTkKaHR0cDovL3hrY2QuY29tLzc3L3R1cGxlCjIKczgKR2FyZmllbGRzMTkKaHR0cDovL3hrY2QuY29tLzc4L3R1cGxlCjIKczE3CklhbWJpYyBQZW50YW1ldGVyczE5Cmh0dHA6Ly94a2NkLmNvbS83OS90dXBsZQoyCnMxMgpNeSBPdGhlciBDYXJzMTkKaHR0cDovL3hrY2QuY29tLzgwL3R1cGxlCjIKczE4CkF0dGVudGlvbiwgc2hvcHBlcnMxOQpodHRwOi8veGtjZC5jb20vODEvdHVwbGUKMgpzNQpGcmFtZXMxOQpodHRwOi8veGtjZC5jb20vODIvdHVwbGUKMgpzOApLYXRhbWFyaXMxOQpodHRwOi8veGtjZC5jb20vODMvdHVwbGUKMgpzMTcKTmF0aW9uYWwgTGFuZ3VhZ2VzMTkKaHR0cDovL3hrY2QuY29tLzg0L3R1cGxlCjIKczUKUGF0aHNzMTkKaHR0cDovL3hrY2QuY29tLzg1L3R1cGxlCjIKczI1CkRpZ2l0YWwgUmlnaHRzIE1hbmFnZW1lbnRzMTkKaHR0cDovL3hrY2QuY29tLzg2L3R1cGxlCjIKczEzClZlbG9jaXJhcHRvcnNzMTkKaHR0cDovL3hrY2QuY29tLzg3L3R1cGxlCjIKczE1CkVzY2hlciBCcmFjZWxldHMxOQpodHRwOi8veGtjZC5jb20vODgvdHVwbGUKMgpzMTgKR3Jhdml0YXRpb25hbCBNYXNzczE5Cmh0dHA6Ly94a2NkLmNvbS84OS90dXBsZQoyCnM2CkphY2tldHMxOQpodHRwOi8veGtjZC5jb20vOTAvdHVwbGUKMgpzNQpQd25lZHMxOQpodHRwOi8veGtjZC5jb20vOTEvdHVwbGUKMgpzNwpTdW5yaXNlczE5Cmh0dHA6Ly94a2NkLmNvbS85Mi90dXBsZQoyCnMxMgpKZXJlbXkgSXJvbnNzMTkKaHR0cDovL3hrY2QuY29tLzkzL3R1cGxlCjIKczI2ClByb2ZpbGUgQ3JlYXRpb24gRmxvd2NoYXJ0czE5Cmh0dHA6Ly94a2NkLmNvbS85NC90dXBsZQoyCnMyNQpUaGUgU2llcnBpbnNraSBQZW5pcyBHYW1lczE5Cmh0dHA6Ly94a2NkLmNvbS85NS90dXBsZQoyCnM0Ck1haWxzMTkKaHR0cDovL3hrY2QuY29tLzk2L3R1cGxlCjIKczEzCkEgU2ltcGxlIFBsYW5zMTkKaHR0cDovL3hrY2QuY29tLzk3L3R1cGxlCjIKczEwCkZhbGwgQXBhcnRzMTkKaHR0cDovL3hrY2QuY29tLzk4L3R1cGxlCjIKczEyCkJpbmFyeSBIZWFydHMxOQpodHRwOi8veGtjZC5jb20vOTkvdHVwbGUKMgpzMTMKRmFtaWx5IENpcmN1c3MyMApodHRwOi8veGtjZC5jb20vMTAwL3R1cGxlCjIKczExCkxhc2VyIFNjb3BlczIwCmh0dHA6Ly94a2NkLmNvbS8xMDEvdHVwbGUKMgpzMTgKQmFjayB0byB0aGUgRnV0dXJlczIwCmh0dHA6Ly94a2NkLmNvbS8xMDIvdHVwbGUKMgpzMTYKTW9yYWwgUmVsYXRpdml0eXMyMApodHRwOi8veGtjZC5jb20vMTAzL3R1cGxlCjIKczgKRmluZCBZb3VzMjAKaHR0cDovL3hrY2QuY29tLzEwNC90dXBsZQoyCnMxNwpQYXJhbGxlbCBVbml2ZXJzZXMyMApodHRwOi8veGtjZC5jb20vMTA1L3R1cGxlCjIKczE1CldyaWdodCBCcm90aGVyc3MyMApodHRwOi8veGtjZC5jb20vMTA2L3R1cGxlCjIKczIwClNuYWtlcyBvbiBhIFBsYW5lISAyczIwCmh0dHA6Ly94a2NkLmNvbS8xMDcvdHVwbGUKMgpzMTcKTS5DLiBIYW1tZXIgU2xpZGVzMjAKaHR0cDovL3hrY2QuY29tLzEwOC90dXBsZQoyCnMxMwpTcG9pbGVyIEFsZXJ0czIwCmh0dHA6Ly94a2NkLmNvbS8xMDkvdHVwbGUKMgpzMTEKQ2xhcmsgR2FibGVzMjAKaHR0cDovL3hrY2QuY29tLzExMC90dXBsZQoyCnM0MApGaXJlZm94IGFuZCBXaXRjaGNyYWZ0IC0gVGhlIENvbm5lY3Rpb24%40czIwCmh0dHA6Ly94a2NkLmNvbS8xMTEvdHVwbGUKMgpzMTUKQmFyaW5nIE15IEhlYXJ0czIwCmh0dHA6Ly94a2NkLmNvbS8xMTIvdHVwbGUKMgpzMTIKUmllbWFubi1aZXRhczIwCmh0dHA6Ly94a2NkLmNvbS8xMTMvdHVwbGUKMgpzMjMKQ29tcHV0YXRpb25hbCBMaW5ndWlzdHNzMjAKaHR0cDovL3hrY2QuY29tLzExNC90dXBsZQoyCnM3Ck1lZXJrYXRzMjAKaHR0cDovL3hrY2QuY29tLzExNS90dXBsZQoyCnM0CkNpdHlzMjAKaHR0cDovL3hrY2QuY29tLzExNi90dXBsZQoyCnM0ClBvbmdzMjAKaHR0cDovL3hrY2QuY29tLzExNy90dXBsZQoyCnM3CjUwIFdheXNzMjAKaHR0cDovL3hrY2QuY29tLzExOC90dXBsZQoyCnMyMApXb3JzdCBCYW5kIE5hbWUgRXZlcnMyMApodHRwOi8veGtjZC5jb20vMTE5L3R1cGxlCjIKczE0CkRhdGluZyBTZXJ2aWNlczIwCmh0dHA6Ly94a2NkLmNvbS8xMjAvdHVwbGUKMgpzNwpCYWxsb29uczIwCmh0dHA6Ly94a2NkLmNvbS8xMjEvdHVwbGUKMgpzMTIKUXVpcmt5IEdpcmxzczIwCmh0dHA6Ly94a2NkLmNvbS8xMjIvdHVwbGUKMgpzMTcKQ2VudHJpZnVnYWwgRm9yY2VzMjAKaHR0cDovL3hrY2QuY29tLzEyMy90dXBsZQoyCnMxMgpCbG9nb2ZyYWN0YWxzMjAKaHR0cDovL3hrY2QuY29tLzEyNC90dXBsZQoyCnMxOQpNYXJrZXRpbmcgSW50ZXJ2aWV3czIwCmh0dHA6Ly94a2NkLmNvbS8xMjUvdHVwbGUKMgpzMTgKUmVkIFNwaWRlcnMgQ29tZXRoczIwCmh0dHA6Ly94a2NkLmNvbS8xMjYvdHVwbGUKMgpzMjQKVGhlIEZhc3QgYW5kIHRoZSBGdXJpb3VzczIwCmh0dHA6Ly94a2NkLmNvbS8xMjcvdHVwbGUKMgpzMTMKZFBhaW4gb3ZlciBkdHMyMApodHRwOi8veGtjZC5jb20vMTI4L3R1cGxlCjIKczE4CkNvbnRlbnQgUHJvdGVjdGlvbnMyMApodHRwOi8veGtjZC5jb20vMTI5L3R1cGxlCjIKczEyCkp1bGlhIFN0aWxlc3MyMApodHRwOi8veGtjZC5jb20vMTMwL3R1cGxlCjIKczQKRmFuc3MyMApodHRwOi8veGtjZC5jb20vMTMxL3R1cGxlCjIKczE1Ck11c2ljIEtub3dsZWRnZXMyMApodHRwOi8veGtjZC5jb20vMTMyL3R1cGxlCjIKczkKVGhlIFJhdmVuczIwCmh0dHA6Ly94a2NkLmNvbS8xMzMvdHVwbGUKMgpzNwpNeXNwYWNlczIwCmh0dHA6Ly94a2NkLmNvbS8xMzQvdHVwbGUKMgpzMTAKU3Vic3RpdHV0ZXMyMApodHRwOi8veGtjZC5jb20vMTM1L3R1cGxlCjIKczEyClNjaWVuY2UgRmFpcnMyMApodHRwOi8veGtjZC5jb20vMTM2L3R1cGxlCjIKczYKRHJlYW1zczIwCmh0dHA6Ly94a2NkLmNvbS8xMzcvdHVwbGUKMgpzOApQb2ludGVyc3MyMApodHRwOi8veGtjZC5jb20vMTM4L3R1cGxlCjIKczM3CkkgSGF2ZSBPd25lZCBUd28gRWxlY3RyaWMgU2thdGVib2FyZHNzMjAKaHR0cDovL3hrY2QuY29tLzEzOS90dXBsZQoyCnM5CkRlbGljaW91c3MyMApodHRwOi8veGtjZC5jb20vMTQwL3R1cGxlCjIKczIxClBhcm9keSBXZWVrOiBBY2hld29vZHMyMApodHRwOi8veGtjZC5jb20vMTQxL3R1cGxlCjIKczIyClBhcm9keSBXZWVrOiBNZWdhdG9reW9zMjAKaHR0cDovL3hrY2QuY29tLzE0Mi90dXBsZQoyCnMzMgpQYXJvZHkgV2VlazogVEZEIGFuZCBOYXRhbGllIERlZXMyMApodHRwOi8veGtjZC5jb20vMTQzL3R1cGxlCjIKczI3ClBhcm9keSBXZWVrOiBBIFNvZnRlciBXb3JsZHMyMApodHRwOi8veGtjZC5jb20vMTQ0L3R1cGxlCjIKczI4ClBhcm9keSBXZWVrOiBEaW5vc2F1ciBDb21pY3NzMjAKaHR0cDovL3hrY2QuY29tLzE0NS90dXBsZQoyCnMxMgpKb2luIE15c3BhY2VzMjAKaHR0cDovL3hrY2QuY29tLzE0Ni90dXBsZQoyCnMxNwpBIFdheSBTbyBGYW1pbGlhcnMyMApodHRwOi8veGtjZC5jb20vMTQ3L3R1cGxlCjIKczE0Ck1pc3Byb25vdW5jaW5nczIwCmh0dHA6Ly94a2NkLmNvbS8xNDgvdHVwbGUKMgpzOApTYW5kd2ljaHMyMApodHRwOi8veGtjZC5jb20vMTQ5L3R1cGxlCjIKczgKR3Jvd251cHNzMjAKaHR0cDovL3hrY2QuY29tLzE1MC90dXBsZQoyCnM1Ck1hcmlvczIwCmh0dHA6Ly94a2NkLmNvbS8xNTEvdHVwbGUKMgpzMTIKSGFtc3RlciBCYWxsczIwCmh0dHA6Ly94a2NkLmNvbS8xNTIvdHVwbGUKMgpzMTIKQ3J5cHRvZ3JhcGh5czIwCmh0dHA6Ly94a2NkLmNvbS8xNTMvdHVwbGUKMgpzNwpCZWxpZWZzczIwCmh0dHA6Ly94a2NkLmNvbS8xNTQvdHVwbGUKMgpzMTQKU2VhcmNoIEhpc3RvcnlzMjAKaHR0cDovL3hrY2QuY29tLzE1NS90dXBsZQoyCnM5CkNvbW1lbnRlZHMyMApodHRwOi8veGtjZC5jb20vMTU2L3R1cGxlCjIKczEwCkZpbGxlciBBcnRzMjAKaHR0cDovL3hrY2QuY29tLzE1Ny90dXBsZQoyCnMxMApTaXggTW9udGhzczIwCmh0dHA6Ly94a2NkLmNvbS8xNTgvdHVwbGUKMgpzNwpCb29tYm94czIwCmh0dHA6Ly94a2NkLmNvbS8xNTkvdHVwbGUKMgpzMTkKUGVubnkgQXJjYWRlIFBhcm9keXMyMApodHRwOi8veGtjZC5jb20vMTYwL3R1cGxlCjIKczgKQWNjaWRlbnRzMjAKaHR0cDovL3hrY2QuY29tLzE2MS90dXBsZQoyCnMxNgpBbmd1bGFyIE1vbWVudHVtczIwCmh0dHA6Ly94a2NkLmNvbS8xNjIvdHVwbGUKMgpzMTIKRG9uYWxkIEtudXRoczIwCmh0dHA6Ly94a2NkLmNvbS8xNjMvdHVwbGUKMgpzMzEKUGxheWluZyBEZXZpbCdzIEFkdm9jYXRlIHRvIFdpbnMyMApodHRwOi8veGtjZC5jb20vMTY0L3R1cGxlCjIKczEyClR1cm4gU2lnbmFsc3MyMApodHRwOi8veGtjZC5jb20vMTY1L3R1cGxlCjIKczE0Ck1pc3VzaW5nIFNsYW5nczIwCmh0dHA6Ly94a2NkLmNvbS8xNjYvdHVwbGUKMgpzOApOaWhpbGlzbXMyMApodHRwOi8veGtjZC5jb20vMTY3L3R1cGxlCjIKczE4ClJldmVyc2UgRXVwaGVtaXNtc3MyMApodHRwOi8veGtjZC5jb20vMTY4L3R1cGxlCjIKczIxCldvcmRzIHRoYXQgRW5kIGluIEdSWXMyMApodHRwOi8veGtjZC5jb20vMTY5L3R1cGxlCjIKczkKVHVybiBCYWNrczIwCmh0dHA6Ly94a2NkLmNvbS8xNzAvdHVwbGUKMgpzMTMKU3RyaW5nIFRoZW9yeXMyMApodHRwOi8veGtjZC5jb20vMTcxL3R1cGxlCjIKczI4ClNrYXRlYm9hcmRpbmcgaXMgTm90IGEgQ3JpbWVzMjAKaHR0cDovL3hrY2QuY29tLzE3Mi90dXBsZQoyCnMxMwpNb3ZpZSBTZWF0aW5nczIwCmh0dHA6Ly94a2NkLmNvbS8xNzMvdHVwbGUKMgpzMjAKVGhhdCdzIFdoYXQgU0hFIFNhaWRzMjAKaHR0cDovL3hrY2QuY29tLzE3NC90dXBsZQoyCnMxNQpBdXRvbWF0aWMgRG9vcnNzMjAKaHR0cDovL3hrY2QuY29tLzE3NS90dXBsZQoyCnMxNApCZWZvcmUgU3VucmlzZXMyMApodHRwOi8veGtjZC5jb20vMTc2L3R1cGxlCjIKczEzCkFsaWNlIGFuZCBCb2JzMjAKaHR0cDovL3hrY2QuY29tLzE3Ny90dXBsZQoyCnMyMwpOb3QgUmVhbGx5IEludG8gUG9rZW1vbnMyMApodHRwOi8veGtjZC5jb20vMTc4L3R1cGxlCjIKczE5CmUgdG8gdGhlIHBpIHRpbWVzIGlzMjAKaHR0cDovL3hrY2QuY29tLzE3OS90dXBsZQoyCnM2CkNhbmFkYXMyMApodHRwOi8veGtjZC5jb20vMTgwL3R1cGxlCjIKczkKSW50ZXJibGFnczIwCmh0dHA6Ly94a2NkLmNvbS8xODEvdHVwbGUKMgpzNApOYXNoczIwCmh0dHA6Ly94a2NkLmNvbS8xODIvdHVwbGUKMgpzMTUKU25hY2t0aW1lIFJ1bGVzczIwCmh0dHA6Ly94a2NkLmNvbS8xODMvdHVwbGUKMgpzMTYKTWF0cml4IFRyYW5zZm9ybXMyMApodHRwOi8veGtjZC5jb20vMTg0L3R1cGxlCjIKczExCldpa2lmcmllbmRzczIwCmh0dHA6Ly94a2NkLmNvbS8xODUvdHVwbGUKMgpzMTMKQ29uc29sZSBMaW5lc3MyMApodHRwOi8veGtjZC5jb20vMTg2L3R1cGxlCjIKczEyClRoZSBGYW1pbGlhcnMyMApodHRwOi8veGtjZC5jb20vMTg3L3R1cGxlCjIKczYKUmVsb2FkczIwCmh0dHA6Ly94a2NkLmNvbS8xODgvdHVwbGUKMgpzOApFeGVyY2lzZXMyMApodHRwOi8veGtjZC5jb20vMTg5L3R1cGxlCjIKczQKSVBvRHMyMApodHRwOi8veGtjZC5jb20vMTkwL3R1cGxlCjIKczYKTG9qYmFuczIwCmh0dHA6Ly94a2NkLmNvbS8xOTEvdHVwbGUKMgpzMTgKV29ya2luZyBmb3IgR29vZ2xlczIwCmh0dHA6Ly94a2NkLmNvbS8xOTIvdHVwbGUKMgpzMTcKVGhlIFBlcmZlY3QgU291bmRzMjAKaHR0cDovL3hrY2QuY29tLzE5My90dXBsZQoyCnM3ClBlbmlzZXNzMjAKaHR0cDovL3hrY2QuY29tLzE5NC90dXBsZQoyCnMxOQpNYXAgb2YgdGhlIEludGVybmV0czIwCmh0dHA6Ly94a2NkLmNvbS8xOTUvdHVwbGUKMgpzMTUKQ29tbWFuZCBMaW5lIEZ1czIwCmh0dHA6Ly94a2NkLmNvbS8xOTYvdHVwbGUKMgpzMTMKTmluamEgVHVydGxlc3MyMApodHRwOi8veGtjZC5jb20vMTk3L3R1cGxlCjIKczExClBlcnNwZWN0aXZlczIwCmh0dHA6Ly94a2NkLmNvbS8xOTgvdHVwbGUKMgpzMTUKUmlnaHQtSGFuZCBSdWxlczIwCmh0dHA6Ly94a2NkLmNvbS8xOTkvdHVwbGUKMgpzOApCaWxsIE55ZXMyMApodHRwOi8veGtjZC5jb20vMjAwLzIKaTEKczIKaWRyMQpzMTAKc3RyaXBzZGF0YTIwMApyMgpyMwpyNApyNQpyNgpyNwpyOApyOQpyMTAKcjExCnIxMgpyMTMKcjE0CnIxNQpyMTYKcjE3CnIxOApyMTkKcjIwCnIyMQpyMjIKcjIzCnIyNApyMjUKcjI2CnIyNwpyMjgKcjI5CnIzMApyMzEKcjMyCnIzMwpyMzQKcjM1CnIzNgpyMzcKcjM4CnIzOQpyNDAKcjQxCnI0MgpyNDMKcjQ0CnI0NQpyNDYKcjQ3CnI0OApyNDkKcjUwCnI1MQpyNTIKcjUzCnI1NApyNTUKcjU2CnI1NwpyNTgKcjU5CnI2MApyNjEKcjYyCnI2MwpyNjQKcjY1CnI2NgpyNjcKcjY4CnI2OQpyNzAKcjcxCnI3MgpyNzMKcjc0CnI3NQpyNzYKcjc3CnI3OApyNzkKcjgwCnI4MQpyODIKcjgzCnI4NApyODUKcjg2CnI4NwpyODgKcjg5CnI5MApyOTEKcjkyCnI5MwpyOTQKcjk1CnI5NgpyOTcKcjk4CnI5OQpyMTAwCnIxMDEKcjEwMgpyMTAzCnIxMDQKcjEwNQpyMTA2CnIxMDcKcjEwOApyMTA5CnIxMTAKcjExMQpyMTEyCnIxMTMKcjExNApyMTE1CnIxMTYKcjExNwpyMTE4CnIxMTkKcjEyMApyMTIxCnIxMjIKcjEyMwpyMTI0CnIxMjUKcjEyNgpyMTI3CnIxMjgKcjEyOQpyMTMwCnIxMzEKcjEzMgpyMTMzCnIxMzQKcjEzNQpyMTM2CnIxMzcKcjEzOApyMTM5CnIxNDAKcjE0MQpyMTQyCnIxNDMKcjE0NApyMTQ1CnIxNDYKcjE0NwpyMTQ4CnIxNDkKcjE1MApyMTUxCnIxNTIKcjE1MwpyMTU0CnIxNTUKcjE1NgpyMTU3CnIxNTgKcjE1OQpyMTYwCnIxNjEKcjE2MgpyMTYzCnIxNjQKcjE2NQpyMTY2CnIxNjcKcjE2OApyMTY5CnIxNzAKcjE3MQpyMTcyCnIxNzMKcjE3NApyMTc1CnIxNzYKcjE3NwpyMTc4CnIxNzkKcjE4MApyMTgxCnIxODIKcjE4MwpyMTg0CnIxODUKcjE4NgpyMTg3CnIxODgKcjE4OQpyMTkwCnIxOTEKcjE5MgpyMTkzCnIxOTQKcjE5NQpyMTk2CnIxOTcKcjE5OApyMTk5CnIyMDAKcjIwMQpyMAo_
2012-10-12 22:47:03,677 (1e08) : DEBUG (runtime:750) - Found route matching /photos/xkcd/:/function/StripDirectory
2012-10-12 22:47:03,677 (1e08) : DEBUG (runtime:143) - Calling function 'StripDirectory'
2012-10-12 22:47:03,709 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/1/' from the HTTP cache
2012-10-12 22:47:03,766 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/2/' from the HTTP cache
2012-10-12 22:47:03,825 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/3/' from the HTTP cache
2012-10-12 22:47:03,882 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/4/' from the HTTP cache
2012-10-12 22:47:03,940 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/5/' from the HTTP cache
2012-10-12 22:47:03,999 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/6/' from the HTTP cache
2012-10-12 22:47:04,055 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/7/' from the HTTP cache
2012-10-12 22:47:04,115 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/8/' from the HTTP cache
2012-10-12 22:47:04,171 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/9/' from the HTTP cache
2012-10-12 22:47:04,230 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/10/' from the HTTP cache
2012-10-12 22:47:04,288 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/11/' from the HTTP cache
2012-10-12 22:47:04,346 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/12/' from the HTTP cache
2012-10-12 22:47:04,404 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/13/' from the HTTP cache
2012-10-12 22:47:04,463 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/14/' from the HTTP cache
2012-10-12 22:47:04,520 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/15/' from the HTTP cache
2012-10-12 22:47:04,578 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/16/' from the HTTP cache
2012-10-12 22:47:04,637 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/17/' from the HTTP cache
2012-10-12 22:47:04,694 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/18/' from the HTTP cache
2012-10-12 22:47:04,756 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/19/' from the HTTP cache
2012-10-12 22:47:04,813 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/20/' from the HTTP cache
2012-10-12 22:47:04,871 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/21/' from the HTTP cache
2012-10-12 22:47:04,930 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/22/' from the HTTP cache
2012-10-12 22:47:04,987 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/23/' from the HTTP cache
2012-10-12 22:47:05,046 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/24/' from the HTTP cache
2012-10-12 22:47:05,104 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/25/' from the HTTP cache
2012-10-12 22:47:05,161 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/26/' from the HTTP cache
2012-10-12 22:47:05,220 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/27/' from the HTTP cache
2012-10-12 22:47:05,278 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/28/' from the HTTP cache
2012-10-12 22:47:05,335 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/29/' from the HTTP cache
2012-10-12 22:47:05,394 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/30/' from the HTTP cache
2012-10-12 22:47:05,451 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/31/' from the HTTP cache
2012-10-12 22:47:05,510 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/32/' from the HTTP cache
2012-10-12 22:47:05,569 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/33/' from the HTTP cache
2012-10-12 22:47:05,625 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/34/' from the HTTP cache
2012-10-12 22:47:05,684 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/35/' from the HTTP cache
2012-10-12 22:47:05,742 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/36/' from the HTTP cache
2012-10-12 22:47:05,799 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/37/' from the HTTP cache
2012-10-12 22:47:05,858 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/38/' from the HTTP cache
2012-10-12 22:47:05,915 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/39/' from the HTTP cache
2012-10-12 22:47:05,973 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/40/' from the HTTP cache
2012-10-12 22:47:06,032 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/41/' from the HTTP cache
2012-10-12 22:47:06,089 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/42/' from the HTTP cache
2012-10-12 22:47:06,157 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/43/' from the HTTP cache
2012-10-12 22:47:06,217 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/44/' from the HTTP cache
2012-10-12 22:47:06,273 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/45/' from the HTTP cache
2012-10-12 22:47:06,332 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/46/' from the HTTP cache
2012-10-12 22:47:06,391 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/47/' from the HTTP cache
2012-10-12 22:47:06,450 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/48/' from the HTTP cache
2012-10-12 22:47:06,509 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/49/' from the HTTP cache
2012-10-12 22:47:06,566 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/50/' from the HTTP cache
2012-10-12 22:47:06,625 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/51/' from the HTTP cache
2012-10-12 22:47:06,683 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/52/' from the HTTP cache
2012-10-12 22:47:06,753 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/53/' from the HTTP cache
2012-10-12 22:47:06,812 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/54/' from the HTTP cache
2012-10-12 22:47:06,869 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/55/' from the HTTP cache
2012-10-12 22:47:06,927 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/56/' from the HTTP cache
2012-10-12 22:47:06,984 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/57/' from the HTTP cache
2012-10-12 22:47:07,043 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/58/' from the HTTP cache
2012-10-12 22:47:07,101 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/59/' from the HTTP cache
2012-10-12 22:47:07,160 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/60/' from the HTTP cache
2012-10-12 22:47:07,217 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/61/' from the HTTP cache
2012-10-12 22:47:07,276 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/62/' from the HTTP cache
2012-10-12 22:47:07,334 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/63/' from the HTTP cache
2012-10-12 22:47:07,392 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/64/' from the HTTP cache
2012-10-12 22:47:07,450 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/65/' from the HTTP cache
2012-10-12 22:47:07,509 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/66/' from the HTTP cache
2012-10-12 22:47:07,566 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/67/' from the HTTP cache
2012-10-12 22:47:07,625 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/68/' from the HTTP cache
2012-10-12 22:47:07,683 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/69/' from the HTTP cache
2012-10-12 22:47:07,740 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/70/' from the HTTP cache
2012-10-12 22:47:07,799 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/71/' from the HTTP cache
2012-10-12 22:47:07,857 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/72/' from the HTTP cache
2012-10-12 22:47:07,914 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/73/' from the HTTP cache
2012-10-12 22:47:07,973 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/74/' from the HTTP cache
2012-10-12 22:47:08,030 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/75/' from the HTTP cache
2012-10-12 22:47:08,088 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/76/' from the HTTP cache
2012-10-12 22:47:08,147 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/77/' from the HTTP cache
2012-10-12 22:47:08,204 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/78/' from the HTTP cache
2012-10-12 22:47:08,263 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/79/' from the HTTP cache
2012-10-12 22:47:08,321 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/80/' from the HTTP cache
2012-10-12 22:47:08,378 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/81/' from the HTTP cache
2012-10-12 22:47:08,437 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/82/' from the HTTP cache
2012-10-12 22:47:08,494 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/83/' from the HTTP cache
2012-10-12 22:47:08,553 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/84/' from the HTTP cache
2012-10-12 22:47:08,611 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/85/' from the HTTP cache
2012-10-12 22:47:08,670 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/86/' from the HTTP cache
2012-10-12 22:47:08,727 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/87/' from the HTTP cache
2012-10-12 22:47:08,786 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/88/' from the HTTP cache
2012-10-12 22:47:08,844 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/89/' from the HTTP cache
2012-10-12 22:47:08,901 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/90/' from the HTTP cache
2012-10-12 22:47:08,960 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/91/' from the HTTP cache
2012-10-12 22:47:09,017 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/92/' from the HTTP cache
2012-10-12 22:47:09,075 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/93/' from the HTTP cache
2012-10-12 22:47:09,134 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/94/' from the HTTP cache
2012-10-12 22:47:09,191 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/95/' from the HTTP cache
2012-10-12 22:47:09,250 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/96/' from the HTTP cache
2012-10-12 22:47:09,308 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/97/' from the HTTP cache
2012-10-12 22:47:09,367 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/98/' from the HTTP cache
2012-10-12 22:47:09,424 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/99/' from the HTTP cache
2012-10-12 22:47:09,483 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/100/' from the HTTP cache
2012-10-12 22:47:09,540 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/101/' from the HTTP cache
2012-10-12 22:47:09,599 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/102/' from the HTTP cache
2012-10-12 22:47:09,657 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/103/' from the HTTP cache
2012-10-12 22:47:09,717 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/104/' from the HTTP cache
2012-10-12 22:47:09,775 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/105/' from the HTTP cache
2012-10-12 22:47:09,835 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/106/' from the HTTP cache
2012-10-12 22:47:09,894 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/107/' from the HTTP cache
2012-10-12 22:47:09,951 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/108/' from the HTTP cache
2012-10-12 22:47:10,009 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/109/' from the HTTP cache
2012-10-12 22:47:10,068 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/110/' from the HTTP cache
2012-10-12 22:47:10,125 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/111/' from the HTTP cache
2012-10-12 22:47:10,184 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/112/' from the HTTP cache
2012-10-12 22:47:10,242 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/113/' from the HTTP cache
2012-10-12 22:47:10,301 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/114/' from the HTTP cache
2012-10-12 22:47:10,358 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/115/' from the HTTP cache
2012-10-12 22:47:10,417 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/116/' from the HTTP cache
2012-10-12 22:47:10,474 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/117/' from the HTTP cache
2012-10-12 22:47:10,533 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/118/' from the HTTP cache
2012-10-12 22:47:10,592 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/119/' from the HTTP cache
2012-10-12 22:47:10,650 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/120/' from the HTTP cache
2012-10-12 22:47:10,707 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/121/' from the HTTP cache
2012-10-12 22:47:10,766 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/122/' from the HTTP cache
2012-10-12 22:47:10,823 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/123/' from the HTTP cache
2012-10-12 22:47:10,881 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/124/' from the HTTP cache
2012-10-12 22:47:10,940 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/125/' from the HTTP cache
2012-10-12 22:47:11,000 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/126/' from the HTTP cache
2012-10-12 22:47:11,058 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/127/' from the HTTP cache
2012-10-12 22:47:11,117 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/128/' from the HTTP cache
2012-10-12 22:47:11,174 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/129/' from the HTTP cache
2012-10-12 22:47:11,233 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/130/' from the HTTP cache
2012-10-12 22:47:11,290 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/131/' from the HTTP cache
2012-10-12 22:47:11,349 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/132/' from the HTTP cache
2012-10-12 22:47:11,407 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/133/' from the HTTP cache
2012-10-12 22:47:11,467 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/134/' from the HTTP cache
2012-10-12 22:47:11,525 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/135/' from the HTTP cache
2012-10-12 22:47:11,582 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/136/' from the HTTP cache
2012-10-12 22:47:11,641 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/137/' from the HTTP cache
2012-10-12 22:47:11,700 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/138/' from the HTTP cache
2012-10-12 22:47:11,756 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/139/' from the HTTP cache
2012-10-12 22:47:11,815 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/140/' from the HTTP cache
2012-10-12 22:47:11,872 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/141/' from the HTTP cache
2012-10-12 22:47:11,931 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/142/' from the HTTP cache
2012-10-12 22:47:11,989 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/143/' from the HTTP cache
2012-10-12 22:47:12,046 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/144/' from the HTTP cache
2012-10-12 22:47:12,105 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/145/' from the HTTP cache
2012-10-12 22:47:12,164 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/146/' from the HTTP cache
2012-10-12 22:47:12,220 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/147/' from the HTTP cache
2012-10-12 22:47:12,279 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/148/' from the HTTP cache
2012-10-12 22:47:12,336 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/149/' from the HTTP cache
2012-10-12 22:47:12,395 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/150/' from the HTTP cache
2012-10-12 22:47:12,453 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/151/' from the HTTP cache
2012-10-12 22:47:12,512 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/152/' from the HTTP cache
2012-10-12 22:47:12,569 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/153/' from the HTTP cache
2012-10-12 22:47:12,628 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/154/' from the HTTP cache
2012-10-12 22:47:12,686 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/155/' from the HTTP cache
2012-10-12 22:47:12,743 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/156/' from the HTTP cache
2012-10-12 22:47:12,802 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/157/' from the HTTP cache
2012-10-12 22:47:12,859 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/158/' from the HTTP cache
2012-10-12 22:47:12,917 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/159/' from the HTTP cache
2012-10-12 22:47:12,976 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/160/' from the HTTP cache
2012-10-12 22:47:13,033 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/161/' from the HTTP cache
2012-10-12 22:47:13,092 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/162/' from the HTTP cache
2012-10-12 22:47:13,151 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/163/' from the HTTP cache
2012-10-12 22:47:13,207 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/164/' from the HTTP cache
2012-10-12 22:47:13,266 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/165/' from the HTTP cache
2012-10-12 22:47:13,325 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/166/' from the HTTP cache
2012-10-12 22:47:13,382 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/167/' from the HTTP cache
2012-10-12 22:47:13,440 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/168/' from the HTTP cache
2012-10-12 22:47:13,499 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/169/' from the HTTP cache
2012-10-12 22:47:13,558 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/170/' from the HTTP cache
2012-10-12 22:47:13,615 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/171/' from the HTTP cache
2012-10-12 22:47:13,674 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/172/' from the HTTP cache
2012-10-12 22:47:13,732 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/173/' from the HTTP cache
2012-10-12 22:47:13,789 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/174/' from the HTTP cache
2012-10-12 22:47:13,848 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/175/' from the HTTP cache
2012-10-12 22:47:13,905 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/176/' from the HTTP cache
2012-10-12 22:47:13,963 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/177/' from the HTTP cache
2012-10-12 22:47:14,022 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/178/' from the HTTP cache
2012-10-12 22:47:14,079 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/179/' from the HTTP cache
2012-10-12 22:47:14,138 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/180/' from the HTTP cache
2012-10-12 22:47:14,196 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/181/' from the HTTP cache
2012-10-12 22:47:14,253 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/182/' from the HTTP cache
2012-10-12 22:47:14,312 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/183/' from the HTTP cache
2012-10-12 22:47:14,369 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/184/' from the HTTP cache
2012-10-12 22:47:14,427 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/185/' from the HTTP cache
2012-10-12 22:47:14,486 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/186/' from the HTTP cache
2012-10-12 22:47:14,545 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/187/' from the HTTP cache
2012-10-12 22:47:14,604 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/188/' from the HTTP cache
2012-10-12 22:47:14,661 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/189/' from the HTTP cache
2012-10-12 22:47:14,766 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/190/' from the HTTP cache
2012-10-12 22:47:14,823 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/191/' from the HTTP cache
2012-10-12 22:47:14,881 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/192/' from the HTTP cache
2012-10-12 22:47:14,940 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/193/' from the HTTP cache
2012-10-12 22:47:15,006 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/194/' from the HTTP cache
2012-10-12 22:47:15,063 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/195/' from the HTTP cache
2012-10-12 22:47:15,122 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/196/' from the HTTP cache
2012-10-12 22:47:15,180 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/197/' from the HTTP cache
2012-10-12 22:47:15,237 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/198/' from the HTTP cache
2012-10-12 22:47:15,296 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/199/' from the HTTP cache
2012-10-12 22:47:15,355 (1e08) : DEBUG (networking:155) - Fetching 'http://xkcd.com/200/' from the HTTP cache
2012-10-12 22:47:15,384 (1e08) : DEBUG (services:598) - No service found for URL 'http://imgs.xkcd.com...rrel_cropped_(1).jpg'
2012-10-12 22:47:15,384 (1e08) : DEBUG (services:613) - No matching services found for 'http://imgs.xkcd.com...rrel_cropped_(1).jpg'
2012-10-12 22:47:15,384 (1e08) : DEBUG (services:41) - Loading service code for Fallback (URLServiceRecord)
2012-10-12 22:47:15,464 (1e08) : INFO (services:691) - No normalization function found for URL 'http://imgs.xkcd.com...rrel_cropped_(1).jpg'
2012-10-12 22:47:15,466 (1e08) : DEBUG (services:598) - No service found for URL 'http://imgs.xkcd.com...rrel_cropped_(1).jpg'
2012-10-12 22:47:15,467 (1e08) : CRITICAL (core:561) - Exception when constructing response (most recent call last):
File "E:\Users\Pierre\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\runtime.py", line 870, in construct_response
el = result._to_xml()
File "E:\Users\Pierre\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\api\objectkit.py", line 497, in _to_xml
el = Framework.modelling.objects.ModelInterfaceObjectContainer._to_xml(self)
File "E:\Users\Pierre\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\modelling\objects.py", line 375, in _to_xml
root = Container._to_xml(self)
File "E:\Users\Pierre\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\modelling\objects.py", line 139, in _to_xml
self._append_children(root, self._objects)
File "E:\Users\Pierre\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\modelling\objects.py", line 145, in _append_children
el = obj._to_xml()
File "E:\Users\Pierre\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\api\objectkit.py", line 434, in _to_xml
if self._core.services.function_in_service_is_deferred(Framework.components.services.MEDIA_OBJECTS_FUNCTION_NAME, service):
File "E:\Users\Pierre\AppData\Local\Plex Media Server\Plug-ins\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\services.py", line 552, in function_in_service_is_deferred
service.sandbox.context.import_values(values)
AttributeError: 'NoneType' object has no attribute 'sandbox'

2012-10-12 22:47:15,467 (1e08) : DEBUG (runtime:946) - Unable to handle response type: <class 'Framework.modelling.objects.MediaContainer'>
2012-10-12 22:47:15,469 (1e08) : DEBUG (runtime:843) - Response: [500] MediaContainer, 0 bytes

The URL it is trying to get http://imgs.xkcd.com...rrel_cropped_(1).jpg corresponds to the first entry http://xkcd.com/1/
Could anyone help me with this?
Thanks

#2 Mikedm139

Mikedm139

    Plugin Developer

  • Plex Ninja
  • PipPipPipPipPipPip
  • 2997 posts
  • Location: Canada

Posted 13 October 2012 - 03:21 PM

Hello,
I am trying to update the XKCD plugin. I did it ok using the old structure, but I ran in timeout problems due to the large amount of pictures.
So I decided to rewrite it using the object structure. Here is the code:

<SNIP>

It is in fact quite simple. My problem is that when I introduce the line to add the photoobject, I run into an internal server error:

The URL it is trying to get http://imgs.xkcd.com...rrel_cropped_(1).jpg corresponds to the first entry http://xkcd.com/1/
Could anyone help me with this?
Thanks


It's great to see more people getting involved in plugin development/upgrading. The problem is that when using the "url" parameter for adding a PhotoObject (or VideoObject), PMS tries to find an URL Service to handle the given URL and return a playable/viewable media object. Since no URL Service currently exists for XKCD, the plugin fails to load the objects. The ideal solution to this is to create an URL Service for XKCD. This has the added bonus of allowing support for the PlexIt bookmarklet on the XKCD website as well as other goodies like being able to recommend comics to friends via myPlex. The URL Service for "Lens" is probably the best example at the moment of how to implement an URL Service with PhotoObjects. Once that's done, there's very little else that would need fixing in your code. I've include some commented changes below.

from urlparse import urljoin
from math import ceil

NAME    = 'xkcd'
PLUGIN_PREFIX   = '/photos/xkcd'
ART      = 'art-default.jpg'
ICON 	= 'icon-default.png'
NB_IMAGES = 200
CACHE_1YEAR = 365 * CACHE_1DAY
####################################################################################################
def Start():
''' ViewGroups are no longer respected by all clients and are being removed from plugins to allow clients to maker "smart" decisions about how to display contents '''
    #Plugin.AddViewGroup("List", viewMode="List", mediaType="items")
    #Plugin.AddViewGroup("Pictures", viewMode="Pictures", mediaType="photos")

    # Set the default ObjectContainer attributes
    ObjectContainer.art = R(ART)
    ObjectContainer.title1 = NAME
    #ObjectContainer.view_group = "List" '''see above'''

    # Default icons for DirectoryObject
    DirectoryObject.thumb = R(ICON)
    DirectoryObject.art = R(ART)

    # Set the default cache time
    HTTP.CacheTime = CACHE_1HOUR

####################################################################################################
@handler(PLUGIN_PREFIX, NAME, art = ART, thumb = ICON)
def XKCDMenu():
    archiveURL = 'http://xkcd.com/archive/'
    archiveXPath = '//div[@id="middleContainer"]/a'
    
    oc = ObjectContainer()
    # Get all the elements needed to determine the number of entries and how to sectionize them
    StripsMainPage = HTML.ElementFromURL(archiveURL).xpath(archiveXPath)
    StripsList = [(comic.text, urljoin(archiveURL, comic.get('href'))) for comic in StripsMainPage]
    StripsList.reverse()

    if len(StripsList) < NB_IMAGES:
        #will never happen but will be implemented later on
        pass
    else:
        #Create subdirectories containing a fixed number of images
        nbdir = ceil(float(len(StripsList))/NB_IMAGES)
        for i in xrange(1,nbdir+1):
            firstelt = (i-1)*NB_IMAGES
            lastelt = i*NB_IMAGES
            refs = StripsList[firstelt:lastelt]
            if i == nbdir:
                refs = StripsList[firstelt:]
                lastelt = len(StripsList)
            name = '%d - %d' % (firstelt+1, lastelt)
	   ''' Forcing the plugin to load every page and grab the thumb in order is very slow. Using a Callback to generate the thumb allows them to load asynchronously'''
            #img = GetDirectoryIcon(StripsList[firstelt])
            oc.add(DirectoryObject(key = Callback(StripDirectory, id = i, stripsdata = refs), title = name, thumb = Callback(GetDirectoryIcon, StripsList[firstelt])))
    return oc

####################################################################################################
''' the @route is much simpler if you make it explicit for each function rather than using variables to define a changeable route'''
@route('/photos/xkcd/stripdir')
#@route('%s/dir-{id}' % PLUGIN_PREFIX, method='POST')
def StripDirectory(id, stripsdata, sender = None):
    imgXpath = '//div[@id="comic"]//img'
    # oc = ObjectContainer(view_group = 'Pictures')
    #oc = ObjectContainer(view_group = 'List') ''' see comments re: View Groups above '''

    for (title,comicURL) in stripsdata:
        imgs = HTML.ElementFromURL(comicURL, cacheTime=CACHE_1YEAR).xpath(imgXpath)
        if len(imgs):
            img = imgs[0].get('src')
            resume = imgs[0].get('title')
	   ''' Use the actual page url for the url parameter to call the URL Service and have it return the MediaObject. Also,
		use a callback to make thumb loading asynchronous
	      oc.add(PhotoObject(url=comicURL, title=title, thumb=Resource.ContentsOfURLWithFallback(url=img, fallback=ICON), summary=resume))
            #oc.add(PhotoObject(url=img, title=title, thumb=img, summary=resume))
    return oc

####################################################################################################
''' add a @route for each function '''
@route('/photos/xkcd/getdir')
def GetDirectoryIcon(stripdata):
    imgXpath = '//div[@id="comic"]//img'
    imgs = HTML.ElementFromURL(stripdata[1], cacheTime=CACHE_1YEAR).xpath(imgXpath)
    img = R(ICON)
    if len(imgs):
        img = imgs[0].get('src')
    return img

Here's a good place to do a little reading about URL Services. If you run into any more trouble, just ask.

P.S. I'm moving this thread to the Channel Development sub-forum.

If you are having trouble with one or more channels, check here first.
If you are asked to provide logs, which you will be if you are having plugin problems, the help center has details on where to find them.
***************************************************************************************************************************************
Check out unofficial channels in the
UnSupported AppStore
Follow my efforts on Github and Twitter
Donate


#3 Sengian

Sengian

    Member

  • Members
  • PipPip
  • 28 posts

Posted 13 October 2012 - 04:53 PM

Thank you for your answer and your help.
Indeed, I posted in the wrong subforum but I didn't find how to change it (don't know if it is even possible for me)

Concerning your comments, I have a few questions. I will look around about the URL service, no problem.

For the routes, I am a little confused: the decorator is only used to give the function a quick way to be accessed by a link with parameters ie like an URL request?
Then what is the interest to use a parameter {x}? I based this part on the National geographic plug-in and I thought this was to get dedicated access for subdirectories.
Did I misunderstand this or was there another reason?

''' Forcing the plugin to load every page and grab the thumb in order is very slow. Using a Callback to generate the thumb allows them to load asynchronously'''
Basically, what you are saying is that any manageable URL call should be handled by a callback function until the bottom level function.

I will look at service for the last comment.

Thanks again.

#4 Mikedm139

Mikedm139

    Plugin Developer

  • Plex Ninja
  • PipPipPipPipPipPip
  • 2997 posts
  • Location: Canada

Posted 14 October 2012 - 12:19 AM

Thank you for your answer and your help.
Indeed, I posted in the wrong subforum but I didn't find how to change it (don't know if it is even possible for me)

No worries. It's really not a big deal :)

Concerning your comments, I have a few questions. I will look around about the URL service, no problem.

For the routes, I am a little confused: the decorator is only used to give the function a quick way to be accessed by a link with parameters ie like an URL request?
Then what is the interest to use a parameter {x}? I based this part on the National geographic plug-in and I thought this was to get dedicated access for subdirectories.
Did I misunderstand this or was there another reason?

TBH, I've only recently started using @route decorators. They're not technically "required". The framework will create them begin the scenes as necessary but then it fills up the logs with message about missing Routes. I haven't looked at National Geo since the @routes were added. Perhaps Jam or one of the other plugin devs can chime in with some clarification.

''' Forcing the plugin to load every page and grab the thumb in order is very slow. Using a Callback to generate the thumb allows them to load asynchronously'''
Basically, what you are saying is that any manageable URL call should be handled by a callback function until the bottom level function.

Essentially, the concept is that when building a list, the concept is to minimize the number of HTTP requests because that really slows things down. Since grabbing a thumb image usually requires at least one HTTP request per item, separating that logic into a callback allows the plugin to load and return the list without waiting for every thumbnail to return. The key (if used) and thumb parameters are the (I think) only ones that will take a Callback to allow asynchronous loading.

I will look at service for the last comment.

Thanks again.


Glad to help. Always happy to see people taking an interest in plugin development.
  • Sengian likes this

If you are having trouble with one or more channels, check here first.
If you are asked to provide logs, which you will be if you are having plugin problems, the help center has details on where to find them.
***************************************************************************************************************************************
Check out unofficial channels in the
UnSupported AppStore
Follow my efforts on Github and Twitter
Donate


#5 Sengian

Sengian

    Member

  • Members
  • PipPip
  • 28 posts

Posted 14 October 2012 - 03:24 PM

Ok.
First, I have a working version of the plugin attached Attached File  xkcd.bundle-v2-working.rar   101.81KB   32 downloads and a not working version I tried to build as Lens with photo album Attached File  xkcd.bundle-not working.rar   100.61KB   28 downloads. I really would love to understand why some things are not working, but nevermind.

Nevertheless, I still have a few questions:

The key (if used) and thumb parameters are the (I think) only ones that will take a Callback to allow asynchronous loading.

You are totally right and this a pain in the ass for me.

Ok, the main bottle neck in this plugin is metadata retrieval ie the part roughly constructed like this:
@route('/photos/xkcd/stripdir')
def StripDirectory(stripsstart, stripsstop, sender = None):
    imgXpath = '//div[@id="comic"]//img'
    oc = ObjectContainer()

    for comicURL in GetStripList()[int(stripsstart):int(stripsstop)]:
        imgs = HTML.ElementFromURL(comicURL, cacheTime=CACHE_1YEAR).xpath(imgXpath)[0]
        img = imgs.get('src')
        resume = imgs.get('title')
        titre = imgs.get('alt')
        oc.add(PhotoObject(url=comicURL, title=titre, thumb=Callback(GetIcon, stripURL=comicURL), summary=resume))
    return oc
The for is making a lot of HTTP calls to get metadata.
First idea was to use Callback to use Plex thread system to speed it -->Not possible
Second idea, use a MetadataFromURL:
test = URLService.MetadataObjectForURL(url=comicURL)
test.add(URLService.MediaObjectsForURL(url=comicURL))
oc.add(test)
This is not working (I would love the code to make it work) and should be bad code, but in this case as you have to call the URL to get metadata, it would in fact be the more efficient method.
URLService.MetadataObjectForURL(url=comicURL) is however slower than the previous code which I don't understand.
Finally, I thought about using PhotoAlbum but don't know exactly what is the interest of this structure.

Anyway, I can nix it by adding threading (I think) but frankly I am not so much interested in going to the big guns if I can do it otherwise.

Another problem which should be easier to solve, is how to put text under the image when you tap it. Previously, I used the summary property but with PhotoObject this doesn't seem to work.
Anyway, I would love to manage the way this is displayed on my tablet but this doesn't easy.
I even have rating under the image in some cases.
Another weird think is that if I don't define a thumb, I don't have any image anymore only a thumb. Hum...

OK, then I think that summ it all! Any help welcome.

#6 Velociraptor

Velociraptor

    Newbie

  • Members
  • Pip
  • 5 posts

Posted 25 December 2012 - 12:50 PM

hi :)
any updates? Is this already in the git(AppStore)?

#7 Sengian

Sengian

    Member

  • Members
  • PipPip
  • 28 posts

Posted 31 December 2012 - 05:08 AM

I forked the modifications on git. I used a working solution, not exactly what I wanted but it gets the job done.
Concerning new modifications, nothing is planned. I won't put any more work on this til there is a decent working doc or people answering technical questions.

#8 Sengian

Sengian

    Member

  • Members
  • PipPip
  • 28 posts

Posted 19 March 2014 - 10:40 PM

Well, having some time on my hands and a new NAS, I got back to this plugin.

A new working and improved version is on my git account: https://github.com/sengian/xkcd.bundle/

 

I still have this old problem about service so as this would really be more efficient, I ask the question:
Is there a way to call an url without a service using a PhotoObject? (I would really love to be able to do this)



#9 Sengian

Sengian

    Member

  • Members
  • PipPip
  • 28 posts

Posted 19 March 2014 - 10:48 PM

As a bonus (if anyone is interested), my windows batch script to kill, copy and restart the server. Not sure it is necessary but it works!

@echo off
@setlocal
set path="C:\Program Files (x86)\Mozilla Firefox\";%path%
set plugin=Path to your Plugin
set devfolder=Path to your Plugin dev folder
set start="C:\Program Files (x86)\Plex\Plex Media Server\Plex Media Server.exe"
set program="Plex Media Server.exe"

taskkill /IM %program% /T /F
timeout 1
robocopy "%devfolder%" "%plugin%" /s /xf "Update.bat" ".gitignore" /xd ".git"
start "" %start%
timeout 1
firefox http://localhost:32400/web/index.html#!/dashboard