@ihsandeen/aya 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/CONTRIBUTING.md +39 -0
- package/LICENSE +21 -0
- package/README.md +141 -0
- package/dist/commands/adab.js +28 -0
- package/dist/commands/adhan.js +58 -0
- package/dist/commands/anatomy.js +29 -0
- package/dist/commands/blame.js +29 -0
- package/dist/commands/commit.js +44 -0
- package/dist/commands/diff.js +54 -0
- package/dist/commands/dua.js +34 -0
- package/dist/commands/fast.js +36 -0
- package/dist/commands/friday.js +21 -0
- package/dist/commands/hero.js +69 -0
- package/dist/commands/hijri.js +42 -0
- package/dist/commands/history.js +98 -0
- package/dist/commands/init.js +54 -0
- package/dist/commands/invest.js +26 -0
- package/dist/commands/journal.js +84 -0
- package/dist/commands/journey.js +24 -0
- package/dist/commands/lens.js +58 -0
- package/dist/commands/memorize.js +117 -0
- package/dist/commands/mirror.js +47 -0
- package/dist/commands/names.js +48 -0
- package/dist/commands/nature.js +28 -0
- package/dist/commands/nazm.js +100 -0
- package/dist/commands/parable.js +332 -0
- package/dist/commands/prayers.js +63 -0
- package/dist/commands/pull.js +28 -0
- package/dist/commands/push.js +156 -0
- package/dist/commands/qibla.js +118 -0
- package/dist/commands/repo.js +34 -0
- package/dist/commands/sabr.js +32 -0
- package/dist/commands/scene.js +54 -0
- package/dist/commands/seek.js +28 -0
- package/dist/commands/shukr.js +22 -0
- package/dist/commands/sleep.js +26 -0
- package/dist/commands/sound.js +35 -0
- package/dist/commands/status.js +109 -0
- package/dist/commands/sunnah.js +24 -0
- package/dist/commands/tafsir.js +89 -0
- package/dist/commands/tasbih.js +50 -0
- package/dist/commands/wudu.js +22 -0
- package/dist/commands/zakat.js +72 -0
- package/dist/data/commands-db.js +365 -0
- package/dist/data/events.js +105 -0
- package/dist/data/gems.js +160 -0
- package/dist/data/nak.js +616 -0
- package/dist/data/tafsir.js +157 -0
- package/dist/data/vocab.js +105 -0
- package/dist/index.js +86 -0
- package/dist/server.js +140 -0
- package/dist/utils/config.js +38 -0
- package/dist/utils/logger.js +104 -0
- package/dist/utils/printer.js +36 -0
- package/docs/index.html +1048 -0
- package/docs/repo.html +952 -0
- package/package.json +55 -0
- package/public/hero.html +285 -0
- package/public/index.html +1039 -0
- package/public/repo.html +904 -0
- package/src/commands/adab.ts +24 -0
- package/src/commands/adhan.ts +55 -0
- package/src/commands/anatomy.ts +25 -0
- package/src/commands/blame.ts +31 -0
- package/src/commands/commit.ts +42 -0
- package/src/commands/diff.ts +56 -0
- package/src/commands/dua.ts +34 -0
- package/src/commands/fast.ts +35 -0
- package/src/commands/friday.ts +17 -0
- package/src/commands/hero.ts +73 -0
- package/src/commands/hijri.ts +43 -0
- package/src/commands/history.ts +103 -0
- package/src/commands/init.ts +53 -0
- package/src/commands/invest.ts +22 -0
- package/src/commands/journal.ts +97 -0
- package/src/commands/journey.ts +20 -0
- package/src/commands/lens.ts +58 -0
- package/src/commands/memorize.ts +131 -0
- package/src/commands/mirror.ts +48 -0
- package/src/commands/names.ts +46 -0
- package/src/commands/nature.ts +24 -0
- package/src/commands/nazm.ts +102 -0
- package/src/commands/parable.ts +360 -0
- package/src/commands/prayers.ts +65 -0
- package/src/commands/pull.ts +28 -0
- package/src/commands/push.ts +171 -0
- package/src/commands/qibla.ts +127 -0
- package/src/commands/repo.ts +34 -0
- package/src/commands/sabr.ts +28 -0
- package/src/commands/scene.ts +56 -0
- package/src/commands/seek.ts +24 -0
- package/src/commands/shukr.ts +19 -0
- package/src/commands/sleep.ts +23 -0
- package/src/commands/sound.ts +34 -0
- package/src/commands/status.ts +132 -0
- package/src/commands/sunnah.ts +21 -0
- package/src/commands/tafsir.ts +86 -0
- package/src/commands/tasbih.ts +49 -0
- package/src/commands/wudu.ts +19 -0
- package/src/commands/zakat.ts +73 -0
- package/src/data/commands-db.ts +372 -0
- package/src/data/events.ts +113 -0
- package/src/data/gems.ts +163 -0
- package/src/data/nak.ts +805 -0
- package/src/data/tafsir.ts +165 -0
- package/src/data/vocab.ts +114 -0
- package/src/index.ts +94 -0
- package/src/server.ts +128 -0
- package/src/utils/config.ts +44 -0
- package/src/utils/logger.ts +122 -0
- package/src/utils/printer.ts +38 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import { adabData } from '../data/nak';
|
|
5
|
+
import { printCommandHeader } from '../utils/printer';
|
|
6
|
+
|
|
7
|
+
export const adabCommand = new Command('adab')
|
|
8
|
+
.description('The Manners Engine (Relationships)')
|
|
9
|
+
.action(async () => {
|
|
10
|
+
printCommandHeader('adab');
|
|
11
|
+
const { relation } = await inquirer.prompt([{
|
|
12
|
+
type: 'list',
|
|
13
|
+
name: 'relation',
|
|
14
|
+
message: 'Select a relationship to improve:',
|
|
15
|
+
choices: adabData.map(r => r.relation)
|
|
16
|
+
}]);
|
|
17
|
+
|
|
18
|
+
const data = adabData.find(r => r.relation === relation);
|
|
19
|
+
if (data) {
|
|
20
|
+
console.log(chalk.blue.bold(`\n Relationship: ${data.relation}`));
|
|
21
|
+
console.log(chalk.yellow(` Quranic Keyword: ${data.arabicKeyword} (${data.meaning})`));
|
|
22
|
+
console.log(chalk.white(` Practice: ${data.practice}\n`));
|
|
23
|
+
}
|
|
24
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import { exec } from 'child_process';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
import { printCommandHeader } from '../utils/printer';
|
|
7
|
+
|
|
8
|
+
export const adhanCommand = new Command('adhan')
|
|
9
|
+
.description('Call to Prayer (Adhan) - Plays audio or shows text')
|
|
10
|
+
.option('-s, --silent', 'Show text only, do not play audio')
|
|
11
|
+
.action(async (options) => {
|
|
12
|
+
printCommandHeader('adhan');
|
|
13
|
+
console.log(chalk.green.bold('\n Allahu Akbar, Allahu Akbar\n'));
|
|
14
|
+
|
|
15
|
+
const lines = [
|
|
16
|
+
{ arabic: 'الله أكبر الله أكبر', translation: 'God is the Greatest, God is the Greatest' },
|
|
17
|
+
{ arabic: 'أشهد أن لا إله إلا الله', translation: 'I bear witness that there is no god except God' },
|
|
18
|
+
{ arabic: 'أشهد أن محمدا رسول الله', translation: 'I bear witness that Muhammad is the Messenger of God' },
|
|
19
|
+
{ arabic: 'حي على الصلاة', translation: 'Hasten to the prayer' },
|
|
20
|
+
{ arabic: 'حي على الفلاح', translation: 'Hasten to success' },
|
|
21
|
+
{ arabic: 'الله أكبر الله أكبر', translation: 'God is the Greatest, God is the Greatest' },
|
|
22
|
+
{ arabic: 'لا إله إلا الله', translation: 'There is no god except God' }
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
// Print Adhan beautifully with delays
|
|
26
|
+
for (const line of lines) {
|
|
27
|
+
console.log(chalk.yellow.bold(line.arabic));
|
|
28
|
+
console.log(chalk.gray(line.translation));
|
|
29
|
+
console.log('');
|
|
30
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!options.silent) {
|
|
34
|
+
const spinner = ora('Playing Adhan...').start();
|
|
35
|
+
|
|
36
|
+
// Attempt to play a system sound
|
|
37
|
+
try {
|
|
38
|
+
if (os.platform() === 'darwin') {
|
|
39
|
+
// macOS
|
|
40
|
+
exec('afplay /System/Library/Sounds/Glass.aiff');
|
|
41
|
+
} else if (os.platform() === 'linux') {
|
|
42
|
+
// Linux (try paplay or aplay)
|
|
43
|
+
exec('paplay /usr/share/sounds/freedesktop/stereo/complete.oga || aplay /usr/share/sounds/alsa/Front_Center.wav');
|
|
44
|
+
} else if (os.platform() === 'win32') {
|
|
45
|
+
// Windows
|
|
46
|
+
// PowerShell beep
|
|
47
|
+
exec('powershell -c "(New-Object Media.SoundPlayer \'C:\\Windows\\Media\\notify.wav\').PlaySync();"');
|
|
48
|
+
}
|
|
49
|
+
} catch (e) {
|
|
50
|
+
// Ignore errors if sound fails
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
spinner.succeed('Adhan completed.');
|
|
54
|
+
}
|
|
55
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import { anatomyData } from '../data/nak';
|
|
5
|
+
import { printCommandHeader } from '../utils/printer';
|
|
6
|
+
|
|
7
|
+
export const anatomyCommand = new Command('anatomy')
|
|
8
|
+
.description('The Spiritual Function of Body Parts')
|
|
9
|
+
.action(async () => {
|
|
10
|
+
printCommandHeader('anatomy');
|
|
11
|
+
const { part } = await inquirer.prompt([{
|
|
12
|
+
type: 'list',
|
|
13
|
+
name: 'part',
|
|
14
|
+
message: 'Select a body part to understand its spiritual role:',
|
|
15
|
+
choices: anatomyData.map(p => p.part)
|
|
16
|
+
}]);
|
|
17
|
+
|
|
18
|
+
const data = anatomyData.find(p => p.part === part);
|
|
19
|
+
if (data) {
|
|
20
|
+
console.log(chalk.blue.bold(`\n ${data.part} (${data.arabic})`));
|
|
21
|
+
console.log(chalk.white(` Function: ${data.function}`));
|
|
22
|
+
console.log(chalk.green(` Spiritual Role: ${data.spiritualRole}`));
|
|
23
|
+
console.log(chalk.gray(`\n Reflection:\n ${data.reflection}\n`));
|
|
24
|
+
}
|
|
25
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { printCommandHeader } from '../utils/printer';
|
|
4
|
+
import boxen from 'boxen';
|
|
5
|
+
|
|
6
|
+
export const blameCommand = new Command('blame')
|
|
7
|
+
.description('Self-reflection tool (Muhasabah)')
|
|
8
|
+
.action(() => {
|
|
9
|
+
printCommandHeader('blame');
|
|
10
|
+
|
|
11
|
+
console.log(
|
|
12
|
+
boxen(
|
|
13
|
+
chalk.red.bold(' git blame? No. ') + '\n' +
|
|
14
|
+
chalk.yellow(" It wasn't the compiler. It wasn't the PM. ") + '\n\n' +
|
|
15
|
+
chalk.white.italic('"Nay, man is evidence against himself." (75:14)'),
|
|
16
|
+
{
|
|
17
|
+
padding: 1,
|
|
18
|
+
margin: 1,
|
|
19
|
+
borderStyle: 'double',
|
|
20
|
+
borderColor: 'red',
|
|
21
|
+
title: 'Muhasabah (Self-Audit)',
|
|
22
|
+
titleAlignment: 'center'
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
console.log(chalk.cyan(' ➜ Take a breath.'));
|
|
28
|
+
console.log(chalk.cyan(' ➜ Say Astaghfirullah.'));
|
|
29
|
+
console.log(chalk.cyan(' ➜ Debug with a clear heart.'));
|
|
30
|
+
console.log('');
|
|
31
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { printCommandHeader } from '../utils/printer';
|
|
5
|
+
import { logger } from '../utils/logger';
|
|
6
|
+
|
|
7
|
+
export const commitCommand = new Command('commit')
|
|
8
|
+
.description('Commit a good deed or intention')
|
|
9
|
+
.option('-m, --message <message>', 'The deed you commit to')
|
|
10
|
+
.action(async (options) => {
|
|
11
|
+
printCommandHeader('commit');
|
|
12
|
+
let message = options.message;
|
|
13
|
+
|
|
14
|
+
if (!message) {
|
|
15
|
+
const answers = await inquirer.prompt([
|
|
16
|
+
{
|
|
17
|
+
type: 'input',
|
|
18
|
+
name: 'message',
|
|
19
|
+
message: 'What good deed are you committing to today?',
|
|
20
|
+
validate: (input) => input.length > 0 ? true : 'Please enter a valid commitment.'
|
|
21
|
+
}
|
|
22
|
+
]);
|
|
23
|
+
message = answers.message;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Log the commit using our new utility
|
|
27
|
+
const commit = logger.logCommit(message);
|
|
28
|
+
const totalDeeds = logger.getTotalDeeds();
|
|
29
|
+
|
|
30
|
+
// NAK Style Output
|
|
31
|
+
console.log(chalk.gray(`[main ${commit.hash}] Commit confirmed.`));
|
|
32
|
+
console.log(chalk.green(' Angels are recording. 📝'));
|
|
33
|
+
console.log(chalk.cyan(` + 1 good deed added to your scale.`));
|
|
34
|
+
|
|
35
|
+
// Encouragement based on total deeds
|
|
36
|
+
let encouragement = "";
|
|
37
|
+
if (totalDeeds % 10 === 0) encouragement = chalk.yellow.bold(" MashaAllah! A milestone reached!");
|
|
38
|
+
else if (totalDeeds === 1) encouragement = chalk.yellow.bold(" Bismillah! Your first step.");
|
|
39
|
+
|
|
40
|
+
console.log(chalk.white(` Total good deeds recorded: ${chalk.bold(totalDeeds)}`) + encouragement);
|
|
41
|
+
console.log(chalk.dim('\n"Verily, the good deeds remove the evil deeds." (11:114)'));
|
|
42
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import { diffData } from '../data/nak';
|
|
5
|
+
import { printCommandHeader } from '../utils/printer';
|
|
6
|
+
|
|
7
|
+
export const diffCommand = new Command('diff')
|
|
8
|
+
.description('The "Almost" Word (Synonym Challenge)')
|
|
9
|
+
.action(async () => {
|
|
10
|
+
printCommandHeader('diff');
|
|
11
|
+
console.clear();
|
|
12
|
+
console.log(chalk.yellow.bold('\n Aya Diff: The Precision of Divine Speech'));
|
|
13
|
+
console.log(chalk.gray('Why did Allah use *this* word and not *that* one?\n'));
|
|
14
|
+
|
|
15
|
+
// Select a random challenge or iterate? Let's just pick one for now or loop.
|
|
16
|
+
// Let's loop through all available challenges.
|
|
17
|
+
|
|
18
|
+
for (const challenge of diffData) {
|
|
19
|
+
console.log(chalk.white.bold(`Prompt: "${challenge.prompt}"`));
|
|
20
|
+
|
|
21
|
+
const answer = await inquirer.prompt([{
|
|
22
|
+
type: 'list',
|
|
23
|
+
name: 'choice',
|
|
24
|
+
message: 'Which word is used in the Quran?',
|
|
25
|
+
choices: challenge.options.map(o => ({
|
|
26
|
+
name: o.label,
|
|
27
|
+
value: o.value
|
|
28
|
+
}))
|
|
29
|
+
}]);
|
|
30
|
+
|
|
31
|
+
const selected = challenge.options.find(o => o.value === answer.choice);
|
|
32
|
+
const isCorrect = selected?.isCorrect;
|
|
33
|
+
|
|
34
|
+
if (isCorrect) {
|
|
35
|
+
console.log(chalk.green.bold('\n Correct!'));
|
|
36
|
+
} else {
|
|
37
|
+
console.log(chalk.red.bold(`\n Not quite. The Quran uses: ${challenge.reveal}`));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
console.log(chalk.cyan.italic(`\n Lesson: ${challenge.lesson}`));
|
|
41
|
+
console.log(chalk.gray('----------------------------------------\n'));
|
|
42
|
+
|
|
43
|
+
// Pause before next?
|
|
44
|
+
const { next } = await inquirer.prompt([{
|
|
45
|
+
type: 'confirm',
|
|
46
|
+
name: 'next',
|
|
47
|
+
message: 'Next challenge?',
|
|
48
|
+
default: true
|
|
49
|
+
}]);
|
|
50
|
+
|
|
51
|
+
if (!next) break;
|
|
52
|
+
console.clear();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
console.log(chalk.yellow('End of challenges. SubhanAllah!'));
|
|
56
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import { duaData } from '../data/nak';
|
|
5
|
+
import { printCommandHeader } from '../utils/printer';
|
|
6
|
+
|
|
7
|
+
export const duaCommand = new Command('dua')
|
|
8
|
+
.description('Prophetic Duas with Context & Backstory')
|
|
9
|
+
.action(async () => {
|
|
10
|
+
printCommandHeader('dua');
|
|
11
|
+
const { situation } = await inquirer.prompt([{
|
|
12
|
+
type: 'list',
|
|
13
|
+
name: 'situation',
|
|
14
|
+
message: 'What are you feeling / facing?',
|
|
15
|
+
choices: duaData.map(d => ({ name: d.situation, value: d }))
|
|
16
|
+
}]);
|
|
17
|
+
|
|
18
|
+
displayDua(situation);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
function displayDua(dua: any) {
|
|
22
|
+
console.clear();
|
|
23
|
+
console.log(chalk.yellow.bold(`\n The Dua of ${dua.prophet}`));
|
|
24
|
+
console.log(chalk.gray(` Situation: ${dua.situation}\n`));
|
|
25
|
+
|
|
26
|
+
console.log(chalk.cyan.bold(' The Backstory (Context):'));
|
|
27
|
+
console.log(chalk.white(` ${dua.context}\n`));
|
|
28
|
+
|
|
29
|
+
console.log(chalk.green.bold(` "${dua.arabic}"`));
|
|
30
|
+
console.log(chalk.white.italic(` "${dua.translation}"\n`));
|
|
31
|
+
|
|
32
|
+
console.log(chalk.magenta.bold(' The Gem:'));
|
|
33
|
+
console.log(chalk.white(` ${dua.gem}\n`));
|
|
34
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { fastData } from '../data/nak';
|
|
4
|
+
import { printCommandHeader } from '../utils/printer';
|
|
5
|
+
|
|
6
|
+
export const fastCommand = new Command('fast')
|
|
7
|
+
.description('Sunnah Fasting Reminders & Spiritual Why')
|
|
8
|
+
.action(async () => {
|
|
9
|
+
printCommandHeader('fast');
|
|
10
|
+
console.clear();
|
|
11
|
+
console.log(chalk.green.bold('\n The Shield of Fasting (As-Sawm)\n'));
|
|
12
|
+
|
|
13
|
+
const today = new Date();
|
|
14
|
+
const day = today.getDay(); // 0 = Sun, 1 = Mon, 4 = Thu
|
|
15
|
+
|
|
16
|
+
// Check if tomorrow is Mon (1) or Thu (4)
|
|
17
|
+
const isSunnahTomorrow = day === 0 || day === 3;
|
|
18
|
+
const isSunnahToday = day === 1 || day === 4;
|
|
19
|
+
|
|
20
|
+
if (isSunnahToday) {
|
|
21
|
+
console.log(chalk.yellow.bold(' Today is a Sunnah fasting day! (Monday/Thursday)'));
|
|
22
|
+
console.log(chalk.gray(' "The gates of Paradise are opened..."\n'));
|
|
23
|
+
} else if (isSunnahTomorrow) {
|
|
24
|
+
console.log(chalk.cyan.bold(' Tomorrow is a Sunnah fasting day! Prepare your Suhoor.'));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
console.log(chalk.white.bold(' Why we fast (beyond Ramadan):'));
|
|
28
|
+
|
|
29
|
+
fastData.forEach(f => {
|
|
30
|
+
console.log(chalk.blue.bold(`\n ${f.type} (${f.when})`));
|
|
31
|
+
console.log(chalk.white(` Reward: ${f.reward}`));
|
|
32
|
+
console.log(chalk.gray.italic(` "${f.spiritualWhy}"`));
|
|
33
|
+
});
|
|
34
|
+
console.log('\n');
|
|
35
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { fridayData } from '../data/nak';
|
|
4
|
+
import { printCommandHeader } from '../utils/printer';
|
|
5
|
+
|
|
6
|
+
export const fridayCommand = new Command('friday')
|
|
7
|
+
.description('The Jumu\'ah Manager')
|
|
8
|
+
.action(() => {
|
|
9
|
+
printCommandHeader('friday');
|
|
10
|
+
console.log(chalk.cyan.bold('\n Friday (Jumu\'ah) Checklist & Reflections\n'));
|
|
11
|
+
|
|
12
|
+
fridayData.forEach((item) => {
|
|
13
|
+
console.log(chalk.blue.bold(` [ ] ${item.item}`));
|
|
14
|
+
console.log(chalk.white(` Significance: ${item.significance}`));
|
|
15
|
+
console.log(chalk.gray(` Deep Dive: ${item.nakNote}\n`));
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import { heroData } from '../data/nak';
|
|
5
|
+
import { printCommandHeader } from '../utils/printer';
|
|
6
|
+
|
|
7
|
+
const drawBar = (val: number, max: number = 10) => {
|
|
8
|
+
// Use simple ASCII blocks if needed, but standard ones are fine
|
|
9
|
+
const filledChar = '█';
|
|
10
|
+
const emptyChar = '░';
|
|
11
|
+
const filled = filledChar.repeat(val);
|
|
12
|
+
const empty = emptyChar.repeat(max - val);
|
|
13
|
+
|
|
14
|
+
// Color logic
|
|
15
|
+
let color = chalk.red;
|
|
16
|
+
if (val >= 8) color = chalk.green;
|
|
17
|
+
else if (val >= 5) color = chalk.yellow;
|
|
18
|
+
|
|
19
|
+
return `${color(filled)}${chalk.gray(empty)} ${val}/${max}`;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const heroCommand = new Command('hero')
|
|
23
|
+
.description('The Prophet Profile (RPG Character Sheet)')
|
|
24
|
+
.argument('[name]', 'Name of the Prophet (e.g. Musa)')
|
|
25
|
+
.action(async (name) => {
|
|
26
|
+
printCommandHeader('hero');
|
|
27
|
+
let data = name
|
|
28
|
+
? heroData.find(h => h.name.toLowerCase().includes(name.toLowerCase()))
|
|
29
|
+
: null;
|
|
30
|
+
|
|
31
|
+
if (!data && name) {
|
|
32
|
+
console.log(chalk.red('Profile not found for that Prophet.'));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!data) {
|
|
36
|
+
const { choice } = await inquirer.prompt([{
|
|
37
|
+
type: 'list',
|
|
38
|
+
name: 'choice',
|
|
39
|
+
message: 'Select a Prophet to view profile:',
|
|
40
|
+
choices: heroData.map(h => ({
|
|
41
|
+
name: h.name,
|
|
42
|
+
value: h
|
|
43
|
+
}))
|
|
44
|
+
}]);
|
|
45
|
+
data = choice;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!data) return;
|
|
49
|
+
|
|
50
|
+
console.clear();
|
|
51
|
+
console.log(chalk.cyan.bold(`\n Aya Hero: ${data.name}`));
|
|
52
|
+
console.log(chalk.gray(`Title: ${data.title}\n`));
|
|
53
|
+
|
|
54
|
+
console.log(chalk.white.bold(' Stats:'));
|
|
55
|
+
console.log(`Strength: ${drawBar(data.stats.strength)}`);
|
|
56
|
+
console.log(`Speech: ${drawBar(data.stats.speech)}`);
|
|
57
|
+
console.log(`Patience: ${drawBar(data.stats.patience)}`);
|
|
58
|
+
console.log(`Wisdom: ${drawBar(data.stats.wisdom)}`);
|
|
59
|
+
console.log(chalk.gray('----------------------------------------'));
|
|
60
|
+
|
|
61
|
+
console.log(chalk.yellow.bold('\n Special Ability:'));
|
|
62
|
+
console.log(chalk.white(data.specialAbility));
|
|
63
|
+
|
|
64
|
+
console.log(chalk.red.bold('\n Weakness / Challenge:'));
|
|
65
|
+
console.log(chalk.white(data.weakness));
|
|
66
|
+
|
|
67
|
+
console.log(chalk.magenta.bold('\n Arch-Nemesis:'));
|
|
68
|
+
console.log(chalk.white(data.archNemesis));
|
|
69
|
+
|
|
70
|
+
console.log(chalk.blue.bold('\n Quranic Profile:'));
|
|
71
|
+
console.log(chalk.italic(data.quranicProfile));
|
|
72
|
+
console.log('');
|
|
73
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
import ora from 'ora';
|
|
5
|
+
import { format } from 'date-fns';
|
|
6
|
+
import { printCommandHeader } from '../utils/printer';
|
|
7
|
+
|
|
8
|
+
export const hijriCommand = new Command('hijri')
|
|
9
|
+
.description('Date Converter (Gregorian <-> Hijri)')
|
|
10
|
+
.option('-d, --date <date>', 'Date to convert (DD-MM-YYYY)')
|
|
11
|
+
.action(async (options) => {
|
|
12
|
+
printCommandHeader('hijri');
|
|
13
|
+
const spinner = ora('Converting date...').start();
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const today = new Date();
|
|
17
|
+
const dateStr = options.date || format(today, 'dd-MM-yyyy');
|
|
18
|
+
|
|
19
|
+
// Use Aladhan API for accurate conversion based on sighting adjustment if needed
|
|
20
|
+
const response = await axios.get(`http://api.aladhan.com/v1/gToH/${dateStr}`);
|
|
21
|
+
const data = response.data.data;
|
|
22
|
+
const hijri = data.hijri;
|
|
23
|
+
const gregorian = data.gregorian;
|
|
24
|
+
|
|
25
|
+
spinner.stop();
|
|
26
|
+
|
|
27
|
+
console.clear();
|
|
28
|
+
console.log(chalk.green.bold('\n Islamic Date Converter'));
|
|
29
|
+
console.log(chalk.gray('----------------------------------------'));
|
|
30
|
+
|
|
31
|
+
console.log(chalk.white('Gregorian: ') + chalk.bold(`${gregorian.day} ${gregorian.month.en} ${gregorian.year}`));
|
|
32
|
+
console.log(chalk.yellow('Hijri: ') + chalk.bold(`${hijri.day} ${hijri.month.en} ${hijri.year}`));
|
|
33
|
+
console.log(chalk.gray(`(${hijri.month.ar})`));
|
|
34
|
+
|
|
35
|
+
console.log('');
|
|
36
|
+
console.log(chalk.cyan(`Weekday: ${hijri.weekday.en} (${hijri.weekday.ar})`));
|
|
37
|
+
console.log('');
|
|
38
|
+
|
|
39
|
+
} catch (error) {
|
|
40
|
+
spinner.fail('Conversion failed.');
|
|
41
|
+
console.log(chalk.red('Please ensure date format is DD-MM-YYYY'));
|
|
42
|
+
}
|
|
43
|
+
});
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import ora from 'ora';
|
|
5
|
+
import { eventsList, HistoricalEvent } from '../data/events';
|
|
6
|
+
import { printCommandHeader } from '../utils/printer';
|
|
7
|
+
|
|
8
|
+
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));
|
|
9
|
+
|
|
10
|
+
export const historyCommand = new Command('history')
|
|
11
|
+
.description('Interactive Timeline of Revelation')
|
|
12
|
+
.argument('[event]', 'Name of the historical event (e.g., badr, uhud, migration)')
|
|
13
|
+
.action(async (event) => {
|
|
14
|
+
printCommandHeader('history');
|
|
15
|
+
|
|
16
|
+
if (event) {
|
|
17
|
+
const selectedEvent = eventsList.find(e => e.name.toLowerCase().includes(event.toLowerCase()) || e.id.toLowerCase().includes(event.toLowerCase()));
|
|
18
|
+
if (selectedEvent) {
|
|
19
|
+
await displayEvent(selectedEvent);
|
|
20
|
+
} else {
|
|
21
|
+
console.log(chalk.red('Event not found.'));
|
|
22
|
+
}
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Interactive Mode
|
|
27
|
+
let currentIndex = 0;
|
|
28
|
+
let keepRunning = true;
|
|
29
|
+
|
|
30
|
+
while (keepRunning) {
|
|
31
|
+
console.clear();
|
|
32
|
+
const currentEvent = eventsList[currentIndex];
|
|
33
|
+
|
|
34
|
+
console.log(chalk.yellow.bold('\n Timeline of the Seerah\n'));
|
|
35
|
+
|
|
36
|
+
// Timeline visualization
|
|
37
|
+
const totalEvents = eventsList.length;
|
|
38
|
+
const progress = Math.round(((currentIndex + 1) / totalEvents) * 20);
|
|
39
|
+
const progressBar = '█'.repeat(progress) + '░'.repeat(20 - progress);
|
|
40
|
+
console.log(chalk.gray(`[${progressBar}] ${currentIndex + 1}/${totalEvents}`));
|
|
41
|
+
|
|
42
|
+
await displayEvent(currentEvent, false);
|
|
43
|
+
|
|
44
|
+
const { action } = await inquirer.prompt([
|
|
45
|
+
{
|
|
46
|
+
type: 'list',
|
|
47
|
+
name: 'action',
|
|
48
|
+
message: 'Navigate:',
|
|
49
|
+
choices: [
|
|
50
|
+
{ name: 'Next Event ▶', value: 'next', disabled: currentIndex === eventsList.length - 1 },
|
|
51
|
+
{ name: 'Previous Event ◀', value: 'prev', disabled: currentIndex === 0 },
|
|
52
|
+
{ name: 'Select Specific Event', value: 'select' },
|
|
53
|
+
{ name: 'Exit', value: 'exit' }
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
if (action === 'next') {
|
|
59
|
+
currentIndex++;
|
|
60
|
+
} else if (action === 'prev') {
|
|
61
|
+
currentIndex--;
|
|
62
|
+
} else if (action === 'select') {
|
|
63
|
+
const { selected } = await inquirer.prompt([
|
|
64
|
+
{
|
|
65
|
+
type: 'list',
|
|
66
|
+
name: 'selected',
|
|
67
|
+
message: 'Jump to:',
|
|
68
|
+
choices: eventsList.map((e, index) => ({ name: `${e.year} - ${e.name}`, value: index }))
|
|
69
|
+
}
|
|
70
|
+
]);
|
|
71
|
+
currentIndex = selected;
|
|
72
|
+
} else {
|
|
73
|
+
keepRunning = false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
async function displayEvent(event: HistoricalEvent, animate = true) {
|
|
79
|
+
if (animate) {
|
|
80
|
+
const spinner = ora('Traveling back in time...').start();
|
|
81
|
+
await sleep(1000);
|
|
82
|
+
spinner.stop();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
console.log(chalk.green.bold(`\n Year: ${event.year}`));
|
|
86
|
+
console.log(chalk.green(` Location: ${event.location}`));
|
|
87
|
+
console.log(chalk.blue.bold(`Event: ${event.name}`));
|
|
88
|
+
console.log('');
|
|
89
|
+
|
|
90
|
+
console.log(chalk.white.italic(event.scene));
|
|
91
|
+
console.log('');
|
|
92
|
+
|
|
93
|
+
if (animate) await sleep(1500);
|
|
94
|
+
|
|
95
|
+
console.log(chalk.yellow.bold(' Revelation Sent Down:'));
|
|
96
|
+
console.log(chalk.cyan(`"${event.revelation}"`));
|
|
97
|
+
console.log(chalk.gray(`(Surah ${event.ayah})`));
|
|
98
|
+
|
|
99
|
+
if (event.details) {
|
|
100
|
+
console.log(chalk.gray(`\nNote: ${event.details}`));
|
|
101
|
+
}
|
|
102
|
+
console.log('');
|
|
103
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { setConfig, getConfig } from '../utils/config';
|
|
5
|
+
import { printCommandHeader } from '../utils/printer';
|
|
6
|
+
|
|
7
|
+
export const initCommand = new Command('init')
|
|
8
|
+
.description('Set your intention (niyyah) for this session')
|
|
9
|
+
.action(async () => {
|
|
10
|
+
printCommandHeader('init');
|
|
11
|
+
const config = getConfig();
|
|
12
|
+
|
|
13
|
+
console.log(chalk.green('Bismillah. Let us begin with the right intention.'));
|
|
14
|
+
|
|
15
|
+
const answers = await inquirer.prompt([
|
|
16
|
+
{
|
|
17
|
+
type: 'input',
|
|
18
|
+
name: 'name',
|
|
19
|
+
message: 'What is your name?',
|
|
20
|
+
default: config.name || 'Abdullah'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
type: 'input',
|
|
24
|
+
name: 'intention',
|
|
25
|
+
message: 'What is your intention for this session?',
|
|
26
|
+
default: config.intention || 'Seeking the pleasure of Allah through code'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
type: 'input',
|
|
30
|
+
name: 'city',
|
|
31
|
+
message: 'Where are you located (City)?',
|
|
32
|
+
default: config.location?.city || 'Mecca'
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
type: 'input',
|
|
36
|
+
name: 'country',
|
|
37
|
+
message: 'Where are you located (Country)?',
|
|
38
|
+
default: config.location?.country || 'Saudi Arabia'
|
|
39
|
+
}
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
setConfig({
|
|
43
|
+
name: answers.name,
|
|
44
|
+
intention: answers.intention,
|
|
45
|
+
location: {
|
|
46
|
+
city: answers.city,
|
|
47
|
+
country: answers.country
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log(chalk.cyan(`\n✨ Intention set: "${answers.intention}"`));
|
|
52
|
+
console.log(chalk.gray('May Allah accept your efforts and place Barakah in your code.'));
|
|
53
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import { printCommandHeader } from '../utils/printer';
|
|
5
|
+
|
|
6
|
+
export const investCommand = new Command('invest')
|
|
7
|
+
.description('Sadaqah Calculator (The Infinite ROI)')
|
|
8
|
+
.action(async () => {
|
|
9
|
+
printCommandHeader('invest');
|
|
10
|
+
const { amount } = await inquirer.prompt([{
|
|
11
|
+
type: 'number',
|
|
12
|
+
name: 'amount',
|
|
13
|
+
message: 'Enter amount to invest (Sadaqah):'
|
|
14
|
+
}]);
|
|
15
|
+
|
|
16
|
+
console.log(chalk.yellow.bold(`\n Investment Analysis for $${amount}`));
|
|
17
|
+
console.log(chalk.white('\n Guarantor: The Lord of the Worlds'));
|
|
18
|
+
console.log(chalk.green(' Multiplier: 700x to Infinity (Surah Al-Baqarah 2:261)'));
|
|
19
|
+
console.log(chalk.blue(` Minimum Return (Hereafter): ${amount * 700} deeds`));
|
|
20
|
+
console.log(chalk.cyan(' Risk Factor: 0% ("Charity does not decrease wealth")'));
|
|
21
|
+
console.log(chalk.gray('\n "Who is it that would loan Allah a goodly loan so He may multiply it for him many times over?" (2:245)\n'));
|
|
22
|
+
});
|