rust_rcs_client/messaging/cpm/sip/
cpm_contact.rs

1// Copyright 2023 宋昊文
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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}