Skip to content

Commit c8ee466

Browse files
Merge pull request #86 from jucasoliveira/85-typeerror-cannot-read-properties-of-undefined-reading-status
Fix console.log and file deletion bugs
2 parents 7479be7 + b4efb15 commit c8ee466

File tree

9 files changed

+3714
-3592
lines changed

9 files changed

+3714
-3592
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "terminalgpt",
3-
"version": "1.7.3",
3+
"version": "1.7.4",
44
"main": "lib/index.js",
55
"description": "Get GPT like chatGPT on your terminal",
66
"scripts": {

src/context.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55

66
let context: any[] = [];
77

8+
/**
9+
* Adds a new context to the existing context array.
10+
*
11+
* @param {any} text - The text to be added to the context array.
12+
*/
813
export function addContext(text: any) {
914
context = [...context, text];
1015
}

src/encrypt.ts

Lines changed: 78 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,60 +5,101 @@ import * as crypto from "crypto";
55
const algorithm = "aes-256-cbc";
66
const secretKey = "terminalGPT";
77

8+
/**
9+
* Encrypts the given text using the specified algorithm, secret key, and initialization vector.
10+
*
11+
* @param {string} text - The text to be encrypted.
12+
* @return {string} The encrypted text in the format: IV:encryptedText.
13+
*/
814
export function encrypt(text: string) {
9-
const iv = crypto.randomBytes(16);
10-
const key = crypto.scryptSync(secretKey, "salt", 32);
11-
const cipher = crypto.createCipheriv(algorithm, key, iv);
12-
let encrypted = cipher.update(text);
15+
const iv = crypto.randomBytes(16);
16+
const key = crypto.scryptSync(secretKey, "salt", 32);
17+
const cipher = crypto.createCipheriv(algorithm, key, iv);
18+
let encrypted = cipher.update(text);
1319

14-
encrypted = Buffer.concat([encrypted, cipher.final()]);
15-
return iv.toString("hex") + ":" + encrypted.toString("hex");
20+
encrypted = Buffer.concat([encrypted, cipher.final()]);
21+
return iv.toString("hex") + ":" + encrypted.toString("hex");
1622
}
1723

24+
/**
25+
* Decrypts the given text using a specific algorithm and secret key.
26+
*
27+
* @param {string} text - The text to be decrypted.
28+
* @return {string} - The decrypted text.
29+
*/
1830
export function decrypt(text: string) {
19-
const textParts = text.split(":");
20-
const iv = Buffer.from(textParts.shift()!, "hex");
21-
const encryptedText = Buffer.from(textParts.join(":"), "hex");
22-
const key = crypto.scryptSync(secretKey, "salt", 32);
23-
const decipher = crypto.createDecipheriv(algorithm, key, iv);
24-
let decrypted = decipher.update(encryptedText);
25-
decrypted = Buffer.concat([decrypted, decipher.final()]);
26-
return decrypted.toString();
31+
const textParts = text.split(":");
32+
const iv = Buffer.from(textParts.shift()!, "hex");
33+
const encryptedText = Buffer.from(textParts.join(":"), "hex");
34+
const key = crypto.scryptSync(secretKey, "salt", 32);
35+
const decipher = crypto.createDecipheriv(algorithm, key, iv);
36+
let decrypted = decipher.update(encryptedText);
37+
decrypted = Buffer.concat([decrypted, decipher.final()]);
38+
return decrypted.toString();
2739
}
2840

41+
/**
42+
* Saves a custom URL to a file.
43+
*
44+
* @param {string | undefined} url - The custom URL to be saved. If undefined, the file is deleted.
45+
* @return {void}
46+
*/
2947
export function saveCustomUrl(url: string | undefined) {
30-
if (url === undefined) {
31-
fs.unlinkSync(`${__dirname}/customUrl.txt`);
32-
} else {
33-
fs.writeFileSync(`${__dirname}/customUrl.txt`, url);
34-
}
48+
if (url === undefined) {
49+
fs.unlinkSync(`${__dirname}/customUrl.txt`);
50+
} else {
51+
fs.writeFileSync(`${__dirname}/customUrl.txt`, url);
52+
}
3553
}
3654

55+
/**
56+
* Retrieves a custom URL from a text file if it exists.
57+
*
58+
* @return {string | undefined} The custom URL if it exists, otherwise undefined.
59+
*/
3760
export function getCustomUrl(): string | undefined {
38-
if (fs.existsSync(`${__dirname}/customUrl.txt`)) {
39-
return fs.readFileSync(
40-
`${__dirname}/customUrl.txt`,
41-
"utf8"
42-
);
43-
}
44-
return undefined
61+
if (fs.existsSync(`${__dirname}/customUrl.txt`)) {
62+
return fs.readFileSync(`${__dirname}/customUrl.txt`, "utf8");
63+
}
64+
return undefined;
4565
}
4666

67+
/**
68+
* Saves the API key to a file.
69+
*
70+
* @param {string} apiKey - The API key to save.
71+
* @return {void} This function does not return anything.
72+
*/
4773
export function saveApiKey(apiKey: string) {
48-
fs.writeFileSync(`${__dirname}/apiKey.txt`, apiKey);
74+
fs.writeFileSync(`${__dirname}/apiKey.txt`, apiKey);
4975
}
5076

77+
/**
78+
* Deletes the API key file if it exists.
79+
*
80+
* @return {boolean} Returns true if the API key file was deleted, false otherwise.
81+
*/
5182
export function deleteApiKey() {
52-
fs.unlinkSync(`${__dirname}/apiKey.txt`);
83+
const apiKeyFilePath = `${__dirname}/apiKey.txt`;
84+
if (fs.existsSync(apiKeyFilePath)) {
85+
fs.unlinkSync(apiKeyFilePath);
86+
return true;
87+
}
88+
return false;
5389
}
5490

91+
/**
92+
* Retrieves the API key from the "apiKey.txt" file, decrypts it, and returns it.
93+
*
94+
* @return {string | null} The decrypted API key, or null if the file does not exist.
95+
*/
5596
export function getApiKey(): string | null {
56-
if (fs.existsSync(`${__dirname}/apiKey.txt`)) {
57-
const getEncryptedScript = fs.readFileSync(
58-
`${__dirname}/apiKey.txt`,
59-
"utf8"
60-
);
61-
return decrypt(getEncryptedScript);
62-
}
63-
return null;
64-
}
97+
if (fs.existsSync(`${__dirname}/apiKey.txt`)) {
98+
const getEncryptedScript = fs.readFileSync(
99+
`${__dirname}/apiKey.txt`,
100+
"utf8"
101+
);
102+
return decrypt(getEncryptedScript);
103+
}
104+
return null;
105+
}

