Compare commits

...

16 Commits

Author SHA1 Message Date
Flatlogic Bot
e6bef456ac V12 2026-02-16 10:02:55 +00:00
Flatlogic Bot
c1675839da V11 2026-02-16 09:51:46 +00:00
Flatlogic Bot
eb07bb3e67 V11 2026-02-16 09:46:47 +00:00
Flatlogic Bot
8ba50eb543 Autosave: 20260216-090952 2026-02-16 09:09:52 +00:00
Flatlogic Bot
7fc547e10f V8 Ultra 2026-02-16 08:38:19 +00:00
Flatlogic Bot
4c686cdfef V8+ 2026-02-16 08:24:38 +00:00
Flatlogic Bot
49dd9b22df V8 2026-02-16 08:12:26 +00:00
Flatlogic Bot
da32ad26c6 V7 2026-02-16 08:01:11 +00:00
Flatlogic Bot
f2d5361ba4 V6 2026-02-16 07:47:49 +00:00
Flatlogic Bot
c2aa0f3687 V5 2026-02-16 07:39:54 +00:00
Flatlogic Bot
96f3e9caa7 Autosave: 20260216-071603 2026-02-16 07:16:04 +00:00
Flatlogic Bot
ca3a32f23e V 4 2026-02-16 06:55:36 +00:00
Flatlogic Bot
a09afbaf39 Autosave: 20260216-055959 2026-02-16 06:00:13 +00:00
Flatlogic Bot
33b1653816 V3 2026-02-16 03:42:10 +00:00
Flatlogic Bot
035a67bfc5 V2 2026-02-16 03:26:39 +00:00
Flatlogic Bot
184c4889b4 BOT 2026-02-16 02:59:27 +00:00
6464 changed files with 1015309 additions and 133 deletions

22
api/bot_status.php Normal file
View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
header('Content-Type: application/json');
$output = [];
$returnVar = 0;
exec('ps aux | grep "node index.js" | grep -v grep', $output, $returnVar);
$isRunning = !empty($output);
$pid = null;
if ($isRunning) {
$parts = preg_split('/\s+/', trim($output[0]));
$pid = $parts[1] ?? null;
}
echo json_encode([
'success' => true,
'running' => $isRunning,
'pid' => $pid,
'details' => $output
]);

35
api/deploy_commands.php Normal file
View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/../db/config.php';
header('Content-Type: application/json');
// Fetch settings
$settings = [];
try {
$stmt = db()->query("SELECT setting_key, setting_value FROM bot_settings");
while ($row = $stmt->fetch()) {
$settings[$row['setting_key']] = $row['setting_value'];
}
} catch (PDOException $e) {
echo json_encode(['success' => false, 'error' => 'Database error']);
exit;
}
$token = $settings['discord_token'] ?? '';
$clientId = $settings['client_id'] ?? '';
if (!$token || !$clientId) {
echo json_encode(['success' => false, 'error' => 'Token and Client ID are required.']);
exit;
}
// Execute deployment script
$cmd = "cd ../bot && DISCORD_TOKEN=" . escapeshellarg($token) . " CLIENT_ID=" . escapeshellarg($clientId) . " node deploy-commands.js 2>&1";
exec($cmd, $output, $returnVar);
if ($returnVar === 0) {
echo json_encode(['success' => true, 'output' => implode("\n", $output)]);
} else {
echo json_encode(['success' => false, 'error' => implode("\n", $output)]);
}

28
api/save_settings.php Normal file
View File

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/../db/config.php';
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['success' => false, 'error' => 'Invalid method']);
exit;
}
$data = [
'discord_token' => $_POST['discord_token'] ?? '',
'client_id' => $_POST['client_id'] ?? '',
'voice_channel_id' => $_POST['voice_channel_id'] ?? '',
'sahur_time' => $_POST['sahur_time'] ?? '03:30',
];
try {
$db = db();
foreach ($data as $key => $value) {
$stmt = $db->prepare('INSERT INTO bot_settings (setting_key, setting_value) VALUES (?, ?) ON DUPLICATE KEY UPDATE setting_value = ?');
$stmt->execute([$key, $value, $value]);
}
echo json_encode(['success' => true]);
} catch (PDOException $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}

13
api/start_bot.php Normal file
View File

@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
header('Content-Type: application/json');
$cmd = "cd ../bot && bash start_bot.sh 2>&1";
exec($cmd, $output, $returnVar);
if ($returnVar === 0) {
echo json_encode(['success' => true, 'output' => implode("\n", $output)]);
} else {
echo json_encode(['success' => false, 'error' => implode("\n", $output)]);
}

41
api/upload_audio.php Normal file
View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['success' => false, 'error' => 'Invalid request method.']);
exit;
}
if (!isset($_FILES['sahur_file'])) {
echo json_encode(['success' => false, 'error' => 'No file uploaded.']);
exit;
}
$file = $_FILES['sahur_file'];
// Basic validation
if ($file['error'] !== UPLOAD_ERR_OK) {
echo json_encode(['success' => false, 'error' => 'Upload error: ' . $file['error']]);
exit;
}
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
if (strtolower($ext) !== 'mp3') {
echo json_encode(['success' => false, 'error' => 'Only MP3 files are allowed.']);
exit;
}
$targetDir = __DIR__ . '/../assets/audio/';
if (!is_dir($targetDir)) {
mkdir($targetDir, 0775, true);
}
$targetPath = $targetDir . 'sahur.mp3';
if (move_uploaded_file($file['tmp_name'], $targetPath)) {
echo json_encode(['success' => true]);
} else {
echo json_encode(['success' => false, 'error' => 'Failed to save file.']);
}

BIN
assets/audio/sahur.mp3 Normal file

Binary file not shown.

126
assets/css/custom.css Normal file
View File

@ -0,0 +1,126 @@
:root {
--primary: #10b981;
--primary-hover: #059669;
--bg: #f8fafc;
--surface: #ffffff;
--text: #1e293b;
--text-muted: #64748b;
--border: #e2e8f0;
--radius: 4px;
}
body {
background-color: var(--bg);
color: var(--text);
font-family: 'Inter', system-ui, -apple-system, sans-serif;
line-height: 1.5;
margin: 0;
}
.container {
max-width: 800px;
margin: 40px auto;
padding: 0 20px;
}
.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 24px;
margin-bottom: 24px;
}
.card-title {
font-size: 1.25rem;
font-weight: 600;
margin: 0 0 16px 0;
display: flex;
align-items: center;
gap: 8px;
}
.form-group {
margin-bottom: 16px;
}
.form-label {
display: block;
font-size: 0.875rem;
font-weight: 500;
margin-bottom: 4px;
color: var(--text-muted);
}
.form-control {
width: 100%;
padding: 8px 12px;
border: 1px solid var(--border);
border-radius: var(--radius);
font-size: 0.875rem;
transition: border-color 0.2s;
box-sizing: border-box;
}
.form-control:focus {
outline: none;
border-color: var(--primary);
}
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 8px 16px;
border-radius: var(--radius);
font-size: 0.875rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
border: 1px solid transparent;
}
.btn-primary {
background: var(--primary);
color: white;
}
.btn-primary:hover {
background: var(--primary-hover);
}
.badge {
display: inline-flex;
padding: 2px 8px;
font-size: 0.75rem;
font-weight: 600;
border-radius: 9999px;
text-transform: uppercase;
}
.badge-disconnected {
background: #fee2e2;
color: #991b1b;
}
.badge-connected {
background: #dcfce7;
color: #166534;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32px;
}
.header h1 {
font-size: 1.5rem;
margin: 0;
}
.audio-player {
width: 100%;
margin-top: 8px;
}

184
assets/js/main.js Normal file
View File

@ -0,0 +1,184 @@
document.addEventListener('DOMContentLoaded', () => {
const configForm = document.getElementById('config-form');
const testAudioBtn = document.getElementById('test-audio-btn');
const audioPlayer = document.querySelector('.audio-player');
const updateBotStatus = async () => {
const statusBadge = document.getElementById('bot-status-badge');
if (!statusBadge) return;
try {
const response = await fetch('api/bot_status.php');
const result = await response.json();
if (result.running) {
statusBadge.textContent = 'Online (PID: ' + result.pid + ')';
statusBadge.className = 'badge badge-connected';
} else {
statusBadge.textContent = 'Offline';
statusBadge.className = 'badge badge-disconnected';
}
} catch (error) {
statusBadge.textContent = 'Error';
statusBadge.className = 'badge badge-disconnected';
}
};
updateBotStatus();
setInterval(updateBotStatus, 5000);
if (configForm) {
configForm.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(configForm);
const submitBtn = configForm.querySelector('button[type="submit"]');
const originalBtnText = submitBtn.textContent;
submitBtn.disabled = true;
submitBtn.textContent = 'Saving...';
try {
const response = await fetch('api/save_settings.php', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.success) {
alert('Settings saved successfully!');
} else {
alert('Error: ' + result.error);
}
} catch (error) {
alert('Network error while saving settings.');
} finally {
submitBtn.disabled = false;
submitBtn.textContent = originalBtnText;
}
});
}
const deployBtn = document.getElementById('deploy-commands-btn');
if (deployBtn) {
deployBtn.addEventListener('click', async () => {
const originalText = deployBtn.textContent;
deployBtn.disabled = true;
deployBtn.textContent = 'Deploying...';
try {
const response = await fetch('api/deploy_commands.php');
const result = await response.json();
if (result.success) {
alert('Slash Commands berhasil didaftarkan! Tunggu beberapa saat agar muncul di Discord.');
} else {
alert('Gagal: ' + result.error);
}
} catch (error) {
alert('Network error.');
} finally {
deployBtn.disabled = false;
deployBtn.textContent = originalText;
}
});
}
const startBotBtn = document.getElementById('start-bot-btn');
if (startBotBtn) {
startBotBtn.addEventListener('click', async () => {
const originalText = startBotBtn.textContent;
startBotBtn.disabled = true;
startBotBtn.textContent = 'Starting...';
try {
const response = await fetch('api/start_bot.php');
const result = await response.json();
if (result.success) {
alert('Bot berhasil dijalankan di background!');
} else {
alert('Gagal menjalankan bot: ' + result.error);
}
} catch (error) {
alert('Network error.');
} finally {
startBotBtn.disabled = false;
startBotBtn.textContent = originalText;
}
});
}
if (testAudioBtn && audioPlayer) {
testAudioBtn.addEventListener('click', () => {
if (audioPlayer.paused) {
audioPlayer.play();
testAudioBtn.textContent = 'Pause';
} else {
audioPlayer.pause();
testAudioBtn.textContent = 'Test Play Locally';
}
});
audioPlayer.addEventListener('ended', () => {
testAudioBtn.textContent = 'Test Play Locally';
});
}
// Sahur MP3 Upload Logic
const sahurUpload = document.getElementById('sahur-upload');
const uploadBtn = document.getElementById('upload-btn');
const uploadStatus = document.getElementById('upload-status');
if (sahurUpload && uploadBtn) {
sahurUpload.addEventListener('change', () => {
if (sahurUpload.files.length > 0) {
uploadBtn.style.display = 'block';
uploadStatus.textContent = `Selected: ${sahurUpload.files[0].name}`;
} else {
uploadBtn.style.display = 'none';
uploadStatus.textContent = '';
}
});
uploadBtn.addEventListener('click', async () => {
if (sahurUpload.files.length === 0) return;
const formData = new FormData();
formData.append('sahur_file', sahurUpload.files[0]);
uploadBtn.disabled = true;
uploadBtn.textContent = 'Uploading...';
uploadStatus.textContent = 'Processing your file...';
try {
const response = await fetch('api/upload_audio.php', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.success) {
uploadStatus.innerHTML = '<span style="color:var(--primary);">✓ Berhasil di-upload!</span>';
// Reload page to refresh status and audio player
setTimeout(() => {
window.location.reload();
}, 1500);
} else {
uploadStatus.innerHTML = `<span style="color:red;">Gagal: ${result.error}</span>`;
}
} catch (error) {
uploadStatus.innerHTML = '<span style="color:red;">Network error.</span>';
} finally {
uploadBtn.disabled = false;
uploadBtn.textContent = 'Upload Now';
uploadBtn.style.display = 'none';
sahurUpload.value = '';
}
});
}
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 KiB

4
bot/.env Normal file
View File

@ -0,0 +1,4 @@
DISCORD_TOKEN=MTQ3MTkwOTE5Mzg4Njg1OTI5NA.GlIuXe._ee-bIu9eyIs1uqePNjQbR6vksYgVBseEMW6qs
VC_ID=1457687430189682781
SAHUR_TIME=03:30
CLIENT_ID=1471909193886859294

BIN
bot/assets/audio/sahur.mp3 Normal file

Binary file not shown.

828
bot/bot.log Normal file
View File

