Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
*.pyc
*.pyo
.DS_Store
.Rhistory
chromedriver
chromedriver/
68 changes: 35 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
# KelloggBot
Credit to SeanDaBlack for the basis of the script.

req.py is selenium python bot.
sc.js is a the base of the ios shortcut [COMING SOON]

# Setup

On mac/pc:

`pip install -r requirements.txt`

You will probably need to go get the chrome driver to make selenium work, as they are version-specific. The one in the repo might not do it for you. Find your chrome version by going to **Chrome** >> **About Google Chrome**.

This will open a tab that shows you your verison. Visit https://sites.google.com/chromium.org/driver/downloads and download the driver for your version.

folder. Extract the downloaded zip file. Move the extracted chromedriver binary to this project folder

`mv ~/Downloads/chromedriver .`

It needs to be found in your `PATH` variable.

`export PATH=$PATH:$(pwd)`

`python req.py` to run. It will loop until you kill the job. `ctrl + c` in your terminal to give the pro lifes a break (optional).

mac:

You might also get a trust issue with the downloaded driver being unverified. To fix that, run

`xattr -d com.apple.quarantine chromedriver`

this just tells the OS it's safe to use this driver, and Selenium will start working. See https://timonweb.com/misc/fixing-error-chromedriver-cannot-be-opened-because-the-developer-cannot-be-verified-unable-to-launch-the-chrome-browser-on-mac-os/ for more info.
# KelloggBot
Credit to SeanDaBlack for the basis of the script.

req.py is selenium python bot.
sc.js is a the base of the ios shortcut [COMING SOON]

# Setup

On mac/pc:

`pip install -r requirements.txt`

You will probably need to go get the chrome driver to make selenium work, as they are version-specific. The one in the repo might not do it for you. Find your chrome version by going to **Chrome** >> **About Google Chrome**.

This will open a tab that shows you your verison. Visit https://sites.google.com/chromium.org/driver/downloads and download the driver for your version.

folder. Extract the downloaded zip file. Move the extracted chromedriver binary to this project folder

`mv ~/Downloads/chromedriver .`

It needs to be found in your `PATH` variable.

`export PATH=$PATH:$(pwd)`

`python req.py` to run. It will loop until you kill the job. `ctrl + c` in your terminal to give the pro lifes a break (optional).

mac:

You might also get a trust issue with the downloaded driver being unverified. To fix that, run

`xattr -d com.apple.quarantine chromedriver`

this just tells the OS it's safe to use this driver, and Selenium will start working. See https://timonweb.com/misc/fixing-error-chromedriver-cannot-be-opened-because-the-developer-cannot-be-verified-unable-to-launch-the-chrome-browser-on-mac-os/ for more info.

