codequiry-cli 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/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # Node.js CLI for Plagiarism Checker API
2
+
3
+ ## Detail
4
+ Command Line Interface (CLI) to interact with the Plagiarism Checker API
5
+
6
+ ## Install
7
+ ```
8
+ npm install
9
+ npm install -g .
10
+ ```
11
+
12
+ ## Usage
13
+ After installation, you can use the following commands:
14
+
15
+ 1. `auth`: Authenticate your API key
16
+ 2. `createCheck`: Create a new plagiarism check
17
+ 3. `uploadToCheck`: Upload a file to be checked
18
+ 4. `startCheck`: Start a plagiarism check
19
+ 5. `retriveCheck`: Retrieve existing checks
20
+ 6. `checkStatus`: Check the status of a plagiarism check
21
+ 7. `resultOverview`: Get an overview of the check results
22
+ 8. `detailedResult`: Get detailed results of a check
23
+
24
+ ## Examples
25
+ Here are detailed examples of how to use each command:
26
+
27
+ ### Authenticate
28
+ ```
29
+ codequiry auth
30
+ ```
31
+ This will prompt you to enter your API key for authentication.
32
+ If you are not authenticated, you will be prompted to enter your API key:
33
+ ```
34
+ Enter your API key:
35
+ ```
36
+ Once you are authenticated successfully, it will save to apikey.json file and you can see following.
37
+ ```
38
+ Hello, lion!
39
+ Your email is victor19930515@outlook.com.
40
+ ? Choose an action:
41
+ ❯ Create Check
42
+ Start Check
43
+ Upload to Check
44
+ ```
45
+ ### Create Check
46
+ This will initiate the process of creating a new check and provide you with a check ID.
47
+ ```
48
+ codequiry createCheck
49
+ ```
50
+ You will be prompted to enter the programming language you want to check and name:
51
+ ```
52
+ ? Enter the programming language: 13
53
+ ? Enter the your name:
54
+ ```
55
+ Available languages are:
56
+ ```
57
+ "available_languages": [
58
+ { id: 13, language: 'Java (.java)' },
59
+ { id: 14, language: 'Python (.py)' },
60
+ { id: 16, language: 'C (.c/.h)' },
61
+ { id: 17, language: 'C/C++ (.cc/.c/.h/.cpp/.hpp)' },
62
+ { id: 18, language: 'C# (.cs)' },
63
+ { id: 20, language: 'Perl (.pl/.sh)' },
64
+ { id: 21, language: 'PHP (.php)' },
65
+ { id: 22, language: 'SQL (.sql)' },
66
+ { id: 23, language: 'VB (.vb/.bas)' },
67
+ { id: 24, language: 'XML (.xml)' },
68
+ { id: 28, language: 'Haskell (.hs/.lhs)' },
69
+ { id: 29, language: 'Pascal (.pas/.inc)' },
70
+ { id: 30, language: 'Go (.go)' },
71
+ { id: 31, language: 'Matlab (.m)' },
72
+ { id: 32, language: 'Lisp (.el)' },
73
+ { id: 33, language: 'Ruby (.rb)' },
74
+ { id: 34, language: 'Assembly (.asm/.s)' },
75
+ { id: 38, language: 'HTML Javascript (.html/.htm/.xhtml)' },
76
+ { id: 39, language: 'Javascript (.js/.ts)' },
77
+ { id: 40, language: 'HTML (.html/.htm/.xhtml)' },
78
+ { id: 41, language: 'Plain text (.txt)' },
79
+ { id: 42, language: 'Text file by char (.txt)' },
80
+ { id: 43, language: 'Swift (.swift)' },
81
+ { id: 44, language: 'Kotlin (.kt/.kts)' },
82
+ { id: 45, language: 'Yacc (.y,.yy,.ypp,.yxx)' },
83
+ { id: 46, language: 'Lex (.l,.ll)' },
84
+ { id: 47, language: 'Elixir (.ex, .exs)' },
85
+ { id: 48, language: 'Python Jupyter Notebook (.ipynb)' },
86
+ { id: 49, language: 'Dart (.dart)' },
87
+ { id: 50, language: 'Shell (.sh/.bash)' },
88
+ { id: 51, language: 'Rust (.rs)' },
89
+ { id: 52, language: 'Scala (.scala)' },
90
+ { id: 53, language: 'R (.r)' },
91
+ { id: 54, language: 'Objective-C (.m, .mm)' },
92
+ { id: 55, language: 'TypeScript (.ts, .tsx)' },
93
+ { id: 56, language: 'Markdown (.md)' },
94
+ { id: 57, language: 'Julia (.jl)' },
95
+ { id: 58, language: 'Groovy (.groovy)' },
96
+ { id: 59, language: 'Sass/SCSS (.scss, .sass)' },
97
+ { id: 60, language: 'CoffeeScript (.coffee)' },
98
+ { id: 61, language: 'Lua (.lua)' },
99
+ { id: 62, language: 'Erlang (.erl, .hrl)' },
100
+ { id: 63, language: 'F# (.fs, .fsi, .fsx)' },
101
+ { id: 64, language: 'Fortran (.f90, .f95)' },
102
+ { id: 65, language: 'Haxe (.hx)' },
103
+ { id: 66, language: 'Scheme (.scm, .ss)' },
104
+ { id: 67, language: 'Tcl (.tcl)' },
105
+ { id: 68, language: 'Ada (.adb, .ads)' },
106
+ { id: 69, language: 'COBOL (.cob, .cbl)' },
107
+ { id: 70, language: 'VHDL (.vhd, .vhdl)' }
108
+ ]
109
+ ```
110
+
111
+ ### Upload to Check
112
+ This will upload files in uploads folder to check.
113
+ **Files in uploads folder must be zip files.**
114
+ ```
115
+ codequiry uploadToCheck
116
+ ```
117
+ You will be prompted to enter check ID.
118
+ ```
119
+ ? Enter the check ID:
120
+ ```
121
+
122
+ ### Start Check
123
+ This will start check.
124
+ ```
125
+ codequiry startCheck
126
+ ```
127
+ You will be prompted to enter check ID.
128
+ ```
129
+ ? Enter the check ID:
130
+ ? Select the additional check type: (Use arrow keys)
131
+ ❯ webcheck
132
+ dbcheck
133
+ ```
134
+ ```
135
+ dbcheck: If you would like to run the database check
136
+ webcheck: If you would like to run the web check
137
+ ```
138
+ ### Retrive Check
139
+ This will retrive check.
140
+ ```
141
+ codequiry retriveCheck
142
+ ```
143
+
144
+ ### Get Check Status
145
+ This will get check status.
146
+ ```
147
+ codequiry checkStatus
148
+ ```
149
+ You will be prompted to enter check ID.
150
+ ```
151
+ ? Enter the check ID:
152
+ ```
153
+
154
+ ### Get Result Overview
155
+ This will get result overview.
156
+ ```
157
+ codequiry resultOverview
158
+ ```
159
+ You will be prompted to enter check ID.
160
+ ```
161
+ ? Enter the check ID:
162
+ ```
163
+
164
+ ### Get Detailed Result
165
+ This will get detailed result.
166
+ ```
167
+ codequiry detailedResult
168
+ ```
169
+ You will be prompted to enter check ID and submission ID.
170
+ ```
171
+ ? Enter the check ID: 95663
172
+ ? Enter the submission ID: 220801
173
+ ```
174
+
175
+ ## Version
176
+ Current version: 1.0.0
177
+
178
+ ## License
179
+ ISC
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "codequiry-cli",
3
+ "version": "1.0.0",
4
+ "description": "Command Line Interface (CLI) to interact with the Code Plagiarism Checker API",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "codequiry": "src/index.js"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "keywords": [],
13
+ "author": "",
14
+ "license": "ISC",
15
+ "dependencies": {
16
+ "axios": "^1.7.2",
17
+ "chalk": "^5.3.0",
18
+ "commander": "^12.1.0",
19
+ "dotenv": "^16.4.5",
20
+ "form-data": "^4.0.0",
21
+ "fs": "^0.0.1-security",
22
+ "fs-extra": "^11.2.0",
23
+ "inquirer": "^10.1.2"
24
+ },
25
+ "type": "module"
26
+ }
package/src/auth.js ADDED
@@ -0,0 +1,47 @@
1
+ import inquirer from 'inquirer';
2
+ import axios from 'axios';
3
+ import fs from 'fs';
4
+ import { manageChecks } from './check.js';
5
+ import { API_KEY_FILE } from './const.js';
6
+ import { getApiKey } from './util.js';
7
+
8
+ export async function authenticate() {
9
+ let apiKey = getApiKey();
10
+
11
+ if (!apiKey) {
12
+ const answers = await inquirer.prompt([
13
+ {
14
+ type: 'input',
15
+ name: 'apiKey',
16
+ message: 'Enter your API key:'
17
+ }
18
+ ]);
19
+
20
+ apiKey = answers.apiKey;
21
+ }
22
+
23
+ if (apiKey) {
24
+ try {
25
+ const response = await axios.post('https://codequiry.com/api/v1/account', null, {
26
+ headers: {
27
+ 'Accept': '*/*',
28
+ 'apikey': apiKey,
29
+ }
30
+ });
31
+
32
+ if (response.status === 200) {
33
+ fs.writeFileSync(API_KEY_FILE, JSON.stringify({ apiKey }));
34
+ console.log(`Hello, ${response.data.user}!\nYour email is ${response.data.email}.`);
35
+
36
+ manageChecks();
37
+ } else {
38
+ console.log('Invalid API key. Please re-enter the key.');
39
+ }
40
+ } catch (error) {
41
+ console.error('Authentication failed:', error.response.data);
42
+ if (fs.existsSync(API_KEY_FILE)) {
43
+ fs.unlinkSync(API_KEY_FILE);
44
+ }
45
+ }
46
+ }
47
+ }
package/src/check.js ADDED
@@ -0,0 +1,444 @@
1
+ import inquirer from 'inquirer';
2
+ import axios from 'axios';
3
+ import fs from 'fs';
4
+ import FormData from 'form-data';
5
+ import { API_KEY_FILE, validLanguageIds } from './const.js'
6
+ import { isValidNumber, getApiKey, getZipFiles } from './util.js'
7
+
8
+
9
+ export async function manageChecks() {
10
+ try {
11
+ const { apiKey } = JSON.parse(fs.readFileSync(API_KEY_FILE, 'utf8'));
12
+
13
+ const action = await inquirer.prompt([
14
+ {
15
+ type: 'list',
16
+ name: 'action',
17
+ message: 'Choose an action:',
18
+ choices: ['Create Check', 'Start Check', 'Upload to Check']
19
+ }
20
+ ]);
21
+
22
+ switch (action.action) {
23
+ case 'Create Check':
24
+ await _createCheck(apiKey);
25
+ break;
26
+ case 'Start Check':
27
+ await _startCheck(apiKey);
28
+ break;
29
+ case 'Upload to Check':
30
+ await _uploadToCheck(apiKey);
31
+ break;
32
+ default:
33
+ console.log('Invalid action.');
34
+ }
35
+ } catch (error) {
36
+ if (error.message.includes('User force closed the prompt')) {
37
+ } else {
38
+ console.error('An unexpected error occurred:', error);
39
+ }
40
+ }
41
+ }
42
+
43
+ export function createCheck() {
44
+ try {
45
+ const apiKey = getApiKey();
46
+ if (!apiKey) {
47
+ console.log('Please authenticate first.');
48
+ return;
49
+ }
50
+ _createCheck(apiKey);
51
+ } catch (error) {
52
+ if (error.message.includes('User force closed the prompt')) {
53
+ } else {
54
+ console.error('An unexpected error occurred:', error);
55
+ }
56
+ }
57
+ }
58
+
59
+ async function _createCheck(apiKey) {
60
+ try {
61
+ const answers = await inquirer.prompt([
62
+ {
63
+ type: 'input',
64
+ name: 'language',
65
+ message: 'Enter the programming language:'
66
+ },
67
+ {
68
+ type: 'input',
69
+ name: 'name',
70
+ message: 'Enter the your name:'
71
+ },
72
+ ]);
73
+
74
+ if (answers.language === '' || !isValidNumber(answers.language)) {
75
+ console.log(validLanguageIds);
76
+ return;
77
+ }
78
+ if (answers.name === '' || answers.name.length < 4) {
79
+ console.log('Please enter name. And name must be at least 4 characters.');
80
+ return;
81
+ }
82
+
83
+ try {
84
+ const response = await axios.post('https://codequiry.com/api/v1/check/create', null, {
85
+ params: {
86
+ name: answers.name,
87
+ language: answers.language,
88
+ },
89
+ headers: {
90
+ 'Accept': '*/*',
91
+ 'apikey': apiKey,
92
+ }
93
+ });
94
+
95
+ if (response.status === 201) {
96
+ console.log('Check created successfully:', response.data);
97
+ } else {
98
+ console.log('Failed to create check.');
99
+ }
100
+ } catch (error) {
101
+ console.error('Error Creating Check:', error.response.data);
102
+ }
103
+ } catch (error) {
104
+ if (error.message.includes('User force closed the prompt')) {
105
+ } else {
106
+ console.error('An unexpected error occurred:', error);
107
+ }
108
+ }
109
+ }
110
+
111
+ export function startCheck() {
112
+ try {
113
+ const apiKey = getApiKey();
114
+ if (!apiKey) {
115
+ console.log('Please authenticate first.');
116
+ return;
117
+ }
118
+ _startCheck(apiKey);
119
+ } catch (error) {
120
+ if (error.message.includes('User force closed the prompt')) {
121
+ } else {
122
+ console.error('An unexpected error occurred:', error);
123
+ }
124
+ }
125
+ }
126
+
127
+ async function _startCheck(apiKey) {
128
+ try {
129
+ const answers = await inquirer.prompt([
130
+ {
131
+ type: 'input',
132
+ name: 'checkId',
133
+ message: 'Enter the check ID:'
134
+ },
135
+ {
136
+ type: 'list',
137
+ name: 'addintionalCheck',
138
+ message: 'Select the additional check type:',
139
+ choices: ['webcheck', 'dbcheck', 'group_similarity_only']
140
+ }
141
+ ]);
142
+
143
+ if (answers.checkId === '' || !isValidNumber(answers.checkId)) {
144
+ console.log('Please enter check ID. And check ID must be a number.');
145
+ return;
146
+ }
147
+ if (answers.addintionalCheck === '') {
148
+ console.log('Please select additional check type.');
149
+ return;
150
+ }
151
+
152
+ let params = {};
153
+ if (answers.addintionalCheck === 'webcheck') {
154
+ params = { 'check_id': answers.checkId, 'webcheck': 1 };
155
+ } else if (answers.addintionalCheck === 'dbcheck') {
156
+ params = { 'check_id': answers.checkId, 'dbcheck': 1 };
157
+ } else if (answers.addintionalCheck === 'group_similarity_only') {
158
+ params = { 'check_id': answers.checkId };
159
+ }
160
+ try {
161
+ const response = await axios.post(`https://codequiry.com/api/v1/check/start`, null, {
162
+ params: {
163
+ ...params
164
+ },
165
+ headers: {
166
+ 'apikey': apiKey,
167
+ }
168
+ });
169
+
170
+ if (response.status === 200 && !response.data.hasOwnProperty('error')) {
171
+ console.log('Check started successfully.\n', response.data);
172
+ } else {
173
+ console.log('Failed to start check.', response.data);
174
+ }
175
+ } catch (error) {
176
+ console.error('Error starting check:', error.response.data);
177
+ }
178
+ } catch (error) {
179
+ if (error.message.includes('User force closed the prompt')) {
180
+ } else {
181
+ console.error('An unexpected error occurred:', error);
182
+ }
183
+ }
184
+
185
+ }
186
+
187
+ export function uploadToCheck() {
188
+ try {
189
+ const apiKey = getApiKey();
190
+ if (!apiKey) {
191
+ console.log('Please authenticate first.');
192
+ return;
193
+ }
194
+ _uploadToCheck(apiKey);
195
+ } catch (error) {
196
+ if (error.message.includes('User force closed the prompt')) {
197
+ } else {
198
+ console.error('An unexpected error occurred:', error);
199
+ }
200
+ }
201
+
202
+ }
203
+
204
+ async function _uploadToCheck(apiKey) {
205
+ try {
206
+ const answers = await inquirer.prompt([
207
+ {
208
+ type: 'input',
209
+ name: 'checkId',
210
+ message: 'Enter the check ID:'
211
+ }
212
+ ]);
213
+
214
+ if (answers.checkId === '' || !isValidNumber(answers.checkId)) {
215
+ console.log('Please enter check ID. And check ID must be a number.');
216
+ return;
217
+ }
218
+
219
+ const files = getZipFiles();
220
+
221
+ if (answers.checkId === '') {
222
+ console.log('Please enter check ID.');
223
+ return;
224
+ }
225
+ if (files.length === 0) {
226
+ console.log('No ZIP files found in uploads folder.\nPlease copy files in upload folder and try again.');
227
+ return;
228
+ }
229
+
230
+
231
+ files.forEach(async (file, index) => {
232
+ try {
233
+ const form = new FormData();
234
+ form.append('file', fs.createReadStream(`./uploads/${file}`));
235
+ form.append('check_id', answers.checkId);
236
+ const response = await axios.post('https://codequiry.com/api/v1/check/upload', form, {
237
+ headers: {
238
+ apikey: apiKey,
239
+ }
240
+ });
241
+
242
+ if (response.status === 200) {
243
+ console.log('File uploaded successfully.', response.data);
244
+ } else {
245
+ console.log('Failed to upload file.');
246
+ }
247
+ } catch (error) {
248
+ console.error('Error uploading file:', error.message);
249
+ }
250
+ });
251
+ } catch (error) {
252
+ if (error.message.includes('User force closed the prompt')) {
253
+ } else {
254
+ console.error('An unexpected error occurred:', error);
255
+ }
256
+ }
257
+ }
258
+
259
+ export async function retriveCheck() {
260
+ try {
261
+ const apiKey = getApiKey();
262
+ if (!apiKey) {
263
+ console.log('Please authenticate first.');
264
+ return;
265
+ }
266
+
267
+ try {
268
+ const response = await axios.post(`https://codequiry.com/api/v1/checks`, null, {
269
+ headers: {
270
+ 'Accept': '*/*',
271
+ 'apikey': apiKey,
272
+ }
273
+ });
274
+
275
+ if (response.status === 200) {
276
+ console.log('Retrive Checks successfully.\n', response.data);
277
+ } else {
278
+ console.log('Failed to retrive check.', response.data);
279
+ }
280
+ } catch (error) {
281
+ console.error('Error retriving checks:', error.response.data);
282
+ }
283
+ } catch (error) {
284
+ if (error.message.includes('User force closed the prompt')) {
285
+ } else {
286
+ console.error('An unexpected error occurred:', error);
287
+ }
288
+ }
289
+
290
+ }
291
+
292
+ export async function checkStatus() {
293
+ try {
294
+ const apiKey = getApiKey();
295
+ if (!apiKey) {
296
+ console.log('Please authenticate first.');
297
+ return;
298
+ }
299
+ const answers = await inquirer.prompt([
300
+ {
301
+ type: 'input',
302
+ name: 'checkId',
303
+ message: 'Enter the check ID:'
304
+ }
305
+ ]);
306
+ if (answers.checkId === '' || !isValidNumber(answers.checkId)) {
307
+ console.log('Please enter check ID. And check ID must be a number.');
308
+ return;
309
+ }
310
+
311
+ let params = { check_id: answers.checkId };
312
+
313
+ try {
314
+ const response = await axios.post(`https://codequiry.com/api/v1/check/get`, null, {
315
+ params: {
316
+ ...params
317
+ },
318
+ headers: {
319
+ 'Accept': '*/*',
320
+ 'apikey': apiKey,
321
+ }
322
+ });
323
+
324
+ if (response.status === 200) {
325
+ console.log('Check status successfully.\n', response.data);
326
+ } else {
327
+ console.log('Failed to check status.', response.data);
328
+ }
329
+ } catch (error) {
330
+ console.error('Error check status:', error.response.data);
331
+ }
332
+ } catch (error) {
333
+ if (error.message.includes('User force closed the prompt')) {
334
+ } else {
335
+ console.error('An unexpected error occurred:', error);
336
+ }
337
+ }
338
+ }
339
+
340
+ export async function resultOverview() {
341
+ try {
342
+ const apiKey = getApiKey();
343
+ if (!apiKey) {
344
+ console.log('Please authenticate first.');
345
+ return;
346
+ }
347
+ const answers = await inquirer.prompt([
348
+ {
349
+ type: 'input',
350
+ name: 'checkId',
351
+ message: 'Enter the check ID:'
352
+ }
353
+ ]);
354
+
355
+ if (answers.checkId === '' || !isValidNumber(answers.checkId)) {
356
+ console.log('Please enter check ID. And check ID must be a number.');
357
+ return;
358
+ }
359
+
360
+ let params = { check_id: answers.checkId };
361
+
362
+ try {
363
+ const response = await axios.post(`https://codequiry.com/api/v1/check/overview`, null, {
364
+ params: {
365
+ ...params
366
+ },
367
+ headers: {
368
+ 'Accept': '*/*',
369
+ 'apikey': apiKey,
370
+ }
371
+ });
372
+
373
+ if (response.status === 200) {
374
+ console.log('Result Overview.\n', response.data);
375
+ } else {
376
+ console.log('Failed to check result overview.', response.data);
377
+ }
378
+ } catch (error) {
379
+ console.error('Error check result overview:', error.response.data);
380
+ }
381
+ } catch (error) {
382
+ if (error.message.includes('User force closed the prompt')) {
383
+ } else {
384
+ console.error('An unexpected error occurred:', error);
385
+ }
386
+ }
387
+ }
388
+
389
+ export async function detailedResult() {
390
+ try {
391
+ const apiKey = getApiKey();
392
+ if (!apiKey) {
393
+ console.log('Please authenticate first.');
394
+ return;
395
+ }
396
+ const answers = await inquirer.prompt([
397
+ {
398
+ type: 'input',
399
+ name: 'checkId',
400
+ message: 'Enter the check ID:'
401
+ },
402
+ {
403
+ type: 'input',
404
+ name: 'submissionId',
405
+ message: 'Enter the submission ID:'
406
+ }
407
+ ]);
408
+ if (answers.checkId === '' || !isValidNumber(answers.checkId)) {
409
+ console.log('Please enter check ID. And check ID must be a number.');
410
+ return;
411
+ }
412
+ if (answers.submissionId === '' || !isValidNumber(answers.submissionId)) {
413
+ console.log('Please enter submission ID. And submission ID must be a number.');
414
+ return;
415
+ }
416
+
417
+ let params = { check_id: answers.checkId, submission_id: answers.submissionId };
418
+
419
+ try {
420
+ const response = await axios.post(`https://codequiry.com/api/v1/check/overview`, null, {
421
+ params: {
422
+ ...params
423
+ },
424
+ headers: {
425
+ 'Accept': '*/*',
426
+ 'apikey': apiKey,
427
+ }
428
+ });
429
+
430
+ if (response.status === 200) {
431
+ console.log('Detailed Result.\n', response.data);
432
+ } else {
433
+ console.log('Failed to detailed result.', response.data);
434
+ }
435
+ } catch (error) {
436
+ console.error('Error get detailed result:', error.response.data);
437
+ }
438
+ } catch (error) {
439
+ if (error.message.includes('User force closed the prompt')) {
440
+ } else {
441
+ console.error('An unexpected error occurred:', error);
442
+ }
443
+ }
444
+ }