@chainpatrol/cli 0.10.0 → 0.12.0
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 +64 -0
- package/README.md +2 -0
- package/dist/{breakdown-63FAOVL7.js → breakdown-KCTKQNDY.js} +1 -1
- package/dist/{check-7QDINQPT.js → check-P5JJJNEX.js} +1 -1
- package/dist/{chunk-BJISZ3CY.js → chunk-DJVB73FL.js} +1 -1
- package/dist/{chunk-Z76CUWSS.js → chunk-NQT77IB7.js} +62 -9
- package/dist/chunk-OSRFCVBT.js +382 -0
- package/dist/{chunk-R2DZGMGT.js → chunk-W42ITB5J.js} +1 -1
- package/dist/cli.js +486 -65
- package/dist/{completions-D6SOLU2D.js → completions-6C6KG5DH.js} +1 -1
- package/dist/{configs-update-2IOSKZH5.js → configs-update-3ZVXGADV.js} +1 -1
- package/dist/{create-EWS3SFCH.js → create-DFH2G7RH.js} +1 -1
- package/dist/{drift-Q3VG3XG3.js → drift-T74V2C3J.js} +1 -1
- package/dist/{found-22B7RZT5.js → found-EVXJZGYX.js} +1 -1
- package/dist/{healthcheck-C3AIMUJT.js → healthcheck-HZYEIIOR.js} +1 -1
- package/dist/{list-DNRWKM5O.js → list-23QQYAV5.js} +1 -1
- package/dist/list-EIVPGMWJ.js +82 -0
- package/dist/list-I7SBGA52.js +50 -0
- package/dist/{list-IA4CSOIY.js → list-IYJBKE2F.js} +1 -1
- package/dist/list-PBAXQSL5.js +85 -0
- package/dist/list-QUFY4IP7.js +146 -0
- package/dist/list-WJQT2XLE.js +143 -0
- package/dist/{list-HFWSMLGJ.js → list-WX5G3IOF.js} +2 -2
- package/dist/list-YCT6DYDI.js +89 -0
- package/dist/{list-SDBLGBVW.js → list-YRJPN4PI.js} +1 -1
- package/dist/{list-AYHDFSQG.js → list-ZFPML3ZR.js} +47 -3
- package/dist/{list-json-CEPGVUGF.js → list-json-T2Z7NV7G.js} +1 -1
- package/dist/organization-IIIOSTHF.js +75 -0
- package/dist/{run-WJGHJPXN.js → run-BHEXWBAS.js} +2 -2
- package/dist/{run-AQMJRFGL.js → run-CJGN6TX4.js} +1 -1
- package/dist/{run-YTWNQD5X.js → run-MSO6IXEV.js} +1 -1
- package/dist/search-WPSKQGUS.js +71 -0
- package/dist/{setup-skill-BLJLRCXL.js → setup-skill-FA4STSGA.js} +2 -2
- package/dist/{snapshot-C5MZWJTW.js → snapshot-ZWAHEG64.js} +1 -1
- package/dist/{summary-NQDZQEOD.js → summary-Y2LG6UJM.js} +1 -1
- package/dist/{validate-5DVPSXJP.js → validate-SM5DD7I2.js} +1 -1
- package/dist/whoami-DH5HVLFN.js +69 -0
- package/package.json +1 -1
- package/dist/chunk-RIKR2WFT.js +0 -174
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CliExitError,
|
|
3
|
+
ExitCode
|
|
4
|
+
} from "./chunk-E2LAMILJ.js";
|
|
5
|
+
import {
|
|
6
|
+
printOutput,
|
|
7
|
+
toCsvRows
|
|
8
|
+
} from "./chunk-VFT3TD3E.js";
|
|
9
|
+
import {
|
|
10
|
+
createApiClient
|
|
11
|
+
} from "./chunk-OSRFCVBT.js";
|
|
12
|
+
import "./chunk-EGWK6SRQ.js";
|
|
13
|
+
import "./chunk-TFCNKBRC.js";
|
|
14
|
+
import "./chunk-U73SABXK.js";
|
|
15
|
+
|
|
16
|
+
// src/commands/orgs/assets/list.ts
|
|
17
|
+
function toRow(asset) {
|
|
18
|
+
return {
|
|
19
|
+
id: asset.id,
|
|
20
|
+
content: asset.content,
|
|
21
|
+
type: asset.type,
|
|
22
|
+
status: asset.status,
|
|
23
|
+
name: asset.name ?? "",
|
|
24
|
+
group: asset.group?.name ?? "",
|
|
25
|
+
groupId: asset.group?.id ?? "",
|
|
26
|
+
createdAt: asset.createdAt,
|
|
27
|
+
updatedAt: asset.updatedAt
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async function runOrgsAssetsList(options) {
|
|
31
|
+
const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
|
|
32
|
+
const perPage = options.perPage;
|
|
33
|
+
if (perPage !== void 0 && (perPage < 1 || perPage > 1e3)) {
|
|
34
|
+
throw new CliExitError(
|
|
35
|
+
"orgs assets list requires --per-page between 1 and 1000.",
|
|
36
|
+
ExitCode.USAGE
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
const client = options.apiClient ?? createApiClient();
|
|
40
|
+
const input = {
|
|
41
|
+
type: options.type ? options.type.toUpperCase() : void 0,
|
|
42
|
+
groupId: options.groupId,
|
|
43
|
+
query: options.query,
|
|
44
|
+
perPage,
|
|
45
|
+
nextPage: options.nextPage
|
|
46
|
+
};
|
|
47
|
+
const result = await client.listOrganizationAssets(input);
|
|
48
|
+
const rows = result.assets.map(toRow);
|
|
49
|
+
printOutput({
|
|
50
|
+
outputFormat,
|
|
51
|
+
json: result,
|
|
52
|
+
markdown: [
|
|
53
|
+
"# Organization assets",
|
|
54
|
+
"",
|
|
55
|
+
`- Returned: ${result.assets.length}`,
|
|
56
|
+
`- Next page cursor: ${result.next_page ?? "none"}`,
|
|
57
|
+
"",
|
|
58
|
+
...rows.map(
|
|
59
|
+
(row) => `- #${row.id} [${row.status}] ${row.content} (${row.type}) group=${row.group || "-"} updated=${row.updatedAt}`
|
|
60
|
+
)
|
|
61
|
+
].join("\n"),
|
|
62
|
+
csv: toCsvRows(rows),
|
|
63
|
+
human: () => {
|
|
64
|
+
if (result.assets.length === 0) {
|
|
65
|
+
console.log("No organization assets found.");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
console.log(`Organization assets \u2014 returned ${result.assets.length}`);
|
|
69
|
+
for (const row of rows) {
|
|
70
|
+
console.log(
|
|
71
|
+
`#${row.id} [${row.status}] ${row.content} (${row.type}) group=${row.group || "-"} name=${row.name || "-"} updated=${row.updatedAt}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (result.next_page) {
|
|
75
|
+
console.log(`Next page cursor: ${result.next_page}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
runOrgsAssetsList
|
|
82
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
printOutput,
|
|
3
|
+
toCsvRows
|
|
4
|
+
} from "./chunk-VFT3TD3E.js";
|
|
5
|
+
import {
|
|
6
|
+
createApiClient
|
|
7
|
+
} from "./chunk-OSRFCVBT.js";
|
|
8
|
+
import "./chunk-EGWK6SRQ.js";
|
|
9
|
+
import "./chunk-TFCNKBRC.js";
|
|
10
|
+
import "./chunk-U73SABXK.js";
|
|
11
|
+
|
|
12
|
+
// src/commands/orgs/asset-groups/list.ts
|
|
13
|
+
function toRow(group) {
|
|
14
|
+
return {
|
|
15
|
+
id: group.id,
|
|
16
|
+
name: group.name,
|
|
17
|
+
assetCount: group.assetCount
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
async function runOrgsAssetGroupsList(options) {
|
|
21
|
+
const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
|
|
22
|
+
const client = options.apiClient ?? createApiClient();
|
|
23
|
+
const result = await client.listOrganizationAssetGroups();
|
|
24
|
+
const rows = result.groups.map(toRow);
|
|
25
|
+
printOutput({
|
|
26
|
+
outputFormat,
|
|
27
|
+
json: result,
|
|
28
|
+
markdown: [
|
|
29
|
+
"# Organization asset groups",
|
|
30
|
+
"",
|
|
31
|
+
`- Returned: ${result.groups.length}`,
|
|
32
|
+
"",
|
|
33
|
+
...rows.map((row) => `- #${row.id} ${row.name} (assets=${row.assetCount})`)
|
|
34
|
+
].join("\n"),
|
|
35
|
+
csv: toCsvRows(rows),
|
|
36
|
+
human: () => {
|
|
37
|
+
if (result.groups.length === 0) {
|
|
38
|
+
console.log("No asset groups found.");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
console.log(`Organization asset groups \u2014 returned ${result.groups.length}`);
|
|
42
|
+
for (const row of rows) {
|
|
43
|
+
console.log(`#${row.id} ${row.name} (assets=${row.assetCount})`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
runOrgsAssetGroupsList
|
|
50
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CliExitError,
|
|
3
|
+
ExitCode
|
|
4
|
+
} from "./chunk-E2LAMILJ.js";
|
|
5
|
+
import {
|
|
6
|
+
printOutput,
|
|
7
|
+
toCsvRows
|
|
8
|
+
} from "./chunk-VFT3TD3E.js";
|
|
9
|
+
import {
|
|
10
|
+
createApiClient
|
|
11
|
+
} from "./chunk-OSRFCVBT.js";
|
|
12
|
+
import "./chunk-EGWK6SRQ.js";
|
|
13
|
+
import "./chunk-TFCNKBRC.js";
|
|
14
|
+
import "./chunk-U73SABXK.js";
|
|
15
|
+
|
|
16
|
+
// src/commands/asset/list.ts
|
|
17
|
+
function toRow(asset) {
|
|
18
|
+
return {
|
|
19
|
+
content: asset.content,
|
|
20
|
+
type: asset.type,
|
|
21
|
+
status: asset.status,
|
|
22
|
+
watchStatus: asset.watchStatus,
|
|
23
|
+
updatedAt: asset.updatedAt
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async function runAssetList(options) {
|
|
27
|
+
const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
|
|
28
|
+
if (!options.type) {
|
|
29
|
+
throw new CliExitError(
|
|
30
|
+
"asset list requires --asset-type <URL|ADDRESS|TWITTER|...>. Pass a single value.",
|
|
31
|
+
ExitCode.USAGE
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
const perPage = options.perPage;
|
|
35
|
+
if (perPage !== void 0 && (perPage < 1 || perPage > 1e4)) {
|
|
36
|
+
throw new CliExitError(
|
|
37
|
+
"asset list requires --per-page between 1 and 10000.",
|
|
38
|
+
ExitCode.USAGE
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
const client = options.apiClient ?? createApiClient();
|
|
42
|
+
const input = {
|
|
43
|
+
type: options.type.toUpperCase(),
|
|
44
|
+
status: options.status ? options.status.toUpperCase() : void 0,
|
|
45
|
+
startDate: options.from,
|
|
46
|
+
endDate: options.to,
|
|
47
|
+
perPage,
|
|
48
|
+
nextPage: options.nextPage
|
|
49
|
+
};
|
|
50
|
+
const result = await client.listAssets(input);
|
|
51
|
+
const rows = result.assets.map(toRow);
|
|
52
|
+
printOutput({
|
|
53
|
+
outputFormat,
|
|
54
|
+
json: result,
|
|
55
|
+
markdown: [
|
|
56
|
+
`# Assets (${input.type})`,
|
|
57
|
+
"",
|
|
58
|
+
`- Returned: ${result.assets.length}`,
|
|
59
|
+
`- Next page cursor: ${result.next_page ?? "none"}`,
|
|
60
|
+
"",
|
|
61
|
+
...rows.map(
|
|
62
|
+
(row) => `- [${row.status}] ${row.content} (${row.type}) watch=${row.watchStatus} updated=${row.updatedAt}`
|
|
63
|
+
)
|
|
64
|
+
].join("\n"),
|
|
65
|
+
csv: toCsvRows(rows),
|
|
66
|
+
human: () => {
|
|
67
|
+
if (result.assets.length === 0) {
|
|
68
|
+
console.log("No assets found.");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
console.log(`Assets (${input.type}) \u2014 returned ${result.assets.length}`);
|
|
72
|
+
for (const row of rows) {
|
|
73
|
+
console.log(
|
|
74
|
+
`[${row.status}] ${row.content} (${row.type}) watch=${row.watchStatus} updated=${row.updatedAt}`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
if (result.next_page) {
|
|
78
|
+
console.log(`Next page cursor: ${result.next_page}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
export {
|
|
84
|
+
runAssetList
|
|
85
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CliExitError,
|
|
3
|
+
ExitCode
|
|
4
|
+
} from "./chunk-E2LAMILJ.js";
|
|
5
|
+
import {
|
|
6
|
+
printOutput,
|
|
7
|
+
toCsvRows
|
|
8
|
+
} from "./chunk-VFT3TD3E.js";
|
|
9
|
+
import {
|
|
10
|
+
DETECTION_CONFIDENCE_LEVELS,
|
|
11
|
+
DETECTION_REPORTED_FILTERS,
|
|
12
|
+
LIVENESS_FILTER_VALUES,
|
|
13
|
+
WATCHLIST_FILTER_VALUES,
|
|
14
|
+
createApiClient
|
|
15
|
+
} from "./chunk-OSRFCVBT.js";
|
|
16
|
+
import "./chunk-EGWK6SRQ.js";
|
|
17
|
+
import "./chunk-TFCNKBRC.js";
|
|
18
|
+
import "./chunk-U73SABXK.js";
|
|
19
|
+
|
|
20
|
+
// src/commands/detections/list.ts
|
|
21
|
+
var CONFIDENCE_SET = new Set(DETECTION_CONFIDENCE_LEVELS);
|
|
22
|
+
var REPORTED_SET = new Set(DETECTION_REPORTED_FILTERS);
|
|
23
|
+
var LIVENESS_SET = new Set(LIVENESS_FILTER_VALUES);
|
|
24
|
+
var WATCHLIST_SET = new Set(WATCHLIST_FILTER_VALUES);
|
|
25
|
+
function validateEnumList(values, validSet, flagName, transform = (v) => v) {
|
|
26
|
+
if (!values || values.length === 0) return void 0;
|
|
27
|
+
const normalized = values.map(transform);
|
|
28
|
+
const invalid = normalized.filter((value) => !validSet.has(value));
|
|
29
|
+
if (invalid.length > 0) {
|
|
30
|
+
throw new CliExitError(
|
|
31
|
+
`Invalid --${flagName} value(s): ${invalid.join(", ")}. Valid: ${Array.from(
|
|
32
|
+
validSet
|
|
33
|
+
).join(", ")}`,
|
|
34
|
+
ExitCode.USAGE
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return normalized;
|
|
38
|
+
}
|
|
39
|
+
function toRow(detection) {
|
|
40
|
+
return {
|
|
41
|
+
id: detection.id,
|
|
42
|
+
source: detection.source,
|
|
43
|
+
confidence: detection.confidence,
|
|
44
|
+
reportStatus: detection.reportStatus,
|
|
45
|
+
threatContent: detection.threatContent,
|
|
46
|
+
assetContent: detection.asset.content,
|
|
47
|
+
assetType: detection.asset.type,
|
|
48
|
+
assetStatus: detection.asset.status,
|
|
49
|
+
createdAt: detection.createdAt
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async function runDetectionsList(options) {
|
|
53
|
+
const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
|
|
54
|
+
const limit = options.limit;
|
|
55
|
+
if (limit !== void 0 && (limit < 1 || limit > 100)) {
|
|
56
|
+
throw new CliExitError(
|
|
57
|
+
"detections list requires --limit between 1 and 100.",
|
|
58
|
+
ExitCode.USAGE
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
const confidence = validateEnumList(
|
|
62
|
+
options.confidence,
|
|
63
|
+
CONFIDENCE_SET,
|
|
64
|
+
"confidence",
|
|
65
|
+
(v) => v.toLowerCase()
|
|
66
|
+
);
|
|
67
|
+
const reported = validateEnumList(
|
|
68
|
+
options.reported,
|
|
69
|
+
REPORTED_SET,
|
|
70
|
+
"reported",
|
|
71
|
+
(v) => v.toLowerCase()
|
|
72
|
+
);
|
|
73
|
+
const liveness = validateEnumList(
|
|
74
|
+
options.liveness,
|
|
75
|
+
LIVENESS_SET,
|
|
76
|
+
"liveness",
|
|
77
|
+
(v) => v.toUpperCase()
|
|
78
|
+
);
|
|
79
|
+
const watchlist = validateEnumList(
|
|
80
|
+
options.watchlist,
|
|
81
|
+
WATCHLIST_SET,
|
|
82
|
+
"watchlist",
|
|
83
|
+
(v) => v.toUpperCase()
|
|
84
|
+
);
|
|
85
|
+
const countryCodes = options.countryCodes?.length ? options.countryCodes.map((code) => code.toUpperCase()) : void 0;
|
|
86
|
+
if (countryCodes?.some((code) => code.length !== 2)) {
|
|
87
|
+
throw new CliExitError(
|
|
88
|
+
"--country-code values must be 2-letter ISO country codes (e.g. US, GB).",
|
|
89
|
+
ExitCode.USAGE
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
const client = options.apiClient ?? createApiClient();
|
|
93
|
+
const input = {
|
|
94
|
+
slug: options.org,
|
|
95
|
+
cursor: options.cursor,
|
|
96
|
+
limit,
|
|
97
|
+
query: options.query,
|
|
98
|
+
startDate: options.from,
|
|
99
|
+
endDate: options.to,
|
|
100
|
+
sources: options.sources?.length ? options.sources : void 0,
|
|
101
|
+
confidence,
|
|
102
|
+
assetStatus: options.assetStatus?.length ? options.assetStatus.map((s) => s.toUpperCase()) : void 0,
|
|
103
|
+
assetType: options.assetType?.length ? options.assetType.map((t) => t.toUpperCase()) : void 0,
|
|
104
|
+
brandIds: options.brandIds?.length ? options.brandIds : void 0,
|
|
105
|
+
liveness,
|
|
106
|
+
watchlist,
|
|
107
|
+
reported,
|
|
108
|
+
countryCodes,
|
|
109
|
+
onlyDeleted: options.onlyDeleted
|
|
110
|
+
};
|
|
111
|
+
const result = await client.listDetections(input);
|
|
112
|
+
const rows = result.detections.map(toRow);
|
|
113
|
+
printOutput({
|
|
114
|
+
outputFormat,
|
|
115
|
+
json: result,
|
|
116
|
+
markdown: [
|
|
117
|
+
`# Detections (${options.org})`,
|
|
118
|
+
"",
|
|
119
|
+
`- Returned: ${result.detections.length}`,
|
|
120
|
+
`- Next cursor: ${result.nextCursor ?? "none"}`,
|
|
121
|
+
"",
|
|
122
|
+
...rows.map(
|
|
123
|
+
(row) => `- #${row.id} [${row.confidence}] ${row.source} \u2192 ${row.assetContent} (${row.assetType}) ${row.assetStatus} reported=${row.reportStatus} created=${row.createdAt}`
|
|
124
|
+
)
|
|
125
|
+
].join("\n"),
|
|
126
|
+
csv: toCsvRows(rows),
|
|
127
|
+
human: () => {
|
|
128
|
+
if (result.detections.length === 0) {
|
|
129
|
+
console.log("No detections found.");
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
console.log(`Detections for ${options.org} \u2014 returned ${result.detections.length}`);
|
|
133
|
+
for (const row of rows) {
|
|
134
|
+
console.log(
|
|
135
|
+
`#${row.id} [${row.confidence}] ${row.source} \u2192 ${row.assetContent} (${row.assetType}/${row.assetStatus}) ${row.reportStatus} ${row.createdAt}`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
if (result.nextCursor !== void 0) {
|
|
139
|
+
console.log(`Next cursor: ${result.nextCursor}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
export {
|
|
145
|
+
runDetectionsList
|
|
146
|
+
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CliExitError,
|
|
3
|
+
ExitCode
|
|
4
|
+
} from "./chunk-E2LAMILJ.js";
|
|
5
|
+
import {
|
|
6
|
+
printOutput,
|
|
7
|
+
toCsvRows
|
|
8
|
+
} from "./chunk-VFT3TD3E.js";
|
|
9
|
+
import {
|
|
10
|
+
LIVENESS_STATUSES,
|
|
11
|
+
TAKEDOWN_SORT_KEYS,
|
|
12
|
+
TAKEDOWN_STATUSES,
|
|
13
|
+
createApiClient
|
|
14
|
+
} from "./chunk-OSRFCVBT.js";
|
|
15
|
+
import "./chunk-EGWK6SRQ.js";
|
|
16
|
+
import "./chunk-TFCNKBRC.js";
|
|
17
|
+
import "./chunk-U73SABXK.js";
|
|
18
|
+
|
|
19
|
+
// src/commands/takedowns/list.ts
|
|
20
|
+
var TAKEDOWN_STATUS_SET = new Set(TAKEDOWN_STATUSES);
|
|
21
|
+
var LIVENESS_STATUS_SET = new Set(LIVENESS_STATUSES);
|
|
22
|
+
var SORT_KEY_SET = new Set(TAKEDOWN_SORT_KEYS);
|
|
23
|
+
function toRow(takedown) {
|
|
24
|
+
return {
|
|
25
|
+
id: takedown.id,
|
|
26
|
+
status: takedown.status,
|
|
27
|
+
asset: takedown.asset.content,
|
|
28
|
+
assetType: takedown.asset.type,
|
|
29
|
+
livenessStatus: takedown.asset.livenessStatus ?? "",
|
|
30
|
+
brand: takedown.brand?.name ?? "",
|
|
31
|
+
assignee: takedown.assignee?.fullName ?? "",
|
|
32
|
+
createdAt: takedown.createdAt,
|
|
33
|
+
updatedAt: takedown.updatedAt
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function validateEnumValues(values, validSet, flagName) {
|
|
37
|
+
if (!values || values.length === 0) return void 0;
|
|
38
|
+
const invalid = values.filter((value) => !validSet.has(value));
|
|
39
|
+
if (invalid.length > 0) {
|
|
40
|
+
throw new CliExitError(
|
|
41
|
+
`Invalid value(s) for --${flagName}: ${invalid.join(", ")}. Valid: ${Array.from(
|
|
42
|
+
validSet
|
|
43
|
+
).join(", ")}`,
|
|
44
|
+
ExitCode.USAGE
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
return values;
|
|
48
|
+
}
|
|
49
|
+
async function runTakedownsList(options) {
|
|
50
|
+
const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
|
|
51
|
+
const perPage = options.perPage ?? 10;
|
|
52
|
+
if (perPage < 1 || perPage > 100) {
|
|
53
|
+
throw new CliExitError(
|
|
54
|
+
"takedowns list requires --per-page between 1 and 100.",
|
|
55
|
+
ExitCode.USAGE
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
const sortDirection = options.sortDirection ?? "desc";
|
|
59
|
+
if (sortDirection !== "asc" && sortDirection !== "desc") {
|
|
60
|
+
throw new CliExitError(
|
|
61
|
+
`Invalid --sort-direction '${sortDirection}'. Use 'asc' or 'desc'.`,
|
|
62
|
+
ExitCode.USAGE
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (options.sortBy && !SORT_KEY_SET.has(options.sortBy)) {
|
|
66
|
+
throw new CliExitError(
|
|
67
|
+
`Invalid --sort-by '${options.sortBy}'. Valid: ${TAKEDOWN_SORT_KEYS.join(", ")}`,
|
|
68
|
+
ExitCode.USAGE
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const assetType = options.assetType?.length ? options.assetType : void 0;
|
|
72
|
+
const takedownStatus = validateEnumValues(
|
|
73
|
+
options.takedownStatus,
|
|
74
|
+
TAKEDOWN_STATUS_SET,
|
|
75
|
+
"takedown-status"
|
|
76
|
+
);
|
|
77
|
+
const livenessStatus = validateEnumValues(
|
|
78
|
+
options.livenessStatus,
|
|
79
|
+
LIVENESS_STATUS_SET,
|
|
80
|
+
"liveness-status"
|
|
81
|
+
);
|
|
82
|
+
const client = options.apiClient ?? createApiClient();
|
|
83
|
+
const input = {
|
|
84
|
+
organizationSlug: options.org,
|
|
85
|
+
query: options.query,
|
|
86
|
+
startDate: options.from,
|
|
87
|
+
endDate: options.to,
|
|
88
|
+
assetType,
|
|
89
|
+
takedownStatus,
|
|
90
|
+
livenessStatus,
|
|
91
|
+
brandIds: options.brandIds?.length ? options.brandIds : void 0,
|
|
92
|
+
assigneeIds: options.assigneeIds?.length ? options.assigneeIds : void 0,
|
|
93
|
+
startedAtStartDate: options.startedFrom,
|
|
94
|
+
startedAtEndDate: options.startedTo,
|
|
95
|
+
hideAutomatedTakedowns: options.hideAutomatedTakedowns,
|
|
96
|
+
hideAutomatedLivenessChecks: options.hideAutomatedLivenessChecks,
|
|
97
|
+
perPage,
|
|
98
|
+
nextPage: options.nextPage,
|
|
99
|
+
sorting: options.sortBy ? [
|
|
100
|
+
{
|
|
101
|
+
key: options.sortBy,
|
|
102
|
+
direction: sortDirection
|
|
103
|
+
}
|
|
104
|
+
] : void 0
|
|
105
|
+
};
|
|
106
|
+
const result = await client.listTakedowns(input);
|
|
107
|
+
const rows = result.takedowns.map(toRow);
|
|
108
|
+
printOutput({
|
|
109
|
+
outputFormat,
|
|
110
|
+
json: result,
|
|
111
|
+
markdown: [
|
|
112
|
+
`# Takedowns${options.org ? ` (${options.org})` : ""}`,
|
|
113
|
+
"",
|
|
114
|
+
`- Returned: ${result.takedowns.length}`,
|
|
115
|
+
`- Next page cursor: ${result.next_page ?? "none"}`,
|
|
116
|
+
"",
|
|
117
|
+
...rows.map(
|
|
118
|
+
(row) => `- #${row.id} [${row.status}] ${row.asset} (${row.assetType}) brand=${row.brand || "-"} updated=${row.updatedAt}`
|
|
119
|
+
)
|
|
120
|
+
].join("\n"),
|
|
121
|
+
csv: toCsvRows(rows),
|
|
122
|
+
human: () => {
|
|
123
|
+
if (result.takedowns.length === 0) {
|
|
124
|
+
console.log("No takedowns found.");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
console.log(
|
|
128
|
+
`Takedowns${options.org ? ` for ${options.org}` : ""} (returned ${result.takedowns.length})`
|
|
129
|
+
);
|
|
130
|
+
for (const row of rows) {
|
|
131
|
+
console.log(
|
|
132
|
+
`#${row.id} [${row.status}] ${row.asset} (${row.assetType}) brand=${row.brand || "-"} assignee=${row.assignee || "-"} updated=${row.updatedAt}`
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
if (result.next_page) {
|
|
136
|
+
console.log(`Next page cursor: ${result.next_page}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
export {
|
|
142
|
+
runTakedownsList
|
|
143
|
+
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PRESETS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-DJVB73FL.js";
|
|
4
4
|
import "./chunk-E2LAMILJ.js";
|
|
5
5
|
import {
|
|
6
6
|
printOutput,
|
|
7
7
|
toCsvRows
|
|
8
8
|
} from "./chunk-VFT3TD3E.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-OSRFCVBT.js";
|
|
10
10
|
import "./chunk-EGWK6SRQ.js";
|
|
11
11
|
import "./chunk-TFCNKBRC.js";
|
|
12
12
|
import "./chunk-U73SABXK.js";
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CliExitError,
|
|
3
|
+
ExitCode
|
|
4
|
+
} from "./chunk-E2LAMILJ.js";
|
|
5
|
+
import {
|
|
6
|
+
printOutput,
|
|
7
|
+
toCsvRows
|
|
8
|
+
} from "./chunk-VFT3TD3E.js";
|
|
9
|
+
import {
|
|
10
|
+
createApiClient
|
|
11
|
+
} from "./chunk-OSRFCVBT.js";
|
|
12
|
+
import "./chunk-EGWK6SRQ.js";
|
|
13
|
+
import "./chunk-TFCNKBRC.js";
|
|
14
|
+
import "./chunk-U73SABXK.js";
|
|
15
|
+
|
|
16
|
+
// src/commands/threats/list.ts
|
|
17
|
+
function toRow(threat) {
|
|
18
|
+
return {
|
|
19
|
+
id: threat.id,
|
|
20
|
+
content: threat.content,
|
|
21
|
+
type: threat.type,
|
|
22
|
+
blockedAt: threat.blockedAt
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
async function runThreatsList(options) {
|
|
26
|
+
const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
|
|
27
|
+
const perPage = options.perPage;
|
|
28
|
+
if (perPage !== void 0 && (perPage < 1 || perPage > 100)) {
|
|
29
|
+
throw new CliExitError(
|
|
30
|
+
"threats list requires --per-page between 1 and 100.",
|
|
31
|
+
ExitCode.USAGE
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
const sortDirection = options.sortDirection;
|
|
35
|
+
if (sortDirection && sortDirection !== "asc" && sortDirection !== "desc") {
|
|
36
|
+
throw new CliExitError(
|
|
37
|
+
`Invalid --sort-direction '${sortDirection}'. Use 'asc' or 'desc'.`,
|
|
38
|
+
ExitCode.USAGE
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
const client = options.apiClient ?? createApiClient();
|
|
42
|
+
const input = {
|
|
43
|
+
query: options.query,
|
|
44
|
+
startDate: options.from,
|
|
45
|
+
endDate: options.to,
|
|
46
|
+
assetType: options.assetType?.length ? options.assetType.map((t) => t.toUpperCase()) : void 0,
|
|
47
|
+
sorting: options.sortBy ? [
|
|
48
|
+
{
|
|
49
|
+
key: options.sortBy,
|
|
50
|
+
direction: sortDirection ?? "desc"
|
|
51
|
+
}
|
|
52
|
+
] : void 0,
|
|
53
|
+
perPage,
|
|
54
|
+
nextPage: options.nextPage
|
|
55
|
+
};
|
|
56
|
+
const result = await client.listThreats(input);
|
|
57
|
+
const rows = result.threats.map(toRow);
|
|
58
|
+
printOutput({
|
|
59
|
+
outputFormat,
|
|
60
|
+
json: result,
|
|
61
|
+
markdown: [
|
|
62
|
+
"# Threats",
|
|
63
|
+
"",
|
|
64
|
+
`- Returned: ${result.threats.length}`,
|
|
65
|
+
`- Next page cursor: ${result.next_page ?? "none"}`,
|
|
66
|
+
"",
|
|
67
|
+
...rows.map(
|
|
68
|
+
(row) => `- #${row.id} (${row.type}) ${row.content} \u2014 blocked=${row.blockedAt}`
|
|
69
|
+
)
|
|
70
|
+
].join("\n"),
|
|
71
|
+
csv: toCsvRows(rows),
|
|
72
|
+
human: () => {
|
|
73
|
+
if (result.threats.length === 0) {
|
|
74
|
+
console.log("No threats found.");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
console.log(`Threats \u2014 returned ${result.threats.length}`);
|
|
78
|
+
for (const row of rows) {
|
|
79
|
+
console.log(`#${row.id} (${row.type}) ${row.content} \u2014 blocked=${row.blockedAt}`);
|
|
80
|
+
}
|
|
81
|
+
if (result.next_page) {
|
|
82
|
+
console.log(`Next page cursor: ${result.next_page}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
export {
|
|
88
|
+
runThreatsList
|
|
89
|
+
};
|