Skip to content
Snippets Groups Projects
foaf.py 6.55 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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)