use super::*;
pub fn extract_ciphertext(msg: CiphertextMessage) -> Option<(&'static str, bool, Box<[u8]>)> {
match msg {
CiphertextMessage::SignalMessage(m) => {
Some((stanza::ENC_TYPE_MSG, false, m.into_serialized()))
}
CiphertextMessage::PreKeySignalMessage(m) => {
Some((stanza::ENC_TYPE_PKMSG, true, m.into_serialized()))
}
_ => None,
}
}
pub(crate) fn unwrap_message(msg: &wa::Message) -> &wa::Message {
macro_rules! try_unwrap {
($($field:ident),+ $(,)?) => {
$(
if let Some(w) = msg.$field.as_option() {
if let Some(inner) = w.message.as_option() {
return unwrap_message(inner);
}
}
)+
};
}
try_unwrap!(
ephemeral_message,
view_once_message,
view_once_message_v2,
view_once_message_v2_extension,
document_with_caption_message,
group_mentioned_message,
bot_invoke_message,
associated_child_message,
poll_creation_option_image_message,
event_cover_image,
group_status_message,
group_status_message_v2,
group_status_mention_message,
status_add_yours,
status_mention_message,
question_message,
question_reply_message,
spoiler_message,
lottie_sticker_message,
limit_sharing_message,
newsletter_admin_profile_message,
newsletter_admin_profile_message_v2,
poll_creation_message_v4,
);
if let Some(dsm) = msg.device_sent_message.as_option()
&& let Some(inner) = dsm.message.as_option()
{
return unwrap_message(inner);
}
msg
}
pub fn stanza_type_from_message(msg: &wa::Message) -> &'static str {
let msg = unwrap_message(msg);
if msg.reaction_message.is_set() || msg.enc_reaction_message.is_set() {
return stanza::MSG_TYPE_REACTION;
}
if msg.event_message.is_set() || msg.enc_event_response_message.is_set() {
return stanza::MSG_TYPE_EVENT;
}
if let Some(sec) = msg.secret_encrypted_message.as_option() {
use wa::message::secret_encrypted_message::SecretEncType;
match sec.secret_enc_type {
Some(SecretEncType::EventEdit) => return stanza::MSG_TYPE_EVENT,
Some(SecretEncType::MessageEdit) => return stanza::MSG_TYPE_TEXT,
Some(SecretEncType::PollEdit | SecretEncType::PollAddOption) => {
return stanza::MSG_TYPE_POLL;
}
_ => {}
}
}
if msg.poll_creation_message.is_set()
|| msg.poll_creation_message_v2.is_set()
|| msg.poll_creation_message_v3.is_set()
|| msg.poll_creation_message_v5.is_set()
|| msg.poll_update_message.is_set()
{
return stanza::MSG_TYPE_POLL;
}
if msg.conversation.is_some()
|| msg.protocol_message.is_set()
|| msg.keep_in_chat_message.is_set()
|| msg.edited_message.is_set()
|| msg.pin_in_chat_message.is_set()
|| msg.interactive_message.is_set()
|| msg.template_button_reply_message.is_set()
|| msg.request_phone_number_message.is_set()
|| msg.enc_comment_message.is_set()
|| msg.newsletter_admin_invite_message.is_set()
|| msg.newsletter_follower_invite_message_v2.is_set()
|| msg.message_history_notice.is_set()
|| msg.album_message.is_set()
|| msg.request_payment_message.is_set()
|| msg.send_payment_message.is_set()
|| msg.payment_invite_message.is_set()
|| msg.decline_payment_request_message.is_set()
|| msg.cancel_payment_request_message.is_set()
{
return stanza::MSG_TYPE_TEXT;
}
if msg.poll_result_snapshot_message.is_set() || msg.poll_result_snapshot_message_v3.is_set() {
return stanza::MSG_TYPE_TEXT;
}
if let Some(ext) = msg.extended_text_message.as_option() {
if ext
.matched_text
.as_ref()
.is_some_and(|t| !t.trim().is_empty())
{
return stanza::MSG_TYPE_MEDIA;
}
return stanza::MSG_TYPE_TEXT;
}
stanza::MSG_TYPE_MEDIA
}
pub fn peer_message_options_from_message(msg: &wa::Message) -> PeerMessageOptions {
use wa::message::PeerDataOperationRequestType as PdoType;
let request_type = unwrap_message(msg)
.protocol_message
.as_option()
.and_then(|pm| pm.peer_data_operation_request_message.as_option())
.and_then(|pdo| pdo.peer_data_operation_request_type);
match request_type {
Some(PdoType::HistorySyncOnDemand) => PeerMessageOptions::high_force_on_demand(),
Some(
PdoType::GenerateLinkPreview
| PdoType::PlaceholderMessageResend
| PdoType::CompanionCanonicalUserNonceFetch,
) => PeerMessageOptions::high_force(),
_ => PeerMessageOptions::default(),
}
}
pub fn media_type_from_message(msg: &wa::Message) -> Option<&'static str> {
if msg.lottie_sticker_message.is_set() {
return Some("sticker");
}
let msg = unwrap_message(msg);
if msg.image_message.is_set() {
return Some("image");
}
if let Some(vid) = msg.video_message.as_option() {
return if vid.gif_playback == Some(true) {
Some("gif")
} else {
Some("video")
};
}
if msg.ptv_message.is_set() {
return Some("ptv");
}
if let Some(audio) = msg.audio_message.as_option() {
return if audio.ptt == Some(true) {
Some("ptt")
} else {
Some("audio")
};
}
if msg.document_message.is_set() {
return Some("document");
}
if msg.sticker_message.is_set() {
return Some("sticker");
}
if msg.sticker_pack_message.is_set() {
return Some("sticker_pack");
}
if let Some(loc) = msg.location_message.as_option() {
return if loc.is_live == Some(true) {
Some("livelocation")
} else {
Some("location")
};
}
if msg.live_location_message.is_set() {
return Some("livelocation");
}
if msg.contact_message.is_set() {
return Some("vcard");
}
if msg.contacts_array_message.is_set() {
return Some("contact_array");
}
if let Some(ext) = msg.extended_text_message.as_option()
&& ext
.matched_text
.as_ref()
.is_some_and(|t| !t.trim().is_empty())
{
return Some("url");
}
if msg.group_invite_message.is_set() {
return Some("url");
}
if msg.list_message.is_set() {
return Some("list");
}
if msg.list_response_message.is_set() {
return Some("list_response");
}
if msg.buttons_response_message.is_set() {
return Some("buttons_response");
}
if msg.order_message.is_set() {
return Some("order");
}
if msg.product_message.is_set() {
return Some("product");
}
if msg.interactive_response_message.is_set() {
return Some("native_flow_response");
}
if msg.message_history_bundle.is_set() {
return Some("group_history");
}
None
}
pub fn should_hide_decrypt_fail_for_send(
edit: Option<&crate::types::message::EditAttribute>,
msg: &wa::Message,
) -> bool {
use crate::types::message::EditAttribute;
edit.is_some_and(|e| {
*e != EditAttribute::Empty
&& *e != EditAttribute::AdminRevoke
&& *e != EditAttribute::SenderRevoke
}) || should_hide_decrypt_fail(msg)
}
pub fn should_hide_decrypt_fail(msg: &wa::Message) -> bool {
let msg = unwrap_message(msg);
use wa::message::protocol_message::Type as ProtocolType;
use wa::message::secret_encrypted_message::SecretEncType;
msg.reaction_message.is_set()
|| msg.enc_reaction_message.is_set()
|| msg.pin_in_chat_message.is_set()
|| msg.edited_message.is_set()
|| msg.keep_in_chat_message.is_set()
|| msg.enc_event_response_message.is_set()
|| msg
.poll_update_message
.as_option()
.is_some_and(|p| p.vote.is_set())
|| msg.message_history_notice.is_set()
|| msg.conditional_reveal_message.is_set()
|| msg.secret_encrypted_message.as_option().is_some_and(|s| {
matches!(
s.secret_enc_type,
Some(
SecretEncType::EventEdit
| SecretEncType::PollEdit
| SecretEncType::PollAddOption
)
)
})
|| msg
.bot_invoke_message
.as_option()
.and_then(|b| b.message.as_option())
.and_then(|m| m.protocol_message.as_option())
.is_some_and(|p| p.r#type == Some(ProtocolType::RequestWelcomeMessage))
|| msg.protocol_message.as_option().is_some_and(|p| {
matches!(
p.r#type,
Some(t) if t == ProtocolType::EphemeralSyncResponse
|| t == ProtocolType::RequestWelcomeMessage
|| t == ProtocolType::GroupMemberLabelChange
) || p.edited_message.is_set()
})
}