From 3fc7d371a93914ea6f639a6cce018bd62ac7d927 Mon Sep 17 00:00:00 2001 From: ForgedCore8 <77468737+ForgedCore8@users.noreply.github.com> Date: Thu, 26 Oct 2023 18:11:21 -0500 Subject: [PATCH] Add files via upload --- Happymeal.ico | Bin 0 -> 97516 bytes main.py | 418 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 418 insertions(+) create mode 100644 Happymeal.ico create mode 100644 main.py diff --git a/Happymeal.ico b/Happymeal.ico new file mode 100644 index 0000000000000000000000000000000000000000..6631c7f19efff5501919311fcd8a53547f290537 GIT binary patch literal 97516 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 current + + +def check_and_create_config(): + """Create the config file with default values if it doesn't exist.""" + if not os.path.exists(os.path.join(cwd, "config.txt")): + with open("config.txt", "w") as file: + default_config = """ +date=mm/dd # The date being used for the orders. e.g. 12/25 would be Christmas day. +store_number=12345 # this is the number of your mcdonalds store +ks_number=01 # This is the number of the till +auto=False # This determines if HappyMeal generates random orders or uses real orders, Overrites date field Accepts True/False (case sensitive) +""" + file.write(default_config.strip()) + print("please edit config.txt") + quit() + + +def read_config(): + config = {} + with open("config.txt", "r") as file: + lines = file.readlines() + for line in lines: + stripped_line = line.split("#")[ + 0 + ].strip() # Split by '#' and take the first part, then strip whitespace + if not stripped_line: # skip empty lines or full comment lines + continue + key, value = stripped_line.split("=") + config[key.strip()] = value.strip() + return config + + +# Initialize webdriver +def get_webdriver(): + chrome_options = webdriver.ChromeOptions() + # chrome_options.add_argument("--headless") + return webdriver.Chrome(options=chrome_options) + + +def validate_input(prompt, pattern, error_message): + while True: + user_input = input(prompt) + if re.match(pattern, user_input): + return user_input + else: + print(Fore.RED + error_message) + + +def safe_click(elem_id, retries=3, delay=2): + for attempt in range(retries): + try: + # Wait until the element is present + WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, elem_id))) + element = driver.find_element(By.ID, elem_id) + # Try clicking using JavaScript + driver.execute_script("arguments[0].click();", element) + + return # If clicked successfully, exit the function + + except (ElementClickInterceptedException, ElementNotInteractableException) as e: + + element.click() + return + + except NoSuchElementException: + if attempt < retries - 1: # if it's not the last retry + # time.sleep(delay) # wait for some time before next retry + continue + else: + print(f"Element with ID {elem_id} does not exist on the page.") + return + + except Exception as e: + print(f"Error clicking on element with ID {elem_id}: {str(e)}") + if attempt < retries - 1: # if it's not the last retry + time.sleep(delay) # wait for some time before next retry + else: + return + + +def click_elements_with_pattern(): + elements = driver.find_elements(By.CSS_SELECTOR, '[id^="R"][id$=".5"]') + for elem in elements: + safe_click(elem.get_attribute("id")) + + +def download_from_github(): + """Download the latest reviews.json from GitHub.""" + print("Getting latest review list") + url = "https://raw.githubusercontent.com/ForgedCore8/happymeal/main/reviews.json" + response = requests.get(url) + with open(os.path.join(cwd, "reviews.json"), "wb") as f: + f.write(response.content) + + +def is_checksum_different(): + """Check if local reviews.json checksum is different from GitHub's.""" + url = "https://raw.githubusercontent.com/ForgedCore8/happymeal/main/reviews.json" + response = requests.get(url) + + # Generate checksum for the GitHub version + github_checksum = hashlib.md5(response.content).hexdigest() + + # Generate checksum for the local version + with open(os.path.join(cwd, "reviews.json"), "rb") as f: + local_checksum = hashlib.md5(f.read()).hexdigest() + + return github_checksum != local_checksum + + +def load_reviews(): + """ + Load reviews from reviews.json. If it doesn't exist, or is different from the GitHub version, download it. + """ + try: + # Check if local file exists and if its checksum is different from the GitHub version + if ( + not os.path.exists(os.path.join(cwd, "reviews.json")) + or is_checksum_different() + ): + download_from_github() + + # Now, read the reviews from the local file + with open(os.path.join(cwd, "reviews.json"), "r") as f: + data = json.load(f) + + general_reviews = data["reviews"]["general"] + breakfast_reviews = data["reviews"]["breakfast"] + lunch_reviews = data["reviews"]["lunch"] + + return general_reviews, breakfast_reviews, lunch_reviews + + except Exception as e: + print(f"An error occurred: {e}") + # Return empty lists in case of an error + return [], [], [] + + +def select_meal_time(hour): + if int(hour) > 11: + safe_click("R000505") + else: + safe_click("R000504") + safe_click("NextButton") + + +def fill_initial_data(config): + + driver.get("https://www.mcdvoice.com/Index.aspx?POSType=PieceMeal") + WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.ID, "InputStoreID")) + ) + driver.find_element(By.ID, "InputStoreID").send_keys(config["store_number"]) + driver.find_element(By.ID, "InputRegisterNum").send_keys(config["ks_number"]) + global hour, transaction_number + global completed_surveys, surveys_target + if config["auto"] == "False": + + date_input = config["date"] + month, day = date_input.split("/") + time_input = validate_input( + "Enter the time in HH:MM format: ", + "^([0-9]|1[0-9]|2[0-3]):[0-5][0-9]$", + "Incorrect time format. Please provide HH:MM.", + ) + + hour, minute = time_input.split(":") + transaction_number = validate_input( + "Enter the 4-digit transaction number: ", + "^\d{4}$", + "Invalid transaction number. Please provide a 4-digit number.", + ) + + amount_spent = validate_input( + "Enter the amount spent in dollars.cents format: ", + "^\d+\.\d{2}$", + "Invalid amount format. Please provide dollars.cents format.", + ) + dollars, cents = amount_spent.split(".") + + + elif config["auto"] == "True": + month = str(datetime.now().month) + current_date = datetime.today() + day_of_month = current_date.day + selected_day = day_of_month - random.randint(0, 5) + # If the selected_day is negative or zero (possible if today's date is in the first 5 days of the month) + if selected_day <= 0: + prev_month_last_date = datetime.current_date.replace( + day=1 + ) - datetime.timedelta(days=1) + selected_day += prev_month_last_date.day + day = str(selected_day) + hour = str(random.randint(5, 11)) + minute = str(random.randint(0, 59)) + ks_number = config["ks_number"] + order_num = str(random.randint(0, 99)) + transaction_number = f"{ks_number}{order_num:02}" + dollars = str(random.randint(1, 30)) + cents = str(random.randint(8, 99)) + + Select(driver.find_element(By.ID, "InputMonth")).select_by_value(month) + Select(driver.find_element(By.ID, "InputDay")).select_by_value(day) + Select(driver.find_element(By.ID, "InputHour")).select_by_value(hour.zfill(2)) + Select(driver.find_element(By.ID, "InputMinute")).select_by_value(minute.zfill(2)) + driver.find_element(By.ID, "InputTransactionNum").send_keys(transaction_number) + driver.find_element(By.ID, "AmountSpent1").send_keys(dollars) + driver.find_element(By.ID, "AmountSpent2").send_keys(cents) + print("Working...") + safe_click("NextButton") + + +def save_to_file(order_number, validation_code): + with open(os.path.join(cwd, "validation_codes.txt"), "a") as file: + file.write(f"Order number {order_number} - {validation_code}\n") + global completed_surveys + completed_surveys += 1 + + +def submit_review(): + if int(hour) < 11: + selected_category = random.choice([breakfast, general]) + else: + selected_category = random.choice([lunch, general]) + # Choose a random review from the selected category + selected_review = random.choice(selected_category) + safe_click("S081000") + driver.find_element(By.ID, "S081000").send_keys(selected_review) + print(f"review chosen: {selected_review}") + print("Working...") + safe_click("NextButton") + + +def get_validation_code(): + WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.CLASS_NAME, "ValCode")) + ) + validation_code_element = driver.find_element(By.CLASS_NAME, "ValCode") + validation_code = validation_code_element.text + print(f"\r{validation_code}") + save_to_file(transaction_number, validation_code) + +def detect_opt(): + # Try to find the specific survey container segment. + try: + driver.find_element(By.ID, "FNSBlock9500") + + # If found, safe click the NextButton + safe_click("NextButton") + except NoSuchElementException: + print("Specific survey HTML not found. Ignoring...") + return + +def survey(driver): + global general, breakfast, lunch, completed_surveys, surveys_target + + + try: + general, breakfast, lunch = load_reviews() + + fill_initial_data(config) + + # List of IDs to safe click + ids_to_click = [ + "R000060.1", + "R000455.1", + "R004000.2", + "R001000.5", + "R000444.1", + "R000473.1", + "R000474.1", + ] + for elem_id in ids_to_click: + safe_click(elem_id) + safe_click("NextButton") + + click_elements_with_pattern() + safe_click("NextButton") + + click_elements_with_pattern() + safe_click("NextButton") + + select_meal_time(hour) + + safe_click("NextButton") + safe_click("R016000.2") + safe_click("NextButton") + + click_elements_with_pattern() + safe_click("NextButton") + + submit_review() + + ids_to_click_end = ["R000026.2", "R020000.2", "R000387.4", "R000482.5"] + for elem_id in ids_to_click_end: + safe_click(elem_id) + safe_click("NextButton") + + detect_opt() + get_validation_code() + + except Exception as e: + # Get the current traceback information + tb_info = traceback.extract_tb(e.__traceback__)[-1] + file_name = tb_info.filename + line_no = tb_info.lineno + + print(f"Unexpected error occurred in {file_name} at line {line_no}: {e}") + driver.quit() + + + +if __name__ == "__main__": + os.system("cls" if os.name == "nt" else "clear") + latest_version = get_latest_release() + if latest_version and is_newer_version(version, latest_version): + print("A newer version is availible!") + logo() + check_and_create_config() + config = read_config() + driver = get_webdriver() + try: + if config["auto"] == "False": + while True: + os.system("cls") + logo() + survey(driver) # survey will return False if interrupted + elif config["auto"] == "True": + if surveys_target is None or surveys_target == 0: + surveys_target = int(input("How many Surveys would you like completed? : ")) + while completed_surveys < surveys_target: + print(f"Survey Number: {completed_surveys + 1}") + survey(driver) # If survey returns False, we ret + except KeyboardInterrupt: + print("\nKeyboardInterrupt caught. Cleaning up...") + finally: + driver.quit() + # result = subprocess.run(["taskkill", "/F", "/IM", "chromedriver.exe", "/T"], capture_output=True, text=True) + # time.sleep(1) + # result = subprocess.run(["taskkill", "/F", "/IM", "chrome.exe", "/T"], capture_output=True, text=True) + # print("Finished flushing chrome processes, exiting in 5 seconds...") + # time.sleep(5) + quit() +