@@ -59,16 +59,16 @@ def get_provider_pk(self, provider_id: str) -> str:
5959 def get_channel_name (self , destination_id : str ) -> str :
6060 return f"{ self .provider .provider_config .name } _{ destination_id } "
6161
62- def get_sender_info (self , owner : str ) -> "UserDisplay | None" :
62+ def get_sender_info (self , sender : RavenUserId ) -> "UserDisplay | None" :
6363 raven_user = frappe .db .get_value (
64- "Raven User" , owner , ["full_name" , "user_image" ], as_dict = True
64+ "Raven User" , sender . user_id , ["full_name" , "user_image" ], as_dict = True
6565 )
6666 if not raven_user :
6767 return None
6868 icon_url = raven_user ["user_image" ]
6969 if icon_url and icon_url .startswith ("/" ):
7070 icon_url = get_url (icon_url )
71- return UserDisplay (name = raven_user ["full_name" ] or "" , icon_url = icon_url or None )
71+ return UserDisplay (name = raven_user ["full_name" ], icon_url = icon_url )
7272
7373 def get_user_id (self , channel_id : str ) -> str :
7474 """Return the provider user_id for a 1:1 customer channel via social login lookup."""
@@ -256,20 +256,34 @@ def create_raven_message(
256256 message : StdMessage ,
257257 sender_user : "User | None" = None ,
258258 provider_metadata : dict | None = None ,
259+ raven_user : "RavenUserId | None" = None ,
260+ raven_message_data : dict | None = None ,
259261 ) -> None :
260- owner = sender_user .name if sender_user else raven_channel .customer_user
261-
262262 doc = frappe .new_doc (doctype = "Raven Message" )
263263 doc .update (
264264 {
265265 "channel_id" : raven_channel .name ,
266266 "message_type" : message .type ,
267267 "is_customer_message" : True ,
268- "owner" : owner ,
269268 "omni_channel_msg_meta" : provider_metadata ,
270269 }
271270 )
272271
272+ if raven_user is not None :
273+ if raven_user .user_type == "Raven User" :
274+ doc .update (
275+ {
276+ "owner" : raven_user .user_id ,
277+ }
278+ )
279+ elif raven_user .user_type == "Raven Bot" :
280+ doc .update (
281+ {
282+ "is_bot_message" : True ,
283+ "bot" : raven_user .user_id ,
284+ }
285+ )
286+
273287 if isinstance (message , TextMessage ):
274288 doc .text = message .text
275289 elif isinstance (message , (ImageMessage , FileMessage )) and isinstance (
@@ -286,6 +300,8 @@ def create_raven_message(
286300 file_doc .insert (ignore_permissions = True )
287301 doc .file = file_doc .file_url
288302
303+ doc .update (raven_message_data or {})
304+
289305 doc .insert (ignore_permissions = True )
290306
291307 # ── Provider Message → Raven Message (inbound) ─────────────────────────────
@@ -343,6 +359,7 @@ def handle_outbound(self, raven_message: "RavenMessage") -> None:
343359 raven_message .is_customer_message
344360 or raven_message .is_bot_message
345361 or raven_message .message_type in ("System" , "Poll" )
362+ or raven_message .omni_channel_skip_push_to_provider
346363 ):
347364 return
348365
@@ -356,6 +373,40 @@ def handle_outbound(self, raven_message: "RavenMessage") -> None:
356373 return
357374
358375 destination_id = self .get_destination_id (raven_message .channel_id )
359- sender = self .get_sender_info (owner = raven_message .owner )
376+ sender = self .get_sender_info (
377+ owner = RavenUserId (user_type = "Raven User" , user_id = raven_message .owner )
378+ )
360379 outbound_msg = self .raven_to_std_msg (raven_message = raven_message , sender = sender )
361380 self .provider .send_message (destination_id = destination_id , message = outbound_msg )
381+
382+ # ── Inject ─────────────────────────────────────────────────────────────────
383+
384+ def handle_inject (
385+ self ,
386+ destination : ChatDestination ,
387+ std_message : StdMessage ,
388+ raven_user : RavenUserId ,
389+ ) -> None :
390+ """Handle programmatically injected messages, e.g. from a bot or workflow.
391+
392+ Saves the message to the Raven channel. The after_insert hook on RavenMessage
393+ automatically calls handle_outbound which pushes the message to the provider.
394+ """
395+ raven_channel = self .get_or_create_channel (
396+ destination = destination ,
397+ )
398+
399+ self .create_raven_message (
400+ raven_channel = raven_channel ,
401+ message = std_message ,
402+ raven_user = raven_user ,
403+ raven_message_data = {"omni_channel_skip_push_to_provider" : True },
404+ )
405+
406+ sender_info = self .get_sender_info (sender = raven_user )
407+ std_message .sender = sender_info
408+
409+ self .provider .send_message (
410+ destination_id = destination .destination_id ,
411+ message = std_message ,
412+ )
0 commit comments