first shoot
This commit is contained in:
1
MANIFEST.in
Normal file
1
MANIFEST.in
Normal file
@@ -0,0 +1 @@
|
|||||||
|
include *.txt *.rst
|
||||||
27
README.rst
Normal file
27
README.rst
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
============
|
||||||
|
Wallabag API
|
||||||
|
============
|
||||||
|
|
||||||
|
Python API for Wallabagap
|
||||||
|
|
||||||
|
Requirements :
|
||||||
|
==============
|
||||||
|
* Flask == 0.10.1
|
||||||
|
* requests == 2.5.0
|
||||||
|
|
||||||
|
|
||||||
|
Installation:
|
||||||
|
=============
|
||||||
|
to get the project, from your virtualenv, do :
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
git clone https://github.com/foxmask/wallabag-api/
|
||||||
|
|
||||||
|
TODO :
|
||||||
|
======
|
||||||
|
|
||||||
|
Wait the final release of http://v2.wallabag.org to be able to use the REST API completly
|
||||||
|
this final release should be able to provide an oauth with the exchange of the token
|
||||||
|
|
||||||
|
|
||||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Flask==0.10.1
|
||||||
|
requests==2.5.0
|
||||||
37
setup.py
Normal file
37
setup.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
from setuptools import setup, find_packages
|
||||||
|
from wallabag_api import __version__ as version
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def strip_comments(l):
|
||||||
|
return l.split('#', 1)[0].strip()
|
||||||
|
|
||||||
|
|
||||||
|
def reqs(*f):
|
||||||
|
return list(filter(None, [strip_comments(l) for l in open(
|
||||||
|
os.path.join(os.getcwd(), *f)).readlines()]))
|
||||||
|
|
||||||
|
install_requires = reqs('requirements.txt')
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='wallabag_api',
|
||||||
|
version=version,
|
||||||
|
description='Wallabag API',
|
||||||
|
author='Olivier Demah',
|
||||||
|
author_email='olivier@foxmask.info',
|
||||||
|
url='https://github.com/foxmask/wallabag_api',
|
||||||
|
download_url="https://github.com/foxmask/wallabag_api/archive/wallabag_api-"
|
||||||
|
+ version + ".zip",
|
||||||
|
packages=find_packages(),
|
||||||
|
classifiers=[
|
||||||
|
'Development Status :: 4 - Beta',
|
||||||
|
'Intended Audience :: Developers',
|
||||||
|
'License :: OSI Approved :: BSD License',
|
||||||
|
'Operating System :: OS Independent',
|
||||||
|
'Programming Language :: Python',
|
||||||
|
'Programming Language :: Python :: 2.7',
|
||||||
|
'Programming Language :: Python :: 3.4',
|
||||||
|
],
|
||||||
|
install_requires=install_requires,
|
||||||
|
include_package_data=True,
|
||||||
|
)
|
||||||
2
wallabag_api/__init__.py
Normal file
2
wallabag_api/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
VERSION = (0, 0, 1) # PEP 386
|
||||||
|
__version__ = ".".join([str(x) for x in VERSION])
|
||||||
135
wallabag_api/wallabag.py
Normal file
135
wallabag_api/wallabag.py
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
__author__ = 'foxmask'
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logging.basicConfig(format='%(message)s', level=logging.INFO)
|
||||||
|
|
||||||
|
__all__ = ['Wallabag']
|
||||||
|
|
||||||
|
|
||||||
|
class Wallabag(object):
|
||||||
|
"""
|
||||||
|
Python Class 'Wallabag' to deal with Wallabagap REST API
|
||||||
|
This class is able to handle any data from your Wallabagap account
|
||||||
|
"""
|
||||||
|
|
||||||
|
host = ''
|
||||||
|
api_key = ''
|
||||||
|
user_agent = ''
|
||||||
|
|
||||||
|
def __init__(self, host='http://v2.wallabag.org', api_key='', user_agent="WallabagPython"):
|
||||||
|
"""
|
||||||
|
init variable
|
||||||
|
:param host: string url to the official API Wallabagap
|
||||||
|
:param api_key: string of the key provided by Wallabagap
|
||||||
|
:param user_agent
|
||||||
|
"""
|
||||||
|
self.host = host
|
||||||
|
self.api_key = api_key
|
||||||
|
self.user_agent = user_agent
|
||||||
|
|
||||||
|
def get_host(self):
|
||||||
|
"""
|
||||||
|
get the host from which to get API
|
||||||
|
:return host
|
||||||
|
"""
|
||||||
|
return self.host
|
||||||
|
|
||||||
|
def query(self, url, params={}, method='get'):
|
||||||
|
"""
|
||||||
|
Do a query to the System API
|
||||||
|
:param url: url to the API
|
||||||
|
:param params: a dict with all the necessary things to query the API
|
||||||
|
:return json data
|
||||||
|
"""
|
||||||
|
#params = params
|
||||||
|
params['key'] = self.api_key
|
||||||
|
if method == 'get':
|
||||||
|
r = requests.get(self.get_host() + url, params=params)
|
||||||
|
elif method == 'post':
|
||||||
|
r = requests.post(self.get_host() + url, params=params)
|
||||||
|
elif method == 'patch':
|
||||||
|
r = requests.patch(self.get_host() + url, params=params)
|
||||||
|
elif method == 'delete':
|
||||||
|
r = requests.delete(self.get_host() + url, params=params)
|
||||||
|
return self.handle_json_response(r)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_json_response(self, responses):
|
||||||
|
"""
|
||||||
|
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)
|
||||||
|
json_data = {}
|
||||||
|
try:
|
||||||
|
json_data = responses.json()
|
||||||
|
except:
|
||||||
|
for error in json_data['errors']:
|
||||||
|
logging.error("Wallabag: %s" % \
|
||||||
|
json_data['errors'][error]['content'])
|
||||||
|
return json_data
|
||||||
|
|
||||||
|
def get(self, token, user):
|
||||||
|
"""
|
||||||
|
List unread entries for the given user
|
||||||
|
:param token: the token that identified the user to access the API
|
||||||
|
:param user: the current user
|
||||||
|
:return json data
|
||||||
|
"""
|
||||||
|
return self.get_entries(token, user)
|
||||||
|
|
||||||
|
def get_entries(self, token, user):
|
||||||
|
"""
|
||||||
|
List unread entries for the given user
|
||||||
|
:param token: the token that identified the user to access the API
|
||||||
|
:param user: the current user
|
||||||
|
:return json data
|
||||||
|
"""
|
||||||
|
return self.query('/api/u/{user}/entries.json'.format(user=user), {'token': token}, method="get")
|
||||||
|
|
||||||
|
def get_entry(self, token, user, entry):
|
||||||
|
"""
|
||||||
|
Fetch an entry, regardless the status flags
|
||||||
|
:param user: entry of that user
|
||||||
|
:param entry: the entry
|
||||||
|
:return json data
|
||||||
|
"""
|
||||||
|
return self.query('/api/u/{user}/entry/{entry}'.format(user=user, entry=entry),
|
||||||
|
{'token': token}, method="get")
|
||||||
|
|
||||||
|
def post_entries(self, token, user, url=[], tags=[]):
|
||||||
|
"""
|
||||||
|
Save a new entry for the given user
|
||||||
|
:param user: entry of that user
|
||||||
|
:param url: the url of the note to store
|
||||||
|
:param tags: the tags of the note to store if provided
|
||||||
|
:return json data
|
||||||
|
"""
|
||||||
|
params = {'token': token, 'url': url}
|
||||||
|
if len(tags) > 0:
|
||||||
|
params = {'token': token, 'url': url, 'tags': tags}
|
||||||
|
return self.query('/api/u/{user}/entries.json'.format(user=user), params, method="post")
|
||||||
|
|
||||||
|
def patch_entries(self, token, user, entry=[]):
|
||||||
|
"""
|
||||||
|
Change several properties of an entry. I.E tags, archived, starred and deleted status
|
||||||
|
:param user: entry of that user
|
||||||
|
:param entry: the entry to 'patch'
|
||||||
|
:return json data
|
||||||
|
"""
|
||||||
|
params = {'token': token, 'entry': entry}
|
||||||
|
return self.query('/api/u/{user}/entries.json'.format(user=user), params, method="patch")
|
||||||
|
|
||||||
|
def delete_entry(self, token, user, entry):
|
||||||
|
"""
|
||||||
|
Delete an entry
|
||||||
|
:param user: entry of that user
|
||||||
|
:param entry: the entry to 'delete'
|
||||||
|
:return json data
|
||||||
|
"""
|
||||||
|
return self.query('/api/u/{user}/entry/{entry}'.format(user=user, entry=entry), {'token': token}, method="delete")
|
||||||
44
wallabag_api/wallabag_test.py
Normal file
44
wallabag_api/wallabag_test.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import unittest
|
||||||
|
from wallabag import Wallabag
|
||||||
|
|
||||||
|
|
||||||
|
class TestWallabag(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.host = "http://localhost:5000"
|
||||||
|
self.api_key = '12334567890'
|
||||||
|
self.user = 'foxmask'
|
||||||
|
|
||||||
|
def test_get(self):
|
||||||
|
w = Wallabag(self.host).get('ABCD', self.user)
|
||||||
|
self.assertIsInstance(w, dict)
|
||||||
|
|
||||||
|
def test_get_entries(self):
|
||||||
|
w = Wallabag(self.host).get('ABCD', self.user)
|
||||||
|
self.assertIsInstance(w, dict)
|
||||||
|
|
||||||
|
def test_get_entry(self):
|
||||||
|
w = Wallabag(self.host).get_entry('ABCD', self.user, 1)
|
||||||
|
self.assertTrue(w, str)
|
||||||
|
|
||||||
|
def test_post_entries(self):
|
||||||
|
url = ['http://foobar.com/', 'http://barfoo.com/']
|
||||||
|
tags = ['foo', 'bar']
|
||||||
|
w = Wallabag(self.host).post_entries('ABCD', self.user, url, tags)
|
||||||
|
self.assertTrue(w, True)
|
||||||
|
|
||||||
|
def test_patch_entries(self):
|
||||||
|
entry = []
|
||||||
|
entry.append('fourth content')
|
||||||
|
entry.append('fifth content')
|
||||||
|
w = Wallabag(self.host).patch_entries('ABCD', self.user, entry)
|
||||||
|
self.assertTrue(w, True)
|
||||||
|
|
||||||
|
def test_delete_entry(self):
|
||||||
|
entry = 1
|
||||||
|
w = Wallabag(self.host).delete_entry('ABCD', self.user, entry)
|
||||||
|
self.assertTrue(w, True)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
62
wallabag_mock.py
Normal file
62
wallabag_mock.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
__author__ = 'foxmask'
|
||||||
|
import json
|
||||||
|
from flask import Flask, request
|
||||||
|
|
||||||
|
"""
|
||||||
|
The main purpose of this script is to replace v2.wallabag.org itself
|
||||||
|
just run :
|
||||||
|
python wallabag_mock.py &
|
||||||
|
and then you can launch
|
||||||
|
python wallabag_test.py
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route('/api/u/<user>/entries.json', methods=['GET'])
|
||||||
|
def get(user):
|
||||||
|
my_data = dict()
|
||||||
|
if user == 'foxmask':
|
||||||
|
my_data['entry'] = 'first content'
|
||||||
|
my_data['entry'] = 'second content'
|
||||||
|
return json.dumps(my_data,encoding='utf-8')
|
||||||
|
|
||||||
|
@app.route('/api/u/<user>/entries.json', methods=['GET'])
|
||||||
|
def get_entries(user):
|
||||||
|
my_data = dict()
|
||||||
|
if user == 'foxmask':
|
||||||
|
my_data['entry'] = 'first content'
|
||||||
|
my_data['entry'] = 'second content'
|
||||||
|
return json.dumps(my_data,encoding='utf-8')
|
||||||
|
|
||||||
|
@app.route('/api/u/<user>/entry/<int:entry>', methods=['GET'])
|
||||||
|
def get_entry(user, entry):
|
||||||
|
my_data = dict()
|
||||||
|
if user == 'foxmask' and entry == 1:
|
||||||
|
my_data['entry'] = 'third content'
|
||||||
|
return json.dumps(my_data,encoding='utf-8')
|
||||||
|
|
||||||
|
@app.route('/api/u/<user>/entries.json', methods=['POST'])
|
||||||
|
def post_entries(user):
|
||||||
|
if user == 'foxmask':
|
||||||
|
return json.dumps(True)
|
||||||
|
else:
|
||||||
|
return json.dumps(False)
|
||||||
|
|
||||||
|
@app.route('/api/u/<user>/entries.json', methods=['PATCH'])
|
||||||
|
def patch_entries(user):
|
||||||
|
if user == 'foxmask':
|
||||||
|
return json.dumps(True)
|
||||||
|
else:
|
||||||
|
return json.dumps(False)
|
||||||
|
|
||||||
|
@app.route('/api/u/<user>/entry/<int:entry>', methods=['DELETE'])
|
||||||
|
def delete_entry(user, entry):
|
||||||
|
if user == 'foxmask' and entry == 1:
|
||||||
|
return json.dumps(True)
|
||||||
|
else:
|
||||||
|
return json.dumps(False)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(debug=True)
|
||||||
Reference in New Issue
Block a user