Adding DIrect Messaging functionality to the API
This commit is contained in:
parent
d6081ddd28
commit
096497db03
105
src/index.js
105
src/index.js
|
@ -6,13 +6,19 @@ const POW_TIME = 1;
|
||||||
const TTL = 10;
|
const TTL = 10;
|
||||||
const POW_TARGET = 0.002;
|
const POW_TARGET = 0.002;
|
||||||
|
|
||||||
function createStatusPayload(msg, isJson) {
|
const GROUP_MESSAGE = "~:public-group-user-message";
|
||||||
let tag = '~#c4';
|
const USER_MESSAGE = "~:user-message";
|
||||||
let content = msg;
|
|
||||||
let messageType = '~:public-group-user-message';
|
const CONTACT_DISCOVERY_TOPIC = '0xf8946aac';
|
||||||
let clockValue = (new Date().getTime()) * 100;
|
|
||||||
let contentType = (isJson ? 'content/json' : 'text/plain');
|
const CONTACT_CODE_REGEXP = /^(0x)?[0-9a-f]{130}$/i;
|
||||||
let timestamp = new Date().getTime();
|
|
||||||
|
function createStatusPayload(content, messageType, isJson) {
|
||||||
|
const tag = '~#c4';
|
||||||
|
const clockValue = (new Date().getTime()) * 100;
|
||||||
|
const contentType = (isJson ? 'content/json' : 'text/plain');
|
||||||
|
const timestamp = new Date().getTime();
|
||||||
|
|
||||||
return asciiToHex(
|
return asciiToHex(
|
||||||
JSON.stringify([
|
JSON.stringify([
|
||||||
tag,
|
tag,
|
||||||
|
@ -25,6 +31,8 @@ class StatusJS {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.channels = {};
|
this.channels = {};
|
||||||
|
this.contacts = {};
|
||||||
|
this.userMessagesSubscription = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async connect(url) {
|
async connect(url) {
|
||||||
|
@ -35,6 +43,16 @@ class StatusJS {
|
||||||
this.sig = await web3.shh.newKeyPair();
|
this.sig = await web3.shh.newKeyPair();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getPublicKey(){
|
||||||
|
const pubKey = await this.shh.getPublicKey(this.sig);
|
||||||
|
return pubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getUserName(){
|
||||||
|
const pubKey = await this.getPublicKey();
|
||||||
|
return utils.generateUsernameFromSeed(pubKey);
|
||||||
|
}
|
||||||
|
|
||||||
async joinChat(channelName, cb) {
|
async joinChat(channelName, cb) {
|
||||||
let channelKey = await this.shh.generateSymKeyFromPassword(channelName);
|
let channelKey = await this.shh.generateSymKeyFromPassword(channelName);
|
||||||
this.channels[channelName] = {
|
this.channels[channelName] = {
|
||||||
|
@ -45,19 +63,39 @@ class StatusJS {
|
||||||
if (cb) cb();
|
if (cb) cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async addContact(contactCode, cb) {
|
||||||
|
this.contacts[contactCode] = {
|
||||||
|
'username': utils.generateUsernameFromSeed(contactCode)
|
||||||
|
}
|
||||||
|
if (cb) cb();
|
||||||
|
}
|
||||||
|
|
||||||
leaveChat(channelName) {
|
leaveChat(channelName) {
|
||||||
this.channels[channelName].unsubscribe();
|
this.channels[channelName].subscription.unsubscribe();
|
||||||
delete this.channels[channelName];
|
delete this.channels[channelName];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async removeContact(contactCode, cb) {
|
||||||
|
delete this.contacts[contactCode];
|
||||||
|
}
|
||||||
|
|
||||||
isSubscribedTo(channelName) {
|
isSubscribedTo(channelName) {
|
||||||
return !!this.channels[channelName];
|
return !!this.channels[channelName];
|
||||||
}
|
}
|
||||||
|
|
||||||
onMessage(channelName, cb) {
|
onMessage(par1, par2) {
|
||||||
|
if(typeof par1 === "function"){
|
||||||
|
this.onUserMessage(par1);
|
||||||
|
} else {
|
||||||
|
this.onChannelMessage(par1, par2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onChannelMessage(channelName, cb) {
|
||||||
if (!this.channels[channelName]) {
|
if (!this.channels[channelName]) {
|
||||||
return cb("unknown channel: " + channelName);
|
return cb("unknown channel: " + channelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.channels[channelName].subscription = this.shh.subscribe("messages", {
|
this.channels[channelName].subscription = this.shh.subscribe("messages", {
|
||||||
minPow: POW_TARGET,
|
minPow: POW_TARGET,
|
||||||
symKeyID: this.channels[channelName].channelKey,
|
symKeyID: this.channels[channelName].channelKey,
|
||||||
|
@ -70,16 +108,51 @@ class StatusJS {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(channelName, msg, cb) {
|
onUserMessage(cb) {
|
||||||
|
this.userMessagesSubscription = this.shh.subscribe("messages", {
|
||||||
|
minPow: POW_TARGET,
|
||||||
|
privateKeyID: this.sig,
|
||||||
|
topics: [CONTACT_DISCOVERY_TOPIC]
|
||||||
|
}).on('data', (data) => {
|
||||||
|
let username = utils.generateUsernameFromSeed(data.sig);
|
||||||
|
if(!this.contacts[data.sig]) this.contacts[data.sig] = {};
|
||||||
|
this.contacts[data.sig].username = username;
|
||||||
|
cb(null, {payload: hexToAscii(data.payload), data: data, username: username});
|
||||||
|
}).on('error', (err) => {
|
||||||
|
cb(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sendUserMessage(contactCode, msg, cb) {
|
||||||
|
this.shh.post({
|
||||||
|
pubKey: contactCode,
|
||||||
|
sig: this.sig,
|
||||||
|
ttl: TTL,
|
||||||
|
topic: CONTACT_DISCOVERY_TOPIC,
|
||||||
|
payload: createStatusPayload(msg, USER_MESSAGE),
|
||||||
|
powTime: POW_TIME,
|
||||||
|
powTarget: POW_TARGET
|
||||||
|
}).then(() => {
|
||||||
|
if (!cb) return;
|
||||||
|
cb(null, true);
|
||||||
|
}).catch((e) => {
|
||||||
|
if (!cb) return;
|
||||||
|
cb(e, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sendGroupMessage(channelName, msg, cb) {
|
||||||
if (!this.channels[channelName]) {
|
if (!this.channels[channelName]) {
|
||||||
|
if(!cb) return;
|
||||||
return cb("unknown channel: " + channelName);
|
return cb("unknown channel: " + channelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.shh.post({
|
this.shh.post({
|
||||||
symKeyID: this.channels[channelName].channelKey,
|
symKeyID: this.channels[channelName].channelKey,
|
||||||
sig: this.sig,
|
sig: this.sig,
|
||||||
ttl: TTL,
|
ttl: TTL,
|
||||||
topic: this.channels[channelName].channelCode,
|
topic: this.channels[channelName].channelCode,
|
||||||
payload: createStatusPayload(msg),
|
payload: createStatusPayload(msg, GROUP_MESSAGE),
|
||||||
powTime: POW_TIME,
|
powTime: POW_TIME,
|
||||||
powTarget: POW_TARGET
|
powTarget: POW_TARGET
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
@ -100,7 +173,7 @@ class StatusJS {
|
||||||
sig: this.sig,
|
sig: this.sig,
|
||||||
ttl: TTL,
|
ttl: TTL,
|
||||||
topic: this.channels[channelName].channelCode,
|
topic: this.channels[channelName].channelCode,
|
||||||
payload: createStatusPayload(JSON.stringify(msg), true),
|
payload: createStatusPayload(JSON.stringify(msg), GROUP_MESSAGE, true),
|
||||||
powTime: POW_TIME,
|
powTime: POW_TIME,
|
||||||
powTarget: POW_TARGET
|
powTarget: POW_TARGET
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
@ -112,6 +185,14 @@ class StatusJS {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendMessage(destination, msg, cb){
|
||||||
|
if (CONTACT_CODE_REGEXP.test(destination)) {
|
||||||
|
this.sendUserMessage(destination, msg, cb);
|
||||||
|
} else {
|
||||||
|
this.sendGroupMessage(destination, msg, cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = StatusJS;
|
module.exports = StatusJS;
|
||||||
|
|
2
test.js
2
test.js
|
@ -2,7 +2,7 @@ var StatusJS = require('./src/index.js');
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
var status = new StatusJS();
|
var status = new StatusJS();
|
||||||
status.connect("ws://localhost:8546");
|
await status.connect("ws://localhost:8546");
|
||||||
|
|
||||||
await status.joinChat("mytest");
|
await status.joinChat("mytest");
|
||||||
await status.joinChat("mytest2");
|
await status.joinChat("mytest2");
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
const StatusJS = require('./src/index.js');
|
||||||
|
const Web3 = require('web3');
|
||||||
|
const { utils: { asciiToHex, hexToAscii } } = Web3;
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
let status1 = new StatusJS();
|
||||||
|
await status1.connect("ws://localhost:8546");
|
||||||
|
|
||||||
|
let status2 = new StatusJS();
|
||||||
|
await status2.connect("ws://localhost:8546");
|
||||||
|
|
||||||
|
|
||||||
|
const user1pubKey = await status1.getPublicKey();
|
||||||
|
const user2pubKey = await status2.getPublicKey();
|
||||||
|
|
||||||
|
console.log("user1 (" + await status1.getUserName() + "):\n" + user1pubKey);
|
||||||
|
console.log("user2 (" + await status2.getUserName() + "):\n" + user2pubKey);
|
||||||
|
console.log("\n")
|
||||||
|
|
||||||
|
|
||||||
|
const receivedMessageCb = (username) => (err, data) => {
|
||||||
|
console.log( username + " received a message from " + data.username);
|
||||||
|
console.log(data.data.sig);
|
||||||
|
console.log(data.payload)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
status1.onMessage(receivedMessageCb('user1'));
|
||||||
|
status2.onMessage(receivedMessageCb('user2'));
|
||||||
|
|
||||||
|
status1.addContact(user2pubKey);
|
||||||
|
status1.sendMessage(user2pubKey, "hello user2!");
|
||||||
|
|
||||||
|
status2.sendMessage(user1pubKey, "hello user1!");
|
||||||
|
|
||||||
|
|
||||||
|
// Text someone at status
|
||||||
|
//status1.sendMessage("0xcontact_code_here", "hello!");
|
||||||
|
|
||||||
|
|
||||||
|
})()
|
Loading…
Reference in New Issue