Comparing version 2.0.0-beta to 2.0.0-rc.1
{ | ||
"name": "retrocord", | ||
"version": "2.0.0-beta", | ||
"version": "2.0.0-rc.1", | ||
"description": "", | ||
@@ -28,2 +28,5 @@ "main": "src/index.js", | ||
"node-emoji": "^1.8.1", | ||
"sharp": "^0.18.2", | ||
"snekparse": "github:devsnek/snekparse", | ||
"tinyint": "^1.0.0", | ||
"uws": "^8.14.0" | ||
@@ -30,0 +33,0 @@ }, |
@@ -10,3 +10,3 @@ [](https://www.npmjs.com/package/retrocord) | ||
`npm i -g retrocord` OR [download a release](/releases) | ||
`npm i -g retrocord` OR [download a release](https://github.com/devsnek/retrocord/releases) | ||
@@ -13,0 +13,0 @@  |
const Storage = require('./Storage'); | ||
const messageElement = require('./elements/message'); | ||
@@ -46,3 +45,3 @@ module.exports = { | ||
channel.fetchMessages({ limit: 5 }).then((messages) => { | ||
for (const message of messages.array().reverse()) ctx.gui.put(messageElement(message), { format: false }); | ||
ctx.gui.putMessages(messages.array().reverse()); | ||
}); | ||
@@ -66,16 +65,32 @@ ctx.current.channel = channel; | ||
run: (ctx, args) => { | ||
ctx.current.channel.search({ content: args.join(' ') }) | ||
ctx.current.channel.search({ | ||
content: args.join(' '), | ||
has: args.has, | ||
authorType: args['author-type'], | ||
limit: args.limit || 10, | ||
}) | ||
.then((r) => r.results.map((msgs) => msgs.find((m) => m.hit))) | ||
.then((messages) => { | ||
.then(async(messages) => { | ||
ctx.gui.put('{bold}-- BEGIN SEARCH --{/bold}'); | ||
const results = messages | ||
.map((r) => messageElement(r, true)) | ||
.slice(0, 10) | ||
.reverse() | ||
.join('\n'); | ||
ctx.gui.put(results, { format: false }); | ||
ctx.gui.put(`{bold} Query: ${args.join(' ')}{/bold}`); | ||
await ctx.gui.putMessages(messages.reverse(), { mdy: true }); | ||
ctx.gui.put('{bold}--- END SEARCH ---{/bold}'); | ||
}) | ||
.catch((err) => { | ||
ctx.gui.put(`{bold}Search Error (${err.message}){/bold}`); | ||
}); | ||
}, | ||
}, | ||
set: { | ||
run: (ctx, [name, value]) => { | ||
if (ctx.rc.set(name, value)) ctx.gui.put(`{bold}Changed setting "${name}" to "${value}"{/bold}`); | ||
else ctx.gui.put(`{bold}Failed to change setting "${name}" to "${value}"{/bold}`); | ||
}, | ||
}, | ||
tableflip: { | ||
run: (ctx, args) => { | ||
if (!ctx.current.channel) return; | ||
ctx.current.channel.send(`${args.join(' ')} w(╯°□°)╯︵ ┻━┻`.trim()); | ||
}, | ||
}, | ||
}; | ||
@@ -82,0 +97,0 @@ |
const Discord = require('discord.js'); | ||
const Storage = require('../Storage'); | ||
const messageElement = require('../elements/message'); | ||
const timestamp = require('../util/timestamp'); | ||
@@ -9,11 +9,39 @@ const client = new Discord.Client({ | ||
client.run = run; | ||
function run(ctx) { | ||
client.on('ready', () => { | ||
ctx.gui.put(`{bold}Logged in as ${client.user.tag}{/bold}`, { center: true }); | ||
ctx.allowInput = true; | ||
if (client.user.bot) { | ||
Storage.delete('token'); | ||
ctx.gui.put(`{bold}Incorrect Token!{/bold} (Bot accounts cannot login as users)`); | ||
} else { | ||
ctx.gui.put(`{bold}Logged in as ${client.user.tag}{/bold}`, { center: true }); | ||
ctx.allowInput = true; | ||
} | ||
}); | ||
client.on('message', (message) => { | ||
if (message.channel !== ctx.current.channel) return; | ||
ctx.gui.put(messageElement(message), { format: false }); | ||
switch (message.channel.type) { | ||
case 'dm': { | ||
if (message.author.id === client.user.id) return; | ||
// eslint-disable-next-line max-len | ||
ctx.gui.put(`{yellow-fg}${timestamp(message.createdAt, false)}{/yellow-fg} {bold}${message.author.tag}{/bold} has sent you a message!`); | ||
break; | ||
} | ||
case 'group': { | ||
if (message.author.id === client.user.id) return; | ||
let dmName = message.channel.name === null ? 'Group' : message.channel.name; | ||
ctx.gui.put(`{yellow-fg}${timestamp(message.createdAt, false)}{/yellow-fg} {bold}${dmName} has a new message!`); | ||
break; | ||
} | ||
case 'text': { | ||
if (message.channel === ctx.current.channel) { | ||
ctx.gui.putMessage(message); | ||
} else if (message.mentions.users.has(client.user.id)) { | ||
// eslint-disable-next-line max-len | ||
ctx.gui.put(`{yellow-fg}${timestamp(message.createdAt, false)}{/yellow-fg} You were mentioned in {bold}${message.guild.name} #${message.channel.name}{/bold} by {bold}${message.author.tag}{/bold}`); | ||
} | ||
break; | ||
} | ||
} | ||
}); | ||
@@ -20,0 +48,0 @@ |
@@ -5,5 +5,6 @@ const emoji = require('node-emoji'); | ||
const hexToRgb = require('../util/hexToRgb'); | ||
const imageElement = require('./image'); | ||
const shortlink = require('../util/shortlink'); | ||
module.exports = (message, mdy = false) => { | ||
const client = message.client; | ||
async function messageElement(message, mdy = false) { | ||
const color = (...x) => { | ||
@@ -23,13 +24,30 @@ if (message.member) { | ||
for (const mention of message.mentions.users.values()) { | ||
if (mention.id === client.user.id) { | ||
content = content.replace(new RegExp(`<@!?${mention.id}>`, 'g'), `{red+bold}@${client.user.username}{/}`); | ||
process.stdout.write('\x07'); | ||
} else { | ||
content = content.replace(new RegExp(`<@!?${mention.id}>`, 'g'), `@${mention.username}`); | ||
} | ||
content = content.replace(new RegExp(`<@!?${mention.id}>`, 'g'), `{blue-fg}@${mention.tag}{/blue-fg}`); | ||
} | ||
for (const mention of message.mentions.channels.values()) { | ||
content = content.replace(new RegExp(`<#${mention.id}>`, 'g'), `{blue-fg}#${mention.name}{/blue-fg}`); | ||
} | ||
for (const match of content.match(/:[^:]+:/g) || []) content = content.replace(match, emoji.get(match)); | ||
return `{yellow-fg}${timestamp(message.createdAt, mdy)}{/yellow-fg} ${color(message.author.tag)} ${content}`; | ||
}; | ||
if (message.mentions.includes && message.mentions.includes(message.client.user)) { | ||
process.stdout.write('\x07'); | ||
content = `{yellow-bg}{black-fg}${content}{/black-fg}{/yellow-bg}`; | ||
} | ||
let images = await Promise.all(message.attachments.map(async(a) => { | ||
const short = a.url.replace('https://cdn.discordapp.com/attachments/', '').split('/'); | ||
const ansi = await imageElement({ id: a.id, url: a.proxyURL, width: a.width, height: a.height }); | ||
return `${a.filename} (${a.width}x${a.height}) ${shortlink(short[2], short[0], short[1])}\n${ansi}`; | ||
})); | ||
let attachments = [...images]; | ||
if (!content) content = '{bold}(No Content){/bold}'; | ||
if (attachments.length) attachments = `{bold}Attachments:{/bold} ${attachments.join('\n')}`; | ||
// eslint-disable-next-line max-len | ||
return `{yellow-fg}${timestamp(message.createdAt, mdy)}{/yellow-fg} ${color(message.author.tag)} ${content}\n${attachments}`.trim(); | ||
} | ||
module.exports = messageElement; |
const EventEmitter = require('events'); | ||
const blessed = require('blessed'); | ||
const messageElement = require('./elements/message'); | ||
@@ -54,2 +55,11 @@ class GUI extends EventEmitter { | ||
} | ||
async putMessages(messages, { mdy = false } = {}) { | ||
messages = await Promise.all(messages.map((m) => messageElement(m, mdy))); | ||
for (const message of messages) this.consolebox.log(message); | ||
} | ||
putMessage(message, opt) { | ||
return this.putMessages([message], opt); | ||
} | ||
} | ||
@@ -60,2 +70,3 @@ | ||
title: 'retrocord', | ||
fullUnicode: true, | ||
}); | ||
@@ -62,0 +73,0 @@ |
@@ -0,1 +1,3 @@ | ||
#!/usr/bin/env node | ||
const emoji = require('node-emoji'); | ||
@@ -7,2 +9,3 @@ const Storage = require('./Storage'); | ||
const discord = require('./discord'); | ||
const snekparse = require('snekparse'); | ||
@@ -17,8 +20,9 @@ const ctx = { | ||
}, | ||
rc: Storage.rc, | ||
}; | ||
gui.on('input', (message) => { | ||
if (message.startsWith(':')) { | ||
if (message.startsWith(ctx.rc.prefix || '/')) { | ||
const [command, ...args] = message.slice(1).split(' '); | ||
if (command in commands) commands[command].run(ctx, args); | ||
if (command in commands) commands[command].run(ctx, snekparse(args)); | ||
} else { | ||
@@ -29,3 +33,3 @@ if (!ctx.allowInput) return; | ||
if (args[word].startsWith('@')) { | ||
const [username, discrim] = args[word].split('#').map((x) => x.replace('@', '').toLowerCase()); | ||
const [username, discrim] = args[word].split('#').map((x) => x.slice(1).toLowerCase()); | ||
let user = ctx.discord.users.find((u) => { | ||
@@ -38,2 +42,10 @@ let match = false; | ||
if (user) args[word] = user.toString(); | ||
} else if (args[word].startsWith('#')) { | ||
if (!ctx.current.scope || ctx.current.scope === 'dm') continue; | ||
const name = args[word].slice(1); | ||
const channel = ctx.current.scope.channels | ||
.filter((c) => c.type === 'text') | ||
.find((c) => | ||
c.name.toLowerCase() === name.toLowerCase()); | ||
if (channel) args[word] = channel.toString(); | ||
} | ||
@@ -45,9 +57,9 @@ } | ||
for (const match of message.match(/:[^:]+:/g) || []) { | ||
if (customEmojis) { | ||
const found = customEmojis.find((x) => x.name.toLowerCase() === match.replace(/:/g, '').toLowerCase()); | ||
message = message.replace(match, found ? found.toString() : null || emoji.get(match)); | ||
if (!found) message = message.replace(match, emoji.get(match)); | ||
} else { | ||
message = message.replace(match, emoji.get(match)); | ||
const unicode = emoji.get(match); | ||
if (unicode !== match) { | ||
message = message.replace(match, unicode); | ||
continue; | ||
} | ||
const found = customEmojis.find((x) => x.name.toLowerCase() === match.replace(/:/g, '').toLowerCase()); | ||
message = message.replace(match, found ? found.toString() : emoji.get(match)); | ||
} | ||
@@ -74,4 +86,12 @@ | ||
} else { | ||
return null; | ||
return []; | ||
} | ||
} | ||
process.on('unhandledRejection', handleError); | ||
process.on('uncaughtException', handleError); | ||
function handleError(e) { | ||
ctx.gui.put(`{red-fg}{bold}Unhandled Error (You should report this){/bold}{/red-fg}\n${e.stack} | ||
{red-fg}{bold}-- End Error --{/bold}{/red-fg}`); | ||
} |
const fs = require('fs'); | ||
const path = require('path'); | ||
const util = require('util'); | ||
const readFileAsync = util.promisify(fs.readFile); | ||
const writeFileAsync = util.promisify(fs.writeFile); | ||
const existsAsync = util.promisify(fs.exists); | ||
const unlinkAsync = util.promisify(fs.unlink); | ||
const OS_STORAGE_PATH = getOSStoragePath(); | ||
if (!fs.existsSync(OS_STORAGE_PATH)) fs.mkdirSync(OS_STORAGE_PATH); | ||
if (!fs.existsSync(OS_STORAGE_PATH)) { | ||
fs.mkdirSync(OS_STORAGE_PATH); | ||
fs.mkdirSync(path.join(OS_STORAGE_PATH, 'files')); | ||
fs.makedirSync(path.join(OS_STORAGE_PATH), '.retrorc'); | ||
} | ||
const STORAGE_PATH = path.join(OS_STORAGE_PATH, 'storage.json'); | ||
// if (!fs.existsSync(STORAGE_PATH)) fs.mkdirSync(STORAGE_PATH); | ||
let cache = {}; | ||
const cache = { | ||
storage: {}, | ||
rc: { | ||
set(key, value) { | ||
this[key] = value; | ||
const src = Object.entries(this) | ||
.filter(([k]) => k !== 'set') | ||
.map((e) => e.join('=')) | ||
.join('\n'); | ||
try { | ||
fs.writeFileSync(path.join(OS_STORAGE_PATH, '.retrorc'), src); | ||
return true; | ||
} catch (err) { | ||
return false; | ||
} | ||
}, | ||
}, | ||
}; | ||
try { | ||
cache = JSON.parse(fs.readFileSync(STORAGE_PATH)); | ||
cache.storage = JSON.parse(fs.readFileSync(STORAGE_PATH)); | ||
} catch (err) {} // eslint-disable-line no-empty | ||
try { | ||
const src = fs.readFileSync(path.join(OS_STORAGE_PATH, '.retrorc')).toString(); | ||
cache.rc = src | ||
.trim().split('\n') | ||
.map((p) => p.split('=')) | ||
.reduce((o, [k, v]) => { | ||
o[k] = v; | ||
return o; | ||
}, cache.rc); | ||
} catch (err) {} // eslint-disable-line no-empty | ||
module.exports = { | ||
rc: cache.rc, | ||
get(key) { | ||
return cache[key]; | ||
return cache.storage[key]; | ||
}, | ||
set(key, value) { | ||
const ret = cache[key] = value; | ||
fs.writeFileSync(STORAGE_PATH, JSON.stringify(cache)); | ||
const ret = cache.storage[key] = value; | ||
fs.writeFileSync(STORAGE_PATH, JSON.stringify(cache.storage)); | ||
return ret; | ||
}, | ||
has(key) { | ||
return Reflect.has(cache, key); | ||
return Reflect.has(cache.storage, key); | ||
}, | ||
delete(key) { | ||
const ret = delete cache[key]; | ||
fs.writeFileSync(STORAGE_PATH, JSON.stringify(cache)); | ||
const ret = delete cache.storage[key]; | ||
fs.writeFileSync(STORAGE_PATH, JSON.stringify(cache.storage)); | ||
return ret; | ||
}, | ||
getFilePath(key) { | ||
return path.join(OS_STORAGE_PATH, 'files', key); | ||
}, | ||
getFile(key) { | ||
try { | ||
return fs.readFileSync(path.join(OS_STORAGE_PATH, key)); | ||
} catch (err) { | ||
return null; | ||
} | ||
return readFileAsync(path.join(OS_STORAGE_PATH, 'files', key)) | ||
.catch(() => null); | ||
}, | ||
getFilePath(key) { | ||
return path.join(OS_STORAGE_PATH, key); | ||
}, | ||
setFile(key, value) { | ||
try { | ||
fs.writeFileSync(path.join(OS_STORAGE_PATH, key), value); | ||
return true; | ||
} catch (err) { | ||
return false; | ||
} | ||
return writeFileAsync(path.join(OS_STORAGE_PATH, 'files', key), value) | ||
.then(() => true).catch(() => false); | ||
}, | ||
hasFile(key) { | ||
return fs.existsSync(path.join(OS_STORAGE_PATH, key)); | ||
return existsAsync(path.join(OS_STORAGE_PATH, 'files', key)).catch(() => false); | ||
}, | ||
deleteFile(key) { | ||
try { | ||
fs.unlinkSync(path.join(OS_STORAGE_PATH, key)); | ||
return true; | ||
} catch (err) { | ||
return false; | ||
} | ||
return unlinkAsync(path.join(OS_STORAGE_PATH, 'files', key)) | ||
.then(() => true).catch(() => false); | ||
}, | ||
@@ -64,8 +92,7 @@ }; | ||
switch (process.platform) { | ||
case 'darwin': | ||
return `${process.env.HOME}/Library/Application Support/retrocord`; | ||
case 'win32': | ||
return `${process.env.APPDATA}\\retrocord`; | ||
case 'darwin': | ||
case 'linux': | ||
return `${process.env.HOME}/.retrocord`; | ||
return `${process.env.HOME}/.config/retrocord`; | ||
default: | ||
@@ -72,0 +99,0 @@ return '.'; |
GitHub dependency
Supply chain riskContains a dependency which resolves to a GitHub URL. Dependencies fetched from GitHub specifiers are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
24161
16
627
4
0
10
4
+ Addedsharp@^0.18.2
+ Addedtinyint@^1.0.0
+ Addedcaw@2.0.1(transitive)
+ Addedchownr@1.1.4(transitive)
+ Addedcolor@2.0.1(transitive)
+ Addedcolor-string@1.9.1(transitive)
+ Addedconfig-chain@1.1.13(transitive)
+ Addeddecompress-response@3.3.0(transitive)
+ Addeddetect-libc@0.2.0(transitive)
+ Addedget-proxy@2.1.0(transitive)
+ Addedhas-symbol-support-x@1.4.2(transitive)
+ Addedhas-to-string-tag-x@1.4.1(transitive)
+ Addedini@1.3.8(transitive)
+ Addedis-arrayish@0.3.2(transitive)
+ Addedis-object@1.0.2(transitive)
+ Addedisurl@1.0.0(transitive)
+ Addedlong@3.2.0(transitive)
+ Addedmimic-response@1.0.1(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedminipass@2.9.0(transitive)
+ Addedminizlib@1.3.3(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addednan@2.22.2(transitive)
+ Addednpm-conf@1.1.3(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedpify@3.0.0(transitive)
+ Addedproto-list@1.2.4(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsemver@5.7.2(transitive)
+ Addedsharp@0.18.4(transitive)
+ Addedsimple-concat@1.0.1(transitive)
+ Addedsimple-get@2.8.2(transitive)
+ Addedsimple-swizzle@0.2.2(transitive)
+ Addedtar@3.2.3(transitive)
+ Addedtinyint@1.0.0(transitive)
+ Addedtunnel-agent@0.6.0(transitive)
+ Addedurl-to-options@1.0.1(transitive)
+ Addedwrappy@1.0.2(transitive)
+ Addedyallist@3.1.1(transitive)