misskey_api/streaming/
note.rs

1use crate::model::{id::Id, note::Reaction, user::User};
2
3use chrono::{DateTime, Utc};
4use serde::Deserialize;
5
6#[derive(Deserialize, Debug, Clone)]
7#[serde(rename_all = "camelCase", tag = "type", content = "body")]
8pub enum NoteUpdateEvent {
9    #[serde(rename_all = "camelCase")]
10    Reacted {
11        reaction: Reaction,
12        user_id: Id<User>,
13    },
14    #[serde(rename_all = "camelCase")]
15    Unreacted {
16        reaction: Reaction,
17        user_id: Id<User>,
18    },
19    #[serde(rename_all = "camelCase")]
20    Deleted { deleted_at: DateTime<Utc> },
21    #[serde(rename_all = "camelCase")]
22    PollVoted { choice: u64, user_id: Id<User> },
23}
24
25impl misskey_core::streaming::SubNoteEvent for NoteUpdateEvent {}
26
27#[cfg(test)]
28mod tests {
29    use super::NoteUpdateEvent;
30    use crate::test::{websocket::TestClient, ClientExt};
31
32    use futures::{future, StreamExt};
33
34    #[tokio::test]
35    async fn subscribe_unsubscribe() {
36        let client = TestClient::new().await;
37        let note = client.create_note(Some("test"), None, None).await;
38
39        let mut stream = client
40            .subnote::<NoteUpdateEvent, _>(note.id.to_string())
41            .await
42            .unwrap();
43        stream.unsubscribe().await.unwrap();
44    }
45
46    #[tokio::test]
47    async fn reacted() {
48        use crate::model::note::Reaction;
49
50        let client = TestClient::new().await;
51        let note = client
52            .user
53            .create_note(Some("looks good"), None, None)
54            .await;
55
56        let mut stream = client.user.subnote(note.id.to_string()).await.unwrap();
57
58        future::join(
59            client
60                .admin
61                .test(crate::endpoint::notes::reactions::create::Request {
62                    note_id: note.id,
63                    reaction: Reaction("👍".to_string()),
64                }),
65            async {
66                loop {
67                    match stream.next().await.unwrap().unwrap() {
68                        NoteUpdateEvent::Reacted { .. } => break,
69                        _ => continue,
70                    }
71                }
72            },
73        )
74        .await;
75    }
76
77    #[tokio::test]
78    async fn unreacted() {
79        use crate::model::note::Reaction;
80
81        let client = TestClient::new().await;
82        let note = client
83            .user
84            .create_note(Some("not so good"), None, None)
85            .await;
86        client
87            .admin
88            .test(crate::endpoint::notes::reactions::create::Request {
89                note_id: note.id.clone(),
90                reaction: Reaction("👍".to_string()),
91            })
92            .await;
93
94        let mut stream = client.user.subnote(note.id.to_string()).await.unwrap();
95
96        future::join(
97            client
98                .admin
99                .test(crate::endpoint::notes::reactions::delete::Request { note_id: note.id }),
100            async {
101                loop {
102                    match stream.next().await.unwrap().unwrap() {
103                        NoteUpdateEvent::Unreacted { .. } => break,
104                        _ => continue,
105                    }
106                }
107            },
108        )
109        .await;
110    }
111
112    #[tokio::test]
113    async fn deleted() {
114        let client = TestClient::new().await;
115        let note = client.user.create_note(Some("hmm..."), None, None).await;
116
117        let mut stream = client.user.subnote(note.id.to_string()).await.unwrap();
118
119        future::join(
120            client
121                .user
122                .test(crate::endpoint::notes::delete::Request { note_id: note.id }),
123            async {
124                loop {
125                    match stream.next().await.unwrap().unwrap() {
126                        NoteUpdateEvent::Deleted { .. } => break,
127                        _ => continue,
128                    }
129                }
130            },
131        )
132        .await;
133    }
134
135    #[tokio::test]
136    async fn poll_voted() {
137        let client = TestClient::new().await;
138        let poll = crate::endpoint::notes::create::PollRequest {
139            choices: vec!["a".to_string(), "b".to_string()],
140            multiple: Some(true),
141            expires_at: Some(chrono::Utc::now() + chrono::Duration::hours(1)),
142            expired_after: None,
143        };
144        let note = client
145            .user
146            .test(crate::endpoint::notes::create::Request {
147                visibility: None,
148                visible_user_ids: None,
149                text: Some("?".to_string()),
150                cw: None,
151                via_mobile: None,
152                local_only: None,
153                no_extract_mentions: None,
154                no_extract_hashtags: None,
155                no_extract_emojis: None,
156                file_ids: None,
157                reply_id: None,
158                renote_id: None,
159                poll: Some(poll),
160                #[cfg(feature = "12-47-0")]
161                channel_id: None,
162            })
163            .await
164            .created_note;
165
166        let mut stream = client.user.subnote(note.id.to_string()).await.unwrap();
167
168        futures::future::join(
169            client
170                .user
171                .test(crate::endpoint::notes::polls::vote::Request {
172                    note_id: note.id,
173                    choice: 0,
174                }),
175            async {
176                loop {
177                    match stream.next().await.unwrap().unwrap() {
178                        NoteUpdateEvent::PollVoted { .. } => break,
179                        _ => continue,
180                    }
181                }
182            },
183        )
184        .await;
185    }
186}