@atproto/bsky 0.0.10 → 0.0.12
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 +26 -0
- package/dist/api/com/atproto/admin/util.d.ts +5 -0
- package/dist/config.d.ts +2 -0
- package/dist/context.d.ts +8 -0
- package/dist/db/index.js +51 -2
- package/dist/db/index.js.map +3 -3
- package/dist/db/migrations/20230929T192920807Z-record-cursor-indexes.d.ts +3 -0
- package/dist/db/migrations/index.d.ts +1 -0
- package/dist/did-cache.d.ts +2 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1818 -580
- package/dist/index.js.map +3 -3
- package/dist/lexicon/index.d.ts +16 -0
- package/dist/lexicon/lexicons.d.ts +330 -3
- package/dist/lexicon/types/app/bsky/actor/defs.d.ts +1 -0
- package/dist/lexicon/types/com/atproto/admin/defs.d.ts +28 -0
- package/dist/lexicon/types/com/atproto/admin/getAccountInfo.d.ts +29 -0
- package/dist/lexicon/types/com/atproto/admin/getSubjectStatus.d.ts +39 -0
- package/dist/lexicon/types/com/atproto/admin/searchRepos.d.ts +0 -1
- package/dist/lexicon/types/com/atproto/admin/updateSubjectStatus.d.ts +46 -0
- package/dist/lexicon/types/com/atproto/server/confirmEmail.d.ts +27 -0
- package/dist/lexicon/types/com/atproto/server/createAccount.d.ts +2 -0
- package/dist/lexicon/types/com/atproto/server/createSession.d.ts +2 -0
- package/dist/lexicon/types/com/atproto/server/getSession.d.ts +1 -0
- package/dist/lexicon/types/com/atproto/server/refreshSession.d.ts +1 -0
- package/dist/lexicon/types/com/atproto/server/requestEmailConfirmation.d.ts +19 -0
- package/dist/lexicon/types/com/atproto/server/requestEmailUpdate.d.ts +30 -0
- package/dist/lexicon/types/com/atproto/server/reserveSigningKey.d.ts +30 -0
- package/dist/lexicon/types/com/atproto/server/updateEmail.d.ts +27 -0
- package/dist/lexicon/types/com/atproto/sync/listRepos.d.ts +1 -0
- package/dist/services/actor/index.d.ts +2 -2
- package/dist/services/actor/types.d.ts +1 -0
- package/dist/services/graph/index.d.ts +2 -0
- package/dist/services/moderation/index.d.ts +13 -3
- package/dist/services/util/search.d.ts +3 -3
- package/package.json +13 -14
- package/src/api/app/bsky/actor/searchActors.ts +36 -22
- package/src/api/app/bsky/actor/searchActorsTypeahead.ts +24 -17
- package/src/api/app/bsky/feed/getAuthorFeed.ts +2 -2
- package/src/api/app/bsky/feed/getPostThread.ts +2 -2
- package/src/api/app/bsky/graph/getSuggestedFollowsByActor.ts +1 -0
- package/src/api/app/bsky/notification/listNotifications.ts +33 -22
- package/src/api/com/atproto/admin/getModerationAction.ts +28 -2
- package/src/api/com/atproto/admin/getModerationReport.ts +27 -2
- package/src/api/com/atproto/admin/getRecord.ts +14 -2
- package/src/api/com/atproto/admin/getRepo.ts +13 -2
- package/src/api/com/atproto/admin/reverseModerationAction.ts +31 -5
- package/src/api/com/atproto/admin/searchRepos.ts +6 -12
- package/src/api/com/atproto/admin/takeModerationAction.ts +41 -7
- package/src/api/com/atproto/admin/util.ts +50 -0
- package/src/api/well-known.ts +8 -0
- package/src/auth.ts +12 -5
- package/src/auto-moderator/index.ts +1 -0
- package/src/config.ts +7 -0
- package/src/context.ts +30 -0
- package/src/db/migrations/20230929T192920807Z-record-cursor-indexes.ts +40 -0
- package/src/db/migrations/index.ts +1 -0
- package/src/did-cache.ts +29 -14
- package/src/feed-gen/with-friends.ts +2 -2
- package/src/index.ts +9 -1
- package/src/indexer/subscription.ts +1 -21
- package/src/lexicon/index.ts +96 -0
- package/src/lexicon/lexicons.ts +368 -4
- package/src/lexicon/types/app/bsky/actor/defs.ts +1 -0
- package/src/lexicon/types/com/atproto/admin/defs.ts +61 -0
- package/src/lexicon/types/com/atproto/admin/getAccountInfo.ts +41 -0
- package/src/lexicon/types/com/atproto/admin/getSubjectStatus.ts +54 -0
- package/src/lexicon/types/com/atproto/admin/searchRepos.ts +0 -1
- package/src/lexicon/types/com/atproto/admin/updateSubjectStatus.ts +61 -0
- package/src/lexicon/types/com/atproto/server/confirmEmail.ts +40 -0
- package/src/lexicon/types/com/atproto/server/createAccount.ts +2 -0
- package/src/lexicon/types/com/atproto/server/createSession.ts +2 -0
- package/src/lexicon/types/com/atproto/server/getSession.ts +1 -0
- package/src/lexicon/types/com/atproto/server/refreshSession.ts +1 -0
- package/src/lexicon/types/com/atproto/server/requestEmailConfirmation.ts +31 -0
- package/src/lexicon/types/com/atproto/server/requestEmailUpdate.ts +43 -0
- package/src/lexicon/types/com/atproto/server/reserveSigningKey.ts +44 -0
- package/src/lexicon/types/com/atproto/server/updateEmail.ts +41 -0
- package/src/lexicon/types/com/atproto/sync/listRepos.ts +1 -0
- package/src/logger.ts +8 -0
- package/src/services/actor/index.ts +16 -10
- package/src/services/actor/types.ts +1 -0
- package/src/services/actor/views.ts +26 -8
- package/src/services/graph/index.ts +26 -7
- package/src/services/indexing/index.ts +15 -17
- package/src/services/moderation/index.ts +94 -14
- package/src/services/moderation/views.ts +1 -0
- package/src/services/util/search.ts +24 -23
- package/tests/__snapshots__/feed-generation.test.ts.snap +12 -12
- package/tests/__snapshots__/indexing.test.ts.snap +4 -4
- package/tests/admin/__snapshots__/get-moderation-action.test.ts.snap +172 -0
- package/tests/admin/__snapshots__/get-moderation-actions.test.ts.snap +178 -0
- package/tests/admin/__snapshots__/get-moderation-report.test.ts.snap +177 -0
- package/tests/admin/__snapshots__/get-moderation-reports.test.ts.snap +307 -0
- package/tests/admin/__snapshots__/get-record.test.ts.snap +275 -0
- package/tests/admin/__snapshots__/get-repo.test.ts.snap +103 -0
- package/tests/admin/get-moderation-action.test.ts +100 -0
- package/tests/admin/get-moderation-actions.test.ts +164 -0
- package/tests/admin/get-moderation-report.test.ts +100 -0
- package/tests/admin/get-moderation-reports.test.ts +332 -0
- package/tests/admin/get-record.test.ts +115 -0
- package/tests/admin/get-repo.test.ts +101 -0
- package/tests/{moderation.test.ts → admin/moderation.test.ts} +107 -9
- package/tests/admin/repo-search.test.ts +124 -0
- package/tests/algos/hot-classic.test.ts +3 -5
- package/tests/algos/whats-hot.test.ts +3 -5
- package/tests/algos/with-friends.test.ts +2 -4
- package/tests/auth.test.ts +64 -0
- package/tests/auto-moderator/fuzzy-matcher.test.ts +2 -3
- package/tests/auto-moderator/labeler.test.ts +5 -7
- package/tests/auto-moderator/takedowns.test.ts +11 -12
- package/tests/blob-resolver.test.ts +1 -3
- package/tests/did-cache.test.ts +2 -5
- package/tests/feed-generation.test.ts +8 -6
- package/tests/handle-invalidation.test.ts +2 -3
- package/tests/image/server.test.ts +1 -4
- package/tests/image/sharp.test.ts +1 -1
- package/tests/indexing.test.ts +4 -4
- package/tests/notification-server.test.ts +2 -3
- package/tests/pipeline/backpressure.test.ts +2 -3
- package/tests/pipeline/reingest.test.ts +7 -4
- package/tests/pipeline/repartition.test.ts +2 -3
- package/tests/reprocessing.test.ts +2 -6
- package/tests/seeds/basic.ts +4 -4
- package/tests/seeds/follows.ts +1 -1
- package/tests/seeds/likes.ts +1 -1
- package/tests/seeds/reposts.ts +1 -1
- package/tests/seeds/users-bulk.ts +1 -1
- package/tests/seeds/users.ts +1 -1
- package/tests/server.test.ts +1 -3
- package/tests/subscription/repo.test.ts +2 -4
- package/tests/views/__snapshots__/author-feed.test.ts.snap +24 -24
- package/tests/views/__snapshots__/block-lists.test.ts.snap +42 -7
- package/tests/views/__snapshots__/blocks.test.ts.snap +2 -2
- package/tests/views/__snapshots__/list-feed.test.ts.snap +6 -6
- package/tests/views/__snapshots__/mute-lists.test.ts.snap +15 -4
- package/tests/views/__snapshots__/mutes.test.ts.snap +2 -2
- package/tests/views/__snapshots__/notifications.test.ts.snap +2 -2
- package/tests/views/__snapshots__/posts.test.ts.snap +8 -8
- package/tests/views/__snapshots__/thread.test.ts.snap +10 -10
- package/tests/views/__snapshots__/timeline.test.ts.snap +58 -58
- package/tests/views/actor-likes.test.ts +2 -3
- package/tests/views/actor-search.test.ts +5 -5
- package/tests/views/admin/repo-search.test.ts +2 -4
- package/tests/views/author-feed.test.ts +2 -4
- package/tests/views/block-lists.test.ts +34 -7
- package/tests/views/blocks.test.ts +6 -3
- package/tests/views/follows.test.ts +2 -4
- package/tests/views/likes.test.ts +2 -5
- package/tests/views/list-feed.test.ts +2 -4
- package/tests/views/mute-lists.test.ts +23 -5
- package/tests/views/mutes.test.ts +2 -5
- package/tests/views/notifications.test.ts +2 -4
- package/tests/views/posts.test.ts +2 -5
- package/tests/views/profile.test.ts +4 -5
- package/tests/views/reposts.test.ts +2 -4
- package/tests/views/suggested-follows.test.ts +2 -3
- package/tests/views/suggestions.test.ts +2 -4
- package/tests/views/thread.test.ts +2 -4
- package/tests/views/threadgating.test.ts +2 -3
- package/tests/views/timeline.test.ts +2 -4
- package/dist/env.d.ts +0 -1
- package/example.dev.env +0 -5
- package/src/env.ts +0 -9
- package/tests/seeds/client.ts +0 -466
- /package/tests/{__snapshots__ → admin/__snapshots__}/moderation.test.ts.snap +0 -0
- /package/tests/{image/fixtures → sample-img}/at.png +0 -0
- /package/tests/{image/fixtures → sample-img}/hd-key.jpg +0 -0
- /package/tests/{image/fixtures → sample-img}/key-alt.jpg +0 -0
- /package/tests/{image/fixtures → sample-img}/key-landscape-large.jpg +0 -0
- /package/tests/{image/fixtures → sample-img}/key-landscape-small.jpg +0 -0
- /package/tests/{image/fixtures → sample-img}/key-portrait-large.jpg +0 -0
- /package/tests/{image/fixtures → sample-img}/key-portrait-small.jpg +0 -0
|
@@ -7,7 +7,12 @@ import { ModerationAction, ModerationReport } from '../../db/tables/moderation'
|
|
|
7
7
|
import { ModerationViews } from './views'
|
|
8
8
|
import { ImageUriBuilder } from '../../image/uri'
|
|
9
9
|
import { ImageInvalidator } from '../../image/invalidator'
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
RepoRef,
|
|
12
|
+
RepoBlobRef,
|
|
13
|
+
TAKEDOWN,
|
|
14
|
+
} from '../../lexicon/types/com/atproto/admin/defs'
|
|
15
|
+
import { Main as StrongRef } from '../../lexicon/types/com/atproto/repo/strongRef'
|
|
11
16
|
import { addHoursToDate } from '../../util/date'
|
|
12
17
|
|
|
13
18
|
export class ModerationService {
|
|
@@ -355,7 +360,10 @@ export class ModerationService {
|
|
|
355
360
|
createdBy,
|
|
356
361
|
createdAt,
|
|
357
362
|
reason,
|
|
358
|
-
}: ReversibleModerationAction) {
|
|
363
|
+
}: ReversibleModerationAction): Promise<{
|
|
364
|
+
result: ModerationActionRow
|
|
365
|
+
restored?: TakedownSubjects
|
|
366
|
+
}> {
|
|
359
367
|
this.db.assertTransaction()
|
|
360
368
|
const result = await this.logReverseAction({
|
|
361
369
|
id,
|
|
@@ -364,6 +372,8 @@ export class ModerationService {
|
|
|
364
372
|
reason,
|
|
365
373
|
})
|
|
366
374
|
|
|
375
|
+
let restored: TakedownSubjects | undefined
|
|
376
|
+
|
|
367
377
|
if (
|
|
368
378
|
result.action === TAKEDOWN &&
|
|
369
379
|
result.subjectType === 'com.atproto.admin.defs#repoRef' &&
|
|
@@ -372,6 +382,15 @@ export class ModerationService {
|
|
|
372
382
|
await this.reverseTakedownRepo({
|
|
373
383
|
did: result.subjectDid,
|
|
374
384
|
})
|
|
385
|
+
restored = {
|
|
386
|
+
did: result.subjectDid,
|
|
387
|
+
subjects: [
|
|
388
|
+
{
|
|
389
|
+
$type: 'com.atproto.admin.defs#repoRef',
|
|
390
|
+
did: result.subjectDid,
|
|
391
|
+
},
|
|
392
|
+
],
|
|
393
|
+
}
|
|
375
394
|
}
|
|
376
395
|
|
|
377
396
|
if (
|
|
@@ -379,12 +398,35 @@ export class ModerationService {
|
|
|
379
398
|
result.subjectType === 'com.atproto.repo.strongRef' &&
|
|
380
399
|
result.subjectUri
|
|
381
400
|
) {
|
|
401
|
+
const uri = new AtUri(result.subjectUri)
|
|
382
402
|
await this.reverseTakedownRecord({
|
|
383
|
-
uri
|
|
403
|
+
uri,
|
|
384
404
|
})
|
|
405
|
+
const did = uri.hostname
|
|
406
|
+
const actionBlobs = await this.db.db
|
|
407
|
+
.selectFrom('moderation_action_subject_blob')
|
|
408
|
+
.where('actionId', '=', id)
|
|
409
|
+
.select('cid')
|
|
410
|
+
.execute()
|
|
411
|
+
restored = {
|
|
412
|
+
did,
|
|
413
|
+
subjects: [
|
|
414
|
+
{
|
|
415
|
+
$type: 'com.atproto.repo.strongRef',
|
|
416
|
+
uri: result.subjectUri,
|
|
417
|
+
cid: result.subjectCid ?? '',
|
|
418
|
+
},
|
|
419
|
+
...actionBlobs.map((row) => ({
|
|
420
|
+
$type: 'com.atproto.admin.defs#repoBlobRef',
|
|
421
|
+
did,
|
|
422
|
+
cid: row.cid,
|
|
423
|
+
recordUri: result.subjectUri,
|
|
424
|
+
})),
|
|
425
|
+
],
|
|
426
|
+
}
|
|
385
427
|
}
|
|
386
428
|
|
|
387
|
-
return result
|
|
429
|
+
return { result, restored }
|
|
388
430
|
}
|
|
389
431
|
|
|
390
432
|
async logReverseAction(
|
|
@@ -410,13 +452,27 @@ export class ModerationService {
|
|
|
410
452
|
return result
|
|
411
453
|
}
|
|
412
454
|
|
|
413
|
-
async takedownRepo(info: {
|
|
455
|
+
async takedownRepo(info: {
|
|
456
|
+
takedownId: number
|
|
457
|
+
did: string
|
|
458
|
+
}): Promise<TakedownSubjects> {
|
|
459
|
+
const { takedownId, did } = info
|
|
414
460
|
await this.db.db
|
|
415
461
|
.updateTable('actor')
|
|
416
|
-
.set({ takedownId
|
|
417
|
-
.where('did', '=',
|
|
462
|
+
.set({ takedownId })
|
|
463
|
+
.where('did', '=', did)
|
|
418
464
|
.where('takedownId', 'is', null)
|
|
419
465
|
.executeTakeFirst()
|
|
466
|
+
|
|
467
|
+
return {
|
|
468
|
+
did,
|
|
469
|
+
subjects: [
|
|
470
|
+
{
|
|
471
|
+
$type: 'com.atproto.admin.defs#repoRef',
|
|
472
|
+
did,
|
|
473
|
+
},
|
|
474
|
+
],
|
|
475
|
+
}
|
|
420
476
|
}
|
|
421
477
|
|
|
422
478
|
async reverseTakedownRepo(info: { did: string }) {
|
|
@@ -430,26 +486,45 @@ export class ModerationService {
|
|
|
430
486
|
async takedownRecord(info: {
|
|
431
487
|
takedownId: number
|
|
432
488
|
uri: AtUri
|
|
489
|
+
cid: CID
|
|
433
490
|
blobCids?: CID[]
|
|
434
|
-
}) {
|
|
491
|
+
}): Promise<TakedownSubjects> {
|
|
492
|
+
const { takedownId, uri, cid, blobCids } = info
|
|
493
|
+
const did = uri.hostname
|
|
435
494
|
this.db.assertTransaction()
|
|
436
495
|
await this.db.db
|
|
437
496
|
.updateTable('record')
|
|
438
|
-
.set({ takedownId
|
|
439
|
-
.where('uri', '=',
|
|
497
|
+
.set({ takedownId })
|
|
498
|
+
.where('uri', '=', uri.toString())
|
|
440
499
|
.where('takedownId', 'is', null)
|
|
441
500
|
.executeTakeFirst()
|
|
442
|
-
if (
|
|
501
|
+
if (blobCids) {
|
|
443
502
|
await Promise.all(
|
|
444
|
-
|
|
503
|
+
blobCids.map(async (cid) => {
|
|
445
504
|
const paths = ImageUriBuilder.presets.map((id) => {
|
|
446
|
-
const
|
|
447
|
-
return
|
|
505
|
+
const imgUri = this.imgUriBuilder.getPresetUri(id, uri.host, cid)
|
|
506
|
+
return imgUri.replace(this.imgUriBuilder.endpoint, '')
|
|
448
507
|
})
|
|
449
508
|
await this.imgInvalidator.invalidate(cid.toString(), paths)
|
|
450
509
|
}),
|
|
451
510
|
)
|
|
452
511
|
}
|
|
512
|
+
return {
|
|
513
|
+
did,
|
|
514
|
+
subjects: [
|
|
515
|
+
{
|
|
516
|
+
$type: 'com.atproto.repo.strongRef',
|
|
517
|
+
uri: uri.toString(),
|
|
518
|
+
cid: cid.toString(),
|
|
519
|
+
},
|
|
520
|
+
...(blobCids || []).map((cid) => ({
|
|
521
|
+
$type: 'com.atproto.admin.defs#repoBlobRef',
|
|
522
|
+
did,
|
|
523
|
+
cid: cid.toString(),
|
|
524
|
+
recordUri: uri.toString(),
|
|
525
|
+
})),
|
|
526
|
+
],
|
|
527
|
+
}
|
|
453
528
|
}
|
|
454
529
|
|
|
455
530
|
async reverseTakedownRecord(info: { uri: AtUri }) {
|
|
@@ -563,6 +638,11 @@ export class ModerationService {
|
|
|
563
638
|
}
|
|
564
639
|
}
|
|
565
640
|
|
|
641
|
+
export type TakedownSubjects = {
|
|
642
|
+
did: string
|
|
643
|
+
subjects: (RepoRef | RepoBlobRef | StrongRef)[]
|
|
644
|
+
}
|
|
645
|
+
|
|
566
646
|
export type ModerationActionRow = Selectable<ModerationAction>
|
|
567
647
|
export type ReversibleModerationAction = Pick<
|
|
568
648
|
ModerationActionRow,
|
|
@@ -211,6 +211,7 @@ export class ModerationViews {
|
|
|
211
211
|
.selectFrom('moderation_report')
|
|
212
212
|
.where('subjectType', '=', 'com.atproto.repo.strongRef')
|
|
213
213
|
.where('subjectUri', '=', result.uri)
|
|
214
|
+
.leftJoin('actor', 'actor.did', 'moderation_report.subjectDid')
|
|
214
215
|
.orderBy('id', 'desc')
|
|
215
216
|
.selectAll()
|
|
216
217
|
.execute(),
|
|
@@ -7,17 +7,17 @@ import { GenericKeyset, paginate } from '../../db/pagination'
|
|
|
7
7
|
export const getUserSearchQuery = (
|
|
8
8
|
db: Database,
|
|
9
9
|
opts: {
|
|
10
|
-
|
|
10
|
+
query: string
|
|
11
11
|
limit: number
|
|
12
12
|
cursor?: string
|
|
13
13
|
includeSoftDeleted?: boolean
|
|
14
14
|
},
|
|
15
15
|
) => {
|
|
16
16
|
const { ref } = db.db.dynamic
|
|
17
|
-
const {
|
|
17
|
+
const { query, limit, cursor, includeSoftDeleted } = opts
|
|
18
18
|
// Matching user accounts based on handle
|
|
19
|
-
const distanceAccount = distance(
|
|
20
|
-
let accountsQb = getMatchingAccountsQb(db, {
|
|
19
|
+
const distanceAccount = distance(query, ref('handle'))
|
|
20
|
+
let accountsQb = getMatchingAccountsQb(db, { query, includeSoftDeleted })
|
|
21
21
|
accountsQb = paginate(accountsQb, {
|
|
22
22
|
limit,
|
|
23
23
|
cursor,
|
|
@@ -25,8 +25,8 @@ export const getUserSearchQuery = (
|
|
|
25
25
|
keyset: new SearchKeyset(distanceAccount, ref('actor.did')),
|
|
26
26
|
})
|
|
27
27
|
// Matching profiles based on display name
|
|
28
|
-
const distanceProfile = distance(
|
|
29
|
-
let profilesQb = getMatchingProfilesQb(db, {
|
|
28
|
+
const distanceProfile = distance(query, ref('displayName'))
|
|
29
|
+
let profilesQb = getMatchingProfilesQb(db, { query, includeSoftDeleted })
|
|
30
30
|
profilesQb = paginate(profilesQb, {
|
|
31
31
|
limit,
|
|
32
32
|
cursor,
|
|
@@ -46,18 +46,18 @@ export const getUserSearchQuery = (
|
|
|
46
46
|
export const getUserSearchQuerySimple = (
|
|
47
47
|
db: Database,
|
|
48
48
|
opts: {
|
|
49
|
-
|
|
49
|
+
query: string
|
|
50
50
|
limit: number
|
|
51
51
|
},
|
|
52
52
|
) => {
|
|
53
53
|
const { ref } = db.db.dynamic
|
|
54
|
-
const {
|
|
54
|
+
const { query, limit } = opts
|
|
55
55
|
// Matching user accounts based on handle
|
|
56
|
-
const accountsQb = getMatchingAccountsQb(db, {
|
|
56
|
+
const accountsQb = getMatchingAccountsQb(db, { query })
|
|
57
57
|
.orderBy('distance', 'asc')
|
|
58
58
|
.limit(limit)
|
|
59
59
|
// Matching profiles based on display name
|
|
60
|
-
const profilesQb = getMatchingProfilesQb(db, {
|
|
60
|
+
const profilesQb = getMatchingProfilesQb(db, { query })
|
|
61
61
|
.orderBy('distance', 'asc')
|
|
62
62
|
.limit(limit)
|
|
63
63
|
// Combine and paginate result set
|
|
@@ -71,29 +71,29 @@ export const getUserSearchQuerySimple = (
|
|
|
71
71
|
// Matching user accounts based on handle
|
|
72
72
|
const getMatchingAccountsQb = (
|
|
73
73
|
db: Database,
|
|
74
|
-
opts: {
|
|
74
|
+
opts: { query: string; includeSoftDeleted?: boolean },
|
|
75
75
|
) => {
|
|
76
76
|
const { ref } = db.db.dynamic
|
|
77
|
-
const {
|
|
78
|
-
const distanceAccount = distance(
|
|
77
|
+
const { query, includeSoftDeleted } = opts
|
|
78
|
+
const distanceAccount = distance(query, ref('handle'))
|
|
79
79
|
return db.db
|
|
80
80
|
.selectFrom('actor')
|
|
81
81
|
.if(!includeSoftDeleted, (qb) =>
|
|
82
82
|
qb.where(notSoftDeletedClause(ref('actor'))),
|
|
83
83
|
)
|
|
84
84
|
.where('actor.handle', 'is not', null)
|
|
85
|
-
.where(similar(
|
|
85
|
+
.where(similar(query, ref('handle'))) // Coarse filter engaging trigram index
|
|
86
86
|
.select(['actor.did as did', distanceAccount.as('distance')])
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// Matching profiles based on display name
|
|
90
90
|
const getMatchingProfilesQb = (
|
|
91
91
|
db: Database,
|
|
92
|
-
opts: {
|
|
92
|
+
opts: { query: string; includeSoftDeleted?: boolean },
|
|
93
93
|
) => {
|
|
94
94
|
const { ref } = db.db.dynamic
|
|
95
|
-
const {
|
|
96
|
-
const distanceProfile = distance(
|
|
95
|
+
const { query, includeSoftDeleted } = opts
|
|
96
|
+
const distanceProfile = distance(query, ref('displayName'))
|
|
97
97
|
return db.db
|
|
98
98
|
.selectFrom('profile')
|
|
99
99
|
.innerJoin('actor', 'actor.did', 'profile.creator')
|
|
@@ -101,7 +101,7 @@ const getMatchingProfilesQb = (
|
|
|
101
101
|
qb.where(notSoftDeletedClause(ref('actor'))),
|
|
102
102
|
)
|
|
103
103
|
.where('actor.handle', 'is not', null)
|
|
104
|
-
.where(similar(
|
|
104
|
+
.where(similar(query, ref('displayName'))) // Coarse filter engaging trigram index
|
|
105
105
|
.select(['profile.creator as did', distanceProfile.as('distance')])
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -133,15 +133,16 @@ const combineAccountsAndProfilesQb = (
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
// Remove leading @ in case a handle is input that way
|
|
136
|
-
export const
|
|
136
|
+
export const cleanQuery = (query: string) => query.trim().replace(/^@/g, '')
|
|
137
137
|
|
|
138
|
-
// Uses pg_trgm strict word similarity to check similarity between a search
|
|
139
|
-
const distance = (
|
|
140
|
-
sql<number>`(${
|
|
138
|
+
// Uses pg_trgm strict word similarity to check similarity between a search query and a stored value
|
|
139
|
+
const distance = (query: string, ref: DbRef) =>
|
|
140
|
+
sql<number>`(${query} <<-> ${ref})`
|
|
141
141
|
|
|
142
142
|
// Can utilize trigram index to match on strict word similarity.
|
|
143
143
|
// The word_similarity_threshold is set to .4 (i.e. distance < .6) in db/index.ts.
|
|
144
|
-
const similar = (
|
|
144
|
+
const similar = (query: string, ref: DbRef) =>
|
|
145
|
+
sql<boolean>`(${query} <% ${ref})`
|
|
145
146
|
|
|
146
147
|
type Result = { distance: number; did: string }
|
|
147
148
|
type LabeledResult = { primary: number; secondary: string }
|
|
@@ -419,12 +419,12 @@ Array [
|
|
|
419
419
|
"$type": "app.bsky.embed.images#view",
|
|
420
420
|
"images": Array [
|
|
421
421
|
Object {
|
|
422
|
-
"alt": "tests/
|
|
422
|
+
"alt": "tests/sample-img/key-landscape-small.jpg",
|
|
423
423
|
"fullsize": "https://bsky.public.url/img/feed_fullsize/plain/user(5)/cids(5)@jpeg",
|
|
424
424
|
"thumb": "https://bsky.public.url/img/feed_thumbnail/plain/user(5)/cids(5)@jpeg",
|
|
425
425
|
},
|
|
426
426
|
Object {
|
|
427
|
-
"alt": "tests/
|
|
427
|
+
"alt": "tests/sample-img/key-alt.jpg",
|
|
428
428
|
"fullsize": "https://bsky.public.url/img/feed_fullsize/plain/user(5)/cids(6)@jpeg",
|
|
429
429
|
"thumb": "https://bsky.public.url/img/feed_thumbnail/plain/user(5)/cids(6)@jpeg",
|
|
430
430
|
},
|
|
@@ -475,7 +475,7 @@ Array [
|
|
|
475
475
|
"$type": "app.bsky.embed.images",
|
|
476
476
|
"images": Array [
|
|
477
477
|
Object {
|
|
478
|
-
"alt": "tests/
|
|
478
|
+
"alt": "tests/sample-img/key-landscape-small.jpg",
|
|
479
479
|
"image": Object {
|
|
480
480
|
"$type": "blob",
|
|
481
481
|
"mimeType": "image/jpeg",
|
|
@@ -486,7 +486,7 @@ Array [
|
|
|
486
486
|
},
|
|
487
487
|
},
|
|
488
488
|
Object {
|
|
489
|
-
"alt": "tests/
|
|
489
|
+
"alt": "tests/sample-img/key-alt.jpg",
|
|
490
490
|
"image": Object {
|
|
491
491
|
"$type": "blob",
|
|
492
492
|
"mimeType": "image/jpeg",
|
|
@@ -679,12 +679,12 @@ Array [
|
|
|
679
679
|
"$type": "app.bsky.embed.images#view",
|
|
680
680
|
"images": Array [
|
|
681
681
|
Object {
|
|
682
|
-
"alt": "tests/
|
|
682
|
+
"alt": "tests/sample-img/key-landscape-small.jpg",
|
|
683
683
|
"fullsize": "https://bsky.public.url/img/feed_fullsize/plain/user(5)/cids(5)@jpeg",
|
|
684
684
|
"thumb": "https://bsky.public.url/img/feed_thumbnail/plain/user(5)/cids(5)@jpeg",
|
|
685
685
|
},
|
|
686
686
|
Object {
|
|
687
|
-
"alt": "tests/
|
|
687
|
+
"alt": "tests/sample-img/key-alt.jpg",
|
|
688
688
|
"fullsize": "https://bsky.public.url/img/feed_fullsize/plain/user(5)/cids(6)@jpeg",
|
|
689
689
|
"thumb": "https://bsky.public.url/img/feed_thumbnail/plain/user(5)/cids(6)@jpeg",
|
|
690
690
|
},
|
|
@@ -735,7 +735,7 @@ Array [
|
|
|
735
735
|
"$type": "app.bsky.embed.images",
|
|
736
736
|
"images": Array [
|
|
737
737
|
Object {
|
|
738
|
-
"alt": "tests/
|
|
738
|
+
"alt": "tests/sample-img/key-landscape-small.jpg",
|
|
739
739
|
"image": Object {
|
|
740
740
|
"$type": "blob",
|
|
741
741
|
"mimeType": "image/jpeg",
|
|
@@ -746,7 +746,7 @@ Array [
|
|
|
746
746
|
},
|
|
747
747
|
},
|
|
748
748
|
Object {
|
|
749
|
-
"alt": "tests/
|
|
749
|
+
"alt": "tests/sample-img/key-alt.jpg",
|
|
750
750
|
"image": Object {
|
|
751
751
|
"$type": "blob",
|
|
752
752
|
"mimeType": "image/jpeg",
|
|
@@ -906,12 +906,12 @@ Array [
|
|
|
906
906
|
"$type": "app.bsky.embed.images#view",
|
|
907
907
|
"images": Array [
|
|
908
908
|
Object {
|
|
909
|
-
"alt": "tests/
|
|
909
|
+
"alt": "tests/sample-img/key-landscape-small.jpg",
|
|
910
910
|
"fullsize": "https://bsky.public.url/img/feed_fullsize/plain/user(5)/cids(4)@jpeg",
|
|
911
911
|
"thumb": "https://bsky.public.url/img/feed_thumbnail/plain/user(5)/cids(4)@jpeg",
|
|
912
912
|
},
|
|
913
913
|
Object {
|
|
914
|
-
"alt": "tests/
|
|
914
|
+
"alt": "tests/sample-img/key-alt.jpg",
|
|
915
915
|
"fullsize": "https://bsky.public.url/img/feed_fullsize/plain/user(5)/cids(5)@jpeg",
|
|
916
916
|
"thumb": "https://bsky.public.url/img/feed_thumbnail/plain/user(5)/cids(5)@jpeg",
|
|
917
917
|
},
|
|
@@ -962,7 +962,7 @@ Array [
|
|
|
962
962
|
"$type": "app.bsky.embed.images",
|
|
963
963
|
"images": Array [
|
|
964
964
|
Object {
|
|
965
|
-
"alt": "tests/
|
|
965
|
+
"alt": "tests/sample-img/key-landscape-small.jpg",
|
|
966
966
|
"image": Object {
|
|
967
967
|
"$type": "blob",
|
|
968
968
|
"mimeType": "image/jpeg",
|
|
@@ -973,7 +973,7 @@ Array [
|
|
|
973
973
|
},
|
|
974
974
|
},
|
|
975
975
|
Object {
|
|
976
|
-
"alt": "tests/
|
|
976
|
+
"alt": "tests/sample-img/key-alt.jpg",
|
|
977
977
|
"image": Object {
|
|
978
978
|
"$type": "blob",
|
|
979
979
|
"mimeType": "image/jpeg",
|
|
@@ -101,7 +101,7 @@ Array [
|
|
|
101
101
|
"$type": "app.bsky.embed.images#view",
|
|
102
102
|
"images": Array [
|
|
103
103
|
Object {
|
|
104
|
-
"alt": "tests/
|
|
104
|
+
"alt": "tests/sample-img/key-landscape-small.jpg",
|
|
105
105
|
"fullsize": "https://bsky.public.url/img/feed_fullsize/plain/user(2)/cids(5)@jpeg",
|
|
106
106
|
"thumb": "https://bsky.public.url/img/feed_thumbnail/plain/user(2)/cids(5)@jpeg",
|
|
107
107
|
},
|
|
@@ -134,7 +134,7 @@ Array [
|
|
|
134
134
|
"$type": "app.bsky.embed.images",
|
|
135
135
|
"images": Array [
|
|
136
136
|
Object {
|
|
137
|
-
"alt": "tests/
|
|
137
|
+
"alt": "tests/sample-img/key-landscape-small.jpg",
|
|
138
138
|
"image": Object {
|
|
139
139
|
"$type": "blob",
|
|
140
140
|
"mimeType": "image/jpeg",
|
|
@@ -245,7 +245,7 @@ Array [
|
|
|
245
245
|
"$type": "app.bsky.embed.images",
|
|
246
246
|
"images": Array [
|
|
247
247
|
Object {
|
|
248
|
-
"alt": "tests/
|
|
248
|
+
"alt": "tests/sample-img/key-landscape-small.jpg",
|
|
249
249
|
"image": Object {
|
|
250
250
|
"$type": "blob",
|
|
251
251
|
"mimeType": "image/jpeg",
|
|
@@ -256,7 +256,7 @@ Array [
|
|
|
256
256
|
},
|
|
257
257
|
},
|
|
258
258
|
Object {
|
|
259
|
-
"alt": "tests/
|
|
259
|
+
"alt": "tests/sample-img/key-alt.jpg",
|
|
260
260
|
"image": Object {
|
|
261
261
|
"$type": "blob",
|
|
262
262
|
"mimeType": "image/jpeg",
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`admin get moderation action view gets moderation action for a record. 1`] = `
|
|
4
|
+
Object {
|
|
5
|
+
"action": "com.atproto.admin.defs#takedown",
|
|
6
|
+
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
7
|
+
"createdBy": "did:example:admin",
|
|
8
|
+
"id": 2,
|
|
9
|
+
"reason": "X",
|
|
10
|
+
"resolvedReports": Array [
|
|
11
|
+
Object {
|
|
12
|
+
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
13
|
+
"id": 2,
|
|
14
|
+
"reason": "defamation",
|
|
15
|
+
"reasonType": "com.atproto.moderation.defs#reasonOther",
|
|
16
|
+
"reportedBy": "user(1)",
|
|
17
|
+
"resolvedByActionIds": Array [
|
|
18
|
+
2,
|
|
19
|
+
1,
|
|
20
|
+
],
|
|
21
|
+
"subject": Object {
|
|
22
|
+
"$type": "com.atproto.repo.strongRef",
|
|
23
|
+
"cid": "cids(0)",
|
|
24
|
+
"uri": "record(0)",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
"subject": Object {
|
|
29
|
+
"$type": "com.atproto.admin.defs#recordView",
|
|
30
|
+
"blobCids": Array [],
|
|
31
|
+
"cid": "cids(0)",
|
|
32
|
+
"indexedAt": "1970-01-01T00:00:00.000Z",
|
|
33
|
+
"moderation": Object {
|
|
34
|
+
"currentAction": Object {
|
|
35
|
+
"action": "com.atproto.admin.defs#takedown",
|
|
36
|
+
"id": 2,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
"repo": Object {
|
|
40
|
+
"did": "user(0)",
|
|
41
|
+
"email": "alice@test.com",
|
|
42
|
+
"handle": "alice.test",
|
|
43
|
+
"indexedAt": "1970-01-01T00:00:00.000Z",
|
|
44
|
+
"invitesDisabled": false,
|
|
45
|
+
"moderation": Object {},
|
|
46
|
+
"relatedRecords": Array [
|
|
47
|
+
Object {
|
|
48
|
+
"$type": "app.bsky.actor.profile",
|
|
49
|
+
"avatar": Object {
|
|
50
|
+
"$type": "blob",
|
|
51
|
+
"mimeType": "image/jpeg",
|
|
52
|
+
"ref": Object {
|
|
53
|
+
"$link": "cids(1)",
|
|
54
|
+
},
|
|
55
|
+
"size": 3976,
|
|
56
|
+
},
|
|
57
|
+
"description": "its me!",
|
|
58
|
+
"displayName": "ali",
|
|
59
|
+
"labels": Object {
|
|
60
|
+
"$type": "com.atproto.label.defs#selfLabels",
|
|
61
|
+
"values": Array [
|
|
62
|
+
Object {
|
|
63
|
+
"val": "self-label-a",
|
|
64
|
+
},
|
|
65
|
+
Object {
|
|
66
|
+
"val": "self-label-b",
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
"uri": "record(0)",
|
|
74
|
+
"value": Object {
|
|
75
|
+
"$type": "app.bsky.feed.post",
|
|
76
|
+
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
77
|
+
"labels": Object {
|
|
78
|
+
"$type": "com.atproto.label.defs#selfLabels",
|
|
79
|
+
"values": Array [
|
|
80
|
+
Object {
|
|
81
|
+
"val": "self-label",
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
"text": "hey there",
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
"subjectBlobs": Array [],
|
|
89
|
+
}
|
|
90
|
+
`;
|
|
91
|
+
|
|
92
|
+
exports[`admin get moderation action view gets moderation action for a repo. 1`] = `
|
|
93
|
+
Object {
|
|
94
|
+
"action": "com.atproto.admin.defs#flag",
|
|
95
|
+
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
96
|
+
"createdBy": "did:example:admin",
|
|
97
|
+
"id": 1,
|
|
98
|
+
"reason": "X",
|
|
99
|
+
"resolvedReports": Array [
|
|
100
|
+
Object {
|
|
101
|
+
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
102
|
+
"id": 2,
|
|
103
|
+
"reason": "defamation",
|
|
104
|
+
"reasonType": "com.atproto.moderation.defs#reasonOther",
|
|
105
|
+
"reportedBy": "user(1)",
|
|
106
|
+
"resolvedByActionIds": Array [
|
|
107
|
+
2,
|
|
108
|
+
1,
|
|
109
|
+
],
|
|
110
|
+
"subject": Object {
|
|
111
|
+
"$type": "com.atproto.repo.strongRef",
|
|
112
|
+
"cid": "cids(1)",
|
|
113
|
+
"uri": "record(0)",
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
Object {
|
|
117
|
+
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
118
|
+
"id": 1,
|
|
119
|
+
"reasonType": "com.atproto.moderation.defs#reasonSpam",
|
|
120
|
+
"reportedBy": "user(2)",
|
|
121
|
+
"resolvedByActionIds": Array [
|
|
122
|
+
1,
|
|
123
|
+
],
|
|
124
|
+
"subject": Object {
|
|
125
|
+
"$type": "com.atproto.admin.defs#repoRef",
|
|
126
|
+
"did": "user(0)",
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
"reversal": Object {
|
|
131
|
+
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
132
|
+
"createdBy": "did:example:admin",
|
|
133
|
+
"reason": "X",
|
|
134
|
+
},
|
|
135
|
+
"subject": Object {
|
|
136
|
+
"$type": "com.atproto.admin.defs#repoView",
|
|
137
|
+
"did": "user(0)",
|
|
138
|
+
"email": "alice@test.com",
|
|
139
|
+
"handle": "alice.test",
|
|
140
|
+
"indexedAt": "1970-01-01T00:00:00.000Z",
|
|
141
|
+
"invitesDisabled": false,
|
|
142
|
+
"moderation": Object {},
|
|
143
|
+
"relatedRecords": Array [
|
|
144
|
+
Object {
|
|
145
|
+
"$type": "app.bsky.actor.profile",
|
|
146
|
+
"avatar": Object {
|
|
147
|
+
"$type": "blob",
|
|
148
|
+
"mimeType": "image/jpeg",
|
|
149
|
+
"ref": Object {
|
|
150
|
+
"$link": "cids(0)",
|
|
151
|
+
},
|
|
152
|
+
"size": 3976,
|
|
153
|
+
},
|
|
154
|
+
"description": "its me!",
|
|
155
|
+
"displayName": "ali",
|
|
156
|
+
"labels": Object {
|
|
157
|
+
"$type": "com.atproto.label.defs#selfLabels",
|
|
158
|
+
"values": Array [
|
|
159
|
+
Object {
|
|
160
|
+
"val": "self-label-a",
|
|
161
|
+
},
|
|
162
|
+
Object {
|
|
163
|
+
"val": "self-label-b",
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
"subjectBlobs": Array [],
|
|
171
|
+
}
|
|
172
|
+
`;
|