Browse Source

Feat(captcha): Pre-solve captcha

master
Samuel Pua 1 year ago
parent
commit
e6c37327ee
  1. 85
      backend/internal/ktmtrainbot/backgroundbookingjob.go

85
backend/internal/ktmtrainbot/backgroundbookingjob.go

@ -447,23 +447,17 @@ func selectBookingSlot(ctx context.Context, page *rod.Page, timeCode string) *ro
time.Sleep(1000 * time.Millisecond)
}
// Wait for 1215am
if needToWait {
log.Println("Waiting for 1215am")
destinationTime := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 15, 1, 0, time.Now().Location())
needToWaitTimer := time.NewTimer(time.Until(destinationTime))
select {
case <-ctx.Done():
return page
case <-needToWaitTimer.C:
log.Println("1215am reached")
}
}
// Start probing
reportedTicketDetails := false
completed := false
retries := 2
for !completed {
if retries <= 0 {
log.Println("Used up retries. Exiting.")
completed = true
break
}
page.MustWaitLoad()
// Checks for context before proceeding
@ -502,51 +496,82 @@ func selectBookingSlot(ctx context.Context, page *rod.Page, timeCode string) *ro
default:
}
// Wait for 1214am
if needToWait {
log.Println("Waiting for 1214am")
destinationTime := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 14, 0, 0, time.Now().Location())
needToWaitTimer := time.NewTimer(time.Until(destinationTime))
select {
case <-ctx.Done():
return page
case <-needToWaitTimer.C:
log.Println("1214am reached")
}
}
selectButtonElement := rowElement.MustElement("a")
selectButtonElement.Eval(`this.click()`)
page.MustWaitLoad()
time.Sleep(500 * time.Millisecond)
// Check if there is captcha
if strings.Contains(bodyText, "Please complete the reCAPTCHA") {
// Reset Body text
time.Sleep(500 * time.Millisecond)
log.Println("Captcha detected")
currURL := "https://shuttleonline.ktmb.com.my/ShuttleTrip"
// Regex research for Google Captcha V2 API Key
gcaptchaElement := page.MustElement(".g-recaptcha")
googleRecaptchaKey := gcaptchaElement.MustAttribute("data-sitekey")
log.Printf("Google CAPTCHA V2 Key: %s", *googleRecaptchaKey)
captchaAnswer := captchasolver.Provider2CaptchaV2E2E(twoCaptchaAPIKey, currURL, *googleRecaptchaKey)
page.MustElement("#g-recaptcha-response").Eval(`this.innerHTML = "` + captchaAnswer + `"`)
// Wait for 1215am
if needToWait {
log.Println("Waiting for 1215am")
destinationTime := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 15, 1, 0, time.Now().Location())
needToWaitTimer := time.NewTimer(time.Until(destinationTime))
select {
case <-ctx.Done():
return page
case <-needToWaitTimer.C:
log.Println("1215am reached")
}
}
page.Eval(`RecaptchaCallback()`)
}
// Check before exiting
bodyText := page.MustElement("body").MustText()
if strings.Contains(bodyText, "System maintenance scheduled at 23:00 to 00:15 (UTC+8).") {
log.Println("Maintenance modal detected on booking page after captcha")
completed = false
closeModalButton := page.MustElement("#popupModalCloseButton")
closeModalButton.Eval(`this.click()`)
time.Sleep(1000 * time.Millisecond)
retries -= 1
continue
}
// Repeat if there's no seats -- seats might be released later
if strings.Contains(bodyText, "Not enough seat for onward trip") {
log.Println("Not enough seat for onward trip")
completed = false
closeModalButton := page.MustElement("#popupModalCloseButton")
closeModalButton.Eval(`this.click()`)
time.Sleep(1000 * time.Millisecond)
retries -= 1
continue
}
// Check if there is captcha
if strings.Contains(bodyText, "Please complete the reCAPTCHA") {
// Reset Body text
time.Sleep(500 * time.Millisecond)
log.Println("Captcha detected")
currURL := "https://shuttleonline.ktmb.com.my/ShuttleTrip"
// Regex research for Google Captcha V2 API Key
gcaptchaElement := page.MustElement(".g-recaptcha")
googleRecaptchaKey := gcaptchaElement.MustAttribute("data-sitekey")
log.Printf("Google CAPTCHA V2 Key: %s", *googleRecaptchaKey)
captchaAnswer := captchasolver.Provider2CaptchaV2E2E(twoCaptchaAPIKey, currURL, *googleRecaptchaKey)
page.MustElement("#g-recaptcha-response").Eval(`this.innerHTML = "` + captchaAnswer + `"`)
page.Eval(`RecaptchaCallback()`)
}
styleAttribute := selectButtonElement.MustAttribute("style")
if styleAttribute == nil || !strings.Contains(*styleAttribute, "display: none") {
completed = false
@ -555,6 +580,8 @@ func selectBookingSlot(ctx context.Context, page *rod.Page, timeCode string) *ro
completed = true
}
retries -= 1
}
// Checks for context before clicking

Loading…
Cancel
Save