fedimovies/fedimovies-models/src/posts/types.rs

283 lines
7.8 KiB
Rust
Raw Normal View History

2021-04-09 00:22:17 +00:00
use chrono::{DateTime, Utc};
use postgres_types::FromSql;
2021-04-09 00:22:17 +00:00
use tokio_postgres::Row;
use uuid::Uuid;
use crate::attachments::types::DbMediaAttachment;
2022-12-03 22:09:42 +00:00
use crate::database::{
int_enum::{int_enum_from_sql, int_enum_to_sql},
2023-04-24 15:35:32 +00:00
DatabaseError, DatabaseTypeError,
2022-12-03 22:09:42 +00:00
};
use crate::emojis::types::DbEmoji;
use crate::profiles::types::DbActorProfile;
2021-04-09 00:22:17 +00:00
#[derive(Clone, Debug, PartialEq)]
pub enum Visibility {
Public,
Direct,
Followers,
Subscribers,
}
impl Default for Visibility {
2023-04-24 15:35:32 +00:00
fn default() -> Self {
Self::Public
}
}
impl From<&Visibility> for i16 {
fn from(value: &Visibility) -> i16 {
match value {
Visibility::Public => 1,
Visibility::Direct => 2,
Visibility::Followers => 3,
Visibility::Subscribers => 4,
}
}
}
impl TryFrom<i16> for Visibility {
2022-12-03 22:09:42 +00:00
type Error = DatabaseTypeError;
fn try_from(value: i16) -> Result<Self, Self::Error> {
let visibility = match value {
1 => Self::Public,
2 => Self::Direct,
3 => Self::Followers,
4 => Self::Subscribers,
2022-12-03 22:09:42 +00:00
_ => return Err(DatabaseTypeError),
};
Ok(visibility)
}
}
int_enum_from_sql!(Visibility);
int_enum_to_sql!(Visibility);
2021-04-09 00:22:17 +00:00
#[derive(FromSql)]
#[postgres(name = "post")]
pub struct DbPost {
pub id: Uuid,
pub author_id: Uuid,
pub content: String,
2021-09-22 16:32:44 +00:00
pub in_reply_to_id: Option<Uuid>,
pub repost_of_id: Option<Uuid>,
pub visibility: Visibility,
2023-04-15 23:43:19 +00:00
pub is_sensitive: bool,
pub reply_count: i32,
pub reaction_count: i32,
pub repost_count: i32,
2021-10-08 22:39:40 +00:00
pub object_id: Option<String>,
2021-04-09 00:22:17 +00:00
pub ipfs_cid: Option<String>,
pub token_id: Option<i32>,
pub token_tx_id: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: Option<DateTime<Utc>>, // edited at
2021-04-09 00:22:17 +00:00
}
// List of user's actions
#[derive(Clone)]
pub struct PostActions {
pub favourited: bool,
pub reposted: bool,
}
#[derive(Clone)]
2021-04-09 00:22:17 +00:00
pub struct Post {
pub id: Uuid,
pub author: DbActorProfile,
pub content: String,
2021-09-22 16:32:44 +00:00
pub in_reply_to_id: Option<Uuid>,
pub repost_of_id: Option<Uuid>,
pub visibility: Visibility,
2023-04-15 23:43:19 +00:00
pub is_sensitive: bool,
pub reply_count: i32,
pub reaction_count: i32,
pub repost_count: i32,
2021-04-09 00:22:17 +00:00
pub attachments: Vec<DbMediaAttachment>,
2021-11-11 19:10:28 +00:00
pub mentions: Vec<DbActorProfile>,
2021-12-07 23:28:58 +00:00
pub tags: Vec<String>,
pub links: Vec<Uuid>,
pub emojis: Vec<DbEmoji>,
2021-10-08 22:39:40 +00:00
pub object_id: Option<String>,
2021-04-09 00:22:17 +00:00
pub ipfs_cid: Option<String>,
pub token_id: Option<i32>,
pub token_tx_id: Option<String>,
pub created_at: DateTime<Utc>,
2022-05-11 12:50:36 +00:00
pub updated_at: Option<DateTime<Utc>>,
// These fields are not populated automatically
// by functions in posts::queries module
pub actions: Option<PostActions>,
pub in_reply_to: Option<Box<Post>>,
pub repost_of: Option<Box<Post>>,
pub linked: Vec<Post>,
2021-04-09 00:22:17 +00:00
}
2021-10-14 20:25:00 +00:00
impl Post {
pub fn new(
db_post: DbPost,
db_author: DbActorProfile,
db_attachments: Vec<DbMediaAttachment>,
2021-11-11 19:10:28 +00:00
db_mentions: Vec<DbActorProfile>,
2021-12-07 23:28:58 +00:00
db_tags: Vec<String>,
db_links: Vec<Uuid>,
db_emojis: Vec<DbEmoji>,
2022-12-03 22:09:42 +00:00
) -> Result<Self, DatabaseTypeError> {
// Consistency checks
if db_post.author_id != db_author.id {
2022-12-03 22:09:42 +00:00
return Err(DatabaseTypeError);
};
if db_author.is_local() != db_post.object_id.is_none() {
2022-12-03 22:09:42 +00:00
return Err(DatabaseTypeError);
};
2023-04-24 15:35:32 +00:00
if db_post.repost_of_id.is_some()
&& (db_post.content.len() != 0
|| db_post.is_sensitive
|| db_post.in_reply_to_id.is_some()
|| db_post.ipfs_cid.is_some()
|| db_post.token_id.is_some()
|| db_post.token_tx_id.is_some()
|| !db_attachments.is_empty()
|| !db_mentions.is_empty()
|| !db_tags.is_empty()
|| !db_links.is_empty()
|| !db_emojis.is_empty())
{
2022-12-03 22:09:42 +00:00
return Err(DatabaseTypeError);
};
let post = Self {
2021-10-14 20:25:00 +00:00
id: db_post.id,
author: db_author,
content: db_post.content,
in_reply_to_id: db_post.in_reply_to_id,
repost_of_id: db_post.repost_of_id,
visibility: db_post.visibility,
2023-04-15 23:43:19 +00:00
is_sensitive: db_post.is_sensitive,
2021-10-14 20:25:00 +00:00
reply_count: db_post.reply_count,
reaction_count: db_post.reaction_count,
repost_count: db_post.repost_count,
2021-10-14 20:25:00 +00:00
attachments: db_attachments,
2021-11-11 19:10:28 +00:00
mentions: db_mentions,
2021-12-07 23:28:58 +00:00
tags: db_tags,
links: db_links,
emojis: db_emojis,
2021-10-14 20:25:00 +00:00
object_id: db_post.object_id,
ipfs_cid: db_post.ipfs_cid,
token_id: db_post.token_id,
token_tx_id: db_post.token_tx_id,
created_at: db_post.created_at,
2022-05-11 12:50:36 +00:00
updated_at: db_post.updated_at,
actions: None,
in_reply_to: None,
repost_of: None,
linked: vec![],
};
Ok(post)
2021-10-14 20:25:00 +00:00
}
2022-11-21 18:55:06 +00:00
pub fn is_local(&self) -> bool {
self.author.is_local()
}
pub fn is_public(&self) -> bool {
matches!(self.visibility, Visibility::Public)
}
2021-10-14 20:25:00 +00:00
}
#[cfg(feature = "test-utils")]
2021-10-09 12:53:53 +00:00
impl Default for Post {
fn default() -> Self {
Self {
id: Uuid::new_v4(),
author: Default::default(),
content: "".to_string(),
in_reply_to_id: None,
repost_of_id: None,
visibility: Visibility::Public,
2023-04-15 23:43:19 +00:00
is_sensitive: false,
2021-10-09 12:53:53 +00:00
reply_count: 0,
reaction_count: 0,
repost_count: 0,
2021-10-09 12:53:53 +00:00
attachments: vec![],
2021-11-11 19:10:28 +00:00
mentions: vec![],
2021-12-07 23:28:58 +00:00
tags: vec![],
links: vec![],
emojis: vec![],
2021-10-09 12:53:53 +00:00
object_id: None,
ipfs_cid: None,
token_id: None,
token_tx_id: None,
created_at: Utc::now(),
2022-05-11 12:50:36 +00:00
updated_at: None,
actions: None,
in_reply_to: None,
repost_of: None,
linked: vec![],
2021-10-09 12:53:53 +00:00
}
}
}
2021-04-09 00:22:17 +00:00
impl TryFrom<&Row> for Post {
type Error = DatabaseError;
2021-04-09 00:22:17 +00:00
fn try_from(row: &Row) -> Result<Self, Self::Error> {
let db_post: DbPost = row.try_get("post")?;
let db_profile: DbActorProfile = row.try_get("actor_profile")?;
let db_attachments: Vec<DbMediaAttachment> = row.try_get("attachments")?;
2021-11-11 19:10:28 +00:00
let db_mentions: Vec<DbActorProfile> = row.try_get("mentions")?;
2021-12-07 23:28:58 +00:00
let db_tags: Vec<String> = row.try_get("tags")?;
let db_links: Vec<Uuid> = row.try_get("links")?;
let db_emojis: Vec<DbEmoji> = row.try_get("emojis")?;
let post = Self::new(
db_post,
db_profile,
db_attachments,
db_mentions,
db_tags,
db_links,
db_emojis,
)?;
2021-04-09 00:22:17 +00:00
Ok(post)
}
}
#[derive(Default)]
2021-04-09 00:22:17 +00:00
pub struct PostCreateData {
pub content: String,
2021-09-22 16:32:44 +00:00
pub in_reply_to_id: Option<Uuid>,
pub repost_of_id: Option<Uuid>,
pub visibility: Visibility,
2023-04-15 23:43:19 +00:00
pub is_sensitive: bool,
2021-04-09 00:22:17 +00:00
pub attachments: Vec<Uuid>,
2021-11-11 19:10:28 +00:00
pub mentions: Vec<Uuid>,
2021-12-07 23:28:58 +00:00
pub tags: Vec<String>,
pub links: Vec<Uuid>,
pub emojis: Vec<Uuid>,
2021-10-08 22:39:40 +00:00
pub object_id: Option<String>,
2022-09-29 15:26:12 +00:00
pub created_at: DateTime<Utc>,
2021-04-09 00:22:17 +00:00
}
impl PostCreateData {
2023-04-24 15:35:32 +00:00
pub fn repost(repost_of_id: Uuid, object_id: Option<String>) -> Self {
2022-10-04 23:18:01 +00:00
Self {
repost_of_id: Some(repost_of_id),
2023-04-25 11:19:04 +00:00
object_id,
2022-10-04 23:18:01 +00:00
created_at: Utc::now(),
..Default::default()
}
}
2021-04-09 00:22:17 +00:00
}
#[cfg_attr(test, derive(Default))]
2022-05-11 12:50:36 +00:00
pub struct PostUpdateData {
pub content: String,
2023-04-15 23:43:19 +00:00
pub is_sensitive: bool,
pub attachments: Vec<Uuid>,
pub mentions: Vec<Uuid>,
pub tags: Vec<String>,
pub links: Vec<Uuid>,
pub emojis: Vec<Uuid>,
2022-05-11 12:50:36 +00:00
pub updated_at: DateTime<Utc>,
}