src/gpt.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export default async (
3232
temperature: opts.temperature ? Number(opts.temperature) : 1,
3333
})
3434
.then((res) => {
35+
console.log("here");
3536
if (typeof res.choices[0].message !== "undefined") {
3637
addContext(res.choices[0].message);
3738
spinner.stop();
@@ -41,6 +42,7 @@ export default async (
4142
}
4243
})
4344
.catch((err) => {
45+
console.log(err);
4446
spinner.stop();
4547
switch (err["response"]["status"]) {
4648
case 404:

src/gradient.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ const referenceGradient: string[] = [
2929
...gradientColors,
3030
];
3131

32+
/**
33+
* Generates the frames for a gradient animation.
34+
*
35+
* @return {string[]} An array of strings representing the frames of the animation.
36+
*/
3237
export function getGradientAnimFrames() {
3338
const frames: string[] = [];
3439
for (let start = 0; start < gradientColors.length * 2; start++) {

src/index.ts

Lines changed: 85 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -6,99 +6,104 @@ import prompts from "prompts";
66

77
import intro from "./intro";
88

9-
import {apiKeyPrompt, generateResponse} from "./utils";
9+
import { apiKeyPrompt, generateResponse } from "./utils";
1010

11-
import {deleteApiKey, saveCustomUrl} from "./encrypt";
11+
import { deleteApiKey, saveCustomUrl } from "./encrypt";
1212

1313
import * as c from "commander";
1414

15-
const commander = new c.Command()
15+
const commander = new c.Command();
1616
commander
17-
.command("chat")
18-
.option("-e, --engine <engine>", "GPT model to use")
19-
.option("-t, --temperature <temperature>", "Response temperature")
20-
.option("-m, --markdown", "Show markdown in the terminal")
21-
.usage(`"<project-directory>" [options]`)
22-
.action(async (opts) => {
23-
intro();
24-
apiKeyPrompt()
25-
.then((apiKey: string | null) => {
26-
const prompt = async () => {
27-
const response = await prompts({
28-
type: "text",
29-
name: "value",
30-
message: `${chalk.blueBright("You: ")}`,
31-
validate: () => {
32-
return true
33-
},
34-
onState: (state) => {
35-
if (state.aborted) {
36-
process.exit(0);
37-
}
38-
}
39-
})
17+
.command("chat")
18+
.option("-e, --engine <engine>", "GPT model to use")
19+
.option("-t, --temperature <temperature>", "Response temperature")
20+
.option("-m, --markdown", "Show markdown in the terminal")
21+
.usage(`"<project-directory>" [options]`)
22+
.action(async (opts) => {
23+
intro();
24+
apiKeyPrompt().then((apiKey: string | null) => {
25+
const prompt = async () => {
26+
const response = await prompts({
27+
type: "text",
28+
name: "value",
29+
message: `${chalk.blueBright("You: ")}`,
30+
validate: () => {
31+
return true;
32+
},
33+
onState: (state) => {
34+
if (state.aborted) {
35+
process.exit(0);
36+
}
37+
},
38+
});
4039

41-
switch (response.value) {
42-
case "exit":
43-
return process.exit(0);
44-
case "clear":
45-
return process.stdout.write("\x1Bc");
46-
default:
47-
if (apiKey != null) {
48-
generateResponse(apiKey, prompt, response, opts);
49-
}
50-
return;
51-
}
52-
};
53-
prompt();
54-
});
40+
switch (response.value) {
41+
case "exit":
42+
return process.exit(0);
43+
case "clear":
44+
return process.stdout.write("\x1Bc");
45+
default:
46+
if (apiKey != null) {
47+
generateResponse(apiKey, prompt, response, opts);
48+
}
49+
return;
50+
}
51+
};
52+
prompt();
5553
});
54+
});
5655

5756
// create commander to delete api key
5857
commander
59-
.command("delete")
60-
.description("Delete your API key")
61-
.action(async () => {
62-
const response = await prompts({
63-
type: "select",
64-
name: "value",
65-
message: "Are you sure?",
66-
choices: [
67-
{title: "Yes", value: "yes"},
68-
{title: "No - exit", value: "no"},
69-
],
70-
initial: 0,
71-
});
72-
73-
if (response.value) {
74-
return process.exit(0)
75-
}
58+
.command("delete")
59+
.description("Delete your API key")
60+
.action(async () => {
61+
const response = await prompts({
62+
type: "select",
63+
name: "value",
64+
message: "Are you sure?",
65+
choices: [
66+
{ title: "Yes", value: "yes" },
67+
{ title: "No - exit", value: "no" },
68+
],
69+
initial: 0,
70+
});
7671

77-
deleteApiKey();
72+
if (response.value === "yes") {
73+
const apiKeyDeleted = deleteApiKey();
74+
if (apiKeyDeleted) {
7875
console.log("API key deleted");
79-
});
76+
} else {
77+
console.log("API key file not found, no action taken.");
78+
}
79+
return process.exit(0);
80+
} else {
81+
console.log("Deletion cancelled");
82+
return process.exit(0);
83+
}
84+
});
8085

8186
commander
82-
.command("endpoint")
83-
.option("--set <url>", "Set your custom endpoint")
84-
.option("-r, --reset", "Reset the API endpoint to default ")
85-
.description("Configure your API endpoint")
86-
.action(async () => {
87-
console.log("Send empty to set default openai endpoint")
88-
prompts({
89-
type: "text",
90-
name: "value",
91-
validate: (t) =>
92-
t.search(/(https?:\/(\/.)+).*/g) === 0 || t === "" ? true : "Urls only allowed",
93-
message: "Insert endpoint: "
94-
})
95-
.then(response =>
96-
(response.value as string)
97-
.replace('/chat/completions', '')
98-
)
99-
.then(value => /(https?:\/(\/.)+).*/g.test(value) ? value : undefined)
100-
.then(saveCustomUrl)
101-
}
102-
)
87+
.command("endpoint")
88+
.option("--set <url>", "Set your custom endpoint")
89+
.option("-r, --reset", "Reset the API endpoint to default ")
90+
.description("Configure your API endpoint")
91+
.action(async () => {
92+
console.log("Send empty to set default openai endpoint");
93+
prompts({
94+
type: "text",
95+
name: "value",
96+
validate: (t) =>
97+
t.search(/(https?:\/(\/.)+).*/g) === 0 || t === ""
98+
? true
99+
: "Urls only allowed",
100+
message: "Insert endpoint: ",
101+
})
102+
.then((response) =>
103+
(response.value as string).replace("/chat/completions", "")
104+
)
105+
.then((value) => (/(https?:\/(\/.)+).*/g.test(value) ? value : undefined))
106+
.then(saveCustomUrl);
107+
});
103108

104109
commander.parse(process.argv);

0 commit comments

Comments
 (0)