Switch notification sound to hohoho.mp3 and add download script

Replaced all references to notification.mp3 with hohoho.mp3 in notification-related components and context. Added hohoho.mp3 to the public directory. Introduced a script (download-notification-sound.js) for downloading notification sounds from YouTube using @distube/ytdl-core, which was added as a devDependency. Also added yt-dlp.exe for alternative audio downloading.
This commit is contained in:
g
2025-12-08 18:42:11 +00:00
parent 996bce6b4b
commit 54cfc62e35
9 changed files with 227 additions and 6 deletions

View File

@@ -130,9 +130,9 @@ export default function ChatDetail({ chatId }: { chatId: string }) {
// Initialize audio element
useEffect(() => {
// Create audio element for notification sound
audioRef.current = new Audio('/notification.mp3');
audioRef.current = new Audio('/hohoho.mp3');
// Fallback if notification.mp3 doesn't exist - use browser API for a simple beep
// Fallback if hohoho.mp3 doesn't exist - use browser API for a simple beep
audioRef.current.addEventListener('error', () => {
audioRef.current = null;
});

View File

@@ -81,7 +81,7 @@ export default function ChatTable() {
// Initialize audio element for notifications
useEffect(() => {
audioRef.current = new Audio('/notification.mp3');
audioRef.current = new Audio('/hohoho.mp3');
return () => {
if (audioRef.current) {
audioRef.current = null;

View File

@@ -33,9 +33,9 @@ export default function OrderNotifications() {
const audioRef = useRef<HTMLAudioElement | null>(null);
useEffect(() => {
audioRef.current = new Audio('/notification.mp3');
audioRef.current = new Audio('/hohoho.mp3');
// Fallback if notification.mp3 doesn't exist
// Fallback if hohoho.mp3 doesn't exist
audioRef.current.addEventListener('error', () => {
audioRef.current = null;
});

View File

@@ -92,7 +92,7 @@ export function NotificationProvider({ children }: NotificationProviderProps) {
}
// Initialize audio
audioRef.current = new Audio('/notification.mp3');
audioRef.current = new Audio('/hohoho.mp3');
audioRef.current.addEventListener('error', () => {
audioRef.current = null;
});

146
package-lock.json generated
View File

@@ -63,6 +63,7 @@
"zod": "^3.24.1"
},
"devDependencies": {
"@distube/ytdl-core": "^4.16.12",
"@next/bundle-analyzer": "^15.4.6",
"@tailwindcss/typography": "^0.5.16",
"@types/lodash": "^4.17.16",
@@ -112,6 +113,28 @@
"node": ">=10.0.0"
}
},
"node_modules/@distube/ytdl-core": {
"version": "4.16.12",
"resolved": "https://registry.npmjs.org/@distube/ytdl-core/-/ytdl-core-4.16.12.tgz",
"integrity": "sha512-/NR8Jur1Q4E2oD+DJta7uwWu7SkqdEkhwERt7f4iune70zg7ZlLLTOHs1+jgg3uD2jQjpdk7RGC16FqstG4RsA==",
"dev": true,
"license": "MIT",
"dependencies": {
"http-cookie-agent": "^7.0.1",
"https-proxy-agent": "^7.0.6",
"m3u8stream": "^0.8.6",
"miniget": "^4.2.3",
"sax": "^1.4.1",
"tough-cookie": "^5.1.2",
"undici": "^7.8.0"
},
"engines": {
"node": ">=20.18.1"
},
"funding": {
"url": "https://github.com/distubejs/ytdl-core?sponsor"
}
},
"node_modules/@emnapi/core": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.3.1.tgz",
@@ -3041,6 +3064,16 @@
"node": ">=0.4.0"
}
},
"node_modules/agent-base": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 14"
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -5603,6 +5636,45 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/http-cookie-agent": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/http-cookie-agent/-/http-cookie-agent-7.0.3.tgz",
"integrity": "sha512-EeZo7CGhfqPW6R006rJa4QtZZUpBygDa2HZH3DJqsTzTjyRE6foDBVQIv/pjVsxHC8z2GIdbB1Hvn9SRorP3WQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.4"
},
"engines": {
"node": ">=20.0.0"
},
"funding": {
"url": "https://github.com/sponsors/3846masa"
},
"peerDependencies": {
"tough-cookie": "^4.0.0 || ^5.0.0 || ^6.0.0",
"undici": "^7.0.0"
},
"peerDependenciesMeta": {
"undici": {
"optional": true
}
}
},
"node_modules/https-proxy-agent": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
"dev": true,
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -6448,6 +6520,20 @@
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
}
},
"node_modules/m3u8stream": {
"version": "0.8.6",
"resolved": "https://registry.npmjs.org/m3u8stream/-/m3u8stream-0.8.6.tgz",
"integrity": "sha512-LZj8kIVf9KCphiHmH7sbFQTVe4tOemb202fWwvJwR9W5ENW/1hxJN6ksAWGhQgSBSa3jyWhnjKU1Fw1GaOdbyA==",
"dev": true,
"license": "MIT",
"dependencies": {
"miniget": "^4.2.2",
"sax": "^1.2.4"
},
"engines": {
"node": ">=12"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -7097,6 +7183,16 @@
"node": ">= 0.6"
}
},
"node_modules/miniget": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/miniget/-/miniget-4.2.3.tgz",
"integrity": "sha512-SjbDPDICJ1zT+ZvQwK0hUcRY4wxlhhNpHL9nJOB2MEAXRGagTljsO8MEDzQMTFf0Q8g4QNi8P9lEm/g7e+qgzA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -8398,6 +8494,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/sax": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz",
"integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==",
"dev": true,
"license": "BlueOak-1.0.0"
},
"node_modules/scheduler": {
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz",
@@ -9131,6 +9234,26 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/tldts": {
"version": "6.1.86",
"resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz",
"integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"tldts-core": "^6.1.86"
},
"bin": {
"tldts": "bin/cli.js"
}
},
"node_modules/tldts-core": {
"version": "6.1.86",
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz",
"integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==",
"dev": true,
"license": "MIT"
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -9154,6 +9277,19 @@
"node": ">=6"
}
},
"node_modules/tough-cookie": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz",
"integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"tldts": "^6.1.32"
},
"engines": {
"node": ">=16"
}
},
"node_modules/trim-lines": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
@@ -9337,6 +9473,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/undici": {
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz",
"integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=20.18.1"
}
},
"node_modules/undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",

