Compare commits
20 Commits
1.0.0
...
wallabag_a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c40a35559 | ||
|
|
a9e0335054 | ||
|
|
6a7573069b | ||
|
|
c92e55208a | ||
|
|
aea9df0978 | ||
|
|
9fbd7cc28d | ||
|
|
3264fda186 | ||
|
|
922c47f1cf | ||
|
|
fa9c6360a5 | ||
|
|
12c30c6af3 | ||
|
|
546d744722 | ||
|
|
fbf71efa71 | ||
|
|
c5c7fa06b1 | ||
|
|
86e5c02b0f | ||
|
|
99bfd7c08b | ||
|
|
8ce21dcdd3 | ||
|
|
b11f648ec9 | ||
|
|
4ad230a83e | ||
|
|
07f6057421 | ||
|
|
944e1302d8 |
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
.idea
|
||||
*.log
|
||||
*.pot
|
||||
*.pyc
|
||||
.coverage
|
||||
*.json
|
||||
.tox
|
||||
build
|
||||
88
README.rst
88
README.rst
@@ -1,13 +1,23 @@
|
||||
.. image:: http://img.shields.io/badge/python-3.6-orange.svg
|
||||
:target: https://pypi.python.org/pypi/django-th/
|
||||
:alt: Python version supported
|
||||
|
||||
|
||||
.. image:: http://img.shields.io/badge/license-BSD-blue.svg
|
||||
:target: https://pypi.python.org/pypi/django-th/
|
||||
:alt: License
|
||||
|
||||
|
||||
============
|
||||
Wallabag API
|
||||
============
|
||||
|
||||
Python API for Wallabag v2
|
||||
Python API for Wallabag v2.2.3
|
||||
|
||||
Requirements :
|
||||
==============
|
||||
|
||||
* requests 2.5.0
|
||||
* aiohttp
|
||||
|
||||
|
||||
Installation:
|
||||
@@ -36,24 +46,66 @@ Creating a post :
|
||||
|
||||
.. code:: python
|
||||
|
||||
#!/usr/bin/env python
|
||||
|
||||
import aiohttp
|
||||
import asyncio
|
||||
|
||||
from wallabag_api.wallabag import Wallabag
|
||||
# settings
|
||||
params = {'username': 'foxmask',
|
||||
'password': 'mypass',
|
||||
'client_id': 'myid',
|
||||
'client_secret': 'mysecret'}
|
||||
# settings
|
||||
my_host = 'http://localhost:8080'
|
||||
# get token
|
||||
token = Wallabag.get_token(host=my_host, **params)
|
||||
|
||||
# create a post
|
||||
wall = Wallabag(host=my_host, client_secret='mysecret', client_id='myid', token=token)
|
||||
|
||||
my_url = 'https://blog.trigger-happy.eu'
|
||||
my_title = 'Trigger Happy blog'
|
||||
my_tags = ['python', 'wallabag']
|
||||
async def main(loop):
|
||||
|
||||
wall.post_entries(url=my_url, title=my_title, tags=my_tags)
|
||||
params = {'username': 'foxmask',
|
||||
'password': 'mypass',
|
||||
'client_id': 'myid',
|
||||
'client_secret': 'mysecret',
|
||||
'extension': 'pdf'}
|
||||
|
||||
# get a new token
|
||||
token = await Wallabag.get_token(host=my_host, **params)
|
||||
|
||||
# initializing
|
||||
async with aiohttp.ClientSession(loop=loop) as session:
|
||||
wall = Wallabag(host=my_host,
|
||||
client_secret=params.get('client_secret'),
|
||||
client_id=params.get('client_id'),
|
||||
token=token,
|
||||
extension=params['extension'],
|
||||
aio_sess=session)
|
||||
|
||||
url = 'https://foxmask.trigger-happy.eu'
|
||||
title = 'foxmask\'s blog'
|
||||
|
||||
await wall.post_entries(url, title, '', 0, 0)
|
||||
|
||||
url = 'https://trigger-happy.eu'
|
||||
title = 'Project TrigerHappy'
|
||||
|
||||
await wall.post_entries(url, title, '', 0, 0)
|
||||
|
||||
# get all the articles
|
||||
my_wallabag = await wall.get_entries()
|
||||
|
||||
all_article = my_wallabag['_embedded']['items']
|
||||
|
||||
for article in all_article:
|
||||
print(article['id'], article['title'])
|
||||
|
||||
# get the version of wallabag
|
||||
version = await wall.version
|
||||
print(f"version {version}")
|
||||
|
||||
# export one article into PDF
|
||||
my_wallabag = await wall.get_entry_export(entry=1)
|
||||
with open("foobar.pdf", "wb") as f:
|
||||
f.write(my_wallabag)
|
||||
|
||||
if __name__ == '__main__':
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(main(loop))
|
||||
|
||||
|
||||
this will give you something like this :
|
||||
@@ -61,15 +113,16 @@ this will give you something like this :
|
||||
.. image:: https://github.com/foxmask/wallabag_api/blob/master/wallabag.png
|
||||
|
||||
|
||||
|
||||
Testing :
|
||||
=========
|
||||
|
||||
Install Wallabag V2 on your own host like explain here http://doc.wallabag.org/en/v2/user/installation.html
|
||||
|
||||
Then run the development version (with make run)
|
||||
|
||||
Then create a client API like explain here http://doc.wallabag.org/en/v2/developer/api.html
|
||||
|
||||
this will give you somthing like this
|
||||
this will give you something like this
|
||||
|
||||
.. image:: https://github.com/foxmask/wallabag_api/blob/master/wallabag_api_key.png
|
||||
|
||||
@@ -79,4 +132,3 @@ Then replace the client_id / client_secret / login / pass to wallabag_test.py an
|
||||
|
||||
python wallabag_test.py
|
||||
|
||||
|
||||
|
||||
12
setup.py
12
setup.py
@@ -1,14 +1,15 @@
|
||||
from setuptools import setup, find_packages
|
||||
from wallabag_api import __version__ as version
|
||||
|
||||
desc = 'Wallabag API to add every pages you want to your Wallabag account'
|
||||
install_requires = [
|
||||
'requests==2.5.0',
|
||||
'aiohttp==2.2.5',
|
||||
]
|
||||
|
||||
setup(
|
||||
name='wallabag_api',
|
||||
version=version,
|
||||
description='Wallabag API to add every pages you want to your Wallabag account',
|
||||
description=desc,
|
||||
author='FoxMaSk',
|
||||
author_email='foxmask@trigger-happy.eu',
|
||||
url='https://github.com/foxmask/wallabag_api',
|
||||
@@ -16,13 +17,14 @@ setup(
|
||||
"wallabag_api-" + version + ".zip",
|
||||
packages=find_packages(),
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Operating System :: OS Independent',
|
||||
'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, 2, 0) # PEP 386
|
||||
__version__ = ".".join([str(x) for x in VERSION])
|
||||
@@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import requests
|
||||
# coding: utf-8
|
||||
import logging
|
||||
import aiohttp
|
||||
from aiohttp.http_exceptions import HttpProcessingError
|
||||
from aiohttp.client_exceptions import ClientResponseError
|
||||
|
||||
__author__ = 'foxmask'
|
||||
|
||||
|
||||
logging.basicConfig(format='%(message)s', level=logging.INFO)
|
||||
|
||||
__all__ = ['Wallabag']
|
||||
@@ -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 = ''
|
||||
@@ -24,6 +25,7 @@ class Wallabag(object):
|
||||
format = ''
|
||||
username = ''
|
||||
password = ''
|
||||
aio_sess = None
|
||||
|
||||
def __init__(self,
|
||||
host='',
|
||||
@@ -31,16 +33,18 @@ class Wallabag(object):
|
||||
client_id='',
|
||||
client_secret='',
|
||||
extension='json',
|
||||
user_agent="WallabagPython/1.0 "
|
||||
"+https://github.com/foxmask/wallabag-api"):
|
||||
user_agent="WallabagPython/1.3 "
|
||||
"+https://github.com/foxmask/wallabag-api",
|
||||
aio_sess=None):
|
||||
"""
|
||||
init variable
|
||||
:param host: string url to the official API Wallabag
|
||||
: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 user_agent
|
||||
init variable
|
||||
:param host: string url to the official API Wallabag
|
||||
:param token: string of the key provided by Wallabag
|
||||
:param client_id client id
|
||||
:param client_secret client secret
|
||||
:param extension: xml|json|txt|csv|pdf|epub|mobi|html
|
||||
:param user_agent
|
||||
:param aio_sess aiohttp session
|
||||
"""
|
||||
self.host = host
|
||||
self.client_id = client_id
|
||||
@@ -48,156 +52,190 @@ class Wallabag(object):
|
||||
self.token = token
|
||||
self.format = extension
|
||||
self.user_agent = user_agent
|
||||
self.aio_sess = aio_sess
|
||||
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):
|
||||
async def query(self, path, method='get', **params):
|
||||
"""
|
||||
get the host from which to get API
|
||||
:return host
|
||||
"""
|
||||
return self.host
|
||||
Do a query to the System API
|
||||
|
||||
def query(self, path, method='get', **params):
|
||||
:param path: url to the API
|
||||
:param method: the kind of query to do
|
||||
:param params: a dict with all the
|
||||
necessary things to query the API
|
||||
:return json data
|
||||
"""
|
||||
Do a query to the System API
|
||||
:param path: url to the API
|
||||
:param method: the kind of query to do
|
||||
:param params: a dict with all the
|
||||
necessary things to query the API
|
||||
:return json data
|
||||
"""
|
||||
if method in ('get', 'post', 'patch', 'delete', 'put', 'get_token'):
|
||||
if method in ('get', 'post', 'patch', 'delete', 'put'):
|
||||
full_path = self.host + path
|
||||
if method == 'get':
|
||||
r = requests.get(self.get_host() + path, params=params)
|
||||
resp = await self.aio_sess.get(full_path, params=params)
|
||||
elif method == 'post':
|
||||
r = requests.post(self.get_host() + path, data=params)
|
||||
resp = await self.aio_sess.post(full_path, data=params)
|
||||
elif method == 'patch':
|
||||
r = requests.patch(self.get_host() + path, data=params)
|
||||
resp = await self.aio_sess.patch(full_path, data=params)
|
||||
elif method == 'delete':
|
||||
r = requests.delete(self.get_host() + path, headers=params)
|
||||
resp = await self.aio_sess.delete(full_path, headers=params)
|
||||
elif method == 'put':
|
||||
r = requests.put(self.get_host() + path, params=params)
|
||||
return self.handle_json_response(r)
|
||||
resp = await self.aio_sess.put(full_path, data=params)
|
||||
|
||||
async with resp:
|
||||
# return the content if its a binary one
|
||||
if resp.content_type.startswith('application/pdf') or \
|
||||
resp.content_type.startswith('application/epub'):
|
||||
return await resp.read()
|
||||
|
||||
return await self.handle_json_response(resp)
|
||||
else:
|
||||
raise ValueError('method expected : get, post, patch, delete or put')
|
||||
raise ValueError('method expected: get, post, patch, delete, put')
|
||||
|
||||
@staticmethod
|
||||
def handle_json_response(responses):
|
||||
async def handle_json_response(responses):
|
||||
"""
|
||||
get the json data response
|
||||
:param responses: the json response
|
||||
:return the json data without 'root' node
|
||||
get the json data response
|
||||
: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)
|
||||
if responses.status != 200:
|
||||
raise HttpProcessingError(code=responses.status,
|
||||
message=await responses.json())
|
||||
json_data = {}
|
||||
try:
|
||||
json_data = responses.json()
|
||||
except:
|
||||
for error in json_data['errors']:
|
||||
error_json = json_data['errors'][error]['content']
|
||||
logging.error("Wallabag: {error}".format(error=error_json))
|
||||
return json_data
|
||||
except ClientResponseError as e:
|
||||
# sometimes json_data does not return any json() without
|
||||
# any error. This is due to the grabbing URL which "rejects"
|
||||
# the URL
|
||||
logging.error("Wallabag: aiohttp error {code} {message}"
|
||||
.format(code=e.code, message=e.message))
|
||||
return await json_data
|
||||
|
||||
def get_entries(self, **kwargs):
|
||||
@staticmethod
|
||||
def __get_attr(what, type_attr, value_attr, **kwargs):
|
||||
"""
|
||||
get the value of a parm
|
||||
:param what: string parm
|
||||
:param type_attr: type of parm
|
||||
:param value_attr:
|
||||
:param kwargs:
|
||||
:return: value of the parm
|
||||
"""
|
||||
value = int(kwargs[what]) if type_attr == 'int' else kwargs[what]
|
||||
if what in kwargs and value in value_attr:
|
||||
return value
|
||||
|
||||
GET /api/entries.{_format}
|
||||
# ENTRIES
|
||||
async def get_entries(self, **kwargs):
|
||||
"""
|
||||
GET /api/entries.{_format}
|
||||
|
||||
Retrieve all entries. It could be filtered by many options.
|
||||
Retrieve all entries. It could be filtered by many options.
|
||||
|
||||
:param kwargs: can contain one of the following filters
|
||||
archive: '0' or '1', default '0' filter by archived status.
|
||||
star: '0' or '1', default '0' filter by starred status.
|
||||
delete: '0' or '1', default '0' filter by deleted status.
|
||||
sort: 'created' or 'updated', default 'created'
|
||||
order: 'asc' or 'desc', default 'desc'
|
||||
page: int default 1 what page you want
|
||||
perPage: int default 30 result per page
|
||||
tags: list of tags url encoded.
|
||||
Will returns entries that matches ALL tags
|
||||
:return data related to the ext
|
||||
:param kwargs: can contain one of the following filters
|
||||
archive: '0' or '1', default '0' filter by archived status.
|
||||
star: '0' or '1', default '0' filter by starred status.
|
||||
delete: '0' or '1', default '0' filter by deleted status.
|
||||
sort: 'created' or 'updated', default 'created'
|
||||
order: 'asc' or 'desc', default 'desc'
|
||||
page: int default 1 what page you want
|
||||
perPage: int default 30 result per page
|
||||
tags: list of tags url encoded.
|
||||
since: int default 0 from what timestamp you want
|
||||
Will returns entries that matches ALL tags
|
||||
:return data related to the ext
|
||||
"""
|
||||
# default values
|
||||
params = {'access_token': self.token,
|
||||
'archive': 0,
|
||||
'star': 0,
|
||||
'delete': 0,
|
||||
'sort': 'created',
|
||||
'order': 'desc',
|
||||
'page': 1,
|
||||
'perPage': 30,
|
||||
'tags': []}
|
||||
params = dict({'access_token': self.token,
|
||||
'archive': 0,
|
||||
'star': 0,
|
||||
'delete': 0,
|
||||
'sort': 'created',
|
||||
'order': 'desc',
|
||||
'page': 1,
|
||||
'perPage': 30,
|
||||
'tags': '',
|
||||
'since': 0})
|
||||
|
||||
params['archive'] = self.__get_attr(what='archive',
|
||||
type_attr=int,
|
||||
value_attr=(0, 1),
|
||||
**params)
|
||||
params['star'] = self.__get_attr(what='star',
|
||||
type_attr=int,
|
||||
value_attr=(0, 1),
|
||||
**params)
|
||||
params['delete'] = self.__get_attr(what='delete',
|
||||
type_attr=int,
|
||||
value_attr=(0, 1),
|
||||
**params)
|
||||
params['order'] = self.__get_attr(what='order',
|
||||
type_attr=str,
|
||||
value_attr=('asc', 'desc'),
|
||||
**params)
|
||||
|
||||
if 'archive' in kwargs and int(kwargs['archive']) in (0, 1):
|
||||
params['archive'] = int(kwargs['archive'])
|
||||
if 'star' in kwargs and int(kwargs['star']) in (0, 1):
|
||||
params['star'] = int(kwargs['star'])
|
||||
if 'delete' in kwargs and int(kwargs['delete']) in (0, 1):
|
||||
params['delete'] = int(kwargs['delete'])
|
||||
if 'order' in kwargs and kwargs['order'] in ('asc', 'desc'):
|
||||
params['order'] = kwargs['order']
|
||||
if 'page' in kwargs and isinstance(kwargs['page'], int):
|
||||
params['page'] = kwargs['page']
|
||||
if 'perPage' in kwargs and isinstance(kwargs['perPage'], int):
|
||||
params['perPage'] = kwargs['perPage']
|
||||
if 'tags' in kwargs and isinstance(kwargs['tags'], list):
|
||||
params['tags'] = kwargs['tags']
|
||||
params['tags'] = ', '.join(kwargs['tags'])
|
||||
if 'since' in kwargs and isinstance(kwargs['since'], int):
|
||||
params['since'] = kwargs['since']
|
||||
|
||||
path = '/api/entries.{ext}'.format(ext=self.format)
|
||||
|
||||
return self.query(path, "get", **params)
|
||||
return await self.query(path, "get", **params)
|
||||
|
||||
def post_entries(self, url, title='', tags='', starred=0, archive=0):
|
||||
async def post_entries(self, url, title='', tags='', starred=0, archive=0):
|
||||
"""
|
||||
POST /api/entries.{_format}
|
||||
|
||||
POST /api/entries.{_format}
|
||||
Create an entry
|
||||
|
||||
Create an entry
|
||||
|
||||
:param url: the url of the note to store
|
||||
:param title: Optional, we'll get the title from the page.
|
||||
:param tags: tag1,tag2,tag3 a comma-separated list of tags.
|
||||
:param starred entry already starred
|
||||
:param archive entry already archived
|
||||
:return result
|
||||
:param url: the url of the note to store
|
||||
:param title: Optional, we'll get the title from the page.
|
||||
:param tags: tag1,tag2,tag3 a comma-separated list of tags.
|
||||
:param starred entry already starred
|
||||
:param archive entry already archived
|
||||
:return result
|
||||
"""
|
||||
params = {'access_token': self.token, 'url': url, 'title': title,
|
||||
'tags': tags, 'starred': starred, 'archive': archive}
|
||||
if len(tags) > 0 and isinstance(tags, list):
|
||||
params['tags'] = ', '.join(tags)
|
||||
if len(tags) > 0 and ',' in tags:
|
||||
params['tags'] = tags.split(',')
|
||||
path = '/api/entries.{ext}'.format(ext=self.format)
|
||||
return self.query(path, "post", **params)
|
||||
return await self.query(path, "post", **params)
|
||||
|
||||
def get_entry(self, entry):
|
||||
async def get_entry(self, entry):
|
||||
"""
|
||||
GET /api/entries/{entry}.{_format}
|
||||
|
||||
GET /api/entries/{entry}.{_format}
|
||||
Retrieve a single entry
|
||||
|
||||
Retrieve a single entry
|
||||
|
||||
:param entry: \w+ an integer The Entry ID
|
||||
:return data related to the ext
|
||||
:param entry: \w+ an integer The Entry ID
|
||||
:return data related to the ext
|
||||
"""
|
||||
params = {'access_token': self.token}
|
||||
url = '/api/entries/{entry}.{ext}'.format(entry=entry, ext=self.format)
|
||||
return self.query(url, "get", **params)
|
||||
url = '/api/entries/{entry}.{ext}'.format(entry=entry,
|
||||
ext=self.format)
|
||||
return await self.query(url, "get", **params)
|
||||
|
||||
def patch_entries(self, entry, **kwargs):
|
||||
async def patch_entries(self, entry, **kwargs):
|
||||
"""
|
||||
PATCH /api/entries/{entry}.{_format}
|
||||
|
||||
PATCH /api/entries/{entry}.{_format}
|
||||
Change several properties of an entry
|
||||
|
||||
Change several properties of an entry
|
||||
|
||||
:param entry: the entry to 'patch' / update
|
||||
:param kwargs: can contain one of the following
|
||||
title: string
|
||||
tags: a list of tags tag1,tag2,tag3
|
||||
archive: '0' or '1', default '0' archived the entry.
|
||||
star: '0' or '1', default '0' starred the entry
|
||||
delete: '0' or '1', default '0' flag as deleted.
|
||||
In case that you don't want to *really* remove it..
|
||||
:return data related to the ext
|
||||
:param entry: the entry to 'patch' / update
|
||||
:param kwargs: can contain one of the following
|
||||
title: string
|
||||
tags: a list of tags tag1,tag2,tag3
|
||||
archive: '0' or '1', default '0' archived the entry.
|
||||
star: '0' or '1', default '0' starred the entry
|
||||
delete: '0' or '1', default '0' flag as deleted.
|
||||
In case that you don't want to *really* remove it..
|
||||
:return data related to the ext
|
||||
"""
|
||||
# default values
|
||||
params = {'access_token': self.token,
|
||||
@@ -206,115 +244,293 @@ 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):
|
||||
params['tags'] = ', '.join(kwargs['tags'])
|
||||
if 'archive' in kwargs and int(kwargs['archive']) in (0, 1):
|
||||
params['archive'] = int(kwargs['archive'])
|
||||
if 'star' in kwargs and int(kwargs['star']) in (0, 1):
|
||||
params['star'] = int(kwargs['star'])
|
||||
if 'delete' in kwargs and int(kwargs['delete']) in (0, 1):
|
||||
params['delete'] = int(kwargs['delete'])
|
||||
|
||||
params['archive'] = self.__get_attr(what='archive',
|
||||
type_attr=int,
|
||||
value_attr=(0, 1),
|
||||
**kwargs)
|
||||
params['star'] = self.__get_attr(what='star',
|
||||
type_attr=int,
|
||||
value_attr=(0, 1),
|
||||
**kwargs)
|
||||
params['delete'] = self.__get_attr(what='delete',
|
||||
type_attr=int,
|
||||
value_attr=(0, 1),
|
||||
**kwargs)
|
||||
params['order'] = self.__get_attr(what='order',
|
||||
type_attr=str,
|
||||
value_attr=('asc', 'desc'),
|
||||
**kwargs)
|
||||
|
||||
path = '/api/entries/{entry}.{ext}'.format(
|
||||
entry=entry, ext=self.format)
|
||||
return self.query(path, "patch", **params)
|
||||
return await self.query(path, "patch", **params)
|
||||
|
||||
def delete_entries(self, entry):
|
||||
async def get_entry_export(self, entry):
|
||||
"""
|
||||
GET /api/entries/{entry}/export.{_format}
|
||||
|
||||
DELETE /api/entries/{entry}.{_format}
|
||||
Retrieve a single entry as a predefined format.
|
||||
|
||||
Delete permanently an entry
|
||||
: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 await self.query(url, "get", **params)
|
||||
|
||||
:param entry: \w+ an integer The Entry ID
|
||||
:return result
|
||||
async 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 await self.query(url, "patch", **params)
|
||||
|
||||
async def delete_entries(self, entry):
|
||||
"""
|
||||
DELETE /api/entries/{entry}.{_format}
|
||||
|
||||
Delete permanently an entry
|
||||
|
||||
:param entry: \w+ an integer The Entry ID
|
||||
:return result
|
||||
"""
|
||||
|
||||
params = {'Authorization': 'Bearer {}'.format(self.token)}
|
||||
path = '/api/entries/{entry}.{ext}'.format(
|
||||
entry=entry, ext=self.format)
|
||||
return self.query(path, "delete", **params)
|
||||
return await self.query(path, "delete", **params)
|
||||
|
||||
def get_entry_tags(self, entry):
|
||||
async def entries_exists(self, url, urls=''):
|
||||
"""
|
||||
GET /api/entries/exists.{_format}
|
||||
|
||||
GET /api/entries/{entry}/tags.{_format}
|
||||
Check if an entry exist by url.
|
||||
|
||||
Retrieve all tags for an entry
|
||||
: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
|
||||
|
||||
:param entry: \w+ an integer The Entry ID
|
||||
:return data related to the ext
|
||||
:return result
|
||||
"""
|
||||
params = {'url': url,
|
||||
'urls': urls}
|
||||
|
||||
path = '/api/entries/exists.{ext}'.format(ext=self.format)
|
||||
return await self.query(path, "get", **params)
|
||||
|
||||
# TAGS
|
||||
|
||||
async def get_entry_tags(self, entry):
|
||||
"""
|
||||
GET /api/entries/{entry}/tags.{_format}
|
||||
|
||||
Retrieve all tags for an entry
|
||||
|
||||
:param entry: \w+ an integer The Entry ID
|
||||
:return data related to the ext
|
||||
"""
|
||||
params = {'access_token': self.token}
|
||||
url = '/api/entries/{entry}/tags.{ext}'.format(
|
||||
entry=entry, ext=self.format)
|
||||
return self.query(url, "get", **params)
|
||||
return await self.query(url, "get", **params)
|
||||
|
||||
def post_entry_tags(self, entry, tags):
|
||||
async def post_entry_tags(self, entry, tags):
|
||||
"""
|
||||
POST /api/entries/{entry}/tags.{_format}
|
||||
|
||||
POST /api/entries/{entry}/tags.{_format}
|
||||
Add one or more tags to an entry
|
||||
|
||||
Add one or more tags to an entry
|
||||
|
||||
:param entry: \w+ an integer The Entry ID
|
||||
:param tags: string
|
||||
:return result
|
||||
:param entry: \w+ an integer The Entry ID
|
||||
:param tags: string
|
||||
:return result
|
||||
"""
|
||||
params = {'access_token': self.token, 'tags': []}
|
||||
if isinstance(tags, list):
|
||||
params['tags'] = tags
|
||||
if len(tags) > 0 and ',' in tags:
|
||||
params['tags'] = tags.split(',')
|
||||
path = '/api/entries/{entry}/tags.{ext}'.format(
|
||||
entry=entry, ext=self.format)
|
||||
return self.query(path, "post", **params)
|
||||
return await self.query(path, "post", **params)
|
||||
|
||||
def delete_entry_tag(self, entry, tag):
|
||||
async def delete_entry_tag(self, entry, tag):
|
||||
"""
|
||||
DELETE /api/entries/{entry}/tags/{tag}.{_format}
|
||||
|
||||
DELETE /api/entries/{entry}/tags/{tag}.{_format}
|
||||
Permanently remove one tag for an entry
|
||||
|
||||
Permanently remove one tag for an entry
|
||||
|
||||
:param entry: \w+ an integer The Entry ID
|
||||
:param tag: string The Tag
|
||||
:return data related to the ext
|
||||
:param entry: \w+ an integer The Entry ID
|
||||
:param tag: string The Tag
|
||||
:return data related to the ext
|
||||
"""
|
||||
params = {'access_token': self.token}
|
||||
url = '/api/entries/{entry}/tags/{tag}.{ext}'.format(
|
||||
entry=entry, tag=tag, ext=self.format)
|
||||
return self.query(url, "delete", **params)
|
||||
return await self.query(url, "delete", **params)
|
||||
|
||||
def get_tags(self):
|
||||
async def get_tags(self):
|
||||
"""
|
||||
GET /api/tags.{_format}
|
||||
|
||||
GET /api/tags.{_format}
|
||||
Retrieve all tags
|
||||
|
||||
Retrieve all tags
|
||||
|
||||
:return data related to the ext
|
||||
:return data related to the ext
|
||||
"""
|
||||
params = {'access_token': self.token}
|
||||
path = '/api/tags.{ext}'.format(ext=self.format)
|
||||
return self.query(path, "get", **params)
|
||||
return await self.query(path, "get", **params)
|
||||
|
||||
def delete_tag(self, tag):
|
||||
async def delete_tag(self, tag):
|
||||
"""
|
||||
DELETE /api/tags/{tag}.{_format}
|
||||
|
||||
DELETE /api/tags/{tag}.{_format}
|
||||
Permanently remove one tag from every entry
|
||||
|
||||
Permanently remove one tag from every entry
|
||||
|
||||
:param tag: string The Tag
|
||||
:return data related to the ext
|
||||
:param tag: string The Tag
|
||||
:return data related to the ext
|
||||
"""
|
||||
path = '/api/tags/{tag}.{ext}'.format(tag=tag, ext=self.format)
|
||||
params = {'access_token': self.token}
|
||||
return self.query(path, "delete", **params)
|
||||
return await self.query(path, "delete", **params)
|
||||
|
||||
async 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 await self.query(path, "delete", **params)
|
||||
|
||||
async 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 await self.query(path, "delete", **params)
|
||||
|
||||
# ANNOTATIONS
|
||||
async 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 await self.query(url, "delete", **params)
|
||||
|
||||
async 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 await self.query(url, "put", **params)
|
||||
|
||||
async 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 await self.query(url, "get", **params)
|
||||
|
||||
async 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 await self.query(url, "post", **params)
|
||||
|
||||
# VERSION
|
||||
@property
|
||||
async 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 await self.query(url, "get", **params)
|
||||
|
||||
@classmethod
|
||||
def get_token(cls, host, **params):
|
||||
async 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 +542,9 @@ 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']
|
||||
async with aiohttp.ClientSession() as sess:
|
||||
async with sess.post(host + path, data=params) as resp:
|
||||
data = await cls.handle_json_response(resp)
|
||||
return data.get("access_token")
|
||||
|
||||
@@ -5,7 +5,7 @@ from wallabag import Wallabag
|
||||
|
||||
class TestWallabag(unittest.TestCase):
|
||||
|
||||
host = 'http://localhost:8080'
|
||||
host = 'http://localhost:8000'
|
||||
client_id = ''
|
||||
client_secret = ''
|
||||
token = ''
|
||||
@@ -20,12 +20,14 @@ class TestWallabag(unittest.TestCase):
|
||||
|
||||
def test_get_token(self):
|
||||
params = {"grant_type": "password",
|
||||
"client_id": '1_37e16ub8a62oc4gwcg0o0wssks800kw0ok408kkwo4kosgc88g',
|
||||
"client_secret": '49etxpn66da8okg4cs40sswsog0sskwg4woc400c4w4w8s4wo4',
|
||||
"username": 'foxmask',
|
||||
"password": 'ratatab00m'}
|
||||
|
||||
data = Wallabag.get_token(host='http://localhost:8080', **params)
|
||||
"client_id":
|
||||
'1_4wqe1riwt0qoks844kwc4go08koogkgk88go4cckkwg0408kcg',
|
||||
"client_secret": '4mzw3qwi1xyc0cks4k80s4c8kco40wwkkkw0g40kwk4o4c44co',
|
||||
"username": 'wallabag',
|
||||
"password": 'wallabag'}
|
||||
print(self.host)
|
||||
data = Wallabag.get_token(host=self.host, **params)
|
||||
print(data)
|
||||
self.assertTrue(isinstance(data, str), True)
|
||||
return data
|
||||
|
||||
@@ -75,6 +77,7 @@ class TestWallabag(unittest.TestCase):
|
||||
params = {'title': 'I change the title',
|
||||
'archive': 0,
|
||||
'tags': ["bimbo", "pipo"],
|
||||
'order': 'asc',
|
||||
'star': 0,
|
||||
'delete': 0}
|
||||
self.assertTrue(isinstance(entry, int), True)
|
||||
|
||||
Reference in New Issue
Block a user