gatewayd: mm, patch_post and username

Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
2026-09-24 04:36:45 -07:00
parent 365e50081d
commit 18791ab389
3 changed files with 179 additions and 0 deletions
+49
View File
@@ -30,6 +30,19 @@ struct Channel {
id: String,
}
#[derive(Deserialize)]
struct User {
username: String,
}
/// A Mattermost username: 1 to 64 characters of `a-z`, `0-9`, `.`, `-` and `_`.
fn valid_username(name: &str) -> bool {
(1..=64).contains(&name.len())
&& name.bytes().all(|b| {
b.is_ascii_lowercase() || b.is_ascii_digit() || matches!(b, b'.' | b'-' | b'_')
})
}
impl Client {
/// `timeout` bounds connecting and each read: no bytes for that long is an error.
pub fn new(connector: Connector, token: Secret, timeout: Duration) -> Client {
@@ -179,6 +192,42 @@ impl Client {
}
Ok(channel.id)
}
/// `PUT /api/v4/posts/{post}/patch`: replace the post's text.
pub fn patch_post(&self, post: &str, message: &str) -> Result<(), MmError> {
// A post that is not `valid_id` is Json, and nothing is sent. Otherwise PUT
// /api/v4/posts/<post>/patch with {"message": message}, through `call`; the answer is a
// Post, `check`ed and dropped.
if !valid_id(post) {
return Err(MmError::Json(
"a post path must be a Mattermost id".to_string(),
));
}
let payload = serde_json::json!({ "message": message }).to_string();
let body = self.call(
"PUT",
&format!("/api/v4/posts/{post}/patch"),
Some(payload.as_bytes()),
)?;
json::<Post>(&body)?.check().map(|_| ())
}
/// `GET /api/v4/users/{user}`: the user's username.
pub fn username(&self, user: &str) -> Result<String, MmError> {
// A user that is not `valid_id` is Json. Otherwise GET /api/v4/users/<user>; a username
// that is not `valid_username` is Json.
if !valid_id(user) {
return Err(MmError::Json(
"a user path must be a Mattermost id".to_string(),
));
}
let body = self.call("GET", &format!("/api/v4/users/{user}"), None)?;
let user: User = json(&body)?;
if !valid_username(&user.username) {
return Err(MmError::Json("the user has no valid username".to_string()));
}
Ok(user.username)
}
}
fn status_error(status: u16, body: &[u8]) -> MmError {