コード例 #1
0
ファイル: models.py プロジェクト: mavit/GRead
 def create_g_object(self):
     """
     Will create a GoogleReader instance. Also make special category.
     """
     # create the object from libgreader
     self.g_object = GoogleReader(self.g_auth)
     # create the category for special feeds
     self.g_object.makeSpecialFeeds()
     self.special_category = SpecialCategory(self)
     self.add_category(self.special_category)
コード例 #2
0
ファイル: models.py プロジェクト: mavit/GRead
class Account(object):
    """
    A Google Reader account.
    We store it's login, it's password, and a ClientAuth object from 
    libgreader and a list of categories.
    The id is the login
    """
    _current = None
    
    def __init__(self, id=None, password=None):
        """
        Instantiate a new Account
        """
        if not id:
            id = str(settings.get('google', 'account'))
        self.id               = id
        self.categories       = []
        self.categories_by_id = {}
        self.is_authenticated = False
        
        # An operation manager for this account
        self.operations_manager = OperationsManager(self,  callbacks = {
            'get_feed_content_done':      self.operation_get_feed_content_done, 
            'get_more_feed_content_done': self.operation_get_feed_content_done, 
        })
        # ClientAuth object (from libgreader)
        self.g_auth = None
        # GoogleReader object (from libgreader)
        self.g_object = None
        
        # category for special feeds
        self.special_category = None
        # and one for orphan feeds
        self.orphan_feeds_category = None
        
        # total unread count
        self.unread = 0
    
    @classmethod
    def get_current(cls):
        """
        A class method returning the current account
        """
        return cls._current
        
    def authenticate(self):
        """
        Create an asynchronous operation to authenticate this account
        """
        self.operations_manager.add(OperationAuthenticate(object=self))
        
    def dist_authenticate(self):
        """
        Authenticate the account with Google Reader
        """
        was_authenticated = self.is_authenticated
        self.is_authenticated = False
        try:
            # if this account was previously authenticated, we try to get
            # another token
            if self.g_auth and was_authenticated:
                try:
                    sys.stderr.write("AUTH: update token\n")
                    self.g_auth.token = self.g_auth._getToken()
                    sys.stderr.write("AUTH: token=%s\n" % self.g_auth.token)
                    self.is_authenticated = True
                    settings.set('google', 'token', self.g_auth.token, save_all=True)
                except:
                    pass

            # else, but if we already had tokens by the past, try with them
            elif settings.get('google', 'auth_token') and settings.get('google', 'token'):
                sys.stderr.write("AUTH: load saved auth\n")
                self.g_auth = SavedAuth(settings.get('google', 'account'), \
                                        settings.get('google', 'password'), \
                                        settings.get('google', 'auth_token'), \
                                        settings.get('google', 'token'))
                try:
                    # test if the token is still valid
                    self.g_auth.token = self.g_auth._getToken()
                except:
                    pass
                else:
                    # it's valid so we are authenticated
                    settings.set('google', 'token', self.g_auth.token, save_all=True)
                    self.is_authenticated = True
                    
            # here, we have not a valid token, so we do a full authentication
            if not self.is_authenticated:
                sys.stderr.write("AUTH: full auth\n")
                self.g_auth = ClientAuth(settings.get('google', 'account'), settings.get('google', 'password'))
                self.is_authenticated = True
                settings.set('google', 'verified', True)
                settings.set('google', 'auth_token', self.g_auth.auth_token)
                settings.set('google', 'token', self.g_auth.token, save_all=True)

            # finally if we are authenticated, update, or create, a new 
            # GoogleReadr object
            if self.is_authenticated:
                if self.g_object:
                    self.g_object.auth = self.g_auth
                else:
                    self.create_g_object()

        # an exception was raised during the authentication. 
        # it is either a authentication failure, or a network failure
        # but let the caller manage this
        except:
            self.is_authenticated = False
            raise
            
    def assert_authenticated(self):
        """
        Raise an exception if the account is not authenticated
        """
        if not self.is_authenticated:
            raise NotAuthenticatedError("Account is not authenticated")
                
    def create_g_object(self):
        """
        Will create a GoogleReader instance. Also make special category.
        """
        # create the object from libgreader
        self.g_object = GoogleReader(self.g_auth)
        # create the category for special feeds
        self.g_object.makeSpecialFeeds()
        self.special_category = SpecialCategory(self)
        self.add_category(self.special_category)
        
    def add_category(self, category):
        """
        Add an category to this account
        """
        if not category.id in self.categories_by_id:
            self.categories_by_id[category.id] = category
            self.categories.append(category)
            
    def fetch_feeds(self, fetch_unread_content=False):
        """
        Create an asynchronous operation to fetch feeds for this account
        """
        self.operations_manager.add(OperationGetAccountFeeds(
            object=self, fetch_unread_content=fetch_unread_content))
            
    def dist_fetch_feeds(self):
        """
        Get google reader feeds for this account
        """
        self.assert_authenticated()
        
        # get content from Google Reader
        self.g_object.buildSubscriptionList()
        
        # if no content, there is a problem : raise
        g_feeds = self.g_object.getFeeds()
        if not g_feeds:
            raise AccountHasNoFeedsError
        
        # add each category
        for g_category in self.g_object.getCategories():
            category = Category.get_by_id(g_category.id, account=self)
            if not category:
                category = Category(
                    id         = g_category.id, 
                    account    = self, 
                    g_category = g_category, 
                )
                self.add_category(category)
            else:
                category.g_category = g_category
            
        # add each feed
        total_unread = 0
        for g_feed in g_feeds:
            total_unread += g_feed.unread
            feed = Feed.get_by_id(g_feed.id, account=self)
            if not feed:
                feed = Feed(
                    id      = g_feed.id, 
                    account = self, 
                    g_feed  = g_feed, 
                )
            old_unread = feed.unread
            feed.unread = g_feed.unread
            feed.update_missing_unread()
            # now no unread and then we have ones : mark all items as read !
            if old_unread and not feed.unread:
                for item in feed.items:
                    item.unread = True
            # update feed's categories
            for g_category in g_feed.getCategories():
                category = Category.get_by_id(g_category.id, account=self)
                category.add_feed(feed)
                
        # we have orphan feeds ?
        if self.g_object.orphanFeeds:
            if not self.orphan_feeds_category:
                self.orphan_feeds_category = OrphanFeedsCategory(self)
                self.add_category(self.orphan_feeds_category)
            for g_feed in self.g_object.orphanFeeds:
                feed = Feed.get_by_id(g_feed.id, account=self)
                self.orphan_feeds_category.add_feed(feed)
                
        # update unread counts
        self.special_category.special_feeds[GoogleReader.READING_LIST].unread = total_unread
        for feed in self.special_category.feeds:
            if feed.special_type not in (GoogleReader.READING_LIST,  GoogleReader.READ_LIST):
                feed.unread = feed.g_feed.unread
        for category in self.categories:
            category.update_unread()
        self.update_unread()
            
    def fetch_unread_content(self):
        """
        Fetch the unread content for all categories
        """
        # first for normal categories
        for category in self.get_categories(unread_only=True)[1:]:
            category.fetch_content(unread_only=True)
        # then for the special one
        self.special_category.fetch_content(unread_only=True)

    def update_unread(self):
        """
        Update the unread count : number of unread items in all feeds
        """
        self.unread = self.special_category.unread
        return self.unread
        
    def get_categories(self, unread_only=False, order_by=None, reverse_order=None):
        """
        Get the list of all categories, filtering only unread if asked, and
        ordering them as asked.
        order_by can be "title" or "unread" (default None, say as in GoogleReder)
        By default reverse_order is False for "title" and True for "unread"
        """
        result = self.categories[:1] # special category always first

        to_sort = []
        if unread_only:
            to_sort = [category for category in self.categories[1:] if category.unread]
        else:
            to_sort= self.categories[1:]
        
        if order_by == 'title':
            if reverse_order is None:
                reverse_order = False
            result += sorted(to_sort, key=locale_keyfunc(attrgetter('title')),\
                reverse=reverse_order)
        elif order_by == 'unread':
            if reverse_order is None:
                reverse_order = True
            result += sorted(to_sort, key=attrgetter('unread'),\
                reverse=reverse_order)
        else:
            result += to_sort
    
        return result
        
    def category_unread_count_changed(self, category):
        """
        When the unread count of a category has changed, this method is called
        to update the total unread count
        """
        if category != self.special_category:
            self.special_category.update_unread()
        self.update_unread()
    
    @property
    def normal_feeds(self):
        """
        Return feeds excluding special ones
        """
        return [feed for feed in Feed.get_for_account(self) if feed.__class__ == Feed]        
        
    def operation_get_feed_content_done(self, operation):
        """
        Called by the operations manager when a "get_feed_content" or
        "get_more_feed_content" operation is done. If the "max_fetch" parameter
        for this operation is not None, then we have to fetch more content for
        this feed.
        """
        if operation.params.get('max_fetch', None) is not None:
            operation.params['object'].fetch_content_next_part(
                unread_only = operation.params.get('unread_only', False), 
                max_fetch   = operation.params['max_fetch'], 
            )