+5
-3
cmd/appview/main.go
+5
-3
cmd/appview/main.go
···
1
1
package main
2
2
3
3
import (
4
-
"fmt"
4
+
"log/slog"
5
5
"net/http"
6
-
"os"
7
6
7
+
"atyo.app/internal/logging"
8
8
appview "atyo.app/internal/server"
9
9
)
10
10
11
11
func main() {
12
+
logging.Level.Set(slog.LevelDebug) // for active development
13
+
12
14
server := appview.NewServer()
13
15
mux := server.InitializeRoutes()
14
16
15
17
// TODO configurable listen address, TLS, etc
16
18
listenAddr := "127.0.0.1:3000"
17
-
fmt.Fprintln(os.Stderr, "Starting server on http://"+listenAddr)
19
+
slog.Info("Starting server on http://" + listenAddr)
18
20
http.ListenAndServe(listenAddr, mux)
19
21
}
+2
go.mod
+2
go.mod
···
37
37
github.com/ipfs/go-log v1.0.5 // indirect
38
38
github.com/ipfs/go-log/v2 v2.5.1 // indirect
39
39
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
40
+
github.com/jba/slog v0.2.0 // indirect
40
41
github.com/jbenet/goprocess v0.1.4 // indirect
41
42
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
42
43
github.com/mattn/go-isatty v0.0.20 // indirect
···
49
50
github.com/multiformats/go-multihash v0.2.3 // indirect
50
51
github.com/multiformats/go-varint v0.0.7 // indirect
51
52
github.com/opentracing/opentracing-go v1.2.0 // indirect
53
+
github.com/phsym/console-slog v0.3.1 // indirect
52
54
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
53
55
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect
54
56
github.com/prometheus/client_golang v1.17.0 // indirect
+4
go.sum
+4
go.sum
···
67
67
github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
68
68
github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg=
69
69
github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY=
70
+
github.com/jba/slog v0.2.0 h1:jI0U5NRR3EJKGsbeEVpItJNogk0c4RMeCl7vJmogCJI=
71
+
github.com/jba/slog v0.2.0/go.mod h1:0Dh7Vyz3Td68Z1OwzadfincHwr7v+PpzadrS2Jua338=
70
72
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
71
73
github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o=
72
74
github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
···
104
106
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
105
107
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
106
108
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
109
+
github.com/phsym/console-slog v0.3.1 h1:Fuzcrjr40xTc004S9Kni8XfNsk+qrptQmyR+wZw9/7A=
110
+
github.com/phsym/console-slog v0.3.1/go.mod h1:oJskjp/X6e6c0mGpfP8ELkfKUsrkDifYRAqJQgmdDS0=
107
111
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
108
112
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
109
113
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+2
-3
internal/auth/auth.go
+2
-3
internal/auth/auth.go
···
2
2
3
3
import (
4
4
"context"
5
-
"fmt"
6
-
"os"
5
+
"log/slog"
7
6
8
7
"atyo.app/internal/lookup"
9
8
"github.com/bluesky-social/indigo/api/atproto"
···
50
49
Rkey: rkey,
51
50
})
52
51
53
-
fmt.Fprintln(os.Stderr, "Created record: "+output.Uri)
52
+
slog.Info("Created ping record", "uri", output.Uri)
54
53
55
54
return err
56
55
}
+2
-2
internal/auth/basic.go
+2
-2
internal/auth/basic.go
···
3
3
import (
4
4
"context"
5
5
"fmt"
6
-
"os"
6
+
"log/slog"
7
7
8
8
"github.com/bluesky-social/indigo/api/atproto"
9
9
"github.com/bluesky-social/indigo/atproto/identity"
···
26
26
return nil, fmt.Errorf("failed to retrieve account PDS")
27
27
}
28
28
29
-
fmt.Fprintln(os.Stderr, "sending login request to "+pds)
29
+
slog.Info("sending login request", "pds", pds)
30
30
31
31
// clear out existing auth first
32
32
// TODO: use refresh token etc instead of this
+24
internal/logging/logging.go
+24
internal/logging/logging.go
···
1
+
// Package log provides a simple facade for [log/slog] to write text logs to
2
+
// stderr. TODO: access logs to stdout.
3
+
4
+
package logging
5
+
6
+
import (
7
+
"log/slog"
8
+
"os"
9
+
10
+
"github.com/phsym/console-slog"
11
+
)
12
+
13
+
const rfc3339Millis = "2006-01-02 15:04:05.000Z07:00"
14
+
15
+
var Level = new(slog.LevelVar) // Info by default
16
+
17
+
func init() {
18
+
logger := slog.New(console.NewHandler(os.Stderr, &console.HandlerOptions{
19
+
AddSource: true,
20
+
TimeFormat: rfc3339Millis,
21
+
}))
22
+
23
+
slog.SetDefault(logger)
24
+
}
+2
-6
internal/lookup/identity.go
+2
-6
internal/lookup/identity.go
···
2
2
3
3
import (
4
4
"context"
5
-
"fmt"
5
+
"log/slog"
6
6
"net/http"
7
-
"os"
8
7
"strings"
9
8
10
9
"atyo.app/internal/errs"
···
39
38
}
40
39
}
41
40
42
-
fmt.Fprintln(
43
-
os.Stderr,
44
-
"resolved to `"+targetId.Handle.String()+"` ("+targetId.DID.String()+")",
45
-
)
41
+
slog.Debug("resolved identity", "did", targetId.DID, "handle", targetId.Handle)
46
42
47
43
return targetId, nil
48
44
}
+28
-35
internal/ping/ingest_pings.go
+28
-35
internal/ping/ingest_pings.go
···
5
5
"encoding/hex"
6
6
"errors"
7
7
"fmt"
8
+
"log/slog"
8
9
"net/http"
9
-
"os"
10
10
"slices"
11
11
12
12
"atyo.app/api"
···
64
64
for _, repo := range response.Repos {
65
65
id, lookupErr := c.directory.LookupID(ctx, repo.Did)
66
66
if lookupErr != nil {
67
-
fmt.Fprintf(os.Stderr, "failed to resolve id %s: %s\n", repo.Did, lookupErr)
67
+
slog.Warn("failed to resolve identity", "did", repo.Did, "err", lookupErr)
68
68
continue
69
69
}
70
70
···
84
84
)
85
85
86
86
if err != nil {
87
-
fmt.Fprintf(os.Stderr, "failed to fetch from %s: %s\n", repo.Did, err)
87
+
slog.Warn("failed to fetch repo", "did", repo.Did, "err", err)
88
88
continue
89
89
}
90
-
fmt.Fprintf(os.Stderr, "got %d records for %s\n", len(records.Records), repo.Did)
90
+
slog.Debug("got repo records", "did", repo.Did, "count", len(records.Records))
91
91
92
92
for _, record := range records.Records {
93
93
ping, ok := record.Value.Val.(*atyo.Ping)
94
94
if !ok {
95
-
fmt.Fprintf(os.Stderr, "failed to convert %s to ping", record.Uri)
95
+
slog.Warn("failed to convert to ping", "uri", record.Uri)
96
96
continue
97
97
}
98
98
99
99
contents, err := decodePingContents(ping, key)
100
100
if err != nil {
101
-
fmt.Fprintln(os.Stderr, "failed to decode ping ", record.Uri, " - ", err)
101
+
slog.Warn("failed to decode ping", "uri", record.Uri, "err", err)
102
102
continue
103
103
}
104
-
if contents != nil {
105
-
from, _ := c.directory.LookupID(ctx, repo.Did)
106
-
var fromHandle *string
107
-
if from != nil {
108
-
handle := from.Handle.String()
109
-
fromHandle = &handle
110
-
}
111
104
112
-
result = append(result, Ping{
113
-
FromDID: repo.Did,
114
-
FromHandle: fromHandle,
115
-
Contents: contents,
116
-
})
117
-
} else {
118
-
fmt.Fprintln(os.Stderr, "ping ", record.Uri, "not targeted to self")
105
+
if contents == nil {
106
+
slog.Debug("ping not targeted to self", "uri", record.Uri)
107
+
continue
108
+
}
109
+
110
+
from, _ := c.directory.LookupID(ctx, repo.Did)
111
+
var fromHandle *string
112
+
if from != nil {
113
+
handle := from.Handle.String()
114
+
fromHandle = &handle
119
115
}
116
+
117
+
result = append(result, Ping{
118
+
FromDID: repo.Did,
119
+
FromHandle: fromHandle,
120
+
Contents: contents,
121
+
})
120
122
}
121
123
}
122
124
···
143
145
var sharedKey *[sharedKeyLen]byte
144
146
145
147
for len(contents) > encryptedHeaderLen {
146
-
fmt.Fprintf(
147
-
os.Stderr,
148
-
"attempting to decode header bytes %s\n",
149
-
hex.EncodeToString(contents[:encryptedHeaderLen]),
148
+
slog.Debug(
149
+
"attempting to decode header",
150
+
"bytes", hex.EncodeToString(contents[:encryptedHeaderLen]),
150
151
)
151
152
header, ok := box.Open(
152
153
nil,
···
157
158
)
158
159
159
160
if ok {
160
-
fmt.Fprintln(os.Stderr, "Success! found shared key for ping")
161
+
slog.Info("found shared key for ping")
161
162
162
163
numRecipients := int(header[0])
163
164
sharedKey = new([sharedKeyLen]byte)
···
171
172
172
173
contents = contents[encryptedHeaderLen:]
173
174
174
-
fmt.Fprintf(
175
-
os.Stderr,
176
-
"failed to decode header, %d bytes remain\n",
177
-
len(contents),
178
-
)
175
+
slog.Debug("failed to decode header", "remaining", len(contents))
179
176
}
180
177
181
178
if sharedKey == nil {
···
217
214
return nil, fmt.Errorf("unexpected type %T decoded", val)
218
215
}
219
216
220
-
fmt.Fprintf(
221
-
os.Stderr,
222
-
"Decoded contents: %s\nCBOR: %+v\n",
223
-
hex.EncodeToString(decryptedContents), pingContents,
224
-
)
217
+
slog.Debug("decoded ping", "contents", pingContents)
225
218
226
219
return pingContents, nil
227
220
}
+3
-2
internal/ping/keys.go
+3
-2
internal/ping/keys.go
···
3
3
import (
4
4
"context"
5
5
"crypto/rand"
6
+
"encoding/hex"
6
7
"fmt"
7
-
"os"
8
+
"log/slog"
8
9
9
10
"atyo.app/api"
10
11
"atyo.app/api/atyo"
···
137
138
return err
138
139
}
139
140
140
-
fmt.Fprintln(os.Stderr, "created pubkey record")
141
+
slog.Info("created pubkey record", "public_key", hex.EncodeToString(selfPubKey[:]))
141
142
142
143
k.selfPrivateKey = selfPrivKey
143
144
return nil
+6
-9
internal/ping/send_ping.go
+6
-9
internal/ping/send_ping.go
···
7
7
"encoding/hex"
8
8
"errors"
9
9
"fmt"
10
-
"os"
10
+
"log/slog"
11
11
12
12
"atyo.app/api"
13
13
"atyo.app/api/atyo"
···
27
27
// Basic ping functionality.
28
28
// - `target` should be a DID or handle
29
29
func (c *Client) SendPing(ctx context.Context, target string) error {
30
-
fmt.Fprintln(os.Stderr, "got request for ping to `"+target+"`")
30
+
slog.Info("Got ping request", "target", target)
31
31
32
32
targetId, err := c.directory.LookupID(ctx, target)
33
33
if err != nil {
···
111
111
// CBOR/JSON encoding, or a schema version? idk if that's really useful for any reason
112
112
contents := append(encHeader, encryptedMessage...)
113
113
114
-
fmt.Fprintf(
115
-
os.Stderr,
116
-
"Targeting ping to pubkey %s\nHeader bytes: %s\n",
117
-
hex.EncodeToString(targetPubkey[:]),
118
-
hex.EncodeToString(encHeader[:]),
114
+
slog.Debug(
115
+
"built ping",
116
+
"target_pubkey", hex.EncodeToString(targetPubkey[:]),
117
+
"len", len(contents),
119
118
)
120
-
121
-
fmt.Fprintln(os.Stderr, "contents total len: ", len(contents))
122
119
123
120
return &atyo.Ping{
124
121
Contents: contents,
+6
-5
internal/server/router.go
+6
-5
internal/server/router.go
···
3
3
import (
4
4
"encoding/json"
5
5
"errors"
6
-
"fmt"
6
+
"log/slog"
7
7
"net/http"
8
-
"os"
9
8
10
9
"atyo.app/internal/auth"
11
10
"atyo.app/internal/errs"
···
85
84
86
85
_, err = w.Write(bytes)
87
86
if err != nil {
88
-
fmt.Fprintln(os.Stderr, "failed to write response: "+err.Error())
87
+
slog.Error("failed to write response", "err", err)
89
88
}
90
89
}
91
90
···
93
92
user := req.FormValue("username")
94
93
pass := req.FormValue("password")
95
94
96
-
fmt.Fprintln(os.Stderr, "Attempting login as `"+user+"`")
95
+
slog.Info("Attempting login", "user", user)
97
96
98
97
var authFactorToken *string
99
98
if req.Form.Has("authFactorToken") {
···
129
128
130
129
_, err = w.Write(bytes)
131
130
if err != nil {
132
-
fmt.Fprintln(os.Stderr, "failed to write JSON response: "+err.Error())
131
+
slog.Warn("failed to write JSON response", "err", err)
133
132
}
134
133
}
135
134
136
135
func handleErr(w http.ResponseWriter, err error) {
136
+
slog.Info("sending error response", "err", err)
137
+
137
138
var xErr *xrpc.Error
138
139
if errors.As(err, &xErr) {
139
140
// Hmm maybe this should be a 50x or certain codes should translate...