Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mitigate TLS fingerprinting #767

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e241c6f
Initial curl_cffi switch
dolfies Aug 14, 2023
3128548
Use Union type instead of new syntax
dolfies Aug 14, 2023
8fd0a43
Improvements
dolfies Aug 15, 2023
e93ec86
Remove unused http endpoint
dolfies Aug 15, 2023
2e5369e
Fix docs and CI issues
dolfies Aug 15, 2023
c273f80
Handle libcurl errors (requires unreleased curl_cffi version)
dolfies Aug 18, 2023
bcb01af
Initial curl_cffi switch
dolfies Aug 14, 2023
d74aa31
Use Union type instead of new syntax
dolfies Aug 14, 2023
965761f
Improvements
dolfies Aug 15, 2023
d7e855e
Remove unused http endpoint
dolfies Aug 15, 2023
83b2c66
Fix docs and CI issues
dolfies Aug 15, 2023
ee5660a
Handle libcurl errors (requires unreleased curl_cffi version)
dolfies Aug 18, 2023
c5599c5
Merge branch 'refactor/tls' of github.com:dolfies/discord.py-self int…
dolfies Aug 21, 2023
cfc7a00
Merge branch 'master' of github.com:dolfies/discord.py-self into refa…
dolfies Dec 27, 2023
3f82855
Merge branch 'master' into refactor/tls
dolfies Dec 31, 2023
0704df8
Merge branch 'master' into refactor/tls
dolfies Dec 31, 2023
0448e93
Update library and fix issues arised
dolfies Dec 31, 2023
352ef23
Log tls impersonation info
dolfies Dec 31, 2023
77bc225
Initial curl websocket migration
dolfies Jan 1, 2024
48050b3
Merge branch 'master' into refactor/tls
dolfies Jan 1, 2024
a7fe80a
Merge branch 'master' into refactor/tls
dolfies Jan 2, 2024
aa6f320
Merge branch 'master' into refactor/tls
dolfies Jan 2, 2024
9ad6d7d
Ignore curl_cffi warnings for now
dolfies Jan 2, 2024
72c6a59
Add websocket send lock
dolfies Jan 3, 2024
249f190
Fix proxy support
dolfies Jan 14, 2024
1a49809
Fix for newer versions
dolfies Dec 1, 2024
1363435
Docs fixes
dolfies Dec 2, 2024
40b362c
More minor fixes
dolfies Dec 2, 2024
436a93c
More minor fixes
dolfies Dec 2, 2024
09b55c8
Ignore CURLE_GOT_NOTHING
dolfies Dec 4, 2024
1992b4e
Refactor property fetching, dynamically generate sec-ch-ua header
dolfies Dec 4, 2024
c0710eb
Asynchronously stream HTTP responses
dolfies Dec 10, 2024
1633016
Update super props
dolfies Dec 13, 2024
df7b52e
Support brands in user agent
dolfies Jan 10, 2025
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
14 changes: 9 additions & 5 deletions discord/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,18 @@

from __future__ import annotations

from typing import Optional, Tuple, Dict

import argparse
import importlib.metadata
import platform
import sys
from pathlib import Path
from typing import Dict, Optional, Tuple

import discord
import importlib.metadata
import aiohttp
import platform
import curl_cffi
import discord_protos

import discord


def show_version() -> None:
Expand All @@ -47,6 +49,8 @@
if version:
entries.append(f' - discord.py-self metadata: v{version}')

entries.append(f'- discord-protos v{discord_protos.__version__}')
entries.append(f'- curl_cffi v{curl_cffi.__version__} (curl v{curl_cffi.__curl_version__})')

Check failure on line 53 in discord/__main__.py

View workflow job for this annotation

GitHub Actions / check

"__version__" is not exported from module "curl_cffi" (reportPrivateImportUsage)

Check failure on line 53 in discord/__main__.py

View workflow job for this annotation

GitHub Actions / check

"__curl_version__" is not exported from module "curl_cffi" (reportPrivateImportUsage)
entries.append(f'- aiohttp v{aiohttp.__version__}')
uname = platform.uname()
entries.append('- system info: {0.system} {0.release} {0.version}'.format(uname))
Expand Down
12 changes: 4 additions & 8 deletions discord/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ class Client:

