···860860 path: &str,
861861 limit: u64,
862862 until: Option<u64>,
863863+ filter_dids: &HashSet<Did>,
863864 ) -> Result<PagedAppendingCollection<RecordId>> {
864865 let target_key = TargetKey(
865866 Target(target.to_string()),
···876877 });
877878 };
878879879879- let linkers = self.get_target_linkers(&target_id)?;
880880+ let mut linkers = self.get_target_linkers(&target_id)?;
881881+ if !filter_dids.is_empty() {
882882+ let mut did_filter = HashSet::new();
883883+ for did in filter_dids {
884884+ let Some(DidIdValue(did_id, active)) =
885885+ self.did_id_table.get_id_val(&self.db, did)?
886886+ else {
887887+ eprintln!("failed to find a did_id for {did:?}");
888888+ continue;
889889+ };
890890+ if !active {
891891+ eprintln!("excluding inactive did from filtered results");
892892+ continue;
893893+ }
894894+ did_filter.insert(did_id);
895895+ }
896896+ linkers.0.retain(|linker| did_filter.contains(&linker.0));
897897+ }
880898881899 let (alive, gone) = linkers.count();
882900 let total = alive + gone;
+9-6
constellation/templates/hello.html.j2
···20202121 <p>
2222 This server has indexed <span class="stat">{{ stats.linking_records|human_number }}</span> links between <span class="stat">{{ stats.targetables|human_number }}</span> targets and sources from <span class="stat">{{ stats.dids|human_number }}</span> identities over <span class="stat">{{ days_indexed|human_number }}</span> days.<br/>
2323- <small>(indexing new records in real time, backfill still TODO)</small>
2323+ <small>(indexing new records in real time, backfill coming soon!)</small>
2424 </p>
25252626- <p>The API is currently <strong>unstable</strong>. But feel free to use it! If you want to be nice, put your project name and bsky username (or email) in your user-agent header for api requests.</p>
2626+ <p>But feel free to use it! If you want to be nice, put your project name and bsky username (or email) in your user-agent header for api requests.</p>
272728282929 <h2>API Endpoints</h2>
···3535 <h4>Query parameters:</h4>
36363737 <ul>
3838- <li><code>target</code>: required, must url-encode. Example: <code>at://did:plc:vc7f4oafdgxsihk4cry2xpze/app.bsky.feed.post/3lgwdn7vd722r</code></li>
3939- <li><code>collection</code>: required. Example: <code>app.bsky.feed.like</code></li>
4040- <li><code>path</code>: required, must url-encode. Example: <code>.subject.uri</code></li>
3838+ <li><p><code>target</code>: required, must url-encode. Example: <code>at://did:plc:vc7f4oafdgxsihk4cry2xpze/app.bsky.feed.post/3lgwdn7vd722r</code></p></li>
3939+ <li><p><code>collection</code>: required. Example: <code>app.bsky.feed.like</code></p></li>
4040+ <li><p><code>path</code>: required, must url-encode. Example: <code>.subject.uri</code></p></li>
4141+ <li><p><code>did</code>: optional, filter links to those from specific users. Include multiple times to filter by multiple users. Example: <code>did=did:plc:vc7f4oafdgxsihk4cry2xpze&did=did:plc:vc7f4oafdgxsihk4cry2xpze</code></p></li>
4242+ <li><p><code>from_dids</code> [deprecated]: optional. Use <code>did</code> instead. Example: <code>from_dids=did:plc:vc7f4oafdgxsihk4cry2xpze,did:plc:vc7f4oafdgxsihk4cry2xpze</code></p></li>
4343+ <li><p><code>limit</code>: optional. Default: <code>16</code>. Maximum: <code>100</code></p></li>
4144 </ul>
42454346 <p style="margin-bottom: 0"><strong>Try it:</strong></p>
4444- {% call try_it::links("at://did:plc:vc7f4oafdgxsihk4cry2xpze/app.bsky.feed.post/3lgwdn7vd722r", "app.bsky.feed.like", ".subject.uri") %}
4747+ {% call try_it::links("at://did:plc:a4pqq234yw7fqbddawjo7y35/app.bsky.feed.post/3m237ilwc372e", "app.bsky.feed.like", ".subject.uri", [""], 16) %}
454846494750 <h3 class="route"><code>GET /links/distinct-dids</code></h3>
···4444 Data(parent): Data<&Option<String>>,
4545 Query(AskQuery { domain }): Query<AskQuery>,
4646) -> Response {
4747- if let Some(parent) = parent {
4848- if let Some(prefix) = domain.strip_suffix(&format!(".{parent}")) {
4949- if !prefix.contains('.') {
5050- // no sub-sub-domains allowed
5151- return Response::builder().body("ok");
5252- }
5353- }
4747+ if let Some(parent) = parent
4848+ && let Some(prefix) = domain.strip_suffix(&format!(".{parent}"))
4949+ && !prefix.contains('.')
5050+ {
5151+ // no sub-sub-domains allowed
5252+ return Response::builder().body("ok");
5453 };
5554 Response::builder()
5655 .status(StatusCode::FORBIDDEN)
+5-5
spacedust/src/subscriber.rs
···4242 loop {
4343 tokio::select! {
4444 l = receiver.recv() => match l {
4545- Ok(link) => if self.filter(&link.properties) {
4646- if let Err(e) = ws_sender.send(link.message.clone()).await {
4747- log::warn!("failed to send link, dropping subscriber: {e:?}");
4848- break;
4949- }
4545+ Ok(link) => if self.filter(&link.properties)
4646+ && let Err(e) = ws_sender.send(link.message.clone()).await
4747+ {
4848+ log::warn!("failed to send link, dropping subscriber: {e:?}");
4949+ break;
5050 },
5151 Err(RecvError::Closed) => self.shutdown.cancel(),
5252 Err(RecvError::Lagged(n)) => {
+4-4
who-am-i/src/server.rs
···268268 Some(parent_host),
269269 );
270270 }
271271- if let Some(ref app) = params.app {
272272- if !allowed_hosts.contains(app) {
273273- return err("Login is not allowed for this app", false, Some(app));
274274- }
271271+ if let Some(ref app) = params.app
272272+ && !allowed_hosts.contains(app)
273273+ {
274274+ return err("Login is not allowed for this app", false, Some(app));
275275 }
276276 let parent_origin = url.origin().ascii_serialization();
277277 if parent_origin == "null" {