@ -0,0 +1,828 @@
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ load multiple .env files with { path: ['.env.local', '.env'] }
[2026-02-16T07:54:16.560Z] Encryption library (libsodium) is ready.
Encryption library (libsodium) is ready.
[2026-02-16T07:54:17.053Z] Bot berhasil login!
Bot berhasil login!
[2026-02-16T07:54:17.054Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T07:54:17.054Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
Ready! Logged in as AsepXiaoQin#6954
FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T07:54:17.101Z] Alarm scheduled at 30 3 * * *
Alarm scheduled at 30 3 * * *
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ write to custom object with { processEnv: myObject }
[2026-02-16T07:56:42.147Z] Encryption library (libsodium) is ready.
Encryption library (libsodium) is ready.
[2026-02-16T07:56:42.566Z] Bot berhasil login!
Bot berhasil login!
[2026-02-16T07:56:42.568Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T07:56:42.568Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
Ready! Logged in as AsepXiaoQin#6954
FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T07:56:42.611Z] Alarm scheduled at 30 3 * * *
Alarm scheduled at 30 3 * * *
[2026-02-16T08:01:31.081Z] Playing local file via DisTube: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
Playing local file via DisTube: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
[2026-02-16T08:01:32.552Z] Error in testsahur: Cannot find any song with this query (/home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3)
Error in testsahur: Cannot find any song with this query (/home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3)
[2026-02-16T08:01:50.209Z] Fetching stream via DisTube for: iwak peyek
Fetching stream via DisTube for: iwak peyek
[2026-02-16T08:01:51.090Z] DisTube Error: undefined
DisTube Error: undefined
[2026-02-16T08:01:51.102Z] Unhandled Rejection: Cannot read properties of undefined (reading 'includes')
TypeError: Cannot read properties of undefined (reading 'includes')
at DisTube.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:250:23)
at DisTube.emit (node:events:518:28)
at DisTube.emitError (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2546:10)
at QueueManager.emitError (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:154:18)
at #handlePlayingError (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2100:10)
at QueueManager.playSong (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2147:31)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async DisTube.play (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2352:24)
at async Client.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:153:17)
Unhandled Rejection: Cannot read properties of undefined (reading 'includes')
TypeError: Cannot read properties of undefined (reading 'includes')
at DisTube.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:250:23)
at DisTube.emit (node:events:518:28)
at DisTube.emitError (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2546:10)
at QueueManager.emitError (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:154:18)
at #handlePlayingError (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2100:10)
at QueueManager.playSong (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2147:31)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async DisTube.play (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2352:24)
at async Client.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:153:17)
[2026-02-16T08:02:06.620Z] Fetching stream via DisTube for: bawa dia kembali
Fetching stream via DisTube for: bawa dia kembali
[2026-02-16T08:02:27.067Z] Fetching stream via DisTube for: y que fue
Fetching stream via DisTube for: y que fue
[2026-02-16T08:02:27.837Z] DisTube Error: undefined
DisTube Error: undefined
TypeError: Cannot read properties of undefined (reading 'includes')
at DisTube.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:250:23)
at DisTube.emit (node:events:518:28)
at DisTube.emitError (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2546:10)
at QueueManager.emitError (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:154:18)
at #handlePlayingError (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2100:10)
at QueueManager.playSong (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2147:31)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async DisTube.play (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2352:24)
at async Client.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:153:17)
[2026-02-16T08:02:27.840Z] Unhandled Rejection: Cannot read properties of undefined (reading 'includes')
Unhandled Rejection: Cannot read properties of undefined (reading 'includes')
TypeError: Cannot read properties of undefined (reading 'includes')
at DisTube.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:250:23)
at DisTube.emit (node:events:518:28)
at DisTube.emitError (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2546:10)
at QueueManager.emitError (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:154:18)
at #handlePlayingError (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2100:10)
at QueueManager.playSong (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2147:31)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async DisTube.play (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2352:24)
at async Client.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:153:17)
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🔐 prevent committing .env to code: https://dotenvx.com/precommit
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:47:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ suppress all logs with { quiet: true }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:47:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ suppress all logs with { quiet: true }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:47:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ suppress all logs with { quiet: true }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:47:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ suppress all logs with { quiet: true }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:47:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🛠️ run anywhere with `dotenvx run -- yourcommand`
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:47:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ specify custom .env file path with { path: '/custom/path/.env' }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:47:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ write to custom object with { processEnv: myObject }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:47:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ specify custom .env file path with { path: '/custom/path/.env' }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:47:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ load multiple .env files with { path: ['.env.local', '.env'] }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:47:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🔐 prevent committing .env to code: https://dotenvx.com/precommit
[2026-02-16T08:08:04.055Z] Encryption library (libsodium) is ready.
Encryption library (libsodium) is ready.
[2026-02-16T08:08:05.553Z] Bot berhasil login!
Bot berhasil login!
[2026-02-16T08:08:05.555Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T08:08:05.558Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
Ready! Logged in as AsepXiaoQin#6954
FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T08:08:06.805Z] Alarm scheduled at 30 3 * * *
Alarm scheduled at 30 3 * * *
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🛡️ auth for agents: https://vestauth.com
[2026-02-16T08:08:28.564Z] Encryption library (libsodium) is ready.
Encryption library (libsodium) is ready.
[2026-02-16T08:08:30.304Z] Bot berhasil login!
[2026-02-16T08:08:30.304Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T08:08:30.305Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
Bot berhasil login!
Ready! Logged in as AsepXiaoQin#6954
FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T08:08:30.810Z] Alarm scheduled at 30 3 * * *
Alarm scheduled at 30 3 * * *
[2026-02-16T08:12:44.247Z] Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
[2026-02-16T08:13:47.227Z] Fetching stream via DisTube for: bawa dia kembali
Fetching stream via DisTube for: bawa dia kembali
[2026-02-16T08:14:09.517Z] Interaction Error (skip): There is no playing queue in this guild
Interaction Error (skip): There is no playing queue in this guild
(node:85527) Warning: Supplying "ephemeral" for interaction response options is deprecated. Utilize flags instead.
(Use `node --trace-warnings ...` to show where the warning was created)
[2026-02-16T08:14:20.609Z] Interaction Error (pause): There is no playing queue in this guild
Interaction Error (pause): There is no playing queue in this guild
[2026-02-16T08:14:55.078Z] Fetching stream via DisTube for: https://youtu.be/aFh6p6Yo_6Y?si=UyXD8ZUhJE_oSX1_
Fetching stream via DisTube for: https://youtu.be/aFh6p6Yo_6Y?si=UyXD8ZUhJE_oSX1_
SyntaxError: Unexpected token 'D', "Deprecated"... is not valid JSON
at JSON.parse (<anonymous>)
at ChildProcess.<anonymous> (/home/ubuntu/executor/workspace/bot/node_modules/@distube/yt-dlp/dist/index.js:84:36)
at ChildProcess.emit (node:events:518:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
[2026-02-16T08:15:02.578Z] Uncaught Exception: Unexpected token 'D', "Deprecated"... is not valid JSON
Uncaught Exception: Unexpected token 'D', "Deprecated"... is not valid JSON
SyntaxError: Unexpected token 'D', "Deprecated"... is not valid JSON
at JSON.parse (<anonymous>)
at ChildProcess.<anonymous> (/home/ubuntu/executor/workspace/bot/node_modules/@distube/yt-dlp/dist/index.js:84:36)
at ChildProcess.emit (node:events:518:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
[2026-02-16T08:17:04.076Z] Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🛡️ auth for agents: https://vestauth.com
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:48:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚡️ secrets for agents: https://dotenvx.com/as2
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:48:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🛠️ run anywhere with `dotenvx run -- yourcommand`
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:48:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ override existing env vars with { override: true }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:48:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ specify custom .env file path with { path: '/custom/path/.env' }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:48:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🔐 prevent building .env in docker: https://dotenvx.com/prebuild
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:48:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ override existing env vars with { override: true }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:48:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ override existing env vars with { override: true }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:48:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ override existing env vars with { override: true }
[2026-02-16T08:21:39.827Z] Encryption library (libsodium) is ready.
Encryption library (libsodium) is ready.
[2026-02-16T08:21:41.582Z] Bot berhasil login!
Bot berhasil login!
[2026-02-16T08:21:41.589Z] Ready! Logged in as AsepXiaoQin#6954
Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T08:21:41.816Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T08:21:42.574Z] Alarm scheduled at 30 3 * * *
Alarm scheduled at 30 3 * * *
[2026-02-16T08:24:55.831Z] Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
[2026-02-16T08:25:49.191Z] Fetching stream via DisTube for: https://on.soundcloud.com/ORjsl2DMlAGkmIXfel
Fetching stream via DisTube for: https://on.soundcloud.com/ORjsl2DMlAGkmIXfel
SyntaxError: Unexpected token 'D', "Deprecated"... is not valid JSON
at JSON.parse (<anonymous>)
at ChildProcess.<anonymous> (/home/ubuntu/executor/workspace/bot/node_modules/@distube/yt-dlp/dist/index.js:84:36)
at ChildProcess.emit (node:events:518:28)
at maybeClose (node:internal/child_process:1101:16)
at Socket.<anonymous> (node:internal/child_process:456:11)
at Socket.emit (node:events:518:28)
at Pipe.<anonymous> (node:net:346:12)
[2026-02-16T08:25:57.742Z] Uncaught Exception: Unexpected token 'D', "Deprecated"... is not valid JSON
Uncaught Exception: Unexpected token 'D', "Deprecated"... is not valid JSON
SyntaxError: Unexpected token 'D', "Deprecated"... is not valid JSON
at JSON.parse (<anonymous>)
at ChildProcess.<anonymous> (/home/ubuntu/executor/workspace/bot/node_modules/@distube/yt-dlp/dist/index.js:84:36)
at ChildProcess.emit (node:events:518:28)
at maybeClose (node:internal/child_process:1101:16)
at Socket.<anonymous> (node:internal/child_process:456:11)
at Socket.emit (node:events:518:28)
at Pipe.<anonymous> (node:net:346:12)
[2026-02-16T08:31:40.298Z] Fetching stream via DisTube for: bawa dia kembali
Fetching stream via DisTube for: bawa dia kembali
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ suppress all logs with { quiet: true }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:49:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🔐 prevent building .env in docker: https://dotenvx.com/prebuild
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:49:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🤖 agentic secret storage: https://dotenvx.com/as2
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:49:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🤖 agentic secret storage: https://dotenvx.com/as2
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:49:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ write to custom object with { processEnv: myObject }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:49:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ enable debug logging with { debug: true }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:49:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ suppress all logs with { quiet: true }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:49:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🔐 prevent committing .env to code: https://dotenvx.com/precommit
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:49:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚡️ secrets for agents: https://dotenvx.com/as2
[2026-02-16T08:36:43.578Z] Encryption library (libsodium) is ready.
Encryption library (libsodium) is ready.
[2026-02-16T08:36:46.294Z] Bot berhasil login!
[2026-02-16T08:36:46.295Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T08:36:46.296Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
Bot berhasil login!
Ready! Logged in as AsepXiaoQin#6954
FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T08:36:47.798Z] Alarm scheduled at 30 3 * * *
Alarm scheduled at 30 3 * * *
[2026-02-16T08:38:33.364Z] Searching via play-dl for: bawa dia kembali
Searching via play-dl for: bawa dia kembali
[2026-02-16T08:38:34.309Z] Found URL via play-dl: https://www.youtube.com/watch?v=j2U08vZSHGA
Found URL via play-dl: https://www.youtube.com/watch?v=j2U08vZSHGA
SyntaxError: Unexpected token 'D', "Deprecated"... is not valid JSON
at JSON.parse (<anonymous>)
at ChildProcess.<anonymous> (/home/ubuntu/executor/workspace/bot/node_modules/@distube/yt-dlp/dist/index.js:84:36)
at ChildProcess.emit (node:events:518:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
[2026-02-16T08:39:01.802Z] Uncaught Exception: Unexpected token 'D', "Deprecated"... is not valid JSON
Uncaught Exception: Unexpected token 'D', "Deprecated"... is not valid JSON
SyntaxError: Unexpected token 'D', "Deprecated"... is not valid JSON
at JSON.parse (<anonymous>)
at ChildProcess.<anonymous> (/home/ubuntu/executor/workspace/bot/node_modules/@distube/yt-dlp/dist/index.js:84:36)
at ChildProcess.emit (node:events:518:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
[2026-02-16T08:39:13.543Z] Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🤖 agentic secret storage: https://dotenvx.com/as2
[2026-02-16T08:46:39.114Z] Encryption library (libsodium) is ready.
Encryption library (libsodium) is ready.
[2026-02-16T08:46:39.571Z] Bot berhasil login!
[2026-02-16T08:46:39.572Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T08:46:39.572Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
Bot berhasil login!
Ready! Logged in as AsepXiaoQin#6954
FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T08:46:39.716Z] Alarm scheduled at 30 3 * * *
Alarm scheduled at 30 3 * * *
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ write to custom object with { processEnv: myObject }
[2026-02-16T08:49:12.201Z] Encryption library (libsodium) is ready.
Encryption library (libsodium) is ready.
[2026-02-16T08:49:13.692Z] Bot berhasil login!
Bot berhasil login!
[2026-02-16T08:49:13.697Z] Ready! Logged in as AsepXiaoQin#6954
Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T08:49:13.700Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T08:49:13.762Z] Alarm scheduled at 30 3 * * *
Alarm scheduled at 30 3 * * *
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🛡️ auth for agents: https://vestauth.com
[2026-02-16T08:49:24.070Z] Encryption library (libsodium) is ready.
Encryption library (libsodium) is ready.
[2026-02-16T08:49:24.735Z] Bot berhasil login!
[2026-02-16T08:49:24.735Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T08:49:24.736Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
Bot berhasil login!
Ready! Logged in as AsepXiaoQin#6954
FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T08:49:24.780Z] Alarm scheduled at 30 3 * * *
Alarm scheduled at 30 3 * * *
[2026-02-16T08:55:08.549Z] Searching via play-dl for: bawa dia kembali
Searching via play-dl for: bawa dia kembali
[2026-02-16T08:55:08.995Z] Found URL via play-dl: https://www.youtube.com/watch?v=dq2i49uwEJg
Found URL via play-dl: https://www.youtube.com/watch?v=dq2i49uwEJg
[2026-02-16T08:55:09.826Z] Play Error: Invalid URL
Play Error: Invalid URL
[2026-02-16T08:55:21.145Z] Searching via play-dl for: https://on.soundcloud.com/ORjsl2DMlAGkmIXfel
Searching via play-dl for: https://on.soundcloud.com/ORjsl2DMlAGkmIXfel
[2026-02-16T08:55:55.931Z] Searching via play-dl for: https://youtu.be/82A9lCx2XgY?si=DfeROWrUs5xUwclK
Searching via play-dl for: https://youtu.be/82A9lCx2XgY?si=DfeROWrUs5xUwclK
[2026-02-16T08:55:56.200Z] Found URL via play-dl: https://www.youtube.com/watch?v=82A9lCx2XgY
Found URL via play-dl: https://www.youtube.com/watch?v=82A9lCx2XgY
[2026-02-16T08:55:56.747Z] Play Error: Invalid URL
Play Error: Invalid URL
[2026-02-16T08:56:24.330Z] Searching via play-dl for: https://open.spotify.com/track/3qhlB30KknSejmIvZZLjOD?si=2NMmRTKnQJ-fMh9OmWm9Bw
Searching via play-dl for: https://open.spotify.com/track/3qhlB30KknSejmIvZZLjOD?si=2NMmRTKnQJ-fMh9OmWm9Bw
[2026-02-16T08:56:35.574Z] Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🔐 encrypt with Dotenvx: https://dotenvx.com
[2026-02-16T09:03:26.677Z] Encryption library (libsodium) is ready.
Encryption library (libsodium) is ready.
[2026-02-16T09:03:27.142Z] Bot berhasil login!
[2026-02-16T09:03:27.144Z] Ready! Logged in as AsepXiaoQin#6954
Bot berhasil login!
[2026-02-16T09:03:27.145Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
Ready! Logged in as AsepXiaoQin#6954
FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T09:03:27.255Z] Alarm scheduled at 30 3 * * *
Alarm scheduled at 30 3 * * *
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ override existing env vars with { override: true }
[2026-02-16T09:04:34.158Z] Encryption library (libsodium) is ready.
Encryption library (libsodium) is ready.
[2026-02-16T09:04:34.816Z] Bot berhasil login!
Bot berhasil login!
[2026-02-16T09:04:34.818Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T09:04:34.821Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
Ready! Logged in as AsepXiaoQin#6954
FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T09:04:34.895Z] Alarm scheduled at 30 3 * * *
Alarm scheduled at 30 3 * * *
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🛠️ run anywhere with `dotenvx run -- yourcommand`
[2026-02-16T09:04:57.611Z] Encryption library (libsodium) is ready.
Encryption library (libsodium) is ready.
[2026-02-16T09:04:58.667Z] Bot berhasil login!
Bot berhasil login!
[2026-02-16T09:04:58.668Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T09:04:58.668Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
Ready! Logged in as AsepXiaoQin#6954
FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T09:04:58.709Z] Alarm scheduled at 30 3 * * *
Alarm scheduled at 30 3 * * *
[2026-02-16T09:08:16.758Z] Validation for "https://open.spotify.com/track/3qhlB30KknSejmIvZZLjOD?si=2NMmRTKnQJ-fMh9OmWm9Bw": sp_track
Validation for "https://open.spotify.com/track/3qhlB30KknSejmIvZZLjOD?si=2NMmRTKnQJ-fMh9OmWm9Bw": sp_track
[2026-02-16T09:08:16.760Z] Info fetch error: This is not a YouTube Watch URL
[2026-02-16T09:08:16.761Z] Playing: https://open.spotify.com/track/3qhlB30KknSejmIvZZLjOD?si=2NMmRTKnQJ-fMh9OmWm9Bw
Info fetch error: This is not a YouTube Watch URL
Playing: https://open.spotify.com/track/3qhlB30KknSejmIvZZLjOD?si=2NMmRTKnQJ-fMh9OmWm9Bw
[2026-02-16T09:08:16.772Z] Play Error: ffmpeg is not installed at 'ffmpeg' path
Play Error: ffmpeg is not installed at 'ffmpeg' path
[2026-02-16T09:08:29.785Z] Validation for "y que fue": search
[2026-02-16T09:08:29.786Z] Searching via play-dl for: y que fue
Validation for "y que fue": search
Searching via play-dl for: y que fue
[2026-02-16T09:08:30.242Z] Playing: https://www.youtube.com/watch?v=vHeO-9G5rxo
Playing: https://www.youtube.com/watch?v=vHeO-9G5rxo
[2026-02-16T09:08:30.247Z] Play Error: ffmpeg is not installed at 'ffmpeg' path
Play Error: ffmpeg is not installed at 'ffmpeg' path
[2026-02-16T09:08:35.195Z] Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ write to custom object with { processEnv: myObject }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:41:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ enable debug logging with { debug: true }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:41:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🔐 prevent building .env in docker: https://dotenvx.com/prebuild
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:41:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🔐 prevent building .env in docker: https://dotenvx.com/prebuild
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:41:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ suppress all logs with { quiet: true }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:41:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: 🔐 prevent committing .env to code: https://dotenvx.com/precommit
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:41:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚙️ write to custom object with { processEnv: myObject }
DisTubeError [INVALID_KEY]: 'ffmpegPath' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:41:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
/home/ubuntu/executor/workspace/bot/index.js:23
const path = require('path');
^
SyntaxError: Identifier 'path' has already been declared
at wrapSafe (node:internal/modules/cjs/loader:1620:18)
at Module._compile (node:internal/modules/cjs/loader:1662:20)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
/home/ubuntu/executor/workspace/bot/index.js:23
const path = require('path');
^
SyntaxError: Identifier 'path' has already been declared
at wrapSafe (node:internal/modules/cjs/loader:1620:18)
at Module._compile (node:internal/modules/cjs/loader:1662:20)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
[dotenv@17.3.1] injecting env (4) from .env -- tip: ⚡️ secrets for agents: https://dotenvx.com/as2
DisTubeError [INVALID_KEY]: 'searchSongs' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:48:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[2026-02-16T09:12:28.825Z] Encryption library (libsodium) is ready.
[2026-02-16T09:12:31.821Z] Bot berhasil login!
[2026-02-16T09:12:31.824Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T09:12:32.048Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T09:12:33.315Z] Alarm scheduled at 30 3 * * *
[2026-02-16T09:12:51.302Z] Encryption library (libsodium) is ready.
[2026-02-16T09:12:52.841Z] Bot berhasil login!
[2026-02-16T09:12:52.842Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T09:12:52.845Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T09:12:53.302Z] Alarm scheduled at 30 3 * * *
[2026-02-16T09:47:09.105Z] Validation for "rindu aku rindu Kamu": search
[2026-02-16T09:47:09.106Z] Searching via play-dl for: rindu aku rindu Kamu
[2026-02-16T09:47:09.551Z] Playing: https://www.youtube.com/watch?v=l6jxy4U4GN0
[2026-02-16T09:47:10.617Z] Play Error: This url is not supported
[2026-02-16T09:47:20.346Z] Validation for "https://open.spotify.com/track/3qhlB30KknSejmIvZZLjOD?si=2NMmRTKnQJ-fMh9OmWm9Bw": sp_track
[2026-02-16T09:47:20.349Z] Info fetch error: This is not a YouTube Watch URL
[2026-02-16T09:47:20.349Z] Playing: https://open.spotify.com/track/3qhlB30KknSejmIvZZLjOD?si=2NMmRTKnQJ-fMh9OmWm9Bw
[2026-02-16T09:48:30.661Z] Playing local file independently: /home/ubuntu/executor/workspace/bot/assets/audio/sahur.mp3
[2026-02-16T09:51:23.713Z] Encryption library (libsodium) is ready.
[2026-02-16T09:51:25.185Z] Bot berhasil login!
[2026-02-16T09:51:25.186Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T09:51:25.186Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T09:51:26.198Z] Alarm scheduled at 30 3 * * *
[2026-02-16T09:53:28.554Z] Uncaught Exception: Unexpected token 'D', "Deprecated"... is not valid JSON

49
bot/deploy-commands.js Normal file
View File

@ -0,0 +1,49 @@
const { REST, Routes, SlashCommandBuilder } = require('discord.js');
const path = require('path');
require('dotenv').config({ path: path.join(__dirname, '.env') });
const commands = [
new SlashCommandBuilder()
.setName('join')
.setDescription('Bot join ke voice channel kamu'),
new SlashCommandBuilder()
.setName('testsahur')
.setDescription('Putar suara sahur.mp3 untuk mengetes'),
new SlashCommandBuilder()
.setName('play')
.setDescription('Putar musik dari YouTube, SoundCloud, atau Spotify')
.addStringOption(option =>
option.setName('query')
.setDescription('Link atau judul lagu')
.setRequired(true)),
new SlashCommandBuilder()
.setName('pause')
.setDescription('Pause musik yang sedang diputar'),
new SlashCommandBuilder()
.setName('resume')
.setDescription('Lanjutkan musik yang dipause'),
new SlashCommandBuilder()
.setName('skip')
.setDescription('Lewati lagu saat ini'),
new SlashCommandBuilder()
.setName('stop')
.setDescription('Berhentikan musik dan hapus antrean'),
].map(command => command.toJSON());
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
(async () => {
try {
console.log('Sedang mendaftarkan slash commands...');
// Register globally
await rest.put(
Routes.applicationCommands(process.env.CLIENT_ID),
{ body: commands },
);
console.log('Berhasil mendaftarkan slash commands!');
} catch (error) {
console.error(error);
}
})();

301
bot/index.js Normal file
View File

@ -0,0 +1,301 @@
process.env.FFMPEG_PATH = require('ffmpeg-static');
const ffmpeg = require('ffmpeg-static');
const path = require('path');
if (ffmpeg) {
const ffmpegDir = path.dirname(ffmpeg);
if (!process.env.PATH.includes(ffmpegDir)) {
process.env.PATH = `${ffmpegDir}${path.delimiter}${process.env.PATH}`;
}
}
const { Client, GatewayIntentBits, Events, EmbedBuilder, PermissionsBitField } = require('discord.js');
const { DisTube } = require('distube');
const { SoundCloudPlugin } = require('@distube/soundcloud');
const { SpotifyPlugin } = require('@distube/spotify');
const { YtDlpPlugin } = require('@distube/yt-dlp');
const play = require('play-dl');
const {
joinVoiceChannel,
createAudioPlayer,
createAudioResource,
AudioPlayerStatus,
StreamType
} = require('@discordjs/voice');
const { CronJob } = require('cron');
const fs = require('fs');
// Load environment variables
require('dotenv').config({ path: path.join(__dirname, '.env') });
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers // Added to fetch members for alarm
]
});
// Detect libsodium
try {
const sodium = require('libsodium-wrappers');
sodium.ready.then(() => {
logToFile("Encryption library (libsodium) is ready.");
});
} catch (e) {
logToFile("Warning: libsodium-wrappers not found or failed to load.");
}
const distube = new DisTube(client, {
ffmpegPath: require('ffmpeg-static'),
plugins: [
new SpotifyPlugin(),
new SoundCloudPlugin(),
new YtDlpPlugin({ update: true })
]
});
const VC_ID = process.env.VC_ID;
const AUDIO_PATH = path.join(__dirname, 'assets', 'audio', 'sahur.mp3');
const PREFIX = '!';
function logToFile(message) {
const logMessage = `[${new Date().toISOString()}] ${message}\n`;
try {
fs.appendFileSync(path.join(__dirname, 'bot.log'), logMessage);
} catch (err) {
console.error('Failed to write to log file:', err);
}
console.log(message);
}
async function playLocalIndependent(channel) {
if (!fs.existsSync(AUDIO_PATH)) {
logToFile(`Audio file not found: ${AUDIO_PATH}`);
return;
}
try {
// Leave DisTube first to avoid collision
await distube.voices.leave(channel.guild.id);
const connection = joinVoiceChannel({
channelId: channel.id,
guildId: channel.guild.id,
adapterCreator: channel.guild.voiceAdapterCreator,
selfDeaf: false,
});
const player = createAudioPlayer();
const resource = createAudioResource(AUDIO_PATH, {
inputType: StreamType.Arbitrary
});
player.play(resource);
connection.subscribe(player);
player.on(AudioPlayerStatus.Idle, () => {
connection.destroy();
});
player.on('error', error => {
logToFile(`Audio Player Error: ${error.message}`);
connection.destroy();
});
} catch (err) {
logToFile(`Independent play error: ${err.message}`);
}
}
client.once(Events.ClientReady, () => {
logToFile(`Bot berhasil login!`);
logToFile(`Ready! Logged in as ${client.user.tag}`);
logToFile(`FFMPEG Path: ${process.env.FFMPEG_PATH}`);
// Sahur Alarm
const rawSahurTime = process.env.SAHUR_TIME || '03:30';
let cronTime = '30 3 * * *';
if (rawSahurTime.includes(':')) {
const [hour, minute] = rawSahurTime.split(':');
cronTime = `${parseInt(minute)} ${parseInt(hour)} * * *`;
} else {
cronTime = rawSahurTime;
}
try {
new CronJob(cronTime, async () => {
logToFile('Sahur alarm triggered!');
const guild = client.guilds.cache.first();
if (!guild) return;
const channel = guild.channels.cache.get(VC_ID);
if (channel && fs.existsSync(AUDIO_PATH)) {
try {
await playLocalIndependent(channel);
logToFile('Alarm playing via independent @discordjs/voice.');
} catch (err) {
logToFile(`Alarm play error: ${err.message}`);
}
}
}, null, true, 'Asia/Jakarta');
logToFile(`Alarm scheduled at ${cronTime}`);
} catch (e) {
logToFile(`Failed to schedule alarm: ${e.message}`);
}
});
// Slash Command Handler
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
const { commandName } = interaction;
const voiceChannel = interaction.member?.voice.channel;
try {
if (commandName === 'join') {
if (!voiceChannel) return interaction.reply({ content: 'Anda harus berada di voice channel!', ephemeral: true });
await interaction.deferReply();
await distube.voices.join(voiceChannel, { selfDeaf: false, selfMute: false });
await interaction.editReply('Sudah join! 🎧');
}
else if (commandName === 'testsahur') {
if (!voiceChannel) return interaction.reply({ content: 'Anda harus berada di voice channel!', ephemeral: true });
if (!fs.existsSync(AUDIO_PATH)) return interaction.reply({ content: `File audio tidak ditemukan di ${AUDIO_PATH}`, ephemeral: true });
await interaction.deferReply();
logToFile(`Playing local file independently: ${AUDIO_PATH}`);
try {
await playLocalIndependent(voiceChannel);
await interaction.editReply('Memainkan suara sahur... 📢');
} catch (e) {
logToFile(`Error in testsahur: ${e.message}`);
await interaction.editReply(`Gagal memutar audio: ${e.message}`);
}
}
else if (commandName === 'play') {
await interaction.deferReply();
const query = interaction.options.getString('query');
const voiceChannel = interaction.member?.voice.channel;
if (!voiceChannel) return interaction.editReply({ content: 'Anda harus berada di voice channel!' });
try {
await distube.play(voiceChannel, query, {
textChannel: interaction.channel,
member: interaction.member
});
await interaction.editReply(`Mencari dan memutar: **${query}**... 🎶`);
} catch (e) {
logToFile(`Play Error: ${e.message}`);
if (interaction.deferred) {
await interaction.editReply(`Terjadi kesalahan: ${e.message}`);
}
}
}
else if (commandName === 'pause') {
distube.pause(interaction.guildId);
await interaction.reply('Musik dipause. ⏸️');
}
else if (commandName === 'resume') {
distube.resume(interaction.guildId);
await interaction.reply('Musik dilanjutkan. ▶️');
}
else if (commandName === 'skip') {
await distube.skip(interaction.guildId);
await interaction.reply('Lagu dilewati! ⏭️');
}
else if (commandName === 'stop') {
await distube.stop(interaction.guildId);
await interaction.reply('Musik dihentikan dan antrean dihapus. 👋');
}
} catch (error) {
logToFile(`Interaction Error (${commandName}): ${error.message}`);
if (!interaction.replied && !interaction.deferred) {
await interaction.reply({ content: `Terjadi kesalahan: ${error.message}`, ephemeral: true });
} else {
await interaction.editReply({ content: `Terjadi kesalahan: ${error.message}`, ephemeral: true });
}
}
});
// Prefix Command Handler (Legacy/Backup)
client.on(Events.MessageCreate, async message => {
if (message.author.bot || !message.content.startsWith(PREFIX)) return;
const args = message.content.slice(PREFIX.length).trim().split(/ +/);
const command = args.shift().toLowerCase();
const voiceChannel = message.member?.voice.channel;
try {
if (command === 'play') {
const query = args.join(' ');
if (!voiceChannel) return message.reply('Anda harus berada di voice channel!');
if (!query) return message.reply('Masukkan judul atau link lagu!');
try {
await distube.play(voiceChannel, query, {
member: message.member,
textChannel: message.channel,
message
});
message.reply(`🔍 Mencari dan memutar: **${query}**...`);
} catch (e) {
logToFile(`Message Play Error: ${e.message}`);
message.reply(`❌ Error: ${e.message}`);
}
} else if (['skip', 'stop', 'pause', 'resume'].includes(command)) {
if (!voiceChannel) return message.reply('Anda harus berada di voice channel!');
const method = command === 'skip' ? 'skip' : (command === 'stop' ? 'stop' : (command === 'pause' ? 'pause' : 'resume'));
await distube[method](message.guildId);
message.reply(`${command} berhasil!`);
} else if (command === 'testsahur') {
if (!voiceChannel) return message.reply('Anda harus berada di voice channel!');
try {
await playLocalIndependent(voiceChannel);
message.reply('Mengetes suara sahur... 📢');
} catch (e) {
message.reply(`❌ Error: ${e.message}`);
}
}
} catch (error) {
logToFile(`Message Command Error: ${error.message}`);
message.reply(`❌ Error: ${error.message}`);
}
});
// DisTube Events
distube
.on('playSong', (queue, song) => {
queue.textChannel.send(`🎵 Sekarang memutar: **${song.name}** - \`${song.formatDuration}\`\nRequested by: ${song.user}`);
})
.on('addSong', (queue, song) => {
queue.textChannel.send(`✅ **${song.name}** ditambahkan ke antrean oleh ${song.user}`);
})
.on('error', (channel, e) => {
logToFile(`DisTube Error: ${e.message || e}`);
if (e.message && e.message.includes('Sign in to confirm youre not a bot')) {
if (channel) channel.send(`❌ YouTube memblokir akses bot. Silakan coba link dari SoundCloud atau Spotify.`);
} else if (channel) {
channel.send(`❌ Terjadi kesalahan: ${(e.message || e).toString().slice(0, 2000)}`);
}
});
// Handle uncaught errors to prevent crash
process.on('unhandledRejection', error => {
logToFile(`Unhandled Rejection: ${error.message}`);
console.error(error);
});
process.on('uncaughtException', error => {
logToFile(`Uncaught Exception: ${error.message}`);
console.error(error);
});
// Login
client.login(process.env.DISCORD_TOKEN);

