def save_data(self, token, trigger_id, **data):
        """
            let's save the data
        """
        if token and 'link' in data and data['link'] is not None and len(data['link']) > 0:
            # get the data of this trigger
            trigger = Readability.objects.get(trigger_id=trigger_id)
            token_key, token_secret = token.split('#TH#')
            readability_instance = ReaderClient(self.consumer_key,
                                                self.consumer_secret,
                                                token_key,
                                                token_secret)

            bookmark_id = readability_instance.add_bookmark(url=data['link'])

            if trigger.tag is not None and len(trigger.tag) > 0:
                try:
                    readability_instance.add_tags_to_bookmark(
                        bookmark_id, tags=(trigger.tag.lower()))
                    sentence = str('readability {} created item id {}').format(
                        data['link'], bookmark_id)
                    logger.debug(sentence)
                except Exception as e:
                    logger.critical(e)
        else:
            sentence = "no token or link provided for trigger ID {} "
            logger.critical(sentence.format(trigger_id))
class ReaderClientNoBookmarkTest(TestCase):
    """Tests for the Readability ReaderClient class that need no bookmarks.

    """
    def setUp(self):
        """Need to get a token for each test.

        """
        token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD)
        self.token_key = token_pair[0]
        self.token_secret = token_pair[1]

        self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET,
            self.token_key, self.token_secret)

    def test_get_article(self):
        """Test the `get_article` method.

        """
        article_id = 'lun3elns'
        response = self.base_client.get_article(article_id)
        self.assertEqual(response.status, 200)
        self.assertTrue(isinstance(response.content, dict))

        # spot check some keys
        some_expected_keys = set(['direction', 'title', 'url', 'excerpt',
            'content', 'processed', 'short_url', 'date_published'])
        keys_set = set(response.content.keys())
        self.assertTrue(some_expected_keys.issubset(keys_set))

    def test_get_article_404(self):
        """Try getting an article that doesn't exist.

        """
        article_id = 1
        response = self.base_client.get_article(article_id)
        self.assertEqual(response.status, 404)
        self.assertTrue(isinstance(response.content, dict))
        self.assertTrue('error_message' in response.content)

    def test_get_user(self):
        """Test getting user data

        """
        user_response = self.base_client.get_user()
        self.assertEqual(user_response.status, 200)
        some_expected_keys = set(['username', 'first_name', 'last_name',
            'date_joined', 'email_into_address'])
        received_keys = set(user_response.content.keys())
        self.assertTrue(some_expected_keys.issubset(received_keys))

    def _test_get_tags(self):
        """Test getting tags.

        """
        tag_response = self.base_client.get_tags()
        self.assertEqual(tag_response.status, 200)
        self.assertTrue('tags' in tag_response.content)
        self.assertTrue(len(tag_response.content['tags']) > 0)
Exemple #3
0
    def setUp(self):
        """Need to get a token for each test.

        """
        token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD)
        self.token_key = token_pair[0]
        self.token_secret = token_pair[1]

        self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET,
                                        self.token_key, self.token_secret)
class ReaderClientNoBookmarkTest(unittest.TestCase):
    """
    Tests for the Readability ReaderClient class that need no bookmarks.
    """
    def setUp(self):
        """
        Need to get a token for each test.

        """
        token_key, token_secret = xauth()
        self.reader_client = ReaderClient(token_key, token_secret)

    def test_get_article(self):
        """
        Test the `get_article` method.
        """
        article_id = 'orrspy2p'
        response = self.reader_client.get_article(article_id)
        self.assertEqual(response.status_code, 200)

        # spot check some keys
        some_expected_keys = set(['direction', 'title', 'url', 'excerpt',
            'content', 'processed', 'short_url', 'date_published'])
        keys_set = set(response.json().keys())
        self.assertTrue(some_expected_keys.issubset(keys_set))

    def test_get_article_404(self):
        """
        Try getting an article that doesn't exist.
        """
        article_id = 'antidisestablishmentarianism'
        response = self.reader_client.get_article(article_id)
        self.assertEqual(response.status_code, 404)

    def test_get_user(self):
        """
        Test getting user data
        """
        user_response = self.reader_client.get_user()
        self.assertEqual(user_response.status_code, 200)
        some_expected_keys = set(['username', 'first_name', 'last_name',
            'date_joined', 'email_into_address'])
        received_keys = set(user_response.json().keys())
        self.assertTrue(some_expected_keys.issubset(received_keys))

    def test_get_empty_tags(self):
        """
        Test getting an empty set of tags. Since there are no bookmarks
        present in this test, there should be no tags.
        """
        tag_response = self.reader_client.get_tags()
        self.assertEqual(tag_response.status_code, 200)
        response_json = tag_response.json()
        self.assertTrue('tags' in response_json)
        self.assertEqual(len(response_json['tags']), 0)
Exemple #5
0
 def __init__(self, token=None):
     base = 'https://www.readability.com'
     self.AUTH_URL = '{}/api/rest/v1/oauth/authorize/'.format(base)
     self.REQ_TOKEN = '{}/api/rest/v1/oauth/request_token/'.format(base)
     self.ACC_TOKEN = '{}/api/rest/v1/oauth/access_token/'.format(base)
     self.consumer_key = settings.TH_READABILITY['consumer_key']
     self.consumer_secret = settings.TH_READABILITY['consumer_secret']
     if token:
         token_key, token_secret = token.split('#TH#')
         self.client = ReaderClient(token_key, token_secret,
                                    self.consumer_key, self.consumer_secret)
Exemple #6
0
    def setUp(self):
        """Get a client and add a bookmark

        """
        token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD)
        self.token_key = token_pair[0]
        self.token_secret = token_pair[1]

        self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET,
                                        self.token_key, self.token_secret)

        self.url = 'http://www.theatlantic.com/technology/archive/2013/01/the-never-before-told-story-of-the-worlds-first-computer-art-its-a-sexy-dame/267439/'
        add_response = self.base_client.add_bookmark(self.url)
        self.assertEqual(add_response.status, 202)
    def setUp(self):
        """
        Need to get a token for each test.

        """
        token_key, token_secret = xauth()
        self.reader_client = ReaderClient(token_key, token_secret)
    def setUp(self):
        """
        Add a few bookmarks.
        """
        token_key, token_secret = xauth()
        self.reader_client = ReaderClient(token_key=token_key, token_secret=token_secret)

        self.urls = [
            'http://www.theatlantic.com/technology/archive/2013/01/the-never-before-told-story-of-the-worlds-first-computer-art-its-a-sexy-dame/267439/',
            'http://www.theatlantic.com/business/archive/2013/01/why-smart-poor-students-dont-apply-to-selective-colleges-and-how-to-fix-it/272490/',
        ]

        self.favorite_urls = [
            'http://www.theatlantic.com/sexes/archive/2013/01/the-lonely-existence-of-mel-feit-mens-rights-advocate/267413/',
            'http://www.theatlantic.com/technology/archive/2013/01/women-in-combat-an-idea-whose-time-has-come-aided-by-technology/272483/'
        ]

        self.archive_urls = [
            'http://www.theatlantic.com/business/archive/2013/01/what-economics-can-and-cant-tell-us-about-the-legacy-of-legal-abortion/267459/',
            'http://www.theatlantic.com/business/archive/2013/01/5-ways-to-understand-just-how-absurd-spains-26-unemployment-rate-is/272502/'
        ]

        self.all_urls = self.urls + self.favorite_urls + self.archive_urls

        for url in self.urls:
            response = self.reader_client.add_bookmark(url)
            self.assertTrue(response.status_code in [201, 202])

        for url in self.favorite_urls:
            response = self.reader_client.add_bookmark(url, favorite=True)
            self.assertTrue(response.status_code in [201, 202])

        for url in self.archive_urls:
            response = self.reader_client.add_bookmark(url, archive=True)
            self.assertTrue(response.status_code in [201, 202])
