fork
Configure Feed
Select the types of activity you want to include in your feed.
Live video on the AT Protocol
fork
Configure Feed
Select the types of activity you want to include in your feed.
1package api
2
3import (
4 "context"
5 "crypto"
6 "fmt"
7
8 "github.com/bluesky-social/indigo/atproto/atcrypto"
9 "github.com/decred/dcrd/dcrec/secp256k1"
10 "github.com/mr-tron/base58"
11 "stream.place/streamplace/pkg/atproto"
12 "stream.place/streamplace/pkg/log"
13 "stream.place/streamplace/pkg/media"
14)
15
16func (a *StreamplaceAPI) MakeMediaSigner(ctx context.Context, keyStr string) (media.MediaSigner, error) {
17 if len(keyStr) < 2 || keyStr[0] != 'z' {
18 return nil, fmt.Errorf("invalid authorization key (not a multibase base58btc string)")
19 }
20
21 var addrBytes []byte
22 var didBytes []byte
23 priv, err := atcrypto.ParsePrivateMultibase(keyStr)
24 if err == nil {
25 addrBytes = priv.Bytes()
26 } else {
27 decoded, err := base58.Decode(keyStr[1:])
28 if err != nil {
29 return nil, fmt.Errorf("invalid authorization key (not a base58btc string)")
30 }
31 addrBytes = decoded[:32]
32 didBytes = decoded[32:]
33 priv, err = atcrypto.ParsePrivateBytesK256(addrBytes)
34 if err != nil {
35 return nil, fmt.Errorf("invalid authorization key (not valid atproto): %w", err)
36 }
37 }
38
39 key, _ := secp256k1.PrivKeyFromBytes(addrBytes)
40 if key == nil {
41 return nil, fmt.Errorf("invalid authorization key (not valid secp256k1)")
42 }
43 var signer crypto.Signer = key.ToECDSA()
44 pub, err := priv.PublicKey()
45 if err != nil {
46 return nil, fmt.Errorf("invalid authorization key (could not parse as atproto): %w", err)
47 }
48
49 did := string(didBytes)
50
51 if did != "" {
52 repo, err := a.ATSync.SyncBlueskyRepo(ctx, did, a.Model)
53 if err != nil {
54 return nil, fmt.Errorf("could not resolve streamplace key: %w", err)
55 }
56 err = a.CLI.StreamIsAllowed(repo.DID)
57 if err != nil {
58 return nil, fmt.Errorf("user is not allowed to stream: %w", err)
59 }
60 signingKey, err := a.Model.GetSigningKey(ctx, pub.DIDKey(), repo.DID)
61 if err != nil {
62 return nil, fmt.Errorf("signing key not found: %w", err)
63 }
64 if signingKey == nil {
65 return nil, fmt.Errorf("signing key not found")
66 }
67 } else {
68 atkey, err := atproto.ParsePubKey(signer.Public())
69 if err != nil {
70 return nil, fmt.Errorf("invalid authorization key (not valid secp256k1): %w", err)
71 }
72 did = atkey.DIDKey()
73 err = a.CLI.StreamIsAllowed(did)
74 if err != nil {
75 return nil, fmt.Errorf("user is not allowed to stream: %w", err)
76 }
77 }
78
79 ctx = log.WithLogValues(ctx, "did", did)
80 err = a.checkBanned(ctx, did)
81 if err != nil {
82 return nil, err
83 }
84
85 mediaSigner, err := media.MakeMediaSigner(ctx, a.CLI, did, signer, a.Model)
86 if err != nil {
87 return nil, fmt.Errorf("invalid authorization key (not valid secp256k1): %w", err)
88 }
89
90 return mediaSigner, nil
91}
92
93func (a *StreamplaceAPI) checkBanned(ctx context.Context, did string) error {
94 labels, err := a.Model.GetActiveLabels(did)
95 if err != nil {
96 return fmt.Errorf("failed to get active labels: %w", err)
97 }
98 if atproto.IsBanned(labels...) {
99 log.Error(ctx, "user is banned", "did", did)
100 return fmt.Errorf("user is banned")
101 }
102 return nil
103}