fastsaver 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastsaver-0.1.0/.gitignore +32 -0
- fastsaver-0.1.0/CHANGELOG.md +65 -0
- fastsaver-0.1.0/CONTRIBUTING.md +110 -0
- fastsaver-0.1.0/LICENSE +21 -0
- fastsaver-0.1.0/PKG-INFO +829 -0
- fastsaver-0.1.0/README.md +795 -0
- fastsaver-0.1.0/SECURITY.md +23 -0
- fastsaver-0.1.0/examples/README.md +14 -0
- fastsaver-0.1.0/examples/async_batch.py +80 -0
- fastsaver-0.1.0/examples/quickstart.py +54 -0
- fastsaver-0.1.0/examples/shazam_identify.py +60 -0
- fastsaver-0.1.0/examples/telegram_bot_aiogram.py +92 -0
- fastsaver-0.1.0/examples/youtube_download.py +67 -0
- fastsaver-0.1.0/pyproject.toml +98 -0
- fastsaver-0.1.0/src/fastsaver/__init__.py +115 -0
- fastsaver-0.1.0/src/fastsaver/__main__.py +10 -0
- fastsaver-0.1.0/src/fastsaver/_base.py +578 -0
- fastsaver-0.1.0/src/fastsaver/_constants.py +141 -0
- fastsaver-0.1.0/src/fastsaver/_endpoints.py +204 -0
- fastsaver-0.1.0/src/fastsaver/_transport.py +358 -0
- fastsaver-0.1.0/src/fastsaver/_version.py +1 -0
- fastsaver-0.1.0/src/fastsaver/async_client.py +301 -0
- fastsaver-0.1.0/src/fastsaver/cli.py +196 -0
- fastsaver-0.1.0/src/fastsaver/client.py +292 -0
- fastsaver-0.1.0/src/fastsaver/exceptions.py +255 -0
- fastsaver-0.1.0/src/fastsaver/models.py +614 -0
- fastsaver-0.1.0/src/fastsaver/py.typed +0 -0
- fastsaver-0.1.0/src/fastsaver/utils.py +100 -0
- fastsaver-0.1.0/tests/conftest.py +46 -0
- fastsaver-0.1.0/tests/payloads.py +287 -0
- fastsaver-0.1.0/tests/test_cli.py +514 -0
- fastsaver-0.1.0/tests/test_client_async.py +784 -0
- fastsaver-0.1.0/tests/test_client_sync.py +875 -0
- fastsaver-0.1.0/tests/test_config.py +395 -0
- fastsaver-0.1.0/tests/test_errors.py +745 -0
- fastsaver-0.1.0/tests/test_hardening.py +388 -0
- fastsaver-0.1.0/tests/test_live.py +65 -0
- fastsaver-0.1.0/tests/test_models.py +686 -0
- fastsaver-0.1.0/tests/test_retry.py +701 -0
- fastsaver-0.1.0/tests/test_save.py +358 -0
- fastsaver-0.1.0/tests/test_utils.py +357 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
*.egg
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.eggs/
|
|
9
|
+
.mypy_cache/
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
.coverage
|
|
13
|
+
htmlcov/
|
|
14
|
+
|
|
15
|
+
# Environments (any local venv: venv/, .venv/, .venv39/, .venv-smoke/ ...)
|
|
16
|
+
venv*/
|
|
17
|
+
.venv*/
|
|
18
|
+
.env
|
|
19
|
+
.env.*
|
|
20
|
+
!.env.example
|
|
21
|
+
|
|
22
|
+
# uv
|
|
23
|
+
uv.lock
|
|
24
|
+
|
|
25
|
+
# Editors / OS
|
|
26
|
+
.idea/
|
|
27
|
+
.vscode/
|
|
28
|
+
.DS_Store
|
|
29
|
+
|
|
30
|
+
# Local
|
|
31
|
+
.claude/
|
|
32
|
+
*.log
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- `save()` treats a destination written with a trailing slash (`"downloads/"`) as a
|
|
13
|
+
directory and creates it on demand; the temporary `.part` file now has a unique,
|
|
14
|
+
exclusively created name and derived file names are sanitised for Windows too.
|
|
15
|
+
- API calls never follow redirects, even with a user-supplied `httpx` client that has
|
|
16
|
+
`follow_redirects=True`; an unexpected 3xx is reported as `APIError` with a
|
|
17
|
+
`base_url` hint.
|
|
18
|
+
- Client-side argument errors raise `InvalidArgumentError` (a `FastSaverError` **and**
|
|
19
|
+
a `ValueError`), so one `except FastSaverError` covers bad input too.
|
|
20
|
+
- HTTP 429 is retried with a slower backoff (2 s, 4 s) and `Retry-After` HTTP-dates are
|
|
21
|
+
understood; non-finite values are ignored.
|
|
22
|
+
- Using a closed client raises `ConfigurationError` instead of a raw `RuntimeError`.
|
|
23
|
+
- `YouTubeInfo.available_formats` is sorted (`audio`, `144p` … `2160p`) and
|
|
24
|
+
`best_video_format` was added; `Track.thumbnail_url`, `MediaResult.thumbnail` and
|
|
25
|
+
`MediaItem.thumbnail` aliases; `FetchError.upstream_status` for `fetch.error: <status>`.
|
|
26
|
+
- `TimeoutArg`, `FileInput`, `InvalidArgumentError` and `parse_duration_seconds` are
|
|
27
|
+
exported from the package root; `fastsaver youtube tg-audio` accepts the aliases
|
|
28
|
+
`tg-bot` and `audio-for-bot`.
|
|
29
|
+
- `shazam.identify()` reads inputs with a 50 MiB cap and rejects non-regular files.
|
|
30
|
+
|
|
31
|
+
## [0.1.0] - 2026-09-05
|
|
32
|
+
|
|
33
|
+
Initial public release.
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- `FastSaver` (sync) and `AsyncFastSaver` (async) clients with identical method
|
|
38
|
+
names and signatures, context-manager support and bring-your-own `httpx` client.
|
|
39
|
+
- Full coverage of the FastSaverAPI v1 endpoints:
|
|
40
|
+
- `client.fetch(url)` — Instagram (posts, reels, stories, highlights), TikTok
|
|
41
|
+
(no watermark), Pinterest, Facebook, X/Twitter, RuTube and Likee.
|
|
42
|
+
- `client.youtube.info()`, `client.youtube.search()`, `client.youtube.download()`
|
|
43
|
+
(audio/MP3 and 144p–2160p) and `client.youtube.audio_for_bot()` (Telegram `file_id`).
|
|
44
|
+
- `client.shazam.identify()`, `client.shazam.top()` and `client.shazam.lyrics()`.
|
|
45
|
+
- `client.balance()` — plan, credits and rate limit of the current key.
|
|
46
|
+
- `client.save(url, dest)` — stream any `download_url` (tunnel or CDN) to disk
|
|
47
|
+
without leaking the API key.
|
|
48
|
+
- Typed, frozen dataclass models (`MediaResult`, `MediaItem`, `Music`, `YouTubeInfo`,
|
|
49
|
+
`YouTubeSearch`, `YouTubeDownload`, `TelegramAudio`, `ShazamMatch`, `ShazamTop`,
|
|
50
|
+
`Track`, `Balance`, ...) with lenient parsing and the full JSON kept on `.raw`.
|
|
51
|
+
- Exception hierarchy rooted at `FastSaverError`: `ConfigurationError`, `APIError`
|
|
52
|
+
(`AuthenticationError`, `InsufficientCreditsError`, `RateLimitError`,
|
|
53
|
+
`InvalidRequestError`, `ValidationError`, `FetchError`, `NotFoundError`,
|
|
54
|
+
`ServerError`), `TransportError` (`RequestTimeoutError`) and `DownloadError`.
|
|
55
|
+
- Automatic retries with exponential backoff and jitter for connection errors,
|
|
56
|
+
HTTP 5xx and HTTP 429 (honours `Retry-After`); read timeouts are never retried.
|
|
57
|
+
- Per-endpoint default timeouts (long read timeouts for YouTube download and
|
|
58
|
+
Telegram audio) with per-call overrides.
|
|
59
|
+
- Helpers: `detect_platform()`, `extract_youtube_id()`, `YOUTUBE_FORMATS`, `CREDIT_COSTS`.
|
|
60
|
+
- `fastsaver` command-line interface (`fastsaver fetch`, `fastsaver youtube ...`,
|
|
61
|
+
`fastsaver shazam ...`, `fastsaver balance`, `fastsaver save`) with JSON output.
|
|
62
|
+
- PEP 561 `py.typed` marker; Python 3.9–3.14 support; only dependency is `httpx`.
|
|
63
|
+
|
|
64
|
+
[Unreleased]: https://github.com/coder2077/fastsaver/compare/v0.1.0...HEAD
|
|
65
|
+
[0.1.0]: https://github.com/coder2077/fastsaver/releases/tag/v0.1.0
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Contributing to fastsaver
|
|
2
|
+
|
|
3
|
+
Thanks for taking the time to contribute! This document explains how to set up a
|
|
4
|
+
development environment, run the checks, and ship a release.
|
|
5
|
+
|
|
6
|
+
## Development setup
|
|
7
|
+
|
|
8
|
+
The project uses [uv](https://docs.astral.sh/uv/) for environment management and
|
|
9
|
+
[hatchling](https://hatch.pypa.io/) as the build backend (src layout).
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
git clone https://github.com/coder2077/fastsaver.git
|
|
13
|
+
cd fastsaver
|
|
14
|
+
|
|
15
|
+
# Create .venv and install the package (editable) plus the "dev" dependency group
|
|
16
|
+
uv sync
|
|
17
|
+
|
|
18
|
+
# Run the checks
|
|
19
|
+
.venv/bin/python -m pytest tests
|
|
20
|
+
.venv/bin/ruff check src tests examples
|
|
21
|
+
.venv/bin/ruff format --check src tests examples
|
|
22
|
+
.venv/bin/mypy
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`uv run <cmd>` works as well (for example `uv run pytest`). To test against a
|
|
26
|
+
specific interpreter use `uv sync --python 3.9` (the package supports 3.9–3.14).
|
|
27
|
+
|
|
28
|
+
Auto-format before committing:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
.venv/bin/ruff format src tests examples
|
|
32
|
+
.venv/bin/ruff check --fix src tests examples
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Running the live tests
|
|
36
|
+
|
|
37
|
+
The regular test-suite is fully mocked with `respx` and needs no network access.
|
|
38
|
+
`tests/test_live.py` talks to the real API and is skipped unless **both** of the
|
|
39
|
+
following environment variables are set:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
export FASTSAVER_API_KEY="fs_sk_..." # your own key from https://api.fastsaver.io
|
|
43
|
+
export FASTSAVER_LIVE=1
|
|
44
|
+
.venv/bin/python -m pytest tests/test_live.py
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Live tests call `balance()` (free) and perform a single `fetch()`, which costs a
|
|
48
|
+
couple of credits. Never paste a real key into source code, fixtures or CI logs —
|
|
49
|
+
tests use fake keys such as `fs_sk_test_...`.
|
|
50
|
+
|
|
51
|
+
## Pull request guidelines
|
|
52
|
+
|
|
53
|
+
- Open an issue first for larger changes so we can agree on the design.
|
|
54
|
+
- Keep pull requests focused; one topic per PR.
|
|
55
|
+
- Add or update tests for every behaviour change (sync **and** async where applicable).
|
|
56
|
+
- Make sure `pytest`, `ruff check`, `ruff format --check` and `mypy` all pass locally;
|
|
57
|
+
CI runs the same commands on Python 3.9–3.14.
|
|
58
|
+
- Keep the public API in sync between `FastSaver` and `AsyncFastSaver`.
|
|
59
|
+
- Models must parse leniently (missing keys -> `None`/empty, unknown keys ignored).
|
|
60
|
+
- Code comments, docstrings and docs are written in English.
|
|
61
|
+
- Update `CHANGELOG.md` under the `[Unreleased]` heading.
|
|
62
|
+
- Use `from __future__ import annotations` and Python 3.9 compatible syntax.
|
|
63
|
+
|
|
64
|
+
## Release process
|
|
65
|
+
|
|
66
|
+
1. Bump the version in `src/fastsaver/_version.py`.
|
|
67
|
+
2. Move the `[Unreleased]` entries in `CHANGELOG.md` under a new
|
|
68
|
+
`## [X.Y.Z] - YYYY-MM-DD` heading and update the comparison links at the bottom.
|
|
69
|
+
3. Commit and push to `main`, then tag and push the tag:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
git tag vX.Y.Z
|
|
73
|
+
git push origin vX.Y.Z
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
4. Create a GitHub Release from the `vX.Y.Z` tag (copy the changelog entry into the
|
|
77
|
+
release notes). Publishing the release triggers `.github/workflows/publish.yml`,
|
|
78
|
+
which builds the sdist/wheel with `uv build`, verifies them with `twine check` and
|
|
79
|
+
uploads them to PyPI using **Trusted Publishing** (OIDC) — no API token is stored
|
|
80
|
+
in the repository.
|
|
81
|
+
|
|
82
|
+
### One-time PyPI Trusted Publisher setup
|
|
83
|
+
|
|
84
|
+
Trusted Publishing has to be configured once on PyPI so that GitHub Actions is
|
|
85
|
+
allowed to upload the `fastsaver` project:
|
|
86
|
+
|
|
87
|
+
1. Log in to https://pypi.org and open the project page for `fastsaver`
|
|
88
|
+
(for the very first release use https://pypi.org/manage/account/publishing/ and
|
|
89
|
+
add a *pending* publisher — the project is created on the first upload).
|
|
90
|
+
2. Under **Publishing** -> **Add a new publisher** choose **GitHub** and fill in:
|
|
91
|
+
- Owner: `coder2077`
|
|
92
|
+
- Repository name: `fastsaver`
|
|
93
|
+
- Workflow name: `publish.yml`
|
|
94
|
+
- Environment name: `pypi`
|
|
95
|
+
3. In the GitHub repository go to **Settings -> Environments**, create an
|
|
96
|
+
environment called `pypi` and (recommended) add required reviewers so a human
|
|
97
|
+
approves every upload.
|
|
98
|
+
|
|
99
|
+
The workflow requests `id-token: write` permission, which is all
|
|
100
|
+
`pypa/gh-action-pypi-publish` needs to exchange the GitHub OIDC token for a
|
|
101
|
+
short-lived PyPI upload token.
|
|
102
|
+
|
|
103
|
+
## Code of conduct
|
|
104
|
+
|
|
105
|
+
Be kind and constructive. Harassment or disrespectful behaviour is not tolerated.
|
|
106
|
+
|
|
107
|
+
## Questions?
|
|
108
|
+
|
|
109
|
+
Open a GitHub Discussion/Issue, join the Telegram channel https://t.me/fastsaverapi
|
|
110
|
+
or e-mail support@fastsaver.io.
|
fastsaver-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 FastSaverAPI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|