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        }
323    }
324}
325
326impl From<crate::FieldsChannel> for FieldsChannel {
327    fn from(value: crate::FieldsChannel) -> Self {
328        match value {
329            crate::FieldsChannel::Description => FieldsChannel::Description,
330            crate::FieldsChannel::Icon => FieldsChannel::Icon,
331            crate::FieldsChannel::DefaultPermissions => FieldsChannel::DefaultPermissions,
332            crate::FieldsChannel::Voice => FieldsChannel::Voice,
333        }
334    }
335}
336
337impl From<crate::Emoji> for Emoji {
338    fn from(value: crate::Emoji) -> Self {
339        Emoji {
340            id: value.id,
341            parent: value.parent.into(),
342            creator_id: value.creator_id,
343            name: value.name,
344            animated: value.animated,
345            nsfw: value.nsfw,
346        }
347    }
348}
349
350impl From<crate::EmojiParent> for EmojiParent {
351    fn from(value: crate::EmojiParent) -> Self {
352        match value {
353            crate::EmojiParent::Detached => EmojiParent::Detached,
354            crate::EmojiParent::Server { id } => EmojiParent::Server { id },
355        }
356    }
357}
358
359impl From<EmojiParent> for crate::EmojiParent {
360    fn from(value: EmojiParent) -> Self {
361        match value {
362            EmojiParent::Detached => crate::EmojiParent::Detached,
363            EmojiParent::Server { id } => crate::EmojiParent::Server { id },
364        }
365    }
366}
367
368impl From<crate::File> for File {
369    fn from(value: crate::File) -> Self {
370        File {
371            id: value.id,
372            tag: value.tag,
373            filename: value.filename,
374            metadata: value.metadata.into(),
375            content_type: value.content_type,
376            size: value.size,
377            deleted: value.deleted,
378            reported: value.reported,
379            message_id: value.message_id,
380            user_id: value.user_id,
381            server_id: value.server_id,
382            object_id: value.object_id,
383        }
384    }
385}
386
387impl From<File> for crate::File {
388    fn from(value: File) -> crate::File {
389        crate::File {
390            id: value.id,
391            tag: value.tag,
392            filename: value.filename,
393            metadata: value.metadata.into(),
394            content_type: value.content_type,
395            size: value.size,
396            deleted: value.deleted,
397            reported: value.reported,
398            message_id: value.message_id,
399            user_id: value.user_id,
400            server_id: value.server_id,
401            object_id: value.object_id,
402            hash: None,
403            uploaded_at: None,
404            uploader_id: None,
405            used_for: None,
406        }
407    }
408}
409
410impl From<crate::Metadata> for Metadata {
411    fn from(value: crate::Metadata) -> Self {
412        match value {
413            crate::Metadata::File => Metadata::File,
414            crate::Metadata::Text => Metadata::Text,
415            crate::Metadata::Image {
416                width,
417                height,
418                thumbhash,
419                animated,
420            } => Metadata::Image {
421                width: width as usize,
422                height: height as usize,
423                thumbhash,
424                animated,
425            },
426            crate::Metadata::Video { width, height } => Metadata::Video {
427                width: width as usize,
428                height: height as usize,
429            },
430            crate::Metadata::Audio => Metadata::Audio,
431        }
432    }
433}
434
435impl From<Metadata> for crate::Metadata {
436    fn from(value: Metadata) -> crate::Metadata {
437        match value {
438            Metadata::File => crate::Metadata::File,
439            Metadata::Text => crate::Metadata::Text,
440            Metadata::Image {
441                width,
442                height,
443                thumbhash,
444                animated,
445            } => crate::Metadata::Image {
446                width: width as isize,
447                height: height as isize,
448                thumbhash,
449                animated,
450            },
451            Metadata::Video { width, height } => crate::Metadata::Video {
452                width: width as isize,
453                height: height as isize,
454            },
455            Metadata::Audio => crate::Metadata::Audio,
456        }
457    }
458}
459
460impl crate::Message {
461    pub fn into_model(self, user: Option<User>, member: Option<Member>) -> Message {
462        Message {
463            id: self.id,
464            nonce: self.nonce,
465            channel: self.channel,
466            author: self.author,
467            user,
468            member,
469            webhook: self.webhook,
470            content: self.content,
471            system: self.system.map(Into::into),
472            attachments: self
473                .attachments
474                .map(|v| v.into_iter().map(|f| f.into()).collect()),
475            edited: self.edited,
476            embeds: self.embeds,
477            mentions: self.mentions,
478            role_mentions: self.role_mentions,
479            replies: self.replies,
480            reactions: self.reactions,
481            interactions: self.interactions.into(),
482            masquerade: self.masquerade.map(Into::into),
483            flags: self.flags.unwrap_or_default(),
484            pinned: self.pinned,
485        }
486    }
487}
488
489impl From<crate::PartialMessage> for PartialMessage {
490    fn from(value: crate::PartialMessage) -> Self {
491        PartialMessage {
492            id: value.id,
493            nonce: value.nonce,
494            channel: value.channel,
495            author: value.author,
496            user: None,
497            member: None,
498            webhook: value.webhook,
499            content: value.content,
500            system: value.system.map(Into::into),
501            attachments: value
502                .attachments
503                .map(|v| v.into_iter().map(|f| f.into()).collect()),
504            edited: value.edited,
505            embeds: value.embeds,
506            mentions: value.mentions,
507            role_mentions: value.role_mentions,
508            replies: value.replies,
509            reactions: value.reactions,
510            interactions: value.interactions.map(Into::into),
511            masquerade: value.masquerade.map(Into::into),
512            flags: value.flags,
513            pinned: value.pinned,
514        }
515    }
516}
517
518impl From<crate::SystemMessage> for SystemMessage {
519    fn from(value: crate::SystemMessage) -> Self {
520        match value {
521            crate::SystemMessage::ChannelDescriptionChanged { by } => {
522                Self::ChannelDescriptionChanged { by }
523            }
524            crate::SystemMessage::ChannelIconChanged { by } => Self::ChannelIconChanged { by },
525            crate::SystemMessage::ChannelOwnershipChanged { from, to } => {
526                Self::ChannelOwnershipChanged { from, to }
527            }
528            crate::SystemMessage::ChannelRenamed { name, by } => Self::ChannelRenamed { name, by },
529            crate::SystemMessage::Text { content } => Self::Text { content },
530            crate::SystemMessage::UserAdded { id, by } => Self::UserAdded { id, by },
531            crate::SystemMessage::UserBanned { id } => Self::UserBanned { id },
532            crate::SystemMessage::UserJoined { id } => Self::UserJoined { id },
533            crate::SystemMessage::UserKicked { id } => Self::UserKicked { id },
534            crate::SystemMessage::UserLeft { id } => Self::UserLeft { id },
535            crate::SystemMessage::UserRemove { id, by } => Self::UserRemove { id, by },
536            crate::SystemMessage::MessagePinned { id, by } => Self::MessagePinned { id, by },
537            crate::SystemMessage::MessageUnpinned { id, by } => Self::MessageUnpinned { id, by },
538            crate::SystemMessage::CallStarted { by, finished_at } => {
539                Self::CallStarted { by, finished_at }
540            }
541        }
542    }
543}
544
545impl From<crate::Interactions> for Interactions {
546    fn from(value: crate::Interactions) -> Self {
547        Interactions {
548            reactions: value
549                .reactions
550                .map(|reactions| reactions.into_iter().collect()),
551            restrict_reactions: value.restrict_reactions,
552        }
553    }
554}
555
556impl From<Interactions> for crate::Interactions {
557    fn from(value: Interactions) -> Self {
558        crate::Interactions {
559            reactions: value
560                .reactions
561                .map(|reactions| reactions.into_iter().collect()),
562            restrict_reactions: value.restrict_reactions,
563        }
564    }
565}
566
567impl From<crate::AppendMessage> for AppendMessage {
568    fn from(value: crate::AppendMessage) -> Self {
569        AppendMessage {
570            embeds: value.embeds,
571        }
572    }
573}
574
575impl From<crate::Masquerade> for Masquerade {
576    fn from(value: crate::Masquerade) -> Self {
577        Masquerade {
578            name: value.name,
579            avatar: value.avatar,
580            colour: value.colour,
581        }
582    }
583}
584
585impl From<Masquerade> for crate::Masquerade {
586    fn from(value: Masquerade) -> Self {
587        crate::Masquerade {
588            name: value.name,
589            avatar: value.avatar,
590            colour: value.colour,
591        }
592    }
593}
594
595impl From<crate::PolicyChange> for PolicyChange {
596    fn from(value: crate::PolicyChange) -> Self {
597        PolicyChange {
598            created_time: value.created_time,
599            effective_time: value.effective_time,
600            description: value.description,
601            url: value.url,
602        }
603    }
604}
605
606impl From<crate::Report> for Report {
607    fn from(value: crate::Report) -> Self {
608        Report {
609            id: value.id,
610            author_id: value.author_id,
611            content: value.content,
612            additional_context: value.additional_context,
613            status: value.status,
614            notes: value.notes,
615        }
616    }
617}
618
619impl From<crate::ServerBan> for ServerBan {
620    fn from(value: crate::ServerBan) -> Self {
621        ServerBan {
622            id: value.id.into(),
623            reason: value.reason,
624        }
625    }
626}
627
628impl From<crate::Member> for Member {
629    fn from(value: crate::Member) -> Self {
630        Member {
631            id: value.id.into(),
632            joined_at: value.joined_at,
633            nickname: value.nickname,
634            avatar: value.avatar.map(|f| f.into()),
635            roles: value.roles,
636            timeout: value.timeout,
637            can_publish: value.can_publish,
638            can_receive: value.can_receive,
639        }
640    }
641}
642
643impl From<Member> for crate::Member {
644    fn from(value: Member) -> crate::Member {
645        crate::Member {
646            id: value.id.into(),
647            joined_at: value.joined_at,
648            nickname: value.nickname,
649            avatar: value.avatar.map(|f| f.into()),
650            roles: value.roles,
651            timeout: value.timeout,
652            can_publish: value.can_publish,
653            can_receive: value.can_receive,
654        }
655    }
656}
657
658impl From<crate::PartialMember> for PartialMember {
659    fn from(value: crate::PartialMember) -> Self {
660        PartialMember {
661            id: value.id.map(|id| id.into()),
662            joined_at: value.joined_at,
663            nickname: value.nickname,
664            avatar: value.avatar.map(|f| f.into()),
665            roles: value.roles,
666            timeout: value.timeout,
667            can_publish: value.can_publish,
668            can_receive: value.can_receive,
669        }
670    }
671}
672
673impl From<PartialMember> for crate::PartialMember {
674    fn from(value: PartialMember) -> crate::PartialMember {
675        crate::PartialMember {
676            id: value.id.map(|id| id.into()),
677            joined_at: value.joined_at,
678            nickname: value.nickname,
679            avatar: value.avatar.map(|f| f.into()),
680            roles: value.roles,
681            timeout: value.timeout,
682            can_publish: value.can_publish,
683            can_receive: value.can_receive,
684        }
685    }
686}
687
688impl From<crate::MemberCompositeKey> for MemberCompositeKey {
689    fn from(value: crate::MemberCompositeKey) -> Self {
690        MemberCompositeKey {
691            server: value.server,
692            user: value.user,
693        }
694    }
695}
696
697impl From<MemberCompositeKey> for crate::MemberCompositeKey {
698    fn from(value: MemberCompositeKey) -> crate::MemberCompositeKey {
699        crate::MemberCompositeKey {
700            server: value.server,
701            user: value.user,
702        }
703    }
704}
705
706impl From<crate::FieldsMember> for FieldsMember {
707    fn from(value: crate::FieldsMember) -> Self {
708        match value {
709            crate::FieldsMember::Avatar => FieldsMember::Avatar,
710            crate::FieldsMember::Nickname => FieldsMember::Nickname,
711            crate::FieldsMember::Roles => FieldsMember::Roles,
712            crate::FieldsMember::Timeout => FieldsMember::Timeout,
713            crate::FieldsMember::CanReceive => FieldsMember::CanReceive,
714            crate::FieldsMember::CanPublish => FieldsMember::CanPublish,
715            crate::FieldsMember::JoinedAt => FieldsMember::JoinedAt,
716            crate::FieldsMember::VoiceChannel => FieldsMember::VoiceChannel,
717        }
718    }
719}
720
721impl From<FieldsMember> for crate::FieldsMember {
722    fn from(value: FieldsMember) -> crate::FieldsMember {
723        match value {
724            FieldsMember::Avatar => crate::FieldsMember::Avatar,
725            FieldsMember::Nickname => crate::FieldsMember::Nickname,
726            FieldsMember::Roles => crate::FieldsMember::Roles,
727            FieldsMember::Timeout => crate::FieldsMember::Timeout,
728            FieldsMember::CanReceive => crate::FieldsMember::CanReceive,
729            FieldsMember::CanPublish => crate::FieldsMember::CanPublish,
730            FieldsMember::JoinedAt => crate::FieldsMember::JoinedAt,
731            FieldsMember::VoiceChannel => crate::FieldsMember::VoiceChannel,
732        }
733    }
734}
735
736impl From<crate::RemovalIntention> for RemovalIntention {
737    fn from(value: crate::RemovalIntention) -> Self {
738        match value {
739            crate::RemovalIntention::Ban => RemovalIntention::Ban,
740            crate::RemovalIntention::Kick => RemovalIntention::Kick,
741            crate::RemovalIntention::Leave => RemovalIntention::Leave,
742        }
743    }
744}
745
746impl From<crate::Server> for Server {
747    fn from(value: crate::Server) -> Self {
748        Server {
749            id: value.id,
750            owner: value.owner,
751            name: value.name,
752            description: value.description,
753            channels: value.channels,
754            categories: value
755                .categories
756                .map(|categories| categories.into_iter().map(|v| v.into()).collect()),
757            system_messages: value.system_messages.map(|v| v.into()),
758            roles: value
759                .roles
760                .into_iter()
761                .map(|(k, v)| (k, v.into()))
762                .collect(),
763            default_permissions: value.default_permissions,
764            icon: value.icon.map(|f| f.into()),
765            banner: value.banner.map(|f| f.into()),
766            flags: value.flags.unwrap_or_default() as u32,
767            nsfw: value.nsfw,
768            analytics: value.analytics,
769            discoverable: value.discoverable,
770        }
771    }
772}
773
774impl From<Server> for crate::Server {
775    fn from(value: Server) -> crate::Server {
776        crate::Server {
777            id: value.id,
778            owner: value.owner,
779            name: value.name,
780            description: value.description,
781            channels: value.channels,
782            categories: value
783                .categories
784                .map(|categories| categories.into_iter().map(|v| v.into()).collect()),
785            system_messages: value.system_messages.map(|v| v.into()),
786            roles: value
787                .roles
788                .into_iter()
789                .map(|(k, v)| (k, v.into()))
790                .collect(),
791            default_permissions: value.default_permissions,
792            icon: value.icon.map(|f| f.into()),
793            banner: value.banner.map(|f| f.into()),
794            flags: Some(value.flags as i32),
795            nsfw: value.nsfw,
796            analytics: value.analytics,
797            discoverable: value.discoverable,
798        }
799    }
800}
801
802impl From<crate::PartialServer> for PartialServer {
803    fn from(value: crate::PartialServer) -> Self {
804        PartialServer {
805            id: value.id,
806            owner: value.owner,
807            name: value.name,
808            description: value.description,
809            channels: value.channels,
810            categories: value
811                .categories
812                .map(|categories| categories.into_iter().map(|v| v.into()).collect()),
813            system_messages: value.system_messages.map(|v| v.into()),
814            roles: value
815                .roles
816                .map(|roles| roles.into_iter().map(|(k, v)| (k, v.into())).collect()),
817            default_permissions: value.default_permissions,
818            icon: value.icon.map(|f| f.into()),
819            banner: value.banner.map(|f| f.into()),
820            flags: value.flags.map(|v| v as u32),
821            nsfw: value.nsfw,
822            analytics: value.analytics,
823            discoverable: value.discoverable,
824        }
825    }
826}
827
828impl From<PartialServer> for crate::PartialServer {
829    fn from(value: PartialServer) -> crate::PartialServer {
830        crate::PartialServer {
831            id: value.id,
832            owner: value.owner,
833            name: value.name,
834            description: value.description,
835            channels: value.channels,
836            categories: value
837                .categories
838                .map(|categories| categories.into_iter().map(|v| v.into()).collect()),
839            system_messages: value.system_messages.map(|v| v.into()),
840            roles: value
841                .roles
842                .map(|roles| roles.into_iter().map(|(k, v)| (k, v.into())).collect()),
843            default_permissions: value.default_permissions,
844            icon: value.icon.map(|f| f.into()),
845            banner: value.banner.map(|f| f.into()),
846            flags: value.flags.map(|v| v as i32),
847            nsfw: value.nsfw,
848            analytics: value.analytics,
849            discoverable: value.discoverable,
850        }
851    }
852}
853
854impl From<crate::FieldsServer> for FieldsServer {
855    fn from(value: crate::FieldsServer) -> Self {
856        match value {
857            crate::FieldsServer::Banner => FieldsServer::Banner,
858            crate::FieldsServer::Categories => FieldsServer::Categories,
859            crate::FieldsServer::Description => FieldsServer::Description,
860            crate::FieldsServer::Icon => FieldsServer::Icon,
861            crate::FieldsServer::SystemMessages => FieldsServer::SystemMessages,
862        }
863    }
864}
865
866impl From<FieldsServer> for crate::FieldsServer {
867    fn from(value: FieldsServer) -> crate::FieldsServer {
868        match value {
869            FieldsServer::Banner => crate::FieldsServer::Banner,
870            FieldsServer::Categories => crate::FieldsServer::Categories,
871            FieldsServer::Description => crate::FieldsServer::Description,
872            FieldsServer::Icon => crate::FieldsServer::Icon,
873            FieldsServer::SystemMessages => crate::FieldsServer::SystemMessages,
874        }
875    }
876}
877
878impl From<crate::Category> for Category {
879    fn from(value: crate::Category) -> Self {
880        Category {
881            id: value.id,
882            title: value.title,
883            channels: value.channels,
884        }
885    }
886}
887
888impl From<Category> for crate::Category {
889    fn from(value: Category) -> Self {
890        crate::Category {
891            id: value.id,
892            title: value.title,
893            channels: value.channels,
894        }
895    }
896}
897
898impl From<crate::SystemMessageChannels> for SystemMessageChannels {
899    fn from(value: crate::SystemMessageChannels) -> Self {
900        SystemMessageChannels {
901            user_joined: value.user_joined,
902            user_left: value.user_left,
903            user_kicked: value.user_kicked,
904            user_banned: value.user_banned,
905        }
906    }
907}
908
909impl From<SystemMessageChannels> for crate::SystemMessageChannels {
910    fn from(value: SystemMessageChannels) -> Self {
911        crate::SystemMessageChannels {
912            user_joined: value.user_joined,
913            user_left: value.user_left,
914            user_kicked: value.user_kicked,
915            user_banned: value.user_banned,
916        }
917    }
918}
919
920impl From<crate::Role> for Role {
921    fn from(value: crate::Role) -> Self {
922        Role {
923            id: value.id,
924            name: value.name,
925            permissions: value.permissions,
926            colour: value.colour,
927            hoist: value.hoist,
928            rank: value.rank,
929            icon: value.icon.map(|f| f.into()),
930        }
931    }
932}
933
934impl From<Role> for crate::Role {
935    fn from(value: Role) -> crate::Role {
936        crate::Role {
937            id: value.id,
938            name: value.name,
939            permissions: value.permissions,
940            colour: value.colour,
941            hoist: value.hoist,
942            rank: value.rank,
943            icon: value.icon.map(|f| f.into()),
944        }
945    }
946}
947
948impl From<crate::PartialRole> for PartialRole {
949    fn from(value: crate::PartialRole) -> Self {
950        PartialRole {
951            id: value.id,
952            name: value.name,
953            permissions: value.permissions,
954            colour: value.colour,
955            hoist: value.hoist,
956            rank: value.rank,
957            icon: value.icon.map(|f| f.into()),
958        }
959    }
960}
961
962impl From<PartialRole> for crate::PartialRole {
963    fn from(value: PartialRole) -> crate::PartialRole {
964        crate::PartialRole {
965            id: value.id,
966            name: value.name,
967            permissions: value.permissions,
968            colour: value.colour,
969            hoist: value.hoist,
970            rank: value.rank,
971            icon: value.icon.map(|f| f.into()),
972        }
973    }
974}
975
976impl From<crate::FieldsRole> for FieldsRole {
977    fn from(value: crate::FieldsRole) -> Self {
978        match value {
979            crate::FieldsRole::Colour => FieldsRole::Colour,
980            crate::FieldsRole::Icon => FieldsRole::Icon,
981        }
982    }
983}
984
985impl From<FieldsRole> for crate::FieldsRole {
986    fn from(value: FieldsRole) -> Self {
987        match value {
988            FieldsRole::Colour => crate::FieldsRole::Colour,
989            FieldsRole::Icon => crate::FieldsRole::Icon,
990        }
991    }
992}
993
994impl crate::User {
995    pub async fn into<'a, P>(self, db: &Database, perspective: P) -> User
996    where
997        P: Into<Option<&'a crate::User>>,
998    {
999        let perspective = perspective.into();
1000        let (relationship, can_see_profile) = if self.bot.is_some() {
1001            (RelationshipStatus::None, true)
1002        } else if let Some(perspective) = perspective {
1003            let mut query = DatabasePermissionQuery::new(db, perspective).user(&self);
1004
1005            if perspective.id == self.id {
1006                (RelationshipStatus::User, true)
1007            } else {
1008                (
1009                    perspective
1010                        .relations
1011                        .as_ref()
1012                        .map(|relations| {
1013                            relations
1014                                .iter()
1015                                .find(|relationship| relationship.id == self.id)
1016                                .map(|relationship| relationship.status.clone().into())
1017                                .unwrap_or_default()
1018                        })
1019                        .unwrap_or_default(),
1020                    calculate_user_permissions(&mut query)
1021                        .await
1022                        .has_user_permission(UserPermission::ViewProfile),
1023                )
1024            }
1025        } else {
1026            (RelationshipStatus::None, false)
1027        };
1028
1029        let badges = self.get_badges().await;
1030
1031        User {
1032            username: self.username,
1033            discriminator: self.discriminator,
1034            display_name: self.display_name,
1035            avatar: self.avatar.map(|file| file.into()),
1036            relations: if let Some(crate::User { id, .. }) = perspective {
1037                if id == &self.id {
1038                    self.relations
1039                        .unwrap_or_default()
1040                        .into_iter()
1041                        .map(|relation| relation.into())
1042                        .collect()
1043                } else {
1044                    vec![]
1045                }
1046            } else {
1047                vec![]
1048            },
1049            badges,
1050            online: can_see_profile
1051                && revolt_presence::is_online(&self.id).await
1052                && !matches!(
1053                    self.status,
1054                    Some(crate::UserStatus {
1055                        presence: Some(crate::Presence::Invisible),
1056                        ..
1057                    })
1058                ),
1059            status: if can_see_profile {
1060                self.status.and_then(|status| status.into(true))
1061            } else {
1062                None
1063            },
1064            flags: self.flags.unwrap_or_default() as u32,
1065            privileged: self.privileged,
1066            bot: self.bot.map(|bot| bot.into()),
1067            relationship,
1068            id: self.id,
1069        }
1070    }
1071
1072    /// Convert user object into user model assuming mutual connection
1073    ///
1074    /// Relations will never be included, i.e. when we process ourselves
1075    pub async fn into_known<'a, P>(self, perspective: P, is_online: bool) -> User
1076    where
1077        P: Into<Option<&'a crate::User>>,
1078    {
1079        let perspective = perspective.into();
1080        let (relationship, can_see_profile) = if self.bot.is_some() {
1081            (RelationshipStatus::None, true)
1082        } else if let Some(perspective) = perspective {
1083            if perspective.id == self.id {
1084                (RelationshipStatus::User, true)
1085            } else {
1086                let relationship = perspective
1087                    .relations
1088                    .as_ref()
1089                    .map(|relations| {
1090                        relations
1091                            .iter()
1092                            .find(|relationship| relationship.id == self.id)
1093                            .map(|relationship| relationship.status.clone().into())
1094                            .unwrap_or_default()
1095                    })
1096                    .unwrap_or_default();
1097
1098                let can_see_profile = relationship != RelationshipStatus::BlockedOther;
1099                (relationship, can_see_profile)
1100            }
1101        } else {
1102            (RelationshipStatus::None, false)
1103        };
1104
1105        let badges = self.get_badges().await;
1106
1107        User {
1108            username: self.username,
1109            discriminator: self.discriminator,
1110            display_name: self.display_name,
1111            avatar: self.avatar.map(|file| file.into()),
1112            relations: vec![],
1113            badges,
1114            online: can_see_profile
1115                && is_online
1116                && !matches!(
1117                    self.status,
1118                    Some(crate::UserStatus {
1119                        presence: Some(crate::Presence::Invisible),
1120                        ..
1121                    })
1122                ),
1123            status: if can_see_profile {
1124                self.status.and_then(|status| status.into(true))
1125            } else {
1126                None
1127            },
1128            flags: self.flags.unwrap_or_default() as u32,
1129            privileged: self.privileged,
1130            bot: self.bot.map(|bot| bot.into()),
1131            relationship,
1132            id: self.id,
1133        }
1134    }
1135
1136    /// Convert user object into user model without presence information
1137    pub async fn into_known_static(self, is_online: bool) -> User {
1138        let badges = self.get_badges().await;
1139
1140        User {
1141            username: self.username,
1142            discriminator: self.discriminator,
1143            display_name: self.display_name,
1144            avatar: self.avatar.map(|file| file.into()),
1145            relations: vec![],
1146            badges,
1147            online: is_online
1148                && !matches!(
1149                    self.status,
1150                    Some(crate::UserStatus {
1151                        presence: Some(crate::Presence::Invisible),
1152                        ..
1153                    })
1154                ),
1155            status: self.status.and_then(|status| status.into(true)),
1156            flags: self.flags.unwrap_or_default() as u32,
1157            privileged: self.privileged,
1158            bot: self.bot.map(|bot| bot.into()),
1159            relationship: RelationshipStatus::None, // events client will populate this from cache
1160            id: self.id,
1161        }
1162    }
1163
1164    pub async fn into_self(self, force_online: bool) -> User {
1165        let badges = self.get_badges().await;
1166
1167        User {
1168            username: self.username,
1169            discriminator: self.discriminator,
1170            display_name: self.display_name,
1171            avatar: self.avatar.map(|file| file.into()),
1172            relations: self
1173                .relations
1174                .map(|relationships| {
1175                    relationships
1176                        .into_iter()
1177                        .map(|relationship| relationship.into())
1178                        .collect()
1179                })
1180                .unwrap_or_default(),
1181            badges,
1182            online: (force_online || revolt_presence::is_online(&self.id).await)
1183                && !matches!(
1184                    self.status,
1185                    Some(crate::UserStatus {
1186                        presence: Some(crate::Presence::Invisible),
1187                        ..
1188                    })
1189                ),
1190            status: self.status.and_then(|status| status.into(true)),
1191            flags: self.flags.unwrap_or_default() as u32,
1192            privileged: self.privileged,
1193            bot: self.bot.map(|bot| bot.into()),
1194            relationship: RelationshipStatus::User,
1195            id: self.id,
1196        }
1197    }
1198
1199    pub fn as_author_for_system(&self) -> MessageAuthor {
1200        MessageAuthor::System {
1201            username: &self.username,
1202            avatar: self.avatar.as_ref().map(|file| file.id.as_ref()),
1203        }
1204    }
1205}
1206
1207impl From<User> for crate::User {
1208    fn from(value: User) -> crate::User {
1209        crate::User {
1210            id: value.id,
1211            username: value.username,
1212            discriminator: value.discriminator,
1213            display_name: value.display_name,
1214            avatar: value.avatar.map(Into::into),
1215            relations: None,
1216            badges: Some(value.badges as i32),
1217            status: value.status.map(Into::into),
1218            profile: None,
1219            flags: Some(value.flags as i32),
1220            privileged: value.privileged,
1221            bot: value.bot.map(Into::into),
1222            suspended_until: None,
1223            last_acknowledged_policy_change: Timestamp::UNIX_EPOCH,
1224        }
1225    }
1226}
1227
1228impl From<crate::PartialUser> for PartialUser {
1229    fn from(value: crate::PartialUser) -> Self {
1230        PartialUser {
1231            username: value.username,
1232            discriminator: value.discriminator,
1233            display_name: value.display_name,
1234            avatar: value.avatar.map(|file| file.into()),
1235            relations: value.relations.map(|relationships| {
1236                relationships
1237                    .into_iter()
1238                    .map(|relationship| relationship.into())
1239                    .collect()
1240            }),
1241            badges: value.badges.map(|badges| badges as u32),
1242            status: value.status.and_then(|status| status.into(false)),
1243            flags: value.flags.map(|flags| flags as u32),
1244            privileged: value.privileged,
1245            bot: value.bot.map(|bot| bot.into()),
1246            relationship: None,
1247            online: None,
1248            id: value.id,
1249        }
1250    }
1251}
1252
1253impl From<FieldsUser> for crate::FieldsUser {
1254    fn from(value: FieldsUser) -> Self {
1255        match value {
1256            FieldsUser::Avatar => crate::FieldsUser::Avatar,
1257            FieldsUser::ProfileBackground => crate::FieldsUser::ProfileBackground,
1258            FieldsUser::ProfileContent => crate::FieldsUser::ProfileContent,
1259            FieldsUser::StatusPresence => crate::FieldsUser::StatusPresence,
1260            FieldsUser::StatusText => crate::FieldsUser::StatusText,
1261            FieldsUser::DisplayName => crate::FieldsUser::DisplayName,
1262
1263            FieldsUser::Internal => crate::FieldsUser::None,
1264        }
1265    }
1266}
1267
1268impl From<crate::FieldsUser> for FieldsUser {
1269    fn from(value: crate::FieldsUser) -> Self {
1270        match value {
1271            crate::FieldsUser::Avatar => FieldsUser::Avatar,
1272            crate::FieldsUser::ProfileBackground => FieldsUser::ProfileBackground,
1273            crate::FieldsUser::ProfileContent => FieldsUser::ProfileContent,
1274            crate::FieldsUser::StatusPresence => FieldsUser::StatusPresence,
1275            crate::FieldsUser::StatusText => FieldsUser::StatusText,
1276            crate::FieldsUser::DisplayName => FieldsUser::DisplayName,
1277
1278            crate::FieldsUser::Suspension => FieldsUser::Internal,
1279            crate::FieldsUser::None => FieldsUser::Internal,
1280        }
1281    }
1282}
1283
1284impl From<crate::RelationshipStatus> for RelationshipStatus {
1285    fn from(value: crate::RelationshipStatus) -> Self {
1286        match value {
1287            crate::RelationshipStatus::None => RelationshipStatus::None,
1288            crate::RelationshipStatus::User => RelationshipStatus::User,
1289            crate::RelationshipStatus::Friend => RelationshipStatus::Friend,
1290            crate::RelationshipStatus::Outgoing => RelationshipStatus::Outgoing,
1291            crate::RelationshipStatus::Incoming => RelationshipStatus::Incoming,
1292            crate::RelationshipStatus::Blocked => RelationshipStatus::Blocked,
1293            crate::RelationshipStatus::BlockedOther => RelationshipStatus::BlockedOther,
1294        }
1295    }
1296}
1297
1298impl From<crate::Relationship> for Relationship {
1299    fn from(value: crate::Relationship) -> Self {
1300        Self {
1301            user_id: value.id,
1302            status: value.status.into(),
1303        }
1304    }
1305}
1306
1307impl From<crate::Presence> for Presence {
1308    fn from(value: crate::Presence) -> Self {
1309        match value {
1310            crate::Presence::Online => Presence::Online,
1311            crate::Presence::Idle => Presence::Idle,
1312            crate::Presence::Focus => Presence::Focus,
1313            crate::Presence::Busy => Presence::Busy,
1314            crate::Presence::Invisible => Presence::Invisible,
1315        }
1316    }
1317}
1318
1319impl From<Presence> for crate::Presence {
1320    fn from(value: Presence) -> crate::Presence {
1321        match value {
1322            Presence::Online => crate::Presence::Online,
1323            Presence::Idle => crate::Presence::Idle,
1324            Presence::Focus => crate::Presence::Focus,
1325            Presence::Busy => crate::Presence::Busy,
1326            Presence::Invisible => crate::Presence::Invisible,
1327        }
1328    }
1329}
1330
1331impl crate::UserStatus {
1332    fn into(self, discard_invisible: bool) -> Option<UserStatus> {
1333        let status = UserStatus {
1334            text: self.text,
1335            presence: self.presence.and_then(|presence| {
1336                if discard_invisible && presence == crate::Presence::Invisible {
1337                    None
1338                } else {
1339                    Some(presence.into())
1340                }
1341            }),
1342        };
1343
1344        if status.text.is_none() && status.presence.is_none() {
1345            None
1346        } else {
1347            Some(status)
1348        }
1349    }
1350}
1351
1352impl From<UserStatus> for crate::UserStatus {
1353    fn from(value: UserStatus) -> crate::UserStatus {
1354        crate::UserStatus {
1355            text: value.text,
1356            presence: value.presence.map(|presence| presence.into()),
1357        }
1358    }
1359}
1360
1361impl From<crate::UserProfile> for UserProfile {
1362    fn from(value: crate::UserProfile) -> Self {
1363        UserProfile {
1364            content: value.content,
1365            background: value.background.map(|file| file.into()),
1366        }
1367    }
1368}
1369
1370impl From<UserProfile> for crate::UserProfile {
1371    fn from(value: UserProfile) -> crate::UserProfile {
1372        crate::UserProfile {
1373            content: value.content,
1374            background: value.background.map(|file| file.into()),
1375        }
1376    }
1377}
1378
1379impl From<crate::BotInformation> for BotInformation {
1380    fn from(value: crate::BotInformation) -> Self {
1381        BotInformation {
1382            owner_id: value.owner,
1383        }
1384    }
1385}
1386
1387impl From<BotInformation> for crate::BotInformation {
1388    fn from(value: BotInformation) -> crate::BotInformation {
1389        crate::BotInformation {
1390            owner: value.owner_id,
1391        }
1392    }
1393}
1394
1395impl From<crate::FieldsMessage> for FieldsMessage {
1396    fn from(value: crate::FieldsMessage) -> Self {
1397        match value {
1398            crate::FieldsMessage::Pinned => FieldsMessage::Pinned,
1399        }
1400    }
1401}
1402impl From<FieldsMessage> for crate::FieldsMessage {
1403    fn from(value: FieldsMessage) -> Self {
1404        match value {
1405            FieldsMessage::Pinned => crate::FieldsMessage::Pinned,
1406        }
1407    }
1408}
1409
1410impl From<VoiceInformation> for crate::VoiceInformation {
1411    fn from(value: VoiceInformation) -> Self {
1412        crate::VoiceInformation {
1413            max_users: value.max_users,
1414        }
1415    }
1416}
1417
1418impl From<crate::VoiceInformation> for VoiceInformation {
1419    fn from(value: crate::VoiceInformation) -> Self {
1420        VoiceInformation {
1421            max_users: value.max_users,
1422        }
1423    }
1424}