diff --git a/.gitignore b/.gitignore index 2602d04..9ad48cb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ node_modules/ cypress/videos/ cypress/screenshots/ irctc-captcha-solver/__pycache__ -cypress/downloads/ \ No newline at end of file +cypress/downloads/"cypress.env.json" +cypress.env.json diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 4f156d1..9e9d9bd 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -7,8 +7,7 @@ import { const MANUAL_CAPTCHA = Cypress.env("MANUAL_CAPTCHA"); Cypress.on("uncaught:exception", (err, runnable) => { - // returning false here prevents Cypress from - // failing the test + // returning false here prevents Cypress from failing the test return false; }); @@ -35,168 +34,144 @@ Cypress.Commands.add( ); function performLogin(LOGGED_IN) { - // if starts if (!LOGGED_IN) { cy.wait(500); cy.get("body") - .should("be.visible") - .then((el) => { - if (el[0].innerText.includes("Logout")) { - cy.task( - "log", - "We have logged in successfully at this stage" - ); - } else if ( - el[0].innerText.includes("FORGOT ACCOUNT DETAILS") && - !el[0].innerText.includes("Please Wait...") - ) { - if (MANUAL_CAPTCHA) { - cy.get("#captcha").focus(); - // wait for user to manually enter captcha and login - cy.get(".search_btn.loginText") - .should("include.text", "Logout") - .then(() => { - performLogin(true); - }); - } else { - // get captcha value base64 starts--------- - cy.get(".captcha-img") - .invoke("attr", "src") - .then((value) => { - // api call to retrieve captcha value - - cy.exec( - `py irctc-captcha-solver/app.py "${value}"` - ).then((result) => { - cy.get("#captcha") - .clear() - .type(result.stdout) - .type("{enter}"); - // cy.contains('SIGN IN').click() + .should("be.visible") + .then((el) => { + if (el[0].innerText.includes("Logout")) { + cy.task("log", "We have logged in successfully at this stage"); + } else if ( + el[0].innerText.includes("FORGOT ACCOUNT DETAILS") && + !el[0].innerText.includes("Please Wait...") + ) { + if (MANUAL_CAPTCHA) { + cy.get("#captcha").focus(); + // Wait for user to manually enter captcha and login + cy.get(".search_btn.loginText") + .should("include.text", "Logout") + .then(() => { + performLogin(true); + }); + } else { + // Use the local server to solve the captcha + cy.get(".captcha-img") + .invoke("attr", "src") + .then((value) => { + // API call to retrieve captcha value + cy.request({ + method: "POST", + url: "http://localhost:5000/extract-text", // URL of the Flask server endpoint + body: { + image: value, // Assuming `value` is your base64 image string + }, + }).then((response) => { + const extractedText = response.body.extracted_text; // Access the extracted text from the server response + cy.get("#captcha") + .clear() + .type(extractedText) + .type("{enter}"); - cy.get("body").then((el) => { - if ( - el[0].innerText.includes( - "Invalid Captcha" - ) - ) { - performLogin(false); - } else if ( - el[0].innerText.includes("Logout") - ) { - performLogin(true); - } else { - performLogin(false); - } - }); - }); - // api call to retrieve captcha value + cy.get("body").then((el) => { + if (el[0].innerText.includes("Invalid Captcha")) { + performLogin(false); + } else if (el[0].innerText.includes("Logout")) { + performLogin(true); + } else { + performLogin(false); + } }); - // get captcha value base64 ends--------- - } - } else { - performLogin(false); + }); + }); } - }); + } else { + performLogin(false); + } + }); } - // if ends } let MAX_ATTEMPT = 120; // function to solveCaptcha after logging in function solveCaptcha() { - // Max attempt for this function to fail MAX_ATTEMPT -= 1; cy.wrap(MAX_ATTEMPT, { timeout: 10000 }).should("be.gt", 0); - // cy.task("log", `Calling solveCaptcha() ${MAX_ATTEMPT}th time`); - cy.wait(500); cy.get("body") - .should("be.visible") - .then((el) => { - if ( - el[0].innerText.includes( - "Unable to process current transaction" - ) && - el[0].innerText.includes("Payment Mode") - ) { - // cy.task("log", "Unable to process current transaction..."); - cy.get(".train_Search").click(); - cy.wait(1000); - } + .should("be.visible") + .then((el) => { + if ( + el[0].innerText.includes( + "Unable to process current transaction" + ) && + el[0].innerText.includes("Payment Mode") + ) { + cy.get(".train_Search").click(); + cy.wait(1000); + } - if (el[0].innerText.includes("Sorry!!! Please Try again!!")) { - throw new Error( - "Sorry!!! Please Try again!! <<< Thrown By IRCTC" - ); - } + if (el[0].innerText.includes("Sorry!!! Please Try again!!")) { + throw new Error("Sorry!!! Please Try again!! <<< Thrown By IRCTC"); + } - if (el[0].innerText.includes("Payment Methods")) { - // cy.task("log", "CAPTCHA .... SOLVED"); - return; - } + if (el[0].innerText.includes("Payment Methods")) { + return; + } - if (el[0].innerText.includes("No seats available")) { - cy.fail( - "Further execution stopped because there are no more tickets." - ); - } + if (el[0].innerText.includes("No seats available")) { + cy.fail("Further execution stopped because there are no more tickets."); + } - // Check whether we are at reviewBooking stage or not if yes keep on solving captcha + if ( + el[0].innerText.includes("Your ticket will be sent to") && + !el[0].innerText.includes("Please Wait...") && + el[0].innerHTML.includes("Enter Captcha") + ) { + if (MANUAL_CAPTCHA) { + cy.get("#captcha").focus(); + cy.get("body").then((el) => { + if (el[0].innerText.includes("Payment Methods")) { + cy.task("log", "Bypassed Captcha"); + } + }); + } else { + cy.get(".captcha-img") + .invoke("attr", "src") + .then((value) => { + // Use the local server to solve the captcha + cy.request({ + method: "POST", + url: "http://localhost:5000/extract-text", // URL of the Flask server endpoint + body: { + image: value, // Assuming `value` is your base64 image string + }, + }).then((response) => { + const extractedText = response.body.extracted_text; + cy.get("#captcha") + .clear() + .type(extractedText) + .type("{enter}"); - if ( - el[0].innerText.includes("Your ticket will be sent to") && - !el[0].innerText.includes("Please Wait...") && - el[0].innerHTML.includes("Enter Captcha") - ) { - if (MANUAL_CAPTCHA) { - cy.get("#captcha").focus(); - cy.get("body").then((el) => { - if (el[0].innerText.includes("Payment Methods")) { - // cy.task("log", "Bypassed Captcha"); - } - }); - } else { - // get captcha value base64 starts--------- - cy.get(".captcha-img") - .invoke("attr", "src") - .then((value) => { - // api call to retrieve captcha value - cy.exec( - `py irctc-captcha-solver/app.py "${value}"` - ).then((result) => { - cy.get("#captcha") - .clear() - .type(result.stdout) - .type("{enter}"); - cy.get("body").then((el) => { - if ( - el[0].innerText.includes( - "Payment Methods" - ) - ) { - cy.task("log", "Bypassed Captcha"); - } else { - solveCaptcha(); - } - }); - }); - // api call to retrieve captcha value + cy.get("body").then((el) => { + if (el[0].innerText.includes("Payment Methods")) { + cy.task("log", "Bypassed Captcha"); + } else { + solveCaptcha(); + } }); - // get captcha value base64 ends--------- - - // recursing until captcha gets solved - solveCaptcha(); - } - } else if (el[0].innerText.includes("Payment Methods")) { - return; - } else { + }); + }); solveCaptcha(); } - }); + } else if (el[0].innerText.includes("Payment Methods")) { + return; + } else { + solveCaptcha(); + } + }); } function BOOK_UNTIL_TATKAL_OPENS( diff --git a/irctc-captcha-solve-server/__pycache__/cloud_vision.cpython-38.pyc b/irctc-captcha-solve-server/__pycache__/cloud_vision.cpython-38.pyc new file mode 100644 index 0000000..6e5e3eb Binary files /dev/null and b/irctc-captcha-solve-server/__pycache__/cloud_vision.cpython-38.pyc differ diff --git a/irctc-captcha-solve-server/captcha.png b/irctc-captcha-solve-server/captcha.png new file mode 100644 index 0000000..42c0772 Binary files /dev/null and b/irctc-captcha-solve-server/captcha.png differ diff --git a/irctc-captcha-solver/EasyOCR/craft_mlt_25k.pth b/irctc-captcha-solver/EasyOCR/craft_mlt_25k.pth new file mode 100644 index 0000000..7461d59 Binary files /dev/null and b/irctc-captcha-solver/EasyOCR/craft_mlt_25k.pth differ diff --git a/irctc-captcha-solver/EasyOCR/english_g2.pth b/irctc-captcha-solver/EasyOCR/english_g2.pth new file mode 100644 index 0000000..6d7ff9e Binary files /dev/null and b/irctc-captcha-solver/EasyOCR/english_g2.pth differ diff --git a/irctc-captcha-solver/app-server.py b/irctc-captcha-solver/app-server.py new file mode 100644 index 0000000..bac0ffb --- /dev/null +++ b/irctc-captcha-solver/app-server.py @@ -0,0 +1,72 @@ +import argparse +import numpy as np +from PIL import Image +import io +import base64 +import easyocr +from flask import Flask, request, jsonify + +# Initialize EasyOCR Reader +reader = easyocr.Reader(["en"], model_storage_directory="./EasyOCR") + +# Initialize Flask app +app = Flask(__name__) + +def extract_text_from_image(base64_image): + try: + # Convert the base64 image to bytes + image_bytes = base64.b64decode(base64_image[22:]) + # Create a BytesIO object from the image bytes + image_buffer = io.BytesIO(image_bytes) + # Open the image using PIL (Python Imaging Library) + image = Image.open(image_buffer) + # Convert the image to grayscale (optional but can improve OCR accuracy) + image = image.convert("L") + + # Convert PIL image to OpenCV format + open_cv_image = np.array(image) + + result = reader.readtext(open_cv_image, detail=0) + if result: + return result[0].replace(" ", "") + else: + return "ABCDEF" + except Exception as e: + return f"Error processing image: {str(e)}" + +@app.route("/extract-text", methods=["POST"]) +def extract_text(): + # Get the base64 image from the request + data = request.get_json() + base64_image = data.get("image", "") + + if not base64_image: + return jsonify({"error": "No base64 image string provided"}), 400 + + extracted_text = extract_text_from_image(base64_image) + return jsonify({"extracted_text": extracted_text}) + +@app.route('/') +def health_check(): + return "Server is running", 200 + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Run the OCR extraction server." + ) + parser.add_argument( + "--host", + type=str, + default="0.0.0.0", + help="Host address to run the server on (default: 0.0.0.0)", + ) + parser.add_argument( + "--port", + type=int, + default=5000, + help="Port to run the server on (default: 5000)", + ) + args = parser.parse_args() + + # Run Flask server + app.run(host=args.host, port=args.port) diff --git a/irctc-captcha-solver/app.py b/irctc-captcha-solver/app.py deleted file mode 100755 index 2afcf9a..0000000 --- a/irctc-captcha-solver/app.py +++ /dev/null @@ -1,49 +0,0 @@ -import argparse -import numpy as np -from PIL import Image -import io -import base64 -import easyocr - - -reader = easyocr.Reader(["en"], model_storage_directory="./EasyOCR") - - -def extract_text_from_image(base64_image): - # Convert the base64 image to bytes - image_bytes = base64.b64decode(base64_image[22:]) - # Create a BytesIO object from the image bytes - image_buffer = io.BytesIO(image_bytes) - # Open the image using PIL (Python Imaging Library) - image = Image.open(image_buffer) - # Convert the image to grayscale (optional but can improve OCR accuracy) - image = image.convert("L") - - # Convert PIL image to OpenCV format - open_cv_image = np.array(image) - - result = reader.readtext(open_cv_image, detail=0) - if result: - return result[0].replace(" ", "") - else: - return "ABCDEF" - - -if __name__ == "__main__": - parser = argparse.ArgumentParser( - description="Extract text from a base64 encoded image." - ) - parser.add_argument( - "image", - type=str, - nargs="?", - default="", - help="Base64 encoded image", - ) - args = parser.parse_args() - - if args.image == "": - print("No base-64 String provided") - else: - extracted_text = extract_text_from_image(args.image) - print(extracted_text) diff --git a/irctc-captcha-solver/requirements.txt b/irctc-captcha-solver/requirements.txt index cd2c45b..013a942 100644 --- a/irctc-captcha-solver/requirements.txt +++ b/irctc-captcha-solver/requirements.txt @@ -1,4 +1,5 @@ argparse pillow easyocr==1.7.1 -numpy \ No newline at end of file +numpy +flask \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 790564e..75296d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,11 @@ "dependencies": { "cypress": "13.7.1", "dayjs": "^1.11.10", - "fs.promises": "^0.1.2" + "fs.promises": "^0.1.2", + "wait-on": "^8.0.1" + }, + "devDependencies": { + "concurrently": "^9.1.0" } }, "node_modules/@colors/colors": { @@ -68,6 +72,42 @@ "ms": "^2.1.1" } }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "license": "BSD-3-Clause" + }, "node_modules/@types/node": { "version": "16.18.46", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.46.tgz", @@ -223,6 +263,37 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/axios/node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -426,6 +497,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -479,6 +565,32 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/concurrently": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.1.0.tgz", + "integrity": "sha512-VxkzwMAn4LP7WyMnJNbHN5mKV9L2IbyDjpzemKr99sXNR3GqRNMMHdm7prV1ws9wg7ETj6WUkNOigZVsptwbgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -627,6 +739,16 @@ "node": ">=8.6" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -727,6 +849,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -780,6 +922,16 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", @@ -1052,6 +1204,19 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -1431,6 +1596,16 @@ "throttleit": "^1.0.0" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -1532,6 +1707,16 @@ "node": ">=8" } }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -1676,6 +1861,16 @@ "node": ">= 4.0.0" } }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -1754,6 +1949,25 @@ "extsprintf": "^1.2.0" } }, + "node_modules/wait-on": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-8.0.1.tgz", + "integrity": "sha512-1wWQOyR2LVVtaqrcIL2+OM+x7bkpmzVROa0Nf6FryXkS+er5Sa1kzFGjzZRqLnHa3n1rACFLeTwUqE1ETL9Mig==", + "license": "MIT", + "dependencies": { + "axios": "^1.7.7", + "joi": "^17.13.3", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "rxjs": "^7.8.1" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -1789,11 +2003,50 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index f364428..52ad2fe 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,10 @@ "version": "3.0.4", "description": "IRCTC Ticket Booking", "scripts": { + "start-captha-server": "python irctc-captcha-solver/app-server.py --host 0.0.0.0 --port 5000", + "wait-for-captha-server-to-come-up": "wait-on http://localhost:5000", + "start-irctc-booking": "cypress run --headed --no-exit", + "start-booking": "concurrently \"npm run start-captha-server\" \"npm run wait-for-captha-server-to-come-up && npm run start-irctc-booking\"", "test": "cypress run" }, "author": "Shivam Pandey", @@ -10,6 +14,10 @@ "dependencies": { "cypress": "13.7.1", "dayjs": "^1.11.10", - "fs.promises": "^0.1.2" + "fs.promises": "^0.1.2", + "wait-on": "^8.0.1" + }, + "devDependencies": { + "concurrently": "^9.1.0" } } diff --git a/readme.md b/readme.md index b43f382..f7d6e47 100644 --- a/readme.md +++ b/readme.md @@ -199,7 +199,19 @@ pip install -r irctc-captcha-solver/requirements.txt # <---- Make Sure You Run T #### Check If Everything Works Fine.... This Would Print **No base-64 String provided** Which Means You Have Followed Correctly at this point. ``` -python irctc-captcha-solver/app.py "" +python irctc-captcha-solver/app-server.py --host 0.0.0.0 --port 5001 +``` +Then run the curl to see if the captcha server is responding fine. +``` +$ curl -X POST "http://localhost:5001/extract-text" +-H "Content-Type: application/json" +-d '{ + "image": "" + }' +``` +You should get below output. +``` +{"error":"No base64 image string provided"} ``` @@ -207,6 +219,6 @@ python irctc-captcha-solver/app.py "" ``` npm install # <---- Make Sure You Run This Command From Code Folder. -npx cypress run --headed --no-exit # <---- Make Sure You Run This Command From Code Folder. +npm run start-booking <---------- This will first bring up captha server then starts booking ```