Exemple #9
0
    def process_data(self, token, trigger_id, date_triggered):
        """
            get the data from the service

            :param trigger_id: trigger ID to process
            :param date_triggered: the date of the last trigger
            :type trigger_id: int
            :type date_triggered: datetime
            :return: list of data found from the date_triggered filter
            :rtype: list
        """
        data = []

        if token is not None:
            token_key, token_secret = token.split('#TH#')

            client = ReaderClient(self.consumer_key, self.consumer_secret,
                                  token_key, token_secret)

            bookmarks = client.get_bookmarks(
                added_since=date_triggered).content

            for bookmark in bookmarks.values():

                for b in bookmark:
                    if 'article' in b:
                        title = ''
                        if 'title' in b['article']:
                            title = b['article']['title']

                        link = ''
                        if 'url' in b['article']:
                            link = b['article']['url']

                        content = ''
                        if 'excerpt' in b['article']:
                            content = b['article']['excerpt']

                        data.append({
                            'title': title,
                            'link': link,
                            'content': content
                        })

        return data
Exemple #10
0
    def create_client(self):
        """
        Connect to Readability API
        (http://readability-python-library.readthedocs.org/en/latest/clients.html#readability.ReaderClient)
        """

        rdb_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET, self.token[0],
                                  self.token[1])
        return rdb_client
Exemple #11
0
 def __init__(self, token=None, **kwargs):
     super(ServiceReadability, self).__init__(token, **kwargs)
     base = 'https://www.readability.com'
     self.AUTH_URL = '{}/api/rest/v1/oauth/authorize/'.format(base)
     self.REQ_TOKEN = '{}/api/rest/v1/oauth/request_token/'.format(base)
     self.ACC_TOKEN = '{}/api/rest/v1/oauth/access_token/'.format(base)
     self.consumer_key = settings.TH_READABILITY['consumer_key']
     self.consumer_secret = settings.TH_READABILITY['consumer_secret']
     self.token = token
     self.service = 'ServiceReadability'
     self.oauth = 'oauth1'
     kwargs = {
         'consumer_key': self.consumer_key,
         'consumer_secret': self.consumer_secret
     }
     if token:
         token_key, token_secret = self.token.split('#TH#')
         self.client = ReaderClient(token_key, token_secret, **kwargs)
Exemple #12
0
def actualizar():
    cred=getAuth()

# If no client credentials are passed to ReaderClient's constructor, they
# will be looked for in your environment variables

    """
    coneccion = pymongo.MongoClient("localhost")
    db = coneccion.readability
    db.drop_collection("bookmarks")
    datos=db.bookmarks"""
    client = ReaderClient(token_key=cred[0],token_secret=cred[1],consumer_key=consumer_key,consumer_secret=consumer_secret)

    print client
    bookmarks_response = client.get_bookmarks()
    dic=bookmarks_response.json()
    for k in dic["bookmarks"]:
        print k["article"]["title"]
 def setUp(self):
     """
     Get a client and add a bookmark
     """
     token_key, token_secret = xauth()
     self.reader_client = ReaderClient(token_key=token_key, token_secret=token_secret)
     self.url = 'http://www.theatlantic.com/technology/archive/2013/01/the-never-before-told-story-of-the-worlds-first-computer-art-its-a-sexy-dame/267439/'
     add_response = self.reader_client.add_bookmark(self.url)
     self.assertTrue(add_response.status_code in [201, 202])
    def setUp(self):
        """Need to get a token for each test.

        """
        token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD)
        self.token_key = token_pair[0]
        self.token_secret = token_pair[1]

        self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET,
            self.token_key, self.token_secret)
Exemple #15
0
    def save_data(self, token, trigger_id, **data):
        """
            let's save the data

            :param trigger_id: trigger ID from which to save data
            :param **data: the data to check to be used and save
            :type trigger_id: int
            :type **data:  dict
            :return: the status of the save statement
            :rtype: boolean
        """
        status = False
        if token and 'link' in data and data['link'] is not None and len(
                data['link']) > 0:
            # get the data of this trigger
            trigger = Readability.objects.get(trigger_id=trigger_id)
            token_key, token_secret = token.split('#TH#')
            readability_instance = ReaderClient(self.consumer_key,
                                                self.consumer_secret,
                                                token_key, token_secret)

            bookmark_id = readability_instance.add_bookmark(url=data['link'])

            if trigger.tag is not None and len(trigger.tag) > 0:
                try:
                    readability_instance.add_tags_to_bookmark(
                        bookmark_id, tags=(trigger.tag.lower()))
                    sentence = str('readability {} created item id {}').format(
                        data['link'], bookmark_id)
                    logger.debug(sentence)
                    status = True
                except Exception as e:
                    logger.critical(e)
                    status = False
        else:
            sentence = "no token or link provided for trigger ID {} "
            logger.critical(sentence.format(trigger_id))
            status = False

        return status
