from functools import partial
import json
from urllib.parse import urlencode

import thor
from thor.http import HttpClient


token_client = HttpClient()


def handle_captcha(webui, top_resource, formatter, presented_token, client_id):
    if not presented_token:
        return webui.error_response(
            formatter,
            b"403",
            b"Forbidden",
            "hCatpcha token required.",
            "hCaptcha token required.",
        )
    exchange = token_client.exchange()

    @thor.events.on(exchange)
    def error(err_msg):
        return webui.error_response(
            formatter,
            b"403",
            b"Forbidden",
            "hCatpcha error.",
            f"hCaptcha error: {err_msg}.",
        )

    @thor.events.on(exchange)
    def response_start(status, phrase, headers):
        exchange.tmp_status = status

    exchange.tmp_res_body = b""

    @thor.events.on(exchange)
    def response_body(chunk):
        exchange.tmp_res_body += chunk

    @thor.events.on(exchange)
    def response_done(trailers):
        if exchange.tmp_status != b"200":
            e_str = (
                f"hCaptcha returned {exchange.tmp_status.decode('utf-8')} status code"
            )
            webui.error_response(
                formatter, b"403", b"Forbidden", e_str, e_str,
            )
        results = json.loads(exchange.tmp_res_body)
        if results["success"]:
            webui.continue_test(top_resource, formatter)
        else:
            e_str = f"hCaptcha errors: {', '.join([e for e in results['error-codes']])}"
            webui.error_response(
                formatter, b"403", b"Forbidden", e_str, e_str,
            )

    request_form = {
        "secret": webui.config["hcaptcha_secret"],
        "response": presented_token,
        "remoteip": client_id,
    }
    exchange.request_start(
        b"POST",
        b"https://hcaptcha.com/siteverify",
        [[b"content-type", b"application/x-www-form-urlencoded"]],
    )
    exchange.request_body(urlencode(request_form).encode("utf-8", "replace"))
    exchange.request_done({})

@@ -35,16 +35,49 @@
 rt json%0A
+from typing import TYPE_CHECKING%0A
 from url
@@ -153,118 +153,460 @@
 ent%0A
-%0A%0Atoken_client = HttpClient()%0A%0A%0Adef handle_captcha(webui, top_resource, formatter, presented_token, client_id)
+from thor.http.error import HttpError%0A%0Afrom redbot.formatter import Formatter%0Afrom redbot.resource import HttpResource%0Afrom redbot.type import RawHeaderListType%0A%0Atoken_client = HttpClient()%0A%0Aif TYPE_CHECKING:%0A    from redbot.webui import RedWebUi  # pylint: disable=cyclic-import,unused-import%0A%0A%0Adef handle_captcha(%0A    webui: %22RedWebUi%22,%0A    top_resource: HttpResource,%0A    formatter: Formatter,%0A    presented_token: str,%0A    client_id: str,%0A) -%3E None
 :%0A  
@@ -918,17 +918,36 @@
 (err_msg
-)
+: HttpError) -%3E None
 :%0A      
@@ -1184,21 +1184,37 @@
 e_start(
-statu
+%0A        status: byte
 s, phras
@@ -1214,16 +1214,23 @@
 , phrase
+: bytes
 , header
@@ -1230,17 +1230,49 @@
  headers
-)
+: RawHeaderListType%0A    ) -%3E None
 :%0A      
@@ -1393,17 +1393,32 @@
 dy(chunk
-)
+: bytes) -%3E None
 :%0A      
@@ -1511,17 +1511,44 @@
 trailers
-)
+: RawHeaderListType) -%3E None
 :%0A      

add type information