opencode-probleemwijken 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -0
- package/dist/index.js +223 -0
- package/package.json +45 -0
- package/sounds/.gitkeep +2 -0
- package/sounds/28-inbraken.mp3 +0 -0
- package/sounds/92-93.mp3 +0 -0
- package/sounds/agentjes.mp3 +0 -0
- package/sounds/beetje-stelen.mp3 +0 -0
- package/sounds/begeleid.mp3 +0 -0
- package/sounds/boertje.mp3 +0 -0
- package/sounds/broodje.mp3 +0 -0
- package/sounds/deze-leven.mp3 +0 -0
- package/sounds/doei-henk.mp3 +0 -0
- package/sounds/dood-rieden.mp3 +0 -0
- package/sounds/drank-duivel.mp3 +0 -0
- package/sounds/dronken.mp3 +0 -0
- package/sounds/euuwwwjoh.mp3 +0 -0
- package/sounds/half-elf.mp3 +0 -0
- package/sounds/herender.mp3 +0 -0
- package/sounds/hoertje-van-assen.mp3 +0 -0
- package/sounds/kakwijk.mp3 +0 -0
- package/sounds/koffie.mp3 +0 -0
- package/sounds/lul.mp3 +0 -0
- package/sounds/nu.mp3 +0 -0
- package/sounds/piemel.mp3 +0 -0
- package/sounds/pitbull.mp3 +0 -0
- package/sounds/tetete.mp3 +0 -0
- package/sounds/turk-in-politieauto.mp3 +0 -0
- package/sounds/twee-kratten.mp3 +0 -0
- package/sounds/uitkering.mp3 +0 -0
- package/sounds/verzoek.mp3 +0 -0
- package/sounds/vis.mp3 +0 -0
- package/sounds/vlieg.mp3 +0 -0
- package/sounds/waardeloze-agent.mp3 +0 -0
- package/sounds/waarheid.mp3 +0 -0
- package/sounds/werk-jij.mp3 +0 -0
- package/sounds/wortels.mp3 +0 -0
- package/sounds/zeker-weten.mp3 +0 -0
- package/sounds/zes-half-week.mp3 +0 -0
- package/sounds/zwerver.mp3 +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# opencode-probleemwijken
|
|
2
|
+
|
|
3
|
+
OpenCode plugin dat een willekeurig geluid afspeelt van de legendarische [Probleemwijken/Derkolk soundboard](https://www.derkolk.nl/probleemwijken/) wanneer een sessie klaar is.
|
|
4
|
+
|
|
5
|
+
## Installatie
|
|
6
|
+
|
|
7
|
+
### Optie 1: Lokale plugin (aanbevolen)
|
|
8
|
+
|
|
9
|
+
1. Kopieer `plugin.ts` naar je OpenCode plugins directory:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
cp plugin.ts ~/.config/opencode/plugins/probleemwijken.ts
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
2. Kopieer de sounds naar je config directory:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
mkdir -p ~/.config/opencode/sounds/random-soundboard
|
|
19
|
+
cp sounds/*.mp3 ~/.config/opencode/sounds/random-soundboard/
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
3. Zorg dat je `@opencode-ai/plugin` hebt in `~/.config/opencode/package.json`:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@opencode-ai/plugin": "^1.0.0"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
4. Herstart OpenCode
|
|
33
|
+
|
|
34
|
+
### Optie 2: Eigen geluiden toevoegen
|
|
35
|
+
|
|
36
|
+
Je kunt ook je eigen MP3/WAV/OGG/M4A bestanden toevoegen aan de `~/.config/opencode/sounds/random-soundboard/` directory.
|
|
37
|
+
|
|
38
|
+
## Wat doet het?
|
|
39
|
+
|
|
40
|
+
Elke keer als OpenCode klaar is met een taak (session.idle) of een error krijgt (session.error), speelt de plugin een willekeurig geluid af uit de collectie.
|
|
41
|
+
|
|
42
|
+
## Geluiden
|
|
43
|
+
|
|
44
|
+
De plugin bevat 36 klassieke Derkolk soundboard fragmenten:
|
|
45
|
+
|
|
46
|
+
- "VLIEG!"
|
|
47
|
+
- "Half elf"
|
|
48
|
+
- "Boertje!?"
|
|
49
|
+
- "Geert is inmiddels dronken"
|
|
50
|
+
- "Broodje"
|
|
51
|
+
- "Koffie"
|
|
52
|
+
- "Pitbull"
|
|
53
|
+
- "Tetete"
|
|
54
|
+
- ... en nog veel meer!
|
|
55
|
+
|
|
56
|
+
## Platform ondersteuning
|
|
57
|
+
|
|
58
|
+
- **macOS**: Gebruikt `afplay` (ingebouwd)
|
|
59
|
+
- **Linux**: Gebruikt `mpv` of `ffplay`
|
|
60
|
+
- **Windows**: Gebruikt Windows Media Player via PowerShell
|
|
61
|
+
|
|
62
|
+
## Credits
|
|
63
|
+
|
|
64
|
+
- Geluiden van [derkolk.nl/probleemwijken](https://www.derkolk.nl/probleemwijken/)
|
|
65
|
+
- Gebaseerd op [opencode-notifier](https://github.com/mohak34/opencode-notifier) door mohak34
|
|
66
|
+
|
|
67
|
+
## Licentie
|
|
68
|
+
|
|
69
|
+
MIT
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// src/config.ts
|
|
2
|
+
import { existsSync, readFileSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
var DEFAULT_CONFIG = {
|
|
6
|
+
enabled: true,
|
|
7
|
+
soundsDir: null,
|
|
8
|
+
events: {
|
|
9
|
+
complete: true,
|
|
10
|
+
subagent_complete: false,
|
|
11
|
+
error: true,
|
|
12
|
+
permission: false
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
function loadConfig() {
|
|
16
|
+
const configPath = join(homedir(), ".config", "opencode", "random-soundboard.json");
|
|
17
|
+
if (!existsSync(configPath)) {
|
|
18
|
+
return DEFAULT_CONFIG;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const content = readFileSync(configPath, "utf-8");
|
|
22
|
+
const userConfig = JSON.parse(content);
|
|
23
|
+
return {
|
|
24
|
+
enabled: userConfig.enabled ?? DEFAULT_CONFIG.enabled,
|
|
25
|
+
soundsDir: userConfig.soundsDir ?? DEFAULT_CONFIG.soundsDir,
|
|
26
|
+
events: {
|
|
27
|
+
complete: userConfig.events?.complete ?? DEFAULT_CONFIG.events.complete,
|
|
28
|
+
subagent_complete: userConfig.events?.subagent_complete ?? DEFAULT_CONFIG.events.subagent_complete,
|
|
29
|
+
error: userConfig.events?.error ?? DEFAULT_CONFIG.events.error,
|
|
30
|
+
permission: userConfig.events?.permission ?? DEFAULT_CONFIG.events.permission
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
} catch {
|
|
34
|
+
return DEFAULT_CONFIG;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function isEventEnabled(config, event) {
|
|
38
|
+
if (!config.enabled)
|
|
39
|
+
return false;
|
|
40
|
+
return config.events[event] ?? false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/sound.ts
|
|
44
|
+
import { platform } from "os";
|
|
45
|
+
import { join as join2, dirname, extname } from "path";
|
|
46
|
+
import { fileURLToPath } from "url";
|
|
47
|
+
import { existsSync as existsSync2, readdirSync } from "fs";
|
|
48
|
+
import { spawn } from "child_process";
|
|
49
|
+
var __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
50
|
+
var SUPPORTED_EXTENSIONS = [".mp3", ".wav", ".ogg", ".m4a", ".aac", ".flac"];
|
|
51
|
+
function getBundledSoundsDir() {
|
|
52
|
+
const possiblePaths = [
|
|
53
|
+
join2(__dirname2, "..", "sounds"),
|
|
54
|
+
join2(__dirname2, "sounds")
|
|
55
|
+
];
|
|
56
|
+
for (const path of possiblePaths) {
|
|
57
|
+
if (existsSync2(path)) {
|
|
58
|
+
return path;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return join2(__dirname2, "..", "sounds");
|
|
62
|
+
}
|
|
63
|
+
function getSoundsDirectory(config) {
|
|
64
|
+
if (config.soundsDir && existsSync2(config.soundsDir)) {
|
|
65
|
+
return config.soundsDir;
|
|
66
|
+
}
|
|
67
|
+
return getBundledSoundsDir();
|
|
68
|
+
}
|
|
69
|
+
function getSoundFiles(directory) {
|
|
70
|
+
if (!existsSync2(directory)) {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const files = readdirSync(directory);
|
|
75
|
+
return files.filter((file) => {
|
|
76
|
+
const ext = extname(file).toLowerCase();
|
|
77
|
+
return SUPPORTED_EXTENSIONS.includes(ext);
|
|
78
|
+
}).map((file) => join2(directory, file));
|
|
79
|
+
} catch {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function getRandomSound(sounds) {
|
|
84
|
+
if (sounds.length === 0)
|
|
85
|
+
return null;
|
|
86
|
+
const index = Math.floor(Math.random() * sounds.length);
|
|
87
|
+
return sounds[index];
|
|
88
|
+
}
|
|
89
|
+
async function runCommand(command, args) {
|
|
90
|
+
return new Promise((resolve, reject) => {
|
|
91
|
+
const proc = spawn(command, args, {
|
|
92
|
+
stdio: "ignore",
|
|
93
|
+
detached: false
|
|
94
|
+
});
|
|
95
|
+
proc.on("error", (err) => {
|
|
96
|
+
reject(err);
|
|
97
|
+
});
|
|
98
|
+
proc.on("close", (code) => {
|
|
99
|
+
if (code === 0) {
|
|
100
|
+
resolve();
|
|
101
|
+
} else {
|
|
102
|
+
reject(new Error(`Command exited with code ${code}`));
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async function playOnLinux(soundPath) {
|
|
108
|
+
const players = [
|
|
109
|
+
{ command: "mpv", args: ["--no-video", "--no-terminal", soundPath] },
|
|
110
|
+
{ command: "ffplay", args: ["-nodisp", "-autoexit", "-loglevel", "quiet", soundPath] },
|
|
111
|
+
{ command: "paplay", args: [soundPath] },
|
|
112
|
+
{ command: "aplay", args: [soundPath] }
|
|
113
|
+
];
|
|
114
|
+
for (const player of players) {
|
|
115
|
+
try {
|
|
116
|
+
await runCommand(player.command, player.args);
|
|
117
|
+
return;
|
|
118
|
+
} catch {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function playOnMac(soundPath) {
|
|
124
|
+
await runCommand("afplay", [soundPath]);
|
|
125
|
+
}
|
|
126
|
+
async function playOnWindows(soundPath) {
|
|
127
|
+
const ext = extname(soundPath).toLowerCase();
|
|
128
|
+
if (ext === ".wav") {
|
|
129
|
+
const script = `& { (New-Object Media.SoundPlayer $args[0]).PlaySync() }`;
|
|
130
|
+
await runCommand("powershell", ["-c", script, soundPath]);
|
|
131
|
+
} else {
|
|
132
|
+
const script = `
|
|
133
|
+
$player = New-Object -ComObject WMPlayer.OCX
|
|
134
|
+
$player.URL = $args[0]
|
|
135
|
+
$player.controls.play()
|
|
136
|
+
Start-Sleep -Milliseconds 500
|
|
137
|
+
while ($player.playState -eq 3) { Start-Sleep -Milliseconds 100 }
|
|
138
|
+
$player.close()
|
|
139
|
+
`;
|
|
140
|
+
await runCommand("powershell", ["-c", script, soundPath]);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async function playRandomSound(config) {
|
|
144
|
+
const soundsDir = getSoundsDirectory(config);
|
|
145
|
+
const sounds = getSoundFiles(soundsDir);
|
|
146
|
+
if (sounds.length === 0) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const soundPath = getRandomSound(sounds);
|
|
150
|
+
if (!soundPath) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const os = platform();
|
|
154
|
+
try {
|
|
155
|
+
switch (os) {
|
|
156
|
+
case "darwin":
|
|
157
|
+
await playOnMac(soundPath);
|
|
158
|
+
break;
|
|
159
|
+
case "linux":
|
|
160
|
+
await playOnLinux(soundPath);
|
|
161
|
+
break;
|
|
162
|
+
case "win32":
|
|
163
|
+
await playOnWindows(soundPath);
|
|
164
|
+
break;
|
|
165
|
+
default:
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
} catch {}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// src/index.ts
|
|
172
|
+
function getSessionIDFromEvent(event) {
|
|
173
|
+
const sessionID = event?.properties?.sessionID;
|
|
174
|
+
if (typeof sessionID === "string" && sessionID.length > 0) {
|
|
175
|
+
return sessionID;
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
async function isChildSession(client, sessionID) {
|
|
180
|
+
try {
|
|
181
|
+
const response = await client.session.get({ path: { id: sessionID } });
|
|
182
|
+
const parentID = response.data?.parentID;
|
|
183
|
+
return !!parentID;
|
|
184
|
+
} catch {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
var RandomSoundboardPlugin = async ({ client }) => {
|
|
189
|
+
const config = loadConfig();
|
|
190
|
+
return {
|
|
191
|
+
event: async ({ event }) => {
|
|
192
|
+
if (event.type === "permission.updated" || event.type === "permission.asked") {
|
|
193
|
+
if (isEventEnabled(config, "permission")) {
|
|
194
|
+
await playRandomSound(config);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (event.type === "session.idle") {
|
|
198
|
+
const sessionID = getSessionIDFromEvent(event);
|
|
199
|
+
if (sessionID) {
|
|
200
|
+
const isChild = await isChildSession(client, sessionID);
|
|
201
|
+
const eventType = isChild ? "subagent_complete" : "complete";
|
|
202
|
+
if (isEventEnabled(config, eventType)) {
|
|
203
|
+
await playRandomSound(config);
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
if (isEventEnabled(config, "complete")) {
|
|
207
|
+
await playRandomSound(config);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (event.type === "session.error") {
|
|
212
|
+
if (isEventEnabled(config, "error")) {
|
|
213
|
+
await playRandomSound(config);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
};
|
|
219
|
+
var src_default = RandomSoundboardPlugin;
|
|
220
|
+
export {
|
|
221
|
+
src_default as default,
|
|
222
|
+
RandomSoundboardPlugin
|
|
223
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "opencode-probleemwijken",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "OpenCode plugin that plays a random Probleemwijken/Derkolk soundboard sound when a session completes",
|
|
5
|
+
"author": "Daan-Friday",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/Daan-Friday/opencode-probleemwijken.git"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/Daan-Friday/opencode-probleemwijken#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/Daan-Friday/opencode-probleemwijken/issues"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"sounds"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "bun build src/index.ts --outdir dist --target node",
|
|
24
|
+
"prepublishOnly": "bun run build",
|
|
25
|
+
"typecheck": "tsc --noEmit"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"opencode",
|
|
29
|
+
"opencode-plugin",
|
|
30
|
+
"soundboard",
|
|
31
|
+
"random",
|
|
32
|
+
"sound",
|
|
33
|
+
"notifications",
|
|
34
|
+
"probleemwijken",
|
|
35
|
+
"derkolk"
|
|
36
|
+
],
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@opencode-ai/plugin": "^1.0.224",
|
|
39
|
+
"@types/node": "^22.0.0",
|
|
40
|
+
"typescript": "^5.0.0"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"@opencode-ai/plugin": ">=1.0.0"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/sounds/.gitkeep
ADDED
|
Binary file
|
package/sounds/92-93.mp3
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/sounds/lul.mp3
ADDED
|
Binary file
|
package/sounds/nu.mp3
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/sounds/vis.mp3
ADDED
|
Binary file
|
package/sounds/vlieg.mp3
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|