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)
|