feat(tenacity): Stable Message Queue (#238)
This commit is contained in:
parent
b22ed65d00
commit
891684d29a
27
src/claim.py
27
src/claim.py
|
@ -11,9 +11,11 @@ import sys
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
import hcaptcha_challenger as solver
|
import importlib_metadata
|
||||||
|
from hcaptcha_challenger import install
|
||||||
|
from hcaptcha_challenger.agents import Malenia
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from playwright.async_api import BrowserContext, async_playwright, TimeoutError
|
from playwright.async_api import BrowserContext, async_playwright
|
||||||
|
|
||||||
from epic_games import (
|
from epic_games import (
|
||||||
EpicPlayer,
|
EpicPlayer,
|
||||||
|
@ -23,7 +25,6 @@ from epic_games import (
|
||||||
get_promotions,
|
get_promotions,
|
||||||
get_order_history,
|
get_order_history,
|
||||||
)
|
)
|
||||||
import importlib_metadata
|
|
||||||
|
|
||||||
self_supervised = True
|
self_supervised = True
|
||||||
|
|
||||||
|
@ -118,19 +119,9 @@ class ISurrender:
|
||||||
single_promotions.append(p)
|
single_promotions.append(p)
|
||||||
|
|
||||||
if single_promotions:
|
if single_promotions:
|
||||||
for _ in range(3):
|
await epic.claim_weekly_games(page, single_promotions)
|
||||||
try:
|
|
||||||
if await epic.claim_weekly_games(page, single_promotions):
|
|
||||||
break
|
|
||||||
except TimeoutError:
|
|
||||||
continue
|
|
||||||
if bundle_promotions:
|
if bundle_promotions:
|
||||||
for _ in range(3):
|
await epic.claim_bundle_games(page, bundle_promotions)
|
||||||
try:
|
|
||||||
if await epic.claim_bundle_games(page, bundle_promotions):
|
|
||||||
break
|
|
||||||
except TimeoutError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
@logger.catch
|
@logger.catch
|
||||||
async def stash(self):
|
async def stash(self):
|
||||||
|
@ -139,11 +130,10 @@ class ISurrender:
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"run",
|
"run",
|
||||||
image="20231105",
|
image="20231121",
|
||||||
version=importlib_metadata.version("hcaptcha-challenger"),
|
version=importlib_metadata.version("hcaptcha-challenger"),
|
||||||
role="EpicPlayer",
|
role="EpicPlayer",
|
||||||
headless=self.headless,
|
headless=self.headless,
|
||||||
self_supervised=self_supervised,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
async with async_playwright() as p:
|
async with async_playwright() as p:
|
||||||
|
@ -155,8 +145,9 @@ class ISurrender:
|
||||||
locale=self.locale,
|
locale=self.locale,
|
||||||
args=["--hide-crash-restore-bubble"],
|
args=["--hide-crash-restore-bubble"],
|
||||||
)
|
)
|
||||||
|
await Malenia.apply_stealth(context)
|
||||||
if not await self.prelude_with_context(context):
|
if not await self.prelude_with_context(context):
|
||||||
solver.install(upgrade=True, clip=self_supervised)
|
install(upgrade=True, clip=True)
|
||||||
await self.claim_epic_games(context)
|
await self.claim_epic_games(context)
|
||||||
await context.close()
|
await context.close()
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ from typing import List, Dict, Literal
|
||||||
import httpx
|
import httpx
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from playwright.async_api import BrowserContext, expect, TimeoutError, Page, FrameLocator, Locator
|
from playwright.async_api import BrowserContext, expect, TimeoutError, Page, FrameLocator, Locator
|
||||||
|
from tenacity import *
|
||||||
|
|
||||||
from epic_games.player import EpicPlayer
|
from epic_games.player import EpicPlayer
|
||||||
from utils import from_dict_to_model, AgentG
|
from utils import from_dict_to_model, AgentG
|
||||||
|
@ -87,6 +88,12 @@ class CommonHandler:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@retry(
|
||||||
|
retry=retry_if_exception_type(TimeoutError),
|
||||||
|
wait=wait_fixed(0.5),
|
||||||
|
stop=stop_after_attempt(15),
|
||||||
|
reraise=True,
|
||||||
|
)
|
||||||
async def insert_challenge(
|
async def insert_challenge(
|
||||||
solver: AgentG,
|
solver: AgentG,
|
||||||
page: Page,
|
page: Page,
|
||||||
|
@ -95,18 +102,19 @@ class CommonHandler:
|
||||||
recur_url: str,
|
recur_url: str,
|
||||||
is_uk: bool,
|
is_uk: bool,
|
||||||
):
|
):
|
||||||
for _ in range(15):
|
response = await solver.execute(window="free")
|
||||||
# {{< if fall in challenge >}}
|
logger.debug("task done", sattus=f"{solver.status.CHALLENGE_SUCCESS}")
|
||||||
match await solver(window="free", recur_url=recur_url):
|
|
||||||
case solver.status.CHALLENGE_BACKCALL | solver.status.CHALLENGE_RETRY:
|
match response:
|
||||||
await wpc.locator("//a[@class='talon_close_button']").click()
|
case solver.status.CHALLENGE_BACKCALL | solver.status.CHALLENGE_RETRY:
|
||||||
await page.wait_for_timeout(1000)
|
await wpc.locator("//a[@class='talon_close_button']").click()
|
||||||
if is_uk:
|
await page.wait_for_timeout(1000)
|
||||||
await CommonHandler.uk_confirm_order(wpc)
|
if is_uk:
|
||||||
await payment_btn.click(delay=200)
|
await CommonHandler.uk_confirm_order(wpc)
|
||||||
case solver.status.CHALLENGE_SUCCESS:
|
await payment_btn.click(delay=200)
|
||||||
await page.wait_for_url(recur_url)
|
case solver.status.CHALLENGE_SUCCESS:
|
||||||
break
|
await page.wait_for_url(recur_url)
|
||||||
|
return
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def empty_cart(page: Page, wait_rerender: int = 30) -> bool | None:
|
async def empty_cart(page: Page, wait_rerender: int = 30) -> bool | None:
|
||||||
|
@ -272,6 +280,12 @@ class EpicGames:
|
||||||
logger.success("flush_token", path=self.player.ctx_cookie_path)
|
logger.success("flush_token", path=self.player.ctx_cookie_path)
|
||||||
return cookies
|
return cookies
|
||||||
|
|
||||||
|
@retry(
|
||||||
|
retry=retry_if_exception_type(TimeoutError),
|
||||||
|
wait=wait_fixed(0.5),
|
||||||
|
stop=(stop_after_delay(360) | stop_after_attempt(3)),
|
||||||
|
reraise=True,
|
||||||
|
)
|
||||||
async def claim_weekly_games(self, page: Page, promotions: List[Game]):
|
async def claim_weekly_games(self, page: Page, promotions: List[Game]):
|
||||||
in_cart_nums = 0
|
in_cart_nums = 0
|
||||||
|
|
||||||
|
@ -326,6 +340,12 @@ class EpicGames:
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@retry(
|
||||||
|
retry=retry_if_exception_type(TimeoutError),
|
||||||
|
wait=wait_fixed(0.5),
|
||||||
|
stop=(stop_after_delay(360) | stop_after_attempt(3)),
|
||||||
|
reraise=True,
|
||||||
|
)
|
||||||
async def claim_bundle_games(self, page: Page, promotions: List[Game]):
|
async def claim_bundle_games(self, page: Page, promotions: List[Game]):
|
||||||
for promotion in promotions:
|
for promotion in promotions:
|
||||||
logger.info("claim_bundle_games", action="go to store", url=promotion.url)
|
logger.info("claim_bundle_games", action="go to store", url=promotion.url)
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
# Author : QIN2DIM
|
# Author : QIN2DIM
|
||||||
# GitHub : https://github.com/QIN2DIM
|
# GitHub : https://github.com/QIN2DIM
|
||||||
# Description:
|
# Description:
|
||||||
|
import asyncio
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from hcaptcha_challenger.agents import AgentT
|
from hcaptcha_challenger.agents import AgentT
|
||||||
from playwright.async_api import Page
|
from playwright.async_api import Page
|
||||||
|
from tenacity import *
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -29,3 +31,38 @@ class AgentG(AgentT):
|
||||||
frame_challenge = frame_purchase.frame_locator(self.HOOK_CHALLENGE)
|
frame_challenge = frame_purchase.frame_locator(self.HOOK_CHALLENGE)
|
||||||
|
|
||||||
return frame_challenge
|
return frame_challenge
|
||||||
|
|
||||||
|
@retry(
|
||||||
|
retry=retry_if_exception_type(asyncio.QueueEmpty),
|
||||||
|
wait=wait_fixed(0.5),
|
||||||
|
stop=(stop_after_delay(30) | stop_after_attempt(60)),
|
||||||
|
reraise=True,
|
||||||
|
)
|
||||||
|
async def _reset_state(self) -> bool | None:
|
||||||
|
self.cr = None
|
||||||
|
self.qr = self.qr_queue.get_nowait()
|
||||||
|
|
||||||
|
if not self.qr_queue.empty():
|
||||||
|
for _ in range(self.qr_queue.qsize()):
|
||||||
|
self.qr = self.qr_queue.get_nowait()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@retry(
|
||||||
|
retry=retry_if_exception_type(asyncio.QueueEmpty),
|
||||||
|
wait=wait_fixed(0.5),
|
||||||
|
stop=(stop_after_delay(30) | stop_after_attempt(60)),
|
||||||
|
reraise=True,
|
||||||
|
)
|
||||||
|
async def _is_success(self):
|
||||||
|
self.cr = self.cr_queue.get_nowait()
|
||||||
|
|
||||||
|
if not self.cr_queue.empty():
|
||||||
|
for _ in range(self.cr_queue.qsize()):
|
||||||
|
self.cr = self.cr_queue.get_nowait()
|
||||||
|
|
||||||
|
# Match: Timeout / Loss
|
||||||
|
if not self.cr or not self.cr.is_pass:
|
||||||
|
return self.status.CHALLENGE_RETRY
|
||||||
|
if self.cr.is_pass:
|
||||||
|
return self.status.CHALLENGE_SUCCESS
|
||||||
|
|
Loading…
Reference in New Issue