+3
cmd/astrolabe/handlers.go
+3
cmd/astrolabe/handlers.go
+23
cmd/astrolabe/parse.go
+23
cmd/astrolabe/parse.go
···
1
+
package main
2
+
3
+
import (
4
+
"fmt"
5
+
"strings"
6
+
)
7
+
8
+
// attempts to parse a service URL to an AT-URI, handle, or DID. if it can't, passes string through as-is
9
+
func ParseServiceURL(raw string) string {
10
+
parts := strings.Split(raw, "/")
11
+
if len(parts) < 3 || parts[0] != "https:" {
12
+
return raw
13
+
}
14
+
if parts[2] == "bsky.app" && len(parts) >= 5 && parts[3] == "profile" {
15
+
if len(parts) == 5 {
16
+
return parts[4]
17
+
}
18
+
if len(parts) == 7 && parts[5] == "post" {
19
+
return fmt.Sprintf("at://%s/app.bsky.feed.post/%s", parts[4], parts[6])
20
+
}
21
+
}
22
+
return raw
23
+
}
+23
cmd/astrolabe/parse_test.go
+23
cmd/astrolabe/parse_test.go
···
1
+
package main
2
+
3
+
import (
4
+
"testing"
5
+
6
+
"github.com/stretchr/testify/assert"
7
+
)
8
+
9
+
func TestParseServiceURL(t *testing.T) {
10
+
assert := assert.New(t)
11
+
12
+
testVec := [][]string{
13
+
{"", ""},
14
+
{"atproto.com", "atproto.com"},
15
+
{"https://bsky.app/profile/atproto.com", "atproto.com"},
16
+
{"https://bsky.app/profile/did:plc:ewvi7nxzyoun6zhxrhs64oiz", "did:plc:ewvi7nxzyoun6zhxrhs64oiz"},
17
+
{"https://bsky.app/profile/atproto.com/post/3lffzv6f4o22r", "at://atproto.com/app.bsky.feed.post/3lffzv6f4o22r"},
18
+
}
19
+
20
+
for _, pair := range testVec {
21
+
assert.Equal(pair[1], ParseServiceURL(pair[0]))
22
+
}
23
+
}
+2
-2
cmd/astrolabe/templates/base.html
+2
-2
cmd/astrolabe/templates/base.html
···
5
5
<meta name="referrer" content="origin-when-cross-origin">
6
6
<meta name="viewport" content="width=device-width, initial-scale=1">
7
7
<meta name="color-scheme" content="light dark" />
8
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.blue.min.css" />
8
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.zinc.min.css" />
9
9
<style>
10
10
html { position: relative; min-height: 100%; height: auto; }
11
11
body { margin-bottom: 3em; }
···
28
28
<input type="text" name="q" placeholder="at://..." {% if uri %}value="{{ uri }}"{% endif %} style="margin: 0.5em;">
29
29
</form>
30
30
<ul>
31
-
<li><a href="https://github.com/bluesky-social/indigo">Code</a></li>
31
+
<li><a href="https://github.com/bluesky-social/indigo/tree/main/cmd/astrolabe">Code</a></li>
32
32
</ul>
33
33
</nav>
34
34
+13
-1
cmd/astrolabe/templates/home.html
+13
-1
cmd/astrolabe/templates/home.html
···
1
1
{% extends "base.html" %}
2
2
3
3
{% block main_content %}
4
-
This is the homepage
4
+
<h2>astrolabe: AT Protocol Repository Browser</h2>
5
+
6
+
<p>This is a tool for browsing <a href="https://atproto.com">AT Protocol</a> ("atproto") repositories and records. You can enter an account identifier or full URI to view content as JSON. It works by fetching data directly from account PDS instances: the data itself is not hosted by this service.
7
+
8
+
<p>Examples:
9
+
<ul>
10
+
<li>Account Handle: <code><a href="/account/bnewbold.net">bnewbold.net</a></code></li>
11
+
<li>Account DID: <code><a href="/account/did:plc:44ybard66vv44zksje25o7dz">did:plc:44ybard66vv44zksje25o7dz</a></code></li>
12
+
<li>Collection: <code><a href="/at/bnewbold.net/app.bsky.feed.post">at://bnewbold.net/app.bsky.feed.post</a></code></li>
13
+
<li>Record: <code><a href="/at/did:plc:44ybard66vv44zksje25o7dz/app.bsky.actor.profile/self">at://bnewbold.net/app.bsky.actor.profile/self</a></code></li>
14
+
</ul>
15
+
16
+
<p>Other similar services include <a href="https://atproto-browser.vercel.app/">atproto-browser.vercel.app</a> and <a href="https://pdsls.dev/">pdsls.dev</a>.
5
17
{% endblock %}