Skip to main content

revolt_database/util/bridge/
v0.rs

1use iso8601_timestamp::Timestamp;
2use revolt_models::v0::*;
3use revolt_permissions::{calculate_user_permissions, UserPermission};
4
5use crate::{util::permissions::DatabasePermissionQuery, Database};
6
7impl crate::Bot {
8    pub fn into_public_bot(self, user: crate::User) -> PublicBot {
9        #[cfg(debug_assertions)]
10        assert_eq!(self.id, user.id);
11
12        PublicBot {
13            id: self.id,
14            username: user.username,
15            avatar: user.avatar.map(|x| x.id).unwrap_or_default(),
16            description: user
17                .profile
18                .and_then(|profile| profile.content)
19                .unwrap_or_default(),
20        }
21    }
22}
23
24impl From<crate::Bot> for Bot {
25    fn from(value: crate::Bot) -> Self {
26        Bot {
27            id: value.id,
28            owner_id: value.owner,
29            token: value.token,
30            public: value.public,
31            analytics: value.analytics,
32            discoverable: value.discoverable,
33            interactions_url: value.interactions_url,
34            terms_of_service_url: value.terms_of_service_url,
35            privacy_policy_url: value.privacy_policy_url,
36            flags: value.flags.unwrap_or_default() as u32,
37        }
38    }
39}
40
41impl From<FieldsBot> for crate::FieldsBot {
42    fn from(value: FieldsBot) -> Self {
43        match value {
44            FieldsBot::InteractionsURL => crate::FieldsBot::InteractionsURL,
45            FieldsBot::Token => crate::FieldsBot::Token,
46        }
47    }
48}
49
50impl From<crate::FieldsBot> for FieldsBot {
51    fn from(value: crate::FieldsBot) -> Self {
52        match value {
53            crate::FieldsBot::InteractionsURL => FieldsBot::InteractionsURL,
54            crate::FieldsBot::Token => FieldsBot::Token,
55        }
56    }
57}
58
59impl From<crate::Invite> for Invite {
60    fn from(value: crate::Invite) -> Self {
61        match value {
62            crate::Invite::Group {
63                code,
64                creator,
65                channel,
66            } => Invite::Group {
67                code,
68                creator,
69                channel,
70            },
71            crate::Invite::Server {
72                code,
73                server,
74                creator,
75                channel,
76            } => Invite::Server {
77                code,
78                server,
79                creator,
80                channel,
81            },
82        }
83    }
84}
85
86impl From<crate::ChannelUnread> for ChannelUnread {
87    fn from(value: crate::ChannelUnread) -> Self {
88        ChannelUnread {
89            id: value.id.into(),
90            last_id: value.last_id,
91            mentions: value.mentions.unwrap_or_default(),
92        }
93    }
94}
95
96impl From<crate::ChannelCompositeKey> for ChannelCompositeKey {
97    fn from(value: crate::ChannelCompositeKey) -> Self {
98        ChannelCompositeKey {
99            channel: value.channel,
100            user: value.user,
101        }
102    }
103}
104
105impl From<crate::Webhook> for Webhook {
106    fn from(value: crate::Webhook) -> Self {
107        Webhook {
108            id: value.id,
109            name: value.name,
110            avatar: value.avatar.map(|file| file.into()),
111            creator_id: value.creator_id,
112            channel_id: value.channel_id,
113            token: value.token,
114            permissions: value.permissions,
115        }
116    }
117}
118
119impl From<crate::PartialWebhook> for PartialWebhook {
120    fn from(value: crate::PartialWebhook) -> Self {
121        PartialWebhook {
122            id: value.id,
123            name: value.name,
124            avatar: value.avatar.map(|file| file.into()),
125            creator_id: value.creator_id,
126            channel_id: value.channel_id,
127            token: value.token,
128            permissions: value.permissions,
129        }
130    }
131}
132
133impl From<FieldsWebhook> for crate::FieldsWebhook {
134    fn from(_value: FieldsWebhook) -> Self {
135        Self::Avatar
136    }
137}
138
139impl From<crate::FieldsWebhook> for FieldsWebhook {
140    fn from(_value: crate::FieldsWebhook) -> Self {
141        Self::Avatar
142    }
143}
144
145impl From<crate::Channel> for Channel {
146    #[allow(deprecated)]
147    fn from(value: crate::Channel) -> Self {
148        match value {
149            crate::Channel::SavedMessages { id, user } => Channel::SavedMessages { id, user },
150            crate::Channel::DirectMessage {
151                id,
152                active,
153                recipients,
154                last_message_id,
155            } => Channel::DirectMessage {
156                id,
157                active,
158                recipients,
159                last_message_id,
160            },
161            crate::Channel::Group {
162                id,
163                name,
164                owner,
165                description,
166                recipients,
167                icon,
168                last_message_id,
169                permissions,
170                nsfw,
171            } => Channel::Group {
172                id,
173                name,
174                owner,
175                description,
176                recipients,
177                icon: icon.map(|file| file.into()),
178                last_message_id,
179                permissions,
180                nsfw,
181            },
182            crate::Channel::TextChannel {
183                id,
184                server,
185                name,
186                description,
187                icon,
188                last_message_id,
189                default_permissions,
190                role_permissions,
191                nsfw,
192                voice,
193                slowmode,
194            } => Channel::TextChannel {
195                id,
196                server,
197                name,
198                description,
199                icon: icon.map(|file| file.into()),
200                last_message_id,
201                default_permissions,
202                role_permissions,
203                nsfw,
204                voice: voice.map(|voice| voice.into()),
205                slowmode,
206            },
207        }
208    }
209}
210
211impl From<Channel> for crate::Channel {
212    #[allow(deprecated)]
213    fn from(value: Channel) -> crate::Channel {
214        match value {
215            Channel::SavedMessages { id, user } => crate::Channel::SavedMessages { id, user },
216            Channel::DirectMessage {
217                id,
218                active,
219                recipients,
220                last_message_id,
221            } => crate::Channel::DirectMessage {
222                id,
223                active,
224                recipients,
225                last_message_id,
226            },
227            Channel::Group {
228                id,
229                name,
230                owner,
231                description,
232                recipients,
233                icon,
234                last_message_id,
235                permissions,
236                nsfw,
237            } => crate::Channel::Group {
238                id,
239                name,
240                owner,
241                description,
242                recipients,
243                icon: icon.map(|file| file.into()),
244                last_message_id,
245                permissions,
246                nsfw,
247            },
248            Channel::TextChannel {
249                id,
250                server,
251                name,
252                description,
253                icon,
254                last_message_id,
255                default_permissions,
256                role_permissions,
257                nsfw,
258                voice,
259                slowmode,
260            } => crate::Channel::TextChannel {
261                id,
262                server,
263                name,
264                description,
265                icon: icon.map(|file| file.into()),
266                last_message_id,
267                default_permissions,
268                role_permissions,
269                nsfw,
270                voice: voice.map(|voice| voice.into()),
271                slowmode,
272            },
273        }
274    }
275}
276
277impl From<crate::PartialChannel> for PartialChannel {
278    fn from(value: crate::PartialChannel) -> Self {
279        PartialChannel {
280            name: value.name,
281            owner: value.owner,
282            description: value.description,
283            icon: value.icon.map(|file| file.into()),
284            nsfw: value.nsfw,
285            active: value.active,
286            permissions: value.permissions,
287            role_permissions: value.role_permissions,
288            default_permissions: value.default_permissions,
289            last_message_id: value.last_message_id,
290            voice: value.voice.map(|voice| voice.into()),
291            slowmode: value.slowmode,
292        }
293    }
294}
295
296impl From<PartialChannel> for crate::PartialChannel {
297    fn from(value: PartialChannel) -> crate::PartialChannel {
298        crate::PartialChannel {
299            name: value.name,
300            owner: value.owner,
301            description: value.description,
302            icon: value.icon.map(|file| file.into()),
303            nsfw: value.nsfw,
304            active: value.active,
305            permissions: value.permissions,
306            role_permissions: value.role_permissions,
307            default_permissions: value.default_permissions,
308            last_message_id: value.last_message_id,
309            voice: value.voice.map(|voice| voice.into()),
310            slowmode: value.slowmode,
311        }
312    }
313}
314
315impl From<FieldsChannel> for crate::FieldsChannel {
316    fn from(value: FieldsChannel) -> Self {
317        match value {
318            FieldsChannel::Description => crate::FieldsChannel::Description,
319            FieldsChannel::Icon => crate::FieldsChannel::Icon,
320            FieldsChannel::DefaultPermissions => crate::FieldsChannel::DefaultPermissions,
321            FieldsChannel::Voice => crate::FieldsChannel::Voice,
322            FieldsChannel::Slowmode => crate::FieldsChannel::Slowmode,
323        }
324    }
325}
326
327impl From<crate::FieldsChannel> for FieldsChannel {
328    fn from(value: crate::FieldsChannel) -> Self {
329        match value {
330            crate::FieldsChannel::Description => FieldsChannel::Description,
331            crate::FieldsChannel::Icon => FieldsChannel::Icon,
332            crate::FieldsChannel::DefaultPermissions => FieldsChannel::DefaultPermissions,
333            crate::FieldsChannel::Voice => FieldsChannel::Voice,
334            crate::FieldsChannel::Slowmode => FieldsChannel::Slowmode,
335        }
336    }
337}
338
339impl From<crate::Emoji> for Emoji {
340    fn from(value: crate::Emoji) -> Self {
341        Emoji {
342            id: value.id,
343            parent: value.parent.into(),
344            creator_id: value.creator_id,
345            name: value.name,
346            animated: value.animated,
347            nsfw: value.nsfw,
348        }
349    }
350}
351
352impl From<crate::EmojiParent> for EmojiParent {
353    fn from(value: crate::EmojiParent) -> Self {
354        match value {
355            crate::EmojiParent::Detached => EmojiParent::Detached,
356            crate::EmojiParent::Server { id } => EmojiParent::Server { id },
357        }
358    }
359}
360
361impl From<EmojiParent> for crate::EmojiParent {
362    fn from(value: EmojiParent) -> Self {
363        match value {
364            EmojiParent::Detached => crate::EmojiParent::Detached,
365            EmojiParent::Server { id } => crate::EmojiParent::Server { id },
366        }
367    }
368}
369
370impl From<crate::File> for File {
371    fn from(value: crate::File) -> Self {
372        File {
373            id: value.id,
374            tag: value.tag,
375            filename: value.filename,
376            metadata: value.metadata.into(),
377            content_type: value.content_type,
378            size: value.size,
379            deleted: value.deleted,
380            reported: value.reported,
381            message_id: value.message_id,
382            user_id: value.user_id,
383            server_id: value.server_id,
384            object_id: value.object_id,
385        }
386    }
387}
388
389impl From<File> for crate::File {
390    fn from(value: File) -> crate::File {
391        crate::File {
392            id: value.id,
393            tag: value.tag,
394            filename: value.filename,
395            metadata: value.metadata.into(),
396            content_type: value.content_type,
397            size: value.size,
398            deleted: value.deleted,
399            reported: value.reported,
400            message_id: value.message_id,
401            user_id: value.user_id,
402            server_id: value.server_id,
403            object_id: value.object_id,
404            hash: None,
405            uploaded_at: None,
406            uploader_id: None,
407            used_for: None,
408        }
409    }
410}
411
412impl From<crate::Metadata> for Metadata {
413    fn from(value: crate::Metadata) -> Self {
414        match value {
415            crate::Metadata::File => Metadata::File,
416            crate::Metadata::Text => Metadata::Text,
417            crate::Metadata::Image {
418                width,
419                height,
420                thumbhash,
421                animated,
422            } => Metadata::Image {
423                width: width as usize,
424                height: height as usize,
425                thumbhash,
426                animated,
427            },
428            crate::Metadata::Video { width, height } => Metadata::Video {
429                width: width as usize,
430                height: height as usize,
431            },
432            crate::Metadata::Audio => Metadata::Audio,
433        }
434    }
435}
436
437impl From<Metadata> for crate::Metadata {
438    fn from(value: Metadata) -> crate::Metadata {
439        match value {
440            Metadata::File => crate::Metadata::File,
441            Metadata::Text => crate::Metadata::Text,
442            Metadata::Image {
443                width,
444                height,
445                thumbhash,
446                animated,
447            } => crate::Metadata::Image {
448                width: width as isize,
449                height: height as isize,
450                thumbhash,
451                animated,
452            },
453            Metadata::Video { width, height } => crate::Metadata::Video {
454                width: width as isize,
455                height: height as isize,
456            },
457            Metadata::Audio => crate::Metadata::Audio,
458        }
459    }
460}
461
462impl crate::Message {
463    pub fn into_model(self, user: Option<User>, member: Option<Member>) -> Message {
464        Message {
465            id: self.id,
466            nonce: self.nonce,
467            channel: self.channel,
468            author: self.author,
469            user,
470            member,
471            webhook: self.webhook,
472            content: self.content,
473            system: self.system.map(Into::into),
474            attachments: self
475                .attachments
476                .map(|v| v.into_iter().map(|f| f.into()).collect()),
477            edited: self.edited,
478            embeds: self.embeds,
479            mentions: self.mentions,
480            role_mentions: self.role_mentions,
481            replies: self.replies,
482            reactions: self.reactions,
483            interactions: self.interactions.into(),
484            masquerade: self.masquerade.map(Into::into),
485            flags: self.flags.unwrap_or_default(),
486            pinned: self.pinned,
487        }
488    }
489}
490
491impl From<crate::PartialMessage> for PartialMessage {
492    fn from(value: crate::PartialMessage) -> Self {
493        PartialMessage {
494            id: value.id,
495            nonce: value.nonce,
496            channel: value.channel,
497            author: value.author,
498            user: None,
499            member: None,
500            webhook: value.webhook,
501            content: value.content,
502            system: value.system.map(Into::into),
503            attachments: value
504                .attachments
505                .map(|v| v.into_iter().map(|f| f.into()).collect()),
506            edited: value.edited,
507            embeds: value.embeds,
508            mentions: value.mentions,
509            role_mentions: value.role_mentions,
510            replies: value.replies,
511            reactions: value.reactions,
512            interactions: value.interactions.map(Into::into),
513            masquerade: value.masquerade.map(Into::into),
514            flags: value.flags,
515            pinned: value.pinned,
516        }
517    }
518}
519
520impl From<crate::SystemMessage> for SystemMessage {
521    fn from(value: crate::SystemMessage) -> Self {
522        match value {
523            crate::SystemMessage::ChannelDescriptionChanged { by } => {
524                Self::ChannelDescriptionChanged { by }
525            }
526            crate::SystemMessage::ChannelIconChanged { by } => Self::ChannelIconChanged { by },
527            crate::SystemMessage::ChannelOwnershipChanged { from, to } => {
528                Self::ChannelOwnershipChanged { from, to }
529            }
530            crate::SystemMessage::ChannelRenamed { name, by } => Self::ChannelRenamed { name, by },
531            crate::SystemMessage::Text { content } => Self::Text { content },
532            crate::SystemMessage::UserAdded { id, by } => Self::UserAdded { id, by },
533            crate::SystemMessage::UserBanned { id } => Self::UserBanned { id },
534            crate::SystemMessage::UserJoined { id } => Self::UserJoined { id },
535            crate::SystemMessage::UserKicked { id } => Self::UserKicked { id },
536            crate::SystemMessage::UserLeft { id } => Self::UserLeft { id },
537            crate::SystemMessage::UserRemove { id, by } => Self::UserRemove { id, by },
538            crate::SystemMessage::MessagePinned { id, by } => Self::MessagePinned { id, by },
539            crate::SystemMessage::MessageUnpinned { id, by } => Self::MessageUnpinned { id, by },
540            crate::SystemMessage::CallStarted { by, finished_at } => {
541                Self::CallStarted { by, finished_at }
542            }
543        }
544    }
545}
546
547impl From<crate::Interactions> for Interactions {
548    fn from(value: crate::Interactions) -> Self {
549        Interactions {
550            reactions: value
551                .reactions
552                .map(|reactions| reactions.into_iter().collect()),
553            restrict_reactions: value.restrict_reactions,
554        }
555    }
556}
557
558impl From<Interactions> for crate::Interactions {
559    fn from(value: Interactions) -> Self {
560        crate::Interactions {
561            reactions: value
562                .reactions
563                .map(|reactions| reactions.into_iter().collect()),
564            restrict_reactions: value.restrict_reactions,
565        }
566    }
567}
568
569impl From<crate::AppendMessage> for AppendMessage {
570    fn from(value: crate::AppendMessage) -> Self {
571        AppendMessage {
572            embeds: value.embeds,
573        }
574    }
575}
576
577impl From<crate::Masquerade> for Masquerade {
578    fn from(value: crate::Masquerade) -> Self {
579        Masquerade {
580            name: value.name,
581            avatar: value.avatar,
582            colour: value.colour,
583        }
584    }
585}
586
587impl From<Masquerade> for crate::Masquerade {
588    fn from(value: Masquerade) -> Self {
589        crate::Masquerade {
590            name: value.name,
591            avatar: value.avatar,
592            colour: value.colour,
593        }
594    }
595}
596
597impl From<crate::PolicyChange> for PolicyChange {
598    fn from(value: crate::PolicyChange) -> Self {
599        PolicyChange {
600            created_time: value.created_time,
601            effective_time: value.effective_time,
602            description: value.description,
603            url: value.url,
604        }
605    }
606}
607
608impl From<crate::Report> for Report {
609    fn from(value: crate::Report) -> Self {
610        Report {
611            id: value.id,
612            author_id: value.author_id,
613            content: value.content,
614            additional_context: value.additional_context,
615            status: value.status,
616            notes: value.notes,
617        }
618    }
619}
620
621impl From<crate::ServerBan> for ServerBan {
622    fn from(value: crate::ServerBan) -> Self {
623        ServerBan {
624            id: value.id.into(),
625            reason: value.reason,
626        }
627    }
628}
629
630impl From<crate::Member> for Member {
631    fn from(value: crate::Member) -> Self {
632        Member {
633            id: value.id.into(),
634            joined_at: value.joined_at,
635            nickname: value.nickname,
636            pronouns: value.pronouns,
637            avatar: value.avatar.map(|f| f.into()),
638            roles: value.roles,
639            timeout: value.timeout,
640            can_publish: value.can_publish,
641            can_receive: value.can_receive,
642        }
643    }
644}
645
646impl From<Member> for crate::Member {
647    fn from(value: Member) -> crate::Member {
648        crate::Member {
649            id: value.id.into(),
650            joined_at: value.joined_at,
651            nickname: value.nickname,
652            pronouns: value.pronouns,
653            avatar: value.avatar.map(|f| f.into()),
654            roles: value.roles,
655            timeout: value.timeout,
656            can_publish: value.can_publish,
657            can_receive: value.can_receive,
658        }
659    }
660}
661
662impl From<crate::PartialMember> for PartialMember {
663    fn from(value: crate::PartialMember) -> Self {
664        PartialMember {
665            id: value.id.map(|id| id.into()),
666            joined_at: value.joined_at,
667            nickname: value.nickname,
668            pronouns: value.pronouns,
669            avatar: value.avatar.map(|f| f.into()),
670            roles: value.roles,
671            timeout: value.timeout,
672            can_publish: value.can_publish,
673            can_receive: value.can_receive,
674        }
675    }
676}
677
678impl From<PartialMember> for crate::PartialMember {
679    fn from(value: PartialMember) -> crate::PartialMember {
680        crate::PartialMember {
681            id: value.id.map(|id| id.into()),
682            joined_at: value.joined_at,
683            nickname: value.nickname,
684            pronouns: value.pronouns,
685            avatar: value.avatar.map(|f| f.into()),
686            roles: value.roles,
687            timeout: value.timeout,
688            can_publish: value.can_publish,
689            can_receive: value.can_receive,
690        }
691    }
692}
693
694impl From<crate::MemberCompositeKey> for MemberCompositeKey {
695    fn from(value: crate::MemberCompositeKey) -> Self {
696        MemberCompositeKey {
697            server: value.server,
698            user: value.user,
699        }
700    }
701}
702
703impl From<MemberCompositeKey> for crate::MemberCompositeKey {
704    fn from(value: MemberCompositeKey) -> crate::MemberCompositeKey {
705        crate::MemberCompositeKey {
706            server: value.server,
707            user: value.user,
708        }
709    }
710}
711
712impl From<crate::FieldsMember> for FieldsMember {
713    fn from(value: crate::FieldsMember) -> Self {
714        match value {
715            crate::FieldsMember::Avatar => FieldsMember::Avatar,
716            crate::FieldsMember::Nickname => FieldsMember::Nickname,
717            crate::FieldsMember::Pronouns => FieldsMember::Pronouns,
718            crate::FieldsMember::Roles => FieldsMember::Roles,
719            crate::FieldsMember::Timeout => FieldsMember::Timeout,
720            crate::FieldsMember::CanReceive => FieldsMember::CanReceive,
721            crate::FieldsMember::CanPublish => FieldsMember::CanPublish,
722            crate::FieldsMember::JoinedAt => FieldsMember::JoinedAt,
723            crate::FieldsMember::VoiceChannel => FieldsMember::VoiceChannel,
724        }
725    }
726}
727
728impl From<FieldsMember> for crate::FieldsMember {
729    fn from(value: FieldsMember) -> crate::FieldsMember {
730        match value {
731            FieldsMember::Avatar => crate::FieldsMember::Avatar,
732            FieldsMember::Nickname => crate::FieldsMember::Nickname,
733            FieldsMember::Pronouns => crate::FieldsMember::Pronouns,
734            FieldsMember::Roles => crate::FieldsMember::Roles,
735            FieldsMember::Timeout => crate::FieldsMember::Timeout,
736            FieldsMember::CanReceive => crate::FieldsMember::CanReceive,
737            FieldsMember::CanPublish => crate::FieldsMember::CanPublish,
738            FieldsMember::JoinedAt => crate::FieldsMember::JoinedAt,
739            FieldsMember::VoiceChannel => crate::FieldsMember::VoiceChannel,
740        }
741    }
742}
743
744impl From<crate::RemovalIntention> for RemovalIntention {
745    fn from(value: crate::RemovalIntention) -> Self {
746        match value {
747            crate::RemovalIntention::Ban => RemovalIntention::Ban,
748            crate::RemovalIntention::Kick => RemovalIntention::Kick,
749            crate::RemovalIntention::Leave => RemovalIntention::Leave,
750        }
751    }
752}
753
754impl crate::Server {
755    pub async fn into(self, db: &Database) -> Server {
756        let approximate_member_count = self.get_approximate_member_count(db).await;
757
758        Server {
759            id: self.id,
760            owner: self.owner,
761            name: self.name,
762            description: self.description,
763            channels: self.channels,
764            categories: self
765                .categories
766                .map(|categories| categories.into_iter().map(|v| v.into()).collect()),
767            system_messages: self.system_messages.map(|v| v.into()),
768            roles: self.roles.into_iter().map(|(k, v)| (k, v.into())).collect(),
769            default_permissions: self.default_permissions,
770            icon: self.icon.map(|f| f.into()),
771            banner: self.banner.map(|f| f.into()),
772            flags: self.flags.unwrap_or_default() as u32,
773            nsfw: self.nsfw,
774            analytics: self.analytics,
775            discoverable: self.discoverable,
776            approximate_member_count,
777        }
778    }
779}
780
781impl From<Server> for crate::Server {
782    fn from(value: Server) -> crate::Server {
783        crate::Server {
784            id: value.id,
785            owner: value.owner,
786            name: value.name,
787            description: value.description,
788            channels: value.channels,
789            categories: value
790                .categories
791                .map(|categories| categories.into_iter().map(|v| v.into()).collect()),
792            system_messages: value.system_messages.map(|v| v.into()),
793            roles: value
794                .roles
795                .into_iter()
796                .map(|(k, v)| (k, v.into()))
797                .collect(),
798            default_permissions: value.default_permissions,
799            icon: value.icon.map(|f| f.into()),
800            banner: value.banner.map(|f| f.into()),
801            flags: Some(value.flags as i32),
802            nsfw: value.nsfw,
803            analytics: value.analytics,
804            discoverable: value.discoverable,
805        }
806    }
807}
808
809impl From<crate::PartialServer> for PartialServer {
810    fn from(value: crate::PartialServer) -> Self {
811        PartialServer {
812            id: value.id,
813            owner: value.owner,
814            name: value.name,
815            description: value.description,
816            channels: value.channels,
817            categories: value
818                .categories
819                .map(|categories| categories.into_iter().map(|v| v.into()).collect()),
820            system_messages: value.system_messages.map(|v| v.into()),
821            roles: value
822                .roles
823                .map(|roles| roles.into_iter().map(|(k, v)| (k, v.into())).collect()),
824            default_permissions: value.default_permissions,
825            icon: value.icon.map(|f| f.into()),
826            banner: value.banner.map(|f| f.into()),
827            flags: value.flags.map(|v| v as u32),
828            nsfw: value.nsfw,
829            analytics: value.analytics,
830            discoverable: value.discoverable,
831            approximate_member_count: None,
832        }
833    }
834}
835
836impl From<PartialServer> for crate::PartialServer {
837    fn from(value: PartialServer) -> crate::PartialServer {
838        crate::PartialServer {
839            id: value.id,
840            owner: value.owner,
841            name: value.name,
842            description: value.description,
843            channels: value.channels,
844            categories: value
845                .categories
846                .map(|categories| categories.into_iter().map(|v| v.into()).collect()),
847            system_messages: value.system_messages.map(|v| v.into()),
848            roles: value
849                .roles
850                .map(|roles| roles.into_iter().map(|(k, v)| (k, v.into())).collect()),
851            default_permissions: value.default_permissions,
852            icon: value.icon.map(|f| f.into()),
853            banner: value.banner.map(|f| f.into()),
854            flags: value.flags.map(|v| v as i32),
855            nsfw: value.nsfw,
856            analytics: value.analytics,
857            discoverable: value.discoverable,
858        }
859    }
860}
861
862impl From<crate::FieldsServer> for FieldsServer {
863    fn from(value: crate::FieldsServer) -> Self {
864        match value {
865            crate::FieldsServer::Banner => FieldsServer::Banner,
866            crate::FieldsServer::Categories => FieldsServer::Categories,
867            crate::FieldsServer::Description => FieldsServer::Description,
868            crate::FieldsServer::Icon => FieldsServer::Icon,
869            crate::FieldsServer::SystemMessages => FieldsServer::SystemMessages,
870        }
871    }
872}
873
874impl From<FieldsServer> for crate::FieldsServer {
875    fn from(value: FieldsServer) -> crate::FieldsServer {
876        match value {
877            FieldsServer::Banner => crate::FieldsServer::Banner,
878            FieldsServer::Categories => crate::FieldsServer::Categories,
879            FieldsServer::Description => crate::FieldsServer::Description,
880            FieldsServer::Icon => crate::FieldsServer::Icon,
881            FieldsServer::SystemMessages => crate::FieldsServer::SystemMessages,
882        }
883    }
884}
885
886impl From<crate::Category> for Category {
887    fn from(value: crate::Category) -> Self {
888        Category {
889            id: value.id,
890            title: value.title,
891            channels: value.channels,
892        }
893    }
894}
895
896impl From<Category> for crate::Category {
897    fn from(value: Category) -> Self {
898        crate::Category {
899            id: value.id,
900            title: value.title,
901            channels: value.channels,
902        }
903    }
904}
905
906impl From<crate::SystemMessageChannels> for SystemMessageChannels {
907    fn from(value: crate::SystemMessageChannels) -> Self {
908        SystemMessageChannels {
909            user_joined: value.user_joined,
910            user_left: value.user_left,
911            user_kicked: value.user_kicked,
912            user_banned: value.user_banned,
913        }
914    }
915}
916
917impl From<SystemMessageChannels> for crate::SystemMessageChannels {
918    fn from(value: SystemMessageChannels) -> Self {
919        crate::SystemMessageChannels {
920            user_joined: value.user_joined,
921            user_left: value.user_left,
922            user_kicked: value.user_kicked,
923            user_banned: value.user_banned,
924        }
925    }
926}
927
928impl From<crate::Role> for Role {
929    fn from(value: crate::Role) -> Self {
930        Role {
931            id: value.id,
932            name: value.name,
933            permissions: value.permissions,
934            colour: value.colour,
935            hoist: value.hoist,
936            rank: value.rank,
937            icon: value.icon.map(|f| f.into()),
938        }
939    }
940}
941
942impl From<Role> for crate::Role {
943    fn from(value: Role) -> crate::Role {
944        crate::Role {
945            id: value.id,
946            name: value.name,
947            permissions: value.permissions,
948            colour: value.colour,
949            hoist: value.hoist,
950            rank: value.rank,
951            icon: value.icon.map(|f| f.into()),
952        }
953    }
954}
955
956impl From<crate::PartialRole> for PartialRole {
957    fn from(value: crate::PartialRole) -> Self {
958        PartialRole {
959            id: value.id,
960            name: value.name,
961            permissions: value.permissions,
962            colour: value.colour,
963            hoist: value.hoist,
964            rank: value.rank,
965            icon: value.icon.map(|f| f.into()),
966        }
967    }
968}
969
970impl From<PartialRole> for crate::PartialRole {
971    fn from(value: PartialRole) -> crate::PartialRole {
972        crate::PartialRole {
973            id: value.id,
974            name: value.name,
975            permissions: value.permissions,
976            colour: value.colour,
977            hoist: value.hoist,
978            rank: value.rank,
979            icon: value.icon.map(|f| f.into()),
980        }
981    }
982}
983
984impl From<crate::FieldsRole> for FieldsRole {
985    fn from(value: crate::FieldsRole) -> Self {
986        match value {
987            crate::FieldsRole::Colour => FieldsRole::Colour,
988            crate::FieldsRole::Icon => FieldsRole::Icon,
989        }
990    }
991}
992
993impl From<FieldsRole> for crate::FieldsRole {
994    fn from(value: FieldsRole) -> Self {
995        match value {
996            FieldsRole::Colour => crate::FieldsRole::Colour,
997            FieldsRole::Icon => crate::FieldsRole::Icon,
998        }
999    }
1000}
1001
1002impl crate::User {
1003    pub async fn into<'a, P>(self, db: &Database, perspective: P) -> User
1004    where
1005        P: Into<Option<&'a crate::User>>,
1006    {
1007        let perspective = perspective.into();
1008        let (relationship, can_see_profile) = if self.bot.is_some() {
1009            (RelationshipStatus::None, true)
1010        } else if let Some(perspective) = perspective {
1011            let mut query = DatabasePermissionQuery::new(db, perspective).user(&self);
1012
1013            if perspective.id == self.id {
1014                (RelationshipStatus::User, true)
1015            } else {
1016                (
1017                    perspective
1018                        .relations
1019                        .as_ref()
1020                        .map(|relations| {
1021                            relations
1022                                .iter()
1023                                .find(|relationship| relationship.id == self.id)
1024                                .map(|relationship| relationship.status.clone().into())
1025                                .unwrap_or_default()
1026                        })
1027                        .unwrap_or_default(),
1028                    calculate_user_permissions(&mut query)
1029                        .await
1030                        .has_user_permission(UserPermission::ViewProfile),
1031                )
1032            }
1033        } else {
1034            (RelationshipStatus::None, false)
1035        };
1036
1037        let badges = self.get_badges().await;
1038
1039        User {
1040            username: self.username,
1041            discriminator: self.discriminator,
1042            display_name: self.display_name,
1043            pronouns: self.pronouns,
1044            avatar: self.avatar.map(|file| file.into()),
1045            relations: if let Some(crate::User { id, .. }) = perspective {
1046                if id == &self.id {
1047                    self.relations
1048                        .unwrap_or_default()
1049                        .into_iter()
1050                        .map(|relation| relation.into())
1051                        .collect()
1052                } else {
1053                    vec![]
1054                }
1055            } else {
1056                vec![]
1057            },
1058            badges,
1059            online: can_see_profile
1060                && revolt_presence::is_online(&self.id).await
1061                && !matches!(
1062                    self.status,
1063                    Some(crate::UserStatus {
1064                        presence: Some(crate::Presence::Invisible),
1065                        ..
1066                    })
1067                ),
1068            status: if can_see_profile {
1069                self.status.and_then(|status| status.into(true))
1070            } else {
1071                None
1072            },
1073            flags: self.flags.unwrap_or_default() as u32,
1074            privileged: self.privileged,
1075            bot: self.bot.map(|bot| bot.into()),
1076            relationship,
1077            id: self.id,
1078        }
1079    }
1080
1081    /// Convert user object into user model assuming mutual connection
1082    ///
1083    /// Relations will never be included, i.e. when we process ourselves
1084    pub async fn into_known<'a, P>(self, perspective: P, is_online: bool) -> User
1085    where
1086        P: Into<Option<&'a crate::User>>,
1087    {
1088        let perspective = perspective.into();
1089        let (relationship, can_see_profile) = if self.bot.is_some() {
1090            (RelationshipStatus::None, true)
1091        } else if let Some(perspective) = perspective {
1092            if perspective.id == self.id {
1093                (RelationshipStatus::User, true)
1094            } else {
1095                let relationship = perspective
1096                    .relations
1097                    .as_ref()
1098                    .map(|relations| {
1099                        relations
1100                            .iter()
1101                            .find(|relationship| relationship.id == self.id)
1102                            .map(|relationship| relationship.status.clone().into())
1103                            .unwrap_or_default()
1104                    })
1105                    .unwrap_or_default();
1106
1107                let can_see_profile = relationship != RelationshipStatus::BlockedOther;
1108                (relationship, can_see_profile)
1109            }
1110        } else {
1111            (RelationshipStatus::None, false)
1112        };
1113
1114        let badges = self.get_badges().await;
1115
1116        User {
1117            username: self.username,
1118            discriminator: self.discriminator,
1119            display_name: self.display_name,
1120            pronouns: self.pronouns,
1121            avatar: self.avatar.map(|file| file.into()),
1122            relations: vec![],
1123            badges,
1124            online: can_see_profile
1125                && is_online
1126                && !matches!(
1127                    self.status,
1128                    Some(crate::UserStatus {
1129                        presence: Some(crate::Presence::Invisible),
1130                        ..
1131                    })
1132                ),
1133            status: if can_see_profile {
1134                self.status.and_then(|status| status.into(true))
1135            } else {
1136                None
1137            },
1138            flags: self.flags.unwrap_or_default() as u32,
1139            privileged: self.privileged,
1140            bot: self.bot.map(|bot| bot.into()),
1141            relationship,
1142            id: self.id,
1143        }
1144    }
1145
1146    /// Convert user object into user model without presence information
1147    pub async fn into_known_static(self, is_online: bool) -> User {
1148        let badges = self.get_badges().await;
1149
1150        User {
1151            username: self.username,
1152            discriminator: self.discriminator,
1153            display_name: self.display_name,
1154            pronouns: self.pronouns,
1155            avatar: self.avatar.map(|file| file.into()),
1156            relations: vec![],
1157            badges,
1158            online: is_online
1159                && !matches!(
1160                    self.status,
1161                    Some(crate::UserStatus {
1162                        presence: Some(crate::Presence::Invisible),
1163                        ..
1164                    })
1165                ),
1166            status: self.status.and_then(|status| status.into(true)),
1167            flags: self.flags.unwrap_or_default() as u32,
1168            privileged: self.privileged,
1169            bot: self.bot.map(|bot| bot.into()),
1170            relationship: RelationshipStatus::None, // events client will populate this from cache
1171            id: self.id,
1172        }
1173    }
1174
1175    pub async fn into_self(self, force_online: bool) -> User {
1176        let badges = self.get_badges().await;
1177
1178        User {
1179            username: self.username,
1180            discriminator: self.discriminator,
1181            display_name: self.display_name,
1182            pronouns: self.pronouns,
1183            avatar: self.avatar.map(|file| file.into()),
1184            relations: self
1185                .relations
1186                .map(|relationships| {
1187                    relationships
1188                        .into_iter()
1189                        .map(|relationship| relationship.into())
1190                        .collect()
1191                })
1192                .unwrap_or_default(),
1193            badges,
1194            online: (force_online || revolt_presence::is_online(&self.id).await)
1195                && !matches!(
1196                    self.status,
1197                    Some(crate::UserStatus {
1198                        presence: Some(crate::Presence::Invisible),
1199                        ..
1200                    })
1201                ),
1202            status: self.status.and_then(|status| status.into(true)),
1203            flags: self.flags.unwrap_or_default() as u32,
1204            privileged: self.privileged,
1205            bot: self.bot.map(|bot| bot.into()),
1206            relationship: RelationshipStatus::User,
1207            id: self.id,
1208        }
1209    }
1210
1211    pub fn as_author_for_system(&self) -> MessageAuthor {
1212        MessageAuthor::System {
1213            username: &self.username,
1214            avatar: self.avatar.as_ref().map(|file| file.id.as_ref()),
1215        }
1216    }
1217}
1218
1219impl From<User> for crate::User {
1220    fn from(value: User) -> crate::User {
1221        crate::User {
1222            id: value.id,
1223            username: value.username,
1224            discriminator: value.discriminator,
1225            display_name: value.display_name,
1226            pronouns: value.pronouns,
1227            avatar: value.avatar.map(Into::into),
1228            relations: None,
1229            badges: Some(value.badges as i32),
1230            status: value.status.map(Into::into),
1231            profile: None,
1232            flags: Some(value.flags as i32),
1233            privileged: value.privileged,
1234            bot: value.bot.map(Into::into),
1235            suspended_until: None,
1236            last_acknowledged_policy_change: Timestamp::UNIX_EPOCH,
1237        }
1238    }
1239}
1240
1241impl From<crate::PartialUser> for PartialUser {
1242    fn from(value: crate::PartialUser) -> Self {
1243        PartialUser {
1244            username: value.username,
1245            discriminator: value.discriminator,
1246            display_name: value.display_name,
1247            pronouns: value.pronouns,
1248            avatar: value.avatar.map(|file| file.into()),
1249            relations: value.relations.map(|relationships| {
1250                relationships
1251                    .into_iter()
1252                    .map(|relationship| relationship.into())
1253                    .collect()
1254            }),
1255            badges: value.badges.map(|badges| badges as u32),
1256            status: value.status.and_then(|status| status.into(false)),
1257            flags: value.flags.map(|flags| flags as u32),
1258            privileged: value.privileged,
1259            bot: value.bot.map(|bot| bot.into()),
1260            relationship: None,
1261            online: None,
1262            id: value.id,
1263        }
1264    }
1265}
1266
1267impl From<FieldsUser> for crate::FieldsUser {
1268    fn from(value: FieldsUser) -> Self {
1269        match value {
1270            FieldsUser::Avatar => crate::FieldsUser::Avatar,
1271            FieldsUser::ProfileBackground => crate::FieldsUser::ProfileBackground,
1272            FieldsUser::ProfileContent => crate::FieldsUser::ProfileContent,
1273            FieldsUser::StatusPresence => crate::FieldsUser::StatusPresence,
1274            FieldsUser::StatusText => crate::FieldsUser::StatusText,
1275            FieldsUser::DisplayName => crate::FieldsUser::DisplayName,
1276            FieldsUser::Pronouns => crate::FieldsUser::Pronouns,
1277
1278            FieldsUser::Internal => crate::FieldsUser::None,
1279        }
1280    }
1281}
1282
1283impl From<crate::FieldsUser> for FieldsUser {
1284    fn from(value: crate::FieldsUser) -> Self {
1285        match value {
1286            crate::FieldsUser::Avatar => FieldsUser::Avatar,
1287            crate::FieldsUser::ProfileBackground => FieldsUser::ProfileBackground,
1288            crate::FieldsUser::ProfileContent => FieldsUser::ProfileContent,
1289            crate::FieldsUser::StatusPresence => FieldsUser::StatusPresence,
1290            crate::FieldsUser::StatusText => FieldsUser::StatusText,
1291            crate::FieldsUser::DisplayName => FieldsUser::DisplayName,
1292            crate::FieldsUser::Pronouns => FieldsUser::Pronouns,
1293
1294            crate::FieldsUser::Suspension => FieldsUser::Internal,
1295            crate::FieldsUser::None => FieldsUser::Internal,
1296        }
1297    }
1298}
1299
1300impl From<crate::RelationshipStatus> for RelationshipStatus {
1301    fn from(value: crate::RelationshipStatus) -> Self {
1302        match value {
1303            crate::RelationshipStatus::None => RelationshipStatus::None,
1304            crate::RelationshipStatus::User => RelationshipStatus::User,
1305            crate::RelationshipStatus::Friend => RelationshipStatus::Friend,
1306            crate::RelationshipStatus::Outgoing => RelationshipStatus::Outgoing,
1307            crate::RelationshipStatus::Incoming => RelationshipStatus::Incoming,
1308            crate::RelationshipStatus::Blocked => RelationshipStatus::Blocked,
1309            crate::RelationshipStatus::BlockedOther => RelationshipStatus::BlockedOther,
1310        }
1311    }
1312}
1313
1314impl From<crate::Relationship> for Relationship {
1315    fn from(value: crate::Relationship) -> Self {
1316        Self {
1317            user_id: value.id,
1318            status: value.status.into(),
1319        }
1320    }
1321}
1322
1323impl From<crate::Presence> for Presence {
1324    fn from(value: crate::Presence) -> Self {
1325        match value {
1326            crate::Presence::Online => Presence::Online,
1327            crate::Presence::Idle => Presence::Idle,
1328            crate::Presence::Focus => Presence::Focus,
1329            crate::Presence::Busy => Presence::Busy,
1330            crate::Presence::Invisible => Presence::Invisible,
1331        }
1332    }
1333}
1334
1335impl From<Presence> for crate::Presence {
1336    fn from(value: Presence) -> crate::Presence {
1337        match value {
1338            Presence::Online => crate::Presence::Online,
1339            Presence::Idle => crate::Presence::Idle,
1340            Presence::Focus => crate::Presence::Focus,
1341            Presence::Busy => crate::Presence::Busy,
1342            Presence::Invisible => crate::Presence::Invisible,
1343        }
1344    }
1345}
1346
1347impl crate::UserStatus {
1348    fn into(self, discard_invisible: bool) -> Option<UserStatus> {
1349        let status = UserStatus {
1350            text: self.text,
1351            presence: self.presence.and_then(|presence| {
1352                if discard_invisible && presence == crate::Presence::Invisible {
1353                    None
1354                } else {
1355                    Some(presence.into())
1356                }
1357            }),
1358        };
1359
1360        if status.text.is_none() && status.presence.is_none() {
1361            None
1362        } else {
1363            Some(status)
1364        }
1365    }
1366}
1367
1368impl From<UserStatus> for crate::UserStatus {
1369    fn from(value: UserStatus) -> crate::UserStatus {
1370        crate::UserStatus {
1371            text: value.text,
1372            presence: value.presence.map(|presence| presence.into()),
1373        }
1374    }
1375}
1376
1377impl From<crate::UserProfile> for UserProfile {
1378    fn from(value: crate::UserProfile) -> Self {
1379        UserProfile {
1380            content: value.content,
1381            background: value.background.map(|file| file.into()),
1382        }
1383    }
1384}
1385
1386impl From<UserProfile> for crate::UserProfile {
1387    fn from(value: UserProfile) -> crate::UserProfile {
1388        crate::UserProfile {
1389            content: value.content,
1390            background: value.background.map(|file| file.into()),
1391        }
1392    }
1393}
1394
1395impl From<crate::BotInformation> for BotInformation {
1396    fn from(value: crate::BotInformation) -> Self {
1397        BotInformation {
1398            owner_id: value.owner,
1399        }
1400    }
1401}
1402
1403impl From<BotInformation> for crate::BotInformation {
1404    fn from(value: BotInformation) -> crate::BotInformation {
1405        crate::BotInformation {
1406            owner: value.owner_id,
1407        }
1408    }
1409}
1410
1411impl From<crate::FieldsMessage> for FieldsMessage {
1412    fn from(value: crate::FieldsMessage) -> Self {
1413        match value {
1414            crate::FieldsMessage::Pinned => FieldsMessage::Pinned,
1415        }
1416    }
1417}
1418impl From<FieldsMessage> for crate::FieldsMessage {
1419    fn from(value: FieldsMessage) -> Self {
1420        match value {
1421            FieldsMessage::Pinned => crate::FieldsMessage::Pinned,
1422        }
1423    }
1424}
1425
1426impl From<crate::VoiceInformation> for VoiceInformation {
1427    fn from(value: crate::VoiceInformation) -> Self {
1428        VoiceInformation {
1429            max_users: value.max_users,
1430        }
1431    }
1432}
1433
1434impl From<VoiceInformation> for crate::VoiceInformation {
1435    fn from(value: VoiceInformation) -> Self {
1436        crate::VoiceInformation {
1437            max_users: value.max_users,
1438        }
1439    }
1440}
1441
1442impl From<crate::AuditLogEntryAction> for AuditLogEntryAction {
1443    fn from(value: crate::AuditLogEntryAction) -> Self {
1444        match value {
1445            crate::AuditLogEntryAction::MessageDelete { author, channel } => {
1446                AuditLogEntryAction::MessageDelete { author, channel }
1447            }
1448            crate::AuditLogEntryAction::BanCreate { user } => {
1449                AuditLogEntryAction::BanCreate { user }
1450            }
1451            crate::AuditLogEntryAction::BanDelete { user } => {
1452                AuditLogEntryAction::BanDelete { user }
1453            }
1454            crate::AuditLogEntryAction::ChannelCreate { channel, name } => {
1455                AuditLogEntryAction::ChannelCreate { channel, name }
1456            }
1457            crate::AuditLogEntryAction::MemberEdit {
1458                user,
1459                before,
1460                after,
1461            } => AuditLogEntryAction::MemberEdit {
1462                user,
1463                before: before.into(),
1464                after: after.into(),
1465            },
1466            crate::AuditLogEntryAction::MemberKick { user } => {
1467                AuditLogEntryAction::MemberKick { user }
1468            }
1469            crate::AuditLogEntryAction::ServerEdit { before, after } => {
1470                AuditLogEntryAction::ServerEdit {
1471                    before: before.into(),
1472                    after: after.into(),
1473                }
1474            }
1475            crate::AuditLogEntryAction::RoleEdit {
1476                role,
1477                before,
1478                after,
1479            } => AuditLogEntryAction::RoleEdit {
1480                role,
1481                before: before.into(),
1482                after: after.into(),
1483            },
1484            crate::AuditLogEntryAction::RoleCreate { role, name } => {
1485                AuditLogEntryAction::RoleCreate { role, name }
1486            }
1487            crate::AuditLogEntryAction::RoleDelete { role, name } => {
1488                AuditLogEntryAction::RoleDelete { role, name }
1489            }
1490            crate::AuditLogEntryAction::RolesReorder { before, after } => {
1491                AuditLogEntryAction::RolesReorder { before, after }
1492            }
1493            crate::AuditLogEntryAction::MessageBulkDelete { channel, count } => {
1494                AuditLogEntryAction::MessageBulkDelete { channel, count }
1495            }
1496            crate::AuditLogEntryAction::ChannelEdit {
1497                channel,
1498                before,
1499                after,
1500            } => AuditLogEntryAction::ChannelEdit {
1501                channel,
1502                before: before.into(),
1503                after: after.into(),
1504            },
1505            crate::AuditLogEntryAction::ChannelRolePermissionsEdit {
1506                channel,
1507                role,
1508                permissions,
1509            } => AuditLogEntryAction::ChannelRolePermissionsEdit {
1510                channel,
1511                role,
1512                permissions: permissions.into(),
1513            },
1514            crate::AuditLogEntryAction::ChannelDelete { channel, name } => {
1515                AuditLogEntryAction::ChannelDelete { channel, name }
1516            }
1517            crate::AuditLogEntryAction::InviteDelete { invite, channel } => {
1518                AuditLogEntryAction::InviteDelete { invite, channel }
1519            }
1520            crate::AuditLogEntryAction::WebhookCreate {
1521                webhook,
1522                name,
1523                channel,
1524            } => AuditLogEntryAction::WebhookCreate {
1525                webhook,
1526                name,
1527                channel,
1528            },
1529            crate::AuditLogEntryAction::WebhookDelete {
1530                webhook,
1531                name,
1532                channel,
1533            } => AuditLogEntryAction::WebhookDelete {
1534                webhook,
1535                name,
1536                channel,
1537            },
1538            crate::AuditLogEntryAction::EmojiCreate { emoji, name } => {
1539                AuditLogEntryAction::EmojiCreate { emoji, name }
1540            }
1541            crate::AuditLogEntryAction::EmojiUpdate {
1542                emoji,
1543                before,
1544                after,
1545            } => AuditLogEntryAction::EmojiUpdate {
1546                emoji,
1547                before: before.into(),
1548                after: after.into(),
1549            },
1550            crate::AuditLogEntryAction::EmojiDelete { emoji, name } => {
1551                AuditLogEntryAction::EmojiDelete { emoji, name }
1552            }
1553            crate::AuditLogEntryAction::MessagePin {
1554                message,
1555                author,
1556                channel,
1557            } => AuditLogEntryAction::MessagePin {
1558                message,
1559                author,
1560                channel,
1561            },
1562            crate::AuditLogEntryAction::MessageUnpin {
1563                message,
1564                author,
1565                channel,
1566            } => AuditLogEntryAction::MessageUnpin {
1567                message,
1568                author,
1569                channel,
1570            },
1571            crate::AuditLogEntryAction::InviteCreate { invite, channel } => {
1572                AuditLogEntryAction::InviteCreate { invite, channel }
1573            }
1574        }
1575    }
1576}
1577
1578impl From<crate::AuditLogEntry> for AuditLogEntry {
1579    fn from(value: crate::AuditLogEntry) -> Self {
1580        AuditLogEntry {
1581            id: value.id,
1582            server: value.server,
1583            reason: value.reason,
1584            user: value.user,
1585            target: value.target,
1586            action: value.action.into(),
1587        }
1588    }
1589}
1590
1591impl From<crate::Account> for AccountInfo {
1592    fn from(item: crate::Account) -> Self {
1593        AccountInfo {
1594            id: item.id,
1595            email: item.email,
1596        }
1597    }
1598}
1599
1600impl From<crate::MFATicket> for MFATicket {
1601    fn from(value: crate::MFATicket) -> Self {
1602        MFATicket {
1603            id: value.id,
1604            account_id: value.account_id,
1605            token: value.token,
1606            validated: value.validated,
1607            authorised: value.authorised,
1608            last_totp_code: value.last_totp_code,
1609        }
1610    }
1611}
1612
1613impl From<crate::MultiFactorAuthentication> for MultiFactorStatus {
1614    fn from(item: crate::MultiFactorAuthentication) -> Self {
1615        MultiFactorStatus {
1616            // email_otp: item.enable_email_otp,
1617            // trusted_handover: item.enable_trusted_handover,
1618            // email_mfa: item.enable_email_mfa,
1619            totp_mfa: !item.totp_token.is_disabled(),
1620            // security_key_mfa: item.security_key_token.is_some(),
1621            recovery_active: !item.recovery_codes.is_empty(),
1622            ..Default::default()
1623        }
1624    }
1625}
1626
1627impl From<crate::MFAMethod> for MFAMethod {
1628    fn from(value: crate::MFAMethod) -> Self {
1629        match value {
1630            crate::MFAMethod::Password => MFAMethod::Password,
1631            crate::MFAMethod::Recovery => MFAMethod::Recovery,
1632            crate::MFAMethod::Totp => MFAMethod::Totp,
1633        }
1634    }
1635}
1636
1637impl From<crate::Session> for SessionInfo {
1638    fn from(item: crate::Session) -> Self {
1639        SessionInfo {
1640            id: item.id,
1641            name: item.name,
1642        }
1643    }
1644}
1645
1646impl From<crate::Session> for Session {
1647    fn from(value: crate::Session) -> Self {
1648        Session {
1649            id: value.id,
1650            user_id: value.user_id,
1651            token: value.token,
1652            name: value.name,
1653            last_seen: value.last_seen,
1654            origin: value.origin,
1655            subscription: value.subscription.map(Into::into),
1656        }
1657    }
1658}
1659
1660impl From<crate::WebPushSubscription> for WebPushSubscription {
1661    fn from(value: crate::WebPushSubscription) -> Self {
1662        WebPushSubscription {
1663            endpoint: value.endpoint,
1664            p256dh: value.p256dh,
1665            auth: value.auth,
1666        }
1667    }
1668}
1669
1670impl From<WebPushSubscription> for crate::WebPushSubscription {
1671    fn from(value: WebPushSubscription) -> Self {
1672        crate::WebPushSubscription {
1673            endpoint: value.endpoint,
1674            p256dh: value.p256dh,
1675            auth: value.auth,
1676        }
1677    }
1678}
1679
1680impl From<crate::PartialEmoji> for PartialEmoji {
1681    fn from(value: crate::PartialEmoji) -> Self {
1682        PartialEmoji { name: value.name }
1683    }
1684}