twitter_archive/structs/following.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/following.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::following;
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/following.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.following.part0 = ", "", 1);
26//! let data: Vec<following::FollowingObject> = 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.following.account_id);
32//! println!("User link: {}", object.following.user_link);
33//! }
34//! }
35//! ```
36//!
37//! ## Example `twitter-<DATE>-<UID>.zip:data/following.js` content
38//!
39//! ```javascript
40//! window.YTD.following.part0 = [
41//! {
42//! "following" : {
43//! "accountId" : "1111111111111111111",
44//! "userLink" : "https://twitter.com/intent/user?user_id=1111111111111111111"
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::following::FollowingObject;
59///
60/// let json = r#"{
61/// "following": {
62/// "accountId": "1111111111111111111",
63/// "userLink": "https://twitter.com/intent/user?user_id=1111111111111111111"
64/// }
65/// }"#;
66///
67/// let data: FollowingObject = serde_json::from_str(&json).unwrap();
68///
69/// // De-serialized properties
70/// assert_eq!(data.following.account_id, "1111111111111111111");
71/// assert_eq!(data.following.user_link, "https://twitter.com/intent/user?user_id=1111111111111111111");
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 FollowingObject {
79 /// ## Example JSON data
80 ///
81 /// ```json
82 /// {
83 /// "following": {
84 /// "accountId": "1111111111111111111",
85 /// "userLink": "https://twitter.com/intent/user?user_id=1111111111111111111"
86 /// }
87 /// }
88 /// ```
89 pub following: Follow,
90}