kimaki 0.4.2 → 0.4.6
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/dist/cli.js +34 -38
- package/dist/discordBot.js +345 -145
- package/dist/escape-backticks.test.js +125 -0
- package/dist/tools.js +2 -1
- package/package.json +12 -14
- package/src/cli.ts +37 -50
- package/src/discordBot.ts +468 -159
- package/src/escape-backticks.test.ts +146 -0
- package/src/tools.ts +2 -1
package/dist/cli.js
CHANGED
|
@@ -2,15 +2,28 @@
|
|
|
2
2
|
import { cac } from 'cac';
|
|
3
3
|
import { intro, outro, text, password, note, cancel, isCancel, confirm, log, multiselect, spinner, } from '@clack/prompts';
|
|
4
4
|
import { deduplicateByKey, generateBotInstallUrl } from './utils.js';
|
|
5
|
-
import { getChannelsWithDescriptions, createDiscordClient, getDatabase, startDiscordBot, initializeOpencodeForDirectory, } from './discordBot.js';
|
|
5
|
+
import { getChannelsWithDescriptions, createDiscordClient, getDatabase, startDiscordBot, initializeOpencodeForDirectory, ensureKimakiCategory, createProjectChannels, } from './discordBot.js';
|
|
6
6
|
import { Events, ChannelType, REST, Routes, SlashCommandBuilder, } from 'discord.js';
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import fs from 'node:fs';
|
|
9
9
|
import { createLogger } from './logger.js';
|
|
10
|
-
import { spawnSync, execSync } from 'node:child_process';
|
|
10
|
+
import { spawn, spawnSync, execSync } from 'node:child_process';
|
|
11
11
|
const cliLogger = createLogger('CLI');
|
|
12
12
|
const cli = cac('kimaki');
|
|
13
13
|
process.title = 'kimaki';
|
|
14
|
+
process.on('SIGUSR2', () => {
|
|
15
|
+
cliLogger.info('Received SIGUSR2, restarting process in 1000ms...');
|
|
16
|
+
setTimeout(() => {
|
|
17
|
+
cliLogger.info('Restarting...');
|
|
18
|
+
spawn(process.argv[0], [...process.execArgv, ...process.argv.slice(1)], {
|
|
19
|
+
stdio: 'inherit',
|
|
20
|
+
detached: true,
|
|
21
|
+
cwd: process.cwd(),
|
|
22
|
+
env: process.env,
|
|
23
|
+
}).unref();
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}, 1000);
|
|
26
|
+
});
|
|
14
27
|
const EXIT_NO_RESTART = 64;
|
|
15
28
|
async function registerCommands(token, appId) {
|
|
16
29
|
const commands = [
|
|
@@ -45,6 +58,18 @@ async function registerCommands(token, appId) {
|
|
|
45
58
|
return option;
|
|
46
59
|
})
|
|
47
60
|
.toJSON(),
|
|
61
|
+
new SlashCommandBuilder()
|
|
62
|
+
.setName('add-project')
|
|
63
|
+
.setDescription('Create Discord channels for a new OpenCode project')
|
|
64
|
+
.addStringOption((option) => {
|
|
65
|
+
option
|
|
66
|
+
.setName('project')
|
|
67
|
+
.setDescription('Select an OpenCode project')
|
|
68
|
+
.setRequired(true)
|
|
69
|
+
.setAutocomplete(true);
|
|
70
|
+
return option;
|
|
71
|
+
})
|
|
72
|
+
.toJSON(),
|
|
48
73
|
];
|
|
49
74
|
const rest = new REST().setToken(token);
|
|
50
75
|
try {
|
|
@@ -58,21 +83,6 @@ async function registerCommands(token, appId) {
|
|
|
58
83
|
throw error;
|
|
59
84
|
}
|
|
60
85
|
}
|
|
61
|
-
async function ensureKimakiCategory(guild) {
|
|
62
|
-
const existingCategory = guild.channels.cache.find((channel) => {
|
|
63
|
-
if (channel.type !== ChannelType.GuildCategory) {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
return channel.name.toLowerCase() === 'kimaki';
|
|
67
|
-
});
|
|
68
|
-
if (existingCategory) {
|
|
69
|
-
return existingCategory;
|
|
70
|
-
}
|
|
71
|
-
return guild.channels.create({
|
|
72
|
-
name: 'Kimaki',
|
|
73
|
-
type: ChannelType.GuildCategory,
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
86
|
async function run({ restart, addChannels }) {
|
|
77
87
|
const forceSetup = Boolean(restart);
|
|
78
88
|
intro('🤖 Discord Bot Setup');
|
|
@@ -344,34 +354,20 @@ async function run({ restart, addChannels }) {
|
|
|
344
354
|
const project = projects.find((p) => p.id === projectId);
|
|
345
355
|
if (!project)
|
|
346
356
|
continue;
|
|
347
|
-
const baseName = path.basename(project.worktree);
|
|
348
|
-
const channelName = `${baseName}`
|
|
349
|
-
.toLowerCase()
|
|
350
|
-
.replace(/[^a-z0-9-]/g, '-')
|
|
351
|
-
.slice(0, 100);
|
|
352
357
|
try {
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
parent: kimakiCategory,
|
|
358
|
-
topic: `<kimaki><directory>${project.worktree}</directory><app>${appId}</app></kimaki>`,
|
|
359
|
-
});
|
|
360
|
-
const voiceChannel = await targetGuild.channels.create({
|
|
361
|
-
name: channelName,
|
|
362
|
-
type: ChannelType.GuildVoice,
|
|
363
|
-
parent: kimakiCategory,
|
|
358
|
+
const { textChannelId, channelName } = await createProjectChannels({
|
|
359
|
+
guild: targetGuild,
|
|
360
|
+
projectDirectory: project.worktree,
|
|
361
|
+
appId,
|
|
364
362
|
});
|
|
365
|
-
db.prepare('INSERT OR REPLACE INTO channel_directories (channel_id, directory, channel_type) VALUES (?, ?, ?)').run(textChannel.id, project.worktree, 'text');
|
|
366
|
-
db.prepare('INSERT OR REPLACE INTO channel_directories (channel_id, directory, channel_type) VALUES (?, ?, ?)').run(voiceChannel.id, project.worktree, 'voice');
|
|
367
363
|
createdChannels.push({
|
|
368
|
-
name:
|
|
369
|
-
id:
|
|
364
|
+
name: channelName,
|
|
365
|
+
id: textChannelId,
|
|
370
366
|
guildId: targetGuild.id,
|
|
371
367
|
});
|
|
372
368
|
}
|
|
373
369
|
catch (error) {
|
|
374
|
-
cliLogger.error(`Failed to create channels for ${
|
|
370
|
+
cliLogger.error(`Failed to create channels for ${path.basename(project.worktree)}:`, error);
|
|
375
371
|
}
|
|
376
372
|
}
|
|
377
373
|
s.stop(`Created ${createdChannels.length} channel(s)`);
|