diff --git a/.gitignore b/.gitignore index 74245dc..9a9941b 100644 --- a/.gitignore +++ b/.gitignore @@ -173,6 +173,4 @@ dist # Finder (MacOS) folder config .DS_Store -*.asc -*.key -ssh_keys \ No newline at end of file +*.asc \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index 8380d39..815d6d3 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/host.key.pub b/host.key.pub deleted file mode 100644 index ca51da2..0000000 --- a/host.key.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOrBXBiOtqX7YEOyLCMag2XFc8unduCPDI3q/pIYBqMD neon@leon diff --git a/package.json b/package.json index 6370f84..d0de61e 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,15 @@ { "name": "nest-pgp-chat", "module": "src/index.ts", + "type": "module", "devDependencies": { - "@types/bun": "latest", - "ts-node": "^10.9.2", - "typescript": "^5.6.2" + "@types/bun": "latest" }, "peerDependencies": { "typescript": "^5.0.0" }, "dependencies": { - "blessed": "^0.1.81", "dotenv": "^16.4.5", - "nodemailer": "^6.9.15", - "nodemailer-direct-transport": "^3.3.2", - "openpgp": "^5.11.2", - "ssh2": "^1.15.0" + "openpgp": "^5.11.2" } -} +} \ No newline at end of file diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 11fb0d5..0000000 --- a/src/index.js +++ /dev/null @@ -1,396 +0,0 @@ - -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); -}); \ No newline at end of file diff --git a/src/_index.ts b/src/index.ts similarity index 79% rename from src/_index.ts rename to src/index.ts index 0fb41f3..6e7cdeb 100644 --- a/src/_index.ts +++ b/src/index.ts @@ -6,7 +6,7 @@ import openpgp from 'openpgp' 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 + userIDs: [{ name: 'Jon Smith', email: 'jon@example.com' }], // you can pass multiple user IDs format: 'object', passphrase: 'super long and hard to guess secret' // protects the private key }); @@ -68,7 +68,6 @@ const Config = { "server": { // nests ram COULD not handle more then 20 sadly "maxConnections": 20, - "noInputTimeout": 55_000 , "host": "127.0.0.1", "port": process.env.PORT }, @@ -76,7 +75,7 @@ const Config = { "messageLength": 150, "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)", - "nickname": "Enter your public PGP key (in base64, in one line once done write in a new line 'ENDKEY'): ", + "nickname": "Enter your public PGP key (in base64, in one line): ", "logout": "%s has left the chat", "login": "%s has joined the chat", "not_allowed": "You may only connect from the nest server. This is not a public server." @@ -86,20 +85,9 @@ const Config = { } const Messages = Config.chat.messages; -// to prevent my ram from being disposed -const all_connections = []; + 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 => { console.log('Received data', data, data.toString()); @@ -164,16 +152,11 @@ function askNickname(socket) { }; const onData = messageListener(data => { - if(data.toString().includes('ENDKEY')) { - socket.off('data', onData) - resolve(str); - } else { - str += data.toString() - if (!data.length) return ask(); - if(!data.toString().includes('ENDKEY')) return ask() - - } - + str += data.toString() + if (!data.length) return ask(); +if(!data.toString().includes('END PGP PUBLIC KEY')) return ask() + socket.off('data', onData) + resolve(str); }); ask(); @@ -182,7 +165,6 @@ function askNickname(socket) { function createServer() { const server = net.createServer(async socket => { - try { console.log(socket.remoteAddress) if(![`::1`].includes(socket.remoteAddress.trim())) { @@ -190,13 +172,6 @@ function createServer() { socket.end(`Bye`) 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}`); sendMessageLn(socket, null, Messages.welcome); @@ -207,10 +182,10 @@ all_connections[all_connections.indexOf(socket)].lastInput = Date.now() console.debug(`$afternic`) let pgp_key=null, nickname= null; try { - // console.log(raw_pgp_data) - console.log(Buffer.from(raw_pgp_data as string, 'base64').toString(), Buffer.from(raw_pgp_data as string, 'base64').toString().length) + console.log(raw_pgp_data) + // console.log(Buffer.from(raw_pgp_data as string, 'base64').toString()) pgp_key = await openpgp.readKey({ - armoredKey: Buffer.from(raw_pgp_data as string, 'base64').toString(), + armoredKey: raw_pgp_data as string, }) // .then(d=>d.users[0]) console.log(pgp_key.users[0]) diff --git a/src/test_mail.js b/src/test_mail.js deleted file mode 100644 index 5edbdf8..0000000 --- a/src/test_mail.js +++ /dev/null @@ -1,38 +0,0 @@ -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) -})() \ No newline at end of file diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index bb880e7..0000000 --- a/yarn.lock +++ /dev/null @@ -1,306 +0,0 @@ -# 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==