mirror of
https://github.com/User0332/rewards-farmer.git
synced 2026-09-17 01:41:37 +00:00
Merge pull request #36 from ethanstoner/feat/query-sources
logging, a query source without an LLM, multi-account and docker
This commit is contained in:
+41
-18
@@ -1,3 +1,5 @@
|
||||
import logging
|
||||
import log_utils
|
||||
import os
|
||||
import random
|
||||
import time
|
||||
@@ -9,13 +11,15 @@ from selenium.webdriver.common.keys import Keys
|
||||
from selenium.webdriver.remote.webelement import WebElement
|
||||
from selenium.common.exceptions import StaleElementReferenceException, TimeoutException, NoSuchElementException
|
||||
import tab_utils
|
||||
import llm_utils
|
||||
import queries
|
||||
import mouse_trajectory
|
||||
import mimic_typing
|
||||
import element_selectors
|
||||
|
||||
VISUAL_SEARCH_IMAGE_PATH = os.path.abspath("visual_search.jpg")
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class RewardsTaskUtils:
|
||||
def __init__(self, driver: webdriver.Edge):
|
||||
self.driver = driver
|
||||
@@ -77,7 +81,10 @@ class RewardsTaskUtils:
|
||||
except TimeoutException:
|
||||
daily_set_links = self.elements.get_daily_set_elements()
|
||||
|
||||
print(f"[WARNING] Daily set panel only shows {len(daily_set_links)} of {expected_activities} activities")
|
||||
logger.warning(
|
||||
"Daily set panel only shows %s of %s activities",
|
||||
len(daily_set_links), expected_activities
|
||||
)
|
||||
|
||||
# Re-read the panel per index: clicking an activity can re-render it and
|
||||
# stale the captured references.
|
||||
@@ -107,7 +114,7 @@ class RewardsTaskUtils:
|
||||
|
||||
for card in explore_on_bing_links:
|
||||
desc = self.elements.extract_card_descriptions(card)
|
||||
query = llm_utils.get_search_query_from_task_description(desc)
|
||||
query = queries.search_query_for_task(desc)
|
||||
|
||||
self.move_to_and_click(card)
|
||||
self.tab_utils.switch_to_other_tab()
|
||||
@@ -127,7 +134,10 @@ class RewardsTaskUtils:
|
||||
|
||||
for card in explore_on_bing_links:
|
||||
if not self.elements.card_is_complete(card):
|
||||
print(f"[WARNING] Explore on Bing Card [desc={self.elements.extract_card_descriptions(card)!r}] is not complete after searching. Please check manually.")
|
||||
logger.warning(
|
||||
"Explore on Bing Card [desc=%r] is not complete after searching. Please check manually.",
|
||||
self.elements.extract_card_descriptions(card)
|
||||
)
|
||||
|
||||
def complete_visual_search(self):
|
||||
self.switch_to_earn_page()
|
||||
@@ -164,7 +174,10 @@ class RewardsTaskUtils:
|
||||
|
||||
for card in misc_cards:
|
||||
if not self.elements.card_is_complete(card) and self.elements.get_card_point_value(card) > 0:
|
||||
print(f"[WARNING] Misc Card [desc={self.elements.extract_card_descriptions(card)!r}] is not complete after clicking. Please check manually.")
|
||||
logger.warning(
|
||||
"Misc Card [desc=%r] is not complete after clicking. Please check manually.",
|
||||
self.elements.extract_card_descriptions(card)
|
||||
)
|
||||
|
||||
self.tab_utils.close_all_other_tabs()
|
||||
|
||||
@@ -179,7 +192,7 @@ class RewardsTaskUtils:
|
||||
# Measure, search, measure again.
|
||||
points_earned, max_pts = self.read_search_points()
|
||||
|
||||
print(f"[INFO] Search points before: {points_earned}/{max_pts}")
|
||||
logger.info("Search points before: %s/%s", points_earned, max_pts)
|
||||
|
||||
for round_number in range(1, max_rounds + 1):
|
||||
if points_earned >= max_pts:
|
||||
@@ -193,16 +206,19 @@ class RewardsTaskUtils:
|
||||
previous = points_earned
|
||||
points_earned, max_pts = self.read_search_points()
|
||||
|
||||
print(f"[INFO] Round {round_number}: {searches} searches -> {points_earned}/{max_pts}")
|
||||
logger.info(
|
||||
"Round %s: %s searches -> %s/%s",
|
||||
round_number, searches, points_earned, max_pts
|
||||
)
|
||||
|
||||
if points_earned <= previous:
|
||||
print("[WARNING] Round produced no points, stopping instead of searching pointlessly.")
|
||||
logger.warning("Round produced no points, stopping instead of searching pointlessly.")
|
||||
break
|
||||
|
||||
if points_earned < max_pts:
|
||||
print(f"[WARNING] Search quota not filled: {points_earned}/{max_pts}")
|
||||
logger.warning("Search quota not filled: %s/%s", points_earned, max_pts)
|
||||
else:
|
||||
print(f"Search quota complete: {points_earned}/{max_pts}")
|
||||
logger.info("Search quota complete: %s/%s", points_earned, max_pts)
|
||||
|
||||
def read_search_points(self):
|
||||
"""Open the points breakdown, read the Bing search row, close it again."""
|
||||
@@ -240,9 +256,7 @@ class RewardsTaskUtils:
|
||||
# search bar should be auto-focused
|
||||
|
||||
for i, query in enumerate(
|
||||
llm_utils.get_related_search_queries(
|
||||
llm_utils.get_random_noun(), num_queries=count
|
||||
)
|
||||
queries.related_queries(count)
|
||||
):
|
||||
self.keyboard.send_keys(f"{query} -noai{Keys.ENTER}")
|
||||
|
||||
@@ -250,7 +264,10 @@ class RewardsTaskUtils:
|
||||
|
||||
try: self.wait_for_then_click(self.elements.get_clear_bing_search_query_button)
|
||||
except StaleElementReferenceException:
|
||||
print(f"[WARNING] StaleElementReferenceException when trying to click the clear button for query {i+1}. Trying again...")
|
||||
logger.warning(
|
||||
"StaleElementReferenceException when trying to click the clear button for query %s. Trying again...",
|
||||
i + 1
|
||||
)
|
||||
self.wait_for_then_click(self.elements.get_clear_bing_search_query_button)
|
||||
|
||||
self.driver.get("https://rewards.bing.com/")
|
||||
@@ -264,7 +281,7 @@ class RewardsTaskUtils:
|
||||
try:
|
||||
self.wait_for_then_click(self.elements.get_claim_bonus_points_button)
|
||||
except TimeoutException:
|
||||
print("[WARNING] Could not find the 'Claim Bonus Points' button. There are likely no bonus points to claim at this time.")
|
||||
logger.warning("Could not find the 'Claim Bonus Points' button. There are likely no bonus points to claim at this time.")
|
||||
|
||||
def complete_all_tasks(self):
|
||||
# Each task is run independently. The Rewards UI differs by market and
|
||||
@@ -280,13 +297,19 @@ class RewardsTaskUtils:
|
||||
)
|
||||
|
||||
for name, step in steps:
|
||||
# The tags stay in the message rather than being folded into the
|
||||
# level, they are the per-task outcome summary and reading a run
|
||||
# means scanning for them.
|
||||
try:
|
||||
step()
|
||||
print(f"[OK] {name}")
|
||||
logger.info("[OK] %s", name)
|
||||
except (NoSuchElementException, TimeoutException) as exc:
|
||||
print(f"[SKIP] {name}: not available in this UI variant ({type(exc).__name__})")
|
||||
logger.warning("[SKIP] %s: not available in this UI variant (%s)", name, type(exc).__name__)
|
||||
except Exception as exc:
|
||||
print(f"[FAIL] {name}: {type(exc).__name__}: {exc}")
|
||||
logger.error(
|
||||
"[FAIL] %s: %s: %s", name, type(exc).__name__, log_utils.exception_summary(exc),
|
||||
exc_info=logger.isEnabledFor(logging.DEBUG)
|
||||
)
|
||||
|
||||
# Leave a clean tab state behind for the next task.
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user