Compare commits

...
64 Commits
Author SHA1 Message Date
ThePhaseless 7e9c2ba97d update readme 2025-05-18 23:22:19 +02:00
ThePhaseless 9fc9af3ba9 add unescaped chars test link 2025-05-18 01:14:32 +02:00
ThePhaseless 55526308f6 bump debian version to bookworm 2025-05-18 01:03:12 +02:00
ThePhaseless cdb3223a87 fix typo 2025-05-17 22:45:55 +00:00
ThePhaseless 329235ba5e add devcontainer stage 2025-05-17 22:45:47 +00:00
ThePhaseless 5031d1e554 set default values 2025-05-17 22:45:21 +00:00
ThePhaseless 090b5487e4 devcontainer tweaks 2025-05-17 20:50:13 +00:00
ThePhaseless c608bbc46e set shm size to prevent memory overload 2025-05-17 20:49:18 +00:00
ThePhaseless 46eff073b7 use base dockerfile for devcontainer 2025-05-17 18:45:59 +02:00
renovate[bot] a347b7046b Update dependency ruff to v0.11.10 (#174)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 23:03:52 +00:00
renovate[bot] 4658d04d2e Update dependency seleniumbase to v4.38.2 (#173)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-13 11:52:53 +00:00
renovate[bot] b6aa1a8c58 Update dependency seleniumbase to v4.38.0 (#169)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-10 02:02:57 +00:00
renovate[bot] 5bff9e1bc1 Update dependency ruff to v0.11.9 (#171)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-09 21:55:22 +00:00
renovate[bot] dbd16882de Update dependency ruff to v0.11.8 (#168)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-01 17:46:00 +00:00
renovate[bot] adc98e8cea Update dependency seleniumbase to v4.37.12 (#167)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-01 11:23:17 +00:00
renovate[bot] 8e7d007c6f Update dependency pydantic to v2.11.4 (#166)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-30 06:01:21 +00:00
renovate[bot] 51c1577d7c Update dependency seleniumbase to v4.37.10 (#165)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 20:40:54 +00:00
ThePhaseless 98f9480157 fix invalid requests response 2025-04-29 10:57:21 +02:00
renovate[bot] 2be9fa55a9 Update dependency seleniumbase to v4.37.9 (#164)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 06:08:17 +00:00
renovate[bot] 6520444d4e Update dependency seleniumbase to v4.37.7 (#160)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-25 16:40:57 +00:00
renovate[bot] 693d67bcfd Update dependency ruff to v0.11.7 (#159)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-25 03:24:57 +00:00
renovate[bot] b217778a79 Update dependency seleniumbase to v4.37.6 (#158)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-23 21:57:08 +00:00
renovate[bot] 3b18dfe522 Update dependency seleniumbase to v4.37.5 (#157)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-23 02:47:45 +00:00
renovate[bot] ee5b7fe027 Update dependency seleniumbase to v4.37.4 (#156)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-20 22:44:02 +00:00
renovate[bot] d2678643c0 Update dependency seleniumbase to v4.37.3 (#155)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-19 21:16:24 +00:00
renovate[bot] 343fdca493 Update dependency uvicorn to v0.34.2 (#154)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-19 10:43:47 +00:00
renovate[bot] 5a8edf13ab Update dependency ruff to v0.11.6 (#153)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-17 19:01:37 +00:00
ThePhaseless 1fa6b66f3a fixes ctrl+c on docker run 2025-04-17 11:38:52 +00:00
ThePhaseless fe797ba2ac add userAgent and version to healthcheck 2025-04-17 11:27:17 +00:00
ThePhaseless 409c0f9d8c [skip ci] add proxybase collaboration info 2025-04-14 10:38:02 +00:00
renovate[bot] d22e780219 Update dependency uvicorn to v0.34.1 (#149)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-13 18:03:26 +00:00
ThePhaseless d4f722d121 [skip ci] Clarified the info 2025-04-13 00:11:15 +02:00
ThePhaseless 38b3407b15 fix versioning 2025-04-12 21:53:11 +00:00
ThePhaseless 81959df037 Added SOCKS5 with auth handling 2025-04-12 21:46:42 +00:00
ThePhaseless 05f9f44c79 add protocol to example 2025-04-12 20:47:52 +00:00
ThePhaseless 08cfd95d6a make all pyfiles as not executable 2025-04-12 20:47:37 +00:00
renovate[bot] f60ecbf2ee Update dependency seleniumbase to v4.37.2 (#148)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-11 06:37:45 +00:00
renovate[bot] 630389aebe Update dependency ruff to v0.11.5 (#147)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-10 22:15:44 +00:00
renovate[bot] 603cd0f9a7 Update dependency pydantic to v2.11.3 (#145)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-08 23:00:30 +00:00
ThePhaseless c75c79a2ad rename and add missing fields 2025-04-08 13:13:01 +00:00
ThePhaseless f3fe419eae Merge pull request #133 from MaxG88/fix/flaresolverr-compatibility 2025-04-08 15:12:32 +02:00
ThePhaseless e1a2e77036 tweak camel aliases 2025-04-08 12:34:25 +00:00
ThePhaseless 1bdd65499d [skip ci] add logs fields 2025-04-08 13:39:35 +02:00
renovate[bot] e15d1facf2 Update dependency seleniumbase to v4.37.1 (#144)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-08 02:46:34 +00:00
renovate[bot] 38d5b7dd21 Update dependency seleniumbase to v4.37.0 (#142)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-07 07:00:05 +00:00
renovate[bot] 96d96c32a6 Update dependency ruff to v0.11.4 (#140)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-04 23:01:16 +00:00
renovate[bot] c9967c85aa Update dependency seleniumbase to v4.36.5 (#139)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-04 09:45:03 +00:00
renovate[bot] ed86a79c4d Update dependency ruff to v0.11.3 (#137)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-03 23:33:34 +00:00
renovate[bot] d6b2036956 Update dependency pydantic to v2.11.2 (#136)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-03 18:47:40 +00:00
Maxime Gagnon dd74f80c18 restore flaresolverr compatibility 2025-03-30 16:31:05 -04:00
renovate[bot] 2d9e415eb0 Update dependency seleniumbase to v4.36.4 (#132)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-29 09:24:01 +00:00
renovate[bot] a328e52471 Update dependency pydantic to v2.11.1 (#130)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-29 01:39:41 +00:00
renovate[bot] e3d1cdfb3e Update dependency pydantic to v2.11.0 (#129)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-27 22:59:27 +00:00
ThePhaseless ae12dc05e4 [skip ci] use text area 2025-03-27 17:18:56 +01:00
ThePhaseless d5a1bed3c1 [skip ci] better description 2025-03-27 17:17:30 +01:00
ThePhaseless 3830149ba0 [skip ci] fix spacing 2025-03-27 17:15:52 +01:00
ThePhaseless 7a9a64a4b2 [skip ci] Add compose config input 2025-03-27 17:15:24 +01:00
renovate[bot] 16efa73f48 Update dependency seleniumbase to v4.36.2 (#125)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-26 03:25:03 +00:00
renovate[bot] a5d6a27b2c Update dependency pytest-asyncio to v0.26.0 (#124)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 15:53:25 +00:00
renovate[bot] 20ab7491e1 Update dependency fastapi to v0.115.12 (#123)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 01:52:38 +00:00
renovate[bot] 9aa041a022 Update dependency seleniumbase to v4.36.1 (#122)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-23 02:14:35 +00:00
renovate[bot] 725339f316 Update dependency seleniumbase to v4.36.0 (#121)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-22 02:39:13 +00:00
renovate[bot] fed8e5d0a6 Update dependency ruff to v0.11.2 (#120)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-21 22:43:45 +00:00
renovate[bot] e612d82c2c Update dependency ruff to v0.11.1 (#118)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 21:36:01 +00:00
17 changed files with 608 additions and 723 deletions
-4
View File
@@ -1,4 +0,0 @@
FROM ghcr.io/astral-sh/uv:debian
ENV UV_LINK_MODE=copy
RUN apt update && apt upgrade -y && apt install -y chromium chromium-driver xvfb git
+5 -25
View File
@@ -3,36 +3,16 @@
{
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"build": {
"dockerfile": "Dockerfile"
"dockerfile": "../Dockerfile",
"target": "devcontainer"
},
"customizations": {
"vscode": {
"extensions": [
"charliermarsh.ruff",
"-ms-python.autopep8",
"-ms-python.vscode-pylance"
],
"extensions": ["charliermarsh.ruff", "ms-python.python"],
"settings": {
"python.venvPath": "./venv"
}
}
},
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "pip3 install --user -r requirements.txt",
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
"name": "Byparr Dev Container",
"runArgs": [
"-p",
"8181:8191"
],
"features": {
"ghcr.io/devcontainers-extra/features/act:1": {},
"ghcr.io/devcontainers/features/desktop-lite:1": {}
}
}
"postCreateCommand": "uv sync --group test && cd .venv/lib/*/site-packages/seleniumbase/drivers && rm -f uc_driver && ln -s /usr/bin/chromedriver uc_driver"
}
-164
View File
@@ -1,164 +0,0 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.extentions/
+1
View File
@@ -0,0 +1 @@
.gitignore
+26 -3
View File
@@ -11,12 +11,13 @@ body:
- label: Read Loop Warning on Readme
- label: Done the troubleshooting from Readme
- label: Checked if such issue already exists
- label: Checked other websites with Cloudflare Turnstile
- type: input
id: docker-host
attributes:
label: OS
placeholder: e.g. Docker, Ubuntu Linux
placeholder: e.g. Docker, WSL2, Ubuntu, Windows
- type: input
id: platform-model
@@ -41,8 +42,30 @@ body:
label: Describe the bug
description: A clear and concise description of what the bug is.
placeholder: "Example: The application crashes when trying to load a new file"
- type: textarea
id: config
attributes:
label: Docker Compose config
placeholder: |
```yaml
services:
...
```
- type: textarea
id: prowlarr-logs
attributes:
label: Prowlarr Logs
placeholder: |
```
put logs between 3x `
```
- type: textarea
id: byparr-logs
attributes:
label: Additional context
description: Add any other context about the problem here.
label: Byparr Logs
placeholder: |
```
put logs between 3x `
```
+3 -1
View File
@@ -108,7 +108,9 @@ jobs:
platforms: ${{ matrix.platform }}
cache-from: type=gha,scope=${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=${{ matrix.platform }}
build-args: GITHUB_BUILD=true,VERSION=${{ github.ref_type == 'tag' && github.ref_name || github.sha }}
build-args: |
GITHUB_BUILD=true
VERSION=${{ github.ref_type == 'tag' && github.ref_name || github.sha }}
merge-and-push:
needs: build
+14 -18
View File
@@ -1,19 +1,15 @@
{
"configurations": [
{
"console": "integratedTerminal",
"env": {
"LOG_LEVEL": "DEBUG"
},
"justMyCode": false,
"name": "Python Debugger: Main",
"program": "main.py",
"request": "launch",
"type": "debugpy"
},
],
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0"
}
"configurations": [
{
"console": "integratedTerminal",
"env": {
"LOG_LEVEL": "DEBUG"
},
"justMyCode": false,
"name": "Python Debugger: Main",
"program": "main.py",
"request": "launch",
"type": "debugpy"
}
]
}
+19 -12
View File
@@ -1,17 +1,17 @@
FROM debian:bullseye-slim AS base
FROM debian:bookworm-slim AS base
ENV HOME=/root
ARG GITHUB_BUILD=false \
VERSION
ENV HOME=/root \
GITHUB_BUILD=${GITHUB_BUILD}\
ENV GITHUB_BUILD=${GITHUB_BUILD}\
VERSION=${VERSION}\
DEBIAN_FRONTEND=noninteractive \
PYTHONUNBUFFERED=1 \
# prevents python creating .pyc files
PYTHONDONTWRITEBYTECODE=1 \
DISPLAY=:0
ENV PATH="${HOME}/.local/bin:$PATH"
DISPLAY=:0\
PATH="${HOME}/.local/bin:$PATH"
WORKDIR /app
@@ -19,22 +19,29 @@ RUN apt-get update && \
apt-get install -y --no-install-recommends --no-install-suggests xauth xvfb scrot curl chromium chromium-driver ca-certificates
ADD https://astral.sh/uv/install.sh install.sh
RUN sh install.sh
RUN sh install.sh && uv --version
FROM base AS devcontainer
RUN apt install -y git && apt upgrade -y
ENV UV_LINK_MODE=copy
ENTRYPOINT [ "sleep", "infinity" ]
FROM base AS app
COPY pyproject.toml uv.lock ./
RUN --mount=type=cache,target=${HOME}/.cache/uv uv sync
# SeleniumBase does not come with an arm64 chromedriver binary
RUN cd .venv/lib/*/site-packages/seleniumbase/drivers && ln -s /usr/bin/chromedriver uc_driver
RUN cd .venv/lib/*/site-packages/seleniumbase/drivers && rm -f uc_driver && ln -s /usr/bin/chromedriver uc_driver
COPY . .
FROM base AS test
FROM app AS test
RUN --mount=type=cache,target=${HOME}/.cache/uv uv sync --group test
RUN ./test.sh
FROM base
FROM app
EXPOSE 8191
HEALTHCHECK --interval=15m --timeout=30s --start-period=5s --retries=3 CMD [ "curl", "http://localhost:8191/health" ]
CMD ["./cmd.sh"]
ENTRYPOINT ["uv", "run", "main.py"]
+12 -9
View File
@@ -3,7 +3,7 @@
An alternative to [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) as a drop-in replacement, built with [seleniumbase](https://seleniumbase.io/) and [FastAPI](https://fastapi.tiangolo.com).
> [!IMPORTANT]
> Due to recent challenge changes, this software does not guarantee that the Cloudflare challenge will be bypassed. Cloudflare likely requires valid network traffic originating from the user’s public IP address to mark a connection as legitimate. While this tool may bypass the initial browser check, it does not ensure that requests will consistently pass Cloudflare's validation. More testing and data are required to understand how Cloudflare identifies connections and requests as valid. Invalid requests will result in Byparr's looping and eventually time-outing.
> This software does not **guarantee** (only greatly increases the chance) that any challenge will be bypassed. While this tool passes the initial browser check, Cloudflare and other captcha providers likely require valid network traffic originating from the user’s public IP address to mark a connection as legitimate. If any website does not pass the challenge, please run troubleshooting steps and check if other websites work before you create an GitHub issue.
> [!IMPORTANT]
> Support for NAS devices (like Synology) is minimal. Please report issues, but do not expect it to be fixed quickly. The only ARM device I have is a free Ampere Oracle VM, so I can only test ARM support on that. See [#22](https://github.com/ThePhaseless/Byparr/issues/22) and [#3](https://github.com/ThePhaseless/Byparr/issues/3)
@@ -33,11 +33,14 @@ An alternative to [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) a
## Options
| Env | Default | Description |
| -------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `USE_XVFB` | `SeleniumBase default` | Use virtual desktop with Xvfb. (Linux only) (Can cause performance hog [#14](https://github.com/ThePhaseless/Byparr/issues/14)) |
| `USE_HEADLESS` | `SeleniumBase default` | Use headless chromium. |
| `PROXY` | None | Proxy to use. (format: `username:password@host:port`) |
| Environment Variable | Default | Description |
| -------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `USE_HEADLESS` | `SeleniumBase default` | Use headless chromium. |
| `PROXY` | None | Proxy to use in format: `protocol://username:password@host:port`. [SOCKS5 with authentication is not supported by Chrome](https://stackoverflow.com/questions/75602916/connection-to-private-proxy-socks5-with-chrome-webrequest-onauthrequired-and), see `compose.yaml` file for a workaround |
## Proxy Recommendation
Recently I've partnered with a *new in town* proxy service - ProxyBase - to offer affordable proxy services that seems to work seamlessly with Byparr! Using my affiliate code `byparr` (case sensitive!) when signing up will not only get you access to their cost-effective (**$0.69/GB with occasional promotions**) proxy network but will also help support the continued development of this project. ProxyBase's proxies can significantly improve your success rate when bypassing anti-bot challenges. [Check out ProxyBase](https://discord.gg/perwbTBxGf) and enhance your Byparr experience! Just remember that it uses `socks5` protocol, so check [Options](#options) section for more details.
## Tags
@@ -53,18 +56,18 @@ See `compose.yaml`
### Docker
```bash
docker run -p 8191:8191 ghcr.io/thephaseless/byparr:latest
docker run --shm-size=2gb -p 8191:8191 ghcr.io/thephaseless/byparr:latest
```
### Local
```bash
uv sync && ./cmd.sh
uv sync && uv run main.py
```
## Need help with / TODO
- [x] Slimming container (only ~650 MB now!)
- [x] Slimming container (only ~1.11 GB now!)
- [x] Add more anti-bot challenges
- [x] Add doc strings
- [x] Implement versioning
-3
View File
@@ -1,3 +0,0 @@
#!/bin/sh
uv run main.py
+20 -6
View File
@@ -1,12 +1,26 @@
services:
byparr:
image: ghcr.io/thephaseless/byparr
image: ghcr.io/thephaseless/byparr:latest
restart: unless-stopped
shm_size: 2gb
build:
context: .
dockerfile: Dockerfile
environment:
- LOG_LEVEL=INFO
# # Uncomment below to use pproxy
# environment:
# - PROXY=http://pproxy:8080
volumes:
- ./screenshots:/app/screenshots # For screenshots when exception occurs
ports:
- "8191:8191"
- ./screenshots:/app/screenshots # (optional) For screenshots when exception occurs
# # Uncomment below to use byparr outside of internal network
# ports:
# - "8191:8191"
# # Uncomment the following lines to enable pproxy for socks5 proxy
# pproxy:
# tty: true # Required for pproxy to work
# container_name: pproxy
# restart: unless-stopped
# image: mosajjal/pproxy:latest
# command:
# - -vv
# - -l http://:8080
# - -r socks5://host:port#username:password # Fill in your proxy credentials and address
+6 -6
View File
@@ -8,23 +8,23 @@ version = "0.1.0"
description = "API for getting cookies for Cloudflare challenges"
readme = "README.md"
dependencies = [
"fastapi[standard]==0.115.11",
"fastapi[standard]==0.115.12",
"pyautogui==0.9.54",
"pydantic==2.10.6",
"seleniumbase==4.35.7",
"uvicorn==0.34.0",
"pydantic==2.11.4",
"seleniumbase==4.38.2",
"uvicorn==0.34.2",
]
urls = { repository = "https://github.com/ThePhaseless/Byparr" }
[dependency-groups]
test = [
"httpx==0.28.1",
"pytest-asyncio==0.25.3",
"pytest-asyncio==0.26.0",
"pytest-progress==1.3.0",
"pytest-retry==1.7.0",
"pytest-xdist==3.6.1",
]
dev = ["deptry==0.23.0", "ruff==0.11.0"]
dev = ["deptry==0.23.0", "ruff==0.11.10"]
[tool.deptry.per_rule_ignores]
DEP002 = ["pyautogui"]
Executable → Regular
+16 -5
View File
@@ -8,12 +8,12 @@ from sbase import BaseCase
from src.consts import CHALLENGE_TITLES
from src.models import (
HealthcheckResponse,
LinkRequest,
LinkResponse,
Solution,
)
from .utils import get_sb, logger, save_screenshot
from src.utils import get_sb, logger, save_screenshot
router = APIRouter()
@@ -41,13 +41,14 @@ def health_check(sb: SeleniumDep):
detail="Health check failed",
)
return {"status": "ok"}
return HealthcheckResponse(user_agent=sb.get_user_agent())
@router.post("/v1")
def read_item(request: LinkRequest, sb: SeleniumDep) -> LinkResponse:
"""Handle POST requests."""
start_time = int(time.time() * 1000)
request.url = request.url.replace('"', "").strip()
sb.uc_open_with_reconnect(request.url)
logger.debug(f"Got webpage: {request.url}")
source_bs = sb.get_beautiful_soup()
@@ -61,13 +62,23 @@ def read_item(request: LinkRequest, sb: SeleniumDep) -> LinkResponse:
save_screenshot(sb)
raise HTTPException(status_code=500, detail="Could not bypass challenge")
cookies = sb.get_cookies()
for cookie in cookies:
name = cookie["name"]
value = cookie["value"]
cookie["size"] = len(f"{name}={value}".encode())
cookie["session"] = False
if "expiry" in cookie:
cookie["expires"] = cookie["expiry"]
return LinkResponse(
message="Success",
solution=Solution(
userAgent=sb.get_user_agent(),
user_agent=sb.get_user_agent(),
url=sb.get_current_url(),
status=200,
cookies=sb.get_cookies(),
cookies=cookies,
headers={},
response=str(sb.get_beautiful_soup()),
),
+1 -1
View File
@@ -10,7 +10,7 @@ from src.utils import logger
class LogRequest(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
"""Log requests."""
if request.url.path != "/v1":
if request.url.path != "/v1" or request.method != "POST":
return await call_next(request)
start_time = time.perf_counter()
+19 -27
View File
@@ -1,11 +1,11 @@
from __future__ import annotations
import time
from http import HTTPStatus
from http.client import INTERNAL_SERVER_ERROR
from typing import Any
from fastapi import Body
from pydantic import BaseModel, Field
from pydantic.alias_generators import to_camel
from src import consts
@@ -19,37 +19,30 @@ class LinkRequest(BaseModel):
max_timeout: int = Field(default=60)
class HealthcheckResponse(BaseModel):
model_config = {"alias_generator": to_camel, "populate_by_name": True}
msg: str = "Byparr is ready!"
version: str = consts.VERSION
user_agent: str
class Solution(BaseModel):
model_config = {"alias_generator": to_camel, "populate_by_name": True}
url: str
status: int
cookies: list
userAgent: str # noqa: N815 # Ignore to preserve compatibility
headers: dict[str, Any]
response: str
@classmethod
def invalid(cls, url: str):
"""
Return an empty Solution with default values.
Useful for returning an error response.
"""
return cls(
url=url,
status=HTTPStatus.INTERNAL_SERVER_ERROR,
cookies=[],
userAgent="",
headers={},
response="",
)
cookies: list = []
user_agent: str = ""
headers: dict[str, Any] = {}
response: str = ""
class LinkResponse(BaseModel):
model_config = {"alias_generator": to_camel, "populate_by_name": True}
status: str = "ok"
message: str
solution: Solution
start_timestamp: int = Field(alias="startTimestamp", default_factory=lambda: int(time.time() * 1000))
end_timestamp: int = Field(alias="endTimestamp", default_factory=lambda: int(time.time() * 1000))
start_timestamp: int
end_timestamp: int = Field(default_factory=lambda: int(time.time() * 1000))
version: str = consts.VERSION
@classmethod
@@ -62,7 +55,6 @@ class LinkResponse(BaseModel):
return cls(
status="error",
message="Invalid request",
solution=Solution.invalid(url),
solution=Solution(url=url, status=INTERNAL_SERVER_ERROR),
start_timestamp=int(time.time() * 1000),
end_timestamp=int(time.time() * 1000),
)
)
+12 -5
View File
@@ -1,7 +1,8 @@
import logging
from time import gmtime, strftime
from fastapi import Header
from fastapi import Header, HTTPException
from httpx import codes
from sbase import SB, BaseCase
from src.consts import LOG_LEVEL, PROXY, USE_HEADLESS
@@ -14,18 +15,24 @@ if len(logger.handlers) == 0:
def get_sb(
proxy: str | None = Header(
default=None,
examples=["username:password@host:port"],
description="Override default proxy from env",
default=PROXY,
examples=["protocol://username:password@host:port"],
description="Override default proxy address",
),
):
"""Get SeleniumBase instance."""
if proxy and proxy.startswith("socks5://") and "@" in proxy:
raise HTTPException(
status_code=codes.BAD_REQUEST,
detail="SOCKS5 proxy with authentication is not supported. Check README for more info.",
)
with SB(
uc=True,
headless=USE_HEADLESS,
locale_code="en",
ad_block=True,
proxy=proxy or PROXY,
proxy=proxy,
) as sb:
yield sb
+1
View File
@@ -15,6 +15,7 @@ test_websites = [
"https://extratorrent.st/",
"https://idope.se/",
"https://speed.cd/login",
'https://www.yggtorrent.top/engine/search?do=search&order=desc&sort=publish_date&name="UNESCAPED"+"DOUBLEQUOTES"&category=2145'
]
Generated
+453 -434
View File
File diff suppressed because it is too large Load Diff