1pub mod create_webhook;
9pub mod delete_webhook;
10pub mod get_server_time;
11pub mod get_webhook;
12pub mod list_webhooks;
13pub mod settings;
14pub mod update_webhook;
15
16
17#[allow(unused_imports)]
18use alloc::collections::BTreeMap;
19
20#[allow(unused_imports)]
21use core::marker::PhantomData;
22use jacquard_common::CowStr;
23
24#[allow(unused_imports)]
25use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation;
26use jacquard_common::types::string::{Datetime, UriValue};
27use jacquard_derive::{IntoStatic, lexicon};
28use jacquard_lexicon::lexicon::LexiconDoc;
29use jacquard_lexicon::schema::LexiconSchema;
30
31#[allow(unused_imports)]
32use jacquard_lexicon::validation::{ConstraintError, ValidationPath};
33use serde::{Serialize, Deserialize};
34use crate::place_stream::server;
35
36#[lexicon]
37#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)]
38#[serde(rename_all = "camelCase")]
39pub struct RewriteRule<'a> {
40 #[serde(borrow)]
42 pub from: CowStr<'a>,
43 #[serde(borrow)]
45 pub to: CowStr<'a>,
46}
47
48#[lexicon]
51#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
52#[serde(rename_all = "camelCase")]
53pub struct Webhook<'a> {
54 pub active: bool,
56 pub created_at: Datetime,
58 #[serde(skip_serializing_if = "Option::is_none")]
60 #[serde(borrow)]
61 pub description: Option<CowStr<'a>>,
62 #[serde(skip_serializing_if = "Option::is_none")]
64 pub error_count: Option<i64>,
65 #[serde(borrow)]
67 pub events: Vec<CowStr<'a>>,
68 #[serde(borrow)]
70 pub id: CowStr<'a>,
71 #[serde(skip_serializing_if = "Option::is_none")]
73 pub last_triggered: Option<Datetime>,
74 #[serde(skip_serializing_if = "Option::is_none")]
76 #[serde(borrow)]
77 pub mute_words: Option<Vec<CowStr<'a>>>,
78 #[serde(skip_serializing_if = "Option::is_none")]
80 #[serde(borrow)]
81 pub name: Option<CowStr<'a>>,
82 #[serde(skip_serializing_if = "Option::is_none")]
84 #[serde(borrow)]
85 pub prefix: Option<CowStr<'a>>,
86 #[serde(skip_serializing_if = "Option::is_none")]
88 #[serde(borrow)]
89 pub rewrite: Option<Vec<server::RewriteRule<'a>>>,
90 #[serde(skip_serializing_if = "Option::is_none")]
92 #[serde(borrow)]
93 pub suffix: Option<CowStr<'a>>,
94 #[serde(skip_serializing_if = "Option::is_none")]
96 pub updated_at: Option<Datetime>,
97 #[serde(borrow)]
99 pub url: UriValue<'a>,
100}
101
102impl<'a> LexiconSchema for RewriteRule<'a> {
103 fn nsid() -> &'static str {
104 "place.stream.server.defs"
105 }
106 fn def_name() -> &'static str {
107 "rewriteRule"
108 }
109 fn lexicon_doc() -> LexiconDoc<'static> {
110 lexicon_doc_place_stream_server_defs()
111 }
112 fn validate(&self) -> Result<(), ConstraintError> {
113 {
114 let value = &self.from;
115 #[allow(unused_comparisons)]
116 if <str>::len(value.as_ref()) > 100usize {
117 return Err(ConstraintError::MaxLength {
118 path: ValidationPath::from_field("from"),
119 max: 100usize,
120 actual: <str>::len(value.as_ref()),
121 });
122 }
123 }
124 {
125 let value = &self.from;
126 #[allow(unused_comparisons)]
127 if <str>::len(value.as_ref()) < 1usize {
128 return Err(ConstraintError::MinLength {
129 path: ValidationPath::from_field("from"),
130 min: 1usize,
131 actual: <str>::len(value.as_ref()),
132 });
133 }
134 }
135 {
136 let value = &self.to;
137 #[allow(unused_comparisons)]
138 if <str>::len(value.as_ref()) > 100usize {
139 return Err(ConstraintError::MaxLength {
140 path: ValidationPath::from_field("to"),
141 max: 100usize,
142 actual: <str>::len(value.as_ref()),
143 });
144 }
145 }
146 Ok(())
147 }
148}
149
150impl<'a> LexiconSchema for Webhook<'a> {
151 fn nsid() -> &'static str {
152 "place.stream.server.defs"
153 }
154 fn def_name() -> &'static str {
155 "webhook"
156 }
157 fn lexicon_doc() -> LexiconDoc<'static> {
158 lexicon_doc_place_stream_server_defs()
159 }
160 fn validate(&self) -> Result<(), ConstraintError> {
161 if let Some(ref value) = self.description {
162 #[allow(unused_comparisons)]
163 if <str>::len(value.as_ref()) > 500usize {
164 return Err(ConstraintError::MaxLength {
165 path: ValidationPath::from_field("description"),
166 max: 500usize,
167 actual: <str>::len(value.as_ref()),
168 });
169 }
170 }
171 if let Some(ref value) = self.name {
172 #[allow(unused_comparisons)]
173 if <str>::len(value.as_ref()) > 100usize {
174 return Err(ConstraintError::MaxLength {
175 path: ValidationPath::from_field("name"),
176 max: 100usize,
177 actual: <str>::len(value.as_ref()),
178 });
179 }
180 }
181 if let Some(ref value) = self.prefix {
182 #[allow(unused_comparisons)]
183 if <str>::len(value.as_ref()) > 100usize {
184 return Err(ConstraintError::MaxLength {
185 path: ValidationPath::from_field("prefix"),
186 max: 100usize,
187 actual: <str>::len(value.as_ref()),
188 });
189 }
190 }
191 if let Some(ref value) = self.suffix {
192 #[allow(unused_comparisons)]
193 if <str>::len(value.as_ref()) > 100usize {
194 return Err(ConstraintError::MaxLength {
195 path: ValidationPath::from_field("suffix"),
196 max: 100usize,
197 actual: <str>::len(value.as_ref()),
198 });
199 }
200 }
201 Ok(())
202 }
203}
204
205fn lexicon_doc_place_stream_server_defs() -> LexiconDoc<'static> {
206 #[allow(unused_imports)]
207 use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType};
208 use jacquard_lexicon::lexicon::*;
209 use alloc::collections::BTreeMap;
210 LexiconDoc {
211 lexicon: Lexicon::Lexicon1,
212 id: CowStr::new_static("place.stream.server.defs"),
213 defs: {
214 let mut map = BTreeMap::new();
215 map.insert(
216 SmolStr::new_static("rewriteRule"),
217 LexUserType::Object(LexObject {
218 required: Some(
219 vec![SmolStr::new_static("from"), SmolStr::new_static("to")],
220 ),
221 properties: {
222 #[allow(unused_mut)]
223 let mut map = BTreeMap::new();
224 map.insert(
225 SmolStr::new_static("from"),
226 LexObjectProperty::String(LexString {
227 description: Some(
228 CowStr::new_static("Text to search for and replace."),
229 ),
230 min_length: Some(1usize),
231 max_length: Some(100usize),
232 ..Default::default()
233 }),
234 );
235 map.insert(
236 SmolStr::new_static("to"),
237 LexObjectProperty::String(LexString {
238 description: Some(
239 CowStr::new_static("Text to replace with."),
240 ),
241 max_length: Some(100usize),
242 ..Default::default()
243 }),
244 );
245 map
246 },
247 ..Default::default()
248 }),
249 );
250 map.insert(
251 SmolStr::new_static("webhook"),
252 LexUserType::Object(LexObject {
253 description: Some(
254 CowStr::new_static(
255 "A webhook configuration for receiving Streamplace events.",
256 ),
257 ),
258 required: Some(
259 vec![
260 SmolStr::new_static("id"), SmolStr::new_static("url"),
261 SmolStr::new_static("events"), SmolStr::new_static("active"),
262 SmolStr::new_static("createdAt")
263 ],
264 ),
265 properties: {
266 #[allow(unused_mut)]
267 let mut map = BTreeMap::new();
268 map.insert(
269 SmolStr::new_static("active"),
270 LexObjectProperty::Boolean(LexBoolean {
271 ..Default::default()
272 }),
273 );
274 map.insert(
275 SmolStr::new_static("createdAt"),
276 LexObjectProperty::String(LexString {
277 description: Some(
278 CowStr::new_static("When this webhook was created."),
279 ),
280 format: Some(LexStringFormat::Datetime),
281 ..Default::default()
282 }),
283 );
284 map.insert(
285 SmolStr::new_static("description"),
286 LexObjectProperty::String(LexString {
287 description: Some(
288 CowStr::new_static(
289 "A description of what this webhook is used for.",
290 ),
291 ),
292 max_length: Some(500usize),
293 ..Default::default()
294 }),
295 );
296 map.insert(
297 SmolStr::new_static("errorCount"),
298 LexObjectProperty::Integer(LexInteger {
299 ..Default::default()
300 }),
301 );
302 map.insert(
303 SmolStr::new_static("events"),
304 LexObjectProperty::Array(LexArray {
305 description: Some(
306 CowStr::new_static(
307 "The types of events this webhook should receive.",
308 ),
309 ),
310 items: LexArrayItem::String(LexString {
311 ..Default::default()
312 }),
313 ..Default::default()
314 }),
315 );
316 map.insert(
317 SmolStr::new_static("id"),
318 LexObjectProperty::String(LexString {
319 description: Some(
320 CowStr::new_static("Unique identifier for this webhook."),
321 ),
322 ..Default::default()
323 }),
324 );
325 map.insert(
326 SmolStr::new_static("lastTriggered"),
327 LexObjectProperty::String(LexString {
328 description: Some(
329 CowStr::new_static("When this webhook was last triggered."),
330 ),
331 format: Some(LexStringFormat::Datetime),
332 ..Default::default()
333 }),
334 );
335 map.insert(
336 SmolStr::new_static("muteWords"),
337 LexObjectProperty::Array(LexArray {
338 description: Some(
339 CowStr::new_static(
340 "Words to filter out from chat messages. Messages containing any of these words will not be forwarded.",
341 ),
342 ),
343 items: LexArrayItem::String(LexString {
344 max_length: Some(100usize),
345 ..Default::default()
346 }),
347 ..Default::default()
348 }),
349 );
350 map.insert(
351 SmolStr::new_static("name"),
352 LexObjectProperty::String(LexString {
353 description: Some(
354 CowStr::new_static("A user-friendly name for this webhook."),
355 ),
356 max_length: Some(100usize),
357 ..Default::default()
358 }),
359 );
360 map.insert(
361 SmolStr::new_static("prefix"),
362 LexObjectProperty::String(LexString {
363 description: Some(
364 CowStr::new_static("Text to prepend to webhook messages."),
365 ),
366 max_length: Some(100usize),
367 ..Default::default()
368 }),
369 );
370 map.insert(
371 SmolStr::new_static("rewrite"),
372 LexObjectProperty::Array(LexArray {
373 description: Some(
374 CowStr::new_static(
375 "Text replacement rules for webhook messages.",
376 ),
377 ),
378 items: LexArrayItem::Ref(LexRef {
379 r#ref: CowStr::new_static("#rewriteRule"),
380 ..Default::default()
381 }),
382 ..Default::default()
383 }),
384 );
385 map.insert(
386 SmolStr::new_static("suffix"),
387 LexObjectProperty::String(LexString {
388 description: Some(
389 CowStr::new_static("Text to append to webhook messages."),
390 ),
391 max_length: Some(100usize),
392 ..Default::default()
393 }),
394 );
395 map.insert(
396 SmolStr::new_static("updatedAt"),
397 LexObjectProperty::String(LexString {
398 description: Some(
399 CowStr::new_static("When this webhook was last updated."),
400 ),
401 format: Some(LexStringFormat::Datetime),
402 ..Default::default()
403 }),
404 );
405 map.insert(
406 SmolStr::new_static("url"),
407 LexObjectProperty::String(LexString {
408 description: Some(
409 CowStr::new_static(
410 "The webhook URL where events will be sent.",
411 ),
412 ),
413 format: Some(LexStringFormat::Uri),
414 ..Default::default()
415 }),
416 );
417 map
418 },
419 ..Default::default()
420 }),
421 );
422 map
423 },
424 ..Default::default()
425 }
426}
427
428pub mod webhook_state {
429
430 pub use crate::builder_types::{Set, Unset, IsSet, IsUnset};
431 #[allow(unused)]
432 use ::core::marker::PhantomData;
433 mod sealed {
434 pub trait Sealed {}
435 }
436 pub trait State: sealed::Sealed {
438 type CreatedAt;
439 type Active;
440 type Id;
441 type Url;
442 type Events;
443 }
444 pub struct Empty(());
446 impl sealed::Sealed for Empty {}
447 impl State for Empty {
448 type CreatedAt = Unset;
449 type Active = Unset;
450 type Id = Unset;
451 type Url = Unset;
452 type Events = Unset;
453 }
454 pub struct SetCreatedAt<S: State = Empty>(PhantomData<fn() -> S>);
456 impl<S: State> sealed::Sealed for SetCreatedAt<S> {}
457 impl<S: State> State for SetCreatedAt<S> {
458 type CreatedAt = Set<members::created_at>;
459 type Active = S::Active;
460 type Id = S::Id;
461 type Url = S::Url;
462 type Events = S::Events;
463 }
464 pub struct SetActive<S: State = Empty>(PhantomData<fn() -> S>);
466 impl<S: State> sealed::Sealed for SetActive<S> {}
467 impl<S: State> State for SetActive<S> {
468 type CreatedAt = S::CreatedAt;
469 type Active = Set<members::active>;
470 type Id = S::Id;
471 type Url = S::Url;
472 type Events = S::Events;
473 }
474 pub struct SetId<S: State = Empty>(PhantomData<fn() -> S>);
476 impl<S: State> sealed::Sealed for SetId<S> {}
477 impl<S: State> State for SetId<S> {
478 type CreatedAt = S::CreatedAt;
479 type Active = S::Active;
480 type Id = Set<members::id>;
481 type Url = S::Url;
482 type Events = S::Events;
483 }
484 pub struct SetUrl<S: State = Empty>(PhantomData<fn() -> S>);
486 impl<S: State> sealed::Sealed for SetUrl<S> {}
487 impl<S: State> State for SetUrl<S> {
488 type CreatedAt = S::CreatedAt;
489 type Active = S::Active;
490 type Id = S::Id;
491 type Url = Set<members::url>;
492 type Events = S::Events;
493 }
494 pub struct SetEvents<S: State = Empty>(PhantomData<fn() -> S>);
496 impl<S: State> sealed::Sealed for SetEvents<S> {}
497 impl<S: State> State for SetEvents<S> {
498 type CreatedAt = S::CreatedAt;
499 type Active = S::Active;
500 type Id = S::Id;
501 type Url = S::Url;
502 type Events = Set<members::events>;
503 }
504 #[allow(non_camel_case_types)]
506 pub mod members {
507 pub struct created_at(());
509 pub struct active(());
511 pub struct id(());
513 pub struct url(());
515 pub struct events(());
517 }
518}
519
520pub struct WebhookBuilder<'a, S: webhook_state::State> {
522 _state: PhantomData<fn() -> S>,
523 _fields: (
524 Option<bool>,
525 Option<Datetime>,
526 Option<CowStr<'a>>,
527 Option<i64>,
528 Option<Vec<CowStr<'a>>>,
529 Option<CowStr<'a>>,
530 Option<Datetime>,
531 Option<Vec<CowStr<'a>>>,
532 Option<CowStr<'a>>,
533 Option<CowStr<'a>>,
534 Option<Vec<server::RewriteRule<'a>>>,
535 Option<CowStr<'a>>,
536 Option<Datetime>,
537 Option<UriValue<'a>>,
538 ),
539 _lifetime: PhantomData<&'a ()>,
540}
541
542impl<'a> Webhook<'a> {
543 pub fn new() -> WebhookBuilder<'a, webhook_state::Empty> {
545 WebhookBuilder::new()
546 }
547}
548
549impl<'a> WebhookBuilder<'a, webhook_state::Empty> {
550 pub fn new() -> Self {
552 WebhookBuilder {
553 _state: PhantomData,
554 _fields: (
555 None,
556 None,
557 None,
558 None,
559 None,
560 None,
561 None,
562 None,
563 None,
564 None,
565 None,
566 None,
567 None,
568 None,
569 ),
570 _lifetime: PhantomData,
571 }
572 }
573}
574
575impl<'a, S> WebhookBuilder<'a, S>
576where
577 S: webhook_state::State,
578 S::Active: webhook_state::IsUnset,
579{
580 pub fn active(
582 mut self,
583 value: impl Into<bool>,
584 ) -> WebhookBuilder<'a, webhook_state::SetActive<S>> {
585 self._fields.0 = Option::Some(value.into());
586 WebhookBuilder {
587 _state: PhantomData,
588 _fields: self._fields,
589 _lifetime: PhantomData,
590 }
591 }
592}
593
594impl<'a, S> WebhookBuilder<'a, S>
595where
596 S: webhook_state::State,
597 S::CreatedAt: webhook_state::IsUnset,
598{
599 pub fn created_at(
601 mut self,
602 value: impl Into<Datetime>,
603 ) -> WebhookBuilder<'a, webhook_state::SetCreatedAt<S>> {
604 self._fields.1 = Option::Some(value.into());
605 WebhookBuilder {
606 _state: PhantomData,
607 _fields: self._fields,
608 _lifetime: PhantomData,
609 }
610 }
611}
612
613impl<'a, S: webhook_state::State> WebhookBuilder<'a, S> {
614 pub fn description(mut self, value: impl Into<Option<CowStr<'a>>>) -> Self {
616 self._fields.2 = value.into();
617 self
618 }
619 pub fn maybe_description(mut self, value: Option<CowStr<'a>>) -> Self {
621 self._fields.2 = value;
622 self
623 }
624}
625
626impl<'a, S: webhook_state::State> WebhookBuilder<'a, S> {
627 pub fn error_count(mut self, value: impl Into<Option<i64>>) -> Self {
629 self._fields.3 = value.into();
630 self
631 }
632 pub fn maybe_error_count(mut self, value: Option<i64>) -> Self {
634 self._fields.3 = value;
635 self
636 }
637}
638
639impl<'a, S> WebhookBuilder<'a, S>
640where
641 S: webhook_state::State,
642 S::Events: webhook_state::IsUnset,
643{
644 pub fn events(
646 mut self,
647 value: impl Into<Vec<CowStr<'a>>>,
648 ) -> WebhookBuilder<'a, webhook_state::SetEvents<S>> {
649 self._fields.4 = Option::Some(value.into());
650 WebhookBuilder {
651 _state: PhantomData,
652 _fields: self._fields,
653 _lifetime: PhantomData,
654 }
655 }
656}
657
658impl<'a, S> WebhookBuilder<'a, S>
659where
660 S: webhook_state::State,
661 S::Id: webhook_state::IsUnset,
662{
663 pub fn id(
665 mut self,
666 value: impl Into<CowStr<'a>>,
667 ) -> WebhookBuilder<'a, webhook_state::SetId<S>> {
668 self._fields.5 = Option::Some(value.into());
669 WebhookBuilder {
670 _state: PhantomData,
671 _fields: self._fields,
672 _lifetime: PhantomData,
673 }
674 }
675}
676
677impl<'a, S: webhook_state::State> WebhookBuilder<'a, S> {
678 pub fn last_triggered(mut self, value: impl Into<Option<Datetime>>) -> Self {
680 self._fields.6 = value.into();
681 self
682 }
683 pub fn maybe_last_triggered(mut self, value: Option<Datetime>) -> Self {
685 self._fields.6 = value;
686 self
687 }
688}
689
690impl<'a, S: webhook_state::State> WebhookBuilder<'a, S> {
691 pub fn mute_words(mut self, value: impl Into<Option<Vec<CowStr<'a>>>>) -> Self {
693 self._fields.7 = value.into();
694 self
695 }
696 pub fn maybe_mute_words(mut self, value: Option<Vec<CowStr<'a>>>) -> Self {
698 self._fields.7 = value;
699 self
700 }
701}
702
703impl<'a, S: webhook_state::State> WebhookBuilder<'a, S> {
704 pub fn name(mut self, value: impl Into<Option<CowStr<'a>>>) -> Self {
706 self._fields.8 = value.into();
707 self
708 }
709 pub fn maybe_name(mut self, value: Option<CowStr<'a>>) -> Self {
711 self._fields.8 = value;
712 self
713 }
714}
715
716impl<'a, S: webhook_state::State> WebhookBuilder<'a, S> {
717 pub fn prefix(mut self, value: impl Into<Option<CowStr<'a>>>) -> Self {
719 self._fields.9 = value.into();
720 self
721 }
722 pub fn maybe_prefix(mut self, value: Option<CowStr<'a>>) -> Self {
724 self._fields.9 = value;
725 self
726 }
727}
728
729impl<'a, S: webhook_state::State> WebhookBuilder<'a, S> {
730 pub fn rewrite(
732 mut self,
733 value: impl Into<Option<Vec<server::RewriteRule<'a>>>>,
734 ) -> Self {
735 self._fields.10 = value.into();
736 self
737 }
738 pub fn maybe_rewrite(mut self, value: Option<Vec<server::RewriteRule<'a>>>) -> Self {
740 self._fields.10 = value;
741 self
742 }
743}
744
745impl<'a, S: webhook_state::State> WebhookBuilder<'a, S> {
746 pub fn suffix(mut self, value: impl Into<Option<CowStr<'a>>>) -> Self {
748 self._fields.11 = value.into();
749 self
750 }
751 pub fn maybe_suffix(mut self, value: Option<CowStr<'a>>) -> Self {
753 self._fields.11 = value;
754 self
755 }
756}
757
758impl<'a, S: webhook_state::State> WebhookBuilder<'a, S> {
759 pub fn updated_at(mut self, value: impl Into<Option<Datetime>>) -> Self {
761 self._fields.12 = value.into();
762 self
763 }
764 pub fn maybe_updated_at(mut self, value: Option<Datetime>) -> Self {
766 self._fields.12 = value;
767 self
768 }
769}
770
771impl<'a, S> WebhookBuilder<'a, S>
772where
773 S: webhook_state::State,
774 S::Url: webhook_state::IsUnset,
775{
776 pub fn url(
778 mut self,
779 value: impl Into<UriValue<'a>>,
780 ) -> WebhookBuilder<'a, webhook_state::SetUrl<S>> {
781 self._fields.13 = Option::Some(value.into());
782 WebhookBuilder {
783 _state: PhantomData,
784 _fields: self._fields,
785 _lifetime: PhantomData,
786 }
787 }
788}
789
790impl<'a, S> WebhookBuilder<'a, S>
791where
792 S: webhook_state::State,
793 S::CreatedAt: webhook_state::IsSet,
794 S::Active: webhook_state::IsSet,
795 S::Id: webhook_state::IsSet,
796 S::Url: webhook_state::IsSet,
797 S::Events: webhook_state::IsSet,
798{
799 pub fn build(self) -> Webhook<'a> {
801 Webhook {
802 active: self._fields.0.unwrap(),
803 created_at: self._fields.1.unwrap(),
804 description: self._fields.2,
805 error_count: self._fields.3,
806 events: self._fields.4.unwrap(),
807 id: self._fields.5.unwrap(),
808 last_triggered: self._fields.6,
809 mute_words: self._fields.7,
810 name: self._fields.8,
811 prefix: self._fields.9,
812 rewrite: self._fields.10,
813 suffix: self._fields.11,
814 updated_at: self._fields.12,
815 url: self._fields.13.unwrap(),
816 extra_data: Default::default(),
817 }
818 }
819 pub fn build_with_data(
821 self,
822 extra_data: BTreeMap<
823 jacquard_common::deps::smol_str::SmolStr,
824 jacquard_common::types::value::Data<'a>,
825 >,
826 ) -> Webhook<'a> {
827 Webhook {
828 active: self._fields.0.unwrap(),
829 created_at: self._fields.1.unwrap(),
830 description: self._fields.2,
831 error_count: self._fields.3,
832 events: self._fields.4.unwrap(),
833 id: self._fields.5.unwrap(),
834 last_triggered: self._fields.6,
835 mute_words: self._fields.7,
836 name: self._fields.8,
837 prefix: self._fields.9,
838 rewrite: self._fields.10,
839 suffix: self._fields.11,
840 updated_at: self._fields.12,
841 url: self._fields.13.unwrap(),
842 extra_data: Some(extra_data),
843 }
844 }
845}