use crate::MessageID;
use crate::ThreemaID;
use flat_bytes::flat_enum;
use flat_bytes::Flat;
use serde::de::Error;
use serde::de::Unexpected;
use serde::de::Visitor;
use serde::Deserializer;
use serde::Serializer;
use serde::{Deserialize, Serialize};
use serde_json::{from_slice, to_vec};
flat_enum! {
#[derive(Debug)]
#[repr(u32)]
pub enum Packet {
EchoRequest(u64) = 0,
EchoReply(u64) = 0x80,
OutgoingMessage(Header) = 1,
OutgoingMessageAck(ThreemaID, MessageID) = 0x81,
IncomingMessage(Header) = 2,
IncomingMessageAck(ThreemaID, MessageID) = 0x82,
PushNotificationToken = 0x20,
PushAllowedIdentities = 0x21,
VoipPushNotificationToken = 0x24,
QueueSendComplete = 0xd0,
LastEphemeralKeyHash = 0xd1,
Error = 0xe0,
Alert = 0xe1,
}
}
pub type BallotID = [u8; 8];
flat_enum! {
#[derive(Debug)]
#[repr(u8)]
pub enum Message {
Text(Text) = 1,
Image,
Location = 0x10,
Video = 0x13,
Audio = 0x14,
BallotCreate {
poll_id: BallotID,
details: Ballot,
} = 0x15,
BallotVote {
sender: ThreemaID,
poll_id: BallotID,
updates: BallotUpdates,
} = 0x16,
File(File) = 0x17,
ContactSetPhoto = 0x18,
ContactDeletePhoto = 0x19,
ContactRequestPhoto = 0x1a,
GroupText = 0x41,
GroupLocation = 0x42,
GroupImage = 0x43,
GroupVideo = 0x44,
GroupAudio = 0x45,
GroupFile = 0x46,
GroupCreate = 0x4a,
GroupRename = 0x4b,
GroupLeave = 0x4c,
GroupAddMember = 0x4d,
GroupRemoveMember = 0x4e,
GroupDestroy = 0x4f,
GroupSetPhoto = 0x50,
GroupRequestSync = 0x51,
GroupBallotCreate = 0x52,
GroupBallotVote = 0x53,
GroupDeletePhoto = 0x54,
VoipCallOffer = 0x60,
VoipCallAnswer = 0x61,
VoipIceCandiates = 0x62,
VoipCallHangup = 0x63,
VoipCallRinging = 0x64,
DeliveryReceipt(MessageStatus, MessageID) = 0x80,
TypingNotification = 0x90,
FsEnvelope = 0xa0,
AuthToken = 0xff,
}
}
flat_enum! {
#[derive(Debug)]
#[repr(u8)]
pub enum MessageStatus {
Delivered = 1,
Read,
Approved,
Disapproved,
}
}
#[derive(Debug, Flat)]
pub struct Header {
pub sender: ThreemaID,
pub receiver: ThreemaID,
pub msg_id: MessageID,
pub timestamp: u32,
pub flags: u32,
pub nickname: [u8; 32],
pub nonce: [u8; 24],
}
#[derive(Debug)]
pub struct Text {
pub message: String,
}
impl Flat for Text {
fn serialize(&self) -> Vec<u8> {
self.message.as_bytes().to_owned()
}
fn deserialize_with_size(data: &[u8]) -> Option<(Self, usize)> {
let message = String::from_utf8(data.to_owned()).ok()?;
Some((Self { message }, data.len()))
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum RenderingType {
File = 0,
Media = 1,
Sticker = 2,
}
impl Serialize for RenderingType {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_u8(*self as u8)
}
}
struct EnumVisitor;
impl<'de> Visitor<'de> for EnumVisitor {
type Value = RenderingType;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
writeln!(formatter, "u8")
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: Error,
{
match v {
0 => Ok(RenderingType::File),
1 => Ok(RenderingType::Media),
2 => Ok(RenderingType::Sticker),
x => Err(Error::invalid_value(Unexpected::Unsigned(x), &self)),
}
}
}
impl<'de> Deserialize<'de> for RenderingType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_u8(EnumVisitor)
}
}
impl Default for RenderingType {
fn default() -> Self {
RenderingType::File
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct File {
#[serde(rename = "b")]
blob_id: String,
#[serde(rename = "n")]
pub name: String,
#[serde(rename = "m")]
pub mime: String,
#[serde(rename = "t")]
#[serde(skip_serializing_if = "Option::is_none")]
thumbnail_blob_id: Option<String>,
#[serde(rename = "p")]
pub thumbnail_mime: String,
#[serde(rename = "s")]
pub size: u64,
#[serde(rename = "d")]
pub description: String,
#[serde(rename = "j")]
rendering_type: RenderingType,
#[serde(rename = "k")]
encryption_key: String,
#[serde(flatten)]
pub unknown: std::collections::HashMap<String, serde_json::Value>,
}
impl Flat for File {
fn serialize(&self) -> Vec<u8> {
to_vec(self).unwrap()
}
fn deserialize_with_size(data: &[u8]) -> Option<(Self, usize)> {
let res = from_slice(data).ok()?;
Some((res, data.len()))
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct PollChoice {
#[serde(rename = "i")]
pub id: u32,
#[serde(rename = "n")]
pub text: String,
#[serde(rename = "o")]
pub order: u32,
#[serde(rename = "r")]
pub results: Vec<u32>,
#[serde(flatten)]
pub unknown: std::collections::HashMap<String, serde_json::Value>,
}
#[derive(Debug, Deserialize, Serialize)]
#[repr(u8)]
pub enum BallotState {
Open = 0,
Closed = 1,
}
#[derive(Debug, Deserialize, Serialize)]
#[repr(u8)]
pub enum BallotType {
ResultOnClose = 0,
Intermediate = 1,
}
#[derive(Debug, Deserialize, Serialize)]
#[repr(u8)]
pub enum AssessmentType {
Single = 0,
Multiple = 1,
}
#[derive(Debug, Deserialize, Serialize)]
#[repr(u8)]
pub enum ChoiceType {
Text = 0,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Ballot {
#[serde(rename = "d")]
pub description: String,
#[serde(rename = "c")]
pub choices: Vec<PollChoice>,
#[serde(rename = "p")]
pub participants: Vec<String>,
#[serde(rename = "s")]
pub state: BallotState,
#[serde(rename = "a")]
pub assessment_type: AssessmentType,
#[serde(rename = "t")]
pub ballot_type: BallotType,
#[serde(rename = "o")]
pub choice_type: ChoiceType,
#[serde(flatten)]
pub unknown: std::collections::HashMap<String, serde_json::Value>,
}
impl Flat for Ballot {
fn serialize(&self) -> Vec<u8> {
to_vec(self).unwrap()
}
fn deserialize_with_size(data: &[u8]) -> Option<(Self, usize)> {
let res = from_slice(data).ok()?;
Some((res, data.len()))
}
}
#[deprecated = "please use Ballot instead"]
pub type PollDetails = Ballot;
#[derive(Debug, Deserialize, Serialize)]
#[serde(transparent)]
pub struct BallotUpdates {
updates: Vec<(u32, u32)>,
}
impl Flat for BallotUpdates {
fn serialize(&self) -> Vec<u8> {
to_vec(self).unwrap()
}
fn deserialize_with_size(data: &[u8]) -> Option<(Self, usize)> {
let res = from_slice(data).ok()?;
Some((res, data.len()))
}
}
#[deprecated = "please use BallotUpdates instead"]
pub type PollUpdate = BallotUpdates;