-
Notifications
You must be signed in to change notification settings - Fork 115
/
deleteVideoAssetsAsModerator.ts
93 lines (82 loc) · 3.15 KB
/
deleteVideoAssetsAsModerator.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { createType } from '@joystream/types'
import { flags } from '@oclif/command'
import { formatBalance } from '@polkadot/util'
import chalk from 'chalk'
import ContentDirectoryCommandBase from '../../base/ContentDirectoryCommandBase'
import ExitCodes from '../../ExitCodes'
import BN from 'bn.js'
export default class DeleteVideoAssetsAsModeratorCommand extends ContentDirectoryCommandBase {
static description = 'Delete the video assets.'
protected requiresQueryNode = true
static flags = {
videoId: flags.integer({
char: 'v',
required: true,
description: 'ID of the Video',
}),
assetIds: flags.string({
char: 'a',
description: `List of data object IDs to delete`,
required: true,
multiple: true,
}),
rationale: flags.string({
char: 'r',
required: true,
description: 'Reason for removing the video assets by moderator',
}),
context: ContentDirectoryCommandBase.moderationActionContextFlag,
...ContentDirectoryCommandBase.flags,
}
async getDataObjectsInfo(videoId: number, assetIds: string[]): Promise<[string, BN][]> {
const dataObjects = await this.getQNApi().dataObjectsByVideoId(videoId.toString())
return assetIds.map((id) => {
const dataObject = dataObjects.find((o) => o.id === id)
if (dataObject) {
return [dataObject.id, new BN(dataObject.stateBloatBond)]
}
this.error(`Data object ${id} is not associated with video ${videoId}`, {
exit: ExitCodes.InvalidInput,
})
})
}
async run(): Promise<void> {
const { videoId, assetIds, rationale, context } = this.parse(DeleteVideoAssetsAsModeratorCommand).flags
// Context
const [actor, address] = await this.getModerationActionActor(context)
// ensure video exists
const { inChannel, nftStatus } = await this.getApi().videoById(videoId)
const { privilegeLevel } = await this.getApi().channelById(inChannel)
// Ensure moderator has required permission
if (
!(await this.isModeratorWithRequiredPermission(actor, privilegeLevel, { DeleteVideoAssets: nftStatus.isSome }))
) {
this.error(
`Only content lead or curator with DeleteVideoAssets(${nftStatus.isSome}) permission can delete video ${videoId} assets!`,
{
exit: ExitCodes.AccessDenied,
}
)
}
const dataObjectsInfo = await this.getDataObjectsInfo(videoId, assetIds)
const stateBloatBond = dataObjectsInfo.reduce((sum, [, bloatBond]) => sum.add(bloatBond), new BN(0))
this.log(
`Data objects state bloat bond of ${chalk.cyanBright(
formatBalance(stateBloatBond)
)} will be repaid with accordance to the bloat bond policy.`
)
await this.requireConfirmation(
`Are you sure you want to remove assets ${assetIds} associated with video ${chalk.magentaBright(videoId)}?`
)
await this.sendAndFollowNamedTx(await this.getDecodedPair(address), 'content', 'deleteVideoAssetsAsModerator', [
actor,
videoId,
await this.getStorageBucketsNumWitness(inChannel),
createType(
'BTreeSet<u64>',
dataObjectsInfo.map(([id]) => Number(id))
),
rationale,
])
}
}