oopsx 1.3.0 → 1.5.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
@@ -52,7 +52,10 @@ program
52
52
  console.log(`
53
53
  __oopsx_precmd() {
54
54
  local exit_code=$?
55
- [[ $exit_code -ne 0 ]] && (oopsx play &>/dev/null &)
55
+ if [[ $exit_code -ne 0 ]]; then
56
+ oopsx play &>/dev/null &
57
+ disown 2>/dev/null
58
+ fi
56
59
  return $exit_code
57
60
  }
58
61
  precmd_functions+=(__oopsx_precmd)
@@ -61,7 +64,10 @@ precmd_functions+=(__oopsx_precmd)
61
64
  console.log(`
62
65
  __oopsx_prompt_command() {
63
66
  local exit_code=$?
64
- [[ $exit_code -ne 0 ]] && (oopsx play &>/dev/null &)
67
+ if [[ $exit_code -ne 0 ]]; then
68
+ oopsx play &>/dev/null &
69
+ disown 2>/dev/null
70
+ fi
65
71
  return $exit_code
66
72
  }
67
73
  PROMPT_COMMAND="__oopsx_prompt_command;\${PROMPT_COMMAND}"
@@ -123,6 +129,20 @@ program
123
129
  console.log("Restart your terminal or run: source " + rc.file);
124
130
  });
125
131
 
132
+ // --- `oopsx instant <url>` — download a sound from myinstants.com ---
133
+ program
134
+ .command("instant <url>")
135
+ .description("Download a sound from myinstants.com and set as default")
136
+ .action(async (url) => {
137
+ try {
138
+ const { fetchInstantSound } = await import("../src/instant.js");
139
+ await fetchInstantSound(url);
140
+ } catch (err) {
141
+ console.error(`Error: ${err.message}`);
142
+ process.exit(1);
143
+ }
144
+ });
145
+
126
146
  // --- `oopsx play` — just play the sound (used by shell hook) ---
127
147
  program
128
148
  .command("play")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oopsx",
3
- "version": "1.3.0",
3
+ "version": "1.5.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 };