twitter_archive/structs/
direct_message_headers.rs

1#!/usr/bin/env rust
2
3//! Tweeter archives as of 2023-08-31 have private data found under;
4//!
5//!   twitter-<DATE>-<UID>.zip:data/direct-message-headers.js
6//!
7//! ## Example file reader
8//!
9//! ```no_build
10//! use std::io::Read;
11//! use std::{fs, path};
12//! use zip::read::ZipArchive;
13//!
14//! use twitter_archive::structs::direct_message_headers;
15//!
16//! fn main() {
17//!     let input_file = "~/Downloads/twitter-archive.zip";
18//!
19//!     let file_descriptor = fs::File::open(input_file).expect("Unable to read --input-file");
20//!     let mut zip_archive = ZipArchive::new(file_descriptor).unwrap();
21//!     let mut zip_file = zip_archive.by_name("data/direct-message-headers.js").unwrap();
22//!     let mut buff = String::new();
23//!     zip_file.read_to_string(&mut buff).unwrap();
24//!
25//!     let json = buff.replacen("window.YTD.direct_message_headers.part0 = ", "", 1);
26//!     let data: Vec<direct_message_headers::DmConversationObject> = serde_json::from_str(&json).expect("Unable to parse");
27//!
28//!     for (index_header, object_header) in data.iter().enumerate() {
29//!         /* Do stuff with each `DmConversationObject` entry */
30//!         println!("Conversation header index: {index_header}");
31//!         println!("Conversation ID: {}", object_header.dm_conversation.conversation_id);
32//!         for (index_message, object_message) in object_header.dm_conversation.messages.iter().enumerate() {
33//!             /* Do stuff with each `object_message` entry */
34//!             println!("Message header index: {index_message}");
35//!             println!("Created at: {}", object_message.message_create.created_at);
36//!             println!("Message ID: {}", object_message.message_create.id);
37//!             println!("Sender ID: {}", object_message.message_create.sender_id);
38//!             println!("Recipient ID: {}", object_message.message_create.recipient_id);
39//!         }
40//!     }
41//! }
42//! ```
43//!
44//! ## Example `twitter-<DATE>-<UID>.zip:data/direct-message-headers.js` content
45//!
46//! ```javascript
47//! window.YTD.direct_message_headers.part0 = [
48//! ]
49//! ```
50
51use chrono::{DateTime, Utc};
52use derive_more::Display;
53use serde::{Deserialize, Serialize};
54
55use crate::convert;
56
57/// ## Example
58///
59/// ```
60/// use chrono::{DateTime, NaiveDateTime, Utc};
61///
62/// use twitter_archive::convert::date_time_iso_8601;
63///
64/// use twitter_archive::structs::direct_message_headers::DmConversationObject;
65///
66/// let created_at_string = "2023-08-12T17:10:37.000Z";
67/// let created_at_native_time = NaiveDateTime::parse_from_str(&created_at_string, date_time_iso_8601::FORMAT).unwrap();
68/// let created_at_date_time = DateTime::<Utc>::from_naive_utc_and_offset(created_at_native_time, Utc);
69///
70/// let json = format!(r#"{{
71///   "dmConversation": {{
72///     "conversationId": "1111-2222",
73///     "messages": [
74///       {{
75///         "messageCreate": {{
76///           "id": "1111111111111111111",
77///           "senderId": "2222",
78///           "recipientId": "1111",
79///           "createdAt": "{created_at_string}"
80///         }}
81///       }}
82///     ]
83///   }}
84/// }}"#);
85///
86/// let data: DmConversationObject = serde_json::from_str(&json).unwrap();
87///
88/// // De-serialized properties
89/// assert_eq!(data.dm_conversation.conversation_id, "1111-2222");
90///
91/// assert_eq!(data.dm_conversation.messages.len(), 1);
92/// assert_eq!(data.dm_conversation.messages[0].message_create.id, "1111111111111111111");
93/// assert_eq!(data.dm_conversation.messages[0].message_create.sender_id, "2222");
94/// assert_eq!(data.dm_conversation.messages[0].message_create.recipient_id, "1111");
95/// assert_eq!(data.dm_conversation.messages[0].message_create.created_at, created_at_date_time);
96///
97/// // Re-serialize is equivalent to original data without pretty printing
98/// assert_eq!(serde_json::to_string_pretty(&data).unwrap(), json);
99/// ```
100#[derive(Deserialize, Serialize, Debug, Clone, Display)]
101#[display(fmt = "{}", "serde_json::to_value(self).unwrap()")]
102#[serde(rename_all = "camelCase")]
103pub struct DmConversationObject {
104	/// ## Example JSON data
105	///
106	/// ```json
107	/// {
108	///   "dmConversation": {
109	///     "conversationId": "1111-2222",
110	///     "messages": [
111	///       {
112	///         "messageCreate": {
113	///           "id": "1111111111111111111",
114	///           "senderId": "2222",
115	///           "recipientId": "1111",
116	///           "createdAt": "2023-08-12T17:10:37.000Z"
117	///         }
118	///       }
119	///     ]
120	///   }
121	/// }
122	/// ```
123	pub dm_conversation: DmConversation,
124}
125
126/// ## Example
127///
128/// ```
129/// use chrono::{DateTime, NaiveDateTime, Utc};
130///
131/// use twitter_archive::convert::date_time_iso_8601;
132///
133/// use twitter_archive::structs::direct_message_headers::DmConversation;
134///
135/// let created_at_string = "2023-08-12T17:10:37.000Z";
136/// let created_at_native_time = NaiveDateTime::parse_from_str(&created_at_string, date_time_iso_8601::FORMAT).unwrap();
137/// let created_at_date_time = DateTime::<Utc>::from_naive_utc_and_offset(created_at_native_time, Utc);
138///
139/// let json = format!(r#"{{
140///   "conversationId": "1111-2222",
141///   "messages": [
142///     {{
143///       "messageCreate": {{
144///         "id": "1111111111111111111",
145///         "senderId": "2222",
146///         "recipientId": "1111",
147///         "createdAt": "{created_at_string}"
148///       }}
149///     }}
150///   ]
151/// }}"#);
152///
153/// let data: DmConversation = serde_json::from_str(&json).unwrap();
154///
155/// // De-serialized properties
156/// assert_eq!(data.conversation_id, "1111-2222");
157///
158/// assert_eq!(data.messages.len(), 1);
159/// assert_eq!(data.messages[0].message_create.id, "1111111111111111111");
160/// assert_eq!(data.messages[0].message_create.sender_id, "2222");
161/// assert_eq!(data.messages[0].message_create.recipient_id, "1111");
162/// assert_eq!(data.messages[0].message_create.created_at, created_at_date_time);
163///
164/// // Re-serialize is equivalent to original data without pretty printing
165/// assert_eq!(serde_json::to_string_pretty(&data).unwrap(), json);
166/// ```
167#[derive(Deserialize, Serialize, Debug, Clone, Display)]
168#[display(fmt = "{}", "serde_json::to_value(self).unwrap()")]
169#[serde(rename_all = "camelCase")]
170pub struct DmConversation {
171	/// ## Example JSON data
172	///
173	/// ```json
174	/// { "conversationId": "1111-2222" }
175	/// ```
176	pub conversation_id: String,
177
178	/// ## Example JSON data
179	///
180	/// ```json
181	/// {
182	///   "messages": [
183	///     {
184	///       "messageCreate": {
185	///         "id": "1111111111111111111",
186	///         "senderId": "2222",
187	///         "recipientId": "1111",
188	///         "createdAt": "2023-08-12T17:10:37.000Z"
189	///       }
190	///     }
191	///   ]
192	/// }
193	/// ```
194	pub messages: Vec<MessageCreateObject>,
195}
196
197/// ## Example
198///
199/// ```
200/// use chrono::{DateTime, NaiveDateTime, Utc};
201///
202/// use twitter_archive::convert::date_time_iso_8601;
203///
204/// use twitter_archive::structs::direct_message_headers::MessageCreateObject;
205///
206/// let created_at_string = "2023-08-12T17:10:37.000Z";
207/// let created_at_native_time = NaiveDateTime::parse_from_str(&created_at_string, date_time_iso_8601::FORMAT).unwrap();
208/// let created_at_date_time = DateTime::<Utc>::from_naive_utc_and_offset(created_at_native_time, Utc);
209///
210/// let json = format!(r#"{{
211///   "messageCreate": {{
212///     "id": "1111111111111111111",
213///     "senderId": "2222",
214///     "recipientId": "1111",
215///     "createdAt": "{created_at_string}"
216///   }}
217/// }}"#);
218///
219/// let data: MessageCreateObject = serde_json::from_str(&json).unwrap();
220///
221/// // De-serialized properties
222/// assert_eq!(data.message_create.id, "1111111111111111111");
223/// assert_eq!(data.message_create.sender_id, "2222");
224/// assert_eq!(data.message_create.recipient_id, "1111");
225/// assert_eq!(data.message_create.created_at, created_at_date_time);
226///
227/// // Re-serialize is equivalent to original data without pretty printing
228/// assert_eq!(serde_json::to_string_pretty(&data).unwrap(), json);
229/// ```
230#[derive(Deserialize, Serialize, Debug, Clone, Display)]
231#[display(fmt = "{}", "serde_json::to_value(self).unwrap()")]
232#[serde(rename_all = "camelCase")]
233pub struct MessageCreateObject {
234	/// ## Example JSON data
235	///
236	/// ```json
237	/// {
238	///   "messageCreate": {
239	///     "id": "1111111111111111111",
240	///     "senderId": "2222",
241	///     "recipientId": "1111",
242	///     "createdAt": "2023-08-12T17:10:37.000Z"
243	///   }
244	/// }
245	/// ```
246	pub message_create: MessageCreate,
247}
248
249/// ## Example
250///
251/// ```
252/// use chrono::{DateTime, NaiveDateTime, Utc};
253///
254/// use twitter_archive::convert::date_time_iso_8601;
255///
256/// use twitter_archive::structs::direct_message_headers::MessageCreate;
257///
258/// let created_at_string = "2023-08-12T17:10:37.000Z";
259/// let created_at_native_time = NaiveDateTime::parse_from_str(&created_at_string, date_time_iso_8601::FORMAT).unwrap();
260/// let created_at_date_time = DateTime::<Utc>::from_naive_utc_and_offset(created_at_native_time, Utc);
261///
262/// let json = format!(r#"{{
263///   "id": "1111111111111111111",
264///   "senderId": "2222",
265///   "recipientId": "1111",
266///   "createdAt": "{created_at_string}"
267/// }}"#);
268///
269/// let data: MessageCreate = serde_json::from_str(&json).unwrap();
270///
271/// // De-serialized properties
272/// assert_eq!(data.id, "1111111111111111111");
273/// assert_eq!(data.sender_id, "2222");
274/// assert_eq!(data.recipient_id, "1111");
275/// assert_eq!(data.created_at, created_at_date_time);
276///
277/// // Re-serialize is equivalent to original data without pretty printing
278/// assert_eq!(serde_json::to_string_pretty(&data).unwrap(), json);
279/// ```
280#[derive(Deserialize, Serialize, Debug, Clone, Display)]
281#[display(fmt = "{}", "serde_json::to_value(self).unwrap()")]
282#[serde(rename_all = "camelCase")]
283pub struct MessageCreate {
284	/// ## Example JSON data
285	///
286	/// ```json
287	/// { "id": "1111111111111111111" }
288	/// ```
289	pub id: String,
290
291	/// ID of user sending message
292	///
293	/// URL formats;
294	///
295	/// - Desktop: `https://twitter.com/i/user/{sender_id}`
296	///
297	/// > Note; does **not** work if not logged-in.  Thanks be to Mr. Musk !-D
298	///
299	/// ## Example JSON data
300	///
301	/// ```json
302	/// { "senderId": "2222" }
303	/// ```
304	pub sender_id: String,
305
306	/// ID of user receiving message
307	///
308	/// URL formats;
309	///
310	/// - Desktop: `https://twitter.com/i/user/{recipient_id}`
311	///
312	/// > Note; does **not** work if not logged-in.  Thanks be to Mr. Musk !-D
313	///
314	/// ## Example JSON data
315	///
316	/// ```json
317	/// { "recipientId": "1111" }
318	/// ```
319	pub recipient_id: String,
320
321	/// Date time stamp when DM was created
322	///
323	/// ## Example JSON data
324	///
325	/// ```json
326	/// { "createdAt": "2023-08-12T17:10:37.000Z" }
327	/// ```
328	#[serde(with = "convert::date_time_iso_8601")]
329	pub created_at: DateTime<Utc>,
330}