Skip to content

Instantly share code, notes, and snippets.

@jonathanstowe
Created April 11, 2026 18:46
Show Gist options
  • Select an option

  • Save jonathanstowe/1ab2f8e81d2474fee4b6eeac4a6b74ed to your computer and use it in GitHub Desktop.

Select an option

Save jonathanstowe/1ab2f8e81d2474fee4b6eeac4a6b74ed to your computer and use it in GitHub Desktop.
#!/usr/bin/env raku
use Cro::WebSocket::Client;
use EventSource::Server;
use JSON::Fast;
use Cro::HTTP::Router;
use Cro::HTTP::Server;
my $client = Cro::WebSocket::Client.new: :json, uri => 'wss://jetstream1.us-east.bsky.network/subscribe';
my $conn = await $client.connect;
my $lock = Lock.new;
my %counts;
my $supply = supply {
whenever $conn.messages -> $message {
whenever $message.body -> $body {
$lock.protect: {
if $body<commit><collection>:exists {
%counts{$body<commit><collection>}++;
}
}
}
}
whenever Supply.interval(1) {
$lock.protect: {
my %out-data =
post => %counts<app.bsky.feed.post> // 0,
like => %counts<app.bsky.feed.like> // 0,
repost => %counts<app.bsky.feed.repost> // 0,
block => %counts<app.bsky.graph.block> // 0,
follow => %counts<app.bsky.graph.follow> // 0;
emit EventSource::Server::Event.new(type => 'hose', data => to-json(%out-data));
%counts = ();
}
}
};
my $es = EventSource::Server.new(:$supply, :keepalive, keepalive-interval => 1 );
my $app = route {
get -> 'stats' {
content 'text/event-stream', $es.out-supply.share;
}
get -> {
content 'text/html', "index.html".IO.slurp;
}
};
my Cro::Service $tick = Cro::HTTP::Server.new(:host<127.0.0.1>, :port<7798>, application => $app);
$tick.start;
react whenever signal(SIGINT) { $tick.stop; exit; }
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Lumberjack!</title>
<style type = "text/css">
</style>
</head>
<body>
<div>
<header><h1>Stats</h1></header>
<table>
<thead>
<tr>
<th>What</th>
<th>Count</th>
</tr>
</thead>
<tbody id="detail">
<tr>
<td>Post</td><td align="right" id="post">0</td>
</tr>
<tr>
<td>Like</td><td align="right" id="like">0</td>
</tr>
<tr>
<td>Repost</td><td align="right" id="repost">0</td>
</tr>
<tr>
<td>Follow</td><td align="right" id="follow">0</td>
</tr>
<tr>
<td>Block</td><td align="right" id="block">0</td>
</tr>
</tbody>
</table>
</div>
<script type="text/javascript">
var eventSource = new EventSource('stats');
eventSource.addEventListener("hose", function(e) {
var msg = JSON.parse(e.data);
post.innerHTML = msg.post;
like.innerHTML = msg.like;
repost.innerHTML = msg.repost;
follow.innerHTML = msg.follow;
block.innerHTML = msg.block;
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment