-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
261 lines (218 loc) · 9.32 KB
/
Copy pathindex.js
File metadata and controls
261 lines (218 loc) · 9.32 KB
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
const chalk = require('chalk');
const api = require('./lib/api');
const { Command } = require('commander');
const path = require('path');
const {performance} = require('perf_hooks');
const {formatTime, formatSize} = require('./lib/util');
const server = require('./lib/serve');
// Create new Commander instance
const program = new Command();
(async () => {
const ora = (await import('ora')).default;
// Initialize configuration
await api.config.init();
// Exit if configuration file is incomplete
if(!api.config.data.webhook || !api.config.data.deta_api_key) {
return api.console.warn(`Discord Webhook URL or Deta Collection Key is missing in \`${api.config.path}\`. Please update configuration and try again.`);
}else if(!api.config.data.encryption_key) {
return api.console.error(`No encryption key found at \`${api.config.path}\`. Exiting!`);
}
// Initialize database
api.db.init();
// Initialize CLI program
program
.name('Distore')
.description('Fast, unlimited, encrypted storage on Discord')
.version('1.5.2');
// Upload command
program.command('upload')
.description('Uploads a file to the virtual filesystem')
.argument('<path>', 'Path to file on disk')
.argument('[destination]', 'Destination file in virtual filesystem')
.option('-p, --parallel <number>', 'No. of parallel chunks to upload', 3)
.action(async (filepath, destination, options) => {
if(typeof destination == "undefined") destination = `/` + path.basename(filepath);
// Initialize spinner
let spinner = ora('Queueing jobs');
let chunks = 0;
let chunksDone = 0;
let avg = 0;
// Measure time start
let startTime = performance.now();
let file = await api.fileManager.uploadFile(path.resolve(filepath), destination, options.parallel, (type, data) => {
if(type === 'start') {
chunks = data.chunks;
spinner.start();
}
if(type === 'registerfile') {
spinner.text = `Registering file to database`;
}
if(type === 'chunkupload') {
spinner.text = `Uploading chunks [${chunksDone}/${chunks}]`;
}
if(type === 'chunkuploaded') {
// Update average upload speed
avg = ((avg * chunksDone) + data.avgSpeed) / (chunksDone + 1);
chunksDone++;
spinner.text = `Uploading chunks [${chunksDone}/${chunks}]`;
}
if(type === 'end') {
// Compute elapsed time in ms
let elapsed = performance.now() - startTime;
spinner.succeed(`Uploaded to \`${data.destination}\` in virtual filesystem ` + chalk.gray(`(${formatTime(elapsed)}, ${formatSize(avg)}/sec)`));
}
});
});
// Download command
program.command('download')
.description('Downloads a file from the virtual filesystem to disk')
.argument('<path>', 'Path to file on virtual filesystem')
.argument('[destination]', 'Destination file on disk')
.option('-p, --parallel <number>', 'No. of parallel chunks to download', 3)
.action(async (filepath, destination, options) => {
if(typeof destination == "undefined") destination = path.resolve('./', path.basename(filepath));
// Initialize spinner
let spinner = ora('Fetching file metadata');
spinner.start();
let chunks = 0;
let chunksDone = 0;
let avg = 0;
let fileMeta = await api.db.getFileFromPath(filepath);
if(fileMeta === null) {
spinner.stop();
return api.console.error(`No file exists at \`${filepath}\`!`);
}
// Clear the spinner so text doesn't overlap
spinner.stop();
// Measure time start
let startTime = performance.now();
// Begin download
let file = await api.fileManager.downloadFile(fileMeta.key, destination, options.parallel, (type, data) => {
if(type === 'start') {
spinner.text = 'Queueing jobs';
spinner.start();
chunks = data.chunks;
}
if(type === 'chunkdownload') {
spinner.text = `Downloading chunks [${chunksDone}/${chunks}]`;
}
if(type === 'chunkdownloaded') {
// Update average upload speed
avg = ((avg * chunksDone) + data.avgSpeed) / (chunksDone + 1);
chunksDone++;
spinner.text = `Downloading chunks [${chunksDone}/${chunks}]`;
}
if(type === 'end') {
// Compute elapsed time in ms
let elapsed = performance.now() - startTime;
spinner.succeed(`Saved to ${data.path} ` + chalk.gray(`(${formatTime(elapsed)}, ${formatSize(avg)}/sec)`));
}
});
});
// Delete command
program.command('delete')
.description('Deletes a file in the virtual filesystem')
.argument('<path>', 'Path to file on virtual filesystem')
.action(async (filepath) => {
// Initialize spinner
let spinner = ora('Fetching chunk list');
spinner.start();
let chunks = 0;
let chunksDone = 0;
let fileMeta = await api.db.getFileFromPath(filepath);
if(fileMeta === null) {
spinner.stop();
return api.console.error(`No file exists at \`${filepath}\`!`);
}
// Clear the spinner so text doesn't overlap
spinner.stop();
// Measure time start
let startTime = performance.now();
// Begin deletion
await api.db.deleteFile(fileMeta.key, (type, data) => {
if(type === 'start') {
spinner.text = 'Fetching chunk list';
spinner.start();
}
if(type === 'fetchchunks') {
chunks = data.chunksList.length;
}
if(type === 'chunkdelete') {
spinner.text = `Deleting chunk ${chalk.gray(data.key)} [${chunksDone}/${chunks}]`;
}
if(type === 'chunkdeleted') {
chunksDone++;
}
if(type === 'end') {
// Compute elapsed time in ms
let elapsed = performance.now() - startTime;
spinner.succeed(`Deleted \`${fileMeta.name}\` ` + chalk.gray(`(${formatTime(elapsed)})`));
}
});
});
// List command
program.command('ls')
.description('Lists files in a directory')
.argument('[path]', 'Path to directory in virtual filesystem', '/')
.action(async (dirpath) => {
console.log(chalk.blueBright("list"), dirpath);
let spinner = ora('Fetching files list');
spinner.start();
// Fetch list of files
let {files, dirs} = await api.db.listDirectory(dirpath);
// Handle empty list
if(files.length < 1 && dirs.length < 1) return spinner.info(`Empty directory or directory does not exist`);
else spinner.stop();
for(let dir of dirs) {
console.log(`📁`, chalk.yellowBright(path.basename(dir.key)));
}
for(let file of files) {
console.log(`-`, file.name, chalk.gray(`(${formatSize(file.size)})`));
}
});
// Search command
program.command('search')
.description('Search for files')
.argument('<name>', 'Name of file to search for')
.action(async (name) => {
console.log(chalk.blueBright("search"), name);
let spinner = ora('Searching');
spinner.start();
// Fetch list of files
let files = await api.db.searchFile(name);
// Handle empty list
if(files.length < 1) return spinner.info(`No files found for this search query`);
else spinner.stop();
for(let file of files) {
console.log(`-`, chalk.yellowBright(file.path + `/`) + file.name, chalk.gray(`(${formatSize(file.size)})`));
}
});
// Serve command
program.command('serve')
.description('Starts an HTTP server for serving files from the virtual filesystem')
.argument('[port]', 'Port to run on', 3000)
.action(async (port) => {
let spinner = ora('Starting server');
spinner.start();
// Start the server
await server.start(port);
spinner.succeed(`Server running on http://127.0.0.1:${port}`);
});
// Config command
program.command('config')
.description('Updates the configuration file')
.argument('<item>', 'Configuration item to update')
.argument('<value>', 'Value of the item')
.action(async (item, value) => {
if(item in api.config.data) {
api.config.data[item] = value;
// Update the config file
await api.config.setConfig(api.config.data);
return api.console.success(`Configuration has been updated`);
}else {
return api.console.error(`Configuration item \`${item}\` does not exist!`);
}
});
// Start parsing CLI commands
program.parse();
})();