3mora2 / WPP_Whatsapp

WPP_Whatsapp aim of exporting functions from WhatsApp Web to the python, which can be used to support the creation of any interaction, such as customer service, media sending, intelligence recognition based on phrases artificial and many other things, use your imagination
MIT License
57 stars 9 forks source link

self.state=OPENING #26

Closed Jeck-Liu-Create closed 5 months ago

Jeck-Liu-Create commented 6 months ago

I'm verifying self.state before sending a message, and I don't understand what self.state=OPENING means.

3mora2 commented 6 months ago

see interface-state.ts

Jeck-Liu-Create commented 6 months ago

I'm experiencing an issue where messageSenderLayer class are timing out, possibly due to high bandwidtself.state property is set toOPENING for an extended period without transitioning to CONNECTED, prompting a proactive

Here's a potential method I've drafted forSenderLayer class:

def reload(self):
    return self.ThreadsafeBrowser.sync_page_evaluate("() => location.reload()",None)

Would this method be effective in ensuring that the page is refreshed in situations where the self.state remains in the OPENING state for too long without establishing a connection?

3mora2 commented 6 months ago

Create take autoClose Automatically closes the wppconnect only when scanning the QR code

timeout for send message, may be not related to it please send your code and error

Jeck-Liu-Create commented 6 months ago

After initializing SetWhatsApp normally, since I am using tkinter, the create_web_send function is used normally. The check_state function is queried every 10 seconds, and the send_image_message function is called approximately every 2 seconds. An error that is not outdated is reported under OPENING, but it is difficult to reproduce. However, most errors are due to Timeout.

Below is a simple modification made to run_threadsafe in threadsafe_browser.py:

    def run_threadsafe(self, func, *args, timeout_=120, **kwargs):
        future = asyncio.run_coroutine_threadsafe(
            func(*args, **kwargs), self.loop
        )
        try:
            result = future.result(timeout=timeout_)
            return result
        except TimeoutError:
            print(f"Function {func.__name__} timed out after {timeout_} seconds.")
            return None
# WhatsApp Sending Class
class SetWhatsApp:
    def __init__(self, session_name):
        self.session_name = session_name
        self.creator = None
        self.client = None
        self.browser_open = False

    # Start WhatsApp session
    async def create_web_send(self, headless=False):
        if headless:
            self.creator = Create(session=self.session_name, browser="firefox", headless=headless)
        else:
            self.creator = Create(session=self.session_name, browser="firefox")
        self.client = self.creator.start()
        self.browser_open = True

    # Send a text message
    def send_text_message(self, to, message_data):
        if self.browser_open and self.client:
            try:
                result = self.client.sendText(to=to, content=message_data)
                if result is None:
                    print(f"Failed to send message to {to} with data {message_data}: Timeout")
                    return False
                elif result.get('sendMsgResult') == {}:
                    return True
                else:
                    return False
            except Exception as e:
                print(f"Failed to send message to {to} with data {message_data}: {e.__class__.__name__}: {e}")
                return False
        else:
            print("Browser is not open.")
            return False

    # Send an image message
    def send_image_message(self, to, image_path):
        print(to, image_path)
        if self.browser_open and self.client:
            try:
                result = self.client.sendImage(to=to, filePath=image_path)
                if result is None:
                    print(f"Failed to send image to {to} with path {image_path}: Timeout")
                    return False
                elif result.get('sendMsgResult', {}).get('messageSendResult') == 'OK':
                    return True
                else:
                    return False
            except Exception as e:
                print(f"Failed to send image to {to} with path {image_path}: {e.__class__.__name__}: {e}")
                return False
        else:
            print("Browser is not open.")
            return False

    def send_video_message(self, to, video_path):
        try:
            result = self.client.sendFile(
                to=to,
                pathOrBase64=video_path,  # Pass in the file path here
                nameOrOptions='video.mp4',  # Pass in the file name here
                caption=None  # Pass in the title here
            )
            if result is None:
                print(f"Failed to send video to {to} with path {video_path}: Timeout")
                return False
            elif result.get('sendMsgResult', {}).get('messageSendResult') == 'OK':
                print("Video File sent successfully:", result)
                return True
            else:
                print("Video File sent failed:", result)
                return False
        except Exception as e:
            print(f"An error occurred: {e.__class__.__name__}: {e}")
        return False

    # Check if WhatsApp session is connected
    def check_state(self):
        try:
            if self.creator.state != 'CONNECTED' and self.creator.state != 'CLOSED':
                print(f"Loading state:{self.creator.state}")
                self.creator_reload()
                time.sleep(5)
                return False
            elif self.creator.state != 'CONNECTED':
                print(f"Connection interrupted state:{self.creator.state}")
                return False
            else:
                return True
        except Exception as e:
            print("check_state error:", e)
            return False

    # Close WhatsApp session
    def creator_close(self):
        if self.creator:
            self.creator.sync_close()
            print("Closing browser")

    # Actively refresh
    def creator_reload(self):
        if self.creator:
            self.client.reload()
            print("Refreshing browser")
