I have cerated linkedin automation tool and want to make changes in it now. There are 2 files . 1 is GUI.py

import sys
from threading import Thread
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QVBoxLayout, QWidget, QFileDialog, QAction, QMenu, QLineEdit, QComboBox, QGroupBox, QSpinBox, QProgressBar
from PyQt5.QtCore import Qt, QObject, pyqtSignal, QThread
import json
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
import time
import yaml
import os
import linkedin_automation_logic

class WorkerSignals(QObject):
    status_update = pyqtSignal(str)
    progress_update = pyqtSignal(int)

class LinkedInAutomationWorker(QThread):
    def __init__(self, cookie, settings):
        super().__init__()
        self.cookie = cookie
        self.settings = settings
        self.signals = WorkerSignals()

    def run(self):
        try:
            keywords = [
                self.settings.get('keyword_1', ''),
                self.settings.get('keyword_2', ''),
                self.settings.get('keyword_3', '')
            ]
            comments_per_day = self.settings.get('comments_per_day', 10)

            # Ensure cookie_data is in JSON format
            if self.cookie:
                linkedin_automation_logic.start_linkedin_automation(
                    self.cookie,
                    keywords,
                    comments_per_day,
                    global_comments=0,
                    headless=False
                )
                self.signals.status_update.emit("Status: Automation Completed Successfully")
            else:
                self.signals.status_update.emit("Status: Cookie Data Not Found in Settings")
        except FileNotFoundError as e:
            self.signals.status_update.emit(f"Status: {str(e)}")
        except Exception as e:
            self.signals.status_update.emit(f"Status: Unexpected error occurred: {str(e)}")

