hyaenidae/profiles/src/apub/actions/mod.rs

803 lines
19 KiB
Rust

use crate::{
apub::Endpoints,
store::{OwnerSource, Visibility},
};
use chrono::{DateTime, Utc};
use hyaenidae_content::bbcode;
use url::Url;
use uuid::Uuid;
mod apub;
mod block;
mod comment;
mod federation;
mod federation_request;
mod follow;
mod follow_request;
mod noop;
mod profile;
mod react;
mod report;
mod server;
mod server_block;
mod submission;
pub(crate) use apub::ingest;
struct CreateServerApub {
application_apub_id: Url,
public_key: String,
endpoints: Endpoints,
}
pub struct CreateServer {
apub: Option<CreateServerApub>,
domain: String,
title: Option<String>,
description: Option<String>,
published: DateTime<Utc>,
}
impl CreateServer {
pub(crate) fn from_domain(domain: String) -> Self {
CreateServer {
apub: None,
domain,
title: None,
description: None,
published: Utc::now(),
}
}
}
struct UpdateServerApub {
public_key: String,
endpoints: Endpoints,
}
pub struct UpdateServer {
apub: Option<UpdateServerApub>,
server_id: Uuid,
title: Option<String>,
title_source: Option<String>,
description: Option<String>,
description_source: Option<String>,
}
impl UpdateServer {
pub fn from_text(server_id: Uuid, title: Option<String>, description: Option<String>) -> Self {
let title_source = title.and_then(|title| {
if title.trim().is_empty() {
None
} else {
Some(title.trim().to_owned())
}
});
let description_source = description.and_then(|description| {
if description.trim().is_empty() {
None
} else {
Some(description.trim().to_owned())
}
});
UpdateServer {
apub: None,
server_id,
title: title_source.clone(),
title_source,
description: description_source.as_deref().map(|s| bbcode(s, |v| v)),
description_source,
}
}
}
pub struct DeleteServer {
server_id: Uuid,
}
impl DeleteServer {
pub fn from_id(server_id: Uuid) -> Self {
DeleteServer { server_id }
}
}
enum Reported {
Submission(Uuid),
Comment(Uuid),
Profile(Uuid),
}
enum Reporter {
Profile(Uuid),
Server(Uuid),
}
pub struct CreateReport {
flag_apub_id: Option<Url>,
reported_item: Reported,
reporter: Reporter,
note: Option<String>,
}
impl CreateReport {
pub fn from_profile(reported_profile: Uuid, reporter: Uuid, note: Option<String>) -> Self {
CreateReport {
flag_apub_id: None,
reported_item: Reported::Profile(reported_profile),
reporter: Reporter::Profile(reporter),
note,
}
}
pub fn from_submission(
reported_submission: Uuid,
reporter: Uuid,
note: Option<String>,
) -> Self {
CreateReport {
flag_apub_id: None,
reported_item: Reported::Submission(reported_submission),
reporter: Reporter::Profile(reporter),
note,
}
}
pub fn from_comment(reported_comment: Uuid, reporter: Uuid, note: Option<String>) -> Self {
CreateReport {
flag_apub_id: None,
reported_item: Reported::Comment(reported_comment),
reporter: Reporter::Profile(reporter),
note,
}
}
}
pub struct ResolveReport {
report_id: Uuid,
resolution: String,
}
impl ResolveReport {
pub fn from_resolution(report_id: Uuid, resolution: String) -> Self {
ResolveReport {
report_id,
resolution,
}
}
}
pub struct ForwardReport {
report_id: Uuid,
}
impl ForwardReport {
pub fn from_report(report_id: Uuid) -> Self {
ForwardReport { report_id }
}
}
pub struct CreateReact {
like_apub_id: Option<Url>,
submission_id: Uuid,
profile_id: Uuid,
comment_id: Option<Uuid>,
react: String,
published: DateTime<Utc>,
}
pub struct DeleteReact {
react_id: Uuid,
}
pub struct CreateComment {
note_apub_id: Option<Url>,
submission_id: Uuid,
profile_id: Uuid,
comment_id: Option<Uuid>,
body: String,
body_source: Option<String>,
published: DateTime<Utc>,
}
impl CreateComment {
pub fn from_text(
submission_id: Uuid,
profile_id: Uuid,
comment_id: Option<Uuid>,
body: String,
) -> Self {
let body_source = body;
let body = bbcode(&body_source, |v| v);
CreateComment {
note_apub_id: None,
submission_id,
profile_id,
comment_id,
body,
body_source: Some(body_source),
published: Utc::now(),
}
}
}
pub struct Noop;
pub struct UpdateComment {
update_apub_id: Option<Url>,
comment_id: Uuid,
body: Option<String>,
body_source: Option<String>,
}
impl UpdateComment {
pub fn from_text(comment_id: Uuid, body: String) -> Self {
let body_source = if body.trim().is_empty() {
None
} else {
Some(body.trim().to_owned())
};
UpdateComment {
update_apub_id: None,
comment_id,
body: body_source.as_deref().map(|s| bbcode(s, |v| v)),
body_source,
}
}
}
pub struct DeleteComment {
delete_apub_id: Option<Url>,
comment_id: Uuid,
}
impl DeleteComment {
pub fn from_id(comment_id: Uuid) -> Self {
DeleteComment {
delete_apub_id: None,
comment_id,
}
}
}
pub struct CreateSubmission {
note_apub_id: Option<Url>,
profile_id: Uuid,
title: String,
description: Option<String>,
files: Vec<Uuid>,
published: Option<DateTime<Utc>>,
visibility: Visibility,
local_only: bool,
logged_in_only: bool,
sensitive: bool,
updated: Option<DateTime<Utc>>,
}
impl CreateSubmission {
pub fn from_file(profile_id: Uuid, file_id: Uuid) -> Self {
CreateSubmission {
note_apub_id: None,
profile_id,
title: "".to_owned(),
description: None,
files: vec![file_id],
published: None,
visibility: Visibility::Public,
local_only: false,
logged_in_only: false,
sensitive: false,
updated: None,
}
}
}
pub struct UpdateSubmission {
submission_id: Uuid,
title: Option<String>,
title_source: Option<String>,
description: Option<String>,
description_source: Option<String>,
visibility: Option<Visibility>,
local_only: Option<bool>,
logged_in_only: Option<bool>,
published: Option<DateTime<Utc>>,
updated: Option<DateTime<Utc>>,
removed_files: Option<Vec<Uuid>>,
new_files: Option<Vec<Uuid>>,
only_files: Option<Vec<Uuid>>,
sensitive: Option<bool>,
}
impl UpdateSubmission {
pub fn from_text(submission_id: Uuid, title: String, description: Option<String>) -> Self {
let title_source = if title.trim().is_empty() {
None
} else {
Some(title.trim().to_owned())
};
let description_source = description.and_then(|s| {
if s.trim().is_empty() {
None
} else {
Some(s.trim().to_owned())
}
});
UpdateSubmission {
submission_id,
title: title_source.clone(),
title_source,
description: description_source.as_deref().map(|s| bbcode(s, |v| v)),
description_source,
visibility: None,
local_only: None,
logged_in_only: None,
published: None,
updated: Some(Utc::now()),
removed_files: None,
new_files: None,
only_files: None,
sensitive: None,
}
}
pub fn from_visibility(
submission_id: Uuid,
visibility: Visibility,
local_only: bool,
logged_in_only: bool,
) -> Self {
UpdateSubmission {
submission_id,
title: None,
title_source: None,
description: None,
description_source: None,
visibility: Some(visibility),
local_only: Some(local_only),
logged_in_only: Some(logged_in_only),
published: None,
updated: Some(Utc::now()),
removed_files: None,
new_files: None,
only_files: None,
sensitive: None,
}
}
pub fn from_new_file(submission_id: Uuid, file_id: Uuid) -> Self {
UpdateSubmission {
submission_id,
title: None,
title_source: None,
description: None,
description_source: None,
visibility: None,
local_only: None,
logged_in_only: None,
published: None,
updated: Some(Utc::now()),
removed_files: None,
new_files: Some(vec![file_id]),
only_files: None,
sensitive: None,
}
}
pub fn from_removed_file(submission_id: Uuid, file_id: Uuid) -> Self {
UpdateSubmission {
submission_id,
title: None,
title_source: None,
description: None,
description_source: None,
visibility: None,
published: None,
updated: Some(Utc::now()),
local_only: None,
logged_in_only: None,
removed_files: Some(vec![file_id]),
new_files: None,
only_files: None,
sensitive: None,
}
}
pub fn from_sensitive(submission_id: Uuid, sensitive: bool) -> Self {
UpdateSubmission {
submission_id,
title: None,
title_source: None,
description: None,
description_source: None,
visibility: None,
local_only: None,
logged_in_only: None,
published: None,
updated: None,
removed_files: None,
new_files: None,
only_files: None,
sensitive: Some(sensitive),
}
}
pub fn publish_now(submission_id: Uuid) -> Self {
UpdateSubmission {
submission_id,
title: None,
title_source: None,
description: None,
description_source: None,
visibility: None,
local_only: None,
logged_in_only: None,
published: Some(Utc::now()),
updated: None,
removed_files: None,
new_files: None,
only_files: None,
sensitive: None,
}
}
}
pub struct DeleteSubmission {
submission_id: Uuid,
}
impl DeleteSubmission {
pub fn from_id(submission_id: Uuid) -> Self {
DeleteSubmission { submission_id }
}
}
pub struct CreateProfileApub {
person_apub_id: Url,
public_key: String,
endpoints: Endpoints,
}
pub struct CreateProfile {
apub: Option<CreateProfileApub>,
owner_source: OwnerSource,
handle: String,
domain: String,
display_name: Option<String>,
description: Option<String>,
login_required: bool,
icon: Option<Uuid>,
banner: Option<Uuid>,
published: DateTime<Utc>,
updated: Option<DateTime<Utc>>,
}
impl CreateProfile {
pub fn from_local(owner_id: Uuid, handle: String, domain: String) -> Self {
CreateProfile {
apub: None,
owner_source: OwnerSource::Local(owner_id),
handle,
domain,
display_name: None,
description: None,
login_required: true,
icon: None,
banner: None,
published: Utc::now(),
updated: None,
}
}
}
struct UpdateProfileApub {
public_key: String,
endpoints: Endpoints,
}
pub struct UpdateProfile {
apub: Option<UpdateProfileApub>,
profile_id: Uuid,
display_name: Option<String>,
display_name_source: Option<String>,
description: Option<String>,
description_source: Option<String>,
login_required: Option<bool>,
icon: Option<Uuid>,
banner: Option<Uuid>,
updated: Option<DateTime<Utc>>,
}
impl UpdateProfile {
pub fn from_text(profile_id: Uuid, display_name: String, description: String) -> Self {
let display_name_source = if display_name.trim().is_empty() {
None
} else {
Some(display_name.trim().to_owned())
};
let description_source = if description.trim().is_empty() {
None
} else {
Some(description.trim().to_owned())
};
UpdateProfile {
apub: None,
profile_id,
display_name: display_name_source.clone(),
display_name_source,
description: description_source.as_deref().map(|s| bbcode(s, |v| v)),
description_source,
login_required: None,
icon: None,
banner: None,
updated: Some(Utc::now()),
}
}
pub fn from_icon(profile_id: Uuid, icon: Uuid) -> Self {
UpdateProfile {
apub: None,
profile_id,
display_name: None,
display_name_source: None,
description: None,
description_source: None,
login_required: None,
icon: Some(icon),
banner: None,
updated: Some(Utc::now()),
}
}
pub fn from_banner(profile_id: Uuid, banner: Uuid) -> Self {
UpdateProfile {
apub: None,
profile_id,
display_name: None,
display_name_source: None,
description: None,
description_source: None,
login_required: None,
icon: None,
banner: Some(banner),
updated: Some(Utc::now()),
}
}
pub fn from_login_required(profile_id: Uuid, login_required: bool) -> Self {
UpdateProfile {
apub: None,
profile_id,
display_name: None,
display_name_source: None,
description: None,
description_source: None,
login_required: Some(login_required),
icon: None,
banner: None,
updated: Some(Utc::now()),
}
}
}
pub struct DeleteProfile {
profile_id: Uuid,
}
impl DeleteProfile {
pub fn from_id(profile_id: Uuid) -> Self {
DeleteProfile { profile_id }
}
}
pub struct SuspendProfile {
profile_id: Uuid,
}
impl SuspendProfile {
pub fn from_id(profile_id: Uuid) -> Self {
SuspendProfile { profile_id }
}
}
pub struct CreateFollowRequest {
follow_apub_id: Option<Url>,
followed_profile: Uuid,
followed_by_profile: Uuid,
published: DateTime<Utc>,
}
impl CreateFollowRequest {
pub fn from_profiles(followed_profile: Uuid, followed_by_profile: Uuid) -> Self {
CreateFollowRequest {
follow_apub_id: None,
followed_profile,
followed_by_profile,
published: Utc::now(),
}
}
}
pub struct AcceptFollowRequest {
accept_apub_id: Option<Url>,
follow_request_id: Uuid,
published: DateTime<Utc>,
}
impl AcceptFollowRequest {
pub fn from_id(follow_request_id: Uuid) -> Self {
AcceptFollowRequest {
accept_apub_id: None,
follow_request_id,
published: Utc::now(),
}
}
}
pub struct RejectFollowRequest {
follow_request_id: Uuid,
}
impl RejectFollowRequest {
pub fn from_id(follow_request_id: Uuid) -> Self {
RejectFollowRequest { follow_request_id }
}
}
pub struct UndoFollowRequest {
follow_request_id: Uuid,
}
impl UndoFollowRequest {
pub fn from_id(follow_request_id: Uuid) -> Self {
UndoFollowRequest { follow_request_id }
}
}
pub struct UndoFollow {
follow_id: Uuid,
}
pub struct UndoAcceptFollow {
follow_id: Uuid,
}
impl UndoFollow {
pub fn from_id(follow_id: Uuid) -> Self {
UndoFollow { follow_id }
}
}
pub struct CreateFederationRequest {
follow_apub_id: Option<Url>,
followed_server: Uuid,
followed_by_server: Uuid,
published: DateTime<Utc>,
}
impl CreateFederationRequest {
pub fn from_servers(followed_server: Uuid, followed_by_server: Uuid) -> Self {
CreateFederationRequest {
follow_apub_id: None,
followed_server,
followed_by_server,
published: Utc::now(),
}
}
}
pub struct AcceptFederationRequest {
accept_apub_id: Option<Url>,
follow_request_id: Uuid,
published: DateTime<Utc>,
}
impl AcceptFederationRequest {
pub fn from_id(follow_request_id: Uuid) -> Self {
AcceptFederationRequest {
accept_apub_id: None,
follow_request_id,
published: Utc::now(),
}
}
}
pub struct RejectFederationRequest {
follow_request_id: Uuid,
}
impl RejectFederationRequest {
pub fn from_id(follow_request_id: Uuid) -> Self {
RejectFederationRequest { follow_request_id }
}
}
pub struct UndoFederationRequest {
follow_request_id: Uuid,
}
impl UndoFederationRequest {
pub fn from_id(follow_request_id: Uuid) -> Self {
UndoFederationRequest { follow_request_id }
}
}
pub struct UndoFederation {
follow_id: Uuid,
}
impl UndoFederation {
pub fn from_id(follow_id: Uuid) -> Self {
UndoFederation { follow_id }
}
}
pub struct UndoAcceptFederation {
follow_id: Uuid,
}
impl UndoAcceptFederation {
pub fn from_id(follow_id: Uuid) -> Self {
UndoAcceptFederation { follow_id }
}
}
pub struct CreateBlock {
block_apub_id: Option<Url>,
blocked_profile: Uuid,
blocked_by_profile: Uuid,
published: DateTime<Utc>,
}
impl CreateBlock {
pub fn from_profiles(blocked_profile: Uuid, blocked_by_profile: Uuid) -> Self {
CreateBlock {
block_apub_id: None,
blocked_profile,
blocked_by_profile,
published: Utc::now(),
}
}
}
pub struct DeleteBlock {
block_id: Uuid,
}
impl DeleteBlock {
pub fn from_id(block_id: Uuid) -> Self {
DeleteBlock { block_id }
}
}
pub struct CreateServerBlock {
blocked_server: Uuid,
blocked_by_server: Uuid,
published: DateTime<Utc>,
}
impl CreateServerBlock {
pub fn from_servers(blocked_server: Uuid, blocked_by_server: Uuid) -> Self {
CreateServerBlock {
blocked_server,
blocked_by_server,
published: Utc::now(),
}
}
}
pub struct DeleteServerBlock {
block_id: Uuid,
}
impl DeleteServerBlock {
pub fn from_id(block_id: Uuid) -> Self {
DeleteServerBlock { block_id }
}
}