rust_rcs_client/messaging/cpm/sip/
cpm_contact.rs1use rust_rcs_core::internet::{
16 name_addr::AsNameAddr, parameter::ParameterParser, AsURI, HeaderField,
17};
18
19pub enum CPMServiceType {
20 OneToOne,
21 Group,
22 Chatbot,
23 System,
24}
25
26pub struct CPMContact {
27 pub service_uri: Vec<u8>,
28
29 pub service_type: CPMServiceType,
30
31 pub service_support_message_revoke: bool,
32 pub service_support_network_fallback: bool,
33}
34
35pub trait AsCPMContact {
36 type Target;
37 fn as_cpm_contact(&self) -> Option<Self::Target>;
38}
39
40impl AsCPMContact for HeaderField<'_> {
41 type Target = CPMContact;
42
43 fn as_cpm_contact(&self) -> Option<Self::Target> {
44 if let Some(name_addr) = self.value.as_name_addresses().first() {
45 if let Some(uri_part) = &name_addr.uri_part {
46 if let Some(uri) = uri_part.uri.as_standard_uri() {
47 let contact_uri = uri.string_representation_without_query_and_fragment();
48
49 let mut service_type = CPMServiceType::OneToOne;
50
51 let mut service_support_message_revoke = false;
52 let mut service_support_network_fallback = false;
53
54 if let Some(contact) = uri.get_query_value(b"contact") {
55 if let Ok(contact) = std::str::from_utf8(contact) {
56 if let Ok(contact) = urlencoding::decode(contact) {
57 for p in ParameterParser::new(contact.as_bytes(), b';', false) {
58 if p.name.eq_ignore_ascii_case(b"+g.gsma.rcs.isbot") {
59 service_type = CPMServiceType::Chatbot;
60 break;
61 }
62 }
63 }
64 }
65 }
66
67 for p in uri_part.get_parameter_iterator() {
68 if p.name.eq_ignore_ascii_case(b"isfocus") {
69 service_type = CPMServiceType::Group;
70 } else if p.name.eq_ignore_ascii_case(b"+g.gsma.rcs.msgrevoke") {
71 service_support_message_revoke = true;
72 } else if p.name.eq_ignore_ascii_case(b"+g.gsma.rcs.msgfallback") {
73 service_support_network_fallback = true;
74 }
75 }
76
77 return Some(CPMContact {
78 service_uri: contact_uri,
79 service_type,
80 service_support_message_revoke,
81 service_support_network_fallback,
82 });
83 }
84 }
85 }
86
87 None
88 }
89}