11"""Stores API connection session and sends requests"""
22
33import re
4+ import time
45import random
56import logging
7+ from functools import partial
8+
9+ from typing import Optional , Union
610from requests import Response
11+
712from cloudscraper import CloudScraper
8- from typing import Optional , Union
913
1014from . import atjsparse
1115from .aterrors import TokenError
@@ -160,8 +164,7 @@ def request_cloudflare(
160164 headers : Optional [dict ] = None ,
161165 reqcookies : Optional [dict ] = None ,
162166 sendtoken : bool = False ,
163- redirect : bool = True ,
164- retry : int = 3 ) -> Response :
167+ retry : int = 5 ) -> Response :
165168
166169 """Sends a request to Aternos API bypass Cloudflare
167170
@@ -181,11 +184,8 @@ def request_cloudflare(
181184 :param sendtoken: If the ajax and SEC token
182185 should be sent, defaults to False
183186 :type sendtoken: bool, optional
184- :param redirect: If requests lib should follow
185- Location header in 3xx responses, defaults to True
186- :type redirect: bool, optional
187187 :param retry: How many times parser must retry
188- connection to API bypass Cloudflare, defaults to 3
188+ connection to API bypass Cloudflare, defaults to 5
189189 :type retry: int, optional
190190 :raises CloudflareError:
191191 When the parser has exceeded retries count
@@ -198,21 +198,26 @@ def request_cloudflare(
198198 if retry <= 0 :
199199 raise CloudflareError ('Unable to bypass Cloudflare protection' )
200200
201+ old_cookies = self .session .cookies
202+ self .session = CloudScraper ()
203+ self .session .cookies .update (old_cookies )
204+
201205 try :
202206 self .atsession = self .session .cookies ['ATERNOS_SESSION' ]
203207 except KeyError :
208+ # don't rewrite atsession value
204209 pass
205210
211+ params = params or {}
212+ data = data or {}
213+ headers = headers or {}
214+ reqcookies = reqcookies or {}
215+
206216 method = method or 'GET'
207217 method = method .upper ().strip ()
208218 if method not in ('GET' , 'POST' ):
209219 raise NotImplementedError ('Only GET and POST are available' )
210220
211- headers = headers or {}
212- params = params or {}
213- data = data or {}
214- reqcookies = reqcookies or {}
215-
216221 if sendtoken :
217222 params ['TOKEN' ] = self .token
218223 params ['SEC' ] = self .sec
@@ -230,26 +235,35 @@ def request_cloudflare(
230235 logging .debug (f'session-cookies={ self .session .cookies } ' )
231236
232237 if method == 'POST' :
233- req = self . session . post (
234- url , data = data , params = params ,
235- headers = headers , cookies = reqcookies ,
236- allow_redirects = redirect
238+ sendreq = partial (
239+ self . session . post ,
240+ params = params ,
241+ data = data
237242 )
238243 else :
239- req = self .session .get (
240- url , params = {** params , ** data },
241- headers = headers , cookies = reqcookies ,
242- allow_redirects = redirect
244+ sendreq = partial (
245+ self .session .get ,
246+ params = {** params , ** data }
243247 )
244248
245- if '<title>Please Wait... | Cloudflare</title>' in req .text :
249+ req = sendreq (
250+ url ,
251+ headers = headers ,
252+ cookies = reqcookies
253+ )
254+
255+ resp_type = req .headers .get ('content-type' , '' )
256+ html_type = resp_type .find ('text/html' ) != - 1
257+ cloudflare = req .status_code == 403
258+
259+ if html_type and cloudflare :
246260 logging .info ('Retrying to bypass Cloudflare' )
261+ time .sleep (0.2 )
247262 return self .request_cloudflare (
248263 url , method ,
249264 params , data ,
250265 headers , reqcookies ,
251- sendtoken , redirect ,
252- retry - 1
266+ sendtoken , retry - 1
253267 )
254268
255269 logging .debug ('AternosConnect received: ' + req .text [:65 ])
0 commit comments