A number of options can be passed to the :class:`Client`.

.. versionchanged:: 2.1

Removed the ``http_trace`` parameter.

Parameters
-----------
max_messages: Optional[:class:`int`]
Expand Down Expand Up @@ -215,12 +219,6 @@ class Client:
Whether to keep presences up-to-date across clients.
The default behavior is ``True`` (what the client does).

.. versionadded:: 2.0
http_trace: :class:`aiohttp.TraceConfig`
The trace configuration to use for tracking HTTP requests the library does using ``aiohttp``.
This allows you to check requests the library is using. For more information, check the
`aiohttp documentation <https://docs.aiohttp.org/en/stable/client_advanced.html#client-tracing>`_.

.. versionadded:: 2.0
captcha_handler: Optional[Callable[[:class:`.CaptchaRequired`, :class:`.Client`], Awaitable[:class:`str`]]
A function that solves captcha challenges.
Expand Down Expand Up @@ -254,7 +252,6 @@ def __init__(self, **options: Any) -> None:
proxy: Optional[str] = options.pop('proxy', None)
proxy_auth: Optional[aiohttp.BasicAuth] = options.pop('proxy_auth', None)
unsync_clock: bool = options.pop('assume_unsync_clock', True)
http_trace: Optional[aiohttp.TraceConfig] = options.pop('http_trace', None)
max_ratelimit_timeout: Optional[float] = options.pop('max_ratelimit_timeout', None)
self.captcha_handler: Optional[Callable[[CaptchaRequired, Client], Awaitable[str]]] = options.pop(
'captcha_handler', None
Expand All @@ -263,7 +260,6 @@ def __init__(self, **options: Any) -> None:
proxy=proxy,
proxy_auth=proxy_auth,
unsync_clock=unsync_clock,
http_trace=http_trace,
captcha=self.handle_captcha,
max_ratelimit_timeout=max_ratelimit_timeout,
locale=lambda: self._connection.locale,
Expand Down
22 changes: 11 additions & 11 deletions discord/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
from .utils import _get_as_snowflake

if TYPE_CHECKING:
from aiohttp import ClientResponse, ClientWebSocketResponse
from aiohttp import ClientResponse
from curl_cffi.requests import Response as CurlResponse, WebSocket

Check failure on line 33 in discord/errors.py

View workflow job for this annotation

GitHub Actions / check

Import "WebSocket" is not accessed (reportUnusedImport)
from requests import Response
from typing_extensions import TypeGuard

Expand All @@ -41,7 +42,7 @@
FormErrorWrapper as FormErrorWrapperPayload,
)

_ResponseType = Union[ClientResponse, Response]
_ResponseType = Union[ClientResponse, CurlResponse, Response]

__all__ = (
'DiscordException',
Expand Down Expand Up @@ -116,10 +117,10 @@

Attributes
------------
response: :class:`aiohttp.ClientResponse`
The response of the failed HTTP request. This is an
instance of :class:`aiohttp.ClientResponse`. In some cases
this could also be a :class:`requests.Response`.
response: Union[:class:`curl_cffi.requests.Response`, :class:`aiohttp.ClientResponse`]
The response of the failed HTTP request. This is an instance of
:class:`curl_cffi.requests.Response` or :class:`aiohttp.ClientResponse`.
In some cases this could also be a :class:`requests.Response`.
text: :class:`str`
The text of the error. Could be an empty string.
status: :class:`int`
Expand Down Expand Up @@ -300,10 +301,9 @@

__slots__ = ('code', 'reason')

def __init__(self, socket: ClientWebSocketResponse, *, code: Optional[int] = None):
def __init__(self, code: Optional[int] = None, reason: Optional[str] = None):
# This exception is just the same exception except
# reconfigured to subclass ClientException for users
self.code: int = code or socket.close_code or -1
# aiohttp doesn't seem to consistently provide close reason
self.reason: str = ''
super().__init__(f'WebSocket closed with {self.code}')
self.code: int = code or -1
self.reason: str = reason or 'unknown'
super().__init__(f'WebSocket closed with {self.code} (reason: {self.reason!r})')
Loading
Loading