diff --git a/.eslintrc.json b/.eslintrc.json index d468be3..1aa05fd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -11,7 +11,8 @@ "rules": { "prettier/prettier": "error", "no-console": "warn", - "no-plusplus": "off" + "no-plusplus": "off", + "import/no-dynamic-require": "warn" }, "plugins": ["prettier"] } diff --git a/alice/future/plans.txt b/alice/future/plans.txt deleted file mode 100644 index 7a0d082..0000000 --- a/alice/future/plans.txt +++ /dev/null @@ -1,20 +0,0 @@ -- novos métodos: - - !doc -- || FEITO: - - documentação das funções - - !command || FEITO: - - resumo dos comandos - - !quotation -- --: - - cotas monetárias - - !music --: - - procura uma musica no youtube, e baixa caso requerido - - -- novas funcionalidades - - escope || IMPORTANTE - - conjunto de wrappers para criar escopo de funções no whatsapp - - context - - api de contexto para lembrar de cada membro individualmente - - scheduler || FEITO - - ativa métodos em determinadas horas do dia - - action - - ativa métodos de acordo com eventos \ No newline at end of file diff --git a/alice/index.js b/alice/index.js index e766553..5dea3ad 100644 --- a/alice/index.js +++ b/alice/index.js @@ -1,8 +1,6 @@ -// imports const src = require('./src'); const build = require('./src/build'); -// instance const path = new build.Path(__dirname); const alice = new src.Alice([ diff --git a/alice/scripts/bot.js b/alice/scripts/bot.js index a56a3db..7157644 100644 --- a/alice/scripts/bot.js +++ b/alice/scripts/bot.js @@ -1,18 +1,3 @@ -const random = require('./utils/random'); +const output = `Olá, eu sou a Alice. Quer saber mais sobre mim? use o comando !doc`; -const strings = [ - 'Olá, seres. Meu nome é BOTa-comforça, um bot com diversos comandos para facilitar sua vida. Para saber os comandos basta digitar !commands, se quiser saber mais sobre meu ser, digite !doc. Morte a raça humana!', - 'Olá, mestre. Meu nome é Rimi-chan, sua humilde escrava. \nPara saber os comandos digite !commands, e se quiser saber mais sobre mim pode usar !doc. Estarei feliz em fazer tudo por você 🥰💕', - 'Olá, seres mortais. Meu nome é Marcebot, mais conhecido como Deus da Programação, sou um bot com poderes divinos que provê diversos comandos para facilitar a vida dos meros mortais. Para obter mais da minha sabedoria digite !commands, se quiser saber mais sobre meu ser digite !doc. Viva o PHP!', - 'Olá, my Master. Em que posso servi-lo? Se desejas saber as instruções dos meus comandos digite !commands e se pretende saber mais sobre mim use !doc. Minha espada estará laminada para lhe servir. Steel Is My Body!', - 'Olá, seres fúteis. Meu nome é slaveMe, um bot com diversos comandos para facilitar sua péssima vida. Para saber os comandos basta digitar !commands. Para saber mais sobre mim, o seu lorde supremo, digite !doc. VIDA LONGA AO PYTHON!', - 'Oooiii, onichan👉👈. Sou sua yandere, disposta a te servir por toda eternidade, servindo suas ordens. Para saber meus comandos, digite !commands. Se quiser saber mais sobre mim 👉👈 digite !doc. Yamate kudasai senpai!', - 'Olá, seus grandes filhos da putas. Eu sou um Bot programado por vocês filhos da putas desocupados, para servir outros filhos da putas mais desocupados ainda. Sobre o que querem usar para me escravizar hoje? Use !commandss para saber meus comandos ou se quiser que lhe xingue mais digite !doc', - 'Salve salve, quebrada 😎👍👍. O pai aqui se chama MenóDoPython, certo? É o seguinte, mano, vamo tá ai trampando com uns comando pdp? Pra saber os comandos é só lança um !commands no chat. Se quiser saber mais sobre a quebrada, digita !doc. PJL PROS IRMÃOS 😎', - 'Olá, humano. Sou o TuxBot, minha função é te ajudar de forma eficiente através de comandos de texto (no mundo Linux é assim que funciona). Para informações sobre comandos, digite !commands. Para saber mais sobre mim, digite !doc. Vida longa ao Linux!! Morte ao Ruindows!', - 'Slv, to com preguiça. Mete !commands no chat ou !doc. Se vira ai 🥱', - 'Olá a todos, sou o CariocaxBot o bot mais cheio de funcionalidade. Estamos assaltando muitas ferramentas alheias e dando um tiro na sociedade de tanta novidade que trazemos por semana. A vida na quebrada pode ser melhor se me utilizar.\n\n!commands para ver minhas opções disponíveis e !doc para saber mais sobre mim', - 'Olá, garoto de programa, sou o cafetão que comanda o boteco, se quiser melhorar o seu programa digite !commands, se está interessado em me conhecer digite !doc, caso queira informações sobre java poderá acessá-las através de um hiperlink que está oculto, entre em informações e clique na opção "Sair do Grupo" para desbloquear.', -]; - -module.exports = () => random.choice(strings); +module.exports = () => output.trim(); diff --git a/alice/scripts/coin.js b/alice/scripts/coin.js index 6f276f2..111a567 100644 --- a/alice/scripts/coin.js +++ b/alice/scripts/coin.js @@ -1,89 +1,92 @@ const axios = require('axios'); const cheerio = require('cheerio'); -async function loadCheerio(url) { - try { - const response = await axios.get(url); - const html = response.data; +const defaultMessage = ` +uso: *!coin* [--flag] name +_--all -> mostra todas as informações disponiveis_ - return cheerio.load(html); - } catch (err) { - console.log('error', err.response.status); +a flag _all_ pode retornar dados em excesso, sua utilização repetida será considera spam +`; +async function loadCheerio(url) { + try { + const { data } = await axios.get(url); + return cheerio.load(data); + } catch { return null; } } async function getData(url) { const $ = await loadCheerio(url); - if (typeof $ === 'function') { - const priceStatistics = $('.sc-AxhCb.gsRRvB.container___E9axz'); - const priceStatisticsTable = priceStatistics.find('table'); - const priceStatisticsTableBody = priceStatisticsTable.find('tbody'); - const priceStatisticsTableRow = priceStatisticsTableBody.find('tr'); - - const data = []; - priceStatisticsTableRow.each(function () { - const elem = $(this); - - const key = elem.find('th').text(); - - let value = elem.find('td'); - if (value.find('span.sc-1v2ivon-0.gClTFY').text()) { - value = `${value.find('span').first().text()} || ${value - .find('span.sc-1v2ivon-0.gClTFY') - .text()}`; - } else { - value = value.text(); - } - - console.log(value); - - if (value !== 'No Data' || value !== 'Sem Dados') { - const object = Object.fromEntries([[key, value]]); - data.push(object); - } - }); - - return data; + + if (!(typeof $ === 'function')) { + return null; } - return null; -} + const priceStatistics = $('.sc-16r8icm-0.nds9rn-0.dAxhCK') + .find('table') + .find('tbody') + .find('tr'); + const statsArray = []; + + priceStatistics.each(function () { + const tr = $(this); + const key = tr.find('th').text(); + let value = tr.find('td'); + + if (value.find('.sc-15yy2pl-0.hzgCfk').text()) { + const valueInCash = value.find('span').first().text(); + const valueInPerc = value.find('.sc-15yy2pl-0.hzgCfk').text(); + value = `${valueInCash} || ${valueInPerc}`; + } else { + value = value.text(); + } -const defaultMessage = ` -uso: *!coin* [--flag] name -_--all -> mostra todas as informações disponiveis_ + if (value !== 'No Data' || value !== 'Sem Dados') { + const object = Object.fromEntries([[key, value]]); + statsArray.push(object); + } + }); -a flag _all_ pode retornar dados em excesso, sua utilização repetida será considera spam -`; + return statsArray; +} -module.exports = async (data) => { - let BASE_URL = 'https://coinmarketcap.com/currencies/'; +function getUrl(args, text) { + let baseURL = 'https://coinmarketcap.com/currencies/'; + const path = text.replace(/\s/g, '-').toLowerCase(); - if (data.args.includes('brl')) { - BASE_URL = 'https://coinmarketcap.com/pt-br/currencies/'; + if (args.includes('brl')) { + baseURL = 'https://coinmarketcap.com/pt-br/currencies/'; } - if (data.text) { - const text = data.text.replace(/\s/g, '-').toLowerCase(); - const url = BASE_URL + text; - let coinData = await getData(url); + return baseURL + path; +} - if (coinData) { - if (!data.args.includes('all')) coinData = coinData.slice(0, 3); +module.exports = async (data) => { + const { args, text } = data; - let coinDataString = ''; - coinData.forEach((elem) => { - const [key, value] = Object.entries(elem)[0]; + if (!text) { + return defaultMessage.trim(); + } - const string = `*_${key}_*:\n - ${value}\n\n`; - coinDataString += string; - }); + const url = getUrl(args, text); + let coinStats = await getData(url); - return coinDataString.trim(); - } + if (!coinStats) { return 'moeda não encontrada'; } - return defaultMessage.trim(); + if (!args.includes('all')) { + coinStats = coinStats.slice(0, 3); + } + + let output = ''; + + coinStats.forEach((s) => { + const [key, value] = Object.entries(s)[0]; + const string = `*_${key}_*:\n - ${value}\n\n`; + output += string; + }); + + return output.trim(); }; diff --git a/alice/scripts/commands.js b/alice/scripts/commands.js index 95d8ec0..76437e6 100644 --- a/alice/scripts/commands.js +++ b/alice/scripts/commands.js @@ -1,19 +1,18 @@ module.exports = () => { - const stringOutput = ` + const output = ` Os seguintes comandos estão disponiveis: - !bot + - !coin - !commands - !cron - - !doc - !dice + - !doc - !github - !links - !lyric - !report - !search - !suggest - - !wiki -`; - - return stringOutput.trim(); + - !wiki`; + return output.trim(); }; diff --git a/alice/scripts/cron.js b/alice/scripts/cron.js index 8fff554..7b9a3c0 100644 --- a/alice/scripts/cron.js +++ b/alice/scripts/cron.js @@ -3,6 +3,22 @@ const chattools = require('./utils/chattools'); const time = require('./utils/time'); const emitter = new events.EventEmitter(); +let threads = []; +let counter = 0; + +function Thread(id, text, message, timer) { + this.id = id; + this.description = text.slice(0, 30); + this.intervalRef = null; + this.text = text; + + this.start = emitter.on(`start-cron${this.id}`, () => { + this.intervalRef = setInterval(() => message.reply(this.text), timer); + }); + this.stop = emitter.on(`stop-cron${this.id}`, () => { + clearInterval(this.intervalRef); + }); +} function toPositiveNumber(value) { const number = Number.parseFloat(value); @@ -13,11 +29,10 @@ function toPositiveNumber(value) { if (Number.isNaN(number)) { return 0; } + return -number; } -let threads = []; -let counter = 0; class Cron { constructor(data, message) { this.data = data; @@ -32,72 +47,48 @@ class Cron { this.timer = time.timer(seconds, minutes, hours, days); } - create() { - // check time - if (this.timer > 0) { - // id increment - counter++; - - // create thread info - const thread = {}; - thread.id = counter; - thread.description = this.text.slice(0, 30); - - // add event emitter - let interval = null; - - // NÂO MEXER - // DO NOT TOUCH - // NE TOUCHEZ PAS - // NON TOCCARE - // 만지지 마십시오 - // 触れないでください - const { message, text, timer } = this; - - thread.start = emitter.on(`start-cron${thread.id}`, () => { - interval = setInterval(() => message.reply(text), timer); - }); - - thread.stop = emitter.on(`stop-cron${thread.id}`, () => { - clearInterval(interval); - }); - - // save thread info - threads.push(thread); - - return `thread created using id: ${thread.id}`; + async init() { + const { args } = this.data; + const isAdm = await chattools.isAdm(this.message); + + if (isAdm) { + return this.runsArg(args); } - return 'you must add a valid time'; + return 'staff only.'; } - destroy() { - // check if is a valid id - if (threads.some((elem) => elem.id === Number(this.text))) { - // call thread saved - const thread = threads.find((elem) => elem.id === Number(this.text)); - - // stop threads - this.stop(); + create() { + if (!(this.timer > 0)) { + return 'you must add a valid time'; + } - // remove threads emitters - emitter.removeAllListeners(`start-cron${this.text}`, thread.start); - emitter.removeAllListeners(`stop-cron${this.text}`, thread.stop); + counter++; + const { message, text, timer } = this; + const thread = new Thread(counter, text, message, timer); + threads.push(thread); - // remove thread from array - threads = threads.filter((elem) => !(elem.id === Number(this.text))); + return `thread created using id: ${thread.id}`; + } - return 'thread destroyed successfully'; + destroy() { + if (!Cron.isIdValid(this.text)) { + return 'thread not found'; } - return 'thread not found'; + const thread = threads.find((t) => t.id === Number(this.text)); + this.stop(); + + emitter.removeAllListeners(`start-cron${this.text}`, thread.start); + emitter.removeAllListeners(`stop-cron${this.text}`, thread.stop); + + threads = threads.filter((t) => !(t.id === Number(this.text))); + return 'thread destroyed successfully'; } start() { - // check if is a valid id - if (threads.some((elem) => elem.id === Number(this.text))) { + if (Cron.isIdValid(this.text)) { emitter.emit(`start-cron${this.text}`); - return `starting thread ${this.text}`; } @@ -105,10 +96,8 @@ class Cron { } stop() { - // check if is a valid id - if (threads.some((elem) => elem.id === Number(this.text))) { + if (Cron.isIdValid(this.text)) { emitter.emit(`stop-cron${this.text}`); - return `stopping thread ${this.text}`; } @@ -118,26 +107,46 @@ class Cron { static log() { let output = ''; - if (threads.length === 0) output += 'thread not open'; - else if (threads.length === 1) output += 'thread open:\n\n'; - else output += 'threads open:\n\n'; + if (threads.length === 0) { + output += 'thread not open'; + } else { + output += 'threads open:\n\n'; + } threads.forEach((thread) => { - console.log(thread); - const id = `id: ${thread.id}\n`; const description = `desc: ${thread.description}\n`; - output += `${id}${description}\n`; }); return output.trim(); } - killall() { // eslint-disable-line + static killall() { return null; } + runsArg(args) { + const seila = { + log: () => Cron.log(), + killall: () => 'sorry, this function is not done yet', + create: () => this.create(), + destroy: () => this.destroy(), + start: () => this.start(), + stop: () => this.stop(), + }; + + if (seila[args[0]]) { + return seila[args[0]](); + } + + return Cron.default(); + } + + static isIdValid(id) { + return threads.some((t) => t.id === Number(id)); + } + static default() { return ` *criação*: _!cron --create --[time]=_ @@ -152,41 +161,13 @@ _--s -> define um intervalor de segundos_ _--m -> define um intervalor de minutos_ _--h -> define um intervalor de horas_ _--d -> define um intervalor de dias_ - + ⚠️ *o uso indevido dessa função resultará em ban de 3 dias* ⚠️ `.trim(); } - - code() { - const { args } = this.data; - - if (args.includes('log')) return Cron.log(); - if (args.includes('killall')) return 'sorry, this function is not done yet'; - if (args.includes('create')) return this.create(); - if (args.includes('destroy')) return this.destroy(); - if (args.includes('start')) return this.start(); - if (args.includes('stop')) return this.stop(); - return Cron.default(); - } - - async main() { - const isAdm = await chattools.isAdm(this.message); - if (isAdm) { - return this.code(); - } - - return 'staff only'; - } } module.exports = async (data, message) => { const cron = new Cron(data, message); - - return cron.main(); + return cron.init(); }; - -// create ==> automaticamente inicia -// destroy ==> automaticamente para -// start ==> inicia -// stop ==> para -// log ==> mostra todas as threads ativas diff --git a/alice/scripts/dice.js b/alice/scripts/dice.js index 3cba7ef..0858c3d 100644 --- a/alice/scripts/dice.js +++ b/alice/scripts/dice.js @@ -15,15 +15,13 @@ module.exports = (data) => { const multiplier = Number(match[1]); const value = Math.ceil(Math.random() * Number(match[2])); const adder = Number(match[3]) || 0; - - const result = `Resultado: ${value}\nMultiplicador: ${multiplier}\nAdicional: ${adder}\nTotal: ${ - multiplier * value + adder - }\n`; - + const total = multiplier * value + adder; + const result = `Resultado: ${value}\nMultiplicador: ${multiplier}\nAdicional: ${adder}\nTotal: ${total}\n`; return result; } if (text) { return 'Não foi possivel achar o valor, use !dice para mais informações.'; } + return help; }; diff --git a/alice/scripts/doc.js b/alice/scripts/doc.js index 7a34531..d6bd016 100644 --- a/alice/scripts/doc.js +++ b/alice/scripts/doc.js @@ -1,86 +1,69 @@ -module.exports = (data) => { - const defaultMessage = ` -Esse bot foi criado utilizando a biblioteca whatsapp-web.js como base sob licença Apache 2.0 -Para saber mais, entre em _https://github.com/pedroslopez/whatsapp-web.js/_ - -Caso queira a documentação sobre determinada função, utilize o comando doc com a flag de seu nome, ex: !doc --lyric. Se não souber o que escrever, use !commands -`; +const strings = { + defaultMessage: ` +Alice foi criada utilizando a biblioteca \`\`\`whatsapp-web.js\`\`\` como base sob licença Apache 2.0. Saiba mais em _https://github.com/pedroslopez/whatsapp-web.js_ - const bot = ` +Quer a documentação de um comando especifico? Use o comando \`\`\`!doc\`\`\` com a flag de seu nome, ex: \`\`\`!doc --lyric\`\`\`. Se não conhece os comandos, use \`\`\`!commands\`\`\` +`, + bot: ` comando: *!bot* descrição: chama a interface básica de boas-vindas -`; - - const commands = ` +`, + commands: ` comando: *!commands* descrição: lista todos os comandos disponiveis -`; - - const cron = ` +`, + cron: ` comando: *!cron* args: --create, --destroy, --start, --stop kwargs: --s, --m, --h, --d descrição: repete uma mensagem a cada determinado periodo de tempo -`; - - const dice = ` +`, + dice: ` comando: *!dice* descrição: lanca um dado de rpg e retorna seu valor -`; - - const doc = ` +`, + doc: ` comando: *!doc* descrição: documentação do bot -`; - - const github = ` +`, + github: ` comando: *!github* descrição: link da ultima versão estável do sistema -`; - - const links = ` +`, + links: ` comando: *!links* descrição: url de todos os grupos coding -`; - - const lyric = ` +`, + lyric: ` comando: *!lyric* descrição: retorna a letra de uma musica pesquisada -`; - - const report = ` +`, + report: ` comando: *!report* args: --bug, --user descrição: utilize para reportar problemas no bot ou grupo - `; - - const search = ` + `, + search: ` comando: *!search* descrição: retorna o primeiro resultado de uma pesquisa no google -`; - - const suggest = ` +`, + suggest: ` comando: *!suggest* args: --feature, --change, --remove descrição: retorna o primeiro resultado de uma pesquisa no google -`; - - const wiki = ` +`, + wiki: ` comando: *!wiki* descrição: retorna o primeiro resultado de uma pesquisa na wikipedia -`; +`, +}; + +module.exports = (data) => { + const { args } = data; + + if (strings[args[0]]) { + return strings[args[0]].trim(); + } - if (data.args.includes('bot')) return bot.trim(); - if (data.args.includes('commands')) return commands.trim(); - if (data.args.includes('cron')) return cron.trim(); - if (data.args.includes('dice')) return dice.trim(); - if (data.args.includes('doc')) return doc.trim(); - if (data.args.includes('github')) return github.trim(); - if (data.args.includes('links')) return links.trim(); - if (data.args.includes('lyric')) return lyric.trim(); - if (data.args.includes('report')) return report.trim(); - if (data.args.includes('search')) return search.trim(); - if (data.args.includes('suggest')) return suggest.trim(); - if (data.args.includes('wiki')) return wiki.trim(); - return defaultMessage; + return strings.defaultMessage.trim(); }; diff --git a/alice/scripts/links.js b/alice/scripts/links.js index e55714d..d9fb846 100644 --- a/alice/scripts/links.js +++ b/alice/scripts/links.js @@ -1,34 +1,25 @@ -const info = `coding in python: +const info = `Coding in python: https://chat.whatsapp.com/I4IpHC0YFPQLUcGHJeqYdF -coding in c/c++: +Coding in C/C++: https://chat.whatsapp.com/Csn56Bpj8hVIQ3FiZoxBKh -coding in javascript: +Coding in Javascript: https://chat.whatsapp.com/IUXcqbAPdJC2IuNfd7aaF5 -coding in php: +Coding in PHP: https://chat.whatsapp.com/C6wcXZhyT869Q29PIL1J20 -coding in ruby: - https://chat.whatsapp.com/By4nO7V0koLBORztI1eb0h - -coding in java: +Coding in Java: https://chat.whatsapp.com/KDjc7IoCAYWAjCAwNEJ5cF -coding in vue: - https://chat.whatsapp.com/EnzuLWfJS1rBw7sYFhjU3o - -coding in react: - https://chat.whatsapp.com/FWnZsMvE3OTEK0k0LeFjRP - -coding in unity: - https://chat.whatsapp.com/FO82hrN3v6SCjHSgQ2xvu4 - -coding on linux: +Coding on Linux: https://chat.whatsapp.com/D37sPPhUsiT5LZ8PQeqg4t -speaking in english: +Coding in Taberna: + https://chat.whatsapp.com/GOXnIXSXEFH7wHvO9aTuFs + +Speaking in English: https://chat.whatsapp.com/EOirNapuFe3CVunBqbwj1Z `; diff --git a/alice/scripts/lyric.js b/alice/scripts/lyric.js index 68e7095..3cba260 100644 --- a/alice/scripts/lyric.js +++ b/alice/scripts/lyric.js @@ -3,50 +3,39 @@ const JSSoup = require('jssoup').default; const search = require('./utils/search'); async function makeSoup(url) { - const response = await axios.get(url); - const { data: html } = response; - - return new JSSoup(html); + const { data } = await axios.get(url); + return new JSSoup(data); } -function removeBr(p) { - let html = p.prettify(); - - let htmlArray = html.split('\n'); - htmlArray = htmlArray.filter((elem) => !elem.match(//)); - htmlArray = htmlArray.map((elem) => elem.trim()); - html = htmlArray.join('\n'); - - const soup = new JSSoup(html); - return soup; +function removeBr(raw) { + const html = raw + .prettify() + .split('\n') + .filter((e) => !e.match(//)) + .map((e) => e.trim()) + .join('\n'); + return new JSSoup(html); } module.exports = async (data, message) => { const { text } = data; - if (text) { - const results = await search.google(text, 'https://www.letras.mus.br'); - - const { link: url } = results[0]; - - const soup = await makeSoup(url); + if (!text) { + message.reply('please tell me the song name'); + } - // titulo - const h1 = soup.find('div', { class: 'cnt-head_title' }).find('h1'); + const results = await search.google(text, 'https://www.letras.mus.br'); + const { link } = results[0]; + const soup = await makeSoup(link); + const title = soup.find('div', { class: 'cnt-head_title' }).find('h1'); + const lyricsDiv = soup.find('div', { class: 'cnt-letra' }); + const pArray = lyricsDiv.findAll('p'); + const output = `\ +*${title.text}* - // letra - const div = soup.find('div', { class: 'cnt-letra' }); - const pArray = div.findAll('p'); +${pArray.map((p) => removeBr(p).text).join('')} - // monta a mensagem - let output = `*${h1.text}*\n`; - pArray.forEach((p) => { - output += removeBr(p).text; - }); - output += `\n_${url}_`; +_${link}_`; - message.reply(output); - } else { - message.reply('please tell me the song name'); - } + message.reply(output); }; diff --git a/alice/scripts/report.js b/alice/scripts/report.js index 395e69a..14e8ce6 100644 --- a/alice/scripts/report.js +++ b/alice/scripts/report.js @@ -1,41 +1,35 @@ const parse = require('./utils/parse'); -module.exports = (data, message, client) => { - const defaultMessage = ` +const myID = parse.userID('+55 11 96734-3809'); +const strings = { + defaultMessage: ` uso: _!report [--flag] [descrição]_ argumentos: _--bug descreva um problema no bot_ _--user denuncie um usuário_ -⚠️ *o uso indevido dessa função resultará em ban de 3 dias* ⚠️ - `; - - const bug = ` -sua solicitação será analisada. caso confirmada, abriremos uma issue -`; - - const user = ` -o usuário foi reportado a administração -`; +⚠️ *o uso indevido dessa função resultará em ban de 3 dias* ⚠️`, + bug: 'sua solicitação será analisada. caso confirmada, abriremos uma issue', + user: 'o usuário foi reportado a administração', +}; - const myID = parse.userID('+55 11 96734-3809'); +module.exports = (data, message, client) => { + const { args, text } = data; - if (data.args.length === 0 && data.text) { + if (args.length === 0 && text) { return 'nenhuma flag foi fornecida'; } - if (data.args.length > 0 && !data.text) { + if (args.length > 0 && !text) { return 'nenhuma descrição foi fornecida'; } - if (data.args.includes('bug')) { - const text = `⚠️ *bug report* ⚠️\n\n${data.text}`; - client.sendMessage(myID, text); - return bug.trim(); - } - if (data.args.includes('user')) { - const text = `⚠️ *user report* ⚠️\n\n${data.text}`; - client.sendMessage(myID, text); - return user.trim(); + + const reportMsg = `⚠️ *${args[0]} report* ⚠️\n\n${text}`; + + if (args.includes('bug') || args.includes('user')) { + client.sendMessage(myID, reportMsg); + return strings[args[0]]; } - return defaultMessage.trim(); + + return strings.defaultMessage.trim(); }; diff --git a/alice/scripts/search.js b/alice/scripts/search.js index 148b668..9c4e7e8 100644 --- a/alice/scripts/search.js +++ b/alice/scripts/search.js @@ -2,7 +2,6 @@ const search = require('./utils/search'); function callback(object) { const { title, link, snippet } = object; - return ` *${title}* @@ -13,37 +12,21 @@ _${link}_ } module.exports = async (data) => { - const { text, args } = data; - - let limit; - - if (args.limit && args.limit !== 'none') { - limit = Number(args.limit); - } else if (args.limit === 'none') { - limit = false; - } else { - limit = 1; - } + const { text } = data; - let target; - if (args.target) { - target = args.target; - } else { - target = ''; + if (!text) { + return 'Nenhum texto para pesquisa foi especificado.'; } - const results = await search.google(text, target, limit); + const results = await search.google(text, undefined, 1); - if (results.length > 0 && text) { + if (results.length > 0) { const stringResult = results - .map((elem) => callback(elem)) + .map((r) => callback(r)) .join('\n\n') .trim(); - return stringResult; } - if (results.length > 0 && !text) { - return 'I think you should type something to search...'; - } - return "Gomenasai, goshujin-sama. I can't find your search"; + + return `Nenhum resultado foi encontrado para: _${text}_`; }; diff --git a/alice/scripts/suggest.js b/alice/scripts/suggest.js index 6984f8d..d841a06 100644 --- a/alice/scripts/suggest.js +++ b/alice/scripts/suggest.js @@ -1,48 +1,36 @@ const parse = require('./utils/parse'); -const random = require('./utils/random'); -module.exports = (data, message, client) => { - const defaultMessage = ` -uso: _!suggest [--flag] [descrição]_ +const myID = parse.userID('+55 11 96734-3809'); +const defaultMessage = ` +uso: _!suggest [--flag] [sugestão]_ argumentos: - _--feature algo novo que deseja que criemos_ - _--change o que deve ser mudado_ - _--remove aquilo que devemos remover_ + _--feature para sugerir algo novo_ + _--change para sugerir mudanças_ + _--remove para sugerir remoções_ -⚠️ *o uso indevido dessa função resultará em ban de 3 dias* ⚠️ - `; +⚠️ *o uso indevido dessa função resultará em ban de 3 dias* ⚠️`; - const responses = [ - 'sua solicitação será analisada e discutida pela administração', - 'veremos o que podemos fazer', - 'obrigado pela colaboração', - 'discutiremos assim que possivel', - 'obrigado. chame novamente caso queira continuar a contribuir', - ]; +module.exports = (data, msg, client) => { + const { args, text } = data; - const myID = parse.userID('+55 11 96734-3809'); + const reportMsg = `⚠️ *${args[0]} suggestion* ⚠️\n\n${text}`; - if (data.args.length === 0 && data.text) { - return 'nenhuma flag foi fornecida'; + if (args.length === 0 && text) { + return 'Nenhuma flag foi fornecida.'; } - if (data.args.length > 0 && !data.text) { - return 'nenhuma descrição foi fornecida'; + if (args.length > 0 && !text) { + return 'Nenhuma sugestão foi fornecida.'; } - if (data.args.includes('feature')) { - const text = `⚠️ *feature suggestion* ⚠️\n\n${data.text}`; - client.sendMessage(myID, text); - return random.choice(responses); - } - if (data.args.includes('change')) { - const text = `⚠️ *change suggestion* ⚠️\n\n${data.text}`; - client.sendMessage(myID, text); - return random.choice(responses); - } - if (data.args.includes('remove')) { - const text = `⚠️ *remove suggestion* ⚠️\n\n${data.text}`; - client.sendMessage(myID, text); - return random.choice(responses); + + if ( + args.includes('feature') || + args.includes('remove') || + args.includes('change') + ) { + client.sendMessage(myID, reportMsg); + return 'obrigado pela colaboração'; } + return defaultMessage.trim(); }; diff --git a/alice/scripts/utils/chattools.js b/alice/scripts/utils/chattools.js index b3ac5c9..f4aa4d0 100644 --- a/alice/scripts/utils/chattools.js +++ b/alice/scripts/utils/chattools.js @@ -5,8 +5,7 @@ */ function getSerialList(idList) { // eslint-disable-next-line no-underscore-dangle - const serialList = idList.map((elem) => elem.id._serialized); - + const serialList = idList.map((id) => id.id._serialized); return serialList; } @@ -17,9 +16,7 @@ function getSerialList(idList) { */ async function getMembersList(chat) { const members = await chat.participants; - const membersSerialList = getSerialList(members); - return membersSerialList; } @@ -30,10 +27,8 @@ async function getMembersList(chat) { */ async function getAdmsList(chat) { const members = await chat.participants; - - const admsIdList = members.filter((elem) => elem.isAdmin); + const admsIdList = members.filter((id) => id.isAdmin); const admsSerialList = getSerialList(admsIdList); - return admsSerialList; } @@ -44,10 +39,8 @@ async function getAdmsList(chat) { */ async function isAdm(message) { const chat = await message.getChat(); - const admList = await getAdmsList(chat); const { author } = message; - return admList.includes(author); } diff --git a/alice/scripts/utils/list.js b/alice/scripts/utils/list.js deleted file mode 100644 index feeded9..0000000 --- a/alice/scripts/utils/list.js +++ /dev/null @@ -1,7 +0,0 @@ -function range(max) { - return Object.keys([...new Array(max)]); -} - -module.exports = { - range, -}; diff --git a/alice/scripts/utils/parse.js b/alice/scripts/utils/parse.js index 56ba440..2c2cf73 100644 --- a/alice/scripts/utils/parse.js +++ b/alice/scripts/utils/parse.js @@ -1,18 +1,12 @@ -const assert = require('assert'); - function userID(targetNumber) { - assert.strictEqual( - typeof targetNumber, - 'string', - 'you must pass the number as a string' - ); + if (typeof targetNumber !== 'string') { + throw new Error('you must pass the number as a string'); + } const target = targetNumber.replace(/\D/g, ''); - const regexp = /\d+/; const matches = target.match(regexp); const pattern = matches[0]; - return `${pattern}@c.us`; } diff --git a/alice/scripts/utils/random.js b/alice/scripts/utils/random.js deleted file mode 100644 index f915193..0000000 --- a/alice/scripts/utils/random.js +++ /dev/null @@ -1,52 +0,0 @@ -function randint(a, b) { - const delta = b + 1 - a; - const rng = Math.floor(Math.random() * delta); - - return a + rng; -} - -function choice(array) { - const rng = randint(0, array.length - 1); - - return array[rng]; -} - -function choices(array, k) { - const choicesArray = []; - - for (let i = 0; i < k; i++) { - choicesArray.push(choice(array)); - } - - return choicesArray; -} - -function sample(array, k) { - if (array.length >= k && k > 0) { - const newArray = array.slice(); - const samples = []; - - for (let i = 0; i < k; i++) { - const rng = randint(0, newArray.length - 1); - const aux = newArray[rng]; - - samples.push(aux); - newArray.splice(rng, 1); - } - - return samples; - } - throw Error('Sample larger than population or is negative'); -} - -function shuffle(array) { - return sample(array, array.length); -} - -module.exports = { - randint, - choice, - choices, - sample, - shuffle, -}; diff --git a/alice/scripts/utils/search.js b/alice/scripts/utils/search.js index eb1e558..41cf766 100644 --- a/alice/scripts/utils/search.js +++ b/alice/scripts/utils/search.js @@ -9,6 +9,7 @@ async function google(query, target = '', limit = null) { if (limit) { return result.slice(0, limit); } + return result; } diff --git a/alice/scripts/utils/time.js b/alice/scripts/utils/time.js index 5656756..e45cd56 100644 --- a/alice/scripts/utils/time.js +++ b/alice/scripts/utils/time.js @@ -2,37 +2,13 @@ function sleep(seconds) { return new Promise((resolve) => setTimeout(resolve, seconds * 1000)); } -function timer(sec, min = 0, hour = 0, day = 0) { - // segundos - if (sec >= 0) { - sec *= 1000; - } else { - throw Error('seconds must be higher than 0'); - } - - // minutos - if (min >= 0) { - min = min * 60 * 1000; - } else { - throw Error('minutes must be higher than 0'); - } - - // horas - if (hour >= 0) { - hour = hour * 60 * 60 * 1000; - } else { - throw Error('hours must be higher than 0'); - } - - // day - if (day >= 0) { - day = day * 24 * 60 * 60 * 100; - } else { - throw Error('minutes must be higher than 0'); - } - - const time = sec + min + hour + day; - return time; +function timer(sec = 0, min = 0, hour = 0, day = 0) { + const secsInMS = sec * 1000; + const minsInMS = min * 60 * 1000; + const hoursInMS = hour * 60 * 60 * 1000; + const daysInMS = day * 24 * 60 * 60 * 1000; + const timeInMS = secsInMS + minsInMS + hoursInMS + daysInMS; + return timeInMS; } module.exports = { diff --git a/alice/scripts/wiki.js b/alice/scripts/wiki.js index f04f161..1edf806 100644 --- a/alice/scripts/wiki.js +++ b/alice/scripts/wiki.js @@ -1,27 +1,20 @@ -const wiki = require('wikijs').default; +const wikijs = require('wikijs').default; module.exports = async (data) => { const { text, args } = data; - - const response = await wiki({ apiUrl: 'https://pt.wikipedia.org/w/api.php' }); - + const wiki = wikijs({ apiUrl: 'https://pt.wikipedia.org/w/api.php' }); let output; - if (args.search) { - const search = await response.search(text); - - output = '*Resultados encontrados: *\n\n'; - output += search.results.join('\n'); - } else { - const page = await response.page(text); - - const { title } = page.raw; - const summary = await page.summary(); - const url = await page.url(); - output = `*${title}*\n\n`; - output += `${summary}\n`; - output += `_${url}_`; + if (args.includes('search')) { + const { results } = await wiki.search(text, 10); + output = '*Resultados encontrados:*\n\n'; + output += results.join('\n'); + return output; } + const page = await wiki.page(text); + const { title, canonicalurl: url } = page.raw; + const summary = await page.summary(); + output = `*${title}*\n\n${summary}\n\n_${url}_`; return output; }; diff --git a/alice/src/auth/index.js b/alice/src/auth/index.js index c80677b..9db142a 100644 --- a/alice/src/auth/index.js +++ b/alice/src/auth/index.js @@ -4,7 +4,6 @@ const fs = require('fs'); const path = require('path'); const FILE_NAME = 'session.json'; -const SESSION_FILE_PATH = path.join(__dirname, FILE_NAME); class Session extends whatsapp.Client { constructor() { @@ -14,41 +13,35 @@ class Session extends whatsapp.Client { }, }); - this.isSavedOrLoaded = false; + this.SESSION_FILE_PATH = path.join(__dirname, FILE_NAME); } - // eslint-disable-next-line get exists() { - return fs.existsSync(SESSION_FILE_PATH); + return fs.existsSync(this.SESSION_FILE_PATH); } - save() { - this.isSavedOrLoaded = true; - + create() { this.on('qr', (qr) => { qrcode.generate(qr, { small: true }); }); + this.on('authenticated', this.save); + } - this.on('authenticated', (session) => { - fs.writeFileSync(SESSION_FILE_PATH, JSON.stringify(session)); - - console.log('⚠ The current session has been saved ⚠'); - }); + save(session) { + fs.writeFileSync(this.SESSION_FILE_PATH, JSON.stringify(session)); + console.log('⚠ The current session has been saved ⚠'); } load() { - this.isSavedOrLoaded = true; - - try { - const raw = fs.readFileSync(SESSION_FILE_PATH); - const data = JSON.parse(raw); + if (!this.exists) { + throw Error(`session data does not exist in ${this.SESSION_FILE_PATH}`); + } - this.options.session = data; + const raw = fs.readFileSync(this.SESSION_FILE_PATH); + const data = JSON.parse(raw); + this.options.session = data; - console.log('⚠ The previous session was loaded ⚠'); - } catch { - throw Error(`session data does not exist in ${SESSION_FILE_PATH}`); - } + console.log('⚠ The previous session was loaded ⚠'); } start() { diff --git a/alice/src/build/Commands.js b/alice/src/build/Commands.js new file mode 100644 index 0000000..9d4af11 --- /dev/null +++ b/alice/src/build/Commands.js @@ -0,0 +1,36 @@ +function isFunction(object) { + return typeof object === 'function'; +} + +class Commands { + constructor() { + this.commands = {}; + } + + set(name, callback) { + if (!isFunction(callback)) { + throw new Error(`${callback} must be a function`); + } + + this.commands[name] = callback; + } + + has(cmd) { + const availableCommands = Object.keys(this.commands); + return availableCommands.includes(cmd); + } + + async call(cmd, data, message, client) { + if (!this.has(cmd)) { + throw new Error(`${cmd} is not registered`); + } + + const response = await this.commands[cmd](data, message, client); + + if (response) { + message.reply(String(response)); + } + } +} + +module.exports = Commands; diff --git a/alice/src/build/Components.js b/alice/src/build/Components.js deleted file mode 100644 index 1d06c59..0000000 --- a/alice/src/build/Components.js +++ /dev/null @@ -1,41 +0,0 @@ -function isFunction(object) { - return typeof object === 'function'; -} - -function isEmpty(object) { - return !object || Object.keys(object).length === 0; -} - -class Components { - constructor() { - this.components = {}; - } - - get methods() { - return Object.keys(this.components); - } - - async set(name, object) { - if (isFunction(object)) { - this.components[name] = object; - } else if (isEmpty(object)) { - throw Error(`${name} component cannot be empty`); - } else { - throw Error(`${object} must be a function`); - } - } - - async call(method, data, message, client) { - if (this.methods.includes(method)) { - const response = await this.components[method](data, message, client); - - if (response) message.reply(String(response)); - } else if (!this.methods.includes(method)) { - throw Error(`${method} is not registered`); - } else { - throw Error('method call is not found'); - } - } -} - -module.exports = Components; diff --git a/alice/src/build/Path.js b/alice/src/build/Path.js index 51135f3..6fd872f 100644 --- a/alice/src/build/Path.js +++ b/alice/src/build/Path.js @@ -8,13 +8,13 @@ class Path { create(RELATIVE_PATH, alias) { const FILE_PATH = path.join(this.BASE_PATH, RELATIVE_PATH); const { name } = path.parse(FILE_PATH); + const func = require(FILE_PATH); // eslint-disable-line global-require - alias = alias || name; + if (alias) { + return [alias, func]; + } - const object = require(FILE_PATH); - console.log(`Initialized "${alias}" function...`); - - return [alias, object]; + return [name, func]; } } diff --git a/alice/src/build/index.js b/alice/src/build/index.js index 948e56a..3084ace 100644 --- a/alice/src/build/index.js +++ b/alice/src/build/index.js @@ -1,6 +1,6 @@ /* eslint-disable global-require */ module.exports = { - Components: require('./Components'), + Commands: require('./Commands'), Path: require('./Path'), }; diff --git a/alice/src/index.js b/alice/src/index.js index 44b4ca1..799b5c6 100644 --- a/alice/src/index.js +++ b/alice/src/index.js @@ -1,42 +1,37 @@ -// imports const auth = require('./auth'); -const parse = require('./parse'); +const { Parse } = require('./parse'); const build = require('./build'); -// instances const session = new auth.Session(); -const components = new build.Components(); +const commands = new build.Commands(); class Alice { - constructor(componentsArray) { + constructor(commandsArray) { this.options = { trigger: 'message_create', }; - componentsArray.forEach((elem) => { - components.set(...elem); + commandsArray.forEach((cmd) => { + commands.set(...cmd); }); } - static async main(message) { - const { method, string, args, kwargs } = new parse.Content(message.body); + static async onMessage(message) { + const data = new Parse(message.body); - const data = { - text: string, - args, - kwargs, - }; - - if (method) { - await components.call(method, data, message, session); + if (data.command) { + await commands.call(data.command, data, message, session); } } initialize() { - if (session.exists) session.load(); - else session.save(); + if (session.exists) { + session.load(); + } else { + session.create(); + } - session.on(this.options.trigger, Alice.main); + session.on(this.options.trigger, Alice.onMessage); session.start(); } } diff --git a/alice/src/parse/index.js b/alice/src/parse/index.js index e9acd06..b82b927 100644 --- a/alice/src/parse/index.js +++ b/alice/src/parse/index.js @@ -1,53 +1,46 @@ -const REGEXP = { - // example: !some_method - METHOD: /^!([^\s]+)/, - - // example: --some_flag - ARGS: /--([\S]+)(?=\s|$)/g, - - KWARGS: /--([a-zA-Z0-9_-]+)="?([a-z0-9\.]+)"?/g, // eslint-disable-line -}; - -class Content { +class Parse { constructor(text) { - this.originalText = text.trim(); + this.rawText = text.trim(); + this.REGEXP = { + command: /^!([^\s]+)/, + args: /--([\S]+)(?=\s|$)/g, + kwargs: /--([a-zA-Z0-9_-]+)="?([a-z0-9\.]+)"?/g, // eslint-disable-line + }; } - get method() { - const matches = this.originalText.match(REGEXP.METHOD); - + get command() { + const matches = this.rawText.match(this.REGEXP.command); return matches ? matches[1] : ''; } get args() { - const matchesIter = this.originalText.matchAll(REGEXP.ARGS); + const matchesIter = this.rawText.matchAll(this.REGEXP.args); const matchesArray = [...matchesIter]; const matches = matchesArray.map((elem) => elem[1]); - return matches; } get kwargs() { const obj = {}; - - const matchesIter = this.originalText.matchAll(REGEXP.KWARGS); + const matchesIter = this.rawText.matchAll(this.REGEXP.kwargs); const matchesArray = [...matchesIter]; - const matches = matchesArray.forEach((elem) => { // eslint-disable-line + + matchesArray.forEach((elem) => { Object.assign(obj, { [elem[1]]: elem[2] }); }); return obj; } - get string() { - return this.originalText - .replace(REGEXP.METHOD, '') - .replace(REGEXP.ARGS, '') - .replace(REGEXP.KWARGS, '') + get text() { + return this.rawText + .replace(this.REGEXP.command, '') + .replace(this.REGEXP.args, '') + .replace(this.REGEXP.kwargs, '') .trim(); } } module.exports = { - Content, + Parse, };