Exemple #16
0
    def setUp(self):
        """Add a few bookmarks.

        """
        token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD)
        self.token_key = token_pair[0]
        self.token_secret = token_pair[1]

        self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET,
                                        self.token_key, self.token_secret)

        self.urls = [
            'http://www.theatlantic.com/technology/archive/2013/01/the-never-before-told-story-of-the-worlds-first-computer-art-its-a-sexy-dame/267439/',
            'http://www.theatlantic.com/business/archive/2013/01/why-smart-poor-students-dont-apply-to-selective-colleges-and-how-to-fix-it/272490/',
        ]

        self.favorite_urls = [
            'http://www.theatlantic.com/sexes/archive/2013/01/the-lonely-existence-of-mel-feit-mens-rights-advocate/267413/',
            'http://www.theatlantic.com/technology/archive/2013/01/women-in-combat-an-idea-whose-time-has-come-aided-by-technology/272483/'
        ]

        self.archive_urls = [
            'http://www.theatlantic.com/business/archive/2013/01/what-economics-can-and-cant-tell-us-about-the-legacy-of-legal-abortion/267459/',
            'http://www.theatlantic.com/business/archive/2013/01/5-ways-to-understand-just-how-absurd-spains-26-unemployment-rate-is/272502/'
        ]

        self.all_urls = self.urls + self.favorite_urls + self.archive_urls

        for url in self.urls:
            add_response = self.base_client.add_bookmark(url)
            self.assertEqual(add_response.status, 202)

        for url in self.favorite_urls:
            add_response = self.base_client.add_bookmark(url, favorite=True)
            self.assertEqual(add_response.status, 202)

        for url in self.archive_urls:
            add_response = self.base_client.add_bookmark(url, archive=True)
            self.assertEqual(add_response.status, 202)
    def process_data(self, token, trigger_id, date_triggered):
        """
            get the data from the service
        """
        data = []

        if token is not None:
            token_key, token_secret = token.split('#TH#')

            client = ReaderClient(
                self.consumer_key, self.consumer_secret,
                token_key, token_secret)

            bookmarks = client.get_bookmarks(
                added_since=date_triggered).content

            for bookmark in bookmarks.values():

                for b in bookmark:
                    if 'article' in b:
                        title = ''
                        if 'title' in b['article']:
                            title = b['article']['title']

                        link = ''
                        if 'url' in b['article']:
                            link = b['article']['url']

                        content = ''
                        if 'excerpt' in b['article']:
                            content = b['article']['excerpt']

                        data.append(
                            {'title': title,
                             'link': link,
                             'content': content})

        return data
    def setUp(self):
        """Get a client and add a bookmark

        """
        token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD)
        self.token_key = token_pair[0]
        self.token_secret = token_pair[1]

        self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET,
            self.token_key, self.token_secret)

        self.url = 'http://www.theatlantic.com/technology/archive/2013/01/the-never-before-told-story-of-the-worlds-first-computer-art-its-a-sexy-dame/267439/'
        add_response = self.base_client.add_bookmark(self.url)
        self.assertEqual(add_response.status, 202)
 def __init__(self, token=None, **kwargs):
     super(ServiceReadability, self).__init__(token, **kwargs)
     base = 'https://www.readability.com'
     self.AUTH_URL = '{}/api/rest/v1/oauth/authorize/'.format(base)
     self.REQ_TOKEN = '{}/api/rest/v1/oauth/request_token/'.format(base)
     self.ACC_TOKEN = '{}/api/rest/v1/oauth/access_token/'.format(base)
     self.consumer_key = settings.TH_READABILITY['consumer_key']
     self.consumer_secret = settings.TH_READABILITY['consumer_secret']
     self.token = token
     self.service = 'ServiceReadability'
     self.oauth = 'oauth1'
     kwargs = {'consumer_key': self.consumer_key,
               'consumer_secret': self.consumer_secret}
     if token:
         token_key, token_secret = self.token.split('#TH#')
         self.client = ReaderClient(token_key, token_secret, **kwargs)
class ReaderClientMultipleBookmarkTest(unittest.TestCase):
    """
    Tests for bookmark functionality
    """
    def setUp(self):
        """
        Add a few bookmarks.
        """
        token_key, token_secret = xauth()
        self.reader_client = ReaderClient(token_key=token_key, token_secret=token_secret)

        self.urls = [
            'http://www.theatlantic.com/technology/archive/2013/01/the-never-before-told-story-of-the-worlds-first-computer-art-its-a-sexy-dame/267439/',
            'http://www.theatlantic.com/business/archive/2013/01/why-smart-poor-students-dont-apply-to-selective-colleges-and-how-to-fix-it/272490/',
        ]

        self.favorite_urls = [
            'http://www.theatlantic.com/sexes/archive/2013/01/the-lonely-existence-of-mel-feit-mens-rights-advocate/267413/',
            'http://www.theatlantic.com/technology/archive/2013/01/women-in-combat-an-idea-whose-time-has-come-aided-by-technology/272483/'
        ]

        self.archive_urls = [
            'http://www.theatlantic.com/business/archive/2013/01/what-economics-can-and-cant-tell-us-about-the-legacy-of-legal-abortion/267459/',
            'http://www.theatlantic.com/business/archive/2013/01/5-ways-to-understand-just-how-absurd-spains-26-unemployment-rate-is/272502/'
        ]

        self.all_urls = self.urls + self.favorite_urls + self.archive_urls

        for url in self.urls:
            response = self.reader_client.add_bookmark(url)
            self.assertTrue(response.status_code in [201, 202])

        for url in self.favorite_urls:
            response = self.reader_client.add_bookmark(url, favorite=True)
            self.assertTrue(response.status_code in [201, 202])

        for url in self.archive_urls:
            response = self.reader_client.add_bookmark(url, archive=True)
            self.assertTrue(response.status_code in [201, 202])

    def test_get_bookmarks(self):
        """
        Test getting all bookmarks
        """
        response = self.reader_client.get_bookmarks()
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            len(response.json()['bookmarks']), len(self.all_urls))

        # test favorite bookmarks
        response = self.reader_client.get_bookmarks(favorite=True)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            len(response.json()['bookmarks']), len(self.favorite_urls))
        for bm in response.json()['bookmarks']:
            self.assertTrue(bm['article']['url'] in self.favorite_urls)

        # test archive bookmarks
        response = self.reader_client.get_bookmarks(archive=True)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            len(response.json()['bookmarks']), len(self.archive_urls))
        for bm in response.json()['bookmarks']:
            self.assertTrue(bm['article']['url'] in self.archive_urls)

    def tearDown(self):
        """
        Remove all added bookmarks.
        """
        for bm in self.reader_client.get_bookmarks().json()['bookmarks']:
            del_response = self.reader_client.delete_bookmark(bm['id'])
            self.assertEqual(del_response.status_code, 204)
