Allow mute accounts

This commit is contained in:
Rafael Caricio 2023-04-27 13:38:49 +02:00
parent bb28bf800d
commit cb61f4a86b
Signed by: rafaelcaricio
GPG key ID: 3C86DBCE8E93C947
6 changed files with 89 additions and 1 deletions

View file

@ -614,6 +614,44 @@ pub async fn show_replies(
Ok(()) Ok(())
} }
pub async fn mute_posts(
db_client: &impl DatabaseClient,
source_id: &Uuid,
target_id: &Uuid,
) -> Result<(), DatabaseError> {
db_client
.execute(
"
INSERT INTO relationship (source_id, target_id, relationship_type)
VALUES ($1, $2, $3)
ON CONFLICT (source_id, target_id, relationship_type) DO NOTHING
",
&[&source_id, &target_id, &RelationshipType::Mute],
)
.await?;
Ok(())
}
pub async fn unmute_posts(
db_client: &impl DatabaseClient,
source_id: &Uuid,
target_id: &Uuid,
) -> Result<(), DatabaseError> {
// Does not return NotFound error
db_client
.execute(
"
DELETE FROM relationship
WHERE
source_id = $1 AND target_id = $2
AND relationship_type = $3
",
&[&source_id, &target_id, &RelationshipType::Mute],
)
.await?;
Ok(())
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View file

@ -17,6 +17,7 @@ pub enum RelationshipType {
Subscription, Subscription,
HideReposts, HideReposts,
HideReplies, HideReplies,
Mute,
} }
impl From<&RelationshipType> for i16 { impl From<&RelationshipType> for i16 {
@ -27,6 +28,7 @@ impl From<&RelationshipType> for i16 {
RelationshipType::Subscription => 3, RelationshipType::Subscription => 3,
RelationshipType::HideReposts => 4, RelationshipType::HideReposts => 4,
RelationshipType::HideReplies => 5, RelationshipType::HideReplies => 5,
RelationshipType::Mute => 6,
} }
} }
} }
@ -41,6 +43,7 @@ impl TryFrom<i16> for RelationshipType {
3 => Self::Subscription, 3 => Self::Subscription,
4 => Self::HideReposts, 4 => Self::HideReposts,
5 => Self::HideReplies, 5 => Self::HideReplies,
6 => Self::Mute,
_ => return Err(DatabaseTypeError), _ => return Err(DatabaseTypeError),
}; };
Ok(relationship_type) Ok(relationship_type)

View file

@ -52,6 +52,11 @@ pub async fn get_relationship(
relationship_map.showing_replies = false; relationship_map.showing_replies = false;
}; };
} }
RelationshipType::Mute => {
if relationship.is_direct(source_id, target_id)? {
relationship_map.muting = true;
};
}
}; };
} }
Ok(relationship_map) Ok(relationship_map)

View file

@ -402,6 +402,7 @@ pub struct RelationshipMap {
pub subscription_from: bool, pub subscription_from: bool,
pub showing_reblogs: bool, pub showing_reblogs: bool,
pub showing_replies: bool, pub showing_replies: bool,
pub muting: bool,
} }
fn default_showing_reblogs() -> bool { fn default_showing_reblogs() -> bool {
@ -423,6 +424,7 @@ impl Default for RelationshipMap {
subscription_from: false, subscription_from: false,
showing_reblogs: default_showing_reblogs(), showing_reblogs: default_showing_reblogs(),
showing_replies: default_showing_replies(), showing_replies: default_showing_replies(),
muting: false,
} }
} }
} }

View file

@ -3,6 +3,7 @@ use actix_web_httpauth::extractors::bearer::BearerAuth;
use uuid::Uuid; use uuid::Uuid;
use fedimovies_config::{Config, DefaultRole, RegistrationType}; use fedimovies_config::{Config, DefaultRole, RegistrationType};
use fedimovies_models::relationships::queries::{mute_posts, unmute_posts};
use fedimovies_models::{ use fedimovies_models::{
database::{get_database_client, DatabaseError, DbPool}, database::{get_database_client, DatabaseError, DbPool},
posts::queries::get_posts_by_author, posts::queries::get_posts_by_author,
@ -367,6 +368,41 @@ async fn unfollow_account(
Ok(HttpResponse::Ok().json(relationship)) Ok(HttpResponse::Ok().json(relationship))
} }
#[post("/{account_id}/mute")]
async fn mute_account(
auth: BearerAuth,
db_pool: web::Data<DbPool>,
account_id: web::Path<Uuid>,
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let target = get_profile_by_id(db_client, &account_id).await?;
mute_posts(db_client, &current_user.id, &target.id).await?;
let relationship = get_relationship(db_client, &current_user.id, &target.id).await?;
Ok(HttpResponse::Ok().json(relationship))
}
#[post("/{account_id}/unmute")]
async fn unmute_account(
auth: BearerAuth,
db_pool: web::Data<DbPool>,
account_id: web::Path<Uuid>,
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let target = get_profile_by_id(db_client, &account_id).await?;
match unmute_posts(db_client, &current_user.id, &target.id).await {
Ok(()) => (),
Err(DatabaseError::NotFound(_)) => (), // not following
Err(other_error) => return Err(other_error.into()),
};
let relationship = get_relationship(db_client, &current_user.id, &target.id).await?;
Ok(HttpResponse::Ok().json(relationship))
}
#[get("/{account_id}/statuses")] #[get("/{account_id}/statuses")]
async fn get_account_statuses( async fn get_account_statuses(
auth: Option<BearerAuth>, auth: Option<BearerAuth>,
@ -566,6 +602,8 @@ pub fn account_api_scope() -> Scope {
.service(get_account) .service(get_account)
.service(follow_account) .service(follow_account)
.service(unfollow_account) .service(unfollow_account)
.service(mute_account)
.service(unmute_account)
.service(get_account_statuses) .service(get_account_statuses)
.service(get_account_followers) .service(get_account_followers)
.service(get_account_following) .service(get_account_following)

View file

@ -18,6 +18,7 @@ struct InstanceStats {
struct InstanceStatusLimits { struct InstanceStatusLimits {
max_characters: usize, max_characters: usize,
max_media_attachments: usize, max_media_attachments: usize,
characters_reserved_per_url: usize,
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -105,6 +106,7 @@ impl InstanceInfo {
statuses: InstanceStatusLimits { statuses: InstanceStatusLimits {
max_characters: config.limits.posts.character_limit, max_characters: config.limits.posts.character_limit,
max_media_attachments: ATTACHMENT_LIMIT, max_media_attachments: ATTACHMENT_LIMIT,
characters_reserved_per_url: 32, // not real, but for compatibility
}, },
media_attachments: InstanceMediaLimits { media_attachments: InstanceMediaLimits {
supported_mime_types: SUPPORTED_MEDIA_TYPES supported_mime_types: SUPPORTED_MEDIA_TYPES
@ -117,7 +119,7 @@ impl InstanceInfo {
}, },
thumbnail: None, thumbnail: None,
email: "".to_string(), email: "".to_string(),
languages: vec![], languages: vec!["en".to_string()],
rules: vec![], rules: vec![],
urls: None, urls: None,
login_message: config.login_message.clone(), login_message: config.login_message.clone(),