malshare-sdk 1.0.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 +15 -0
- package/LICENSE +21 -0
- package/README.md +366 -0
- package/dist/index.js +215 -0
- package/package.json +59 -0
- package/src/cli.js +210 -0
- package/src/index.d.ts +309 -0
- package/src/index.js +404 -0
package/src/cli.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* MalShare CLI — command-line interface for the MalShare API.
|
|
4
|
+
*
|
|
5
|
+
* Install: npm install -g malshare-sdk (or bun install -g)
|
|
6
|
+
* Usage: malshare <command> [options]
|
|
7
|
+
*
|
|
8
|
+
* Auth: MALSHARE_KEY env var, or --key flag
|
|
9
|
+
*
|
|
10
|
+
* @module malshare-sdk/cli
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { MalShare } from './index.js';
|
|
14
|
+
import { parseArgs } from 'node:util';
|
|
15
|
+
|
|
16
|
+
const KEY = process.env.MALSHARE_KEY || '';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get configured MalShare client.
|
|
20
|
+
*/
|
|
21
|
+
function getClient(key) {
|
|
22
|
+
if (!key) {
|
|
23
|
+
console.error('⚠️ MALSHARE_KEY env var is not set.');
|
|
24
|
+
console.error(' Register at https://malshare.com/register.php');
|
|
25
|
+
console.error(' Then: export MALSHARE_KEY=your-key-here');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
return new MalShare(key);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Format bytes to human-readable.
|
|
33
|
+
*/
|
|
34
|
+
function formatBytes(bytes) {
|
|
35
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
36
|
+
if (bytes < 1_048_576) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
37
|
+
return `${(bytes / 1_048_576).toFixed(1)} MB`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ══════════════════════════════════════════════════════════════════
|
|
41
|
+
// MAIN
|
|
42
|
+
// ══════════════════════════════════════════════════════════════════
|
|
43
|
+
|
|
44
|
+
async function main() {
|
|
45
|
+
const args = process.argv.slice(2);
|
|
46
|
+
const cmd = args[0];
|
|
47
|
+
|
|
48
|
+
// Parse --key flag
|
|
49
|
+
let key = KEY;
|
|
50
|
+
const keyIdx = args.indexOf('--key');
|
|
51
|
+
if (keyIdx > -1 && args[keyIdx + 1]) {
|
|
52
|
+
key = args[keyIdx + 1];
|
|
53
|
+
args.splice(keyIdx, 2);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {
|
|
57
|
+
console.log(`
|
|
58
|
+
MalShare CLI — https://malshare.com
|
|
59
|
+
|
|
60
|
+
Usage: malshare <command> [options]
|
|
61
|
+
|
|
62
|
+
Commands:
|
|
63
|
+
list List SHA256 hashes from the past 24 hours
|
|
64
|
+
raw List SHA256 hashes (raw text, one per line)
|
|
65
|
+
sources List sample sources from the past 24 hours
|
|
66
|
+
filenames List file names from the past 24 hours
|
|
67
|
+
types List file types and counts
|
|
68
|
+
info <hash> Get sample details by hash
|
|
69
|
+
search <q> Search by hash, source, or file name
|
|
70
|
+
type <type> List hashes by file type (PE32, ELF, PDF...)
|
|
71
|
+
download <h> Download a sample (raw bytes to stdout)
|
|
72
|
+
save <h> <f> Download a sample and save to file
|
|
73
|
+
quota Check API quota
|
|
74
|
+
url <url> Submit URL for MalShare to download
|
|
75
|
+
|
|
76
|
+
Auth:
|
|
77
|
+
export MALSHARE_KEY=your-key-here
|
|
78
|
+
Or use --key flag: malshare list --key your-key
|
|
79
|
+
|
|
80
|
+
Examples:
|
|
81
|
+
malshare list # latest samples
|
|
82
|
+
malshare info 46faab8ab153... # sample details
|
|
83
|
+
malshare save 46faab8ab153... ./malware.bin
|
|
84
|
+
malshare types # file type distribution
|
|
85
|
+
malshare quota # API calls remaining
|
|
86
|
+
`);
|
|
87
|
+
process.exit(0);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const ms = getClient(key);
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
switch (cmd) {
|
|
94
|
+
case 'list': {
|
|
95
|
+
const hashes = await ms.listSamples();
|
|
96
|
+
console.log(`${hashes.length} samples in the last 24 hours`);
|
|
97
|
+
hashes.slice(0, 20).forEach((h) => console.log(` ${h}`));
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
case 'raw': {
|
|
102
|
+
const text = await ms.listSamplesRaw();
|
|
103
|
+
process.stdout.write(text);
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
case 'sources': {
|
|
108
|
+
const sources = await ms.listSources();
|
|
109
|
+
console.log(`${sources.length} sources`);
|
|
110
|
+
for (const s of (Array.isArray(sources) ? sources : [])) {
|
|
111
|
+
console.log(` ${s.source || s.name || JSON.stringify(s)}`);
|
|
112
|
+
}
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
case 'filenames': {
|
|
117
|
+
const names = await ms.listFileNames();
|
|
118
|
+
console.log(`${names.length} file names`);
|
|
119
|
+
for (const n of names.slice(0, 20)) console.log(` ${n}`);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
case 'types': {
|
|
124
|
+
const types = await ms.listTypes();
|
|
125
|
+
console.log(`${types.length} file types`);
|
|
126
|
+
for (const t of (Array.isArray(types) ? types : [])) {
|
|
127
|
+
console.log(` ${t.type || t.name || JSON.stringify(t)}`);
|
|
128
|
+
}
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
case 'info': {
|
|
133
|
+
const hash = args[1];
|
|
134
|
+
if (!hash) { console.error('Usage: malshare info <hash>'); process.exit(1); }
|
|
135
|
+
const details = await ms.details(hash);
|
|
136
|
+
if (!details) { console.log('Sample not found'); process.exit(1); }
|
|
137
|
+
console.log('SHA256: ', details.SHA256);
|
|
138
|
+
console.log('SHA1: ', details.SHA1);
|
|
139
|
+
console.log('MD5: ', details.MD5);
|
|
140
|
+
console.log('Type: ', details.F_TYPE);
|
|
141
|
+
console.log('Size: ', formatBytes(details.F_SIZE));
|
|
142
|
+
console.log('Name: ', details.F_NAME || 'N/A');
|
|
143
|
+
console.log('Sources: ', (details.SOURCES || []).join(', '));
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
case 'search': {
|
|
148
|
+
const query = args.slice(1).join(' ');
|
|
149
|
+
if (!query) { console.error('Usage: malshare search <query>'); process.exit(1); }
|
|
150
|
+
const results = await ms.search(query);
|
|
151
|
+
console.log(results);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
case 'type': {
|
|
156
|
+
const fileType = args.slice(1).join(' ');
|
|
157
|
+
if (!fileType) { console.error('Usage: malshare type <filetype>'); process.exit(1); }
|
|
158
|
+
const hashes = await ms.searchByType(fileType);
|
|
159
|
+
console.log(`${hashes.length} ${fileType} samples (24h)`);
|
|
160
|
+
hashes.slice(0, 20).forEach((h) => console.log(` ${h}`));
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
case 'download': {
|
|
165
|
+
const hash = args[1];
|
|
166
|
+
if (!hash) { console.error('Usage: malshare download <hash>'); process.exit(1); }
|
|
167
|
+
const bytes = await ms.download(hash);
|
|
168
|
+
process.stdout.write(bytes);
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
case 'save': {
|
|
173
|
+
const hash = args[1];
|
|
174
|
+
const filePath = args[2];
|
|
175
|
+
if (!hash || !filePath) { console.error('Usage: malshare save <hash> <filepath>'); process.exit(1); }
|
|
176
|
+
const result = await ms.downloadTo(hash, filePath);
|
|
177
|
+
console.log(`✅ Saved ${formatBytes(result.size)} → ${result.path}`);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
case 'quota': {
|
|
182
|
+
const quota = await ms.getQuota();
|
|
183
|
+
console.log(`Daily limit: ${quota.limit}`);
|
|
184
|
+
console.log(`Remaining: ${quota.remaining}`);
|
|
185
|
+
console.log(`Used: ${(quota.limit - quota.remaining)}`);
|
|
186
|
+
console.log(`Usage: ${((1 - quota.remaining / quota.limit) * 100).toFixed(1)}%`);
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
case 'url': {
|
|
191
|
+
const url = args[1];
|
|
192
|
+
if (!url) { console.error('Usage: malshare url <url> [--recursive]'); process.exit(1); }
|
|
193
|
+
const recursive = args.includes('--recursive');
|
|
194
|
+
const result = await ms.downloadUrl(url, recursive);
|
|
195
|
+
console.log(JSON.stringify(result, null, 2));
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
default:
|
|
200
|
+
console.error(`Unknown command: ${cmd}`);
|
|
201
|
+
console.error('Run: malshare help');
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
} catch (err) {
|
|
205
|
+
console.error(`❌ Error: ${err.message}`);
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
main();
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MalShare SDK — JavaScript client for the MalShare API.
|
|
3
|
+
*
|
|
4
|
+
* MalShare is a free malware sample repository with 1M+ samples.
|
|
5
|
+
* API: https://malshare.com/doc.php
|
|
6
|
+
* Registration: https://malshare.com/register.php
|
|
7
|
+
*
|
|
8
|
+
* Works on: Bun, Node.js, Deno, Cloudflare Workers.
|
|
9
|
+
* Zero dependencies. Uses native fetch() or Bun/node:http.
|
|
10
|
+
*
|
|
11
|
+
* @module malshare-sdk
|
|
12
|
+
* @license MIT
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* import { MalShare } from 'malshare-sdk';
|
|
16
|
+
* const ms = new MalShare('your-api-key');
|
|
17
|
+
* const hashes = await ms.listSamples();
|
|
18
|
+
* const sample = await ms.download('abc123...');
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {Object} MalShareConfig
|
|
22
|
+
* @property {string} apiKey — MalShare API key
|
|
23
|
+
* @property {string} [baseUrl='https://malshare.com/api.php'] — API base URL
|
|
24
|
+
* @property {number} [timeoutMs=60000] — request timeout in ms
|
|
25
|
+
* @property {Function} [fetch] — custom fetch implementation (for CF Workers etc.)
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {Object} FileDetails
|
|
29
|
+
* @property {string} MD5 — MD5 hash
|
|
30
|
+
* @property {string} SHA1 — SHA1 hash
|
|
31
|
+
* @property {string} SHA256 — SHA256 hash
|
|
32
|
+
* @property {string} F_TYPE — file type (e.g. 'PE32 executable')
|
|
33
|
+
* @property {number} F_SIZE — file size in bytes
|
|
34
|
+
* @property {string} [F_NAME] — original file name
|
|
35
|
+
* @property {string[]} [SOURCES] — sample sources
|
|
36
|
+
* @property {string} [FIRST_SEEN] — first seen timestamp
|
|
37
|
+
* @property {string} [LAST_SEEN] — last seen timestamp
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* @typedef {Object} UploadResult
|
|
41
|
+
* @property {string} status — 'OK' or 'ERROR'
|
|
42
|
+
* @property {string} [guid] — upload GUID for status tracking
|
|
43
|
+
* @property {string} [error] — error message if status is ERROR
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {Object} DownloadUrlResult
|
|
47
|
+
* @property {string} status — 'OK' or 'ERROR'
|
|
48
|
+
* @property {string} [guid] — task GUID for checking status
|
|
49
|
+
* @property {string} [error] — error message
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* @typedef {Object} DownloadUrlStatus
|
|
53
|
+
* @property {string} status — 'missing' | 'pending' | 'processing' | 'finished'
|
|
54
|
+
* @property {string} [guid] — task GUID
|
|
55
|
+
*/
|
|
56
|
+
/**
|
|
57
|
+
* @typedef {Object} QuotaInfo
|
|
58
|
+
* @property {number} limit — allocated API calls per day
|
|
59
|
+
* @property {number} remaining — remaining API calls
|
|
60
|
+
*/
|
|
61
|
+
export class MalShare {
|
|
62
|
+
/**
|
|
63
|
+
* @param {string} apiKey — MalShare API key (free at https://malshare.com/register.php)
|
|
64
|
+
* @param {Partial<MalShareConfig>} [config]
|
|
65
|
+
*/
|
|
66
|
+
constructor(apiKey: string, config?: Partial<MalShareConfig>);
|
|
67
|
+
/** @type {MalShareConfig} */
|
|
68
|
+
config: MalShareConfig;
|
|
69
|
+
/**
|
|
70
|
+
* Make an API request.
|
|
71
|
+
* @param {string} action — API action
|
|
72
|
+
* @param {Object} [params={}] — query parameters
|
|
73
|
+
* @param {Object} [opts={}] — request options
|
|
74
|
+
* @returns {Promise<any>}
|
|
75
|
+
*/
|
|
76
|
+
_request(action: string, params?: Object, opts?: Object): Promise<any>;
|
|
77
|
+
/**
|
|
78
|
+
* List SHA256 hashes from the past 24 hours.
|
|
79
|
+
* @returns {Promise<string[]>}
|
|
80
|
+
*/
|
|
81
|
+
listSamples(): Promise<string[]>;
|
|
82
|
+
/**
|
|
83
|
+
* List SHA256 hashes from the past 24 hours (raw text, one per line).
|
|
84
|
+
* @returns {Promise<string>}
|
|
85
|
+
*/
|
|
86
|
+
listSamplesRaw(): Promise<string>;
|
|
87
|
+
/**
|
|
88
|
+
* List sample sources from the past 24 hours.
|
|
89
|
+
* @returns {Promise<{source: string, count: number}[]>}
|
|
90
|
+
*/
|
|
91
|
+
listSources(): Promise<{
|
|
92
|
+
source: string;
|
|
93
|
+
count: number;
|
|
94
|
+
}[]>;
|
|
95
|
+
/**
|
|
96
|
+
* List sample sources from the past 24 hours (raw text).
|
|
97
|
+
* @returns {Promise<string>}
|
|
98
|
+
*/
|
|
99
|
+
listSourcesRaw(): Promise<string>;
|
|
100
|
+
/**
|
|
101
|
+
* List file names from uploads in the past 24 hours.
|
|
102
|
+
* @returns {Promise<string[]>}
|
|
103
|
+
*/
|
|
104
|
+
listFileNames(): Promise<string[]>;
|
|
105
|
+
/**
|
|
106
|
+
* Get file types and counts from the past 24 hours.
|
|
107
|
+
* @returns {Promise<{type: string, count: number}[]>}
|
|
108
|
+
*/
|
|
109
|
+
listTypes(): Promise<{
|
|
110
|
+
type: string;
|
|
111
|
+
count: number;
|
|
112
|
+
}[]>;
|
|
113
|
+
/**
|
|
114
|
+
* Get detailed information about a sample.
|
|
115
|
+
*
|
|
116
|
+
* @param {string} hash — MD5, SHA1, or SHA256 hash
|
|
117
|
+
* @returns {Promise<FileDetails|null>}
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* const details = await ms.details('46faab8ab153fae...');
|
|
121
|
+
* console.log(details.F_TYPE, details.MD5);
|
|
122
|
+
*/
|
|
123
|
+
details(hash: string): Promise<FileDetails | null>;
|
|
124
|
+
/**
|
|
125
|
+
* Bulk hash lookup — supply an array of hashes.
|
|
126
|
+
*
|
|
127
|
+
* @param {string[]} hashes — array of hex-encoded hashes
|
|
128
|
+
* @returns {Promise<FileDetails[]>}
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* const results = await ms.hashLookup(['abc123...', 'def456...']);
|
|
132
|
+
*/
|
|
133
|
+
hashLookup(hashes: string[]): Promise<FileDetails[]>;
|
|
134
|
+
/**
|
|
135
|
+
* Search by file type (samples from past 24h).
|
|
136
|
+
*
|
|
137
|
+
* @param {string} fileType — e.g. 'PE32', 'ELF', 'PDF', 'Zip', 'JavaScript'
|
|
138
|
+
* @returns {Promise<string[]>} — array of MD5/SHA1/SHA256 hashes
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* const hashes = await ms.searchByType('PE32 executable');
|
|
142
|
+
*/
|
|
143
|
+
searchByType(fileType: string): Promise<string[]>;
|
|
144
|
+
/**
|
|
145
|
+
* Search samples by query (hash, source, or file name).
|
|
146
|
+
* Returns raw text results.
|
|
147
|
+
*
|
|
148
|
+
* @param {string} query — search term
|
|
149
|
+
* @returns {Promise<string>} — raw search results
|
|
150
|
+
*/
|
|
151
|
+
search(query: string): Promise<string>;
|
|
152
|
+
/**
|
|
153
|
+
* Download a malware sample by hash.
|
|
154
|
+
* Returns raw bytes. **Handle with care — this is live malware.**
|
|
155
|
+
*
|
|
156
|
+
* @param {string} hash — MD5, SHA1, or SHA256 hash
|
|
157
|
+
* @returns {Promise<Uint8Array>} — raw file bytes
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* const bytes = await ms.download('46faab8ab153fae...');
|
|
161
|
+
* await Bun.write('/tmp/malware.bin', bytes);
|
|
162
|
+
*/
|
|
163
|
+
download(hash: string): Promise<Uint8Array>;
|
|
164
|
+
/**
|
|
165
|
+
* Download a sample and save to disk (Bun/Node only).
|
|
166
|
+
*
|
|
167
|
+
* @param {string} hash — file hash
|
|
168
|
+
* @param {string} filePath — where to save
|
|
169
|
+
* @returns {Promise<{path: string, size: number}>}
|
|
170
|
+
*/
|
|
171
|
+
downloadTo(hash: string, filePath: string): Promise<{
|
|
172
|
+
path: string;
|
|
173
|
+
size: number;
|
|
174
|
+
}>;
|
|
175
|
+
/**
|
|
176
|
+
* Upload a malware sample.
|
|
177
|
+
* Uploading files temporarily increases your API quota.
|
|
178
|
+
*
|
|
179
|
+
* @param {Uint8Array|Buffer|Blob} file — the sample to upload
|
|
180
|
+
* @param {string} [fileName='sample.bin'] — file name
|
|
181
|
+
* @returns {Promise<UploadResult>}
|
|
182
|
+
*/
|
|
183
|
+
upload(file: Uint8Array | Buffer | Blob, fileName?: string): Promise<UploadResult>;
|
|
184
|
+
/**
|
|
185
|
+
* Submit a URL for MalShare to download and add to its collection.
|
|
186
|
+
*
|
|
187
|
+
* @param {string} url — URL to download
|
|
188
|
+
* @param {boolean} [recursive=false] — enable crawling
|
|
189
|
+
* @returns {Promise<DownloadUrlResult>}
|
|
190
|
+
*/
|
|
191
|
+
downloadUrl(url: string, recursive?: boolean): Promise<DownloadUrlResult>;
|
|
192
|
+
/**
|
|
193
|
+
* Check the status of a URL download task.
|
|
194
|
+
*
|
|
195
|
+
* @param {string} guid — task GUID from downloadUrl()
|
|
196
|
+
* @returns {Promise<DownloadUrlStatus>}
|
|
197
|
+
*/
|
|
198
|
+
downloadUrlStatus(guid: string): Promise<DownloadUrlStatus>;
|
|
199
|
+
/**
|
|
200
|
+
* Get API quota information.
|
|
201
|
+
* @returns {Promise<QuotaInfo>}
|
|
202
|
+
*/
|
|
203
|
+
getQuota(): Promise<QuotaInfo>;
|
|
204
|
+
}
|
|
205
|
+
export default MalShare;
|
|
206
|
+
export type MalShareConfig = {
|
|
207
|
+
/**
|
|
208
|
+
* — MalShare API key
|
|
209
|
+
*/
|
|
210
|
+
apiKey: string;
|
|
211
|
+
/**
|
|
212
|
+
* — API base URL
|
|
213
|
+
*/
|
|
214
|
+
baseUrl?: string | undefined;
|
|
215
|
+
/**
|
|
216
|
+
* — request timeout in ms
|
|
217
|
+
*/
|
|
218
|
+
timeoutMs?: number | undefined;
|
|
219
|
+
/**
|
|
220
|
+
* — custom fetch implementation (for CF Workers etc.)
|
|
221
|
+
*/
|
|
222
|
+
fetch?: Function | undefined;
|
|
223
|
+
};
|
|
224
|
+
export type FileDetails = {
|
|
225
|
+
/**
|
|
226
|
+
* — MD5 hash
|
|
227
|
+
*/
|
|
228
|
+
MD5: string;
|
|
229
|
+
/**
|
|
230
|
+
* — SHA1 hash
|
|
231
|
+
*/
|
|
232
|
+
SHA1: string;
|
|
233
|
+
/**
|
|
234
|
+
* — SHA256 hash
|
|
235
|
+
*/
|
|
236
|
+
SHA256: string;
|
|
237
|
+
/**
|
|
238
|
+
* — file type (e.g. 'PE32 executable')
|
|
239
|
+
*/
|
|
240
|
+
F_TYPE: string;
|
|
241
|
+
/**
|
|
242
|
+
* — file size in bytes
|
|
243
|
+
*/
|
|
244
|
+
F_SIZE: number;
|
|
245
|
+
/**
|
|
246
|
+
* — original file name
|
|
247
|
+
*/
|
|
248
|
+
F_NAME?: string | undefined;
|
|
249
|
+
/**
|
|
250
|
+
* — sample sources
|
|
251
|
+
*/
|
|
252
|
+
SOURCES?: string[] | undefined;
|
|
253
|
+
/**
|
|
254
|
+
* — first seen timestamp
|
|
255
|
+
*/
|
|
256
|
+
FIRST_SEEN?: string | undefined;
|
|
257
|
+
/**
|
|
258
|
+
* — last seen timestamp
|
|
259
|
+
*/
|
|
260
|
+
LAST_SEEN?: string | undefined;
|
|
261
|
+
};
|
|
262
|
+
export type UploadResult = {
|
|
263
|
+
/**
|
|
264
|
+
* — 'OK' or 'ERROR'
|
|
265
|
+
*/
|
|
266
|
+
status: string;
|
|
267
|
+
/**
|
|
268
|
+
* — upload GUID for status tracking
|
|
269
|
+
*/
|
|
270
|
+
guid?: string | undefined;
|
|
271
|
+
/**
|
|
272
|
+
* — error message if status is ERROR
|
|
273
|
+
*/
|
|
274
|
+
error?: string | undefined;
|
|
275
|
+
};
|
|
276
|
+
export type DownloadUrlResult = {
|
|
277
|
+
/**
|
|
278
|
+
* — 'OK' or 'ERROR'
|
|
279
|
+
*/
|
|
280
|
+
status: string;
|
|
281
|
+
/**
|
|
282
|
+
* — task GUID for checking status
|
|
283
|
+
*/
|
|
284
|
+
guid?: string | undefined;
|
|
285
|
+
/**
|
|
286
|
+
* — error message
|
|
287
|
+
*/
|
|
288
|
+
error?: string | undefined;
|
|
289
|
+
};
|
|
290
|
+
export type DownloadUrlStatus = {
|
|
291
|
+
/**
|
|
292
|
+
* — 'missing' | 'pending' | 'processing' | 'finished'
|
|
293
|
+
*/
|
|
294
|
+
status: string;
|
|
295
|
+
/**
|
|
296
|
+
* — task GUID
|
|
297
|
+
*/
|
|
298
|
+
guid?: string | undefined;
|
|
299
|
+
};
|
|
300
|
+
export type QuotaInfo = {
|
|
301
|
+
/**
|
|
302
|
+
* — allocated API calls per day
|
|
303
|
+
*/
|
|
304
|
+
limit: number;
|
|
305
|
+
/**
|
|
306
|
+
* — remaining API calls
|
|
307
|
+
*/
|
|
308
|
+
remaining: number;
|
|
309
|
+
};
|