twitter_archive/structs/
screen_name_change.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/screen-name-change.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::screen_name_change;
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/screen-name-change.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.screen_name_change.part0 = ", "", 1);
26//!     let data: Vec<screen_name_change::ScreenNameChangeObject> = serde_json::from_str(&json).expect("Unable to parse");
27//!
28//!     for (index, object) in data.iter().enumerate() {
29//!         /* Do stuff with each ScreenNameChange */
30//!         println!("Screen name change index: {index}");
31//!         println!("Account ID: {}", object.screen_name_change.account_id);
32//!         println!("Changed At: {}", object.screen_name_change.screen_name_change.changed_at);
33//!         println!("Changed From: {}", object.screen_name_change.screen_name_change.changed_from);
34//!         println!("Changed To: {}", object.screen_name_change.screen_name_change.changed_to);
35//!     }
36//! }
37//! ```
38//!
39//! ## Example `twitter-<DATE>-<UID>.zip:data/screen-name-change.js` content
40//!
41//! ```javascript
42//! window.YTD.screen_name_change.part0 = [
43//!   {
44//!     "screenNameChange" : {
45//!       "accountId" : "111111111",
46//!       "screenNameChange" : {
47//!         "changedAt" : "2023-08-12T17:10:37.000Z",
48//!         "changedFrom" : "SomeOneElse",
49//!         "changedTo" : "SomeOneNew"
50//!       }
51//!     }
52//!   }
53//! ]
54//! ```
55
56use chrono::{DateTime, Utc};
57use derive_more::Display;
58use serde::{Deserialize, Serialize};
59
60use crate::convert;
61
62/// ## Example
63///
64/// ```
65/// use chrono::{DateTime, NaiveDateTime, Utc};
66///
67/// use twitter_archive::convert::{created_at, date_time_iso_8601};
68///
69/// use twitter_archive::structs::screen_name_change::ScreenNameChangeObject;
70///
71/// let changed_at_string = "2023-08-12T17:10:37.000Z";
72/// let changed_at_native_time = NaiveDateTime::parse_from_str(&changed_at_string, date_time_iso_8601::FORMAT).unwrap();
73/// let changed_at_date_time = DateTime::<Utc>::from_naive_utc_and_offset(changed_at_native_time, Utc);
74///
75/// let json = format!(r#"{{
76///   "screenNameChange": {{
77///     "accountId": "111111111",
78///     "screenNameChange": {{
79///       "changedAt": "{changed_at_string}",
80///       "changedFrom": "SomeOneElse",
81///       "changedTo": "SomeOneNew"
82///     }}
83///   }}
84/// }}"#);
85///
86/// let data: ScreenNameChangeObject = serde_json::from_str(&json).unwrap();
87///
88/// // De-serialized properties
89/// assert_eq!(data.screen_name_change.account_id, "111111111");
90/// assert_eq!(data.screen_name_change.screen_name_change.changed_at, changed_at_date_time);
91/// assert_eq!(data.screen_name_change.screen_name_change.changed_from, "SomeOneElse");
92/// assert_eq!(data.screen_name_change.screen_name_change.changed_to, "SomeOneNew");
93///
94/// // Re-serialize is equivalent to original data
95/// assert_eq!(serde_json::to_string_pretty(&data).unwrap(), json);
96/// ```
97#[derive(Deserialize, Serialize, Debug, Clone, Display)]
98#[display(fmt = "{}", "serde_json::to_value(self).unwrap()")]
99#[serde(rename_all = "camelCase")]
100pub struct ScreenNameChangeObject {
101	/// Why they wrapped a list of name changes within unnecessary object label is anyone's guess
102	///
103	/// ## Example JSON data
104	///
105	/// ```json
106	/// {
107	///   "screenNameChange": {
108	///     "accountId": "111111111",
109	///     "screenNameChange": {
110	///       "changedAt": "2023-08-12T17:10:37.000Z",
111	///       "changedFrom": "SomeOneElse",
112	///       "changedTo": "SomeOneNew"
113	///     }
114	///   }
115	/// }
116	/// ```
117	pub screen_name_change: ScreenNameChangeEntry,
118}
119
120/// ## Example
121///
122/// ```
123/// use chrono::{DateTime, NaiveDateTime, Utc};
124///
125/// use twitter_archive::convert::{created_at, date_time_iso_8601};
126///
127/// use twitter_archive::structs::screen_name_change::ScreenNameChangeEntry;
128///
129/// let changed_at_string = "2023-08-12T17:10:37.000Z";
130/// let changed_at_native_time = NaiveDateTime::parse_from_str(&changed_at_string, date_time_iso_8601::FORMAT).unwrap();
131/// let changed_at_date_time = DateTime::<Utc>::from_naive_utc_and_offset(changed_at_native_time, Utc);
132///
133/// let json = format!(r#"{{
134///   "accountId": "111111111",
135///   "screenNameChange": {{
136///     "changedAt": "{changed_at_string}",
137///     "changedFrom": "SomeOneElse",
138///     "changedTo": "SomeOneNew"
139///   }}
140/// }}"#);
141///
142/// let data: ScreenNameChangeEntry = serde_json::from_str(&json).unwrap();
143///
144/// // De-serialized properties
145/// assert_eq!(data.account_id, "111111111");
146/// assert_eq!(data.screen_name_change.changed_at, changed_at_date_time);
147/// assert_eq!(data.screen_name_change.changed_from, "SomeOneElse");
148/// assert_eq!(data.screen_name_change.changed_to, "SomeOneNew");
149///
150/// // Re-serialize is equivalent to original data
151/// assert_eq!(serde_json::to_string_pretty(&data).unwrap(), json);
152/// ```
153#[derive(Deserialize, Serialize, Debug, Clone, Display)]
154#[display(fmt = "{}", "serde_json::to_value(self).unwrap()")]
155#[serde(rename_all = "camelCase")]
156pub struct ScreenNameChangeEntry {
157	/// ## Example JSON data
158	///
159	/// ```json
160	/// { "accountId": "111111111" }
161	/// ```
162	pub account_id: String,
163
164	/// ## Example JSON data
165	///
166	/// ```json
167	/// {
168	///   "screenNameChange": {
169	///     "changedAt": "2023-08-12T17:10:37.000Z",
170	///     "changedFrom": "SomeOneElse",
171	///     "changedTo": "SomeOneNew"
172	///    }
173	/// }
174	/// ```
175	pub screen_name_change: ScreenNameChange,
176}
177
178/// ## Example
179///
180/// ```
181/// use chrono::{DateTime, NaiveDateTime, Utc};
182///
183/// use twitter_archive::convert::{created_at, date_time_iso_8601};
184///
185/// use twitter_archive::structs::screen_name_change::ScreenNameChange;
186///
187/// let changed_at_string = "2023-08-12T17:10:37.000Z";
188/// let changed_at_native_time = NaiveDateTime::parse_from_str(&changed_at_string, date_time_iso_8601::FORMAT).unwrap();
189/// let changed_at_date_time = DateTime::<Utc>::from_naive_utc_and_offset(changed_at_native_time, Utc);
190///
191/// let json = format!(r#"{{
192///   "changedAt": "{changed_at_string}",
193///   "changedFrom": "SomeOneElse",
194///   "changedTo": "SomeOneNew"
195/// }}"#);
196///
197/// let data: ScreenNameChange = serde_json::from_str(&json).unwrap();
198///
199/// // De-serialized properties
200/// assert_eq!(data.changed_at, changed_at_date_time);
201/// assert_eq!(data.changed_from, "SomeOneElse");
202/// assert_eq!(data.changed_to, "SomeOneNew");
203///
204/// // Re-serialize is equivalent to original data
205/// assert_eq!(serde_json::to_string_pretty(&data).unwrap(), json);
206/// ```
207#[derive(Deserialize, Serialize, Debug, Clone, Display)]
208#[display(fmt = "{}", "serde_json::to_value(self).unwrap()")]
209#[serde(rename_all = "camelCase")]
210pub struct ScreenNameChange {
211	/// ## Example JSON data
212	///
213	/// ```json
214	/// { "changedAt": "2023-08-12T17:10:37.000Z" }
215	/// ```
216	#[serde(with = "convert::date_time_iso_8601")]
217	pub changed_at: DateTime<Utc>,
218
219	/// ## Example JSON data
220	///
221	/// ```json
222	/// { "changedFrom": "SomeOneElse" }
223	/// ```
224	pub changed_from: String,
225
226	/// ## Example JSON data
227	///
228	/// ```json
229	/// { "changedTo": "SomeOneNew" }
230	/// ```
231	pub changed_to: String,
232}