u-wave-announce 0.5.0 → 0.5.3
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 -26
- package/package.json +5 -4
- package/src/plugin.js +55 -43
- package/src/signatures.js +2 -0
- package/test.js +9 -0
package/README.md
CHANGED
|
@@ -5,28 +5,22 @@ server listing at https://hub.u-wave.net.
|
|
|
5
5
|
|
|
6
6
|
## Usage
|
|
7
7
|
|
|
8
|
+
The announce plugin is added by default if you use the executable provided
|
|
9
|
+
with üWave Core. If you are using the üWave Core Node.js API, install and
|
|
10
|
+
add it manually:
|
|
11
|
+
|
|
8
12
|
```bash
|
|
9
|
-
npm install
|
|
13
|
+
npm install u-wave-announce
|
|
10
14
|
```
|
|
11
15
|
|
|
12
16
|
```js
|
|
13
17
|
import announce from 'u-wave-announce';
|
|
14
18
|
|
|
15
|
-
uw.use(announce
|
|
16
|
-
name: 'Your server name',
|
|
17
|
-
subtitle: 'Very short description', // Up to about 30 characters.
|
|
18
|
-
description: `
|
|
19
|
-
Longer description about your server, perhaps with a list of rules.
|
|
20
|
-
May include _markdown_, even!
|
|
21
|
-
`,
|
|
22
|
-
url: 'https://my-uwave-server.com',
|
|
23
|
-
}));
|
|
19
|
+
uw.use(announce);
|
|
24
20
|
```
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
## Options
|
|
22
|
+
## Runtime Options
|
|
23
|
+
This plugin can be configured at runtime using the admin panel.
|
|
30
24
|
|
|
31
25
|
### `name` (required)
|
|
32
26
|
|
|
@@ -51,18 +45,6 @@ including images and links. This can be a good place to put rules, links to
|
|
|
51
45
|
social media accounts associated with your server, and whatever else you want
|
|
52
46
|
visitors to know.
|
|
53
47
|
|
|
54
|
-
Indentation is stripped from this option, so template strings can be used like:
|
|
55
|
-
|
|
56
|
-
```js
|
|
57
|
-
announce({
|
|
58
|
-
description: `
|
|
59
|
-
# My Awesome Server
|
|
60
|
-
|
|
61
|
-
We play cool stuff, and cool stuff only!
|
|
62
|
-
`
|
|
63
|
-
});
|
|
64
|
-
```
|
|
65
|
-
|
|
66
48
|
### `hub`
|
|
67
49
|
|
|
68
50
|
The announce server to announce to. Uses https://announce.u-wave.net, the server
|
package/package.json
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "u-wave-announce",
|
|
3
3
|
"description": "Announce your üWave server's existence to the world.",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.3",
|
|
5
5
|
"author": "Renée Kooi <renee@kooi.me>",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"debug": "^4.
|
|
8
|
-
"find-cache-dir": "^3.0.0",
|
|
7
|
+
"debug": "^4.3.2",
|
|
9
8
|
"libsodium-wrappers": "^0.7.8",
|
|
10
|
-
"ms": "^2.0.0",
|
|
11
9
|
"node-fetch": "^2.6.0",
|
|
12
10
|
"strip-indent": "^3.0.0"
|
|
13
11
|
},
|
|
@@ -19,5 +17,8 @@
|
|
|
19
17
|
"repository": {
|
|
20
18
|
"git": "https://github.com/u-wave/hub.git",
|
|
21
19
|
"directory": "plugin"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"test": "node test"
|
|
22
23
|
}
|
|
23
24
|
}
|
package/src/plugin.js
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { promisify } = require('util');
|
|
4
|
+
const randomBytes = promisify(require('crypto').randomBytes);
|
|
2
5
|
const fetch = require('node-fetch');
|
|
3
|
-
const ms = require('ms');
|
|
4
6
|
const stripIndent = require('strip-indent');
|
|
5
|
-
const findCacheDir = require('find-cache-dir');
|
|
6
7
|
const debug = require('debug')('uwave:announce');
|
|
7
8
|
const sodium = require('./signatures');
|
|
8
9
|
const pkg = require('../package.json');
|
|
9
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Fallback logger implementation for üWave Core versions that do
|
|
13
|
+
* not come with a logger yet.
|
|
14
|
+
*/
|
|
15
|
+
const debugLogger = {
|
|
16
|
+
debug,
|
|
17
|
+
info: debug,
|
|
18
|
+
error: debug,
|
|
19
|
+
};
|
|
20
|
+
|
|
10
21
|
const optionsSchema = {
|
|
11
22
|
type: 'object',
|
|
12
23
|
title: 'Announce',
|
|
@@ -19,6 +30,14 @@ const optionsSchema = {
|
|
|
19
30
|
description: 'Whether to announce at all.',
|
|
20
31
|
default: false,
|
|
21
32
|
},
|
|
33
|
+
seed: {
|
|
34
|
+
type: 'string',
|
|
35
|
+
pattern: /^[0-9a-f]{64}$/.source,
|
|
36
|
+
// Should not be edited by users.
|
|
37
|
+
readOnly: true,
|
|
38
|
+
// Should not be exposed to users.
|
|
39
|
+
writeOnly: true,
|
|
40
|
+
},
|
|
22
41
|
name: {
|
|
23
42
|
type: 'string',
|
|
24
43
|
title: 'Server Name',
|
|
@@ -81,36 +100,6 @@ function stripSlashes(url) {
|
|
|
81
100
|
return url.replace(/\/+$/, '');
|
|
82
101
|
}
|
|
83
102
|
|
|
84
|
-
async function getKeyPair(seed) {
|
|
85
|
-
const keyPairPath = findCacheDir({
|
|
86
|
-
name: pkg.name,
|
|
87
|
-
create: true,
|
|
88
|
-
thunk: true,
|
|
89
|
-
})('keypair.json');
|
|
90
|
-
try {
|
|
91
|
-
const { publicKey, secretKey, forSeed } = JSON.parse(
|
|
92
|
-
await fs.readFile(keyPairPath, 'utf8'),
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
if (Buffer.compare(Buffer.from(forSeed), Buffer.from(seed)) !== 0) {
|
|
96
|
-
throw new Error('this error object is unused');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
publicKey: Buffer.from(publicKey, 'base64'),
|
|
101
|
-
secretKey: Buffer.from(secretKey, 'base64'),
|
|
102
|
-
};
|
|
103
|
-
} catch (error) {
|
|
104
|
-
const { publicKey, secretKey } = await sodium.keyPair(seed);
|
|
105
|
-
await fs.writeFile(keyPairPath, JSON.stringify({
|
|
106
|
-
publicKey: publicKey.toString('base64'),
|
|
107
|
-
secretKey: secretKey.toString('base64'),
|
|
108
|
-
forSeed: seed,
|
|
109
|
-
}, null, 2), 'utf8');
|
|
110
|
-
return { publicKey, secretKey };
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
103
|
async function getAnnounceData(uw, options) {
|
|
115
104
|
const url = stripSlashes(options.url);
|
|
116
105
|
|
|
@@ -118,8 +107,12 @@ async function getAnnounceData(uw, options) {
|
|
|
118
107
|
// the relationships.
|
|
119
108
|
const entry = await uw.booth.getCurrentEntry();
|
|
120
109
|
if (entry) {
|
|
121
|
-
entry.
|
|
122
|
-
|
|
110
|
+
if (entry.execPopulate) {
|
|
111
|
+
entry.populate('user media.media');
|
|
112
|
+
await entry.execPopulate();
|
|
113
|
+
} else {
|
|
114
|
+
await entry.populate('user media.media');
|
|
115
|
+
}
|
|
123
116
|
}
|
|
124
117
|
|
|
125
118
|
// TODO add something to üWave Core so we don't have to manually ask Redis for
|
|
@@ -158,25 +151,43 @@ async function getAnnounceData(uw, options) {
|
|
|
158
151
|
};
|
|
159
152
|
}
|
|
160
153
|
|
|
161
|
-
async function
|
|
162
|
-
const
|
|
154
|
+
async function getOrGenerateSeed(uw) {
|
|
155
|
+
const options = await uw.config.get(optionsSchema['uw:key']);
|
|
156
|
+
if (!options.seed) {
|
|
157
|
+
options.seed = (await randomBytes(32)).toString('hex');
|
|
158
|
+
await uw.config.set(optionsSchema['uw:key'], options);
|
|
159
|
+
}
|
|
160
|
+
return Buffer.from(options.seed, 'hex');
|
|
161
|
+
}
|
|
163
162
|
|
|
163
|
+
async function announcePlugin(uw, staticOptions) {
|
|
164
164
|
uw.config.register(optionsSchema['uw:key'], optionsSchema);
|
|
165
165
|
|
|
166
|
+
// üWave Core 0.5.0 and up have a `pino` logger
|
|
167
|
+
const logger = uw.logger
|
|
168
|
+
? uw.logger.child({ ns: 'uwave:announce' })
|
|
169
|
+
: debugLogger;
|
|
170
|
+
|
|
171
|
+
const seed = staticOptions.seed || await getOrGenerateSeed(uw);
|
|
172
|
+
// This takes up to a few 100 ms but it is a one-time startup cost…
|
|
173
|
+
// Maybe it makes sense to cache this, or to not block the rest of
|
|
174
|
+
// the startup work. For now, we just do the easy thing.
|
|
175
|
+
const { publicKey, secretKey } = await sodium.keyPair(seed);
|
|
176
|
+
|
|
166
177
|
async function announce() {
|
|
167
178
|
const options = await uw.config.get(optionsSchema['uw:key']);
|
|
168
179
|
if (typeof options !== 'object') {
|
|
169
|
-
debug('announcing not configured, skipping');
|
|
180
|
+
logger.debug('announcing not configured, skipping');
|
|
170
181
|
return;
|
|
171
182
|
}
|
|
172
183
|
if (!options.enabled) {
|
|
173
|
-
debug('announcing disabled, skipping');
|
|
184
|
+
logger.debug('announcing disabled, skipping');
|
|
174
185
|
return;
|
|
175
186
|
}
|
|
176
187
|
|
|
177
188
|
const hubHost = options.hub || 'https://announce.u-wave.net';
|
|
178
189
|
const announceUrl = `${stripSlashes(hubHost)}/announce/${Buffer.from(publicKey).toString('hex')}`;
|
|
179
|
-
|
|
190
|
+
logger.info('announcing to', announceUrl);
|
|
180
191
|
|
|
181
192
|
const announcement = await getAnnounceData(uw, options);
|
|
182
193
|
const data = JSON.stringify(announcement);
|
|
@@ -185,6 +196,7 @@ async function announcePlugin(uw, staticOptions) {
|
|
|
185
196
|
await fetch(announceUrl, {
|
|
186
197
|
method: 'post',
|
|
187
198
|
headers: {
|
|
199
|
+
'user-agent': `u-wave-announce ${pkg.version}`,
|
|
188
200
|
'content-type': 'application/json',
|
|
189
201
|
},
|
|
190
202
|
body: JSON.stringify({
|
|
@@ -194,8 +206,8 @@ async function announcePlugin(uw, staticOptions) {
|
|
|
194
206
|
});
|
|
195
207
|
}
|
|
196
208
|
|
|
197
|
-
function onError(
|
|
198
|
-
|
|
209
|
+
function onError(error) {
|
|
210
|
+
logger.error({ err: error });
|
|
199
211
|
}
|
|
200
212
|
|
|
201
213
|
let interval;
|
|
@@ -208,7 +220,7 @@ async function announcePlugin(uw, staticOptions) {
|
|
|
208
220
|
// we're still alive.
|
|
209
221
|
interval = setInterval(() => {
|
|
210
222
|
announce().catch(onError);
|
|
211
|
-
},
|
|
223
|
+
}, 60_000);
|
|
212
224
|
});
|
|
213
225
|
|
|
214
226
|
// Announce again every time the song changes.
|
package/src/signatures.js
CHANGED