twitter_archive/structs/
follower.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/follower.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::follower;
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/follower.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.follower.part0 = ", "", 1);
26//!     let data: Vec<follower::FollowerObject> = serde_json::from_str(&json).expect("Unable to parse");
27//!
28//!     for (index, object) in data.iter().enumerate() {
29//!         /* Do stuff with each `RegisteredDevices` entry */
30//!         println!("IP audit index: {index}");
31//!         println!("Account ID: {}", object.follower.account_id);
32//!         println!("User link: {}", object.follower.user_link);
33//!     }
34//! }
35//! ```
36//!
37//! ## Example `twitter-<DATE>-<UID>.zip:data/follower.js` content
38//!
39//! ```javascript
40//! window.YTD.follower.part0 = [
41//!   {
42//!     "follower" : {
43//!       "accountId" : "2222222222222222222",
44//!       "userLink" : "https://twitter.com/intent/user?user_id=2222222222222222222"
45//!     }
46//!   }
47//! ]
48//! ```
49
50use derive_more::Display;
51use serde::{Deserialize, Serialize};
52
53use crate::structs::follow::Follow;
54
55/// ## Example
56///
57/// ```
58/// use twitter_archive::structs::follower::FollowerObject;
59///
60/// let json = r#"{
61///   "follower": {
62///     "accountId": "2222222222222222222",
63///     "userLink": "https://twitter.com/intent/user?user_id=2222222222222222222"
64///   }
65/// }"#;
66///
67/// let data: FollowerObject = serde_json::from_str(&json).unwrap();
68///
69/// // De-serialized properties
70/// assert_eq!(data.follower.account_id, "2222222222222222222");
71/// assert_eq!(data.follower.user_link, "https://twitter.com/intent/user?user_id=2222222222222222222");
72///
73/// // Re-serialize is equivalent to original data
74/// assert_eq!(serde_json::to_string_pretty(&data).unwrap(), json);
75/// ```
76#[derive(Deserialize, Serialize, Debug, Clone, Display)]
77#[display(fmt = "{}", "serde_json::to_value(self).unwrap()")]
78pub struct FollowerObject {
79	/// ## Example JSON data
80	///
81	/// ```json
82	/// {
83	///   "follower": {
84	///     "accountId": "2222222222222222222",
85	///     "userLink": "https://twitter.com/intent/user?user_id=2222222222222222222"
86	///   }
87	/// }
88	/// ```
89	pub follower: Follow,
90}