kitsune-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 +149 -0
- package/dist/cli_engin/cli_engin.js +18 -0
- package/dist/commands/apiStorage.js +9 -0
- package/dist/commands/help.js +153 -0
- package/dist/commands/init.js +52 -0
- package/dist/commands/joke.js +60 -0
- package/dist/commands/loud.js +37 -0
- package/dist/commands/riddle.js +84 -0
- package/dist/commands/speak.js +39 -0
- package/dist/commands/spirit.js +96 -0
- package/dist/commands/weather.js +125 -0
- package/dist/commands/wordel.js +103 -0
- package/dist/index.js +19 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/bhavish-codes/Kitsune-cli/main/assets/logo.png" alt="Kitsune CLI" width="200" onerror="this.style.display='none'"/>
|
|
3
|
+
|
|
4
|
+
<h1>🦊 Kitsune CLI</h1>
|
|
5
|
+
<p><b>A mystical, fox-spirit themed command-line interface companion.</b></p>
|
|
6
|
+
|
|
7
|
+
<p>
|
|
8
|
+
<a href="https://github.com/bhavish-codes/Kitsune-cli/issues"><img src="https://img.shields.io/github/issues/bhavish-codes/Kitsune-cli?style=flat-square&color=magenta" alt="Issues"></a>
|
|
9
|
+
<a href="https://github.com/bhavish-codes/Kitsune-cli/stargazers"><img src="https://img.shields.io/github/stars/bhavish-codes/Kitsune-cli?style=flat-square&color=cyan" alt="Stars"></a>
|
|
10
|
+
<a href="https://github.com/bhavish-codes/Kitsune-cli/blob/main/LICENSE"><img src="https://img.shields.io/github/license/bhavish-codes/Kitsune-cli?style=flat-square&color=yellow" alt="License"></a>
|
|
11
|
+
</p>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
**Kitsune CLI** (`kit`) is a beautifully crafted, terminal-based companion. Channeling the ancient wisdom of the Kitsune (fox spirit), this CLI tool provides mystical advice, speaks to you directly through your terminal, and offers a visually stunning experience using gradients, beautiful boxes, and terminal animations.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- 🦊 **Mystical Aesthetic:** Beautiful terminal styling using `chalk`, `gradient-string`, and `boxen`.
|
|
22
|
+
- 🗣️ **Auditory Responses:** The spirit actually speaks to you using the `say` package.
|
|
23
|
+
- 🧘♂️ **Wisdom & Quotes:** Summons random wisdom and philosophical quotes via the API Ninjas service.
|
|
24
|
+
- 🛠️ **Modular Architecture:** Built with TypeScript and Node.js using `commander`.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
Ensure you have [Node.js](https://nodejs.org/) installed, then follow these steps:
|
|
29
|
+
|
|
30
|
+
1. **Clone the repository:**
|
|
31
|
+
```bash
|
|
32
|
+
git clone https://github.com/bhavish-codes/Kitsune-cli.git
|
|
33
|
+
cd Kitsune-cli
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. **Install dependencies:**
|
|
37
|
+
```bash
|
|
38
|
+
npm install
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
3. **Set up your environment variables:**
|
|
42
|
+
Create a `.env` file in the root directory and add your API Ninjas Key:
|
|
43
|
+
```env
|
|
44
|
+
API_NINJAS_KEY=your_api_key_here
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
4. **Build the TypeScript files:**
|
|
48
|
+
```bash
|
|
49
|
+
npx tsc
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
5. **Link the package globally:**
|
|
53
|
+
```bash
|
|
54
|
+
npm link
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Now you can summon the spirit from anywhere using the `kit` command!
|
|
58
|
+
|
|
59
|
+
## Usage & Commands
|
|
60
|
+
|
|
61
|
+
Here are the currently active incantations you can use:
|
|
62
|
+
|
|
63
|
+
### 1. Speak
|
|
64
|
+
Have the Kitsune channel ancient wisdom and speak your words aloud.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
kit speak "Hello traveler, welcome to my realm."
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 2. Spirit
|
|
71
|
+
Summon the Kitsune spirit to receive a piece of wisdom, philosophy, or truth. Optionally, have the spirit speak the quote out loud.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
kit spirit
|
|
75
|
+
# Or to hear the spirit speak:
|
|
76
|
+
kit spirit speak
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 3. Help
|
|
80
|
+
Summon the mystical help menu for detailed information about a specific command.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
kit help speak
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 4. Loud
|
|
87
|
+
Make the Kitsune shout your message across the digital realm, using large text.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
kit loud "Wake up!"
|
|
91
|
+
# Or to hear the spirit speak loud:
|
|
92
|
+
kit loud "Wake up!" speak
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 5. Riddle
|
|
96
|
+
The cunning fox presents a puzzle for your mind. You can provide a timer in seconds.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
kit riddle 30
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 6. Joke
|
|
103
|
+
A touch of kitsune mischief. Summon the fox to tell you a witty joke.
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
kit joke
|
|
107
|
+
# Or to hear the spirit speak the joke:
|
|
108
|
+
kit joke speak
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 7. Weather
|
|
112
|
+
Read the winds and skies. The spirit will consult the atmosphere to divine your local conditions or any specified location.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
kit weather
|
|
116
|
+
# For a specific location:
|
|
117
|
+
kit weather tokyo
|
|
118
|
+
# To hear the forecast aloud:
|
|
119
|
+
kit weather london speak
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 8. Wordel
|
|
123
|
+
The cunning fox tests your vocabulary with a game of Wordel. You have 6 tries to guess a mystery word. You can optionally specify the word length.
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
kit wordel
|
|
127
|
+
# For a specific word length between 3 and 8:
|
|
128
|
+
kit wordel 6
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Built With
|
|
134
|
+
|
|
135
|
+
- [TypeScript](https://www.typescriptlang.org/) - For robust, strongly-typed code.
|
|
136
|
+
- [Commander.js](https://github.com/tj/commander.js) - The complete solution for node.js command-line interfaces.
|
|
137
|
+
- [Chalk](https://github.com/chalk/chalk) & [Gradient-String](https://github.com/bokub/gradient-string) - For beautiful terminal styling.
|
|
138
|
+
- [Boxen](https://github.com/sindresorhus/boxen) - For creating terminal boxes.
|
|
139
|
+
- [Ora](https://github.com/sindresorhus/ora) - Elegant terminal spinners.
|
|
140
|
+
- [Say](https://github.com/Marak/say.js) - TTS (Text To Speech) wrapper.
|
|
141
|
+
|
|
142
|
+
## Contributing
|
|
143
|
+
|
|
144
|
+
Contributions, issues, and feature requests are welcome!
|
|
145
|
+
Feel free to check the [issues page](https://github.com/bhavish-codes/Kitsune-cli/issues) if you want to contribute.
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
This project is licensed under the ISC License.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const commander_1 = require("commander");
|
|
4
|
+
class CLI {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.program = new commander_1.Command();
|
|
7
|
+
}
|
|
8
|
+
registerCommand(command) {
|
|
9
|
+
command.forEach((value) => {
|
|
10
|
+
const cmdInstance = new value(this.program);
|
|
11
|
+
cmdInstance.register();
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
run() {
|
|
15
|
+
this.program.parse();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.default = CLI;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getApiKey = exports.setApiKey = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const FILE_PATH = __dirname + "/file.txt";
|
|
6
|
+
const setApiKey = (key) => (0, fs_1.writeFileSync)(FILE_PATH, key.trim(), "utf-8");
|
|
7
|
+
exports.setApiKey = setApiKey;
|
|
8
|
+
const getApiKey = () => (0, fs_1.existsSync)(FILE_PATH) ? (0, fs_1.readFileSync)(FILE_PATH, "utf-8").trim() : null;
|
|
9
|
+
exports.getApiKey = getApiKey;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
7
|
+
const gradient_string_1 = __importDefault(require("gradient-string"));
|
|
8
|
+
const boxen_1 = __importDefault(require("boxen"));
|
|
9
|
+
class Help {
|
|
10
|
+
constructor(program) {
|
|
11
|
+
this.existingCommands = [
|
|
12
|
+
"spirit",
|
|
13
|
+
"speak",
|
|
14
|
+
"riddle",
|
|
15
|
+
"joke",
|
|
16
|
+
"loud",
|
|
17
|
+
"wordel",
|
|
18
|
+
"weather"
|
|
19
|
+
];
|
|
20
|
+
this.implementedCommands = ["speak", "spirit", "loud", "riddle", "joke", "weather", "wordel"];
|
|
21
|
+
this.commandHelpData = {
|
|
22
|
+
speak: {
|
|
23
|
+
title: "🦊 Kitsune Speak Command",
|
|
24
|
+
summary: "Have the Kitsune channel ancient wisdom and speak your words aloud.",
|
|
25
|
+
usage: "kitsune speak <message>",
|
|
26
|
+
description: "Invoke the fox spirit to vocalize a message through your terminal.\nThe spirit uses TTS (Text-to-Speech) to clearly enunciate your thoughts.",
|
|
27
|
+
examples: [
|
|
28
|
+
'kit speak "Hello traveler"',
|
|
29
|
+
'kit speak "Build completed successfully"',
|
|
30
|
+
'kit speak "The spiritual realm awaits"',
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
spirit: {
|
|
34
|
+
title: "🦊 Kitsune Spirit Command",
|
|
35
|
+
summary: "Summon the Kitsune spirit to receive quotes of philosophy and truth.",
|
|
36
|
+
usage: "kitsune spirit [speak]",
|
|
37
|
+
description: "Calls upon the fox spirit to guide your terminal journey with timeless wisdom.\nPass the optional `speak` argument to hear the spirit read the quote aloud.",
|
|
38
|
+
examples: [
|
|
39
|
+
"kit spirit",
|
|
40
|
+
"kit spirit speak"
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
loud: {
|
|
44
|
+
title: "🦊 Kitsune Loud Command",
|
|
45
|
+
summary: "Make the Kitsune shout your message across the digital realm.",
|
|
46
|
+
usage: "kitsune loud <text> [speak]",
|
|
47
|
+
description: "Proclaim a grand message with large, shadow-styled ASCII text.\nPass the optional `speak` argument to have the spirit announce it out loud.",
|
|
48
|
+
examples: [
|
|
49
|
+
'kit loud "Wake up!"',
|
|
50
|
+
'kit loud "Tests Passing!" speak',
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
riddle: {
|
|
54
|
+
title: "🦊 Kitsune Riddle Command",
|
|
55
|
+
summary: "The Kitsune spirit shares a mysterious riddle.",
|
|
56
|
+
usage: "kitsune riddle <timer>",
|
|
57
|
+
description: "The cunning fox tests your wits by presenting a riddle.\nYou have the given time (in seconds) to contemplate the answer.",
|
|
58
|
+
examples: [
|
|
59
|
+
"kit riddle 30",
|
|
60
|
+
"kit riddle 60"
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
joke: {
|
|
64
|
+
title: "🦊 Kitsune Joke Command",
|
|
65
|
+
summary: "The Kitsune spirit shares a humorous joke.",
|
|
66
|
+
usage: "kitsune joke [speak]",
|
|
67
|
+
description: "The playful fox entertains you with a witty joke.\nPass the optional `speak` argument to have the spirit tell the joke aloud.",
|
|
68
|
+
examples: [
|
|
69
|
+
"kit joke",
|
|
70
|
+
"kit joke speak"
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
weather: {
|
|
74
|
+
title: "🦊 Kitsune Weather Command",
|
|
75
|
+
summary: "Read the winds and skies for any location.",
|
|
76
|
+
usage: "kitsune weather [location] [speak]",
|
|
77
|
+
description: "The spirit looks into the atmosphere to tell you the current weather.\nYou can specify a location or let it read your local skies.\nPass the optional `speak` argument to hear the forecast aloud.",
|
|
78
|
+
examples: [
|
|
79
|
+
"kit weather",
|
|
80
|
+
"kit weather tokyo",
|
|
81
|
+
"kit weather speak",
|
|
82
|
+
"kit weather london speak"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
wordel: {
|
|
86
|
+
title: "🦊 Kitsune Wordel Command",
|
|
87
|
+
summary: "The Kitsune challenges your vocabulary with a game of Wordel.",
|
|
88
|
+
usage: "kitsune wordel [wordlength]",
|
|
89
|
+
description: "Play a mystical game of Wordel with the fox.\nYou have 6 tries to guess a mystery word. You can optionally specify the word length (between 3 and 8).",
|
|
90
|
+
examples: [
|
|
91
|
+
"kit wordel",
|
|
92
|
+
"kit wordel 6"
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
this.kitsune = `
|
|
97
|
+
/\\_/\\
|
|
98
|
+
=( °w° )=
|
|
99
|
+
) (
|
|
100
|
+
(__ __)
|
|
101
|
+
`;
|
|
102
|
+
this.program = program;
|
|
103
|
+
}
|
|
104
|
+
register() {
|
|
105
|
+
this.program
|
|
106
|
+
.command("help <command>")
|
|
107
|
+
.description("Display help information for a specific command")
|
|
108
|
+
.action((command) => this.show(command));
|
|
109
|
+
}
|
|
110
|
+
show(command) {
|
|
111
|
+
console.log(gradient_string_1.default.instagram.multiline(`
|
|
112
|
+
╔══════════════════════════════╗
|
|
113
|
+
🦊 KITSUNE CLI HELP
|
|
114
|
+
╚══════════════════════════════╝
|
|
115
|
+
`));
|
|
116
|
+
if (this.implementedCommands.includes(command)) {
|
|
117
|
+
const details = this.commandHelpData[command];
|
|
118
|
+
if (details) {
|
|
119
|
+
console.log(gradient_string_1.default.pastel(this.kitsune));
|
|
120
|
+
const examplesText = details.examples.map(ex => ` ${ex}`).join("\n");
|
|
121
|
+
const helpText = `
|
|
122
|
+
${details.title}
|
|
123
|
+
|
|
124
|
+
${details.summary}
|
|
125
|
+
|
|
126
|
+
Usage
|
|
127
|
+
${details.usage}
|
|
128
|
+
|
|
129
|
+
Description
|
|
130
|
+
${details.description}
|
|
131
|
+
|
|
132
|
+
Examples
|
|
133
|
+
${examplesText}
|
|
134
|
+
`;
|
|
135
|
+
console.log((0, boxen_1.default)(chalk_1.default.cyan(helpText), {
|
|
136
|
+
padding: 1,
|
|
137
|
+
borderStyle: "round",
|
|
138
|
+
borderColor: "magenta",
|
|
139
|
+
}));
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
console.log(chalk_1.default.yellow(`\nHelp documentation for '${command}' is being written by the spirits...`));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else if (this.existingCommands.includes(command)) {
|
|
146
|
+
console.log(chalk_1.default.yellow(`\nThe command '${command}' is still in development. Please check back later!`));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
console.log(chalk_1.default.red(`\nThe command '${command}' is not available.`));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
exports.default = Help;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const apiStorage_1 = require("./apiStorage");
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
class Init {
|
|
10
|
+
constructor(program) {
|
|
11
|
+
this.program = program;
|
|
12
|
+
}
|
|
13
|
+
register() {
|
|
14
|
+
this.program
|
|
15
|
+
.command("init [apikey]")
|
|
16
|
+
.description("Initialize the Kitsune CLI environment")
|
|
17
|
+
.action((apikey) => this.initialize(apikey));
|
|
18
|
+
}
|
|
19
|
+
async initialize(apiKey) {
|
|
20
|
+
if (!apiKey) {
|
|
21
|
+
console.log("enter your api ninja api key:");
|
|
22
|
+
console.log("https://api-ninjas.com/profile");
|
|
23
|
+
console.log("kit init <your-api-key>");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
console.log("Initializing Kitsune CLI...");
|
|
27
|
+
const spinner = (0, ora_1.default)({
|
|
28
|
+
text: chalk_1.default.magenta("🦊 Validating your API Key..."),
|
|
29
|
+
spinner: "dots",
|
|
30
|
+
}).start();
|
|
31
|
+
try {
|
|
32
|
+
const res = await fetch(`https://api.api-ninjas.com/v1/jokes`, {
|
|
33
|
+
headers: {
|
|
34
|
+
"X-Api-Key": apiKey,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
if (!res.ok) {
|
|
38
|
+
spinner.fail(chalk_1.default.red("Invalid API Key! The key was not saved. Please check your key."));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
spinner.succeed(chalk_1.default.green("API Key is valid!"));
|
|
42
|
+
(0, apiStorage_1.setApiKey)(apiKey);
|
|
43
|
+
console.log(chalk_1.default.green('API Key saved successfully!'));
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
spinner.fail(chalk_1.default.red('Failed to validate API Key: ' + err));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
console.log("Kitsune CLI is ready to use! Type 'kit --help' to see available commands.");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.default = Init;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
7
|
+
const gradient_string_1 = __importDefault(require("gradient-string"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
const say_1 = __importDefault(require("say"));
|
|
10
|
+
const apiStorage_1 = require("./apiStorage");
|
|
11
|
+
class Joke {
|
|
12
|
+
constructor(program) {
|
|
13
|
+
this.kitsune = `
|
|
14
|
+
/\\_/\\
|
|
15
|
+
=( °w° )=
|
|
16
|
+
) (
|
|
17
|
+
(__ __)
|
|
18
|
+
`;
|
|
19
|
+
this.program = program;
|
|
20
|
+
}
|
|
21
|
+
register() {
|
|
22
|
+
this.program
|
|
23
|
+
.command("joke [speak]")
|
|
24
|
+
.description("The Kitsune spirit shares a humorous joke")
|
|
25
|
+
.action((speak) => this.joker(speak));
|
|
26
|
+
}
|
|
27
|
+
async joker(speak) {
|
|
28
|
+
if (!(0, apiStorage_1.getApiKey)()) {
|
|
29
|
+
console.log(chalk_1.default.red("\nYou have to first write kit init <apikey>\n"));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
console.log(gradient_string_1.default.pastel(this.kitsune));
|
|
33
|
+
console.log(chalk_1.default.red("\n🔥 KITSUNE APEARS 🔥\n"));
|
|
34
|
+
const spinner = (0, ora_1.default)({
|
|
35
|
+
text: chalk_1.default.magenta("🦊 Summoning the Kitsune spirit..."),
|
|
36
|
+
spinner: "dots",
|
|
37
|
+
}).start();
|
|
38
|
+
try {
|
|
39
|
+
const res = await fetch(`https://api.api-ninjas.com/v1/jokes`, {
|
|
40
|
+
headers: {
|
|
41
|
+
"X-Api-Key": (0, apiStorage_1.getApiKey)() || "",
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
throw new Error("Failed to fetch joke");
|
|
46
|
+
}
|
|
47
|
+
const data = await res.json();
|
|
48
|
+
spinner.stop();
|
|
49
|
+
console.log(chalk_1.default.yellow(`😂 Joke: ${data[0].joke}\n`));
|
|
50
|
+
if (speak) {
|
|
51
|
+
say_1.default.speak(data[0].joke, "Kyoko");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
spinner.stop();
|
|
56
|
+
console.log(chalk_1.default.red("🌪️ The spirit could not remember a joke at this time."));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.default = Joke;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const figlet_1 = __importDefault(require("figlet"));
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const say_1 = __importDefault(require("say"));
|
|
9
|
+
const gradient_string_1 = __importDefault(require("gradient-string"));
|
|
10
|
+
class Loud {
|
|
11
|
+
constructor(program) {
|
|
12
|
+
this.kitsune = `
|
|
13
|
+
/\\_/\\
|
|
14
|
+
=( °w° )=
|
|
15
|
+
) (
|
|
16
|
+
(__ __)
|
|
17
|
+
`;
|
|
18
|
+
this.program = program;
|
|
19
|
+
}
|
|
20
|
+
register() {
|
|
21
|
+
this.program
|
|
22
|
+
.command("loud <text> [speak]")
|
|
23
|
+
.description("Make the Kitsune shout your message across the digital realm")
|
|
24
|
+
.action((text, speak) => this.loud(text, speak));
|
|
25
|
+
}
|
|
26
|
+
async loud(text, speak) {
|
|
27
|
+
console.log(gradient_string_1.default.pastel(this.kitsune));
|
|
28
|
+
console.log(chalk_1.default.red("\n🔥 KITSUNE PROCLAMATION 🔥\n"));
|
|
29
|
+
(0, figlet_1.default)(text.toUpperCase(), { font: "ANSI Shadow" }, (err, data) => {
|
|
30
|
+
console.log(gradient_string_1.default.passion(data));
|
|
31
|
+
if (speak) {
|
|
32
|
+
say_1.default.speak(text, "Kyoko", 1.8);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.default = Loud;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const gradient_string_1 = __importDefault(require("gradient-string"));
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
const boxen_1 = __importDefault(require("boxen"));
|
|
10
|
+
const apiStorage_1 = require("./apiStorage");
|
|
11
|
+
class Riddle {
|
|
12
|
+
constructor(program) {
|
|
13
|
+
this.kitsune = `
|
|
14
|
+
/\\_/\\
|
|
15
|
+
=( °w° )=
|
|
16
|
+
) (
|
|
17
|
+
(__ __)
|
|
18
|
+
`;
|
|
19
|
+
this.program = program;
|
|
20
|
+
}
|
|
21
|
+
register() {
|
|
22
|
+
this.program
|
|
23
|
+
.command("riddle <timer>")
|
|
24
|
+
.description("The Kitsune spirit shares a mysterious riddle")
|
|
25
|
+
.action((timer) => this.startrRiddle(timer));
|
|
26
|
+
}
|
|
27
|
+
async startrRiddle(timer) {
|
|
28
|
+
if (!(0, apiStorage_1.getApiKey)()) {
|
|
29
|
+
console.log(chalk_1.default.red("\nYou have to first write kit init <apikey>\n"));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
console.log(gradient_string_1.default.pastel(this.kitsune));
|
|
34
|
+
console.log(chalk_1.default.red(`\n🔥 The Kitsune presents you with a riddle. You have ${timer} seconds to solve it! 🔥\n`));
|
|
35
|
+
const spinner = (0, ora_1.default)({
|
|
36
|
+
text: chalk_1.default.magenta("🦊 Summoning the Kitsune spirit..."),
|
|
37
|
+
spinner: "dots",
|
|
38
|
+
}).start();
|
|
39
|
+
const res = await fetch(`https://api.api-ninjas.com/v1/riddles`, {
|
|
40
|
+
headers: {
|
|
41
|
+
"X-Api-Key": (0, apiStorage_1.getApiKey)() || "",
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
throw new Error("Failed to fetch riddle");
|
|
46
|
+
}
|
|
47
|
+
const data = await res.json();
|
|
48
|
+
spinner.stop();
|
|
49
|
+
const riddle = data[0].question;
|
|
50
|
+
const answer = data[0].answer;
|
|
51
|
+
console.log(chalk_1.default.yellow(`🧩 Riddle: ${riddle}\n`));
|
|
52
|
+
let timeLeft = Number(timer);
|
|
53
|
+
await new Promise((resolve) => {
|
|
54
|
+
const interval = setInterval(() => {
|
|
55
|
+
console.clear();
|
|
56
|
+
const message = `
|
|
57
|
+
🧩 Riddle:
|
|
58
|
+
${riddle}
|
|
59
|
+
|
|
60
|
+
⏳ Time left: ${timeLeft}s
|
|
61
|
+
`;
|
|
62
|
+
console.log((0, boxen_1.default)(chalk_1.default.cyan(message), {
|
|
63
|
+
padding: 1,
|
|
64
|
+
borderStyle: "round",
|
|
65
|
+
borderColor: "magenta",
|
|
66
|
+
title: "🦊 Kitsune Wisdom",
|
|
67
|
+
titleAlignment: "center",
|
|
68
|
+
}));
|
|
69
|
+
timeLeft--;
|
|
70
|
+
if (timeLeft < 0) {
|
|
71
|
+
clearInterval(interval);
|
|
72
|
+
process.stdout.write("\n");
|
|
73
|
+
resolve(null);
|
|
74
|
+
}
|
|
75
|
+
}, 1000);
|
|
76
|
+
});
|
|
77
|
+
console.log(chalk_1.default.green(`💡 Answer: ${answer}`));
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error(chalk_1.default.red("An error occurred while fetching the riddle. Please try again later."));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.default = Riddle;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const say_1 = __importDefault(require("say"));
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
const gradient_string_1 = __importDefault(require("gradient-string"));
|
|
10
|
+
class Speak {
|
|
11
|
+
constructor(program) {
|
|
12
|
+
this.kitsune = `
|
|
13
|
+
/\\_/\\
|
|
14
|
+
=( °w° )=
|
|
15
|
+
) (
|
|
16
|
+
(__ __)
|
|
17
|
+
`;
|
|
18
|
+
this.program = program;
|
|
19
|
+
}
|
|
20
|
+
register() {
|
|
21
|
+
this.program
|
|
22
|
+
.command("speak <text>")
|
|
23
|
+
.description("Have the Kitsune channel ancient wisdom and speak your words aloud")
|
|
24
|
+
.action((text) => this.talk(text));
|
|
25
|
+
}
|
|
26
|
+
talk(text) {
|
|
27
|
+
console.log(gradient_string_1.default.pastel(this.kitsune));
|
|
28
|
+
const spinner = (0, ora_1.default)({
|
|
29
|
+
text: chalk_1.default.cyan("The Kitsune is channeling ancient wisdom..."),
|
|
30
|
+
spinner: "dots",
|
|
31
|
+
}).start();
|
|
32
|
+
setTimeout(() => {
|
|
33
|
+
spinner.stop();
|
|
34
|
+
console.log(chalk_1.default.yellow(`🦊 ${text}`));
|
|
35
|
+
say_1.default.speak(text, "Kyoko");
|
|
36
|
+
}, 3000);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.default = Speak;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
7
|
+
const say_1 = __importDefault(require("say"));
|
|
8
|
+
const boxen_1 = __importDefault(require("boxen"));
|
|
9
|
+
const gradient_string_1 = __importDefault(require("gradient-string"));
|
|
10
|
+
const ora_1 = __importDefault(require("ora"));
|
|
11
|
+
const apiStorage_1 = require("./apiStorage");
|
|
12
|
+
class Spirit {
|
|
13
|
+
constructor(program) {
|
|
14
|
+
this.program = program;
|
|
15
|
+
}
|
|
16
|
+
register() {
|
|
17
|
+
this.program
|
|
18
|
+
.command("spirit [speak]")
|
|
19
|
+
.description("Summon the Kitsune spirit to receive quotes of philosophy and truth")
|
|
20
|
+
.action((speak) => this.invoke(speak));
|
|
21
|
+
}
|
|
22
|
+
async invoke(speak) {
|
|
23
|
+
if (!(0, apiStorage_1.getApiKey)()) {
|
|
24
|
+
console.log(chalk_1.default.red("\nYou have to first write kit init <apikey>\n"));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const spinner = (0, ora_1.default)({
|
|
29
|
+
text: chalk_1.default.magenta("🦊 Summoning the Kitsune spirit..."),
|
|
30
|
+
spinner: "dots",
|
|
31
|
+
}).start();
|
|
32
|
+
const categories = [
|
|
33
|
+
"wisdom",
|
|
34
|
+
"philosophy",
|
|
35
|
+
"life",
|
|
36
|
+
"truth",
|
|
37
|
+
"inspirational",
|
|
38
|
+
"relationships",
|
|
39
|
+
"love",
|
|
40
|
+
"faith",
|
|
41
|
+
"humor",
|
|
42
|
+
"success",
|
|
43
|
+
"courage",
|
|
44
|
+
"happiness",
|
|
45
|
+
"art",
|
|
46
|
+
"writing",
|
|
47
|
+
"fear",
|
|
48
|
+
"nature",
|
|
49
|
+
"time",
|
|
50
|
+
"freedom",
|
|
51
|
+
"death",
|
|
52
|
+
"leadership",
|
|
53
|
+
];
|
|
54
|
+
const shuffled = [...categories].sort(() => 0.5 - Math.random());
|
|
55
|
+
const count = Math.floor(Math.random() * 3) + 1;
|
|
56
|
+
const selected = shuffled.slice(0, count);
|
|
57
|
+
const categoryParam = encodeURIComponent(selected.join(","));
|
|
58
|
+
const res = await fetch(`https://api.api-ninjas.com/v2/quotes?categories=${categoryParam}`, {
|
|
59
|
+
headers: {
|
|
60
|
+
"X-Api-Key": (0, apiStorage_1.getApiKey)() || "",
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
const data = await res.json();
|
|
64
|
+
spinner.stop();
|
|
65
|
+
const quote = data[0].quote;
|
|
66
|
+
const author = data[0].author;
|
|
67
|
+
const fox = `
|
|
68
|
+
/\\_/\\
|
|
69
|
+
=( °w° )=
|
|
70
|
+
) (
|
|
71
|
+
(__ __)
|
|
72
|
+
`;
|
|
73
|
+
console.log(gradient_string_1.default.pastel(fox));
|
|
74
|
+
const message = `
|
|
75
|
+
"${quote}"
|
|
76
|
+
|
|
77
|
+
— ${author}
|
|
78
|
+
`;
|
|
79
|
+
console.log((0, boxen_1.default)(chalk_1.default.cyan(message), {
|
|
80
|
+
padding: 1,
|
|
81
|
+
borderStyle: "round",
|
|
82
|
+
borderColor: "magenta",
|
|
83
|
+
title: "🦊 Kitsune Wisdom",
|
|
84
|
+
titleAlignment: "center",
|
|
85
|
+
}));
|
|
86
|
+
console.log(chalk_1.default.gray("\n✨ The fox spirit fades into the forest...\n"));
|
|
87
|
+
if (speak) {
|
|
88
|
+
say_1.default.speak(quote, "Kyoko");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
console.log("🦊 The spirit could not be summoned...");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.default = Spirit;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
7
|
+
const gradient_string_1 = __importDefault(require("gradient-string"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
const boxen_1 = __importDefault(require("boxen"));
|
|
10
|
+
const say_1 = __importDefault(require("say"));
|
|
11
|
+
const weatherReplies = {
|
|
12
|
+
"Haze": "A mystical veil blurs the horizon. The kitsune's eyes glow through the haze.",
|
|
13
|
+
"Rain with thunderstorm": "Lightning cracks the weeping sky! The fox seeks the safety of the deep woods.",
|
|
14
|
+
"Haze, rain with thunderstorm": "A mystical veil blurs the horizon as lightning cracks the weeping sky! The fox seeks the safety of the deep woods.",
|
|
15
|
+
"Sunny": "The fox lounges in golden warmth, tail curled in bliss. The heavens smile upon your journey today.",
|
|
16
|
+
"Clear": "Not a single cloud dares interrupt the sky. The spirit realm is open — your path is unobstructed.",
|
|
17
|
+
"Partly Cloudy": "The sun plays hide and seek with the clouds. Even the sky cannot make up its mind today.",
|
|
18
|
+
"Partly cloudy": "The sun plays hide and seek with the clouds. Even the sky cannot make up its mind today.",
|
|
19
|
+
"Cloudy": "The heavens have drawn grey curtains across the sky. The fox watches from the shadows.",
|
|
20
|
+
"Overcast": "A heavy blanket smothers the sky. The spirits are in deep thought. Tread quietly today.",
|
|
21
|
+
"Mist": "The veil between realms grows thin. Walk carefully — not all that moves in the mist is of this world.",
|
|
22
|
+
"Fog": "The fox vanishes into the white silence. The world beyond ten steps is a mystery.",
|
|
23
|
+
"Freezing Fog": "Frozen spirits drift through the air. The cold bites and blinds. Even the fox stays close to warmth.",
|
|
24
|
+
"Freezing fog": "Frozen spirits drift through the air. The cold bites and blinds. Even the fox stays close to warmth.",
|
|
25
|
+
"Patchy rain possible": "The fox flicks its ears. A few droplets dance nearby — not enough to drench, just enough to tease.",
|
|
26
|
+
"Patchy rain nearby": "The fox flicks its ears. A few droplets dance nearby — not enough to drench, just enough to tease.",
|
|
27
|
+
"Light drizzle": "The sky weeps softly, barely a whisper of rain. The fox does not even bother to find shelter.",
|
|
28
|
+
"Rain": "The spirits cleanse the earth. The fox dances in the refreshing downpour.",
|
|
29
|
+
"Light rain": "Tears from the sky fall gently. The earth drinks quietly under the fox's watchful gaze.",
|
|
30
|
+
"Moderate rain": "A steady rhythm of water from the heavens. The foxes are singing to the rainfall.",
|
|
31
|
+
"Heavy rain": "The skies roar with watery fury. The kitsune seeks refuge until the storm passes.",
|
|
32
|
+
"Snow": "Glistening white dust falls from the heavens. The fox leaves delicate tracks in the fresh snow.",
|
|
33
|
+
"Light snow": "Tiny crystalline spirits dance down. The fox tries to catch them on its nose.",
|
|
34
|
+
"Heavy snow": "The world is buried in a deep, silent white slumber. The kitsune wanders through the frozen dream.",
|
|
35
|
+
"Thunderstorm": "The sky gods' drums beat fiercely! The fox's fur stands on end with electric energy.",
|
|
36
|
+
"Thundery outbreaks in nearby": "Distant rumblings echo. The spirits are restless, warning of a coming storm.",
|
|
37
|
+
"Thundery outbreaks possible": "Distant rumblings echo. The spirits are restless, warning of a coming storm.",
|
|
38
|
+
"Blowing snow": "The fierce winds scatter the frozen crystals like fleeing spirits.",
|
|
39
|
+
"Blizzard": "A terrible frozen tempest! The kitsune has long sought the safety of its den.",
|
|
40
|
+
};
|
|
41
|
+
const windDirections = {
|
|
42
|
+
"N": "North",
|
|
43
|
+
"NNE": "North-Northeast",
|
|
44
|
+
"NE": "Northeast",
|
|
45
|
+
"ENE": "East-Northeast",
|
|
46
|
+
"E": "East",
|
|
47
|
+
"ESE": "East-Southeast",
|
|
48
|
+
"SE": "Southeast",
|
|
49
|
+
"SSE": "South-Southeast",
|
|
50
|
+
"S": "South",
|
|
51
|
+
"SSW": "South-Southwest",
|
|
52
|
+
"SW": "Southwest",
|
|
53
|
+
"WSW": "West-Southwest",
|
|
54
|
+
"W": "West",
|
|
55
|
+
"WNW": "West-Northwest",
|
|
56
|
+
"NW": "Northwest",
|
|
57
|
+
"NNW": "North-Northwest"
|
|
58
|
+
};
|
|
59
|
+
class Weather {
|
|
60
|
+
constructor(program) {
|
|
61
|
+
this.kitsune = `
|
|
62
|
+
/\\_/\\
|
|
63
|
+
=( °w° )=
|
|
64
|
+
) (
|
|
65
|
+
(__ __)
|
|
66
|
+
`;
|
|
67
|
+
this.program = program;
|
|
68
|
+
}
|
|
69
|
+
register() {
|
|
70
|
+
this.program
|
|
71
|
+
.command("weather [location] [speak]")
|
|
72
|
+
.description("Read the winds and skies for any location")
|
|
73
|
+
.action((location, speak) => this.readWinds(location, speak));
|
|
74
|
+
}
|
|
75
|
+
async readWinds(locationArg, speakArg) {
|
|
76
|
+
var _a, _b;
|
|
77
|
+
let location = locationArg;
|
|
78
|
+
let speak = false;
|
|
79
|
+
if (locationArg === "speak") {
|
|
80
|
+
location = "";
|
|
81
|
+
speak = true;
|
|
82
|
+
}
|
|
83
|
+
else if (speakArg === "speak") {
|
|
84
|
+
speak = true;
|
|
85
|
+
}
|
|
86
|
+
console.log(gradient_string_1.default.pastel(this.kitsune));
|
|
87
|
+
console.log(chalk_1.default.cyan("\n☁️ THE SPIRIT READS THE WINDS ☁️\n"));
|
|
88
|
+
const spinner = (0, ora_1.default)({
|
|
89
|
+
text: chalk_1.default.blue("🦊 The Kitsune is seeking the weather signs..."),
|
|
90
|
+
spinner: "dots",
|
|
91
|
+
}).start();
|
|
92
|
+
try {
|
|
93
|
+
const query = location ? encodeURIComponent(location) : "";
|
|
94
|
+
const res = await fetch(`https://wttr.in/${query}?format=j1`);
|
|
95
|
+
if (!res.ok) {
|
|
96
|
+
throw new Error("The winds are obscured.");
|
|
97
|
+
}
|
|
98
|
+
const data = await res.json();
|
|
99
|
+
spinner.stop();
|
|
100
|
+
const current = data.current_condition[0];
|
|
101
|
+
const area = data.nearest_area[0].areaName[0].value;
|
|
102
|
+
const temp = current.temp_C;
|
|
103
|
+
const desc = current.weatherDesc[0].value;
|
|
104
|
+
const windDirCode = current.winddir16Point;
|
|
105
|
+
const windDir = (_a = windDirections[windDirCode]) !== null && _a !== void 0 ? _a : windDirCode;
|
|
106
|
+
const windSpeed = current.windspeedKmph;
|
|
107
|
+
const reply = (_b = weatherReplies[desc]) !== null && _b !== void 0 ? _b : "The fox peers at the sky, but the spirits reveal nothing familiar.";
|
|
108
|
+
const mysticalWeather = `The winds over ${chalk_1.default.yellow(area)} reveal ${chalk_1.default.magenta(desc.toLowerCase())}. \n${chalk_1.default.italic(reply)}\n\nStill, feel the air at ${chalk_1.default.green(temp + '°C')}, as the winds from the ${chalk_1.default.cyan(windDir)} travels at ${chalk_1.default.cyan(windSpeed + ' km/h')}.`;
|
|
109
|
+
const spokenText = `The winds over ${area} reveal ${desc.toLowerCase()}. ${reply} Still, feel the air at ${temp} degrees Celsius, as the winds from the ${windDir} travels at ${windSpeed} kilometers per hour.`;
|
|
110
|
+
console.log((0, boxen_1.default)(mysticalWeather, {
|
|
111
|
+
padding: 1,
|
|
112
|
+
borderStyle: "round",
|
|
113
|
+
borderColor: "cyan",
|
|
114
|
+
}));
|
|
115
|
+
if (speak) {
|
|
116
|
+
say_1.default.speak(spokenText, "Kyoko");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
spinner.stop();
|
|
121
|
+
console.log(chalk_1.default.red("🌪️ The spirit could not discern the weather at this time."));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.default = Weather;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
7
|
+
const gradient_string_1 = __importDefault(require("gradient-string"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
const boxen_1 = __importDefault(require("boxen"));
|
|
10
|
+
const readline_1 = __importDefault(require("readline"));
|
|
11
|
+
const fox = `
|
|
12
|
+
/\\_/\\
|
|
13
|
+
=( °w° )=
|
|
14
|
+
) (
|
|
15
|
+
(__ __)
|
|
16
|
+
`;
|
|
17
|
+
class Wordel {
|
|
18
|
+
constructor(program) {
|
|
19
|
+
this.program = program;
|
|
20
|
+
}
|
|
21
|
+
register() {
|
|
22
|
+
this.program
|
|
23
|
+
.command("wordel [wordlength]")
|
|
24
|
+
.description("Play a game of Wordel")
|
|
25
|
+
.action((wordlength) => this.playWordel(wordlength));
|
|
26
|
+
}
|
|
27
|
+
async playWordel(wordlength) {
|
|
28
|
+
let length = wordlength !== null && wordlength !== void 0 ? wordlength : 5;
|
|
29
|
+
if (isNaN(length) || length < 3 || length > 8) {
|
|
30
|
+
console.log(chalk_1.default.yellow(`⚠ Word length must be between 3 and 8. Defaulting to 5.`));
|
|
31
|
+
length = 5;
|
|
32
|
+
}
|
|
33
|
+
console.log(gradient_string_1.default.cristal(fox));
|
|
34
|
+
console.log(chalk_1.default.italic.magentaBright(` ✦ Now the ancient game of Wordel begins... ✦\n`));
|
|
35
|
+
console.log((0, boxen_1.default)(gradient_string_1.default.pastel(` W O R D E L \n`) +
|
|
36
|
+
chalk_1.default.gray(` Guess the ${length}-letter word in 6 tries`), { padding: 1, borderStyle: "round", borderColor: "cyan" }));
|
|
37
|
+
const spinner = (0, ora_1.default)("Fetching a secret word...").start();
|
|
38
|
+
let secret;
|
|
39
|
+
try {
|
|
40
|
+
const res = await fetch(`https://random-word-api.herokuapp.com/word?length=${length}`);
|
|
41
|
+
const data = await res.json();
|
|
42
|
+
secret = data[0].toUpperCase();
|
|
43
|
+
spinner.succeed(chalk_1.default.green("Secret word ready!"));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
spinner.fail(chalk_1.default.red("Failed to fetch word. Check your connection."));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const rl = readline_1.default.createInterface({ input: process.stdin, output: process.stdout });
|
|
50
|
+
const ask = (q) => new Promise((r) => rl.question(q, r));
|
|
51
|
+
const history = [];
|
|
52
|
+
for (let attempt = 1; attempt <= 6; attempt++) {
|
|
53
|
+
console.log(chalk_1.default.dim(`\nAttempt ${attempt}/6`));
|
|
54
|
+
let guess = "";
|
|
55
|
+
while (true) {
|
|
56
|
+
guess = (await ask(chalk_1.default.cyan(`Enter a ${length}-letter word: `))).trim().toUpperCase();
|
|
57
|
+
if (guess.length !== length) {
|
|
58
|
+
console.log(chalk_1.default.red(`Must be exactly ${length} letters.`));
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const valSpinner = (0, ora_1.default)("Validating word...").start();
|
|
62
|
+
try {
|
|
63
|
+
const res = await fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${guess.toLowerCase()}`);
|
|
64
|
+
if (res.ok) {
|
|
65
|
+
valSpinner.succeed(chalk_1.default.green("Valid word!"));
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
valSpinner.fail(chalk_1.default.red("Not a valid word. Try again."));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
valSpinner.warn(chalk_1.default.yellow("Could not validate — accepting anyway."));
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const row = this.buildRow(guess, secret);
|
|
78
|
+
history.forEach((r) => console.log(r));
|
|
79
|
+
console.log(row);
|
|
80
|
+
history.push(row);
|
|
81
|
+
if (guess === secret) {
|
|
82
|
+
console.log((0, boxen_1.default)(gradient_string_1.default.rainbow(`🎉 You got it in ${attempt}!`), { padding: 1, borderColor: "green", borderStyle: "double" }));
|
|
83
|
+
rl.close();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
console.log((0, boxen_1.default)(chalk_1.default.red(`💀 Out of attempts!\nThe word was: `) + chalk_1.default.bold.white(secret), { padding: 1, borderColor: "red", borderStyle: "round" }));
|
|
88
|
+
rl.close();
|
|
89
|
+
}
|
|
90
|
+
buildRow(guess, secret) {
|
|
91
|
+
return guess
|
|
92
|
+
.split("")
|
|
93
|
+
.map((ch, i) => {
|
|
94
|
+
if (ch === secret[i])
|
|
95
|
+
return chalk_1.default.bgGreen.black(` ${ch} `);
|
|
96
|
+
if (secret.includes(ch))
|
|
97
|
+
return chalk_1.default.bgYellow.black(` ${ch} `);
|
|
98
|
+
return chalk_1.default.bgGray.white(` ${ch} `);
|
|
99
|
+
})
|
|
100
|
+
.join(" ");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.default = Wordel;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const cli_engin_1 = __importDefault(require("./cli_engin/cli_engin"));
|
|
8
|
+
const speak_1 = __importDefault(require("./commands/speak"));
|
|
9
|
+
const help_1 = __importDefault(require("./commands/help"));
|
|
10
|
+
const spirit_1 = __importDefault(require("./commands/spirit"));
|
|
11
|
+
const loud_1 = __importDefault(require("./commands/loud"));
|
|
12
|
+
const wordel_1 = __importDefault(require("./commands/wordel"));
|
|
13
|
+
const riddle_1 = __importDefault(require("./commands/riddle"));
|
|
14
|
+
const joke_1 = __importDefault(require("./commands/joke"));
|
|
15
|
+
const weather_1 = __importDefault(require("./commands/weather"));
|
|
16
|
+
const init_1 = __importDefault(require("./commands/init"));
|
|
17
|
+
const cli = new cli_engin_1.default();
|
|
18
|
+
cli.registerCommand([speak_1.default, help_1.default, spirit_1.default, loud_1.default, wordel_1.default, riddle_1.default, joke_1.default, weather_1.default, init_1.default]);
|
|
19
|
+
cli.run();
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kitsune-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A magical Fox Spirit CLI tool offering wisdom, jokes, riddles, weather, and more.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist/",
|
|
8
|
+
"README.md"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc && chmod +x dist/index.js",
|
|
12
|
+
"prepare": "npm run build",
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/bhavish-codes/Kitsune-cli.git"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"cli",
|
|
21
|
+
"kitsune",
|
|
22
|
+
"fox",
|
|
23
|
+
"spirit",
|
|
24
|
+
"weather",
|
|
25
|
+
"riddle",
|
|
26
|
+
"joke"
|
|
27
|
+
],
|
|
28
|
+
"author": "bhavish dhar",
|
|
29
|
+
"license": "ISC",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/bhavish-codes/Kitsune-cli/issues"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/bhavish-codes/Kitsune-cli#readme",
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^25.3.3",
|
|
36
|
+
"nodemon": "^3.1.14",
|
|
37
|
+
"ts-node": "^10.9.2",
|
|
38
|
+
"typescript": "^5.9.3"
|
|
39
|
+
},
|
|
40
|
+
"bin": {
|
|
41
|
+
"kit": "dist/index.js"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"boxen": "^8.0.1",
|
|
45
|
+
"chalk": "^5.6.2",
|
|
46
|
+
"commander": "^14.0.3",
|
|
47
|
+
"dotenv": "^17.3.1",
|
|
48
|
+
"figlet": "^1.10.0",
|
|
49
|
+
"gradient-string": "^3.0.0",
|
|
50
|
+
"ora": "^9.3.0",
|
|
51
|
+
"say": "^0.16.0"
|
|
52
|
+
}
|
|
53
|
+
}
|