@atproto/bsky 0.0.214 → 0.0.215
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 +11 -0
- package/dist/api/app/bsky/unspecced/getSuggestedOnboardingUsers.d.ts +4 -0
- package/dist/api/app/bsky/unspecced/getSuggestedOnboardingUsers.d.ts.map +1 -0
- package/dist/api/app/bsky/unspecced/getSuggestedOnboardingUsers.js +104 -0
- package/dist/api/app/bsky/unspecced/getSuggestedOnboardingUsers.js.map +1 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +2 -0
- package/dist/api/index.js.map +1 -1
- package/dist/feature-gates.d.ts +1 -0
- package/dist/feature-gates.d.ts.map +1 -1
- package/dist/feature-gates.js +1 -0
- package/dist/feature-gates.js.map +1 -1
- package/dist/lexicon/index.d.ts +4 -0
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +8 -0
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +228 -10
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +116 -5
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/draft/defs.d.ts +1 -1
- package/dist/lexicon/types/app/bsky/draft/defs.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/draft/defs.js.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsers.d.ts +26 -0
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsers.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsers.js +7 -0
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsers.js.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsersSkeleton.d.ts +27 -0
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsersSkeleton.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsersSkeleton.js +7 -0
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsersSkeleton.js.map +1 -0
- package/dist/lexicon/types/com/germnetwork/declaration.d.ts +7 -1
- package/dist/lexicon/types/com/germnetwork/declaration.d.ts.map +1 -1
- package/dist/lexicon/types/com/germnetwork/declaration.js.map +1 -1
- package/package.json +7 -7
- package/src/api/app/bsky/unspecced/getSuggestedOnboardingUsers.ts +176 -0
- package/src/api/index.ts +2 -0
- package/src/feature-gates.ts +1 -0
- package/src/lexicon/index.ts +26 -0
- package/src/lexicon/lexicons.ts +128 -5
- package/src/lexicon/types/app/bsky/draft/defs.ts +1 -1
- package/src/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsers.ts +44 -0
- package/src/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsersSkeleton.ts +45 -0
- package/src/lexicon/types/com/germnetwork/declaration.ts +7 -1
- package/tests/views/get-suggested-onboarding-users.test.ts +186 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/src/lexicon/lexicons.ts
CHANGED
|
@@ -2392,9 +2392,10 @@ export const schemaDict = {
|
|
|
2392
2392
|
properties: {
|
|
2393
2393
|
text: {
|
|
2394
2394
|
type: 'string',
|
|
2395
|
-
maxLength:
|
|
2396
|
-
maxGraphemes:
|
|
2397
|
-
description:
|
|
2395
|
+
maxLength: 10000,
|
|
2396
|
+
maxGraphemes: 1000,
|
|
2397
|
+
description:
|
|
2398
|
+
'The primary post content. It has a higher limit than post contents to allow storing a larger text that can later be refined into smaller posts.',
|
|
2398
2399
|
},
|
|
2399
2400
|
labels: {
|
|
2400
2401
|
type: 'union',
|
|
@@ -8343,6 +8344,105 @@ export const schemaDict = {
|
|
|
8343
8344
|
},
|
|
8344
8345
|
},
|
|
8345
8346
|
},
|
|
8347
|
+
AppBskyUnspeccedGetSuggestedOnboardingUsers: {
|
|
8348
|
+
lexicon: 1,
|
|
8349
|
+
id: 'app.bsky.unspecced.getSuggestedOnboardingUsers',
|
|
8350
|
+
defs: {
|
|
8351
|
+
main: {
|
|
8352
|
+
type: 'query',
|
|
8353
|
+
description: 'Get a list of suggested users for onboarding',
|
|
8354
|
+
parameters: {
|
|
8355
|
+
type: 'params',
|
|
8356
|
+
properties: {
|
|
8357
|
+
category: {
|
|
8358
|
+
type: 'string',
|
|
8359
|
+
description: 'Category of users to get suggestions for.',
|
|
8360
|
+
},
|
|
8361
|
+
limit: {
|
|
8362
|
+
type: 'integer',
|
|
8363
|
+
minimum: 1,
|
|
8364
|
+
maximum: 50,
|
|
8365
|
+
default: 25,
|
|
8366
|
+
},
|
|
8367
|
+
},
|
|
8368
|
+
},
|
|
8369
|
+
output: {
|
|
8370
|
+
encoding: 'application/json',
|
|
8371
|
+
schema: {
|
|
8372
|
+
type: 'object',
|
|
8373
|
+
required: ['actors'],
|
|
8374
|
+
properties: {
|
|
8375
|
+
actors: {
|
|
8376
|
+
type: 'array',
|
|
8377
|
+
items: {
|
|
8378
|
+
type: 'ref',
|
|
8379
|
+
ref: 'lex:app.bsky.actor.defs#profileView',
|
|
8380
|
+
},
|
|
8381
|
+
},
|
|
8382
|
+
recId: {
|
|
8383
|
+
type: 'string',
|
|
8384
|
+
description:
|
|
8385
|
+
'Snowflake for this recommendation, use when submitting recommendation events.',
|
|
8386
|
+
},
|
|
8387
|
+
},
|
|
8388
|
+
},
|
|
8389
|
+
},
|
|
8390
|
+
},
|
|
8391
|
+
},
|
|
8392
|
+
},
|
|
8393
|
+
AppBskyUnspeccedGetSuggestedOnboardingUsersSkeleton: {
|
|
8394
|
+
lexicon: 1,
|
|
8395
|
+
id: 'app.bsky.unspecced.getSuggestedOnboardingUsersSkeleton',
|
|
8396
|
+
defs: {
|
|
8397
|
+
main: {
|
|
8398
|
+
type: 'query',
|
|
8399
|
+
description:
|
|
8400
|
+
'Get a skeleton of suggested users for onboarding. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedOnboardingUsers',
|
|
8401
|
+
parameters: {
|
|
8402
|
+
type: 'params',
|
|
8403
|
+
properties: {
|
|
8404
|
+
viewer: {
|
|
8405
|
+
type: 'string',
|
|
8406
|
+
format: 'did',
|
|
8407
|
+
description:
|
|
8408
|
+
'DID of the account making the request (not included for public/unauthenticated queries).',
|
|
8409
|
+
},
|
|
8410
|
+
category: {
|
|
8411
|
+
type: 'string',
|
|
8412
|
+
description: 'Category of users to get suggestions for.',
|
|
8413
|
+
},
|
|
8414
|
+
limit: {
|
|
8415
|
+
type: 'integer',
|
|
8416
|
+
minimum: 1,
|
|
8417
|
+
maximum: 50,
|
|
8418
|
+
default: 25,
|
|
8419
|
+
},
|
|
8420
|
+
},
|
|
8421
|
+
},
|
|
8422
|
+
output: {
|
|
8423
|
+
encoding: 'application/json',
|
|
8424
|
+
schema: {
|
|
8425
|
+
type: 'object',
|
|
8426
|
+
required: ['dids'],
|
|
8427
|
+
properties: {
|
|
8428
|
+
dids: {
|
|
8429
|
+
type: 'array',
|
|
8430
|
+
items: {
|
|
8431
|
+
type: 'string',
|
|
8432
|
+
format: 'did',
|
|
8433
|
+
},
|
|
8434
|
+
},
|
|
8435
|
+
recId: {
|
|
8436
|
+
type: 'string',
|
|
8437
|
+
description:
|
|
8438
|
+
'Snowflake for this recommendation, use when submitting recommendation events.',
|
|
8439
|
+
},
|
|
8440
|
+
},
|
|
8441
|
+
},
|
|
8442
|
+
},
|
|
8443
|
+
},
|
|
8444
|
+
},
|
|
8445
|
+
},
|
|
8346
8446
|
AppBskyUnspeccedGetSuggestedStarterPacks: {
|
|
8347
8447
|
lexicon: 1,
|
|
8348
8448
|
id: 'app.bsky.unspecced.getSuggestedStarterPacks',
|
|
@@ -15346,7 +15446,7 @@ export const schemaDict = {
|
|
|
15346
15446
|
defs: {
|
|
15347
15447
|
main: {
|
|
15348
15448
|
type: 'record',
|
|
15349
|
-
description: 'A
|
|
15449
|
+
description: 'A declaration of a Germ Network account',
|
|
15350
15450
|
key: 'literal:self',
|
|
15351
15451
|
record: {
|
|
15352
15452
|
type: 'object',
|
|
@@ -15354,22 +15454,33 @@ export const schemaDict = {
|
|
|
15354
15454
|
properties: {
|
|
15355
15455
|
version: {
|
|
15356
15456
|
type: 'string',
|
|
15457
|
+
description:
|
|
15458
|
+
'Semver version number, without pre-release or build information, for the format of opaque content',
|
|
15459
|
+
minLength: 5,
|
|
15460
|
+
maxLength: 14,
|
|
15357
15461
|
},
|
|
15358
15462
|
currentKey: {
|
|
15359
15463
|
type: 'bytes',
|
|
15464
|
+
description:
|
|
15465
|
+
'Opaque value, an ed25519 public key prefixed with a byte enum',
|
|
15360
15466
|
},
|
|
15361
15467
|
messageMe: {
|
|
15362
15468
|
type: 'ref',
|
|
15469
|
+
description: 'Controls who can message this account',
|
|
15363
15470
|
ref: 'lex:com.germnetwork.declaration#messageMe',
|
|
15364
15471
|
},
|
|
15365
15472
|
keyPackage: {
|
|
15366
15473
|
type: 'bytes',
|
|
15474
|
+
description:
|
|
15475
|
+
'Opaque value, contains MLS KeyPackage(s), and other signature data, and is signed by the currentKey',
|
|
15367
15476
|
},
|
|
15368
15477
|
continuityProofs: {
|
|
15369
15478
|
type: 'array',
|
|
15479
|
+
description: 'Array of opaque values to allow for key rolling',
|
|
15370
15480
|
items: {
|
|
15371
15481
|
type: 'bytes',
|
|
15372
15482
|
},
|
|
15483
|
+
maxLength: 1000,
|
|
15373
15484
|
},
|
|
15374
15485
|
},
|
|
15375
15486
|
},
|
|
@@ -15380,11 +15491,19 @@ export const schemaDict = {
|
|
|
15380
15491
|
properties: {
|
|
15381
15492
|
messageMeUrl: {
|
|
15382
15493
|
type: 'string',
|
|
15494
|
+
description:
|
|
15495
|
+
'A URL to present to an account that does not have its own com.germnetwork.declaration record, must have an empty fragment component, where the app should fill in the fragment component with the DIDs of the two accounts who wish to message each other',
|
|
15383
15496
|
format: 'uri',
|
|
15497
|
+
minLength: 1,
|
|
15498
|
+
maxLength: 2047,
|
|
15384
15499
|
},
|
|
15385
15500
|
showButtonTo: {
|
|
15386
15501
|
type: 'string',
|
|
15387
|
-
knownValues: ['usersIFollow', 'everyone'],
|
|
15502
|
+
knownValues: ['none', 'usersIFollow', 'everyone'],
|
|
15503
|
+
description:
|
|
15504
|
+
"The policy of who can message the account, this value is included in the keyPackage, but is duplicated here to allow applications to decide if they should show a 'Message on Germ' button to the viewer.",
|
|
15505
|
+
minLength: 1,
|
|
15506
|
+
maxLength: 100,
|
|
15388
15507
|
},
|
|
15389
15508
|
},
|
|
15390
15509
|
},
|
|
@@ -15555,6 +15674,10 @@ export const ids = {
|
|
|
15555
15674
|
AppBskyUnspeccedGetSuggestedFeeds: 'app.bsky.unspecced.getSuggestedFeeds',
|
|
15556
15675
|
AppBskyUnspeccedGetSuggestedFeedsSkeleton:
|
|
15557
15676
|
'app.bsky.unspecced.getSuggestedFeedsSkeleton',
|
|
15677
|
+
AppBskyUnspeccedGetSuggestedOnboardingUsers:
|
|
15678
|
+
'app.bsky.unspecced.getSuggestedOnboardingUsers',
|
|
15679
|
+
AppBskyUnspeccedGetSuggestedOnboardingUsersSkeleton:
|
|
15680
|
+
'app.bsky.unspecced.getSuggestedOnboardingUsersSkeleton',
|
|
15558
15681
|
AppBskyUnspeccedGetSuggestedStarterPacks:
|
|
15559
15682
|
'app.bsky.unspecced.getSuggestedStarterPacks',
|
|
15560
15683
|
AppBskyUnspeccedGetSuggestedStarterPacksSkeleton:
|
|
@@ -75,7 +75,7 @@ export function validateDraft<V>(v: V) {
|
|
|
75
75
|
/** One of the posts that compose a draft. */
|
|
76
76
|
export interface DraftPost {
|
|
77
77
|
$type?: 'app.bsky.draft.defs#draftPost'
|
|
78
|
-
/** The primary post content. */
|
|
78
|
+
/** The primary post content. It has a higher limit than post contents to allow storing a larger text that can later be refined into smaller posts. */
|
|
79
79
|
text: string
|
|
80
80
|
labels?: $Typed<ComAtprotoLabelDefs.SelfLabels> | { $type: string }
|
|
81
81
|
embedImages?: DraftEmbedImage[]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
5
|
+
import { CID } from 'multiformats/cid'
|
|
6
|
+
import { validate as _validate } from '../../../../lexicons'
|
|
7
|
+
import {
|
|
8
|
+
type $Typed,
|
|
9
|
+
is$typed as _is$typed,
|
|
10
|
+
type OmitKey,
|
|
11
|
+
} from '../../../../util'
|
|
12
|
+
import type * as AppBskyActorDefs from '../actor/defs.js'
|
|
13
|
+
|
|
14
|
+
const is$typed = _is$typed,
|
|
15
|
+
validate = _validate
|
|
16
|
+
const id = 'app.bsky.unspecced.getSuggestedOnboardingUsers'
|
|
17
|
+
|
|
18
|
+
export type QueryParams = {
|
|
19
|
+
/** Category of users to get suggestions for. */
|
|
20
|
+
category?: string
|
|
21
|
+
limit: number
|
|
22
|
+
}
|
|
23
|
+
export type InputSchema = undefined
|
|
24
|
+
|
|
25
|
+
export interface OutputSchema {
|
|
26
|
+
actors: AppBskyActorDefs.ProfileView[]
|
|
27
|
+
/** Snowflake for this recommendation, use when submitting recommendation events. */
|
|
28
|
+
recId?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type HandlerInput = void
|
|
32
|
+
|
|
33
|
+
export interface HandlerSuccess {
|
|
34
|
+
encoding: 'application/json'
|
|
35
|
+
body: OutputSchema
|
|
36
|
+
headers?: { [key: string]: string }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface HandlerError {
|
|
40
|
+
status: number
|
|
41
|
+
message?: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type HandlerOutput = HandlerError | HandlerSuccess
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
5
|
+
import { CID } from 'multiformats/cid'
|
|
6
|
+
import { validate as _validate } from '../../../../lexicons'
|
|
7
|
+
import {
|
|
8
|
+
type $Typed,
|
|
9
|
+
is$typed as _is$typed,
|
|
10
|
+
type OmitKey,
|
|
11
|
+
} from '../../../../util'
|
|
12
|
+
|
|
13
|
+
const is$typed = _is$typed,
|
|
14
|
+
validate = _validate
|
|
15
|
+
const id = 'app.bsky.unspecced.getSuggestedOnboardingUsersSkeleton'
|
|
16
|
+
|
|
17
|
+
export type QueryParams = {
|
|
18
|
+
/** DID of the account making the request (not included for public/unauthenticated queries). */
|
|
19
|
+
viewer?: string
|
|
20
|
+
/** Category of users to get suggestions for. */
|
|
21
|
+
category?: string
|
|
22
|
+
limit: number
|
|
23
|
+
}
|
|
24
|
+
export type InputSchema = undefined
|
|
25
|
+
|
|
26
|
+
export interface OutputSchema {
|
|
27
|
+
dids: string[]
|
|
28
|
+
/** Snowflake for this recommendation, use when submitting recommendation events. */
|
|
29
|
+
recId?: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type HandlerInput = void
|
|
33
|
+
|
|
34
|
+
export interface HandlerSuccess {
|
|
35
|
+
encoding: 'application/json'
|
|
36
|
+
body: OutputSchema
|
|
37
|
+
headers?: { [key: string]: string }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface HandlerError {
|
|
41
|
+
status: number
|
|
42
|
+
message?: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type HandlerOutput = HandlerError | HandlerSuccess
|
|
@@ -12,10 +12,14 @@ const id = 'com.germnetwork.declaration'
|
|
|
12
12
|
|
|
13
13
|
export interface Main {
|
|
14
14
|
$type: 'com.germnetwork.declaration'
|
|
15
|
+
/** Semver version number, without pre-release or build information, for the format of opaque content */
|
|
15
16
|
version: string
|
|
17
|
+
/** Opaque value, an ed25519 public key prefixed with a byte enum */
|
|
16
18
|
currentKey: Uint8Array
|
|
17
19
|
messageMe?: MessageMe
|
|
20
|
+
/** Opaque value, contains MLS KeyPackage(s), and other signature data, and is signed by the currentKey */
|
|
18
21
|
keyPackage?: Uint8Array
|
|
22
|
+
/** Array of opaque values to allow for key rolling */
|
|
19
23
|
continuityProofs?: Uint8Array[]
|
|
20
24
|
[k: string]: unknown
|
|
21
25
|
}
|
|
@@ -38,8 +42,10 @@ export {
|
|
|
38
42
|
|
|
39
43
|
export interface MessageMe {
|
|
40
44
|
$type?: 'com.germnetwork.declaration#messageMe'
|
|
45
|
+
/** A URL to present to an account that does not have its own com.germnetwork.declaration record, must have an empty fragment component, where the app should fill in the fragment component with the DIDs of the two accounts who wish to message each other */
|
|
41
46
|
messageMeUrl: string
|
|
42
|
-
|
|
47
|
+
/** The policy of who can message the account, this value is included in the keyPackage, but is duplicated here to allow applications to decide if they should show a 'Message on Germ' button to the viewer. */
|
|
48
|
+
showButtonTo: 'none' | 'usersIFollow' | 'everyone' | (string & {})
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
const hashMessageMe = 'messageMe'
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { once } from 'node:events'
|
|
2
|
+
import { Server, createServer } from 'node:http'
|
|
3
|
+
import { AddressInfo } from 'node:net'
|
|
4
|
+
import express, { Application } from 'express'
|
|
5
|
+
import AtpAgent from '@atproto/api'
|
|
6
|
+
import { SeedClient, TestNetwork } from '@atproto/dev-env'
|
|
7
|
+
import { ids } from '../../src/lexicon/lexicons'
|
|
8
|
+
import { OutputSchema } from '../../src/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsersSkeleton'
|
|
9
|
+
|
|
10
|
+
type User = {
|
|
11
|
+
id: string
|
|
12
|
+
did: string
|
|
13
|
+
email: string
|
|
14
|
+
handle: string
|
|
15
|
+
password: string
|
|
16
|
+
displayName: string
|
|
17
|
+
description: string
|
|
18
|
+
selfLabels: undefined
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function createUser(name: string): User {
|
|
22
|
+
return {
|
|
23
|
+
id: name,
|
|
24
|
+
// @ts-ignore overwritten below
|
|
25
|
+
did: undefined,
|
|
26
|
+
email: `${name}@test.com`,
|
|
27
|
+
handle: `${name}.test`,
|
|
28
|
+
password: `${name}-pass`,
|
|
29
|
+
displayName: name,
|
|
30
|
+
description: `hi im ${name}`,
|
|
31
|
+
selfLabels: undefined,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const users = {
|
|
36
|
+
suggestedUser: createUser('suggested-user'),
|
|
37
|
+
viewer: createUser('viewer'),
|
|
38
|
+
viewerBlocker: createUser('viewer-blocker'),
|
|
39
|
+
followedUser: createUser('followed-user'),
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type Users = typeof users
|
|
43
|
+
|
|
44
|
+
async function seed(sc: SeedClient) {
|
|
45
|
+
const u = structuredClone(users)
|
|
46
|
+
|
|
47
|
+
for (const [key, user] of Object.entries(u)) {
|
|
48
|
+
await sc.createAccount(key, user)
|
|
49
|
+
u[key].did = sc.dids[key]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
await sc.block(u.viewerBlocker.did, u.suggestedUser.did)
|
|
53
|
+
await sc.follow(u.viewer.did, u.followedUser.did)
|
|
54
|
+
|
|
55
|
+
await sc.network.processAll()
|
|
56
|
+
|
|
57
|
+
return { users: u }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
describe('getSuggestedOnboardingUsers', () => {
|
|
61
|
+
let network: TestNetwork
|
|
62
|
+
let agent: AtpAgent
|
|
63
|
+
let sc: SeedClient
|
|
64
|
+
let seededUsers: Users
|
|
65
|
+
let mockServer: MockServer
|
|
66
|
+
|
|
67
|
+
beforeAll(async () => {
|
|
68
|
+
mockServer = new MockServer()
|
|
69
|
+
await mockServer.listen()
|
|
70
|
+
|
|
71
|
+
network = await TestNetwork.create({
|
|
72
|
+
dbPostgresSchema: 'bsky_tests_get_suggested_onboarding_users',
|
|
73
|
+
bsky: {
|
|
74
|
+
topicsUrl: mockServer.url,
|
|
75
|
+
topicsApiKey: 'test',
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
agent = network.bsky.getClient()
|
|
79
|
+
sc = network.getSeedClient()
|
|
80
|
+
|
|
81
|
+
const result = await seed(sc)
|
|
82
|
+
seededUsers = result.users
|
|
83
|
+
|
|
84
|
+
await network.processAll()
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
afterAll(async () => {
|
|
88
|
+
await network.close()
|
|
89
|
+
await mockServer.stop()
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
describe(`basic handling`, () => {
|
|
93
|
+
beforeAll(() => {
|
|
94
|
+
mockServer.mockedDids.set('suggestedUser', seededUsers.suggestedUser.did)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
afterAll(() => {
|
|
98
|
+
mockServer.mockedDids.delete('suggestedUser')
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it(`returns users for non-blocking viewer`, async () => {
|
|
102
|
+
const { data } =
|
|
103
|
+
await agent.app.bsky.unspecced.getSuggestedOnboardingUsers(undefined, {
|
|
104
|
+
headers: await network.serviceHeaders(
|
|
105
|
+
seededUsers.viewer.did,
|
|
106
|
+
ids.AppBskyUnspeccedGetSuggestedOnboardingUsers,
|
|
107
|
+
),
|
|
108
|
+
})
|
|
109
|
+
const actor = data.actors.find(
|
|
110
|
+
(a) => a.did === seededUsers.suggestedUser.did,
|
|
111
|
+
)
|
|
112
|
+
expect(actor).toBeDefined()
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it(`does not return user if blocked by viewer`, async () => {
|
|
116
|
+
const { data } =
|
|
117
|
+
await agent.app.bsky.unspecced.getSuggestedOnboardingUsers(undefined, {
|
|
118
|
+
headers: await network.serviceHeaders(
|
|
119
|
+
seededUsers.viewerBlocker.did,
|
|
120
|
+
ids.AppBskyUnspeccedGetSuggestedOnboardingUsers,
|
|
121
|
+
),
|
|
122
|
+
})
|
|
123
|
+
const actor = data.actors.find(
|
|
124
|
+
(a) => a.did === seededUsers.suggestedUser.did,
|
|
125
|
+
)
|
|
126
|
+
expect(actor).not.toBeDefined()
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it(`does not return users that viewer already follows`, async () => {
|
|
130
|
+
mockServer.mockedDids.set('followedUser', seededUsers.followedUser.did)
|
|
131
|
+
const { data } =
|
|
132
|
+
await agent.app.bsky.unspecced.getSuggestedOnboardingUsers(undefined, {
|
|
133
|
+
headers: await network.serviceHeaders(
|
|
134
|
+
seededUsers.viewer.did,
|
|
135
|
+
ids.AppBskyUnspeccedGetSuggestedOnboardingUsers,
|
|
136
|
+
),
|
|
137
|
+
})
|
|
138
|
+
const actor = data.actors.find(
|
|
139
|
+
(a) => a.did === seededUsers.followedUser.did,
|
|
140
|
+
)
|
|
141
|
+
expect(actor).not.toBeDefined()
|
|
142
|
+
mockServer.mockedDids.delete('followedUser')
|
|
143
|
+
})
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
class MockServer {
|
|
148
|
+
app: Application
|
|
149
|
+
server: Server
|
|
150
|
+
|
|
151
|
+
mockedDids = new Map<string, string>()
|
|
152
|
+
|
|
153
|
+
constructor() {
|
|
154
|
+
this.app = this.createApp()
|
|
155
|
+
this.server = createServer(this.app)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async listen(port?: number) {
|
|
159
|
+
this.server.listen(port)
|
|
160
|
+
await once(this.server, 'listening')
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async stop() {
|
|
164
|
+
this.server.close()
|
|
165
|
+
await once(this.server, 'close')
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
get url() {
|
|
169
|
+
const address = this.server.address() as AddressInfo
|
|
170
|
+
return `http://localhost:${address.port}`
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private createApp() {
|
|
174
|
+
const app = express()
|
|
175
|
+
app.get(
|
|
176
|
+
'/xrpc/app.bsky.unspecced.getSuggestedUsersSkeleton',
|
|
177
|
+
(req, res) => {
|
|
178
|
+
const skeleton: OutputSchema = {
|
|
179
|
+
dids: Array.from(this.mockedDids.values()),
|
|
180
|
+
}
|
|
181
|
+
return res.json(skeleton)
|
|
182
|
+
},
|
|
183
|
+
)
|
|
184
|
+
return app
|
|
185
|
+
}
|
|
186
|
+
}
|