Schema: add follows, blocks, split lib.rs

This commit is contained in:
Aode (Lion) 2022-05-18 20:35:32 -05:00
parent b8c6c4e13a
commit c9d988bdd2
9 changed files with 793 additions and 462 deletions

84
schema/src/account.rs Normal file
View file

@ -0,0 +1,84 @@
use crate::keys::{Created, DatetimeKey, TaggedKey, Updated, UuidKey};
use bonsaidb::core::{
document::{CollectionDocument, Emit},
schema::{
view::{map::Mappings, CollectionViewSchema},
Collection, ReduceResult, View, ViewMapResult,
},
};
use serde::{Deserialize, Serialize};
#[derive(Collection, Debug, Deserialize, Serialize)]
#[collection(
name = "accounts",
views = [AccountsByUsername, AccountsByEmail],
primary_key = TaggedKey<UuidKey, Account>,
natural_id = |account: &Account| Some(account.id)
)]
pub struct Account {
id: TaggedKey<UuidKey, Self>,
username: String,
emails: Vec<String>,
created_at: TaggedKey<DatetimeKey, Created>,
updated_at: TaggedKey<DatetimeKey, Updated>,
}
#[derive(Debug, Clone, View)]
#[view(collection = Account, key = String, value = usize, name = "accounts-by-username")]
pub struct AccountsByUsername;
#[derive(Debug, Clone, View)]
#[view(collection = Account, key = String, value = usize, name = "accounts-by-email")]
pub struct AccountsByEmail;
impl CollectionViewSchema for AccountsByUsername {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.username, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for AccountsByEmail {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
if document.contents.emails.is_empty() {
return Ok(Mappings::none());
}
let mut mappings = Vec::new();
for email in document.contents.emails {
mappings.extend(document.header.emit_key_and_value(email, 1)?);
}
Ok(Mappings::List(mappings))
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}

96
schema/src/block.rs Normal file
View file

@ -0,0 +1,96 @@
use crate::{
keys::{CompoundKey, Created, DatetimeKey, KeyExt, TaggedKey, Updated, UuidKey},
profile::Profile,
};
use bonsaidb::core::{
document::{CollectionDocument, Emit},
schema::{view::CollectionViewSchema, Collection, ReduceResult, View, ViewMapResult},
};
use serde::{Deserialize, Serialize};
#[derive(Collection, Debug, Deserialize, Serialize)]
#[collection(
name = "blocks",
views = [BlocksByAccount, BlockersByAccount],
primary_key = TaggedKey<UuidKey, Block>,
natural_id = |block: &Block| Some(block.id)
)]
pub struct Block {
id: TaggedKey<UuidKey, Self>,
target_profile: TaggedKey<UuidKey, Profile>,
actor_profile: TaggedKey<UuidKey, Profile>,
created_at: TaggedKey<DatetimeKey, Created>,
updated_at: TaggedKey<DatetimeKey, Updated>,
}
pub type AccountBlocksKey = CompoundKey<
CompoundKey<TaggedKey<UuidKey, Profile>, TaggedKey<DatetimeKey, Updated>>,
TaggedKey<UuidKey, Profile>,
>;
pub type AccountBlockersKey = CompoundKey<
CompoundKey<TaggedKey<UuidKey, Profile>, TaggedKey<DatetimeKey, Updated>>,
TaggedKey<UuidKey, Profile>,
>;
#[derive(Debug, Clone, View)]
#[view(collection = Block, key = AccountBlocksKey, value = usize, name = "blocks-by-account")]
pub struct BlocksByAccount;
#[derive(Debug, Clone, View)]
#[view(collection = Block, key = AccountBlockersKey, value = usize, name = "blockers-by-account")]
pub struct BlockersByAccount;
impl CollectionViewSchema for BlockersByAccount {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document.header.emit_key_and_value(
document
.contents
.target_profile
.compound(document.contents.updated_at)
.compound(document.contents.actor_profile),
1,
)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for BlocksByAccount {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document.header.emit_key_and_value(
document
.contents
.actor_profile
.compound(document.contents.updated_at)
.compound(document.contents.target_profile),
1,
)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}

187
schema/src/follow.rs Normal file
View file

@ -0,0 +1,187 @@
use crate::{
keys::{CompoundKey, Created, DatetimeKey, KeyExt, TaggedKey, Updated, UuidKey},
profile::Profile,
};
use bonsaidb::core::{
document::{CollectionDocument, Emit},
schema::{
view::{map::Mappings, CollectionViewSchema},
Collection, ReduceResult, View, ViewMapResult,
},
};
use serde::{Deserialize, Serialize};
#[derive(Collection, Debug, Deserialize, Serialize)]
#[collection(
name = "follows",
views = [FollowsByAccount, FollowersByAccount, InboundFollowRequestsByAccount, OutboundFollowRequestsByAccount],
primary_key = TaggedKey<UuidKey, Follow>,
natural_id = |follow: &Follow| Some(follow.id)
)]
pub struct Follow {
id: TaggedKey<UuidKey, Self>,
confirmed: bool,
target_profile: TaggedKey<UuidKey, Profile>,
actor_profile: TaggedKey<UuidKey, Profile>,
created_at: TaggedKey<DatetimeKey, Created>,
updated_at: TaggedKey<DatetimeKey, Updated>,
}
pub type AccountFollowsKey = CompoundKey<
CompoundKey<TaggedKey<UuidKey, Profile>, TaggedKey<DatetimeKey, Updated>>,
TaggedKey<UuidKey, Profile>,
>;
pub type AccountFollowersKey = CompoundKey<
CompoundKey<TaggedKey<UuidKey, Profile>, TaggedKey<DatetimeKey, Updated>>,
TaggedKey<UuidKey, Profile>,
>;
pub type AccountInboundFollowRequestsKey = CompoundKey<
CompoundKey<TaggedKey<UuidKey, Profile>, TaggedKey<DatetimeKey, Created>>,
TaggedKey<UuidKey, Profile>,
>;
pub type AccountOutboundFollowRequestsKey = CompoundKey<
CompoundKey<TaggedKey<UuidKey, Profile>, TaggedKey<DatetimeKey, Created>>,
TaggedKey<UuidKey, Profile>,
>;
#[derive(Debug, Clone, View)]
#[view(collection = Follow, key = AccountFollowsKey, value = usize, name = "follows-by-account")]
pub struct FollowsByAccount;
#[derive(Debug, Clone, View)]
#[view(collection = Follow, key = AccountFollowersKey, value = usize, name = "followers-by-account")]
pub struct FollowersByAccount;
#[derive(Debug, Clone, View)]
#[view(collection = Follow, key = AccountInboundFollowRequestsKey, value = usize, name = "inbound-follow-requests-by-account")]
pub struct InboundFollowRequestsByAccount;
#[derive(Debug, Clone, View)]
#[view(collection = Follow, key = AccountOutboundFollowRequestsKey, value = usize, name = "outbound-follow-requests-by-account")]
pub struct OutboundFollowRequestsByAccount;
impl CollectionViewSchema for FollowersByAccount {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
if document.contents.confirmed {
document.header.emit_key_and_value(
document
.contents
.target_profile
.compound(document.contents.updated_at)
.compound(document.contents.actor_profile),
1,
)
} else {
Ok(Mappings::none())
}
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for FollowsByAccount {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
if document.contents.confirmed {
document.header.emit_key_and_value(
document
.contents
.actor_profile
.compound(document.contents.updated_at)
.compound(document.contents.target_profile),
1,
)
} else {
Ok(Mappings::none())
}
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for InboundFollowRequestsByAccount {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
if document.contents.confirmed {
Ok(Mappings::none())
} else {
document.header.emit_key_and_value(
document
.contents
.target_profile
.compound(document.contents.created_at)
.compound(document.contents.actor_profile),
1,
)
}
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for OutboundFollowRequestsByAccount {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
if document.contents.confirmed {
Ok(Mappings::none())
} else {
document.header.emit_key_and_value(
document
.contents
.actor_profile
.compound(document.contents.created_at)
.compound(document.contents.target_profile),
1,
)
}
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}

View file

@ -1,468 +1,35 @@
pub mod account;
pub mod block;
pub mod follow;
pub mod keys;
pub mod media;
pub mod post;
pub mod profile;
pub mod report;
pub mod tag;
use bonsaidb::core::{
document::{CollectionDocument, Emit},
schema::{
view::{map::Mappings, CollectionViewSchema},
Collection, ReduceResult, Schema, View, ViewMapResult,
},
};
use keys::{Created, DatetimeKey, KeyExt, ProfileKind, ReportState, TaggedKey, Updated, UuidKey};
use account::Account;
use block::Block;
use bonsaidb::core::schema::Schema;
use follow::Follow;
use media::Media;
use post::Post;
use serde::{Deserialize, Serialize};
use profile::Profile;
use report::Report;
use tag::Tag;
#[derive(Debug, Schema)]
#[schema(
name = "SiteSchema",
collections = [
Account,
Profile,
Block,
Follow,
Media,
Post,
Tag,
Profile,
Report,
Tag,
]
)]
pub struct SiteSchema;
#[derive(Collection, Debug, Deserialize, Serialize)]
#[collection(
name = "accounts",
views = [AccountsByUsername, AccountsByEmail],
primary_key = TaggedKey<UuidKey, Account>,
natural_id = |account: &Account| Some(account.id)
)]
pub struct Account {
id: TaggedKey<UuidKey, Self>,
username: String,
emails: Vec<String>,
created_at: TaggedKey<DatetimeKey, Created>,
updated_at: TaggedKey<DatetimeKey, Updated>,
}
#[derive(Collection, Debug, Deserialize, Serialize)]
#[collection(
name = "profiles",
views = [ProfilesByHandle, RemoteProfilesByDomain, LocalProfilesById, ProfilesByCollaborator, ProfilesByKind],
primary_key = TaggedKey<UuidKey, Profile>,
natural_id = |profile: &Profile| Some(profile.id)
)]
pub struct Profile {
id: TaggedKey<UuidKey, Self>,
kind: ProfileKind,
handle: String,
domain: Option<String>,
full_url: Option<String>,
name: Option<String>,
description: Option<String>,
local_account: Option<TaggedKey<UuidKey, Account>>,
collaborators: Vec<TaggedKey<UuidKey, Profile>>,
created_at: TaggedKey<DatetimeKey, Created>,
updated_at: TaggedKey<DatetimeKey, Updated>,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum MediaState {
Uploading {
upload_id: String,
},
Finished {
filename: String,
delete_token: String,
},
}
#[derive(Collection, Debug, Deserialize, Serialize)]
#[collection(
name = "media",
views = [],
primary_key = TaggedKey<UuidKey, Media>,
natural_id = |media: &Media| Some(media.id)
)]
pub struct Media {
id: TaggedKey<UuidKey, Self>,
state: MediaState,
created_at: TaggedKey<DatetimeKey, Created>,
updated_at: TaggedKey<DatetimeKey, Updated>,
}
#[derive(Collection, Debug, Deserialize, Serialize)]
#[collection(
name = "tags",
views = [TagsByName],
primary_key = TaggedKey<UuidKey, Tag>,
natural_id = |tag: &Tag| Some(tag.id)
)]
pub struct Tag {
id: TaggedKey<UuidKey, Self>,
name: String,
created_at: TaggedKey<DatetimeKey, Created>,
updated_at: TaggedKey<DatetimeKey, Updated>,
}
#[derive(Collection, Debug, Deserialize, Serialize)]
#[collection(
name = "reports",
views = [ReportsByPost, ReportsByState, ReportsByAccount],
primary_key = TaggedKey<UuidKey, Report>,
natural_id = |report: &Report| Some(report.id)
)]
pub struct Report {
id: TaggedKey<UuidKey, Self>,
message: Option<String>,
moderation_note: Option<String>,
post: TaggedKey<UuidKey, Post>,
state: ReportState,
handled_by: Option<TaggedKey<UuidKey, Account>>,
created_at: TaggedKey<DatetimeKey, Created>,
updated_at: TaggedKey<DatetimeKey, Updated>,
}
#[derive(Debug, Clone, View)]
#[view(collection = Account, key = String, value = usize, name = "by-username")]
pub struct AccountsByUsername;
#[derive(Debug, Clone, View)]
#[view(collection = Account, key = String, value = usize, name = "by-email")]
pub struct AccountsByEmail;
#[derive(Debug, Clone, View)]
#[view(collection = Profile, key = String, value = usize, name = "by-handle")]
pub struct ProfilesByHandle;
#[derive(Debug, Clone, View)]
#[view(collection = Profile, key = Option<String>, value = usize, name = "by-remote-domain")]
pub struct RemoteProfilesByDomain;
#[derive(Debug, Clone, View)]
#[view(collection = Profile, key = Option<TaggedKey<UuidKey, Account>>, value = usize, name = "by-local-id")]
pub struct LocalProfilesById;
#[derive(Debug, Clone, View)]
#[view(collection = Profile, key = TaggedKey<UuidKey, Profile>, value = usize, name = "by-collaborator")]
pub struct ProfilesByCollaborator;
#[derive(Debug, Clone, View)]
#[view(collection = Profile, key = ProfileKind, value = usize, name = "by-kind")]
pub struct ProfilesByKind;
#[derive(Debug, Clone, View)]
#[view(collection = Tag, key = String, value = usize, name = "by-name")]
pub struct TagsByName;
#[derive(Debug, Clone, View)]
#[view(collection = Report, key = TaggedKey<UuidKey, Post>, value = usize, name = "by-name")]
pub struct ReportsByPost;
#[derive(Debug, Clone, View)]
#[view(collection = Report, key = ReportState, value = usize, name = "by-state")]
pub struct ReportsByState;
#[derive(Debug, Clone, View)]
#[view(collection = Report, key = Option<TaggedKey<UuidKey, Account>>, value = usize, name = "by-account")]
pub struct ReportsByAccount;
impl CollectionViewSchema for AccountsByUsername {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.username, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for AccountsByEmail {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
if document.contents.emails.is_empty() {
return Ok(Mappings::none());
}
let mut mappings = Vec::new();
for email in document.contents.emails {
mappings.extend(document.header.emit_key_and_value(email, 1)?);
}
Ok(Mappings::List(mappings))
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for ProfilesByHandle {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
let mut mappings = Vec::new();
if document.contents.handle.is_empty() {
return Ok(Mappings::none());
}
const MAX_SEARCH_LEN: usize = 16;
// enable searching for profiles by handle lol
// turns 'asonix' into 'a', 'as', 'aso', 'ason', 'asoni', 'asonix'
// cap search characters
for i in 1..=document.contents.handle.len().min(MAX_SEARCH_LEN) {
mappings.extend(
document
.header
.emit_key_and_value(document.contents.handle[..i].to_owned(), 1)?,
);
}
// Ensure we index the full handle if longer than max characters as well
if document.contents.handle.len() > MAX_SEARCH_LEN {
mappings.extend(
document
.header
.emit_key_and_value(document.contents.handle, 1)?,
);
}
Ok(Mappings::List(mappings))
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for RemoteProfilesByDomain {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.domain, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for LocalProfilesById {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.local_account, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for ProfilesByCollaborator {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
if document.contents.collaborators.is_empty() {
return Ok(Mappings::none());
}
let mut mappings = Vec::new();
for collaborator in document.contents.collaborators {
mappings.extend(document.header.emit_key_and_value(collaborator, 1)?);
}
Ok(Mappings::List(mappings))
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for ProfilesByKind {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.kind, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for TagsByName {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.name, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for ReportsByPost {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.post, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for ReportsByState {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.state, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for ReportsByAccount {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.handled_by, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl Tag {
pub fn new(name: String) -> Self {
Self {
id: UuidKey::generate().tag(),
name,
created_at: DatetimeKey::now().tag(),
updated_at: DatetimeKey::now().tag(),
}
}
pub fn name(&self) -> &str {
&self.name
}
}

31
schema/src/media.rs Normal file
View file

@ -0,0 +1,31 @@
use crate::keys::{Created, DatetimeKey, TaggedKey, Updated, UuidKey};
use bonsaidb::core::schema::Collection;
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum MediaState {
Uploading {
upload_id: String,
},
Finished {
filename: String,
delete_token: String,
},
}
#[derive(Collection, Debug, Deserialize, Serialize)]
#[collection(
name = "media",
views = [],
primary_key = TaggedKey<UuidKey, Media>,
natural_id = |media: &Media| Some(media.id)
)]
pub struct Media {
id: TaggedKey<UuidKey, Self>,
state: MediaState,
created_at: TaggedKey<DatetimeKey, Created>,
updated_at: TaggedKey<DatetimeKey, Updated>,
}

View file

@ -72,43 +72,43 @@ pub type AuthorPostKindUnpublishedKey = CompoundKey<
>;
#[derive(Debug, Clone, View)]
#[view(collection = Post, key = PostKind, value = usize, name = "by-kind")]
#[view(collection = Post, key = PostKind, value = usize, name = "posts-by-kind")]
pub struct PostsByKind;
#[derive(Debug, Clone, View)]
#[view(collection = Post, key = PostKindPublishedKey, value = usize, name = "by-kind-and-published")]
#[view(collection = Post, key = PostKindPublishedKey, value = usize, name = "posts-by-kind-and-published")]
pub struct PublishedPostsByKind;
#[derive(Debug, Clone, View)]
#[view(collection = Post, key = TaggedKey<UuidKey, Profile>, value = usize, name = "by-author")]
#[view(collection = Post, key = TaggedKey<UuidKey, Profile>, value = usize, name = "posts-by-author")]
pub struct PostsByAuthor;
#[derive(Debug, Clone, View)]
#[view(collection = Post, key = AuthorPublishedKey, value = usize, name = "by-author-and-published")]
#[view(collection = Post, key = AuthorPublishedKey, value = usize, name = "posts-by-author-and-published")]
pub struct PublishedPostsByAuthor;
#[derive(Debug, Clone, View)]
#[view(collection = Post, key = AuthorPostKindPublishedKey, value = usize, name = "by-author-and-published")]
#[view(collection = Post, key = AuthorPostKindPublishedKey, value = usize, name = "posts-by-author-kind-and-published")]
pub struct PublishedPostsByAuthorAndKind;
#[derive(Debug, Clone, View)]
#[view(collection = Post, key = AuthorUnpublishedKey, value = usize, name = "by-author-and-unpublished")]
#[view(collection = Post, key = AuthorUnpublishedKey, value = usize, name = "posts-by-author-and-unpublished")]
pub struct UnpublishedPostsByAuthor;
#[derive(Debug, Clone, View)]
#[view(collection = Post, key = AuthorPostKindUnpublishedKey, value = usize, name = "by-author-and-unpublished")]
#[view(collection = Post, key = AuthorPostKindUnpublishedKey, value = usize, name = "posts-by-author-kind-and-unpublished")]
pub struct UnpublishedPostsByAuthorAndKind;
#[derive(Debug, Clone, View)]
#[view(collection = Post, key = TaggedKey<UuidKey, Tag>, value = usize, name = "by-tag")]
#[view(collection = Post, key = TaggedKey<UuidKey, Tag>, value = usize, name = "posts-by-tag")]
pub struct PostsByTag;
#[derive(Debug, Clone, View)]
#[view(collection = Post, key = TaggedKey<UuidKey, Profile>, value = usize, name = "by-mention")]
#[view(collection = Post, key = TaggedKey<UuidKey, Profile>, value = usize, name = "posts-by-mention")]
pub struct PostsByMention;
#[derive(Debug, Clone, View)]
#[view(collection = Post, key = Option<TaggedKey<UuidKey, Post>>, value = usize, name = "by-parent")]
#[view(collection = Post, key = Option<TaggedKey<UuidKey, Post>>, value = usize, name = "posts-by-parent")]
pub struct PostsByParent;
impl CollectionViewSchema for PostsByKind {

196
schema/src/profile.rs Normal file
View file

@ -0,0 +1,196 @@
use crate::{
account::Account,
keys::{Created, DatetimeKey, ProfileKind, TaggedKey, Updated, UuidKey},
};
use bonsaidb::core::{
document::{CollectionDocument, Emit},
schema::{
view::{map::Mappings, CollectionViewSchema},
Collection, ReduceResult, View, ViewMapResult,
},
};
use serde::{Deserialize, Serialize};
#[derive(Collection, Debug, Deserialize, Serialize)]
#[collection(
name = "profiles",
views = [ProfilesByHandle, RemoteProfilesByDomain, LocalProfilesById, ProfilesByCollaborator, ProfilesByKind],
primary_key = TaggedKey<UuidKey, Profile>,
natural_id = |profile: &Profile| Some(profile.id)
)]
pub struct Profile {
id: TaggedKey<UuidKey, Self>,
kind: ProfileKind,
handle: String,
domain: Option<String>,
full_url: Option<String>,
name: Option<String>,
description: Option<String>,
local_account: Option<TaggedKey<UuidKey, Account>>,
collaborators: Vec<TaggedKey<UuidKey, Profile>>,
created_at: TaggedKey<DatetimeKey, Created>,
updated_at: TaggedKey<DatetimeKey, Updated>,
}
#[derive(Debug, Clone, View)]
#[view(collection = Profile, key = String, value = usize, name = "profiles-by-handle")]
pub struct ProfilesByHandle;
#[derive(Debug, Clone, View)]
#[view(collection = Profile, key = Option<String>, value = usize, name = "profiles-by-remote-domain")]
pub struct RemoteProfilesByDomain;
#[derive(Debug, Clone, View)]
#[view(collection = Profile, key = Option<TaggedKey<UuidKey, Account>>, value = usize, name = "profiles-by-local-id")]
pub struct LocalProfilesById;
#[derive(Debug, Clone, View)]
#[view(collection = Profile, key = TaggedKey<UuidKey, Profile>, value = usize, name = "profiles-by-collaborator")]
pub struct ProfilesByCollaborator;
#[derive(Debug, Clone, View)]
#[view(collection = Profile, key = ProfileKind, value = usize, name = "profiles-by-kind")]
pub struct ProfilesByKind;
impl CollectionViewSchema for ProfilesByHandle {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
let mut mappings = Vec::new();
if document.contents.handle.is_empty() {
return Ok(Mappings::none());
}
const MAX_SEARCH_LEN: usize = 16;
// enable searching for profiles by handle lol
// turns 'asonix' into 'asonix', 'sonix', 'onix', 'nix', 'ix', 'x'
// cap search characters
for i in 0..document.contents.handle.len().min(MAX_SEARCH_LEN) {
mappings.extend(
document
.header
.emit_key_and_value(document.contents.handle[i..].to_owned(), 1)?,
);
}
// Ensure we index the full handle if longer than max characters as well
if document.contents.handle.len() >= MAX_SEARCH_LEN {
mappings.extend(
document
.header
.emit_key_and_value(document.contents.handle, 1)?,
);
}
Ok(Mappings::List(mappings))
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for RemoteProfilesByDomain {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.domain, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for LocalProfilesById {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.local_account, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for ProfilesByCollaborator {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
if document.contents.collaborators.is_empty() {
return Ok(Mappings::none());
}
let mut mappings = Vec::new();
for collaborator in document.contents.collaborators {
mappings.extend(document.header.emit_key_and_value(collaborator, 1)?);
}
Ok(Mappings::List(mappings))
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for ProfilesByKind {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.kind, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}

108
schema/src/report.rs Normal file
View file

@ -0,0 +1,108 @@
use crate::{
account::Account,
keys::{Created, DatetimeKey, ReportState, TaggedKey, Updated, UuidKey},
post::Post,
};
use bonsaidb::core::{
document::{CollectionDocument, Emit},
schema::{view::CollectionViewSchema, Collection, ReduceResult, View, ViewMapResult},
};
use serde::{Deserialize, Serialize};
#[derive(Collection, Debug, Deserialize, Serialize)]
#[collection(
name = "reports",
views = [ReportsByPost, ReportsByState, ReportsByAccount],
primary_key = TaggedKey<UuidKey, Report>,
natural_id = |report: &Report| Some(report.id)
)]
pub struct Report {
id: TaggedKey<UuidKey, Self>,
message: Option<String>,
moderation_note: Option<String>,
post: TaggedKey<UuidKey, Post>,
state: ReportState,
handled_by: Option<TaggedKey<UuidKey, Account>>,
created_at: TaggedKey<DatetimeKey, Created>,
updated_at: TaggedKey<DatetimeKey, Updated>,
}
#[derive(Debug, Clone, View)]
#[view(collection = Report, key = TaggedKey<UuidKey, Post>, value = usize, name = "reports-by-name")]
pub struct ReportsByPost;
#[derive(Debug, Clone, View)]
#[view(collection = Report, key = ReportState, value = usize, name = "reports-by-state")]
pub struct ReportsByState;
#[derive(Debug, Clone, View)]
#[view(collection = Report, key = Option<TaggedKey<UuidKey, Account>>, value = usize, name = "reports-by-account")]
pub struct ReportsByAccount;
impl CollectionViewSchema for ReportsByPost {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.post, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for ReportsByState {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.state, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl CollectionViewSchema for ReportsByAccount {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.handled_by, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}

62
schema/src/tag.rs Normal file
View file

@ -0,0 +1,62 @@
use crate::keys::{Created, DatetimeKey, KeyExt, TaggedKey, Updated, UuidKey};
use bonsaidb::core::{
document::{CollectionDocument, Emit},
schema::{view::CollectionViewSchema, Collection, ReduceResult, View, ViewMapResult},
};
use serde::{Deserialize, Serialize};
#[derive(Collection, Debug, Deserialize, Serialize)]
#[collection(
name = "tags",
views = [TagsByName],
primary_key = TaggedKey<UuidKey, Tag>,
natural_id = |tag: &Tag| Some(tag.id)
)]
pub struct Tag {
id: TaggedKey<UuidKey, Self>,
name: String,
created_at: TaggedKey<DatetimeKey, Created>,
updated_at: TaggedKey<DatetimeKey, Updated>,
}
#[derive(Debug, Clone, View)]
#[view(collection = Tag, key = String, value = usize, name = "tags-by-name")]
pub struct TagsByName;
impl CollectionViewSchema for TagsByName {
type View = Self;
fn map(
&self,
document: CollectionDocument<<Self::View as View>::Collection>,
) -> ViewMapResult<Self::View> {
document
.header
.emit_key_and_value(document.contents.name, 1)
}
fn reduce(
&self,
mappings: &[bonsaidb::core::schema::ViewMappedValue<Self::View>],
_rereduce: bool,
) -> ReduceResult<Self::View> {
Ok(mappings.iter().map(|m| m.value).sum())
}
}
impl Tag {
pub fn new(name: String) -> Self {
Self {
id: UuidKey::generate().tag(),
name,
created_at: DatetimeKey::now().tag(),
updated_at: DatetimeKey::now().tag(),
}
}
pub fn name(&self) -> &str {
&self.name
}
}