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