Canadian cities labeler over Bluesky DMs
Users DM @cities.pds.cosocial.ca their city and get a signed account label. Serves com.atproto.label.queryLabels and subscribeLabels, built on jacquard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
a7d410fd6d
17 files changed
+5306
No files matched your search
@@ -0,0 +1,61 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
use jacquard::types::string::Did;
|
||||
use k256::ecdsa::SigningKey;
|
||||
use tokio::sync::broadcast;
|
||||
|
||||
use crate::db::{Db, SeqLabel};
|
||||
use crate::labels::sign_label;
|
||||
|
||||
pub struct Labeler {
|
||||
pub db: Arc<Db>,
|
||||
pub did: Did,
|
||||
key: SigningKey,
|
||||
published: broadcast::Sender<SeqLabel>,
|
||||
}
|
||||
|
||||
impl Labeler {
|
||||
pub fn new(db: Arc<Db>, did: Did, key: SigningKey) -> Self {
|
||||
let (published, _) = broadcast::channel(1024);
|
||||
Self {
|
||||
db,
|
||||
did,
|
||||
key,
|
||||
published,
|
||||
}
|
||||
}
|
||||
|
||||
/// Live labels for `subscribeLabels`.
|
||||
pub fn subscribe(&self) -> broadcast::Receiver<SeqLabel> {
|
||||
self.published.subscribe()
|
||||
}
|
||||
|
||||
pub fn current_city(&self, subject: &Did<&str>) -> Result<Option<String>> {
|
||||
Ok(self.db.active_vals(subject.as_str())?.into_iter().next())
|
||||
}
|
||||
|
||||
/// Make `city` the account's only city label; `None` removes it.
|
||||
pub fn set_city(&self, subject: &Did<&str>, city: Option<&str>) -> Result<()> {
|
||||
let active = self.db.active_vals(subject.as_str())?;
|
||||
for val in active.iter().filter(|v| Some(v.as_str()) != city) {
|
||||
self.emit(subject, val, true)?;
|
||||
}
|
||||
if let Some(city) = city.filter(|c| !active.iter().any(|v| v == c)) {
|
||||
self.emit(subject, city, false)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit(&self, subject: &Did<&str>, val: &str, neg: bool) -> Result<()> {
|
||||
let label = sign_label(&self.key, &self.did, subject, val, neg)?;
|
||||
let seq = self.db.insert_label(&label)?;
|
||||
// no receivers just means no one is subscribed right now
|
||||
let _ = self.published.send(SeqLabel { seq, label });
|
||||
println!(
|
||||
"{} {val} on {subject} (seq {seq})",
|
||||
if neg { "negated" } else { "applied" }
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user