Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -225,39 +225,79 @@ async def get_chatwoot_conversation(conversation_id: int) -> Optional[dict]:
|
|
| 225 |
|
| 226 |
msgs_resp.raise_for_status()
|
| 227 |
|
| 228 |
-
#
|
| 229 |
response_data = msgs_resp.json()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 230 |
|
| 231 |
-
# Extract messages from the response
|
| 232 |
-
messages = response_data.get('payload', [])
|
| 233 |
if not isinstance(messages, list):
|
| 234 |
-
print(f"β οΈ
|
| 235 |
return None
|
| 236 |
|
| 237 |
print(f"\nπ© Successfully parsed {len(messages)} messages")
|
| 238 |
if messages:
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
|
| 241 |
-
#
|
| 242 |
filtered_messages = []
|
| 243 |
for msg in messages:
|
| 244 |
-
|
| 245 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 246 |
filtered_msg = {
|
| 247 |
'id': msg.get('id'),
|
| 248 |
-
'content': msg
|
| 249 |
'created_at': msg.get('created_at'),
|
| 250 |
'sender': {
|
| 251 |
-
'type':
|
| 252 |
-
'name':
|
| 253 |
},
|
| 254 |
-
'message_type': msg.get('message_type')
|
|
|
|
| 255 |
}
|
| 256 |
filtered_messages.append(filtered_msg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
|
| 258 |
-
# Return the filtered messages with metadata
|
| 259 |
return {
|
| 260 |
-
'meta':
|
| 261 |
'payload': filtered_messages
|
| 262 |
}
|
| 263 |
|
|
@@ -428,6 +468,7 @@ async def _process_slack_command(conversation_id: str, response_url: str):
|
|
| 428 |
)
|
| 429 |
|
| 430 |
async def send_chatwoot_message(conversation_id: str, content: str):
|
|
|
|
| 431 |
message_payload = {
|
| 432 |
"content": content,
|
| 433 |
"message_type": "outgoing",
|
|
@@ -437,19 +478,53 @@ async def send_chatwoot_message(conversation_id: str, content: str):
|
|
| 437 |
}
|
| 438 |
|
| 439 |
try:
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 444 |
|
| 445 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 446 |
url,
|
| 447 |
-
headers=
|
| 448 |
-
|
| 449 |
-
"api_access_token": CHATWOOT_API_KEY,
|
| 450 |
-
},
|
| 451 |
-
json=message_payload,
|
| 452 |
)
|
| 453 |
-
print("π¬ Chatwoot Response:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 454 |
except Exception as e:
|
| 455 |
print("β Chatwoot Send Error:", e)
|
|
|
|
| 225 |
|
| 226 |
msgs_resp.raise_for_status()
|
| 227 |
|
| 228 |
+
# Parse the JSON response
|
| 229 |
response_data = msgs_resp.json()
|
| 230 |
+
print(f"π Response data type: {type(response_data).__name__}")
|
| 231 |
+
|
| 232 |
+
# Handle different response formats
|
| 233 |
+
if isinstance(response_data, dict):
|
| 234 |
+
# If the response has a 'payload' key, use that
|
| 235 |
+
messages = response_data.get('payload', [])
|
| 236 |
+
meta = response_data.get('meta', {})
|
| 237 |
+
elif isinstance(response_data, list):
|
| 238 |
+
# If the response is directly a list of messages
|
| 239 |
+
messages = response_data
|
| 240 |
+
meta = {}
|
| 241 |
+
else:
|
| 242 |
+
print(f"β οΈ Unexpected response format: {type(response_data)}")
|
| 243 |
+
return None
|
| 244 |
|
|
|
|
|
|
|
| 245 |
if not isinstance(messages, list):
|
| 246 |
+
print(f"β οΈ Messages is not a list: {type(messages)}")
|
| 247 |
return None
|
| 248 |
|
| 249 |
print(f"\nπ© Successfully parsed {len(messages)} messages")
|
| 250 |
if messages:
|
| 251 |
+
first_msg = messages[0]
|
| 252 |
+
print(f"First message type: {type(first_msg).__name__}")
|
| 253 |
+
print(f"First message keys: {list(first_msg.keys()) if hasattr(first_msg, 'keys') else 'N/A'}")
|
| 254 |
|
| 255 |
+
# Process and filter messages
|
| 256 |
filtered_messages = []
|
| 257 |
for msg in messages:
|
| 258 |
+
try:
|
| 259 |
+
# Skip if no content or sender info
|
| 260 |
+
if not msg.get('content') or not isinstance(msg.get('content'), str):
|
| 261 |
+
continue
|
| 262 |
+
|
| 263 |
+
# Get sender info, handle different formats
|
| 264 |
+
sender = msg.get('sender', {})
|
| 265 |
+
sender_type = None
|
| 266 |
+
sender_name = 'Unknown'
|
| 267 |
+
|
| 268 |
+
if isinstance(sender, dict):
|
| 269 |
+
sender_type = sender.get('type')
|
| 270 |
+
sender_name = sender.get('name') or sender.get('available_name', 'Unknown')
|
| 271 |
+
|
| 272 |
+
# Only include relevant message types
|
| 273 |
+
if sender_type not in ['contact', 'user', 'agent']:
|
| 274 |
+
continue
|
| 275 |
+
|
| 276 |
+
# Create the filtered message
|
| 277 |
filtered_msg = {
|
| 278 |
'id': msg.get('id'),
|
| 279 |
+
'content': msg['content'],
|
| 280 |
'created_at': msg.get('created_at'),
|
| 281 |
'sender': {
|
| 282 |
+
'type': sender_type,
|
| 283 |
+
'name': sender_name
|
| 284 |
},
|
| 285 |
+
'message_type': 'incoming' if msg.get('message_type') == 0 else 'outgoing',
|
| 286 |
+
'timestamp': msg.get('created_at')
|
| 287 |
}
|
| 288 |
filtered_messages.append(filtered_msg)
|
| 289 |
+
|
| 290 |
+
except Exception as e:
|
| 291 |
+
print(f"β οΈ Error processing message {msg.get('id')}: {str(e)}")
|
| 292 |
+
continue
|
| 293 |
+
|
| 294 |
+
print(f"β
Filtered to {len(filtered_messages)} relevant messages")
|
| 295 |
+
|
| 296 |
+
# Sort messages by timestamp if available
|
| 297 |
+
filtered_messages.sort(key=lambda x: x.get('timestamp', 0))
|
| 298 |
|
|
|
|
| 299 |
return {
|
| 300 |
+
'meta': meta,
|
| 301 |
'payload': filtered_messages
|
| 302 |
}
|
| 303 |
|
|
|
|
| 468 |
)
|
| 469 |
|
| 470 |
async def send_chatwoot_message(conversation_id: str, content: str):
|
| 471 |
+
"""Send a message to a Chatwoot conversation"""
|
| 472 |
message_payload = {
|
| 473 |
"content": content,
|
| 474 |
"message_type": "outgoing",
|
|
|
|
| 478 |
}
|
| 479 |
|
| 480 |
try:
|
| 481 |
+
url = f"{CHATWOOT_BASE_URL}/api/v1/accounts/{CHATWOOT_ACCOUNT_ID}/conversations/{conversation_id}/messages"
|
| 482 |
+
headers = {
|
| 483 |
+
"Content-Type": "application/json",
|
| 484 |
+
"api_access_token": CHATWOOT_API_KEY,
|
| 485 |
+
}
|
| 486 |
+
|
| 487 |
+
print(f"π€ Sending to Chatwoot: {url}")
|
| 488 |
+
print(f"π Using API key: {CHATWOOT_API_KEY[:5]}..." if CHATWOOT_API_KEY else "β No API key provided!")
|
| 489 |
+
print("π¦ Payload:", json.dumps(message_payload, indent=2))
|
| 490 |
+
print("π Headers:", json.dumps({k: '***' if 'token' in k.lower() or 'key' in k.lower() else v for k, v in headers.items()}, indent=2))
|
| 491 |
|
| 492 |
+
async with httpx.AsyncClient() as http:
|
| 493 |
+
# First, try to get the conversation to verify access
|
| 494 |
+
conv_url = f"{CHATWOOT_BASE_URL}/api/v1/accounts/{CHATWOOT_ACCOUNT_ID}/conversations/{conversation_id}"
|
| 495 |
+
print(f"π Checking conversation access: {conv_url}")
|
| 496 |
+
|
| 497 |
+
# Test GET request to verify conversation access
|
| 498 |
+
test_resp = await http.get(conv_url, headers=headers)
|
| 499 |
+
print(f"π Conversation check status: {test_resp.status_code}")
|
| 500 |
+
print(f"π Response: {test_resp.text[:500]}..." if test_resp.text else "No response body")
|
| 501 |
+
|
| 502 |
+
if test_resp.status_code != 200:
|
| 503 |
+
error_msg = f"Failed to access conversation: {test_resp.status_code} - {test_resp.text}"
|
| 504 |
+
print(f"β {error_msg}")
|
| 505 |
+
return {"status": "error", "message": error_msg}
|
| 506 |
+
|
| 507 |
+
# If we can access the conversation, try to send the message
|
| 508 |
+
print("β
Conversation access verified. Sending message...")
|
| 509 |
+
resp = await http.post(
|
| 510 |
url,
|
| 511 |
+
headers=headers,
|
| 512 |
+
json=message_payload
|
|
|
|
|
|
|
|
|
|
| 513 |
)
|
| 514 |
+
print(f"π¬ Chatwoot Response Status: {resp.status_code}")
|
| 515 |
+
print(f"π¬ Response Body: {resp.text}")
|
| 516 |
+
|
| 517 |
+
if resp.status_code != 200:
|
| 518 |
+
error_msg = f"Failed to send message: {resp.status_code} - {resp.text}"
|
| 519 |
+
print(f"β {error_msg}")
|
| 520 |
+
return {"status": "error", "message": error_msg}
|
| 521 |
+
|
| 522 |
+
return {"status": "success", "data": resp.json()}
|
| 523 |
+
|
| 524 |
+
except httpx.HTTPStatusError as e:
|
| 525 |
+
error_msg = f"HTTP error occurred: {str(e)}"
|
| 526 |
+
print(f"β {error_msg}")
|
| 527 |
+
print(f"Response: {e.response.text if hasattr(e, 'response') else 'No response'}")
|
| 528 |
+
return {"status": "error", "message": error_msg}
|
| 529 |
except Exception as e:
|
| 530 |
print("β Chatwoot Send Error:", e)
|