windsor-bot 0.1.0 → 0.1.2
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 +8 -1
- package/dist/index.js +6 -7
- package/dist/server.js +24 -7
- package/dist/web/app.bundle.js +955 -0
- package/package.json +3 -3
- package/scripts/build-web.mjs +13 -0
- package/src/index.ts +7 -7
- package/src/server.ts +24 -7
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "windsor-bot",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Self-hosted Discord bot automation for household list and todo printing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"prepare": "
|
|
9
|
-
"build": "tsc",
|
|
8
|
+
"prepare": "npm run build",
|
|
9
|
+
"build": "tsc && node scripts/build-web.mjs",
|
|
10
10
|
"dev": "node src/index.ts",
|
|
11
11
|
"test": "node --test src/tests/*.test.ts"
|
|
12
12
|
},
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { build } from 'esbuild';
|
|
2
|
+
|
|
3
|
+
await build({
|
|
4
|
+
entryPoints: ['src/web/app.tsx'],
|
|
5
|
+
bundle: true,
|
|
6
|
+
outfile: 'dist/web/app.bundle.js',
|
|
7
|
+
platform: 'browser',
|
|
8
|
+
format: 'esm',
|
|
9
|
+
target: ['es2022'],
|
|
10
|
+
jsx: 'automatic',
|
|
11
|
+
jsxImportSource: 'preact',
|
|
12
|
+
sourcemap: 'inline',
|
|
13
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { loadConfig
|
|
2
|
+
import { loadConfig } from './config.ts';
|
|
3
3
|
import { logEvent, startDiagnosticsServer, setDiscordChannels, setRestartHandler, setRefreshChannelsHandler } from './server.ts';
|
|
4
4
|
import { createWindsorBot, checkScheduledTasks } from './bot.ts';
|
|
5
5
|
import { ChannelType } from 'discord.js';
|
|
6
|
+
import type { WindsorConfig } from './types.ts';
|
|
6
7
|
|
|
7
|
-
const config =
|
|
8
|
+
const { config } = await loadConfig();
|
|
8
9
|
|
|
9
10
|
startDiagnosticsServer(config.diagnosticsPort);
|
|
10
11
|
|
|
11
12
|
let bot: ReturnType<typeof createWindsorBot> | null = null;
|
|
12
13
|
let startInFlight = false;
|
|
13
14
|
|
|
14
|
-
async function startBot(): Promise<void> {
|
|
15
|
+
async function startBot(cfg: WindsorConfig): Promise<void> {
|
|
15
16
|
if (startInFlight) return;
|
|
16
|
-
const cfg = getCurrentConfig();
|
|
17
17
|
if (!cfg.discordToken) {
|
|
18
18
|
logEvent('info', 'No Discord token configured. Visit the control panel to set up.');
|
|
19
19
|
return;
|
|
@@ -58,8 +58,8 @@ export async function restartBot(): Promise<void> {
|
|
|
58
58
|
bot = null;
|
|
59
59
|
}
|
|
60
60
|
setDiscordChannels([]);
|
|
61
|
-
await loadConfig();
|
|
62
|
-
await startBot();
|
|
61
|
+
const { config } = await loadConfig();
|
|
62
|
+
await startBot(config);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// Recurring task checker
|
|
@@ -95,4 +95,4 @@ async function refreshChannels(): Promise<void> {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
setRefreshChannelsHandler(refreshChannels);
|
|
98
|
-
await startBot();
|
|
98
|
+
await startBot(config);
|
package/src/server.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createServer, type IncomingMessage, type ServerResponse } from 'http';
|
|
2
2
|
import { build } from 'esbuild';
|
|
3
|
-
import { stat } from 'fs/promises';
|
|
4
|
-
import { join } from 'path';
|
|
3
|
+
import { readFile, stat } from 'fs/promises';
|
|
4
|
+
import { dirname, join } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
5
6
|
import {
|
|
6
7
|
getCurrentConfig,
|
|
7
8
|
updateConfig,
|
|
@@ -90,14 +91,30 @@ async function readJsonBody(req: IncomingMessage): Promise<Record<string, unknow
|
|
|
90
91
|
let appBundleCache: { script: string; mtimeMs: number } | null = null;
|
|
91
92
|
|
|
92
93
|
async function loadAppScript(): Promise<string> {
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
|
|
94
|
+
const runtimeDir = dirname(fileURLToPath(import.meta.url));
|
|
95
|
+
const bundledApp = join(runtimeDir, 'web', 'app.bundle.js');
|
|
96
|
+
const sourceEntryPoint = join(runtimeDir, '..', 'src', 'web', 'app.tsx');
|
|
97
|
+
const appPath = await stat(bundledApp).then(() => bundledApp).catch((error: unknown) => {
|
|
98
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
99
|
+
return sourceEntryPoint;
|
|
100
|
+
}
|
|
101
|
+
throw error;
|
|
102
|
+
});
|
|
103
|
+
const appStat = await stat(appPath);
|
|
104
|
+
if (appPath === bundledApp) {
|
|
105
|
+
if (appBundleCache && appBundleCache.mtimeMs === appStat.mtimeMs) {
|
|
106
|
+
return appBundleCache.script;
|
|
107
|
+
}
|
|
108
|
+
const script = await readFile(appPath, 'utf8');
|
|
109
|
+
appBundleCache = { script, mtimeMs: appStat.mtimeMs };
|
|
110
|
+
return script;
|
|
111
|
+
}
|
|
112
|
+
if (appBundleCache && appBundleCache.mtimeMs === appStat.mtimeMs) {
|
|
96
113
|
return appBundleCache.script;
|
|
97
114
|
}
|
|
98
115
|
|
|
99
116
|
const result = await build({
|
|
100
|
-
entryPoints: [
|
|
117
|
+
entryPoints: [sourceEntryPoint],
|
|
101
118
|
bundle: true,
|
|
102
119
|
write: false,
|
|
103
120
|
platform: 'browser',
|
|
@@ -110,7 +127,7 @@ async function loadAppScript(): Promise<string> {
|
|
|
110
127
|
|
|
111
128
|
const firstFile = result.outputFiles[0];
|
|
112
129
|
if (!firstFile) throw new Error('Failed to generate app bundle');
|
|
113
|
-
appBundleCache = { script: firstFile.text, mtimeMs:
|
|
130
|
+
appBundleCache = { script: firstFile.text, mtimeMs: appStat.mtimeMs };
|
|
114
131
|
return firstFile.text;
|
|
115
132
|
}
|
|
116
133
|
|