From b65a51a1efaf75b5cbbacb848cbbc7a54b6da83d Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Fri, 17 May 2024 13:24:41 +0200 Subject: [PATCH 01/23] feat: Update API domain variable name --- Cargo.lock | 9 ++++ Cargo.toml | 9 ++++ src/lysand/objects.rs | 107 ++++++++++++++++++++++++++++++++++-------- src/lysand/superx.rs | 20 ++++++++ src/lysand/test.rs | 11 +++++ src/main.rs | 4 +- 6 files changed, 139 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d4dfd4..eb62c0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -457,6 +457,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + [[package]] name = "autocfg" version = "1.2.0" @@ -1917,6 +1923,7 @@ dependencies = [ "tokio", "tracing", "url", + "uuid", "vcpkg", ] @@ -3784,7 +3791,9 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ + "atomic", "getrandom", + "rand", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index 973d159..dc6dad7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,15 @@ features = [ "sqlx-sqlite","sqlx-mysql","with-chrono" ] +[dependencies.uuid] +version = "1.8.0" +features = [ + "v4", + "v7", + "fast-rng", # Use a faster (but still sufficiently random) RNG + "serde", +] + [build-dependencies] vcpkg = "0.2.15" diff --git a/src/lysand/objects.rs b/src/lysand/objects.rs index 4ed13de..08d09ee 100644 --- a/src/lysand/objects.rs +++ b/src/lysand/objects.rs @@ -13,6 +13,7 @@ use time::{ OffsetDateTime, }; use url::Url; +use uuid::Uuid; const FORMAT: Iso8601<6651332276412969266533270467398074368> = Iso8601::< { @@ -49,6 +50,25 @@ pub enum LysandType { ServerMetadata, } +#[derive(Debug, Serialize, Deserialize, Clone)] +pub enum CategoryType { + Microblog, + Forum, + Blog, + Image, + Video, + Audio, + Messaging +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub enum VisibilityType { + Public, + Unlisted, + Followers, + Direct +} + #[derive(Debug, Serialize, Deserialize, Clone)] pub enum LysandExtensions { #[serde(rename = "org.lysand:microblogging/Announce")] @@ -116,7 +136,7 @@ impl<'de> Deserialize<'de> for ContentFormat { #[derive(Debug, Serialize, Deserialize, Clone)] struct FieldKV { - key: ContentFormat, + name: ContentFormat, value: ContentFormat, } @@ -135,25 +155,74 @@ pub struct ContentEntry { #[derive(Debug, Serialize, Deserialize, Clone)] pub struct User { - public_key: PublicKey, + pub public_key: PublicKey, #[serde(rename = "type")] - rtype: LysandType, - id: String, - uri: Url, + pub rtype: LysandType, + pub id: Uuid, + pub uri: Url, #[serde(with = "iso_lysand")] - created_at: OffsetDateTime, - display_name: Option, + pub created_at: OffsetDateTime, + pub display_name: Option, // TODO bio: Option, - inbox: Url, - outbox: Url, - featured: Url, - followers: Url, - following: Url, - likes: Url, - dislikes: Url, - username: String, - bio: Option, - avatar: Option, - header: Option, - fields: Option>, + pub inbox: Url, + pub outbox: Url, + pub featured: Url, + pub followers: Url, + pub following: Url, + pub likes: Url, + pub dislikes: Url, + pub username: String, + pub bio: Option, + pub avatar: Option, + pub header: Option, + pub fields: Option>, } + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct DeviceInfo { + name: String, + version: String, + url: Url, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct LinkPreview { + description: String, + title: String, + link: Url, + image: Option, + icon: Option +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Note { + #[serde(rename = "type")] + pub rtype: LysandType, + pub id: Uuid, + pub uri: Url, + pub author: Url, + #[serde(with = "iso_lysand")] + pub created_at: OffsetDateTime, + pub category: Option, + pub content: Option, + pub device: Option, + pub previews: Option>, + pub group: Option, + pub attachments: Option>, + pub replies_to: Option, + pub quotes: Option, + pub mentions: Option>, + pub subject: Option, + pub is_sensitive: Option, + pub visibility: Option, + //TODO extensions +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Outbox { + pub first: Url, + pub last: Url, + pub next: Option, + pub prev: Option, + pub items: Vec, +} \ No newline at end of file diff --git a/src/lysand/superx.rs b/src/lysand/superx.rs index d8d8f92..a7843de 100644 --- a/src/lysand/superx.rs +++ b/src/lysand/superx.rs @@ -22,6 +22,26 @@ pub async fn serialize_lysand_type( Ok(data) } +pub async fn deserialize_note(data: String) -> anyhow::Result { + let post: super::objects::Note = serde_json::from_str(&data)?; + Ok(post) +} + +pub async fn serialize_note(post: super::objects::Note) -> anyhow::Result { + let data = serde_json::to_string(&SortAlphabetically(&post))?; + Ok(data) +} + +pub async fn deserialize_outbox(data: String) -> anyhow::Result { + let outbox: super::objects::Outbox = serde_json::from_str(&data)?; + Ok(outbox) +} + +pub async fn serialize_outbox(outbox: super::objects::Outbox) -> anyhow::Result { + let data = serde_json::to_string(&SortAlphabetically(&outbox))?; + Ok(data) +} + #[inline] pub fn request_client() -> reqwest::Client { reqwest::Client::builder() diff --git a/src/lysand/test.rs b/src/lysand/test.rs index 50b3a5b..733b3c4 100644 --- a/src/lysand/test.rs +++ b/src/lysand/test.rs @@ -22,5 +22,16 @@ pub async fn main() -> anyhow::Result<()> { let user_json = serde_json::to_string_pretty(&SortAlphabetically(&user))?; println!("{}", user_json); + let response_outbox = client + .get(user.outbox.as_str()) + .send() + .await?; + + let outbox_json = response_outbox.text().await?; + let outbox = super::superx::deserialize_outbox(outbox_json).await?; + + println!("\n\n\nOutbox: "); + print!("{:#?}", outbox); + Ok(()) } diff --git a/src/main.rs b/src/main.rs index 6b08c78..66dbcf5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -151,8 +151,8 @@ async fn main() -> actix_web::Result<(), anyhow::Error> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); //TODO remove this - //lysand::test::main().await?; - //return Ok(()); + lysand::test::main().await?; + return Ok(()); let ap_id = Url::parse(&format!( "https://{}/{}", From e42baf51e4435eb7ae420cd8b017cc001ca10de7 Mon Sep 17 00:00:00 2001 From: April John Date: Sun, 19 May 2024 07:17:13 +0200 Subject: [PATCH 02/23] save changes, fake commit --- src/http.rs | 10 +++++---- src/lysand/conversion.rs | 46 ++++++++++++++++++++++++++++++++++++++++ src/lysand/mod.rs | 1 + src/lysand/objects.rs | 8 +++---- src/lysand/test.rs | 5 +---- src/main.rs | 37 +++++++++++++------------------- src/objects/post.rs | 1 + src/utils.rs | 25 ++++++++++++---------- 8 files changed, 88 insertions(+), 45 deletions(-) create mode 100644 src/lysand/conversion.rs diff --git a/src/http.rs b/src/http.rs index 9b99203..6ea3e0e 100644 --- a/src/http.rs +++ b/src/http.rs @@ -1,8 +1,5 @@ use crate::{ - database::StateHandle, - entities::user, - error::Error, - objects::person::{DbUser, PersonAcceptedActivities}, + database::StateHandle, entities::user, error::Error, lysand::{self, conversion::receive_lysand_note}, objects::person::{DbUser, PersonAcceptedActivities} }; use activitypub_federation::{ actix_web::{inbox::receive_activity, signing_actor}, @@ -36,6 +33,11 @@ pub fn listen(config: &FederationConfig) -> Result<(), Error> { Ok(()) } +pub fn lysand_inbox(note: web::Json, id: web::Path, data: Data) -> Result { + tokio::spawn(receive_lysand_note(note.into_inner(), id.into_inner(), data.app_data().clone())); + Ok(HttpResponse::Created().finish()) +} + /// Handles requests to fetch system user json over HTTP /*pub async fn http_get_system_user(data: Data) -> Result { let json_user = data.system_user.clone().into_json(&data).await?; diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs new file mode 100644 index 0000000..ff4770a --- /dev/null +++ b/src/lysand/conversion.rs @@ -0,0 +1,46 @@ +use activitypub_federation::fetch::object_id::ObjectId; +use activitystreams_kinds::public; +use sea_orm::{EntityTrait, QueryFilter}; +use url::Url; + +use crate::{database::State, entities::{self, post, prelude}, objects::post::Mention, utils::{generate_object_id, generate_user_id}, FEDERATION_CONFIG}; + +use super::objects::Note; + +pub async fn receive_lysand_note(note: Note, db_id: String, db: State) { + let author: entities::user::Model = todo!(); + let user_res = prelude::User::find_by_id(db_id).one(db.database_connection.as_ref()).await; + if user_res.is_err() { + println!("{}", user_res.unwrap_err()); + return; + } + if let Some(target) = user_res.ok().unwrap() { + let data = FEDERATION_CONFIG.get().unwrap(); + let id: ObjectId = generate_object_id(data.domain(), ¬e.id.to_string()).unwrap().into(); + let user_id = generate_user_id(data.domain(), &target.id.to_string()).unwrap(); + let to = match note.visibility.unwrap_or(super::objects::VisibilityType::Public) { + super::objects::VisibilityType::Public => vec![public(), Url::parse(&author.inbox).unwrap()], + super::objects::VisibilityType::Followers => vec![Url::parse(&author.inbox).unwrap()], + super::objects::VisibilityType::Direct => vec![user_id], + super::objects::VisibilityType::Unlisted => vec![Url::parse(&author.inbox).unwrap()], + }; + let cc = match note.visibility.unwrap_or(super::objects::VisibilityType::Public) { + super::objects::VisibilityType::Unlisted => Some(vec![public()]), + _ => None + }; + let mut tag: Vec = Vec::new(); + for l_tag in note.mentions.unwrap_or_default() { + tag.push(Mention { href: l_tag, //todo convert to ap url + kind: Default::default(), }) + } + let ap_note = crate::objects::post::Note { + kind: Default::default(), + id, + sensitive: note.is_sensitive.unwrap_or(false), + cc, + to, + tag, + + } + } +} \ No newline at end of file diff --git a/src/lysand/mod.rs b/src/lysand/mod.rs index c1ee410..58e6578 100644 --- a/src/lysand/mod.rs +++ b/src/lysand/mod.rs @@ -1,3 +1,4 @@ pub mod objects; pub mod superx; pub mod test; +pub mod conversion; \ No newline at end of file diff --git a/src/lysand/objects.rs b/src/lysand/objects.rs index 08d09ee..da9bfa3 100644 --- a/src/lysand/objects.rs +++ b/src/lysand/objects.rs @@ -58,7 +58,7 @@ pub enum CategoryType { Image, Video, Audio, - Messaging + Messaging, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -66,7 +66,7 @@ pub enum VisibilityType { Public, Unlisted, Followers, - Direct + Direct, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -191,7 +191,7 @@ pub struct LinkPreview { title: String, link: Url, image: Option, - icon: Option + icon: Option, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -225,4 +225,4 @@ pub struct Outbox { pub next: Option, pub prev: Option, pub items: Vec, -} \ No newline at end of file +} diff --git a/src/lysand/test.rs b/src/lysand/test.rs index 733b3c4..a45032b 100644 --- a/src/lysand/test.rs +++ b/src/lysand/test.rs @@ -22,10 +22,7 @@ pub async fn main() -> anyhow::Result<()> { let user_json = serde_json::to_string_pretty(&SortAlphabetically(&user))?; println!("{}", user_json); - let response_outbox = client - .get(user.outbox.as_str()) - .send() - .await?; + let response_outbox = client.get(user.outbox.as_str()).send().await?; let outbox_json = response_outbox.text().await?; let outbox = super::superx::deserialize_outbox(outbox_json).await?; diff --git a/src/main.rs b/src/main.rs index 66dbcf5..27ceb1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,12 +76,12 @@ async fn post_manually( ) -> actix_web::Result { let local_user = state.local_user().await?; let data = FEDERATION_CONFIG.get().unwrap(); - let creator = + let target = webfinger_resolve_actor::(path.0.as_str(), &data.to_request_data()) .await?; let mention = Mention { - href: Url::parse(&creator.id)?, + href: Url::parse(&target.id)?, kind: Default::default(), }; let id: ObjectId = generate_object_id(data.domain())?.into(); @@ -89,16 +89,16 @@ async fn post_manually( kind: Default::default(), id, sensitive: false, - attributed_to: Url::parse(&data.local_user().await?.id).unwrap().into(), + attributed_to: Url::parse(&local_user.id).unwrap().into(), to: vec![public()], - content: format!("{} {}", path.1, creator.name), + content: format!("{} {}", path.1, target.name), tag: vec![mention], in_reply_to: None, }; CreatePost::send( note, - creator.shared_inbox_or_inbox(), + target.shared_inbox_or_inbox(), &data.to_request_data(), ) .await?; @@ -131,16 +131,18 @@ async fn follow_manually( Ok(HttpResponse::Ok().json(Response { health: true })) } -const DOMAIN_DEF: &str = "example.com"; +const DOMAIN_DEF: &str = "social.lysand.org"; const LOCAL_USER_NAME: &str = "example"; lazy_static! { - static ref SERVER_URL: String = env::var("LISTEN").unwrap_or("127.0.0.1:8080".to_string()); + static ref SERVER_URL: String = env::var("LISTEN").unwrap_or("0.0.0.0:8080".to_string()); static ref DATABASE_URL: String = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); static ref USERNAME: String = env::var("LOCAL_USER_NAME").unwrap_or(LOCAL_USER_NAME.to_string()); - static ref API_DOMAIN: String = env::var("API_DOMAIN").unwrap_or(DOMAIN_DEF.to_string()); - static ref FEDERATED_DOMAIN: String = env::var("FEDERATED_DOMAIN").unwrap_or(DOMAIN_DEF.to_string()); + static ref API_DOMAIN: String = env::var("API_DOMAIN").expect("not set API_DOMAIN"); + static ref LYSAND_DOMAIN: String = env::var("LYSAND_DOMAIN").expect("not set LYSAND_DOMAIN"); + static ref FEDERATED_DOMAIN: String = + env::var("FEDERATED_DOMAIN").unwrap_or(API_DOMAIN.to_string()); } static DB: OnceLock = OnceLock::new(); @@ -204,7 +206,7 @@ async fn main() -> actix_web::Result<(), anyhow::Error> { }; let data = FederationConfig::builder() - .domain(env::var("FEDERATED_DOMAIN").expect("FEDERATED_DOMAIN must be set")) + .domain(FEDERATED_DOMAIN.to_string()) .app_data(state.clone()) .http_signature_compat(true) .signed_fetch_actor(&state.local_user().await.unwrap()) @@ -214,18 +216,9 @@ async fn main() -> actix_web::Result<(), anyhow::Error> { let _ = FEDERATION_CONFIG.set(data.clone()); let mut labels = HashMap::new(); - labels.insert( - "domain".to_string(), - env::var("FEDERATED_DOMAIN") - .expect("FEDERATED_DOMAIN must be set") - .to_string(), - ); - labels.insert( - "name".to_string(), - env::var("LOCAL_USER_NAME") - .expect("LOCAL_USER_NAME must be set") - .to_string(), - ); + labels.insert("domain".to_string(), FEDERATED_DOMAIN.to_string()); + labels.insert("name".to_string(), USERNAME.to_string()); + labels.insert("api_domain".to_string(), API_DOMAIN.to_string()); let prometheus = PrometheusMetricsBuilder::new("api") .endpoint("/metrics") diff --git a/src/objects/post.rs b/src/objects/post.rs index 09fbb83..ee2a83e 100644 --- a/src/objects/post.rs +++ b/src/objects/post.rs @@ -40,6 +40,7 @@ pub struct Note { pub(crate) in_reply_to: Option>, pub(crate) tag: Vec, pub(crate) sensitive: bool, + pub(crate) cc: Option>, } #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/src/utils.rs b/src/utils.rs index 04f4195..55fd266 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,18 +1,21 @@ -use rand::{distributions::Alphanumeric, thread_rng, Rng}; use url::{ParseError, Url}; -/// Just generate random url as object id. In a real project, you probably want to use -/// an url which contains the database id for easy retrieval (or store the random id in db). -pub fn generate_object_id(domain: &str) -> Result { - let id: String = thread_rng() - .sample_iter(&Alphanumeric) - .take(7) - .map(char::from) - .collect(); - Url::parse(&format!("https://{}/objects/{}", domain, id)) +pub fn generate_object_id(domain: &str, uuid: &str) -> Result { + let id: String = uuid::Uuid::new_v4().to_string(); + Url::parse(&format!("https://{}/apbridge/object/{}", domain, id)) +} + +pub fn generate_user_id(domain: &str, uuid: &str) -> Result { + let id: String = uuid::Uuid::new_v4().to_string(); + Url::parse(&format!("https://{}/apbridge/user/{}", domain, id)) +} + +pub fn generate_random_object_id(domain: &str) -> Result { + let id: String = uuid::Uuid::new_v4().to_string(); + Url::parse(&format!("https://{}/apbridge/object/{}", domain, id)) } /// Generate a follow accept id pub fn generate_follow_accept_id(domain: &str, db_id: i32) -> Result { - Url::parse(&format!("https://{}/activities/follow/{}", domain, db_id)) + Url::parse(&format!("https://{}/apbridge/activity/follow/{}", domain, db_id)) } From bcab516a1f4086c30618b813db28143b27d81ec5 Mon Sep 17 00:00:00 2001 From: April John Date: Tue, 21 May 2024 04:59:47 +0200 Subject: [PATCH 03/23] feat: function to receive lysand note --- src/http.rs | 2 +- src/lysand/conversion.rs | 124 +++++++++++++++++++++++++++++++-------- src/lysand/objects.rs | 49 +++++++++++++++- src/main.rs | 1 + 4 files changed, 148 insertions(+), 28 deletions(-) diff --git a/src/http.rs b/src/http.rs index 6ea3e0e..52360cb 100644 --- a/src/http.rs +++ b/src/http.rs @@ -34,7 +34,7 @@ pub fn listen(config: &FederationConfig) -> Result<(), Error> { } pub fn lysand_inbox(note: web::Json, id: web::Path, data: Data) -> Result { - tokio::spawn(receive_lysand_note(note.into_inner(), id.into_inner(), data.app_data().clone())); + tokio::spawn(receive_lysand_note(note.into_inner(), id.into_inner())); Ok(HttpResponse::Created().finish()) } diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index ff4770a..f016135 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -1,38 +1,107 @@ -use activitypub_federation::fetch::object_id::ObjectId; +use activitypub_federation::{fetch::object_id::ObjectId, http_signatures::generate_actor_keypair}; use activitystreams_kinds::public; -use sea_orm::{EntityTrait, QueryFilter}; +use chrono::{DateTime, Utc}; +use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set}; +use anyhow::anyhow; use url::Url; -use crate::{database::State, entities::{self, post, prelude}, objects::post::Mention, utils::{generate_object_id, generate_user_id}, FEDERATION_CONFIG}; +use crate::{database::State, entities::{self, post, prelude, user}, objects::post::Mention, utils::{generate_object_id, generate_user_id}, API_DOMAIN, DB, FEDERATION_CONFIG, LYSAND_DOMAIN}; -use super::objects::Note; +use super::{objects::{ContentFormat, Note}, superx::request_client}; -pub async fn receive_lysand_note(note: Note, db_id: String, db: State) { - let author: entities::user::Model = todo!(); - let user_res = prelude::User::find_by_id(db_id).one(db.database_connection.as_ref()).await; - if user_res.is_err() { - println!("{}", user_res.unwrap_err()); - return; +pub async fn fetch_user_from_url(url: Url) -> anyhow::Result { + let req_client = request_client(); + let request = req_client.get(url).send().await?; + Ok(request.json::().await?) +} + +pub async fn option_content_format_text(opt: Option) -> Option { + if let Some(format) = opt { + return Some(format.select_rich_text().await.unwrap()); } - if let Some(target) = user_res.ok().unwrap() { + + None +} + +pub async fn db_user_from_url(url: Url) -> anyhow::Result { + if !url.domain().eq(&Some(LYSAND_DOMAIN.as_str())) { + return Err(anyhow!("not lysands domain")); + } + let user_res = prelude::User::find().filter(entities::user::Column::Url.eq(url.to_string())).one(DB.get().unwrap()).await?; + + if let Some(user) = user_res { + Ok(user) + } else { + let ls_user = fetch_user_from_url(url).await?; + let keypair = generate_actor_keypair()?; + let user = entities::user::ActiveModel { + id: Set(ls_user.id.to_string()), + username: Set(ls_user.username.clone()), + name: Set(ls_user.display_name.unwrap_or(ls_user.username)), + inbox: Set(ls_user.inbox.to_string()), + public_key: Set(keypair.public_key.clone()), + private_key: Set(Some(keypair.private_key.clone())), + last_refreshed_at: Set(Utc::now()), + follower_count: Set(0), + following_count: Set(0), + url: Set(ls_user.uri.to_string()), + local: Set(true), + created_at: Set(DateTime::from_timestamp(ls_user.created_at.unix_timestamp(), 0).unwrap()), + summary: Set(option_content_format_text(ls_user.bio).await), + updated_at: Set(Some(Utc::now())), + followers: Set(Some(ls_user.followers.to_string())), + following: Set(Some(ls_user.following.to_string())), + ..Default::default() + }; + let db = DB.get().unwrap(); + Ok(user.insert(db).await?) + } +} + +pub async fn fetch_note_from_url(url: Url) -> anyhow::Result { + let req_client = request_client(); + let request = req_client.get(url).send().await?; + Ok(request.json::().await?) +} + +pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result<()> { + let author: entities::user::Model = db_user_from_url(note.author.clone()).await?; + let user_res = prelude::User::find_by_id(db_id).one(DB.get().unwrap()).await; + if user_res.is_err() { + println!("{}", user_res.as_ref().unwrap_err()); + return Err(user_res.err().unwrap().into()); + } + if let Some(target) = user_res? { let data = FEDERATION_CONFIG.get().unwrap(); - let id: ObjectId = generate_object_id(data.domain(), ¬e.id.to_string()).unwrap().into(); - let user_id = generate_user_id(data.domain(), &target.id.to_string()).unwrap(); - let to = match note.visibility.unwrap_or(super::objects::VisibilityType::Public) { - super::objects::VisibilityType::Public => vec![public(), Url::parse(&author.inbox).unwrap()], - super::objects::VisibilityType::Followers => vec![Url::parse(&author.inbox).unwrap()], - super::objects::VisibilityType::Direct => vec![user_id], - super::objects::VisibilityType::Unlisted => vec![Url::parse(&author.inbox).unwrap()], + let id: ObjectId = generate_object_id(data.domain(), ¬e.id.to_string())?.into(); + let user_id = generate_user_id(data.domain(), &target.id.to_string())?; + let user = fetch_user_from_url(user_id).await?; + let mut tag: Vec = Vec::new(); + for l_tag in note.mentions.clone().unwrap_or_default() { + tag.push(Mention { href: l_tag, //todo convert to ap url + kind: Default::default(), }) + } + let to = match note.visibility.clone().unwrap_or(super::objects::VisibilityType::Public) { + super::objects::VisibilityType::Public => vec![public(), Url::parse(&author.followers.unwrap_or_default())?], + super::objects::VisibilityType::Followers => vec![Url::parse(&author.followers.unwrap_or_default())?], + super::objects::VisibilityType::Direct => note.mentions.unwrap_or_default(), + super::objects::VisibilityType::Unlisted => vec![Url::parse(&author.followers.unwrap_or_default())?], }; let cc = match note.visibility.unwrap_or(super::objects::VisibilityType::Public) { super::objects::VisibilityType::Unlisted => Some(vec![public()]), _ => None }; - let mut tag: Vec = Vec::new(); - for l_tag in note.mentions.unwrap_or_default() { - tag.push(Mention { href: l_tag, //todo convert to ap url - kind: Default::default(), }) - } + let reply: Option> = if let Some(rep) = note.replies_to { + let note = fetch_note_from_url(rep).await?; + let fake_rep_url = Url::parse(&format!( + "https://{}/lysand/apnote/{}", + API_DOMAIN.to_string(), + ¬e.id.to_string() + ))?; + Some(fake_rep_url.into()) + } else { + None + }; let ap_note = crate::objects::post::Note { kind: Default::default(), id, @@ -40,7 +109,12 @@ pub async fn receive_lysand_note(note: Note, db_id: String, db: State) { cc, to, tag, - - } + attributed_to: Url::parse(author.url.clone().as_str()).unwrap().into(), + content: option_content_format_text(note.content).await.unwrap_or_default(), + in_reply_to: reply + }; } + + + Ok(()) } \ No newline at end of file diff --git a/src/lysand/objects.rs b/src/lysand/objects.rs index da9bfa3..bcec067 100644 --- a/src/lysand/objects.rs +++ b/src/lysand/objects.rs @@ -108,8 +108,53 @@ pub struct ContentHash { } #[derive(Debug, Clone)] -struct ContentFormat { +pub struct ContentFormat { x: HashMap, +} + +impl ContentFormat { + pub async fn select_rich_text(&self) -> anyhow::Result { + if let Some(entry) = self.x.get("text/x.misskeymarkdown") { + return Ok(entry.content.clone()) + } + if let Some(entry) = self.x.get("text/html") { + return Ok(entry.content.clone()) + } + if let Some(entry) = self.x.get("text/markdown") { + return Ok(entry.content.clone()) + } + if let Some(entry) = self.x.get("text/plain") { + return Ok(entry.content.clone()) + } + + Ok(self.x.clone().values().next().unwrap().content.clone()) + } + + pub async fn select_rich_img(&self) -> anyhow::Result { + if let Some(entry) = self.x.get("image/webp") { + return Ok(entry.content.clone()) + } + if let Some(entry) = self.x.get("image/png") { + return Ok(entry.content.clone()) + } + if let Some(entry) = self.x.get("image/avif") { + return Ok(entry.content.clone()) + } + if let Some(entry) = self.x.get("image/jxl") { + return Ok(entry.content.clone()) + } + if let Some(entry) = self.x.get("image/jpeg") { + return Ok(entry.content.clone()) + } + if let Some(entry) = self.x.get("image/gif") { + return Ok(entry.content.clone()) + } + if let Some(entry) = self.x.get("image/bmp") { + return Ok(entry.content.clone()) + } + + Ok(self.x.clone().values().next().unwrap().content.clone()) + } } impl Serialize for ContentFormat { @@ -136,7 +181,7 @@ impl<'de> Deserialize<'de> for ContentFormat { #[derive(Debug, Serialize, Deserialize, Clone)] struct FieldKV { - name: ContentFormat, + key: ContentFormat, value: ContentFormat, } diff --git a/src/main.rs b/src/main.rs index 27ceb1d..7ef8956 100644 --- a/src/main.rs +++ b/src/main.rs @@ -94,6 +94,7 @@ async fn post_manually( content: format!("{} {}", path.1, target.name), tag: vec![mention], in_reply_to: None, + cc: vec![].into() }; CreatePost::send( From 1174f929157a75ffa6ce3958d1f005561ed4a0e4 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Sat, 15 Jun 2024 02:06:01 +0200 Subject: [PATCH 04/23] [feat]: lysand to ap for posts and users --- src/activities/create_post.rs | 4 +- src/activities/follow.rs | 4 +- src/entities/post.rs | 3 +- src/lysand/conversion.rs | 80 ++++++++++++++++++++++++++++------- src/lysand/funcs.rs | 0 src/lysand/http.rs | 24 +++++++++++ src/lysand/mod.rs | 4 +- src/lysand/objects.rs | 1 + src/lysand/test.rs | 21 +++++++++ src/main.rs | 13 +++--- src/objects/post.rs | 36 +++++++++++----- 11 files changed, 151 insertions(+), 39 deletions(-) create mode 100644 src/lysand/funcs.rs create mode 100644 src/lysand/http.rs diff --git a/src/activities/create_post.rs b/src/activities/create_post.rs index 514f9a6..771bb46 100644 --- a/src/activities/create_post.rs +++ b/src/activities/create_post.rs @@ -6,7 +6,7 @@ use crate::{ person::DbUser, post::{DbPost, Note}, }, - utils::generate_object_id, + utils::generate_random_object_id, }; use activitypub_federation::{ activity_sending::SendActivityTask, @@ -39,7 +39,7 @@ impl CreatePost { to: note.to.clone(), object: note, kind: CreateType::Create, - id: generate_object_id(data.domain())?, + id: generate_random_object_id(data.domain())?, }; let create_with_context = WithContext::new_default(create); let sends = SendActivityTask::prepare( diff --git a/src/activities/follow.rs b/src/activities/follow.rs index b0e0f93..b9986de 100644 --- a/src/activities/follow.rs +++ b/src/activities/follow.rs @@ -14,7 +14,7 @@ use crate::{ database::StateHandle, entities::{follow_relation, post, user}, error, - utils::{generate_follow_accept_id, generate_object_id}, + utils::{generate_follow_accept_id, generate_random_object_id}, DB, }; @@ -39,7 +39,7 @@ impl Follow { actor: local_user.clone(), object: followee.clone(), kind: FollowType::Follow, - id: generate_object_id(data.domain())?, + id: generate_random_object_id(data.domain())?, }; let create_with_context = WithContext::new_default(create); let sends = SendActivityTask::prepare( diff --git a/src/entities/post.rs b/src/entities/post.rs index 97bbd23..0062f05 100644 --- a/src/entities/post.rs +++ b/src/entities/post.rs @@ -15,8 +15,7 @@ pub struct Model { pub created_at: chrono::DateTime, #[sea_orm(column_type = "Timestamp")] pub updated_at: Option>, - #[sea_orm(column_type = "Timestamp")] - pub reblog_id: Option>, + pub reblog_id: Option, pub content_type: String, pub visibility: String, pub reply_id: Option, diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index f016135..fa3d46c 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -1,8 +1,8 @@ use activitypub_federation::{fetch::object_id::ObjectId, http_signatures::generate_actor_keypair}; use activitystreams_kinds::public; -use chrono::{DateTime, Utc}; +use chrono::{DateTime, TimeZone, Utc}; use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set}; -use anyhow::anyhow; +use anyhow::{anyhow, Ok}; use url::Url; use crate::{database::State, entities::{self, post, prelude, user}, objects::post::Mention, utils::{generate_object_id, generate_user_id}, API_DOMAIN, DB, FEDERATION_CONFIG, LYSAND_DOMAIN}; @@ -27,7 +27,7 @@ pub async fn db_user_from_url(url: Url) -> anyhow::Result if !url.domain().eq(&Some(LYSAND_DOMAIN.as_str())) { return Err(anyhow!("not lysands domain")); } - let user_res = prelude::User::find().filter(entities::user::Column::Url.eq(url.to_string())).one(DB.get().unwrap()).await?; + let user_res: Option = prelude::User::find().filter(entities::user::Column::Url.eq(url.to_string())).one(DB.get().unwrap()).await?; if let Some(user) = user_res { Ok(user) @@ -64,8 +64,8 @@ pub async fn fetch_note_from_url(url: Url) -> anyhow::Result().await?) } -pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result<()> { - let author: entities::user::Model = db_user_from_url(note.author.clone()).await?; +pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result { + let lysand_author: entities::user::Model = db_user_from_url(note.author.clone()).await?; let user_res = prelude::User::find_by_id(db_id).one(DB.get().unwrap()).await; if user_res.is_err() { println!("{}", user_res.as_ref().unwrap_err()); @@ -75,23 +75,45 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result<() let data = FEDERATION_CONFIG.get().unwrap(); let id: ObjectId = generate_object_id(data.domain(), ¬e.id.to_string())?.into(); let user_id = generate_user_id(data.domain(), &target.id.to_string())?; - let user = fetch_user_from_url(user_id).await?; + let user = fetch_user_from_url(note.author.clone()).await?; let mut tag: Vec = Vec::new(); for l_tag in note.mentions.clone().unwrap_or_default() { - tag.push(Mention { href: l_tag, //todo convert to ap url + tag.push(Mention { href: l_tag, //TODO convert to ap url kind: Default::default(), }) } let to = match note.visibility.clone().unwrap_or(super::objects::VisibilityType::Public) { - super::objects::VisibilityType::Public => vec![public(), Url::parse(&author.followers.unwrap_or_default())?], - super::objects::VisibilityType::Followers => vec![Url::parse(&author.followers.unwrap_or_default())?], + super::objects::VisibilityType::Public => vec![public(), Url::parse(&user.followers.to_string().as_str())?], + super::objects::VisibilityType::Followers => vec![Url::parse(&user.followers.to_string().as_str())?], super::objects::VisibilityType::Direct => note.mentions.unwrap_or_default(), - super::objects::VisibilityType::Unlisted => vec![Url::parse(&author.followers.unwrap_or_default())?], + super::objects::VisibilityType::Unlisted => vec![Url::parse(&user.followers.to_string().as_str())?], }; - let cc = match note.visibility.unwrap_or(super::objects::VisibilityType::Public) { + let cc = match note.visibility.clone().unwrap_or(super::objects::VisibilityType::Public) { super::objects::VisibilityType::Unlisted => Some(vec![public()]), _ => None }; - let reply: Option> = if let Some(rep) = note.replies_to { + let reply: Option> = if let Some(rep) = note.replies_to.clone() { + let note = fetch_note_from_url(rep).await?; + let fake_rep_url = Url::parse(&format!( + "https://{}/lysand/apnote/{}", + API_DOMAIN.to_string(), + ¬e.id.to_string() + ))?; + Some(fake_rep_url.into()) + } else { + None + }; + let reply_string: Option = if let Some(rep) = note.replies_to { + let note = fetch_note_from_url(rep).await?; + let fake_rep_url = Url::parse(&format!( + "https://{}/lysand/apnote/{}", + API_DOMAIN.to_string(), + ¬e.id.to_string() + ))?; + Some(fake_rep_url.into()) + } else { + None + }; + let quote_string: Option = if let Some(rep) = note.quotes.clone() { let note = fetch_note_from_url(rep).await?; let fake_rep_url = Url::parse(&format!( "https://{}/lysand/apnote/{}", @@ -109,12 +131,38 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result<() cc, to, tag, - attributed_to: Url::parse(author.url.clone().as_str()).unwrap().into(), + attributed_to: Url::parse(user.uri.clone().as_str()).unwrap().into(), content: option_content_format_text(note.content).await.unwrap_or_default(), in_reply_to: reply }; + + let visibility = match note.visibility.clone().unwrap_or(super::objects::VisibilityType::Public) { + super::objects::VisibilityType::Public => "public", + super::objects::VisibilityType::Followers => "followers", + super::objects::VisibilityType::Direct => "direct", + super::objects::VisibilityType::Unlisted => "unlisted", + }; + + let post = entities::post::ActiveModel { + id: Set(note.id.to_string()), + creator: Set(lysand_author.id.clone()), + content: Set(ap_note.content.clone()), + sensitive: Set(ap_note.sensitive), + created_at: Set(Utc.timestamp_micros(note.created_at.unix_timestamp()).unwrap()), + local: Set(true), + updated_at: Set(Some(Utc::now())), + content_type: Set("Note".to_string()), + visibility: Set(visibility.to_string()), + title: Set(note.subject.clone()), + url: Set(ap_note.id.to_string()), + reply_id: Set(reply_string), + quoting_id: Set(quote_string), + spoiler_text: Set(note.subject), + ..Default::default() + }; + post.insert(DB.get().unwrap()).await?; + Ok(ap_note) + } else { + Err(anyhow!("User not found")) } - - - Ok(()) } \ No newline at end of file diff --git a/src/lysand/funcs.rs b/src/lysand/funcs.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/lysand/http.rs b/src/lysand/http.rs new file mode 100644 index 0000000..229193d --- /dev/null +++ b/src/lysand/http.rs @@ -0,0 +1,24 @@ +use std::os::linux::raw::stat; + +use activitypub_federation::{traits::Object, FEDERATION_CONTENT_TYPE}; +use actix_web::{get, web, HttpResponse}; +use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; + +use crate::{database::State, entities::{post::{self, Entity}, prelude}, error, Response, DB, FEDERATION_CONFIG}; + +#[get("/apbridge/object/{post}")] +async fn post_manually( + path: web::Path<(String, String)>, + state: web::Data, +) -> actix_web::Result { + let db = DB.get().unwrap(); + + let post = prelude::Post::find() + .filter(post::Column::Id.eq(path.0.as_str())) + .one(db) + .await?; + + let post = post.unwrap(); + + Ok(HttpResponse::Ok().content_type(FEDERATION_CONTENT_TYPE).json(post.into_json(&FEDERATION_CONFIG.get().unwrap().to_request_data()).await?)) +} \ No newline at end of file diff --git a/src/lysand/mod.rs b/src/lysand/mod.rs index 58e6578..ab468b7 100644 --- a/src/lysand/mod.rs +++ b/src/lysand/mod.rs @@ -1,4 +1,6 @@ pub mod objects; pub mod superx; pub mod test; -pub mod conversion; \ No newline at end of file +pub mod conversion; +pub mod funcs; +pub mod http; \ No newline at end of file diff --git a/src/lysand/objects.rs b/src/lysand/objects.rs index bcec067..ad52eb5 100644 --- a/src/lysand/objects.rs +++ b/src/lysand/objects.rs @@ -62,6 +62,7 @@ pub enum CategoryType { } #[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(rename_all = "snake_case")] pub enum VisibilityType { Public, Unlisted, diff --git a/src/lysand/test.rs b/src/lysand/test.rs index a45032b..d56ef63 100644 --- a/src/lysand/test.rs +++ b/src/lysand/test.rs @@ -2,6 +2,19 @@ use crate::lysand::objects::SortAlphabetically; use super::superx::request_client; +#[actix_web::test] +async fn test_user_serial() { + let client = request_client(); + let response = client + .get("https://social.lysand.org/users/018ec082-0ae1-761c-b2c5-22275a611771") + .send() + .await.unwrap(); + let user = super::superx::deserialize_user(response.text().await.unwrap()).await.unwrap(); + let response_outbox = client.get(user.outbox.as_str()).send().await.unwrap(); + let outbox = super::superx::deserialize_outbox(response_outbox.text().await.unwrap()).await.unwrap(); + assert!(outbox.items.len() > 0); +} + pub async fn main() -> anyhow::Result<()> { let client = request_client(); @@ -30,5 +43,13 @@ pub async fn main() -> anyhow::Result<()> { println!("\n\n\nOutbox: "); print!("{:#?}", outbox); + println!("\n\n\nas AP:"); + for item in outbox.items { + let ap_item = super::conversion::receive_lysand_note(item, "https://ap.lysand.org/example".to_string()).await?; + println!("{:#?}", ap_item); + let ap_json = serde_json::to_string_pretty(&SortAlphabetically(&ap_item))?; + println!("{}", ap_json); + } + Ok(()) } diff --git a/src/main.rs b/src/main.rs index 7ef8956..0119c63 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,7 +28,7 @@ use tokio::signal; use tracing::{info, instrument::WithSubscriber}; use url::Url; -use crate::utils::generate_object_id; +use crate::utils::generate_random_object_id; use crate::{ activities::create_post::CreatePost, database::{Config, State}, @@ -84,7 +84,8 @@ async fn post_manually( href: Url::parse(&target.id)?, kind: Default::default(), }; - let id: ObjectId = generate_object_id(data.domain())?.into(); + // TODO change + let id: ObjectId = generate_random_object_id(data.domain())?.into(); let note = Note { kind: Default::default(), id, @@ -153,10 +154,6 @@ static FEDERATION_CONFIG: OnceLock> = OnceLock::new(); async fn main() -> actix_web::Result<(), anyhow::Error> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); - //TODO remove this - lysand::test::main().await?; - return Ok(()); - let ap_id = Url::parse(&format!( "https://{}/{}", API_DOMAIN.to_string(), @@ -246,6 +243,10 @@ async fn main() -> actix_web::Result<(), anyhow::Error> { .keep_alive(KeepAlive::Os) .run(); + //TODO remove this + lysand::test::main().await?; + return Ok(()); + tokio::spawn(http_server); match signal::ctrl_c().await { diff --git a/src/objects/post.rs b/src/objects/post.rs index ee2a83e..9b0ba09 100644 --- a/src/objects/post.rs +++ b/src/objects/post.rs @@ -1,10 +1,5 @@ use crate::{ - activities::create_post::CreatePost, - database::StateHandle, - entities::{post, user}, - error::Error, - objects::person::DbUser, - utils::generate_object_id, + activities::create_post::CreatePost, database::StateHandle, entities::{post, user}, error::Error, lysand::conversion::db_user_from_url, objects::person::DbUser, utils::generate_object_id }; use activitypub_federation::{ config::Data, @@ -14,7 +9,7 @@ use activitypub_federation::{ traits::{Actor, Object}, }; use activitystreams_kinds::link::MentionType; -use sea_orm::{ActiveModelTrait, Set}; +use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set}; use serde::{Deserialize, Serialize}; use tracing::info; use url::Url; @@ -57,14 +52,35 @@ impl Object for post::Model { type Error = Error; async fn read_from_id( - _object_id: Url, - _data: &Data, + object_id: Url, + data: &Data, ) -> Result, Self::Error> { + let post = crate::entities::prelude::Post::find() + .filter(post::Column::Id.eq(object_id.to_string())) + .one(data.app_data().database_connection.clone().as_ref()).await; Ok(None) } async fn into_json(self, _data: &Data) -> Result { - todo!() + let creator = db_user_from_url(Url::parse(self.creator.as_str()).unwrap()).await?; + let to = match self.visibility.as_str() { + "public" => vec![public(), Url::parse(creator.followers.unwrap().as_str()).unwrap()], + "followers" => vec![Url::parse(creator.followers.unwrap().as_str()).unwrap()], + "direct" => vec![], //TODO: implement this + "unlisted" => vec![Url::parse(creator.followers.unwrap().as_str()).unwrap(), public()], + _ => vec![public()], + }; + Ok(Note { + kind: Default::default(), + id: Url::parse(self.url.as_str()).unwrap().into(), + attributed_to: Url::parse(self.creator.as_str()).unwrap().into(), + to: to.clone(), + content: self.content, + in_reply_to: None, + tag: vec![], + sensitive: self.sensitive, + cc: Some(to), + }) } async fn verify( From 15bba70d2ae125c366e1a641fbad2f4ad607dbfa Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Mon, 17 Jun 2024 19:52:51 +0200 Subject: [PATCH 05/23] feat: Add .env file to gitignore and update dependencies The commit adds the `.env` file to the `.gitignore` and updates the dependencies in the `Cargo.toml` and `Cargo.lock` files. This change ensures that sensitive environment variables are not committed to the repository and keeps the dependencies up to date. --- .env.example | 4 ++++ .gitignore | 3 ++- Cargo.lock | 7 +++++++ Cargo.toml | 1 + migration/Cargo.lock | 7 +++++++ migration/Cargo.toml | 1 + migration/src/main.rs | 2 ++ nix-bootstrap.sh | 2 ++ src/lysand/conversion.rs | 27 ++++++++++++++++++++++----- src/lysand/http.rs | 11 +++++++---- src/main.rs | 2 ++ src/objects/post.rs | 2 +- 12 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 .env.example create mode 100644 nix-bootstrap.sh diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..422c1bd --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +DATABASE_URL="sqlite:///home/aprl/Documents/lysand-ap-layer/db.sqlite?mode=rwc" +LYSAND_DOMAIN="social.lysand.org" +API_DOMAIN="ap.lysand.org" +RUST_LOG="debug" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 39f22b2..03e16ed 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ /result-lib .direnv migration/target -db.sqlite \ No newline at end of file +db.sqlite +.env \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index eb62c0d..da608e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1027,6 +1027,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "dotenvy" version = "0.15.7" @@ -1908,6 +1914,7 @@ dependencies = [ "async_once", "chrono", "clap", + "dotenv", "enum_delegate", "env_logger", "lazy_static", diff --git a/Cargo.toml b/Cargo.toml index dc6dad7..4b47ca8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ async_once = "0.2.6" reqwest = { version = "0.12.4", features = ["blocking", "json", "multipart"] } time = { version = "0.3.36", features = ["serde"] } serde_derive = "1.0.201" +dotenv = "0.15.0" [dependencies.sea-orm] version = "0.12.0" diff --git a/migration/Cargo.lock b/migration/Cargo.lock index f852531..bd6aa45 100644 --- a/migration/Cargo.lock +++ b/migration/Cargo.lock @@ -583,6 +583,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "dotenvy" version = "0.15.7" @@ -1129,6 +1135,7 @@ version = "0.1.0" dependencies = [ "async-std", "chrono", + "dotenv", "sea-orm-migration", ] diff --git a/migration/Cargo.toml b/migration/Cargo.toml index edbcccf..579479a 100644 --- a/migration/Cargo.toml +++ b/migration/Cargo.toml @@ -11,6 +11,7 @@ path = "src/lib.rs" [dependencies] async-std = { version = "1", features = ["attributes", "tokio1"] } chrono = "0.4.38" +dotenv = "0.15.0" [dependencies.sea-orm-migration] version = "0.12.0" diff --git a/migration/src/main.rs b/migration/src/main.rs index c6b6e48..98a18fc 100644 --- a/migration/src/main.rs +++ b/migration/src/main.rs @@ -1,6 +1,8 @@ use sea_orm_migration::prelude::*; +use dotenv::dotenv; #[async_std::main] async fn main() { + dotenv().ok(); cli::run_cli(migration::Migrator).await; } diff --git a/nix-bootstrap.sh b/nix-bootstrap.sh new file mode 100644 index 0000000..65f6b25 --- /dev/null +++ b/nix-bootstrap.sh @@ -0,0 +1,2 @@ +nix run .#ls-ap-migration +nix run .#lysand-ap-layer \ No newline at end of file diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index fa3d46c..6a1941c 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -76,6 +76,7 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result = generate_object_id(data.domain(), ¬e.id.to_string())?.into(); let user_id = generate_user_id(data.domain(), &target.id.to_string())?; let user = fetch_user_from_url(note.author.clone()).await?; + let data = FEDERATION_CONFIG.get().unwrap(); let mut tag: Vec = Vec::new(); for l_tag in note.mentions.clone().unwrap_or_default() { tag.push(Mention { href: l_tag, //TODO convert to ap url @@ -94,7 +95,18 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result> = if let Some(rep) = note.replies_to.clone() { let note = fetch_note_from_url(rep).await?; let fake_rep_url = Url::parse(&format!( - "https://{}/lysand/apnote/{}", + "https://{}/apbridge/object/{}", + API_DOMAIN.to_string(), + ¬e.id.to_string() + ))?; + Some(fake_rep_url.into()) + } else { + None + }; + let quote: Option> = if let Some(rep) = note.quotes.clone() { + let note = fetch_note_from_url(rep).await?; + let fake_rep_url = Url::parse(&format!( + "https://{}/apbridge/object/{}", API_DOMAIN.to_string(), ¬e.id.to_string() ))?; @@ -105,7 +117,7 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result = if let Some(rep) = note.replies_to { let note = fetch_note_from_url(rep).await?; let fake_rep_url = Url::parse(&format!( - "https://{}/lysand/apnote/{}", + "https://{}/apbridge/object/{}", API_DOMAIN.to_string(), ¬e.id.to_string() ))?; @@ -116,7 +128,7 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result = if let Some(rep) = note.quotes.clone() { let note = fetch_note_from_url(rep).await?; let fake_rep_url = Url::parse(&format!( - "https://{}/lysand/apnote/{}", + "https://{}/apbridge/object/{}", API_DOMAIN.to_string(), ¬e.id.to_string() ))?; @@ -133,7 +145,7 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result anyhow::Result "direct", super::objects::VisibilityType::Unlisted => "unlisted", }; - + if let Some(obj) = quote { + println!("Quoting: {}", obj.dereference(&data.to_request_data()).await.unwrap().url); + } + if let Some(obj) = reply { + println!("Replying to: {}", obj.dereference(&data.to_request_data()).await.unwrap().url); + } let post = entities::post::ActiveModel { id: Set(note.id.to_string()), creator: Set(lysand_author.id.clone()), diff --git a/src/lysand/http.rs b/src/lysand/http.rs index 229193d..8f08871 100644 --- a/src/lysand/http.rs +++ b/src/lysand/http.rs @@ -7,18 +7,21 @@ use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; use crate::{database::State, entities::{post::{self, Entity}, prelude}, error, Response, DB, FEDERATION_CONFIG}; #[get("/apbridge/object/{post}")] -async fn post_manually( - path: web::Path<(String, String)>, +async fn fetch_post( + path: web::Path, state: web::Data, ) -> actix_web::Result { let db = DB.get().unwrap(); let post = prelude::Post::find() - .filter(post::Column::Id.eq(path.0.as_str())) + .filter(post::Column::Id.eq(path.as_str())) .one(db) .await?; - let post = post.unwrap(); + let post = match post { + Some(post) => post, + None => return Ok(HttpResponse::NotFound().finish()), + }; Ok(HttpResponse::Ok().content_type(FEDERATION_CONTENT_TYPE).json(post.into_json(&FEDERATION_CONFIG.get().unwrap().to_request_data()).await?)) } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 0119c63..91eabef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,6 +36,7 @@ use crate::{ }; use crate::{activities::follow::Follow, entities::user}; use lazy_static::lazy_static; +use dotenv::dotenv; mod activities; mod database; @@ -152,6 +153,7 @@ static FEDERATION_CONFIG: OnceLock> = OnceLock::new(); #[actix_web::main] async fn main() -> actix_web::Result<(), anyhow::Error> { + dotenv().ok(); env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); let ap_id = Url::parse(&format!( diff --git a/src/objects/post.rs b/src/objects/post.rs index 9b0ba09..6a1c3df 100644 --- a/src/objects/post.rs +++ b/src/objects/post.rs @@ -58,7 +58,7 @@ impl Object for post::Model { let post = crate::entities::prelude::Post::find() .filter(post::Column::Id.eq(object_id.to_string())) .one(data.app_data().database_connection.clone().as_ref()).await; - Ok(None) + Ok(post.unwrap()) } async fn into_json(self, _data: &Data) -> Result { From 1588b2e46c78c27295d2b26f9896ab8253cd7539 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Mon, 17 Jun 2024 21:35:21 +0200 Subject: [PATCH 06/23] feat: Add db_post_from_url function The commit adds the `db_post_from_url` function to the `conversion.rs` file. This function retrieves a post from the database based on a given URL. If the post is not found in the database, it fetches the post from the URL, saves it to the database, and returns the post. This change enhances the functionality of the codebase by providing a convenient way to retrieve and store posts. --- src/lysand/conversion.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index 6a1941c..e236cd1 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -23,6 +23,23 @@ pub async fn option_content_format_text(opt: Option) -> Option anyhow::Result { + if !url.domain().eq(&Some(LYSAND_DOMAIN.as_str())) { + return Err(anyhow!("not lysands domain")); + } + let str_url = url.to_string(); + let post_res: Option = prelude::Post::find().filter(entities::post::Column::Url.eq(str_url.clone())).one(DB.get().unwrap()).await?; + + if let Some(post) = post_res { + Ok(post) + } else { + let post = fetch_note_from_url(url.clone()).await?; + receive_lysand_note(post, "1".to_string()).await?; + let post_res: Option = prelude::Post::find().filter(entities::post::Column::Url.eq(str_url)).one(DB.get().unwrap()).await?; + Ok(post_res.unwrap()) + } +} + pub async fn db_user_from_url(url: Url) -> anyhow::Result { if !url.domain().eq(&Some(LYSAND_DOMAIN.as_str())) { return Err(anyhow!("not lysands domain")); @@ -155,10 +172,10 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result "unlisted", }; if let Some(obj) = quote { - println!("Quoting: {}", obj.dereference(&data.to_request_data()).await.unwrap().url); + println!("Quoting: {}", db_post_from_url(note.replies_to.unwrap()).await?.url); } if let Some(obj) = reply { - println!("Replying to: {}", obj.dereference(&data.to_request_data()).await.unwrap().url); + println!("Replying to: {}", db_post_from_url(note.quotes.unwrap()).await?.url); } let post = entities::post::ActiveModel { id: Set(note.id.to_string()), From 9e148fe77f4dcd97a9a65f0ffba5294e401747e1 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Mon, 17 Jun 2024 21:40:25 +0200 Subject: [PATCH 07/23] feat: Update dependencies and add async-recursion crate --- Cargo.lock | 12 ++++++++++++ Cargo.toml | 1 + src/lysand/conversion.rs | 7 ++++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da608e1..1c4b74b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -409,6 +409,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -1910,6 +1921,7 @@ dependencies = [ "actix-web", "actix-web-prom", "anyhow", + "async-recursion", "async-trait", "async_once", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 4b47ca8..d99743c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ reqwest = { version = "0.12.4", features = ["blocking", "json", "multipart"] } time = { version = "0.3.36", features = ["serde"] } serde_derive = "1.0.201" dotenv = "0.15.0" +async-recursion = "1.1.1" [dependencies.sea-orm] version = "0.12.0" diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index e236cd1..8b3ef37 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -4,6 +4,7 @@ use chrono::{DateTime, TimeZone, Utc}; use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set}; use anyhow::{anyhow, Ok}; use url::Url; +use async_recursion::async_recursion; use crate::{database::State, entities::{self, post, prelude, user}, objects::post::Mention, utils::{generate_object_id, generate_user_id}, API_DOMAIN, DB, FEDERATION_CONFIG, LYSAND_DOMAIN}; @@ -22,7 +23,7 @@ pub async fn option_content_format_text(opt: Option) -> Option anyhow::Result { if !url.domain().eq(&Some(LYSAND_DOMAIN.as_str())) { return Err(anyhow!("not lysands domain")); @@ -80,7 +81,7 @@ pub async fn fetch_note_from_url(url: Url) -> anyhow::Result().await?) } - +#[async_recursion] pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result { let lysand_author: entities::user::Model = db_user_from_url(note.author.clone()).await?; let user_res = prelude::User::find_by_id(db_id).one(DB.get().unwrap()).await; @@ -131,7 +132,7 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result = if let Some(rep) = note.replies_to { + let reply_string: Option = if let Some(rep) = note.replies_to.clone() { let note = fetch_note_from_url(rep).await?; let fake_rep_url = Url::parse(&format!( "https://{}/apbridge/object/{}", From 21a3447a8437dea0a4ae794be0080eb13ddf2b6c Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Mon, 17 Jun 2024 21:44:29 +0200 Subject: [PATCH 08/23] fix: Refactor lysand note handling in conversion.rs The commit refactors the lysand note handling in the `conversion.rs` file. It updates the `receive_lysand_note` function to properly handle quoting and replying to notes. This change improves the functionality and readability of the codebase. --- src/lysand/conversion.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index 8b3ef37..4242e71 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -172,11 +172,11 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result "direct", super::objects::VisibilityType::Unlisted => "unlisted", }; - if let Some(obj) = quote { - println!("Quoting: {}", db_post_from_url(note.replies_to.unwrap()).await?.url); + if let Some(obj) = note.replies_to { + println!("Quoting: {}", db_post_from_url(obj).await?.url); } - if let Some(obj) = reply { - println!("Replying to: {}", db_post_from_url(note.quotes.unwrap()).await?.url); + if let Some(obj) = note.quotes { + println!("Replying to: {}", db_post_from_url(obj).await?.url); } let post = entities::post::ActiveModel { id: Set(note.id.to_string()), From a6c0fc47558db4c539b6769d4f6363867ef6d2b5 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Mon, 17 Jun 2024 21:47:48 +0200 Subject: [PATCH 09/23] fix: use example as default user --- src/lysand/conversion.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index 4242e71..8a0ef4d 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -35,7 +35,7 @@ pub async fn db_post_from_url(url: Url) -> anyhow::Result Ok(post) } else { let post = fetch_note_from_url(url.clone()).await?; - receive_lysand_note(post, "1".to_string()).await?; + receive_lysand_note(post, "example".to_string()).await?; let post_res: Option = prelude::Post::find().filter(entities::post::Column::Url.eq(str_url)).one(DB.get().unwrap()).await?; Ok(post_res.unwrap()) } From e8d716c7a5b55e81b210bd969898f3ab953cab26 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Mon, 17 Jun 2024 21:50:33 +0200 Subject: [PATCH 10/23] me oopid --- src/lysand/conversion.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index 8a0ef4d..b0569c9 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -35,7 +35,7 @@ pub async fn db_post_from_url(url: Url) -> anyhow::Result Ok(post) } else { let post = fetch_note_from_url(url.clone()).await?; - receive_lysand_note(post, "example".to_string()).await?; + receive_lysand_note(post, "https://ap.lysand.org/example".to_string()).await?; let post_res: Option = prelude::Post::find().filter(entities::post::Column::Url.eq(str_url)).one(DB.get().unwrap()).await?; Ok(post_res.unwrap()) } From da40e5b5e66355c11ed2454fbb966871dbb754f2 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Mon, 17 Jun 2024 21:55:42 +0200 Subject: [PATCH 11/23] fix: Refactor lysand note handling in conversion.rs --- src/lysand/conversion.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index b0569c9..38503b1 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -35,9 +35,8 @@ pub async fn db_post_from_url(url: Url) -> anyhow::Result Ok(post) } else { let post = fetch_note_from_url(url.clone()).await?; - receive_lysand_note(post, "https://ap.lysand.org/example".to_string()).await?; - let post_res: Option = prelude::Post::find().filter(entities::post::Column::Url.eq(str_url)).one(DB.get().unwrap()).await?; - Ok(post_res.unwrap()) + let res = receive_lysand_note(post, "https://ap.lysand.org/example".to_string()).await?; + Ok(res) } } @@ -82,7 +81,7 @@ pub async fn fetch_note_from_url(url: Url) -> anyhow::Result().await?) } #[async_recursion] -pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result { +pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result { let lysand_author: entities::user::Model = db_user_from_url(note.author.clone()).await?; let user_res = prelude::User::find_by_id(db_id).one(DB.get().unwrap()).await; if user_res.is_err() { @@ -195,8 +194,8 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result Date: Mon, 17 Jun 2024 21:58:00 +0200 Subject: [PATCH 12/23] fix: fix post printing --- src/lysand/test.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lysand/test.rs b/src/lysand/test.rs index d56ef63..64edbc3 100644 --- a/src/lysand/test.rs +++ b/src/lysand/test.rs @@ -47,8 +47,6 @@ pub async fn main() -> anyhow::Result<()> { for item in outbox.items { let ap_item = super::conversion::receive_lysand_note(item, "https://ap.lysand.org/example".to_string()).await?; println!("{:#?}", ap_item); - let ap_json = serde_json::to_string_pretty(&SortAlphabetically(&ap_item))?; - println!("{}", ap_json); } Ok(()) From 03f66637681555fded839e615a48caaf9521b482 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Mon, 17 Jun 2024 22:33:30 +0200 Subject: [PATCH 13/23] fix: Refactor lysand note handling in conversion.rs --- src/lysand/conversion.rs | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index 38503b1..3155804 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -131,25 +131,13 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result = if let Some(rep) = note.replies_to.clone() { - let note = fetch_note_from_url(rep).await?; - let fake_rep_url = Url::parse(&format!( - "https://{}/apbridge/object/{}", - API_DOMAIN.to_string(), - ¬e.id.to_string() - ))?; - Some(fake_rep_url.into()) + let reply_uuid: Option = if let Some(rep) = note.replies_to.clone() { + Some(db_post_from_url(rep).await?.id) } else { None }; - let quote_string: Option = if let Some(rep) = note.quotes.clone() { - let note = fetch_note_from_url(rep).await?; - let fake_rep_url = Url::parse(&format!( - "https://{}/apbridge/object/{}", - API_DOMAIN.to_string(), - ¬e.id.to_string() - ))?; - Some(fake_rep_url.into()) + let quote_uuid: Option = if let Some(rep) = note.quotes.clone() { + Some(db_post_from_url(rep).await?.id) } else { None }; @@ -189,8 +177,8 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result Date: Mon, 17 Jun 2024 22:39:03 +0200 Subject: [PATCH 14/23] fix: Refactor lysand note handling in conversion.rs --- src/lysand/conversion.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index 3155804..117689b 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -176,7 +176,7 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result Date: Mon, 17 Jun 2024 22:47:21 +0200 Subject: [PATCH 15/23] fix: make nix-bootstrap executable --- nix-bootstrap.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 nix-bootstrap.sh diff --git a/nix-bootstrap.sh b/nix-bootstrap.sh old mode 100644 new mode 100755 From ef89602d6fbd049e5b78415e3cf0bc801e0e2d7a Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Mon, 17 Jun 2024 23:49:40 +0200 Subject: [PATCH 16/23] fix: remove unused linux only import --- src/lysand/http.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lysand/http.rs b/src/lysand/http.rs index 8f08871..5b1f080 100644 --- a/src/lysand/http.rs +++ b/src/lysand/http.rs @@ -1,5 +1,3 @@ -use std::os::linux::raw::stat; - use activitypub_federation::{traits::Object, FEDERATION_CONTENT_TYPE}; use actix_web::{get, web, HttpResponse}; use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; From a90a2695a94654654d4d6b6d232c02a25b45f60b Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Mon, 17 Jun 2024 23:50:31 +0200 Subject: [PATCH 17/23] fix: make person stop screaming at me :( --- build.rs | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 build.rs diff --git a/build.rs b/build.rs deleted file mode 100644 index 5d67e88..0000000 --- a/build.rs +++ /dev/null @@ -1,11 +0,0 @@ -#[cfg(target_os = "windows")] -fn main() { - vcpkg::Config::new() - .emit_includes(true) - .copy_dlls(true) - .find_package("libpq") - .unwrap(); -} - -#[cfg(not(target_os = "windows"))] -fn main() {} From b6ca94b809bf8b8dea101973f361bbc9ca8f86d9 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Tue, 18 Jun 2024 01:46:24 +0200 Subject: [PATCH 18/23] feat: remove test code --- src/main.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 91eabef..7601a15 100644 --- a/src/main.rs +++ b/src/main.rs @@ -245,10 +245,6 @@ async fn main() -> actix_web::Result<(), anyhow::Error> { .keep_alive(KeepAlive::Os) .run(); - //TODO remove this - lysand::test::main().await?; - return Ok(()); - tokio::spawn(http_server); match signal::ctrl_c().await { From 3359da61398887ca77c77ab3132f852cbe45aa76 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Tue, 18 Jun 2024 01:48:17 +0200 Subject: [PATCH 19/23] fix: update deps --- Cargo.lock | 1044 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 641 insertions(+), 403 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c4b74b..da118f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,15 +4,15 @@ version = 3 [[package]] name = "activitypub_federation" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e16130d5914e6483f99bde5a9bb97ca62e1f359e0b9791c8ebd5c7abd50fe8e" +checksum = "ac8ff2d0151ce9ac02eb29e4a58b41d28693f141f7963d4bfabd2f9d402ecec7" dependencies = [ "activitystreams-kinds", "actix-web", "async-trait", "axum", - "base64 0.21.7", + "base64 0.22.1", "bytes", "chrono", "derive_builder", @@ -25,7 +25,7 @@ dependencies = [ "http-signature-normalization", "http-signature-normalization-reqwest", "httpdate", - "hyper 0.14.28", + "hyper 0.14.29", "itertools", "moka", "once_cell", @@ -73,16 +73,16 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.6.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d223b13fd481fc0d1f83bb12659ae774d9e3601814c68a0bc539731698cca743" +checksum = "4eb9843d84c775696c37d9a418bbb01b932629d01870722c0f13eb3f95e2536d" dependencies = [ "actix-codec", "actix-rt", "actix-service", "actix-utils", "ahash 0.8.11", - "base64 0.21.7", + "base64 0.22.1", "bitflags 2.5.0", "brotli", "bytes", @@ -117,27 +117,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] name = "actix-router" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22475596539443685426b6bdadb926ad0ecaefdfc5fb05e5e3441f15463c511" +checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" dependencies = [ "bytestring", + "cfg-if", "http 0.2.12", "regex", + "regex-lite", "serde", "tracing", ] [[package]] name = "actix-rt" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" +checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" dependencies = [ "futures-core", "tokio", @@ -145,9 +147,9 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb13e7eef0423ea6eab0e59f6c72e7cb46d33691ad56a726b3cd07ddec2c2d4" +checksum = "b02303ce8d4e8be5b855af6cf3c3a08f3eff26880faad82bab679c22d3650cb5" dependencies = [ "actix-rt", "actix-service", @@ -183,9 +185,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.5.1" +version = "4.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a6556ddebb638c2358714d853257ed226ece6023ef9364f23f0c70737ea984" +checksum = "5d6316df3fa569627c98b12557a8b6ff0674e5be4bb9b5e4ae2550ddb4964ed6" dependencies = [ "actix-codec", "actix-http", @@ -212,6 +214,7 @@ dependencies = [ "once_cell", "pin-project-lite", "regex", + "regex-lite", "serde", "serde_json", "serde_urlencoded", @@ -223,14 +226,14 @@ dependencies = [ [[package]] name = "actix-web-codegen" -version = "4.2.2" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1f50ebbb30eca122b188319a4398b3f7bb4a8cdf50ecfb73bfc6a3c3ce54f5" +checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -250,9 +253,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -340,47 +343,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -388,9 +392,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arrayvec" @@ -400,11 +404,11 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-lock" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 4.0.3", + "event-listener 5.3.1", "event-listener-strategy", "pin-project-lite", ] @@ -417,7 +421,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -439,7 +443,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -450,7 +454,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -475,10 +479,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" [[package]] -name = "autocfg" -version = "1.2.0" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" @@ -494,7 +504,7 @@ dependencies = [ "headers", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.29", "itoa", "matchit", "memchr", @@ -505,7 +515,7 @@ dependencies = [ "serde", "serde_json", "serde_path_to_error", - "sync_wrapper", + "sync_wrapper 0.1.2", "tower", "tower-layer", "tower-service", @@ -530,9 +540,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -616,9 +626,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.3.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ "borsh-derive", "cfg_aliases", @@ -626,23 +636,23 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.3.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aadb5b6ccbd078890f6d7003694e33816e6b784358f18e15e7e6d9f065a57cd" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", "syn_derive", ] [[package]] name = "brotli" -version = "3.5.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" +checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -651,9 +661,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.5.1" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -710,12 +720,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.94" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" dependencies = [ "jobserver", "libc", + "once_cell", ] [[package]] @@ -726,9 +737,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" @@ -747,9 +758,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.4" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -757,45 +768,45 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim", ] [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -865,18 +876,18 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -901,9 +912,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crypto-common" @@ -917,9 +928,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.14.4" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ "darling_core", "darling_macro", @@ -927,27 +938,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.14.4" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 1.0.109", + "strsim", + "syn 2.0.66", ] [[package]] name = "darling_macro" -version = "0.14.4" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] @@ -984,46 +995,46 @@ dependencies = [ [[package]] name = "derive_builder" -version = "0.12.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" +checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" dependencies = [ "derive_builder_macro", ] [[package]] name = "derive_builder_core" -version = "0.12.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" +checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" dependencies = [ "darling", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] name = "derive_builder_macro" -version = "0.12.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] @@ -1038,6 +1049,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "dotenv" version = "0.15.0" @@ -1058,9 +1080,9 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" dependencies = [ "serde", ] @@ -1129,9 +1151,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1156,20 +1178,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "4.0.3" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", @@ -1178,31 +1189,25 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 4.0.3", + "event-listener 5.3.1", "pin-project-lite", ] [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" - -[[package]] -name = "finl_unicode" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -1322,7 +1327,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -1367,9 +1372,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -1378,9 +1383,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "h2" @@ -1403,15 +1408,15 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http 1.1.0", "indexmap", "slab", @@ -1431,9 +1436,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash 0.8.11", "allocator-api2", @@ -1445,7 +1450,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -1571,12 +1576,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http 1.1.0", "http-body 1.0.0", "pin-project-lite", @@ -1610,9 +1615,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -1628,9 +1633,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" dependencies = [ "bytes", "futures-channel", @@ -1659,7 +1664,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.4", + "h2 0.4.5", "http 1.1.0", "http-body 1.0.0", "httparse", @@ -1670,6 +1675,23 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.3.1", + "hyper-util", + "rustls 0.23.10", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -1677,7 +1699,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.28", + "hyper 0.14.29", "native-tls", "tokio", "tokio-native-tls", @@ -1701,9 +1723,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ "bytes", "futures-channel", @@ -1742,6 +1764,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1750,12 +1890,14 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", ] [[package]] @@ -1765,7 +1907,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -1776,18 +1918,7 @@ checksum = "0122b7114117e64a63ac49f752a5ca4624d534c7b1c7de796ac196381cd2d947" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", + "syn 2.0.66", ] [[package]] @@ -1796,6 +1927,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.12.1" @@ -1813,9 +1950,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] @@ -1846,9 +1983,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libm" @@ -1869,15 +2006,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.1.4" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] -name = "linux-raw-sys" -version = "0.4.13" +name = "litemap" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" [[package]] name = "local-channel" @@ -1898,9 +2035,9 @@ checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1932,7 +2069,7 @@ dependencies = [ "lazy_static", "num_cpus", "rand", - "reqwest 0.12.4", + "reqwest 0.12.5", "sea-orm", "serde", "serde_derive", @@ -1964,9 +2101,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" @@ -1992,9 +2129,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] @@ -2013,16 +2150,16 @@ dependencies = [ [[package]] name = "moka" -version = "0.12.6" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87bfd249f570638bfb0b4f9d258e6b8cddd2a5a7d0ed47e8bb8b176bfc0e7a17" +checksum = "9e0d88686dc561d743b40de8269b26eaf0dc58781bde087b0984646602021d08" dependencies = [ "async-lock", "async-trait", "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", - "event-listener 5.3.0", + "event-listener 5.3.1", "futures-util", "once_cell", "parking_lot", @@ -2037,11 +2174,10 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -2065,11 +2201,10 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -2108,9 +2243,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -2119,9 +2254,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -2139,9 +2274,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] @@ -2175,7 +2310,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -2226,7 +2361,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -2237,9 +2372,9 @@ checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -2247,22 +2382,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.2", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pem-rfc7468" @@ -2296,7 +2431,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -2385,31 +2520,41 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.80" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] [[package]] name = "procfs" -version = "0.14.2" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69" +checksum = "731e0d9356b0c25f16f33b5be79b1c57b562f141ebfcdb0ad8ac2c13a24293b4" dependencies = [ - "bitflags 1.3.2", - "byteorder", + "bitflags 2.5.0", "hex", "lazy_static", - "rustix 0.36.17", + "procfs-core", + "rustix", +] + +[[package]] +name = "procfs-core" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29" +dependencies = [ + "bitflags 2.5.0", + "hex", ] [[package]] name = "prometheus" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ "cfg-if", "fnv", @@ -2503,9 +2648,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d86a7c4638d42c44551f4791a20e687dbb4c3de1f33c43dd71e355cd429def1" +checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd" dependencies = [ "bitflags 2.5.0", ] @@ -2520,10 +2665,19 @@ dependencies = [ ] [[package]] -name = "regex" -version = "1.10.4" +name = "redox_syscall" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +dependencies = [ + "bitflags 2.5.0", +] + +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -2533,9 +2687,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -2543,10 +2697,16 @@ dependencies = [ ] [[package]] -name = "regex-syntax" -version = "0.8.3" +name = "regex-lite" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rend" @@ -2571,7 +2731,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.29", "hyper-tls 0.5.0", "ipnet", "js-sys", @@ -2586,7 +2746,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 0.1.2", "system-configuration", "tokio", "tokio-native-tls", @@ -2602,9 +2762,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "base64 0.22.1", "bytes", @@ -2612,11 +2772,12 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.4", + "h2 0.4.5", "http 1.1.0", "http-body 1.0.0", "http-body-util", "hyper 1.3.1", + "hyper-rustls", "hyper-tls 0.6.0", "hyper-util", "ipnet", @@ -2632,7 +2793,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.1", "system-configuration", "tokio", "tokio-native-tls", @@ -2725,9 +2886,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.34.3" +version = "1.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39449a79f45e8da28c57c341891b69a183044b29518bb8f86dbac9df60bb7df" +checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a" dependencies = [ "arrayvec", "borsh", @@ -2741,9 +2902,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" @@ -2756,42 +2917,41 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.17" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305efbd14fde4139eb501df5f136994bb520b033fa9fbdce287507dc23b8c7ed" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.1.4", - "windows-sys 0.45.0", -] - -[[package]] -name = "rustix" -version = "0.38.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", "libc", - "linux-raw-sys 0.4.13", + "linux-raw-sys", "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "ring", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki 0.102.4", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -2828,16 +2988,27 @@ dependencies = [ ] [[package]] -name = "rustversion" -version = "1.0.15" +name = "rustls-webpki" +version = "0.102.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" @@ -2874,7 +3045,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -2915,7 +3086,7 @@ dependencies = [ "proc-macro2", "quote", "sea-bae", - "syn 2.0.58", + "syn 2.0.66", "unicode-ident", ] @@ -2960,11 +3131,11 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -2973,9 +3144,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -2983,35 +3154,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.201" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.201" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "indexmap", "itoa", @@ -3065,9 +3236,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -3105,9 +3276,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3140,11 +3311,10 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" dependencies = [ - "itertools", "nom", "unicode_categories", ] @@ -3192,7 +3362,7 @@ dependencies = [ "paste", "percent-encoding", "rust_decimal", - "rustls", + "rustls 0.21.12", "rustls-pemfile 1.0.4", "serde", "serde_json", @@ -3365,6 +3535,12 @@ dependencies = [ "uuid", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -3379,21 +3555,15 @@ checksum = "7a8348af2d9fc3258c8733b8d9d8db2e56f54b2363a4b5b81585c7875ed65e65" [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -3425,9 +3595,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.58" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -3443,7 +3613,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -3452,6 +3622,23 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -3502,28 +3689,28 @@ checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "rustix 0.38.32", + "rustix", "windows-sys 0.52.0", ] [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -3557,6 +3744,16 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -3574,9 +3771,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -3593,13 +3790,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -3612,6 +3809,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.10", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.15" @@ -3625,23 +3833,22 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" [[package]] name = "toml_edit" @@ -3702,7 +3909,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -3716,9 +3923,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" +checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" [[package]] name = "try-lock" @@ -3762,6 +3969,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" + [[package]] name = "unicode-segmentation" version = "1.11.0" @@ -3782,9 +3995,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" dependencies = [ "form_urlencoded", "idna", @@ -3799,10 +4012,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] -name = "utf8parse" -version = "0.2.1" +name = "utf16_iter" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" @@ -3870,7 +4095,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -3904,7 +4129,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3950,7 +4175,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" dependencies = [ - "redox_syscall", + "redox_syscall 0.4.1", "wasite", ] @@ -3985,15 +4210,6 @@ dependencies = [ "windows-targets 0.52.5", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -4012,21 +4228,6 @@ dependencies = [ "windows-targets 0.52.5", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.48.5" @@ -4058,12 +4259,6 @@ dependencies = [ "windows_x86_64_msvc 0.52.5", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -4076,12 +4271,6 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -4094,12 +4283,6 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -4118,12 +4301,6 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -4136,12 +4313,6 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -4154,12 +4325,6 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -4172,12 +4337,6 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -4219,6 +4378,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.5.1" @@ -4229,30 +4400,97 @@ dependencies = [ ] [[package]] -name = "zerocopy" -version = "0.7.32" +name = "yoke" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] [[package]] name = "zstd" @@ -4274,9 +4512,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.11+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "75652c55c0b6f3e6f12eb786fe1bc960396bf05a1eb3bf1f3691c3610ac2e6d4" dependencies = [ "cc", "pkg-config", From c601fb03eb53230ad58c3d49007413b5be2087b9 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Tue, 18 Jun 2024 01:52:47 +0200 Subject: [PATCH 20/23] fix: rm build.rs fully --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d99743c..8566309 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,6 @@ name = "lysand-ap-layer" version = "0.1.0" edition = "2021" -build = "build.rs" authors = ["April John "] license = "AGPL-3.0-or-later" repository = "https://github.com/lysand-org/lysand-ap-layer" From 489a216aca67faa2f9f562d67d9bd57ee990274e Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Tue, 18 Jun 2024 03:34:37 +0200 Subject: [PATCH 21/23] feat: standard user to apservice --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 7601a15..d452588 100644 --- a/src/main.rs +++ b/src/main.rs @@ -135,7 +135,7 @@ async fn follow_manually( } const DOMAIN_DEF: &str = "social.lysand.org"; -const LOCAL_USER_NAME: &str = "example"; +const LOCAL_USER_NAME: &str = "apservice"; lazy_static! { static ref SERVER_URL: String = env::var("LISTEN").unwrap_or("0.0.0.0:8080".to_string()); From cd6ff024e4c94e88ee16d20eaeb29f45371a7fa4 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Tue, 18 Jun 2024 03:43:59 +0200 Subject: [PATCH 22/23] fix: format files --- migration/src/main.rs | 4 +- src/http.rs | 12 +++- src/lysand/conversion.rs | 119 +++++++++++++++++++++++++++------------ src/lysand/funcs.rs | 1 + src/lysand/http.rs | 18 +++++- src/lysand/mod.rs | 6 +- src/lysand/objects.rs | 24 ++++---- src/lysand/test.rs | 17 ++++-- src/main.rs | 4 +- src/objects/post.rs | 23 ++++++-- src/utils.rs | 5 +- 11 files changed, 164 insertions(+), 69 deletions(-) diff --git a/migration/src/main.rs b/migration/src/main.rs index 98a18fc..c3fce3e 100644 --- a/migration/src/main.rs +++ b/migration/src/main.rs @@ -1,8 +1,8 @@ -use sea_orm_migration::prelude::*; use dotenv::dotenv; +use sea_orm_migration::prelude::*; #[async_std::main] async fn main() { - dotenv().ok(); + dotenv().ok(); cli::run_cli(migration::Migrator).await; } diff --git a/src/http.rs b/src/http.rs index 52360cb..759bb43 100644 --- a/src/http.rs +++ b/src/http.rs @@ -1,5 +1,9 @@ use crate::{ - database::StateHandle, entities::user, error::Error, lysand::{self, conversion::receive_lysand_note}, objects::person::{DbUser, PersonAcceptedActivities} + database::StateHandle, + entities::user, + error::Error, + lysand::{self, conversion::receive_lysand_note}, + objects::person::{DbUser, PersonAcceptedActivities}, }; use activitypub_federation::{ actix_web::{inbox::receive_activity, signing_actor}, @@ -33,7 +37,11 @@ pub fn listen(config: &FederationConfig) -> Result<(), Error> { Ok(()) } -pub fn lysand_inbox(note: web::Json, id: web::Path, data: Data) -> Result { +pub fn lysand_inbox( + note: web::Json, + id: web::Path, + data: Data, +) -> Result { tokio::spawn(receive_lysand_note(note.into_inner(), id.into_inner())); Ok(HttpResponse::Created().finish()) } diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index 117689b..0c940ee 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -1,14 +1,23 @@ use activitypub_federation::{fetch::object_id::ObjectId, http_signatures::generate_actor_keypair}; use activitystreams_kinds::public; +use anyhow::{anyhow, Ok}; +use async_recursion::async_recursion; use chrono::{DateTime, TimeZone, Utc}; use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set}; -use anyhow::{anyhow, Ok}; use url::Url; -use async_recursion::async_recursion; -use crate::{database::State, entities::{self, post, prelude, user}, objects::post::Mention, utils::{generate_object_id, generate_user_id}, API_DOMAIN, DB, FEDERATION_CONFIG, LYSAND_DOMAIN}; +use crate::{ + database::State, + entities::{self, post, prelude, user}, + objects::post::Mention, + utils::{generate_object_id, generate_user_id}, + API_DOMAIN, DB, FEDERATION_CONFIG, LYSAND_DOMAIN, +}; -use super::{objects::{ContentFormat, Note}, superx::request_client}; +use super::{ + objects::{ContentFormat, Note}, + superx::request_client, +}; pub async fn fetch_user_from_url(url: Url) -> anyhow::Result { let req_client = request_client(); @@ -29,7 +38,10 @@ pub async fn db_post_from_url(url: Url) -> anyhow::Result return Err(anyhow!("not lysands domain")); } let str_url = url.to_string(); - let post_res: Option = prelude::Post::find().filter(entities::post::Column::Url.eq(str_url.clone())).one(DB.get().unwrap()).await?; + let post_res: Option = prelude::Post::find() + .filter(entities::post::Column::Url.eq(str_url.clone())) + .one(DB.get().unwrap()) + .await?; if let Some(post) = post_res { Ok(post) @@ -44,7 +56,10 @@ pub async fn db_user_from_url(url: Url) -> anyhow::Result if !url.domain().eq(&Some(LYSAND_DOMAIN.as_str())) { return Err(anyhow!("not lysands domain")); } - let user_res: Option = prelude::User::find().filter(entities::user::Column::Url.eq(url.to_string())).one(DB.get().unwrap()).await?; + let user_res: Option = prelude::User::find() + .filter(entities::user::Column::Url.eq(url.to_string())) + .one(DB.get().unwrap()) + .await?; if let Some(user) = user_res { Ok(user) @@ -63,7 +78,9 @@ pub async fn db_user_from_url(url: Url) -> anyhow::Result following_count: Set(0), url: Set(ls_user.uri.to_string()), local: Set(true), - created_at: Set(DateTime::from_timestamp(ls_user.created_at.unix_timestamp(), 0).unwrap()), + created_at: Set( + DateTime::from_timestamp(ls_user.created_at.unix_timestamp(), 0).unwrap(), + ), summary: Set(option_content_format_text(ls_user.bio).await), updated_at: Set(Some(Utc::now())), followers: Set(Some(ls_user.followers.to_string())), @@ -81,46 +98,70 @@ pub async fn fetch_note_from_url(url: Url) -> anyhow::Result().await?) } #[async_recursion] -pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result { +pub async fn receive_lysand_note( + note: Note, + db_id: String, +) -> anyhow::Result { let lysand_author: entities::user::Model = db_user_from_url(note.author.clone()).await?; - let user_res = prelude::User::find_by_id(db_id).one(DB.get().unwrap()).await; + let user_res = prelude::User::find_by_id(db_id) + .one(DB.get().unwrap()) + .await; if user_res.is_err() { println!("{}", user_res.as_ref().unwrap_err()); return Err(user_res.err().unwrap().into()); } if let Some(target) = user_res? { let data = FEDERATION_CONFIG.get().unwrap(); - let id: ObjectId = generate_object_id(data.domain(), ¬e.id.to_string())?.into(); + let id: ObjectId = + generate_object_id(data.domain(), ¬e.id.to_string())?.into(); let user_id = generate_user_id(data.domain(), &target.id.to_string())?; let user = fetch_user_from_url(note.author.clone()).await?; let data = FEDERATION_CONFIG.get().unwrap(); let mut tag: Vec = Vec::new(); for l_tag in note.mentions.clone().unwrap_or_default() { - tag.push(Mention { href: l_tag, //TODO convert to ap url - kind: Default::default(), }) + tag.push(Mention { + href: l_tag, //TODO convert to ap url + kind: Default::default(), + }) } - let to = match note.visibility.clone().unwrap_or(super::objects::VisibilityType::Public) { - super::objects::VisibilityType::Public => vec![public(), Url::parse(&user.followers.to_string().as_str())?], - super::objects::VisibilityType::Followers => vec![Url::parse(&user.followers.to_string().as_str())?], + let to = match note + .visibility + .clone() + .unwrap_or(super::objects::VisibilityType::Public) + { + super::objects::VisibilityType::Public => { + vec![public(), Url::parse(&user.followers.to_string().as_str())?] + } + super::objects::VisibilityType::Followers => { + vec![Url::parse(&user.followers.to_string().as_str())?] + } super::objects::VisibilityType::Direct => note.mentions.unwrap_or_default(), - super::objects::VisibilityType::Unlisted => vec![Url::parse(&user.followers.to_string().as_str())?], + super::objects::VisibilityType::Unlisted => { + vec![Url::parse(&user.followers.to_string().as_str())?] + } }; - let cc = match note.visibility.clone().unwrap_or(super::objects::VisibilityType::Public) { + let cc = match note + .visibility + .clone() + .unwrap_or(super::objects::VisibilityType::Public) + { super::objects::VisibilityType::Unlisted => Some(vec![public()]), - _ => None + _ => None, }; - let reply: Option> = if let Some(rep) = note.replies_to.clone() { - let note = fetch_note_from_url(rep).await?; - let fake_rep_url = Url::parse(&format!( - "https://{}/apbridge/object/{}", - API_DOMAIN.to_string(), - ¬e.id.to_string() - ))?; - Some(fake_rep_url.into()) - } else { - None - }; - let quote: Option> = if let Some(rep) = note.quotes.clone() { + let reply: Option> = + if let Some(rep) = note.replies_to.clone() { + let note = fetch_note_from_url(rep).await?; + let fake_rep_url = Url::parse(&format!( + "https://{}/apbridge/object/{}", + API_DOMAIN.to_string(), + ¬e.id.to_string() + ))?; + Some(fake_rep_url.into()) + } else { + None + }; + let quote: Option> = if let Some(rep) = note.quotes.clone() + { let note = fetch_note_from_url(rep).await?; let fake_rep_url = Url::parse(&format!( "https://{}/apbridge/object/{}", @@ -149,11 +190,17 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result "public", super::objects::VisibilityType::Followers => "followers", super::objects::VisibilityType::Direct => "direct", @@ -170,7 +217,9 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result anyhow::Result return Ok(HttpResponse::NotFound().finish()), }; - Ok(HttpResponse::Ok().content_type(FEDERATION_CONTENT_TYPE).json(post.into_json(&FEDERATION_CONFIG.get().unwrap().to_request_data()).await?)) -} \ No newline at end of file + Ok(HttpResponse::Ok() + .content_type(FEDERATION_CONTENT_TYPE) + .json( + post.into_json(&FEDERATION_CONFIG.get().unwrap().to_request_data()) + .await?, + )) +} diff --git a/src/lysand/mod.rs b/src/lysand/mod.rs index ab468b7..ff9c29c 100644 --- a/src/lysand/mod.rs +++ b/src/lysand/mod.rs @@ -1,6 +1,6 @@ +pub mod conversion; +pub mod funcs; +pub mod http; pub mod objects; pub mod superx; pub mod test; -pub mod conversion; -pub mod funcs; -pub mod http; \ No newline at end of file diff --git a/src/lysand/objects.rs b/src/lysand/objects.rs index ad52eb5..c50302b 100644 --- a/src/lysand/objects.rs +++ b/src/lysand/objects.rs @@ -111,21 +111,21 @@ pub struct ContentHash { #[derive(Debug, Clone)] pub struct ContentFormat { x: HashMap, -} +} impl ContentFormat { pub async fn select_rich_text(&self) -> anyhow::Result { if let Some(entry) = self.x.get("text/x.misskeymarkdown") { - return Ok(entry.content.clone()) + return Ok(entry.content.clone()); } if let Some(entry) = self.x.get("text/html") { - return Ok(entry.content.clone()) + return Ok(entry.content.clone()); } if let Some(entry) = self.x.get("text/markdown") { - return Ok(entry.content.clone()) + return Ok(entry.content.clone()); } if let Some(entry) = self.x.get("text/plain") { - return Ok(entry.content.clone()) + return Ok(entry.content.clone()); } Ok(self.x.clone().values().next().unwrap().content.clone()) @@ -133,25 +133,25 @@ impl ContentFormat { pub async fn select_rich_img(&self) -> anyhow::Result { if let Some(entry) = self.x.get("image/webp") { - return Ok(entry.content.clone()) + return Ok(entry.content.clone()); } if let Some(entry) = self.x.get("image/png") { - return Ok(entry.content.clone()) + return Ok(entry.content.clone()); } if let Some(entry) = self.x.get("image/avif") { - return Ok(entry.content.clone()) + return Ok(entry.content.clone()); } if let Some(entry) = self.x.get("image/jxl") { - return Ok(entry.content.clone()) + return Ok(entry.content.clone()); } if let Some(entry) = self.x.get("image/jpeg") { - return Ok(entry.content.clone()) + return Ok(entry.content.clone()); } if let Some(entry) = self.x.get("image/gif") { - return Ok(entry.content.clone()) + return Ok(entry.content.clone()); } if let Some(entry) = self.x.get("image/bmp") { - return Ok(entry.content.clone()) + return Ok(entry.content.clone()); } Ok(self.x.clone().values().next().unwrap().content.clone()) diff --git a/src/lysand/test.rs b/src/lysand/test.rs index 64edbc3..556f4bc 100644 --- a/src/lysand/test.rs +++ b/src/lysand/test.rs @@ -8,10 +8,15 @@ async fn test_user_serial() { let response = client .get("https://social.lysand.org/users/018ec082-0ae1-761c-b2c5-22275a611771") .send() - .await.unwrap(); - let user = super::superx::deserialize_user(response.text().await.unwrap()).await.unwrap(); + .await + .unwrap(); + let user = super::superx::deserialize_user(response.text().await.unwrap()) + .await + .unwrap(); let response_outbox = client.get(user.outbox.as_str()).send().await.unwrap(); - let outbox = super::superx::deserialize_outbox(response_outbox.text().await.unwrap()).await.unwrap(); + let outbox = super::superx::deserialize_outbox(response_outbox.text().await.unwrap()) + .await + .unwrap(); assert!(outbox.items.len() > 0); } @@ -45,7 +50,11 @@ pub async fn main() -> anyhow::Result<()> { println!("\n\n\nas AP:"); for item in outbox.items { - let ap_item = super::conversion::receive_lysand_note(item, "https://ap.lysand.org/example".to_string()).await?; + let ap_item = super::conversion::receive_lysand_note( + item, + "https://ap.lysand.org/example".to_string(), + ) + .await?; println!("{:#?}", ap_item); } diff --git a/src/main.rs b/src/main.rs index d452588..5e1036f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,8 +35,8 @@ use crate::{ objects::post::{Mention, Note}, }; use crate::{activities::follow::Follow, entities::user}; -use lazy_static::lazy_static; use dotenv::dotenv; +use lazy_static::lazy_static; mod activities; mod database; @@ -96,7 +96,7 @@ async fn post_manually( content: format!("{} {}", path.1, target.name), tag: vec![mention], in_reply_to: None, - cc: vec![].into() + cc: vec![].into(), }; CreatePost::send( diff --git a/src/objects/post.rs b/src/objects/post.rs index 6a1c3df..e67403c 100644 --- a/src/objects/post.rs +++ b/src/objects/post.rs @@ -1,5 +1,11 @@ use crate::{ - activities::create_post::CreatePost, database::StateHandle, entities::{post, user}, error::Error, lysand::conversion::db_user_from_url, objects::person::DbUser, utils::generate_object_id + activities::create_post::CreatePost, + database::StateHandle, + entities::{post, user}, + error::Error, + lysand::conversion::db_user_from_url, + objects::person::DbUser, + utils::generate_object_id, }; use activitypub_federation::{ config::Data, @@ -56,18 +62,25 @@ impl Object for post::Model { data: &Data, ) -> Result, Self::Error> { let post = crate::entities::prelude::Post::find() - .filter(post::Column::Id.eq(object_id.to_string())) - .one(data.app_data().database_connection.clone().as_ref()).await; + .filter(post::Column::Id.eq(object_id.to_string())) + .one(data.app_data().database_connection.clone().as_ref()) + .await; Ok(post.unwrap()) } async fn into_json(self, _data: &Data) -> Result { let creator = db_user_from_url(Url::parse(self.creator.as_str()).unwrap()).await?; let to = match self.visibility.as_str() { - "public" => vec![public(), Url::parse(creator.followers.unwrap().as_str()).unwrap()], + "public" => vec![ + public(), + Url::parse(creator.followers.unwrap().as_str()).unwrap(), + ], "followers" => vec![Url::parse(creator.followers.unwrap().as_str()).unwrap()], "direct" => vec![], //TODO: implement this - "unlisted" => vec![Url::parse(creator.followers.unwrap().as_str()).unwrap(), public()], + "unlisted" => vec![ + Url::parse(creator.followers.unwrap().as_str()).unwrap(), + public(), + ], _ => vec![public()], }; Ok(Note { diff --git a/src/utils.rs b/src/utils.rs index 55fd266..daa0274 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -17,5 +17,8 @@ pub fn generate_random_object_id(domain: &str) -> Result { /// Generate a follow accept id pub fn generate_follow_accept_id(domain: &str, db_id: i32) -> Result { - Url::parse(&format!("https://{}/apbridge/activity/follow/{}", domain, db_id)) + Url::parse(&format!( + "https://{}/apbridge/activity/follow/{}", + domain, db_id + )) } From dc4afd84115fbfc9bb783724ad90eed94b41f169 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Thu, 27 Jun 2024 05:13:38 +0200 Subject: [PATCH 23/23] feat: meow meow akkoma? --- Cargo.lock | 10 ++++ Cargo.toml | 1 + migration/src/lib.rs | 2 + ...m20240626_030922_store_ap_json_in_posts.rs | 35 ++++++++++++++ src/activities/create_post.rs | 12 +++-- src/activities/follow.rs | 2 +- src/entities/post.rs | 1 + src/lysand/conversion.rs | 1 + src/lysand/http.rs | 46 ++++++++++++++++++- src/main.rs | 23 +++++++++- src/objects/person.rs | 5 ++ src/objects/post.rs | 6 +++ src/utils.rs | 30 ++++++++++-- 13 files changed, 163 insertions(+), 11 deletions(-) create mode 100644 migration/src/m20240626_030922_store_ap_json_in_posts.rs diff --git a/Cargo.lock b/Cargo.lock index da118f7..92138c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -571,6 +571,15 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64-url" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2b6c78c06f7288d5e3c3d683bde35a79531127c83b087e5d0d77c974b4b28" +dependencies = [ + "base64 0.22.1", +] + [[package]] name = "base64ct" version = "1.6.0" @@ -2061,6 +2070,7 @@ dependencies = [ "async-recursion", "async-trait", "async_once", + "base64-url", "chrono", "clap", "dotenv", diff --git a/Cargo.toml b/Cargo.toml index 8566309..74d7f0f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ time = { version = "0.3.36", features = ["serde"] } serde_derive = "1.0.201" dotenv = "0.15.0" async-recursion = "1.1.1" +base64-url = "3.0.0" [dependencies.sea-orm] version = "0.12.0" diff --git a/migration/src/lib.rs b/migration/src/lib.rs index 7e4572a..08b1e65 100644 --- a/migration/src/lib.rs +++ b/migration/src/lib.rs @@ -4,6 +4,7 @@ mod m20220101_000001_post_table; mod m20240417_230111_user_table; mod m20240417_233430_post_user_keys; mod m20240505_002524_user_follow_relation; +mod m20240626_030922_store_ap_json_in_posts; pub struct Migrator; @@ -15,6 +16,7 @@ impl MigratorTrait for Migrator { Box::new(m20240417_230111_user_table::Migration), Box::new(m20240417_233430_post_user_keys::Migration), Box::new(m20240505_002524_user_follow_relation::Migration), + Box::new(m20240626_030922_store_ap_json_in_posts::Migration), ] } } diff --git a/migration/src/m20240626_030922_store_ap_json_in_posts.rs b/migration/src/m20240626_030922_store_ap_json_in_posts.rs new file mode 100644 index 0000000..fd3aad7 --- /dev/null +++ b/migration/src/m20240626_030922_store_ap_json_in_posts.rs @@ -0,0 +1,35 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .alter_table( + Table::alter() + .table(Post::Table) + .add_column_if_not_exists(ColumnDef::new(Post::ApJson).string()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .alter_table( + Table::alter() + .table(Post::Table) + .drop_column(Post::ApJson) + .to_owned(), + ) + .await + } +} + +#[derive(DeriveIden)] +pub enum Post { + Table, + ApJson, +} diff --git a/src/activities/create_post.rs b/src/activities/create_post.rs index 771bb46..cf8e825 100644 --- a/src/activities/create_post.rs +++ b/src/activities/create_post.rs @@ -6,7 +6,7 @@ use crate::{ person::DbUser, post::{DbPost, Note}, }, - utils::generate_random_object_id, + utils::{base_url_encode, generate_create_id, generate_random_object_id}, }; use activitypub_federation::{ activity_sending::SendActivityTask, @@ -32,14 +32,20 @@ pub struct CreatePost { } impl CreatePost { - pub async fn send(note: Note, inbox: Url, data: &Data) -> Result<(), Error> { + pub async fn send( + note: Note, + db_entry: post::Model, + inbox: Url, + data: &Data, + ) -> Result<(), Error> { print!("Sending reply to {}", ¬e.attributed_to); + let encoded_url = base_url_encode(¬e.id.clone().into()); let create = CreatePost { actor: note.attributed_to.clone(), to: note.to.clone(), object: note, kind: CreateType::Create, - id: generate_random_object_id(data.domain())?, + id: generate_create_id(data.domain(), &db_entry.id, &encoded_url)?, }; let create_with_context = WithContext::new_default(create); let sends = SendActivityTask::prepare( diff --git a/src/activities/follow.rs b/src/activities/follow.rs index b9986de..fe175e0 100644 --- a/src/activities/follow.rs +++ b/src/activities/follow.rs @@ -77,7 +77,7 @@ impl Accept { actor: follow_req.object.clone(), object: follow_req, kind: AcceptType::Accept, - id: generate_follow_accept_id(data.domain(), follow_relation.id)?, + id: generate_follow_accept_id(data.domain(), follow_relation.id.to_string().as_str())?, }; let create_with_context = WithContext::new_default(create); let sends = SendActivityTask::prepare( diff --git a/src/entities/post.rs b/src/entities/post.rs index 0062f05..92aa9db 100644 --- a/src/entities/post.rs +++ b/src/entities/post.rs @@ -24,6 +24,7 @@ pub struct Model { pub spoiler_text: Option, pub creator: String, pub url: String, + pub ap_json: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/src/lysand/conversion.rs b/src/lysand/conversion.rs index 0c940ee..42f7cbe 100644 --- a/src/lysand/conversion.rs +++ b/src/lysand/conversion.rs @@ -229,6 +229,7 @@ pub async fn receive_lysand_note( reply_id: Set(reply_uuid), quoting_id: Set(quote_uuid), spoiler_text: Set(note.subject), + ap_json: Set(Some(serde_json::to_string(&ap_note).unwrap())), ..Default::default() }; let res = post.insert(DB.get().unwrap()).await?; diff --git a/src/lysand/http.rs b/src/lysand/http.rs index d1e594d..6bc9446 100644 --- a/src/lysand/http.rs +++ b/src/lysand/http.rs @@ -1,4 +1,7 @@ -use activitypub_federation::{traits::Object, FEDERATION_CONTENT_TYPE}; +use activitypub_federation::{ + protocol::context::WithContext, traits::Object, FEDERATION_CONTENT_TYPE, +}; +use activitystreams_kinds::{activity::CreateType, object}; use actix_web::{get, web, HttpResponse}; use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; @@ -8,7 +11,9 @@ use crate::{ post::{self, Entity}, prelude, }, - error, Response, DB, FEDERATION_CONFIG, + error, objects, + utils::{base_url_decode, generate_create_id}, + Response, DB, FEDERATION_CONFIG, }; #[get("/apbridge/object/{post}")] @@ -35,3 +40,40 @@ async fn fetch_post( .await?, )) } + +#[get("/apbridge/create/{id}/{base64url}")] +async fn create_activity( + path: web::Path<(String, String)>, + state: web::Data, +) -> actix_web::Result { + let db = DB.get().unwrap(); + + let url = base_url_decode(path.1.as_str()); + + let post = prelude::Post::find() + .filter(post::Column::Id.eq(path.0.as_str())) + .one(db) + .await?; + + let post = match post { + Some(post) => post, + None => return Ok(HttpResponse::NotFound().finish()), + }; + + let ap_post = crate::objects::post::Note::from_db(&post); + + let data = FEDERATION_CONFIG.get().unwrap(); + + let create = crate::activities::create_post::CreatePost { + actor: ap_post.attributed_to.clone(), + to: ap_post.to.clone(), + object: ap_post, + kind: CreateType::Create, + id: generate_create_id(&data.to_request_data().domain(), &path.0, &path.1)?, + }; + let create_with_context = WithContext::new_default(create); + + Ok(HttpResponse::Ok() + .content_type(FEDERATION_CONTENT_TYPE) + .json(create_with_context)) +} diff --git a/src/main.rs b/src/main.rs index 5e1036f..badfc29 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,7 @@ use clap::Parser; use database::Database; use entities::post; use http::{http_get_user, http_post_user_inbox, webfinger}; +use lysand::http::{create_activity, fetch_post}; use objects::person::DbUser; use sea_orm::{ActiveModelTrait, DatabaseConnection, Set}; use serde::{Deserialize, Serialize}; @@ -89,7 +90,7 @@ async fn post_manually( let id: ObjectId = generate_random_object_id(data.domain())?.into(); let note = Note { kind: Default::default(), - id, + id: id.clone(), sensitive: false, attributed_to: Url::parse(&local_user.id).unwrap().into(), to: vec![public()], @@ -99,8 +100,26 @@ async fn post_manually( cc: vec![].into(), }; + let post = entities::post::ActiveModel { + id: Set(uuid::Uuid::now_v7().to_string()), + creator: Set(local_user.id.clone()), + content: Set(note.content.clone()), + sensitive: Set(false), + created_at: Set(Utc::now()), + local: Set(true), + updated_at: Set(Some(Utc::now())), + content_type: Set("Note".to_string()), + visibility: Set("public".to_string()), + url: Set(id.to_string()), + ap_json: Set(Some(serde_json::to_string(¬e).unwrap())), + ..Default::default() + }; + + let post = post.insert(DB.get().unwrap()).await?; + CreatePost::send( note, + post, target.shared_inbox_or_inbox(), &data.to_request_data(), ) @@ -238,6 +257,8 @@ async fn main() -> actix_web::Result<(), anyhow::Error> { .route("/{user}/inbox", web::post().to(http_post_user_inbox)) .route("/.well-known/webfinger", web::get().to(webfinger)) .service(index) + .service(fetch_post) + .service(create_activity) }) .bind(SERVER_URL.to_string())? .workers(num_cpus::get()) diff --git a/src/objects/person.rs b/src/objects/person.rs index 304c32f..0888f3c 100644 --- a/src/objects/person.rs +++ b/src/objects/person.rs @@ -176,4 +176,9 @@ impl Actor for user::Model { fn inbox(&self) -> Url { Url::parse(&self.inbox).unwrap() } + + //TODO: Differenciate shared inbox + fn shared_inbox(&self) -> Option { + None + } } diff --git a/src/objects/post.rs b/src/objects/post.rs index e67403c..1f42e23 100644 --- a/src/objects/post.rs +++ b/src/objects/post.rs @@ -44,6 +44,12 @@ pub struct Note { pub(crate) cc: Option>, } +impl Note { + pub fn from_db(post: &post::Model) -> Self { + serde_json::from_str(&post.ap_json.as_ref().unwrap()).unwrap() + } +} + #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Mention { pub href: Url, diff --git a/src/utils.rs b/src/utils.rs index daa0274..d901109 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -12,13 +12,35 @@ pub fn generate_user_id(domain: &str, uuid: &str) -> Result { pub fn generate_random_object_id(domain: &str) -> Result { let id: String = uuid::Uuid::new_v4().to_string(); - Url::parse(&format!("https://{}/apbridge/object/{}", domain, id)) + generate_object_id(domain, &id) } /// Generate a follow accept id -pub fn generate_follow_accept_id(domain: &str, db_id: i32) -> Result { +pub fn generate_follow_accept_id(domain: &str, db_id: &str) -> Result { + Url::parse(&format!("https://{}/apbridge/follow/{}", domain, db_id)) +} + +// TODO for later aprl: needs to be base64url!!! +pub fn generate_create_id( + domain: &str, + create_db_id: &str, + basesixfour_url: &str, +) -> Result { Url::parse(&format!( - "https://{}/apbridge/activity/follow/{}", - domain, db_id + "https://{}/apbridge/create/{}/{}", + domain, create_db_id, basesixfour_url )) } + +pub fn generate_random_create_id(domain: &str, basesixfour_url: &str) -> Result { + let id: String = uuid::Uuid::new_v4().to_string(); + generate_create_id(domain, &id, basesixfour_url) +} + +pub fn base_url_encode(url: &Url) -> String { + base64_url::encode(&url.to_string()) +} + +pub fn base_url_decode(encoded: &str) -> String { + String::from_utf8(base64_url::decode(encoded).unwrap()).unwrap() +}