oopsx 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,6 +12,14 @@ Restart your terminal. Every failed command now plays a sound.
12
12
 
13
13
  ## Custom sound
14
14
 
15
+ Pick any sound from [myinstants.com](https://www.myinstants.com) and set it as your error sound:
16
+
17
+ ```bash
18
+ oopsx instant https://www.myinstants.com/en/instant/bruh-sound-effect-26614/
19
+ ```
20
+
21
+ Or use a local file:
22
+
15
23
  ```bash
16
24
  oopsx --sound ~/bruh.mp3 --set-default echo hi
17
25
  ```
package/bin/merr.js CHANGED
@@ -123,6 +123,20 @@ program
123
123
  console.log("Restart your terminal or run: source " + rc.file);
124
124
  });
125
125
 
126
+ // --- `oopsx instant <url>` — download a sound from myinstants.com ---
127
+ program
128
+ .command("instant <url>")
129
+ .description("Download a sound from myinstants.com and set as default")
130
+ .action(async (url) => {
131
+ try {
132
+ const { fetchInstantSound } = await import("../src/instant.js");
133
+ await fetchInstantSound(url);
134
+ } catch (err) {
135
+ console.error(`Error: ${err.message}`);
136
+ process.exit(1);
137
+ }
138
+ });
139
+
126
140
  // --- `oopsx play` — just play the sound (used by shell hook) ---
127
141
  program
128
142
  .command("play")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oopsx",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Play a meme sound when your terminal command fails",
5
5
  "type": "module",
6
6
  "bin": {
package/src/instant.js ADDED
@@ -0,0 +1,48 @@
1
+ import { join } from "node:path";
2
+ import { existsSync, createWriteStream, copyFileSync } from "node:fs";
3
+ import { pipeline } from "node:stream/promises";
4
+ import { createHash } from "node:crypto";
5
+ import { SOUNDS_DIR, DEFAULT_SOUND_PATH, ensureDirs } from "./config.js";
6
+
7
+ const MP3_REGEX = /https?:\/\/www\.myinstants\.com\/media\/sounds\/[^\s"']+\.mp3/;
8
+ const TITLE_REGEX = /<title>([^<]+)<\/title>/i;
9
+
10
+ const fetchInstantSound = async (pageUrl) => {
11
+ if (!pageUrl.includes("myinstants.com")) {
12
+ throw new Error("URL must be from myinstants.com");
13
+ }
14
+
15
+ console.log("Fetching page...");
16
+ const res = await fetch(pageUrl, {
17
+ headers: { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" },
18
+ });
19
+
20
+ if (!res.ok) throw new Error(`Failed to fetch page: ${res.status}`);
21
+
22
+ const html = await res.text();
23
+
24
+ const mp3Match = html.match(MP3_REGEX);
25
+ if (!mp3Match) throw new Error("Could not find MP3 link on this page");
26
+ const mp3Url = mp3Match[0];
27
+
28
+ const titleMatch = html.match(TITLE_REGEX);
29
+ const title = titleMatch
30
+ ? titleMatch[1].replace(/\s*[-–|].*$/, "").trim()
31
+ : "Unknown sound";
32
+
33
+ ensureDirs();
34
+ const hash = createHash("sha1").update(mp3Url).digest("hex");
35
+ const cached = join(SOUNDS_DIR, `${hash}.mp3`);
36
+
37
+ if (!existsSync(cached)) {
38
+ console.log(`Downloading "${title}"...`);
39
+ const mp3Res = await fetch(mp3Url);
40
+ if (!mp3Res.ok) throw new Error(`Failed to download MP3: ${mp3Res.status}`);
41
+ await pipeline(mp3Res.body, createWriteStream(cached));
42
+ }
43
+
44
+ copyFileSync(cached, DEFAULT_SOUND_PATH);
45
+ console.log(`✓ "${title}" set as default error sound`);
46
+ };
47
+
48
+ export { fetchInstantSound };