tangled
alpha
login
or
join now
stream.place
/
streamplace
Live video on the AT Protocol
74
fork
atom
overview
issues
1
pulls
pipelines
moderation: ozone proxy experiment
Eli Mallon
6 months ago
6ad92bb2
408408f0
+123
-4
4 changed files
expand all
collapse all
unified
split
go.mod
go.sum
pkg
spxrpc
com_atproto_moderation.go
spxrpc.go
+3
-1
go.mod
···
10
10
11
11
replace github.com/AxisCommunications/go-dpop => github.com/streamplace/go-dpop v0.0.0-20250510031900-c897158a8ad4
12
12
13
13
+
replace github.com/streamplace/oatproxy => ../oatproxy
14
14
+
13
15
require (
14
16
firebase.google.com/go/v4 v4.14.1
15
17
git.stream.place/streamplace/c2pa-go v0.7.0
···
37
39
github.com/johncgriffin/overflow v0.0.0-20211019200055-46fa312c352c
38
40
github.com/julienschmidt/httprouter v1.3.0
39
41
github.com/labstack/echo/v4 v4.13.3
42
42
+
github.com/labstack/gommon v0.4.2
40
43
github.com/lestrrat-go/jwx/v2 v2.1.6
41
44
github.com/livepeer/lpms v0.0.0-20240812093642-b5181eb92cb2
42
45
github.com/lmittmann/tint v1.1.0
···
267
270
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
268
271
github.com/kulti/thelper v0.6.3 // indirect
269
272
github.com/kunwardeep/paralleltest v1.0.14 // indirect
270
270
-
github.com/labstack/gommon v0.4.2 // indirect
271
273
github.com/lasiar/canonicalheader v1.1.2 // indirect
272
274
github.com/ldez/exptostd v0.4.3 // indirect
273
275
github.com/ldez/gomoddirectives v0.6.1 // indirect
-2
go.sum
···
938
938
github.com/streamplace/atproto-oauth-golang v0.0.0-20250619231223-a9c04fb888ac/go.mod h1:9LlKkqciiO5lRfbX0n4Wn5KNY9nvFb4R3by8FdW2TWc=
939
939
github.com/streamplace/go-dpop v0.0.0-20250510031900-c897158a8ad4 h1:L1fS4HJSaAyNnkwfuZubgfeZy8rkWmA0cMtH5Z0HqNc=
940
940
github.com/streamplace/go-dpop v0.0.0-20250510031900-c897158a8ad4/go.mod h1:bGUXY9Wd4mnd+XUrOYZr358J2f6z9QO/dLhL1SsiD+0=
941
941
-
github.com/streamplace/oatproxy v0.0.0-20250619231549-b15df1b82a3a h1:rbfSEm9IgK6jhXXtOExexL+ACNDOE/zJ5VYp6ujTpCA=
942
942
-
github.com/streamplace/oatproxy v0.0.0-20250619231549-b15df1b82a3a/go.mod h1:pXi24hA7xBHj8eEywX6wGqJOR9FaEYlGwQ/72rN6okw=
943
941
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
944
942
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
945
943
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+99
-1
pkg/spxrpc/com_atproto_moderation.go
···
1
1
package spxrpc
2
2
3
3
import (
4
4
+
"bytes"
4
5
"context"
6
6
+
"encoding/json"
7
7
+
"fmt"
8
8
+
"io"
9
9
+
"net/http"
5
10
6
11
comatprototypes "github.com/bluesky-social/indigo/api/atproto"
12
12
+
"github.com/bluesky-social/indigo/xrpc"
13
13
+
"github.com/labstack/echo/v4"
14
14
+
"github.com/streamplace/oatproxy/pkg/oatproxy"
15
15
+
"stream.place/streamplace/pkg/aqhttp"
16
16
+
"stream.place/streamplace/pkg/log"
7
17
)
8
18
9
19
func (s *Server) handleComAtprotoModerationCreateReport(ctx context.Context, body *comatprototypes.ModerationCreateReport_Input) (*comatprototypes.ModerationCreateReport_Output, error) {
10
10
-
panic("not implemented")
20
20
+
c, ok := ctx.Value(echoContextKey).(echo.Context)
21
21
+
if !ok {
22
22
+
return nil, echo.NewHTTPError(http.StatusInternalServerError, "echo context not found")
23
23
+
}
24
24
+
25
25
+
dPoP := c.Request().Header.Get("DPoP")
26
26
+
if dPoP == "" {
27
27
+
return s.handleComAtprotoModerationCreateReportToOzone(ctx, c, body)
28
28
+
} else {
29
29
+
return s.handleComAtprotoModerationCreateReportToPDS(ctx, c, body)
30
30
+
}
31
31
+
}
32
32
+
33
33
+
func (s *Server) handleComAtprotoModerationCreateReportToOzone(ctx context.Context, c echo.Context, body *comatprototypes.ModerationCreateReport_Input) (*comatprototypes.ModerationCreateReport_Output, error) {
34
34
+
// Serialize the input body to JSON
35
35
+
jsonBody, err := json.Marshal(body)
36
36
+
if err != nil {
37
37
+
return nil, echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to marshal request body: %v", err))
38
38
+
}
39
39
+
40
40
+
// Create the request URL
41
41
+
url := fmt.Sprintf("%s/xrpc/com.atproto.moderation.createReport", s.cli.OzoneURL)
42
42
+
43
43
+
// Create the HTTP request
44
44
+
req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(jsonBody))
45
45
+
if err != nil {
46
46
+
return nil, echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to create request: %v", err))
47
47
+
}
48
48
+
49
49
+
authorization := c.Request().Header.Get("Authorization")
50
50
+
if authorization == "" {
51
51
+
return nil, echo.NewHTTPError(http.StatusUnauthorized, "Authorization header not found")
52
52
+
}
53
53
+
54
54
+
log.Log(ctx, "handleComAtprotoModerationCreateReportToOzone", "authorization", authorization)
55
55
+
56
56
+
// Set headers
57
57
+
req.Header.Set("Content-Type", "application/json")
58
58
+
req.Header.Set("Authorization", authorization)
59
59
+
60
60
+
// Send the request
61
61
+
resp, err := aqhttp.Client.Do(req)
62
62
+
if err != nil {
63
63
+
return nil, echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to send request: %v", err))
64
64
+
}
65
65
+
defer resp.Body.Close()
66
66
+
67
67
+
// Read the response body
68
68
+
respBody, err := io.ReadAll(resp.Body)
69
69
+
if err != nil {
70
70
+
return nil, echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to read response body: %v", err))
71
71
+
}
72
72
+
73
73
+
// Check if the response was successful
74
74
+
if resp.StatusCode != http.StatusOK {
75
75
+
return nil, echo.NewHTTPError(resp.StatusCode, fmt.Sprintf("upstream error: %s", string(respBody)))
76
76
+
}
77
77
+
78
78
+
// Deserialize the response
79
79
+
var output comatprototypes.ModerationCreateReport_Output
80
80
+
if err := json.Unmarshal(respBody, &output); err != nil {
81
81
+
return nil, echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to unmarshal response: %v", err))
82
82
+
}
83
83
+
84
84
+
return &output, nil
85
85
+
}
86
86
+
87
87
+
func (s *Server) handleComAtprotoModerationCreateReportToPDS(ctx context.Context, c echo.Context, body *comatprototypes.ModerationCreateReport_Input) (*comatprototypes.ModerationCreateReport_Output, error) {
88
88
+
log.Log(ctx, "handleComAtprotoModerationCreateReport", "body", body)
89
89
+
if s.cli.OzoneURL == "" {
90
90
+
return nil, echo.NewHTTPError(http.StatusNotImplemented, "Ozone URL is not set")
91
91
+
}
92
92
+
93
93
+
session, client := oatproxy.GetOAuthSession(ctx)
94
94
+
if session == nil {
95
95
+
return nil, echo.NewHTTPError(http.StatusUnauthorized, "oauth session not found")
96
96
+
}
97
97
+
98
98
+
client.SetHeaders(map[string]string{
99
99
+
"Atproto-Proxy": fmt.Sprintf("%s#atproto_labeler", s.cli.MyDID()),
100
100
+
})
101
101
+
102
102
+
var output comatprototypes.ModerationCreateReport_Output
103
103
+
err := client.Do(ctx, xrpc.Procedure, "application/json", "com.atproto.moderation.createReport", nil, body, &output)
104
104
+
if err != nil {
105
105
+
return nil, echo.NewHTTPError(http.StatusInternalServerError, err.Error())
106
106
+
}
107
107
+
108
108
+
return &output, nil
11
109
}
+21
pkg/spxrpc/spxrpc.go
···
27
27
model: model,
28
28
}
29
29
e.Use(s.ErrorHandlingMiddleware())
30
30
+
e.Use(s.ContextPreservingMiddleware())
30
31
e.Use(echomiddleware.Handler("", mdlw))
31
32
e.Use(op.OAuthMiddleware)
32
33
err := s.RegisterHandlersPlaceStream(e)
···
71
72
}
72
73
}
73
74
}
75
75
+
76
76
+
// unique type to prevent assignment.
77
77
+
type echoContextKeyType struct{}
78
78
+
79
79
+
// singleton value to identify our logging metadata in context
80
80
+
var echoContextKey = echoContextKeyType{}
81
81
+
82
82
+
func (s *Server) ContextPreservingMiddleware() echo.MiddlewareFunc {
83
83
+
return func(next echo.HandlerFunc) echo.HandlerFunc {
84
84
+
return func(c echo.Context) error {
85
85
+
ctx := c.Request().Context()
86
86
+
if ctx == nil {
87
87
+
ctx = context.Background()
88
88
+
}
89
89
+
ctx = context.WithValue(ctx, echoContextKey, c)
90
90
+
c.SetRequest(c.Request().WithContext(ctx))
91
91
+
return next(c)
92
92
+
}
93
93
+
}
94
94
+
}