UPDATE
because of heavy anti-bot protection, it is more difficult to make a fully automatic login on a headless device. If one is not on a headless device, it will login using seleniubbase, but you might have to install chromium browser. On a headless device, one needs to install xvfb to simulate a non-headless device. Alternatively, on can import manually a refresh token. It can be used to get a new access token, (for example regulary witha cronjob), but it will eventually expire after 10 hours.
pytolino
A client to interact (login, upload, delete ebooks, etc..) with the tolino cloud with python. thanks to https://github.com/darkphoenix/tolino-calibre-sync for the inspiration.
One difference is that I aim to create a python package from it and to put it on pypi, so that one can use this python module in other projects.
Installation
pip install pytolino
Usage
First, one need to login. if chromium browser is installed and there is a monitor, it can be done automaticaly:
from pytolino.tolino_cloud import Client
partner = 'orellfuessli' # or 'thalia' / 'thalia_at'
client = Client(username='USERNAME', server_name=partner)
client.login('PASSWORD')
if this is the first login on the device, it will use selenium and store an access token on the device.
On a headless device, this will work only if xvfb is installed.
Alternatively, one can instead import a refresh token: First, login manually with another device, and use an inspector tool in the browser to inspect the requests. After connecting to the digital libray of tolino, there is POST request (named token). From the request response, copy the value of the refresh token. Then, in a PATCH request, in the request header, find the device_id number.
You can then import the token:
client = Client(username='USERNAME')
print('please login manually and use inspector tool to find refresh token'
' in a token request')
refresh_token = input('refresh login: ')
print('find the hardware id in the request header '
'of a patch request for example')
hardware_id = input('hardware id: ')
client.import_token(refresh_token, hardware_id)
client.login('PASSWORD', allow_GUI_autologin=False) # seleniumbase will not be used
After this, the login will method will only refresh the access token for on hour, and you can work with the libraty:
try:
client.login(password)
except PytolinoException as e:
print(e)
else:
ebook_id = client.upload(EPUB_FILE_PATH) # return a unique id that can be used for reference
client.add_collection(epub_id, 'science fiction') # add the previous book to the collection science-fiction
client.add_cover(epub_id, cover_path) # to upload a cover on the book.
client.delete_ebook(epub_id) # delete the previousely uploaded ebook
inventory = client.get_inventory() # get a list of all the books on the cloud and their metadata
client.upload_metadata(epub_id, title='my title', author='someone') # you can upload various kind of metadata
To get a list of the supported partners:
from pytolino.tolino_cloud import PARTNERS
print(PARTNERS)
Supported partners currently include orellfuessli, thalia and thalia_at. Thalia uses the same Tolino backend endpoints as Orell Füssli, but the login flow is partner-specific.
Features
upload ebook
delete ebook from the cloud
add a book to a collection
download inventory
upload metadata
License
The project is licensed under GNU GENERAL PUBLIC LICENSE v3.0
Metadata
Release files for pytolino 3.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pytolino-3.6.tar.gz | 845.5 kB | Without provenance | Details for pytolino-3.6.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pytolino-3.6-py3-none-any.whl | Python 3 | none | any | Details for pytolino-3.6-py3-none-any.whl |
Total release size: 870.3 kB
Release files / pytolino-3.6.tar.gz
| Download URL | pytolino-3.6.tar.gz |
|---|---|
| Size | 845.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4a1577f89cdda6ac396b932b1db95f854269bee1298e8b4a7d5f1322e666b353
|
|
BLAKE2b-256 checksum How to use checksums |
689b9b9e5944eb0667c17ea2e680fed89e0eda698cf9b7b6837cfa3e86894d37
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / pytolino-3.6-py3-none-any.whl
| Download URL | pytolino-3.6-py3-none-any.whl |
|---|---|
| Size | 24.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
82a89b12111ac690ec4cd5bb5ecbdbaa92638d0087eb8c240730a6f9f32323b6
|
|
BLAKE2b-256 checksum How to use checksums |
49a863c6670e62cf381f9d294584b6d1cf2b317323692b089bc22afb8882cf87
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for pytolino 3.6
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.