misskey-api 0.2.0

API bindings of Misskey, including requests/responses of endpoints and messages on channels
Documentation
use crate::model::{id::Id, note::Reaction, user::User};

use chrono::{DateTime, Utc};
use serde::Deserialize;

#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase", tag = "type", content = "body")]
pub enum NoteUpdateEvent {
    #[serde(rename_all = "camelCase")]
    Reacted {
        reaction: Reaction,
        user_id: Id<User>,
    },
    #[serde(rename_all = "camelCase")]
    Unreacted {
        reaction: Reaction,
        user_id: Id<User>,
    },
    #[serde(rename_all = "camelCase")]
    Deleted { deleted_at: DateTime<Utc> },
    #[serde(rename_all = "camelCase")]
    PollVoted { choice: u64, user_id: Id<User> },
}

impl misskey_core::streaming::SubNoteEvent for NoteUpdateEvent {}

#[cfg(test)]
mod tests {
    use super::NoteUpdateEvent;
    use crate::test::{websocket::TestClient, ClientExt};

    use futures::{future, StreamExt};

    #[tokio::test]
    async fn subscribe_unsubscribe() {
        let client = TestClient::new().await;
        let note = client.create_note(Some("test"), None, None).await;

        let mut stream = client
            .subnote::<NoteUpdateEvent, _>(note.id.to_string())
            .await
            .unwrap();
        stream.unsubscribe().await.unwrap();
    }

    #[tokio::test]
    async fn reacted() {
        use crate::model::note::Reaction;

        let client = TestClient::new().await;
        let note = client
            .user
            .create_note(Some("looks good"), None, None)
            .await;

        let mut stream = client.user.subnote(note.id.to_string()).await.unwrap();

        future::join(
            client
                .admin
                .test(crate::endpoint::notes::reactions::create::Request {
                    note_id: note.id,
                    reaction: Reaction("👍".to_string()),
                }),
            async {
                loop {
                    match stream.next().await.unwrap().unwrap() {
                        NoteUpdateEvent::Reacted { .. } => break,
                        _ => continue,
                    }
                }
            },
        )
        .await;
    }

    #[tokio::test]
    async fn unreacted() {
        use crate::model::note::Reaction;

        let client = TestClient::new().await;
        let note = client
            .user
            .create_note(Some("not so good"), None, None)
            .await;
        client
            .admin
            .test(crate::endpoint::notes::reactions::create::Request {
                note_id: note.id.clone(),
                reaction: Reaction("👍".to_string()),
            })
            .await;

        let mut stream = client.user.subnote(note.id.to_string()).await.unwrap();

        future::join(
            client
                .admin
                .test(crate::endpoint::notes::reactions::delete::Request { note_id: note.id }),
            async {
                loop {
                    match stream.next().await.unwrap().unwrap() {
                        NoteUpdateEvent::Unreacted { .. } => break,
                        _ => continue,
                    }
                }
            },
        )
        .await;
    }

    #[tokio::test]
    async fn deleted() {
        let client = TestClient::new().await;
        let note = client.user.create_note(Some("hmm..."), None, None).await;

        let mut stream = client.user.subnote(note.id.to_string()).await.unwrap();

        future::join(
            client
                .user
                .test(crate::endpoint::notes::delete::Request { note_id: note.id }),
            async {
                loop {
                    match stream.next().await.unwrap().unwrap() {
                        NoteUpdateEvent::Deleted { .. } => break,
                        _ => continue,
                    }
                }
            },
        )
        .await;
    }

    #[tokio::test]
    async fn poll_voted() {
        let client = TestClient::new().await;
        let poll = crate::endpoint::notes::create::PollRequest {
            choices: vec!["a".to_string(), "b".to_string()],
            multiple: Some(true),
            expires_at: Some(chrono::Utc::now() + chrono::Duration::hours(1)),
            expired_after: None,
        };
        let note = client
            .user
            .test(crate::endpoint::notes::create::Request {
                visibility: None,
                visible_user_ids: None,
                text: Some("?".to_string()),
                cw: None,
                via_mobile: None,
                local_only: None,
                no_extract_mentions: None,
                no_extract_hashtags: None,
                no_extract_emojis: None,
                file_ids: None,
                reply_id: None,
                renote_id: None,
                poll: Some(poll),
                #[cfg(feature = "12-47-0")]
                channel_id: None,
            })
            .await
            .created_note;

        let mut stream = client.user.subnote(note.id.to_string()).await.unwrap();

        futures::future::join(
            client
                .user
                .test(crate::endpoint::notes::polls::vote::Request {
                    note_id: note.id,
                    choice: 0,
                }),
            async {
                loop {
                    match stream.next().await.unwrap().unwrap() {
                        NoteUpdateEvent::PollVoted { .. } => break,
                        _ => continue,
                    }
                }
            },
        )
        .await;
    }
}