Auto detect fields instead of manual labor
This commit is contained in:
+12
-46
@@ -6,56 +6,22 @@ userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML
|
||||
|
||||
# Global credentials to be used for any site that doesn't have its own specific credentials.
|
||||
[global_credentials]
|
||||
username = "pikzuigendemetalhead"
|
||||
email = "florianwkristallis@gmail.com"
|
||||
password = "FlorianhoudvanPIEMELS"
|
||||
username = "Thisisgebruikersnaam"
|
||||
email = "thisisanothertestbusiness@hotmail.com"
|
||||
password = "Fuckingstrongpassword123!"
|
||||
phone = "+31610488717"
|
||||
firstName = "Thisfirstname"
|
||||
lastName = "Thislastname"
|
||||
|
||||
[[sites]]
|
||||
name = "CameraBoys"
|
||||
category = "Social" # New category field
|
||||
url = "https://www.cameraboys.com/en/auth/sign-up"
|
||||
needsPreSubmitAction = true
|
||||
|
||||
# You can now paste the entire HTML element here.
|
||||
[sites.locators]
|
||||
username = '<input class="form-input" type="text" placeholder="Username" name="username">'
|
||||
password = '<input class="form-input" type="password" placeholder="Password" name="password">'
|
||||
email = '<input class="form-input" type="text" placeholder="Email" name="email">'
|
||||
submit = '<button type="submit" class="form-submit btn form-label">'
|
||||
|
||||
[[sites]]
|
||||
url = "https://pro.gaynetwork.com/en/compte/authentification"
|
||||
name = "Dutch News Test"
|
||||
category = "Newsletter"
|
||||
url = "https://www.dutchnews.nl/dutchnews-newsletter-signup/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email" class="form-control" placeholder="Email" name="login[email]" value="" autocomplete="current-username" required="">'
|
||||
password = '<input type="password" class="form-control" placeholder="Password" name="login[password]" value="" autocomplete="current-password" required="">'
|
||||
submit = '<button type="submit" class="btn btn-block btn-primary" name="fn_login">Login</button>'
|
||||
# autoDetect is enabled by default
|
||||
|
||||
[[sites]]
|
||||
url = "https://www.queermenow.net/blog/signup-for-free-gay-porn-news/"
|
||||
name = "Immaculate Vegan"
|
||||
category = "Newsletter"
|
||||
url = "https://immaculatevegan.com/blogs/magazine"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input id="23510" class="required email" style="width: 100%;" maxlength="4000" name="23510" type="text">'
|
||||
email = '<input id="confirmEmail" class="email required" style="width: 100%;" name="confirmEmail" type="text">'
|
||||
submit = '<input id="SubmitButton" class="btnStyle" style="background-color: #465d9b; color: white;" name="SubmitButton" type="submit" value="Join free list">'
|
||||
|
||||
[[sites]]
|
||||
url = "https://justthegays.tv/register"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
username = '<input type="text" required="" class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500">'
|
||||
email = '<input type="email" required="" class="text-gray-700 mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500">'
|
||||
password = '<input type="password" required="" class="text-gray-700 mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500">'
|
||||
|
||||
[[sites]]
|
||||
url = "https://www.casinonyc.info/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input id="email-yui_3_17_2_1_1704040106050_24491-field" class="newsletter-form-field-element field-element" name="email" x-autocompletetype="email" autocomplete="email" type="email" spellcheck="false" placeholder="Email Address">'
|
||||
submit = '<span class="newsletter-form-button-label">Sumbit</span>'
|
||||
|
||||
|
||||
+750
@@ -0,0 +1,750 @@
|
||||
# Configuration file for the multi-site sign-up script.
|
||||
|
||||
[browser]
|
||||
userDataDir = "/home/someone/.config/chromium"
|
||||
userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
|
||||
|
||||
# Global credentials to be used for any site that doesn't have its own specific credentials.
|
||||
[global_credentials]
|
||||
username = "pikzuigendemetalhead"
|
||||
email = "florianwkristallis@gmail.com"
|
||||
password = "FlorianhoudvanPIEMELS"
|
||||
phone = "+31610488717"
|
||||
|
||||
[[sites]]
|
||||
name = "CameraBoys"
|
||||
category = "Social" # New category field
|
||||
url = "https://www.cameraboys.com/en/auth/sign-up"
|
||||
needsPreSubmitAction = true
|
||||
|
||||
# You can now paste the entire HTML element here.
|
||||
[sites.locators]
|
||||
username = '<input class="form-input" type="text" placeholder="Username" name="username">'
|
||||
password = '<input class="form-input" type="password" placeholder="Password" name="password">'
|
||||
email = '<input class="form-input" type="text" placeholder="Email" name="email">'
|
||||
submit = '<button type="submit" class="form-submit btn form-label">'
|
||||
|
||||
[[sites]]
|
||||
url = "https://pro.gaynetwork.com/en/compte/authentification"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email" class="form-control" placeholder="Email" name="login[email]" value="" autocomplete="current-username" required="">'
|
||||
password = '<input type="password" class="form-control" placeholder="Password" name="login[password]" value="" autocomplete="current-password" required="">'
|
||||
submit = '<button type="submit" class="btn btn-block btn-primary" name="fn_login">Login</button>'
|
||||
|
||||
[[sites]]
|
||||
url = "https://www.queermenow.net/blog/signup-for-free-gay-porn-news/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input id="23510" class="required email" style="width: 100%;" maxlength="4000" name="23510" type="text">'
|
||||
confirmEmail = '<input id="confirmEmail" class="email required" style="width: 100%;" name="confirmEmail" type="text">'
|
||||
submit = '<input id="SubmitButton" class="btnStyle" style="background-color: #465d9b; color: white;" name="SubmitButton" type="submit" value="Join free list">'
|
||||
|
||||
[[sites]]
|
||||
url = "https://justthegays.tv/register"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
username = '<input type="text" required="" class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500">'
|
||||
email = '<input type="email" required="" class="text-gray-700 mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500">'
|
||||
password = '<input type="password" required="" class="text-gray-700 mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500">'
|
||||
|
||||
[[sites]]
|
||||
url = "https://www.casinonyc.info/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input id="email-yui_3_17_2_1_1704040106050_24491-field" class="newsletter-form-field-element field-element" name="email" x-autocompletetype="email" autocomplete="email" type="email" spellcheck="false" placeholder="Email Address">'
|
||||
submit = '<span class="newsletter-form-button-label">Sumbit</span>'
|
||||
|
||||
|
||||
# Sites from email_subscription.json
|
||||
[[sites]]
|
||||
name = "USA Today Sports"
|
||||
category = "Newsletter"
|
||||
url = "https://profile.usatoday.com/newsletters/sports"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input id="email">'
|
||||
submit = '<button class="primary">'
|
||||
|
||||
[[sites]]
|
||||
name = "Uptain"
|
||||
category = "Newsletter"
|
||||
url = "https://uptain.de/en/blog/how-online-shops-generate-newsletter-subscribers"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="wpforms[fields][1]">'
|
||||
submit = '<button name="wpforms[submit]">'
|
||||
|
||||
[[sites]]
|
||||
name = "Finnish Design Shop"
|
||||
category = "Newsletter"
|
||||
url = "https://www.finnishdesignshop.com/en-us/newsletters"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="newsletter-ajax-submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "The Cut"
|
||||
category = "Newsletter"
|
||||
url = "https://www.thecut.com/promo/cut-shop-newsletter-sign-up.html"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Sign up">'
|
||||
|
||||
[[sites]]
|
||||
name = "Uniqlo"
|
||||
category = "Newsletter"
|
||||
url = "https://www.uniqlo.com/sg/en/member/e-news/subscription"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="subscribe">'
|
||||
submit = '<button class="primary">'
|
||||
|
||||
[[sites]]
|
||||
name = "Defi Times"
|
||||
category = "Newsletter"
|
||||
url = "https://newsletter.defitimes.io/about"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="subscribe-btn">'
|
||||
|
||||
[[sites]]
|
||||
name = "NoCode Landscape"
|
||||
category = "Newsletter"
|
||||
url = "https://nocodelandscape.beehiiv.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "Space Known"
|
||||
category = "Newsletter"
|
||||
url = "https://newsletter.spaceknown.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "Oh My Rockness"
|
||||
category = "Newsletter"
|
||||
url = "https://www.ohmyrockness.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Sign Up >">'
|
||||
|
||||
[[sites]]
|
||||
name = "Axios Pro Rata"
|
||||
category = "Newsletter"
|
||||
url = "https://www.axios.com/signup/pro-rata"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "Sales Stoic"
|
||||
category = "Newsletter"
|
||||
url = "https://salesstoic.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Start crushing it in sales...">'
|
||||
|
||||
[[sites]]
|
||||
name = "Fastlane Fleet"
|
||||
category = "Newsletter"
|
||||
url = "https://fastlane-fleet.beehiiv.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = """<button value="Don't miss out on the ride of a lifetime!">"""
|
||||
|
||||
[[sites]]
|
||||
name = "Geekout Matt Navarra"
|
||||
category = "Newsletter"
|
||||
url = "https://geekout.mattnavarra.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = """<button value="Subscribe (It's free!)">"""
|
||||
|
||||
[[sites]]
|
||||
name = "Humans in the Loop"
|
||||
category = "Newsletter"
|
||||
url = "https://thehumansintheloop.substack.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="subscribe-btn">'
|
||||
|
||||
[[sites]]
|
||||
name = "Better Stack"
|
||||
category = "Newsletter"
|
||||
url = "https://newsletter.betterstack.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="subscribe-btn">'
|
||||
|
||||
[[sites]]
|
||||
name = "Unconventional Empires"
|
||||
category = "Newsletter"
|
||||
url = "https://unconventional-empires.beehiiv.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Join Us! ">'
|
||||
|
||||
[[sites]]
|
||||
name = "DotNet News"
|
||||
category = "Newsletter"
|
||||
url = "https://dotnetnews.co/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="EMAIL">'
|
||||
submit = '<button class="js-submit-button">'
|
||||
|
||||
[[sites]]
|
||||
name = "Substack"
|
||||
category = "Newsletter"
|
||||
url = "https://substack.com/signup"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="primary">'
|
||||
|
||||
[[sites]]
|
||||
name = "AI Did That"
|
||||
category = "Newsletter"
|
||||
url = "https://www.aididthat.com/subscribe"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "Dhara B"
|
||||
category = "Newsletter"
|
||||
url = "https://dharab.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="EMAIL">'
|
||||
submit = '<button name="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Pale Ale Travel"
|
||||
category = "Newsletter"
|
||||
url = "https://palealetravel.beehiiv.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "7x7"
|
||||
category = "Newsletter"
|
||||
url = "https://7x7.news/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="subscribe-btn">'
|
||||
|
||||
[[sites]]
|
||||
name = "Astukari"
|
||||
category = "Newsletter"
|
||||
url = "https://astukari.substack.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="subscribe-btn">'
|
||||
|
||||
[[sites]]
|
||||
name = "JBR Works"
|
||||
category = "Newsletter"
|
||||
url = "https://jbrworks.substack.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="subscribe-btn">'
|
||||
|
||||
[[sites]]
|
||||
name = "Web Tools Weekly"
|
||||
category = "Newsletter"
|
||||
url = "https://webtoolsweekly.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="EMAIL">'
|
||||
submit = '<button name="subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "Tech Productivity"
|
||||
category = "Newsletter"
|
||||
url = "https://techproductivity.co"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="EMAIL">'
|
||||
submit = '<button name="subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "VS Code Email"
|
||||
category = "Newsletter"
|
||||
url = "https://vscode.email"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="EMAIL">'
|
||||
submit = '<button name="subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "Standard Hoy"
|
||||
category = "Newsletter"
|
||||
url = "https://standardhoy.substack.com"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="subscribe-btn">'
|
||||
|
||||
[[sites]]
|
||||
name = "Badger and Yote"
|
||||
category = "Newsletter"
|
||||
url = "https://www.badgerandyote.com"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "Insights Innovation Econ"
|
||||
category = "Newsletter"
|
||||
url = "https://insightsinnovationecon.substack.com"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="subscribe-btn">'
|
||||
|
||||
[[sites]]
|
||||
name = "Kapansrt"
|
||||
category = "Newsletter"
|
||||
url = "https://kapansrt.substack.com"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="subscribe-btn">'
|
||||
|
||||
[[sites]]
|
||||
name = "The Donut"
|
||||
category = "Newsletter"
|
||||
url = "https://thedonut.co/news-personality-quiz/results/?medium=email&interests=world"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="emailAddress">'
|
||||
submit = '<button class="NewsQuizSubscribeBar-module--button--c5311">'
|
||||
|
||||
[[sites]]
|
||||
name = "Coin Brain"
|
||||
category = "Newsletter"
|
||||
url = "https://coinbrain.beehiiv.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "Inside Small Giants"
|
||||
category = "Newsletter"
|
||||
url = "https://www.insidesmallgiants.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="subscribe-btn">'
|
||||
|
||||
[[sites]]
|
||||
name = "De Ascentis"
|
||||
category = "Newsletter"
|
||||
url = "https://deascentiis.substack.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="subscribe-btn">'
|
||||
|
||||
[[sites]]
|
||||
name = "Attn Seek"
|
||||
category = "Newsletter"
|
||||
url = "https://www.attnseek.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "The Core Daily"
|
||||
category = "Newsletter"
|
||||
url = "https://daily.thecore.email/subscribe"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value=" Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "World of AI"
|
||||
category = "Newsletter"
|
||||
url = "https://worldofai.beehiiv.com?ref=amazingnewsletters.com&utm_source=amazingnewsletters.com"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "The Baseline"
|
||||
category = "Newsletter"
|
||||
url = "https://the-baseline.beehiiv.com/?ref=amazingnewsletters.com&utm_source=amazingnewsletters.com"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "This Week in React"
|
||||
category = "Newsletter"
|
||||
url = "https://thisweekinreact.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email_address">'
|
||||
submit = '<button class="formkit-submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "LinkedIn Prompts"
|
||||
category = "Newsletter"
|
||||
url = "https://linkedinprompts.beehiiv.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "For Starters"
|
||||
category = "Newsletter"
|
||||
url = "https://www.forstarters.co/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "The Atlantic"
|
||||
category = "Newsletter"
|
||||
url = "https://www.theatlantic.com/newsletters/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button class="NewslettersSignupBar_button__H1vw5">'
|
||||
|
||||
[[sites]]
|
||||
name = "Forbes"
|
||||
category = "Newsletter"
|
||||
url = "https://account.forbes.com/newsletters"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input class="email">'
|
||||
submit = '<button class="subscribe-button">'
|
||||
|
||||
[[sites]]
|
||||
name = "Keyence"
|
||||
category = "Newsletter"
|
||||
url = "https://www.keyence.com.sg/enews/subscribe/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="enewsEmailAddress">'
|
||||
submit = '<button name="subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "UN News"
|
||||
category = "Newsletter"
|
||||
url = "https://news.un.org/en/content/un-newsletter-subscribe"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="EMAIL">'
|
||||
submit = '<button name="subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "Brugg Pipes"
|
||||
category = "Newsletter"
|
||||
url = "https://www.bruggpipes.com/en/newsletter-sign-up/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="tx_powermail_pi1[field][e_mail]">'
|
||||
submit = '<button value="Subscribe">'
|
||||
|
||||
[[sites]]
|
||||
name = "NUS News"
|
||||
category = "Newsletter"
|
||||
url = "https://news.nus.edu.sg/subscribe-to-email-newsletter/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input name="email">'
|
||||
submit = '<button id="submit_button-ppmail">'
|
||||
|
||||
# Sites from list.txt
|
||||
[[sites]]
|
||||
name = "Immunate Vegan"
|
||||
category = "Newsletter"
|
||||
url = "https://immaculatevegan.com/blogs/magazine"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Gate6"
|
||||
category = "Newsletter"
|
||||
url = "https://gate6.vn/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Sprintzeal"
|
||||
category = "Newsletter"
|
||||
url = "https://www.sprintzeal.com/blog"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Kulala Land"
|
||||
category = "Newsletter"
|
||||
url = "https://kulalaland.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Go Places"
|
||||
category = "Newsletter"
|
||||
url = "https://www.goplaces.co.uk/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "FiftyFifty Bottles"
|
||||
category = "Newsletter"
|
||||
url = "https://www.fiftyfiftybottles.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Jubina"
|
||||
category = "Newsletter"
|
||||
url = "https://jubina.com/blog"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Sneaky Whole Foods"
|
||||
category = "Newsletter"
|
||||
url = "https://www.sneakywholefoods.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Veg News"
|
||||
category = "Newsletter"
|
||||
url = "https://vegnews.com/signup"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Yona Yona Beer Works"
|
||||
category = "Newsletter"
|
||||
url = "https://yonayonabeerworks.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Louis Powersports"
|
||||
category = "Newsletter"
|
||||
url = "https://www.louispowersportsonline.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Hairworthy"
|
||||
category = "Newsletter"
|
||||
url = "https://www.hairworthy.co.uk/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Endota Spa"
|
||||
category = "Newsletter"
|
||||
url = "https://endotaspa.com.au/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Prestigify"
|
||||
category = "Newsletter"
|
||||
url = "https://prestigify.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "No Bones"
|
||||
category = "Newsletter"
|
||||
url = "https://nobones.co/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Sofamania"
|
||||
category = "Newsletter"
|
||||
url = "https://www.sofamania.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Dimora Delle Balze"
|
||||
category = "Newsletter"
|
||||
url = "https://dimoradellebalze.com/en/restaurant/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "42 Photo"
|
||||
category = "Newsletter"
|
||||
url = "https://www.42photo.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "I Finished My Basement"
|
||||
category = "Newsletter"
|
||||
url = "https://ifinishedmybasement.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Tettix Games"
|
||||
category = "Newsletter"
|
||||
url = "https://tettixgames.com/"
|
||||
needsPreSubmitAction = false
|
||||
|
||||
[sites.locators]
|
||||
email = '<input type="email">'
|
||||
submit = '<button type="submit">'
|
||||
|
||||
[[sites]]
|
||||
name = "Dutch News Test"
|
||||
category = "Newsletter"
|
||||
url = "https://www.dutchnews.nl/dutchnews-newsletter-signup/"
|
||||
needsPreSubmitAction = false
|
||||
# No locators needed - auto-detection will handle it!
|
||||
@@ -5,7 +5,87 @@ const puppeteer = require('puppeteer-extra');
|
||||
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
|
||||
puppeteer.use(StealthPlugin());
|
||||
|
||||
// --- Helper Functions ---
|
||||
const FIELD_PATTERNS = {
|
||||
email: {
|
||||
priority: 1,
|
||||
types: ['email'],
|
||||
names: ['email', 'e-mail', 'mail', 'user_email', 'login_email', 'email_address', 'emailaddress'],
|
||||
ids: ['email', 'e-mail', 'mail', 'user-email', 'login-email'],
|
||||
placeholders: ['email', 'e-mail', 'email address', 'your email', 'enter email'],
|
||||
autocomplete: ['email']
|
||||
},
|
||||
confirmEmail: {
|
||||
priority: 2,
|
||||
types: ['email'],
|
||||
names: ['confirm_email', 'confirmemail', 'email_confirm', 'verify_email', 'email_verify'],
|
||||
ids: ['confirm-email', 'confirmemail', 'verify-email', 'email-confirm'],
|
||||
placeholders: ['confirm email', 'verify email', 're-enter email', 'repeat email'],
|
||||
mustHaveConfirmIndicator: true
|
||||
},
|
||||
firstName: {
|
||||
priority: 3,
|
||||
types: ['text'],
|
||||
names: ['first_name', 'firstname', 'fname', 'first-name', 'vorname', 'prenom', 'fname'],
|
||||
ids: ['first-name', 'firstname', 'fname', 'firstName', 'mce-fname'],
|
||||
placeholders: ['first name', 'firstname', 'first'],
|
||||
autocomplete: ['given-name', 'first-name']
|
||||
},
|
||||
lastName: {
|
||||
priority: 4,
|
||||
types: ['text'],
|
||||
names: ['last_name', 'lastname', 'lname', 'surname', 'family_name', 'last-name', 'lname'],
|
||||
ids: ['last-name', 'lastname', 'lname', 'surname', 'lastName', 'mce-lname'],
|
||||
placeholders: ['last name', 'lastname', 'surname', 'last'],
|
||||
autocomplete: ['family-name', 'last-name']
|
||||
},
|
||||
username: {
|
||||
priority: 5,
|
||||
types: ['text'],
|
||||
names: ['username', 'user_name', 'login', 'usr', 'uname', 'user-id', 'userid', 'account_name', 'login_id'],
|
||||
ids: ['username', 'user-name', 'login', 'usr', 'uname'],
|
||||
placeholders: ['username', 'user name', 'login', 'username or email'],
|
||||
autocomplete: ['username']
|
||||
},
|
||||
password: {
|
||||
priority: 6,
|
||||
types: ['password'],
|
||||
names: ['password', 'pass', 'pwd', 'user_password', 'login_password'],
|
||||
ids: ['password', 'pass', 'pwd'],
|
||||
placeholders: ['password', 'pass', 'enter password'],
|
||||
autocomplete: ['current-password', 'new-password']
|
||||
},
|
||||
fullName: {
|
||||
priority: 7,
|
||||
types: ['text'],
|
||||
names: ['full_name', 'fullname', 'name'],
|
||||
ids: ['full-name', 'fullname', 'name'],
|
||||
placeholders: ['full name', 'your name', 'complete name'],
|
||||
autocomplete: ['name']
|
||||
},
|
||||
phone: {
|
||||
priority: 8,
|
||||
types: ['tel', 'text'],
|
||||
names: ['phone', 'telephone', 'mobile', 'cell', 'cellphone', 'phone_number'],
|
||||
ids: ['phone', 'telephone', 'mobile', 'cell', 'tel'],
|
||||
placeholders: ['phone', 'telephone', 'mobile number'],
|
||||
autocomplete: ['tel']
|
||||
},
|
||||
age: {
|
||||
priority: 9,
|
||||
types: ['number', 'text'],
|
||||
names: ['age', 'user_age'],
|
||||
ids: ['age'],
|
||||
placeholders: ['age', 'your age']
|
||||
},
|
||||
company: {
|
||||
priority: 10,
|
||||
types: ['text'],
|
||||
names: ['company', 'organization', 'company_name', 'employer'],
|
||||
ids: ['company', 'organization', 'employer'],
|
||||
placeholders: ['company', 'organization'],
|
||||
autocomplete: ['organization']
|
||||
}
|
||||
};
|
||||
|
||||
function loadConfig() {
|
||||
try {
|
||||
@@ -25,20 +105,18 @@ function generateRandomData() {
|
||||
const username = `user${randomString}`;
|
||||
const email = `${username}@gmail.com`;
|
||||
const password = `pass${randomString}`;
|
||||
const age = Math.floor(Math.random() * 30 + 20).toString(); // Random age between 20-49
|
||||
return { username, email, password, age };
|
||||
const age = Math.floor(Math.random() * 30 + 20).toString();
|
||||
const firstName = 'John';
|
||||
const lastName = 'Doe';
|
||||
const phone = '+31610488717';
|
||||
const company = 'Example Corp';
|
||||
return { username, email, password, age, firstName, lastName, phone, company };
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a locator string. If it's an HTML snippet, it generates a CSS selector.
|
||||
* If it's already a selector, it returns it as is.
|
||||
* @param {string} locatorStr - The locator string from the config.
|
||||
* @returns {string} A CSS selector.
|
||||
*/
|
||||
function parseLocator(locatorStr) {
|
||||
locatorStr = locatorStr.trim();
|
||||
if (!locatorStr.startsWith('<')) {
|
||||
return locatorStr; // It's already a selector
|
||||
return locatorStr;
|
||||
}
|
||||
|
||||
const getAttr = (attr) => {
|
||||
@@ -48,9 +126,8 @@ function parseLocator(locatorStr) {
|
||||
|
||||
const tagName = (locatorStr.match(/^<([a-zA-Z0-9]+)/) || [])[1] || '';
|
||||
const id = getAttr('id');
|
||||
// FIX: Handle numeric IDs by creating an attribute selector
|
||||
if (id) {
|
||||
if (/^\\d/.test(id)) { // If id starts with a digit
|
||||
if (/^\d/.test(id)) {
|
||||
return `${tagName}[id='${id}']`;
|
||||
}
|
||||
return `${tagName}#${id}`;
|
||||
@@ -65,16 +142,279 @@ function parseLocator(locatorStr) {
|
||||
const type = getAttr('type');
|
||||
if (type) return `${tagName}[type='${type}']`;
|
||||
|
||||
console.warn(`Could not generate a reliable selector for: ${locatorStr}.`);
|
||||
return tagName;
|
||||
}
|
||||
|
||||
async function detectFormFields(page) {
|
||||
console.log('🔍 Auto-detecting form fields...');
|
||||
|
||||
const detectedFields = await page.evaluate((patterns) => {
|
||||
const results = {};
|
||||
const usedElements = new Set();
|
||||
|
||||
// Get all visible input fields, excluding hidden fields
|
||||
const inputs = Array.from(document.querySelectorAll('input, select, textarea')).filter(input => {
|
||||
const type = input.type?.toLowerCase() || 'text';
|
||||
const style = window.getComputedStyle(input);
|
||||
const rect = input.getBoundingClientRect();
|
||||
|
||||
// Skip hidden fields and honeypots
|
||||
if (type === 'hidden' || type === 'submit' || type === 'button') return false;
|
||||
if (input.tabIndex === -1 && input.style.position === 'absolute') return false; // Likely honeypot
|
||||
if (rect.width === 0 || rect.height === 0) return false;
|
||||
if (style.display === 'none' || style.visibility === 'hidden') return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
const calculateScore = (input, pattern, fieldName) => {
|
||||
let score = 0;
|
||||
const inputType = (input.type || 'text').toLowerCase();
|
||||
const inputName = (input.name || '').toLowerCase();
|
||||
const inputId = (input.id || '').toLowerCase();
|
||||
const placeholder = (input.placeholder || '').toLowerCase();
|
||||
const autocomplete = (input.autocomplete || '').toLowerCase();
|
||||
|
||||
// Type matching
|
||||
if (pattern.types && pattern.types.includes(inputType)) {
|
||||
score += 5;
|
||||
}
|
||||
|
||||
// Name matching - exact matches get high scores
|
||||
if (pattern.names) {
|
||||
for (const name of pattern.names) {
|
||||
const nameLower = name.toLowerCase();
|
||||
if (inputName === nameLower) {
|
||||
score += 20; // Exact match
|
||||
break;
|
||||
} else if (inputName.includes(nameLower)) {
|
||||
// Partial match - be careful not to match fname with username
|
||||
if (fieldName === 'firstName' && (inputName.includes('user') || inputName.includes('login'))) {
|
||||
score -= 5; // Penalize if it looks like username
|
||||
} else if (fieldName === 'lastName' && (inputName.includes('user') || inputName.includes('login'))) {
|
||||
score -= 5;
|
||||
} else {
|
||||
score += 10;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ID matching - very specific
|
||||
if (pattern.ids) {
|
||||
for (const id of pattern.ids) {
|
||||
const idLower = id.toLowerCase();
|
||||
if (inputId === idLower) {
|
||||
score += 20; // Exact match
|
||||
break;
|
||||
} else if (inputId.includes(idLower)) {
|
||||
score += 10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Placeholder matching
|
||||
if (pattern.placeholders) {
|
||||
for (const ph of pattern.placeholders) {
|
||||
const phLower = ph.toLowerCase();
|
||||
if (placeholder === phLower) {
|
||||
score += 15;
|
||||
break;
|
||||
} else if (placeholder.includes(phLower)) {
|
||||
score += 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Autocomplete matching
|
||||
if (pattern.autocomplete) {
|
||||
for (const ac of pattern.autocomplete) {
|
||||
if (autocomplete === ac.toLowerCase()) {
|
||||
score += 12;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check label text
|
||||
const labels = input.labels;
|
||||
if (labels && labels.length > 0) {
|
||||
const labelText = labels[0].textContent.toLowerCase();
|
||||
const fieldNameLower = fieldName.toLowerCase().replace(/([A-Z])/g, ' $1').trim();
|
||||
if (labelText.includes(fieldNameLower) || labelText.includes(pattern.names?.[0] || '')) {
|
||||
score += 15;
|
||||
}
|
||||
}
|
||||
|
||||
// Penalize if field appears to be a honeypot
|
||||
if (inputName.includes('b_') || inputId.includes('b_')) {
|
||||
score -= 30; // Likely Mailchimp honeypot
|
||||
}
|
||||
|
||||
// Penalize disabled/readonly
|
||||
if (input.disabled || input.readOnly) {
|
||||
score -= 20;
|
||||
}
|
||||
|
||||
// Special handling for confirmEmail
|
||||
if (pattern.mustHaveConfirmIndicator) {
|
||||
const hasConfirm = inputId.includes('confirm') || inputId.includes('verify') ||
|
||||
inputName.includes('confirm') || inputName.includes('verify') ||
|
||||
placeholder.includes('confirm') || placeholder.includes('verify') ||
|
||||
placeholder.includes('re-') || placeholder.includes('again');
|
||||
if (!hasConfirm) {
|
||||
score -= 15;
|
||||
}
|
||||
}
|
||||
|
||||
return score;
|
||||
};
|
||||
|
||||
// Sort patterns by priority
|
||||
const sortedPatterns = Object.entries(patterns).sort((a, b) => a[1].priority - b[1].priority);
|
||||
|
||||
for (const [fieldName, pattern] of sortedPatterns) {
|
||||
let bestMatch = null;
|
||||
let bestScore = 0;
|
||||
let bestIndex = -1;
|
||||
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
if (usedElements.has(i)) continue;
|
||||
|
||||
const input = inputs[i];
|
||||
const score = calculateScore(input, pattern, fieldName);
|
||||
|
||||
if (score > bestScore && score >= 10) {
|
||||
bestScore = score;
|
||||
bestMatch = input;
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestMatch && bestIndex >= 0) {
|
||||
usedElements.add(bestIndex);
|
||||
|
||||
// Generate selector
|
||||
let selector = '';
|
||||
if (bestMatch.id) {
|
||||
selector = `#${bestMatch.id}`;
|
||||
} else if (bestMatch.name) {
|
||||
selector = `[name="${bestMatch.name}"]`;
|
||||
} else if (bestMatch.placeholder) {
|
||||
selector = `[placeholder="${bestMatch.placeholder}"]`;
|
||||
} else {
|
||||
const tagName = bestMatch.tagName.toLowerCase();
|
||||
const type = bestMatch.type ? `[type="${bestMatch.type}"]` : '';
|
||||
const allSame = Array.from(document.querySelectorAll(`${tagName}${type}`));
|
||||
const index = allSame.indexOf(bestMatch) + 1;
|
||||
selector = `${tagName}${type}:nth-of-type(${index})`;
|
||||
}
|
||||
|
||||
results[fieldName] = {
|
||||
selector,
|
||||
confidence: bestScore,
|
||||
name: bestMatch.name,
|
||||
id: bestMatch.id
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}, FIELD_PATTERNS);
|
||||
|
||||
const detectedCount = Object.keys(detectedFields).length;
|
||||
if (detectedCount > 0) {
|
||||
console.log(` ✅ Auto-detected ${detectedCount} fields:`);
|
||||
for (const [field, info] of Object.entries(detectedFields)) {
|
||||
console.log(` - ${field}: ${info.selector} (score: ${info.confidence})`);
|
||||
}
|
||||
} else {
|
||||
console.log(' ⚠️ No fields auto-detected');
|
||||
}
|
||||
|
||||
return detectedFields;
|
||||
}
|
||||
|
||||
async function handleCameraBoysGDPR(page) {
|
||||
// ... (This function remains the same)
|
||||
async function detectSubmitButton(page) {
|
||||
console.log('🔍 Auto-detecting submit button...');
|
||||
|
||||
const submitSelector = await page.evaluate(() => {
|
||||
const buttons = Array.from(document.querySelectorAll('button[type="submit"], input[type="submit"], button, input[type="button"]'));
|
||||
let bestMatch = null;
|
||||
let bestScore = 0;
|
||||
|
||||
buttons.forEach(btn => {
|
||||
const text = (btn.textContent || btn.value || '').toLowerCase().trim();
|
||||
const type = btn.type?.toLowerCase() || '';
|
||||
const className = (btn.className || '').toLowerCase();
|
||||
let score = 0;
|
||||
|
||||
if (type === 'submit') score += 20;
|
||||
|
||||
if (text.includes('subscribe')) score += 15;
|
||||
else if (text.includes('sign up')) score += 12;
|
||||
else if (text.includes('submit')) score += 10;
|
||||
else if (text.includes('join')) score += 8;
|
||||
else if (text.includes('register')) score += 8;
|
||||
else if (text.includes('send')) score += 5;
|
||||
|
||||
if (className.includes('submit')) score += 8;
|
||||
if (className.includes('subscribe')) score += 8;
|
||||
|
||||
if (className.includes('close') || text.includes('close')) score -= 20;
|
||||
if (className.includes('cancel') || text.includes('cancel')) score -= 20;
|
||||
if (className.includes('back') || text.includes('back')) score -= 15;
|
||||
if (className.includes('drawer')) score -= 15;
|
||||
|
||||
const rect = btn.getBoundingClientRect();
|
||||
if (rect.width > 0 && rect.height > 0 && rect.top > 0) {
|
||||
score += 3;
|
||||
}
|
||||
|
||||
if (score > bestScore) {
|
||||
bestScore = score;
|
||||
bestMatch = btn;
|
||||
}
|
||||
});
|
||||
|
||||
if (bestMatch && bestScore >= 10) {
|
||||
if (bestMatch.id) return `#${bestMatch.id}`;
|
||||
if (bestMatch.name) return `[name="${bestMatch.name}"]`;
|
||||
|
||||
const className = bestMatch.className;
|
||||
if (className) {
|
||||
const classes = className.split(' ').filter(c => c.length > 0);
|
||||
for (const cls of classes) {
|
||||
const clsLower = cls.toLowerCase();
|
||||
if (clsLower.includes('submit') || clsLower.includes('subscribe')) {
|
||||
return `.${cls}`;
|
||||
}
|
||||
}
|
||||
for (const cls of classes) {
|
||||
if (!cls.toLowerCase().includes('close') && !cls.toLowerCase().includes('cancel')) {
|
||||
return `.${cls}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const allBtns = Array.from(document.querySelectorAll('button'));
|
||||
const index = allBtns.indexOf(bestMatch) + 1;
|
||||
return `button:nth-of-type(${index})`;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
if (submitSelector) {
|
||||
console.log(` ✅ Auto-detected submit button: ${submitSelector}`);
|
||||
}
|
||||
|
||||
return submitSelector;
|
||||
}
|
||||
|
||||
// --- Main Execution ---
|
||||
async function main() {
|
||||
const config = loadConfig();
|
||||
const sitesToProcess = config.sites || [];
|
||||
@@ -104,14 +444,13 @@ async function main() {
|
||||
creds = { ...globalCreds };
|
||||
console.log(`Using global credentials for site: ${site.name}`);
|
||||
}
|
||||
// If any credential is still missing, generate it randomly
|
||||
if (!creds.username || !creds.email || !creds.password || !creds.age) {
|
||||
|
||||
if (!creds.username || !creds.email || !creds.password) {
|
||||
const randomData = generateRandomData();
|
||||
creds = { ...randomData, ...creds };
|
||||
console.log('Filled in missing credentials with random data.');
|
||||
}
|
||||
|
||||
|
||||
console.log(`\n--- Processing Site: ${site.name} (Category: ${site.category || 'N/A'}) ---`);
|
||||
|
||||
const page = isFirstSite ? (await browser.pages())[0] : await browser.newPage();
|
||||
@@ -123,44 +462,69 @@ async function main() {
|
||||
|
||||
await page.goto(site.url, { waitUntil: 'networkidle2' });
|
||||
|
||||
if (site.needsPreSubmitAction && site.name === 'CameraBoys') {
|
||||
await handleCameraBoysGDPR(page);
|
||||
}
|
||||
|
||||
console.log('Dynamically filling out the form...');
|
||||
|
||||
let fieldsToFill = {};
|
||||
const definedLocators = site.locators || {};
|
||||
|
||||
for (const fieldName in definedLocators) {
|
||||
if (fieldName === 'submit') continue; // Skip the submit button
|
||||
|
||||
const selector = parseLocator(definedLocators[fieldName]);
|
||||
|
||||
if (site.autoDetect !== false) {
|
||||
const detectedFields = await detectFormFields(page);
|
||||
for (const [fieldName, fieldInfo] of Object.entries(detectedFields)) {
|
||||
fieldsToFill[fieldName] = fieldInfo.selector;
|
||||
}
|
||||
}
|
||||
|
||||
for (const [fieldName, locator] of Object.entries(definedLocators)) {
|
||||
if (fieldName !== 'submit') {
|
||||
fieldsToFill[fieldName] = parseLocator(locator);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [fieldName, selector] of Object.entries(fieldsToFill)) {
|
||||
let valueToFill = creds[fieldName];
|
||||
|
||||
// Special case for 'confirmEmail', use the email value
|
||||
|
||||
if (fieldName === 'confirmEmail') {
|
||||
valueToFill = creds['email'];
|
||||
}
|
||||
|
||||
|
||||
if (selector && valueToFill) {
|
||||
try {
|
||||
console.log(` - Filling field: ${fieldName}`);
|
||||
await page.type(selector, valueToFill, { delay: 100 });
|
||||
console.log(` - Filling field: ${fieldName} with "${valueToFill}"`);
|
||||
await page.evaluate((sel, val) => {
|
||||
const el = document.querySelector(sel);
|
||||
if (el) {
|
||||
el.value = val;
|
||||
el.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
el.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
}
|
||||
}, selector, valueToFill);
|
||||
} catch (e) {
|
||||
console.warn(` - Could not fill field '${fieldName}' with selector '${selector}'. Error: ${e.message}`);
|
||||
console.warn(` - Could not fill field '${fieldName}': ${e.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Form filled. Attempting to submit...');
|
||||
const submitSelector = parseLocator(definedLocators.submit);
|
||||
await page.click(submitSelector);
|
||||
|
||||
console.log(`✅ Submission attempt for ${site.name} is complete.`);
|
||||
let submitSelector = null;
|
||||
if (definedLocators.submit) {
|
||||
submitSelector = parseLocator(definedLocators.submit);
|
||||
} else if (site.autoDetect !== false) {
|
||||
submitSelector = await detectSubmitButton(page);
|
||||
}
|
||||
|
||||
if (submitSelector) {
|
||||
console.log('Form filled. Attempting to submit...');
|
||||
await page.click(submitSelector);
|
||||
console.log(`✅ Submission attempt for ${site.name} is complete.`);
|
||||
} else {
|
||||
console.warn('⚠️ No submit button found.');
|
||||
}
|
||||
|
||||
await new Promise(r => setTimeout(r, 2000));
|
||||
}
|
||||
} catch(error) {
|
||||
console.error('❌ A critical error occurred during execution:', error.message);
|
||||
console.error('❌ A critical error occurred:', error.message);
|
||||
} finally {
|
||||
console.log('\n🎉 All tasks complete. The browser window will remain open for inspection.');
|
||||
console.log('\n🎉 All tasks complete.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Generated
+62
-67
@@ -18,12 +18,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
|
||||
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
|
||||
"integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.27.1",
|
||||
"@babel/helper-validator-identifier": "^7.28.5",
|
||||
"js-tokens": "^4.0.0",
|
||||
"picocolors": "^1.1.1"
|
||||
},
|
||||
@@ -47,16 +47,16 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@puppeteer/browsers": {
|
||||
"version": "2.10.13",
|
||||
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.13.tgz",
|
||||
"integrity": "sha512-a9Ruw3j3qlnB5a/zHRTkruppynxqaeE4H9WNj5eYGRWqw0ZauZ23f4W2ARf3hghF5doozyD+CRtt7XSYuYRI/Q==",
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.12.1.tgz",
|
||||
"integrity": "sha512-fXa6uXLxfslBlus3MEpW8S6S9fe5RwmAE5Gd8u3krqOwnkZJV3/lQJiY3LaFdTctLLqJtyMgEUGkbDnRNf6vbQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"debug": "^4.4.3",
|
||||
"extract-zip": "^2.0.1",
|
||||
"progress": "^2.0.3",
|
||||
"proxy-agent": "^6.5.0",
|
||||
"semver": "^7.7.3",
|
||||
"semver": "^7.7.4",
|
||||
"tar-fs": "^3.1.1",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
@@ -89,9 +89,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz",
|
||||
"integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
|
||||
"version": "25.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.3.tgz",
|
||||
"integrity": "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
@@ -169,9 +169,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/b4a": {
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz",
|
||||
"integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==",
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.4.tgz",
|
||||
"integrity": "sha512-u20zJLDaSWpxaZ+zaAkEIB2dZZ1o+DF4T/MRbmsvGp9nletHOyiai19OzX1fF8xUBYsO1bPXxODvcd0978pnug==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"react-native-b4a": "*"
|
||||
@@ -203,9 +203,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/bare-fs": {
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.1.tgz",
|
||||
"integrity": "sha512-zGUCsm3yv/ePt2PHNbVxjjn0nNB1MkIaR4wOCxJ2ig5pCf5cCVAYJXVhQg/3OhhJV6DB1ts7Hv0oUaElc2TPQg==",
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.4.tgz",
|
||||
"integrity": "sha512-POK4oplfA7P7gqvetNmCs4CNtm9fNsx+IAh7jH7GgU0OJdge2rso0R20TNWVq6VoWcCvsTdlNDaleLHGaKx8CA==",
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
@@ -280,9 +280,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/basic-ftp": {
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
|
||||
"integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.1.0.tgz",
|
||||
"integrity": "sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
@@ -317,9 +317,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chromium-bidi": {
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-11.0.0.tgz",
|
||||
"integrity": "sha512-cM3DI+OOb89T3wO8cpPSro80Q9eKYJ7hGVXoGS3GkDPxnYSqiv+6xwpIf6XERyJ9Tdsl09hmNmY94BkgZdVekw==",
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-14.0.0.tgz",
|
||||
"integrity": "sha512-9gYlLtS6tStdRWzrtXaTMnqcM4dudNegMXJxkR0I/CXObHalYeYcAMPrL19eroNZHtJ8DQmu1E+ZNOYu/IXMXw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"mitt": "^3.0.1",
|
||||
@@ -459,11 +459,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/devtools-protocol": {
|
||||
"version": "0.0.1521046",
|
||||
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1521046.tgz",
|
||||
"integrity": "sha512-vhE6eymDQSKWUXwwA37NtTTVEzjtGVfDr3pRbsWEQ5onH/Snp2c+2xZHWJJawG/0hCCJLRGt4xVtEVUVILol4w==",
|
||||
"license": "BSD-3-Clause",
|
||||
"peer": true
|
||||
"version": "0.0.1566079",
|
||||
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1566079.tgz",
|
||||
"integrity": "sha512-MJfAEA1UfVhSs7fbSQOG4czavUp1ajfg6prlAN0+cmfa2zNjaIbvq8VneP7do1WAQQIvgNJWSMeP6UyI90gIlQ==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
@@ -700,7 +699,7 @@
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"deprecated": "Glob versions prior to v9 are no longer supported",
|
||||
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
@@ -1076,13 +1075,12 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.56.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz",
|
||||
"integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==",
|
||||
"version": "1.58.2",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz",
|
||||
"integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"playwright-core": "1.56.1"
|
||||
"playwright-core": "1.58.2"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@@ -1095,9 +1093,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.56.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz",
|
||||
"integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==",
|
||||
"version": "1.58.2",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz",
|
||||
"integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
@@ -1111,7 +1109,6 @@
|
||||
"resolved": "https://registry.npmjs.org/playwright-extra/-/playwright-extra-4.3.6.tgz",
|
||||
"integrity": "sha512-q2rVtcE8V8K3vPVF1zny4pvwZveHLH8KBuVU2MoE3Jw4OKVoBWsHI9CH9zPydovHHOCDxjGN2Vg+2m644q3ijA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
@@ -1176,18 +1173,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/puppeteer": {
|
||||
"version": "24.30.0",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.30.0.tgz",
|
||||
"integrity": "sha512-A5OtCi9WpiXBQgJ2vQiZHSyrAzQmO/WDsvghqlN4kgw21PhxA5knHUaUQq/N3EMt8CcvSS0RM+kmYLJmedR3TQ==",
|
||||
"version": "24.37.3",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.37.3.tgz",
|
||||
"integrity": "sha512-AUGGWq0BhPM+IOS2U9A+ZREH3HDFkV1Y5HERYGDg5cbGXjoGsTCT7/A6VZRfNU0UJJdCclyEimZICkZW6pqJyw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@puppeteer/browsers": "2.10.13",
|
||||
"chromium-bidi": "11.0.0",
|
||||
"@puppeteer/browsers": "2.12.1",
|
||||
"chromium-bidi": "14.0.0",
|
||||
"cosmiconfig": "^9.0.0",
|
||||
"devtools-protocol": "0.0.1521046",
|
||||
"puppeteer-core": "24.30.0",
|
||||
"devtools-protocol": "0.0.1566079",
|
||||
"puppeteer-core": "24.37.3",
|
||||
"typed-query-selector": "^2.12.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -1198,18 +1194,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/puppeteer-core": {
|
||||
"version": "24.30.0",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.30.0.tgz",
|
||||
"integrity": "sha512-2S3Smy0t0W4wJnNvDe7W0bE7wDmZjfZ3ljfMgJd6hn2Hq/f0jgN+x9PULZo2U3fu5UUIJ+JP8cNUGllu8P91Pg==",
|
||||
"version": "24.37.3",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.37.3.tgz",
|
||||
"integrity": "sha512-fokQ8gv+hNgsRWqVuP5rUjGp+wzV5aMTP3fcm8ekNabmLGlJdFHas1OdMscAH9Gzq4Qcf7cfI/Pe6wEcAqQhqg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@puppeteer/browsers": "2.10.13",
|
||||
"chromium-bidi": "11.0.0",
|
||||
"@puppeteer/browsers": "2.12.1",
|
||||
"chromium-bidi": "14.0.0",
|
||||
"debug": "^4.4.3",
|
||||
"devtools-protocol": "0.0.1521046",
|
||||
"devtools-protocol": "0.0.1566079",
|
||||
"typed-query-selector": "^2.12.0",
|
||||
"webdriver-bidi-protocol": "0.3.8",
|
||||
"ws": "^8.18.3"
|
||||
"webdriver-bidi-protocol": "0.4.1",
|
||||
"ws": "^8.19.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -1220,7 +1216,6 @@
|
||||
"resolved": "https://registry.npmjs.org/puppeteer-extra/-/puppeteer-extra-3.3.6.tgz",
|
||||
"integrity": "sha512-rsLBE/6mMxAjlLd06LuGacrukP2bqbzKCLzV1vrhHFavqQE/taQ2UXv3H5P0Ls7nsrASa+6x3bDbXHpqMwq+7A==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/debug": "^4.1.0",
|
||||
"debug": "^4.1.1",
|
||||
@@ -1387,9 +1382,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.7.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
||||
"version": "7.7.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
||||
"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
@@ -1545,9 +1540,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/text-decoder": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz",
|
||||
"integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==",
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.6.tgz",
|
||||
"integrity": "sha512-27FeW5GQFDfw0FpwMQhMagB7BztOOlmjcSRi97t2oplhKVTZtp0DZbSegSaXS5IIC6mxMvBG4AR1Sgc6BX3CQg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"b4a": "^1.6.4"
|
||||
@@ -1582,9 +1577,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webdriver-bidi-protocol": {
|
||||
"version": "0.3.8",
|
||||
"resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.3.8.tgz",
|
||||
"integrity": "sha512-21Yi2GhGntMc671vNBCjiAeEVknXjVRoyu+k+9xOMShu+ZQfpGQwnBqbNz/Sv4GXZ6JmutlPAi2nIJcrymAWuQ==",
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.1.tgz",
|
||||
"integrity": "sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
@@ -1611,9 +1606,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.18.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||
"version": "8.19.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
|
||||
"integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
|
||||
Reference in New Issue
Block a user