Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions apps/web/src/views/pages.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,45 @@ export const ItemPage = ({
)}
/>
{item.data?.exit ? <WayInOut data={item.data} /> : null}
{item.kind === 'scanner-stream' ? (
<section>
<h2>Listen live</h2>
<p>{item.data?.location_label ?? item.data?.jurisdiction ?? ''}</p>
{item.data?.directory_present === false ? (
<p>This scanner is no longer listed.</p>
) : (
<p>
<a href={item.data?.player_url ?? item.url} rel="noopener nofollow">
Open scanner player ↗
</a>
{item.data?.stream_url ? (
<>
{' '}
·{' '}
<a href={item.data.stream_url} rel="noopener nofollow">
Open audio stream ↗
</a>
</>
) : null}
{item.data?.playlist_url ? (
<>
{' '}
·{' '}
<a href={item.data.playlist_url} rel="noopener nofollow">
Media-player playlist ↗
</a>
</>
) : null}
</p>
)}
{item.data?.directory_url ? (
<p class="small muted">
Source: <a href={item.data.directory_url}>ProScan public directory</a>. Audio comes
directly from the scanner operator.
</p>
) : null}
</section>
) : null}
{nearby !== null ? (
<section>
<h2>Reported incidents in scanner coverage</h2>
Expand Down
35 changes: 35 additions & 0 deletions docs/geographic-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,41 @@ geographic flags. The corresponding MCP tools expose the same fields;
a snapshot: concurrent arrivals or location changes can shift pages. Use the
existing ID/update cursors for synchronization with the default ordering.

## Default public scanner directory

`proscan-scanners` seeds the enabled `scanners-proscan` source on startup. It
indexes the public [ProScan server directory](https://www.proscan.org/web_servers/list)
every 15 minutes, keeping player URLs, location labels, scanner models and source
attribution. No API key or manually supplied JSON catalog is needed.

Each run visits up to 12 player pages, least recently checked first, within the
worker deadline. It extracts explicitly advertised `<audio src>`, nested audio
sources, direct audio links and `.m3u`/`.pls` playlist links. ProScan's unclosed
`<audio>` markup is supported. It never guesses a stream endpoint or downloads
an audio stream. Listings appear even before their player has been checked.

The scanner page links directly to the operator's player, audio URL and media
playlist. `stream_access: "publicly-advertised"` identifies discovered links;
`stream_reuse_allowed` remains false because link discovery is not a grant to
record or redistribute audio. HTTP-only streams open at their source, avoiding
mixed-content playback problems on NicheDB's HTTPS pages.

Robots rules are checked per origin/path, including redirected player pages.
Unavailable robots due to a server error, rate limit or network failure defer
the visit. Missing robots (HTTP 4xx other than 429) has no rules. Authentication
failures and challenges are not bypassed. Requests pin a validated public DNS
address, revalidate redirects, cap text responses and use short timeouts.

Disappearing directory entries are marked `directory_present: false` and their
obsolete audio links are cleared. Transient player failures retain previously
advertised links with `discovery_status: "unreachable"` and separate discovery
and attempt timestamps. A failed/changed directory page does not erase records.

Directory locations are labels, not verified radio coverage polygons. No county
centroid or receiver location is invented: these entries retain unknown GPS
coverage until a source supplies it, and therefore do not produce speculative
nearby-crime associations.

## Permissioned scanner catalogs

Add a `scanner-directory` source in the `crime` collection with `config.url`
Expand Down
2 changes: 2 additions & 0 deletions packages/adapters/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ import { p0dcasters } from './p0dcasters.js';
import { buildingPermits } from './permits.js';
import { podcastindexCatalog } from './podcastindex-catalog.js';
import { podcasts } from './podcasts.js';
import { proscanDirectory } from './proscan.js';
import { pypi } from './pypi.js';
import { redditDeals } from './redditdeals.js';
import { rogueIncidents, rogueResearch } from './rogueaitracker.js';
Expand Down Expand Up @@ -163,6 +164,7 @@ export const ADAPTERS = [
ecbFxRates,
socrataCrime,
scannerDirectory,
proscanDirectory,
ukPoliceCrime,
fbiCrimeEstimates,
usaspendingAwards,
Expand Down
Loading
Loading