46
bot/node_modules/.abbrev-O32X2JcX/LICENSE generated vendored Normal file
View File

@ -0,0 +1,46 @@
This software is dual-licensed under the ISC and MIT licenses.
You may use this software under EITHER of the following licenses.
----------
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
----------
Copyright Isaac Z. Schlueter and Contributors
All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

23
bot/node_modules/.abbrev-O32X2JcX/README.md generated vendored Normal file
View File

@ -0,0 +1,23 @@
# abbrev-js
Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).
Usage:
var abbrev = require("abbrev");
abbrev("foo", "fool", "folding", "flop");
// returns:
{ fl: 'flop'
, flo: 'flop'
, flop: 'flop'
, fol: 'folding'
, fold: 'folding'
, foldi: 'folding'
, foldin: 'folding'
, folding: 'folding'
, foo: 'foo'
, fool: 'fool'
}
This is handy for command-line scripts, or other cases where you want to be able to accept shorthands.

61
bot/node_modules/.abbrev-O32X2JcX/abbrev.js generated vendored Normal file
View File

@ -0,0 +1,61 @@
module.exports = exports = abbrev.abbrev = abbrev
abbrev.monkeyPatch = monkeyPatch
function monkeyPatch () {
Object.defineProperty(Array.prototype, 'abbrev', {
value: function () { return abbrev(this) },
enumerable: false, configurable: true, writable: true
})
Object.defineProperty(Object.prototype, 'abbrev', {
value: function () { return abbrev(Object.keys(this)) },
enumerable: false, configurable: true, writable: true
})
}
function abbrev (list) {
if (arguments.length !== 1 || !Array.isArray(list)) {
list = Array.prototype.slice.call(arguments, 0)
}
for (var i = 0, l = list.length, args = [] ; i < l ; i ++) {
args[i] = typeof list[i] === "string" ? list[i] : String(list[i])
}
// sort them lexicographically, so that they're next to their nearest kin
args = args.sort(lexSort)
// walk through each, seeing how much it has in common with the next and previous
var abbrevs = {}
, prev = ""
for (var i = 0, l = args.length ; i < l ; i ++) {
var current = args[i]
, next = args[i + 1] || ""
, nextMatches = true
, prevMatches = true
if (current === next) continue
for (var j = 0, cl = current.length ; j < cl ; j ++) {
var curChar = current.charAt(j)
nextMatches = nextMatches && curChar === next.charAt(j)
prevMatches = prevMatches && curChar === prev.charAt(j)
if (!nextMatches && !prevMatches) {
j ++
break
}
}
prev = current
if (j === cl) {
abbrevs[current] = current
continue
}
for (var a = current.substr(0, j) ; j <= cl ; j ++) {
abbrevs[a] = current
a += current.charAt(j)
}
}
return abbrevs
}
function lexSort (a, b) {
return a === b ? 0 : a > b ? 1 : -1
}

21
bot/node_modules/.abbrev-O32X2JcX/package.json generated vendored Normal file
View File

@ -0,0 +1,21 @@
{
"name": "abbrev",
"version": "1.1.1",
"description": "Like ruby's abbrev module, but in js",
"author": "Isaac Z. Schlueter <i@izs.me>",
"main": "abbrev.js",
"scripts": {
"test": "tap test.js --100",
"preversion": "npm test",
"postversion": "npm publish",
"postpublish": "git push origin --all; git push origin --tags"
},
"repository": "http://github.com/isaacs/abbrev-js",
"license": "ISC",
"devDependencies": {
"tap": "^10.1"
},
"files": [
"abbrev.js"
]
}

37
bot/node_modules/.ansi-regex-JfBN4D2f/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,37 @@
declare namespace ansiRegex {
interface Options {
/**
Match only the first ANSI escape.
@default false
*/
onlyFirst: boolean;
}
}
/**
Regular expression for matching ANSI escape codes.
@example
```
import ansiRegex = require('ansi-regex');
ansiRegex().test('\u001B[4mcake\u001B[0m');
//=> true
ansiRegex().test('cake');
//=> false
'\u001B[4mcake\u001B[0m'.match(ansiRegex());
//=> ['\u001B[4m', '\u001B[0m']
'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true}));
//=> ['\u001B[4m']
'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex());
//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007']
```
*/
declare function ansiRegex(options?: ansiRegex.Options): RegExp;
export = ansiRegex;

10
bot/node_modules/.ansi-regex-JfBN4D2f/index.js generated vendored Normal file
View File

@ -0,0 +1,10 @@
'use strict';
module.exports = ({onlyFirst = false} = {}) => {
const pattern = [
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
].join('|');
return new RegExp(pattern, onlyFirst ? undefined : 'g');
};

9
bot/node_modules/.ansi-regex-JfBN4D2f/license generated vendored Normal file
View File

@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

55
bot/node_modules/.ansi-regex-JfBN4D2f/package.json generated vendored Normal file
View File

@ -0,0 +1,55 @@
{
"name": "ansi-regex",
"version": "5.0.1",
"description": "Regular expression for matching ANSI escape codes",
"license": "MIT",
"repository": "chalk/ansi-regex",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=8"
},
"scripts": {
"test": "xo && ava && tsd",
"view-supported": "node fixtures/view-codes.js"
},
"files": [
"index.js",
"index.d.ts"
],
"keywords": [
"ansi",
"styles",
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"tty",
"escape",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"command-line",
"text",
"regex",
"regexp",
"re",
"match",
"test",
"find",
"pattern"
],
"devDependencies": {
"ava": "^2.4.0",
"tsd": "^0.9.0",
"xo": "^0.25.3"
}
}

78
bot/node_modules/.ansi-regex-JfBN4D2f/readme.md generated vendored Normal file
View File

@ -0,0 +1,78 @@
# ansi-regex
> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)
## Install
```
$ npm install ansi-regex
```
## Usage
```js
const ansiRegex = require('ansi-regex');
ansiRegex().test('\u001B[4mcake\u001B[0m');
//=> true
ansiRegex().test('cake');
//=> false
'\u001B[4mcake\u001B[0m'.match(ansiRegex());
//=> ['\u001B[4m', '\u001B[0m']
'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true}));
//=> ['\u001B[4m']
'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex());
//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007']
```
## API
### ansiRegex(options?)
Returns a regex for matching ANSI escape codes.
#### options
Type: `object`
##### onlyFirst
Type: `boolean`<br>
Default: `false` *(Matches any ANSI escape codes in a string)*
Match only the first ANSI escape.
## FAQ
### Why do you test for codes not in the ECMA 48 standard?
Some of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.
On the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of "interrupts" that can mean different things on certain brands of processors, most of which have been phased out.
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)
---
<div align="center">
<b>
<a href="https://tidelift.com/subscription/pkg/npm-ansi-regex?utm_source=npm-ansi-regex&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>