class LinkedInAutomationTool(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("LinkedIn Automation Tool")
        self.setGeometry(100, 100, 800, 500)  # Adjust window size for better UX
        self.initUI()
        self.driver = None  # Initialize driver as None
        self.browser_shown = False  # To track if the browser is visible
        self.worker = None

    def initUI(self):
        # Central Widget to hold all other widgets
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # Layout for the central widget
        layout = QVBoxLayout(central_widget)
        layout.setContentsMargins(20, 20, 20, 20)  # Set margins for better UX
        layout.setSpacing(15)  # Set spacing between widgets for better UX
        central_widget.setLayout(layout)

        # Button to load cookie from a file
        self.load_cookie_button = QPushButton("Load Cookie from File")
        self.load_cookie_button.setIcon(self.style().standardIcon(QPushButton().style().SP_DialogOpenButton))
        self.load_cookie_button.setToolTip("Load LinkedIn cookie in JSON format")
        self.load_cookie_button.clicked.connect(self.load_cookie)
        layout.addWidget(self.load_cookie_button)

        # Button to start the commenting automation process
        self.start_button = QPushButton("Start Commenting Automation")
        self.start_button.setIcon(self.style().standardIcon(QPushButton().style().SP_ArrowRight))
        self.start_button.setToolTip("Start the LinkedIn commenting automation")
        self.start_button.clicked.connect(self.start_automation)
        layout.addWidget(self.start_button)

        # Button to show the browser
        self.show_browser_button = QPushButton("Show Browser")
        self.show_browser_button.setIcon(self.style().standardIcon(QPushButton().style().SP_ComputerIcon))
        self.show_browser_button.setToolTip("Show the browser window")
        self.show_browser_button.clicked.connect(self.show_browser)
        self.show_browser_button.setEnabled(False)  # Disable initially
        layout.addWidget(self.show_browser_button)

        # Button to hide the browser
        self.hide_browser_button = QPushButton("Hide Browser")
        self.hide_browser_button.setIcon(self.style().standardIcon(QPushButton().style().SP_DesktopIcon))
        self.hide_browser_button.setToolTip("Hide the browser window")
        self.hide_browser_button.clicked.connect(self.hide_browser)
        self.hide_browser_button.setEnabled(False)  # Disable initially
        layout.addWidget(self.hide_browser_button)

        # Button to close the browser
        self.close_browser_button = QPushButton("Close Browser")
        self.close_browser_button.setIcon(self.style().standardIcon(QPushButton().style().SP_BrowserStop))
        self.close_browser_button.setToolTip("Close the browser instance")
        self.close_browser_button.clicked.connect(self.close_browser)
        self.close_browser_button.setEnabled(False)  # Disable initially
        layout.addWidget(self.close_browser_button)

        # Label to display the current status of the tool
        self.status_label = QLabel("Status: Waiting to start...")
        layout.addWidget(self.status_label)

        # Progress bar for automation
        self.progress_bar = QProgressBar()
        self.progress_bar.setValue(0)
        layout.addWidget(self.progress_bar)

        # Create Settings Menu
        self.settings_menu = QMenu("Settings", self)
        self.settings_action = QAction("Open Settings", self)
        self.settings_action.setShortcut("Ctrl+S")
        self.settings_action.triggered.connect(self.open_settings)
        self.settings_menu.addAction(self.settings_action)
        self.menuBar().addMenu(self.settings_menu)

    def open_settings(self):
        # Function to open settings for LinkedIn automation
        if hasattr(self, 'settings_window') and self.settings_window is not None:
            self.settings_window.show()  # Ensure the window is displayed properly and stays open
            return
        
        # Load existing settings if available
        script_dir = os.path.dirname(os.path.abspath(__file__))
        settings_path = os.path.join(script_dir, 'settings.yaml')
        if os.path.exists(settings_path):
            with open(settings_path, 'r') as file:
                settings_data = yaml.safe_load(file)
        else:
            settings_data = {
                'keyword_1': 'en Empowerment OR Female Empowerment',
                'keyword_2': 'Online business',
                'keyword_3': 'Startup',
                'comment_length': '30 Words',
                'question_frequency': 'Never',
                'formality_level': 'Semi-formal',
                'personality': 'Whimsical',
                'tone': 'Professional',
                'like_commented_post': 'No',
                'hashtags': '#binteahan',
                'comments_per_day': 100,
                'profile_pages_to_mention': 'Bint e Ahan',
                'comment_as_page': 'No'
            }
        
        self.settings_window = QWidget()
        self.settings_window.setWindowTitle("Settings")
        self.settings_window.setGeometry(150, 150, 500, 700)
        settings_layout = QVBoxLayout(self.settings_window)
        settings_layout.setContentsMargins(20, 20, 20, 20)  # Set margins for better UX
        settings_layout.setSpacing(15)  # Set spacing between widgets for better UX

        # Group Box for Keywords
        keywords_group = QGroupBox("Keywords Settings")
        keywords_layout = QVBoxLayout()
        self.keyword_1_input = QLineEdit(settings_data.get('keyword_1', 'en Empowerment OR Female Empowerment'))
        keywords_layout.addWidget(QLabel("Keyword - 1:"))
        keywords_layout.addWidget(self.keyword_1_input)

        self.keyword_2_input = QLineEdit(settings_data.get('keyword_2', 'Online business'))
        keywords_layout.addWidget(QLabel("Keyword - 2:"))
        keywords_layout.addWidget(self.keyword_2_input)

        self.keyword_3_input = QLineEdit(settings_data.get('keyword_3', 'Startup'))
        keywords_layout.addWidget(QLabel("Keyword - 3:"))
        keywords_layout.addWidget(self.keyword_3_input)
        keywords_group.setLayout(keywords_layout)
        settings_layout.addWidget(keywords_group)

        # Group Box for Personalization Settings
        personalization_group = QGroupBox("Personalization Settings")
        personalization_layout = QVBoxLayout()

        # Comment Length Dropdown
        self.comment_length_input = QComboBox()
        self.comment_length_input.addItems(["10 Words", "20 Words", "30 Words", "50 Words", "100 Words"])
        self.comment_length_input.setCurrentText(settings_data.get('comment_length', '30 Words'))
        personalization_layout.addWidget(QLabel("Personalized Tone - Comments Length:"))
        personalization_layout.addWidget(self.comment_length_input)

        # Question Frequency Dropdown
        self.question_frequency_input = QComboBox()
        self.question_frequency_input.addItems(["Sometimes", "Rarely", "Never"])
        self.question_frequency_input.setCurrentText(settings_data.get('question_frequency', 'Never'))
        personalization_layout.addWidget(QLabel("Questions Frequency:"))
        personalization_layout.addWidget(self.question_frequency_input)

        # Formality Level Dropdown
        self.formality_level_input = QComboBox()
        self.formality_level_input.addItems(["Formal", "Semi-formal", "Informal"])
        self.formality_level_input.setCurrentText(settings_data.get('formality_level', 'Semi-formal'))
        personalization_layout.addWidget(QLabel("Formality Level:"))
        personalization_layout.addWidget(self.formality_level_input)

        # Personality Dropdown
        self.personality_input = QComboBox()
        self.personality_input.addItems(["Humouristic", "Analytical", "Serious", "Whimsical", "Irreverant", "Sarcastic", "Sincere", "Playful", "Optimistic", "Pessimistic", "Neutral"])
        self.personality_input.setCurrentText(settings_data.get('personality', 'Whimsical'))
        personalization_layout.addWidget(QLabel("Personality:"))
        personalization_layout.addWidget(self.personality_input)

        # Tone Dropdown
        self.tone_input = QComboBox()
        self.tone_input.addItems(["Friendly", "Professional", "Casual"])
        self.tone_input.setCurrentText(settings_data.get('tone', 'Professional'))
        personalization_layout.addWidget(QLabel("Tone:"))
        personalization_layout.addWidget(self.tone_input)

        personalization_group.setLayout(personalization_layout)
        settings_layout.addWidget(personalization_group)

        # Other Settings
        other_group = QGroupBox("Other Settings")
        other_layout = QVBoxLayout()

        # Like Commented Post Checkbox
        self.like_commented_post_input = QComboBox()
        self.like_commented_post_input.addItems(["Yes", "No"])
        self.like_commented_post_input.setCurrentText(settings_data.get('like_commented_post', 'No'))
        other_layout.addWidget(QLabel("Like the Commented Post:"))
        other_layout.addWidget(self.like_commented_post_input)

        # Hashtags Input
        self.hashtags_input = QLineEdit(settings_data.get('hashtags', '#binteahan'))
        other_layout.addWidget(QLabel("Hashtags:"))
        other_layout.addWidget(self.hashtags_input)

        # Number of Comments Per Day Input (SpinBox)
        self.comments_per_day_input = QSpinBox()
        self.comments_per_day_input.setRange(1, 1000)
        self.comments_per_day_input.setValue(settings_data.get('comments_per_day', 100))
        other_layout.addWidget(QLabel("Number of Comments Per Day:"))
        other_layout.addWidget(self.comments_per_day_input)

        # Profile/Pages to Mention Input
        self.profile_pages_to_mention_input = QLineEdit(settings_data.get('profile_pages_to_mention', 'Bint e Ahan'))
        other_layout.addWidget(QLabel("Profile/Pages to Mention:"))
        other_layout.addWidget(self.profile_pages_to_mention_input)

        # Comment as Page Input
        self.comment_as_page_input = QComboBox()
        self.comment_as_page_input.addItems(["No", "Yes"])
        self.comment_as_page_input.setCurrentText(settings_data.get('comment_as_page', 'No'))
        other_layout.addWidget(QLabel("Comment as Page?:"))
        other_layout.addWidget(self.comment_as_page_input)

        other_group.setLayout(other_layout)
        settings_layout.addWidget(other_group)

        # Save Button
        self.save_settings_button = QPushButton("Save Settings")
        self.save_settings_button.clicked.connect(self.save_settings)
        settings_layout.addWidget(self.save_settings_button)

        self.settings_window.setLayout(settings_layout)
        self.settings_window.show()

    def save_settings(self):
        # Function to save settings from the Settings Window
        self.keyword_1_value = self.keyword_1_input.text()
        self.keyword_2_value = self.keyword_2_input.text()
        self.keyword_3_value = self.keyword_3_input.text()
        self.comment_length_value = self.comment_length_input.currentText()
        self.question_frequency_value = self.question_frequency_input.currentText()
        self.formality_level_value = self.formality_level_input.currentText()
        self.personality_value = self.personality_input.currentText()
        self.tone_value = self.tone_input.currentText()
        self.like_commented_post_value = self.like_commented_post_input.currentText()
        self.hashtags_value = self.hashtags_input.text()
        self.comments_per_day_value = self.comments_per_day_input.value()
        self.profile_pages_to_mention_value = self.profile_pages_to_mention_input.text()
        self.comment_as_page_value = self.comment_as_page_input.currentText()

        # Save settings to YAML file
        settings_data = {
            'keyword_1': self.keyword_1_value,
            'keyword_2': self.keyword_2_value,
            'keyword_3': self.keyword_3_value,
            'comment_length': self.comment_length_value,
            'question_frequency': self.question_frequency_value,
            'formality_level': self.formality_level_value,
            'personality': self.personality_value,
            'tone': self.tone_value,
            'like_commented_post': self.like_commented_post_value,
            'hashtags': self.hashtags_value,
            'comments_per_day': self.comments_per_day_value,
            'profile_pages_to_mention': self.profile_pages_to_mention_value,
            'comment_as_page': self.comment_as_page_value
        }
        script_dir = os.path.dirname(os.path.abspath(__file__))
        settings_path = os.path.join(script_dir, 'settings.yaml')
        with open(settings_path, 'w') as file:
            yaml.dump(settings_data, file)
        print(f"Settings saved to {settings_path}")

        # Update status to indicate settings have been saved
        self.status_label.setText("Status: Settings Saved")
        self.status_label.setStyleSheet("color: green;")


    def load_cookie(self):
        # Function to load cookie from a file
        options = QFileDialog.Options()
        file_name, _ = QFileDialog.getOpenFileName(self, "Open Cookie File", "", "JSON Files (*.json);;All Files (*)", options=options)
        if file_name:
            # Read cookie data from the file and check format
            try:
                with open(file_name, 'r') as file:
                    cookie_data = json.load(file)  # Load as JSON to validate format
                self.cookie = cookie_data  # Store the cookie data
                self.status_label.setText("Status: Cookie Loaded Successfully")
                self.save_cookies_to_settings(cookie_data)
                self.status_label.setStyleSheet("color: green;")  # Set text color to green
            except json.JSONDecodeError:
                self.status_label.setText("Status: Invalid Cookie Format")
                self.status_label.setStyleSheet("color: red;")  # Set text color to red

    def save_cookies_to_settings(self, cookie_data):
        # Load existing settings
        script_dir = os.path.dirname(os.path.abspath(__file__))
        settings_path = os.path.join(script_dir, 'settings.yaml')
        
        if os.path.exists(settings_path):
            with open(settings_path, 'r') as file:
                settings_data = yaml.safe_load(file)
        else:
            settings_data = {}
        
        # Save the cookies to settings data
        settings_data['cookie'] = cookie_data

        # Write back the updated settings to the file
        with open(settings_path, 'w') as file:
            yaml.dump(settings_data, file)
        print("Cookies saved to settings.yaml")
        
    def start_automation(self):
        # Function to start the automation process
        if hasattr(self, 'cookie') and self.cookie:
            self.status_label.setText("Status: Automation Started...")
            self.status_label.setStyleSheet("color: black;")
            # Start the automation in a separate thread
            Thread(target=self.run_automation_logic).start()
        else:
            # If no cookie data is provided, prompt the user to load a cookie
            self.status_label.setText("Status: Please Load a Cookie First")
            self.status_label.setStyleSheet("color: red;")

    def run_automation_logic(self):
        # Load settings
        try:
            settings = linkedin_automation_logic.load_settings()
            cookie_data = self.cookie
            keywords = [settings.get('keyword_1', ''), settings.get('keyword_2', ''), settings.get('keyword_3', '')]
            comments_per_day = settings.get('comments_per_day', 10)

            # Ensure cookie_data is in JSON format
            if cookie_data:
                linkedin_automation_logic.start_linkedin_automation(
                    cookie_data,
                    keywords,
                    comments_per_day,
                    global_comments=0,
                    headless=False
                )
                self.status_label.setText("Status: Automation Completed Successfully")
                self.status_label.setStyleSheet("color: green;")
            else:
                self.status_label.setText("Status: Cookie Data Not Found in Settings")
                self.status_label.setStyleSheet("color: red;")
        except FileNotFoundError as e:
            self.status_label.setText(f"Status: {str(e)}")
            self.status_label.setStyleSheet("color: red;")
        except Exception as e:
            self.status_label.setText(f"Status: Unexpected error occurred: {str(e)}")
            self.status_label.setStyleSheet("color: red;")

    def show_browser(self):
        # Show the browser window
        if self.driver and not self.browser_shown:
            try:
                self.driver.maximize_window()
            except Exception as e:
                print(f"Error during maximizing window: {e}")
                self.status_label.setText(f"Error: Could not maximize browser window")
                self.status_label.setStyleSheet("color: red;")
            self.browser_shown = True

    def hide_browser(self):
        # Hide the browser window
        if self.driver and self.browser_shown:
            try:
                self.driver.minimize_window()
            except Exception as e:
                print(f"Error during minimizing window: {e}")
                self.status_label.setText(f"Error: Could not minimize browser window")
                self.status_label.setStyleSheet("color: red;")
            self.browser_shown = False

    def close_browser(self):
        # Close the browser
        if self.driver:
            try:
                self.driver.quit()

            except Exception as e:
                print(f"Error during closing browser: {e}")
                self.status_label.setText(f"Error: Could not close browser properly")
                self.status_label.setStyleSheet("color: red;")
            self.driver = None
            self.browser_shown = False
            # Disable buttons for browser control after closing
            self.show_browser_button.setEnabled(False)
            self.hide_browser_button.setEnabled(False)
            self.close_browser_button.setEnabled(False)
            self.status_label.setText("Status: Browser closed.")
            self.status_label.setStyleSheet("color: black;")

if __name__ == '__main__':
    # Main entry point of the application
    app = QApplication(sys.argv)
    window = LinkedInAutomationTool()
    window.show()
    sys.exit(app.exec_())


another is linkedin_automation_logic.py

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import time
import json
import yaml  # Import yaml to load settings properly
import os  # Import os to work with file paths
import logging
import pyperclip  # Import pyperclip to handle clipboard operations

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# Suppress unnecessary log messages
os.environ['WDM_LOG_LEVEL'] = '0'


def normalize_cookie(cookie):
    # Ensure all required fields are present and format is compatible with Selenium
    required_fields = ["name", "value", "domain", "path"]
    normalized = {key: cookie.get(key, '') for key in required_fields}

    # Convert expirationDate to expiry for Selenium compatibility
    if "expirationDate" in cookie:
        normalized["expiry"] = int(cookie["expirationDate"])
    
    # Set default secure and httpOnly values
    normalized["secure"] = cookie.get("secure", True)
    normalized["httpOnly"] = cookie.get("httpOnly", False)
    
    # Normalize sameSite values to match Selenium expectations
    same_site = cookie.get("sameSite", '').lower()
    if same_site in ["no_restriction", "unspecified"]:
        normalized["sameSite"] = "None"
    elif same_site in ["strict", "lax", "none"]:
        normalized["sameSite"] = same_site.capitalize()
    else:
        normalized["sameSite"] = "None"  # Default to 'None' if value is invalid

    return normalized


def load_settings():
    # Load settings from YAML file
    logger.info("Loading settings from YAML file...")
    script_dir = os.path.dirname(os.path.abspath(__file__))
    settings_path = os.path.join(script_dir, 'settings.yaml')
    if os.path.exists(settings_path):
        with open(settings_path, 'r') as file:
            settings_data = yaml.safe_load(file)
            logger.info("Settings loaded successfully.")
            return settings_data
    else:
        raise FileNotFoundError("Settings file not found. Please ensure settings.yaml exists.")


def wait_for_element(driver, locator, condition=EC.presence_of_element_located, timeout=20):
    # Helper function to wait for an element based on a specific condition
    try:
        element = WebDriverWait(driver, timeout).until(condition(locator))
        return element
    except TimeoutException:
        logger.error(f"Timeout waiting for element: {locator}")
        return None


def search_linkedin(driver, keyword, post_no_elements):
    # Function to perform LinkedIn search for a single keyword
    try:
        logger.info(f"Searching for keyword: {keyword}")
        search_url = f"https://www.linkedin.com/search/results/content/?datePosted=%22past-24h%22&keywords={keyword}&origin=FACETED_SEARCH&sid=&sortBy=%22date_posted%22"
        driver.get(search_url)
        if wait_for_element(driver, (By.CLASS_NAME, 'search-results-container')):
            logger.info(f"Search completed for keyword: {keyword}")
            
            # Read URLs in the file and save them into a list
            script_dir = os.path.dirname(os.path.abspath(__file__))
            urls_path = os.path.join(script_dir, 'urls.txt')
            with open(urls_path, 'r') as file:
                urls_in_file = [line.strip() for line in file.readlines()]
            logger.info(f"Read {len(urls_in_file)} URLs from urls.txt file.")
            
            time.sleep(3)  # Wait for 3 seconds after reading URLs

            # Wait for the copy link option and click
            overflow_web_ios_small_xpath = f"(//button[contains(@class,'feed-shared-control-menu__trigger artdeco-button')])[ {post_no_elements} ]"
            overflow_web_ios_small = wait_for_element(driver, (By.XPATH, overflow_web_ios_small_xpath))
            if overflow_web_ios_small:
                overflow_web_ios_small.click()
                logger.info("Clicked post successfully.")
                
                # Wait for the copy link button to appear and click it
                copy_link_xpath = "//*/text()[normalize-space(.)='Copy link to post']/parent::*"
                copy_link_element = wait_for_element(driver, (By.XPATH, copy_link_xpath))
                if copy_link_element:
                    copy_link_element.click()
                    logger.info("Clicked on 'Copy link to post' button successfully.")
                    time.sleep(3)  # Wait for 3 seconds after clicking the link
                    
                    # Get the copied URL from the clipboard
                    copied_url = pyperclip.paste()
                    logger.info(f"Copied URL: {copied_url}")

                    # Append the copied URL to urls.txt
                    with open(urls_path, 'a') as file:
                        file.write(f"{copied_url}\n\n")
                    logger.info("Copied URL added to urls.txt successfully.")
                    
                    # Increment the post number for subsequent actions
                    post_no_elements += 1
    except TimeoutException:
        logger.error(f"Timeout while searching for keyword: {keyword}")


def create_or_check_urls_file():
    # Function to create or check the urls.txt file
    script_dir = os.path.dirname(os.path.abspath(__file__))
    urls_path = os.path.join(script_dir, 'urls.txt')
    if not os.path.exists(urls_path):
        with open(urls_path, 'w') as file:
            logger.info("urls.txt file created.")
    else:
        logger.info("urls.txt file already exists.")


def start_linkedin_automation(cookie, keywords, comments_per_day, global_comments, headless=True, close_browser_after=True):
    logger.info("Starting LinkedIn automation...")
    # Setup WebDriver using webdriver-manager to automatically manage ChromeDriver
    chrome_options = Options()
    if headless:
        chrome_options.add_argument("--headless")  # Run in headless mode if desired

    # Suppress unnecessary log messages
    chrome_options.add_argument("--log-level=3")  # Suppress Chrome logs
    chrome_options.add_argument("--disable-gpu")  # Disable GPU to avoid GPU-related issues
    chrome_options.add_argument("--no-sandbox")  # Disables the sandbox for all process types that are normally sandboxed
    chrome_options.add_argument("--disable-dev-shm-usage")  # Overcome limited resource problems
    chrome_options.add_argument("--incognito")  # Opens the browser in incognito mode

    # Suppress "Chrome is being controlled by automated test software" message
    chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
    chrome_options.add_experimental_option('useAutomationExtension', False)

    # Disable WebGL and suppress warnings to avoid unnecessary logs
    chrome_options.add_argument("--disable-webgl")
    chrome_options.add_argument("--disable-logging")
    chrome_options.add_argument("--disable-blink-features=AutomationControlled")
    chrome_options.add_argument("--disable-features=WebGL2ComputeContext")

    driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=chrome_options)

    try:
        # Load LinkedIn
        logger.info("Opening LinkedIn website...")
        driver.get("https://www.linkedin.com")
        if not wait_for_element(driver, (By.TAG_NAME, 'body'), EC.presence_of_element_located, timeout=30):
            logger.error("Failed to load LinkedIn home page.")
            return

        # Load Cookies
        logger.info("Loading cookies...")
        try:
            for c in cookie['cookies']:
                normalized_cookie = normalize_cookie(c)  # Normalize the cookie format for Selenium
                driver.add_cookie(normalized_cookie)
        except KeyError as e:
            logger.error(f"Error loading cookies, missing key: {str(e)}")
            return
        except Exception as e:
            logger.error(f"Unexpected error while loading cookies: {str(e)}")
            return
        
        driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
        driver.refresh()  # Refresh after adding cookies to log in
        logger.info("Cookies loaded and page refreshed.")

        # Confirm Login Successful
        if "feed" not in driver.current_url:
            logger.error("Login failed. Please check the cookie.")
            return
        
        logger.info("Logged in successfully!")
        logger.info(f"Bot will do Total: {comments_per_day} comments")

        # Create or check urls.txt file
        create_or_check_urls_file()

        # Perform search for each keyword
        post_no_elements = 1
        for keyword in keywords:
            search_linkedin(driver, keyword, post_no_elements)
            global_comments += 1
            post_no_elements += 1  # Increase post_no_elements to make subsequent searches dynamic
            logger.info(f"Total comments completed: {global_comments}")
            if global_comments >= comments_per_day:
                break
        
        logger.info("Search process completed.")

    finally:
        # Close the browser after reaching the required number of comments
        if global_comments >= comments_per_day or close_browser_after:
            logger.info("Closing browser...")
            try:
                driver.quit()
                logger.info("Browser closed after completing the comments.")
            except Exception as e:
                logger.error(f"Error occurred while closing the browser: {str(e)}")
        else:
            logger.info("Automation complete. Browser will remain open for manual inspection.")