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

Use with discord.py bot #57

Closed
lexicalunit opened this issue Jun 22, 2022 · 10 comments
Closed

Use with discord.py bot #57

lexicalunit opened this issue Jun 22, 2022 · 10 comments

Comments

@lexicalunit
Copy link

I'm on a M1 mac so I wasn't able to get it to work via docker. But I cloned this repo then:

cargo build --release
DISCORD_TOKEN="my token" PORT=3000 ./target/release/twilight-http-proxy
2022-06-22T15:52:23.122150Z  INFO twilight_http_proxy: Listening on http://0.0.0.0:3000

Note also that the README.md is wrong and the built binary is twilight-http-proxy rather than twilight_http_proxy.

Now I start up my bot using proxy="http://localhost:3000" and I immediately have issues. In the proxy log I see:

2022-06-22T15:53:40.514419Z ERROR twilight_http_proxy: Unsupported HTTP method in request, CONNECT

And in my bot's log we can see that it's trying to GET /users/@me:

[...]
  File "mybot/env/lib/python3.10/site-packages/discord/http.py", line 561, in static_login
    data = await self.request(Route('GET', '/users/@me'))
  File "mybot/env/lib/python3.10/site-packages/discord/http.py", line 444, in request
    async with self.__session.request(method, url, **kwargs) as response:
  File "mybot/env/lib/python3.10/site-packages/aiohttp/client.py", line 1117, in __aenter__
    self._resp = await self._coro
  File "mybot/env/lib/python3.10/site-packages/aiohttp/client.py", line 520, in _request
    conn = await self._connector.connect(
  File "mybot/env/lib/python3.10/site-packages/aiohttp/connector.py", line 535, in connect
    proto = await self._create_connection(req, traces, timeout)
  File "mybot/env/lib/python3.10/site-packages/aiohttp/connector.py", line 890, in _create_connection
    _, proto = await self._create_proxy_connection(req, traces, timeout)
  File "mybot/env/lib/python3.10/site-packages/aiohttp/connector.py", line 1124, in _create_proxy_connection
    raise ClientHttpProxyError(
aiohttp.client_exceptions.ClientHttpProxyError: 501, message='Not Implemented', url=URL('http://localhost:3000')
@Gelbpunkt
Copy link
Member

As is stated in the README, the proxy replaces the Discord API instead of serving as a real HTTP CONNECT proxy. You're using it as if it were a HTTP CONNECT proxy, which is unsupported.

@lexicalunit
Copy link
Author

Aw, that's too bad. I was hoping that https://fusebit.io/blog/discord-rate-limiting/ knew what it was talking about, but apparently it doesn't. Thanks for the heads up. I might as well ask: Do you know of any real http proxies for Discord bots?

@Erk-
Copy link
Member

Erk- commented Jun 22, 2022

I don't know of any proper proxies, but it is probably our own fault for the name. You can get it working with discord.py by monkeypatching discord.http.Route.BASE to being in your example http://localhost:3000 and I think that should work.

@Gelbpunkt
Copy link
Member

Gelbpunkt commented Jun 22, 2022

It is practically impossible to use a real HTTP CONNECT proxy for this from what I know about the CONNECT protocol. You see, the client only specifies the host and port to open a connection with, and all the traffic itself is then tunneled. The issue is that if SSL is being used, which it would in this case, the proxy won't be able to tell which exact URLs are being requested. It will know that discord.com port 443 is being connected to, but not that you're requesting /api/users/@me - because that's encrypted.

@Gelbpunkt
Copy link
Member

I don't know of any proper proxies, but it is probably our own fault for the name. You can get it working with discord.py by monkeypatching discord.http.Route.BASE to being in your example http://localhost:3000 and I think that should work.

This is the bare minimum - if you want to hand full control to the proxy, you could use something like this patch as a base to get rid off local rate limit handling and leave everything to the proxy.

@lexicalunit
Copy link
Author

lexicalunit commented Jun 22, 2022

Thank you so much, y'all have been super helpful ❤️

🤔 This seems to work ok:

def patch_discord_proxy(PROXY_URL: str):
    """Patch discord.http to use our Discord API proxy."""
    from discord import http

    http.Route.BASE = f"{PROXY_URL}/api/v10"
    http._set_api_version = lambda v: f"{PROXY_URL}/api/v{v}"

@Gelbpunkt I see you did similar, but also ripped out a lot of discord.py's own rate limiting. That makes sense, for sure. But for the most part discord.py's rate limiting works fine for me. It's just the global rate limiting that discord.py is awful about handling. Rather than proactively prevent the bot from hitting the global rate limit, it just reacts to the rate limit being hit by shutting the bot down until the 1 hour CloudFlare ban wears off.

IIUC twilight's http-proxy will actually stop the requests from going out, queue them up, and then resume them later to avoid the 50 requests/s CloudFlare limit. Is that right?

Maybe I can just use my quick and dirty patch + twilight-http-proxy to get that nice proactive intelligent global rate limiting feature, and just leave all the discord.py rate limiting stuff in there (which hopefully won't hurt anything 🤞🏻)?

@lexicalunit lexicalunit changed the title /users/@me is not implemented Use with discord.py bot Jun 22, 2022
@Gelbpunkt
Copy link
Member

IIUC twilight's http-proxy will actually stop the requests from going out, queue them up, and then resume them later to avoid the 50 requests/s CloudFlare limit. Is that right?

It will hold your connection and send the request to Discord once it won't be ratelimited. Therefore you might run into timeouts if the client is configured with a low timeout.

Maybe I can just use my quick and dirty patch + twilight-http-proxy to get that nice proactive intelligent global rate limiting feature, and just leave all the discord.py rate limiting stuff in there (which hopefully won't hurt anything 🤞🏻)?

You can and it will certainly work. I just don't see a reason to have overhead in Python code, based on limited knowledge, instead of just leaving everything to the proxy, because it does these computations already. That said, what you are doing will work fine, so no need to worry about that.

@lexicalunit
Copy link
Author

lexicalunit commented Jun 28, 2022

Hrm, something didn't work. I am currently getting the dreaded HTTPException: 429 Too Many Requests (error code: 0): You are being blocked from accessing our API temporarily due to exceeding our rate limits frequently. Please read our docs at https://discord.com/developers/docs/topics/rate-limits to prevent this moving forward. error in my bot with every request it tries to make. All Discord API requests are being routed through twilight-http-proxy.

Did I misconfigure something?

I see no logs for twilight-http-proxy besides:

INFO twilight_http_proxy: Listening on http://[0.0.0.0](OMIT):3000

@Erk-
Copy link
Member

Erk- commented Jun 28, 2022

No it probably is correct. The issue here is that we do not preemptively handle the global rate limit see twilight-rs/twilight#650

@itohatweb
Copy link
Member

Closing this since it looks like this issue is resolved/related to twilight-rs/twilight#650.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants