Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ jobs:
- linux/i386
- linux/arm64
- linux/arm/v7
- linux/ppc64le
steps:
- name: Prepare
run: |
Expand Down
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ RUN /usr/local/bin/pip install --user \
lxml==6.0.2 \
httptools==0.7.1 \
MarkupSafe==3.0.3 \
pyyaml==6.0.3
pyyaml==6.0.3 \
curl-cffi==0.14.0

# Create a fake eddrit package to install dependencies
WORKDIR /app/
Expand Down
1 change: 0 additions & 1 deletion doc/deployment/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ The following architectures are supported by the Docker image:
- `linux/i386`
- `linux/arm64`
- `linux/arm/v7`
- `linux/ppc64le`

### Option 2: without Docker

Expand Down
2 changes: 2 additions & 0 deletions eddrit/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
subreddit_user_and_wiki,
)
from eddrit.routes.xhr import routes
from eddrit.utils.http import get_httpx_async_transport
from eddrit.utils.middlewares import (
CookiesRefreshMiddleware,
CurrentHostMiddleware,
Expand Down Expand Up @@ -64,6 +65,7 @@ async def lifespan(app: Starlette) -> typing.AsyncIterator[State]:
"""Init the app lifespan: httpx client etc.."""
async with httpx.AsyncClient(
http2=True,
transport=get_httpx_async_transport(),
proxy=config.PROXY,
event_hooks={
"request": [oauth_before_request],
Expand Down
14 changes: 14 additions & 0 deletions eddrit/utils/http.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import httpx
from httpx_curl_cffi import AsyncCurlTransport, CurlTransport

IMPERSONATE = "chrome131_android"


def get_httpx_transport() -> httpx.BaseTransport:
"""Get an HTTPX transport with fingerprint impersonation."""
return CurlTransport(impersonate=IMPERSONATE, default_headers=True)


def get_httpx_async_transport() -> httpx.AsyncBaseTransport:
"""Get an HTTPX transport with fingerprint impersonation."""
return AsyncCurlTransport(impersonate=IMPERSONATE, default_headers=True)
5 changes: 4 additions & 1 deletion eddrit/utils/oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from eddrit.config import PROXY, VALKEY_URL
from eddrit.constants import REDDIT_BASE_API_URL_HOST
from eddrit.exceptions import RateLimitedError
from eddrit.utils.http import get_httpx_transport

OFFICIAL_ANDROID_OAUTH_ID = "ohXpoqrZYub1kg"
OFFICIAL_ANDROID_APP_VERSIONS = [
Expand Down Expand Up @@ -146,7 +147,9 @@ def oauth_login() -> None:

# Login
client = httpx.Client(
http2=True, proxy=PROXY
http2=True,
proxy=PROXY,
transport=get_httpx_transport(),
) # not async but not supported by cachier
id_to_encode = f"{OFFICIAL_ANDROID_OAUTH_ID}:"
res = client.post(
Expand Down
163 changes: 161 additions & 2 deletions poetry.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ dependencies = [
"tldextract (>=5.1.3,<6.0.0)",
"uvicorn[standard] (>=0.34.0,<1.0.0)",
"valkey (>=6.0.0,<7.0.0)",
"httpx-curl-cffi (>=0.1.5,<0.2.0)",
]

[tool.poetry.group.dev.dependencies]
Expand Down