snapchat_log_parser/
types.rs1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use serde_with::rust::string_empty_as_none;
6
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
9#[serde(untagged)]
10pub enum Message {
11 Sent {
13 #[serde(rename = "To")]
15 to: String,
16 #[serde(rename = "Media Type")]
18 media_type: MediaType,
19 #[serde(rename = "Created", with = "crate::timestamp")]
21 created_at: DateTime<Utc>,
22 #[serde(rename = "Text", with = "string_empty_as_none")]
24 text: Option<String>,
25 },
26 Recieved {
28 #[serde(rename = "From")]
30 from: String,
31 #[serde(rename = "Media Type")]
33 media_type: MediaType,
34 #[serde(rename = "Created", with = "crate::timestamp")]
36 created_at: DateTime<Utc>,
37 #[serde(rename = "Text", with = "string_empty_as_none")]
39 text: Option<String>,
40 }
41}
42
43impl Message {
44 pub fn recipient(&self) -> String {
46 match self {
47 Message::Recieved { from, ..} => from.to_owned(),
48 Message::Sent { to, .. } => to.to_owned(),
49 }
50 }
51 pub fn media_type(&self) -> MediaType {
53 match self {
54 Self::Recieved { media_type, .. } => media_type.clone(),
55 Self::Sent { media_type, .. } => media_type.clone(),
56 }
57 }
58 pub fn created_at(&self) -> DateTime<Utc> {
60 match self {
61 Self::Recieved { created_at, .. } => created_at.clone(),
62 Self::Sent { created_at, .. } => created_at.clone(),
63 }
64 }
65 pub fn text(&self) -> Option<String> {
69 match self {
70 Self::Recieved { text, .. } => text.clone(),
71 Self::Sent { text, ..} => text.clone()
72 }
73 }
74}
75
76#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
78pub struct SnapchatData {
79 #[serde(rename = "Received Saved Chat History")]
81 pub saved_recieved: Vec<Message>,
82 #[serde(rename = "Sent Saved Chat History")]
84 pub saved_sent: Vec<Message>,
85}
86
87impl SnapchatData {
88 pub fn from_reader<R: std::io::Read>(rdr: R) -> serde_json::Result<Self> {
100 serde_json::from_reader(rdr)
101 }
102 pub fn from_str<'a>(s: &'a str) -> serde_json::Result<Self> {
118 serde_json::from_str(s)
119 }
120 pub fn get_user_chats(self, user: &str) -> Vec<Message> {
122 let predicate = |x: &Message| x.recipient() == user;
123
124 let rec = self.saved_recieved.into_iter().filter(&predicate);
126 let sent = self.saved_sent.into_iter().filter(&predicate);
127
128 let mut combined: Vec<Message> = rec.chain(sent).collect();
130 combined.sort_by(|a, b| a.created_at().partial_cmp(&b.created_at()).unwrap());
132 combined
133 }
134}
135
136#[derive(Debug, Deserialize, Serialize, Copy, Clone, PartialEq)]
138pub enum MediaType {
139 #[serde(rename = "TEXT")]
141 Text,
142 #[serde(rename = "MEDIA")]
144 Media,
145 #[serde(rename = "STICKER")]
147 Sticker,
148 #[serde(rename = "SHARE")]
149 Share,
150 #[serde(rename = "NOTE")]
151 Note,
152 #[serde(rename = "LOCATION")]
154 Location,
155}