From dcb6cad8001f691c751340236e5e2c640966ecf5 Mon Sep 17 00:00:00 2001 From: Bezleputh Date: Thu, 22 May 2014 11:15:54 +0200 Subject: [PATCH] [twitter] allow to browse home tweets --- modules/twitter/backend.py | 18 +++++++++++++++++- modules/twitter/browser.py | 18 ++++++++++++++---- modules/twitter/pages.py | 23 +++++++++++++++++------ 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/modules/twitter/backend.py b/modules/twitter/backend.py index 34baa90e..c625586a 100644 --- a/modules/twitter/backend.py +++ b/modules/twitter/backend.py @@ -22,6 +22,7 @@ from datetime import time, datetime, timedelta from weboob.tools.value import Value, ValueBackendPassword from weboob.tools.backend import BaseBackend, BackendConfig from weboob.capabilities.messages import ICapMessages, Thread, ICapMessagesPost +from weboob.capabilities.collection import ICapCollection, CollectionNotFound from weboob.capabilities.base import find_object from weboob.tools.exceptions import BrowserForbidden from .browser import TwitterBrowser @@ -30,7 +31,7 @@ from .browser import TwitterBrowser __all__ = ['TwitterBackend'] -class TwitterBackend(BaseBackend, ICapMessages, ICapMessagesPost): +class TwitterBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapCollection): NAME = 'twitter' DESCRIPTION = u'twitter website' MAINTAINER = u'Bezleputh' @@ -96,4 +97,19 @@ class TwitterBackend(BaseBackend, ICapMessages, ICapMessagesPost): self.browser.post(find_object(self.iter_threads(), id=message.full_id.split('.')[0]), message.content) + def iter_resources(self, objs, split_path): + collection = self.get_collection(objs, split_path) + if collection.path_level == 0: + return self.browser.get_collections() + if collection.path_level == 1: + return self.browser.get_tweets_from_collection(collection.split_path[0]) + + def validate_collection(self, objs, collection): + if collection.path_level == 0: + return + if collection.path_level == 1: + return + + raise CollectionNotFound(collection.split_path) + OBJECTS = {Thread: fill_thread} diff --git a/modules/twitter/browser.py b/modules/twitter/browser.py index 14d13d46..f59405df 100644 --- a/modules/twitter/browser.py +++ b/modules/twitter/browser.py @@ -20,8 +20,8 @@ from weboob.tools.browser2 import LoginBrowser, URL, need_login from weboob.tools.browser import BrowserIncorrectPassword from weboob.capabilities.messages import Message - -from .pages import LoginPage, LoginErrorPage, ThreadPage, HomePage, Tweet +from weboob.capabilities.collection import Collection +from .pages import LoginPage, LoginErrorPage, ThreadPage, TwitterBasePage, Tweet __all__ = ['TwitterBrowser'] @@ -33,7 +33,7 @@ class TwitterBrowser(LoginBrowser): thread_page = URL(u'(?P.+)/status/(?P<_id>.+)', ThreadPage) login_error = URL(u'login/error.+', LoginErrorPage) tweet = URL(u'i/tweet/create', Tweet) - home = URL(u'(?P.+)', HomePage) + twitter_page = URL(u'(?P.+)', TwitterBasePage) login = URL(u'', LoginPage) def do_login(self): @@ -45,7 +45,9 @@ class TwitterBrowser(LoginBrowser): if not self.page.logged or self.login_error.is_here(): raise BrowserIncorrectPassword() - self.me = self.page.get_me() + @need_login + def get_me(self): + return self.login.stay_or_go().get_me() @need_login def iter_threads(self): @@ -94,3 +96,11 @@ class TwitterBrowser(LoginBrowser): thread.root.children.append(comment) return thread + + def get_collections(self): + if self.username: + me = self.get_me() + yield Collection([me], me) + + def get_tweets_from_collection(self, path): + return self.twitter_page.go(path=path).iter_threads() diff --git a/modules/twitter/pages.py b/modules/twitter/pages.py index 63257cc9..60aac702 100644 --- a/modules/twitter/pages.py +++ b/modules/twitter/pages.py @@ -24,7 +24,7 @@ from weboob.tools.browser2.page import HTMLPage, JsonPage, method, ListElement, from weboob.tools.browser2.filters import CleanText, Format, Link, Regexp, Env, DateTime, Attr, Filter from weboob.capabilities.messages import Thread, Message -__all__ = ['LoginPage', 'LoginErrorPage', 'ThreadPage', 'HomePage', 'Tweet'] +__all__ = ['LoginPage', 'LoginErrorPage', 'ThreadPage', 'TwitterBasePage', 'Tweet'] class DatetimeFromTimestamp(Filter): @@ -32,7 +32,22 @@ class DatetimeFromTimestamp(Filter): return datetime.fromtimestamp(float(el)) -class LoginPage(HTMLPage): +class TwitterBasePage(HTMLPage): + @method + class iter_threads(ListElement): + item_xpath = '//li[@data-item-type="tweet"]/div' + + class item(ItemElement): + klass = Thread + + obj_id = Regexp(Link('./div/div/a[@class="details with-icn js-details"]'), '/(.+)/status/(.+)', '\\1#\\2') + obj_title = Format('%s \n\t %s', + CleanText('./div/div[@class="stream-item-header"]/a'), + CleanText('./div/p')) + obj_date = DatetimeFromTimestamp(Attr('./div/div[@class="stream-item-header"]/small/a/span', 'data-time')) + + +class LoginPage(TwitterBasePage): def login(self, login, passwd): form = self.get_form(xpath='//form[@action="https://twitter.com/sessions"]') form['session[username_or_email]'] = login @@ -100,7 +115,3 @@ class LoginErrorPage(HTMLPage): class Tweet(JsonPage): pass - - -class HomePage(HTMLPage): - pass