0

I'm trying to build a Whatsapp bot in java using selenium and I'm working on a function that shows on the screen the response of a recipient that got messaged by the bot earlier.

I found the class "_2wUmf _21bY5 message-in focusable-list-item" to be fitting as it shows incoming messages but when I try to search by class name it doesn't find anything, even tried to use css selector but still nothing.

How can I locate those elements and why does it happen?

My code:

import javax.swing.*;

class Main extends JFrame {

public static void main(String[] args) {
    new Main();
}

public Main() {
    this.setTitle("Whatsapp bot");
    this.setLayout(null);
    this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    this.setResizable(false);
    this.setSize(Constants.WINDOW_WIDTH, Constants.WINDOW_HEIGHT);
    this.add(new MainPanel(0, 0, Constants.WINDOW_WIDTH, Constants.WINDOW_HEIGHT));
    this.setVisible(true);

}


}

'

public class Constants {
public static final int WINDOW_WIDTH = 1400;
public static final int WINDOW_HEIGHT = 800;
public static final int LABEL_WIDTH = 110;
public static final int LABEL_HEIGHT = 30;
public static final int SPACE_BETWEEN_BOXES = 30;
public static final int SPACE_BETWEEN_LINES=20;
public static final int TEXT_FIELD_WIDTH = 100;
public static final int TEXT_FIELD_HEIGHT = 30;
public static final int BUTTON_WIDTH = 100;
public static final int BUTTON_HEIGHT = 30;
public static final int SLEEP_TIME=30;
public static final int ONE=1;
public static final int TWO=2;
public static final int THREE=3;
public static final int FOUR=4;
public static final int ONE_HUNDRED=100;
public static final int MARGIN_FROM_TOP = 10;
public static final int MARGIN_FROM_LEFT = 5;

}

'

import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

import javax.swing.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;


