windsor-bot 0.1.7 → 0.1.10
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 +330 -77
- package/assets/wordsearches/animals.txt +404 -0
- package/assets/wordsearches/colors.txt +404 -0
- package/assets/wordsearches/food.txt +404 -0
- package/assets/wordsearches/fruits.txt +404 -0
- package/assets/wordsearches/household.txt +404 -0
- package/assets/wordsearches/music.txt +404 -0
- package/assets/wordsearches/nature.txt +404 -0
- package/assets/wordsearches/space.txt +404 -0
- package/assets/wordsearches/sports.txt +404 -0
- package/assets/wordsearches/travel.txt +404 -0
- package/dist/bot.js +82 -9
- package/dist/commands/index.js +2 -0
- package/dist/commands/pokemon.js +1 -1
- package/dist/commands/retry.js +17 -0
- package/dist/commands/wordsearch.js +111 -89
- package/dist/reactions.js +2 -1
- package/dist/web/app.bundle.js +23 -4
- package/dist/web/app.js +20 -1
- package/package.json +5 -2
- package/dist/bot.d.ts +0 -22
- package/dist/bot.d.ts.map +0 -1
- package/dist/bot.js.map +0 -1
- package/dist/commands/hello.d.ts +0 -3
- package/dist/commands/hello.d.ts.map +0 -1
- package/dist/commands/hello.js +0 -8
- package/dist/commands/hello.js.map +0 -1
- package/dist/commands/index.d.ts +0 -3
- package/dist/commands/index.d.ts.map +0 -1
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/print.d.ts +0 -9
- package/dist/commands/print.d.ts.map +0 -1
- package/dist/commands/print.js +0 -46
- package/dist/commands/print.js.map +0 -1
- package/dist/config.d.ts +0 -8
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/server.d.ts +0 -5
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/types.d.ts +0 -55
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,135 +1,388 @@
|
|
|
1
1
|
# Windsor: Your Friendly Household Helper Bot
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Windsor turns Discord messages into useful paper: shopping lists, reminders, QR
|
|
4
|
+
codes, puzzles, and more. It is designed to run continuously on a Raspberry Pi
|
|
5
|
+
with a USB thermal printer, but it also supports any Node.js machine with a
|
|
6
|
+
serial printer, a CUPS printer, or the browser-based image feed.
|
|
6
7
|
|
|
7
|
-
##
|
|
8
|
+
## What you need
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
* A Discord server where you can install an app
|
|
11
|
+
* A computer that can stay online (a Raspberry Pi is ideal!)
|
|
12
|
+
* A compatible printer, connected by USB or available through CUPS
|
|
13
|
+
* (Optional) An OpenAI API key enables certain features
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
## Installation
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
Install the published package globally:
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g windsor-bot
|
|
21
|
+
```
|
|
16
22
|
|
|
17
|
-
|
|
23
|
+
The global install provides the `windsor-bot` command. Windsor creates
|
|
24
|
+
`windsor.config.json` in its working directory, so choose a permanent directory
|
|
25
|
+
for the bot before starting it.
|
|
26
|
+
|
|
27
|
+
## Initial setup
|
|
28
|
+
|
|
29
|
+
### 1. Create a Discord bot
|
|
30
|
+
|
|
31
|
+
1. Open the [Discord Developer Portal](https://discord.com/developers/applications)
|
|
32
|
+
and select **New Application**.
|
|
33
|
+
2. Give the application a name and open its **Bot** page.
|
|
34
|
+
3. Click **Reset Token**, then copy the token. Treat it like a password: do
|
|
35
|
+
not commit it, paste it into public issues, or share it. Discord will not
|
|
36
|
+
show the token again without resetting it.
|
|
37
|
+
4. On the **Bot** page, enable the **Message Content Intent**. Windsor reads
|
|
38
|
+
ordinary message text, so this privileged intent is required. Windsor also
|
|
39
|
+
uses guilds, guild messages, and guild message reactions.
|
|
18
40
|
|
|
19
|
-
|
|
41
|
+
### 2. Invite the bot to your server
|
|
42
|
+
|
|
43
|
+
From the application's **Installation** or **OAuth2 > URL Generator** page,
|
|
44
|
+
create an installation URL with the `bot` scope. Grant these permissions:
|
|
45
|
+
|
|
46
|
+
* View Channels
|
|
47
|
+
* Send Messages
|
|
48
|
+
* Read Message History
|
|
49
|
+
* Add Reactions
|
|
50
|
+
|
|
51
|
+
Open the generated URL, choose the target server, and authorize it. The person
|
|
52
|
+
installing the bot must have permission to manage the server. The bot must be
|
|
53
|
+
able to view and read history in every channel that Windsor monitors.
|
|
54
|
+
|
|
55
|
+
### 3. Set up a Raspberry Pi (headless)
|
|
56
|
+
|
|
57
|
+
These steps assume a Raspberry Pi 4 or 5, a blank microSD card, and a wired or
|
|
58
|
+
wireless network. The [official Raspberry Pi OS documentation](https://www.raspberrypi.com/documentation/computers/getting-started.html)
|
|
59
|
+
has screenshots and troubleshooting for each step.
|
|
60
|
+
|
|
61
|
+
1. Use [Raspberry Pi Imager](https://www.raspberrypi.com/software/) to write
|
|
62
|
+
**Raspberry Pi OS Lite (64-bit)** to the microSD card. Before writing,
|
|
63
|
+
open the OS customization screen and set:
|
|
64
|
+
* a hostname such as `windsor-pi`
|
|
65
|
+
* a username such as `piuser` (the Linux account that will run Windsor)
|
|
66
|
+
* a strong password
|
|
67
|
+
* your Wi-Fi country, network name, and password (if using Wi-Fi)
|
|
68
|
+
* the correct time zone and keyboard layout
|
|
69
|
+
* **Enable SSH**, using password authentication for the first login
|
|
70
|
+
2. Eject the card, insert it into the Pi, connect the printer, and power on the
|
|
71
|
+
Pi. Wait two to five minutes for the first boot.
|
|
72
|
+
3. From another computer on the same network, connect using the hostname:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
ssh piuser@windsor-pi.local
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
If that name does not resolve, find the Pi in the router's client list and
|
|
79
|
+
use its address instead:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
ssh piuser@192.168.1.50
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
See the
|
|
86
|
+
[Raspberry Pi SSH guide](https://www.raspberrypi.com/documentation/computers/remote-access.html#ssh)
|
|
87
|
+
if hostname discovery does not work.
|
|
88
|
+
4. Update Raspberry Pi OS and install Node.js, npm, and the optional CUPS
|
|
89
|
+
printing tools:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
sudo apt update && sudo apt upgrade -y
|
|
93
|
+
sudo apt install -y nodejs npm cups
|
|
94
|
+
node --version
|
|
95
|
+
npm --version
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
5. Install Windsor globally:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
sudo npm install --global windsor-bot
|
|
102
|
+
command -v windsor-bot
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
6. Create a dedicated working directory. Configuration and cached icons will
|
|
106
|
+
be stored here:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
mkdir -p ~/windsor
|
|
110
|
+
cd ~/windsor
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
7. Connect the USB printer. For a direct ESC/P printer, identify the device:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
ls -l /dev/ttyUSB* /dev/ttyACM* 2>/dev/null
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The usual result is `/dev/ttyUSB0` or `/dev/ttyACM0`. Add the login user to
|
|
120
|
+
the device-access group, then reconnect over SSH:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
sudo usermod -aG dialout "$USER"
|
|
124
|
+
exit
|
|
125
|
+
ssh piuser@windsor-pi.local
|
|
126
|
+
cd ~/windsor
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
For a CUPS printer, enable the service and list configured printers:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
sudo systemctl enable --now cups
|
|
133
|
+
lpstat -p
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Add the printer in CUPS, then use the name returned by `lpstat -p` in the
|
|
137
|
+
Windsor control panel.
|
|
138
|
+
|
|
139
|
+
### 4. Install Windsor as a boot-time service
|
|
20
140
|
|
|
21
|
-
|
|
141
|
+
Windsor should run under `systemd`, so it starts automatically whenever the Pi
|
|
142
|
+
boots and restarts if the process exits. `systemd` does not use your interactive
|
|
143
|
+
shell's username or `nvm` settings, so use the actual account and absolute
|
|
144
|
+
binary path. Record them while logged in as the account that should run
|
|
145
|
+
Windsor:
|
|
22
146
|
|
|
23
|
-
|
|
147
|
+
```bash
|
|
148
|
+
id -un
|
|
149
|
+
echo "$HOME"
|
|
150
|
+
command -v windsor-bot
|
|
151
|
+
```
|
|
24
152
|
|
|
25
|
-
|
|
153
|
+
The first command must print an existing Linux username, and the last command
|
|
154
|
+
must print an executable path. In the example below the account is `piuser`,
|
|
155
|
+
the home directory is `/home/piuser`, and the installed command is
|
|
156
|
+
`/usr/bin/windsor-bot`. If your output is different, substitute your values
|
|
157
|
+
everywhere in the service file. For example, a Pi account named `windsor`
|
|
158
|
+
uses `User=windsor` and `/home/windsor/...`; do not leave `User=piuser` unless
|
|
159
|
+
that account actually exists.
|
|
26
160
|
|
|
27
|
-
|
|
161
|
+
Create `/etc/systemd/system/windsor.service`:
|
|
28
162
|
|
|
163
|
+
```bash
|
|
164
|
+
sudo nano /etc/systemd/system/windsor.service
|
|
165
|
+
```
|
|
29
166
|
|
|
30
|
-
|
|
167
|
+
Paste the following, replacing the three example values with the output from
|
|
168
|
+
the commands above:
|
|
169
|
+
|
|
170
|
+
```ini
|
|
171
|
+
[Unit]
|
|
172
|
+
Description=Windsor Bot
|
|
173
|
+
After=network-online.target
|
|
174
|
+
Wants=network-online.target
|
|
175
|
+
|
|
176
|
+
[Service]
|
|
177
|
+
Type=simple
|
|
178
|
+
User=piuser
|
|
179
|
+
WorkingDirectory=/home/piuser/windsor
|
|
180
|
+
ExecStart=/usr/bin/windsor-bot
|
|
181
|
+
Restart=on-failure
|
|
182
|
+
RestartSec=10
|
|
183
|
+
|
|
184
|
+
[Install]
|
|
185
|
+
WantedBy=multi-user.target
|
|
186
|
+
```
|
|
31
187
|
|
|
32
|
-
|
|
188
|
+
Enable and start the service:
|
|
33
189
|
|
|
34
|
-
|
|
190
|
+
```bash
|
|
191
|
+
sudo systemctl daemon-reload
|
|
192
|
+
sudo systemctl enable windsor
|
|
193
|
+
sudo systemctl start windsor
|
|
194
|
+
sudo systemctl status windsor
|
|
195
|
+
```
|
|
35
196
|
|
|
36
|
-
|
|
37
|
-
You don't need to assign a behavior for every channel; channels without a behavior won't be monitored.
|
|
197
|
+
The service starts Windsor on every boot. View its logs with:
|
|
38
198
|
|
|
39
|
-
|
|
199
|
+
```bash
|
|
200
|
+
journalctl -u windsor -f
|
|
201
|
+
```
|
|
40
202
|
|
|
41
|
-
|
|
203
|
+
If the unit was already started with the wrong username or path, edit the unit,
|
|
204
|
+
then run `sudo systemctl daemon-reload`, `sudo systemctl reset-failed windsor`,
|
|
205
|
+
and `sudo systemctl restart windsor`.
|
|
42
206
|
|
|
43
|
-
|
|
44
|
-
This is ideal for "to do" items.
|
|
207
|
+
### 5. Configure credentials
|
|
45
208
|
|
|
46
|
-
|
|
209
|
+
Open [http://localhost:8080](http://localhost:8080) (or port 8080 on the Pi's
|
|
210
|
+
hostname/IP) from a computer on the same network. The service starts with no
|
|
211
|
+
Discord token, but the control panel is available immediately. Enter:
|
|
47
212
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
213
|
+
1. The Discord bot token.
|
|
214
|
+
2. Optionally, the server ID to restrict Windsor to one server. To copy
|
|
215
|
+
IDs in Discord, enable **Developer Mode**, then right-click the server and
|
|
216
|
+
choose **Copy Server ID**.
|
|
217
|
+
3. Optionally enter an OpenAI API key. It is required for AI-generated icons
|
|
218
|
+
and recurring schedules.
|
|
219
|
+
4. Set a control-panel password in the **Security** section.
|
|
220
|
+
5. Save, then click **Restart Server**. This restarts the bot while leaving the
|
|
221
|
+
boot service enabled.
|
|
53
222
|
|
|
54
|
-
|
|
223
|
+
Credentials may instead be supplied through environment variables:
|
|
55
224
|
|
|
56
|
-
|
|
57
|
-
|
|
225
|
+
| Variable | Purpose |
|
|
226
|
+
| --- | --- |
|
|
227
|
+
| `DISCORD_TOKEN` | Discord bot token |
|
|
228
|
+
| `SERVER_ID` | Optional Discord server ID |
|
|
229
|
+
| `OPENAI_API_KEY` | Optional OpenAI API key |
|
|
230
|
+
| `DIAGNOSTICS_PORT` | Control-panel port, default `8080` |
|
|
231
|
+
| `WINDSOR_CONFIG_PATH` | Path to the configuration file |
|
|
58
232
|
|
|
59
|
-
|
|
233
|
+
The control panel listens on all interfaces. Set a control-panel password in
|
|
234
|
+
the **Security** section before exposing it beyond your trusted local network.
|
|
235
|
+
`windsor.config.json` is gitignored because it contains secrets.
|
|
60
236
|
|
|
61
|
-
|
|
237
|
+
## Configure printing
|
|
62
238
|
|
|
63
|
-
|
|
239
|
+
Open the **Print Mode** section in the control panel, select an output mode, and
|
|
240
|
+
save it. Use **Print Test Page** before configuring channels.
|
|
64
241
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
242
|
+
* **ESC/P via Serial Port** sends thermal-printer commands directly to a
|
|
243
|
+
device such as `/dev/ttyUSB0` (or `COM3` on Windows).
|
|
244
|
+
* **PDF via CUPS** renders a PDF and submits it with `lp`. Enter the CUPS
|
|
245
|
+
printer name, paper size (for example `Letter`, `A4`, or `80x297mm`), and
|
|
246
|
+
the display label for the paper.
|
|
247
|
+
* **Image Feed** renders jobs as PNGs instead of printing them. View them at
|
|
248
|
+
`/feed`; this is useful for development and printer-independent testing.
|
|
69
249
|
|
|
70
|
-
|
|
250
|
+
## Configure channels
|
|
71
251
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
252
|
+
Windsor only monitors channels that have a behavior assigned. In **Channel
|
|
253
|
+
Behaviors**, choose a Discord text channel, select a behavior, and click
|
|
254
|
+
**Add**. Expand a channel row to edit its options. Use **Refresh Discord
|
|
255
|
+
Channels** after creating or renaming channels.
|
|
75
256
|
|
|
76
|
-
|
|
257
|
+
### 🖨️ Immediate Print
|
|
77
258
|
|
|
78
|
-
|
|
259
|
+
Every eligible message is printed immediately. This is useful for to-do items
|
|
260
|
+
and quick notes. Available options:
|
|
79
261
|
|
|
80
|
-
|
|
262
|
+
* **Header** and **Footer**: fixed text around each job
|
|
263
|
+
* **Include metadata footer**: includes the author and timestamp
|
|
264
|
+
* **Include AI-generated icon**: creates an icon from the message (requires an
|
|
265
|
+
OpenAI key)
|
|
81
266
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
>
|
|
86
|
-
> Call Bob a week before his birthday (6/12)
|
|
267
|
+
Messages can contain up to 800 non-URL characters. Up to five `https://` URLs
|
|
268
|
+
are extracted, replaced in the text with `[link]` (or `[link 1]`, etc.), and
|
|
269
|
+
printed as QR codes after the message.
|
|
87
270
|
|
|
88
|
-
|
|
271
|
+
### 🛒 Accumulating List
|
|
89
272
|
|
|
90
|
-
|
|
273
|
+
Messages are collected until someone posts `print` (case-insensitive; extra
|
|
274
|
+
punctuation is allowed). Windsor prints the items since the previous successful
|
|
275
|
+
print and marks the trigger with a reaction. This is useful for shopping lists.
|
|
91
276
|
|
|
92
|
-
|
|
277
|
+
Available options are **Header**, **Footer**, **Include metadata footer**, and
|
|
278
|
+
**Include checklist boxes**.
|
|
93
279
|
|
|
94
|
-
|
|
280
|
+
### 🔄 Recurring Print
|
|
95
281
|
|
|
96
|
-
|
|
282
|
+
Each message becomes a scheduled print. This behavior requires an OpenAI key
|
|
283
|
+
because Windsor uses it to interpret natural-language schedules. Examples:
|
|
97
284
|
|
|
98
|
-
|
|
285
|
+
```text
|
|
286
|
+
Take out the trash every other Tuesday at 7 PM
|
|
287
|
+
Change out the batteries on the 3rd of the month at 2 PM
|
|
288
|
+
Call Bob a week before his birthday (6/12)
|
|
289
|
+
```
|
|
99
290
|
|
|
100
|
-
|
|
291
|
+
Windsor replies with the interpreted schedule. If it is wrong, delete the
|
|
292
|
+
original message and post a corrected version. If no time is specified, the
|
|
293
|
+
default is 8:00 AM local time. Schedules are restored from recent channel
|
|
294
|
+
history when the bot starts.
|
|
101
295
|
|
|
102
|
-
|
|
296
|
+
### 💬 On-Demand
|
|
103
297
|
|
|
104
|
-
|
|
298
|
+
Only recognized commands are processed. Messages without a command prefix are
|
|
299
|
+
ignored. Commands accept either `!` or `/`; these are message prefixes, not
|
|
300
|
+
registered Discord slash commands.
|
|
105
301
|
|
|
106
|
-
|
|
107
|
-
Themes are chosen randomly and are always kid-appropriate.
|
|
302
|
+
## On-demand commands
|
|
108
303
|
|
|
109
|
-
|
|
304
|
+
| Command | Aliases | Description |
|
|
305
|
+
| --- | --- | --- |
|
|
306
|
+
| `/sudoku [kid\|easy\|medium\|hard]` | — | Prints a puzzle; defaults to `easy`. |
|
|
307
|
+
| `/wordsearch` | — | Prints a randomly themed, kid-appropriate word search. |
|
|
308
|
+
| `/pokemon [name\|1-151]` | `/kanto` | Prints a random Kanto Pokémon, or the named/numbered Pokémon. |
|
|
309
|
+
| `/hello` | `/helloworld` | Replies with a greeting without printing. |
|
|
110
310
|
|
|
111
|
-
|
|
311
|
+
For example, send `!sudoku hard` or `/pokemon Pikachu` in an on-demand
|
|
312
|
+
channel.
|
|
112
313
|
|
|
113
|
-
|
|
314
|
+
Wordsearches are pre-generated offline from the theme banks in
|
|
315
|
+
`scripts/wordsearch-themes`; the generator validates words against the
|
|
316
|
+
ROT13-encoded family-friendly denylist in
|
|
317
|
+
`scripts/wordsearch-blocklist.rot13.txt`. Run `npm run generate-wordsearches`
|
|
318
|
+
after changing the banks or generator.
|
|
114
319
|
|
|
115
|
-
|
|
116
|
-
npm run dev
|
|
117
|
-
```
|
|
320
|
+
## Control panel and local configuration
|
|
118
321
|
|
|
119
|
-
|
|
322
|
+
The diagnostics server provides:
|
|
120
323
|
|
|
121
|
-
|
|
122
|
-
|
|
324
|
+
* Bot connection status and recent events
|
|
325
|
+
* Discord credentials, server selection, and diagnostics port
|
|
326
|
+
* Channel behavior mappings
|
|
327
|
+
* Printer mode and test printing
|
|
328
|
+
* A password for the control panel
|
|
329
|
+
* Server restart and image-feed access
|
|
330
|
+
|
|
331
|
+
The panel saves settings to `windsor.config.json` in the current working
|
|
332
|
+
directory unless `WINDSOR_CONFIG_PATH` is set. The file is JSON and can be
|
|
333
|
+
backed up, but keep it private.
|
|
334
|
+
|
|
335
|
+
## Updating a production installation
|
|
336
|
+
|
|
337
|
+
Keep the Discord token and OpenAI key in the protected configuration file, or
|
|
338
|
+
configure them once through the panel. Upgrade the global package, then
|
|
339
|
+
restart the boot service:
|
|
123
340
|
|
|
124
341
|
```bash
|
|
125
|
-
|
|
342
|
+
sudo npm install --global windsor-bot
|
|
343
|
+
sudo systemctl restart windsor
|
|
126
344
|
```
|
|
127
345
|
|
|
128
|
-
|
|
346
|
+
Check the service after an update with `sudo systemctl status windsor` and view
|
|
347
|
+
logs with `journalctl -u windsor -f`.
|
|
348
|
+
|
|
349
|
+
## Troubleshooting
|
|
350
|
+
|
|
351
|
+
* **The bot is connected but ignores messages:** verify the channel has a
|
|
352
|
+
behavior, the bot can view/read the channel, and **Message Content Intent**
|
|
353
|
+
is enabled.
|
|
354
|
+
* **The server is missing from the panel:** verify the token, installation,
|
|
355
|
+
and optional `SERVER_ID`; then use **Refresh Discord Channels**.
|
|
356
|
+
* **Printing fails:** use **Print Test Page**, confirm the selected mode, check
|
|
357
|
+
the serial device permissions, or verify the CUPS name with `lpstat -p`.
|
|
358
|
+
* **The control panel cannot be reached:** confirm Windsor is running, check
|
|
359
|
+
the configured port, and use the Pi's reachable hostname or IP instead of
|
|
360
|
+
`localhost`.
|
|
361
|
+
* **AI features fail:** confirm `OPENAI_API_KEY` is present and restart Windsor
|
|
362
|
+
after changing it.
|
|
363
|
+
* **`status=217/USER`:** the `User=` account in
|
|
364
|
+
`/etc/systemd/system/windsor.service` does not exist. Set it to the username
|
|
365
|
+
printed by `id -un`, update `WorkingDirectory` to that user's home directory,
|
|
366
|
+
reload systemd, and restart the service.
|
|
367
|
+
|
|
368
|
+
## Local development
|
|
369
|
+
|
|
370
|
+
The normal installation does not require a checkout. These commands are for
|
|
371
|
+
contributors working from the source tree:
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
npm run dev # run Windsor and the diagnostics server
|
|
375
|
+
npm run build # type-check and build the web panel
|
|
376
|
+
npm test # run the Node test suite
|
|
377
|
+
npm run gen-image -- a friendly shopping list # generate test.png using the local config
|
|
378
|
+
```
|
|
129
379
|
|
|
130
|
-
|
|
131
|
-
|
|
380
|
+
The control-panel source is `src/web/app.tsx`. The browser app is bundled into
|
|
381
|
+
the npm package during `npm run build`.
|
|
132
382
|
|
|
133
|
-
|
|
383
|
+
## Sources
|
|
134
384
|
|
|
135
|
-
|
|
385
|
+
* [Discord: Building your first Discord bot](https://docs.discord.com/developers/quick-start/getting-started)
|
|
386
|
+
* [Discord: OAuth2 and bot authorization](https://docs.discord.com/developers/topics/oauth2#bot-authorization-flow)
|
|
387
|
+
* [Raspberry Pi: Getting started](https://www.raspberrypi.com/documentation/computers/getting-started.html)
|
|
388
|
+
* [Raspberry Pi: Remote access over SSH](https://www.raspberrypi.com/documentation/computers/remote-access.html#ssh)
|