class ReaderClientSingleBookmarkTest(unittest.TestCase):
    """
    Tests that only need one bookmark
    """
    def setUp(self):
        """
        Get a client and add a bookmark
        """
        token_key, token_secret = xauth()
        self.reader_client = ReaderClient(token_key=token_key, token_secret=token_secret)
        self.url = 'http://www.theatlantic.com/technology/archive/2013/01/the-never-before-told-story-of-the-worlds-first-computer-art-its-a-sexy-dame/267439/'
        add_response = self.reader_client.add_bookmark(self.url)
        self.assertTrue(add_response.status_code in [201, 202])

    def tearDown(self):
        """
        Remove all added bookmarks.
        """
        for bm in self.reader_client.get_bookmarks().json()['bookmarks']:
            del_response = self.reader_client.delete_bookmark(bm['id'])
            self.assertEqual(del_response.status_code, 204)

    def test_get_bookmark(self):
        """
        Test getting one bookmark by id
        """
        bookmark_id = self._get_bookmark_data()['id']

        bm_response = self.reader_client.get_bookmark(bookmark_id)
        self.assertEqual(bm_response.status_code, 200)
        some_expected_keys = set(['article', 'user_id', 'favorite', 'id'])
        received_keys = set(bm_response.json().keys())
        self.assertTrue(some_expected_keys.issubset(received_keys))

    def test_bookmark_tag_functionality(self):
        """
        Test adding, fetching and deleting tags on a bookmark.
        """
        bookmark_id = self._get_bookmark_data()['id']

        # test getting empty tags
        tag_response = self.reader_client.get_bookmark_tags(bookmark_id)
        self.assertEqual(tag_response.status_code, 200)
        self.assertEqual(len(tag_response.json()['tags']), 0)

        # test adding tags
        tags = ['tag', 'another tag']
        tag_string = ', '.join(tags)
        tag_add_response = \
            self.reader_client.add_tags_to_bookmark(bookmark_id, tag_string)
        self.assertEqual(tag_add_response.status_code, 202)

        # re-fetch tags. should have 2
        retag_response = self.reader_client.get_bookmark_tags(bookmark_id)
        self.assertEqual(retag_response.status_code, 200)
        self.assertEqual(len(retag_response.json()['tags']), 2)
        for tag in retag_response.json()['tags']:
            self.assertTrue(tag['text'] in tags)

        # test getting tags for user
        user_tag_resp = self.reader_client.get_tags()
        self.assertEqual(user_tag_resp.status_code, 200)
        self.assertEqual(len(user_tag_resp.json()['tags']), 2)
        for tag in user_tag_resp.json()['tags']:
            self.assertTrue(tag['text'] in tags)

            # test getting a single tag while we're here
            single_tag_resp = self.reader_client.get_tag(tag['id'])
            self.assertEqual(single_tag_resp.status_code, 200)
            self.assertTrue('applied_count' in single_tag_resp.json())
            self.assertTrue('id' in single_tag_resp.json())
            self.assertTrue('text' in single_tag_resp.json())

        # delete tags
        for tag in retag_response.json()['tags']:
            del_response = self.reader_client.delete_tag_from_bookmark(
                bookmark_id, tag['id'])
            self.assertEqual(del_response.status_code, 204)

        # check that tags are gone
        tag_response = self.reader_client.get_bookmark_tags(bookmark_id)
        self.assertEqual(tag_response.status_code, 200)
        self.assertEqual(len(tag_response.json()['tags']), 0)

    def _get_bookmark_data(self):
        """
        Convenience method to get a single bookmark's data.
        """
        bm_response = self.reader_client.get_bookmarks()
        self.assertEqual(bm_response.status_code, 200)
        bm_response_json = bm_response.json()
        self.assertTrue(len(bm_response_json['bookmarks']) > 0)
        return bm_response_json['bookmarks'][0]
        "since": since,
        "sort": "oldest",
        "count": 20
       })


articles = res.json()['list']

if not articles:
    since = res.json()['since']
    with open('metadata.json', 'w') as f:
        f.write(json.dumps({"since": since}))
    exit(0)

articles = sorted(articles.values(), key=lambda x: x['sort_id'])  # sort_id is provided by pocket to denote sort order

since = str(int(articles[-1]['time_updated']) + 1)
with open('metadata.json', 'w') as f:
    f.write(json.dumps({"since": since}))

readability = ReaderClient(
                token_key=config.READABILITY_USER_KEY,
                token_secret=config.READABILITY_USER_SECRET,
                consumer_key=config.READABILITY_CONSUMER_KEY,
                consumer_secret=config.READABILITY_CONSUMER_SECRET
              )

for a in articles:
    readability.add_bookmark(a['resolved_url'])

Exemple #23
0
class ReaderClientSingleBookmarkTest(TestCase):
    """Tests that only need one bookmark

    """
    def setUp(self):
        """Get a client and add a bookmark

        """
        token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD)
        self.token_key = token_pair[0]
        self.token_secret = token_pair[1]

        self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET,
                                        self.token_key, self.token_secret)

        self.url = 'http://www.theatlantic.com/technology/archive/2013/01/the-never-before-told-story-of-the-worlds-first-computer-art-its-a-sexy-dame/267439/'
        add_response = self.base_client.add_bookmark(self.url)
        self.assertEqual(add_response.status, 202)

    def tearDown(self):
        """Remove all added bookmarks.

        """
        for bm in self.base_client.get_bookmarks().content['bookmarks']:
            del_response = self.base_client.delete_bookmark(bm['id'])
            self.assertEqual(del_response.status, 204)

    def test_get_bookmark(self):
        """Test getting one bookmark by id

        """
        # get a bookmark id
        bm_response = self.base_client.get_bookmarks()
        self.assertEqual(bm_response.status, 200)
        self.assertTrue(len(bm_response.content['bookmarks']) > 0)
        bookmark_id = bm_response.content['bookmarks'][0]['id']

        bm_response = self.base_client.get_bookmark(bookmark_id)
        self.assertEqual(bm_response.status, 200)
        some_expected_keys = set(['article', 'user_id', 'favorite', 'id'])
        received_keys = set(bm_response.content.keys())
        self.assertTrue(some_expected_keys.issubset(received_keys))

    def test_bookmark_tag_functionality(self):
        """Test adding, fetching and deleting tags on a bookmark.

        """
        # get a bookmark id
        bm_response = self.base_client.get_bookmarks()
        self.assertEqual(bm_response.status, 200)
        self.assertTrue(len(bm_response.content['bookmarks']) > 0)
        bookmark_id = bm_response.content['bookmarks'][0]['id']

        # test getting empty tags
        tag_response = self.base_client.get_bookmark_tags(bookmark_id)
        self.assertEqual(tag_response.status, 200)
        self.assertEqual(len(tag_response.content['tags']), 0)

        # test adding tags
        tags = ['tag', 'another tag']
        tag_string = ', '.join(tags)
        tag_add_response = \
            self.base_client.add_tags_to_bookmark(bookmark_id, tag_string)
        self.assertEqual(tag_add_response.status, 202)

        # re-fetch tags. should have 2
        retag_response = self.base_client.get_bookmark_tags(bookmark_id)
        self.assertEqual(retag_response.status, 200)
        self.assertEqual(len(retag_response.content['tags']), 2)
        for tag in retag_response.content['tags']:
            self.assertTrue(tag['text'] in tags)

        # test getting tags for user
        user_tag_resp = self.base_client.get_tags()
        self.assertEqual(user_tag_resp.status, 200)
        self.assertEqual(len(user_tag_resp.content['tags']), 2)
        for tag in user_tag_resp.content['tags']:
            self.assertTrue(tag['text'] in tags)

            # test getting a single tag while we're here
            single_tag_resp = self.base_client.get_tag(tag['id'])
            self.assertEqual(single_tag_resp.status, 200)
            self.assertTrue('applied_count' in single_tag_resp.content)
            self.assertTrue('id' in single_tag_resp.content)
            self.assertTrue('text' in single_tag_resp.content)

        # delete tags
        for tag in retag_response.content['tags']:
            del_response = self.base_client.delete_tag_from_bookmark(
                bookmark_id, tag['id'])
            self.assertEqual(del_response.status, 204)

        # check that tags are gone
        tag_response = self.base_client.get_bookmark_tags(bookmark_id)
        self.assertEqual(tag_response.status, 200)
        self.assertEqual(len(tag_response.content['tags']), 0)