public class MainPanel extends JPanel {
private JButton openWhatsappButton;
private JLabel loginSuccessful;
private JTextField enterPhone;
private JTextField enterMessage;
private JLabel enterPhoneLabel;
private JLabel enterMessageLabel;
private JLabel whyIsThePhoneEmptyLabelOrInvalid;
private JLabel whyIsTheMessageEmptyLabel;
private JLabel messageSentLabel;
private JLabel messageReadOrDeliveredLabel;
private JLabel responseLabel;

public String phoneNumberFormatValidationAndReformation(String givenPhoneNumber) {
    String ans = new String();
    final int CORRECT_LENGTH_VERSION_A = 12;
    final String CORRECT_START_OF_PHONE_NUMBER_VERSION_A = "9725";
    final int START = 0;
    final int END_VERSION_A = 4;
    final int CORRECT_LENGTH_VERSION_B = 10;
    final String CORRECT_START_OF_PHONE_NUMBER_VERSION_B = "05";
    final int END_VERSION_B = 2;
    final int START_OF_REFORMATTED_VERSION_B_ORIGIN = 2;
    if ((CORRECT_LENGTH_VERSION_A == givenPhoneNumber.length()) && (CORRECT_START_OF_PHONE_NUMBER_VERSION_A.equals(givenPhoneNumber.substring(START, END_VERSION_A)))) {
        ans = givenPhoneNumber;
    }
    if ((CORRECT_LENGTH_VERSION_B == givenPhoneNumber.length()) && (CORRECT_START_OF_PHONE_NUMBER_VERSION_B.equals(givenPhoneNumber.substring(START, END_VERSION_B)))) {
        ans = CORRECT_START_OF_PHONE_NUMBER_VERSION_A + givenPhoneNumber.substring(START_OF_REFORMATTED_VERSION_B_ORIGIN);
    }
    return ans;
}

public MainPanel(int x, int y, int width, int height) {
    this.setLayout(null);
    this.setBounds(x, y, width, height);
    System.setProperty("webdriver.chrome.driver", "C:\\Users\\danie\\OneDrive\\Desktop\\chromedriver.exe");
    ChromeDriver driver = new ChromeDriver();
    driver.manage().window().minimize();
    openWhatsappButton = new JButton("Send");
    openWhatsappButton.setBounds(Constants.WINDOW_WIDTH / Constants.TWO - Constants.BUTTON_WIDTH / Constants.TWO, Constants.WINDOW_HEIGHT / Constants.TWO - Constants.BUTTON_HEIGHT / Constants.TWO, Constants.BUTTON_WIDTH, Constants.BUTTON_HEIGHT);
    this.add(openWhatsappButton);
    loginSuccessful = new JLabel("Logged in successfully!");

    enterPhone = new JTextField();
    enterPhone.setBounds(Constants.WINDOW_WIDTH / Constants.FOUR - Constants.TEXT_FIELD_WIDTH, Constants.WINDOW_HEIGHT / Constants.TWO - Constants.SPACE_BETWEEN_LINES * Constants.FOUR, Constants.TEXT_FIELD_WIDTH * Constants.TWO, Constants.TEXT_FIELD_HEIGHT);
    this.add(enterPhone);
    enterPhoneLabel = new JLabel("Enter a phone number: ");
    enterPhoneLabel.setBounds(enterPhone.getX() - Constants.ONE - Constants.FOUR * Constants.LABEL_WIDTH / Constants.THREE, enterPhone.getY(), Constants.FOUR * Constants.LABEL_WIDTH / Constants.THREE, Constants.LABEL_HEIGHT);
    this.add(enterPhoneLabel);
    whyIsThePhoneEmptyLabelOrInvalid = new JLabel("~You must enter a number...");
    whyIsThePhoneEmptyLabelOrInvalid.setBounds(enterPhone.getX() + Constants.ONE + Constants.TEXT_FIELD_WIDTH * Constants.TWO, enterPhone.getY(), Constants.FOUR * Constants.LABEL_WIDTH, Constants.LABEL_HEIGHT);
    enterMessage = new JTextField();
    enterMessage.setBounds(Constants.THREE * Constants.WINDOW_WIDTH / Constants.FOUR - Constants.TEXT_FIELD_WIDTH, Constants.WINDOW_HEIGHT / Constants.TWO - Constants.SPACE_BETWEEN_LINES * Constants.FOUR, Constants.TEXT_FIELD_WIDTH * Constants.TWO, Constants.TEXT_FIELD_HEIGHT);
    this.add(enterMessage);
    enterMessageLabel = new JLabel("Enter a message: ");
    enterMessageLabel.setBounds(enterMessage.getX() - Constants.ONE - Constants.LABEL_WIDTH, enterMessage.getY(), Constants.LABEL_WIDTH, Constants.LABEL_HEIGHT);
    this.add(enterMessageLabel);
    whyIsTheMessageEmptyLabel = new JLabel("~You must enter a message...");
    whyIsTheMessageEmptyLabel.setBounds(enterMessage.getX() + Constants.ONE + Constants.TEXT_FIELD_WIDTH * Constants.TWO, enterMessage.getY(), Constants.TWO * Constants.LABEL_WIDTH, Constants.LABEL_HEIGHT);
    loginSuccessful.setBounds(Constants.WINDOW_WIDTH / Constants.TWO - Constants.LABEL_WIDTH, openWhatsappButton.getY() - Constants.TWO * Constants.SPACE_BETWEEN_LINES, Constants.TWO * Constants.LABEL_WIDTH, Constants.BUTTON_HEIGHT);
    messageSentLabel = new JLabel("Message sent");
    messageSentLabel.setBounds(Constants.WINDOW_WIDTH / Constants.TWO - Constants.LABEL_WIDTH / Constants.TWO, openWhatsappButton.getY() + Constants.TWO * Constants.SPACE_BETWEEN_LINES, Constants.LABEL_WIDTH, Constants.LABEL_HEIGHT);
    messageReadOrDeliveredLabel = new JLabel("Message has been delivered");
    messageReadOrDeliveredLabel.setBounds(Constants.WINDOW_WIDTH / Constants.TWO - Constants.LABEL_WIDTH, messageSentLabel.getY() + Constants.TWO * Constants.SPACE_BETWEEN_LINES, Constants.TWO * Constants.LABEL_WIDTH, Constants.LABEL_HEIGHT);
    responseLabel = new JLabel("No response yet");
    responseLabel.setBounds(Constants.WINDOW_WIDTH / Constants.TWO - Constants.LABEL_WIDTH, messageSentLabel.getY() + Constants.FOUR * Constants.SPACE_BETWEEN_LINES, Constants.TWO * Constants.LABEL_WIDTH, Constants.LABEL_HEIGHT);

    openWhatsappButton.addActionListener(e -> {
        boolean toBraek = false;
        List<WebElement> messagesDoubleChecksBefore = null;
        boolean toContinue = true;
        if (enterMessage.getText().equals("") || enterMessage.getText() == null) {
            whyIsTheMessageEmptyLabel.setText("~You must enter a message...");
            this.add(whyIsTheMessageEmptyLabel);
            repaint();
            toContinue = false;
        } else {
            whyIsTheMessageEmptyLabel.setText("");
            repaint();
        }
        String phoneNumber = phoneNumberFormatValidationAndReformation(enterPhone.getText());
        if (enterPhone.getText().equals("") || enterPhone.getText() == null) {
            whyIsThePhoneEmptyLabelOrInvalid.setText("~You must enter a number...");
            this.add(whyIsThePhoneEmptyLabelOrInvalid);
            repaint();
            toContinue = false;
        } else {
            if (phoneNumber.equals("") || phoneNumber == null) {
                whyIsThePhoneEmptyLabelOrInvalid.setText("~phone number invalid");
                this.add(whyIsThePhoneEmptyLabelOrInvalid);
                repaint();
                toContinue = false;
            }
        }
        if (toContinue) {
            driver.get("https://web.whatsapp.com/send?phone=" + phoneNumber);
            driver.manage().window().maximize();

            try {
                Thread.sleep(Constants.SLEEP_TIME);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }

            boolean loggedIn = false;
            while (true) {
                if (!loggedIn) {
                    try {

                        if (driver.findElement(By.id("pane-side")).isEnabled()) {

                            this.add(loginSuccessful);
                            repaint();
                            loggedIn = true;
                        } else {
                            continue;
                        }

                    } catch (NoSuchElementException exception) {
                        continue;
                    }
                }
                if (loggedIn) {
                    boolean triedToSend = false;
                    try {
                        if (driver.findElement(By.cssSelector("div[ title=\"loading messages…\"]")).isEnabled()) {
                            System.out.println("massage loading");
                            continue;
                        }
                    } catch (NoSuchElementException exception) {

                    }
                    List<WebElement> messagesChecksBefore = null;
                    try {
                        System.out.println("message not loading anymore");


                        messagesDoubleChecksBefore = driver.findElements(By.cssSelector("span[data-icon='msg-dblcheck']"));
                        messagesChecksBefore = driver.findElements(By.cssSelector("span[data-icon='msg-dblcheck']"));
                        messagesChecksBefore.addAll(driver.findElements(By.cssSelector("span[data-icon='msg-check']")));
                        messagesChecksBefore.addAll(driver.findElements(By.cssSelector("span[data-icon='msg-time']")));
                        System.out.println(messagesChecksBefore.size());
                    } catch (NoSuchElementException exception) {
                    }
                    try {
                        Thread.sleep(Constants.SLEEP_TIME);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                    try {
                        WebElement typingBox = driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/div/footer/div[1]/div/span[2]/div/div[2]/div[1]/div/div[2]"));
                        typingBox.sendKeys(enterMessage.getText());
                        driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/div/footer/div[1]/div/span[2]/div/div[2]/div[2]/button/span")).click();
                        triedToSend = true;
                    } catch (NoSuchElementException exception) {
                    }
                    try {
                        Thread.sleep(Constants.ONE_HUNDRED * Constants.SLEEP_TIME);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                    List<WebElement> messagesChecksAfter = null;
                    try {
                        messagesChecksAfter = driver.findElements(By.cssSelector("span[data-icon='msg-dblcheck']"));
                        messagesChecksAfter.addAll(driver.findElements(By.cssSelector("span[data-icon='msg-check']")));
                        messagesChecksAfter.addAll(driver.findElements(By.cssSelector("span[data-icon='msg-time']")));
                        System.out.println(messagesChecksAfter.size());
                    } catch (NoSuchElementException exception) {
                    }
                    if (messagesChecksAfter.size() == Constants.ONE + messagesChecksBefore.size() && triedToSend) {
                        this.add(messageSentLabel);
                        repaint();
                        System.out.println("should paint the message sent label");
                        toBraek = true;
                    }


                    if (toBraek) {
                        break;
                    } else {
                        System.out.println("reattempting to send...");
                    }

                }

            }
            AtomicReference<List<WebElement>> messagesInTimeOfReading = null;
            List<WebElement> effectivelyFinalMessagesDoubleChecksBefore = messagesDoubleChecksBefore;
            AtomicBoolean threadClosed = new AtomicBoolean(false);
            new Thread(() -> {
                while (true) {
                    System.out.println("loops in thread");
                    List<WebElement> messagesDoubleChecksAfter = null;
                    boolean toBreakThatLoop = false;
                    try {
                        messagesDoubleChecksAfter = driver.findElements(By.cssSelector("span[data-icon='msg-dblcheck']"));
                    } catch (NoSuchElementException exception) {

                    }
                    if (messagesDoubleChecksAfter.size() > effectivelyFinalMessagesDoubleChecksBefore.size()) {
                        toBreakThatLoop = true;
                        WebElement lastDoubleCheck = messagesDoubleChecksAfter.get(messagesDoubleChecksAfter.size() - Constants.ONE);
                        while (true) {
                            if (lastDoubleCheck.getAccessibleName().equals("Read ") || lastDoubleCheck.getAccessibleName().equals("Read")) {
                                messageReadOrDeliveredLabel.setText("Message has been read");
                                this.add(messageReadOrDeliveredLabel);
                                repaint();
                                System.out.println("message was read");
                                try {
                                    messagesInTimeOfReading.set(driver.findElements(By.cssSelector("div[ class='_2wUmf _21bY5 message-in focusable-list-item']")));
                                } catch (NoSuchElementException exception){

                                } catch (NullPointerException exception2) {

                                }
                                try{
                                messagesInTimeOfReading.get().addAll(driver.findElements(By.cssSelector("div[class='_2wUmf.message-in.focusable-list-item']")));
                                } catch (NoSuchElementException exception){

                                } catch (NullPointerException exception2) {

                                }
                                break;
                            } else {
                                messageReadOrDeliveredLabel.setText("Message has been delivered");
                                this.add(messageReadOrDeliveredLabel);
                                repaint();
                            }
                        }
                        if (toBreakThatLoop) {
                            break;
                        }
                    } else {
                        try {
                            Thread.sleep(Constants.SLEEP_TIME);
                        } catch (InterruptedException ex) {
                            ex.printStackTrace();
                        }
                    }

                }
                threadClosed.set(true);
            }).start();
            this.add(responseLabel);
            int messagesInTimeOfReadingCount=0;
            messagesInTimeOfReading.get().size();
            if (messagesInTimeOfReading!=null){
                messagesInTimeOfReadingCount=messagesInTimeOfReading.get().size();
                System.out.println("found incoming messages");
            }
            int effectivelyFinalMessagesInTimeOfReadingCount = messagesInTimeOfReadingCount;
            new Thread(() -> {
                while (true) {
                    if (threadClosed.get()) {
                        List<WebElement> currentMessages = null;
                        try {
                            currentMessages=(driver.findElements(By.cssSelector("div[ class='_2wUmf _21bY5 message-in focusable-list-item']")));
                        } catch (NoSuchElementException exception){

                        } catch (NullPointerException exception2) {

                        }
                        try{
                            currentMessages.addAll(driver.findElements(By.cssSelector("div[class='_2wUmf.message-in.focusable-list-item']")));
                        } catch (NoSuchElementException exception){

                        } catch (NullPointerException exception2) {

                        }
                        int currentMessagesCount=0;

                        if (currentMessages!=null){
                            currentMessagesCount=currentMessages.size();
                        }
                        if (currentMessagesCount > effectivelyFinalMessagesInTimeOfReadingCount) {
                            WebElement response = currentMessages.get(currentMessages.size() - Constants.ONE);
                            String printToResponseLabel = "Response: " + response.getAccessibleName();
                            int textLength = printToResponseLabel.length();
                            responseLabel.setBounds(Constants.WINDOW_WIDTH / Constants.TWO - Constants.TWO * textLength, messageSentLabel.getY() + Constants.FOUR * Constants.SPACE_BETWEEN_LINES, Constants.FOUR * textLength, Constants.LABEL_HEIGHT);
                            responseLabel.setText(printToResponseLabel);
                            repaint();
                            break;
                        }
                    }
                }
            }).start();
        }
    });

 }

}
DGStar
  • 17
  • 7

1 Answers1

0

Your CSS expression is incorrect so it's why Selenium can't find webelement. The correct CSS expressions for <div class='_2wUmf _21bY5 message-in focusable-list-item'> are:

  • div._2wUmf._21bY5.message-in.focusable-list-item
  • div.message-in.focusable-list-item

Explanation:

  • in CSS class selector is specified with leading dot
  • in html attribute class can contain multiple classes, divided by space
  • _2wUmf and _21bY5 are autogenerated class names and can be changed somewhen
Yevhen B
  • 306
  • 1
  • 4