@atproto/api 0.12.26-next.0 → 0.12.26
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 +6 -0
- package/dist/bsky-agent.d.ts +23 -1
- package/dist/bsky-agent.d.ts.map +1 -1
- package/dist/bsky-agent.js +106 -42
- package/dist/bsky-agent.js.map +1 -1
- package/dist/client/index.d.ts +0 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +4 -6
- package/dist/client/index.js.map +1 -1
- package/dist/client/lexicons.d.ts +29 -101
- package/dist/client/lexicons.d.ts.map +1 -1
- package/dist/client/lexicons.js +32 -112
- package/dist/client/lexicons.js.map +1 -1
- package/dist/client/types/app/bsky/actor/defs.d.ts +5 -0
- package/dist/client/types/app/bsky/actor/defs.d.ts.map +1 -1
- package/dist/client/types/app/bsky/actor/defs.js.map +1 -1
- package/dist/client/types/app/bsky/embed/images.d.ts +10 -3
- package/dist/client/types/app/bsky/embed/images.d.ts.map +1 -1
- package/dist/client/types/app/bsky/embed/images.js +11 -1
- package/dist/client/types/app/bsky/embed/images.js.map +1 -1
- package/dist/client/types/app/bsky/embed/record.d.ts +1 -2
- package/dist/client/types/app/bsky/embed/record.d.ts.map +1 -1
- package/dist/client/types/app/bsky/embed/record.js.map +1 -1
- package/dist/client/types/app/bsky/embed/recordWithMedia.d.ts +2 -3
- package/dist/client/types/app/bsky/embed/recordWithMedia.d.ts.map +1 -1
- package/dist/client/types/app/bsky/embed/recordWithMedia.js.map +1 -1
- package/dist/client/types/app/bsky/feed/defs.d.ts +1 -2
- package/dist/client/types/app/bsky/feed/defs.d.ts.map +1 -1
- package/dist/client/types/app/bsky/feed/defs.js.map +1 -1
- package/dist/client/types/app/bsky/feed/post.d.ts +1 -2
- package/dist/client/types/app/bsky/feed/post.d.ts.map +1 -1
- package/dist/client/types/app/bsky/feed/post.js.map +1 -1
- package/dist/moderation/mutewords.d.ts +2 -1
- package/dist/moderation/mutewords.d.ts.map +1 -1
- package/dist/moderation/mutewords.js +7 -1
- package/dist/moderation/mutewords.js.map +1 -1
- package/dist/moderation/subjects/post.js +13 -0
- package/dist/moderation/subjects/post.js.map +1 -1
- package/package.json +3 -3
- package/src/bsky-agent.ts +139 -45
- package/src/client/index.ts +0 -4
- package/src/client/lexicons.ts +35 -114
- package/src/client/types/app/bsky/actor/defs.ts +5 -0
- package/src/client/types/app/bsky/embed/images.ts +21 -3
- package/src/client/types/app/bsky/embed/record.ts +0 -2
- package/src/client/types/app/bsky/embed/recordWithMedia.ts +0 -3
- package/src/client/types/app/bsky/feed/defs.ts +0 -2
- package/src/client/types/app/bsky/feed/post.ts +0 -2
- package/src/moderation/mutewords.ts +11 -0
- package/src/moderation/subjects/post.ts +15 -0
- package/tests/bsky-agent.test.ts +525 -156
- package/tests/moderation-mutewords.test.ts +308 -50
- package/dist/client/types/app/bsky/embed/defs.d.ts +0 -13
- package/dist/client/types/app/bsky/embed/defs.d.ts.map +0 -1
- package/dist/client/types/app/bsky/embed/defs.js +0 -16
- package/dist/client/types/app/bsky/embed/defs.js.map +0 -1
- package/dist/client/types/app/bsky/embed/video.d.ts +0 -33
- package/dist/client/types/app/bsky/embed/video.d.ts.map +0 -1
- package/dist/client/types/app/bsky/embed/video.js +0 -35
- package/dist/client/types/app/bsky/embed/video.js.map +0 -1
- package/src/client/types/app/bsky/embed/defs.ts +0 -26
- package/src/client/types/app/bsky/embed/video.ts +0 -67
package/src/bsky-agent.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
AppBskyLabelerDefs,
|
|
10
10
|
ComAtprotoRepoPutRecord,
|
|
11
11
|
} from './client'
|
|
12
|
+
import { MutedWord } from './client/types/app/bsky/actor/defs'
|
|
12
13
|
import {
|
|
13
14
|
BskyPreferences,
|
|
14
15
|
BskyFeedViewPreference,
|
|
@@ -477,6 +478,14 @@ export class BskyAgent extends AtpAgent {
|
|
|
477
478
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
478
479
|
const { $type, ...v } = pref
|
|
479
480
|
prefs.moderationPrefs.mutedWords = v.items
|
|
481
|
+
|
|
482
|
+
if (prefs.moderationPrefs.mutedWords.length) {
|
|
483
|
+
prefs.moderationPrefs.mutedWords =
|
|
484
|
+
prefs.moderationPrefs.mutedWords.map((word) => {
|
|
485
|
+
word.actorTarget = word.actorTarget || 'all'
|
|
486
|
+
return word
|
|
487
|
+
})
|
|
488
|
+
}
|
|
480
489
|
} else if (
|
|
481
490
|
AppBskyActorDefs.isHiddenPostsPref(pref) &&
|
|
482
491
|
AppBskyActorDefs.validateHiddenPostsPref(pref).success
|
|
@@ -937,7 +946,19 @@ export class BskyAgent extends AtpAgent {
|
|
|
937
946
|
})
|
|
938
947
|
}
|
|
939
948
|
|
|
940
|
-
|
|
949
|
+
/**
|
|
950
|
+
* Add a muted word to user preferences.
|
|
951
|
+
*/
|
|
952
|
+
async addMutedWord(
|
|
953
|
+
mutedWord: Pick<
|
|
954
|
+
MutedWord,
|
|
955
|
+
'value' | 'targets' | 'actorTarget' | 'expiresAt'
|
|
956
|
+
>,
|
|
957
|
+
) {
|
|
958
|
+
const sanitizedValue = sanitizeMutedWordValue(mutedWord.value)
|
|
959
|
+
|
|
960
|
+
if (!sanitizedValue) return
|
|
961
|
+
|
|
941
962
|
await updatePreferences(this, (prefs: AppBskyActorDefs.Preferences) => {
|
|
942
963
|
let mutedWordsPref = prefs.findLast(
|
|
943
964
|
(pref) =>
|
|
@@ -945,40 +966,27 @@ export class BskyAgent extends AtpAgent {
|
|
|
945
966
|
AppBskyActorDefs.validateMutedWordsPref(pref).success,
|
|
946
967
|
)
|
|
947
968
|
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
// was trimmed down to an empty string e.g. single `#`
|
|
956
|
-
if (!sanitizedUpdatedValue) continue
|
|
969
|
+
const newMutedWord: AppBskyActorDefs.MutedWord = {
|
|
970
|
+
id: TID.nextStr(),
|
|
971
|
+
value: sanitizedValue,
|
|
972
|
+
targets: mutedWord.targets || [],
|
|
973
|
+
actorTarget: mutedWord.actorTarget || 'all',
|
|
974
|
+
expiresAt: mutedWord.expiresAt || undefined,
|
|
975
|
+
}
|
|
957
976
|
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
existingItem.targets = Array.from(
|
|
961
|
-
new Set([...existingItem.targets, ...updatedWord.targets]),
|
|
962
|
-
)
|
|
963
|
-
foundMatch = true
|
|
964
|
-
break
|
|
965
|
-
}
|
|
966
|
-
}
|
|
977
|
+
if (mutedWordsPref && AppBskyActorDefs.isMutedWordsPref(mutedWordsPref)) {
|
|
978
|
+
mutedWordsPref.items.push(newMutedWord)
|
|
967
979
|
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
}
|
|
980
|
+
/**
|
|
981
|
+
* Migrate any old muted words that don't have an id
|
|
982
|
+
*/
|
|
983
|
+
mutedWordsPref.items = migrateLegacyMutedWordsItems(
|
|
984
|
+
mutedWordsPref.items,
|
|
985
|
+
)
|
|
975
986
|
} else {
|
|
976
987
|
// if the pref doesn't exist, create it
|
|
977
988
|
mutedWordsPref = {
|
|
978
|
-
items:
|
|
979
|
-
...w,
|
|
980
|
-
value: sanitizeMutedWordValue(w.value),
|
|
981
|
-
})),
|
|
989
|
+
items: [newMutedWord],
|
|
982
990
|
}
|
|
983
991
|
}
|
|
984
992
|
|
|
@@ -990,6 +998,28 @@ export class BskyAgent extends AtpAgent {
|
|
|
990
998
|
})
|
|
991
999
|
}
|
|
992
1000
|
|
|
1001
|
+
/**
|
|
1002
|
+
* Convenience method to add muted words to user preferences
|
|
1003
|
+
*/
|
|
1004
|
+
async addMutedWords(newMutedWords: AppBskyActorDefs.MutedWord[]) {
|
|
1005
|
+
await Promise.all(newMutedWords.map((word) => this.addMutedWord(word)))
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
/**
|
|
1009
|
+
* @deprecated use `addMutedWords` or `addMutedWord` instead
|
|
1010
|
+
*/
|
|
1011
|
+
async upsertMutedWords(
|
|
1012
|
+
mutedWords: Pick<
|
|
1013
|
+
MutedWord,
|
|
1014
|
+
'value' | 'targets' | 'actorTarget' | 'expiresAt'
|
|
1015
|
+
>[],
|
|
1016
|
+
) {
|
|
1017
|
+
await this.addMutedWords(mutedWords)
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* Update a muted word in user preferences.
|
|
1022
|
+
*/
|
|
993
1023
|
async updateMutedWord(mutedWord: AppBskyActorDefs.MutedWord) {
|
|
994
1024
|
await updatePreferences(this, (prefs: AppBskyActorDefs.Preferences) => {
|
|
995
1025
|
const mutedWordsPref = prefs.findLast(
|
|
@@ -999,22 +1029,48 @@ export class BskyAgent extends AtpAgent {
|
|
|
999
1029
|
)
|
|
1000
1030
|
|
|
1001
1031
|
if (mutedWordsPref && AppBskyActorDefs.isMutedWordsPref(mutedWordsPref)) {
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1032
|
+
mutedWordsPref.items = mutedWordsPref.items.map((existingItem) => {
|
|
1033
|
+
const match = matchMutedWord(existingItem, mutedWord)
|
|
1034
|
+
|
|
1035
|
+
if (match) {
|
|
1036
|
+
const updated = {
|
|
1037
|
+
...existingItem,
|
|
1038
|
+
...mutedWord,
|
|
1039
|
+
}
|
|
1040
|
+
return {
|
|
1041
|
+
id: existingItem.id || TID.nextStr(),
|
|
1042
|
+
value:
|
|
1043
|
+
sanitizeMutedWordValue(updated.value) || existingItem.value,
|
|
1044
|
+
targets: updated.targets || [],
|
|
1045
|
+
actorTarget: updated.actorTarget || 'all',
|
|
1046
|
+
expiresAt: updated.expiresAt || undefined,
|
|
1047
|
+
}
|
|
1048
|
+
} else {
|
|
1049
|
+
return existingItem
|
|
1006
1050
|
}
|
|
1007
|
-
}
|
|
1051
|
+
})
|
|
1052
|
+
|
|
1053
|
+
/**
|
|
1054
|
+
* Migrate any old muted words that don't have an id
|
|
1055
|
+
*/
|
|
1056
|
+
mutedWordsPref.items = migrateLegacyMutedWordsItems(
|
|
1057
|
+
mutedWordsPref.items,
|
|
1058
|
+
)
|
|
1059
|
+
|
|
1060
|
+
return prefs
|
|
1061
|
+
.filter((p) => !AppBskyActorDefs.isMutedWordsPref(p))
|
|
1062
|
+
.concat([
|
|
1063
|
+
{ ...mutedWordsPref, $type: 'app.bsky.actor.defs#mutedWordsPref' },
|
|
1064
|
+
])
|
|
1008
1065
|
}
|
|
1009
1066
|
|
|
1010
1067
|
return prefs
|
|
1011
|
-
.filter((p) => !AppBskyActorDefs.isMutedWordsPref(p))
|
|
1012
|
-
.concat([
|
|
1013
|
-
{ ...mutedWordsPref, $type: 'app.bsky.actor.defs#mutedWordsPref' },
|
|
1014
|
-
])
|
|
1015
1068
|
})
|
|
1016
1069
|
}
|
|
1017
1070
|
|
|
1071
|
+
/**
|
|
1072
|
+
* Remove a muted word from user preferences.
|
|
1073
|
+
*/
|
|
1018
1074
|
async removeMutedWord(mutedWord: AppBskyActorDefs.MutedWord) {
|
|
1019
1075
|
await updatePreferences(this, (prefs: AppBskyActorDefs.Preferences) => {
|
|
1020
1076
|
const mutedWordsPref = prefs.findLast(
|
|
@@ -1025,22 +1081,39 @@ export class BskyAgent extends AtpAgent {
|
|
|
1025
1081
|
|
|
1026
1082
|
if (mutedWordsPref && AppBskyActorDefs.isMutedWordsPref(mutedWordsPref)) {
|
|
1027
1083
|
for (let i = 0; i < mutedWordsPref.items.length; i++) {
|
|
1028
|
-
const
|
|
1029
|
-
|
|
1084
|
+
const match = matchMutedWord(mutedWordsPref.items[i], mutedWord)
|
|
1085
|
+
|
|
1086
|
+
if (match) {
|
|
1030
1087
|
mutedWordsPref.items.splice(i, 1)
|
|
1031
1088
|
break
|
|
1032
1089
|
}
|
|
1033
1090
|
}
|
|
1091
|
+
|
|
1092
|
+
/**
|
|
1093
|
+
* Migrate any old muted words that don't have an id
|
|
1094
|
+
*/
|
|
1095
|
+
mutedWordsPref.items = migrateLegacyMutedWordsItems(
|
|
1096
|
+
mutedWordsPref.items,
|
|
1097
|
+
)
|
|
1098
|
+
|
|
1099
|
+
return prefs
|
|
1100
|
+
.filter((p) => !AppBskyActorDefs.isMutedWordsPref(p))
|
|
1101
|
+
.concat([
|
|
1102
|
+
{ ...mutedWordsPref, $type: 'app.bsky.actor.defs#mutedWordsPref' },
|
|
1103
|
+
])
|
|
1034
1104
|
}
|
|
1035
1105
|
|
|
1036
1106
|
return prefs
|
|
1037
|
-
.filter((p) => !AppBskyActorDefs.isMutedWordsPref(p))
|
|
1038
|
-
.concat([
|
|
1039
|
-
{ ...mutedWordsPref, $type: 'app.bsky.actor.defs#mutedWordsPref' },
|
|
1040
|
-
])
|
|
1041
1107
|
})
|
|
1042
1108
|
}
|
|
1043
1109
|
|
|
1110
|
+
/**
|
|
1111
|
+
* Convenience method to remove muted words from user preferences
|
|
1112
|
+
*/
|
|
1113
|
+
async removeMutedWords(mutedWords: AppBskyActorDefs.MutedWord[]) {
|
|
1114
|
+
await Promise.all(mutedWords.map((word) => this.removeMutedWord(word)))
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1044
1117
|
async hidePost(postUri: string) {
|
|
1045
1118
|
await updateHiddenPost(this, postUri, 'hide')
|
|
1046
1119
|
}
|
|
@@ -1369,3 +1442,24 @@ function isBskyPrefs(v: any): v is BskyPreferences {
|
|
|
1369
1442
|
function isModPrefs(v: any): v is ModerationPrefs {
|
|
1370
1443
|
return v && typeof v === 'object' && 'labelers' in v
|
|
1371
1444
|
}
|
|
1445
|
+
|
|
1446
|
+
function migrateLegacyMutedWordsItems(items: AppBskyActorDefs.MutedWord[]) {
|
|
1447
|
+
return items.map((item) => ({
|
|
1448
|
+
...item,
|
|
1449
|
+
id: item.id || TID.nextStr(),
|
|
1450
|
+
}))
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
function matchMutedWord(
|
|
1454
|
+
existingWord: AppBskyActorDefs.MutedWord,
|
|
1455
|
+
newWord: AppBskyActorDefs.MutedWord,
|
|
1456
|
+
): boolean {
|
|
1457
|
+
// id is undefined in legacy implementation
|
|
1458
|
+
const existingId = existingWord.id
|
|
1459
|
+
// prefer matching based on id
|
|
1460
|
+
const matchById = existingId && existingId === newWord.id
|
|
1461
|
+
// handle legacy case where id is not set
|
|
1462
|
+
const legacyMatchByValue = !existingId && existingWord.value === newWord.value
|
|
1463
|
+
|
|
1464
|
+
return matchById || legacyMatchByValue
|
|
1465
|
+
}
|
package/src/client/index.ts
CHANGED
|
@@ -95,12 +95,10 @@ import * as AppBskyActorProfile from './types/app/bsky/actor/profile'
|
|
|
95
95
|
import * as AppBskyActorPutPreferences from './types/app/bsky/actor/putPreferences'
|
|
96
96
|
import * as AppBskyActorSearchActors from './types/app/bsky/actor/searchActors'
|
|
97
97
|
import * as AppBskyActorSearchActorsTypeahead from './types/app/bsky/actor/searchActorsTypeahead'
|
|
98
|
-
import * as AppBskyEmbedDefs from './types/app/bsky/embed/defs'
|
|
99
98
|
import * as AppBskyEmbedExternal from './types/app/bsky/embed/external'
|
|
100
99
|
import * as AppBskyEmbedImages from './types/app/bsky/embed/images'
|
|
101
100
|
import * as AppBskyEmbedRecord from './types/app/bsky/embed/record'
|
|
102
101
|
import * as AppBskyEmbedRecordWithMedia from './types/app/bsky/embed/recordWithMedia'
|
|
103
|
-
import * as AppBskyEmbedVideo from './types/app/bsky/embed/video'
|
|
104
102
|
import * as AppBskyFeedDefs from './types/app/bsky/feed/defs'
|
|
105
103
|
import * as AppBskyFeedDescribeFeedGenerator from './types/app/bsky/feed/describeFeedGenerator'
|
|
106
104
|
import * as AppBskyFeedGenerator from './types/app/bsky/feed/generator'
|
|
@@ -294,12 +292,10 @@ export * as AppBskyActorProfile from './types/app/bsky/actor/profile'
|
|
|
294
292
|
export * as AppBskyActorPutPreferences from './types/app/bsky/actor/putPreferences'
|
|
295
293
|
export * as AppBskyActorSearchActors from './types/app/bsky/actor/searchActors'
|
|
296
294
|
export * as AppBskyActorSearchActorsTypeahead from './types/app/bsky/actor/searchActorsTypeahead'
|
|
297
|
-
export * as AppBskyEmbedDefs from './types/app/bsky/embed/defs'
|
|
298
295
|
export * as AppBskyEmbedExternal from './types/app/bsky/embed/external'
|
|
299
296
|
export * as AppBskyEmbedImages from './types/app/bsky/embed/images'
|
|
300
297
|
export * as AppBskyEmbedRecord from './types/app/bsky/embed/record'
|
|
301
298
|
export * as AppBskyEmbedRecordWithMedia from './types/app/bsky/embed/recordWithMedia'
|
|
302
|
-
export * as AppBskyEmbedVideo from './types/app/bsky/embed/video'
|
|
303
299
|
export * as AppBskyFeedDefs from './types/app/bsky/feed/defs'
|
|
304
300
|
export * as AppBskyFeedDescribeFeedGenerator from './types/app/bsky/feed/describeFeedGenerator'
|
|
305
301
|
export * as AppBskyFeedGenerator from './types/app/bsky/feed/generator'
|
package/src/client/lexicons.ts
CHANGED
|
@@ -4341,6 +4341,9 @@ export const schemaDict = {
|
|
|
4341
4341
|
description: 'A word that the account owner has muted.',
|
|
4342
4342
|
required: ['value', 'targets'],
|
|
4343
4343
|
properties: {
|
|
4344
|
+
id: {
|
|
4345
|
+
type: 'string',
|
|
4346
|
+
},
|
|
4344
4347
|
value: {
|
|
4345
4348
|
type: 'string',
|
|
4346
4349
|
description: 'The muted word itself.',
|
|
@@ -4355,6 +4358,19 @@ export const schemaDict = {
|
|
|
4355
4358
|
ref: 'lex:app.bsky.actor.defs#mutedWordTarget',
|
|
4356
4359
|
},
|
|
4357
4360
|
},
|
|
4361
|
+
actorTarget: {
|
|
4362
|
+
type: 'string',
|
|
4363
|
+
description:
|
|
4364
|
+
'Groups of users to apply the muted word to. If undefined, applies to all users.',
|
|
4365
|
+
knownValues: ['all', 'exclude-following'],
|
|
4366
|
+
default: 'all',
|
|
4367
|
+
},
|
|
4368
|
+
expiresAt: {
|
|
4369
|
+
type: 'string',
|
|
4370
|
+
format: 'datetime',
|
|
4371
|
+
description:
|
|
4372
|
+
'The date and time at which the muted word will expire and no longer be applied.',
|
|
4373
|
+
},
|
|
4358
4374
|
},
|
|
4359
4375
|
},
|
|
4360
4376
|
mutedWordsPref: {
|
|
@@ -4762,28 +4778,6 @@ export const schemaDict = {
|
|
|
4762
4778
|
},
|
|
4763
4779
|
},
|
|
4764
4780
|
},
|
|
4765
|
-
AppBskyEmbedDefs: {
|
|
4766
|
-
lexicon: 1,
|
|
4767
|
-
id: 'app.bsky.embed.defs',
|
|
4768
|
-
defs: {
|
|
4769
|
-
aspectRatio: {
|
|
4770
|
-
type: 'object',
|
|
4771
|
-
description:
|
|
4772
|
-
'width:height represents an aspect ratio. It may be approximate, and may not correspond to absolute dimensions in any given unit.',
|
|
4773
|
-
required: ['width', 'height'],
|
|
4774
|
-
properties: {
|
|
4775
|
-
width: {
|
|
4776
|
-
type: 'integer',
|
|
4777
|
-
minimum: 1,
|
|
4778
|
-
},
|
|
4779
|
-
height: {
|
|
4780
|
-
type: 'integer',
|
|
4781
|
-
minimum: 1,
|
|
4782
|
-
},
|
|
4783
|
-
},
|
|
4784
|
-
},
|
|
4785
|
-
},
|
|
4786
|
-
},
|
|
4787
4781
|
AppBskyEmbedExternal: {
|
|
4788
4782
|
lexicon: 1,
|
|
4789
4783
|
id: 'app.bsky.embed.external',
|
|
@@ -4888,7 +4882,23 @@ export const schemaDict = {
|
|
|
4888
4882
|
},
|
|
4889
4883
|
aspectRatio: {
|
|
4890
4884
|
type: 'ref',
|
|
4891
|
-
ref: 'lex:app.bsky.embed.
|
|
4885
|
+
ref: 'lex:app.bsky.embed.images#aspectRatio',
|
|
4886
|
+
},
|
|
4887
|
+
},
|
|
4888
|
+
},
|
|
4889
|
+
aspectRatio: {
|
|
4890
|
+
type: 'object',
|
|
4891
|
+
description:
|
|
4892
|
+
'width:height represents an aspect ratio. It may be approximate, and may not correspond to absolute dimensions in any given unit.',
|
|
4893
|
+
required: ['width', 'height'],
|
|
4894
|
+
properties: {
|
|
4895
|
+
width: {
|
|
4896
|
+
type: 'integer',
|
|
4897
|
+
minimum: 1,
|
|
4898
|
+
},
|
|
4899
|
+
height: {
|
|
4900
|
+
type: 'integer',
|
|
4901
|
+
minimum: 1,
|
|
4892
4902
|
},
|
|
4893
4903
|
},
|
|
4894
4904
|
},
|
|
@@ -4929,7 +4939,7 @@ export const schemaDict = {
|
|
|
4929
4939
|
},
|
|
4930
4940
|
aspectRatio: {
|
|
4931
4941
|
type: 'ref',
|
|
4932
|
-
ref: 'lex:app.bsky.embed.
|
|
4942
|
+
ref: 'lex:app.bsky.embed.images#aspectRatio',
|
|
4933
4943
|
},
|
|
4934
4944
|
},
|
|
4935
4945
|
},
|
|
@@ -5011,7 +5021,6 @@ export const schemaDict = {
|
|
|
5011
5021
|
type: 'union',
|
|
5012
5022
|
refs: [
|
|
5013
5023
|
'lex:app.bsky.embed.images#view',
|
|
5014
|
-
'lex:app.bsky.embed.video#view',
|
|
5015
5024
|
'lex:app.bsky.embed.external#view',
|
|
5016
5025
|
'lex:app.bsky.embed.record#view',
|
|
5017
5026
|
'lex:app.bsky.embed.recordWithMedia#view',
|
|
@@ -5074,11 +5083,7 @@ export const schemaDict = {
|
|
|
5074
5083
|
},
|
|
5075
5084
|
media: {
|
|
5076
5085
|
type: 'union',
|
|
5077
|
-
refs: [
|
|
5078
|
-
'lex:app.bsky.embed.images',
|
|
5079
|
-
'lex:app.bsky.embed.video',
|
|
5080
|
-
'lex:app.bsky.embed.external',
|
|
5081
|
-
],
|
|
5086
|
+
refs: ['lex:app.bsky.embed.images', 'lex:app.bsky.embed.external'],
|
|
5082
5087
|
},
|
|
5083
5088
|
},
|
|
5084
5089
|
},
|
|
@@ -5094,7 +5099,6 @@ export const schemaDict = {
|
|
|
5094
5099
|
type: 'union',
|
|
5095
5100
|
refs: [
|
|
5096
5101
|
'lex:app.bsky.embed.images#view',
|
|
5097
|
-
'lex:app.bsky.embed.video#view',
|
|
5098
5102
|
'lex:app.bsky.embed.external#view',
|
|
5099
5103
|
],
|
|
5100
5104
|
},
|
|
@@ -5102,85 +5106,6 @@ export const schemaDict = {
|
|
|
5102
5106
|
},
|
|
5103
5107
|
},
|
|
5104
5108
|
},
|
|
5105
|
-
AppBskyEmbedVideo: {
|
|
5106
|
-
lexicon: 1,
|
|
5107
|
-
id: 'app.bsky.embed.video',
|
|
5108
|
-
description: 'A video embedded in a Bluesky record (eg, a post).',
|
|
5109
|
-
defs: {
|
|
5110
|
-
main: {
|
|
5111
|
-
type: 'object',
|
|
5112
|
-
required: ['video'],
|
|
5113
|
-
properties: {
|
|
5114
|
-
video: {
|
|
5115
|
-
type: 'blob',
|
|
5116
|
-
accept: ['video/mp4'],
|
|
5117
|
-
maxSize: 50000000,
|
|
5118
|
-
},
|
|
5119
|
-
captions: {
|
|
5120
|
-
type: 'array',
|
|
5121
|
-
items: {
|
|
5122
|
-
type: 'ref',
|
|
5123
|
-
ref: 'lex:app.bsky.embed.video#caption',
|
|
5124
|
-
},
|
|
5125
|
-
maxLength: 20,
|
|
5126
|
-
},
|
|
5127
|
-
alt: {
|
|
5128
|
-
type: 'string',
|
|
5129
|
-
description:
|
|
5130
|
-
'Alt text description of the video, for accessibility.',
|
|
5131
|
-
maxGraphemes: 1000,
|
|
5132
|
-
maxLength: 10000,
|
|
5133
|
-
},
|
|
5134
|
-
aspectRatio: {
|
|
5135
|
-
type: 'ref',
|
|
5136
|
-
ref: 'lex:app.bsky.embed.defs#aspectRatio',
|
|
5137
|
-
},
|
|
5138
|
-
},
|
|
5139
|
-
},
|
|
5140
|
-
caption: {
|
|
5141
|
-
type: 'object',
|
|
5142
|
-
required: ['lang', 'file'],
|
|
5143
|
-
properties: {
|
|
5144
|
-
lang: {
|
|
5145
|
-
type: 'string',
|
|
5146
|
-
format: 'language',
|
|
5147
|
-
},
|
|
5148
|
-
file: {
|
|
5149
|
-
type: 'blob',
|
|
5150
|
-
accept: ['text/vtt'],
|
|
5151
|
-
maxSize: 20000,
|
|
5152
|
-
},
|
|
5153
|
-
},
|
|
5154
|
-
},
|
|
5155
|
-
view: {
|
|
5156
|
-
type: 'object',
|
|
5157
|
-
required: ['cid', 'playlist'],
|
|
5158
|
-
properties: {
|
|
5159
|
-
cid: {
|
|
5160
|
-
type: 'string',
|
|
5161
|
-
format: 'cid',
|
|
5162
|
-
},
|
|
5163
|
-
playlist: {
|
|
5164
|
-
type: 'string',
|
|
5165
|
-
format: 'uri',
|
|
5166
|
-
},
|
|
5167
|
-
thumbnail: {
|
|
5168
|
-
type: 'string',
|
|
5169
|
-
format: 'uri',
|
|
5170
|
-
},
|
|
5171
|
-
alt: {
|
|
5172
|
-
type: 'string',
|
|
5173
|
-
maxGraphemes: 1000,
|
|
5174
|
-
maxLength: 10000,
|
|
5175
|
-
},
|
|
5176
|
-
aspectRatio: {
|
|
5177
|
-
type: 'ref',
|
|
5178
|
-
ref: 'lex:app.bsky.embed.defs#aspectRatio',
|
|
5179
|
-
},
|
|
5180
|
-
},
|
|
5181
|
-
},
|
|
5182
|
-
},
|
|
5183
|
-
},
|
|
5184
5109
|
AppBskyFeedDefs: {
|
|
5185
5110
|
lexicon: 1,
|
|
5186
5111
|
id: 'app.bsky.feed.defs',
|
|
@@ -5208,7 +5133,6 @@ export const schemaDict = {
|
|
|
5208
5133
|
type: 'union',
|
|
5209
5134
|
refs: [
|
|
5210
5135
|
'lex:app.bsky.embed.images#view',
|
|
5211
|
-
'lex:app.bsky.embed.video#view',
|
|
5212
5136
|
'lex:app.bsky.embed.external#view',
|
|
5213
5137
|
'lex:app.bsky.embed.record#view',
|
|
5214
5138
|
'lex:app.bsky.embed.recordWithMedia#view',
|
|
@@ -6563,7 +6487,6 @@ export const schemaDict = {
|
|
|
6563
6487
|
type: 'union',
|
|
6564
6488
|
refs: [
|
|
6565
6489
|
'lex:app.bsky.embed.images',
|
|
6566
|
-
'lex:app.bsky.embed.video',
|
|
6567
6490
|
'lex:app.bsky.embed.external',
|
|
6568
6491
|
'lex:app.bsky.embed.record',
|
|
6569
6492
|
'lex:app.bsky.embed.recordWithMedia',
|
|
@@ -11833,12 +11756,10 @@ export const ids = {
|
|
|
11833
11756
|
AppBskyActorPutPreferences: 'app.bsky.actor.putPreferences',
|
|
11834
11757
|
AppBskyActorSearchActors: 'app.bsky.actor.searchActors',
|
|
11835
11758
|
AppBskyActorSearchActorsTypeahead: 'app.bsky.actor.searchActorsTypeahead',
|
|
11836
|
-
AppBskyEmbedDefs: 'app.bsky.embed.defs',
|
|
11837
11759
|
AppBskyEmbedExternal: 'app.bsky.embed.external',
|
|
11838
11760
|
AppBskyEmbedImages: 'app.bsky.embed.images',
|
|
11839
11761
|
AppBskyEmbedRecord: 'app.bsky.embed.record',
|
|
11840
11762
|
AppBskyEmbedRecordWithMedia: 'app.bsky.embed.recordWithMedia',
|
|
11841
|
-
AppBskyEmbedVideo: 'app.bsky.embed.video',
|
|
11842
11763
|
AppBskyFeedDefs: 'app.bsky.feed.defs',
|
|
11843
11764
|
AppBskyFeedDescribeFeedGenerator: 'app.bsky.feed.describeFeedGenerator',
|
|
11844
11765
|
AppBskyFeedGenerator: 'app.bsky.feed.generator',
|
|
@@ -370,10 +370,15 @@ export type MutedWordTarget = 'content' | 'tag' | (string & {})
|
|
|
370
370
|
|
|
371
371
|
/** A word that the account owner has muted. */
|
|
372
372
|
export interface MutedWord {
|
|
373
|
+
id?: string
|
|
373
374
|
/** The muted word itself. */
|
|
374
375
|
value: string
|
|
375
376
|
/** The intended targets of the muted word. */
|
|
376
377
|
targets: MutedWordTarget[]
|
|
378
|
+
/** Groups of users to apply the muted word to. If undefined, applies to all users. */
|
|
379
|
+
actorTarget: 'all' | 'exclude-following' | (string & {})
|
|
380
|
+
/** The date and time at which the muted word will expire and no longer be applied. */
|
|
381
|
+
expiresAt?: string
|
|
377
382
|
[k: string]: unknown
|
|
378
383
|
}
|
|
379
384
|
|
|
@@ -5,7 +5,6 @@ import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
|
5
5
|
import { isObj, hasProp } from '../../../../util'
|
|
6
6
|
import { lexicons } from '../../../../lexicons'
|
|
7
7
|
import { CID } from 'multiformats/cid'
|
|
8
|
-
import * as AppBskyEmbedDefs from './defs'
|
|
9
8
|
|
|
10
9
|
export interface Main {
|
|
11
10
|
images: Image[]
|
|
@@ -29,7 +28,7 @@ export interface Image {
|
|
|
29
28
|
image: BlobRef
|
|
30
29
|
/** Alt text description of the image, for accessibility. */
|
|
31
30
|
alt: string
|
|
32
|
-
aspectRatio?:
|
|
31
|
+
aspectRatio?: AspectRatio
|
|
33
32
|
[k: string]: unknown
|
|
34
33
|
}
|
|
35
34
|
|
|
@@ -43,6 +42,25 @@ export function validateImage(v: unknown): ValidationResult {
|
|
|
43
42
|
return lexicons.validate('app.bsky.embed.images#image', v)
|
|
44
43
|
}
|
|
45
44
|
|
|
45
|
+
/** width:height represents an aspect ratio. It may be approximate, and may not correspond to absolute dimensions in any given unit. */
|
|
46
|
+
export interface AspectRatio {
|
|
47
|
+
width: number
|
|
48
|
+
height: number
|
|
49
|
+
[k: string]: unknown
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function isAspectRatio(v: unknown): v is AspectRatio {
|
|
53
|
+
return (
|
|
54
|
+
isObj(v) &&
|
|
55
|
+
hasProp(v, '$type') &&
|
|
56
|
+
v.$type === 'app.bsky.embed.images#aspectRatio'
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function validateAspectRatio(v: unknown): ValidationResult {
|
|
61
|
+
return lexicons.validate('app.bsky.embed.images#aspectRatio', v)
|
|
62
|
+
}
|
|
63
|
+
|
|
46
64
|
export interface View {
|
|
47
65
|
images: ViewImage[]
|
|
48
66
|
[k: string]: unknown
|
|
@@ -65,7 +83,7 @@ export interface ViewImage {
|
|
|
65
83
|
fullsize: string
|
|
66
84
|
/** Alt text description of the image, for accessibility. */
|
|
67
85
|
alt: string
|
|
68
|
-
aspectRatio?:
|
|
86
|
+
aspectRatio?: AspectRatio
|
|
69
87
|
[k: string]: unknown
|
|
70
88
|
}
|
|
71
89
|
|
|
@@ -12,7 +12,6 @@ import * as AppBskyLabelerDefs from '../labeler/defs'
|
|
|
12
12
|
import * as AppBskyActorDefs from '../actor/defs'
|
|
13
13
|
import * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs'
|
|
14
14
|
import * as AppBskyEmbedImages from './images'
|
|
15
|
-
import * as AppBskyEmbedVideo from './video'
|
|
16
15
|
import * as AppBskyEmbedExternal from './external'
|
|
17
16
|
import * as AppBskyEmbedRecordWithMedia from './recordWithMedia'
|
|
18
17
|
|
|
@@ -69,7 +68,6 @@ export interface ViewRecord {
|
|
|
69
68
|
likeCount?: number
|
|
70
69
|
embeds?: (
|
|
71
70
|
| AppBskyEmbedImages.View
|
|
72
|
-
| AppBskyEmbedVideo.View
|
|
73
71
|
| AppBskyEmbedExternal.View
|
|
74
72
|
| View
|
|
75
73
|
| AppBskyEmbedRecordWithMedia.View
|
|
@@ -7,14 +7,12 @@ import { lexicons } from '../../../../lexicons'
|
|
|
7
7
|
import { CID } from 'multiformats/cid'
|
|
8
8
|
import * as AppBskyEmbedRecord from './record'
|
|
9
9
|
import * as AppBskyEmbedImages from './images'
|
|
10
|
-
import * as AppBskyEmbedVideo from './video'
|
|
11
10
|
import * as AppBskyEmbedExternal from './external'
|
|
12
11
|
|
|
13
12
|
export interface Main {
|
|
14
13
|
record: AppBskyEmbedRecord.Main
|
|
15
14
|
media:
|
|
16
15
|
| AppBskyEmbedImages.Main
|
|
17
|
-
| AppBskyEmbedVideo.Main
|
|
18
16
|
| AppBskyEmbedExternal.Main
|
|
19
17
|
| { $type: string; [k: string]: unknown }
|
|
20
18
|
[k: string]: unknown
|
|
@@ -37,7 +35,6 @@ export interface View {
|
|
|
37
35
|
record: AppBskyEmbedRecord.View
|
|
38
36
|
media:
|
|
39
37
|
| AppBskyEmbedImages.View
|
|
40
|
-
| AppBskyEmbedVideo.View
|
|
41
38
|
| AppBskyEmbedExternal.View
|
|
42
39
|
| { $type: string; [k: string]: unknown }
|
|
43
40
|
[k: string]: unknown
|
|
@@ -7,7 +7,6 @@ import { lexicons } from '../../../../lexicons'
|
|
|
7
7
|
import { CID } from 'multiformats/cid'
|
|
8
8
|
import * as AppBskyActorDefs from '../actor/defs'
|
|
9
9
|
import * as AppBskyEmbedImages from '../embed/images'
|
|
10
|
-
import * as AppBskyEmbedVideo from '../embed/video'
|
|
11
10
|
import * as AppBskyEmbedExternal from '../embed/external'
|
|
12
11
|
import * as AppBskyEmbedRecord from '../embed/record'
|
|
13
12
|
import * as AppBskyEmbedRecordWithMedia from '../embed/recordWithMedia'
|
|
@@ -22,7 +21,6 @@ export interface PostView {
|
|
|
22
21
|
record: {}
|
|
23
22
|
embed?:
|
|
24
23
|
| AppBskyEmbedImages.View
|
|
25
|
-
| AppBskyEmbedVideo.View
|
|
26
24
|
| AppBskyEmbedExternal.View
|
|
27
25
|
| AppBskyEmbedRecord.View
|
|
28
26
|
| AppBskyEmbedRecordWithMedia.View
|
|
@@ -7,7 +7,6 @@ import { lexicons } from '../../../../lexicons'
|
|
|
7
7
|
import { CID } from 'multiformats/cid'
|
|
8
8
|
import * as AppBskyRichtextFacet from '../richtext/facet'
|
|
9
9
|
import * as AppBskyEmbedImages from '../embed/images'
|
|
10
|
-
import * as AppBskyEmbedVideo from '../embed/video'
|
|
11
10
|
import * as AppBskyEmbedExternal from '../embed/external'
|
|
12
11
|
import * as AppBskyEmbedRecord from '../embed/record'
|
|
13
12
|
import * as AppBskyEmbedRecordWithMedia from '../embed/recordWithMedia'
|
|
@@ -24,7 +23,6 @@ export interface Record {
|
|
|
24
23
|
reply?: ReplyRef
|
|
25
24
|
embed?:
|
|
26
25
|
| AppBskyEmbedImages.Main
|
|
27
|
-
| AppBskyEmbedVideo.Main
|
|
28
26
|
| AppBskyEmbedExternal.Main
|
|
29
27
|
| AppBskyEmbedRecord.Main
|
|
30
28
|
| AppBskyEmbedRecordWithMedia.Main
|
|
@@ -27,12 +27,14 @@ export function hasMutedWord({
|
|
|
27
27
|
facets,
|
|
28
28
|
outlineTags,
|
|
29
29
|
languages,
|
|
30
|
+
actor,
|
|
30
31
|
}: {
|
|
31
32
|
mutedWords: AppBskyActorDefs.MutedWord[]
|
|
32
33
|
text: string
|
|
33
34
|
facets?: AppBskyRichtextFacet.Main[]
|
|
34
35
|
outlineTags?: string[]
|
|
35
36
|
languages?: string[]
|
|
37
|
+
actor?: AppBskyActorDefs.ProfileView
|
|
36
38
|
}) {
|
|
37
39
|
const exception = LANGUAGE_EXCEPTIONS.includes(languages?.[0] || '')
|
|
38
40
|
const tags = ([] as string[])
|
|
@@ -48,6 +50,15 @@ export function hasMutedWord({
|
|
|
48
50
|
const mutedWord = mute.value.toLowerCase()
|
|
49
51
|
const postText = text.toLowerCase()
|
|
50
52
|
|
|
53
|
+
// expired, ignore
|
|
54
|
+
if (mute.expiresAt && mute.expiresAt < new Date().toISOString()) continue
|
|
55
|
+
|
|
56
|
+
if (
|
|
57
|
+
mute.actorTarget === 'exclude-following' &&
|
|
58
|
+
Boolean(actor?.viewer?.following)
|
|
59
|
+
)
|
|
60
|
+
continue
|
|
61
|
+
|
|
51
62
|
// `content` applies to tags as well
|
|
52
63
|
if (tags.includes(mutedWord)) return true
|
|
53
64
|
// rest of the checks are for `content` only
|