1package rules
2
3import (
4 "bytes"
5 "context"
6 "log/slog"
7 "testing"
8
9 appbsky "github.com/bluesky-social/indigo/api/bsky"
10 "github.com/bluesky-social/indigo/atproto/identity"
11 "github.com/bluesky-social/indigo/atproto/syntax"
12 "github.com/bluesky-social/indigo/automod"
13 "github.com/bluesky-social/indigo/automod/engine"
14 "github.com/bluesky-social/indigo/automod/helpers"
15
16 "github.com/stretchr/testify/assert"
17)
18
19func TestMisleadingURLPostRule(t *testing.T) {
20 assert := assert.New(t)
21 ctx := context.Background()
22
23 eng := engine.EngineTestFixture()
24 am1 := automod.AccountMeta{
25 Identity: &identity.Identity{
26 DID: syntax.DID("did:plc:abc111"),
27 Handle: syntax.Handle("handle.example.com"),
28 },
29 }
30 cid1 := syntax.CID("cid123")
31 p1 := appbsky.FeedPost{
32 Text: "https://safe.com/ is very reputable",
33 Facets: []*appbsky.RichtextFacet{
34 &appbsky.RichtextFacet{
35 Features: []*appbsky.RichtextFacet_Features_Elem{
36 &appbsky.RichtextFacet_Features_Elem{
37 RichtextFacet_Link: &appbsky.RichtextFacet_Link{
38 Uri: "https://evil.com",
39 },
40 },
41 },
42 Index: &appbsky.RichtextFacet_ByteSlice{
43 ByteStart: 0,
44 ByteEnd: 16,
45 },
46 },
47 },
48 }
49 p1buf := new(bytes.Buffer)
50 assert.NoError(p1.MarshalCBOR(p1buf))
51 p1cbor := p1buf.Bytes()
52 op := engine.RecordOp{
53 Action: engine.CreateOp,
54 DID: am1.Identity.DID,
55 Collection: syntax.NSID("app.bsky.feed.post"),
56 RecordKey: syntax.RecordKey("abc123"),
57 CID: &cid1,
58 RecordCBOR: p1cbor,
59 }
60 c1 := engine.NewRecordContext(ctx, &eng, am1, op)
61 assert.NoError(MisleadingURLPostRule(&c1, &p1))
62 eff1 := engine.ExtractEffects(&c1.BaseContext)
63 assert.NotEmpty(eff1.RecordFlags)
64}
65
66func TestMisleadingMentionPostRule(t *testing.T) {
67 assert := assert.New(t)
68 ctx := context.Background()
69
70 eng := engine.EngineTestFixture()
71 am1 := automod.AccountMeta{
72 Identity: &identity.Identity{
73 DID: syntax.DID("did:plc:abc111"),
74 Handle: syntax.Handle("handle.example.com"),
75 },
76 }
77 cid1 := syntax.CID("cid123")
78 p1 := appbsky.FeedPost{
79 Text: "@handle.example.com is a friend",
80 Facets: []*appbsky.RichtextFacet{
81 &appbsky.RichtextFacet{
82 Features: []*appbsky.RichtextFacet_Features_Elem{
83 &appbsky.RichtextFacet_Features_Elem{
84 RichtextFacet_Mention: &appbsky.RichtextFacet_Mention{
85 Did: "did:plc:abc222",
86 },
87 },
88 },
89 Index: &appbsky.RichtextFacet_ByteSlice{
90 ByteStart: 1,
91 ByteEnd: 19,
92 },
93 },
94 },
95 }
96 p1buf := new(bytes.Buffer)
97 assert.NoError(p1.MarshalCBOR(p1buf))
98 p1cbor := p1buf.Bytes()
99 op := engine.RecordOp{
100 Action: engine.CreateOp,
101 DID: am1.Identity.DID,
102 Collection: syntax.NSID("app.bsky.feed.post"),
103 RecordKey: syntax.RecordKey("abc123"),
104 CID: &cid1,
105 RecordCBOR: p1cbor,
106 }
107 c1 := engine.NewRecordContext(ctx, &eng, am1, op)
108 assert.NoError(MisleadingMentionPostRule(&c1, &p1))
109 eff1 := engine.ExtractEffects(&c1.BaseContext)
110 assert.NotEmpty(eff1.RecordFlags)
111}
112
113func pstr(raw string) *string {
114 return &raw
115}
116
117func TestIsMisleadingURL(t *testing.T) {
118 assert := assert.New(t)
119 logger := slog.Default()
120
121 fixtures := []struct {
122 facet helpers.PostFacet
123 out bool
124 }{
125 {
126 facet: helpers.PostFacet{
127 Text: "https://atproto.com",
128 URL: pstr("https://atproto.com"),
129 },
130 out: false,
131 },
132 {
133 facet: helpers.PostFacet{
134 Text: "https://atproto.com",
135 URL: pstr("https://evil.com"),
136 },
137 out: true,
138 },
139 {
140 facet: helpers.PostFacet{
141 Text: "https://www.atproto.com",
142 URL: pstr("https://atproto.com"),
143 },
144 out: false,
145 },
146 {
147 facet: helpers.PostFacet{
148 Text: "https://atproto.com",
149 URL: pstr("https://www.atproto.com"),
150 },
151 out: false,
152 },
153 {
154 facet: helpers.PostFacet{
155 Text: "[example.com]",
156 URL: pstr("https://www.example.com"),
157 },
158 out: false,
159 },
160 {
161 facet: helpers.PostFacet{
162 Text: "example.com...",
163 URL: pstr("https://example.com.evil.com"),
164 },
165 out: true,
166 },
167 {
168 facet: helpers.PostFacet{
169 Text: "ATPROTO.com...",
170 URL: pstr("https://atproto.com"),
171 },
172 out: false,
173 },
174 {
175 facet: helpers.PostFacet{
176 Text: "1234.5678",
177 URL: pstr("https://arxiv.org/abs/1234.5678"),
178 },
179 out: false,
180 },
181 {
182 facet: helpers.PostFacet{
183 Text: "www.techdirt.com…",
184 URL: pstr("https://www.techdirt.com/"),
185 },
186 out: false,
187 },
188 }
189
190 for _, fix := range fixtures {
191 assert.Equal(fix.out, isMisleadingURLFacet(fix.facet, logger))
192 }
193}