archiving community contributions on YouTube: unpublished captions, title and description translations and caption credits
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

71 lines
2.4 KiB

  1. import asyncio
  2. from typing import cast
  3. from urllib.parse import urlparse
  4. from aioquic.h3.connection import H3_ALPN
  5. from aioquic.asyncio.client import connect
  6. from aioquic.quic.configuration import QuicConfiguration
  7. from http3_base import HttpClient, prepare_response, perform_http_request
  8. from urllib.parse import urlparse
  9. class HTTP3Response:
  10. def __init__(self, input) -> None:
  11. headers, content, url, redirect = input
  12. self.content = content
  13. try:
  14. self.text = content.decode()
  15. except:
  16. print("Text decoding error")
  17. self.text = ""
  18. self.headers = {}
  19. for k, v in headers.items():
  20. self.headers[k.decode()] = v.decode()
  21. try:
  22. self.status_code = int(headers[b":status"])
  23. self.url = url
  24. except:
  25. print("Status code not included as header, defaulting to 200")
  26. self.status_code = 200
  27. self.ok = self.status_code < 400
  28. async def main(address, headers={}):
  29. parsed = urlparse(address)
  30. configuration = QuicConfiguration(
  31. is_client=True, alpn_protocols=H3_ALPN
  32. )
  33. async with connect(parsed.netloc, port=443, configuration=configuration, create_protocol=HttpClient) as client:
  34. client = cast(HttpClient, client)
  35. redirect = False
  36. while True:
  37. events = await perform_http_request(client=client, url=address, headers=headers)
  38. oheaders, ocontent = prepare_response(events)
  39. statuscode = int(oheaders[b":status"])
  40. if statuscode >= 300 and statuscode < 400 and b"location" in oheaders.keys():
  41. redirect = True
  42. origurl = address
  43. parsedorig = urlparse(origurl)
  44. address = oheaders[b"location"].decode()
  45. parsednew = urlparse(address)
  46. if not parsednew.scheme and not parsednew.netloc:
  47. address = parsedorig.scheme + "://" + parsedorig.netloc + address
  48. else:
  49. break
  50. return HTTP3Response((oheaders, ocontent, address, redirect))
  51. def get(url, headers={}, params={}):
  52. plist = []
  53. for item in params:
  54. k, v = item
  55. plist.append(str(k)+"="+str(v))
  56. if plist:
  57. pstring = "?"+"&".join(plist)
  58. else:
  59. pstring = ""
  60. url = url+pstring
  61. loop = asyncio.new_event_loop()
  62. return loop.run_until_complete(main(url, headers=headers))