Skip to content

Instantly share code, notes, and snippets.

@starbackr-dev
Last active June 22, 2023 01:37
Show Gist options
  • Save starbackr-dev/b753e9c1c28fc62a3356960d02a7e3a3 to your computer and use it in GitHub Desktop.
Save starbackr-dev/b753e9c1c28fc62a3356960d02a7e3a3 to your computer and use it in GitHub Desktop.
const {WebSocket} = require('websocket-polyfill');
const {relayInit,
getEventHash,
getPublicKey,
verifySignature,
signEvent,
generatePrivateKey} = require('nostr-tools');
const https = require('https');
//********* Constants **********************************************************************
const regUserPrivateKey = 'c776822b744112daeb279a7616650d87124df3c04fc16d3a08a4e3a68f7042d3';
const newUserPrivateKey = generatePrivateKey();
const relay_url = 'wss://spool.chat';
const relay_pubkey = '805efff537b6376991cae73a0b0f605d0aa594b4518fbcca4f6ebb74404363e2';
const groupSlug = '/nostrdevs-gpUNoQ7CLjQ';
//*******************************************************************************************
let connectStatus = false;
let relay = relayInit(relay_url);
let groupSlug1= groupSlug; //groupSlug + '-' + makeid(12);
let subgroupSlug = groupSlug1+ '/subgroup';
//1. Create a group
const createGroup = async () => {
return new Promise((resolve, reject) => {
console.log('\x1b[33m 1. create a group with name and confirm relay is creating the group and verify the event generated by the relay: \x1b[0m', groupSlug1 );
let postevent = {
kind: 9000,
tags: [['g', groupSlug1],
['action', 'name', 'This is a super shadowy group'],
['action', 'picture', 'https://i.current.fyi/npub1current/profile/current.png'],
],
content: 'Test group ' + groupSlug1
};
postGroupEventToRelay(postevent,regUserPrivateKey).then((result) => {resolve(true)});
});
}
//2. Post message to the group
const postMessageToGroup = async () => {
return new Promise((resolve, reject) => {
console.log('\x1b[33m 2. Post a message to relay and confirm relay is allowing the user to post messages to the group: \x1b[0m', groupSlug1 );
let postevent = {
kind: 9,
tags: [['g', groupSlug1]],
content: 'I am posting my message to the group: ' + groupSlug1
};
postGroupEventToRelay(postevent,regUserPrivateKey).then((result) => {resolve(true)});
});
}
//3. New user joins the group
const newUserJoinsGroup = async () => {
return new Promise((resolve, reject) => {
console.log('\x1b[33m 3. New user joining the group \x1b[0m', groupSlug1 );
let postevent = {
kind: 9000,
tags: [['g', groupSlug1],
['action', 'add', getPublicKey(newUserPrivateKey), 'user'],
],
content: 'This is content'
};
postGroupEventToRelay(postevent, newUserPrivateKey).then((result) => {resolve(true)});
});
}
//4. Post message as new user to the group
const postMessageAsNewUserToGroup = async () => {
return new Promise((resolve, reject) => {
console.log('\x1b[33m 4. Post a message to relay and confirm relay is allowing the user to post messages to the group: \x1b[0m', groupSlug1 );
let postevent = {
kind: 9,
tags: [['g', groupSlug1]],
content: 'Hello from new user: ' + groupSlug1
};
postGroupEventToRelay(postevent, newUserPrivateKey).then((result) => {resolve(true)});
});
}
//5. New user leaves the group
const newUserLeaveGroup = async () => {
return new Promise((resolve, reject) => {
console.log('\x1b[33m 5. New user leaving the group \x1b[0m', groupSlug1 );
let postevent = {
kind: 9000,
tags: [['g', groupSlug1],
['action', 'remove', getPublicKey(newUserPrivateKey), 'user'],
],
content: 'this is content'
};
postGroupEventToRelay(postevent, newUserPrivateKey).then((result) => {resolve(true)});
});
}
//6. Create a Sub group
const createSubGroup = async () => {
return new Promise((resolve, reject) => {
console.log('\x1b[33m 6. create a sub group with name and confirm relay is creating the group and verify the event generated by the relay: \x1b[0m ', subgroupSlug );
let postevent = {
kind: 9000,
tags: [
['g', subgroupSlug],
['action', 'name', 'This is a super shadowy sub group'],
['action', 'picture', 'https://i.current.fyi/npub1current/profile/current.png'],
],
content: 'Creating subgroup ' + subgroupSlug
};
postGroupEventToRelay(postevent,regUserPrivateKey).then((result) => {resolve(true)});
});
}
//7. Post message to the sub group
const postMessageToSubGroup = async () => {
return new Promise((resolve, reject) => {
console.log('\x1b[33m 7. Post a message to subgroup and confirm relay is allowing the user to post messages to the subgroup: \x1b[0m', groupSlug1 );
let postevent = {
kind: 9,
tags: [['g', subgroupSlug]],
content: 'I am posting my message to the subgroup: ' + subgroupSlug
};
postGroupEventToRelay(postevent,regUserPrivateKey).then((result) => {resolve(true)});
});
}
//8. Admin adds a user to the group
const adminAddsUserGroup = async () => {
return new Promise((resolve, reject) => {
console.log('\x1b[33m 8. Group admin adds an user to the group: \x1b[0m', groupSlug1 );
let postevent = {
kind: 9000,
tags: [['g', groupSlug1],
['action', 'add', getPublicKey(newUserPrivateKey), 'user']
],
content: 'Adding user to the group ' + groupSlug1
};
postGroupEventToRelay(postevent,regUserPrivateKey).then((result) => {resolve(true)});
});
}
//9. Admin removes a user to the group
const adminRemovesUserGroup = async () => {
return new Promise((resolve, reject) => {
console.log('\x1b[33m 9. Group admin adds an user to the group: \x1b[0m', groupSlug1 );
let postevent = {
kind: 9000,
tags: [['g', groupSlug1],
['action', 'remove', getPublicKey(newUserPrivateKey), 'user']
],
content: 'Removing user to the group ' + groupSlug1
};
postGroupEventToRelay(postevent,regUserPrivateKey).then((result) => {resolve(true)});
});
}
//10. User tries to message the group but fails since removed by the admin
const userMessageFailGroup = async () => {
return new Promise((resolve, reject) => {
console.log('\x1b[33m 10. User tries to message the group but fails since removed by the admin \x1b[0m', groupSlug1 );
let postevent = {
kind: 9,
tags: [['g', groupSlug1]],
content: 'Hello from new user again: ' + groupSlug1
};
postGroupEventToRelay(postevent, newUserPrivateKey).then((result) => {resolve(true)});
});
}
//11. Get all subscribed groups for a pubkey
const get39004Event = async (relay) => {
return new Promise((resolve, reject) => {
console.log('\x1b[33m 11. Get all subscribed groups for a pubkey \x1b[0m', getPublicKey(regUserPrivateKey) );
let sub = relay.sub([
{
limit: 1,
kinds: [39004],
'#p': [getPublicKey(regUserPrivateKey)],
}
])
sub.on('event', event => {
console.log('event: ', event);
})
sub.on('eose', () => {
resolve(true);
})
});
}
//12. Get all messages for a group '/nostrdevs-oOXekJwokRSd'
const getMessagesForGroup = async (relay) => {
return new Promise((resolve, reject) => {
console.log('\x1b[33m 12. Get all messages for a group /nostrdevs-oOXekJwokRSd \x1b[0m', getPublicKey(regUserPrivateKey) );
let sub = relay.sub([
{
limit: 100,
kinds: [9],
'#g': ['/nostrdevs-oOXekJwokRSd'],
}
])
sub.on('event', event => {
//console.log('event: ', event);
if (event.kind === 9) console.log('kind 9 event content: ', event.content);
})
sub.on('eose', () => {
resolve(true);
})
});
}
const connectToRelay = (relay) => {
return new Promise((resolve, reject) => {
relay.connect();
relay.on('connect', () => {
console.log(`connected to ${relay.url}`)
resolve(true);
})
relay.on('error', () => {
console.log(`failed to connect to ${relay.url}`)
reject(false);
})
relay.on('notice', (msg) => {
console.log('notice: ', msg);
})
});
}
const postGroupEventToRelay = (postevent, privateKey) => {
return new Promise((resolve, reject) => {
(async () => {
postevent.created_at= Math.floor(Date.now() / 1000),
postevent.pubkey = getPublicKey(privateKey);
postevent.id = await getEventHash(postevent);
postevent.sig = await signEvent(postevent, privateKey);
const ready = await verifySignature(postevent);
let pub = await relay.publish(postevent);
pub.on('ok', () => {
console.log(`${relay.url} has accepted our event`)
resolve(true);
})
pub.on('failed', reason => {
console.log(`failed to publish to ${relay.url}: ${reason}`)
resolve(false);
})
})()
});
}
const subscribeGroupEvents = () => {
return new Promise((resolve, reject) => {
let sub = relay.sub([
{
limit: 0,
kinds: [39000, 39001, 39003, 39004],
//'#g': ['/no-bitcoin-talk'],
}
])
sub.on('event', event => {
//console.log('event: ', event);
console.log('Event with kind ' + event.kind + ' received. Signature verfication is ' + verifySignature(event));
if (event.pubkey === relay_pubkey) console.log('Relay pubkey matched with event');
if (event.kind === 9) console.log('kind 9 event content: ', event.content);
if (event.kind === 39000) console.log('kind 39000 tags: ', event.tags);
if (event.kind === 39001) console.log('kind 39001 p tag is: ', event.tags);
})
sub.on('eose', () => {
resolve(true);
})
});
}
function makeid(length) {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
let counter = 0;
while (counter < length) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
counter += 1;
}
return result;
}
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function run() {
console.log('Relay URL: ', relay_url);
console.log('Relay pubkey: ', relay_pubkey);
console.log('Registered user pubkey: ', getPublicKey(regUserPrivateKey));
console.log('New user pubkey: ', getPublicKey(newUserPrivateKey));
connectStatus = await connectToRelay(relay);
if (connectStatus) await subscribeGroupEvents();
if (connectStatus) await createGroup(); //1
if (connectStatus) await postMessageToGroup(); //2
await sleep(5000);
if (connectStatus) await newUserJoinsGroup(); //3
if (connectStatus) await postMessageAsNewUserToGroup(); //4
if (connectStatus) await newUserLeaveGroup(); //5
await sleep(5000);
if (connectStatus) await createSubGroup(); //6
if (connectStatus) await postMessageToSubGroup(); //7
await sleep(5000);
if (connectStatus) await adminAddsUserGroup() //8
if (connectStatus) await adminRemovesUserGroup() //9
if (connectStatus) await userMessageFailGroup() //10
if (connectStatus) await get39002Event(relay) //11
if (connectStatus) await getMessagesForGroup(relay) //12
if (connectStatus) await newUserJoinsGroup(); //3
if (connectStatus) await postMessageAsNewUserToGroup(); //4
if (connectStatus) await newUserLeaveGroup(); //5
}
run().catch(console.log);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment