Fix all integrations
This commit is contained in:
@@ -2105,45 +2105,28 @@ class WhatsAppClient(ClientBase):
|
||||
"""
|
||||
Extract user-visible text from diverse WhatsApp message payload shapes.
|
||||
"""
|
||||
candidates = (
|
||||
self._pluck(msg_obj, "conversation"),
|
||||
self._pluck(msg_obj, "Conversation"),
|
||||
self._pluck(msg_obj, "extendedTextMessage", "text"),
|
||||
self._pluck(msg_obj, "ExtendedTextMessage", "Text"),
|
||||
self._pluck(msg_obj, "extended_text_message", "text"),
|
||||
self._pluck(msg_obj, "imageMessage", "caption"),
|
||||
self._pluck(msg_obj, "videoMessage", "caption"),
|
||||
self._pluck(msg_obj, "documentMessage", "caption"),
|
||||
self._pluck(msg_obj, "ephemeralMessage", "message", "conversation"),
|
||||
self._pluck(
|
||||
msg_obj, "ephemeralMessage", "message", "extendedTextMessage", "text"
|
||||
),
|
||||
self._pluck(msg_obj, "viewOnceMessage", "message", "conversation"),
|
||||
self._pluck(
|
||||
msg_obj, "viewOnceMessage", "message", "extendedTextMessage", "text"
|
||||
),
|
||||
self._pluck(msg_obj, "viewOnceMessageV2", "message", "conversation"),
|
||||
self._pluck(
|
||||
msg_obj, "viewOnceMessageV2", "message", "extendedTextMessage", "text"
|
||||
),
|
||||
self._pluck(
|
||||
msg_obj, "viewOnceMessageV2Extension", "message", "conversation"
|
||||
),
|
||||
self._pluck(
|
||||
msg_obj,
|
||||
"viewOnceMessageV2Extension",
|
||||
"message",
|
||||
"extendedTextMessage",
|
||||
"text",
|
||||
),
|
||||
for candidate in self._iter_message_variants(msg_obj):
|
||||
for value in (
|
||||
self._pluck(candidate, "conversation"),
|
||||
self._pluck(candidate, "Conversation"),
|
||||
self._pluck(candidate, "extendedTextMessage", "text"),
|
||||
self._pluck(candidate, "ExtendedTextMessage", "Text"),
|
||||
self._pluck(candidate, "extended_text_message", "text"),
|
||||
self._pluck(candidate, "imageMessage", "caption"),
|
||||
self._pluck(candidate, "videoMessage", "caption"),
|
||||
self._pluck(candidate, "documentMessage", "caption"),
|
||||
):
|
||||
text = str(value or "").strip()
|
||||
if text:
|
||||
return text
|
||||
for value in (
|
||||
self._pluck(event_obj, "message", "conversation"),
|
||||
self._pluck(event_obj, "message", "extendedTextMessage", "text"),
|
||||
self._pluck(event_obj, "Message", "conversation"),
|
||||
self._pluck(event_obj, "Message", "extendedTextMessage", "text"),
|
||||
self._pluck(event_obj, "conversation"),
|
||||
self._pluck(event_obj, "text"),
|
||||
)
|
||||
for value in candidates:
|
||||
):
|
||||
text = str(value or "").strip()
|
||||
if text:
|
||||
return text
|
||||
@@ -2318,7 +2301,40 @@ class WhatsAppClient(ClientBase):
|
||||
return str(user)
|
||||
return raw
|
||||
|
||||
def _is_media_message(self, message_obj):
|
||||
def _iter_message_variants(self, message_obj, max_depth: int = 8):
|
||||
wrapper_paths = (
|
||||
("deviceSentMessage", "message"),
|
||||
("DeviceSentMessage", "Message"),
|
||||
("ephemeralMessage", "message"),
|
||||
("EphemeralMessage", "Message"),
|
||||
("viewOnceMessage", "message"),
|
||||
("ViewOnceMessage", "Message"),
|
||||
("viewOnceMessageV2", "message"),
|
||||
("ViewOnceMessageV2", "Message"),
|
||||
("viewOnceMessageV2Extension", "message"),
|
||||
("ViewOnceMessageV2Extension", "Message"),
|
||||
("editedMessage", "message"),
|
||||
("EditedMessage", "Message"),
|
||||
)
|
||||
queue = [(message_obj, 0)]
|
||||
seen = set()
|
||||
while queue:
|
||||
current, depth = queue.pop(0)
|
||||
if current is None:
|
||||
continue
|
||||
marker = id(current)
|
||||
if marker in seen:
|
||||
continue
|
||||
seen.add(marker)
|
||||
yield current
|
||||
if depth >= max_depth:
|
||||
continue
|
||||
for path in wrapper_paths:
|
||||
nested = self._pluck(current, *path)
|
||||
if nested is not None:
|
||||
queue.append((nested, depth + 1))
|
||||
|
||||
def _direct_media_payload(self, message_obj):
|
||||
media_fields = (
|
||||
"imageMessage",
|
||||
"videoMessage",
|
||||
@@ -2334,8 +2350,17 @@ class WhatsAppClient(ClientBase):
|
||||
for field in media_fields:
|
||||
value = self._pluck(message_obj, field)
|
||||
if value:
|
||||
return True
|
||||
return False
|
||||
return value
|
||||
return None
|
||||
|
||||
def _resolve_media_message(self, message_obj):
|
||||
for candidate in self._iter_message_variants(message_obj):
|
||||
if self._direct_media_payload(candidate):
|
||||
return candidate
|
||||
return None
|
||||
|
||||
def _is_media_message(self, message_obj):
|
||||
return self._resolve_media_message(message_obj) is not None
|
||||
|
||||
def _infer_media_content_type(self, message_obj):
|
||||
if self._pluck(message_obj, "imageMessage") or self._pluck(
|
||||
@@ -2439,13 +2464,14 @@ class WhatsAppClient(ClientBase):
|
||||
if not self._client:
|
||||
return []
|
||||
msg_obj = self._pluck(event, "message") or self._pluck(event, "Message")
|
||||
if msg_obj is None or not self._is_media_message(msg_obj):
|
||||
media_msg = self._resolve_media_message(msg_obj)
|
||||
if media_msg is None:
|
||||
return []
|
||||
if not hasattr(self._client, "download_any"):
|
||||
return []
|
||||
|
||||
try:
|
||||
payload = await self._maybe_await(self._client.download_any(msg_obj))
|
||||
payload = await self._maybe_await(self._client.download_any(media_msg))
|
||||
except Exception as exc:
|
||||
self.log.warning("whatsapp media download failed: %s", exc)
|
||||
return []
|
||||
@@ -2455,19 +2481,21 @@ class WhatsAppClient(ClientBase):
|
||||
if not isinstance(payload, (bytes, bytearray)):
|
||||
return []
|
||||
|
||||
filename = self._pluck(msg_obj, "documentMessage", "fileName") or self._pluck(
|
||||
msg_obj, "document_message", "file_name"
|
||||
filename = self._pluck(
|
||||
media_msg, "documentMessage", "fileName"
|
||||
) or self._pluck(
|
||||
media_msg, "document_message", "file_name"
|
||||
)
|
||||
content_type = (
|
||||
self._pluck(msg_obj, "documentMessage", "mimetype")
|
||||
or self._pluck(msg_obj, "document_message", "mimetype")
|
||||
or self._pluck(msg_obj, "imageMessage", "mimetype")
|
||||
or self._pluck(msg_obj, "image_message", "mimetype")
|
||||
or self._pluck(msg_obj, "videoMessage", "mimetype")
|
||||
or self._pluck(msg_obj, "video_message", "mimetype")
|
||||
or self._pluck(msg_obj, "audioMessage", "mimetype")
|
||||
or self._pluck(msg_obj, "audio_message", "mimetype")
|
||||
or self._infer_media_content_type(msg_obj)
|
||||
self._pluck(media_msg, "documentMessage", "mimetype")
|
||||
or self._pluck(media_msg, "document_message", "mimetype")
|
||||
or self._pluck(media_msg, "imageMessage", "mimetype")
|
||||
or self._pluck(media_msg, "image_message", "mimetype")
|
||||
or self._pluck(media_msg, "videoMessage", "mimetype")
|
||||
or self._pluck(media_msg, "video_message", "mimetype")
|
||||
or self._pluck(media_msg, "audioMessage", "mimetype")
|
||||
or self._pluck(media_msg, "audio_message", "mimetype")
|
||||
or self._infer_media_content_type(media_msg)
|
||||
)
|
||||
if not filename:
|
||||
ext = mimetypes.guess_extension(
|
||||
@@ -2651,6 +2679,38 @@ class WhatsAppClient(ClientBase):
|
||||
if not identifiers:
|
||||
return
|
||||
|
||||
is_self_chat = bool(
|
||||
is_from_me
|
||||
and str(sender or "").strip()
|
||||
and str(chat or "").strip()
|
||||
and str(sender).strip() == str(chat).strip()
|
||||
)
|
||||
if is_self_chat and str(text or "").strip().startswith("."):
|
||||
responded_user_ids = set()
|
||||
reply_target = str(chat or sender or "").strip()
|
||||
for identifier in identifiers:
|
||||
if identifier.user_id in responded_user_ids:
|
||||
continue
|
||||
responded_user_ids.add(identifier.user_id)
|
||||
replies = await self.ur.xmpp.client.execute_gateway_command(
|
||||
sender_user=identifier.user,
|
||||
body=text,
|
||||
service=self.service,
|
||||
channel_identifier=str(identifier.identifier or ""),
|
||||
sender_identifier=str(identifier.identifier or ""),
|
||||
local_message=None,
|
||||
message_meta={
|
||||
"whatsapp": {
|
||||
"sender": str(sender or ""),
|
||||
"chat": str(chat or ""),
|
||||
"self_chat": True,
|
||||
}
|
||||
},
|
||||
)
|
||||
for line in replies:
|
||||
await self.send_message_raw(reply_target, f"[>] {line}")
|
||||
return
|
||||
|
||||
attachments = await self._download_event_media(event)
|
||||
xmpp_attachments = []
|
||||
if attachments:
|
||||
@@ -3186,28 +3246,20 @@ class WhatsAppClient(ClientBase):
|
||||
url = (attachment or {}).get("url")
|
||||
if url:
|
||||
safe_url = validate_attachment_url(url)
|
||||
timeout = aiohttp.ClientTimeout(total=20)
|
||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||
async with session.get(safe_url) as response:
|
||||
if response.status != 200:
|
||||
return None
|
||||
payload = await response.read()
|
||||
filename, content_type = validate_attachment_metadata(
|
||||
filename=(attachment or {}).get("filename")
|
||||
or safe_url.rstrip("/").split("/")[-1]
|
||||
or "attachment.bin",
|
||||
content_type=(attachment or {}).get("content_type")
|
||||
or response.headers.get(
|
||||
"Content-Type", "application/octet-stream"
|
||||
),
|
||||
size=len(payload),
|
||||
)
|
||||
return {
|
||||
"content": payload,
|
||||
"filename": filename,
|
||||
"content_type": content_type,
|
||||
"size": len(payload),
|
||||
}
|
||||
filename, content_type = validate_attachment_metadata(
|
||||
filename=(attachment or {}).get("filename")
|
||||
or safe_url.rstrip("/").split("/")[-1]
|
||||
or "attachment.bin",
|
||||
content_type=(attachment or {}).get("content_type")
|
||||
or "application/octet-stream",
|
||||
size=(attachment or {}).get("size"),
|
||||
)
|
||||
return {
|
||||
"url": safe_url,
|
||||
"filename": filename,
|
||||
"content_type": content_type,
|
||||
"size": (attachment or {}).get("size"),
|
||||
}
|
||||
return None
|
||||
|
||||
async def send_message_raw(
|
||||
@@ -3364,18 +3416,26 @@ class WhatsAppClient(ClientBase):
|
||||
payload = await self._fetch_attachment_payload(attachment)
|
||||
if not payload:
|
||||
continue
|
||||
data = payload.get("content") or b""
|
||||
data = payload.get("content")
|
||||
source_url = str(payload.get("url") or "").strip()
|
||||
try:
|
||||
filename, mime = validate_attachment_metadata(
|
||||
filename=payload.get("filename") or "attachment.bin",
|
||||
content_type=payload.get("content_type")
|
||||
or "application/octet-stream",
|
||||
size=payload.get("size")
|
||||
or (len(data) if isinstance(data, (bytes, bytearray)) else 0),
|
||||
or (len(data) if isinstance(data, (bytes, bytearray)) else None),
|
||||
)
|
||||
except Exception as exc:
|
||||
self.log.warning("whatsapp blocked attachment: %s", exc)
|
||||
continue
|
||||
file_arg = (
|
||||
data
|
||||
if isinstance(data, (bytes, bytearray))
|
||||
else source_url
|
||||
)
|
||||
if not file_arg:
|
||||
continue
|
||||
mime = str(mime).lower()
|
||||
attachment_target = jid_obj if jid_obj is not None else jid
|
||||
send_method = "document"
|
||||
@@ -3392,27 +3452,31 @@ class WhatsAppClient(ClientBase):
|
||||
send_method,
|
||||
mime,
|
||||
filename,
|
||||
len(data) if isinstance(data, (bytes, bytearray)) else 0,
|
||||
(
|
||||
len(data)
|
||||
if isinstance(data, (bytes, bytearray))
|
||||
else (payload.get("size") or 0)
|
||||
),
|
||||
)
|
||||
|
||||
try:
|
||||
if mime.startswith("image/") and hasattr(self._client, "send_image"):
|
||||
response = await self._maybe_await(
|
||||
self._client.send_image(attachment_target, data, caption="")
|
||||
self._client.send_image(attachment_target, file_arg, caption="")
|
||||
)
|
||||
elif mime.startswith("video/") and hasattr(self._client, "send_video"):
|
||||
response = await self._maybe_await(
|
||||
self._client.send_video(attachment_target, data, caption="")
|
||||
self._client.send_video(attachment_target, file_arg, caption="")
|
||||
)
|
||||
elif mime.startswith("audio/") and hasattr(self._client, "send_audio"):
|
||||
response = await self._maybe_await(
|
||||
self._client.send_audio(attachment_target, data)
|
||||
self._client.send_audio(attachment_target, file_arg)
|
||||
)
|
||||
elif hasattr(self._client, "send_document"):
|
||||
response = await self._maybe_await(
|
||||
self._client.send_document(
|
||||
attachment_target,
|
||||
data,
|
||||
file_arg,
|
||||
filename=filename,
|
||||
mimetype=mime,
|
||||
caption="",
|
||||
|
||||
Reference in New Issue
Block a user