View File

@@ -72,6 +72,7 @@
"zod": "^3.24.1"
},
"devDependencies": {
"@distube/ytdl-core": "^4.16.12",
"@next/bundle-analyzer": "^15.4.6",
"@tailwindcss/typography": "^0.5.16",
"@types/lodash": "^4.17.16",

BIN
public/hohoho.mp3 Normal file

Binary file not shown.

View File

@@ -0,0 +1,74 @@
/**
* Script to download notification sound from YouTube
* Uses @distube/ytdl-core to download audio
*/
const ytdl = require('@distube/ytdl-core');
const fs = require('fs');
const path = require('path');
const YOUTUBE_URL = 'https://www.youtube.com/watch?v=utmKQWAuYH4';
const OUTPUT_PATH = path.join(__dirname, '..', 'public', 'notification.mp3');
console.log('Downloading notification sound from YouTube...');
console.log(`URL: ${YOUTUBE_URL}`);
console.log(`Output: ${OUTPUT_PATH}`);
async function downloadAudio() {
try {
// Validate URL
if (!ytdl.validateURL(YOUTUBE_URL)) {
throw new Error('Invalid YouTube URL');
}
// Get video info
console.log('\nFetching video information...');
const info = await ytdl.getInfo(YOUTUBE_URL);
console.log(`Title: ${info.videoDetails.title}`);
// Get audio format
const audioFormats = ytdl.filterFormats(info.formats, 'audioonly');
if (audioFormats.length === 0) {
throw new Error('No audio formats available');
}
// Select best quality audio
const format = audioFormats[0];
console.log(`\nDownloading audio format: ${format.audioCodec || 'unknown'}`);
// Create write stream
const outputStream = fs.createWriteStream(OUTPUT_PATH);
// Download audio
const audioStream = ytdl.downloadFromInfo(info, { format });
audioStream.pipe(outputStream);
audioStream.on('progress', (chunkLength, downloaded, total) => {
const percent = (downloaded / total * 100).toFixed(2);
process.stdout.write(`\rDownloaded: ${percent}%`);
});
await new Promise((resolve, reject) => {
outputStream.on('finish', () => {
console.log('\n\n✅ Successfully downloaded notification sound!');
resolve();
});
outputStream.on('error', reject);
audioStream.on('error', reject);
});
} catch (error) {
console.error('\n❌ Error downloading audio:', error.message);
console.error('\nAlternative options:');
console.log('1. Install yt-dlp: pip install yt-dlp');
console.log('2. Download executable: https://github.com/yt-dlp/yt-dlp/releases');
console.log('3. Use online converter');
console.log('\nThen run:');
console.log(`yt-dlp -x --audio-format mp3 --audio-quality 0 -o "public/notification.mp3" "${YOUTUBE_URL}"`);
process.exit(1);
}
}
downloadAudio();

BIN
yt-dlp.exe Normal file

Binary file not shown.