|
|
|
|
|
""" |
|
|
WordPress Elementor Design Agent (Basic Implementation) |
|
|
""" |
|
|
|
|
|
import time |
|
|
import logging |
|
|
import argparse |
|
|
import os |
|
|
from typing import Optional |
|
|
from selenium import webdriver |
|
|
from selenium.webdriver.chrome.service import Service |
|
|
from selenium.webdriver.chrome.options import Options |
|
|
from selenium.webdriver.common.by import By |
|
|
from selenium.webdriver.support.ui import WebDriverWait |
|
|
from selenium.webdriver.support import expected_conditions as EC |
|
|
from webdriver_manager.chrome import ChromeDriverManager |
|
|
|
|
|
|
|
|
logging.basicConfig( |
|
|
level=logging.INFO, |
|
|
format='%(asctime)s - %(levelname)s - %(message)s' |
|
|
) |
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
class ElementorAgent: |
|
|
""" |
|
|
Agent for automating Elementor page builder tasks in WordPress (Basic Implementation). |
|
|
""" |
|
|
|
|
|
def __init__(self, url: str, username: str, password: str, post_id: Optional[int] = None, headless: bool = False): |
|
|
""" |
|
|
Initialize the Elementor agent. |
|
|
""" |
|
|
self.url = url |
|
|
self.username = username |
|
|
self.password = password |
|
|
self.post_id = post_id |
|
|
self.headless = headless |
|
|
self.driver: Optional[webdriver.Chrome] = None |
|
|
|
|
|
def start(self) -> bool: |
|
|
""" |
|
|
Start the browser and log in to WordPress (Placeholder Implementation). |
|
|
""" |
|
|
logger.info(f"Starting Elementor Agent (basic) for {self.url}") |
|
|
|
|
|
chrome_options = Options() |
|
|
if self.headless: |
|
|
chrome_options.add_argument("--headless") |
|
|
chrome_options.add_argument("--no-sandbox") |
|
|
chrome_options.add_argument("--disable-dev-shm-usage") |
|
|
|
|
|
try: |
|
|
self.driver = webdriver.Chrome( |
|
|
service=Service(ChromeDriverManager().install()), |
|
|
options=chrome_options |
|
|
) |
|
|
|
|
|
|
|
|
logger.info(f"Navigating to {self.url}") |
|
|
self.driver.get(self.url) |
|
|
|
|
|
|
|
|
username_field = WebDriverWait(self.driver, 10).until( |
|
|
EC.presence_of_element_located((By.ID, "user_login")) |
|
|
) |
|
|
password_field = self.driver.find_element(By.ID, "user_pass") |
|
|
|
|
|
|
|
|
username_field.send_keys(self.username) |
|
|
password_field.send_keys(self.password) |
|
|
|
|
|
|
|
|
password_field.submit() |
|
|
|
|
|
|
|
|
WebDriverWait(self.driver, 10).until( |
|
|
EC.presence_of_element_located((By.ID, "wpadminbar")) |
|
|
) |
|
|
|
|
|
logger.info("Successfully logged in to WordPress") |
|
|
|
|
|
|
|
|
if self.post_id: |
|
|
self.navigate_to_elementor() |
|
|
|
|
|
return True |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Error starting browser: {e}") |
|
|
if self.driver: |
|
|
self.driver.quit() |
|
|
self.driver = None |
|
|
return False |
|
|
|
|
|
def navigate_to_elementor(self) -> bool: |
|
|
""" |
|
|
Navigate to the Elementor editor for the specified post. |
|
|
""" |
|
|
if not self.driver or not self.post_id: |
|
|
return False |
|
|
|
|
|
try: |
|
|
editor_url = f"{self.url}post.php?post={self.post_id}&action=elementor" |
|
|
logger.info(f"Navigating to Elementor editor: {editor_url}") |
|
|
self.driver.get(editor_url) |
|
|
|
|
|
|
|
|
WebDriverWait(self.driver, 30).until( |
|
|
EC.presence_of_element_located((By.ID, "elementor-preview-iframe")) |
|
|
) |
|
|
|
|
|
logger.info("Successfully loaded Elementor editor") |
|
|
return True |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Error navigating to Elementor: {e}") |
|
|
return False |
|
|
|
|
|
def close(self) -> None: |
|
|
""" |
|
|
Close the browser and clean up. |
|
|
""" |
|
|
if self.driver: |
|
|
logger.info("Closing browser") |
|
|
self.driver.quit() |
|
|
self.driver = None |
|
|
|
|
|
def add_widget(self, widget_type: str) -> bool: |
|
|
""" |
|
|
Add a widget to the Elementor page. |
|
|
""" |
|
|
if not self.driver: |
|
|
return False |
|
|
|
|
|
try: |
|
|
|
|
|
preview_iframe = self.driver.find_element(By.ID, "elementor-preview-iframe") |
|
|
self.driver.switch_to.frame(preview_iframe) |
|
|
|
|
|
|
|
|
add_section = WebDriverWait(self.driver, 10).until( |
|
|
EC.element_to_be_clickable((By.CLASS_NAME, "elementor-add-section-button")) |
|
|
) |
|
|
add_section.click() |
|
|
|
|
|
|
|
|
self.driver.switch_to.default_content() |
|
|
|
|
|
|
|
|
search_input = WebDriverWait(self.driver, 10).until( |
|
|
EC.presence_of_element_located((By.CSS_SELECTOR, ".elementor-panel-search-input")) |
|
|
) |
|
|
search_input.send_keys(widget_type) |
|
|
|
|
|
|
|
|
widget_element = WebDriverWait(self.driver, 10).until( |
|
|
EC.element_to_be_clickable((By.XPATH, f"//div[contains(@class, 'elementor-element-title-wrapper') and contains(text(), '{widget_type}')]")) |
|
|
) |
|
|
widget_element.click() |
|
|
|
|
|
logger.info(f"Added widget: {widget_type}") |
|
|
return True |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Error adding widget: {e}") |
|
|
return False |
|
|
|
|
|
def edit_text(self, element_selector: str, text: str) -> bool: |
|
|
""" |
|
|
Edit text content of an Elementor element. |
|
|
""" |
|
|
if not self.driver: |
|
|
return False |
|
|
|
|
|
try: |
|
|
|
|
|
preview_iframe = self.driver.find_element(By.ID, "elementor-preview-iframe") |
|
|
self.driver.switch_to.frame(preview_iframe) |
|
|
|
|
|
|
|
|
element = WebDriverWait(self.driver, 10).until( |
|
|
EC.element_to_be_clickable((By.CSS_SELECTOR, element_selector)) |
|
|
) |
|
|
element.click() |
|
|
|
|
|
|
|
|
self.driver.switch_to.default_content() |
|
|
|
|
|
|
|
|
text_editor = WebDriverWait(self.driver, 10).until( |
|
|
EC.presence_of_element_located((By.CSS_SELECTOR, ".elementor-control-content [data-setting='editor']")) |
|
|
) |
|
|
|
|
|
|
|
|
self.driver.execute_script("arguments[0].innerHTML = arguments[1]", text_editor, text) |
|
|
|
|
|
logger.info(f"Edited text for selector: {element_selector}") |
|
|
return True |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Error editing text: {e}") |
|
|
return False |
|
|
|
|
|
def save_changes(self) -> bool: |
|
|
""" |
|
|
Save changes made in the Elementor editor. |
|
|
""" |
|
|
if not self.driver: |
|
|
return False |
|
|
|
|
|
try: |
|
|
|
|
|
self.driver.switch_to.default_content() |
|
|
|
|
|
|
|
|
save_button = WebDriverWait(self.driver, 10).until( |
|
|
EC.element_to_be_clickable((By.CSS_SELECTOR, ".elementor-button.elementor-button-success")) |
|
|
) |
|
|
save_button.click() |
|
|
|
|
|
|
|
|
WebDriverWait(self.driver, 10).until( |
|
|
EC.visibility_of_element_located((By.CSS_SELECTOR, ".elementor-button-success .elementor-state-icon")) |
|
|
) |
|
|
|
|
|
logger.info("Successfully saved changes") |
|
|
return True |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Error saving changes: {e}") |
|
|
return False |
|
|
|
|
|
def take_screenshot(self, filename: str = "elementor_screenshot.png") -> bool: |
|
|
""" |
|
|
Take a screenshot of the current state of the Elementor editor. |
|
|
""" |
|
|
if not self.driver: |
|
|
return False |
|
|
|
|
|
try: |
|
|
|
|
|
self.driver.switch_to.default_content() |
|
|
|
|
|
|
|
|
self.driver.save_screenshot(filename) |
|
|
logger.info(f"Screenshot saved: {filename}") |
|
|
return True |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Error taking screenshot: {e}") |
|
|
return False |
|
|
|
|
|
|
|
|
def parse_arguments(): |
|
|
"""Parse command line arguments.""" |
|
|
parser = argparse.ArgumentParser(description='WordPress Elementor Design Agent (Basic)') |
|
|
parser.add_argument('--url', default=os.environ.get('WP_ADMIN_URL', 'http://localhost/wp-admin/'), |
|
|
help='WordPress admin URL') |
|
|
parser.add_argument('--username', default=os.environ.get('WP_USERNAME', 'admin'), |
|
|
help='WordPress username') |
|
|
parser.add_argument('--password', default=os.environ.get('WP_PASSWORD', ''), |
|
|
help='WordPress password') |
|
|
parser.add_argument('--post-id', type=int, default=os.environ.get('WP_POST_ID', 1), |
|
|
help='Post ID to edit with Elementor') |
|
|
parser.add_argument('--headless', action='store_true', |
|
|
help='Run browser in headless mode') |
|
|
parser.add_argument('--screenshot', action='store_true', |
|
|
help='Take a screenshot after loading Elementor') |
|
|
parser.add_argument('--screenshot-path', default='elementor_editor.png', |
|
|
help='Path to save the screenshot') |
|
|
parser.add_argument('--wait-time', type=int, default=5, |
|
|
help='Time to wait after loading Elementor (seconds)') |
|
|
|
|
|
return parser.parse_arguments() |
|
|
|
|
|
|
|
|
def main(): |
|
|
"""Main function to run the script.""" |
|
|
args = parse_arguments() |
|
|
|
|
|
agent = ElementorAgent( |
|
|
url=args.url, |
|
|
username=args.username, |
|
|
password=args.password, |
|
|
post_id=args.post_id, |
|
|
headless=args.headless |
|
|
) |
|
|
|
|
|
if agent.start(): |
|
|
try: |
|
|
logger.info(f"Elementor Agent (basic) started successfully for post ID {args.post_id}") |
|
|
|
|
|
|
|
|
if args.screenshot: |
|
|
agent.take_screenshot(args.screenshot_path) |
|
|
|
|
|
|
|
|
if args.wait_time > 0: |
|
|
logger.info(f"Waiting for {args.wait_time} seconds...") |
|
|
time.sleep(args.wait_time) |
|
|
|
|
|
finally: |
|
|
agent.close() |
|
|
else: |
|
|
logger.error("Failed to start Elementor Agent (basic)") |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |
|
|
|