You will also need to install ffmpeg if it is not already installed: [Mac installation guide](https://superuser.com/a/624562) [Windows installation guide](https://www.wikihow.com/Install-FFmpeg-on-Windows)
3 changes: 3 additions & 0 deletions captchaAudio/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*
*/
!.gitignore
2 changes: 2 additions & 0 deletions constants/classNames.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CAPTCHA_BOX = 'recapBorderAccessible'
AUDIO_ERROR_MESSAGE = 'rc-audiochallenge-error-message'
4 changes: 4 additions & 0 deletions constants/elementIds.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@
RELATIVE_WORKER_LABEL = '227:_select'
ESSENTIAL_FUNCTIONS_LABEL = '231:_select'
GENDER_LABEL = '235:_select'
RECAPTCHA_AUDIO_BUTTON = 'recaptcha-audio-button'
RECAPTCHA_ANCHOR = 'recaptcha-anchor'
AUDIO_SOURCE = 'audio-source'
AUDIO_RESPONSE = 'audio-response'
2 changes: 2 additions & 0 deletions constants/fileNames.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CAPTCHA_MP3_FILENAME = 'captchaAudio/1.mp3'
CAPTCHA_WAV_FILENAME = 'captchaAudio/2.wav'
88 changes: 88 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,113 @@
import requests
import functools
import os
import subprocess
import random
import sys
import time

import speech_recognition as sr
from faker import Faker
from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.keys import Keys

from constants.common import *
from constants.fileNames import *
from constants.classNames import *
from constants.elementIds import *
from constants.email import *
from constants.location import *
from constants.urls import *
from constants.xPaths import *

os.environ["PATH"] += ":/usr/local/bin" # Adds /usr/local/bin to my path which is where my ffmpeg is stored

fake = Faker()
chromedriver_location = CHROMEDRIVER_PATH
# Change default in module for print to flush
# https://stackoverflow.com/questions/230751/how-can-i-flush-the-output-of-the-print-function-unbuffer-python-output#:~:text=Changing%20the%20default%20in%20one%20module%20to%20flush%3DTrue
print = functools.partial(print, flush=True)

r = sr.Recognizer()

def audioToText(mp3Path):
# deletes old file
try:
os.remove(CAPTCHA_WAV_FILENAME)
except FileNotFoundError:
pass
# convert wav to mp3
subprocess.run(f"ffmpeg -i {mp3Path} {CAPTCHA_WAV_FILENAME}", shell=True, timeout=5)

@jmrushing jmrushing Dec 12, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any benefits to using ffmpeg over pydub's AudioSegment? Seems like an extra layer of complexity for the end user (installing ffmpeg & setting up the path) vs 3 lines of code in main.py and 1 in requirements.txt à la #26 .
A better way than both methods would be probably be to save the incoming stream straight to WAV, but my brain is too fried to work that out at the moment.
Also, is checking for the file and deleting necessary before running ffmpeg? Using the solution in #26, sound.export() overwrites the old WAV file during each new iteration. Perhaps ffmpeg can't do that for some reason (permissions?) or needs an additional command flag?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I simply couldn't get pydubs working. I think you are right though saving directly to wav would be best

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also my understanding is that pydubs relies on ffmpeg for conversion anyway

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I wonder if anyone else who's tested with the #26 solution has had issues with pydub? I hope not... 🤦
I didn't mean to give you hard time about ffmpeg, but I've done A LOT of scripting with it in the past. And while it's been...a while...for me, ffmpeg used to have a pretty dodgy reputation for breaking things with their updates, in addition to some nasty security loopholes stemming from outdated libraries. Maybe that's not the case anymore, but it was bad enough just a few years ago that I would regularly have to re-write scripts after updates to account for altered internal default values or implementation differences between distros. That's my unsolicited $0.02 on ffmpeg 😅

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also my understanding is that pydubs relies on ffmpeg for conversion anyway

Well I learned something today. I should have RTFM. Doh!

ffmpeg on its own is still kludgy IMO, maybe that's why I prefer using the pydub wrapper. When I get some time, I'll work out the "clean" solution and hopefully we'll be done with creating multiple audio files.


with sr.AudioFile(CAPTCHA_WAV_FILENAME) as source:
audio_text = r.listen(source)
try:
text = r.recognize_google(audio_text)
print('Converting audio transcripts into text ...')
return(text)
except Exception as e:
print(e)
print('Sorry.. run again...')

def saveFile(content,filename):
with open(filename, "wb") as handle:
for data in content.iter_content():
handle.write(data)
# END TEST

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you remove this


def solveCaptcha(driver):
# Logic to click through the reCaptcha to the Audio Challenge, download the challenge mp3 file, run it through the audioToText function, and send answer
googleClass = driver.find_elements_by_class_name(CAPTCHA_BOX)[0]
time.sleep(2)
outeriframe = googleClass.find_element_by_tag_name('iframe')
time.sleep(1)
outeriframe.click()
time.sleep(2)
allIframesLen = driver.find_elements_by_tag_name('iframe')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"allIFrames" seems like a more accurate name for this variable, unless you want to just save the len() of this directly and skip it on line 71

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you are correct there

time.sleep(1)
audioBtnFound = False
audioBtnIndex = -1
for index in range(len(allIframesLen)):
driver.switch_to.default_content()
iframe = driver.find_elements_by_tag_name('iframe')[index]
driver.switch_to.frame(iframe)
driver.implicitly_wait(2)
try:
audioBtn = driver.find_element_by_id(RECAPTCHA_AUDIO_BUTTON) or driver.find_element_by_id(RECAPTCHA_ANCHOR)
audioBtn.click()
audioBtnFound = True
audioBtnIndex = index
break
except Exception as e:
pass
if audioBtnFound:
try:
while True:
href = driver.find_element_by_id(AUDIO_SOURCE).get_attribute('src')
response = requests.get(href, stream=True)
saveFile(response, CAPTCHA_MP3_FILENAME)
response = audioToText(CAPTCHA_MP3_FILENAME)
print(response)
driver.switch_to.default_content()
iframe = driver.find_elements_by_tag_name('iframe')[audioBtnIndex]
driver.switch_to.frame(iframe)
inputbtn = driver.find_element_by_id(AUDIO_RESPONSE)
inputbtn.send_keys(response)
inputbtn.send_keys(Keys.ENTER)
time.sleep(2)
errorMsg = driver.find_elements_by_class_name(AUDIO_ERROR_MESSAGE)[0]
if errorMsg.text == "" or errorMsg.value_of_css_property('display') == 'none':
print("reCaptcha defeated!")
break
except Exception as e:
print(e)
print('Oops, something happened. Check above this message for errors or check the chrome window to see if captcha locked you out...')
else:
print('Button not found. This should not happen.')

time.sleep(2)
driver.switch_to.default_content()

def start_driver(random_city):
driver = webdriver.Chrome(chromedriver_location)
Expand Down Expand Up @@ -66,6 +153,7 @@ def generate_account(driver):
time.sleep(1.5)
driver.find_element_by_xpath(ACCEPT_BUTTON).click()
time.sleep(2)
solveCaptcha(driver)
driver.find_element_by_xpath(CREATE_ACCOUNT_BUTTON).click()
time.sleep(1.5)

Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ idna==3.2
requests==2.26.0
selenium==3.141.0
urllib3==1.26.6
Faker==9.9.1
Faker==9.9.1
speechrecognition==3.8.1