Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e5fdb1c50 | ||
|
|
e892d3ceeb | ||
|
|
e52b8befe4 | ||
|
|
259f62efd9 | ||
|
|
07f6057421 | ||
|
|
944e1302d8 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.idea
|
||||
@@ -7,8 +7,7 @@ Python API for Wallabag v2
|
||||
Requirements :
|
||||
==============
|
||||
|
||||
* requests 2.5.0
|
||||
|
||||
* requests
|
||||
|
||||
Installation:
|
||||
=============
|
||||
@@ -17,7 +16,7 @@ to get the project, from your virtualenv, do :
|
||||
|
||||
.. code:: python
|
||||
|
||||
git clone https://github.com/foxmask/wallabag-api/
|
||||
git clone https://github.com/push-things/wallabag-api/
|
||||
|
||||
|
||||
or
|
||||
@@ -58,7 +57,7 @@ Creating a post :
|
||||
|
||||
this will give you something like this :
|
||||
|
||||
.. image:: https://github.com/foxmask/wallabag_api/blob/master/wallabag.png
|
||||
.. image:: https://github.com/push-things/wallabag_api/blob/master/wallabag.png
|
||||
|
||||
|
||||
|
||||
@@ -71,7 +70,7 @@ Then create a client API like explain here http://doc.wallabag.org/en/v2/develop
|
||||
|
||||
this will give you somthing like this
|
||||
|
||||
.. image:: https://github.com/foxmask/wallabag_api/blob/master/wallabag_api_key.png
|
||||
.. image:: https://github.com/push-things/wallabag_api/blob/master/wallabag_api_key.png
|
||||
|
||||
Then replace the client_id / client_secret / login / pass to wallabag_test.py and run
|
||||
|
||||
|
||||
14
setup.py
14
setup.py
@@ -2,18 +2,19 @@ from setuptools import setup, find_packages
|
||||
from wallabag_api import __version__ as version
|
||||
|
||||
install_requires = [
|
||||
'requests==2.5.0',
|
||||
'requests',
|
||||
]
|
||||
|
||||
setup(
|
||||
name='wallabag_api',
|
||||
version=version,
|
||||
description='Wallabag API to add every pages you want to your Wallabag account',
|
||||
long_desc='Wallabag is a "read it later" service, and that Wallabag API allow you to save web pages '
|
||||
'to your own account',
|
||||
author='FoxMaSk',
|
||||
author_email='foxmask@trigger-happy.eu',
|
||||
url='https://github.com/foxmask/wallabag_api',
|
||||
download_url="https://github.com/foxmask/wallabag_api/archive/"
|
||||
"wallabag_api-" + version + ".zip",
|
||||
author_email='foxmaskhome@gmail.com',
|
||||
url='https://github.com/push-things/wallabag_api',
|
||||
download_url="https://github.com/push-things/wallabag_api/archive/wallabag_api-" + version + ".zip",
|
||||
packages=find_packages(),
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
@@ -23,6 +24,9 @@ setup(
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Topic :: Internet',
|
||||
'Topic :: Communications',
|
||||
],
|
||||
install_requires=install_requires,
|
||||
include_package_data=True,
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
VERSION = (1, 0, 0) # PEP 386
|
||||
VERSION = (1, 1, 4) # PEP 386
|
||||
__version__ = ".".join([str(x) for x in VERSION])
|
||||
@@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# coding: utf-8
|
||||
import requests
|
||||
from requests import HTTPError
|
||||
import logging
|
||||
|
||||
__author__ = 'foxmask'
|
||||
@@ -15,7 +16,7 @@ class Wallabag(object):
|
||||
Python Class 'Wallabag' to deal with Wallabag REST API
|
||||
This class is able to handle any data from your Wallabag account
|
||||
"""
|
||||
|
||||
EXTENTIONS = ('xml', 'json', 'txt', 'csv', 'pdf', 'epub', 'mobi', 'html')
|
||||
host = ''
|
||||
token = ''
|
||||
client_id = ''
|
||||
@@ -39,7 +40,7 @@ class Wallabag(object):
|
||||
:param token: string of the key provided by Wallabag
|
||||
:param client_id client id
|
||||
:param client_secret client secret
|
||||
:param extension: json/xml/html
|
||||
:param extension: xml|json|txt|csv|pdf|epub|mobi|html
|
||||
:param user_agent
|
||||
"""
|
||||
self.host = host
|
||||
@@ -49,6 +50,10 @@ class Wallabag(object):
|
||||
self.format = extension
|
||||
self.user_agent = user_agent
|
||||
|
||||
if self.format not in self.EXTENTIONS:
|
||||
raise ValueError("format invalid {0} should be one of {1}".format(
|
||||
self.format, self.EXTENTIONS))
|
||||
|
||||
def get_host(self):
|
||||
"""
|
||||
get the host from which to get API
|
||||
@@ -87,9 +92,13 @@ class Wallabag(object):
|
||||
:param responses: the json response
|
||||
:return the json data without 'root' node
|
||||
"""
|
||||
if responses.status_code != 200:
|
||||
raise Exception("Wrong status code: ", responses.status_code)
|
||||
json_data = {}
|
||||
if responses.status_code != 200:
|
||||
err_msg = HTTPError(responses.status_code, responses.reason)
|
||||
msg = "Wallabag: error {err_msg}".format(err_msg=err_msg)
|
||||
logging.error(msg)
|
||||
raise HTTPError(msg)
|
||||
else:
|
||||
try:
|
||||
json_data = responses.json()
|
||||
except:
|
||||
@@ -98,6 +107,7 @@ class Wallabag(object):
|
||||
logging.error("Wallabag: {error}".format(error=error_json))
|
||||
return json_data
|
||||
|
||||
# ENTRIES
|
||||
def get_entries(self, **kwargs):
|
||||
"""
|
||||
|
||||
@@ -147,9 +157,9 @@ class Wallabag(object):
|
||||
|
||||
return self.query(path, "get", **params)
|
||||
|
||||
def post_entries(self, url, title='', tags='', starred=0, archive=0):
|
||||
def post_entries(self, url, title='', tags='', starred=0, archive=0, content='', language='', published_at='',
|
||||
authors='', public=1, original_url=''):
|
||||
"""
|
||||
|
||||
POST /api/entries.{_format}
|
||||
|
||||
Create an entry
|
||||
@@ -159,10 +169,18 @@ class Wallabag(object):
|
||||
:param tags: tag1,tag2,tag3 a comma-separated list of tags.
|
||||
:param starred entry already starred
|
||||
:param archive entry already archived
|
||||
:param content additionnal html content
|
||||
:param language
|
||||
:param published_at
|
||||
:param authors
|
||||
:param public
|
||||
:param original_url
|
||||
:return result
|
||||
"""
|
||||
params = {'access_token': self.token, 'url': url, 'title': title,
|
||||
'tags': tags, 'starred': starred, 'archive': archive}
|
||||
'tags': tags, 'starred': starred, 'archive': archive,
|
||||
'content': content, 'language': language, 'published_at': published_at,
|
||||
'authors': authors, 'public': public, 'original_url': original_url}
|
||||
if len(tags) > 0 and isinstance(tags, list):
|
||||
params['tags'] = ', '.join(tags)
|
||||
path = '/api/entries.{ext}'.format(ext=self.format)
|
||||
@@ -170,7 +188,6 @@ class Wallabag(object):
|
||||
|
||||
def get_entry(self, entry):
|
||||
"""
|
||||
|
||||
GET /api/entries/{entry}.{_format}
|
||||
|
||||
Retrieve a single entry
|
||||
@@ -184,7 +201,6 @@ class Wallabag(object):
|
||||
|
||||
def patch_entries(self, entry, **kwargs):
|
||||
"""
|
||||
|
||||
PATCH /api/entries/{entry}.{_format}
|
||||
|
||||
Change several properties of an entry
|
||||
@@ -206,6 +222,7 @@ class Wallabag(object):
|
||||
'tags': [],
|
||||
'star': 0,
|
||||
'delete': 0}
|
||||
|
||||
if 'title' in kwargs:
|
||||
params['title'] = kwargs['title']
|
||||
if 'tags' in kwargs and isinstance(kwargs['tags'], list):
|
||||
@@ -220,9 +237,38 @@ class Wallabag(object):
|
||||
entry=entry, ext=self.format)
|
||||
return self.query(path, "patch", **params)
|
||||
|
||||
def get_entry_export(self, entry):
|
||||
"""
|
||||
GET /api/entries/{entry}/export.{_format}
|
||||
|
||||
Retrieve a single entry as a predefined format.
|
||||
|
||||
:param entry: \w+ an integer The Entry ID
|
||||
:return data related to the ext
|
||||
"""
|
||||
params = {'access_token': self.token}
|
||||
url = '/api/entries/{entry}/export.{ext}'.format(entry=entry,
|
||||
ext=self.format)
|
||||
return self.query(url, "get", **params)
|
||||
|
||||
def patch_entry_reload(self, entry):
|
||||
"""
|
||||
PATCH /api/entries/{entry}/reload.{_format}
|
||||
|
||||
Reload an entry. An empty response with HTTP Status 304 will be send
|
||||
if we weren't able to update the content (because it hasn't changed
|
||||
or we got an error).
|
||||
|
||||
:param entry: \w+ an integer The Entry ID
|
||||
:return data related to the ext
|
||||
"""
|
||||
params = {'access_token': self.token}
|
||||
url = '/api/entries/{entry}/reload.{ext}'.format(entry=entry,
|
||||
ext=self.format)
|
||||
return self.query(url, "patch", **params)
|
||||
|
||||
def delete_entries(self, entry):
|
||||
"""
|
||||
|
||||
DELETE /api/entries/{entry}.{_format}
|
||||
|
||||
Delete permanently an entry
|
||||
@@ -236,9 +282,28 @@ class Wallabag(object):
|
||||
entry=entry, ext=self.format)
|
||||
return self.query(path, "delete", **params)
|
||||
|
||||
def entries_exists(self, url, urls=''):
|
||||
"""
|
||||
GET /api/entries/exists.{_format}
|
||||
|
||||
Check if an entry exist by url.
|
||||
|
||||
:param url string true An url Url to check if it exists
|
||||
:param urls string false An array of urls
|
||||
(?urls[]=http...&urls[]=http...) Urls (as an array)
|
||||
to check if it exists
|
||||
|
||||
:return result
|
||||
"""
|
||||
params = {'url': url,
|
||||
'urls': urls}
|
||||
|
||||
path = '/api/entries/exists.{ext}'.format(ext=self.format)
|
||||
return self.query(path, "get", **params)
|
||||
|
||||
# TAGS
|
||||
def get_entry_tags(self, entry):
|
||||
"""
|
||||
|
||||
GET /api/entries/{entry}/tags.{_format}
|
||||
|
||||
Retrieve all tags for an entry
|
||||
@@ -253,7 +318,6 @@ class Wallabag(object):
|
||||
|
||||
def post_entry_tags(self, entry, tags):
|
||||
"""
|
||||
|
||||
POST /api/entries/{entry}/tags.{_format}
|
||||
|
||||
Add one or more tags to an entry
|
||||
@@ -271,7 +335,6 @@ class Wallabag(object):
|
||||
|
||||
def delete_entry_tag(self, entry, tag):
|
||||
"""
|
||||
|
||||
DELETE /api/entries/{entry}/tags/{tag}.{_format}
|
||||
|
||||
Permanently remove one tag for an entry
|
||||
@@ -287,7 +350,6 @@ class Wallabag(object):
|
||||
|
||||
def get_tags(self):
|
||||
"""
|
||||
|
||||
GET /api/tags.{_format}
|
||||
|
||||
Retrieve all tags
|
||||
@@ -300,7 +362,6 @@ class Wallabag(object):
|
||||
|
||||
def delete_tag(self, tag):
|
||||
"""
|
||||
|
||||
DELETE /api/tags/{tag}.{_format}
|
||||
|
||||
Permanently remove one tag from every entry
|
||||
@@ -312,9 +373,129 @@ class Wallabag(object):
|
||||
params = {'access_token': self.token}
|
||||
return self.query(path, "delete", **params)
|
||||
|
||||
def delete_tag_label(self, tag):
|
||||
"""
|
||||
DELETE /api/tag/label.{_format}
|
||||
|
||||
Permanently remove one tag from every entry.
|
||||
|
||||
:param tag: string The Tag
|
||||
:return data related to the ext
|
||||
"""
|
||||
path = '/api/tag/label.{ext}'.format(ext=self.format)
|
||||
params = {'access_token': self.token,
|
||||
'tag': tag}
|
||||
return self.query(path, "delete", **params)
|
||||
|
||||
def delete_tags_label(self, tags):
|
||||
"""
|
||||
DELETE /api/tags/label.{_format}
|
||||
|
||||
Permanently remove some tags from every entry.
|
||||
|
||||
:param tags: string tags as strings (comma splitted)
|
||||
:return data related to the ext
|
||||
"""
|
||||
path = '/api/tag/label.{ext}'.format(ext=self.format)
|
||||
params = {'access_token': self.token,
|
||||
'tags': tags}
|
||||
return self.query(path, "delete", **params)
|
||||
|
||||
# ANNOTATIONS
|
||||
def delete_annotations(self, annotation):
|
||||
"""
|
||||
DELETE /api/annotations/{annotation}.{_format}
|
||||
|
||||
Removes an annotation.
|
||||
|
||||
:param annotation \w+ string The annotation ID
|
||||
|
||||
Will returns annotation for this entry
|
||||
:return data related to the ext
|
||||
"""
|
||||
params = {'access_token': self.token}
|
||||
url = '/api/annotations/{annotation}.{ext}'.format(
|
||||
annotation=annotation, ext=self.format)
|
||||
return self.query(url, "delete", **params)
|
||||
|
||||
def put_annotations(self, annotation):
|
||||
"""
|
||||
PUT /api/annotations/{annotation}.{_format}
|
||||
|
||||
Updates an annotation.
|
||||
|
||||
:param annotation \w+ string The annotation ID
|
||||
|
||||
Will returns annotation for this entry
|
||||
:return data related to the ext
|
||||
"""
|
||||
params = {'access_token': self.token}
|
||||
url = '/api/annotations/{annotation}.{ext}'.format(
|
||||
annotation=annotation, ext=self.format)
|
||||
return self.query(url, "put", **params)
|
||||
|
||||
def get_annotations(self, entry):
|
||||
"""
|
||||
GET /api/annotations/{entry}.{_format}
|
||||
|
||||
Retrieve annotations for an entry
|
||||
|
||||
:param entry \w+ integer The entry ID
|
||||
|
||||
Will returns annotation for this entry
|
||||
:return data related to the ext
|
||||
"""
|
||||
params = {'access_token': self.token}
|
||||
url = '/api/annotations/{entry}.{ext}'.format(entry=entry,
|
||||
ext=self.format)
|
||||
return self.query(url, "get", **params)
|
||||
|
||||
def post_annotations(self, entry, **kwargs):
|
||||
"""
|
||||
POST /api/annotations/{entry}.{_format}
|
||||
|
||||
Creates a new annotation.
|
||||
|
||||
:param entry \w+ integer The entry ID
|
||||
|
||||
:return
|
||||
"""
|
||||
params = dict({'access_token': self.token,
|
||||
'ranges': [],
|
||||
'quote': '',
|
||||
'text': ''})
|
||||
if 'ranges' in kwargs:
|
||||
params['ranges'] = kwargs['ranges']
|
||||
if 'quote' in kwargs:
|
||||
params['quote'] = kwargs['quote']
|
||||
if 'text' in kwargs:
|
||||
params['text'] = kwargs['text']
|
||||
|
||||
url = '/api/annotations/{entry}.{ext}'.format(entry=entry,
|
||||
ext=self.format)
|
||||
return self.query(url, "post", **params)
|
||||
|
||||
# VERSION
|
||||
@property
|
||||
def version(self):
|
||||
"""
|
||||
GET /api/version.{_format}
|
||||
|
||||
Retrieve version number
|
||||
|
||||
:return data related to the ext
|
||||
"""
|
||||
params = {'access_token': self.token}
|
||||
url = '/api/version.{ext}'.format(ext=self.format)
|
||||
return self.query(url, "get", **params)
|
||||
|
||||
@classmethod
|
||||
def get_token(cls, host, **params):
|
||||
"""
|
||||
POST /oauth/v2/token
|
||||
|
||||
Get a new token
|
||||
|
||||
:param host: host of the service
|
||||
:param params: will contain :
|
||||
|
||||
@@ -326,7 +507,8 @@ class Wallabag(object):
|
||||
|
||||
:return: access token
|
||||
"""
|
||||
params['grant_type'] = ["password"]
|
||||
params['grant_type'] = "password"
|
||||
path = "/oauth/v2/token"
|
||||
r = requests.post(host + path, data=params)
|
||||
return cls.handle_json_response(r)['access_token']
|
||||
resp = requests.post(host + path, data=params)
|
||||
data = cls.handle_json_response(resp)
|
||||
return data.get('access_token')
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# coding: utf-8
|
||||
import datetime
|
||||
import unittest
|
||||
from wallabag import Wallabag
|
||||
|
||||
|
||||
class TestWallabag(unittest.TestCase):
|
||||
|
||||
host = 'http://localhost:8080'
|
||||
host = 'http://bag.foxmask'
|
||||
client_id = ''
|
||||
client_secret = ''
|
||||
token = ''
|
||||
@@ -20,22 +21,29 @@ class TestWallabag(unittest.TestCase):
|
||||
|
||||
def test_get_token(self):
|
||||
params = {"grant_type": "password",
|
||||
"client_id": '1_37e16ub8a62oc4gwcg0o0wssks800kw0ok408kkwo4kosgc88g',
|
||||
"client_secret": '49etxpn66da8okg4cs40sswsog0sskwg4woc400c4w4w8s4wo4',
|
||||
"client_id": '1_3to3042y05gk8g4wcsk40w40k8kk00s04gwcoo4sows8wskcg0',
|
||||
"client_secret": 'ift9k07vd20ccg4ocosg0cw4kkgk4o8080848scwg0oosowow',
|
||||
"username": 'foxmask',
|
||||
"password": 'ratatab00m'}
|
||||
|
||||
data = Wallabag.get_token(host='http://localhost:8080', **params)
|
||||
data = Wallabag.get_token(host=self.host, **params)
|
||||
self.assertTrue(isinstance(data, str), True)
|
||||
return data
|
||||
|
||||
def create_entry(self):
|
||||
title = 'foobar title'
|
||||
url = 'https://smcomm.trigger-happy.eu/'
|
||||
url = 'https://somwhere.over.the.raibow.com/'
|
||||
tags = ['foo', 'bar']
|
||||
starred = 0
|
||||
archive = 0
|
||||
data = self.w.post_entries(url, title, tags, starred, archive)
|
||||
content = '<p>Additional content</p>'
|
||||
language = 'FR'
|
||||
published_at = datetime.datetime.now()
|
||||
authors = 'John Doe'
|
||||
public = 0
|
||||
original_url = 'http://localhost'
|
||||
data = self.w.post_entries(url, title, tags, starred, archive, content, language, published_at, authors,
|
||||
public, original_url)
|
||||
return data
|
||||
|
||||
def test_get_entries(self):
|
||||
@@ -96,15 +104,6 @@ class TestWallabag(unittest.TestCase):
|
||||
data = self.w.post_entry_tags(entry, tags)
|
||||
self.assertTrue(data, True)
|
||||
|
||||
"""
|
||||
def test_delete_entry_tag(self):
|
||||
entry = self.create_entry()
|
||||
tag = 'bar'
|
||||
self.assertTrue(isinstance(entry['id'], int), True)
|
||||
self.assertTrue(isinstance(tag, str), True)
|
||||
resp = self.w.delete_entry_tag(entry['id'], tag)
|
||||
self.assertTrue(resp, True)
|
||||
"""
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user