@nekosuneprojects/vector-sdk 1.0.3 → 1.0.4
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 +6 -5
- package/dist/bot.js +11 -7
- package/dist/client.js +7 -0
- package/dist/demo.js +1 -1
- package/dist/keys.js +21 -10
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -56,22 +56,23 @@ client.on('error', (error) => {
|
|
|
56
56
|
console.error('Bot error:', error);
|
|
57
57
|
});
|
|
58
58
|
|
|
59
|
-
client.on('message', async (
|
|
59
|
+
client.on('message', async (senderPubkey, tags, message, self) => {
|
|
60
60
|
if (self) return;
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
const senderName = tags.displayName || senderPubkey;
|
|
63
|
+
console.log(`${senderName}: ${message}`);
|
|
63
64
|
|
|
64
65
|
if (message.startsWith('!ping')) {
|
|
65
|
-
await client.sendMessage(
|
|
66
|
+
await client.sendMessage(senderPubkey, 'pong');
|
|
66
67
|
return;
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
if (message.startsWith('!upload')) {
|
|
70
71
|
if (!process.env.UPLOAD_FILE_PATH) {
|
|
71
|
-
await client.sendMessage(
|
|
72
|
+
await client.sendMessage(senderPubkey, 'Set UPLOAD_FILE_PATH to send a file.');
|
|
72
73
|
return;
|
|
73
74
|
}
|
|
74
|
-
await client.sendFile(
|
|
75
|
+
await client.sendFile(senderPubkey, process.env.UPLOAD_FILE_PATH);
|
|
75
76
|
}
|
|
76
77
|
});
|
|
77
78
|
|
package/dist/bot.js
CHANGED
|
@@ -126,17 +126,19 @@ export class Channel {
|
|
|
126
126
|
}
|
|
127
127
|
async sendReaction(referenceId, emoji) {
|
|
128
128
|
try {
|
|
129
|
-
const
|
|
129
|
+
const rumor = {
|
|
130
130
|
kind: kinds.Reaction,
|
|
131
131
|
created_at: Math.floor(Date.now() / 1000),
|
|
132
132
|
tags: [
|
|
133
133
|
['e', referenceId],
|
|
134
134
|
['p', this.recipient],
|
|
135
|
+
['k', kinds.PrivateDirectMessage.toString()],
|
|
135
136
|
['ms', (Date.now() % 1000).toString()],
|
|
136
137
|
],
|
|
137
138
|
content: emoji,
|
|
138
|
-
}
|
|
139
|
-
|
|
139
|
+
};
|
|
140
|
+
const wrapped = nip59.wrapEvent(rumor, this.baseBot.privateKeyBytes, this.recipient);
|
|
141
|
+
await this.baseBot.client.publishEvent(wrapped);
|
|
140
142
|
return true;
|
|
141
143
|
}
|
|
142
144
|
catch (error) {
|
|
@@ -147,17 +149,19 @@ export class Channel {
|
|
|
147
149
|
async sendTypingIndicator() {
|
|
148
150
|
try {
|
|
149
151
|
const now = Math.floor(Date.now() / 1000);
|
|
150
|
-
const
|
|
152
|
+
const rumor = {
|
|
151
153
|
kind: kinds.Application,
|
|
152
154
|
created_at: now,
|
|
153
155
|
tags: [
|
|
154
156
|
['p', this.recipient],
|
|
157
|
+
['d', 'vector'],
|
|
155
158
|
['ms', (Date.now() % 1000).toString()],
|
|
156
|
-
['expiration', (now +
|
|
159
|
+
['expiration', (now + 30).toString()],
|
|
157
160
|
],
|
|
158
161
|
content: 'typing',
|
|
159
|
-
}
|
|
160
|
-
|
|
162
|
+
};
|
|
163
|
+
const wrapped = nip59.wrapEvent(rumor, this.baseBot.privateKeyBytes, this.recipient);
|
|
164
|
+
await this.baseBot.client.publishEvent(wrapped);
|
|
161
165
|
return true;
|
|
162
166
|
}
|
|
163
167
|
catch (error) {
|
package/dist/client.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SimplePool } from 'nostr-tools';
|
|
2
2
|
import { finalizeEvent, getPublicKey } from 'nostr-tools/pure';
|
|
3
|
+
import WebSocket from 'ws';
|
|
3
4
|
import { normalizePrivateKey } from './keys.js';
|
|
4
5
|
const DEFAULT_RELAYS = [
|
|
5
6
|
'wss://jskitty.cat/nostr',
|
|
@@ -7,9 +8,15 @@ const DEFAULT_RELAYS = [
|
|
|
7
8
|
'wss://auth.nostr1.com',
|
|
8
9
|
'wss://nostr.computingcache.com',
|
|
9
10
|
];
|
|
11
|
+
function ensureWebSocket() {
|
|
12
|
+
if (typeof globalThis.WebSocket === 'undefined') {
|
|
13
|
+
globalThis.WebSocket = WebSocket;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
10
16
|
export class VectorClient {
|
|
11
17
|
constructor(keys, config) {
|
|
12
18
|
this.pool = new SimplePool();
|
|
19
|
+
ensureWebSocket();
|
|
13
20
|
const normalized = normalizePrivateKey(keys);
|
|
14
21
|
this.privateKey = normalized.hex;
|
|
15
22
|
this.privateKeyBytes = normalized.bytes;
|
package/dist/demo.js
CHANGED
|
@@ -170,7 +170,7 @@ export class VectorBotClient extends EventEmitter {
|
|
|
170
170
|
}
|
|
171
171
|
async emitMessage(bot, pubkey, kind, rawEvent, content, wrapped) {
|
|
172
172
|
const profile = await this.getProfile(bot, pubkey);
|
|
173
|
-
this.emit('message',
|
|
173
|
+
this.emit('message', pubkey, {
|
|
174
174
|
pubkey,
|
|
175
175
|
kind,
|
|
176
176
|
rawEvent,
|
package/dist/keys.js
CHANGED
|
@@ -2,32 +2,43 @@ import { nip19 } from 'nostr-tools';
|
|
|
2
2
|
import { bytesToHex, hexToBytes } from 'nostr-tools/utils';
|
|
3
3
|
export class KeyFormatError extends Error {
|
|
4
4
|
}
|
|
5
|
+
function stripNostrUriPrefix(value) {
|
|
6
|
+
const trimmed = value.trim();
|
|
7
|
+
if (trimmed.toLowerCase().startsWith('nostr:')) {
|
|
8
|
+
return trimmed.slice('nostr:'.length).trim();
|
|
9
|
+
}
|
|
10
|
+
return trimmed;
|
|
11
|
+
}
|
|
5
12
|
export function normalizePrivateKey(privateKey) {
|
|
6
|
-
const trimmed = privateKey
|
|
7
|
-
|
|
8
|
-
|
|
13
|
+
const trimmed = stripNostrUriPrefix(privateKey);
|
|
14
|
+
const lowered = trimmed.toLowerCase();
|
|
15
|
+
if (lowered.startsWith('nsec1')) {
|
|
16
|
+
const decoded = nip19.decode(lowered);
|
|
9
17
|
if (decoded.type !== 'nsec') {
|
|
10
18
|
throw new KeyFormatError('Invalid nsec private key');
|
|
11
19
|
}
|
|
12
20
|
return { hex: bytesToHex(decoded.data), bytes: decoded.data };
|
|
13
21
|
}
|
|
14
|
-
|
|
22
|
+
const hexCandidate = lowered.startsWith('0x') ? lowered.slice(2) : lowered;
|
|
23
|
+
if (!/^[0-9a-f]{64}$/.test(hexCandidate)) {
|
|
15
24
|
throw new KeyFormatError('Private key must be a 32-byte hex string or nsec');
|
|
16
25
|
}
|
|
17
|
-
const hex =
|
|
26
|
+
const hex = hexCandidate;
|
|
18
27
|
return { hex, bytes: hexToBytes(hex) };
|
|
19
28
|
}
|
|
20
29
|
export function normalizePublicKey(publicKey) {
|
|
21
|
-
const trimmed = publicKey
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
const trimmed = stripNostrUriPrefix(publicKey);
|
|
31
|
+
const lowered = trimmed.toLowerCase();
|
|
32
|
+
if (lowered.startsWith('npub1')) {
|
|
33
|
+
const decoded = nip19.decode(lowered);
|
|
24
34
|
if (decoded.type !== 'npub') {
|
|
25
35
|
throw new KeyFormatError('Invalid npub public key');
|
|
26
36
|
}
|
|
27
37
|
return decoded.data;
|
|
28
38
|
}
|
|
29
|
-
|
|
39
|
+
const hexCandidate = lowered.startsWith('0x') ? lowered.slice(2) : lowered;
|
|
40
|
+
if (!/^[0-9a-f]{64}$/.test(hexCandidate)) {
|
|
30
41
|
throw new KeyFormatError('Public key must be a 32-byte hex string or npub');
|
|
31
42
|
}
|
|
32
|
-
return
|
|
43
|
+
return hexCandidate;
|
|
33
44
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nekosuneprojects/vector-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Node.js reimplementation of the Vector Bot SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -35,11 +35,13 @@
|
|
|
35
35
|
"form-data": "^4.0.5",
|
|
36
36
|
"mime-types": "^3.0.2",
|
|
37
37
|
"node-fetch": "^3.3.1",
|
|
38
|
-
"nostr-tools": "^2.19.4"
|
|
38
|
+
"nostr-tools": "^2.19.4",
|
|
39
|
+
"ws": "^8.18.3"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
42
|
"@types/mime-types": "^2.1.4",
|
|
42
43
|
"@types/node": "^20.7.0",
|
|
44
|
+
"@types/ws": "^8.18.1",
|
|
43
45
|
"typescript": "^5.5.2"
|
|
44
46
|
}
|
|
45
47
|
}
|