Exemple #24
0
class ReaderClientMultipleBookmarkTest(TestCase):
    """Tests for bookmark functionality

    """
    def setUp(self):
        """Add a few bookmarks.

        """
        token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD)
        self.token_key = token_pair[0]
        self.token_secret = token_pair[1]

        self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET,
                                        self.token_key, self.token_secret)

        self.urls = [
            'http://www.theatlantic.com/technology/archive/2013/01/the-never-before-told-story-of-the-worlds-first-computer-art-its-a-sexy-dame/267439/',
            'http://www.theatlantic.com/business/archive/2013/01/why-smart-poor-students-dont-apply-to-selective-colleges-and-how-to-fix-it/272490/',
        ]

        self.favorite_urls = [
            'http://www.theatlantic.com/sexes/archive/2013/01/the-lonely-existence-of-mel-feit-mens-rights-advocate/267413/',
            'http://www.theatlantic.com/technology/archive/2013/01/women-in-combat-an-idea-whose-time-has-come-aided-by-technology/272483/'
        ]

        self.archive_urls = [
            'http://www.theatlantic.com/business/archive/2013/01/what-economics-can-and-cant-tell-us-about-the-legacy-of-legal-abortion/267459/',
            'http://www.theatlantic.com/business/archive/2013/01/5-ways-to-understand-just-how-absurd-spains-26-unemployment-rate-is/272502/'
        ]

        self.all_urls = self.urls + self.favorite_urls + self.archive_urls

        for url in self.urls:
            add_response = self.base_client.add_bookmark(url)
            self.assertEqual(add_response.status, 202)

        for url in self.favorite_urls:
            add_response = self.base_client.add_bookmark(url, favorite=True)
            self.assertEqual(add_response.status, 202)

        for url in self.archive_urls:
            add_response = self.base_client.add_bookmark(url, archive=True)
            self.assertEqual(add_response.status, 202)

    def test_get_bookmarks(self):
        """Test getting all bookmarks

        """
        bm_response = self.base_client.get_bookmarks()
        self.assertEqual(bm_response.status, 200)
        self.assertEqual(len(bm_response.content['bookmarks']),
                         len(self.all_urls))

        # test favorite bookmarks
        bm_response = self.base_client.get_bookmarks(favorite=True)
        self.assertEqual(bm_response.status, 200)
        self.assertEqual(len(bm_response.content['bookmarks']),
                         len(self.favorite_urls))
        for bm in bm_response.content['bookmarks']:
            self.assertTrue(bm['article']['url'] in self.favorite_urls)

        # test archive bookmarks
        bm_response = self.base_client.get_bookmarks(archive=True)
        self.assertEqual(bm_response.status, 200)
        self.assertEqual(len(bm_response.content['bookmarks']),
                         len(self.archive_urls))
        for bm in bm_response.content['bookmarks']:
            self.assertTrue(bm['article']['url'] in self.archive_urls)

    def tearDown(self):
        """Remove all added bookmarks.

        """
        for bm in self.base_client.get_bookmarks().content['bookmarks']:
            del_response = self.base_client.delete_bookmark(bm['id'])
            self.assertEqual(del_response.status, 204)
Exemple #25
0
def readability_exporter(api_key, api_secret, login_user, login_pw, format,
                         bookmarks, export_directory, export_filename,
                         not_show_file, http_error_threshold):
    """Readability Exporter
   
   This little script takes credentials for a Readability account and the API key and secret to create the standard
   Readability export file in JSON format that can be used to import your links into Instapaper.
   We think about adding support for the del.icio.us flavour of bookmarks.html to allow direct import into Pocket.
   
   You can find more information about this script on GitHub at https://github.com/goetzb/readability-exporter
   """
    click.echo(click.style('Readability Exporter', bold=True))

    # Create string for export filename
    if '{timestamp}' not in export_filename:
        export_filename += '_{timestamp}'
    if '{format}' not in export_filename:
        export_filename += '_{format}'
    if '{filetype}' not in export_filename:
        export_filename += '.{filetype}'

    # Prepare json export dictionary
    export_dict = OrderedDict()
    export_dict['bookmarks'] = []
    # Add empty recommendations list - in my example this was just empty.
    export_dict["recommendations"] = []

    # Prepare jsonraw export dictionary
    export_dict_raw = OrderedDict()

    # Prepare html export string
    export_html = """<!DOCTYPE NETSCAPE-Bookmark-file-1>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<!-- This is an automatically generated file.
It will be read and overwritten.
Do Not Edit! -->
<TITLE>Bookmarks</TITLE>
<H1>Bookmarks</H1>
<DL><p>
"""

    auth_tokens = get_auth_tokens(api_key=api_key,
                                  api_secret=api_secret,
                                  login_user=login_user,
                                  login_pw=login_pw)
    if len(auth_tokens) != 2:
        click.ClickException(
            """An error occurred and you could not be authenticated successfully.
Please check your Readability API keys and login details.""")

    client = ReaderClient(token_key=auth_tokens[0],
                          token_secret=auth_tokens[1],
                          consumer_key=api_key,
                          consumer_secret=api_secret)
    meta_infos = get_readability_meta_infos(readability_reader_client=client)
    click.echo("* You have saved " + click.style("{link_count}".format(
        link_count=meta_infos['bookmarks_total']),
                                                 bold=True) +
               " links on Readability")

    if bookmarks == 0:
        bookmarks = meta_infos['bookmarks_total']

    click.echo("* We are now going to export the latest " +
               click.style("{export_count}".format(export_count=bookmarks),
                           bold=True) + " of your links")

    if bookmarks < 50:
        bookmarks_per_page = bookmarks + 1
    else:
        bookmarks_per_page = 50
    bookmarks_get_pages = int(ceil(bookmarks / bookmarks_per_page))

    data_export = export_bookmarks_via_api(
        readability_reader_client=client,
        export_formats=format,
        bookmarks_number=bookmarks,
        bookmarks_per_page=bookmarks_per_page,
        bookmarks_get_pages=bookmarks_get_pages,
        export_json=export_dict,
        export_html=export_html,
        export_jsonraw=export_dict_raw,
        error_threshold=http_error_threshold)

    click.echo(
        "Bear with us, we are almost there. In the next step we bring the data into the right formats."
    )

    exported_files = []
    files_export_count = 0
    timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S")
    with click.progressbar(label='Writing export files...',
                           length=len(format),
                           show_percent=True) as files_bar:
        for export_format in format:
            output_data = data_export[export_format]
            if export_format == 'json' or export_format == 'jsonraw':
                filetype = 'json'
            elif export_format == 'html':
                filetype = 'html'
                output_data += "</DL><p>"

            format_export_filename = export_filename.format(
                timestamp=timestamp, format=export_format, filetype=filetype)

            export_file = write_export_data(filetype=filetype,
                                            directory=export_directory,
                                            filename=format_export_filename,
                                            data=output_data)

            exported_files.append(export_file)

            files_export_count += 1
            files_bar.update(files_export_count)

    # TODO: Improve bookmark count to verify if actually the correct number of bookmarks has been exported
    # Get length of 'bookmarks' in json export dictionary
    click.echo(
        click.style(
            "Good news! We have successfully exported {number_of_bookmarks} bookmarks for you."
            .format(number_of_bookmarks=bookmarks),
            fg='green'))

    for exported_file in exported_files:
        if exported_file['file_size'] / 1024 > 1024:
            file_size_string = '{size:d} MiB'.format(
                size=int(round(exported_file['file_size'] / 1024 / 1024)))
        elif exported_file['file_size'] > 1024:
            file_size_string = '{size:d} KiB'.format(
                size=int(round(exported_file['file_size'] / 1024)))
        else:
            file_size_string = '{size:d} B'.format(
                size=exported_file['file_size'])

        click.echo("You can find your exported data in ")
        click.echo(
            click.style("  {path}".format(path=exported_file['file_path']),
                        bold=True))
        click.echo("  (~{size})".format(size=file_size_string))

    click.echo(
        click.style("Thank you for using this little tool!", reverse=True))
    if not not_show_file:
        click.echo(
            click.style(
                "We will now try to open your file manager with the exported file selected.",
                reverse=True))
        click.launch(export_directory, locate=True)
