Skip to content

Commit b74728b

Browse files
committed
feat: support line group
1 parent 80889c6 commit b74728b

5 files changed

Lines changed: 69 additions & 20 deletions

File tree

raven/omni_channel_chat/omni_channel_raven_connector.py

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
)

raven/raven_channel_management/doctype/raven_channel/raven_channel.json

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
"last_message_timestamp",
2929
"dm_user_1",
3030
"dm_user_2",
31-
"customer_user",
3231
"omni_channel_chat_provider",
3332
"omni_channel_destination_id",
3433
"column_break_eckt",
@@ -237,14 +236,6 @@
237236
"label": "Is Customer",
238237
"set_only_once": 1
239238
},
240-
{
241-
"depends_on": "eval:doc.is_customer;",
242-
"fieldname": "customer_user",
243-
"fieldtype": "Link",
244-
"label": "Customer",
245-
"options": "Raven User",
246-
"read_only": 1
247-
},
248239
{
249240
"depends_on": "eval:doc.is_customer;",
250241
"fieldname": "omni_channel_chat_provider",
@@ -271,7 +262,7 @@
271262
"link_fieldname": "channel_id"
272263
}
273264
],
274-
"modified": "2026-04-19 14:41:55.728586",
265+
"modified": "2026-04-22 13:32:23.357346",
275266
"modified_by": "Administrator",
276267
"module": "Raven Channel Management",
277268
"name": "Raven Channel",

raven/raven_channel_management/doctype/raven_channel/raven_channel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ class RavenChannel(Document):
2020

2121
channel_description: DF.SmallText | None
2222
channel_name: DF.Data
23-
customer_user: DF.Link | None
2423
dm_user_1: DF.Link | None
2524
dm_user_2: DF.Link | None
2625
is_ai_thread: DF.Check
@@ -36,6 +35,7 @@ class RavenChannel(Document):
3635
linked_doctype: DF.Link | None
3736
linked_document: DF.DynamicLink | None
3837
omni_channel_chat_provider: DF.Link | None
38+
omni_channel_destination_id: DF.Data | None
3939
openai_thread_id: DF.Data | None
4040
pinned_messages: DF.Table[RavenPinnedMessages]
4141
pinned_messages_string: DF.SmallText | None

raven/raven_messaging/doctype/raven_message/raven_message.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"hide_link_preview",
3939
"notification",
4040
"is_customer_message",
41+
"omni_channel_skip_push_to_provider",
4142
"omni_channel_msg_meta"
4243
],
4344
"fields": [
@@ -221,11 +222,17 @@
221222
"fieldname": "omni_channel_msg_meta",
222223
"fieldtype": "JSON",
223224
"label": "Omni-Channel Message Meta"
225+
},
226+
{
227+
"default": "0",
228+
"fieldname": "omni_channel_skip_push_to_provider",
229+
"fieldtype": "Check",
230+
"label": "Omni-channel Skip Push to Provider"
224231
}
225232
],
226233
"index_web_pages_for_search": 1,
227234
"links": [],
228-
"modified": "2026-04-19 16:05:30.311091",
235+
"modified": "2026-04-22 13:42:16.280165",
229236
"modified_by": "Administrator",
230237
"module": "Raven Messaging",
231238
"name": "Raven Message",

raven/raven_messaging/doctype/raven_message/raven_message.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ class RavenMessage(Document):
3434

3535
if TYPE_CHECKING:
3636
from frappe.types import DF
37-
3837
from raven.raven_messaging.doctype.raven_mention.raven_mention import RavenMention
3938

4039
blurhash: DF.SmallText | None
@@ -62,6 +61,7 @@ class RavenMessage(Document):
6261
message_type: DF.Literal["Text", "Image", "File", "Poll", "System"]
6362
notification: DF.Data | None
6463
omni_channel_msg_meta: DF.JSON | None
64+
omni_channel_skip_push_to_provider: DF.Check
6565
poll_id: DF.Link | None
6666
replied_message_details: DF.JSON | None
6767
text: DF.LongText | None

0 commit comments

Comments
 (0)