Exception in thread Thread-8:
Traceback (most recent call last):
  File "threading.py", line 932, in _bootstrap_inner
  File "threading.py", line 870, in run
  File "WPP_Whatsapp\api\Whatsapp.py", line 54, in _loop_
    func()
  File "WPP_Whatsapp\api\Whatsapp.py", line 63, in __intervalHandel
    newConnected = self.ThreadsafeBrowser.sync_page_evaluate("() => window.WPP && window.WPP.conn.isRegistered()")
  File "WPP_Whatsapp\PlaywrightSafeThread\browser\threadsafe_browser.py", line 352, in sync_page_evaluate
    return self.run_threadsafe(self.page.evaluate, expression, arg, timeout_=timeout_)
  File "WPP_Whatsapp\PlaywrightSafeThread\browser\threadsafe_browser.py", line 403, in run_threadsafe
    result = future.result(timeout=timeout_)
  File "concurrent\futures\_base.py", line 446, in result
concurrent.futures._base.TimeoutError
Jeck-Liu-Create commented 6 months ago

After initializing SetWhatsApp normally, since I am using tkinter, the create_web_send function is used normally. The check_state function is queried every 10 seconds, and the send_image_message function is called approximately every 2 seconds. An error that is not outdated is reported under OPENING, but it is difficult to reproduce. However, most errors are due to Timeout.

Below is a simple modification made to run_threadsafe in threadsafe_browser.py:

    def run_threadsafe(self, func, *args, timeout_=120, **kwargs):
        future = asyncio.run_coroutine_threadsafe(
            func(*args, **kwargs), self.loop
        )
        try:
            result = future.result(timeout=timeout_)
            return result
        except TimeoutError:
            print(f"Function {func.__name__} timed out after {timeout_} seconds.")
            return None
