twitter_archive/structs/
community_note_rating.rs

1#!/usr/bin/env rust
2
3//! Tweeter archives as of 2023-08-31 have public community_note_rating found under;
4//!
5//!   twitter-<DATE>-<UID>.zip:data/community-note-rating.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::community_note_rating;
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/community-note-rating.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.community_note_rating.part0 = ", "", 1);
26//!     let data: Vec<community_note_rating::CommunityNoteRatingObject> = serde_json::from_str(&json).expect("Unable to parse");
27//!
28//!     for (index, object) in data.iter().enumerate() {
29//!         /* Do stuff with each deleted Tweet */
30//!         println!("Community note rating index: {index}");
31//!         println!("Not helpful tags: {:?}", object.community_note_rating.not_helpful_tags);
32//!         println!("Note ID: {}", object.community_note_rating.note_id);
33//!         println!("Helpfulness level: {}", object.community_note_rating.helpfulness_level);
34//!         println!("Created at: {}", object.community_note_rating.created_at);
35//!         println!("User ID: {}", object.community_note_rating.user_id);
36//!     }
37//! }
38//! ```
39//!
40//! ## Example `twitter-<DATE>-<UID>.zip:data/community-note-rating.js` content
41//!
42//! ```javascript
43//! window.YTD.community_note_rating.part0 = [
44//!   {
45//!     "communityNoteRating" : {
46//!       "notHelpfulTags" : [
47//!         "OpinionSpeculation",
48//!         "NoteNotNeeded"
49//!       ],
50//!       "noteId" : "9999999999999999999",
51//!       "helpfulnessLevel" : "NotHelpful",
52//!       "createdAt" : "2020-01-20T21:42:09.068Z",
53//!       "userId" : "111111111"
54//!     }
55//!   }
56//! ]
57//! ```
58
59use chrono::{DateTime, Utc};
60use derive_more::Display;
61use serde::{Deserialize, Serialize};
62
63use crate::convert;
64
65/// ## Example
66///
67/// ```
68/// use chrono::{DateTime, NaiveDateTime, Utc};
69///
70/// use twitter_archive::convert::date_time_iso_8601::FORMAT;
71///
72/// use twitter_archive::structs::community_note_rating::CommunityNoteRatingObject;
73///
74/// let created_at_string = "2020-01-20T21:42:09.068Z";
75/// let created_at_native_time = NaiveDateTime::parse_from_str(&created_at_string, FORMAT).unwrap();
76/// let created_at_date_time = DateTime::<Utc>::from_naive_utc_and_offset(created_at_native_time, Utc);
77///
78/// let json = format!(r#"{{
79///   "communityNoteRating" : {{
80///     "notHelpfulTags" : [
81///       "OpinionSpeculation",
82///       "NoteNotNeeded"
83///     ],
84///     "noteId" : "9999999999999999999",
85///     "helpfulnessLevel" : "NotHelpful",
86///     "createdAt" : "{created_at_string}",
87///     "userId" : "111111111"
88///   }}
89/// }}"#);
90///
91/// let data: CommunityNoteRatingObject = serde_json::from_str(&json).unwrap();
92///
93/// // De-serialized properties
94/// assert_eq!(data.community_note_rating.not_helpful_tags.len(), 2);
95/// assert_eq!(data.community_note_rating.not_helpful_tags[0], "OpinionSpeculation");
96/// assert_eq!(data.community_note_rating.not_helpful_tags[1], "NoteNotNeeded");
97///
98/// assert_eq!(data.community_note_rating.note_id, "9999999999999999999");
99/// assert_eq!(data.community_note_rating.helpfulness_level, "NotHelpful");
100/// assert_eq!(data.community_note_rating.created_at, created_at_date_time);
101/// assert_eq!(data.community_note_rating.user_id, "111111111");
102///
103/// assert_eq!(data.community_note_rating.created_at, created_at_date_time);
104///
105/// // Re-serialize is equivalent to original data without pretty printing
106/// // assert_eq!(serde_json::to_string(&data).unwrap(), json.replace("\n", "").replace(" ", ""));
107/// ```
108#[derive(Deserialize, Serialize, Debug, Clone, Display)]
109#[display(fmt = "{}", "serde_json::to_value(self).unwrap()")]
110#[serde(rename_all = "camelCase")]
111pub struct CommunityNoteRatingObject {
112	/// ## Example JSON data
113	///
114	/// ```json
115	/// {
116	///   "communityNoteRating" : {
117	///     "notHelpfulTags" : [
118	///       "OpinionSpeculation",
119	///       "NoteNotNeeded"
120	///     ],
121	///     "noteId" : "9999999999999999999",
122	///     "helpfulnessLevel" : "NotHelpful",
123	///     "createdAt" : "2020-01-20T21:42:09.068Z",
124	///     "userId" : "111111111"
125	///   }
126	/// }
127	/// ```
128	pub community_note_rating: CommunityNoteRating,
129}
130
131/// ## Example
132///
133/// ```
134/// use chrono::{DateTime, NaiveDateTime, Utc};
135///
136/// use twitter_archive::convert::date_time_iso_8601::FORMAT;
137///
138/// use twitter_archive::structs::community_note_rating::CommunityNoteRating;
139///
140/// let created_at_string = "2020-01-20T21:42:09.068Z";
141/// let created_at_native_time = NaiveDateTime::parse_from_str(&created_at_string, FORMAT).unwrap();
142/// let created_at_date_time = DateTime::<Utc>::from_naive_utc_and_offset(created_at_native_time, Utc);
143///
144/// let json = format!(r#"{{
145///   "notHelpfulTags" : [
146///     "OpinionSpeculation",
147///     "NoteNotNeeded"
148///   ],
149///   "noteId" : "9999999999999999999",
150///   "helpfulnessLevel" : "NotHelpful",
151///   "createdAt" : "{created_at_string}",
152///   "userId" : "111111111"
153/// }}"#);
154///
155/// let data: CommunityNoteRating = serde_json::from_str(&json).unwrap();
156///
157/// // De-serialized properties
158/// assert_eq!(data.not_helpful_tags.len(), 2);
159/// assert_eq!(data.not_helpful_tags[0], "OpinionSpeculation");
160/// assert_eq!(data.not_helpful_tags[1], "NoteNotNeeded");
161///
162/// assert_eq!(data.note_id, "9999999999999999999");
163/// assert_eq!(data.helpfulness_level, "NotHelpful");
164/// assert_eq!(data.created_at, created_at_date_time);
165/// assert_eq!(data.user_id, "111111111");
166///
167/// // Re-serialize is equivalent to original data without pretty printing
168/// assert_eq!(serde_json::to_string(&data).unwrap(), json.replace("\n", "").replace(" ", ""));
169/// ```
170#[derive(Deserialize, Serialize, Debug, Clone, Display)]
171#[display(fmt = "{}", "serde_json::to_value(self).unwrap()")]
172#[serde(rename_all = "camelCase")]
173pub struct CommunityNoteRating {
174	/// List of tags about why community note was not helpful
175	///
176	/// ## Example JSON data
177	///
178	/// ```json
179	/// {
180	///   "notHelpfulTags" : [
181	///     "OpinionSpeculation",
182	///     "NoteNotNeeded"
183	///   ]
184	/// }
185	/// ```
186	pub not_helpful_tags: Vec<String>,
187
188	/// ## Example JSON data
189	///
190	/// ```json
191	/// { "noteId" : "9999999999999999999" }
192	/// ```
193	pub note_id: String,
194
195	/// ## Example JSON data
196	///
197	/// ```json
198	/// { "helpfulnessLevel" : "NotHelpful" }
199	/// ```
200	pub helpfulness_level: String,
201
202	/// ## Example JSON data
203	///
204	/// ```json
205	/// { "createdAt" : "2020-01-20T21:42:09.068Z" }
206	/// ```
207	#[serde(with = "convert::date_time_iso_8601")]
208	pub created_at: DateTime<Utc>,
209
210	/// ## Example JSON data
211	///
212	/// ```json
213	/// { "userId" : "111111111" }
214	/// ```
215	pub user_id: String,
216}