14
bot/node_modules/.aproba-TCLTmkVC/LICENSE generated vendored Normal file
View File

@ -0,0 +1,14 @@
Copyright (c) 2015, Rebecca Turner <me@re-becca.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

94
bot/node_modules/.aproba-TCLTmkVC/README.md generated vendored Normal file
View File

@ -0,0 +1,94 @@
aproba
======
A ridiculously light-weight function argument validator
```
var validate = require("aproba")
function myfunc(a, b, c) {
// `a` must be a string, `b` a number, `c` a function
validate('SNF', arguments) // [a,b,c] is also valid
}
myfunc('test', 23, function () {}) // ok
myfunc(123, 23, function () {}) // type error
myfunc('test', 23) // missing arg error
myfunc('test', 23, function () {}, true) // too many args error
```
Valid types are:
| type | description
| :--: | :----------
| * | matches any type
| A | `Array.isArray` OR an `arguments` object
| S | typeof == string
| N | typeof == number
| F | typeof == function
| O | typeof == object and not type A and not type E
| B | typeof == boolean
| E | `instanceof Error` OR `null` **(special: see below)**
| Z | == `null`
Validation failures throw one of three exception types, distinguished by a
`code` property of `EMISSINGARG`, `EINVALIDTYPE` or `ETOOMANYARGS`.
If you pass in an invalid type then it will throw with a code of
`EUNKNOWNTYPE`.
If an **error** argument is found and is not null then the remaining
arguments are optional. That is, if you say `ESO` then that's like using a
non-magical `E` in: `E|ESO|ZSO`.
### But I have optional arguments?!
You can provide more than one signature by separating them with pipes `|`.
If any signature matches the arguments then they'll be considered valid.
So for example, say you wanted to write a signature for
`fs.createWriteStream`. The docs for it describe it thusly:
```
fs.createWriteStream(path[, options])
```
This would be a signature of `SO|S`. That is, a string and and object, or
just a string.
Now, if you read the full `fs` docs, you'll see that actually path can ALSO
be a buffer. And options can be a string, that is:
```
path <String> | <Buffer>
options <String> | <Object>
```
To reproduce this you have to fully enumerate all of the possible
combinations and that implies a signature of `SO|SS|OO|OS|S|O`. The
awkwardness is a feature: It reminds you of the complexity you're adding to
your API when you do this sort of thing.
### Browser support
This has no dependencies and should work in browsers, though you'll have
noisier stack traces.
### Why this exists
I wanted a very simple argument validator. It needed to do two things:
1. Be more concise and easier to use than assertions
2. Not encourage an infinite bikeshed of DSLs
This is why types are specified by a single character and there's no such
thing as an optional argument.
This is not intended to validate user data. This is specifically about
asserting the interface of your functions.
If you need greater validation, I encourage you to write them by hand or
look elsewhere.

105
bot/node_modules/.aproba-TCLTmkVC/index.js generated vendored Normal file
View File

@ -0,0 +1,105 @@
'use strict'
module.exports = validate
function isArguments (thingy) {
return thingy != null && typeof thingy === 'object' && thingy.hasOwnProperty('callee')
}
const types = {
'*': {label: 'any', check: () => true},
A: {label: 'array', check: _ => Array.isArray(_) || isArguments(_)},
S: {label: 'string', check: _ => typeof _ === 'string'},
N: {label: 'number', check: _ => typeof _ === 'number'},
F: {label: 'function', check: _ => typeof _ === 'function'},
O: {label: 'object', check: _ => typeof _ === 'object' && _ != null && !types.A.check(_) && !types.E.check(_)},
B: {label: 'boolean', check: _ => typeof _ === 'boolean'},
E: {label: 'error', check: _ => _ instanceof Error},
Z: {label: 'null', check: _ => _ == null}
}
function addSchema (schema, arity) {
const group = arity[schema.length] = arity[schema.length] || []
if (group.indexOf(schema) === -1) group.push(schema)
}
function validate (rawSchemas, args) {
if (arguments.length !== 2) throw wrongNumberOfArgs(['SA'], arguments.length)
if (!rawSchemas) throw missingRequiredArg(0, 'rawSchemas')
if (!args) throw missingRequiredArg(1, 'args')
if (!types.S.check(rawSchemas)) throw invalidType(0, ['string'], rawSchemas)
if (!types.A.check(args)) throw invalidType(1, ['array'], args)
const schemas = rawSchemas.split('|')
const arity = {}
schemas.forEach(schema => {
for (let ii = 0; ii < schema.length; ++ii) {
const type = schema[ii]
if (!types[type]) throw unknownType(ii, type)
}
if (/E.*E/.test(schema)) throw moreThanOneError(schema)
addSchema(schema, arity)
if (/E/.test(schema)) {
addSchema(schema.replace(/E.*$/, 'E'), arity)
addSchema(schema.replace(/E/, 'Z'), arity)
if (schema.length === 1) addSchema('', arity)
}
})
let matching = arity[args.length]
if (!matching) {
throw wrongNumberOfArgs(Object.keys(arity), args.length)
}
for (let ii = 0; ii < args.length; ++ii) {
let newMatching = matching.filter(schema => {
const type = schema[ii]
const typeCheck = types[type].check
return typeCheck(args[ii])
})
if (!newMatching.length) {
const labels = matching.map(_ => types[_[ii]].label).filter(_ => _ != null)
throw invalidType(ii, labels, args[ii])
}
matching = newMatching
}
}
function missingRequiredArg (num) {
return newException('EMISSINGARG', 'Missing required argument #' + (num + 1))
}
function unknownType (num, type) {
return newException('EUNKNOWNTYPE', 'Unknown type ' + type + ' in argument #' + (num + 1))
}
function invalidType (num, expectedTypes, value) {
let valueType
Object.keys(types).forEach(typeCode => {
if (types[typeCode].check(value)) valueType = types[typeCode].label
})
return newException('EINVALIDTYPE', 'Argument #' + (num + 1) + ': Expected ' +
englishList(expectedTypes) + ' but got ' + valueType)
}
function englishList (list) {
return list.join(', ').replace(/, ([^,]+)$/, ' or $1')
}
function wrongNumberOfArgs (expected, got) {
const english = englishList(expected)
const args = expected.every(ex => ex.length === 1)
? 'argument'
: 'arguments'
return newException('EWRONGARGCOUNT', 'Expected ' + english + ' ' + args + ' but got ' + got)
}
function moreThanOneError (schema) {
return newException('ETOOMANYERRORTYPES',
'Only one error type per argument signature is allowed, more than one found in "' + schema + '"')
}
function newException (code, msg) {
const err = new TypeError(msg)
err.code = code
/* istanbul ignore else */
if (Error.captureStackTrace) Error.captureStackTrace(err, validate)
return err
}

35
bot/node_modules/.aproba-TCLTmkVC/package.json generated vendored Normal file
View File

@ -0,0 +1,35 @@
{
"name": "aproba",
"version": "2.1.0",
"description": "A ridiculously light-weight argument validator (now browser friendly)",
"main": "index.js",
"directories": {
"test": "test"
},
"dependencies": {},
"devDependencies": {
"standard": "^11.0.1",
"tap": "^12.0.1"
},
"files": [
"index.js"
],
"scripts": {
"pretest": "standard",
"test": "tap --100 -J test/*.js"
},
"repository": {
"type": "git",
"url": "https://github.com/iarna/aproba"
},
"keywords": [
"argument",
"validate"
],
"author": "Rebecca Turner <me@re-becca.org>",
"license": "ISC",
"bugs": {
"url": "https://github.com/iarna/aproba/issues"
},
"homepage": "https://github.com/iarna/aproba"
}

18
bot/node_modules/.are-we-there-yet-8CTQ7ygo/LICENSE.md generated vendored Normal file
View File

@ -0,0 +1,18 @@
ISC License
Copyright npm, Inc.
Permission to use, copy, modify, and/or distribute this
software for any purpose with or without fee is hereby
granted, provided that the above copyright notice and this
permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.

208
bot/node_modules/.are-we-there-yet-8CTQ7ygo/README.md generated vendored Normal file
View File

@ -0,0 +1,208 @@
are-we-there-yet
----------------
Track complex hierarchies of asynchronous task completion statuses. This is
intended to give you a way of recording and reporting the progress of the big
recursive fan-out and gather type workflows that are so common in async.
What you do with this completion data is up to you, but the most common use case is to
feed it to one of the many progress bar modules.
Most progress bar modules include a rudimentary version of this, but my
needs were more complex.
Usage
=====
```javascript
var TrackerGroup = require("are-we-there-yet").TrackerGroup
var top = new TrackerGroup("program")
var single = top.newItem("one thing", 100)
single.completeWork(20)
console.log(top.completed()) // 0.2
fs.stat("file", function(er, stat) {
if (er) throw er
var stream = top.newStream("file", stat.size)
console.log(top.completed()) // now 0.1 as single is 50% of the job and is 20% complete
// and 50% * 20% == 10%
fs.createReadStream("file").pipe(stream).on("data", function (chunk) {
// do stuff with chunk
})
top.on("change", function (name) {
// called each time a chunk is read from "file"
// top.completed() will start at 0.1 and fill up to 0.6 as the file is read
})
})
```
Shared Methods
==============
* var completed = tracker.completed()
Implemented in: `Tracker`, `TrackerGroup`, `TrackerStream`
Returns the ratio of completed work to work to be done. Range of 0 to 1.
* tracker.finish()
Implemented in: `Tracker`, `TrackerGroup`
Marks the tracker as completed. With a TrackerGroup this marks all of its
components as completed.
Marks all of the components of this tracker as finished, which in turn means
that `tracker.completed()` for this will now be 1.
This will result in one or more `change` events being emitted.
Events
======
All tracker objects emit `change` events with the following arguments:
```
function (name, completed, tracker)
```
`name` is the name of the tracker that originally emitted the event,
or if it didn't have one, the first containing tracker group that had one.
`completed` is the percent complete (as returned by `tracker.completed()` method).
`tracker` is the tracker object that you are listening for events on.
TrackerGroup
============
* var tracker = new TrackerGroup(**name**)
* **name** *(optional)* - The name of this tracker group, used in change
notifications if the component updating didn't have a name. Defaults to undefined.
Creates a new empty tracker aggregation group. These are trackers whose
completion status is determined by the completion status of other trackers added to this aggregation group.
Ex.
```javascript
var tracker = new TrackerGroup("parent")
var foo = tracker.newItem("firstChild", 100)
var bar = tracker.newItem("secondChild", 100)
foo.finish()
console.log(tracker.completed()) // 0.5
bar.finish()
console.log(tracker.completed()) // 1
```
* tracker.addUnit(**otherTracker**, **weight**)
* **otherTracker** - Any of the other are-we-there-yet tracker objects
* **weight** *(optional)* - The weight to give the tracker, defaults to 1.
Adds the **otherTracker** to this aggregation group. The weight determines
how long you expect this tracker to take to complete in proportion to other
units. So for instance, if you add one tracker with a weight of 1 and
another with a weight of 2, you're saying the second will take twice as long
to complete as the first. As such, the first will account for 33% of the
completion of this tracker and the second will account for the other 67%.
Returns **otherTracker**.
* var subGroup = tracker.newGroup(**name**, **weight**)
The above is exactly equivalent to:
```javascript
var subGroup = tracker.addUnit(new TrackerGroup(name), weight)
```
* var subItem = tracker.newItem(**name**, **todo**, **weight**)
The above is exactly equivalent to:
```javascript
var subItem = tracker.addUnit(new Tracker(name, todo), weight)
```
* var subStream = tracker.newStream(**name**, **todo**, **weight**)
The above is exactly equivalent to:
```javascript
var subStream = tracker.addUnit(new TrackerStream(name, todo), weight)
```
* console.log( tracker.debug() )
Returns a tree showing the completion of this tracker group and all of its
children, including recursively entering all of the children.
Tracker
=======
* var tracker = new Tracker(**name**, **todo**)
* **name** *(optional)* The name of this counter to report in change
events. Defaults to undefined.
* **todo** *(optional)* The amount of work todo (a number). Defaults to 0.
Ordinarily these are constructed as a part of a tracker group (via
`newItem`).
* var completed = tracker.completed()
Returns the ratio of completed work to work to be done. Range of 0 to 1. If
total work to be done is 0 then it will return 0.
* tracker.addWork(**todo**)
* **todo** A number to add to the amount of work to be done.
Increases the amount of work to be done, thus decreasing the completion
percentage. Triggers a `change` event.
* tracker.completeWork(**completed**)
* **completed** A number to add to the work complete
Increase the amount of work complete, thus increasing the completion percentage.
Will never increase the work completed past the amount of work todo. That is,
percentages > 100% are not allowed. Triggers a `change` event.
* tracker.finish()
Marks this tracker as finished, tracker.completed() will now be 1. Triggers
a `change` event.
TrackerStream
=============
* var tracker = new TrackerStream(**name**, **size**, **options**)
* **name** *(optional)* The name of this counter to report in change
events. Defaults to undefined.
* **size** *(optional)* The number of bytes being sent through this stream.
* **options** *(optional)* A hash of stream options
The tracker stream object is a pass through stream that updates an internal
tracker object each time a block passes through. It's intended to track
downloads, file extraction and other related activities. You use it by piping
your data source into it and then using it as your data source.
If your data has a length attribute then that's used as the amount of work
completed when the chunk is passed through. If it does not (eg, object
streams) then each chunk counts as completing 1 unit of work, so your size
should be the total number of objects being streamed.
* tracker.addWork(**todo**)
* **todo** Increase the expected overall size by **todo** bytes.
Increases the amount of work to be done, thus decreasing the completion
percentage. Triggers a `change` event.

View File

@ -0,0 +1,4 @@
'use strict'
exports.TrackerGroup = require('./tracker-group.js')
exports.Tracker = require('./tracker.js')
exports.TrackerStream = require('./tracker-stream.js')

View File

@ -0,0 +1,11 @@
'use strict'
var EventEmitter = require('events').EventEmitter
var util = require('util')
var trackerId = 0
var TrackerBase = module.exports = function (name) {
EventEmitter.call(this)
this.id = ++trackerId
this.name = name
}
util.inherits(TrackerBase, EventEmitter)

View File

@ -0,0 +1,116 @@
'use strict'
var util = require('util')
var TrackerBase = require('./tracker-base.js')
var Tracker = require('./tracker.js')
var TrackerStream = require('./tracker-stream.js')
var TrackerGroup = module.exports = function (name) {
TrackerBase.call(this, name)
this.parentGroup = null
this.trackers = []
this.completion = {}
this.weight = {}
this.totalWeight = 0
this.finished = false
this.bubbleChange = bubbleChange(this)
}
util.inherits(TrackerGroup, TrackerBase)
function bubbleChange (trackerGroup) {
return function (name, completed, tracker) {
trackerGroup.completion[tracker.id] = completed
if (trackerGroup.finished) {
return
}
trackerGroup.emit('change', name || trackerGroup.name, trackerGroup.completed(), trackerGroup)
}
}
TrackerGroup.prototype.nameInTree = function () {
var names = []
var from = this
while (from) {
names.unshift(from.name)
from = from.parentGroup
}
return names.join('/')
}
TrackerGroup.prototype.addUnit = function (unit, weight) {
if (unit.addUnit) {
var toTest = this
while (toTest) {
if (unit === toTest) {
throw new Error(
'Attempted to add tracker group ' +
unit.name + ' to tree that already includes it ' +
this.nameInTree(this))
}
toTest = toTest.parentGroup
}
unit.parentGroup = this
}
this.weight[unit.id] = weight || 1
this.totalWeight += this.weight[unit.id]
this.trackers.push(unit)
this.completion[unit.id] = unit.completed()
unit.on('change', this.bubbleChange)
if (!this.finished) {
this.emit('change', unit.name, this.completion[unit.id], unit)
}
return unit
}
TrackerGroup.prototype.completed = function () {
if (this.trackers.length === 0) {
return 0
}
var valPerWeight = 1 / this.totalWeight
var completed = 0
for (var ii = 0; ii < this.trackers.length; ii++) {
var trackerId = this.trackers[ii].id
completed +=
valPerWeight * this.weight[trackerId] * this.completion[trackerId]
}
return completed
}
TrackerGroup.prototype.newGroup = function (name, weight) {
return this.addUnit(new TrackerGroup(name), weight)
}
TrackerGroup.prototype.newItem = function (name, todo, weight) {
return this.addUnit(new Tracker(name, todo), weight)
}
TrackerGroup.prototype.newStream = function (name, todo, weight) {
return this.addUnit(new TrackerStream(name, todo), weight)
}
TrackerGroup.prototype.finish = function () {
this.finished = true
if (!this.trackers.length) {
this.addUnit(new Tracker(), 1, true)
}
for (var ii = 0; ii < this.trackers.length; ii++) {
var tracker = this.trackers[ii]
tracker.finish()
tracker.removeListener('change', this.bubbleChange)
}
this.emit('change', this.name, 1, this)
}
var buffer = ' '
TrackerGroup.prototype.debug = function (depth) {
depth = depth || 0
var indent = depth ? buffer.substr(0, depth) : ''
var output = indent + (this.name || 'top') + ': ' + this.completed() + '\n'
this.trackers.forEach(function (tracker) {
if (tracker instanceof TrackerGroup) {
output += tracker.debug(depth + 1)
} else {
output += indent + ' ' + tracker.name + ': ' + tracker.completed() + '\n'
}
})
return output
}

View File