Exemple #26
0
class ReaderClientNoBookmarkTest(TestCase):
    """Tests for the Readability ReaderClient class that need no bookmarks.

    """
    def setUp(self):
        """Need to get a token for each test.

        """
        token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD)
        self.token_key = token_pair[0]
        self.token_secret = token_pair[1]

        self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET,
                                        self.token_key, self.token_secret)

    def test_get_article(self):
        """Test the `get_article` method.

        """
        article_id = 'lun3elns'
        response = self.base_client.get_article(article_id)
        self.assertEqual(response.status, 200)
        self.assertTrue(isinstance(response.content, dict))

        # spot check some keys
        some_expected_keys = set([
            'direction', 'title', 'url', 'excerpt', 'content', 'processed',
            'short_url', 'date_published'
        ])
        keys_set = set(response.content.keys())
        self.assertTrue(some_expected_keys.issubset(keys_set))

    def test_get_article_404(self):
        """Try getting an article that doesn't exist.

        """
        article_id = 1
        response = self.base_client.get_article(article_id)
        self.assertEqual(response.status, 404)
        self.assertTrue(isinstance(response.content, dict))
        self.assertTrue('error_message' in response.content)

    def test_get_user(self):
        """Test getting user data

        """
        user_response = self.base_client.get_user()
        self.assertEqual(user_response.status, 200)
        some_expected_keys = set([
            'username', 'first_name', 'last_name', 'date_joined',
            'email_into_address'
        ])
        received_keys = set(user_response.content.keys())
        self.assertTrue(some_expected_keys.issubset(received_keys))

    def _test_get_tags(self):
        """Test getting tags.

        """
        tag_response = self.base_client.get_tags()
        self.assertEqual(tag_response.status, 200)
        self.assertTrue('tags' in tag_response.content)
        self.assertTrue(len(tag_response.content['tags']) > 0)
Exemple #27
0
class ServiceReadability(ServicesMgr):

    def __init__(self, token=None):
        base = 'https://www.readability.com'
        self.AUTH_URL = '{}/api/rest/v1/oauth/authorize/'.format(base)
        self.REQ_TOKEN = '{}/api/rest/v1/oauth/request_token/'.format(base)
        self.ACC_TOKEN = '{}/api/rest/v1/oauth/access_token/'.format(base)
        self.consumer_key = settings.TH_READABILITY['consumer_key']
        self.consumer_secret = settings.TH_READABILITY['consumer_secret']
        if token:
            token_key, token_secret = token.split('#TH#')
            self.client = ReaderClient(token_key, token_secret,
                                       self.consumer_key, self.consumer_secret)

    def read_data(self, token, trigger_id, date_triggered):
        """
            get the data from the service

            :param trigger_id: trigger ID to process
            :param date_triggered: the date of the last trigger
            :type trigger_id: int
            :type date_triggered: datetime
            :return: list of data found from the date_triggered filter
            :rtype: list
        """
        data = []

        if token is not None:

            bookmarks = self.client.get_bookmarks(
                added_since=date_triggered).content

            for bookmark in bookmarks.values():

                for b in bookmark:
                    if 'article' in b:
                        title = ''
                        if 'title' in b['article']:
                            title = b['article']['title']

                        link = ''
                        if 'url' in b['article']:
                            link = b['article']['url']

                        content = ''
                        if 'excerpt' in b['article']:
                            content = b['article']['excerpt']

                        data.append(
                            {'title': title,
                             'link': link,
                             'content': content})

            cache.set('th_readability_' + str(trigger_id), data)

        return data

    def process_data(self, trigger_id):
        """
            get the data from the cache
            :param trigger_id: trigger ID from which to save data
            :type trigger_id: int
        """
        cache_data = cache.get('th_readability_' + str(trigger_id))
        return PublishingLimit.get_data('th_readability_',
                                        cache_data,
                                        trigger_id)

    def save_data(self, token, trigger_id, **data):
        """
            let's save the data

            :param trigger_id: trigger ID from which to save data
            :param **data: the data to check to be used and save
            :type trigger_id: int
            :type **data:  dict
            :return: the status of the save statement
            :rtype: boolean
        """
        status = False
        if token and 'link' in data and\
           data['link'] is not None and\
           len(data['link']) > 0:
            # get the data of this trigger
            trigger = Readability.objects.get(trigger_id=trigger_id)

            bookmark_id = self.client.add_bookmark(url=data['link'])

            if trigger.tag is not None and len(trigger.tag) > 0:
                try:
                    self.client.add_tags_to_bookmark(
                        bookmark_id, tags=(trigger.tag.lower()))
                    sentence = str('readability {} created item id {}').format(
                        data['link'], bookmark_id)
                    logger.debug(sentence)
                    status = True
                except Exception as e:
                    logger.critical(e)
                    status = False
        else:
            sentence = "no token or link provided for trigger ID {} "
            logger.critical(sentence.format(trigger_id))
            status = False

        return status

    def auth(self, request):
        """
            let's auth the user to the Service
        """
        callback_url = 'http://%s%s' % (
            request.get_host(), reverse('readability_callback'))

        request_token = self.get_request_token()

        # Save the request token information for later
        request.session['oauth_token'] = request_token['oauth_token']
        request.session['oauth_token_secret'] = request_token[
            'oauth_token_secret']

        # URL to redirect user to, to authorize your app
        auth_url_str = '%s?oauth_token=%s&oauth_callback=%s'
        auth_url = auth_url_str % (self.AUTH_URL,
                                   request_token['oauth_token'],
                                   callback_url)

        return auth_url

    def callback(self, request):
        """
            Called from the Service when the user accept to activate it
        """

        try:
            # finally we save the user auth token
            # As we already stored the object ServicesActivated
            # from the UserServiceCreateView now we update the same
            # object to the database so :
            # 1) we get the previous objet
            us = UserService.objects.get(
                user=request.user,
                name=ServicesActivated.objects.get(name='ServiceReadability'))
            # 2) Readability API require to use 4 parms consumer_key/secret +
            # token_key/secret instead of usually get just the token
            # from an access_token request. So we need to add a string
            # seperator for later use to slpit on this one
            access_token = self.get_access_token(
                request.session['oauth_token'],
                request.session['oauth_token_secret'],
                request.GET.get('oauth_verifier', '')
            )
            us.token = access_token.get('oauth_token') + \
                '#TH#' + access_token.get('oauth_token_secret')

            # 3) and save everything
            us.save()
        except KeyError:
            return '/'

        return 'readability/callback.html'

    def get_request_token(self):
        oauth = OAuth1Session(self.consumer_key,
                              client_secret=self.consumer_secret)
        return oauth.fetch_request_token(self.REQ_TOKEN)

    def get_access_token(self, oauth_token, oauth_token_secret,
                         oauth_verifier):
        # Using OAuth1Session
        oauth = OAuth1Session(self.consumer_key,
                              client_secret=self.consumer_secret,
                              resource_owner_key=oauth_token,
                              resource_owner_secret=oauth_token_secret,
                              verifier=oauth_verifier)
        oauth_tokens = oauth.fetch_access_token(self.ACC_TOKEN)

        return oauth_tokens
