[lutim] upgrade to Browser2

This commit is contained in:
Vincent A 2015-03-29 14:33:08 +02:00 committed by Romain Bignon
commit 89cda8fac9
5 changed files with 95 additions and 76 deletions

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright(C) 2014 Vincent A # Copyright(C) 2015 Vincent A
# #
# This file is part of weboob. # This file is part of weboob.
# #

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright(C) 2014 Vincent A # Copyright(C) 2015 Vincent A
# #
# This file is part of weboob. # This file is part of weboob.
# #
@ -18,31 +18,39 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>. # along with weboob. If not, see <http://www.gnu.org/licenses/>.
from weboob.deprecated.browser import Browser import math
from urlparse import urljoin
from StringIO import StringIO from StringIO import StringIO
import re from weboob.browser import PagesBrowser, URL
from .pages import PageAll from .pages import ImagePage, UploadPage
__all__ = ['LutimBrowser'] class LutimBrowser(PagesBrowser):
BASEURL = 'https://lut.im'
VERIFY = False # XXX SNI is not supported
image_page = URL('/(?P<id>.+)', ImagePage)
class LutimBrowser(Browser): upload_page = URL('/', UploadPage)
ENCODING = 'utf-8'
def __init__(self, base_url, *args, **kw): def __init__(self, base_url, *args, **kw):
Browser.__init__(self, *args, **kw) PagesBrowser.__init__(self, *args, **kw)
self.base_url = base_url self.base_url = self.BASEURL = base_url
self.PAGES = {re.escape(self.base_url): PageAll}
def post(self, name, content, max_days): def fetch(self, paste):
self.location(self.base_url) self.location(paste.id)
assert self.is_on_page(PageAll) assert self.image_page.is_here()
self.select_form(nr=0) paste.contents = unicode(self.page.contents.encode('base64'))
self.form['delete-day'] = [str(max_days)] paste.title = self.page.filename
self.form.find_control('file').add_file(StringIO(content), filename=name)
self.submit()
assert self.is_on_page(PageAll) def post(self, paste, max_age=0):
return self.page.get_info() bin = paste.contents.decode('base64')
name = paste.title or 'file' # filename is mandatory
filefield = {'file': (name, StringIO(bin))}
params = {'format': 'json'}
if max_age:
params['delete-day'] = math.ceil(max_age / 86400.)
self.location('/', data=params, files=filefield)
assert self.upload_page.is_here()
info = self.page.fetch_info()
paste.id = urljoin(self.base_url, info['short'])

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright(C) 2014 Vincent A # Copyright(C) 2015 Vincent A
# #
# This file is part of weboob. # This file is part of weboob.
# #
@ -18,12 +18,12 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>. # along with weboob. If not, see <http://www.gnu.org/licenses/>.
import re
from urlparse import urljoin
from weboob.tools.backend import Module, BackendConfig from weboob.tools.backend import Module, BackendConfig
from weboob.capabilities.paste import CapPaste, BasePaste from weboob.capabilities.paste import CapPaste, BasePaste
from weboob.tools.capabilities.paste import image_mime from weboob.tools.capabilities.paste import image_mime
from weboob.tools.value import Value from weboob.tools.value import Value
import re
from urlparse import urljoin
from .browser import LutimBrowser from .browser import LutimBrowser
@ -33,7 +33,7 @@ __all__ = ['LutimModule']
class LutimModule(Module, CapPaste): class LutimModule(Module, CapPaste):
NAME = 'lutim' NAME = 'lutim'
DESCRIPTION = u'LUTIm website' DESCRIPTION = u'lutim website'
MAINTAINER = u'Vincent A' MAINTAINER = u'Vincent A'
EMAIL = 'dev@indigo.re' EMAIL = 'dev@indigo.re'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
@ -41,55 +41,45 @@ class LutimModule(Module, CapPaste):
BROWSER = LutimBrowser BROWSER = LutimBrowser
CONFIG = BackendConfig(Value('base_url', label='Hoster base URL', default='http://lut.im/')) CONFIG = BackendConfig(Value('base_url', label='Hoster base URL', default='https://lut.im/'))
def _base_url(self): @property
def base_url(self):
url = self.config['base_url'].get() url = self.config['base_url'].get()
if not url.endswith('/'): if not url.endswith('/'):
url = url + '/' url = url + '/'
return url return url
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self._base_url()) return self.create_browser(self.base_url)
def can_post(self, contents, title=None, public=None, max_age=None): def can_post(self, contents, title=None, public=None, max_age=None):
if re.search(r'[^a-zA-Z0-9=+/\s]', contents): if public:
return 0 return 0
elif max_age and max_age < 86400: elif max_age and max_age < 86400:
return 0 # it cannot be shorter than one day return 0 # it cannot be shorter than one day
elif re.search(r'[^a-zA-Z0-9=+/\s]', contents):
return 0 # not base64, thus not binary
else: else:
mime = image_mime(contents, ('gif', 'jpeg', 'png')) mime = image_mime(contents, ('gif', 'jpeg', 'png'))
return 20 * int(mime is not None) return 20 * int(mime is not None)
def new_paste(self, *a, **kw): def get_paste(self, url):
base_url = self._base_url() if not url.startswith('http'):
url = urljoin(self.base_url, url)
paste = self.new_paste(url)
self.browser.fetch(paste)
return paste
class LutImage(BasePaste): def new_paste(self, _id):
@classmethod paste = LutimPaste(_id)
def id2url(cls, id): return paste
return urljoin(base_url, id)
@classmethod def post_paste(self, paste, max_age):
def url2id(cls, url): return self.browser.post(paste, max_age)
if url.startswith(base_url):
return url[len(base_url):]
return LutImage(*a, **kw)
def get_paste(self, id): class LutimPaste(BasePaste):
paste = self.new_paste(id) @classmethod
def id2url(cls, id):
if '/' in id: return id
paste.id = paste.url2id(id)
if not paste.id:
return None
response = self.browser.readurl(paste.page_url)
if response:
paste.contents = response.encode('base64')
return paste
def post_paste(self, paste, max_age=None):
d = self.browser.post(paste.title or None, paste.contents.decode('base64'), (max_age or 0) // 86400)
if d:
paste.id = d['id']

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright(C) 2014 Vincent A # Copyright(C) 2015 Vincent A
# #
# This file is part of weboob. # This file is part of weboob.
# #
@ -18,17 +18,26 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>. # along with weboob. If not, see <http://www.gnu.org/licenses/>.
from weboob.deprecated.browser import Page
import re import re
from weboob.browser.pages import JsonPage, RawPage
from weboob.capabilities.base import UserError
class PageAll(Page): class ImagePage(RawPage):
def post(self, name, content, max_days): @property
pass def contents(self):
return self.doc
def get_info(self): @property
for link in self.browser.links(): def filename(self):
linkurl = link.absolute_url header = self.response.headers['content-disposition']
m = re.match(re.escape(self.url) + r'([a-zA-Z0-9]+)\?dl$', linkurl) m = re.match('inline;filename="(.*)"', header)
if m: return unicode(m.group(1))
return {'id': m.group(1)}
class UploadPage(JsonPage):
def fetch_info(self):
if not self.doc['success']:
raise UserError(self.doc['msg']['msg'])
return self.doc['msg']

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright(C) 2014 Vincent A # Copyright(C) 2015 Vincent A
# #
# This file is part of weboob. # This file is part of weboob.
# #
@ -25,17 +25,29 @@ class LutimTest(BackendTest):
MODULE = 'lutim' MODULE = 'lutim'
# small gif file # small gif file
DATA = 'R0lGODlhAQABAIAAAP///wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==\n' DATA = u'R0lGODlhAQABAIAAAP///wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==\n'
TITLE = u'foo.gif'
def test_lutim(self): def test_lutim(self):
assert self.backend.can_post(self.DATA, max_age=86400)
post = self.backend.new_paste(None) post = self.backend.new_paste(None)
post.contents = self.DATA post.contents = self.DATA
post.public = True post.title = self.TITLE
assert self.backend.can_post(post.contents, post.title)
self.backend.post_paste(post, max_age=86400) self.backend.post_paste(post, max_age=86400)
assert post.id assert post.id
got = self.backend.get_paste(post.id) got = self.backend.get_paste(post.id)
assert got assert got
assert got.contents.decode('base64') == self.DATA.decode('base64') assert got.title == self.TITLE
assert got.contents == self.DATA
# test with an empty name
post.title = u''
self.backend.post_paste(post, max_age=86400)
def test_invalid(self):
post = self.backend.new_paste(None)
post.contents = u'FAIL'
post.title = self.TITLE
assert not self.backend.can_post(post.contents, post.title)