Files
rewards-farmer/src/rewards_tasks.py
T

196 lines
6.4 KiB
Python
Raw Normal View History

2026-08-19 14:03:22 -04:00
import os
import random
import time
from typing import Callable
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.common.action_chains import ActionChains
import tab_utils
import llm_utils
import mouse_trajectory
import mimic_typing
import element_selectors
class RewardsTaskUtils:
def __init__(self, driver: webdriver.Edge):
self.driver = driver
self.tab_utils = tab_utils.TabUtils(driver)
self.mouse = mouse_trajectory.MouseUtils(driver)
self.keyboard = mimic_typing.KeyboardUtils(driver)
self.elements = element_selectors.ElementSelectionUtils(driver)
def find_element(self, xpath: str):
return self.driver.find_element(By.XPATH, xpath)
def wait_for_element(self, element_getter: Callable[[], WebElement | list[WebElement]], timeout: int = 10) -> WebElement | list[WebElement]:
def condition(_: webdriver.Edge):
try:
element_or_elements = element_getter()
return element_or_elements
except:
return False
return WebDriverWait(self.driver, timeout).until(condition)
def switch_to_earn_page(self):
self.move_to_and_click(self.elements.get_earn_tab())
def switch_to_dashboard(self):
self.move_to_and_click(self.elements.get_dashboard_tab())
def move_to_and_click(self, elem: WebElement):
self.mouse.move_to_element(elem)
self.mouse.human_like_click()
def wait_for_then_click(self, element_getter: Callable[[], WebElement], timeout: int = 10):
elem = self.wait_for_element(element_getter, timeout)
self.move_to_and_click(elem)
def complete_bing_daily_set(self):
self.switch_to_earn_page()
self.wait_for_then_click(self.elements.get_open_daily_set_button)
daily_set_links = self.wait_for_element(self.elements.get_daily_set_elements)
self.move_to_and_click(daily_set_links[0])
time.sleep(random.uniform(2, 3))
self.driver.switch_to.window(self.driver.current_window_handle) # refocus on the main tab
self.move_to_and_click(daily_set_links[1])
time.sleep(random.uniform(2, 3))
self.driver.switch_to.window(self.driver.current_window_handle)
self.move_to_and_click(daily_set_links[2])
time.sleep(random.uniform(2, 3))
self.driver.switch_to.window(self.driver.current_window_handle)
self.tab_utils.close_all_other_tabs()
def complete_explore_on_bing_tasks(self):
self.switch_to_earn_page()
explore_on_bing_links = self.wait_for_element(self.elements.get_explore_on_bing_elements)
for card in explore_on_bing_links:
desc = self.elements.extract_card_descriptions(card)
query = llm_utils.get_search_query_from_task_description(desc)
self.move_to_and_click(card)
self.tab_utils.switch_to_other_tab()
self.wait_for_element(self.elements.get_bing_search_bar)
# search bar should be auto-focused
self.keyboard.send_keys(query+Keys.ENTER)
time.sleep(random.uniform(2, 3))
self.tab_utils.switch_to_other_tab()
self.tab_utils.close_all_other_tabs()
for card in explore_on_bing_links:
if not self.elements.card_is_complete(card):
2026-08-20 09:28:54 -04:00
print(f"[WARNING] Explore on Bing Card [desc={self.elements.extract_card_descriptions(card)!r}] is not complete after searching. Please check manually.")
2026-08-19 14:03:22 -04:00
def complete_visual_search(self):
self.switch_to_earn_page()
self.wait_for_then_click(self.elements.get_open_visual_search_sidebar)
self.wait_for_then_click(self.elements.get_search_now_link_from_visual_search_sidebar)
self.tab_utils.switch_to_other_tab()
self.mouse.reinitialize()
self.wait_for_then_click(self.elements.get_visual_search_button)
file_input = self.wait_for_element(self.elements.get_visual_search_file_input)
file_input.send_keys(os.path.abspath("keypress_times.png"))
time.sleep(random.uniform(3, 5))
self.tab_utils.switch_to_other_tab()
self.tab_utils.close_all_other_tabs()
self.mouse.reinitialize()
def complete_misc_cards(self):
self.switch_to_earn_page()
misc_cards: list[WebElement] = self.wait_for_element(self.elements.get_all_misc_cards)
for card in misc_cards:
while not self.elements.element_is_fully_in_viewport(card): # this should work for top-down iteration
ActionChains(self.driver).scroll_by_amount(0, 100).perform()
if not self.elements.card_is_complete(card) and self.elements.get_card_point_value(card) > 0:
self.move_to_and_click(card)
time.sleep(random.uniform(1, 2))
self.driver.switch_to.window(self.driver.current_window_handle)
for card in misc_cards:
if not self.elements.card_is_complete(card) and self.elements.get_card_point_value(card) > 0:
2026-08-20 09:28:54 -04:00
print(f"[WARNING] Misc Card [desc={self.elements.extract_card_descriptions(card)!r}] is not complete after clicking. Please check manually.")
2026-08-19 14:03:22 -04:00
self.tab_utils.close_all_other_tabs()
def complete_twenty_searches(self):
self.driver.get("https://www.bing.com/")
search_bar = self.wait_for_element(self.elements.get_bing_search_bar)
# search bar should be auto-focused
for query in llm_utils.get_related_search_queries(
llm_utils.get_random_noun(), num_queries=20
):
self.keyboard.send_keys(query+Keys.ENTER)
time.sleep(random.uniform(2, 3))
# clear search bar for next query
# the 't' can be any character, it just needs to be there to
# auto-focus the search bar so that the backspaces will work
self.keyboard.send_keys('t'+Keys.BACKSPACE*(len(query)+1))
self.driver.get("https://rewards.bing.com/")
self.mouse.reinitialize()
self.switch_to_earn_page()
self.wait_for_then_click(self.elements.get_points_breakdown_button)
close_btn = self.wait_for_element(self.elements.get_close_button_on_points_breakdown)
points_earned, max_pts = self.elements.get_points_earned_from_searches_on_points_breakdown()
self.move_to_and_click(close_btn)
print(f"Points earned from 20 searches: {points_earned}/{max_pts}")
def claim_bonus_points(self):
self.switch_to_dashboard()
self.wait_for_then_click(self.elements.get_bonus_button_on_dashboard)
try:
self.move_to_and_click(self.elements.get_claim_bonus_points_button())
except IndexError:
print("[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):
self.complete_bing_daily_set()
self.complete_explore_on_bing_tasks()
self.complete_visual_search()
self.complete_misc_cards()
self.complete_twenty_searches()
self.claim_bonus_points()