# WhatsApp Sending Class
class SetWhatsApp:
    def __init__(self, session_name):
        self.session_name = session_name
        self.creator = None
        self.client = None
        self.browser_open = False

    # Start WhatsApp session
    async def create_web_send(self, headless=False):
        if headless:
            self.creator = Create(session=self.session_name, browser="firefox", headless=headless)
        else:
            self.creator = Create(session=self.session_name, browser="firefox")
        self.client = self.creator.start()
        self.browser_open = True

    # Send a text message
    def send_text_message(self, to, message_data):
        if self.browser_open and self.client:
            try:
                result = self.client.sendText(to=to, content=message_data)
                if result is None:
                    print(f"Failed to send message to {to} with data {message_data}: Timeout")
                    return False
                elif result.get('sendMsgResult') == {}:
                    return True
                else:
                    return False
            except Exception as e:
                print(f"Failed to send message to {to} with data {message_data}: {e.__class__.__name__}: {e}")
                return False
        else:
            print("Browser is not open.")
            return False

    # Send an image message
    def send_image_message(self, to, image_path):
        print(to, image_path)
        if self.browser_open and self.client:
            try:
                result = self.client.sendImage(to=to, filePath=image_path)
                if result is None:
                    print(f"Failed to send image to {to} with path {image_path}: Timeout")
                    return False
                elif result.get('sendMsgResult', {}).get('messageSendResult') == 'OK':
                    return True
                else:
                    return False
            except Exception as e:
                print(f"Failed to send image to {to} with path {image_path}: {e.__class__.__name__}: {e}")
                return False
        else:
            print("Browser is not open.")
            return False

    def send_video_message(self, to, video_path):
        try:
            result = self.client.sendFile(
                to=to,
                pathOrBase64=video_path,  # Pass in the file path here
                nameOrOptions='video.mp4',  # Pass in the file name here
                caption=None  # Pass in the title here
            )
            if result is None:
                print(f"Failed to send video to {to} with path {video_path}: Timeout")
                return False
            elif result.get('sendMsgResult', {}).get('messageSendResult') == 'OK':
                print("Video File sent successfully:", result)
                return True
            else:
                print("Video File sent failed:", result)
                return False
        except Exception as e:
            print(f"An error occurred: {e.__class__.__name__}: {e}")
        return False

    # Check if WhatsApp session is connected
    def check_state(self):
        try:
            if self.creator.state != 'CONNECTED' and self.creator.state != 'CLOSED':
                print(f"Loading state:{self.creator.state}")
                self.creator_reload()
                time.sleep(5)
                return False
            elif self.creator.state != 'CONNECTED':
                print(f"Connection interrupted state:{self.creator.state}")
                return False
            else:
                return True
        except Exception as e:
            print("check_state error:", e)
            return False

    # Close WhatsApp session
    def creator_close(self):
        if self.creator:
            self.creator.sync_close()
            print("Closing browser")

    # Actively refresh
    def creator_reload(self):
        if self.creator:
            self.client.reload()
            print("Refreshing browser")
Exception in thread Thread-8:
Traceback (most recent call last):
  File "threading.py", line 932, in _bootstrap_inner
  File "threading.py", line 870, in run
  File "WPP_Whatsapp\api\Whatsapp.py", line 54, in _loop_
    func()
  File "WPP_Whatsapp\api\Whatsapp.py", line 63, in __intervalHandel
    newConnected = self.ThreadsafeBrowser.sync_page_evaluate("() => window.WPP && window.WPP.conn.isRegistered()")
  File "WPP_Whatsapp\PlaywrightSafeThread\browser\threadsafe_browser.py", line 352, in sync_page_evaluate
    return self.run_threadsafe(self.page.evaluate, expression, arg, timeout_=timeout_)
  File "WPP_Whatsapp\PlaywrightSafeThread\browser\threadsafe_browser.py", line 403, in run_threadsafe
    result = future.result(timeout=timeout_)
  File "concurrent\futures\_base.py", line 446, in result
concurrent.futures._base.TimeoutError

creator_reload is something I added later and can be ignored.

3mora2 commented 6 months ago

to create custom Create follow custom_create

# Start Whatsapp
client = Whatsapp(session, ThreadsafeBrowser)
client.start()
# after start client you need 
# wait for scan qrcode and login
is_logged = client.waitForLogin()

when use async method, you dont need run_threadsafe any more for example:

    async def sendText_(self, to, content, options=None):
        if not options:
            options = {}
        to = self.valid_chatId(to)
        send_result = await self.ThreadsafeBrowser.page_evaluate("""({ to, content, options }) =>
                            WPP.chat.sendTextMessage(to, content, {
                              ...options,
                              waitForAck: true,
                            })""", {"to": to, "content": content, "options": options})
        self.logger.debug(f'{self.session}: Send Message {send_result=}')

        return send_result