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}