diff --git a/Cargo.lock b/Cargo.lock index db9068b51..bd6f0d82b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1754,7 +1754,7 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jacquard" -version = "0.3.0" +version = "0.4.0" dependencies = [ "async-trait", "bon", @@ -1785,7 +1785,7 @@ dependencies = [ [[package]] name = "jacquard-api" -version = "0.3.0" +version = "0.4.0" dependencies = [ "bon", "bytes", @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "jacquard-axum" -version = "0.3.0" +version = "0.4.0" dependencies = [ "axum", "axum-macros", @@ -1821,7 +1821,7 @@ dependencies = [ [[package]] name = "jacquard-common" -version = "0.3.0" +version = "0.4.0" dependencies = [ "async-trait", "base64 0.22.1", @@ -1857,7 +1857,7 @@ dependencies = [ [[package]] name = "jacquard-derive" -version = "0.3.0" +version = "0.4.0" dependencies = [ "heck 0.5.0", "itertools", @@ -1874,7 +1874,7 @@ dependencies = [ [[package]] name = "jacquard-identity" -version = "0.3.0" +version = "0.3.1" dependencies = [ "async-trait", "bon", @@ -1897,7 +1897,7 @@ dependencies = [ [[package]] name = "jacquard-lexicon" -version = "0.3.0" +version = "0.4.0" dependencies = [ "async-trait", "clap", @@ -1926,7 +1926,7 @@ dependencies = [ [[package]] name = "jacquard-oauth" -version = "0.3.0" +version = "0.3.1" dependencies = [ "async-trait", "base64 0.22.1", diff --git a/Cargo.toml b/Cargo.toml index 5af47f1b2..5138faf7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ members = ["crates/*"] [workspace.package] edition = "2024" -version = "0.3.0" +version = "0.4.0" authors = ["Orual "] repository = "https://tangled.org/@nonbinary.computer/jacquard" keywords = ["atproto", "at", "bluesky", "api", "client"] diff --git a/crates/jacquard-api/Cargo.toml b/crates/jacquard-api/Cargo.toml index 14f52c4fa..4af3d5af1 100644 --- a/crates/jacquard-api/Cargo.toml +++ b/crates/jacquard-api/Cargo.toml @@ -2,7 +2,7 @@ name = "jacquard-api" description = "Generated AT Protocol API bindings for Jacquard" edition.workspace = true -version.workspace = true +version = "0.4.0" authors.workspace = true repository.workspace = true keywords.workspace = true @@ -12,78 +12,74 @@ exclude.workspace = true license.workspace = true [package.metadata.docs.rs] -features = [ "bluesky", "other", "ufos" ] +features = [ "bluesky", "other", "lexicon_community", "ufos" ] [dependencies] bon.workspace = true bytes = { workspace = true, features = ["serde"] } -jacquard-common = { version = "0.3.0", path = "../jacquard-common" } -jacquard-derive = { version = "0.3.0", path = "../jacquard-derive" } +jacquard-common = { version = "*", path = "../jacquard-common" } +jacquard-derive = { version = "*", path = "../jacquard-derive" } miette.workspace = true serde.workspace = true thiserror.workspace = true [features] -default = [ "com_atproto", "com_bad_example"] -bluesky = [ "com_atproto", "app_bsky", "chat_bsky", "tools_ozone"] -other = ["sh_tangled", "sh_weaver", "pub_leaflet", "net_anisota", "events_smokesignal","network_slices", "tools_smokesignal", "com_whtwnd", "community_lexicon", "place_stream", "blue__2048" ] -lexicon_community = ["community_lexicon", "my_skylights", "com_whtwnd", "social_psky", "lol_atmo", "blue_linkat"] -ufos = ["place_artwork", "moe_karashiiro", "dev_regnault", "buzz_bookhive", "place_artwork", "how_bun", "lol_atmo", "inc_toronto", "uk_ewancroft", "lol_skittr", "win_tomo", "dev_fudgeu", "dev_ocbwoy3", "blog_pckt", "blue_rito", "com_welistskyblue", "net_bnewbold", "club_stellz", "dev_baileytownsend", "net_aftertheinter", "org_devcon","org_robocracy", "garden_lexicon", "social_clippr", "social_grain", "social_pmsky", "com_crabdance", "app_blebbit", "app_ocho", "uk_skyblur", "us_polhem", "blue_atplane", "net_mmatt" ] -app_bsky = [] -chat_bsky = [] -com_atproto = [] -tools_ozone = [] -sh_tangled = [] -sh_weaver = [] -pub_leaflet = [] -net_anisota = [] -network_slices = [] -place_atwork = [] -tools_smokesignal = [] -uk_ewancroft = [] -place_artwork = [] -moe_karashiiro = [] -buzz_bookhive = [] -dev_regnault = [] -events_smokesignal = [] -dev_baileytownsend = [] +default = [ "minimal"] +minimal = [ "com_atproto", "com_bad_example"] +bluesky = [ "com_atproto", "app_bsky", "chat_bsky", "tools_ozone", "minimal"] +other = ["sh_tangled", "sh_weaver", "pub_leaflet", "net_anisota", "network_slices", "tools_smokesignal", "com_whtwnd", "community_lexicon", "place_stream", "blue__2048", "minimal" ] +lexicon_community = ["community_lexicon", "my_skylights", "com_whtwnd", "social_psky", "blue_linkat", "minimal"] +ufos = [ "moe_karashiiro", "dev_regnault", "buzz_bookhive", "uk_ewancroft", "win_tomo_x", "dev_fudgeu", "dev_ocbwoy3", "blog_pckt", "net_bnewbold", "club_stellz", "dev_baileytownsend", "net_aftertheinter", "org_devcon","org_robocracy", "garden_lexicon", "social_clippr", "social_grain", "social_pmsky", "com_crabdance", "app_blebbit", "app_ocho", "uk_skyblur", "us_polhem", "blue_atplane", "net_mmatt", "minimal" ] + +# --- generated --- +# Generated namespace features +# Each namespace feature automatically enables its dependencies +app_blebbit = [] +app_bsky = ["com_atproto"] +app_ocho = [] +beauty_cybernetic = [] +blog_pckt = [] blue__2048 = [] blue_atplane = [] +blue_linkat = [] +blue_zio = [] +buzz_bookhive = [] +chat_bsky = ["app_bsky"] club_stellz = [] -net_mmatt = [] -how_bun = [] -lol_atmo = [] -lol_skittr = [] -win_tomo = [] -inc_toronto = [] +com_atproto = [] com_bad_example = [] -dev_ocbwoy3 = [] -dev_fudgeu = [] -com_welistskyblue = [] -blog_pckt = [] -blue_rito = [] -net_bnewbold = [] -win_tomo_x = [] +com_crabdance = [] com_shinolabs = [] -fyi_unravel = [] -blue_zio = [] -blue_linkat = [] com_whtwnd = [] community_lexicon = [] -social_psky = [] -place_stream = [] +dev_baileytownsend = [] +dev_fudgeu = [] +dev_ocbwoy3 = [] +dev_regnault = [] +fyi_unravel = [] +garden_lexicon = [] +moe_karashiiro = [] my_skylights = [] net_aftertheinter = [] +net_anisota = ["app_bsky", "com_atproto"] +net_bnewbold = [] +net_mmatt = [] +network_slices = [] org_devcon = [] org_robocracy = [] -garden_lexicon = [] +place_atwork = [] +place_stream = [] +pub_leaflet = [] +sh_tangled = [] +sh_weaver = ["app_bsky"] social_clippr = [] -social_grain = [] +social_grain = ["com_atproto"] social_pmsky = [] -com_crabdance = [] -app_blebbit = [] -beauty_cybernetic = [] -app_ocho = [] +social_psky = [] +tools_ozone = ["chat_bsky", "com_atproto"] +tools_smokesignal = [] +uk_ewancroft = [] uk_skyblur = [] us_polhem = [] +win_tomo_x = [] diff --git a/crates/jacquard-api/lexicons/events_smokesignal_automation_InvokeWebhook.json b/crates/jacquard-api/lexicons/events_smokesignal_automation_InvokeWebhook.json new file mode 100644 index 000000000..6d14b4336 --- /dev/null +++ b/crates/jacquard-api/lexicons/events_smokesignal_automation_InvokeWebhook.json @@ -0,0 +1,46 @@ +{ + "lexicon": 1, + "id": "events.smokesignal.automation.InvokeWebhook", + "defs": { + "main": { + "type": "procedure", + "description": "Process a Smoke Signal webhook event.", + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": [ + "event", + "record", + "context" + ], + "properties": { + "context": { + "type": "object", + "properties": {} + }, + "event": { + "type": "string", + "knownValues": [ + "test", + "rsvp.created", + "event.created" + ] + }, + "record": { + "type": "object", + "properties": {} + } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "properties": {} + } + } + } + } +} \ No newline at end of file diff --git a/crates/jacquard-api/src/app_bsky/actor/status.rs b/crates/jacquard-api/src/app_bsky/actor/status.rs index bb1a0a8b6..f47ee40a1 100644 --- a/crates/jacquard-api/src/app_bsky/actor/status.rs +++ b/crates/jacquard-api/src/app_bsky/actor/status.rs @@ -5,6 +5,24 @@ // This file was automatically generated from Lexicon schemas. // Any manual changes will be overwritten on the next regeneration. +///Advertises an account as currently offering live content. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Live; +impl std::fmt::Display for Live { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "live") + } +} + ///A declaration of a Bluesky account status. #[jacquard_derive::lexicon] #[derive( diff --git a/crates/jacquard-api/src/app_bsky/feed.rs b/crates/jacquard-api/src/app_bsky/feed.rs index 186a02c96..f6ab30695 100644 --- a/crates/jacquard-api/src/app_bsky/feed.rs +++ b/crates/jacquard-api/src/app_bsky/feed.rs @@ -68,6 +68,114 @@ pub struct BlockedPost<'a> { pub uri: jacquard_common::types::string::AtUri<'a>, } +///User clicked through to the author of the feed item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ClickthroughAuthor; +impl std::fmt::Display for ClickthroughAuthor { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "clickthroughAuthor") + } +} + +///User clicked through to the embedded content of the feed item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ClickthroughEmbed; +impl std::fmt::Display for ClickthroughEmbed { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "clickthroughEmbed") + } +} + +///User clicked through to the feed item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ClickthroughItem; +impl std::fmt::Display for ClickthroughItem { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "clickthroughItem") + } +} + +///User clicked through to the reposter of the feed item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ClickthroughReposter; +impl std::fmt::Display for ClickthroughReposter { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "clickthroughReposter") + } +} + +///Declares the feed generator returns any types of posts. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ContentModeUnspecified; +impl std::fmt::Display for ContentModeUnspecified { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "contentModeUnspecified") + } +} + +///Declares the feed generator returns posts containing app.bsky.embed.video embeds. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ContentModeVideo; +impl std::fmt::Display for ContentModeVideo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "contentModeVideo") + } +} + #[jacquard_derive::lexicon] #[derive( serde::Serialize, @@ -205,6 +313,114 @@ pub struct Interaction<'a> { pub req_id: std::option::Option>, } +///User liked the feed item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct InteractionLike; +impl std::fmt::Display for InteractionLike { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "interactionLike") + } +} + +///User quoted the feed item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct InteractionQuote; +impl std::fmt::Display for InteractionQuote { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "interactionQuote") + } +} + +///User replied to the feed item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct InteractionReply; +impl std::fmt::Display for InteractionReply { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "interactionReply") + } +} + +///User reposted the feed item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct InteractionRepost; +impl std::fmt::Display for InteractionRepost { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "interactionRepost") + } +} + +///Feed item was seen by user +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct InteractionSeen; +impl std::fmt::Display for InteractionSeen { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "interactionSeen") + } +} + +///User shared the feed item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct InteractionShare; +impl std::fmt::Display for InteractionShare { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "interactionShare") + } +} + #[jacquard_derive::lexicon] #[derive( serde::Serialize, @@ -377,6 +593,42 @@ pub enum ReplyRefRecordParent<'a> {} #[serde(tag = "$type")] #[serde(bound(deserialize = "'de: 'a"))] pub enum ReplyRefRecordRoot<'a> {} +///Request that less content like the given feed item be shown in the feed +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct RequestLess; +impl std::fmt::Display for RequestLess { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "requestLess") + } +} + +///Request that more content like the given feed item be shown in the feed +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct RequestMore; +impl std::fmt::Display for RequestMore { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "requestMore") + } +} + #[jacquard_derive::lexicon] #[derive( serde::Serialize, diff --git a/crates/jacquard-api/src/app_bsky/graph.rs b/crates/jacquard-api/src/app_bsky/graph.rs index 08b1ed6e1..4db56b4da 100644 --- a/crates/jacquard-api/src/app_bsky/graph.rs +++ b/crates/jacquard-api/src/app_bsky/graph.rs @@ -36,6 +36,24 @@ pub mod unmute_actor_list; pub mod unmute_thread; pub mod verification; +///A list of actors used for curation purposes such as list feeds or interaction gating. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Curatelist; +impl std::fmt::Display for Curatelist { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "curatelist") + } +} + #[jacquard_derive::lexicon] #[derive( serde::Serialize, @@ -237,6 +255,24 @@ pub struct ListViewerState<'a> { pub muted: std::option::Option, } +///A list of actors to apply an aggregate moderation action (mute/block) on. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Modlist; +impl std::fmt::Display for Modlist { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "modlist") + } +} + ///indicates that a handle or DID could not be resolved #[jacquard_derive::lexicon] #[derive( @@ -255,6 +291,24 @@ pub struct NotFoundActor<'a> { pub not_found: bool, } +///A list of actors used for only for reference purposes such as within a starter pack. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Referencelist; +impl std::fmt::Display for Referencelist { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "referencelist") + } +} + ///lists the bi-directional graph relationships between one actor (not indicated in the object), and the target actors (the DID included in the object) #[jacquard_derive::lexicon] #[derive( diff --git a/crates/jacquard-api/src/buzz_bookhive.rs b/crates/jacquard-api/src/buzz_bookhive.rs index 007116c0d..a63d59642 100644 --- a/crates/jacquard-api/src/buzz_bookhive.rs +++ b/crates/jacquard-api/src/buzz_bookhive.rs @@ -12,6 +12,24 @@ pub mod get_profile; pub mod hive_book; pub mod search_books; +///User has abandoned the book +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Abandoned; +impl std::fmt::Display for Abandoned { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "abandoned") + } +} + #[jacquard_derive::lexicon] #[derive( serde::Serialize, @@ -64,6 +82,42 @@ pub struct Comment<'a> { pub parent: crate::com_atproto::repo::strong_ref::StrongRef<'a>, } +///User has finished reading the book +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Finished; +impl std::fmt::Display for Finished { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "finished") + } +} + +///User owns the book +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Owned; +impl std::fmt::Display for Owned { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "owned") + } +} + #[jacquard_derive::lexicon] #[derive( serde::Serialize, @@ -90,6 +144,24 @@ pub struct Profile<'a> { pub reviews: i64, } +///User is currently reading the book +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Reading; +impl std::fmt::Display for Reading { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reading") + } +} + #[jacquard_derive::lexicon] #[derive( serde::Serialize, @@ -170,4 +242,22 @@ pub struct UserBook<'a> { ///The title of the book #[serde(borrow)] pub title: jacquard_common::CowStr<'a>, +} + +///User wants to read the book +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct WantToRead; +impl std::fmt::Display for WantToRead { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "wantToRead") + } } \ No newline at end of file diff --git a/crates/jacquard-api/src/com_atproto/moderation.rs b/crates/jacquard-api/src/com_atproto/moderation.rs index 96c9f6cc9..f2ad24450 100644 --- a/crates/jacquard-api/src/com_atproto/moderation.rs +++ b/crates/jacquard-api/src/com_atproto/moderation.rs @@ -7,6 +7,114 @@ pub mod create_report; +///Appeal a previously taken moderation action +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonAppeal; +impl std::fmt::Display for ReasonAppeal { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonAppeal") + } +} + +///Misleading identity, affiliation, or content. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingOther`. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonMisleading; +impl std::fmt::Display for ReasonMisleading { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonMisleading") + } +} + +///Reports not falling under another report category. Prefer new lexicon definition `tools.ozone.report.defs#reasonOther`. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonOther; +impl std::fmt::Display for ReasonOther { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonOther") + } +} + +///Rude, harassing, explicit, or otherwise unwelcoming behavior. Prefer new lexicon definition `tools.ozone.report.defs#reasonHarassmentOther`. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonRude; +impl std::fmt::Display for ReasonRude { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonRude") + } +} + +///Unwanted or mislabeled sexual content. Prefer new lexicon definition `tools.ozone.report.defs#reasonSexualUnlabeled`. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSexual; +impl std::fmt::Display for ReasonSexual { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSexual") + } +} + +///Spam: frequent unwanted promotion, replies, mentions. Prefer new lexicon definition `tools.ozone.report.defs#reasonMisleadingSpam`. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSpam; +impl std::fmt::Display for ReasonSpam { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSpam") + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ReasonType<'a> { ComAtprotoModerationDefsReasonSpam, @@ -684,6 +792,24 @@ impl jacquard_common::IntoStatic for ReasonType<'_> { } } +///Direct violation of server rules, laws, terms of service. Prefer new lexicon definition `tools.ozone.report.defs#reasonRuleOther`. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonViolation; +impl std::fmt::Display for ReasonViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonViolation") + } +} + ///Tag describing a type of subject that might be reported. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum SubjectType<'a> { diff --git a/crates/jacquard-api/src/community_lexicon/calendar/event.rs b/crates/jacquard-api/src/community_lexicon/calendar/event.rs index 9904f2681..2bfbf3e9f 100644 --- a/crates/jacquard-api/src/community_lexicon/calendar/event.rs +++ b/crates/jacquard-api/src/community_lexicon/calendar/event.rs @@ -5,6 +5,60 @@ // This file was automatically generated from Lexicon schemas. // Any manual changes will be overwritten on the next regeneration. +///The event has been cancelled. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Cancelled; +impl std::fmt::Display for Cancelled { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "cancelled") + } +} + +///A hybrid event that takes place both online and offline. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Hybrid; +impl std::fmt::Display for Hybrid { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "hybrid") + } +} + +///An in-person event that takes place offline. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Inperson; +impl std::fmt::Display for Inperson { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "inperson") + } +} + ///A calendar event. #[jacquard_derive::lexicon] #[derive( @@ -165,6 +219,78 @@ impl jacquard_common::IntoStatic for Mode<'_> { } } +///The event has been created, but not finalized. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Planned; +impl std::fmt::Display for Planned { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "planned") + } +} + +///The event has been postponed and a new start date has not been set. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Postponed; +impl std::fmt::Display for Postponed { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "postponed") + } +} + +///The event has been rescheduled. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Rescheduled; +impl std::fmt::Display for Rescheduled { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "rescheduled") + } +} + +///The event has been created and scheduled. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Scheduled; +impl std::fmt::Display for Scheduled { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "scheduled") + } +} + ///The status of the event. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Status<'a> { @@ -316,4 +442,22 @@ pub struct Uri<'a> { pub name: std::option::Option>, #[serde(borrow)] pub uri: jacquard_common::types::string::Uri<'a>, +} + +///A virtual event that takes place online. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Virtual; +impl std::fmt::Display for Virtual { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "virtual") + } } \ No newline at end of file diff --git a/crates/jacquard-api/src/community_lexicon/calendar/rsvp.rs b/crates/jacquard-api/src/community_lexicon/calendar/rsvp.rs index 662ee6244..13afc40f5 100644 --- a/crates/jacquard-api/src/community_lexicon/calendar/rsvp.rs +++ b/crates/jacquard-api/src/community_lexicon/calendar/rsvp.rs @@ -5,6 +5,42 @@ // This file was automatically generated from Lexicon schemas. // Any manual changes will be overwritten on the next regeneration. +///Going to the event +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Going; +impl std::fmt::Display for Going { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "going") + } +} + +///Interested in the event +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Interested; +impl std::fmt::Display for Interested { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "interested") + } +} + ///An RSVP for an event. #[jacquard_derive::lexicon] #[derive( @@ -26,4 +62,22 @@ pub struct Rsvp<'a> { impl jacquard_common::types::collection::Collection for Rsvp<'_> { const NSID: &'static str = "community.lexicon.calendar.rsvp"; +} + +///Not going to the event +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Notgoing; +impl std::fmt::Display for Notgoing { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "notgoing") + } } \ No newline at end of file diff --git a/crates/jacquard-api/src/events_smokesignal.rs b/crates/jacquard-api/src/events_smokesignal.rs deleted file mode 100644 index 3eb0a8819..000000000 --- a/crates/jacquard-api/src/events_smokesignal.rs +++ /dev/null @@ -1,6 +0,0 @@ -// @generated by jacquard-lexicon. DO NOT EDIT. -// -// This file was automatically generated from Lexicon schemas. -// Any manual changes will be overwritten on the next regeneration. - -pub mod automation; \ No newline at end of file diff --git a/crates/jacquard-api/src/events_smokesignal/automation.rs b/crates/jacquard-api/src/events_smokesignal/automation.rs deleted file mode 100644 index dff606a45..000000000 --- a/crates/jacquard-api/src/events_smokesignal/automation.rs +++ /dev/null @@ -1,6 +0,0 @@ -// @generated by jacquard-lexicon. DO NOT EDIT. -// -// This file was automatically generated from Lexicon schemas. -// Any manual changes will be overwritten on the next regeneration. - -pub mod invoke_webhook; \ No newline at end of file diff --git a/crates/jacquard-api/src/events_smokesignal/automation/invoke_webhook.rs b/crates/jacquard-api/src/events_smokesignal/automation/invoke_webhook.rs deleted file mode 100644 index 41b44d998..000000000 --- a/crates/jacquard-api/src/events_smokesignal/automation/invoke_webhook.rs +++ /dev/null @@ -1,78 +0,0 @@ -// @generated by jacquard-lexicon. DO NOT EDIT. -// -// Lexicon: events.smokesignal.automation.InvokeWebhook -// -// This file was automatically generated from Lexicon schemas. -// Any manual changes will be overwritten on the next regeneration. - -#[jacquard_derive::lexicon] -#[derive( - serde::Serialize, - serde::Deserialize, - Debug, - Clone, - PartialEq, - Eq, - bon::Builder, - jacquard_derive::IntoStatic -)] -#[serde(rename_all = "camelCase")] -#[builder(start_fn = new)] -pub struct InvokeWebhook<'a> { - #[serde(borrow)] - pub context: InvokeWebhookRecordContext<'a>, - #[serde(borrow)] - #[builder(into)] - pub event: jacquard_common::CowStr<'a>, - #[serde(borrow)] - pub record: InvokeWebhookRecordRecord<'a>, - #[serde(flatten)] - #[serde(borrow)] - #[builder(default)] - pub extra_data: ::std::collections::BTreeMap< - ::jacquard_common::smol_str::SmolStr, - ::jacquard_common::types::value::Data<'a>, - >, -} - -#[jacquard_derive::lexicon] -#[derive( - serde::Serialize, - serde::Deserialize, - Debug, - Clone, - PartialEq, - Eq, - jacquard_derive::IntoStatic -)] -#[serde(rename_all = "camelCase")] -pub struct InvokeWebhookOutput<'a> {} -///Response type for -///events.smokesignal.automation.InvokeWebhook -pub struct InvokeWebhookResponse; -impl jacquard_common::xrpc::XrpcResp for InvokeWebhookResponse { - const NSID: &'static str = "events.smokesignal.automation.InvokeWebhook"; - const ENCODING: &'static str = "application/json"; - type Output<'de> = InvokeWebhookOutput<'de>; - type Err<'de> = jacquard_common::xrpc::GenericError<'de>; -} - -impl<'de> jacquard_common::xrpc::XrpcRequest<'de> for InvokeWebhook<'de> { - const NSID: &'static str = "events.smokesignal.automation.InvokeWebhook"; - const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Procedure( - "application/json", - ); - type Response = InvokeWebhookResponse; -} - -///Endpoint type for -///events.smokesignal.automation.InvokeWebhook -pub struct InvokeWebhookRequest; -impl jacquard_common::xrpc::XrpcEndpoint for InvokeWebhookRequest { - const PATH: &'static str = "/xrpc/events.smokesignal.automation.InvokeWebhook"; - const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Procedure( - "application/json", - ); - type Request<'de> = InvokeWebhook<'de>; - type Response = InvokeWebhookResponse; -} \ No newline at end of file diff --git a/crates/jacquard-api/src/lol_atmo.rs b/crates/jacquard-api/src/lol_atmo.rs deleted file mode 100644 index 9e49ee8d4..000000000 --- a/crates/jacquard-api/src/lol_atmo.rs +++ /dev/null @@ -1,6 +0,0 @@ -// @generated by jacquard-lexicon. DO NOT EDIT. -// -// This file was automatically generated from Lexicon schemas. -// Any manual changes will be overwritten on the next regeneration. - -pub mod link; \ No newline at end of file diff --git a/crates/jacquard-api/src/lol_atmo/link.rs b/crates/jacquard-api/src/lol_atmo/link.rs deleted file mode 100644 index 634b01565..000000000 --- a/crates/jacquard-api/src/lol_atmo/link.rs +++ /dev/null @@ -1,28 +0,0 @@ -// @generated by jacquard-lexicon. DO NOT EDIT. -// -// Lexicon: lol.atmo.link -// -// This file was automatically generated from Lexicon schemas. -// Any manual changes will be overwritten on the next regeneration. - -#[jacquard_derive::lexicon] -#[derive( - serde::Serialize, - serde::Deserialize, - Debug, - Clone, - PartialEq, - Eq, - jacquard_derive::IntoStatic -)] -#[serde(rename_all = "camelCase")] -pub struct Link<'a> { - #[serde(borrow)] - pub short: jacquard_common::CowStr<'a>, - #[serde(borrow)] - pub url: jacquard_common::CowStr<'a>, -} - -impl jacquard_common::types::collection::Collection for Link<'_> { - const NSID: &'static str = "lol.atmo.link"; -} \ No newline at end of file diff --git a/crates/jacquard-api/src/lol_skittr.rs b/crates/jacquard-api/src/lol_skittr.rs deleted file mode 100644 index 0d0a56e15..000000000 --- a/crates/jacquard-api/src/lol_skittr.rs +++ /dev/null @@ -1,7 +0,0 @@ -// @generated by jacquard-lexicon. DO NOT EDIT. -// -// This file was automatically generated from Lexicon schemas. -// Any manual changes will be overwritten on the next regeneration. - -pub mod actor; -pub mod server; \ No newline at end of file diff --git a/crates/jacquard-api/src/lol_skittr/actor.rs b/crates/jacquard-api/src/lol_skittr/actor.rs deleted file mode 100644 index dde94cb4b..000000000 --- a/crates/jacquard-api/src/lol_skittr/actor.rs +++ /dev/null @@ -1,7 +0,0 @@ -// @generated by jacquard-lexicon. DO NOT EDIT. -// -// This file was automatically generated from Lexicon schemas. -// Any manual changes will be overwritten on the next regeneration. - -pub mod get_theme; -pub mod theme; \ No newline at end of file diff --git a/crates/jacquard-api/src/lol_skittr/actor/get_theme.rs b/crates/jacquard-api/src/lol_skittr/actor/get_theme.rs deleted file mode 100644 index 83dfb578f..000000000 --- a/crates/jacquard-api/src/lol_skittr/actor/get_theme.rs +++ /dev/null @@ -1,66 +0,0 @@ -// @generated by jacquard-lexicon. DO NOT EDIT. -// -// Lexicon: lol.skittr.actor.getTheme -// -// This file was automatically generated from Lexicon schemas. -// Any manual changes will be overwritten on the next regeneration. - -#[derive( - serde::Serialize, - serde::Deserialize, - Debug, - Clone, - PartialEq, - Eq, - bon::Builder, - jacquard_derive::IntoStatic -)] -#[builder(start_fn = new)] -#[serde(rename_all = "camelCase")] -pub struct GetTheme<'a> { - #[serde(borrow)] - pub actor: jacquard_common::types::ident::AtIdentifier<'a>, -} - -#[jacquard_derive::lexicon] -#[derive( - serde::Serialize, - serde::Deserialize, - Debug, - Clone, - PartialEq, - Eq, - jacquard_derive::IntoStatic -)] -#[serde(rename_all = "camelCase")] -pub struct GetThemeOutput<'a> { - #[serde(flatten)] - #[serde(borrow)] - pub value: crate::lol_skittr::actor::theme::Theme<'a>, -} - -///Response type for -///lol.skittr.actor.getTheme -pub struct GetThemeResponse; -impl jacquard_common::xrpc::XrpcResp for GetThemeResponse { - const NSID: &'static str = "lol.skittr.actor.getTheme"; - const ENCODING: &'static str = "application/json"; - type Output<'de> = GetThemeOutput<'de>; - type Err<'de> = jacquard_common::xrpc::GenericError<'de>; -} - -impl<'de> jacquard_common::xrpc::XrpcRequest<'de> for GetTheme<'de> { - const NSID: &'static str = "lol.skittr.actor.getTheme"; - const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; - type Response = GetThemeResponse; -} - -///Endpoint type for -///lol.skittr.actor.getTheme -pub struct GetThemeRequest; -impl jacquard_common::xrpc::XrpcEndpoint for GetThemeRequest { - const PATH: &'static str = "/xrpc/lol.skittr.actor.getTheme"; - const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; - type Request<'de> = GetTheme<'de>; - type Response = GetThemeResponse; -} \ No newline at end of file diff --git a/crates/jacquard-api/src/lol_skittr/actor/theme.rs b/crates/jacquard-api/src/lol_skittr/actor/theme.rs deleted file mode 100644 index ad391b058..000000000 --- a/crates/jacquard-api/src/lol_skittr/actor/theme.rs +++ /dev/null @@ -1,39 +0,0 @@ -// @generated by jacquard-lexicon. DO NOT EDIT. -// -// Lexicon: lol.skittr.actor.theme -// -// This file was automatically generated from Lexicon schemas. -// Any manual changes will be overwritten on the next regeneration. - -///Profile customization values -#[jacquard_derive::lexicon] -#[derive( - serde::Serialize, - serde::Deserialize, - Debug, - Clone, - PartialEq, - Eq, - jacquard_derive::IntoStatic -)] -#[serde(rename_all = "camelCase")] -pub struct Theme<'a> { - ///A background image, must be either PNG or JPEG - #[serde(skip_serializing_if = "std::option::Option::is_none")] - #[serde(borrow)] - pub background: std::option::Option>, - #[serde(borrow)] - pub bg_color: jacquard_common::CowStr<'a>, - #[serde(borrow)] - pub link_color: jacquard_common::CowStr<'a>, - #[serde(borrow)] - pub side_border: jacquard_common::CowStr<'a>, - #[serde(borrow)] - pub side_color: jacquard_common::CowStr<'a>, - #[serde(borrow)] - pub text_color: jacquard_common::CowStr<'a>, -} - -impl jacquard_common::types::collection::Collection for Theme<'_> { - const NSID: &'static str = "lol.skittr.actor.theme"; -} \ No newline at end of file diff --git a/crates/jacquard-api/src/lol_skittr/server.rs b/crates/jacquard-api/src/lol_skittr/server.rs deleted file mode 100644 index 29d4f3077..000000000 --- a/crates/jacquard-api/src/lol_skittr/server.rs +++ /dev/null @@ -1,6 +0,0 @@ -// @generated by jacquard-lexicon. DO NOT EDIT. -// -// This file was automatically generated from Lexicon schemas. -// Any manual changes will be overwritten on the next regeneration. - -pub mod get_meta; \ No newline at end of file diff --git a/crates/jacquard-api/src/lol_skittr/server/get_meta.rs b/crates/jacquard-api/src/lol_skittr/server/get_meta.rs deleted file mode 100644 index 13411256e..000000000 --- a/crates/jacquard-api/src/lol_skittr/server/get_meta.rs +++ /dev/null @@ -1,67 +0,0 @@ -// @generated by jacquard-lexicon. DO NOT EDIT. -// -// Lexicon: lol.skittr.server.getMeta -// -// This file was automatically generated from Lexicon schemas. -// Any manual changes will be overwritten on the next regeneration. - -#[jacquard_derive::lexicon] -#[derive( - serde::Serialize, - serde::Deserialize, - Debug, - Clone, - PartialEq, - Eq, - jacquard_derive::IntoStatic -)] -#[serde(rename_all = "camelCase")] -pub struct GetMetaOutput<'a> { - #[serde(borrow)] - pub software: jacquard_common::CowStr<'a>, - #[serde(skip_serializing_if = "std::option::Option::is_none")] - #[serde(borrow)] - pub supported_extensions: std::option::Option>>, - #[serde(borrow)] - pub supported_lexicons: Vec>, - #[serde(borrow)] - pub version: jacquard_common::CowStr<'a>, -} - -/// XRPC request marker type -#[derive( - Debug, - Clone, - Copy, - PartialEq, - Eq, - serde::Serialize, - serde::Deserialize, - jacquard_derive::IntoStatic -)] -pub struct GetMeta; -///Response type for -///lol.skittr.server.getMeta -pub struct GetMetaResponse; -impl jacquard_common::xrpc::XrpcResp for GetMetaResponse { - const NSID: &'static str = "lol.skittr.server.getMeta"; - const ENCODING: &'static str = "application/json"; - type Output<'de> = GetMetaOutput<'de>; - type Err<'de> = jacquard_common::xrpc::GenericError<'de>; -} - -impl<'de> jacquard_common::xrpc::XrpcRequest<'de> for GetMeta { - const NSID: &'static str = "lol.skittr.server.getMeta"; - const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; - type Response = GetMetaResponse; -} - -///Endpoint type for -///lol.skittr.server.getMeta -pub struct GetMetaRequest; -impl jacquard_common::xrpc::XrpcEndpoint for GetMetaRequest { - const PATH: &'static str = "/xrpc/lol.skittr.server.getMeta"; - const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Query; - type Request<'de> = GetMeta; - type Response = GetMetaResponse; -} \ No newline at end of file diff --git a/crates/jacquard-api/src/my_skylights/list_item.rs b/crates/jacquard-api/src/my_skylights/list_item.rs index 2bbf12d4d..f52b1d7ed 100644 --- a/crates/jacquard-api/src/my_skylights/list_item.rs +++ b/crates/jacquard-api/src/my_skylights/list_item.rs @@ -5,6 +5,24 @@ // This file was automatically generated from Lexicon schemas. // Any manual changes will be overwritten on the next regeneration. +///User gave up on finishing the item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Abandoned; +impl std::fmt::Display for Abandoned { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "abandoned") + } +} + #[jacquard_derive::lexicon] #[derive( serde::Serialize, @@ -47,6 +65,24 @@ pub enum BuiltinRecordType<'a> { ListItemWishlist(Box), } +///User is currently reading/watching/... the item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct InProgress; +impl std::fmt::Display for InProgress { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "inProgress") + } +} + #[jacquard_derive::lexicon] #[derive( serde::Serialize, @@ -87,4 +123,58 @@ pub struct ListItem<'a> { pub enum ListItemRecordList<'a> { #[serde(rename = "my.skylights.list")] List(Box>), +} + +///User owns the item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Owned; +impl std::fmt::Display for Owned { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "owned") + } +} + +///User plans to read/watch/... the item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Queue; +impl std::fmt::Display for Queue { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "queue") + } +} + +///User wants to own the item +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Wishlist; +impl std::fmt::Display for Wishlist { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "wishlist") + } } \ No newline at end of file diff --git a/crates/jacquard-api/src/place_atwork/profile.rs b/crates/jacquard-api/src/place_atwork/profile.rs index 2e83c6512..6468f521a 100644 --- a/crates/jacquard-api/src/place_atwork/profile.rs +++ b/crates/jacquard-api/src/place_atwork/profile.rs @@ -5,6 +5,42 @@ // This file was automatically generated from Lexicon schemas. // Any manual changes will be overwritten on the next regeneration. +///Indicates the identity is available for hire +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Forhire; +impl std::fmt::Display for Forhire { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "forhire") + } +} + +///Indicates the identity is actively hiring +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Hiring; +impl std::fmt::Display for Hiring { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "hiring") + } +} + ///A user profile for AT://Work.Place #[jacquard_derive::lexicon] #[derive( diff --git a/crates/jacquard-api/src/pub_leaflet/pages/linear_document.rs b/crates/jacquard-api/src/pub_leaflet/pages/linear_document.rs index e0ad86c97..69fc1e186 100644 --- a/crates/jacquard-api/src/pub_leaflet/pages/linear_document.rs +++ b/crates/jacquard-api/src/pub_leaflet/pages/linear_document.rs @@ -112,4 +112,55 @@ pub struct Quote<'a> { pub end: crate::pub_leaflet::pages::linear_document::Position<'a>, #[serde(borrow)] pub start: crate::pub_leaflet::pages::linear_document::Position<'a>, +} + +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct TextAlignCenter; +impl std::fmt::Display for TextAlignCenter { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "textAlignCenter") + } +} + +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct TextAlignLeft; +impl std::fmt::Display for TextAlignLeft { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "textAlignLeft") + } +} + +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct TextAlignRight; +impl std::fmt::Display for TextAlignRight { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "textAlignRight") + } } \ No newline at end of file diff --git a/crates/jacquard-api/src/sh_tangled/repo/issue/state/closed.rs b/crates/jacquard-api/src/sh_tangled/repo/issue/state/closed.rs index 55de10294..27fad3fda 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/issue/state/closed.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/issue/state/closed.rs @@ -5,3 +5,20 @@ // This file was automatically generated from Lexicon schemas. // Any manual changes will be overwritten on the next regeneration. +///closed issue +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Closed; +impl std::fmt::Display for Closed { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "main") + } +} \ No newline at end of file diff --git a/crates/jacquard-api/src/sh_tangled/repo/issue/state/open.rs b/crates/jacquard-api/src/sh_tangled/repo/issue/state/open.rs index 61e72d5f0..559e2f53c 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/issue/state/open.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/issue/state/open.rs @@ -5,3 +5,20 @@ // This file was automatically generated from Lexicon schemas. // Any manual changes will be overwritten on the next regeneration. +///open issue +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Open; +impl std::fmt::Display for Open { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "main") + } +} \ No newline at end of file diff --git a/crates/jacquard-api/src/sh_tangled/repo/pull/status/closed.rs b/crates/jacquard-api/src/sh_tangled/repo/pull/status/closed.rs index c82dff7b8..3bc7b4abc 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/pull/status/closed.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/pull/status/closed.rs @@ -5,3 +5,20 @@ // This file was automatically generated from Lexicon schemas. // Any manual changes will be overwritten on the next regeneration. +///closed pull request +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Closed; +impl std::fmt::Display for Closed { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "main") + } +} \ No newline at end of file diff --git a/crates/jacquard-api/src/sh_tangled/repo/pull/status/merged.rs b/crates/jacquard-api/src/sh_tangled/repo/pull/status/merged.rs index 6039d0868..2cb9e3377 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/pull/status/merged.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/pull/status/merged.rs @@ -5,3 +5,20 @@ // This file was automatically generated from Lexicon schemas. // Any manual changes will be overwritten on the next regeneration. +///merged pull request +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Merged; +impl std::fmt::Display for Merged { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "main") + } +} \ No newline at end of file diff --git a/crates/jacquard-api/src/sh_tangled/repo/pull/status/open.rs b/crates/jacquard-api/src/sh_tangled/repo/pull/status/open.rs index bd2351015..8de1f3ffd 100644 --- a/crates/jacquard-api/src/sh_tangled/repo/pull/status/open.rs +++ b/crates/jacquard-api/src/sh_tangled/repo/pull/status/open.rs @@ -5,3 +5,20 @@ // This file was automatically generated from Lexicon schemas. // Any manual changes will be overwritten on the next regeneration. +///open pull request +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct Open; +impl std::fmt::Display for Open { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "main") + } +} \ No newline at end of file diff --git a/crates/jacquard-api/src/sh_weaver/embed/record_with_media.rs b/crates/jacquard-api/src/sh_weaver/embed/record_with_media.rs index c2de42581..0c6eb2f8a 100644 --- a/crates/jacquard-api/src/sh_weaver/embed/record_with_media.rs +++ b/crates/jacquard-api/src/sh_weaver/embed/record_with_media.rs @@ -41,11 +41,11 @@ pub enum RecordWithMediaRecordMedia<'a> { #[serde(rename = "sh.weaver.embed.external")] External(Box>), #[serde(rename = "app.bsky.embed.images")] - Images(Box>), + BskyImages(Box>), #[serde(rename = "app.bsky.embed.video")] Video(Box>), #[serde(rename = "app.bsky.embed.external")] - External(Box>), + BskyExternal(Box>), } #[jacquard_derive::open_union] @@ -107,7 +107,7 @@ pub enum ViewRecordMedia<'a> { #[serde(rename = "app.bsky.embed.video#view")] VideoView(Box>), #[serde(rename = "app.bsky.embed.external#view")] - ExternalView(Box>), + BskyExternalView(Box>), } #[jacquard_derive::open_union] diff --git a/crates/jacquard-api/src/tools_ozone/moderation.rs b/crates/jacquard-api/src/tools_ozone/moderation.rs index 9af1cbd4c..dc8b4e975 100644 --- a/crates/jacquard-api/src/tools_ozone/moderation.rs +++ b/crates/jacquard-api/src/tools_ozone/moderation.rs @@ -1078,6 +1078,78 @@ pub struct ReporterStats<'a> { pub takendown_record_count: i64, } +///Moderator review status of a subject: Closed. Indicates that the subject was already reviewed and resolved by a moderator +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReviewClosed; +impl std::fmt::Display for ReviewClosed { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reviewClosed") + } +} + +///Moderator review status of a subject: Escalated. Indicates that the subject was escalated for review by a moderator +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReviewEscalated; +impl std::fmt::Display for ReviewEscalated { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reviewEscalated") + } +} + +///Moderator review status of a subject: Unnecessary. Indicates that the subject does not need a review at the moment but there is probably some moderation related metadata available for it +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReviewNone; +impl std::fmt::Display for ReviewNone { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reviewNone") + } +} + +///Moderator review status of a subject: Open. Indicates that the subject needs to be reviewed by a moderator +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReviewOpen; +impl std::fmt::Display for ReviewOpen { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reviewOpen") + } +} + ///Account credentials revocation by moderators. Only works on DID subjects. #[jacquard_derive::lexicon] #[derive( @@ -1435,6 +1507,60 @@ pub struct SubjectView<'a> { #[serde(tag = "$type")] #[serde(bound(deserialize = "'de: 'a"))] pub enum SubjectViewRecordProfile<'a> {} +///Moderation event timeline event for a PLC create operation +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct TimelineEventPlcCreate; +impl std::fmt::Display for TimelineEventPlcCreate { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "timelineEventPlcCreate") + } +} + +///Moderation event timeline event for generic PLC operation +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct TimelineEventPlcOperation; +impl std::fmt::Display for TimelineEventPlcOperation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "timelineEventPlcOperation") + } +} + +///Moderation event timeline event for a PLC tombstone operation +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct TimelineEventPlcTombstone; +impl std::fmt::Display for TimelineEventPlcTombstone { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "timelineEventPlcTombstone") + } +} + #[jacquard_derive::lexicon] #[derive( serde::Serialize, diff --git a/crates/jacquard-api/src/tools_ozone/report.rs b/crates/jacquard-api/src/tools_ozone/report.rs index 2921a8e60..3d592b9d4 100644 --- a/crates/jacquard-api/src/tools_ozone/report.rs +++ b/crates/jacquard-api/src/tools_ozone/report.rs @@ -5,6 +5,600 @@ // This file was automatically generated from Lexicon schemas. // Any manual changes will be overwritten on the next regeneration. +///Appeal a previously taken moderation action +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonAppeal; +impl std::fmt::Display for ReasonAppeal { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonAppeal") + } +} + +///Child sexual abuse material (CSAM). These reports will be sent only be sent to the application's Moderation Authority. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonChildSafetyCsam; +impl std::fmt::Display for ReasonChildSafetyCsam { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonChildSafetyCSAM") + } +} + +///Grooming or predatory behavior. These reports will be sent only be sent to the application's Moderation Authority. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonChildSafetyGroom; +impl std::fmt::Display for ReasonChildSafetyGroom { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonChildSafetyGroom") + } +} + +///Harassment or bullying of minors +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonChildSafetyHarassment; +impl std::fmt::Display for ReasonChildSafetyHarassment { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonChildSafetyHarassment") + } +} + +///Other child safety. These reports will be sent only be sent to the application's Moderation Authority. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonChildSafetyOther; +impl std::fmt::Display for ReasonChildSafetyOther { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonChildSafetyOther") + } +} + +///Privacy violation involving a minor +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonChildSafetyPrivacy; +impl std::fmt::Display for ReasonChildSafetyPrivacy { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonChildSafetyPrivacy") + } +} + +///Doxxing +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonHarassmentDoxxing; +impl std::fmt::Display for ReasonHarassmentDoxxing { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonHarassmentDoxxing") + } +} + +///Hate speech +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonHarassmentHateSpeech; +impl std::fmt::Display for ReasonHarassmentHateSpeech { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonHarassmentHateSpeech") + } +} + +///Other harassing or hateful content +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonHarassmentOther; +impl std::fmt::Display for ReasonHarassmentOther { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonHarassmentOther") + } +} + +///Targeted harassment +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonHarassmentTargeted; +impl std::fmt::Display for ReasonHarassmentTargeted { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonHarassmentTargeted") + } +} + +///Trolling +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonHarassmentTroll; +impl std::fmt::Display for ReasonHarassmentTroll { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonHarassmentTroll") + } +} + +///Fake account or bot +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonMisleadingBot; +impl std::fmt::Display for ReasonMisleadingBot { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonMisleadingBot") + } +} + +///False information about elections +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonMisleadingElections; +impl std::fmt::Display for ReasonMisleadingElections { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonMisleadingElections") + } +} + +///Impersonation +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonMisleadingImpersonation; +impl std::fmt::Display for ReasonMisleadingImpersonation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonMisleadingImpersonation") + } +} + +///Other misleading content +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonMisleadingOther; +impl std::fmt::Display for ReasonMisleadingOther { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonMisleadingOther") + } +} + +///Scam +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonMisleadingScam; +impl std::fmt::Display for ReasonMisleadingScam { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonMisleadingScam") + } +} + +///Spam +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonMisleadingSpam; +impl std::fmt::Display for ReasonMisleadingSpam { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonMisleadingSpam") + } +} + +///An issue not included in these options +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonOther; +impl std::fmt::Display for ReasonOther { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonOther") + } +} + +///Banned user returning +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonRuleBanEvasion; +impl std::fmt::Display for ReasonRuleBanEvasion { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonRuleBanEvasion") + } +} + +///Other +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonRuleOther; +impl std::fmt::Display for ReasonRuleOther { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonRuleOther") + } +} + +///Promoting or selling prohibited items or services +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonRuleProhibitedSales; +impl std::fmt::Display for ReasonRuleProhibitedSales { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonRuleProhibitedSales") + } +} + +///Hacking or system attacks +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonRuleSiteSecurity; +impl std::fmt::Display for ReasonRuleSiteSecurity { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonRuleSiteSecurity") + } +} + +///Content promoting or depicting self-harm +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSelfHarmContent; +impl std::fmt::Display for ReasonSelfHarmContent { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSelfHarmContent") + } +} + +///Eating disorders +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSelfHarmEd; +impl std::fmt::Display for ReasonSelfHarmEd { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSelfHarmED") + } +} + +///Other dangerous content +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSelfHarmOther; +impl std::fmt::Display for ReasonSelfHarmOther { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSelfHarmOther") + } +} + +///Dangerous challenges or activities +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSelfHarmStunts; +impl std::fmt::Display for ReasonSelfHarmStunts { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSelfHarmStunts") + } +} + +///Dangerous substances or drug abuse +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSelfHarmSubstances; +impl std::fmt::Display for ReasonSelfHarmSubstances { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSelfHarmSubstances") + } +} + +///Adult sexual abuse content +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSexualAbuseContent; +impl std::fmt::Display for ReasonSexualAbuseContent { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSexualAbuseContent") + } +} + +///Animal sexual abuse +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSexualAnimal; +impl std::fmt::Display for ReasonSexualAnimal { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSexualAnimal") + } +} + +///Deepfake adult content +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSexualDeepfake; +impl std::fmt::Display for ReasonSexualDeepfake { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSexualDeepfake") + } +} + +///Non-consensual intimate imagery +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSexualNcii; +impl std::fmt::Display for ReasonSexualNcii { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSexualNCII") + } +} + +///Other sexual violence content +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSexualOther; +impl std::fmt::Display for ReasonSexualOther { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSexualOther") + } +} + +///Unlabelled adult content +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonSexualUnlabeled; +impl std::fmt::Display for ReasonSexualUnlabeled { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonSexualUnlabeled") + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ReasonType<'a> { ToolsOzoneReportDefsReasonAppeal, @@ -589,4 +1183,130 @@ impl jacquard_common::IntoStatic for ReasonType<'_> { ReasonType::Other(v) => ReasonType::Other(v.into_static()), } } +} + +///Animal welfare violations +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonViolenceAnimal; +impl std::fmt::Display for ReasonViolenceAnimal { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonViolenceAnimal") + } +} + +///Extremist content. These reports will be sent only be sent to the application's Moderation Authority. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonViolenceExtremistContent; +impl std::fmt::Display for ReasonViolenceExtremistContent { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonViolenceExtremistContent") + } +} + +///Glorification of violence +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonViolenceGlorification; +impl std::fmt::Display for ReasonViolenceGlorification { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonViolenceGlorification") + } +} + +///Graphic violent content +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonViolenceGraphicContent; +impl std::fmt::Display for ReasonViolenceGraphicContent { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonViolenceGraphicContent") + } +} + +///Other violent content +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonViolenceOther; +impl std::fmt::Display for ReasonViolenceOther { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonViolenceOther") + } +} + +///Threats or incitement +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonViolenceThreats; +impl std::fmt::Display for ReasonViolenceThreats { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonViolenceThreats") + } +} + +///Human trafficking +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct ReasonViolenceTrafficking; +impl std::fmt::Display for ReasonViolenceTrafficking { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "reasonViolenceTrafficking") + } } \ No newline at end of file diff --git a/crates/jacquard-api/src/tools_ozone/team.rs b/crates/jacquard-api/src/tools_ozone/team.rs index 8d64796f2..03d675daa 100644 --- a/crates/jacquard-api/src/tools_ozone/team.rs +++ b/crates/jacquard-api/src/tools_ozone/team.rs @@ -38,4 +38,76 @@ pub struct Member<'a> { pub role: jacquard_common::CowStr<'a>, #[serde(skip_serializing_if = "std::option::Option::is_none")] pub updated_at: std::option::Option, +} + +///Admin role. Highest level of access, can perform all actions. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct RoleAdmin; +impl std::fmt::Display for RoleAdmin { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "roleAdmin") + } +} + +///Moderator role. Can perform most actions. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct RoleModerator; +impl std::fmt::Display for RoleModerator { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "roleModerator") + } +} + +///Triage role. Mostly intended for monitoring and escalating issues. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct RoleTriage; +impl std::fmt::Display for RoleTriage { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "roleTriage") + } +} + +///Verifier role. Only allowed to issue verifications. +#[derive( + serde::Serialize, + serde::Deserialize, + Debug, + Clone, + PartialEq, + Eq, + Hash, + jacquard_derive::IntoStatic +)] +pub struct RoleVerifier; +impl std::fmt::Display for RoleVerifier { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "roleVerifier") + } } \ No newline at end of file diff --git a/crates/jacquard-axum/Cargo.toml b/crates/jacquard-axum/Cargo.toml index fad99ca5b..3d149c290 100644 --- a/crates/jacquard-axum/Cargo.toml +++ b/crates/jacquard-axum/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "jacquard-axum" edition.workspace = true -version.workspace = true +version = "0.4.0" authors.workspace = true repository.workspace = true keywords.workspace = true @@ -24,8 +24,8 @@ path = "src/main.rs" axum = "0.8.6" axum-macros = "0.5.0" bytes.workspace = true -jacquard = { version = "0.3.0", path = "../jacquard" } -jacquard-common = { version = "0.3.0", path = "../jacquard-common", features = ["reqwest-client"] } +jacquard = { version = "*", path = "../jacquard" } +jacquard-common = { version = "*", path = "../jacquard-common", features = ["reqwest-client"] } miette.workspace = true serde.workspace = true serde_html_form.workspace = true diff --git a/crates/jacquard-common/Cargo.toml b/crates/jacquard-common/Cargo.toml index 5d2d04b29..ab90238dd 100644 --- a/crates/jacquard-common/Cargo.toml +++ b/crates/jacquard-common/Cargo.toml @@ -2,7 +2,7 @@ name = "jacquard-common" description = "Core AT Protocol types and utilities for Jacquard" edition.workspace = true -version.workspace = true +version = "0.4.0" authors.workspace = true repository.workspace = true keywords.workspace = true diff --git a/crates/jacquard-common/src/types/value/convert.rs b/crates/jacquard-common/src/types/value/convert.rs index f8a767a39..778e0caed 100644 --- a/crates/jacquard-common/src/types/value/convert.rs +++ b/crates/jacquard-common/src/types/value/convert.rs @@ -1,12 +1,12 @@ +use crate::IntoStatic; use crate::types::{ DataModelType, cid::Cid, string::AtprotoStr, value::{Array, Data, Object, RawData, parsing}, }; -use crate::{CowStr, IntoStatic}; use bytes::Bytes; -use core::{any::TypeId, fmt}; +use core::any::TypeId; use smol_str::SmolStr; use std::{borrow::ToOwned, boxed::Box, collections::BTreeMap, vec::Vec}; @@ -282,17 +282,20 @@ impl<'s> TryFrom> for Data<'s> { if let Some(RawData::String(type_str)) = map.get("$type") { if parsing::infer_from_type(type_str) == DataModelType::Blob { // Try to parse as blob - if let (Some(RawData::CidLink(cid)), Some(RawData::String(mime)), Some(size)) = ( - map.get("ref"), - map.get("mimeType"), - map.get("size") - ) { + if let ( + Some(RawData::CidLink(cid)), + Some(RawData::String(mime)), + Some(size), + ) = (map.get("ref"), map.get("mimeType"), map.get("size")) + { let size_val = match size { RawData::UnsignedInt(u) => *u as usize, RawData::SignedInt(i) => *i as usize, - _ => return Err(ConversionError::InvalidRawData { - message: "blob size must be integer".to_string(), - }), + _ => { + return Err(ConversionError::InvalidRawData { + message: "blob size must be integer".to_string(), + }); + } }; return Ok(Data::Blob(crate::types::blob::Blob { r#ref: cid.clone(), diff --git a/crates/jacquard-common/src/types/value/serde_impl.rs b/crates/jacquard-common/src/types/value/serde_impl.rs index fa108b843..558604e70 100644 --- a/crates/jacquard-common/src/types/value/serde_impl.rs +++ b/crates/jacquard-common/src/types/value/serde_impl.rs @@ -1135,13 +1135,10 @@ impl<'de> serde::de::MapAccess<'de> for RawObjectDeserializer<'de> { } } -// ======================================================================== -// SERIALIZER IMPLEMENTATION - Serializing to RawData -// ======================================================================== - /// Error type for RawData serialization #[derive(Debug)] pub enum RawDataSerializerError { + /// Error message Message(String), } @@ -1344,7 +1341,7 @@ impl serde::Serializer for RawDataSerializer { } } -// Sequence serializer accumulator +/// Sequence serializer accumulator pub struct RawDataSeqSerializer { items: Vec>, } @@ -1414,7 +1411,7 @@ impl serde::ser::SerializeTupleVariant for RawDataSeqSerializer { } } -// Map serializer accumulator +/// Map serializer accumulator pub struct RawDataMapSerializer { map: BTreeMap>, next_key: Option, diff --git a/crates/jacquard-common/src/xrpc.rs b/crates/jacquard-common/src/xrpc.rs index edfb9214e..da991f7fb 100644 --- a/crates/jacquard-common/src/xrpc.rs +++ b/crates/jacquard-common/src/xrpc.rs @@ -127,6 +127,24 @@ pub trait XrpcResp { type Err<'de>: Error + Deserialize<'de> + IntoStatic; } +/// XRPC server endpoint trait +/// +/// Defines the fully-qualified path and method, as well as request and response types +/// This exists primarily to work around lifetime issues for crates like Axum +/// by moving the lifetime from the trait itself into an associated type. +/// +/// It is implemented by the code generation on a marker struct, like the client-side [XrpcResp] trait. +pub trait XrpcEndpoint { + /// Fully-qualified path ('/xrpc/[nsid]') where this endpoint should live on the server + const PATH: &'static str; + /// XRPC method (query/GET or procedure/POST) + const METHOD: XrpcMethod; + /// XRPC Request data type + type Request<'de>: XrpcRequest<'de> + IntoStatic; + /// XRPC Response data type + type Response: XrpcResp; +} + /// Error type for XRPC endpoints that don't define any errors #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] pub struct GenericError<'a>(#[serde(borrow)] Data<'a>); @@ -483,13 +501,6 @@ where .map_err(|e| TransportError::InvalidRequest(e.to_string())) } -pub trait XrpcEndpoint { - const PATH: &'static str; - const METHOD: XrpcMethod; - type Request<'de>: XrpcRequest<'de> + IntoStatic; - type Response: XrpcResp; -} - /// XRPC response wrapper that owns the response buffer /// /// Allows borrowing from the buffer when parsing to avoid unnecessary allocations. diff --git a/crates/jacquard-derive/Cargo.toml b/crates/jacquard-derive/Cargo.toml index c92f5fafe..f2cfecc3a 100644 --- a/crates/jacquard-derive/Cargo.toml +++ b/crates/jacquard-derive/Cargo.toml @@ -28,4 +28,4 @@ syn.workspace = true [dev-dependencies] -jacquard-common = { version = "0.3.0", path = "../jacquard-common" } +jacquard-common = { version = "*", path = "../jacquard-common" } diff --git a/crates/jacquard-identity/Cargo.toml b/crates/jacquard-identity/Cargo.toml index b4b38c610..3e2a4e9cd 100644 --- a/crates/jacquard-identity/Cargo.toml +++ b/crates/jacquard-identity/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "jacquard-identity" edition.workspace = true -version.workspace = true +version = "0.3.1" authors.workspace = true repository.workspace = true keywords.workspace = true @@ -10,7 +10,7 @@ readme.workspace = true exclude.workspace = true homepage.workspace = true license.workspace = true -description.workspace = true +description = "ATProto identity resolution utilities for Jacquard" [features] dns = ["dep:hickory-resolver"] @@ -19,7 +19,8 @@ dns = ["dep:hickory-resolver"] async-trait.workspace = true bon.workspace = true bytes.workspace = true -jacquard-common = { version = "0.3", path = "../jacquard-common", features = ["reqwest-client"] } +jacquard-common = { version = "*", path = "../jacquard-common", features = ["reqwest-client"] } +jacquard-api = { version = "*", path = "../jacquard-api" } percent-encoding.workspace = true reqwest.workspace = true url.workspace = true @@ -30,6 +31,5 @@ serde_json.workspace = true thiserror.workspace = true miette.workspace = true http.workspace = true -jacquard-api = { version = "0.3.0", path = "../jacquard-api" } serde_html_form.workspace = true urlencoding.workspace = true diff --git a/crates/jacquard-lexicon/Cargo.toml b/crates/jacquard-lexicon/Cargo.toml index 9ab90a196..13eeeeceb 100644 --- a/crates/jacquard-lexicon/Cargo.toml +++ b/crates/jacquard-lexicon/Cargo.toml @@ -25,9 +25,9 @@ clap.workspace = true glob = "0.3" heck.workspace = true itertools.workspace = true -jacquard-api = { version = "0.3.0", path = "../jacquard-api" } -jacquard-common = { version = "0.3.0", path = "../jacquard-common" } -jacquard-identity = { version = "0.3.0", path = "../jacquard-identity" } +jacquard-api = { version = "*", path = "../jacquard-api" } +jacquard-common = { version = "*", path = "../jacquard-common" } +jacquard-identity = { version = "*", path = "../jacquard-identity" } kdl = "6" miette = { workspace = true, features = ["fancy"] } prettyplease.workspace = true diff --git a/crates/jacquard-lexicon/src/bin/lex_fetch.rs b/crates/jacquard-lexicon/src/bin/lex_fetch.rs index cd607d022..c49411911 100644 --- a/crates/jacquard-lexicon/src/bin/lex_fetch.rs +++ b/crates/jacquard-lexicon/src/bin/lex_fetch.rs @@ -78,9 +78,42 @@ async fn main() -> Result<()> { codegen.write_to_disk(&config.output.codegen_dir)?; println!("Generated code to {:?}", config.output.codegen_dir); + + // Update Cargo.toml features if cargo_toml_path is specified + if let Some(cargo_toml_path) = &config.output.cargo_toml_path { + if args.verbose { + println!("Updating Cargo.toml features..."); + } + + update_cargo_features(&codegen, cargo_toml_path, &config.output.codegen_dir)?; + println!("Updated features in {:?}", cargo_toml_path); + } } else { println!("Lexicons written to {:?}", config.output.lexicons_dir); } Ok(()) } + +fn update_cargo_features(codegen: &CodeGenerator, cargo_toml_path: &PathBuf, codegen_dir: &PathBuf) -> Result<()> { + // Read existing Cargo.toml + let content = std::fs::read_to_string(cargo_toml_path).into_diagnostic()?; + + // Find the "# --- generated ---" marker + const MARKER: &str = "# --- generated ---"; + + let (before, _after) = content.split_once(MARKER) + .ok_or_else(|| miette::miette!("Cargo.toml missing '{}' marker", MARKER))?; + + // Generate new features, passing lib.rs path to detect existing modules + let lib_rs_path = codegen_dir.join("lib.rs"); + let features = codegen.generate_cargo_features(Some(&lib_rs_path)); + + // Reconstruct file + let new_content = format!("{}{}\n{}", before, MARKER, features); + + // Write back + std::fs::write(cargo_toml_path, new_content).into_diagnostic()?; + + Ok(()) +} diff --git a/crates/jacquard-lexicon/src/codegen.rs b/crates/jacquard-lexicon/src/codegen.rs index 2a59bb71a..051ce31cb 100644 --- a/crates/jacquard-lexicon/src/codegen.rs +++ b/crates/jacquard-lexicon/src/codegen.rs @@ -78,6 +78,9 @@ fn make_ident(s: &str) -> syn::Ident { pub struct CodeGenerator<'c> { corpus: &'c LexiconCorpus, root_module: String, + /// Track namespace dependencies (namespace -> set of namespaces it depends on) + namespace_deps: + std::cell::RefCell>>, } impl<'c> CodeGenerator<'c> { @@ -86,6 +89,7 @@ impl<'c> CodeGenerator<'c> { Self { corpus, root_module: root_module.into(), + namespace_deps: std::cell::RefCell::new(std::collections::HashMap::new()), } } @@ -101,11 +105,26 @@ impl<'c> CodeGenerator<'c> { LexUserType::Object(obj) => self.generate_object(nsid, def_name, obj), LexUserType::XrpcQuery(query) => self.generate_query(nsid, def_name, query), LexUserType::XrpcProcedure(proc) => self.generate_procedure(nsid, def_name, proc), - LexUserType::Token(_) => { - // Token types are marker types used in knownValues enums. - // We don't generate anything for them - the knownValues enum - // is the actual type that gets used. - Ok(quote! {}) + LexUserType::Token(token) => { + // Token types are marker structs that can be used as union refs + let type_name = self.def_to_type_name(nsid, def_name); + let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site()); + let doc = self.generate_doc_comment(token.description.as_ref()); + + // Token name for Display impl (just the def name, not the full ref) + let token_name = def_name; + + Ok(quote! { + #doc + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, Hash, jacquard_derive::IntoStatic)] + pub struct #ident; + + impl std::fmt::Display for #ident { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, #token_name) + } + } + }) } LexUserType::String(s) if s.known_values.is_some() => { self.generate_known_values_enum(nsid, def_name, s) @@ -220,7 +239,7 @@ impl<'c> CodeGenerator<'c> { // Clone refs to avoid lifetime issues let refs: Vec<_> = union.refs.iter().cloned().collect(); let union_def = - self.generate_union(&union_name, &refs, None, union.closed)?; + self.generate_union(nsid, &union_name, &refs, None, union.closed)?; unions.push(union_def); } LexObjectProperty::Object(nested_obj) => { @@ -287,7 +306,8 @@ impl<'c> CodeGenerator<'c> { LexObjectProperty::Union(union) => { let union_name = format!("{}Record{}", type_name, field_name.to_pascal_case()); let refs: Vec<_> = union.refs.iter().cloned().collect(); - let union_def = self.generate_union(&union_name, &refs, None, union.closed)?; + let union_def = + self.generate_union(nsid, &union_name, &refs, None, union.closed)?; unions.push(union_def); } LexObjectProperty::Object(nested_obj) => { @@ -742,7 +762,7 @@ impl<'c> CodeGenerator<'c> { } if let Some(body) = &query.output { - let output_struct = self.generate_output_struct(&type_base, body)?; + let output_struct = self.generate_output_struct(nsid, &type_base, body)?; output.push(output_struct); } @@ -805,12 +825,12 @@ impl<'c> CodeGenerator<'c> { } if let Some(body) = &proc.input { - let input_struct = self.generate_input_struct(&type_base, body)?; + let input_struct = self.generate_input_struct(nsid, &type_base, body)?; output.push(input_struct); } if let Some(body) = &proc.output { - let output_struct = self.generate_output_struct(&type_base, body)?; + let output_struct = self.generate_output_struct(nsid, &type_base, body)?; output.push(output_struct); } @@ -870,7 +890,7 @@ impl<'c> CodeGenerator<'c> { if let Some(message) = &sub.message { if let Some(schema) = &message.schema { - let message_type = self.generate_subscription_message(&type_base, schema)?; + let message_type = self.generate_subscription_message(nsid, &type_base, schema)?; output.push(message_type); } } @@ -887,6 +907,7 @@ impl<'c> CodeGenerator<'c> { fn generate_subscription_message( &self, + nsid: &str, type_base: &str, schema: &LexXrpcSubscriptionMessageSchema<'static>, ) -> Result { @@ -992,7 +1013,7 @@ impl<'c> CodeGenerator<'c> { format!("{}Record{}", struct_name, field_name.to_pascal_case()); let refs: Vec<_> = union.refs.iter().cloned().collect(); let union_def = - self.generate_union(&union_name, &refs, None, union.closed)?; + self.generate_union(nsid, &union_name, &refs, None, union.closed)?; unions.push(union_def); } } @@ -1545,6 +1566,7 @@ impl<'c> CodeGenerator<'c> { /// Generate input struct from XRPC body fn generate_input_struct( &self, + nsid: &str, type_base: &str, body: &LexXrpcBody<'static>, ) -> Result { @@ -1604,7 +1626,8 @@ impl<'c> CodeGenerator<'c> { if let LexObjectProperty::Union(union) = field_type { let union_name = format!("{}Record{}", type_base, field_name.to_pascal_case()); let refs: Vec<_> = union.refs.iter().cloned().collect(); - let union_def = self.generate_union(&union_name, &refs, None, union.closed)?; + let union_def = + self.generate_union(nsid, &union_name, &refs, None, union.closed)?; unions.push(union_def); } } @@ -1648,6 +1671,7 @@ impl<'c> CodeGenerator<'c> { /// Generate output struct from XRPC body fn generate_output_struct( &self, + nsid: &str, type_base: &str, body: &LexXrpcBody<'static>, ) -> Result { @@ -1682,7 +1706,8 @@ impl<'c> CodeGenerator<'c> { let union_name = format!("{}Record{}", struct_name, field_name.to_pascal_case()); let refs: Vec<_> = union.refs.iter().cloned().collect(); - let union_def = self.generate_union(&union_name, &refs, None, union.closed)?; + let union_def = + self.generate_union(nsid, &union_name, &refs, None, union.closed)?; unions.push(union_def); } } @@ -2245,6 +2270,7 @@ impl<'c> CodeGenerator<'c> { /// Generate a union enum pub fn generate_union( &self, + current_nsid: &str, union_name: &str, refs: &[jacquard_common::CowStr<'static>], description: Option<&str>, @@ -2252,7 +2278,24 @@ impl<'c> CodeGenerator<'c> { ) -> Result { let enum_ident = syn::Ident::new(union_name, proc_macro2::Span::call_site()); - let mut variants = Vec::new(); + // Extract namespace prefix from current NSID (first two segments: "sh.weaver" from "sh.weaver.embed.recordWithMedia") + let parts: Vec<_> = current_nsid.splitn(3, '.').collect(); + let current_namespace = if parts.len() >= 2 { + format!("{}.{}", parts[0], parts[1]) + } else { + current_nsid.to_string() + }; + + // First pass: collect all variant names and detect collisions + #[derive(Debug)] + struct VariantInfo<'a> { + ref_str: &'a str, + ref_nsid: &'a str, + simple_name: String, + is_current_namespace: bool, + } + + let mut variant_infos = Vec::new(); for ref_str in refs { // Parse ref to get NSID and def name let (ref_nsid, ref_def) = if let Some((nsid, fragment)) = ref_str.split_once('#') { @@ -2266,23 +2309,73 @@ impl<'c> CodeGenerator<'c> { continue; } - // Generate variant name from def name (or last NSID segment if main) - // For non-main refs, include the last NSID segment to avoid collisions - // e.g. app.bsky.embed.images#view -> ImagesView - // app.bsky.embed.video#view -> VideoView - let variant_name = if ref_def == "main" { + // Check if ref is in current namespace + let is_current_namespace = ref_nsid.starts_with(¤t_namespace); + + // Generate simple variant name (without namespace prefix) + let simple_name = if ref_def == "main" { ref_nsid.split('.').last().unwrap().to_pascal_case() } else { let last_segment = ref_nsid.split('.').last().unwrap().to_pascal_case(); format!("{}{}", last_segment, ref_def.to_pascal_case()) }; + + variant_infos.push(VariantInfo { + ref_str: ref_str.as_ref(), + ref_nsid, + simple_name, + is_current_namespace, + }); + } + + // Second pass: detect collisions and disambiguate + use std::collections::HashMap; + let mut name_counts: HashMap = HashMap::new(); + for info in &variant_infos { + *name_counts.entry(info.simple_name.clone()).or_insert(0) += 1; + } + + let mut variants = Vec::new(); + for info in variant_infos { + let has_collision = name_counts.get(&info.simple_name).copied().unwrap_or(0) > 1; + + // Track namespace dependency for foreign refs + if !info.is_current_namespace { + let parts: Vec<_> = info.ref_nsid.splitn(3, '.').collect(); + let foreign_namespace = if parts.len() >= 2 { + format!("{}.{}", parts[0], parts[1]) + } else { + info.ref_nsid.to_string() + }; + self.namespace_deps + .borrow_mut() + .entry(current_namespace.clone()) + .or_default() + .insert(foreign_namespace); + } + + // Disambiguate: add second NSID segment prefix only to foreign refs when there's a collision + let variant_name = if has_collision && !info.is_current_namespace { + // Get second segment (namespace identifier: "bsky" from "app.bsky.embed.images") + let segments: Vec<&str> = info.ref_nsid.split('.').collect(); + let prefix = if segments.len() >= 2 { + segments[1].to_pascal_case() + } else { + // Fallback: use first segment if only one exists + segments[0].to_pascal_case() + }; + format!("{}{}", prefix, info.simple_name) + } else { + info.simple_name.clone() + }; + let variant_ident = syn::Ident::new(&variant_name, proc_macro2::Span::call_site()); // Get the Rust type for this ref - let rust_type = self.ref_to_rust_type(ref_str.as_ref())?; + let rust_type = self.ref_to_rust_type(info.ref_str)?; // Add serde rename for the full NSID - let ref_str_literal = ref_str.as_ref(); + let ref_str_literal = info.ref_str; variants.push(quote! { #[serde(rename = #ref_str_literal)] #variant_ident(Box<#rust_type>) @@ -2481,6 +2574,116 @@ impl<'c> CodeGenerator<'c> { } } } + + /// Get namespace dependencies collected during code generation + pub fn get_namespace_dependencies( + &self, + ) -> std::collections::HashMap> { + self.namespace_deps.borrow().clone() + } + + /// Generate Cargo.toml features section from namespace dependencies + pub fn generate_cargo_features(&self, lib_rs_path: Option<&std::path::Path>) -> String { + use std::fmt::Write; + + let deps = self.namespace_deps.borrow(); + let mut all_namespaces: std::collections::HashSet = + std::collections::HashSet::new(); + + // Collect all namespaces from the corpus (first two segments of each NSID) + for (nsid, _doc) in self.corpus.iter() { + let parts: Vec<_> = nsid.as_str().splitn(3, '.').collect(); + let namespace = if parts.len() >= 2 { + format!("{}.{}", parts[0], parts[1]) + } else { + nsid.to_string() + }; + all_namespaces.insert(namespace); + } + + // Also collect existing feature names from lib.rs + let mut existing_features = std::collections::HashSet::new(); + if let Some(lib_rs) = lib_rs_path { + if let Ok(content) = std::fs::read_to_string(lib_rs) { + for line in content.lines() { + if let Some(feature) = line.trim() + .strip_prefix("#[cfg(feature = \"") + .and_then(|s| s.strip_suffix("\")]")) + { + existing_features.insert(feature.to_string()); + } + } + } + } + + let mut output = String::new(); + writeln!(&mut output, "# Generated namespace features").unwrap(); + writeln!(&mut output, "# Each namespace feature automatically enables its dependencies").unwrap(); + + // Convert namespace to feature name (matching module path sanitization) + let to_feature_name = |ns: &str| { + ns.split('.') + .map(|segment| { + // Apply same sanitization as module names + let mut result = segment.replace('-', "_"); + // Prefix with underscore if starts with digit + if result.chars().next().map_or(false, |c| c.is_ascii_digit()) { + result.insert(0, '_'); + } + result + }) + .collect::>() + .join("_") + }; + + // Collect all feature names (from corpus + existing lib.rs) + let mut all_feature_names = std::collections::HashSet::new(); + for ns in &all_namespaces { + all_feature_names.insert(to_feature_name(ns)); + } + all_feature_names.extend(existing_features); + + // Sort for consistent output + let mut feature_names: Vec<_> = all_feature_names.iter().collect(); + feature_names.sort(); + + // Map namespace to feature name for dependency lookup + let mut ns_to_feature: std::collections::HashMap<&str, String> = std::collections::HashMap::new(); + for ns in &all_namespaces { + ns_to_feature.insert(ns.as_str(), to_feature_name(ns)); + } + + for feature_name in feature_names { + // Find corresponding namespace for this feature (if any) to look up deps + let feature_deps: Vec = all_namespaces + .iter() + .find(|ns| to_feature_name(ns) == *feature_name) + .and_then(|ns| deps.get(ns.as_str())) + .map(|ns_deps| { + let mut dep_features: Vec<_> = ns_deps + .iter() + .map(|d| format!("\"{}\"", to_feature_name(d))) + .collect(); + dep_features.sort(); + dep_features + }) + .unwrap_or_default(); + + if !feature_deps.is_empty() { + writeln!( + &mut output, + "{} = [{}]", + feature_name, + feature_deps.join(", ") + ) + .unwrap(); + } else { + writeln!(&mut output, "{} = []", feature_name).unwrap(); + } + } + + output + } } /// Enum variant kind for IntoStatic generation @@ -2534,7 +2737,13 @@ mod tests { ]; let tokens = codegen - .generate_union("RecordEmbed", &refs, Some("Post embed union"), None) + .generate_union( + "app.bsky.feed.post", + "RecordEmbed", + &refs, + Some("Post embed union"), + None, + ) .expect("generate union"); let file: syn::File = syn::parse2(tokens).expect("parse tokens"); diff --git a/crates/jacquard-lexicon/src/fetch/config.rs b/crates/jacquard-lexicon/src/fetch/config.rs index 554ab4cfc..afb17ff24 100644 --- a/crates/jacquard-lexicon/src/fetch/config.rs +++ b/crates/jacquard-lexicon/src/fetch/config.rs @@ -16,6 +16,7 @@ pub struct OutputConfig { pub lexicons_dir: PathBuf, pub codegen_dir: PathBuf, pub root_module: Option, + pub cargo_toml_path: Option, } impl Config { @@ -58,6 +59,7 @@ fn parse_output(node: &kdl::KdlNode) -> Result { let mut lexicons_dir: Option = None; let mut codegen_dir: Option = None; let mut root_module: Option = None; + let mut cargo_toml_path: Option = None; for child in children.nodes() { match child.name().value() { @@ -85,6 +87,14 @@ fn parse_output(node: &kdl::KdlNode) -> Result { .ok_or_else(|| miette!("root-module expects a string value"))?; root_module = Some(val.to_string()); } + "cargo-toml" => { + let val = child + .entries() + .get(0) + .and_then(|e| e.value().as_string()) + .ok_or_else(|| miette!("cargo-toml expects a string value"))?; + cargo_toml_path = Some(PathBuf::from(val)); + } other => { return Err(miette!("Unknown output field: {}", other)); } @@ -95,6 +105,7 @@ fn parse_output(node: &kdl::KdlNode) -> Result { lexicons_dir: lexicons_dir.ok_or_else(|| miette!("Missing lexicons directory"))?, codegen_dir: codegen_dir.ok_or_else(|| miette!("Missing codegen directory"))?, root_module, + cargo_toml_path, }) } diff --git a/crates/jacquard-oauth/Cargo.toml b/crates/jacquard-oauth/Cargo.toml index 85387bcab..bf975f60c 100644 --- a/crates/jacquard-oauth/Cargo.toml +++ b/crates/jacquard-oauth/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "jacquard-oauth" -version = "0.3.0" -edition = "2024" +version = "0.3.1" +edition.workspace = true description = "AT Protocol OAuth 2.1 core types and helpers for Jacquard" authors.workspace = true repository.workspace = true @@ -12,8 +12,8 @@ exclude.workspace = true license.workspace = true [dependencies] -jacquard-common = { version = "0.3.0", path = "../jacquard-common", features = ["reqwest-client"] } -jacquard-identity = { version = "0.3.0", path = "../jacquard-identity" } +jacquard-common = { version = "*", path = "../jacquard-common", features = ["reqwest-client"] } +jacquard-identity = { version = "*", path = "../jacquard-identity" } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } url = { workspace = true } diff --git a/crates/jacquard/Cargo.toml b/crates/jacquard/Cargo.toml index e05823ff6..6a671010f 100644 --- a/crates/jacquard/Cargo.toml +++ b/crates/jacquard/Cargo.toml @@ -2,7 +2,7 @@ name = "jacquard" description.workspace = true edition.workspace = true -version = "0.3.0" +version.workspace = true authors.workspace = true repository.workspace = true keywords.workspace = true @@ -12,10 +12,12 @@ exclude.workspace = true license.workspace = true [features] -default = ["api_all", "dns", "fancy", "loopback"] +default = ["api_full", "dns", "fancy", "loopback"] derive = ["dep:jacquard-derive"] -api = ["jacquard-api/com_atproto"] -api_all = ["api", "jacquard-api/app_bsky", "jacquard-api/chat_bsky", "jacquard-api/tools_ozone"] +api = ["jacquard-api/com_atproto", "jacquard-api/com_bad_example" ] +api_bluesky = ["api", "jacquard-api/bluesky" ] +api_full = ["api", "jacquard-api/bluesky", "jacquard-api/other", "jacquard-api/lexicon_community"] +api_all = ["api_full", "jacquard-api/ufos"] dns = ["jacquard-identity/dns"] fancy = ["miette/fancy"] # Propagate loopback to oauth (server + browser helper) @@ -31,11 +33,11 @@ path = "src/main.rs" [dependencies] -jacquard-api = { version = "0.3.0", path = "../jacquard-api" } -jacquard-common = { version = "0.3.0", path = "../jacquard-common", features = ["reqwest-client"] } -jacquard-oauth = { version = "0.3.0", path = "../jacquard-oauth" } -jacquard-derive = { version = "0.3.0", path = "../jacquard-derive", optional = true } -jacquard-identity = { version = "0.3.0", path = "../jacquard-identity" } +jacquard-api = { version = "*", path = "../jacquard-api" } +jacquard-common = { version = "*", path = "../jacquard-common", features = ["reqwest-client"] } +jacquard-oauth = { version = "*", path = "../jacquard-oauth" } +jacquard-derive = { version = "*", path = "../jacquard-derive", optional = true } +jacquard-identity = { version = "*", path = "../jacquard-identity" } bon.workspace = true async-trait.workspace = true @@ -57,3 +59,6 @@ urlencoding.workspace = true jose-jwk = { workspace = true, features = ["p256"] } p256 = { workspace = true, features = ["ecdsa"] } rand_core.workspace = true + +[package.metadata.docs.rs] +features = [ "api_all", "derive", "dns", "fancy", "loopback" ] diff --git a/lexicons.kdl b/lexicons.kdl index aa2669d08..a5a7b34e0 100644 --- a/lexicons.kdl +++ b/lexicons.kdl @@ -1,6 +1,7 @@ output { lexicons "crates/jacquard-api/lexicons" codegen "crates/jacquard-api/src" + cargo-toml "crates/jacquard-api/Cargo.toml" } source "leaflet" type="git" priority=100 { @@ -59,7 +60,7 @@ source "whitewind" type="git" priority=50 { pattern "**/*.json" } -source "lexicon-community" type="git" priority=50 { +source "lexicon-community" type="git" priority=60 { repo "https://github.com/lexicon-community/lexicon" pattern "**/*.json" } diff --git a/nix/modules/devshell.nix b/nix/modules/devshell.nix index 7111d6181..d62c1a12f 100644 --- a/nix/modules/devshell.nix +++ b/nix/modules/devshell.nix @@ -18,6 +18,7 @@ bacon rust-analyzer cargo-release + cargo-semver-checks ]; }; };