diff --git a/README.md b/README.md index 7a501b5b..7f5eb60e 100644 --- a/README.md +++ b/README.md @@ -133,9 +133,10 @@ BYOP (Bring Your Own Proxy) lets you connect external proxies to bypass anti-bot - ✨ Turn Websites to APIs - ✨ Turn Websites to Spreadsheets - ✨ Adapt To Website Layout Changes -- ✨ Extract Behind Login, -- ✨ Bypass Two-Factor Authentication For Extract Behind Login (coming soon) +- ✨ Extract Behind Login - ✨ Integrations +- ✨ MCP Server +- ✨ Bypass 2FA & MFA For Extract Behind Login (coming soon) - +++ A lot of amazing things! # Screenshots @@ -150,7 +151,7 @@ BYOP (Bring Your Own Proxy) lets you connect external proxies to bypass anti-bot ![Maxun PH Launch (1)-9-1](https://github.com/user-attachments/assets/160f46fa-0357-4c1b-ba50-b4fe64453bb7) # Note -This project is in early stages of development. Your feedback is very important for us - we're actively working to improve the product. +This project is in early stages of development. Your feedback is very important for us - we're actively working on improvements. # License

diff --git a/src/components/action/action-settings/scrape.tsx b/src/components/action/action-settings/Scrape.tsx similarity index 100% rename from src/components/action/action-settings/scrape.tsx rename to src/components/action/action-settings/Scrape.tsx diff --git a/src/components/action/action-settings/scrapeSchema.tsx b/src/components/action/action-settings/ScrapeSchema.tsx similarity index 100% rename from src/components/action/action-settings/scrapeSchema.tsx rename to src/components/action/action-settings/ScrapeSchema.tsx diff --git a/src/components/action/action-settings/screenshot.tsx b/src/components/action/action-settings/Screenshot.tsx similarity index 100% rename from src/components/action/action-settings/screenshot.tsx rename to src/components/action/action-settings/Screenshot.tsx diff --git a/src/components/action/action-settings/scroll.tsx b/src/components/action/action-settings/Scroll.tsx similarity index 100% rename from src/components/action/action-settings/scroll.tsx rename to src/components/action/action-settings/Scroll.tsx diff --git a/src/components/action/action-settings/index.ts b/src/components/action/action-settings/index.ts index 58e3f3c4..09e571d1 100644 --- a/src/components/action/action-settings/index.ts +++ b/src/components/action/action-settings/index.ts @@ -1,7 +1,7 @@ -import { ScrollSettings } from './scroll'; -import { ScreenshotSettings } from "./screenshot"; -import { ScrapeSettings } from "./scrape"; -import { ScrapeSchemaSettings } from "./scrapeSchema"; +import { ScrollSettings } from './Scroll'; +import { ScreenshotSettings } from "./Screenshot"; +import { ScrapeSettings } from "./Scrape"; +import { ScrapeSchemaSettings } from "./ScrapeSchema"; export { ScrollSettings, diff --git a/src/components/browser/BrowserContent.tsx b/src/components/browser/BrowserContent.tsx index 14b9385e..46a8886d 100644 --- a/src/components/browser/BrowserContent.tsx +++ b/src/components/browser/BrowserContent.tsx @@ -130,7 +130,7 @@ export const BrowserContent = () => { } }) .catch((error) => { - console.log("Fetching current url failed"); + console.log(`Fetching current url failed: ${error}`); }); }, []); diff --git a/src/components/browser/BrowserNavBar.tsx b/src/components/browser/BrowserNavBar.tsx index a9a1a8d0..a06b7b4e 100644 --- a/src/components/browser/BrowserNavBar.tsx +++ b/src/components/browser/BrowserNavBar.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components'; import ReplayIcon from '@mui/icons-material/Replay'; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; -import { NavBarButton } from '../ui/buttons/buttons'; +import { NavBarButton } from '../ui/buttons/Buttons'; import { UrlForm } from './UrlForm'; import { useCallback, useEffect } from "react"; import { useSocketStore } from "../../context/socket"; @@ -63,7 +63,7 @@ const BrowserNavBar: FC = ({ handleUrlChanged(response); } }).catch((error) => { - console.log("Fetching current url failed"); + console.log(`Fetching current url failed: ${error}`); }) }, []); diff --git a/src/components/browser/BrowserWindow.tsx b/src/components/browser/BrowserWindow.tsx index 5aec1e61..9d11d302 100644 --- a/src/components/browser/BrowserWindow.tsx +++ b/src/components/browser/BrowserWindow.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useContext, useEffect, useRef, useState } from 'react'; import { useSocketStore } from '../../context/socket'; import { Button } from '@mui/material'; -import Canvas from "../recorder/canvas"; +import Canvas from "../recorder/Canvas"; import { Highlighter } from "../recorder/Highlighter"; import { GenericModal } from '../ui/GenericModal'; import { useActionContext } from '../../context/browserActions'; diff --git a/src/components/browser/UrlForm.tsx b/src/components/browser/UrlForm.tsx index fe97c664..227b9cb8 100644 --- a/src/components/browser/UrlForm.tsx +++ b/src/components/browser/UrlForm.tsx @@ -1,8 +1,8 @@ import React, { useState, useEffect, useCallback, useRef } from 'react'; import type { SyntheticEvent } from 'react'; import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; -import { NavBarForm, NavBarInput } from "../ui/form"; -import { UrlFormButton } from "../ui/buttons/buttons"; +import { NavBarForm, NavBarInput } from "../ui/Form"; +import { UrlFormButton } from "../ui/buttons/Buttons"; import { useSocketStore } from '../../context/socket'; import { Socket } from "socket.io-client"; @@ -40,7 +40,7 @@ export const UrlForm = ({ lastSubmittedRef.current = url; // Update the last submitted URL } catch (e) { //alert(`ERROR: ${url} is not a valid url!`); - console.log(e) + console.log(`Failed to submit form:`,e) } }, [setCurrentAddress]); diff --git a/src/components/pickers/DatePicker.tsx b/src/components/pickers/DatePicker.tsx index ec4334e0..41c449c6 100644 --- a/src/components/pickers/DatePicker.tsx +++ b/src/components/pickers/DatePicker.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { useSocketStore } from '../../context/socket'; -import { Coordinates } from '../recorder/canvas'; +import { Coordinates } from '../recorder/Canvas'; interface DatePickerProps { coordinates: Coordinates; diff --git a/src/components/pickers/DateTimeLocalPicker.tsx b/src/components/pickers/DateTimeLocalPicker.tsx index 0cc952bc..51ac62c6 100644 --- a/src/components/pickers/DateTimeLocalPicker.tsx +++ b/src/components/pickers/DateTimeLocalPicker.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { useSocketStore } from '../../context/socket'; -import { Coordinates } from '../recorder/canvas'; +import { Coordinates } from '../recorder/Canvas'; interface DateTimeLocalPickerProps { coordinates: Coordinates; diff --git a/src/components/pickers/Dropdown.tsx b/src/components/pickers/Dropdown.tsx index 743d721e..a944592a 100644 --- a/src/components/pickers/Dropdown.tsx +++ b/src/components/pickers/Dropdown.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { useSocketStore } from '../../context/socket'; -import { Coordinates } from '../recorder/canvas'; +import { Coordinates } from '../recorder/Canvas'; interface DropdownProps { coordinates: Coordinates; diff --git a/src/components/pickers/TimePicker.tsx b/src/components/pickers/TimePicker.tsx index 7877787e..a9c02cae 100644 --- a/src/components/pickers/TimePicker.tsx +++ b/src/components/pickers/TimePicker.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { useSocketStore } from '../../context/socket'; -import { Coordinates } from '../recorder/canvas'; +import { Coordinates } from '../recorder/Canvas'; interface TimePickerProps { coordinates: Coordinates; diff --git a/src/components/recorder/canvas.tsx b/src/components/recorder/Canvas.tsx similarity index 99% rename from src/components/recorder/canvas.tsx rename to src/components/recorder/Canvas.tsx index c8c7502c..15fb9a70 100644 --- a/src/components/recorder/canvas.tsx +++ b/src/components/recorder/Canvas.tsx @@ -307,4 +307,4 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { }; -export default memo(Canvas); \ No newline at end of file +export default memo(Canvas); diff --git a/src/components/recorder/LeftSidePanel.tsx b/src/components/recorder/LeftSidePanel.tsx index af519200..8fddbbb4 100644 --- a/src/components/recorder/LeftSidePanel.tsx +++ b/src/components/recorder/LeftSidePanel.tsx @@ -19,7 +19,7 @@ const fetchWorkflow = (id: string, callback: (response: WorkflowFile) => void) = throw new Error("No workflow found"); } } - ).catch((error) => { console.log(error.message) }) + ).catch((error) => { console.log(`Failed to fetch workflow:`,error.message) }) }; interface LeftSidePanelProps { diff --git a/src/components/recorder/RightSidePanel.tsx b/src/components/recorder/RightSidePanel.tsx index d405e58c..3fd3fcf6 100644 --- a/src/components/recorder/RightSidePanel.tsx +++ b/src/components/recorder/RightSidePanel.tsx @@ -32,7 +32,7 @@ const fetchWorkflow = (id: string, callback: (response: WorkflowFile) => void) = throw new Error("No workflow found"); } } - ).catch((error) => { console.log(error.message) }) + ).catch((error) => { console.log(`Failed to fetch workflow:`,error.message) }) }; interface RightSidePanelProps { @@ -256,7 +256,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture ); updateListStepData(currentListId, extractedData); - console.log("✅ Client-side extraction completed:", extractedData); + console.log("✅ UI extraction completed:"); } catch (error) { console.error("Error in client-side data extraction:", error); notify("error", "Failed to extract data client-side"); @@ -276,7 +276,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture pagination: { type: "", selector: "" }, }); - console.log("📤 Sent extraction request to backend"); + console.log("📤 Sent extraction request to server"); } catch (error) { console.error("Error in backend data extraction:", error); } diff --git a/src/components/ui/form.tsx b/src/components/ui/Form.tsx similarity index 100% rename from src/components/ui/form.tsx rename to src/components/ui/Form.tsx diff --git a/src/components/ui/buttons/buttons.tsx b/src/components/ui/buttons/Buttons.tsx similarity index 100% rename from src/components/ui/buttons/buttons.tsx rename to src/components/ui/buttons/Buttons.tsx diff --git a/src/context/browserSteps.tsx b/src/context/browserSteps.tsx index fa8358be..8b4769aa 100644 --- a/src/context/browserSteps.tsx +++ b/src/context/browserSteps.tsx @@ -250,4 +250,4 @@ export const useBrowserSteps = () => { throw new Error('useBrowserSteps must be used within a BrowserStepsProvider'); } return context; -}; \ No newline at end of file +}; diff --git a/src/helpers/clientListExtractor.ts b/src/helpers/clientListExtractor.ts index b68b67cf..c7b21fd3 100644 --- a/src/helpers/clientListExtractor.ts +++ b/src/helpers/clientListExtractor.ts @@ -464,8 +464,6 @@ class ClientListExtractor { } } - console.log("📦 Found containers:", containers.length); - // Analyze fields for table vs non-table context const containerFields: ContainerFields[] = containers.map(() => ({ tableFields: {}, @@ -642,7 +640,6 @@ class ClientListExtractor { const value = this.extractValue(element, attribute); if (value !== null && value !== "") { record[label] = value; - console.log(`✅ Extracted ${label}:`, value); } else { console.warn( `❌ No value for ${label} in row ${rowIndex + 1}` @@ -691,7 +688,6 @@ class ClientListExtractor { const value = this.extractValue(element, attribute); if (value !== null && value !== "") { record[label] = value; - console.log(`✅ Extracted ${label}:`, value); } else { console.warn( `❌ No value for ${label} in container ${containerIndex + 1}` @@ -716,13 +712,6 @@ class ClientListExtractor { // Combine and limit results const extractedData = [...tableData, ...nonTableData].slice(0, limit); - console.log("🎉 Client extraction complete:", { - totalRecords: extractedData.length, - tableRecords: tableData.length, - nonTableRecords: nonTableData.length, - data: extractedData, - }); - return extractedData; } catch (error) { console.error("Error in client-side extractListData:", error); diff --git a/src/helpers/clientSelectorGenerator.ts b/src/helpers/clientSelectorGenerator.ts index 8dc8b4e4..28134dbb 100644 --- a/src/helpers/clientSelectorGenerator.ts +++ b/src/helpers/clientSelectorGenerator.ts @@ -1803,22 +1803,16 @@ class ClientSelectorGenerator { let elements = iframeDoc.elementsFromPoint(x, y) as HTMLElement[]; if (!elements.length) return null; - console.log("ALL ELEMENTS", elements); - const dialogElement = elements.find( (el) => el.getAttribute("role") === "dialog" ); if (dialogElement) { - console.log("FOUND DIALOG ELEMENT", dialogElement); - // Filter to keep only the dialog and its children const dialogElements = elements.filter( (el) => el === dialogElement || dialogElement.contains(el) ); - console.log("FILTERED DIALOG ELEMENTS", dialogElements); - // Get deepest element within the dialog const findDeepestInDialog = ( elements: HTMLElement[] @@ -1852,7 +1846,6 @@ class ClientSelectorGenerator { }; const deepestInDialog = findDeepestInDialog(dialogElements); - console.log("DEEPEST IN DIALOG", deepestInDialog); return deepestInDialog; } @@ -1874,13 +1867,11 @@ class ClientSelectorGenerator { (style.position === "fixed" || style.position === "absolute") && zIndex > 50 ) { - console.log("FOUND POSITIONED ELEMENT", element); return element; } // For SVG elements (like close buttons), prefer them if they're in the top elements if (element.tagName === "SVG" && i < 2) { - console.log("FOUND SVG ELEMENT", element); return element; } } @@ -1913,8 +1904,6 @@ class ClientSelectorGenerator { let deepestElement = findDeepestElement(elements); - console.log("DEEPEST ELEMENT", deepestElement); - if (!deepestElement) return null; const traverseShadowDOM = (element: HTMLElement): HTMLElement => { @@ -3133,13 +3122,6 @@ class ClientSelectorGenerator { childSelectors?: string[]; } | null { try { - console.log("🐛 DEBUG: generateDataForHighlighter called with:", { - coordinates, - getList: this.getList, - listSelector: this.listSelector, - isDOMMode, - }); - // Use instance variables instead of parameters const rect = this.getRect( iframeDocument, @@ -3161,11 +3143,6 @@ class ClientSelectorGenerator { ); if (!rect || !elementInfo || !displaySelector) { - console.log("🐛 DEBUG: Missing basic data:", { - rect: !!rect, - elementInfo: !!elementInfo, - selectors: !!displaySelector, - }); return null; } @@ -3183,24 +3160,12 @@ class ClientSelectorGenerator { if (this.getList === true) { if (this.listSelector !== "") { - console.log( - "🐛 DEBUG: Getting child selectors for:", - this.listSelector - ); const childSelectors = this.getChildSelectors( iframeDocument, this.listSelector ); - console.log("🐛 DEBUG: Generated child selectors:", { - count: childSelectors.length, - selectors: childSelectors.slice(0, 10), // First 10 - listSelector: this.listSelector, - }); return { ...highlighterData, childSelectors }; } else { - console.log( - "🐛 DEBUG: No listSelector set, returning without childSelectors" - ); return highlighterData; } } else { @@ -3234,8 +3199,6 @@ class ClientSelectorGenerator { ) : this.getSelectors(iframeDocument, coordinates); - console.log("SELECTOR BASED ON CUSTOM ACTION", selectorBasedOnCustomAction); - if (this.paginationMode && selectorBasedOnCustomAction) { // Chain selectors in specific priority order const selectors = selectorBasedOnCustomAction; diff --git a/src/pages/Register.tsx b/src/pages/Register.tsx index 909382d0..d9bdd64c 100644 --- a/src/pages/Register.tsx +++ b/src/pages/Register.tsx @@ -42,7 +42,6 @@ const Register = () => { setLoading(true); try { const { data } = await axios.post(`${apiUrl}/auth/register`, { email, password }); - console.log(data); dispatch({ type: "LOGIN", payload: data }); notify("success", t('register.welcome_notification')); window.localStorage.setItem("user", JSON.stringify(data));