fedimovies/src/mastodon_api/statuses/types.rs

221 lines
6 KiB
Rust
Raw Normal View History

2021-04-09 00:22:17 +00:00
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use mitra_models::{
emojis::types::DbEmoji,
posts::types::{Post, Visibility},
profiles::types::DbActorProfile,
};
use crate::activitypub::identifiers::{
local_tag_collection,
post_object_id,
profile_actor_url,
};
2023-02-02 12:38:02 +00:00
use crate::mastodon_api::{
accounts::types::Account,
custom_emojis::types::CustomEmoji,
media::types::Attachment,
};
2021-11-11 19:10:28 +00:00
/// https://docs.joinmastodon.org/entities/mention/
#[derive(Serialize)]
pub struct Mention {
id: String,
username: String,
acct: String,
url: String,
}
impl Mention {
fn from_profile(instance_url: &str, profile: DbActorProfile) -> Self {
2021-11-11 19:10:28 +00:00
Mention {
id: profile.id.to_string(),
username: profile.username.clone(),
acct: profile.acct.clone(),
url: profile_actor_url(instance_url, &profile),
2021-11-11 19:10:28 +00:00
}
}
}
2021-04-09 00:22:17 +00:00
2021-12-07 23:28:58 +00:00
/// https://docs.joinmastodon.org/entities/tag/
#[derive(Serialize)]
pub struct Tag {
name: String,
url: String,
}
impl Tag {
pub fn from_tag_name(instance_url: &str, tag_name: String) -> Self {
let tag_url = local_tag_collection(instance_url, &tag_name);
2021-12-07 23:28:58 +00:00
Tag {
name: tag_name,
url: tag_url,
2021-12-07 23:28:58 +00:00
}
}
}
2021-04-09 00:22:17 +00:00
/// https://docs.joinmastodon.org/entities/status/
#[derive(Serialize)]
pub struct Status {
pub id: Uuid,
2021-11-21 15:08:20 +00:00
pub uri: String,
2021-04-09 00:22:17 +00:00
pub created_at: DateTime<Utc>,
2022-05-11 12:50:36 +00:00
// Undocumented https://github.com/mastodon/mastodon/blob/v3.5.2/app/serializers/rest/status_serializer.rb
edited_at: Option<DateTime<Utc>>,
2021-04-09 00:22:17 +00:00
pub account: Account,
pub content: String,
2021-09-22 16:32:44 +00:00
pub in_reply_to_id: Option<Uuid>,
pub reblog: Option<Box<Status>>,
pub visibility: String,
2023-04-15 23:43:19 +00:00
pub sensitive: bool,
pub spoiler_text: Option<String>,
pub replies_count: i32,
pub favourites_count: i32,
pub reblogs_count: i32,
2021-04-09 00:22:17 +00:00
pub media_attachments: Vec<Attachment>,
2021-11-11 19:10:28 +00:00
mentions: Vec<Mention>,
2021-12-07 23:28:58 +00:00
tags: Vec<Tag>,
2023-01-16 22:40:03 +00:00
emojis: Vec<CustomEmoji>,
2021-04-09 00:22:17 +00:00
// Authorized user attributes
pub favourited: bool,
pub reblogged: bool,
2021-04-09 00:22:17 +00:00
// Extra fields
pub ipfs_cid: Option<String>,
pub token_id: Option<i32>,
pub token_tx_id: Option<String>,
links: Vec<Status>,
2021-04-09 00:22:17 +00:00
}
impl Status {
pub fn from_post(
base_url: &str,
instance_url: &str,
post: Post,
) -> Self {
let object_id = post_object_id(instance_url, &post);
2021-04-09 00:22:17 +00:00
let attachments: Vec<Attachment> = post.attachments.into_iter()
.map(|item| Attachment::from_db(base_url, item))
2021-04-09 00:22:17 +00:00
.collect();
2021-11-11 19:10:28 +00:00
let mentions: Vec<Mention> = post.mentions.into_iter()
.map(|item| Mention::from_profile(instance_url, item))
2021-11-11 19:10:28 +00:00
.collect();
2021-12-07 23:28:58 +00:00
let tags: Vec<Tag> = post.tags.into_iter()
.map(|tag_name| Tag::from_tag_name(instance_url, tag_name))
2021-12-07 23:28:58 +00:00
.collect();
2023-01-16 22:40:03 +00:00
let emojis: Vec<CustomEmoji> = post.emojis.into_iter()
.map(|emoji| CustomEmoji::from_db(base_url, emoji))
2023-01-16 22:40:03 +00:00
.collect();
let account = Account::from_profile(
base_url,
instance_url,
post.author,
);
let reblog = if let Some(repost_of) = post.repost_of {
let status = Status::from_post(base_url, instance_url, *repost_of);
Some(Box::new(status))
} else {
None
};
let links = post.linked.into_iter().map(|post| {
Status::from_post(base_url, instance_url, post)
}).collect();
let visibility = match post.visibility {
Visibility::Public => "public",
Visibility::Direct => "direct",
Visibility::Followers => "private",
Visibility::Subscribers => "subscribers",
};
2021-04-09 00:22:17 +00:00
Self {
id: post.id,
2021-11-21 15:08:20 +00:00
uri: object_id,
2021-04-09 00:22:17 +00:00
created_at: post.created_at,
2022-05-11 12:50:36 +00:00
edited_at: post.updated_at,
2021-04-09 00:22:17 +00:00
account: account,
content: post.content,
2021-09-22 16:32:44 +00:00
in_reply_to_id: post.in_reply_to_id,
reblog: reblog,
visibility: visibility.to_string(),
2023-04-15 23:43:19 +00:00
sensitive: post.is_sensitive,
spoiler_text: None,
replies_count: post.reply_count,
favourites_count: post.reaction_count,
reblogs_count: post.repost_count,
2021-04-09 00:22:17 +00:00
media_attachments: attachments,
2021-11-11 19:10:28 +00:00
mentions: mentions,
2021-12-07 23:28:58 +00:00
tags: tags,
2023-01-16 22:40:03 +00:00
emojis: emojis,
favourited: post.actions.as_ref().map_or(false, |actions| actions.favourited),
reblogged: post.actions.as_ref().map_or(false, |actions| actions.reposted),
2021-04-09 00:22:17 +00:00
ipfs_cid: post.ipfs_cid,
token_id: post.token_id,
token_tx_id: post.token_tx_id,
links: links,
2021-04-09 00:22:17 +00:00
}
}
}
fn default_post_content_type() -> String { "text/html".to_string() }
2021-04-09 00:22:17 +00:00
/// https://docs.joinmastodon.org/methods/statuses/
#[derive(Deserialize)]
pub struct StatusData {
pub status: String,
#[serde(rename = "media_ids[]")]
pub media_ids: Option<Vec<Uuid>>,
2021-09-22 16:32:44 +00:00
pub in_reply_to_id: Option<Uuid>,
2022-01-07 20:41:46 +00:00
pub visibility: Option<String>,
2023-04-15 23:43:19 +00:00
#[serde(default)]
pub sensitive: bool,
// Not supported by Mastodon
pub mentions: Option<Vec<Uuid>>,
#[serde(default = "default_post_content_type")]
pub content_type: String,
2021-04-09 00:22:17 +00:00
}
#[derive(Deserialize)]
pub struct StatusPreviewData {
pub status: String,
#[serde(default = "default_post_content_type")]
pub content_type: String,
}
#[derive(Serialize)]
pub struct StatusPreview {
pub content: String,
2023-01-21 22:45:25 +00:00
pub emojis: Vec<CustomEmoji>
}
impl StatusPreview {
pub fn new(
instance_url: &str,
content: String,
emojis: Vec<DbEmoji>,
) -> Self {
let emojis: Vec<CustomEmoji> = emojis.into_iter()
.map(|emoji| CustomEmoji::from_db(instance_url, emoji))
.collect();
Self { content, emojis }
}
}
#[derive(Serialize)]
pub struct Context {
pub ancestors: Vec<Status>,
pub descendants: Vec<Status>,
}
#[derive(Deserialize)]
pub struct TransactionData {
pub transaction_id: String,
}