Exemple #28
0
class ServiceReadability(ServicesMgr):
    def __init__(self, token=None):
        base = 'https://www.readability.com'
        self.AUTH_URL = '{}/api/rest/v1/oauth/authorize/'.format(base)
        self.REQ_TOKEN = '{}/api/rest/v1/oauth/request_token/'.format(base)
        self.ACC_TOKEN = '{}/api/rest/v1/oauth/access_token/'.format(base)
        self.consumer_key = settings.TH_READABILITY['consumer_key']
        self.consumer_secret = settings.TH_READABILITY['consumer_secret']
        self.token = token
        if token:
            token_key, token_secret = self.token.split('#TH#')
            self.client = ReaderClient(token_key, token_secret,
                                       self.consumer_key, self.consumer_secret)

    def read_data(self, **kwargs):
        """
            get the data from the service

            :param kwargs: contain keyword args : trigger_id at least
            :type kwargs: dict

            :rtype: list
        """
        date_triggered = kwargs['date_triggered']
        trigger_id = kwargs['trigger_id']
        data = []

        if self.token is not None:

            bookmarks = self.client.get_bookmarks(
                added_since=date_triggered).content

            for bookmark in bookmarks.values():

                for b in bookmark:
                    if 'article' in b:
                        title = ''
                        if 'title' in b['article']:
                            title = b['article']['title']

                        link = ''
                        if 'url' in b['article']:
                            link = b['article']['url']

                        content = ''
                        if 'excerpt' in b['article']:
                            content = b['article']['excerpt']

                        data.append({
                            'title': title,
                            'link': link,
                            'content': content
                        })

            cache.set('th_readability_' + str(trigger_id), data)

        return data

    def process_data(self, **kwargs):
        """
            get the data from the cache
            :param kwargs: contain keyword args : trigger_id at least
            :type kwargs: dict
        """
        kw = {
            'cache_stack': 'th_readability',
            'trigger_id': str(kwargs['trigger_id'])
        }
        return super(ServiceReadability, self).process_data(**kw)

    def save_data(self, trigger_id, **data):
        """
            let's save the data

            :param trigger_id: trigger ID from which to save data
            :param data: the data to check to be used and save
            :type trigger_id: int
            :type data:  dict
            :return: the status of the save statement
            :rtype: boolean
        """
        status = False
        if self.token and 'link' in data and\
           data['link'] is not None and\
           len(data['link']) > 0:
            # get the data of this trigger
            trigger = Readability.objects.get(trigger_id=trigger_id)

            bookmark_id = self.client.add_bookmark(url=data['link'])

            if trigger.tag is not None and len(trigger.tag) > 0:
                try:
                    self.client.add_tags_to_bookmark(
                        bookmark_id, tags=(trigger.tag.lower()))
                    sentence = str('readability {} created item id {}').format(
                        data['link'], bookmark_id)
                    logger.debug(sentence)
                    status = True
                except Exception as e:
                    logger.critical(e)
                    status = False
        else:
            sentence = "no token or link provided for trigger ID {} "
            logger.critical(sentence.format(trigger_id))
            status = False

        return status

    def auth(self, request):
        """
            let's auth the user to the Service
        """
        request_token = super(ServiceReadability, self).auth(request)
        callback_url = self.callback_url(request, 'readability')

        # URL to redirect user to, to authorize your app
        auth_url_str = '%s?oauth_token=%s&oauth_callback=%s'
        auth_url = auth_url_str % (self.AUTH_URL, request_token['oauth_token'],
                                   callback_url)

        return auth_url

    def callback(self, request):
        """
            Called from the Service when the user accept to activate it
        """
        kwargs = {
            'access_token': '',
            'service': 'ServiceReadability',
            'return': 'readability'
        }
        return super(ServiceReadability, self).callback(request, **kwargs)
