diff --git a/src/api.rs b/src/api.rs index b8c3e21..11de909 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1252,6 +1252,24 @@ impl MisskeyClient { Ok(()) } + /// 自分が送ったフォローリクエストを取り消す (following/requests/cancel)。 + /// 鍵アカウント宛ての未承認リクエストに使う (following/delete は notFollowing エラーになる)。 + pub async fn cancel_follow_request( + &self, + host: &str, + token: &str, + user_id: &str, + ) -> Result<(), NoteDeckError> { + self.request( + host, + token, + "following/requests/cancel", + json!({ "userId": user_id }), + ) + .await?; + Ok(()) + } + /// Fetch server meta information. pub async fn get_meta(&self, host: &str, token: &str) -> Result { self.request(host, token, "meta", json!({})).await @@ -2886,6 +2904,23 @@ mod tests { client.follow_user("h", "token", "u1").await.unwrap(); } + #[tokio::test] + async fn cancel_follow_request_succeeds() { + let server = MockServer::start().await; + Mock::given(method("POST")) + .and(path("/api/following/requests/cancel")) + .and(body_partial_json(json!({ "userId": "u1" }))) + .respond_with(ResponseTemplate::new(200).set_body_string("")) + .mount(&server) + .await; + + let client = MisskeyClient::with_base_url(&server.uri()); + client + .cancel_follow_request("h", "token", "u1") + .await + .unwrap(); + } + #[tokio::test] async fn extract_reaction_palette_valid() { let data = json!([ diff --git a/src/models.rs b/src/models.rs index 5f815a9..6e7a615 100644 --- a/src/models.rs +++ b/src/models.rs @@ -255,6 +255,9 @@ pub struct NormalizedUserDetail { pub is_following: bool, #[serde(default)] pub is_followed: bool, + /// 鍵アカウントへフォローリクエスト送信済みで未承認の状態 + #[serde(default)] + pub has_pending_follow_request_from_you: bool, #[serde(default)] pub created_at: String, #[serde(default)] @@ -1192,6 +1195,9 @@ pub struct RawUserDetail { pub is_following: bool, #[serde(default)] pub is_followed: bool, + /// 鍵アカウントへフォローリクエスト送信済みで未承認の状態 + #[serde(default)] + pub has_pending_follow_request_from_you: bool, #[serde(default)] pub created_at: String, #[serde(default)] @@ -1411,6 +1417,7 @@ impl RawUserDetail { is_cat: self.is_cat, is_following: self.is_following, is_followed: self.is_followed, + has_pending_follow_request_from_you: self.has_pending_follow_request_from_you, created_at: self.created_at, avatar_decorations: self.avatar_decorations, emojis: self.emojis, @@ -1794,8 +1801,9 @@ mod tests { "notesCount": 200, "isBot": true, "isCat": true, - "isFollowing": true, + "isFollowing": false, "isFollowed": false, + "hasPendingFollowRequestFromYou": true, "createdAt": "2024-01-01T00:00:00.000Z", "avatarDecorations": [], "emojis": {}, @@ -1812,7 +1820,8 @@ mod tests { assert_eq!(detail.host.as_deref(), Some("remote.example.com")); assert!(detail.is_bot); assert!(detail.is_cat); - assert!(detail.is_following); + assert!(!detail.is_following); + assert!(detail.has_pending_follow_request_from_you); assert_eq!(detail.followers_count, 100); assert_eq!(detail.notes_count, 200); assert_eq!(detail.roles.len(), 1);