1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//! Trashing a topic, including the confirmation HEY asks for before it trashes a shared
//! one.
//!
//! [`Topics::get_entries`] is paged by geared pagination, so its `page` is a cursor out of
//! the previous answer's `Link` header rather than an offset: a number is ignored and
//! answered with the first page. [`crate::Page::next_page`] carries the cursor to pass back.
use crate::client::Response;
use crate::error::Error;
use crate::generated::routes;
use crate::generated::types::MoveTopicRequestContent;
pub use crate::generated::services::topics::*;
impl Topics<'_> {
/// Moves a topic to a box, by the box's id. The generated [`Topics::move_topic`] takes
/// the request body; this takes the one thing it carries.
pub async fn move_to_box(&self, topic_id: i64, box_id: i64) -> Result<(), Error> {
self.move_topic(topic_id, &MoveTopicRequestContent { box_id })
.await
}
/// Trashes a topic.
///
/// HEY will not trash a shared topic without being asked twice: it answers the removal
/// confirmation page instead, which comes back here as a usage error rather than as a
/// trashing that quietly did nothing. Confirming trashes the topic and removes your
/// access to it.
///
/// The generated [`Topics::trash`] sends the same request from its parts, and follows
/// that redirect rather than reading it.
pub async fn trash_topic(&self, topic_id: i64, confirm_destroy: bool) -> Result<(), Error> {
let mut operation = self.client().operation(&routes::TRASH_TOPIC, &[&topic_id]);
operation.resource_id(topic_id);
// An empty confirm_destroy reads as truthy on the server and skips the
// confirmation, so it is sent only when it is asked for.
if confirm_destroy {
operation.query("confirm_destroy", 1);
}
operation.capture_redirects();
let response = self.client().execute(operation).await?;
if awaiting_confirmation(&response, topic_id) {
Err(Error::usage_with_hint(
format!("topic {topic_id} is shared; HEY wants confirmation before trashing it"),
"Call trash_topic with confirm_destroy = true to trash it and remove your access",
))
} else {
Ok(())
}
}
}
/// Whether HEY answered by sending the caller to the topic's removal confirmation page,
/// which is how it says it will not trash a shared topic unasked. Any other redirect is HEY
/// sending the caller back to where the topic was, with the trashing done.
fn awaiting_confirmation(response: &Response, topic_id: i64) -> bool {
match response.header("location") {
Some(location) => response
.url
.join(location)
.is_ok_and(|target| target.path() == format!("/topics/{topic_id}/removal/new")),
None => false,
}
}