Exemple #29
0
class ServiceReadability(ServicesMgr):

    def __init__(self, token=None):
        base = 'https://www.readability.com'
        self.AUTH_URL = '{}/api/rest/v1/oauth/authorize/'.format(base)
        self.REQ_TOKEN = '{}/api/rest/v1/oauth/request_token/'.format(base)
        self.ACC_TOKEN = '{}/api/rest/v1/oauth/access_token/'.format(base)
        self.consumer_key = settings.TH_READABILITY['consumer_key']
        self.consumer_secret = settings.TH_READABILITY['consumer_secret']
        self.token = token
        if token:
            token_key, token_secret = self.token.split('#TH#')
            self.client = ReaderClient(token_key, token_secret,
                                       self.consumer_key, self.consumer_secret)

    def read_data(self, **kwargs):
        """
            get the data from the service

            :param kwargs: contain keyword args : trigger_id at least
            :type kwargs: dict

            :rtype: list
        """
        date_triggered = kwargs['date_triggered']
        trigger_id = kwargs['trigger_id']
        data = []

        if self.token is not None:

            bookmarks = self.client.get_bookmarks(
                added_since=date_triggered).content

            for bookmark in bookmarks.values():

                for b in bookmark:
                    if 'article' in b:
                        title = ''
                        if 'title' in b['article']:
                            title = b['article']['title']

                        link = ''
                        if 'url' in b['article']:
                            link = b['article']['url']

                        content = ''
                        if 'excerpt' in b['article']:
                            content = b['article']['excerpt']

                        data.append(
                            {'title': title,
                             'link': link,
                             'content': content})

            cache.set('th_readability_' + str(trigger_id), data)

        return data

    def process_data(self, **kwargs):
        """
            get the data from the cache
            :param kwargs: contain keyword args : trigger_id at least
            :type kwargs: dict
        """
        kw = {'cache_stack': 'th_readability', 'trigger_id': str(kwargs['trigger_id'])}
        return super(ServiceReadability, self).process_data(**kw)

    def save_data(self, trigger_id, **data):
        """
            let's save the data

            :param trigger_id: trigger ID from which to save data
            :param data: the data to check to be used and save
            :type trigger_id: int
            :type data:  dict
            :return: the status of the save statement
            :rtype: boolean
        """
        status = False
        if self.token and 'link' in data and\
           data['link'] is not None and\
           len(data['link']) > 0:
            # get the data of this trigger
            trigger = Readability.objects.get(trigger_id=trigger_id)

            bookmark_id = self.client.add_bookmark(url=data['link'])

            if trigger.tag is not None and len(trigger.tag) > 0:
                try:
                    self.client.add_tags_to_bookmark(
                        bookmark_id, tags=(trigger.tag.lower()))
                    sentence = str('readability {} created item id {}').format(
                        data['link'], bookmark_id)
                    logger.debug(sentence)
                    status = True
                except Exception as e:
                    logger.critical(e)
                    status = False
        else:
            sentence = "no token or link provided for trigger ID {} "
            logger.critical(sentence.format(trigger_id))
            status = False

        return status

    def auth(self, request):
        """
            let's auth the user to the Service
        """
        request_token = super(ServiceReadability, self).auth(request)
        callback_url = self.callback_url(request, 'readability')

        # URL to redirect user to, to authorize your app
        auth_url_str = '%s?oauth_token=%s&oauth_callback=%s'
        auth_url = auth_url_str % (self.AUTH_URL,
                                   request_token['oauth_token'],
                                   callback_url)

        return auth_url

    def callback(self, request):
        """
            Called from the Service when the user accept to activate it
        """
        kwargs = {'access_token': '', 'service': 'ServiceReadability',
                  'return': 'readability'}
        return super(ServiceReadability, self).callback(request, **kwargs)
class ReaderClientSingleBookmarkTest(TestCase):
    """Tests that only need one bookmark

    """
    def setUp(self):
        """Get a client and add a bookmark

        """
        token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD)
        self.token_key = token_pair[0]
        self.token_secret = token_pair[1]

        self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET,
            self.token_key, self.token_secret)

        self.url = 'http://www.theatlantic.com/technology/archive/2013/01/the-never-before-told-story-of-the-worlds-first-computer-art-its-a-sexy-dame/267439/'
        add_response = self.base_client.add_bookmark(self.url)
        self.assertEqual(add_response.status, 202)

    def tearDown(self):
        """Remove all added bookmarks.

        """
        for bm in self.base_client.get_bookmarks().content['bookmarks']:
            del_response = self.base_client.delete_bookmark(bm['id'])
            self.assertEqual(del_response.status, 204)

    def test_get_bookmark(self):
        """Test getting one bookmark by id

        """
        # get a bookmark id
        bm_response = self.base_client.get_bookmarks()
        self.assertEqual(bm_response.status, 200)
        self.assertTrue(len(bm_response.content['bookmarks']) > 0)
        bookmark_id = bm_response.content['bookmarks'][0]['id']

        bm_response = self.base_client.get_bookmark(bookmark_id)
        self.assertEqual(bm_response.status, 200)
        some_expected_keys = set(['article', 'user_id', 'favorite', 'id'])
        received_keys = set(bm_response.content.keys())
        self.assertTrue(some_expected_keys.issubset(received_keys))


    def test_bookmark_tag_functionality(self):
        """Test adding, fetching and deleting tags on a bookmark.

        """
        # get a bookmark id
        bm_response = self.base_client.get_bookmarks()
        self.assertEqual(bm_response.status, 200)
        self.assertTrue(len(bm_response.content['bookmarks']) > 0)
        bookmark_id = bm_response.content['bookmarks'][0]['id']

        # test getting empty tags
        tag_response = self.base_client.get_bookmark_tags(bookmark_id)
        self.assertEqual(tag_response.status, 200)
        self.assertEqual(len(tag_response.content['tags']), 0)

        # test adding tags
        tags = ['tag', 'another tag']
        tag_string = ', '.join(tags)
        tag_add_response = \
            self.base_client.add_tags_to_bookmark(bookmark_id, tag_string)
        self.assertEqual(tag_add_response.status, 202)

        # re-fetch tags. should have 2
        retag_response = self.base_client.get_bookmark_tags(bookmark_id)
        self.assertEqual(retag_response.status, 200)
        self.assertEqual(len(retag_response.content['tags']), 2)
        for tag in retag_response.content['tags']:
            self.assertTrue(tag['text'] in tags)

        # test getting tags for user
        user_tag_resp = self.base_client.get_tags()
        self.assertEqual(user_tag_resp.status, 200)
        self.assertEqual(len(user_tag_resp.content['tags']), 2)
        for tag in user_tag_resp.content['tags']:
            self.assertTrue(tag['text'] in tags)

            # test getting a single tag while we're here
            single_tag_resp = self.base_client.get_tag(tag['id'])
            self.assertEqual(single_tag_resp.status, 200)
            self.assertTrue('applied_count' in single_tag_resp.content)
            self.assertTrue('id' in single_tag_resp.content)
            self.assertTrue('text' in single_tag_resp.content)

        # delete tags
        for tag in retag_response.content['tags']:
            del_response = self.base_client.delete_tag_from_bookmark(
                bookmark_id, tag['id'])
            self.assertEqual(del_response.status, 204)

        # check that tags are gone
        tag_response = self.base_client.get_bookmark_tags(bookmark_id)
        self.assertEqual(tag_response.status, 200)
        self.assertEqual(len(tag_response.content['tags']), 0)