initial commit
All checks were successful
Build and Upload Python Package / build (push) Successful in 52s
All checks were successful
Build and Upload Python Package / build (push) Successful in 52s
This commit is contained in:
commit
a1fd24c92d
28
.gitea/workflows/build-pypi.yml
Normal file
28
.gitea/workflows/build-pypi.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
name: Build and Upload Python Package
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: "3.x"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install setuptools wheel twine build
|
||||||
|
|
||||||
|
- name: Build the package
|
||||||
|
run: python -m build
|
||||||
|
|
||||||
|
- name: Upload to Gitea PyPI Registry
|
||||||
|
run: |
|
||||||
|
twine upload --repository-url https://gitea.suda.codes/api/packages/sudacode/pypi -u ${{ secrets.PYPI_USERNAME }} -p ${{ secrets.PYPI_PASSWORD }} dist/*
|
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.git/*
|
||||||
|
dist/*
|
||||||
|
env/*
|
||||||
|
src/wallabag_api_client.egg-info
|
||||||
|
src/__pycache__/*
|
||||||
|
src/wallabag_api_client/__pycache__/*
|
||||||
|
src/wallabag_api_client/methods/__pycache__/*
|
||||||
|
tests/test.py
|
32
pyproject.toml
Normal file
32
pyproject.toml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=61.0", "wheel"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "wallabag-api-client"
|
||||||
|
version = "0.0.1"
|
||||||
|
description = "A Python client to interact with the Wallabag API"
|
||||||
|
readme = "README.md"
|
||||||
|
license = { text = "MIT" }
|
||||||
|
authors = [
|
||||||
|
{ name = "sudacode", email = "suda@sudacode.com" }
|
||||||
|
]
|
||||||
|
dependencies = [
|
||||||
|
"requests>=2.20.0"
|
||||||
|
]
|
||||||
|
requires-python = ">=3.7"
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
"Homepage" = "https://gitea.suda.codes/sudacode/wallabag-api-client"
|
||||||
|
"Source" = "https://gitea.suda.codes/sudacode/wallabag-api-client"
|
||||||
|
"Issue Tracker" = "https://gitea.suda.codes/sudacode/wallabag-api-client/issues"
|
||||||
|
|
||||||
|
[tool.setuptools.packages.find]
|
||||||
|
where = ["src"]
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = [
|
||||||
|
"black",
|
||||||
|
"pytest",
|
||||||
|
]
|
||||||
|
|
16
requirements.txt
Normal file
16
requirements.txt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
black==24.8.0
|
||||||
|
certifi==2024.8.30
|
||||||
|
charset-normalizer==3.3.2
|
||||||
|
click==8.1.7
|
||||||
|
idna==3.8
|
||||||
|
iniconfig==2.0.0
|
||||||
|
mypy==1.11.2
|
||||||
|
mypy-extensions==1.0.0
|
||||||
|
packaging==24.1
|
||||||
|
pathspec==0.12.1
|
||||||
|
platformdirs==4.3.1
|
||||||
|
pluggy==1.5.0
|
||||||
|
pytest==8.3.2
|
||||||
|
requests==2.32.3
|
||||||
|
typing_extensions==4.12.2
|
||||||
|
urllib3==2.2.2
|
21
src/wallabag_api_client/__init__.py
Normal file
21
src/wallabag_api_client/__init__.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from .client import WallabagClient
|
||||||
|
from .methods.annotations import AnnotationsAPI
|
||||||
|
from .methods.entries import EntriesAPI
|
||||||
|
from .methods.tags import TagsAPI
|
||||||
|
|
||||||
|
|
||||||
|
class WallabagAPI:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
client_id,
|
||||||
|
client_secret,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
base_url="https://app.wallabag.it",
|
||||||
|
):
|
||||||
|
self.client = WallabagClient(
|
||||||
|
client_id, client_secret, username, password, base_url
|
||||||
|
)
|
||||||
|
self.entries = EntriesAPI(self.client)
|
||||||
|
self.tags = TagsAPI(self.client)
|
||||||
|
self.annotations = AnnotationsAPI(self.client)
|
124
src/wallabag_api_client/client.py
Normal file
124
src/wallabag_api_client/client.py
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
class WallabagClient:
|
||||||
|
"""
|
||||||
|
A client to interact with the Wallabag API using OAuth2 for authentication.
|
||||||
|
|
||||||
|
This class handles authentication and sending requests to the API endpoints.
|
||||||
|
----------
|
||||||
|
Attributes
|
||||||
|
|
||||||
|
client_id : str
|
||||||
|
The client ID for OAuth2 authentication.
|
||||||
|
client_secret : str
|
||||||
|
The client secret for OAuth2 authentication.
|
||||||
|
username : str
|
||||||
|
The username of the Wallabag account.
|
||||||
|
password : str
|
||||||
|
The password of the Wallabag account.
|
||||||
|
base_url : str
|
||||||
|
The base URL of the Wallabag instance.
|
||||||
|
token : str
|
||||||
|
The access token obtained from the OAuth2 authentication.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
client_id,
|
||||||
|
client_secret,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
base_url="https://app.wallabag.it",
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Initializes the WallabagClient with user credentials and OAuth2 tokens.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
client_id : str
|
||||||
|
The client ID for OAuth2 authentication.
|
||||||
|
client_secret : str
|
||||||
|
The client secret for OAuth2 authentication.
|
||||||
|
username : str
|
||||||
|
The username of the Wallabag account.
|
||||||
|
password : str
|
||||||
|
The password of the Wallabag account.
|
||||||
|
base_url : str, optional
|
||||||
|
The base URL of the Wallabag instance (default is "https://app.wallabag.it").
|
||||||
|
"""
|
||||||
|
self.client_id = client_id
|
||||||
|
self.client_secret = client_secret
|
||||||
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
self.base_url = base_url
|
||||||
|
self.token = self.authenticate()
|
||||||
|
|
||||||
|
def authenticate(self):
|
||||||
|
"""
|
||||||
|
Authenticates the user and retrieves the access token using OAuth2.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Returns
|
||||||
|
|
||||||
|
str
|
||||||
|
The access token for making authenticated API requests.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Raises
|
||||||
|
|
||||||
|
requests.exceptions.HTTPError
|
||||||
|
If the authentication request fails.
|
||||||
|
"""
|
||||||
|
auth_url = f"{self.base_url}/oauth/v2/token"
|
||||||
|
data = {
|
||||||
|
"grant_type": "password",
|
||||||
|
"client_id": self.client_id,
|
||||||
|
"client_secret": self.client_secret,
|
||||||
|
"username": self.username,
|
||||||
|
"password": self.password,
|
||||||
|
}
|
||||||
|
response = requests.post(auth_url, data=data)
|
||||||
|
response.raise_for_status()
|
||||||
|
token_info = response.json()
|
||||||
|
return token_info["access_token"]
|
||||||
|
|
||||||
|
def make_request(self, method, endpoint, params=None, data=None):
|
||||||
|
"""
|
||||||
|
Makes a request to the Wallabag API with the given parameters.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
method : str
|
||||||
|
The HTTP method (GET, POST, DELETE, etc.).
|
||||||
|
endpoint : str
|
||||||
|
The API endpoint (e.g., 'entries.json').
|
||||||
|
params : dict, optional
|
||||||
|
The query parameters to include in the request.
|
||||||
|
data : dict, optional
|
||||||
|
The data to send with the request (for POST, PUT, etc.).
|
||||||
|
|
||||||
|
----------
|
||||||
|
Returns
|
||||||
|
|
||||||
|
dict
|
||||||
|
The response from the API as a dictionary.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Raises
|
||||||
|
|
||||||
|
requests.exceptions.HTTPError
|
||||||
|
If the request fails.
|
||||||
|
"""
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {self.token}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
url = f"{self.base_url}/api/{endpoint}"
|
||||||
|
response = requests.request(
|
||||||
|
method, url, headers=headers, params=params, json=data
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
0
src/wallabag_api_client/methods/__init__.py
Normal file
0
src/wallabag_api_client/methods/__init__.py
Normal file
83
src/wallabag_api_client/methods/annotations.py
Normal file
83
src/wallabag_api_client/methods/annotations.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
class AnnotationsAPI:
|
||||||
|
"""
|
||||||
|
A class to interact with the Wallabag API for managing annotations on entries.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Attributes
|
||||||
|
|
||||||
|
client : WallabagClient
|
||||||
|
The client instance to send API requests.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, client):
|
||||||
|
"""
|
||||||
|
Initializes the AnnotationsAPI with the WallabagClient.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
client : WallabagClient
|
||||||
|
The WallabagClient instance to send requests.
|
||||||
|
"""
|
||||||
|
self.client = client
|
||||||
|
|
||||||
|
def get_annotations(self, entry_id):
|
||||||
|
"""
|
||||||
|
Retrieves all annotations for a specific entry.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
entry_id : int
|
||||||
|
The ID of the entry for which to retrieve annotations.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Returns
|
||||||
|
|
||||||
|
dict
|
||||||
|
The list of annotations for the specified entry.
|
||||||
|
"""
|
||||||
|
return self.client.make_request("GET", f"annotations/{entry_id}.json")
|
||||||
|
|
||||||
|
def add_annotation(self, entry_id, text, quote):
|
||||||
|
"""
|
||||||
|
Adds a new annotation to a specific entry.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
entry_id : int
|
||||||
|
The ID of the entry to annotate.
|
||||||
|
text : str
|
||||||
|
The text of the annotation.
|
||||||
|
quote : str
|
||||||
|
The quote related to the annotation.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Returns
|
||||||
|
|
||||||
|
dict
|
||||||
|
The details of the newly added annotation.
|
||||||
|
"""
|
||||||
|
data = {"text": text, "quote": quote}
|
||||||
|
return self.client.make_request(
|
||||||
|
"POST", f"annotations/{entry_id}.json", data=data
|
||||||
|
)
|
||||||
|
|
||||||
|
def delete_annotation(self, annotation_id):
|
||||||
|
"""
|
||||||
|
Deletes an annotation from a specific entry.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
annotation_id : int
|
||||||
|
The ID of the annotation to delete.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Returns
|
||||||
|
|
||||||
|
dict
|
||||||
|
The response from the API after deleting the annotation.
|
||||||
|
"""
|
||||||
|
return self.client.make_request("DELETE", f"annotations/{annotation_id}.json")
|
98
src/wallabag_api_client/methods/entries.py
Normal file
98
src/wallabag_api_client/methods/entries.py
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
class EntriesAPI:
|
||||||
|
"""
|
||||||
|
A class to interact with the Wallabag API for managing entries (articles).
|
||||||
|
|
||||||
|
----------
|
||||||
|
Attributes
|
||||||
|
|
||||||
|
client : WallabagClient
|
||||||
|
The client instance to send API requests.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, client):
|
||||||
|
"""
|
||||||
|
Initializes the EntriesAPI with the WallabagClient.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
client : WallabagClient
|
||||||
|
The WallabagClient instance to send requests.
|
||||||
|
"""
|
||||||
|
self.client = client
|
||||||
|
|
||||||
|
def get_entries(self, page=1, per_page=30):
|
||||||
|
"""
|
||||||
|
Retrieves a paginated list of entries (articles).
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
page : int, optional
|
||||||
|
The page number to retrieve (default is 1).
|
||||||
|
per_page : int, optional
|
||||||
|
The number of entries per page (default is 30).
|
||||||
|
|
||||||
|
----------
|
||||||
|
Returns
|
||||||
|
|
||||||
|
dict
|
||||||
|
The list of entries and pagination info.
|
||||||
|
"""
|
||||||
|
params = {"page": page, "perPage": per_page}
|
||||||
|
return self.client.make_request("GET", "entries.json", params=params)
|
||||||
|
|
||||||
|
def add_entry(self, url):
|
||||||
|
"""
|
||||||
|
Adds a new entry to Wallabag by providing a URL.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
url : str
|
||||||
|
The URL of the article to add.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Returns
|
||||||
|
|
||||||
|
dict
|
||||||
|
The details of the newly added entry.
|
||||||
|
"""
|
||||||
|
data = {"url": url}
|
||||||
|
return self.client.make_request("POST", "entries.json", data=data)
|
||||||
|
|
||||||
|
def delete_entry(self, entry_id):
|
||||||
|
"""
|
||||||
|
Deletes an entry from Wallabag by its entry ID.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
entry_id : int
|
||||||
|
The ID of the entry to delete.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Returns
|
||||||
|
|
||||||
|
dict
|
||||||
|
The response from the API after deleting the entry.
|
||||||
|
"""
|
||||||
|
return self.client.make_request("DELETE", f"entries/{entry_id}.json")
|
||||||
|
|
||||||
|
def get_entry(self, entry_id):
|
||||||
|
"""
|
||||||
|
Retrieves the details of a specific entry by its ID.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
entry_id : int
|
||||||
|
The ID of the entry to retrieve.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Returns
|
||||||
|
|
||||||
|
dict
|
||||||
|
The details of the specified entry.
|
||||||
|
"""
|
||||||
|
return self.client.make_request("GET", f"entries/{entry_id}.json")
|
73
src/wallabag_api_client/methods/tags.py
Normal file
73
src/wallabag_api_client/methods/tags.py
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
class TagsAPI:
|
||||||
|
"""
|
||||||
|
A class to interact with the Wallabag API for managing tags.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Attributes
|
||||||
|
|
||||||
|
client : WallabagClient
|
||||||
|
The client instance to send API requests.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, client):
|
||||||
|
"""
|
||||||
|
Initializes the TagsAPI with the WallabagClient.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
client : WallabagClient
|
||||||
|
The WallabagClient instance to send requests.
|
||||||
|
"""
|
||||||
|
self.client = client
|
||||||
|
|
||||||
|
def get_tags(self):
|
||||||
|
"""
|
||||||
|
Retrieves all tags associated with entries in Wallabag.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Returns
|
||||||
|
|
||||||
|
dict
|
||||||
|
The list of tags.
|
||||||
|
"""
|
||||||
|
return self.client.make_request("GET", "tags.json")
|
||||||
|
|
||||||
|
def add_tag(self, entry_id, tag):
|
||||||
|
"""
|
||||||
|
Adds a tag to a specific entry.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
entry_id : int
|
||||||
|
The ID of the entry to tag.
|
||||||
|
tag : str
|
||||||
|
The tag to add to the entry.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Returns
|
||||||
|
|
||||||
|
dict
|
||||||
|
The response from the API after adding the tag.
|
||||||
|
"""
|
||||||
|
data = {"entry_id": entry_id, "label": tag}
|
||||||
|
return self.client.make_request("POST", "tags.json", data=data)
|
||||||
|
|
||||||
|
def delete_tag(self, tag_id):
|
||||||
|
"""
|
||||||
|
Deletes a tag from an entry.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Parameters
|
||||||
|
|
||||||
|
tag_id : int
|
||||||
|
The ID of the tag to delete.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Returns
|
||||||
|
|
||||||
|
dict
|
||||||
|
The response from the API after deleting the tag.
|
||||||
|
"""
|
||||||
|
return self.client.make_request("DELETE", f"tags/{tag_id}.json")
|
Loading…
Reference in New Issue
Block a user