Compare commits
2 commits
444156138b
...
5ae62595b4
Author | SHA1 | Date | |
---|---|---|---|
5ae62595b4 | |||
7db24166a0 |
8 changed files with 790 additions and 17 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -174,3 +174,5 @@ dist
|
||||||
# Finder (MacOS) folder config
|
# Finder (MacOS) folder config
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.asc
|
*.asc
|
||||||
|
*.key
|
||||||
|
ssh_keys
|
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
1
host.key.pub
Normal file
1
host.key.pub
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOrBXBiOtqX7YEOyLCMag2XFc8unduCPDI3q/pIYBqMD neon@leon
|
11
package.json
11
package.json
|
@ -1,15 +1,20 @@
|
||||||
{
|
{
|
||||||
"name": "nest-pgp-chat",
|
"name": "nest-pgp-chat",
|
||||||
"module": "src/index.ts",
|
"module": "src/index.ts",
|
||||||
"type": "module",
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "latest"
|
"@types/bun": "latest",
|
||||||
|
"ts-node": "^10.9.2",
|
||||||
|
"typescript": "^5.6.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"blessed": "^0.1.81",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"openpgp": "^5.11.2"
|
"nodemailer": "^6.9.15",
|
||||||
|
"nodemailer-direct-transport": "^3.3.2",
|
||||||
|
"openpgp": "^5.11.2",
|
||||||
|
"ssh2": "^1.15.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,7 +6,7 @@ import openpgp from 'openpgp'
|
||||||
const { privateKey, publicKey } = await openpgp.generateKey({
|
const { privateKey, publicKey } = await openpgp.generateKey({
|
||||||
type: 'rsa', // Type of the key
|
type: 'rsa', // Type of the key
|
||||||
rsaBits: 2048, // RSA key size (defaults to 4096 bits)
|
rsaBits: 2048, // RSA key size (defaults to 4096 bits)
|
||||||
userIDs: [{ name: 'Jon Smith', email: 'jon@example.com' }], // you can pass multiple user IDs
|
userIDs: [{ name: 'Server', email: 'neon+pgp_server__temp@hackclub.app' }], // you can pass multiple user IDs
|
||||||
format: 'object',
|
format: 'object',
|
||||||
passphrase: 'super long and hard to guess secret' // protects the private key
|
passphrase: 'super long and hard to guess secret' // protects the private key
|
||||||
});
|
});
|
||||||
|
@ -68,6 +68,7 @@ const Config = {
|
||||||
"server": {
|
"server": {
|
||||||
// nests ram COULD not handle more then 20 sadly
|
// nests ram COULD not handle more then 20 sadly
|
||||||
"maxConnections": 20,
|
"maxConnections": 20,
|
||||||
|
"noInputTimeout": 55_000 ,
|
||||||
"host": "127.0.0.1",
|
"host": "127.0.0.1",
|
||||||
"port": process.env.PORT
|
"port": process.env.PORT
|
||||||
},
|
},
|
||||||
|
@ -75,7 +76,7 @@ const Config = {
|
||||||
"messageLength": 150,
|
"messageLength": 150,
|
||||||
"messages": {
|
"messages": {
|
||||||
"welcome": "Welcome to chat server. Press CTRL+C to leave.\n(note: pgp key name will be used in server. extra metadata such as [email, pgp key id] can be found via whois cmd)",
|
"welcome": "Welcome to chat server. Press CTRL+C to leave.\n(note: pgp key name will be used in server. extra metadata such as [email, pgp key id] can be found via whois cmd)",
|
||||||
"nickname": "Enter your public PGP key (in base64, in one line): ",
|
"nickname": "Enter your public PGP key (in base64, in one line once done write in a new line 'ENDKEY'): ",
|
||||||
"logout": "%s has left the chat",
|
"logout": "%s has left the chat",
|
||||||
"login": "%s has joined the chat",
|
"login": "%s has joined the chat",
|
||||||
"not_allowed": "You may only connect from the nest server. This is not a public server."
|
"not_allowed": "You may only connect from the nest server. This is not a public server."
|
||||||
|
@ -85,9 +86,20 @@ const Config = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Messages = Config.chat.messages;
|
const Messages = Config.chat.messages;
|
||||||
|
// to prevent my ram from being disposed
|
||||||
|
const all_connections = [];
|
||||||
const clients = [];
|
const clients = [];
|
||||||
|
setInterval(() => {
|
||||||
|
all_connections.forEach(client => {
|
||||||
|
try {
|
||||||
|
if(Date.now() - client.lastInput >= 0) {
|
||||||
|
client.end(`Timed out`)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e.message, 'e')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, Config.server.noInputTimeout)
|
||||||
const messageListener = fn => data => {
|
const messageListener = fn => data => {
|
||||||
console.log('Received data', data, data.toString());
|
console.log('Received data', data, data.toString());
|
||||||
|
|
||||||
|
@ -152,11 +164,16 @@ function askNickname(socket) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const onData = messageListener(data => {
|
const onData = messageListener(data => {
|
||||||
str += data.toString()
|
if(data.toString().includes('ENDKEY')) {
|
||||||
if (!data.length) return ask();
|
socket.off('data', onData)
|
||||||
if(!data.toString().includes('END PGP PUBLIC KEY')) return ask()
|
resolve(str);
|
||||||
socket.off('data', onData)
|
} else {
|
||||||
resolve(str);
|
str += data.toString()
|
||||||
|
if (!data.length) return ask();
|
||||||
|
if(!data.toString().includes('ENDKEY')) return ask()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ask();
|
ask();
|
||||||
|
@ -165,6 +182,7 @@ if(!data.toString().includes('END PGP PUBLIC KEY')) return ask()
|
||||||
|
|
||||||
function createServer() {
|
function createServer() {
|
||||||
const server = net.createServer(async socket => {
|
const server = net.createServer(async socket => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log(socket.remoteAddress)
|
console.log(socket.remoteAddress)
|
||||||
if(![`::1`].includes(socket.remoteAddress.trim())) {
|
if(![`::1`].includes(socket.remoteAddress.trim())) {
|
||||||
|
@ -172,6 +190,13 @@ function createServer() {
|
||||||
socket.end(`Bye`)
|
socket.end(`Bye`)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
socket.on('data', () => {
|
||||||
|
//@ts-ignore
|
||||||
|
all_connections[all_connections.indexOf(socket)].lastInput = Date.now()
|
||||||
|
})
|
||||||
|
//@ts-ignore
|
||||||
|
socket.lastInput = Date.now()
|
||||||
|
all_connections.push(socket)
|
||||||
console.log(`Connection from ${socket.remoteAddress}`);
|
console.log(`Connection from ${socket.remoteAddress}`);
|
||||||
|
|
||||||
sendMessageLn(socket, null, Messages.welcome);
|
sendMessageLn(socket, null, Messages.welcome);
|
||||||
|
@ -182,10 +207,10 @@ function createServer() {
|
||||||
console.debug(`$afternic`)
|
console.debug(`$afternic`)
|
||||||
let pgp_key=null, nickname= null;
|
let pgp_key=null, nickname= null;
|
||||||
try {
|
try {
|
||||||
console.log(raw_pgp_data)
|
// console.log(raw_pgp_data)
|
||||||
// console.log(Buffer.from(raw_pgp_data as string, 'base64').toString())
|
console.log(Buffer.from(raw_pgp_data as string, 'base64').toString(), Buffer.from(raw_pgp_data as string, 'base64').toString().length)
|
||||||
pgp_key = await openpgp.readKey({
|
pgp_key = await openpgp.readKey({
|
||||||
armoredKey: raw_pgp_data as string,
|
armoredKey: Buffer.from(raw_pgp_data as string, 'base64').toString(),
|
||||||
})
|
})
|
||||||
// .then(d=>d.users[0])
|
// .then(d=>d.users[0])
|
||||||
console.log(pgp_key.users[0])
|
console.log(pgp_key.users[0])
|
396
src/index.js
Normal file
396
src/index.js
Normal file
|
@ -0,0 +1,396 @@
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const openpgp = require('openpgp')
|
||||||
|
const path = require('path')
|
||||||
|
const { readFileSync } = fs
|
||||||
|
const blessed = require('blessed');
|
||||||
|
const { utils: { parseKey }, Server } = require('ssh2');
|
||||||
|
const RE_SPECIAL =
|
||||||
|
// eslint-disable-next-line no-control-regex
|
||||||
|
/[\x00-\x1F\x7F]+|(?:\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K])/g;
|
||||||
|
const MAX_MSG_LEN = 128;
|
||||||
|
const MAX_NAME_LEN = 10;
|
||||||
|
const PROMPT_NAME = `Enter a nickname to use (max ${MAX_NAME_LEN} chars): `;
|
||||||
|
|
||||||
|
const users = [];
|
||||||
|
|
||||||
|
function formatMessage(msg, output) {
|
||||||
|
output.parseTags = true;
|
||||||
|
msg = output._parseTags(msg);
|
||||||
|
output.parseTags = false;
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
function userBroadcast(msg, source) {
|
||||||
|
const sourceMsg = `> ${msg}`;
|
||||||
|
const name = `{cyan-fg}{bold}${source.name}{/}`;
|
||||||
|
msg = `: ${msg}`;
|
||||||
|
for (const user of users) {
|
||||||
|
const output = user.output;
|
||||||
|
if (source === user)
|
||||||
|
output.add(sourceMsg);
|
||||||
|
else
|
||||||
|
output.add(formatMessage(name, output) + msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function localMessage(msg, source) {
|
||||||
|
const output = source.output;
|
||||||
|
output.add(formatMessage(msg, output));
|
||||||
|
}
|
||||||
|
function noop(v) {}
|
||||||
|
let known_keys = require('fs').readdirSync('./ssh_keys').map(dir => {
|
||||||
|
const files = fs.readdirSync(path.join(__dirname, 'ssh_keys', dir))
|
||||||
|
return {
|
||||||
|
parsedKey: parseKey(fs.readFileSync(files.find(f => f.endsWith('.sshkey')))),
|
||||||
|
armoredGPGKey: fs.readFileSync(files.find(f => f.endsWith('.asc')))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
new Server({
|
||||||
|
hostKeys: [readFileSync('host.key')],
|
||||||
|
}, (client) => {
|
||||||
|
let stream;
|
||||||
|
let name;
|
||||||
|
|
||||||
|
// client.on('authentication', (ctx) => {
|
||||||
|
// console.log(ctx, ctx.key, ctx.method)
|
||||||
|
// let nick = ctx.username;
|
||||||
|
// let prompt = PROMPT_NAME;
|
||||||
|
// let lowered;
|
||||||
|
|
||||||
|
// // Try to use username as nickname
|
||||||
|
// if (nick.length > 0 && nick.length <= MAX_NAME_LEN) {
|
||||||
|
// lowered = nick.toLowerCase();
|
||||||
|
// let ok = true;
|
||||||
|
// for (const user of users) {
|
||||||
|
// if (user.name.toLowerCase() === lowered) {
|
||||||
|
// ok = false;
|
||||||
|
// prompt = `That nickname is already in use.\n${PROMPT_NAME}`;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (ok) {
|
||||||
|
// name = nick;
|
||||||
|
// return ctx.accept();
|
||||||
|
// }
|
||||||
|
// } else if (nick.length === 0) {
|
||||||
|
// prompt = 'A nickname is required.\n' + PROMPT_NAME;
|
||||||
|
// } else {
|
||||||
|
// prompt = 'That nickname is too long.\n' + PROMPT_NAME;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (ctx.method !== 'keyboard-interactive')
|
||||||
|
// return ctx.reject(['keyboard-interactive']);
|
||||||
|
|
||||||
|
// ctx.prompt(prompt, function retryPrompt(answers) {
|
||||||
|
// if (answers.length === 0)
|
||||||
|
// return ctx.reject(['keyboard-interactive']);
|
||||||
|
// nick = answers[0];
|
||||||
|
// if (nick.length > MAX_NAME_LEN) {
|
||||||
|
// return ctx.prompt(`That nickname is too long.\n${PROMPT_NAME}`,
|
||||||
|
// retryPrompt);
|
||||||
|
// } else if (nick.length === 0) {
|
||||||
|
// return ctx.prompt(`A nickname is required.\n${PROMPT_NAME}`,
|
||||||
|
// retryPrompt);
|
||||||
|
// }
|
||||||
|
// lowered = nick.toLowerCase();
|
||||||
|
// for (const user of users) {
|
||||||
|
// if (user.name.toLowerCase() === lowered) {
|
||||||
|
// return ctx.prompt(`That nickname is already in use.\n${PROMPT_NAME}`,
|
||||||
|
// retryPrompt);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// name = nick;
|
||||||
|
// ctx.accept();
|
||||||
|
// });
|
||||||
|
// })
|
||||||
|
let username = null;
|
||||||
|
let reject_on_connect = false;
|
||||||
|
client.on('authentication', (ctx) => {
|
||||||
|
let allowed = false;
|
||||||
|
username = ctx.username;
|
||||||
|
if (ctx.username == "gimmie-key") {
|
||||||
|
allowed = true;
|
||||||
|
ctx.accept();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ctx.method) {
|
||||||
|
case 'password':
|
||||||
|
// console.log('Not passwor')
|
||||||
|
ctx.reject();
|
||||||
|
break;
|
||||||
|
case 'publickey':
|
||||||
|
console.log(`pubkey`)
|
||||||
|
// let is_allowed =
|
||||||
|
// console.log(ctx.key.data.toString())
|
||||||
|
known_keys.forEach((info) => {
|
||||||
|
let allowedPubKey = info.parsedKey
|
||||||
|
if (ctx.key.algo !== allowedPubKey.type
|
||||||
|
|| !checkValue(ctx.key.data, allowedPubKey.getPublicSSH())
|
||||||
|
|| (ctx.signature && allowedPubKey.verify(ctx.blob, ctx.signature, ctx.hashAlgo) !== true)) {
|
||||||
|
// do nothing;
|
||||||
|
} else {
|
||||||
|
allowed = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ctx.reject();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowed)
|
||||||
|
ctx.accept();
|
||||||
|
else {
|
||||||
|
console.error(`no`, ctx.prompt)
|
||||||
|
// ctx.prompt(`Your ssh key was not found/provided please add by sshing with the username gimmie-key`, () => {
|
||||||
|
// ctx.reject();
|
||||||
|
// })
|
||||||
|
reject_on_connect = true;
|
||||||
|
ctx.accept()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('ready', () => {
|
||||||
|
let rows;
|
||||||
|
let cols;
|
||||||
|
let term;
|
||||||
|
|
||||||
|
client.once('session', (accept, reject) => {
|
||||||
|
accept().once('pty', (accept, reject, info) => {
|
||||||
|
rows = info.rows;
|
||||||
|
cols = info.cols;
|
||||||
|
term = info.term;
|
||||||
|
accept && accept();
|
||||||
|
}).on('window-change', (accept, reject, info) => {
|
||||||
|
rows = info.rows;
|
||||||
|
cols = info.cols;
|
||||||
|
if (stream) {
|
||||||
|
stream.rows = rows;
|
||||||
|
stream.columns = cols;
|
||||||
|
stream.emit('resize');
|
||||||
|
}
|
||||||
|
accept && accept();
|
||||||
|
}).once('shell', (accept, reject) => {
|
||||||
|
stream = accept();
|
||||||
|
stream.name = name;
|
||||||
|
stream.rows = rows || 24;
|
||||||
|
stream.columns = cols || 80;
|
||||||
|
stream.isTTY = true;
|
||||||
|
stream.setRawMode = noop;
|
||||||
|
stream.on('error', noop);
|
||||||
|
if(reject_on_connect) {
|
||||||
|
stream.write("Your ssh key was not found/provided please add by sshing with the username gimmie-key`\n")
|
||||||
|
stream.end()
|
||||||
|
}
|
||||||
|
if(username == 'gimmie-key') {
|
||||||
|
const screen = new blessed.screen({
|
||||||
|
autoPadding: true,
|
||||||
|
smartCSR: true,
|
||||||
|
program: new blessed.program({
|
||||||
|
input: stream,
|
||||||
|
output: stream
|
||||||
|
}),
|
||||||
|
terminal: term || 'ansi'
|
||||||
|
});
|
||||||
|
const output = stream.output = new blessed.log({
|
||||||
|
screen: screen,
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
bottom: 2,
|
||||||
|
scrollOnInput: true
|
||||||
|
});
|
||||||
|
screen.append(output);
|
||||||
|
|
||||||
|
screen.append(new blessed.box({
|
||||||
|
screen: screen,
|
||||||
|
height: 1,
|
||||||
|
bottom: 3,
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
type: 'line',
|
||||||
|
ch: '='
|
||||||
|
}));
|
||||||
|
|
||||||
|
const input = new blessed.textarea({
|
||||||
|
screen: screen,
|
||||||
|
bottom: 0,
|
||||||
|
height: 3,
|
||||||
|
width: '100%',
|
||||||
|
inputOnFocus: true
|
||||||
|
});
|
||||||
|
const btn = new blessed.button({
|
||||||
|
screen,
|
||||||
|
bottom: 5,
|
||||||
|
height: 2,
|
||||||
|
mouse: true,
|
||||||
|
keys: true,
|
||||||
|
shrink: true,
|
||||||
|
padding: {
|
||||||
|
left: 1,
|
||||||
|
right: 1
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
bg: 'blue',
|
||||||
|
focus: {
|
||||||
|
bg: 'red'
|
||||||
|
},
|
||||||
|
hover: {
|
||||||
|
bg: 'red'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
content: "submit",
|
||||||
|
width: '10%',
|
||||||
|
})
|
||||||
|
screen.append(input);
|
||||||
|
screen.append(btn)
|
||||||
|
input.focus();
|
||||||
|
output.add('Please send your public GPG key here! ')
|
||||||
|
output.add(`Once you have pasted it click the red submit button`)
|
||||||
|
output.add('You will then recive an email shortly pgp-signed with your ssh pirv key')
|
||||||
|
// console.log(input)
|
||||||
|
btn.on('press', async () => {
|
||||||
|
console.debug(`#click`)
|
||||||
|
let line = input.getValue()
|
||||||
|
stream.lastInput = Date.now()
|
||||||
|
// input.clearValue();
|
||||||
|
// screen.render();
|
||||||
|
if (!input.focused)
|
||||||
|
input.focus();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const key = await openpgp.readKey({ armoredKey: line })
|
||||||
|
output.add(`PGP key added.`)
|
||||||
|
console.log( key.getFingerprint(), key.users[0].userID.name)
|
||||||
|
sendMail(key)
|
||||||
|
stream.end()
|
||||||
|
} catch (e) {
|
||||||
|
output.add(`Error! Your key is an invalid pgp key`)
|
||||||
|
output.add(`> ${e.message}`)
|
||||||
|
}
|
||||||
|
// line = line.replace(RE_SPECIAL, '').trim();
|
||||||
|
// if (line.length > MAX_MSG_LEN)
|
||||||
|
// line = line.substring(0, MAX_MSG_LEN);
|
||||||
|
// if (line.length > 0) {
|
||||||
|
// if (line === '/quit' || line === '/exit')
|
||||||
|
// stream.end();
|
||||||
|
// else
|
||||||
|
// userBroadcast(line, stream);
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
// stream.end()
|
||||||
|
} else {
|
||||||
|
|
||||||
|
users.push(stream);
|
||||||
|
stream.lastInput = Date.now()
|
||||||
|
|
||||||
|
|
||||||
|
const screen = new blessed.screen({
|
||||||
|
autoPadding: true,
|
||||||
|
smartCSR: true,
|
||||||
|
program: new blessed.program({
|
||||||
|
input: stream,
|
||||||
|
output: stream
|
||||||
|
}),
|
||||||
|
terminal: term || 'ansi'
|
||||||
|
});
|
||||||
|
|
||||||
|
screen.title = 'SSH Chatting as ' + name;
|
||||||
|
// Disable local echo
|
||||||
|
screen.program.attr('invisible', true);
|
||||||
|
|
||||||
|
const output = stream.output = new blessed.log({
|
||||||
|
screen: screen,
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
bottom: 2,
|
||||||
|
scrollOnInput: true
|
||||||
|
});
|
||||||
|
screen.append(output);
|
||||||
|
|
||||||
|
screen.append(new blessed.box({
|
||||||
|
screen: screen,
|
||||||
|
height: 1,
|
||||||
|
bottom: 1,
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
type: 'line',
|
||||||
|
ch: '='
|
||||||
|
}));
|
||||||
|
|
||||||
|
const input = new blessed.textbox({
|
||||||
|
screen: screen,
|
||||||
|
bottom: 0,
|
||||||
|
height: 1,
|
||||||
|
width: '100%',
|
||||||
|
inputOnFocus: true
|
||||||
|
});
|
||||||
|
screen.append(input);
|
||||||
|
|
||||||
|
input.focus();
|
||||||
|
|
||||||
|
// Local greetings
|
||||||
|
localMessage('{blue-bg}{white-fg}{bold}Welcome to SSH Chat!{/}\n'
|
||||||
|
+ 'There are {bold}'
|
||||||
|
+ (users.length - 1)
|
||||||
|
+ '{/} other user(s) connected.\n'
|
||||||
|
+ 'Type /quit or /exit to exit the chat.',
|
||||||
|
stream);
|
||||||
|
|
||||||
|
// Let everyone else know that this user just joined
|
||||||
|
for (const user of users) {
|
||||||
|
const output = user.output;
|
||||||
|
if (user === stream)
|
||||||
|
continue;
|
||||||
|
output.add(formatMessage('{green-fg}*** {bold}', output)
|
||||||
|
+ name
|
||||||
|
+ formatMessage('{/bold} has joined the chat{/}', output));
|
||||||
|
}
|
||||||
|
|
||||||
|
screen.render();
|
||||||
|
// XXX This fake resize event is needed for some terminals in order to
|
||||||
|
// have everything display correctly
|
||||||
|
screen.program.emit('resize');
|
||||||
|
setInterval(() => {
|
||||||
|
if(Date.now() - stream.lastInput >= 60_000) {
|
||||||
|
return stream.end();
|
||||||
|
}
|
||||||
|
},1000)
|
||||||
|
// Read a line of input from the user
|
||||||
|
input.on('submit', (line) => {
|
||||||
|
stream.lastInput = Date.now()
|
||||||
|
input.clearValue();
|
||||||
|
screen.render();
|
||||||
|
if (!input.focused)
|
||||||
|
input.focus();
|
||||||
|
line = line.replace(RE_SPECIAL, '').trim();
|
||||||
|
if (line.length > MAX_MSG_LEN)
|
||||||
|
line = line.substring(0, MAX_MSG_LEN);
|
||||||
|
if (line.length > 0) {
|
||||||
|
if (line === '/quit' || line === '/exit')
|
||||||
|
stream.end();
|
||||||
|
else
|
||||||
|
userBroadcast(line, stream);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).on('close', () => {
|
||||||
|
if (stream !== undefined) {
|
||||||
|
users.splice(users.indexOf(stream), 1);
|
||||||
|
// Let everyone else know that this user just left
|
||||||
|
for (const user of users) {
|
||||||
|
const output = user.output;
|
||||||
|
output.add(formatMessage('{magenta-fg}*** {bold}', output)
|
||||||
|
+ name
|
||||||
|
+ formatMessage('{/bold} has left the chat{/}', output));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).on('error', (err) => {
|
||||||
|
// Ignore errors
|
||||||
|
});
|
||||||
|
}).listen(3001, function() {
|
||||||
|
console.log('Listening on port ' + this.address().port);
|
||||||
|
});
|
38
src/test_mail.js
Normal file
38
src/test_mail.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
const nodemailer = require('nodemailer')
|
||||||
|
const openpgp = require('openpgp')
|
||||||
|
var directTransport = require('nodemailer-direct-transport');
|
||||||
|
var transporter = nodemailer.createTransport(directTransport())
|
||||||
|
const { utils: { generateKeyPair, generateKeyPairSync } } = require('ssh2');
|
||||||
|
// transporter.sendMail({
|
||||||
|
// to:"neon@saahild.com",
|
||||||
|
// from: "neon@localhost",
|
||||||
|
// html: "hello world"
|
||||||
|
// })
|
||||||
|
|
||||||
|
;(async () => {
|
||||||
|
// create this sessions PGP key
|
||||||
|
const { privateKey, publicKey } = await openpgp.generateKey({
|
||||||
|
type: 'rsa', // Type of the key
|
||||||
|
rsaBits: 2048, // RSA key size (defaults to 4096 bits)
|
||||||
|
userIDs: [{ name: 'Server', email: 'neon+pgp_server__temp@hackclub.app' }], // you can pass multiple user IDs
|
||||||
|
format: 'object',
|
||||||
|
passphrase: 'super long and hard to guess secret' // protects the private key
|
||||||
|
});
|
||||||
|
function sendMail(key) {
|
||||||
|
const usersSSHKey = generateKeyPairSync('rsa', { bits: 2048, comment: 'Priv key for nest pgp chat - GPG FINGERPRINT: '+ key.getFingerprint() });
|
||||||
|
|
||||||
|
transporter.sendMail({
|
||||||
|
from: publicKey.users[0].userID.email,
|
||||||
|
to: key.users[0].userID.email,
|
||||||
|
attachments: [{
|
||||||
|
filename: `privkey.asc`,
|
||||||
|
|
||||||
|
}, {
|
||||||
|
filename: `pubkey.pub.asc`
|
||||||
|
}]
|
||||||
|
// html: await
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const clientKey = await openpgp.readKey({ armoredKey: require('fs').readSync('./key.asc').toString() })
|
||||||
|
sendMail(clientKey)
|
||||||
|
})()
|
306
yarn.lock
Normal file
306
yarn.lock
Normal file
|
@ -0,0 +1,306 @@
|
||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@cspotcode/source-map-support@^0.8.0":
|
||||||
|
version "0.8.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
|
||||||
|
integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/trace-mapping" "0.3.9"
|
||||||
|
|
||||||
|
"@jridgewell/resolve-uri@^3.0.3":
|
||||||
|
version "3.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
|
||||||
|
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
|
||||||
|
|
||||||
|
"@jridgewell/sourcemap-codec@^1.4.10":
|
||||||
|
version "1.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
|
||||||
|
integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
|
||||||
|
|
||||||
|
"@jridgewell/trace-mapping@0.3.9":
|
||||||
|
version "0.3.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
|
||||||
|
integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/resolve-uri" "^3.0.3"
|
||||||
|
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||||
|
|
||||||
|
"@tsconfig/node10@^1.0.7":
|
||||||
|
version "1.0.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2"
|
||||||
|
integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==
|
||||||
|
|
||||||
|
"@tsconfig/node12@^1.0.7":
|
||||||
|
version "1.0.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d"
|
||||||
|
integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==
|
||||||
|
|
||||||
|
"@tsconfig/node14@^1.0.0":
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1"
|
||||||
|
integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==
|
||||||
|
|
||||||
|
"@tsconfig/node16@^1.0.2":
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
|
||||||
|
integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
|
||||||
|
|
||||||
|
"@types/bun@latest":
|
||||||
|
version "1.1.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/bun/-/bun-1.1.9.tgz#2a10783816f178538be72f78e93e2f4f4d73825d"
|
||||||
|
integrity sha512-SXJRejXpmAc3qxyN/YS4/JGWEzLf4dDBa5fLtRDipQXHqNccuMU4EUYCooXNTsylG0DmwFQsGgEDHxZF+3DqRw==
|
||||||
|
dependencies:
|
||||||
|
bun-types "1.1.27"
|
||||||
|
|
||||||
|
"@types/node@*":
|
||||||
|
version "22.5.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.5.tgz#52f939dd0f65fc552a4ad0b392f3c466cc5d7a44"
|
||||||
|
integrity sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==
|
||||||
|
dependencies:
|
||||||
|
undici-types "~6.19.2"
|
||||||
|
|
||||||
|
"@types/node@~20.12.8":
|
||||||
|
version "20.12.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.14.tgz#0c5cf7ef26aedfd64b0539bba9380ed1f57dcc77"
|
||||||
|
integrity sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==
|
||||||
|
dependencies:
|
||||||
|
undici-types "~5.26.4"
|
||||||
|
|
||||||
|
"@types/ws@~8.5.10":
|
||||||
|
version "8.5.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.12.tgz#619475fe98f35ccca2a2f6c137702d85ec247b7e"
|
||||||
|
integrity sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
|
acorn-walk@^8.1.1:
|
||||||
|
version "8.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7"
|
||||||
|
integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==
|
||||||
|
dependencies:
|
||||||
|
acorn "^8.11.0"
|
||||||
|
|
||||||
|
acorn@^8.11.0, acorn@^8.4.1:
|
||||||
|
version "8.12.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248"
|
||||||
|
integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==
|
||||||
|
|
||||||
|
arg@^4.1.0:
|
||||||
|
version "4.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
|
||||||
|
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
|
||||||
|
|
||||||
|
asn1.js@^5.0.0:
|
||||||
|
version "5.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07"
|
||||||
|
integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==
|
||||||
|
dependencies:
|
||||||
|
bn.js "^4.0.0"
|
||||||
|
inherits "^2.0.1"
|
||||||
|
minimalistic-assert "^1.0.0"
|
||||||
|
safer-buffer "^2.1.0"
|
||||||
|
|
||||||
|
asn1@^0.2.6:
|
||||||
|
version "0.2.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d"
|
||||||
|
integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==
|
||||||
|
dependencies:
|
||||||
|
safer-buffer "~2.1.0"
|
||||||
|
|
||||||
|
bcrypt-pbkdf@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
|
||||||
|
integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==
|
||||||
|
dependencies:
|
||||||
|
tweetnacl "^0.14.3"
|
||||||
|
|
||||||
|
blessed@^0.1.81:
|
||||||
|
version "0.1.81"
|
||||||
|
resolved "https://registry.yarnpkg.com/blessed/-/blessed-0.1.81.tgz#f962d687ec2c369570ae71af843256e6d0ca1129"
|
||||||
|
integrity sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==
|
||||||
|
|
||||||
|
bn.js@^4.0.0:
|
||||||
|
version "4.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
|
||||||
|
integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
|
||||||
|
|
||||||
|
buildcheck@~0.0.6:
|
||||||
|
version "0.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.6.tgz#89aa6e417cfd1e2196e3f8fe915eb709d2fe4238"
|
||||||
|
integrity sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==
|
||||||
|
|
||||||
|
bun-types@1.1.27:
|
||||||
|
version "1.1.27"
|
||||||
|
resolved "https://registry.yarnpkg.com/bun-types/-/bun-types-1.1.27.tgz#53cbc56d412157fbaf0ba30328208494a6f52cc6"
|
||||||
|
integrity sha512-rHXAiIDefeMS/fleNM1rRDYqolJGNRdch3+AuCRwcZWaqTa1vjGBNsahH/HVV7Y82frllYhJomCVSEiHzLzkgg==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "~20.12.8"
|
||||||
|
"@types/ws" "~8.5.10"
|
||||||
|
|
||||||
|
cpu-features@~0.0.9:
|
||||||
|
version "0.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.10.tgz#9aae536db2710c7254d7ed67cb3cbc7d29ad79c5"
|
||||||
|
integrity sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==
|
||||||
|
dependencies:
|
||||||
|
buildcheck "~0.0.6"
|
||||||
|
nan "^2.19.0"
|
||||||
|
|
||||||
|
create-require@^1.1.0:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
|
||||||
|
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
|
||||||
|
|
||||||
|
diff@^4.0.1:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||||
|
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
|
||||||
|
|
||||||
|
dotenv@^16.4.5:
|
||||||
|
version "16.4.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
|
||||||
|
integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==
|
||||||
|
|
||||||
|
httpntlm@1.6.1:
|
||||||
|
version "1.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/httpntlm/-/httpntlm-1.6.1.tgz#ad01527143a2e8773cfae6a96f58656bb52a34b2"
|
||||||
|
integrity sha512-Tcz3Ct9efvNqw3QdTl3h6IgRRlIQxwKkJELN/aAIGnzi2xvb3pDHdnMs8BrxWLV6OoT4DlVyhzSVhFt/tk0lIw==
|
||||||
|
dependencies:
|
||||||
|
httpreq ">=0.4.22"
|
||||||
|
underscore "~1.7.0"
|
||||||
|
|
||||||
|
httpreq@>=0.4.22:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/httpreq/-/httpreq-1.1.1.tgz#b8818316cdfd6b1bfb0f68b822fa1306cd24be68"
|
||||||
|
integrity sha512-uhSZLPPD2VXXOSN8Cni3kIsoFHaU2pT/nySEU/fHr/ePbqHYr0jeiQRmUKLEirC09SFPsdMoA7LU7UXMd/w0Kw==
|
||||||
|
|
||||||
|
inherits@^2.0.1:
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||||
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
|
|
||||||
|
make-error@^1.1.1:
|
||||||
|
version "1.3.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||||
|
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
||||||
|
|
||||||
|
minimalistic-assert@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
|
||||||
|
integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
|
||||||
|
|
||||||
|
nan@^2.18.0, nan@^2.19.0:
|
||||||
|
version "2.20.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.20.0.tgz#08c5ea813dd54ed16e5bd6505bf42af4f7838ca3"
|
||||||
|
integrity sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==
|
||||||
|
|
||||||
|
nodemailer-direct-transport@^3.3.2:
|
||||||
|
version "3.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz#e96fafb90358560947e569017d97e60738a50a86"
|
||||||
|
integrity sha512-vEMLWdUZP9NpbeabM8VTiB3Ar1R0ixASp/6DdKX372LK4USKB4Lq12/WCp69k/+kWk4RiCWWEGo57CcsXOs/bw==
|
||||||
|
dependencies:
|
||||||
|
nodemailer-shared "1.1.0"
|
||||||
|
smtp-connection "2.12.0"
|
||||||
|
|
||||||
|
nodemailer-fetch@1.6.0:
|
||||||
|
version "1.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz#79c4908a1c0f5f375b73fe888da9828f6dc963a4"
|
||||||
|
integrity sha512-P7S5CEVGAmDrrpn351aXOLYs1R/7fD5NamfMCHyi6WIkbjS2eeZUB/TkuvpOQr0bvRZicVqo59+8wbhR3yrJbQ==
|
||||||
|
|
||||||
|
nodemailer-shared@1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz#cf5994e2fd268d00f5cf0fa767a08169edb07ec0"
|
||||||
|
integrity sha512-68xW5LSyPWv8R0GLm6veAvm7E+XFXkVgvE3FW0FGxNMMZqMkPFeGDVALfR1DPdSfcoO36PnW7q5AAOgFImEZGg==
|
||||||
|
dependencies:
|
||||||
|
nodemailer-fetch "1.6.0"
|
||||||
|
|
||||||
|
nodemailer@^6.9.15:
|
||||||
|
version "6.9.15"
|
||||||
|
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.15.tgz#57b79dc522be27e0e47ac16cc860aa0673e62e04"
|
||||||
|
integrity sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==
|
||||||
|
|
||||||
|
openpgp@^5.11.2:
|
||||||
|
version "5.11.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/openpgp/-/openpgp-5.11.2.tgz#2c035a26b13feb3b0bb5180718ec91c8e65cc686"
|
||||||
|
integrity sha512-f8dJFVLwdkvPvW3VPFs6q9Vs2+HNhdvwls7a/MIFcQUB+XiQzRe7alfa3RtwfGJU7oUDDMAWPZ0nYsHa23Az+A==
|
||||||
|
dependencies:
|
||||||
|
asn1.js "^5.0.0"
|
||||||
|
|
||||||
|
safer-buffer@^2.1.0, safer-buffer@~2.1.0:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||||
|
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||||
|
|
||||||
|
smtp-connection@2.12.0:
|
||||||
|
version "2.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/smtp-connection/-/smtp-connection-2.12.0.tgz#d76ef9127cb23c2259edb1e8349c2e8d5e2d74c1"
|
||||||
|
integrity sha512-UP5jK4s5SGcUcqPN4U9ingqKt9mXYSKa52YhqxPuMecAnUOsVJpOmtgGaOm1urUBJZlzDt1M9WhZZkgbhxQlvg==
|
||||||
|
dependencies:
|
||||||
|
httpntlm "1.6.1"
|
||||||
|
nodemailer-shared "1.1.0"
|
||||||
|
|
||||||
|
ssh2@^1.15.0:
|
||||||
|
version "1.15.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-1.15.0.tgz#2f998455036a7f89e0df5847efb5421748d9871b"
|
||||||
|
integrity sha512-C0PHgX4h6lBxYx7hcXwu3QWdh4tg6tZZsTfXcdvc5caW/EMxaB4H9dWsl7qk+F7LAW762hp8VbXOX7x4xUYvEw==
|
||||||
|
dependencies:
|
||||||
|
asn1 "^0.2.6"
|
||||||
|
bcrypt-pbkdf "^1.0.2"
|
||||||
|
optionalDependencies:
|
||||||
|
cpu-features "~0.0.9"
|
||||||
|
nan "^2.18.0"
|
||||||
|
|
||||||
|
ts-node@^10.9.2:
|
||||||
|
version "10.9.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f"
|
||||||
|
integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==
|
||||||
|
dependencies:
|
||||||
|
"@cspotcode/source-map-support" "^0.8.0"
|
||||||
|
"@tsconfig/node10" "^1.0.7"
|
||||||
|
"@tsconfig/node12" "^1.0.7"
|
||||||
|
"@tsconfig/node14" "^1.0.0"
|
||||||
|
"@tsconfig/node16" "^1.0.2"
|
||||||
|
acorn "^8.4.1"
|
||||||
|
acorn-walk "^8.1.1"
|
||||||
|
arg "^4.1.0"
|
||||||
|
create-require "^1.1.0"
|
||||||
|
diff "^4.0.1"
|
||||||
|
make-error "^1.1.1"
|
||||||
|
v8-compile-cache-lib "^3.0.1"
|
||||||
|
yn "3.1.1"
|
||||||
|
|
||||||
|
tweetnacl@^0.14.3:
|
||||||
|
version "0.14.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||||
|
integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==
|
||||||
|
|
||||||
|
typescript@^5.6.2:
|
||||||
|
version "5.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.2.tgz#d1de67b6bef77c41823f822df8f0b3bcff60a5a0"
|
||||||
|
integrity sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==
|
||||||
|
|
||||||
|
underscore@~1.7.0:
|
||||||
|
version "1.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209"
|
||||||
|
integrity sha512-cp0oQQyZhUM1kpJDLdGO1jPZHgS/MpzoWYfe9+CM2h/QGDZlqwT2T3YGukuBdaNJ/CAPoeyAZRRHz8JFo176vA==
|
||||||
|
|
||||||
|
undici-types@~5.26.4:
|
||||||
|
version "5.26.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||||
|
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||||
|
|
||||||
|
undici-types@~6.19.2:
|
||||||
|
version "6.19.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
|
||||||
|
integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
|
||||||
|
|
||||||
|
v8-compile-cache-lib@^3.0.1:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
|
||||||
|
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
|
||||||
|
|
||||||
|
yn@3.1.1:
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
||||||
|
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
|
Loading…
Reference in a new issue