tangled
alpha
login
or
join now
parakeet.at
/
parakeet
63
fork
atom
Parakeet is a Rust-based Bluesky AppServer aiming to implement most of the functionality required to support the Bluesky client
appview
atproto
bluesky
rust
appserver
63
fork
atom
overview
issues
12
pulls
pipelines
fix!: labeler subjectTypes and subjectCollections
mia.omg.lol
10 months ago
7365f6b2
fec183f5
+54
-8
6 changed files
expand all
collapse all
unified
split
consumer
src
indexer
db.rs
lexica
src
com_atproto
moderation.rs
migrations
2025-04-11-155301_labels
up.sql
parakeet
src
hydration
labeler.rs
parakeet-db
src
models.rs
schema.rs
+6
consumer/src/indexer/db.rs
···
798
798
.reason_types
799
799
.as_ref()
800
800
.map(|v| v.iter().map(|v| v.to_string()).collect());
801
801
+
let subject_types = rec
802
802
+
.subject_types
803
803
+
.as_ref()
804
804
+
.map(|v| v.iter().map(|v| v.to_string()).collect());
801
805
802
806
let data = models::UpsertLabelerService {
803
807
did: repo,
804
808
cid: cid.to_string(),
805
809
reasons,
810
810
+
subject_types,
811
811
+
subject_collections: rec.subject_collections.as_ref(),
806
812
indexed_at: Utc::now().naive_utc(),
807
813
};
808
814
+23
lexica/src/com_atproto/moderation.rs
···
58
58
Record,
59
59
Chat,
60
60
}
61
61
+
62
62
+
impl Display for SubjectType {
63
63
+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
64
64
+
match self {
65
65
+
SubjectType::Account => write!(f, "account"),
66
66
+
SubjectType::Record => write!(f, "record"),
67
67
+
SubjectType::Chat => write!(f, "chat"),
68
68
+
}
69
69
+
}
70
70
+
}
71
71
+
72
72
+
impl FromStr for SubjectType {
73
73
+
type Err = String;
74
74
+
75
75
+
fn from_str(s: &str) -> Result<Self, Self::Err> {
76
76
+
match s {
77
77
+
"account" => Ok(SubjectType::Account),
78
78
+
"record" => Ok(SubjectType::Record),
79
79
+
"chat" => Ok(SubjectType::Chat),
80
80
+
x => Err(format!("Unrecognized variant {}", x)),
81
81
+
}
82
82
+
}
83
83
+
}
+7
-5
migrations/2025-04-11-155301_labels/up.sql
···
1
1
create table labelers
2
2
(
3
3
-
did text primary key references actors (did) on delete cascade,
4
4
-
cid text not null,
3
3
+
did text primary key references actors (did) on delete cascade,
4
4
+
cid text not null,
5
5
6
6
-
reasons text[],
6
6
+
reasons text[],
7
7
+
subject_types text[],
8
8
+
subject_collections text[],
7
9
8
8
-
created_at timestamp not null default now(),
9
9
-
indexed_at timestamp not null default now()
10
10
+
created_at timestamp not null default now(),
11
11
+
indexed_at timestamp not null default now()
10
12
);
11
13
12
14
create table labeler_defs
+4
parakeet-db/src/models.rs
···
593
593
pub cid: String,
594
594
595
595
pub reasons: Option<Vec<Option<String>>>,
596
596
+
pub subject_types: Option<Vec<Option<String>>>,
597
597
+
pub subject_collections: Option<Vec<Option<String>>>,
596
598
597
599
pub created_at: NaiveDateTime,
598
600
pub indexed_at: NaiveDateTime,
···
606
608
pub cid: String,
607
609
608
610
pub reasons: Option<Vec<String>>,
611
611
+
pub subject_types: Option<Vec<String>>,
612
612
+
pub subject_collections: Option<&'a Vec<String>>,
609
613
610
614
pub indexed_at: NaiveDateTime,
611
615
}
+2
parakeet-db/src/schema.rs
···
95
95
did -> Text,
96
96
cid -> Text,
97
97
reasons -> Nullable<Array<Nullable<Text>>>,
98
98
+
subject_types -> Nullable<Array<Nullable<Text>>>,
99
99
+
subject_collections -> Nullable<Array<Nullable<Text>>>,
98
100
created_at -> Timestamp,
99
101
indexed_at -> Timestamp,
100
102
}
+12
-3
parakeet/src/hydration/labeler.rs
···
2
2
use lexica::app_bsky::actor::ProfileView;
3
3
use lexica::app_bsky::labeler::{LabelerPolicy, LabelerView, LabelerViewDetailed};
4
4
use lexica::com_atproto::label::{Blurs, LabelValueDefinition, Severity};
5
5
-
use lexica::com_atproto::moderation::ReasonType;
5
5
+
use lexica::com_atproto::moderation::{ReasonType, SubjectType};
6
6
use parakeet_db::models;
7
7
use std::collections::HashMap;
8
8
use std::str::FromStr;
···
62
62
})
63
63
})
64
64
.collect();
65
65
+
let subject_types = labeler.subject_types.map(|v| {
66
66
+
v.into_iter()
67
67
+
.flatten()
68
68
+
.filter_map(|v| SubjectType::from_str(&v).ok())
69
69
+
.collect()
70
70
+
});
71
71
+
let subject_collections = labeler
72
72
+
.subject_collections
73
73
+
.map(|v| v.into_iter().flatten().collect());
65
74
66
75
LabelerViewDetailed {
67
76
uri: format!("at://{}/app.bsky.labeler.service/self", labeler.did),
···
73
82
label_value_definitions,
74
83
},
75
84
reason_types,
76
76
-
subject_types: None,
77
77
-
subject_collections: None,
85
85
+
subject_types,
86
86
+
subject_collections,
78
87
labels: map_labels(labels),
79
88
indexed_at: labeler.indexed_at,
80
89
}