@atproto/api 0.10.2 → 0.10.4

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,27 @@
1
1
  # @atproto/api
2
2
 
3
+ ## 0.10.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#2260](https://github.com/bluesky-social/atproto/pull/2260) [`6ec885992`](https://github.com/bluesky-social/atproto/commit/6ec8859929a16f9725319cc398b716acf913b01f) Thanks [@estrattonbailey](https://github.com/estrattonbailey)! - Export regex from rich text detection
8
+
9
+ - [#2260](https://github.com/bluesky-social/atproto/pull/2260) [`6ec885992`](https://github.com/bluesky-social/atproto/commit/6ec8859929a16f9725319cc398b716acf913b01f) Thanks [@estrattonbailey](https://github.com/estrattonbailey)! - Disallow rare unicode whitespace characters from tags
10
+
11
+ - [#2260](https://github.com/bluesky-social/atproto/pull/2260) [`6ec885992`](https://github.com/bluesky-social/atproto/commit/6ec8859929a16f9725319cc398b716acf913b01f) Thanks [@estrattonbailey](https://github.com/estrattonbailey)! - Allow tags to lead with numbers
12
+
13
+ ## 0.10.3
14
+
15
+ ### Patch Changes
16
+
17
+ - [#2247](https://github.com/bluesky-social/atproto/pull/2247) [`2a0ceb818`](https://github.com/bluesky-social/atproto/commit/2a0ceb8180faa17de8061d4fa6c361b57a2005ed) Thanks [@estrattonbailey](https://github.com/estrattonbailey)! - Fix double sanitization bug when editing muted words.
18
+
19
+ - [#2247](https://github.com/bluesky-social/atproto/pull/2247) [`2a0ceb818`](https://github.com/bluesky-social/atproto/commit/2a0ceb8180faa17de8061d4fa6c361b57a2005ed) Thanks [@estrattonbailey](https://github.com/estrattonbailey)! - More sanitization of muted words, including newlines and leading/trailing whitespace
20
+
21
+ - [#2247](https://github.com/bluesky-social/atproto/pull/2247) [`2a0ceb818`](https://github.com/bluesky-social/atproto/commit/2a0ceb8180faa17de8061d4fa6c361b57a2005ed) Thanks [@estrattonbailey](https://github.com/estrattonbailey)! - Add `sanitizeMutedWordValue` util
22
+
23
+ - [#2247](https://github.com/bluesky-social/atproto/pull/2247) [`2a0ceb818`](https://github.com/bluesky-social/atproto/commit/2a0ceb8180faa17de8061d4fa6c361b57a2005ed) Thanks [@estrattonbailey](https://github.com/estrattonbailey)! - Handle hash emoji in mute words
24
+
3
25
  ## 0.10.2
4
26
 
5
27
  ### Patch Changes
@@ -85,7 +85,7 @@ export declare class BskyAgent extends AtpAgent {
85
85
  setFeedViewPrefs(feed: string, pref: Partial<BskyFeedViewPreference>): Promise<void>;
86
86
  setThreadViewPrefs(pref: Partial<BskyThreadViewPreference>): Promise<void>;
87
87
  setInterestsPref(pref: Partial<BskyInterestsPreference>): Promise<void>;
88
- upsertMutedWords(mutedWords: AppBskyActorDefs.MutedWord[]): Promise<void>;
88
+ upsertMutedWords(newMutedWords: AppBskyActorDefs.MutedWord[]): Promise<void>;
89
89
  updateMutedWord(mutedWord: AppBskyActorDefs.MutedWord): Promise<void>;
90
90
  removeMutedWord(mutedWord: AppBskyActorDefs.MutedWord): Promise<void>;
91
91
  hidePost(postUri: string): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -2,11 +2,13 @@ export { AtUri } from '@atproto/syntax';
2
2
  export { BlobRef, lexToJson, stringifyLex, jsonToLex, jsonStringToLex, } from '@atproto/lexicon';
3
3
  export { parseLanguage } from '@atproto/common-web';
4
4
  export * from './types';
5
+ export * from './util';
5
6
  export * from './client';
6
7
  export * from './agent';
7
8
  export * from './rich-text/rich-text';
8
9
  export * from './rich-text/sanitization';
9
10
  export * from './rich-text/unicode';
11
+ export * from './rich-text/util';
10
12
  export * from './moderation';
11
13
  export * from './moderation/types';
12
14
  export { LABELS } from './moderation/const/labels';
package/dist/index.js CHANGED
@@ -9059,13 +9059,17 @@ __export(src_exports2, {
9059
9059
  ListRecord: () => ListRecord,
9060
9060
  ListblockRecord: () => ListblockRecord,
9061
9061
  ListitemRecord: () => ListitemRecord,
9062
+ MENTION_REGEX: () => MENTION_REGEX,
9062
9063
  ModerationDecision: () => ModerationDecision,
9063
9064
  PostRecord: () => PostRecord,
9064
9065
  ProfileRecord: () => ProfileRecord,
9065
9066
  RepostRecord: () => RepostRecord,
9066
9067
  RichText: () => RichText,
9067
9068
  RichTextSegment: () => RichTextSegment,
9069
+ TAG_REGEX: () => TAG_REGEX,
9070
+ TRAILING_PUNCTUATION_REGEX: () => TRAILING_PUNCTUATION_REGEX,
9068
9071
  ThreadgateRecord: () => ThreadgateRecord,
9072
+ URL_REGEX: () => URL_REGEX,
9069
9073
  UnicodeString: () => UnicodeString,
9070
9074
  default: () => AtpAgent,
9071
9075
  jsonStringToLex: () => jsonStringToLex,
@@ -9076,6 +9080,7 @@ __export(src_exports2, {
9076
9080
  moderateProfile: () => moderateProfile,
9077
9081
  moderateUserList: () => moderateUserList,
9078
9082
  parseLanguage: () => parseLanguage,
9083
+ sanitizeMutedWordValue: () => sanitizeMutedWordValue,
9079
9084
  sanitizeRichText: () => sanitizeRichText,
9080
9085
  stringifyLex: () => stringifyLex
9081
9086
  });
@@ -15383,6 +15388,11 @@ var jsonStringToLex = (val) => {
15383
15388
  return jsonToLex(JSON.parse(val));
15384
15389
  };
15385
15390
 
15391
+ // src/util.ts
15392
+ function sanitizeMutedWordValue(value) {
15393
+ return value.trim().replace(/^#(?!\ufe0f)/, "").replace(/[\r\n\u00AD\u2060\u200D\u200C\u200B]+/, "");
15394
+ }
15395
+
15386
15396
  // ../xrpc/src/types.ts
15387
15397
  var errorResponseBody = z.object({
15388
15398
  error: z.string().optional(),
@@ -30131,12 +30141,18 @@ var tlds_default = [
30131
30141
  "\uD55C\uAD6D"
30132
30142
  ];
30133
30143
 
30144
+ // src/rich-text/util.ts
30145
+ var MENTION_REGEX = /(^|\s|\()(@)([a-zA-Z0-9.-]+)(\b)/g;
30146
+ var URL_REGEX = /(^|\s|\()((https?:\/\/[\S]+)|((?<domain>[a-z][a-z0-9]*(\.[a-z0-9]+)+)[\S]*))/gim;
30147
+ var TRAILING_PUNCTUATION_REGEX = /\p{P}+$/gu;
30148
+ var TAG_REGEX = /(^|\s)[##]((?!\ufe0f)[^\s\u00AD\u2060\u200A\u200B\u200C\u200D\u20e2]*[^\d\s\p{P}\u00AD\u2060\u200A\u200B\u200C\u200D\u20e2]+[^\s\u00AD\u2060\u200A\u200B\u200C\u200D\u20e2]*)?/gu;
30149
+
30134
30150
  // src/rich-text/detection.ts
30135
30151
  function detectFacets(text) {
30136
30152
  let match;
30137
30153
  const facets = [];
30138
30154
  {
30139
- const re = /(^|\s|\()(@)([a-zA-Z0-9.-]+)(\b)/g;
30155
+ const re = MENTION_REGEX;
30140
30156
  while (match = re.exec(text.utf16)) {
30141
30157
  if (!isValidDomain(match[3]) && !match[3].endsWith(".test")) {
30142
30158
  continue;
@@ -30158,7 +30174,7 @@ function detectFacets(text) {
30158
30174
  }
30159
30175
  }
30160
30176
  {
30161
- const re = /(^|\s|\()((https?:\/\/[\S]+)|((?<domain>[a-z][a-z0-9]*(\.[a-z0-9]+)+)[\S]*))/gim;
30177
+ const re = URL_REGEX;
30162
30178
  while (match = re.exec(text.utf16)) {
30163
30179
  let uri2 = match[2];
30164
30180
  if (!uri2.startsWith("http")) {
@@ -30193,10 +30209,12 @@ function detectFacets(text) {
30193
30209
  }
30194
30210
  }
30195
30211
  {
30196
- const re = /(^|\s)#((?!\ufe0f)[^\d\s]\S*)(?=\s)?/g;
30212
+ const re = TAG_REGEX;
30197
30213
  while (match = re.exec(text.utf16)) {
30198
30214
  let [, leading, tag] = match;
30199
- tag = tag.trim().replace(/\p{P}+$/gu, "");
30215
+ if (!tag)
30216
+ continue;
30217
+ tag = tag.trim().replace(TRAILING_PUNCTUATION_REGEX, "");
30200
30218
  if (tag.length === 0 || tag.length > 64)
30201
30219
  continue;
30202
30220
  const index = match.index + leading.length;
@@ -32227,14 +32245,74 @@ var BskyAgent = class extends AtpAgent {
32227
32245
  return prefs.filter((p) => !defs_exports5.isInterestsPref(p)).concat([{ ...pref, $type: "app.bsky.actor.defs#interestsPref" }]);
32228
32246
  });
32229
32247
  }
32230
- async upsertMutedWords(mutedWords) {
32231
- await updateMutedWords(this, mutedWords, "upsert");
32248
+ async upsertMutedWords(newMutedWords) {
32249
+ await updatePreferences(this, (prefs) => {
32250
+ let mutedWordsPref = prefs.findLast((pref) => defs_exports5.isMutedWordsPref(pref) && defs_exports5.validateMutedWordsPref(pref).success);
32251
+ if (mutedWordsPref && defs_exports5.isMutedWordsPref(mutedWordsPref)) {
32252
+ for (const updatedWord of newMutedWords) {
32253
+ let foundMatch = false;
32254
+ const sanitizedUpdatedValue = sanitizeMutedWordValue(updatedWord.value);
32255
+ if (!sanitizedUpdatedValue)
32256
+ continue;
32257
+ for (const existingItem of mutedWordsPref.items) {
32258
+ if (existingItem.value === sanitizedUpdatedValue) {
32259
+ existingItem.targets = Array.from(/* @__PURE__ */ new Set([...existingItem.targets, ...updatedWord.targets]));
32260
+ foundMatch = true;
32261
+ break;
32262
+ }
32263
+ }
32264
+ if (!foundMatch) {
32265
+ mutedWordsPref.items.push({
32266
+ ...updatedWord,
32267
+ value: sanitizedUpdatedValue
32268
+ });
32269
+ }
32270
+ }
32271
+ } else {
32272
+ mutedWordsPref = {
32273
+ items: newMutedWords.map((w) => ({
32274
+ ...w,
32275
+ value: sanitizeMutedWordValue(w.value)
32276
+ }))
32277
+ };
32278
+ }
32279
+ return prefs.filter((p) => !defs_exports5.isMutedWordsPref(p)).concat([
32280
+ { ...mutedWordsPref, $type: "app.bsky.actor.defs#mutedWordsPref" }
32281
+ ]);
32282
+ });
32232
32283
  }
32233
32284
  async updateMutedWord(mutedWord) {
32234
- await updateMutedWords(this, [mutedWord], "update");
32285
+ await updatePreferences(this, (prefs) => {
32286
+ let mutedWordsPref = prefs.findLast((pref) => defs_exports5.isMutedWordsPref(pref) && defs_exports5.validateMutedWordsPref(pref).success);
32287
+ if (mutedWordsPref && defs_exports5.isMutedWordsPref(mutedWordsPref)) {
32288
+ for (const existingItem of mutedWordsPref.items) {
32289
+ if (existingItem.value === mutedWord.value) {
32290
+ existingItem.targets = mutedWord.targets;
32291
+ break;
32292
+ }
32293
+ }
32294
+ }
32295
+ return prefs.filter((p) => !defs_exports5.isMutedWordsPref(p)).concat([
32296
+ { ...mutedWordsPref, $type: "app.bsky.actor.defs#mutedWordsPref" }
32297
+ ]);
32298
+ });
32235
32299
  }
32236
32300
  async removeMutedWord(mutedWord) {
32237
- await updateMutedWords(this, [mutedWord], "remove");
32301
+ await updatePreferences(this, (prefs) => {
32302
+ let mutedWordsPref = prefs.findLast((pref) => defs_exports5.isMutedWordsPref(pref) && defs_exports5.validateMutedWordsPref(pref).success);
32303
+ if (mutedWordsPref && defs_exports5.isMutedWordsPref(mutedWordsPref)) {
32304
+ for (let i = 0; i < mutedWordsPref.items.length; i++) {
32305
+ const existing = mutedWordsPref.items[i];
32306
+ if (existing.value === mutedWord.value) {
32307
+ mutedWordsPref.items.splice(i, 1);
32308
+ break;
32309
+ }
32310
+ }
32311
+ }
32312
+ return prefs.filter((p) => !defs_exports5.isMutedWordsPref(p)).concat([
32313
+ { ...mutedWordsPref, $type: "app.bsky.actor.defs#mutedWordsPref" }
32314
+ ]);
32315
+ });
32238
32316
  }
32239
32317
  async hidePost(postUri) {
32240
32318
  await updateHiddenPost(this, postUri, "hide");
@@ -32273,51 +32351,6 @@ async function updateFeedPreferences(agent, cb) {
32273
32351
  });
32274
32352
  return res;
32275
32353
  }
32276
- async function updateMutedWords(agent, mutedWords, action) {
32277
- const sanitizeMutedWord = (word) => ({
32278
- value: word.value.replace(/^#/, ""),
32279
- targets: word.targets
32280
- });
32281
- await updatePreferences(agent, (prefs) => {
32282
- let mutedWordsPref = prefs.findLast((pref) => defs_exports5.isMutedWordsPref(pref) && defs_exports5.validateMutedWordsPref(pref).success);
32283
- if (mutedWordsPref && defs_exports5.isMutedWordsPref(mutedWordsPref)) {
32284
- if (action === "upsert" || action === "update") {
32285
- for (const word of mutedWords) {
32286
- let foundMatch = false;
32287
- for (const existingItem of mutedWordsPref.items) {
32288
- if (existingItem.value === sanitizeMutedWord(word).value) {
32289
- existingItem.targets = action === "upsert" ? Array.from(/* @__PURE__ */ new Set([...existingItem.targets, ...word.targets])) : word.targets;
32290
- foundMatch = true;
32291
- break;
32292
- }
32293
- }
32294
- if (action === "upsert" && !foundMatch) {
32295
- mutedWordsPref.items.push(sanitizeMutedWord(word));
32296
- }
32297
- }
32298
- } else if (action === "remove") {
32299
- for (const word of mutedWords) {
32300
- for (let i = 0; i < mutedWordsPref.items.length; i++) {
32301
- const existing = mutedWordsPref.items[i];
32302
- if (existing.value === sanitizeMutedWord(word).value) {
32303
- mutedWordsPref.items.splice(i, 1);
32304
- break;
32305
- }
32306
- }
32307
- }
32308
- }
32309
- } else {
32310
- if (action === "upsert") {
32311
- mutedWordsPref = {
32312
- items: mutedWords.map(sanitizeMutedWord)
32313
- };
32314
- }
32315
- }
32316
- return prefs.filter((p) => !defs_exports5.isMutedWordsPref(p)).concat([
32317
- { ...mutedWordsPref, $type: "app.bsky.actor.defs#mutedWordsPref" }
32318
- ]);
32319
- });
32320
- }
32321
32354
  async function updateHiddenPost(agent, postUri, action) {
32322
32355
  await updatePreferences(agent, (prefs) => {
32323
32356
  let pref = prefs.findLast((pref2) => defs_exports5.isHiddenPostsPref(pref2) && defs_exports5.validateHiddenPostsPref(pref2).success);