@ -0,0 +1,36 @@
'use strict'
var util = require('util')
var stream = require('readable-stream')
var delegate = require('delegates')
var Tracker = require('./tracker.js')
var TrackerStream = module.exports = function (name, size, options) {
stream.Transform.call(this, options)
this.tracker = new Tracker(name, size)
this.name = name
this.id = this.tracker.id
this.tracker.on('change', delegateChange(this))
}
util.inherits(TrackerStream, stream.Transform)
function delegateChange (trackerStream) {
return function (name, completion, tracker) {
trackerStream.emit('change', name, completion, trackerStream)
}
}
TrackerStream.prototype._transform = function (data, encoding, cb) {
this.tracker.completeWork(data.length ? data.length : 1)
this.push(data)
cb()
}
TrackerStream.prototype._flush = function (cb) {
this.tracker.finish()
cb()
}
delegate(TrackerStream.prototype, 'tracker')
.method('completed')
.method('addWork')
.method('finish')

View File

@ -0,0 +1,32 @@
'use strict'
var util = require('util')
var TrackerBase = require('./tracker-base.js')
var Tracker = module.exports = function (name, todo) {
TrackerBase.call(this, name)
this.workDone = 0
this.workTodo = todo || 0
}
util.inherits(Tracker, TrackerBase)
Tracker.prototype.completed = function () {
return this.workTodo === 0 ? 0 : this.workDone / this.workTodo
}
Tracker.prototype.addWork = function (work) {
this.workTodo += work
this.emit('change', this.name, this.completed(), this)
}
Tracker.prototype.completeWork = function (work) {
this.workDone += work
if (this.workDone > this.workTodo) {
this.workDone = this.workTodo
}
this.emit('change', this.name, this.completed(), this)
}
Tracker.prototype.finish = function () {
this.workTodo = this.workDone = 1
this.emit('change', this.name, 1, this)
}

View File

@ -0,0 +1,53 @@
{
"name": "are-we-there-yet",
"version": "2.0.0",
"description": "Keep track of the overall completion of many disparate processes",
"main": "lib/index.js",
"scripts": {
"test": "tap",
"npmclilint": "npmcli-lint",
"lint": "eslint '**/*.js'",
"lintfix": "npm run lint -- --fix",
"posttest": "npm run lint",
"postsnap": "npm run lintfix --",
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"snap": "tap"
},
"repository": {
"type": "git",
"url": "https://github.com/npm/are-we-there-yet.git"
},
"author": "GitHub Inc.",
"license": "ISC",
"bugs": {
"url": "https://github.com/npm/are-we-there-yet/issues"
},
"homepage": "https://github.com/npm/are-we-there-yet",
"devDependencies": {
"@npmcli/eslint-config": "^1.0.0",
"@npmcli/template-oss": "^1.0.2",
"eslint": "^7.32.0",
"eslint-plugin-node": "^11.1.0",
"tap": "^15.0.9"
},
"dependencies": {
"delegates": "^1.0.0",
"readable-stream": "^3.6.0"
},
"files": [
"bin",
"lib"
],
"engines": {
"node": ">=10"
},
"tap": {
"branches": 68,
"statements": 92,
"functions": 86,
"lines": 92
},
"templateVersion": "1.0.2"
}

View File

@ -0,0 +1,2 @@
tidelift: "npm/balanced-match"
patreon: juliangruber

21
bot/node_modules/.balanced-match-xbdHUzPT/LICENSE.md generated vendored Normal file
View File

@ -0,0 +1,21 @@
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

97
bot/node_modules/.balanced-match-xbdHUzPT/README.md generated vendored Normal file
View File

