1#[allow(unused_imports)]
9use alloc::collections::BTreeMap;
10
11#[allow(unused_imports)]
12use core::marker::PhantomData;
13use jacquard_common::CowStr;
14
15#[allow(unused_imports)]
16use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation;
17use jacquard_common::types::collection::{Collection, RecordError};
18use jacquard_common::types::string::{AtUri, Cid, Datetime};
19use jacquard_common::types::uri::{RecordUri, UriError};
20use jacquard_common::xrpc::XrpcResp;
21use jacquard_derive::{IntoStatic, lexicon, open_union};
22use jacquard_lexicon::lexicon::LexiconDoc;
23use jacquard_lexicon::schema::LexiconSchema;
24
25#[allow(unused_imports)]
26use jacquard_lexicon::validation::{ConstraintError, ValidationPath};
27use serde::{Serialize, Deserialize};
28use crate::app_bsky::feed::threadgate;
29#[lexicon]
32#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)]
33#[serde(rename_all = "camelCase")]
34pub struct FollowerRule<'a> {}
35#[lexicon]
38#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)]
39#[serde(rename_all = "camelCase")]
40pub struct FollowingRule<'a> {}
41#[lexicon]
44#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
45#[serde(rename_all = "camelCase")]
46pub struct ListRule<'a> {
47 #[serde(borrow)]
48 pub list: AtUri<'a>,
49}
50
51#[lexicon]
54#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
55#[serde(rename_all = "camelCase", rename = "app.bsky.feed.threadgate", tag = "$type")]
56pub struct Threadgate<'a> {
57 #[serde(skip_serializing_if = "Option::is_none")]
59 #[serde(borrow)]
60 pub allow: Option<Vec<ThreadgateAllowItem<'a>>>,
61 pub created_at: Datetime,
62 #[serde(skip_serializing_if = "Option::is_none")]
64 #[serde(borrow)]
65 pub hidden_replies: Option<Vec<AtUri<'a>>>,
66 #[serde(borrow)]
68 pub post: AtUri<'a>,
69}
70
71
72#[open_union]
73#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
74#[serde(tag = "$type", bound(deserialize = "'de: 'a"))]
75pub enum ThreadgateAllowItem<'a> {
76 #[serde(rename = "app.bsky.feed.threadgate#mentionRule")]
77 MentionRule(Box<threadgate::MentionRule<'a>>),
78 #[serde(rename = "app.bsky.feed.threadgate#followerRule")]
79 FollowerRule(Box<threadgate::FollowerRule<'a>>),
80 #[serde(rename = "app.bsky.feed.threadgate#followingRule")]
81 FollowingRule(Box<threadgate::FollowingRule<'a>>),
82 #[serde(rename = "app.bsky.feed.threadgate#listRule")]
83 ListRule(Box<threadgate::ListRule<'a>>),
84}
85
86#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
89#[serde(rename_all = "camelCase")]
90pub struct ThreadgateGetRecordOutput<'a> {
91 #[serde(skip_serializing_if = "Option::is_none")]
92 #[serde(borrow)]
93 pub cid: Option<Cid<'a>>,
94 #[serde(borrow)]
95 pub uri: AtUri<'a>,
96 #[serde(borrow)]
97 pub value: Threadgate<'a>,
98}
99
100#[lexicon]
103#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)]
104#[serde(rename_all = "camelCase")]
105pub struct MentionRule<'a> {}
106impl<'a> Threadgate<'a> {
107 pub fn uri(
108 uri: impl Into<CowStr<'a>>,
109 ) -> Result<RecordUri<'a, ThreadgateRecord>, UriError> {
110 RecordUri::try_from_uri(AtUri::new_cow(uri.into())?)
111 }
112}
113
114impl<'a> LexiconSchema for FollowerRule<'a> {
115 fn nsid() -> &'static str {
116 "app.bsky.feed.threadgate"
117 }
118 fn def_name() -> &'static str {
119 "followerRule"
120 }
121 fn lexicon_doc() -> LexiconDoc<'static> {
122 lexicon_doc_app_bsky_feed_threadgate()
123 }
124 fn validate(&self) -> Result<(), ConstraintError> {
125 Ok(())
126 }
127}
128
129impl<'a> LexiconSchema for FollowingRule<'a> {
130 fn nsid() -> &'static str {
131 "app.bsky.feed.threadgate"
132 }
133 fn def_name() -> &'static str {
134 "followingRule"
135 }
136 fn lexicon_doc() -> LexiconDoc<'static> {
137 lexicon_doc_app_bsky_feed_threadgate()
138 }
139 fn validate(&self) -> Result<(), ConstraintError> {
140 Ok(())
141 }
142}
143
144impl<'a> LexiconSchema for ListRule<'a> {
145 fn nsid() -> &'static str {
146 "app.bsky.feed.threadgate"
147 }
148 fn def_name() -> &'static str {
149 "listRule"
150 }
151 fn lexicon_doc() -> LexiconDoc<'static> {
152 lexicon_doc_app_bsky_feed_threadgate()
153 }
154 fn validate(&self) -> Result<(), ConstraintError> {
155 Ok(())
156 }
157}
158
159#[derive(Debug, Serialize, Deserialize)]
162pub struct ThreadgateRecord;
163impl XrpcResp for ThreadgateRecord {
164 const NSID: &'static str = "app.bsky.feed.threadgate";
165 const ENCODING: &'static str = "application/json";
166 type Output<'de> = ThreadgateGetRecordOutput<'de>;
167 type Err<'de> = RecordError<'de>;
168}
169
170impl From<ThreadgateGetRecordOutput<'_>> for Threadgate<'_> {
171 fn from(output: ThreadgateGetRecordOutput<'_>) -> Self {
172 use jacquard_common::IntoStatic;
173 output.value.into_static()
174 }
175}
176
177impl Collection for Threadgate<'_> {
178 const NSID: &'static str = "app.bsky.feed.threadgate";
179 type Record = ThreadgateRecord;
180}
181
182impl Collection for ThreadgateRecord {
183 const NSID: &'static str = "app.bsky.feed.threadgate";
184 type Record = ThreadgateRecord;
185}
186
187impl<'a> LexiconSchema for Threadgate<'a> {
188 fn nsid() -> &'static str {
189 "app.bsky.feed.threadgate"
190 }
191 fn def_name() -> &'static str {
192 "main"
193 }
194 fn lexicon_doc() -> LexiconDoc<'static> {
195 lexicon_doc_app_bsky_feed_threadgate()
196 }
197 fn validate(&self) -> Result<(), ConstraintError> {
198 if let Some(ref value) = self.allow {
199 #[allow(unused_comparisons)]
200 if value.len() > 5usize {
201 return Err(ConstraintError::MaxLength {
202 path: ValidationPath::from_field("allow"),
203 max: 5usize,
204 actual: value.len(),
205 });
206 }
207 }
208 if let Some(ref value) = self.hidden_replies {
209 #[allow(unused_comparisons)]
210 if value.len() > 300usize {
211 return Err(ConstraintError::MaxLength {
212 path: ValidationPath::from_field("hidden_replies"),
213 max: 300usize,
214 actual: value.len(),
215 });
216 }
217 }
218 Ok(())
219 }
220}
221
222impl<'a> LexiconSchema for MentionRule<'a> {
223 fn nsid() -> &'static str {
224 "app.bsky.feed.threadgate"
225 }
226 fn def_name() -> &'static str {
227 "mentionRule"
228 }
229 fn lexicon_doc() -> LexiconDoc<'static> {
230 lexicon_doc_app_bsky_feed_threadgate()
231 }
232 fn validate(&self) -> Result<(), ConstraintError> {
233 Ok(())
234 }
235}
236
237fn lexicon_doc_app_bsky_feed_threadgate() -> LexiconDoc<'static> {
238 #[allow(unused_imports)]
239 use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType};
240 use jacquard_lexicon::lexicon::*;
241 use alloc::collections::BTreeMap;
242 LexiconDoc {
243 lexicon: Lexicon::Lexicon1,
244 id: CowStr::new_static("app.bsky.feed.threadgate"),
245 defs: {
246 let mut map = BTreeMap::new();
247 map.insert(
248 SmolStr::new_static("followerRule"),
249 LexUserType::Object(LexObject {
250 description: Some(
251 CowStr::new_static("Allow replies from actors who follow you."),
252 ),
253 properties: {
254 #[allow(unused_mut)]
255 let mut map = BTreeMap::new();
256 map
257 },
258 ..Default::default()
259 }),
260 );
261 map.insert(
262 SmolStr::new_static("followingRule"),
263 LexUserType::Object(LexObject {
264 description: Some(
265 CowStr::new_static("Allow replies from actors you follow."),
266 ),
267 properties: {
268 #[allow(unused_mut)]
269 let mut map = BTreeMap::new();
270 map
271 },
272 ..Default::default()
273 }),
274 );
275 map.insert(
276 SmolStr::new_static("listRule"),
277 LexUserType::Object(LexObject {
278 description: Some(
279 CowStr::new_static("Allow replies from actors on a list."),
280 ),
281 required: Some(vec![SmolStr::new_static("list")]),
282 properties: {
283 #[allow(unused_mut)]
284 let mut map = BTreeMap::new();
285 map.insert(
286 SmolStr::new_static("list"),
287 LexObjectProperty::String(LexString {
288 format: Some(LexStringFormat::AtUri),
289 ..Default::default()
290 }),
291 );
292 map
293 },
294 ..Default::default()
295 }),
296 );
297 map.insert(
298 SmolStr::new_static("main"),
299 LexUserType::Record(LexRecord {
300 description: Some(
301 CowStr::new_static(
302 "Record defining interaction gating rules for a thread (aka, reply controls). The record key (rkey) of the threadgate record must match the record key of the thread's root post, and that record must be in the same repository.",
303 ),
304 ),
305 key: Some(CowStr::new_static("tid")),
306 record: LexRecordRecord::Object(LexObject {
307 required: Some(
308 vec![
309 SmolStr::new_static("post"),
310 SmolStr::new_static("createdAt")
311 ],
312 ),
313 properties: {
314 #[allow(unused_mut)]
315 let mut map = BTreeMap::new();
316 map.insert(
317 SmolStr::new_static("allow"),
318 LexObjectProperty::Array(LexArray {
319 description: Some(
320 CowStr::new_static(
321 "List of rules defining who can reply to this post. If value is an empty array, no one can reply. If value is undefined, anyone can reply.",
322 ),
323 ),
324 items: LexArrayItem::Union(LexRefUnion {
325 refs: vec![
326 CowStr::new_static("#mentionRule"),
327 CowStr::new_static("#followerRule"),
328 CowStr::new_static("#followingRule"),
329 CowStr::new_static("#listRule")
330 ],
331 ..Default::default()
332 }),
333 max_length: Some(5usize),
334 ..Default::default()
335 }),
336 );
337 map.insert(
338 SmolStr::new_static("createdAt"),
339 LexObjectProperty::String(LexString {
340 format: Some(LexStringFormat::Datetime),
341 ..Default::default()
342 }),
343 );
344 map.insert(
345 SmolStr::new_static("hiddenReplies"),
346 LexObjectProperty::Array(LexArray {
347 description: Some(
348 CowStr::new_static("List of hidden reply URIs."),
349 ),
350 items: LexArrayItem::String(LexString {
351 format: Some(LexStringFormat::AtUri),
352 ..Default::default()
353 }),
354 max_length: Some(300usize),
355 ..Default::default()
356 }),
357 );
358 map.insert(
359 SmolStr::new_static("post"),
360 LexObjectProperty::String(LexString {
361 description: Some(
362 CowStr::new_static("Reference (AT-URI) to the post record."),
363 ),
364 format: Some(LexStringFormat::AtUri),
365 ..Default::default()
366 }),
367 );
368 map
369 },
370 ..Default::default()
371 }),
372 ..Default::default()
373 }),
374 );
375 map.insert(
376 SmolStr::new_static("mentionRule"),
377 LexUserType::Object(LexObject {
378 description: Some(
379 CowStr::new_static(
380 "Allow replies from actors mentioned in your post.",
381 ),
382 ),
383 properties: {
384 #[allow(unused_mut)]
385 let mut map = BTreeMap::new();
386 map
387 },
388 ..Default::default()
389 }),
390 );
391 map
392 },
393 ..Default::default()
394 }
395}
396
397pub mod list_rule_state {
398
399 pub use crate::builder_types::{Set, Unset, IsSet, IsUnset};
400 #[allow(unused)]
401 use ::core::marker::PhantomData;
402 mod sealed {
403 pub trait Sealed {}
404 }
405 pub trait State: sealed::Sealed {
407 type List;
408 }
409 pub struct Empty(());
411 impl sealed::Sealed for Empty {}
412 impl State for Empty {
413 type List = Unset;
414 }
415 pub struct SetList<S: State = Empty>(PhantomData<fn() -> S>);
417 impl<S: State> sealed::Sealed for SetList<S> {}
418 impl<S: State> State for SetList<S> {
419 type List = Set<members::list>;
420 }
421 #[allow(non_camel_case_types)]
423 pub mod members {
424 pub struct list(());
426 }
427}
428
429pub struct ListRuleBuilder<'a, S: list_rule_state::State> {
431 _state: PhantomData<fn() -> S>,
432 _fields: (Option<AtUri<'a>>,),
433 _lifetime: PhantomData<&'a ()>,
434}
435
436impl<'a> ListRule<'a> {
437 pub fn new() -> ListRuleBuilder<'a, list_rule_state::Empty> {
439 ListRuleBuilder::new()
440 }
441}
442
443impl<'a> ListRuleBuilder<'a, list_rule_state::Empty> {
444 pub fn new() -> Self {
446 ListRuleBuilder {
447 _state: PhantomData,
448 _fields: (None,),
449 _lifetime: PhantomData,
450 }
451 }
452}
453
454impl<'a, S> ListRuleBuilder<'a, S>
455where
456 S: list_rule_state::State,
457 S::List: list_rule_state::IsUnset,
458{
459 pub fn list(
461 mut self,
462 value: impl Into<AtUri<'a>>,
463 ) -> ListRuleBuilder<'a, list_rule_state::SetList<S>> {
464 self._fields.0 = Option::Some(value.into());
465 ListRuleBuilder {
466 _state: PhantomData,
467 _fields: self._fields,
468 _lifetime: PhantomData,
469 }
470 }
471}
472
473impl<'a, S> ListRuleBuilder<'a, S>
474where
475 S: list_rule_state::State,
476 S::List: list_rule_state::IsSet,
477{
478 pub fn build(self) -> ListRule<'a> {
480 ListRule {
481 list: self._fields.0.unwrap(),
482 extra_data: Default::default(),
483 }
484 }
485 pub fn build_with_data(
487 self,
488 extra_data: BTreeMap<
489 jacquard_common::deps::smol_str::SmolStr,
490 jacquard_common::types::value::Data<'a>,
491 >,
492 ) -> ListRule<'a> {
493 ListRule {
494 list: self._fields.0.unwrap(),
495 extra_data: Some(extra_data),
496 }
497 }
498}
499
500pub mod threadgate_state {
501
502 pub use crate::builder_types::{Set, Unset, IsSet, IsUnset};
503 #[allow(unused)]
504 use ::core::marker::PhantomData;
505 mod sealed {
506 pub trait Sealed {}
507 }
508 pub trait State: sealed::Sealed {
510 type CreatedAt;
511 type Post;
512 }
513 pub struct Empty(());
515 impl sealed::Sealed for Empty {}
516 impl State for Empty {
517 type CreatedAt = Unset;
518 type Post = Unset;
519 }
520 pub struct SetCreatedAt<S: State = Empty>(PhantomData<fn() -> S>);
522 impl<S: State> sealed::Sealed for SetCreatedAt<S> {}
523 impl<S: State> State for SetCreatedAt<S> {
524 type CreatedAt = Set<members::created_at>;
525 type Post = S::Post;
526 }
527 pub struct SetPost<S: State = Empty>(PhantomData<fn() -> S>);
529 impl<S: State> sealed::Sealed for SetPost<S> {}
530 impl<S: State> State for SetPost<S> {
531 type CreatedAt = S::CreatedAt;
532 type Post = Set<members::post>;
533 }
534 #[allow(non_camel_case_types)]
536 pub mod members {
537 pub struct created_at(());
539 pub struct post(());
541 }
542}
543
544pub struct ThreadgateBuilder<'a, S: threadgate_state::State> {
546 _state: PhantomData<fn() -> S>,
547 _fields: (
548 Option<Vec<ThreadgateAllowItem<'a>>>,
549 Option<Datetime>,
550 Option<Vec<AtUri<'a>>>,
551 Option<AtUri<'a>>,
552 ),
553 _lifetime: PhantomData<&'a ()>,
554}
555
556impl<'a> Threadgate<'a> {
557 pub fn new() -> ThreadgateBuilder<'a, threadgate_state::Empty> {
559 ThreadgateBuilder::new()
560 }
561}
562
563impl<'a> ThreadgateBuilder<'a, threadgate_state::Empty> {
564 pub fn new() -> Self {
566 ThreadgateBuilder {
567 _state: PhantomData,
568 _fields: (None, None, None, None),
569 _lifetime: PhantomData,
570 }
571 }
572}
573
574impl<'a, S: threadgate_state::State> ThreadgateBuilder<'a, S> {
575 pub fn allow(
577 mut self,
578 value: impl Into<Option<Vec<ThreadgateAllowItem<'a>>>>,
579 ) -> Self {
580 self._fields.0 = value.into();
581 self
582 }
583 pub fn maybe_allow(mut self, value: Option<Vec<ThreadgateAllowItem<'a>>>) -> Self {
585 self._fields.0 = value;
586 self
587 }
588}
589
590impl<'a, S> ThreadgateBuilder<'a, S>
591where
592 S: threadgate_state::State,
593 S::CreatedAt: threadgate_state::IsUnset,
594{
595 pub fn created_at(
597 mut self,
598 value: impl Into<Datetime>,
599 ) -> ThreadgateBuilder<'a, threadgate_state::SetCreatedAt<S>> {
600 self._fields.1 = Option::Some(value.into());
601 ThreadgateBuilder {
602 _state: PhantomData,
603 _fields: self._fields,
604 _lifetime: PhantomData,
605 }
606 }
607}
608
609impl<'a, S: threadgate_state::State> ThreadgateBuilder<'a, S> {
610 pub fn hidden_replies(mut self, value: impl Into<Option<Vec<AtUri<'a>>>>) -> Self {
612 self._fields.2 = value.into();
613 self
614 }
615 pub fn maybe_hidden_replies(mut self, value: Option<Vec<AtUri<'a>>>) -> Self {
617 self._fields.2 = value;
618 self
619 }
620}
621
622impl<'a, S> ThreadgateBuilder<'a, S>
623where
624 S: threadgate_state::State,
625 S::Post: threadgate_state::IsUnset,
626{
627 pub fn post(
629 mut self,
630 value: impl Into<AtUri<'a>>,
631 ) -> ThreadgateBuilder<'a, threadgate_state::SetPost<S>> {
632 self._fields.3 = Option::Some(value.into());
633 ThreadgateBuilder {
634 _state: PhantomData,
635 _fields: self._fields,
636 _lifetime: PhantomData,
637 }
638 }
639}
640
641impl<'a, S> ThreadgateBuilder<'a, S>
642where
643 S: threadgate_state::State,
644 S::CreatedAt: threadgate_state::IsSet,
645 S::Post: threadgate_state::IsSet,
646{
647 pub fn build(self) -> Threadgate<'a> {
649 Threadgate {
650 allow: self._fields.0,
651 created_at: self._fields.1.unwrap(),
652 hidden_replies: self._fields.2,
653 post: self._fields.3.unwrap(),
654 extra_data: Default::default(),
655 }
656 }
657 pub fn build_with_data(
659 self,
660 extra_data: BTreeMap<
661 jacquard_common::deps::smol_str::SmolStr,
662 jacquard_common::types::value::Data<'a>,
663 >,
664 ) -> Threadgate<'a> {
665 Threadgate {
666 allow: self._fields.0,
667 created_at: self._fields.1.unwrap(),
668 hidden_replies: self._fields.2,
669 post: self._fields.3.unwrap(),
670 extra_data: Some(extra_data),
671 }
672 }
673}