@atproto/api 0.12.1 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @atproto/api
2
2
 
3
+ ## 0.12.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#2344](https://github.com/bluesky-social/atproto/pull/2344) [`abc6f82da`](https://github.com/bluesky-social/atproto/commit/abc6f82da38abef2b1bbe8d9e41a0534a5418c9e) Thanks [@estrattonbailey](https://github.com/estrattonbailey)! - Support muting words that contain apostrophes and other punctuation
8
+
3
9
  ## 0.12.1
4
10
 
5
11
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"mutewords.d.ts","sourceRoot":"","sources":["../../src/moderation/mutewords.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAuBlE,wBAAgB,YAAY,CAAC,EAC3B,UAAU,EACV,IAAI,EACJ,MAAM,EACN,WAAW,EACX,SAAS,GACV,EAAE;IACD,UAAU,EAAE,gBAAgB,CAAC,SAAS,EAAE,CAAA;IACxC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,oBAAoB,CAAC,IAAI,EAAE,CAAA;IACpC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB,WAuFA"}
1
+ {"version":3,"file":"mutewords.d.ts","sourceRoot":"","sources":["../../src/moderation/mutewords.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAuBlE,wBAAgB,YAAY,CAAC,EAC3B,UAAU,EACV,IAAI,EACJ,MAAM,EACN,WAAW,EACX,SAAS,GACV,EAAE;IACD,UAAU,EAAE,gBAAgB,CAAC,SAAS,EAAE,CAAA;IACxC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,oBAAoB,CAAC,IAAI,EAAE,CAAA;IACpC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB,WAiEA"}
@@ -64,30 +64,16 @@ function hasMutedWord({ mutedWords, text, facets, outlineTags, languages, }) {
64
64
  return true;
65
65
  if (mutedWord.length > wordTrimmedPunctuation.length)
66
66
  continue;
67
- // handle hyphenated, slash separated words, etc
68
- if (REGEX.SEPARATORS.test(wordTrimmedPunctuation)) {
69
- // check against full normalized phrase
70
- const wordNormalizedSeparators = wordTrimmedPunctuation.replace(REGEX.SEPARATORS, ' ');
71
- const mutedWordNormalizedSeparators = mutedWord.replace(REGEX.SEPARATORS, ' ');
72
- // hyphenated (or other sep) to spaced words
73
- if (wordNormalizedSeparators === mutedWordNormalizedSeparators)
67
+ if (/\p{P}+/u.test(wordTrimmedPunctuation)) {
68
+ const spacedWord = wordTrimmedPunctuation.replace(/\p{P}+/gu, ' ');
69
+ if (spacedWord === mutedWord)
74
70
  return true;
75
- /* Disabled for now e.g. `super-cool` to `supercool`
76
- const wordNormalizedCompressed = wordNormalizedSeparators.replace(
77
- REGEX.WORD_BOUNDARY,
78
- '',
79
- )
80
- const mutedWordNormalizedCompressed =
81
- mutedWordNormalizedSeparators.replace(/\s+?/g, '')
82
- // hyphenated (or other sep) to non-hyphenated contiguous word
83
- if (mutedWordNormalizedCompressed === wordNormalizedCompressed)
84
- return true
85
- */
86
- // then individual parts of separated phrases/words
87
- const wordParts = wordTrimmedPunctuation.split(REGEX.SEPARATORS);
88
- for (const wp of wordParts) {
89
- // still retain internal punctuation
90
- if (wp === mutedWord)
71
+ const contiguousWord = spacedWord.replace(/\s/gu, '');
72
+ if (contiguousWord === mutedWord)
73
+ return true;
74
+ const wordParts = wordTrimmedPunctuation.split(/\p{P}+/u);
75
+ for (const wordPart of wordParts) {
76
+ if (wordPart === mutedWord)
91
77
  return true;
92
78
  }
93
79
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mutewords.js","sourceRoot":"","sources":["../../src/moderation/mutewords.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mutewords.js","sourceRoot":"","sources":["../../src/moderation/mutewords.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/api",
3
- "version": "0.12.1",
3
+ "version": "0.12.2",
4
4
  "license": "MIT",
5
5
  "description": "Client library for atproto and Bluesky",
6
6
  "keywords": [
@@ -82,38 +82,16 @@ export function hasMutedWord({
82
82
  if (mutedWord === wordTrimmedPunctuation) return true
83
83
  if (mutedWord.length > wordTrimmedPunctuation.length) continue
84
84
 
85
- // handle hyphenated, slash separated words, etc
86
- if (REGEX.SEPARATORS.test(wordTrimmedPunctuation)) {
87
- // check against full normalized phrase
88
- const wordNormalizedSeparators = wordTrimmedPunctuation.replace(
89
- REGEX.SEPARATORS,
90
- ' ',
91
- )
92
- const mutedWordNormalizedSeparators = mutedWord.replace(
93
- REGEX.SEPARATORS,
94
- ' ',
95
- )
96
- // hyphenated (or other sep) to spaced words
97
- if (wordNormalizedSeparators === mutedWordNormalizedSeparators)
98
- return true
85
+ if (/\p{P}+/u.test(wordTrimmedPunctuation)) {
86
+ const spacedWord = wordTrimmedPunctuation.replace(/\p{P}+/gu, ' ')
87
+ if (spacedWord === mutedWord) return true
99
88
 
100
- /* Disabled for now e.g. `super-cool` to `supercool`
101
- const wordNormalizedCompressed = wordNormalizedSeparators.replace(
102
- REGEX.WORD_BOUNDARY,
103
- '',
104
- )
105
- const mutedWordNormalizedCompressed =
106
- mutedWordNormalizedSeparators.replace(/\s+?/g, '')
107
- // hyphenated (or other sep) to non-hyphenated contiguous word
108
- if (mutedWordNormalizedCompressed === wordNormalizedCompressed)
109
- return true
110
- */
89
+ const contiguousWord = spacedWord.replace(/\s/gu, '')
90
+ if (contiguousWord === mutedWord) return true
111
91
 
112
- // then individual parts of separated phrases/words
113
- const wordParts = wordTrimmedPunctuation.split(REGEX.SEPARATORS)
114
- for (const wp of wordParts) {
115
- // still retain internal punctuation
116
- if (wp === mutedWord) return true
92
+ const wordParts = wordTrimmedPunctuation.split(/\p{P}+/u)
93
+ for (const wordPart of wordParts) {
94
+ if (wordPart === mutedWord) return true
117
95
  }
118
96
  }
119
97
  }
@@ -1582,6 +1582,13 @@ describe('agent', () => {
1582
1582
  expect(end.mutedWords.find((m) => m.value === '##️⃣')).toBeFalsy()
1583
1583
  })
1584
1584
 
1585
+ it(`apostrophe: Bluesky's`, async () => {
1586
+ await agent.upsertMutedWords([{ value: `Bluesky's`, targets: [] }])
1587
+ const { mutedWords } = (await agent.getPreferences()).moderationPrefs
1588
+
1589
+ expect(mutedWords.find((m) => m.value === `Bluesky's`)).toBeTruthy()
1590
+ })
1591
+
1585
1592
  describe(`invalid characters`, () => {
1586
1593
  it('zero width space', async () => {
1587
1594
  const prev = (await agent.getPreferences()).moderationPrefs
@@ -89,6 +89,22 @@ describe(`hasMutedWord`, () => {
89
89
  expect(match).toBe(true)
90
90
  })
91
91
 
92
+ it(`match: single char with length > 1 ☠︎`, () => {
93
+ const rt = new RichText({
94
+ text: `Idk why ☠︎ but maybe`,
95
+ })
96
+ rt.detectFacetsWithoutResolution()
97
+
98
+ const match = hasMutedWord({
99
+ mutedWords: [{ value: '☠︎', targets: ['content'] }],
100
+ text: rt.text,
101
+ facets: rt.facets,
102
+ outlineTags: [],
103
+ })
104
+
105
+ expect(match).toBe(true)
106
+ })
107
+
92
108
  it(`no match: long muted word, short post`, () => {
93
109
  const rt = new RichText({
94
110
  text: `hey`,
@@ -248,6 +264,57 @@ describe(`hasMutedWord`, () => {
248
264
  })
249
265
  })
250
266
 
267
+ describe(`apostrophes: Bluesky's`, () => {
268
+ const rt = new RichText({
269
+ text: `Yay, Bluesky's mutewords work`,
270
+ })
271
+ rt.detectFacetsWithoutResolution()
272
+
273
+ it(`match: Bluesky's`, () => {
274
+ const match = hasMutedWord({
275
+ mutedWords: [{ value: `Bluesky's`, targets: ['content'] }],
276
+ text: rt.text,
277
+ facets: rt.facets,
278
+ outlineTags: [],
279
+ })
280
+
281
+ expect(match).toBe(true)
282
+ })
283
+
284
+ it(`match: Bluesky`, () => {
285
+ const match = hasMutedWord({
286
+ mutedWords: [{ value: 'Bluesky', targets: ['content'] }],
287
+ text: rt.text,
288
+ facets: rt.facets,
289
+ outlineTags: [],
290
+ })
291
+
292
+ expect(match).toBe(true)
293
+ })
294
+
295
+ it(`match: bluesky`, () => {
296
+ const match = hasMutedWord({
297
+ mutedWords: [{ value: 'bluesky', targets: ['content'] }],
298
+ text: rt.text,
299
+ facets: rt.facets,
300
+ outlineTags: [],
301
+ })
302
+
303
+ expect(match).toBe(true)
304
+ })
305
+
306
+ it(`match: blueskys`, () => {
307
+ const match = hasMutedWord({
308
+ mutedWords: [{ value: 'blueskys', targets: ['content'] }],
309
+ text: rt.text,
310
+ facets: rt.facets,
311
+ outlineTags: [],
312
+ })
313
+
314
+ expect(match).toBe(true)
315
+ })
316
+ })
317
+
251
318
  describe(`Why so S@assy?`, () => {
252
319
  const rt = new RichText({
253
320
  text: `Why so S@assy?`,
@@ -398,6 +465,17 @@ describe(`hasMutedWord`, () => {
398
465
  expect(match).toBe(true)
399
466
  })
400
467
 
468
+ it(`match: bad`, () => {
469
+ const match = hasMutedWord({
470
+ mutedWords: [{ value: `bad`, targets: ['content'] }],
471
+ text: rt.text,
472
+ facets: rt.facets,
473
+ outlineTags: [],
474
+ })
475
+
476
+ expect(match).toBe(true)
477
+ })
478
+
401
479
  it(`match: super bad`, () => {
402
480
  const match = hasMutedWord({
403
481
  mutedWords: [{ value: `super bad`, targets: ['content'] }],
@@ -417,7 +495,7 @@ describe(`hasMutedWord`, () => {
417
495
  outlineTags: [],
418
496
  })
419
497
 
420
- expect(match).toBe(false)
498
+ expect(match).toBe(true)
421
499
  })
422
500
  })
423
501
 
@@ -474,7 +552,7 @@ describe(`hasMutedWord`, () => {
474
552
  outlineTags: [],
475
553
  })
476
554
 
477
- expect(match).toBe(false)
555
+ expect(match).toBe(true)
478
556
  })
479
557
  })
480
558