# # From http://www.kosta.tk/2008/06/02/python-diigo-bookmarks-mover-and-diigo-api import logging logger = logging.getLogger("modules.Diigo") import conduit import conduit.utils as Utils import conduit.utils.Memstats as Memstats import conduit.TypeConverter as TypeConverter import conduit.dataproviders.DataProvider as DataProvider import conduit.dataproviders.DataProviderCategory as DataProviderCategory import conduit.dataproviders.SimpleFactory as SimpleFactory import conduit.dataproviders.Image as Image import conduit.dataproviders.File as FileDataProvider import conduit.Exceptions as Exceptions import conduit.Web as Web from conduit.datatypes import Rid, DataType, Bookmark import simplejson # for encoding/decoding json<->python import urllib2 # For interacting with the diigo servers import urllib # For encoding queries to be transmitted via POST import time # For waiting between queries import sys # For the logging methods. from optparse import OptionParser # For parsing commandline options. # Constants: API_SERVER = "api2.diigo.com" BOOKMARKS_URL = "http://api2.diigo.com/bookmarks" INFO=3 DEBUG=6 FULL=9 # /Constants def getUserBookmarks(username): """ Takes a username from which to extract the bookmarks. Optionaly takes a password to extract private bookmarks. Returns a list with the user's bookmarks. This function does not handle authentication and therefore urllib2 should be set up correctly in advance. """ response = '' json = [] start = 0 # The diigo api returns up to 100 bookmarks at a time. # Therefore we iterate until we stop getting bookmarks. while response != '[]': # Get the bookmarks in json format from the diigo api bookmarks = urllib2.urlopen(BOOKMARKS_URL + '?users=' + username +'&start=' + str(start)) response = bookmarks.read() json.extend( simplejson.loads(response) ) break # Wait a little to not choke the api servers, then get the next 100 time.sleep(2) start += 100 return json def addUserBookmarks(username, bookmarks): """ Takes a username for which we are adding bookmarks and list containint the bookmarks to be added. This function does not handle authentication and therefore urllib2 should be set up correctly in advance. """ for bookmark in bookmarks: # Delete unnecessary fields to conserve bandwidth. # The diigo api ignores them at the moment. if bookmark['user']: del bookmark['user'] if bookmark['created_at']: del bookmark['created_at'] if bookmark['updated_at']: del bookmark['updated_at'] if type(bookmark) == dict: # The diigo api requires the tag list to be a comma seperated # string, so if it is a dict we parse and format it tags = '' for tag in bookmark['tags']: tags += tag + ', ' else: tags = tags[:-2] bookmark['tags'] = tags # The diigo api only allows to add up to 100 bookmarks at a time # so we iterate and send 100 bookmarks each time. iterations = len(bookmarks)/100 + 1 for range_index in range(iterations): # Take 100 bookmarks or what's left when there is less then 100 if range_index == iterations - 1: partial_bookmarks = bookmarks[range_index*100 : ] else: partial_bookmarks = bookmarks[range_index*100 : (range_index+1)*100] # Turn the list into json for sending over http json = simplejson.dumps(partial_bookmarks) # Encode the json into a safe format for transmission data = urllib.urlencode({'bookmarks':json}) # Submit the bookmark response = urllib2.urlopen(BOOKMARKS_URL, data) # Sleep a little to not load up the api servers time.sleep(2) return len(bookmarks) def basicAuthSetup(user, password, naked_url): """ Sets up urllib2 to automatically use basic authentication in the supplied url (which is supplied w/o the protocol) using the supplied username and password """ passman = urllib2.HTTPPasswordMgrWithDefaultRealm() # This will use the supplied user/password for all # child urls of naked_url because of the 'None' param. passman.add_password(None, naked_url, user, password) # This creates and assigns a custom authentication handler # for urllib2, which will be used when we call urlopen. authhandler = urllib2.HTTPBasicAuthHandler(passman) opener = urllib2.build_opener(authhandler) urllib2.install_opener(opener) MODULES = { "Diigo": {'type': 'dataprovider'}, } class Diigo(DataProvider.TwoWay): _name_ = "Diigo" _description_ = "Emits TestDataTypes" _category_ = conduit.dataproviders.CATEGORY_MISC _module_type_ = "twoway" _in_type_ = "Bookmark" _out_type_ = "Bookmark" _icon_ = "go-next" _configurable_ = True DEFAULT_NUM_DATA = 10 def __init__(self, *args): DataProvider.DataSource.__init__(self) self.data = {} self.numData = self.DEFAULT_NUM_DATA self.username = '' self.password = '' self.UID = 'Diigo' self.slow = False def initialize(self): return True def configure(self, window): import gtk import conduit.gtkui.SimpleConfigurator as SimpleConfigurator def setUsername(param): self.username = param def setPassword(param): self.password = param items = [ { "Name" : "Username:", "Widget" : gtk.Entry, "Callback" : setUsername, "InitialValue" : self.username }, { "Name" : "Password:", "Widget" : gtk.Entry, "Callback" : setPassword, "InitialValue" : self.password }, ] dialog = SimpleConfigurator.SimpleConfigurator(window, self._name_, items) dialog.run() def get_UID(self): return self.UID def get_configuration(self): return { "UID" : self.UID, "username" : self.username, "password" : self.password, } def refresh(self): basicAuthSetup(self.username, self.password, BOOKMARKS_URL) DataProvider.DataSource.refresh(self) data = getUserBookmarks(self.username) self.data = {} for obj in data: self.data[obj['url']] = obj def get_all(self): DataProvider.DataSource.get_all(self) logger.info("getall") data = [] for i in self.data: data.append(i) return data def get(self, LUID): DataProvider.DataSource.get(self, LUID) if self.slow: time.sleep(1) data = Bookmark.Bookmark(title=self.data[LUID]['title'], uri=LUID) data.set_UID(LUID) data.set_open_URI(LUID) return data def finish(self, aborted, error, conflict): DataProvider.DataSource.finish(self) self.data = []