@ -0,0 +1,97 @@
# balanced-match
Match balanced string pairs, like `{` and `}` or `<b>` and `</b>`. Supports regular expressions as well!
[![build status](https://secure.travis-ci.org/juliangruber/balanced-match.svg)](http://travis-ci.org/juliangruber/balanced-match)
[![downloads](https://img.shields.io/npm/dm/balanced-match.svg)](https://www.npmjs.org/package/balanced-match)
[![testling badge](https://ci.testling.com/juliangruber/balanced-match.png)](https://ci.testling.com/juliangruber/balanced-match)
## Example
Get the first matching pair of braces:
```js
var balanced = require('balanced-match');
console.log(balanced('{', '}', 'pre{in{nested}}post'));
console.log(balanced('{', '}', 'pre{first}between{second}post'));
console.log(balanced(/\s+\{\s+/, /\s+\}\s+/, 'pre { in{nest} } post'));
```
The matches are:
```bash
$ node example.js
{ start: 3, end: 14, pre: 'pre', body: 'in{nested}', post: 'post' }
{ start: 3,
end: 9,
pre: 'pre',
body: 'first',
post: 'between{second}post' }
{ start: 3, end: 17, pre: 'pre', body: 'in{nest}', post: 'post' }
```
## API
### var m = balanced(a, b, str)
For the first non-nested matching pair of `a` and `b` in `str`, return an
object with those keys:
* **start** the index of the first match of `a`
* **end** the index of the matching `b`
* **pre** the preamble, `a` and `b` not included
* **body** the match, `a` and `b` not included
* **post** the postscript, `a` and `b` not included
If there's no match, `undefined` will be returned.
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `['{', 'a', '']` and `{a}}` will match `['', 'a', '}']`.
### var r = balanced.range(a, b, str)
For the first non-nested matching pair of `a` and `b` in `str`, return an
array with indexes: `[ <a index>, <b index> ]`.
If there's no match, `undefined` will be returned.
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `[ 1, 3 ]` and `{a}}` will match `[0, 2]`.
## Installation
With [npm](https://npmjs.org) do:
```bash
npm install balanced-match
```
## Security contact information
To report a security vulnerability, please use the
[Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

62
bot/node_modules/.balanced-match-xbdHUzPT/index.js generated vendored Normal file
View File

@ -0,0 +1,62 @@
'use strict';
module.exports = balanced;
function balanced(a, b, str) {
if (a instanceof RegExp) a = maybeMatch(a, str);
if (b instanceof RegExp) b = maybeMatch(b, str);
var r = range(a, b, str);
return r && {
start: r[0],
end: r[1],
pre: str.slice(0, r[0]),
body: str.slice(r[0] + a.length, r[1]),
post: str.slice(r[1] + b.length)
};
}
function maybeMatch(reg, str) {
var m = str.match(reg);
return m ? m[0] : null;
}
balanced.range = range;
function range(a, b, str) {
var begs, beg, left, right, result;
var ai = str.indexOf(a);
var bi = str.indexOf(b, ai + 1);
var i = ai;
if (ai >= 0 && bi > 0) {
if(a===b) {
return [ai, bi];
}
begs = [];
left = str.length;
while (i >= 0 && !result) {
if (i == ai) {
begs.push(i);
ai = str.indexOf(a, i + 1);
} else if (begs.length == 1) {
result = [ begs.pop(), bi ];
} else {
beg = begs.pop();
if (beg < left) {
left = beg;
right = bi;
}
bi = str.indexOf(b, i + 1);
}
i = ai < bi && ai >= 0 ? ai : bi;
}
if (begs.length) {
result = [ left, right ];
}
}
return result;
}

48
bot/node_modules/.balanced-match-xbdHUzPT/package.json generated vendored Normal file
View File

@ -0,0 +1,48 @@
{
"name": "balanced-match",
"description": "Match balanced character pairs, like \"{\" and \"}\"",
"version": "1.0.2",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/balanced-match.git"
},
"homepage": "https://github.com/juliangruber/balanced-match",
"main": "index.js",
"scripts": {
"test": "tape test/test.js",
"bench": "matcha test/bench.js"
},
"devDependencies": {
"matcha": "^0.7.0",
"tape": "^4.6.0"
},
"keywords": [
"match",
"regexp",
"test",
"balanced",
"parse"
],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT",
"testling": {
"files": "test/*.js",
"browsers": [
"ie/8..latest",
"firefox/20..latest",
"firefox/nightly",
"chrome/25..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
}
}

1
bot/node_modules/.bin/.color-support-LdKYIFux generated vendored Symbolic link
View File

@ -0,0 +1 @@
../color-support/bin.js

1
bot/node_modules/.bin/.mkdirp-fSVFHkeL generated vendored Symbolic link
View File

@ -0,0 +1 @@
../mkdirp/bin/cmd.js

1
bot/node_modules/.bin/.node-pre-gyp-8zQEs6Yi generated vendored Symbolic link
View File

@ -0,0 +1 @@
../@discordjs/node-pre-gyp/bin/node-pre-gyp

1
bot/node_modules/.bin/.nopt-O63AwRKp generated vendored Symbolic link
View File

@ -0,0 +1 @@
../nopt/bin/nopt.js

1
bot/node_modules/.bin/.rimraf-shgW6yNX generated vendored Symbolic link
View File

@ -0,0 +1 @@
../rimraf/bin.js

1
bot/node_modules/.bin/.semver-8A0xkVgO generated vendored Symbolic link
View File

@ -0,0 +1 @@
../semver/bin/semver.js

1
bot/node_modules/.bin/color-support generated vendored Symbolic link
View File

@ -0,0 +1 @@
../color-support/bin.js

1
bot/node_modules/.bin/mime generated vendored Symbolic link
View File

@ -0,0 +1 @@
../mime/cli.js

1
bot/node_modules/.bin/mkdirp generated vendored Symbolic link
View File

@ -0,0 +1 @@
../mkdirp/bin/cmd.js

1
bot/node_modules/.bin/node-pre-gyp generated vendored Symbolic link
View File

@ -0,0 +1 @@
../@discordjs/node-pre-gyp/bin/node-pre-gyp

1
bot/node_modules/.bin/nopt generated vendored Symbolic link
View File

@ -0,0 +1 @@
../nopt/bin/nopt.js

1
bot/node_modules/.bin/rimraf generated vendored Symbolic link
View File

@ -0,0 +1 @@
../rimraf/bin.js

1
bot/node_modules/.bin/semver generated vendored Symbolic link
View File

@ -0,0 +1 @@
../semver/bin/semver.js

21
bot/node_modules/.brace-expansion-U5SNDfbX/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

129
bot/node_modules/.brace-expansion-U5SNDfbX/README.md generated vendored Normal file
View File

@ -0,0 +1,129 @@
# brace-expansion
[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html),
as known from sh/bash, in JavaScript.
[![build status](https://secure.travis-ci.org/juliangruber/brace-expansion.svg)](http://travis-ci.org/juliangruber/brace-expansion)
[![downloads](https://img.shields.io/npm/dm/brace-expansion.svg)](https://www.npmjs.org/package/brace-expansion)
[![Greenkeeper badge](https://badges.greenkeeper.io/juliangruber/brace-expansion.svg)](https://greenkeeper.io/)
[![testling badge](https://ci.testling.com/juliangruber/brace-expansion.png)](https://ci.testling.com/juliangruber/brace-expansion)
## Example
```js
var expand = require('brace-expansion');
expand('file-{a,b,c}.jpg')
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
expand('-v{,,}')
// => ['-v', '-v', '-v']
expand('file{0..2}.jpg')
// => ['file0.jpg', 'file1.jpg', 'file2.jpg']
expand('file-{a..c}.jpg')
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
expand('file{2..0}.jpg')
// => ['file2.jpg', 'file1.jpg', 'file0.jpg']
expand('file{0..4..2}.jpg')
// => ['file0.jpg', 'file2.jpg', 'file4.jpg']
expand('file-{a..e..2}.jpg')
// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg']
expand('file{00..10..5}.jpg')
// => ['file00.jpg', 'file05.jpg', 'file10.jpg']
expand('{{A..C},{a..c}}')
// => ['A', 'B', 'C', 'a', 'b', 'c']
expand('ppp{,config,oe{,conf}}')
// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']
```
## API
```js
var expand = require('brace-expansion');
```
### var expanded = expand(str)
Return an array of all possible and valid expansions of `str`. If none are
found, `[str]` is returned.
Valid expansions are:
```js
/^(.*,)+(.+)?$/
// {a,b,...}
```
A comma separated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`.
```js
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
// {x..y[..incr]}
```
A numeric sequence from `x` to `y` inclusive, with optional increment.
If `x` or `y` start with a leading `0`, all the numbers will be padded
to have equal length. Negative numbers and backwards iteration work too.
```js
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
// {x..y[..incr]}
```
An alphabetic sequence from `x` to `y` inclusive, with optional increment.
`x` and `y` must be exactly one character, and if given, `incr` must be a
number.
For compatibility reasons, the string `${` is not eligible for brace expansion.
## Installation
With [npm](https://npmjs.org) do:
```bash
npm install brace-expansion
```
## Contributors
- [Julian Gruber](https://github.com/juliangruber)
- [Isaac Z. Schlueter](https://github.com/isaacs)
## Sponsors
This module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)!
Do you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)!
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

201
bot/node_modules/.brace-expansion-U5SNDfbX/index.js generated vendored Normal file
View File

@ -0,0 +1,201 @@
var concatMap = require('concat-map');
var balanced = require('balanced-match');
module.exports = expandTop;
var escSlash = '\0SLASH'+Math.random()+'\0';
var escOpen = '\0OPEN'+Math.random()+'\0';
var escClose = '\0CLOSE'+Math.random()+'\0';
var escComma = '\0COMMA'+Math.random()+'\0';
var escPeriod = '\0PERIOD'+Math.random()+'\0';
function numeric(str) {
return parseInt(str, 10) == str
? parseInt(str, 10)
: str.charCodeAt(0);
}
function escapeBraces(str) {
return str.split('\\\\').join(escSlash)
.split('\\{').join(escOpen)
.split('\\}').join(escClose)
.split('\\,').join(escComma)
.split('\\.').join(escPeriod);
}
function unescapeBraces(str) {
return str.split(escSlash).join('\\')
.split(escOpen).join('{')
.split(escClose).join('}')
.split(escComma).join(',')
.split(escPeriod).join('.');
}
// Basically just str.split(","), but handling cases
// where we have nested braced sections, which should be
// treated as individual members, like {a,{b,c},d}
function parseCommaParts(str) {
if (!str)
return [''];
var parts = [];
var m = balanced('{', '}', str);
if (!m)
return str.split(',');
var pre = m.pre;
var body = m.body;
var post = m.post;
var p = pre.split(',');
p[p.length-1] += '{' + body + '}';
var postParts = parseCommaParts(post);
if (post.length) {
p[p.length-1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
function expandTop(str) {
if (!str)
return [];
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
// but a{},b}c will be expanded to [a}c,abc].
// One could argue that this is a bug in Bash, but since the goal of
// this module is to match Bash's rules, we escape a leading {}
if (str.substr(0, 2) === '{}') {
str = '\\{\\}' + str.substr(2);
}
return expand(escapeBraces(str), true).map(unescapeBraces);
}
function identity(e) {
return e;
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
function expand(str, isTop) {
var expansions = [];
var m = balanced('{', '}', str);
if (!m || /\$$/.test(m.pre)) return [str];
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
var isSequence = isNumericSequence || isAlphaSequence;
var isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,(?!,).*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
return expand(str);
}
return [str];
}
var n;
if (isSequence) {
n = m.body.split(/\.\./);
} else {
n = parseCommaParts(m.body);
if (n.length === 1) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand(n[0], false).map(embrace);
if (n.length === 1) {
var post = m.post.length
? expand(m.post, false)
: [''];
return post.map(function(p) {
return m.pre + n[0] + p;
});
}
}
}
// at this point, n is the parts, and we know it's not a comma set
// with a single entry.
// no need to expand pre, since it is guaranteed to be free of brace-sets
var pre = m.pre;
var post = m.post.length
? expand(m.post, false)
: [''];
var N;
if (isSequence) {
var x = numeric(n[0]);
var y = numeric(n[1]);
var width = Math.max(n[0].length, n[1].length)
var incr = n.length == 3
? Math.abs(numeric(n[2]))
: 1;
var test = lte;
var reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
var pad = n.some(isPadded);
N = [];
for (var i = x; test(i, y); i += incr) {
var c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\')
c = '';
} else {
c = String(i);
if (pad) {
var need = width - c.length;
if (need > 0) {
var z = new Array(need + 1).join('0');
if (i < 0)
c = '-' + z + c.slice(1);
else
c = z + c;
}
}
}
N.push(c);
}
} else {
N = concatMap(n, function(el) { return expand(el, false) });
}
for (var j = 0; j < N.length; j++) {
for (var k = 0; k < post.length; k++) {
var expansion = pre + N[j] + post[k];
if (!isTop || isSequence || expansion)
expansions.push(expansion);
}
}
return expansions;
}

View File

@ -0,0 +1,50 @@
{
"name": "brace-expansion",
"description": "Brace expansion as known from sh/bash",
"version": "1.1.12",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/brace-expansion.git"
},
"homepage": "https://github.com/juliangruber/brace-expansion",
"main": "index.js",
"scripts": {
"test": "tape test/*.js",
"gentest": "bash test/generate.sh",
"bench": "matcha test/perf/bench.js"
},
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
},
"devDependencies": {
"matcha": "^0.7.0",
"tape": "^4.6.0"
},
"keywords": [],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT",
"testling": {
"files": "test/*.js",
"browsers": [
"ie/8..latest",
"firefox/20..latest",
"firefox/nightly",
"chrome/25..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
},
"publishConfig": {
"tag": "1.x"
}
}

15
bot/node_modules/.chownr-Mb0E5y9w/LICENSE generated vendored Normal file
View File

@ -0,0 +1,15 @@
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

3
bot/node_modules/.chownr-Mb0E5y9w/README.md generated vendored Normal file
View File

@ -0,0 +1,3 @@
Like `chown -R`.
Takes the same arguments as `fs.chown()`

167
bot/node_modules/.chownr-Mb0E5y9w/chownr.js generated vendored Normal file
View File

@ -0,0 +1,167 @@
'use strict'
const fs = require('fs')
const path = require('path')
/* istanbul ignore next */
const LCHOWN = fs.lchown ? 'lchown' : 'chown'
/* istanbul ignore next */
const LCHOWNSYNC = fs.lchownSync ? 'lchownSync' : 'chownSync'
/* istanbul ignore next */
const needEISDIRHandled = fs.lchown &&
!process.version.match(/v1[1-9]+\./) &&
!process.version.match(/v10\.[6-9]/)
const lchownSync = (path, uid, gid) => {
try {
return fs[LCHOWNSYNC](path, uid, gid)
} catch (er) {
if (er.code !== 'ENOENT')
throw er
}
}
/* istanbul ignore next */
const chownSync = (path, uid, gid) => {
try {
return fs.chownSync(path, uid, gid)
} catch (er) {
if (er.code !== 'ENOENT')
throw er
}
}
/* istanbul ignore next */
const handleEISDIR =
needEISDIRHandled ? (path, uid, gid, cb) => er => {
// Node prior to v10 had a very questionable implementation of
// fs.lchown, which would always try to call fs.open on a directory
// Fall back to fs.chown in those cases.
if (!er || er.code !== 'EISDIR')
cb(er)
else
fs.chown(path, uid, gid, cb)
}
: (_, __, ___, cb) => cb
/* istanbul ignore next */
const handleEISDirSync =
needEISDIRHandled ? (path, uid, gid) => {
try {
return lchownSync(path, uid, gid)
} catch (er) {
if (er.code !== 'EISDIR')
throw er
chownSync(path, uid, gid)
}
}
: (path, uid, gid) => lchownSync(path, uid, gid)
// fs.readdir could only accept an options object as of node v6
const nodeVersion = process.version
let readdir = (path, options, cb) => fs.readdir(path, options, cb)
let readdirSync = (path, options) => fs.readdirSync(path, options)
/* istanbul ignore next */
if (/^v4\./.test(nodeVersion))
readdir = (path, options, cb) => fs.readdir(path, cb)
const chown = (cpath, uid, gid, cb) => {
fs[LCHOWN](cpath, uid, gid, handleEISDIR(cpath, uid, gid, er => {
// Skip ENOENT error
cb(er && er.code !== 'ENOENT' ? er : null)
}))
}
const chownrKid = (p, child, uid, gid, cb) => {
if (typeof child === 'string')
return fs.lstat(path.resolve(p, child), (er, stats) => {
// Skip ENOENT error
if (er)
return cb(er.code !== 'ENOENT' ? er : null)
stats.name = child
chownrKid(p, stats, uid, gid, cb)
})
if (child.isDirectory()) {
chownr(path.resolve(p, child.name), uid, gid, er => {
if (er)
return cb(er)
const cpath = path.resolve(p, child.name)
chown(cpath, uid, gid, cb)
})
} else {
const cpath = path.resolve(p, child.name)
chown(cpath, uid, gid, cb)
}
}
const chownr = (p, uid, gid, cb) => {
readdir(p, { withFileTypes: true }, (er, children) => {
// any error other than ENOTDIR or ENOTSUP means it's not readable,
// or doesn't exist. give up.
if (er) {
if (er.code === 'ENOENT')
return cb()
else if (er.code !== 'ENOTDIR' && er.code !== 'ENOTSUP')
return cb(er)
}
if (er || !children.length)
return chown(p, uid, gid, cb)
let len = children.length
let errState = null
const then = er => {
if (errState)
return
if (er)
return cb(errState = er)
if (-- len === 0)
return chown(p, uid, gid, cb)
}
children.forEach(child => chownrKid(p, child, uid, gid, then))
})
}
const chownrKidSync = (p, child, uid, gid) => {
if (typeof child === 'string') {
try {
const stats = fs.lstatSync(path.resolve(p, child))
stats.name = child
child = stats
} catch (er) {
if (er.code === 'ENOENT')
return
else
throw er
}
}
if (child.isDirectory())
chownrSync(path.resolve(p, child.name), uid, gid)
handleEISDirSync(path.resolve(p, child.name), uid, gid)
}
const chownrSync = (p, uid, gid) => {
let children
try {
children = readdirSync(p, { withFileTypes: true })
} catch (er) {
if (er.code === 'ENOENT')
return
else if (er.code === 'ENOTDIR' || er.code === 'ENOTSUP')
return handleEISDirSync(p, uid, gid)
else
throw er
}
if (children && children.length)
children.forEach(child => chownrKidSync(p, child, uid, gid))
return handleEISDirSync(p, uid, gid)
}
module.exports = chownr
chownr.sync = chownrSync

32
bot/node_modules/.chownr-Mb0E5y9w/package.json generated vendored Normal file
View File

@ -0,0 +1,32 @@
{
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
"name": "chownr",
"description": "like `chown -R`",
"version": "2.0.0",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/chownr.git"
},
"main": "chownr.js",
"files": [
"chownr.js"
],
"devDependencies": {
"mkdirp": "0.3",
"rimraf": "^2.7.1",
"tap": "^14.10.6"
},
"tap": {
"check-coverage": true
},
"scripts": {
"test": "tap",
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags"
},
"license": "ISC",
"engines": {
"node": ">=10"
}
}

15
bot/node_modules/.color-support-7PREFjRY/LICENSE generated vendored Normal file
View File

@ -0,0 +1,15 @@
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

129
bot/node_modules/.color-support-7PREFjRY/README.md generated vendored Normal file
View File

@ -0,0 +1,129 @@
# color-support
A module which will endeavor to guess your terminal's level of color
support.
[![Build Status](https://travis-ci.org/isaacs/color-support.svg?branch=master)](https://travis-ci.org/isaacs/color-support) [![Coverage Status](https://coveralls.io/repos/github/isaacs/color-support/badge.svg?branch=master)](https://coveralls.io/github/isaacs/color-support?branch=master)
This is similar to `supports-color`, but it does not read
`process.argv`.
1. If not in a node environment, not supported.
2. If stdout is not a TTY, not supported, unless the `ignoreTTY`
option is set.
3. If the `TERM` environ is `dumb`, not supported, unless the
`ignoreDumb` option is set.
4. If on Windows, then support 16 colors.
5. If using Tmux, then support 256 colors.
7. Handle continuous-integration servers. If `CI` or
`TEAMCITY_VERSION` are set in the environment, and `TRAVIS` is not
set, then color is not supported, unless `ignoreCI` option is set.
6. Guess based on the `TERM_PROGRAM` environ. These terminals support
16m colors:
- `iTerm.app` version 3.x supports 16m colors, below support 256
- `MacTerm` supports 16m colors
- `Apple_Terminal` supports 256 colors
- Have more things that belong on this list? Send a PR!
8. Make a guess based on the `TERM` environment variable. Any
`xterm-256color` will get 256 colors. Any screen, xterm, vt100,
color, ansi, cygwin, or linux `TERM` will get 16 colors.
9. If `COLORTERM` environment variable is set, then support 16 colors.
10. At this point, we assume that color is not supported.
## USAGE
```javascript
var testColorSupport = require('color-support')
var colorSupport = testColorSupport(/* options object */)
if (!colorSupport) {
console.log('color is not supported')
} else if (colorSupport.has16m) {
console.log('\x1b[38;2;102;194;255m16m colors\x1b[0m')
} else if (colorSupport.has256) {
console.log('\x1b[38;5;119m256 colors\x1b[0m')
} else if (colorSupport.hasBasic) {
console.log('\x1b[31mbasic colors\x1b[0m')
} else {
console.log('this is impossible, but colors are not supported')
}
```
If you don't have any options to set, you can also just look at the
flags which will all be set on the test function itself. (Of course,
this doesn't return a falsey value when colors aren't supported, and
doesn't allow you to set options.)
```javascript
var colorSupport = require('color-support')
if (colorSupport.has16m) {
console.log('\x1b[38;2;102;194;255m16m colors\x1b[0m')
} else if (colorSupport.has256) {
console.log('\x1b[38;5;119m256 colors\x1b[0m')
} else if (colorSupport.hasBasic) {
console.log('\x1b[31mbasic colors\x1b[0m')
} else {
console.log('colors are not supported')
}
```
## Options
You can pass in the following options.
* ignoreTTY - default false. Ignore the `isTTY` check.
* ignoreDumb - default false. Ignore `TERM=dumb` environ check.
* ignoreCI - default false. Ignore `CI` environ check.
* env - Object for environment vars. Defaults to `process.env`.
* stream - Stream for `isTTY` check. Defaults to `process.stdout`.
* term - String for `TERM` checking. Defaults to `env.TERM`.
* alwaysReturn - default false. Return an object when colors aren't
supported (instead of returning `false`).
* level - A number from 0 to 3. This will return a result for the
specified level. This is useful if you want to be able to set the
color support level explicitly as a number in an environment
variable or config, but then use the object flags in your program.
Except for `alwaysReturn` to return an object for level 0, all other
options are ignored, since no checking is done if a level is
explicitly set.
## Return Value
If no color support is available, then `false` is returned by default,
unless the `alwaysReturn` flag is set to `true`. This is so that the
simple question of "can I use colors or not" can treat any truthy
return as "yes".
Otherwise, the return object has the following fields:
* `level` - A number from 0 to 3
* `0` - No color support
* `1` - Basic (16) color support
* `2` - 256 color support
* `3` - 16 million (true) color support
* `hasBasic` - Boolean
* `has256` - Boolean
* `has16m` - Boolean
## CLI
You can run the `color-support` bin from the command line which will
just dump the values as this module calculates them in whatever env
it's run. It takes no command line arguments.
## Credits
This is a spiritual, if not actual, fork of
[supports-color](http://npm.im/supports-color) by the ever prolific
[Sindre Sorhus](http://npm.im/~sindresorhus).

3
bot/node_modules/.color-support-7PREFjRY/bin.js generated vendored Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env node
var colorSupport = require('./')({alwaysReturn: true })
console.log(JSON.stringify(colorSupport, null, 2))

14
bot/node_modules/.color-support-7PREFjRY/browser.js generated vendored Normal file
View File

@ -0,0 +1,14 @@
module.exports = colorSupport({ alwaysReturn: true }, colorSupport)
function colorSupport(options, obj) {
obj = obj || {}
options = options || {}
obj.level = 0
obj.hasBasic = false
obj.has256 = false
obj.has16m = false
if (!options.alwaysReturn) {
return false
}
return obj
}

134
bot/node_modules/.color-support-7PREFjRY/index.js generated vendored Normal file
View File

@ -0,0 +1,134 @@
// call it on itself so we can test the export val for basic stuff
module.exports = colorSupport({ alwaysReturn: true }, colorSupport)
function hasNone (obj, options) {
obj.level = 0
obj.hasBasic = false
obj.has256 = false
obj.has16m = false
if (!options.alwaysReturn) {
return false
}
return obj
}
function hasBasic (obj) {
obj.hasBasic = true
obj.has256 = false
obj.has16m = false
obj.level = 1
return obj
}
function has256 (obj) {
obj.hasBasic = true
obj.has256 = true
obj.has16m = false
obj.level = 2
return obj
}
function has16m (obj) {
obj.hasBasic = true
obj.has256 = true
obj.has16m = true
obj.level = 3
return obj
}
function colorSupport (options, obj) {
options = options || {}
obj = obj || {}
// if just requesting a specific level, then return that.
if (typeof options.level === 'number') {
switch (options.level) {
case 0:
return hasNone(obj, options)
case 1:
return hasBasic(obj)
case 2:
return has256(obj)
case 3:
return has16m(obj)
}
}
obj.level = 0
obj.hasBasic = false
obj.has256 = false
obj.has16m = false
if (typeof process === 'undefined' ||
!process ||
!process.stdout ||
!process.env ||
!process.platform) {
return hasNone(obj, options)
}
var env = options.env || process.env
var stream = options.stream || process.stdout
var term = options.term || env.TERM || ''
var platform = options.platform || process.platform
if (!options.ignoreTTY && !stream.isTTY) {
return hasNone(obj, options)
}
if (!options.ignoreDumb && term === 'dumb' && !env.COLORTERM) {
return hasNone(obj, options)
}
if (platform === 'win32') {
return hasBasic(obj)
}
if (env.TMUX) {
return has256(obj)
}
if (!options.ignoreCI && (env.CI || env.TEAMCITY_VERSION)) {
if (env.TRAVIS) {
return has256(obj)
} else {
return hasNone(obj, options)
}
}
// TODO: add more term programs
switch (env.TERM_PROGRAM) {
case 'iTerm.app':
var ver = env.TERM_PROGRAM_VERSION || '0.'
if (/^[0-2]\./.test(ver)) {
return has256(obj)
} else {
return has16m(obj)
}
case 'HyperTerm':
case 'Hyper':
return has16m(obj)
case 'MacTerm':
return has16m(obj)
case 'Apple_Terminal':
return has256(obj)
}
if (/^xterm-256/.test(term)) {
return has256(obj)
}
if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(term)) {
return hasBasic(obj)
}
if (env.COLORTERM) {
return hasBasic(obj)
}
return hasNone(obj, options)
}

36
bot/node_modules/.color-support-7PREFjRY/package.json generated vendored Normal file
View File

@ -0,0 +1,36 @@
{
"name": "color-support",
"version": "1.1.3",
"description": "A module which will endeavor to guess your terminal's level of color support.",
"main": "index.js",
"browser": "browser.js",
"bin": "bin.js",
"devDependencies": {
"tap": "^10.3.3"
},
"scripts": {
"test": "tap test/*.js --100 -J",
"preversion": "npm test",
"postversion": "npm publish",
"postpublish": "git push origin --all; git push origin --tags"
},
"repository": {
"type": "git",
"url": "git+https://github.com/isaacs/color-support.git"
},
"keywords": [
"terminal",
"color",
"support",
"xterm",
"truecolor",
"256"
],
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
"license": "ISC",
"files": [
"browser.js",
"index.js",
"bin.js"
]
}

4
bot/node_modules/.concat-map-frJh08yO/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,4 @@
language: node_js
node_js:
- 0.4
- 0.6

18
bot/node_modules/.concat-map-frJh08yO/LICENSE generated vendored Normal file
View File

@ -0,0 +1,18 @@
This software is released under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

62
bot/node_modules/.concat-map-frJh08yO/README.markdown generated vendored Normal file
View File

@ -0,0 +1,62 @@
concat-map
==========
Concatenative mapdashery.
[![browser support](http://ci.testling.com/substack/node-concat-map.png)](http://ci.testling.com/substack/node-concat-map)
[![build status](https://secure.travis-ci.org/substack/node-concat-map.png)](http://travis-ci.org/substack/node-concat-map)
example
=======
``` js
var concatMap = require('concat-map');
var xs = [ 1, 2, 3, 4, 5, 6 ];
var ys = concatMap(xs, function (x) {
return x % 2 ? [ x - 0.1, x, x + 0.1 ] : [];
});
console.dir(ys);
```
***
```
[ 0.9, 1, 1.1, 2.9, 3, 3.1, 4.9, 5, 5.1 ]
```
methods
=======
``` js
var concatMap = require('concat-map')
```
concatMap(xs, fn)
-----------------
Return an array of concatenated elements by calling `fn(x, i)` for each element
`x` and each index `i` in the array `xs`.
When `fn(x, i)` returns an array, its result will be concatenated with the
result array. If `fn(x, i)` returns anything else, that value will be pushed
onto the end of the result array.
install
=======
With [npm](http://npmjs.org) do:
```
npm install concat-map
```
license
=======
MIT
notes
=====
This module was written while sitting high above the ground in a tree.

6
bot/node_modules/.concat-map-frJh08yO/example/map.js generated vendored Normal file
View File

@ -0,0 +1,6 @@
var concatMap = require('../');
var xs = [ 1, 2, 3, 4, 5, 6 ];
var ys = concatMap(xs, function (x) {
return x % 2 ? [ x - 0.1, x, x + 0.1 ] : [];
});
console.dir(ys);

13
bot/node_modules/.concat-map-frJh08yO/index.js generated vendored Normal file
View File

@ -0,0 +1,13 @@
module.exports = function (xs, fn) {
var res = [];
for (var i = 0; i < xs.length; i++) {
var x = fn(xs[i], i);
if (isArray(x)) res.push.apply(res, x);
else res.push(x);
}
return res;
};
var isArray = Array.isArray || function (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};

43
bot/node_modules/.concat-map-frJh08yO/package.json generated vendored Normal file
View File

@ -0,0 +1,43 @@
{
"name" : "concat-map",
"description" : "concatenative mapdashery",
"version" : "0.0.1",
"repository" : {
"type" : "git",
"url" : "git://github.com/substack/node-concat-map.git"
},
"main" : "index.js",
"keywords" : [
"concat",
"concatMap",
"map",
"functional",
"higher-order"
],
"directories" : {
"example" : "example",
"test" : "test"
},
"scripts" : {
"test" : "tape test/*.js"
},
"devDependencies" : {
"tape" : "~2.4.0"
},
"license" : "MIT",
"author" : {
"name" : "James Halliday",
"email" : "mail@substack.net",
"url" : "http://substack.net"
},
"testling" : {
"files" : "test/*.js",
"browsers" : {
"ie" : [ 6, 7, 8, 9 ],
"ff" : [ 3.5, 10, 15.0 ],
"chrome" : [ 10, 22 ],
"safari" : [ 5.1 ],
"opera" : [ 12 ]
}
}
}

39
bot/node_modules/.concat-map-frJh08yO/test/map.js generated vendored Normal file
View File

@ -0,0 +1,39 @@
var concatMap = require('../');
var test = require('tape');
test('empty or not', function (t) {
var xs = [ 1, 2, 3, 4, 5, 6 ];
var ixes = [];
var ys = concatMap(xs, function (x, ix) {
ixes.push(ix);
return x % 2 ? [ x - 0.1, x, x + 0.1 ] : [];
});
t.same(ys, [ 0.9, 1, 1.1, 2.9, 3, 3.1, 4.9, 5, 5.1 ]);
t.same(ixes, [ 0, 1, 2, 3, 4, 5 ]);
t.end();
});
test('always something', function (t) {
var xs = [ 'a', 'b', 'c', 'd' ];
var ys = concatMap(xs, function (x) {
return x === 'b' ? [ 'B', 'B', 'B' ] : [ x ];
});
t.same(ys, [ 'a', 'B', 'B', 'B', 'c', 'd' ]);
t.end();
});
test('scalars', function (t) {
var xs = [ 'a', 'b', 'c', 'd' ];
var ys = concatMap(xs, function (x) {
return x === 'b' ? [ 'B', 'B', 'B' ] : x;
});
t.same(ys, [ 'a', 'B', 'B', 'B', 'c', 'd' ]);
t.end();
});
test('undefs', function (t) {
var xs = [ 'a', 'b', 'c', 'd' ];
var ys = concatMap(xs, function () {});
t.same(ys, [ undefined, undefined, undefined, undefined ]);
t.end();
});

View File

@ -0,0 +1,13 @@
Copyright (c) 2014, Rebecca Turner <me@re-becca.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@ -0,0 +1,145 @@
# Console Control Strings
A library of cross-platform tested terminal/console command strings for
doing things like color and cursor positioning. This is a subset of both
ansi and vt100. All control codes included work on both Windows & Unix-like
OSes, except where noted.
## Usage
```js
var consoleControl = require('console-control-strings')
console.log(consoleControl.color('blue','bgRed', 'bold') + 'hi there' + consoleControl.color('reset'))
process.stdout.write(consoleControl.goto(75, 10))
```
## Why Another?
There are tons of libraries similar to this one. I wanted one that was:
1. Very clear about compatibility goals.
2. Could emit, for instance, a start color code without an end one.
3. Returned strings w/o writing to streams.
4. Was not weighed down with other unrelated baggage.
## Functions
### var code = consoleControl.up(_num = 1_)
Returns the escape sequence to move _num_ lines up.
### var code = consoleControl.down(_num = 1_)
Returns the escape sequence to move _num_ lines down.
### var code = consoleControl.forward(_num = 1_)
Returns the escape sequence to move _num_ lines righ.
### var code = consoleControl.back(_num = 1_)
Returns the escape sequence to move _num_ lines left.
### var code = consoleControl.nextLine(_num = 1_)
Returns the escape sequence to move _num_ lines down and to the beginning of
the line.
### var code = consoleControl.previousLine(_num = 1_)
Returns the escape sequence to move _num_ lines up and to the beginning of
the line.
### var code = consoleControl.eraseData()
Returns the escape sequence to erase everything from the current cursor
position to the bottom right of the screen. This is line based, so it
erases the remainder of the current line and all following lines.
### var code = consoleControl.eraseLine()
Returns the escape sequence to erase to the end of the current line.
### var code = consoleControl.goto(_x_, _y_)
Returns the escape sequence to move the cursor to the designated position.
Note that the origin is _1, 1_ not _0, 0_.
### var code = consoleControl.gotoSOL()
Returns the escape sequence to move the cursor to the beginning of the
current line. (That is, it returns a carriage return, `\r`.)
### var code = consoleControl.beep()
Returns the escape sequence to cause the termianl to beep. (That is, it
returns unicode character `\x0007`, a Control-G.)
### var code = consoleControl.hideCursor()
Returns the escape sequence to hide the cursor.
### var code = consoleControl.showCursor()
Returns the escape sequence to show the cursor.
### var code = consoleControl.color(_colors = []_)
### var code = consoleControl.color(_color1_, _color2_, _…_, _colorn_)
Returns the escape sequence to set the current terminal display attributes
(mostly colors). Arguments can either be a list of attributes or an array
of attributes. The difference between passing in an array or list of colors
and calling `.color` separately for each one, is that in the former case a
single escape sequence will be produced where as in the latter each change
will have its own distinct escape sequence. Each attribute can be one of:
* Reset:
* **reset** Reset all attributes to the terminal default.
* Styles:
* **bold** Display text as bold. In some terminals this means using a
bold font, in others this means changing the color. In some it means
both.
* **italic** Display text as italic. This is not available in most Windows terminals.
* **underline** Underline text. This is not available in most Windows Terminals.
* **inverse** Invert the foreground and background colors.
* **stopBold** Do not display text as bold.
* **stopItalic** Do not display text as italic.
* **stopUnderline** Do not underline text.
* **stopInverse** Do not invert foreground and background.
* Colors:
* **white**
* **black**
* **blue**
* **cyan**
* **green**
* **magenta**
* **red**
* **yellow**
* **grey** / **brightBlack**
* **brightRed**
* **brightGreen**
* **brightYellow**
* **brightBlue**
* **brightMagenta**
* **brightCyan**
* **brightWhite**
* Background Colors:
* **bgWhite**
* **bgBlack**
* **bgBlue**
* **bgCyan**
* **bgGreen**
* **bgMagenta**
* **bgRed**
* **bgYellow**
* **bgGrey** / **bgBrightBlack**
* **bgBrightRed**
* **bgBrightGreen**
* **bgBrightYellow**
* **bgBrightBlue**
* **bgBrightMagenta**
* **bgBrightCyan**
* **bgBrightWhite**

View File

@ -0,0 +1,140 @@
# Console Control Strings
A library of cross-platform tested terminal/console command strings for
doing things like color and cursor positioning. This is a subset of both
ansi and vt100. All control codes included work on both Windows & Unix-like
OSes, except where noted.
## Usage
```js
var consoleControl = require('console-control-strings')
console.log(consoleControl.color('blue','bgRed', 'bold') + 'hi there' + consoleControl.color('reset'))
process.stdout.write(consoleControl.goto(75, 10))
```
## Why Another?
There are tons of libraries similar to this one. I wanted one that was:
1. Very clear about compatibility goals.
2. Could emit, for instance, a start color code without an end one.
3. Returned strings w/o writing to streams.
4. Was not weighed down with other unrelated baggage.
## Functions
### var code = consoleControl.up(_num = 1_)
Returns the escape sequence to move _num_ lines up.
### var code = consoleControl.down(_num = 1_)
Returns the escape sequence to move _num_ lines down.
### var code = consoleControl.forward(_num = 1_)
Returns the escape sequence to move _num_ lines righ.
### var code = consoleControl.back(_num = 1_)
Returns the escape sequence to move _num_ lines left.
### var code = consoleControl.nextLine(_num = 1_)
Returns the escape sequence to move _num_ lines down and to the beginning of
the line.
### var code = consoleControl.previousLine(_num = 1_)
Returns the escape sequence to move _num_ lines up and to the beginning of
the line.
### var code = consoleControl.eraseData()
Returns the escape sequence to erase everything from the current cursor
position to the bottom right of the screen. This is line based, so it
erases the remainder of the current line and all following lines.
### var code = consoleControl.eraseLine()
Returns the escape sequence to erase to the end of the current line.
### var code = consoleControl.goto(_x_, _y_)
Returns the escape sequence to move the cursor to the designated position.
Note that the origin is _1, 1_ not _0, 0_.
### var code = consoleControl.gotoSOL()
Returns the escape sequence to move the cursor to the beginning of the
current line. (That is, it returns a carriage return, `\r`.)
### var code = consoleControl.hideCursor()
Returns the escape sequence to hide the cursor.
### var code = consoleControl.showCursor()
Returns the escape sequence to show the cursor.
### var code = consoleControl.color(_colors = []_)
### var code = consoleControl.color(_color1_, _color2_, _…_, _colorn_)
Returns the escape sequence to set the current terminal display attributes
(mostly colors). Arguments can either be a list of attributes or an array
of attributes. The difference between passing in an array or list of colors
and calling `.color` separately for each one, is that in the former case a
single escape sequence will be produced where as in the latter each change
will have its own distinct escape sequence. Each attribute can be one of:
* Reset:
* **reset** Reset all attributes to the terminal default.
* Styles:
* **bold** Display text as bold. In some terminals this means using a
bold font, in others this means changing the color. In some it means
both.
* **italic** Display text as italic. This is not available in most Windows terminals.
* **underline** Underline text. This is not available in most Windows Terminals.
* **inverse** Invert the foreground and background colors.
* **stopBold** Do not display text as bold.
* **stopItalic** Do not display text as italic.
* **stopUnderline** Do not underline text.
* **stopInverse** Do not invert foreground and background.
* Colors:
* **white**
* **black**
* **blue**
* **cyan**
* **green**
* **magenta**
* **red**
* **yellow**
* **grey** / **brightBlack**
* **brightRed**
* **brightGreen**
* **brightYellow**
* **brightBlue**
* **brightMagenta**
* **brightCyan**
* **brightWhite**
* Background Colors:
* **bgWhite**
* **bgBlack**
* **bgBlue**
* **bgCyan**
* **bgGreen**
* **bgMagenta**
* **bgRed**
* **bgYellow**
* **bgGrey** / **bgBrightBlack**
* **bgBrightRed**
* **bgBrightGreen**
* **bgBrightYellow**
* **bgBrightBlue**
* **bgBrightMagenta**
* **bgBrightCyan**
* **bgBrightWhite**

View File

@ -0,0 +1,125 @@
'use strict'
// These tables borrowed from `ansi`
var prefix = '\x1b['
exports.up = function up (num) {
return prefix + (num || '') + 'A'
}
exports.down = function down (num) {
return prefix + (num || '') + 'B'
}
exports.forward = function forward (num) {
return prefix + (num || '') + 'C'
}
exports.back = function back (num) {
return prefix + (num || '') + 'D'
}
exports.nextLine = function nextLine (num) {
return prefix + (num || '') + 'E'
}
exports.previousLine = function previousLine (num) {
return prefix + (num || '') + 'F'
}
exports.horizontalAbsolute = function horizontalAbsolute (num) {
if (num == null) throw new Error('horizontalAboslute requires a column to position to')
return prefix + num + 'G'
}
exports.eraseData = function eraseData () {
return prefix + 'J'
}
exports.eraseLine = function eraseLine () {
return prefix + 'K'
}
exports.goto = function (x, y) {
return prefix + y + ';' + x + 'H'
}
exports.gotoSOL = function () {
return '\r'
}
exports.beep = function () {
return '\x07'
}
exports.hideCursor = function hideCursor () {
return prefix + '?25l'
}
exports.showCursor = function showCursor () {
return prefix + '?25h'
}
var colors = {
reset: 0,
// styles
bold: 1,
italic: 3,
underline: 4,
inverse: 7,
// resets
stopBold: 22,
stopItalic: 23,
stopUnderline: 24,
stopInverse: 27,
// colors
white: 37,
black: 30,
blue: 34,
cyan: 36,
green: 32,
magenta: 35,
red: 31,
yellow: 33,
bgWhite: 47,
bgBlack: 40,
bgBlue: 44,
bgCyan: 46,
bgGreen: 42,
bgMagenta: 45,
bgRed: 41,
bgYellow: 43,
grey: 90,
brightBlack: 90,
brightRed: 91,
brightGreen: 92,
brightYellow: 93,
brightBlue: 94,
brightMagenta: 95,
brightCyan: 96,
brightWhite: 97,
bgGrey: 100,
bgBrightBlack: 100,
bgBrightRed: 101,
bgBrightGreen: 102,
bgBrightYellow: 103,
bgBrightBlue: 104,
bgBrightMagenta: 105,
bgBrightCyan: 106,
bgBrightWhite: 107
}
exports.color = function color (colorWith) {
if (arguments.length !== 1 || !Array.isArray(colorWith)) {
colorWith = Array.prototype.slice.call(arguments)
}
return prefix + colorWith.map(colorNameToCode).join(';') + 'm'
}
function colorNameToCode (color) {
if (colors[color] != null) return colors[color]
throw new Error('Unknown color or style name: ' + color)
}

View File

@ -0,0 +1,27 @@
{
"name": "console-control-strings",
"version": "1.1.0",
"description": "A library of cross-platform tested terminal/console command strings for doing things like color and cursor positioning. This is a subset of both ansi and vt100. All control codes included work on both Windows & Unix-like OSes, except where noted.",
"main": "index.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "standard && tap test/*.js"
},
"repository": {
"type": "git",
"url": "https://github.com/iarna/console-control-strings"
},
"keywords": [],
"author": "Rebecca Turner <me@re-becca.org> (http://re-becca.org/)",
"license": "ISC",
"files": [
"LICENSE",
"index.js"
],
"devDependencies": {
"standard": "^7.1.2",
"tap": "^5.7.2"
}
}

1
bot/node_modules/.delegates-zGR9Jik2/.npmignore generated vendored Normal file
View File

@ -0,0 +1 @@
node_modules/

22
bot/node_modules/.delegates-zGR9Jik2/History.md generated vendored Normal file
View File

@ -0,0 +1,22 @@
1.0.0 / 2015-12-14
==================
* Merge pull request #12 from kasicka/master
* Add license text
0.1.0 / 2014-10-17
==================
* adds `.fluent()` to api
0.0.3 / 2014-01-13
==================
* fix receiver for .method()
0.0.2 / 2014-01-13
==================
* Object.defineProperty() sucks
* Initial commit

20
bot/node_modules/.delegates-zGR9Jik2/License generated vendored Normal file
View File

@ -0,0 +1,20 @@
Copyright (c) 2015 TJ Holowaychuk <tj@vision-media.ca>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

8
bot/node_modules/.delegates-zGR9Jik2/Makefile generated vendored Normal file
View File

@ -0,0 +1,8 @@
test:
@./node_modules/.bin/mocha \
--require should \
--reporter spec \
--bail
.PHONY: test

94
bot/node_modules/.delegates-zGR9Jik2/Readme.md generated vendored Normal file
View File

@ -0,0 +1,94 @@
# delegates
Node method and accessor delegation utilty.
## Installation
```
$ npm install delegates
```
## Example
```js
var delegate = require('delegates');
...
delegate(proto, 'request')
.method('acceptsLanguages')
.method('acceptsEncodings')
.method('acceptsCharsets')
.method('accepts')
.method('is')
.access('querystring')
.access('idempotent')
.access('socket')
.access('length')
.access('query')
.access('search')
.access('status')
.access('method')
.access('path')
.access('body')
.access('host')
.access('url')
.getter('subdomains')
.getter('protocol')
.getter('header')
.getter('stale')
.getter('fresh')
.getter('secure')
.getter('ips')
.getter('ip')
```
# API
## Delegate(proto, prop)
Creates a delegator instance used to configure using the `prop` on the given
`proto` object. (which is usually a prototype)
## Delegate#method(name)
Allows the given method `name` to be accessed on the host.
## Delegate#getter(name)
Creates a "getter" for the property with the given `name` on the delegated
object.
## Delegate#setter(name)
Creates a "setter" for the property with the given `name` on the delegated
object.
## Delegate#access(name)
Creates an "accessor" (ie: both getter *and* setter) for the property with the
given `name` on the delegated object.
## Delegate#fluent(name)
A unique type of "accessor" that works for a "fluent" API. When called as a
getter, the method returns the expected value. However, if the method is called
with a value, it will return itself so it can be chained. For example:
```js
delegate(proto, 'request')
.fluent('query')
// getter
var q = request.query();
// setter (chainable)
request
.query({ a: 1 })
.query({ b: 2 });
```
# License
MIT

121
bot/node_modules/.delegates-zGR9Jik2/index.js generated vendored Normal file
View File

@ -0,0 +1,121 @@
/**
* Expose `Delegator`.
*/
module.exports = Delegator;
/**
* Initialize a delegator.
*
* @param {Object} proto
* @param {String} target
* @api public
*/
function Delegator(proto, target) {
if (!(this instanceof Delegator)) return new Delegator(proto, target);
this.proto = proto;
this.target = target;
this.methods = [];
this.getters = [];
this.setters = [];
this.fluents = [];
}
/**
* Delegate method `name`.
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
Delegator.prototype.method = function(name){
var proto = this.proto;
var target = this.target;
this.methods.push(name);
proto[name] = function(){
return this[target][name].apply(this[target], arguments);
};
return this;
};
/**
* Delegator accessor `name`.
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
Delegator.prototype.access = function(name){
return this.getter(name).setter(name);
};
/**
* Delegator getter `name`.
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
Delegator.prototype.getter = function(name){
var proto = this.proto;
var target = this.target;
this.getters.push(name);
proto.__defineGetter__(name, function(){
return this[target][name];
});
return this;
};
/**
* Delegator setter `name`.
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
Delegator.prototype.setter = function(name){
var proto = this.proto;
var target = this.target;
this.setters.push(name);
proto.__defineSetter__(name, function(val){
return this[target][name] = val;
});
return this;
};
/**
* Delegator fluent accessor
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
Delegator.prototype.fluent = function (name) {
var proto = this.proto;
var target = this.target;
this.fluents.push(name);
proto[name] = function(val){
if ('undefined' != typeof val) {
this[target][name] = val;
return this;
} else {
return this[target][name];
}
};
return this;
};

13
bot/node_modules/.delegates-zGR9Jik2/package.json generated vendored Normal file
View File

@ -0,0 +1,13 @@
{
"name": "delegates",
"version": "1.0.0",
"repository": "visionmedia/node-delegates",
"description": "delegate methods and accessors to another property",
"keywords": ["delegate", "delegation"],
"dependencies": {},
"devDependencies": {
"mocha": "*",
"should": "*"
},
"license": "MIT"
}

94
bot/node_modules/.delegates-zGR9Jik2/test/index.js generated vendored Normal file
View File

@ -0,0 +1,94 @@
var assert = require('assert');
var delegate = require('..');
describe('.method(name)', function(){
it('should delegate methods', function(){
var obj = {};
obj.request = {
foo: function(bar){
assert(this == obj.request);
return bar;
}
};
delegate(obj, 'request').method('foo');
obj.foo('something').should.equal('something');
})
})
describe('.getter(name)', function(){
it('should delegate getters', function(){
var obj = {};
obj.request = {
get type() {
return 'text/html';
}
}
delegate(obj, 'request').getter('type');
obj.type.should.equal('text/html');
})
})
describe('.setter(name)', function(){
it('should delegate setters', function(){
var obj = {};
obj.request = {
get type() {
return this._type.toUpperCase();
},
set type(val) {
this._type = val;
}
}
delegate(obj, 'request').setter('type');
obj.type = 'hey';
obj.request.type.should.equal('HEY');
})
})
describe('.access(name)', function(){
it('should delegate getters and setters', function(){
var obj = {};
obj.request = {
get type() {
return this._type.toUpperCase();
},
set type(val) {
this._type = val;
}
}
delegate(obj, 'request').access('type');
obj.type = 'hey';
obj.type.should.equal('HEY');
})
})
describe('.fluent(name)', function () {
it('should delegate in a fluent fashion', function () {
var obj = {
settings: {
env: 'development'
}
};
delegate(obj, 'settings').fluent('env');
obj.env().should.equal('development');
obj.env('production').should.equal(obj);
obj.settings.env.should.equal('production');
})
})

201
bot/node_modules/.detect-libc-mXa1danF/LICENSE generated vendored Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

163
bot/node_modules/.detect-libc-mXa1danF/README.md generated vendored Normal file
View File

@ -0,0 +1,163 @@
# detect-libc
Node.js module to detect details of the C standard library (libc)
implementation provided by a given Linux system.
Currently supports detection of GNU glibc and MUSL libc.
Provides asychronous and synchronous functions for the
family (e.g. `glibc`, `musl`) and version (e.g. `1.23`, `1.2.3`).
The version numbers of libc implementations
are not guaranteed to be semver-compliant.
For previous v1.x releases, please see the
[v1](https://github.com/lovell/detect-libc/tree/v1) branch.
## Install
```sh
npm install detect-libc
```
## API
### GLIBC
```ts
const GLIBC: string = 'glibc';
```
A String constant containing the value `glibc`.
### MUSL
```ts
const MUSL: string = 'musl';
```
A String constant containing the value `musl`.
### family
```ts
function family(): Promise<string | null>;
```
Resolves asychronously with:
* `glibc` or `musl` when the libc family can be determined
* `null` when the libc family cannot be determined
* `null` when run on a non-Linux platform
```js
const { family, GLIBC, MUSL } = require('detect-libc');
switch (await family()) {
case GLIBC: ...
case MUSL: ...
case null: ...
}
```
### familySync
```ts
function familySync(): string | null;
```
Synchronous version of `family()`.
```js
const { familySync, GLIBC, MUSL } = require('detect-libc');
switch (familySync()) {
case GLIBC: ...
case MUSL: ...
case null: ...
}
```
### version
```ts
function version(): Promise<string | null>;
```
Resolves asychronously with:
* The version when it can be determined
* `null` when the libc family cannot be determined
* `null` when run on a non-Linux platform
```js
const { version } = require('detect-libc');
const v = await version();
if (v) {
const [major, minor, patch] = v.split('.');
}
```
### versionSync
```ts
function versionSync(): string | null;
```
Synchronous version of `version()`.
```js
const { versionSync } = require('detect-libc');
const v = versionSync();
if (v) {
const [major, minor, patch] = v.split('.');
}
```
### isNonGlibcLinux
```ts
function isNonGlibcLinux(): Promise<boolean>;
```
Resolves asychronously with:
* `false` when the libc family is `glibc`
* `true` when the libc family is not `glibc`
* `false` when run on a non-Linux platform
```js
const { isNonGlibcLinux } = require('detect-libc');
if (await isNonGlibcLinux()) { ... }
```
### isNonGlibcLinuxSync
```ts
function isNonGlibcLinuxSync(): boolean;
```
Synchronous version of `isNonGlibcLinux()`.
```js
const { isNonGlibcLinuxSync } = require('detect-libc');
if (isNonGlibcLinuxSync()) { ... }
```
## Licensing
Copyright 2017 Lovell Fuller and others.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0.html)
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

14
bot/node_modules/.detect-libc-mXa1danF/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,14 @@
// Copyright 2017 Lovell Fuller and others.
// SPDX-License-Identifier: Apache-2.0
export const GLIBC: 'glibc';
export const MUSL: 'musl';
export function family(): Promise<string | null>;
export function familySync(): string | null;
export function isNonGlibcLinux(): Promise<boolean>;
export function isNonGlibcLinuxSync(): boolean;
export function version(): Promise<string | null>;
export function versionSync(): string | null;

View File

@ -0,0 +1,313 @@
// Copyright 2017 Lovell Fuller and others.
// SPDX-License-Identifier: Apache-2.0
'use strict';
const childProcess = require('child_process');
const { isLinux, getReport } = require('./process');
const { LDD_PATH, SELF_PATH, readFile, readFileSync } = require('./filesystem');
const { interpreterPath } = require('./elf');
let cachedFamilyInterpreter;
let cachedFamilyFilesystem;
let cachedVersionFilesystem;
const command = 'getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true';
let commandOut = '';
const safeCommand = () => {
if (!commandOut) {
return new Promise((resolve) => {
childProcess.exec(command, (err, out) => {
commandOut = err ? ' ' : out;
resolve(commandOut);
});
});
}
return commandOut;
};
const safeCommandSync = () => {
if (!commandOut) {
try {
commandOut = childProcess.execSync(command, { encoding: 'utf8' });
} catch (_err) {
commandOut = ' ';
}
}
return commandOut;
};
/**
* A String constant containing the value `glibc`.
* @type {string}
* @public
*/
const GLIBC = 'glibc';
/**
* A Regexp constant to get the GLIBC Version.
* @type {string}
*/
const RE_GLIBC_VERSION = /LIBC[a-z0-9 \-).]*?(\d+\.\d+)/i;
/**
* A String constant containing the value `musl`.
* @type {string}
* @public
*/
const MUSL = 'musl';
const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-');
const familyFromReport = () => {
const report = getReport();
if (report.header && report.header.glibcVersionRuntime) {
return GLIBC;
}
if (Array.isArray(report.sharedObjects)) {
if (report.sharedObjects.some(isFileMusl)) {
return MUSL;
}
}
return null;
};
const familyFromCommand = (out) => {
const [getconf, ldd1] = out.split(/[\r\n]+/);
if (getconf && getconf.includes(GLIBC)) {
return GLIBC;
}
if (ldd1 && ldd1.includes(MUSL)) {
return MUSL;
}
return null;
};
const familyFromInterpreterPath = (path) => {
if (path) {
if (path.includes('/ld-musl-')) {
return MUSL;
} else if (path.includes('/ld-linux-')) {
return GLIBC;
}
}
return null;
};
const getFamilyFromLddContent = (content) => {
content = content.toString();
if (content.includes('musl')) {
return MUSL;
}
if (content.includes('GNU C Library')) {
return GLIBC;
}
return null;
};
const familyFromFilesystem = async () => {
if (cachedFamilyFilesystem !== undefined) {
return cachedFamilyFilesystem;
}
cachedFamilyFilesystem = null;
try {
const lddContent = await readFile(LDD_PATH);
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
} catch (e) {}
return cachedFamilyFilesystem;
};
const familyFromFilesystemSync = () => {
if (cachedFamilyFilesystem !== undefined) {
return cachedFamilyFilesystem;
}
cachedFamilyFilesystem = null;
try {
const lddContent = readFileSync(LDD_PATH);
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
} catch (e) {}
return cachedFamilyFilesystem;
};
const familyFromInterpreter = async () => {
if (cachedFamilyInterpreter !== undefined) {
return cachedFamilyInterpreter;
}
cachedFamilyInterpreter = null;
try {
const selfContent = await readFile(SELF_PATH);
const path = interpreterPath(selfContent);
cachedFamilyInterpreter = familyFromInterpreterPath(path);
} catch (e) {}
return cachedFamilyInterpreter;
};
const familyFromInterpreterSync = () => {
if (cachedFamilyInterpreter !== undefined) {
return cachedFamilyInterpreter;
}
cachedFamilyInterpreter = null;
try {
const selfContent = readFileSync(SELF_PATH);
const path = interpreterPath(selfContent);
cachedFamilyInterpreter = familyFromInterpreterPath(path);
} catch (e) {}
return cachedFamilyInterpreter;
};
/**
* Resolves with the libc family when it can be determined, `null` otherwise.
* @returns {Promise<?string>}
*/
const family = async () => {
let family = null;
if (isLinux()) {
family = await familyFromInterpreter();
if (!family) {
family = await familyFromFilesystem();
if (!family) {
family = familyFromReport();
}
if (!family) {
const out = await safeCommand();
family = familyFromCommand(out);
}
}
}
return family;
};
/**
* Returns the libc family when it can be determined, `null` otherwise.
* @returns {?string}
*/
const familySync = () => {
let family = null;
if (isLinux()) {
family = familyFromInterpreterSync();
if (!family) {
family = familyFromFilesystemSync();
if (!family) {
family = familyFromReport();
}
if (!family) {
const out = safeCommandSync();
family = familyFromCommand(out);
}
}
}
return family;
};
/**
* Resolves `true` only when the platform is Linux and the libc family is not `glibc`.
* @returns {Promise<boolean>}
*/
const isNonGlibcLinux = async () => isLinux() && await family() !== GLIBC;
/**
* Returns `true` only when the platform is Linux and the libc family is not `glibc`.
* @returns {boolean}
*/
const isNonGlibcLinuxSync = () => isLinux() && familySync() !== GLIBC;
const versionFromFilesystem = async () => {
if (cachedVersionFilesystem !== undefined) {
return cachedVersionFilesystem;
}
cachedVersionFilesystem = null;
try {
const lddContent = await readFile(LDD_PATH);
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
if (versionMatch) {
cachedVersionFilesystem = versionMatch[1];
}
} catch (e) {}
return cachedVersionFilesystem;
};
const versionFromFilesystemSync = () => {
if (cachedVersionFilesystem !== undefined) {
return cachedVersionFilesystem;
}
cachedVersionFilesystem = null;
try {
const lddContent = readFileSync(LDD_PATH);
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
if (versionMatch) {
cachedVersionFilesystem = versionMatch[1];
}
} catch (e) {}
return cachedVersionFilesystem;
};
const versionFromReport = () => {
const report = getReport();
if (report.header && report.header.glibcVersionRuntime) {
return report.header.glibcVersionRuntime;
}
return null;
};
const versionSuffix = (s) => s.trim().split(/\s+/)[1];
const versionFromCommand = (out) => {
const [getconf, ldd1, ldd2] = out.split(/[\r\n]+/);
if (getconf && getconf.includes(GLIBC)) {
return versionSuffix(getconf);
}
if (ldd1 && ldd2 && ldd1.includes(MUSL)) {
return versionSuffix(ldd2);
}
return null;
};
/**
* Resolves with the libc version when it can be determined, `null` otherwise.
* @returns {Promise<?string>}
*/
const version = async () => {
let version = null;
if (isLinux()) {
version = await versionFromFilesystem();
if (!version) {
version = versionFromReport();
}
if (!version) {
const out = await safeCommand();
version = versionFromCommand(out);
}
}
return version;
};
/**
* Returns the libc version when it can be determined, `null` otherwise.
* @returns {?string}
*/
const versionSync = () => {
let version = null;
if (isLinux()) {
version = versionFromFilesystemSync();
if (!version) {
version = versionFromReport();
}
if (!version) {
const out = safeCommandSync();
version = versionFromCommand(out);
}
}
return version;
};
module.exports = {
GLIBC,
MUSL,
family,
familySync,
isNonGlibcLinux,
isNonGlibcLinuxSync,
version,
versionSync
};

39
bot/node_modules/.detect-libc-mXa1danF/lib/elf.js generated vendored Normal file
View File

@ -0,0 +1,39 @@
// Copyright 2017 Lovell Fuller and others.
// SPDX-License-Identifier: Apache-2.0
'use strict';
const interpreterPath = (elf) => {
if (elf.length < 64) {
return null;
}
if (elf.readUInt32BE(0) !== 0x7F454C46) {
// Unexpected magic bytes
return null;
}
if (elf.readUInt8(4) !== 2) {
// Not a 64-bit ELF
return null;
}
if (elf.readUInt8(5) !== 1) {
// Not little-endian
return null;
}
const offset = elf.readUInt32LE(32);
const size = elf.readUInt16LE(54);
const count = elf.readUInt16LE(56);
for (let i = 0; i < count; i++) {
const headerOffset = offset + (i * size);
const type = elf.readUInt32LE(headerOffset);
if (type === 3) {
const fileOffset = elf.readUInt32LE(headerOffset + 8);
const fileSize = elf.readUInt32LE(headerOffset + 32);
return elf.subarray(fileOffset, fileOffset + fileSize).toString().replace(/\0.*$/g, '');
}
}
return null;
};
module.exports = {
interpreterPath
};

View File

@ -0,0 +1,51 @@
// Copyright 2017 Lovell Fuller and others.
// SPDX-License-Identifier: Apache-2.0
'use strict';
const fs = require('fs');
const LDD_PATH = '/usr/bin/ldd';
const SELF_PATH = '/proc/self/exe';
const MAX_LENGTH = 2048;
/**
* Read the content of a file synchronous
*
* @param {string} path
* @returns {Buffer}
*/
const readFileSync = (path) => {
const fd = fs.openSync(path, 'r');
const buffer = Buffer.alloc(MAX_LENGTH);
const bytesRead = fs.readSync(fd, buffer, 0, MAX_LENGTH, 0);
fs.close(fd, () => {});
return buffer.subarray(0, bytesRead);
};
/**
* Read the content of a file
*
* @param {string} path
* @returns {Promise<Buffer>}
*/
const readFile = (path) => new Promise((resolve, reject) => {
fs.open(path, 'r', (err, fd) => {
if (err) {
reject(err);
} else {
const buffer = Buffer.alloc(MAX_LENGTH);
fs.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
resolve(buffer.subarray(0, bytesRead));
fs.close(fd, () => {});
});
}
});
});
module.exports = {
LDD_PATH,
SELF_PATH,
readFileSync,
readFile
};

24
bot/node_modules/.detect-libc-mXa1danF/lib/process.js generated vendored Normal file
View File

@ -0,0 +1,24 @@
// Copyright 2017 Lovell Fuller and others.
// SPDX-License-Identifier: Apache-2.0
'use strict';
const isLinux = () => process.platform === 'linux';
let report = null;
const getReport = () => {
if (!report) {
/* istanbul ignore next */
if (isLinux() && process.report) {
const orig = process.report.excludeNetwork;
process.report.excludeNetwork = true;
report = process.report.getReport();
process.report.excludeNetwork = orig;
} else {
report = {};
}
}
return report;
};
module.exports = { isLinux, getReport };

44
bot/node_modules/.detect-libc-mXa1danF/package.json generated vendored Normal file
View File

@ -0,0 +1,44 @@
{
"name": "detect-libc",
"version": "2.1.2",
"description": "Node.js module to detect the C standard library (libc) implementation family and version",
"main": "lib/detect-libc.js",
"files": [
"lib/",
"index.d.ts"
],
"scripts": {
"test": "semistandard && nyc --reporter=text --check-coverage --branches=100 ava test/unit.js",
"changelog": "conventional-changelog -i CHANGELOG.md -s",
"bench": "node benchmark/detect-libc",
"bench:calls": "node benchmark/call-familySync.js && sleep 1 && node benchmark/call-isNonGlibcLinuxSync.js && sleep 1 && node benchmark/call-versionSync.js"
},
"repository": {
"type": "git",
"url": "git://github.com/lovell/detect-libc.git"
},
"keywords": [
"libc",
"glibc",
"musl"
],
"author": "Lovell Fuller <npm@lovell.info>",
"contributors": [
"Niklas Salmoukas <niklas@salmoukas.com>",
"Vinícius Lourenço <vinyygamerlol@gmail.com>"
],
"license": "Apache-2.0",
"devDependencies": {
"ava": "^2.4.0",
"benchmark": "^2.1.4",
"conventional-changelog-cli": "^5.0.0",
"eslint-config-standard": "^13.0.1",
"nyc": "^15.1.0",
"proxyquire": "^2.1.3",
"semistandard": "^14.2.3"
},
"engines": {
"node": ">=8"
},
"types": "index.d.ts"
}

20
bot/node_modules/.emoji-regex-GnU9Pkks/LICENSE-MIT.txt generated vendored Normal file
View File

@ -0,0 +1,20 @@
Copyright Mathias Bynens <https://mathiasbynens.be/>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Some files were not shown because too many files have changed in this diff Show More