diff --git a/modules/unsplash/__init__.py b/modules/unsplash/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..d8efe61a9857a94cc59ea66e724dca4194dc3c1a
--- /dev/null
+++ b/modules/unsplash/__init__.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2017 Vincent A
+#
+# This file is part of a weboob module.
+#
+# This weboob module is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This weboob module is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this weboob module. If not, see .
+
+from __future__ import unicode_literals
+
+
+from .module import UnsplashModule
+
+
+__all__ = ['UnsplashModule']
diff --git a/modules/unsplash/browser.py b/modules/unsplash/browser.py
new file mode 100644
index 0000000000000000000000000000000000000000..8b4572872c79f4fcd83061b3880f40e0b1915579
--- /dev/null
+++ b/modules/unsplash/browser.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2017 Vincent A
+#
+# This file is part of a weboob module.
+#
+# This weboob module is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This weboob module is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this weboob module. If not, see .
+
+from weboob.browser import PagesBrowser, URL
+
+from .pages import ImageSearch
+
+
+class UnsplashBrowser(PagesBrowser):
+ BASEURL = 'https://unsplash.com'
+
+ collection_search = URL(r'/napi/search/collections\?query=(?P[^&]+)&page=(?P\d+)&per_page=20')
+ image_search = URL(r'/napi/search/photos\?query=(?P[^&]+)&page=(?P\d+)&per_page=20', ImageSearch)
+
+ def __init__(self, *args, **kwargs):
+ super(UnsplashBrowser, self).__init__(*args, **kwargs)
+ self.session.headers['Authorization'] = 'Client-ID d69927c7ea5c770fa2ce9a2f1e3589bd896454f7068f689d8e41a25b54fa6042'
+
+ def search_image(self, term):
+ n = 1
+ nb_pages = 1
+ while n <= nb_pages:
+ self.image_search.go(term=term, page=n)
+ for img in self.page.iter_images():
+ yield img
+ nb_pages = self.page.nb_pages()
+ n += 1
diff --git a/modules/unsplash/module.py b/modules/unsplash/module.py
new file mode 100644
index 0000000000000000000000000000000000000000..122df705b7dbf0720f322b84b3a9cf63a7a6b38a
--- /dev/null
+++ b/modules/unsplash/module.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2017 Vincent A
+#
+# This file is part of a weboob module.
+#
+# This weboob module is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This weboob module is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this weboob module. If not, see .
+
+from weboob.tools.backend import Module
+from weboob.capabilities.file import CapFile
+from weboob.capabilities.image import CapImage, BaseImage
+
+from .browser import UnsplashBrowser
+
+
+__all__ = ['UnsplashModule']
+
+
+class UnsplashModule(Module, CapImage):
+ NAME = 'unsplash'
+ DESCRIPTION = u'unsplash website'
+ MAINTAINER = u'Vincent A'
+ EMAIL = 'dev@indigo.re'
+ LICENSE = 'AGPLv3+'
+ VERSION = '2.1'
+
+ BROWSER = UnsplashBrowser
+
+ def search_image(self, pattern, sortby=CapFile.SEARCH_RELEVANCE, nsfw=False):
+ return self.browser.search_image(pattern)
+
+ def fill_image(self, img, fields):
+ if 'data' in fields:
+ img.data = self.browser.open(img.url).content
+ if 'thumbnail' in fields:
+ img.thumbnail.data = self.browser.open(img.thumbnail.url).content
+
+ OBJECTS = {BaseImage: fill_image}
diff --git a/modules/unsplash/pages.py b/modules/unsplash/pages.py
new file mode 100644
index 0000000000000000000000000000000000000000..c9644490cb668f01039666427ef297e51c176ea9
--- /dev/null
+++ b/modules/unsplash/pages.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2017 Vincent A
+#
+# This file is part of a weboob module.
+#
+# This weboob module is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This weboob module is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this weboob module. If not, see .
+
+from weboob.browser.pages import JsonPage
+from weboob.browser.elements import DictElement, ItemElement, method
+from weboob.browser.filters.json import Dict
+from weboob.browser.filters.standard import DateTime, Field, Format
+from weboob.capabilities.image import BaseImage, Thumbnail
+from weboob.capabilities.file import LICENSES
+
+
+class CollectionSearch(JsonPage):
+ def do_stuff(self, _id):
+ raise NotImplementedError()
+
+
+class ImageSearch(JsonPage):
+ def nb_pages(self):
+ return self.doc['total_pages']
+
+ @method
+ class iter_images(DictElement):
+ item_xpath = 'results'
+
+ class item(ItemElement):
+ klass = BaseImage
+
+ obj_id = Dict('id')
+ obj_nsfw = False
+ obj_license = LICENSES.PD
+ obj_author = Dict('user/name')
+ obj_url = Dict('urls/full')
+ obj_date = DateTime(Dict('created_at'))
+ obj_title = Format('%s (%s)', Field('id'), Field('author'))
+ obj_ext = 'jpg'
+
+ def obj_thumbnail(self):
+ return Thumbnail(Dict('urls/thumb')(self))
diff --git a/modules/unsplash/test.py b/modules/unsplash/test.py
new file mode 100644
index 0000000000000000000000000000000000000000..9d38f09027c7d1b728e2955598a0e242ed32817c
--- /dev/null
+++ b/modules/unsplash/test.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2017 Vincent A
+#
+# This file is part of a weboob module.
+#
+# This weboob module is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This weboob module is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this weboob module. If not, see .
+
+from weboob.tools.test import BackendTest
+
+
+class UnsplashTest(BackendTest):
+ MODULE = 'unsplash'
+
+ def test_search_img(self):
+ it = self.backend.search_image('tree')
+ images = [img for _, img in zip(range(20), it)]
+
+ self.assertEqual(len(images), 20)
+ for img in images:
+ assert img.id
+ assert img.title
+ assert img.ext
+ assert img.author
+ assert img.date
+ assert img.url
+
+ self.backend.fillobj(img, 'data')
+ assert img.data
+
+ self.backend.fillobj(img, 'thumbnail')
+ assert img.thumbnail.data