@atproto/ozone 0.1.46 → 0.1.47
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 +12 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +4 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/moderation/getRecord.d.ts.map +1 -1
- package/dist/api/moderation/getRecord.js +5 -4
- package/dist/api/moderation/getRecord.js.map +1 -1
- package/dist/api/moderation/getRecords.d.ts +4 -0
- package/dist/api/moderation/getRecords.d.ts.map +1 -0
- package/dist/api/moderation/getRecords.js +37 -0
- package/dist/api/moderation/getRecords.js.map +1 -0
- package/dist/api/moderation/getRepo.d.ts.map +1 -1
- package/dist/api/moderation/getRepo.js +5 -4
- package/dist/api/moderation/getRepo.js.map +1 -1
- package/dist/api/moderation/getRepos.d.ts +4 -0
- package/dist/api/moderation/getRepos.d.ts.map +1 -0
- package/dist/api/moderation/getRepos.js +36 -0
- package/dist/api/moderation/getRepos.js.map +1 -0
- package/dist/api/util.d.ts +1 -1
- package/dist/api/util.d.ts.map +1 -1
- package/dist/api/util.js +13 -9
- package/dist/api/util.js.map +1 -1
- package/dist/db/migrations/20241001T205730722Z-subject-status-review-state-index.d.ts +4 -0
- package/dist/db/migrations/20241001T205730722Z-subject-status-review-state-index.d.ts.map +1 -0
- package/dist/db/migrations/20241001T205730722Z-subject-status-review-state-index.js +18 -0
- package/dist/db/migrations/20241001T205730722Z-subject-status-review-state-index.js.map +1 -0
- package/dist/db/migrations/index.d.ts +1 -0
- package/dist/db/migrations/index.d.ts.map +1 -1
- package/dist/db/migrations/index.js +2 -1
- package/dist/db/migrations/index.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 +85 -0
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +93 -0
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/com/atproto/repo/getRecord.d.ts +1 -0
- package/dist/lexicon/types/com/atproto/repo/getRecord.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/getRecords.d.ts +39 -0
- package/dist/lexicon/types/tools/ozone/moderation/getRecords.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/moderation/getRecords.js +3 -0
- package/dist/lexicon/types/tools/ozone/moderation/getRecords.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/moderation/getRepos.d.ts +39 -0
- package/dist/lexicon/types/tools/ozone/moderation/getRepos.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/moderation/getRepos.js +3 -0
- package/dist/lexicon/types/tools/ozone/moderation/getRepos.js.map +1 -0
- package/dist/mod-service/views.d.ts +5 -5
- package/dist/mod-service/views.d.ts.map +1 -1
- package/dist/mod-service/views.js +75 -48
- package/dist/mod-service/views.js.map +1 -1
- package/package.json +5 -5
- package/src/api/index.ts +4 -0
- package/src/api/moderation/getRecord.ts +7 -5
- package/src/api/moderation/getRecords.ts +50 -0
- package/src/api/moderation/getRepo.ts +7 -5
- package/src/api/moderation/getRepos.ts +41 -0
- package/src/api/util.ts +16 -9
- package/src/db/migrations/20241001T205730722Z-subject-status-review-state-index.ts +15 -0
- package/src/db/migrations/index.ts +1 -0
- package/src/lexicon/index.ts +24 -0
- package/src/lexicon/lexicons.ts +93 -0
- package/src/lexicon/types/com/atproto/repo/getRecord.ts +1 -0
- package/src/lexicon/types/tools/ozone/moderation/getRecords.ts +50 -0
- package/src/lexicon/types/tools/ozone/moderation/getRepos.ts +50 -0
- package/src/mod-service/views.ts +93 -52
- package/tests/__snapshots__/get-records.test.ts.snap +153 -0
- package/tests/__snapshots__/get-repos.test.ts.snap +108 -0
- package/tests/get-records.test.ts +87 -0
- package/tests/get-repos.test.ts +87 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Server } from '../../lexicon'
|
|
2
|
+
import AppContext from '../../context'
|
|
3
|
+
import { addAccountInfoToRepoViewDetail, getPdsAccountInfos } from '../util'
|
|
4
|
+
|
|
5
|
+
export default function (server: Server, ctx: AppContext) {
|
|
6
|
+
server.tools.ozone.moderation.getRepos({
|
|
7
|
+
auth: ctx.authVerifier.modOrAdminToken,
|
|
8
|
+
handler: async ({ params, auth, req }) => {
|
|
9
|
+
const { dids } = params
|
|
10
|
+
const db = ctx.db
|
|
11
|
+
const labelers = ctx.reqLabelers(req)
|
|
12
|
+
const [partialRepos, accountInfo] = await Promise.all([
|
|
13
|
+
ctx.modService(db).views.repoDetails(dids, labelers),
|
|
14
|
+
getPdsAccountInfos(ctx, dids),
|
|
15
|
+
])
|
|
16
|
+
|
|
17
|
+
const repos = dids.map((did) => {
|
|
18
|
+
const partialRepo = partialRepos.get(did)
|
|
19
|
+
if (!partialRepo) {
|
|
20
|
+
return {
|
|
21
|
+
did,
|
|
22
|
+
$type: 'tools.ozone.moderation.defs#repoViewNotFound',
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
$type: 'tools.ozone.moderation.defs#repoViewDetail',
|
|
27
|
+
...addAccountInfoToRepoViewDetail(
|
|
28
|
+
partialRepo,
|
|
29
|
+
accountInfo.get(did) || null,
|
|
30
|
+
auth.credentials.isModerator,
|
|
31
|
+
),
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
encoding: 'application/json',
|
|
37
|
+
body: { repos },
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
}
|
package/src/api/util.ts
CHANGED
|
@@ -28,19 +28,26 @@ import {
|
|
|
28
28
|
} from '../lexicon/types/tools/ozone/team/defs'
|
|
29
29
|
import { ids } from '../lexicon/lexicons'
|
|
30
30
|
|
|
31
|
-
export const
|
|
31
|
+
export const getPdsAccountInfos = async (
|
|
32
32
|
ctx: AppContext,
|
|
33
|
-
|
|
34
|
-
): Promise<AccountView | null
|
|
33
|
+
dids: string[],
|
|
34
|
+
): Promise<Map<string, AccountView | null>> => {
|
|
35
|
+
const results = new Map<string, AccountView | null>()
|
|
36
|
+
|
|
35
37
|
const agent = ctx.pdsAgent
|
|
36
|
-
if (!agent) return
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
if (!agent) return results
|
|
39
|
+
|
|
40
|
+
const auth = await ctx.pdsAuth(ids.ComAtprotoAdminGetAccountInfos)
|
|
41
|
+
if (!auth) return results
|
|
42
|
+
|
|
39
43
|
try {
|
|
40
|
-
const res = await agent.
|
|
41
|
-
|
|
44
|
+
const res = await agent.com.atproto.admin.getAccountInfos({ dids }, auth)
|
|
45
|
+
res.data.infos.forEach((info) => {
|
|
46
|
+
results.set(info.did, info)
|
|
47
|
+
})
|
|
48
|
+
return results
|
|
42
49
|
} catch {
|
|
43
|
-
return
|
|
50
|
+
return results
|
|
44
51
|
}
|
|
45
52
|
}
|
|
46
53
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Kysely } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema
|
|
5
|
+
.createIndex('moderation_subject_status_review_state_idx')
|
|
6
|
+
.on('moderation_subject_status')
|
|
7
|
+
.column('reviewState')
|
|
8
|
+
.execute()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
12
|
+
await db.schema
|
|
13
|
+
.dropIndex('moderation_subject_status_review_state_idx')
|
|
14
|
+
.execute()
|
|
15
|
+
}
|
|
@@ -13,3 +13,4 @@ export * as _20240430T211332580Z from './20240521T211332580Z-member'
|
|
|
13
13
|
export * as _20240814T003647759Z from './20240814T003647759Z-event-created-at-index'
|
|
14
14
|
export * as _20240903T205730722Z from './20240903T205730722Z-add-template-lang'
|
|
15
15
|
export * as _20240904T205730722Z from './20240904T205730722Z-add-subject-did-index'
|
|
16
|
+
export * as _20241001T205730722Z from './20241001T205730722Z-subject-status-review-state-index'
|
package/src/lexicon/index.ts
CHANGED
|
@@ -166,7 +166,9 @@ import * as ToolsOzoneCommunicationUpdateTemplate from './types/tools/ozone/comm
|
|
|
166
166
|
import * as ToolsOzoneModerationEmitEvent from './types/tools/ozone/moderation/emitEvent'
|
|
167
167
|
import * as ToolsOzoneModerationGetEvent from './types/tools/ozone/moderation/getEvent'
|
|
168
168
|
import * as ToolsOzoneModerationGetRecord from './types/tools/ozone/moderation/getRecord'
|
|
169
|
+
import * as ToolsOzoneModerationGetRecords from './types/tools/ozone/moderation/getRecords'
|
|
169
170
|
import * as ToolsOzoneModerationGetRepo from './types/tools/ozone/moderation/getRepo'
|
|
171
|
+
import * as ToolsOzoneModerationGetRepos from './types/tools/ozone/moderation/getRepos'
|
|
170
172
|
import * as ToolsOzoneModerationQueryEvents from './types/tools/ozone/moderation/queryEvents'
|
|
171
173
|
import * as ToolsOzoneModerationQueryStatuses from './types/tools/ozone/moderation/queryStatuses'
|
|
172
174
|
import * as ToolsOzoneModerationSearchRepos from './types/tools/ozone/moderation/searchRepos'
|
|
@@ -2262,6 +2264,17 @@ export class ToolsOzoneModerationNS {
|
|
|
2262
2264
|
return this._server.xrpc.method(nsid, cfg)
|
|
2263
2265
|
}
|
|
2264
2266
|
|
|
2267
|
+
getRecords<AV extends AuthVerifier>(
|
|
2268
|
+
cfg: ConfigOf<
|
|
2269
|
+
AV,
|
|
2270
|
+
ToolsOzoneModerationGetRecords.Handler<ExtractAuth<AV>>,
|
|
2271
|
+
ToolsOzoneModerationGetRecords.HandlerReqCtx<ExtractAuth<AV>>
|
|
2272
|
+
>,
|
|
2273
|
+
) {
|
|
2274
|
+
const nsid = 'tools.ozone.moderation.getRecords' // @ts-ignore
|
|
2275
|
+
return this._server.xrpc.method(nsid, cfg)
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2265
2278
|
getRepo<AV extends AuthVerifier>(
|
|
2266
2279
|
cfg: ConfigOf<
|
|
2267
2280
|
AV,
|
|
@@ -2273,6 +2286,17 @@ export class ToolsOzoneModerationNS {
|
|
|
2273
2286
|
return this._server.xrpc.method(nsid, cfg)
|
|
2274
2287
|
}
|
|
2275
2288
|
|
|
2289
|
+
getRepos<AV extends AuthVerifier>(
|
|
2290
|
+
cfg: ConfigOf<
|
|
2291
|
+
AV,
|
|
2292
|
+
ToolsOzoneModerationGetRepos.Handler<ExtractAuth<AV>>,
|
|
2293
|
+
ToolsOzoneModerationGetRepos.HandlerReqCtx<ExtractAuth<AV>>
|
|
2294
|
+
>,
|
|
2295
|
+
) {
|
|
2296
|
+
const nsid = 'tools.ozone.moderation.getRepos' // @ts-ignore
|
|
2297
|
+
return this._server.xrpc.method(nsid, cfg)
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2276
2300
|
queryEvents<AV extends AuthVerifier>(
|
|
2277
2301
|
cfg: ConfigOf<
|
|
2278
2302
|
AV,
|
package/src/lexicon/lexicons.ts
CHANGED
|
@@ -1686,6 +1686,11 @@ export const schemaDict = {
|
|
|
1686
1686
|
},
|
|
1687
1687
|
},
|
|
1688
1688
|
},
|
|
1689
|
+
errors: [
|
|
1690
|
+
{
|
|
1691
|
+
name: 'RecordNotFound',
|
|
1692
|
+
},
|
|
1693
|
+
],
|
|
1689
1694
|
},
|
|
1690
1695
|
},
|
|
1691
1696
|
},
|
|
@@ -11643,6 +11648,49 @@ export const schemaDict = {
|
|
|
11643
11648
|
},
|
|
11644
11649
|
},
|
|
11645
11650
|
},
|
|
11651
|
+
ToolsOzoneModerationGetRecords: {
|
|
11652
|
+
lexicon: 1,
|
|
11653
|
+
id: 'tools.ozone.moderation.getRecords',
|
|
11654
|
+
defs: {
|
|
11655
|
+
main: {
|
|
11656
|
+
type: 'query',
|
|
11657
|
+
description: 'Get details about some records.',
|
|
11658
|
+
parameters: {
|
|
11659
|
+
type: 'params',
|
|
11660
|
+
required: ['uris'],
|
|
11661
|
+
properties: {
|
|
11662
|
+
uris: {
|
|
11663
|
+
type: 'array',
|
|
11664
|
+
maxLength: 100,
|
|
11665
|
+
items: {
|
|
11666
|
+
type: 'string',
|
|
11667
|
+
format: 'at-uri',
|
|
11668
|
+
},
|
|
11669
|
+
},
|
|
11670
|
+
},
|
|
11671
|
+
},
|
|
11672
|
+
output: {
|
|
11673
|
+
encoding: 'application/json',
|
|
11674
|
+
schema: {
|
|
11675
|
+
type: 'object',
|
|
11676
|
+
required: ['records'],
|
|
11677
|
+
properties: {
|
|
11678
|
+
records: {
|
|
11679
|
+
type: 'array',
|
|
11680
|
+
items: {
|
|
11681
|
+
type: 'union',
|
|
11682
|
+
refs: [
|
|
11683
|
+
'lex:tools.ozone.moderation.defs#recordViewDetail',
|
|
11684
|
+
'lex:tools.ozone.moderation.defs#recordViewNotFound',
|
|
11685
|
+
],
|
|
11686
|
+
},
|
|
11687
|
+
},
|
|
11688
|
+
},
|
|
11689
|
+
},
|
|
11690
|
+
},
|
|
11691
|
+
},
|
|
11692
|
+
},
|
|
11693
|
+
},
|
|
11646
11694
|
ToolsOzoneModerationGetRepo: {
|
|
11647
11695
|
lexicon: 1,
|
|
11648
11696
|
id: 'tools.ozone.moderation.getRepo',
|
|
@@ -11675,6 +11723,49 @@ export const schemaDict = {
|
|
|
11675
11723
|
},
|
|
11676
11724
|
},
|
|
11677
11725
|
},
|
|
11726
|
+
ToolsOzoneModerationGetRepos: {
|
|
11727
|
+
lexicon: 1,
|
|
11728
|
+
id: 'tools.ozone.moderation.getRepos',
|
|
11729
|
+
defs: {
|
|
11730
|
+
main: {
|
|
11731
|
+
type: 'query',
|
|
11732
|
+
description: 'Get details about some repositories.',
|
|
11733
|
+
parameters: {
|
|
11734
|
+
type: 'params',
|
|
11735
|
+
required: ['dids'],
|
|
11736
|
+
properties: {
|
|
11737
|
+
dids: {
|
|
11738
|
+
type: 'array',
|
|
11739
|
+
maxLength: 100,
|
|
11740
|
+
items: {
|
|
11741
|
+
type: 'string',
|
|
11742
|
+
format: 'did',
|
|
11743
|
+
},
|
|
11744
|
+
},
|
|
11745
|
+
},
|
|
11746
|
+
},
|
|
11747
|
+
output: {
|
|
11748
|
+
encoding: 'application/json',
|
|
11749
|
+
schema: {
|
|
11750
|
+
type: 'object',
|
|
11751
|
+
required: ['repos'],
|
|
11752
|
+
properties: {
|
|
11753
|
+
repos: {
|
|
11754
|
+
type: 'array',
|
|
11755
|
+
items: {
|
|
11756
|
+
type: 'union',
|
|
11757
|
+
refs: [
|
|
11758
|
+
'lex:tools.ozone.moderation.defs#repoViewDetail',
|
|
11759
|
+
'lex:tools.ozone.moderation.defs#repoViewNotFound',
|
|
11760
|
+
],
|
|
11761
|
+
},
|
|
11762
|
+
},
|
|
11763
|
+
},
|
|
11764
|
+
},
|
|
11765
|
+
},
|
|
11766
|
+
},
|
|
11767
|
+
},
|
|
11768
|
+
},
|
|
11678
11769
|
ToolsOzoneModerationQueryEvents: {
|
|
11679
11770
|
lexicon: 1,
|
|
11680
11771
|
id: 'tools.ozone.moderation.queryEvents',
|
|
@@ -12491,7 +12582,9 @@ export const ids = {
|
|
|
12491
12582
|
ToolsOzoneModerationEmitEvent: 'tools.ozone.moderation.emitEvent',
|
|
12492
12583
|
ToolsOzoneModerationGetEvent: 'tools.ozone.moderation.getEvent',
|
|
12493
12584
|
ToolsOzoneModerationGetRecord: 'tools.ozone.moderation.getRecord',
|
|
12585
|
+
ToolsOzoneModerationGetRecords: 'tools.ozone.moderation.getRecords',
|
|
12494
12586
|
ToolsOzoneModerationGetRepo: 'tools.ozone.moderation.getRepo',
|
|
12587
|
+
ToolsOzoneModerationGetRepos: 'tools.ozone.moderation.getRepos',
|
|
12495
12588
|
ToolsOzoneModerationQueryEvents: 'tools.ozone.moderation.queryEvents',
|
|
12496
12589
|
ToolsOzoneModerationQueryStatuses: 'tools.ozone.moderation.queryStatuses',
|
|
12497
12590
|
ToolsOzoneModerationSearchRepos: 'tools.ozone.moderation.searchRepos',
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import express from 'express'
|
|
5
|
+
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
6
|
+
import { lexicons } from '../../../../lexicons'
|
|
7
|
+
import { isObj, hasProp } from '../../../../util'
|
|
8
|
+
import { CID } from 'multiformats/cid'
|
|
9
|
+
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
|
10
|
+
import * as ToolsOzoneModerationDefs from './defs'
|
|
11
|
+
|
|
12
|
+
export interface QueryParams {
|
|
13
|
+
uris: string[]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type InputSchema = undefined
|
|
17
|
+
|
|
18
|
+
export interface OutputSchema {
|
|
19
|
+
records: (
|
|
20
|
+
| ToolsOzoneModerationDefs.RecordViewDetail
|
|
21
|
+
| ToolsOzoneModerationDefs.RecordViewNotFound
|
|
22
|
+
| { $type: string; [k: string]: unknown }
|
|
23
|
+
)[]
|
|
24
|
+
[k: string]: unknown
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type HandlerInput = undefined
|
|
28
|
+
|
|
29
|
+
export interface HandlerSuccess {
|
|
30
|
+
encoding: 'application/json'
|
|
31
|
+
body: OutputSchema
|
|
32
|
+
headers?: { [key: string]: string }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface HandlerError {
|
|
36
|
+
status: number
|
|
37
|
+
message?: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
|
41
|
+
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
|
42
|
+
auth: HA
|
|
43
|
+
params: QueryParams
|
|
44
|
+
input: HandlerInput
|
|
45
|
+
req: express.Request
|
|
46
|
+
res: express.Response
|
|
47
|
+
}
|
|
48
|
+
export type Handler<HA extends HandlerAuth = never> = (
|
|
49
|
+
ctx: HandlerReqCtx<HA>,
|
|
50
|
+
) => Promise<HandlerOutput> | HandlerOutput
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import express from 'express'
|
|
5
|
+
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
6
|
+
import { lexicons } from '../../../../lexicons'
|
|
7
|
+
import { isObj, hasProp } from '../../../../util'
|
|
8
|
+
import { CID } from 'multiformats/cid'
|
|
9
|
+
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
|
10
|
+
import * as ToolsOzoneModerationDefs from './defs'
|
|
11
|
+
|
|
12
|
+
export interface QueryParams {
|
|
13
|
+
dids: string[]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type InputSchema = undefined
|
|
17
|
+
|
|
18
|
+
export interface OutputSchema {
|
|
19
|
+
repos: (
|
|
20
|
+
| ToolsOzoneModerationDefs.RepoViewDetail
|
|
21
|
+
| ToolsOzoneModerationDefs.RepoViewNotFound
|
|
22
|
+
| { $type: string; [k: string]: unknown }
|
|
23
|
+
)[]
|
|
24
|
+
[k: string]: unknown
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type HandlerInput = undefined
|
|
28
|
+
|
|
29
|
+
export interface HandlerSuccess {
|
|
30
|
+
encoding: 'application/json'
|
|
31
|
+
body: OutputSchema
|
|
32
|
+
headers?: { [key: string]: string }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface HandlerError {
|
|
36
|
+
status: number
|
|
37
|
+
message?: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
|
41
|
+
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
|
42
|
+
auth: HA
|
|
43
|
+
params: QueryParams
|
|
44
|
+
input: HandlerInput
|
|
45
|
+
req: express.Request
|
|
46
|
+
res: express.Response
|
|
47
|
+
}
|
|
48
|
+
export type Handler<HA extends HandlerAuth = never> = (
|
|
49
|
+
ctx: HandlerReqCtx<HA>,
|
|
50
|
+
) => Promise<HandlerOutput> | HandlerOutput
|
package/src/mod-service/views.ts
CHANGED
|
@@ -223,25 +223,33 @@ export class ModerationViews {
|
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
-
async
|
|
227
|
-
|
|
226
|
+
async repoDetails(
|
|
227
|
+
dids: string[],
|
|
228
228
|
labelers?: ParsedLabelers,
|
|
229
|
-
): Promise<
|
|
229
|
+
): Promise<Map<string, RepoView>> {
|
|
230
|
+
const results = new Map<string, RepoView>()
|
|
230
231
|
const [repos, localLabels, externalLabels] = await Promise.all([
|
|
231
|
-
this.repos(
|
|
232
|
-
this.labels(
|
|
233
|
-
this.getExternalLabels(
|
|
232
|
+
this.repos(dids),
|
|
233
|
+
this.labels(dids),
|
|
234
|
+
this.getExternalLabels(dids, labelers),
|
|
234
235
|
])
|
|
235
|
-
const repo = repos.get(did)
|
|
236
|
-
if (!repo) return
|
|
237
236
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
...
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
237
|
+
repos.forEach((repo, did) => {
|
|
238
|
+
const labels = [
|
|
239
|
+
...(localLabels.get(did) || []),
|
|
240
|
+
...(externalLabels.get(did) || []),
|
|
241
|
+
]
|
|
242
|
+
const repoView = {
|
|
243
|
+
...repo,
|
|
244
|
+
labels,
|
|
245
|
+
moderation: {
|
|
246
|
+
...repo.moderation,
|
|
247
|
+
},
|
|
248
|
+
}
|
|
249
|
+
results.set(did, repoView)
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
return results
|
|
245
253
|
}
|
|
246
254
|
|
|
247
255
|
async fetchRecords(
|
|
@@ -308,47 +316,59 @@ export class ModerationViews {
|
|
|
308
316
|
}, new Map<string, RecordView>())
|
|
309
317
|
}
|
|
310
318
|
|
|
311
|
-
async
|
|
312
|
-
|
|
319
|
+
async recordDetails(
|
|
320
|
+
subjects: RecordSubject[],
|
|
313
321
|
labelers?: ParsedLabelers,
|
|
314
|
-
): Promise<RecordViewDetail
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
322
|
+
): Promise<Map<string, RecordViewDetail>> {
|
|
323
|
+
const subjectUris = subjects.map((s) => s.uri)
|
|
324
|
+
const [records, subjectStatusesResult, localLabels, externalLabels] =
|
|
325
|
+
await Promise.all([
|
|
326
|
+
this.records(subjects),
|
|
327
|
+
this.getSubjectStatus(subjectUris),
|
|
328
|
+
this.labels(subjectUris),
|
|
329
|
+
this.getExternalLabels(subjectUris, labelers),
|
|
330
|
+
])
|
|
331
|
+
|
|
332
|
+
const results = new Map<string, RecordViewDetail>()
|
|
333
|
+
|
|
334
|
+
await Promise.all(
|
|
335
|
+
Array.from(records.entries()).map(async ([uri, record]) => {
|
|
336
|
+
const selfLabels = getSelfLabels({
|
|
337
|
+
uri: record.uri,
|
|
338
|
+
cid: record.cid,
|
|
339
|
+
record: record.value,
|
|
340
|
+
})
|
|
321
341
|
|
|
322
|
-
|
|
342
|
+
const status = subjectStatusesResult.get(uri)
|
|
343
|
+
const blobs = await this.blob(findBlobRefs(record.value))
|
|
323
344
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
345
|
+
results.set(uri, {
|
|
346
|
+
...record,
|
|
347
|
+
blobs,
|
|
348
|
+
moderation: {
|
|
349
|
+
...record.moderation,
|
|
350
|
+
subjectStatus: status
|
|
351
|
+
? this.formatSubjectStatus(status)
|
|
352
|
+
: undefined,
|
|
353
|
+
},
|
|
354
|
+
labels: [
|
|
355
|
+
...(localLabels.get(uri) || []),
|
|
356
|
+
...selfLabels,
|
|
357
|
+
...(externalLabels.get(uri) || []),
|
|
358
|
+
],
|
|
359
|
+
})
|
|
360
|
+
}),
|
|
361
|
+
)
|
|
335
362
|
|
|
336
|
-
return
|
|
337
|
-
...record,
|
|
338
|
-
blobs,
|
|
339
|
-
moderation: {
|
|
340
|
-
...record.moderation,
|
|
341
|
-
subjectStatus,
|
|
342
|
-
},
|
|
343
|
-
labels: [...labels, ...selfLabels, ...externalLabels],
|
|
344
|
-
}
|
|
363
|
+
return results
|
|
345
364
|
}
|
|
346
365
|
|
|
347
366
|
async getExternalLabels(
|
|
348
367
|
subjects: string[],
|
|
349
368
|
labelers?: ParsedLabelers,
|
|
350
|
-
): Promise<Label[]
|
|
351
|
-
|
|
369
|
+
): Promise<Map<string, Label[]>> {
|
|
370
|
+
const results = new Map<string, Label[]>()
|
|
371
|
+
if (!labelers?.dids.length && !labelers?.redact.size) return results
|
|
352
372
|
try {
|
|
353
373
|
const {
|
|
354
374
|
data: { labels },
|
|
@@ -356,13 +376,20 @@ export class ModerationViews {
|
|
|
356
376
|
uriPatterns: subjects,
|
|
357
377
|
sources: labelers.dids,
|
|
358
378
|
})
|
|
359
|
-
|
|
379
|
+
labels.forEach((label) => {
|
|
380
|
+
if (!results.has(label.uri)) {
|
|
381
|
+
results.set(label.uri, [label])
|
|
382
|
+
return
|
|
383
|
+
}
|
|
384
|
+
results.get(label.uri)?.push(label)
|
|
385
|
+
})
|
|
386
|
+
return results
|
|
360
387
|
} catch (err) {
|
|
361
388
|
httpLogger.error(
|
|
362
389
|
{ err, subjects, labelers },
|
|
363
390
|
'failed to resolve labels from appview',
|
|
364
391
|
)
|
|
365
|
-
return
|
|
392
|
+
return results
|
|
366
393
|
}
|
|
367
394
|
}
|
|
368
395
|
|
|
@@ -452,14 +479,28 @@ export class ModerationViews {
|
|
|
452
479
|
})
|
|
453
480
|
}
|
|
454
481
|
|
|
455
|
-
async labels(
|
|
482
|
+
async labels(
|
|
483
|
+
subjects: string[],
|
|
484
|
+
includeNeg?: boolean,
|
|
485
|
+
): Promise<Map<string, Label[]>> {
|
|
486
|
+
const labels = new Map<string, Label[]>()
|
|
456
487
|
const res = await this.db.db
|
|
457
488
|
.selectFrom('label')
|
|
458
|
-
.where('label.uri', '
|
|
489
|
+
.where('label.uri', 'in', subjects)
|
|
459
490
|
.if(!includeNeg, (qb) => qb.where('neg', '=', false))
|
|
460
491
|
.selectAll()
|
|
461
492
|
.execute()
|
|
462
|
-
|
|
493
|
+
|
|
494
|
+
await Promise.all(
|
|
495
|
+
res.map(async (labelRow) => {
|
|
496
|
+
const signedLabel = await this.formatLabelAndEnsureSig(labelRow)
|
|
497
|
+
if (!labels.has(labelRow.uri)) {
|
|
498
|
+
labels.set(labelRow.uri, [])
|
|
499
|
+
}
|
|
500
|
+
labels.get(labelRow.uri)?.push(signedLabel)
|
|
501
|
+
}),
|
|
502
|
+
)
|
|
503
|
+
return labels
|
|
463
504
|
}
|
|
464
505
|
|
|
465
506
|
async formatLabelAndEnsureSig(row: LabelRow) {
|