docstr: Sends a whatsapp message
  
  Args:
      body: message body
      from_number: number from which to send the message
      to_number: number to which message will be sent
docstr_tok: ["Sends","a","whatsapp","message","Args",":","body",":","message","body","from_number",":","number","from","which","to","send","the","message","to_number",":","number","to","which","message","will","be","sent"]
code: def insert(self, query: ast.Insert):
      """
      Sends a whatsapp message
  
      Args:
          body: message body
          from_number: number from which to send the message
          to_number: number to which message will be sent
      """
  
      # get column names and values from the query
      columns = [col.name for col in query.columns]
  
      ret = []
  
      insert_params = ["body", "from_number", "to_number"]
      for row in query.values:
          params = dict(zip(columns, row))
  
          # Check text length
          max_text_len = 1500
          text = params["body"]
          words = re.split("( )", text)
          messages = []
  
          """
                  Regex for matching if any URls are present, if yes then replace with string of hyphens(-)
  
                  Example:
                      words = ['Check', ' ', 'out', ' ', 'this', ' ', 'cool', ' ', 'website:', ' ', 'https://example.com.', "It's", ' ', 'awesome!']
  
                      After parsing through regex ('https://example.com') URL is matched
  
                      Final output:
                      messages = ['Check - out - this - cool - website: ----------------------- "It\'s - awesome!']
              """
  
          text2 = ""
          pattern = r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+"
          for word in words:
              # replace the links in word to string with the length as twitter short url (23)
              word2 = re.sub(pattern, "-" * 23, word)
              if (
                  len(text2) + len(word2) > max_text_len - 3 - 7
              ):  # 3 is for ..., 7 is for (10/11)
                  messages.append(text2.strip())
  
                  text2 = ""
              text2 += word
  
          # Parse last message
          if text2.strip() != "":
              messages.append(text2.strip())
  
          len_messages = len(messages)
  
          # Modify message based on the length
          for i, text in enumerate(messages):
              if i < len_messages - 1:
                  text += "..."
              else:
                  text += " "
  
              if i >= 1:
                  text += f"({i + 1}/{len_messages})"
  
              # Pass parameters and call 'send_message'
              params["body"] = text
              params_to_send = {
                  key: params[key]
                  for key in insert_params
                  if (key in params)
              }
              ret_row = self.handler.send_message(
                  params_to_send, ret_as_dict=True
              )
  
              # Save the results
              ret_row["body"] = text
              ret.append(ret_row)
  
      return pd.DataFrame(ret)
  
imports: import os
  from twilio.rest import Client
  import re
  from datetime import datetime
  from typing import List
  import pandas
  from mindsdb.utilities import log
  from mindsdb.utilities.config import Config
  from mindsdb_sql.parser import ast
  from mindsdb.integrations.utilities.date_utils import parse_local_date
  from mindsdb.integrations.libs.api_handler import APIHandler, APITable
  from mindsdb.integrations.utilities.sql_utils import extract_comparison_conditions, project_dataframe, filter_dataframe
  from mindsdb.integrations.libs.response import HandlerStatusResponse, HandlerResponse, RESPONSE_TYPE
label_desc: Use image node_id 3 for calling the WhatsAppMessagesTable obj's underlying member method code with example usage: obj.insert(query) and returns: pd