|
|
@ -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
|
|
|
|