planet/planet/foaf.py

198 lines
6.6 KiB
Python

from ConfigParser import ConfigParser
inheritable_options = [ 'online_accounts' ]
def load_accounts(config, section):
accounts = {}
if(config.has_option(section, 'online_accounts')):
values = config.get(section, 'online_accounts')
for account_map in values.split('\n'):
try:
homepage, map = account_map.split('|')
accounts[homepage] = map
except:
pass
return accounts
def load_model(rdf, base_uri):
if hasattr(rdf, 'find_statements'):
return rdf
if hasattr(rdf, 'read'):
rdf = rdf.read()
def handler(code, level, facility, message, line, column, byte, file, uri):
pass
from RDF import Model, Parser
model = Model()
Parser().parse_string_into_model(model,rdf,base_uri,handler)
return model
# input = foaf, output = ConfigParser
def foaf2config(rdf, config, subject=None, section=None):
if not config or not config.sections():
return
# there should be only be 1 section
if not section: section = config.sections().pop()
try:
from RDF import Model, NS, Parser, Statement
except:
return
# account mappings, none by default
# form: accounts = {url to service homepage (as found in FOAF)}|{URI template}\n*
# example: http://del.icio.us/|http://del.icio.us/rss/{foaf:accountName}
accounts = load_accounts(config, section)
depth = 0
if(config.has_option(section, 'depth')):
depth = config.getint(section, 'depth')
model = load_model(rdf, section)
dc = NS('http://purl.org/dc/elements/1.1/')
foaf = NS('http://xmlns.com/foaf/0.1/')
rdfs = NS('http://www.w3.org/2000/01/rdf-schema#')
rdf = NS('http://www.w3.org/1999/02/22-rdf-syntax-ns#')
rss = NS('http://purl.org/rss/1.0/')
for statement in model.find_statements(Statement(subject,foaf.weblog,None)):
# feed owner
person = statement.subject
# title is required (at the moment)
title = model.get_target(person,foaf.name)
if not title: title = model.get_target(statement.object,dc.title)
if not title:
continue
# blog is optional
feed = model.get_target(statement.object,rdfs.seeAlso)
if feed and rss.channel == model.get_target(feed, rdf.type):
feed = str(feed.uri)
if not config.has_section(feed):
config.add_section(feed)
config.set(feed, 'name', str(title))
# now look for OnlineAccounts for the same person
if accounts.keys():
for statement in model.find_statements(Statement(person,foaf.holdsAccount,None)):
rdfaccthome = model.get_target(statement.object,foaf.accountServiceHomepage)
rdfacctname = model.get_target(statement.object,foaf.accountName)
if not rdfaccthome or not rdfacctname: continue
if not rdfaccthome.is_resource() or not accounts.has_key(str(rdfaccthome.uri)): continue
if not rdfacctname.is_literal(): continue
rdfacctname = rdfacctname.literal_value['string']
rdfaccthome = str(rdfaccthome.uri)
# shorten feed title a bit
try:
servicetitle = rdfaccthome.replace('http://','').split('/')[0]
except:
servicetitle = rdfaccthome
feed = accounts[rdfaccthome].replace("{foaf:accountName}", rdfacctname)
if not config.has_section(feed):
config.add_section(feed)
config.set(feed, 'name', "%s (%s)" % (title, servicetitle))
if depth > 0:
# now the fun part, let's go after more friends
for statement in model.find_statements(Statement(person,foaf.knows,None)):
friend = statement.object
# let's be safe
if friend.is_literal(): continue
seeAlso = model.get_target(friend,rdfs.seeAlso)
# nothing to see
if not seeAlso or not seeAlso.is_resource(): continue
seeAlso = str(seeAlso.uri)
if not config.has_section(seeAlso):
config.add_section(seeAlso)
copy_options(config, section, seeAlso,
{ 'content_type' : 'foaf',
'depth' : str(depth - 1) })
try:
from planet.config import downloadReadingList
downloadReadingList(seeAlso, config,
lambda data, subconfig : friend2config(model, friend, seeAlso, subconfig, data),
False)
except:
pass
return
def copy_options(config, parent_section, child_section, overrides = {}):
global inheritable_options
for option in [x for x in config.options(parent_section) if x in inheritable_options]:
if not overrides.has_key(option):
config.set(child_section, option, config.get(parent_section, option))
for option, value in overrides.items():
config.set(child_section, option, value)
def friend2config(friend_model, friend, seeAlso, subconfig, data):
try:
from RDF import Model, NS, Parser, Statement
except:
return
dc = NS('http://purl.org/dc/elements/1.1/')
foaf = NS('http://xmlns.com/foaf/0.1/')
rdf = NS('http://www.w3.org/1999/02/22-rdf-syntax-ns#')
rdfs = NS('http://www.w3.org/2000/01/rdf-schema#')
# FOAF InverseFunctionalProperties
ifps = [foaf.mbox, foaf.mbox_sha1sum, foaf.jabberID, foaf.aimChatID,
foaf.icqChatID, foaf.yahooChatID, foaf.msnChatID, foaf.homepage, foaf.weblog]
model = load_model(data, seeAlso)
for statement in model.find_statements(Statement(None,rdf.type,foaf.Person)):
samefriend = statement.subject
# maybe they have the same uri
if friend.is_resource() and samefriend.is_resource() and friend == samefriend:
foaf2config(model, subconfig, samefriend)
return
for ifp in ifps:
object = model.get_target(samefriend,ifp)
if object and object == friend_model.get_target(friend, ifp):
foaf2config(model, subconfig, samefriend)
return
if __name__ == "__main__":
import sys, urllib
config = ConfigParser()
for uri in sys.argv[1:]:
config.add_section(uri)
foaf2config(urllib.urlopen(uri), config, section=uri)
config.remove_section(uri)
config.write(sys.stdout)