@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 +22 -0
- package/dist/bsky-agent.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +86 -53
- package/dist/index.js.map +3 -3
- package/dist/rich-text/util.d.ts +4 -0
- package/dist/util.d.ts +1 -0
- package/package.json +2 -2
- package/src/bsky-agent.ts +97 -74
- package/src/index.ts +2 -0
- package/src/rich-text/detection.ts +13 -5
- package/src/rich-text/util.ts +11 -0
- package/src/util.ts +6 -0
- package/tests/bsky-agent.test.ts +131 -7
- package/tests/rich-text-detection.test.ts +38 -3
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
|
package/dist/bsky-agent.d.ts
CHANGED
|
@@ -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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
30212
|
+
const re = TAG_REGEX;
|
|
30197
30213
|
while (match = re.exec(text.utf16)) {
|
|
30198
30214
|
let [, leading, tag] = match;
|
|
30199
|
-
|
|
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(
|
|
32231
|
-
await
|
|
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
|
|
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
|
|
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);
|