Skip to content

Instantly share code, notes, and snippets.

@koenbollen
Created July 4, 2010 20:44
Show Gist options
  • Save koenbollen/463742 to your computer and use it in GitHub Desktop.
Save koenbollen/463742 to your computer and use it in GitHub Desktop.
Download a random wallpaper from go4celebrity.com
#!/usr/bin/env python
# Koen Bollen <meneer koenbollen nl>
# 2010 GPL
#
# Download an random wallpaper from go4celebrity.com
#
#
# My setup:
# =========
#
# Set gnome's background to "~/.wallpaper" and let crontab execute
# the following script every X minutes: (gnome updates automatically)
#
# file: next.sh
# #!/bin/bash
# # Sets the next wallpaper.
#
# target=$HOME/.wallpaper
# name=$(go4celebrity.py -n "$1" -s 1680x1050 -f "%(name)s" -d /tmp/wallpaper)
# mv /tmp/wallpaper $target
# echo $name > $target.txt
# notify-send "Wallpaper:" "$name"
#
# Have fun!
#
from collections import namedtuple
from optparse import OptionParser
from time import time, sleep
import cPickle as pickle
import multiprocessing
import os
import random
import re
import sys
from functools import partial
import urllib2
celebrity = namedtuple( "celebrity", "id name images" )
image = namedtuple( "image", "url width height celebrity" )
dbfile = os.path.expanduser( "~/.go4celebrity.db" )
workers = 50
def download( url, fp=None ):
response = None
try:
req = urllib2.Request( url, headers={"User-Agent": "FF"} )
response = urllib2.urlopen( req, timeout=5 )
if fp is not None:
while True:
chunk = response.read( 4096 )
if not chunk: break
fp.write( chunk )
else:
data = response.read()
return data
except IOError, e:
if fp is None:
return None
raise
finally:
if response:
response.close()
def evaljs( data ):
mtch = evaljs.rx.search( data )
if not mtch:
return []
return eval( mtch.group(1) )
evaljs.rx = re.compile( r"var .=(\[\[.*\]\])", re.M |re.S )
def fetch( data ):
id, name, count = data
c = celebrity( id, name, [] )
tries = 10
while tries > 0:
data = download( "http://www.go4celebrity.com/celebrities/view_js/%d"%id )
if data is not None:
break
sleep( 1 )
tries -= 1
if data is None:
return None
for row in evaljs( data ):
_,_,w,h,file,_,_,_,_,_ = row
slug = name.replace( " ", "-" )
url = "http://static.go4celebrity.com/wallpapers/%s/%s" % (slug,file)
c.images.append( image( url, w, h, c ) )
sleep( 0.5 )
return c
def fetchcache():
pool = multiprocessing.Pool( processes=workers )
data = download( "http://www.go4celebrity.com/celebrities/js_array" )
records = evaljs(data)
celebrities = pool.map( fetch, records, len(records)/workers )
pool.close()
result = ( celebrities, time() )
with open( dbfile, "wb" ) as fp:
pickle.dump( result, fp, -1 )
return result
def getcache(i=0):
try:
with open( dbfile ) as fp:
celebrities, created = pickle.load( fp )
except IOError, (n,s):
if n != 2:
raise
print >>sys.stderr, "no cache found, downloading..."
try:
if i >= 1: raise IOError
with open( dbfile, "wb" ) as fp:
download( "http://koen.it/upload/go4celebrity.db", fp )
return getcache(i+1)
except IOError:
celebrities, created = fetchcache()
else:
if time()-created > 60*60*24*7:
print >>sys.stderr, "cache expired, downloading..."
celebrities, created = fetchcache()
return celebrities
def lev(s,t):
s = ' ' + s
t = ' ' + t
d = {}
S = len(s)
T = len(t)
for i in range(S):
d[i, 0] = i
for j in range (T):
d[0, j] = j
for j in range(1,T):
for i in range(1,S):
if s[i] == t[j]:
d[i, j] = d[i-1, j-1]
else:
d[i, j] = min(d[i-1, j] + 1, d[i, j-1] + 1, d[i-1, j-1] + 1)
return d[S-1, T-1]
def score( input, name ):
input = input.lower()
name = name.lower()
score = 0
for word in input.split():
score += min( [lev(word, n) for n in name.split()] )
return score
def main():
op = OptionParser()
op.add_option( "-d", "--download", metavar="FILE",
help="download wallpaper to FILE" )
op.add_option( "-f", "--format", metavar="FMT",
default="%(url)s", help="set output format" )
op.add_option( "-n", "--name", metavar="NAME",
help="select wallpaper from celebrity NAME" )
op.add_option( "-s", "--size", metavar="WxH",
help="find wallpaper by resolution" )
options, args = op.parse_args()
if options.size:
try:
options.size = map(int, options.size.split("x",1) )
except ValueError:
op.error( "option -s expects: WxH" )
celebrities = getcache()
if options.name:
curried = partial( score, options.name )
scores = sorted( [ (curried(c.name), c) for c in celebrities if c] )
c = scores[0][1]
celebrities = [c]
if options.size:
w, h = options.size
images = []
for i in reduce( lambda x,y: x+y, [c.images for c in celebrities if c]):
diff = abs( i.width - w ) + abs( i.height - h )
images.append( (diff, i) )
images.sort()
dist = images[0][0]
images = [i[1] for i in images if i[0] == dist]
else:
images = reduce( lambda x,y: x+y, [c.images for c in celebrities if c])
celebrities = {}
for i in images:
cid = i.celebrity.id
if cid not in celebrities:
celebrities[cid] = []
celebrities[cid].append( i )
images = random.choice( celebrities.values() )
i = random.choice( images )
c = i.celebrity
context = {
'id': c.id,
'name': c.name,
'url': i.url,
'width': i.width,
'height': i.height,
}
if options.format:
try:
print options.format % context
except KeyError, e:
print >>sys.stderr, "invalid format key:", e,
print >>sys.stderr, "(availible: "+", ".join(context.keys())+")"
if options.download:
try:
with open( options.download, "wb" ) as fp:
download( i.url, fp )
except IOError, e:
print >>sys.stderr, "unable to download image:", e
if __name__ == "__main__":
main()
# vim: expandtab shiftwidth=4 softtabstop=4 textwidth=79:
@K405
Copy link

K405 commented Jul 8, 2010

gnome2

#!/bin/bash

Sets the next wallpaper.

target=$HOME/.wallpaper
name=$($HOME/go4celebrity.py -n "$1" -s 1600x1200 -f "%(name)s" -d /tmp/wallpaper)
mv /tmp/wallpaper $target
gconftool-2 -t string -s /desktop/gnome/background/picture_filename $HOME/.wallpaper/wallpaper
echo $name > $target.txt
notify-send "Wallpaper:" "$name"

@koenbollen
Copy link
Author

K405, that's not necessary. If you overwrite the wallpaper file gnome detects this and automatically updates your background.

@K405
Copy link

K405 commented Jul 8, 2010

In Ubuntu 10.04 LTS Lucid Lynx overwriting the chosen background image file with a new background image file doesn't automatically change it to the new image.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment