diff --git a/.babelrc b/.babelrc index 7f191e4..72009ce 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,12 @@ { - "presets": ["node8"] + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "node": "current" + } + } + ] + ] } diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..779f99a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..94b3750 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +# /node_modules/* and /bower_components/* ignored by default + +# Ignore built files except build/index.js +dist/* \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..53309ab --- /dev/null +++ b/.eslintrc @@ -0,0 +1,41 @@ +{ + "parser": "babel-eslint", + "env": { + "node": true + }, + "extends": ["airbnb-base", "prettier"], + "rules": { + "func-names": 0, + "max-len": [1, 240], + "no-unused-vars": 0, + "no-script-url": 0, + "no-unused-expressions":"off", + "import/no-unresolved": 0, + "import/no-extraneous-dependencies": 0, + "no-console": 0, + "no-undef": 0, + "import/prefer-default-export": 0, + "global-require": 0, + "comma-dangle": ["off"], + "import/extensions": 0, + "guard-for-in": ["warn"], + "no-restricted-syntax": ["off"], + "object-curly-spacing": ["off"], + "padded-blocks": ["off"], + "no-underscore-dangle": [ + "error", + { + "allowAfterThis": true + } + ], + "no-plusplus": 0, + "no-shadow": 0, + "class-methods-use-this": 0, + "consistent-return": 0, + "indent": ["error", 4], + "eol-last": [1, "always"] + }, + "parserOptions": { + "ecmaVersion": 6 + } +} diff --git a/.gitignore b/.gitignore index 08f6d4e..32f0be5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,9 @@ # Logs -logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* -# dist -dist/* -#configuration -config/default.json - # Runtime data pids *.pid @@ -34,7 +28,7 @@ bower_components # node-waf configuration .lock-wscript -# Compiled binary addons (https://nodejs.org/api/addons.html) +# Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directories @@ -60,4 +54,17 @@ typings/ .yarn-integrity # dotenv environment variables file -.env \ No newline at end of file +.env + +dist/ +dist/* +.vscode/ +.idea +.idea/* +################################### + +# Ignore config directory +config/* + +# Besides examples +!config/*.example.json diff --git a/LICENSE b/LICENSE index 21e9899..c1a0219 100644 --- a/LICENSE +++ b/LICENSE @@ -1,15 +1,21 @@ -The MIT License (MIT) +MIT License -Copyright (c) 2016-2018 LBRY Inc +Copyright (c) 2018 LBRYio -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the -following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 3d0fba6..32ad90c 100644 --- a/README.md +++ b/README.md @@ -1,107 +1,2 @@ -## Bot for [LBRY's Discord](https://discord.gg/tgnNHf5) - -(This README will be updated along with bot updates) - -

-
Features: - -* Price bot displays price of lbc for currency given. - - - *Responds to `!price `* - -* Stats bot displays current market stats of lbc. - - - *Responds to `!stats`* - -* Hash bot displays current hashrate of lbc network. Also Includes to calculate given MH/s to LBC & fiat per hr, day, week, month. - - - *Responds to `!hash`* - - - *Responds to `!hash power `* - -* AltStats bot displays current market stats of specfied currency - - - *Responds to `!altstats `* - -* AltPrice bot displays current price for given coin and currency - - - *Responds to `!altprice `* - -* Github Release Notes bot displays release notes for current LBRY Desktop release. - - - *Responds to `!releasenotes`* - - - *(moderator only) `!releasenotes post` - send to release notes channel* - -* Purge Bot deletes X amount of messages. - - - *(moderator only) Responds to `!purge `* - -* Speech bot displays top claim from provided image name(coming soon posting to - speech). - - - *Responds to `!speech `* - -* Welcome bot sends Direct Message when new users join, - - - *(moderator only) Responds to `!welcome <@username>`* - -* Timeout bot assigns members the timeout roll for X-minutes where they are restricted from talking - - - *(moderator only) Responds to `!timeout <@username> `* - -* Roll Setter bot allows users to assign themselves rolls - - - *Responds to `!addrole ` - Adds to Role* - - - *Responds to `!delrole ` - Deletes from Role* - - - *Responds to `!roles` - List Available Roles* - -* LBRY URL Linker displays lbry:// urls as open.lbry.io links to make them clickable - -* LBRY claim bot displays recent publishes on the lbry protocol - -* IRC bot to connect an irc channel with discord - -* Spam Detection Bot to Prevent Discord Raids and Spammers - -* Dynamic plugin loading with permission support. - -
-

- -____ - -### Requirements - -* node > 8.0.0 -* npm > 0.12.x -* yarn ( install with npm install -g yarn if not installed ) -____ -### Installation - -Create a bot and get the bot's API Token: -https://discordapp.com/developers/applications/me - -Edit and rename default.json.example in /config, then cd to wunderbot directory -and run: - -``` -yarn install -node bot/bot.js -``` -____ -### Development - -Be sure to run the command below before working on any code, this ensures -prettier goes to work and keeps code to our standard. - -``` -yarn install --production=false -``` -to run prettier before submitting your code simply run the following in the bots root directory. - -``` -yarn precommit -``` +# wunderbot +A blazing fast discord bot diff --git a/bot/bot.js b/bot/bot.js deleted file mode 100644 index 392a822..0000000 --- a/bot/bot.js +++ /dev/null @@ -1,215 +0,0 @@ -'use strict'; - -// Load up libraries -const Discord = require('discord.js'); -// Load config! -let config = require('config'); -config = config.get('bot'); - -//load modules -const claimbot = require('./modules/claimbot.js'); -const commandsV2 = require('./modules/commandsV2.js'); -const supportbot = require('./modules/supportbot.js'); - -let aliases; -try { - aliases = require('./alias.json'); -} catch (e) { - console.log('No aliases defined'); - //No aliases defined - aliases = { - test: { - process: function(bot, msg) { - msg.channel.send('test'); - } - } - }; -} -let commands = { - ping: { - description: 'responds pong, useful for checking if bot is alive', - process: async function(bot, msg, suffix) { - let m = await msg.channel.send(msg.author + ' Ping?'); - m.edit(`Pong! Latency is ${m.createdTimestamp - msg.createdTimestamp}ms. API Latency is ${Math.round(bot.ping)}ms`); - if (suffix) { - msg.channel.send('note that !ping takes no arguments!'); - } - } - } -}; - -let bot = new Discord.Client(); - -bot.on('ready', function() { - console.log('Logged in! Serving in ' + bot.guilds.array().length + ' servers'); - require('./plugins.js').init(); - console.log('type ' + config.prefix + 'help in Discord for a commands list.'); - bot.user.setActivity(config.prefix + 'help', { type: 'LISTENING' }).catch(console.error); - - //initialize the claimbot (content bot) - claimbot.init(bot); - //initialize the commandsBot - commandsV2.init(bot); - //initialize the support bot - supportbot.init(bot); -}); - -process.on('unhandledRejection', err => { - console.log('unhandledRejection: ' + err); - process.exit(1); //exit node.js with an error -}); - -bot.on('disconnected', function() { - console.log('Disconnected!'); - process.exit(1); //exit node.js with an error -}); - -bot.on('error', function(error) { - console.log('error: ' + error); - process.exit(1); //exit node.js with an error -}); - -function checkMessageForCommand(msg, isEdit) { - //check if message is a command - if (msg.author.id != bot.user.id && msg.content.startsWith(config.prefix)) { - //check if user is Online - if (!msg.author.presence.status || msg.author.presence.status == 'offline' || msg.author.presence.status == 'invisible') { - msg.author.send('Please set your Discord Presence to Online to talk to the bot!').catch(function(error) { - msg.channel - .send( - msg.author + - ', Please enable Direct Messages from server members to communicate fully with our bot, ' + - 'it is located in the user setting area under Privacy & Safety tab, ' + - 'select the option allow direct messages from server members' - ) - .then(msg.channel.send('Please set your Discord Presence to Online to talk to the Bot!')); - return; - }); - } - let cmdTxt = msg.content.split(' ')[0].substring(config.prefix.length); - let suffix = msg.content.substring(cmdTxt.length + config.prefix.length + 1); //add one for the ! and one for the space - if (msg.isMentioned(bot.user)) { - try { - cmdTxt = msg.content.split(' ')[1]; - suffix = msg.content.substring(bot.user.mention().length + cmdTxt.length + config.prefix.length + 1); - } catch (e) { - //no command - msg.channel.send('Yes?'); - return; - } - } - let cmd = aliases.hasOwnProperty(cmdTxt) ? commands[aliases[cmdTxt]] : commands[cmdTxt]; - let alias = aliases[cmdTxt]; - if (alias) { - cmd = alias; - } else { - cmd = commands[cmdTxt]; - } - if (cmdTxt === 'help') { - //help is special since it iterates over the other commands - if (suffix) { - let cmds = suffix.split(' ').filter(function(cmd) { - return commands[cmd]; - }); - let info = ''; - for (let i = 0; i < cmds.length; i++) { - let cmd = cmds[i]; - info += '**' + config.prefix + cmd + '**'; - let usage = commands[cmd].usage; - if (usage) { - info += ' ' + usage; - } - let description = commands[cmd].description; - if (description instanceof Function) { - description = description(); - } - if (description) { - info += '\n\t' + description; - } - info += '\n'; - } - msg.channel.send(info); - } else { - msg.author.send('**Available Commands:**').then(function() { - let batch = ''; - let sortedCommands = Object.keys(commands).sort(); - for (let i in sortedCommands) { - let cmd = sortedCommands[i]; - let info = '**' + config.prefix + cmd + '**'; - let usage = commands[cmd].usage; - if (usage) { - info += ' ' + usage; - } - let description = commands[cmd].description; - if (description instanceof Function) { - description = description(); - } - if (description) { - info += '\n\t' + description; - } - let newBatch = batch + '\n' + info; - if (newBatch.length > 1024 - 8) { - //limit message length - msg.author.send(batch); - batch = info; - } else { - batch = newBatch; - } - } - if (batch.length > 0) { - msg.author.send(batch); - } - }); - } - } else if (cmd) { - // Add permission check here later on ;) - console.log('treating ' + msg.content + ' from UserID:' + msg.author + ' || UserName: ' + msg.author.username + ' as command'); - try { - cmd.process(bot, msg, suffix, isEdit); - } catch (e) { - let msgTxt = 'command ' + cmdTxt + ' failed :('; - if (config.debug) { - msgTxt += '\n' + e.stack; - } - msg.channel.send(msgTxt); - } - } else { - //msg.channel.send(cmdTxt + ' not recognized as a command!').then(message => message.delete(10000)); - } - } else { - //message isn't a command or is from us - //drop our own messages to prevent feedback loops - if (msg.author == bot.user) { - return; - } - - if (msg.author != bot.user && msg.isMentioned(bot.user)) { - msg.channel.send('yes?'); //using a mention here can lead to looping - } else { - } - } -} - -bot.on('message', msg => checkMessageForCommand(msg, false)); -bot.on('messageUpdate', (oldMessage, newMessage) => { - checkMessageForCommand(newMessage, true); -}); - -exports.addCommand = function(commandName, commandObject) { - try { - commands[commandName] = commandObject; - } catch (err) { - console.log(err); - } -}; -exports.addCustomFunc = function(customFunc) { - try { - customFunc(bot); - } catch (err) { - console.log(err); - } -}; -exports.commandCount = function() { - return Object.keys(commands).length; -}; -bot.login(config.token); diff --git a/bot/helpers.js b/bot/helpers.js deleted file mode 100644 index c869bd9..0000000 --- a/bot/helpers.js +++ /dev/null @@ -1,47 +0,0 @@ -let config = require('config'); -let permRanks = config.get('moderation'); -let speechBotChannels = config.get('speechbot'); -let priceBotChannels = config.get('pricebot'); -let ExcludedSpam = config.get('spamdetection'); -let hashBotChannels = config.get('hashbot'); -let statsBotChannels = config.get('statsbot'); - -// Checks if user is allowed to use a command only for mods/team members -exports.hasPerms = function(msg) { - return msg.member.roles !== null && msg.member.roles.some(r => permRanks.perms.includes(r.name)); -}; - -// Check if command was sent in dm -exports.inPrivate = function(msg) { - return msg.channel.type == 'dm'; -}; - -// Checks if Message was sent from a channel in speechBot Channels list -exports.hasSpeechBotChannels = function(msg) { - return speechBotChannels.channels.includes(msg.channel.id); -}; - -// Checks if Message was sent from a channel in priceBot Channels list -exports.hasPriceBotChannels = function(msg) { - return priceBotChannels.channels.includes(msg.channel.id); -}; - -// Checks if Message was sent from a Excluded channel -exports.hasExcludedSpamChannels = function(msg) { - return ExcludedSpam.channels.includes(msg.channel.id); -}; - -// Checks if Message was sent from a Excluded user -exports.hasExcludedSpamUsers = function(msg) { - return ExcludedSpam.users.includes(msg.author.id); -}; - -// Checks if Message was sent from a channel in hashBot Channels list -exports.hasHashBotChannels = function(msg) { - return hashBotChannels.channels.includes(msg.channel.id); -}; - -// Checks if Message was sent from a channel in statsBot Channels list -exports.hasStatsBotChannels = function(msg) { - retrun(statsBotChannels.channels.includes(msg.channel.id)); -}; diff --git a/bot/modules/altprice.js b/bot/modules/altprice.js deleted file mode 100644 index 365aa64..0000000 --- a/bot/modules/altprice.js +++ /dev/null @@ -1,71 +0,0 @@ -let needle = require('needle'); -let hasPriceBotChannels = require('../helpers.js').hasPriceBotChannels; -let inPrivate = require('../helpers.js').inPrivate; -let config = require('config'); -let ChannelID = config.get('pricebot').mainchannel; - -exports.commands = ['altprice']; - -exports.altprice = { - usage: ' ', - description: 'display price of specified alt coin from crypto compare\n**Example:** *!altprice ETH USD 100*', - process: function(bot, msg, suffix) { - let dt = new Date(); - let timestamp = dt.toUTCString(); - if (!hasPriceBotChannels(msg) && !inPrivate(msg)) { - msg.channel.send('Please use <#' + ChannelID + '> or DMs to talk to price bot.'); - return; - } - if (suffix !== '') { - words = suffix - .trim() - .split(' ') - .filter(function(n) { - return n !== ''; - }); - let currency1 = words[0].toUpperCase(); - if (words[1] == undefined) { - let currency2 = 'BTC'; - } else { - let currency2 = words[1].toUpperCase(); - } - if (words[2] == undefined) { - let amount = '1'; - } else { - if (getValidatedAmount(words[2]) === null) { - msg.reply('Please specify a number for '); - return; - } - let amount = words[2].toUpperCase(); - } - } else { - let currency1 = 'BTC'; - let currency2 = 'USD'; - let amount = '1'; - } - needle.get('https://min-api.cryptocompare.com/data/all/coinlist', function(error, response) { - if (error || response.statusCode !== 200) { - msg.channel.send('coinmarketcap API is not available'); - } else { - if (!response.body.Data.hasOwnProperty(currency1)) { - msg.channel.send('Invalid Alt Coin'); - return; - } - needle.get('https://min-api.cryptocompare.com/data/price?fsym=' + currency1 + '&tsyms=' + currency2, function(error, response) { - if (error || response.statusCode !== 200) { - msg.channel.send('coinmarketcap API is not available'); - } else { - let price = Number(response.body[currency2]); - let newprice = price * amount; - let message = amount + ' ' + currency1 + ' = ' + newprice.toFixed(8) + ' ' + currency2 + '\n' + '*Updated: ' + timestamp + '*'; - msg.channel.send(message); - } - }); - } - }); - function getValidatedAmount(amount) { - amount = amount.trim(); - return amount.match(/^[0-9]+(\.[0-9]+)?$/) ? amount : null; - } - } -}; diff --git a/bot/modules/claimbot.js b/bot/modules/claimbot.js deleted file mode 100644 index f4866d9..0000000 --- a/bot/modules/claimbot.js +++ /dev/null @@ -1,285 +0,0 @@ -'use strict'; - -let lbry; -let mongo; -let discordBot; -let moment = require('moment'); -let request = require('request'); -let sleep = require('sleep'); -let config = require('config'); -let channels = config.get('claimbot').channels; -const Discord = require('discord.js'); - -module.exports = { - init: init -}; - -function init(discordBot_) { - if (lbry) { - throw new Error('init was already called once'); - } - - discordBot = discordBot_; - - const MongoClient = require('mongodb').MongoClient; - MongoClient.connect(config.get('mongodb').url, function(err, db) { - if (err) { - throw err; - } - mongo = db; - - const bitcoin = require('bitcoin'); - lbry = new bitcoin.Client(config.get('lbrycrd')); - - console.log('Activating claimbot '); - discordBot.channels.get(channels[0]).send('activating claimbot'); - - setInterval(function() { - announceNewClaims(); - }, 60 * 1000); - announceNewClaims(); - }); -} - -function announceNewClaims() { - if (!mongo) { - discordPost('Failed to connect to mongo', {}); - return; - } - - if (!lbry) { - discordPost('Failed to connect to lbrycrd', {}); - return; - } - - Promise.all([getLastBlock(), lbryCall('getinfo')]) - .then(function([lastProcessedBlock, currentBlockInfo]) { - const currentHeight = currentBlockInfo['blocks']; - console.log(currentHeight); - if (lastProcessedBlock === null) { - console.log('First run. Setting last processed block to ' + currentHeight + ' and exiting.'); - return setLastBlock(currentHeight); - } - - const testBlock = false; - - if (testBlock || lastProcessedBlock < currentHeight) { - const firstBlockToProcess = testBlock || lastProcessedBlock + 1, - lastBlockToProcess = testBlock || currentHeight; - - console.log('Doing blocks ' + firstBlockToProcess + ' to ' + lastBlockToProcess); - return announceClaimsLoop(firstBlockToProcess, lastBlockToProcess, currentHeight); - } - }) - .catch(function(err) { - discordPost(err.stack, {}); - }); -} - -function announceClaimsLoop(block, lastBlock, currentHeight) { - let claimsFound = 0; - return lbryCall('getblockhash', block) - .then(function(blockHash) { - return lbryCall('getblock', blockHash); - }) - .then(function(blockData) { - return Promise.all(blockData['tx'].map(getClaimsForTxid)); - }) - .then(function(arrayOfClaimArrays) { - const claims = Array.prototype.concat(...arrayOfClaimArrays).filter(function(c) { - return !!c; - }); - console.log('Found ' + claims.length + ' claims in ' + block); - claimsFound = claims.length; - return Promise.all( - claims.map(function(claim) { - //the API has a rate limit. to avoid hitting it we must have a small delay between each message - //if claims were found in this block, then we wait, otherwise we don't - if (claimsFound > 0 && claim.hasOwnProperty('claimId')) sleep.msleep(300); - return announceClaim(claim, block, currentHeight); - }) - ); - }) - .then(function() { - return setLastBlock(block); - }) - .then(function() { - const nextBlock = block + 1; - if (nextBlock <= lastBlock) { - return announceClaimsLoop(nextBlock, lastBlock, currentHeight); - } - }); -} - -function announceClaim(claim, claimBlockHeight, currentHeight) { - console.log('' + claimBlockHeight + ': New claim for ' + claim['name']); - console.log(claim); - - //ignore supports for now - //the issue with supports is that they should be treated completely differently - //they are not new claims... - if (claim.hasOwnProperty('supported claimId')) return; - - let options = { - method: 'GET', - url: 'http://127.0.0.1:5000/claim_decode/' + claim['name'] - }; - - request(options, function(error, response, body) { - if (error) throw new Error(error); - try { - console.log(JSON.stringify(JSON.parse(body), null, 2)); - let claimData = null; - let channelName = null; - try { - body = JSON.parse(body); - if (body.hasOwnProperty('stream') && body.stream.hasOwnProperty('metadata')) { - claimData = body.stream.metadata; - channelName = body.hasOwnProperty('channel_name') ? body['channel_name'] : null; - } - } catch (e) { - console.error(e); - return; - } - - return Promise.all([lbryCall('getvalueforname', claim['name']), lbryCall('getclaimsforname', claim['name'])]).then(function([currentWinningClaim, claimsForName]) { - //console.log(JSON.stringify(claimData)); - let value = null; - if (claimData !== null) value = claimData; - else { - try { - value = JSON.parse(claim['value']); - } catch (e) {} - } - - const text = []; - - if (value) { - /* - if (channelName) { - text.push("Channel: lbry://" + channelName); - } - else - */ - console.log(value); - if (value['author']) { - text.push('author: ' + value['author']); - } - if (value['description']) { - text.push(value['description']); - } - // if (value['content_type']) - // { - // text.push("*Content Type:* " + value['content_type']); - // } - if (value['nsfw']) { - text.push('*Warning: Adult Content*'); - } - - //"fee":{"currency":"LBC","amount":186,"version":"_0_0_1","address":"bTGoFCakvQXvBrJg1b7FJzombFUu6iRJsk"} - if (value['fee']) { - const fees = []; - text.push('Price: ' + value['fee'].amount + ' *' + value['fee'].currency + '*'); - } - - if (!claim['is controlling']) { - // the following is based on https://lbry.io/faq/claimtrie-implementation - const lastTakeoverHeight = claimsForName['nLastTakeoverHeight'], - maxDelay = 4032, // 7 days of blocks at 2.5min per block - activationDelay = Math.min(maxDelay, Math.floor((claimBlockHeight - lastTakeoverHeight) / 32)), - takeoverHeight = claimBlockHeight + activationDelay, - secondsPerBlock = 161, // in theory this should be 150, but in practice its closer to 161 - takeoverTime = Date.now() + (takeoverHeight - currentHeight) * secondsPerBlock * 1000; - - text.push('Takes effect on approx. **' + moment(takeoverTime, 'x').format('MMMM Do [at] HH:mm [UTC]') + '** (block ' + takeoverHeight + ')'); - } - - const richEmbeded = { - author: { - name: value['author'] || 'Anonymous', - url: `http://open.lbry.io/${claim['name']}#${claim['claimId']}`, - icon_url: 'http://barkpost-assets.s3.amazonaws.com/wp-content/uploads/2013/11/3dDoge.gif' - }, - title: 'lbry://' + (channelName ? channelName + '/' : '') + claim['name'], - color: 1399626, - description: escapeSlackHtml(text.join('\n')), - footer: { - text: 'Block ' + claimBlockHeight + ' • Claim ID ' + claim['claimId'] - }, - image: { url: !value['nsfw'] ? value['thumbnail'] || '' : '' }, - url: 'http://open.lbry.io/' + claim['name'] - }; - - discordPost(text, richEmbeded); - } - }); - } catch (e) { - console.error(e); - } - }); -} - -function escapeSlackHtml(txt) { - return txt - .replace('&', '&') - .replace('<', '<') - .replace('>', '>'); -} - -function getClaimsForTxid(txid) { - return lbryCall('getclaimsfortx', txid).catch(function(err) { - // an error here most likely means the transaction is spent, - // which also means there are no claims worth looking at - return []; - }); -} - -function getLastBlock() { - return new Promise(function(resolve, reject) { - mongo.collection('claimbot').findOne({}, function(err, obj) { - if (err) { - reject(err); - } else if (!obj) { - mongo.collection('claimbot').createIndex({ last_block: 1 }, { unique: true }); - resolve(null); - } else { - resolve(obj.last_block); - } - }); - }); -} - -function setLastBlock(block) { - return new Promise(function(resolve, reject) { - mongo.collection('claimbot').findOneAndUpdate({ last_block: { $exists: true } }, { last_block: block }, { upsert: true, returnOriginal: false }, function(err, obj) { - if (!err && obj && obj.value.last_block != block) { - reject('Last value should be ' + block + ', but it is ' + obj.value.last_block); - } else { - resolve(); - } - }); - }); -} - -function discordPost(text, params) { - let richEmbeded = new Discord.RichEmbed(params); - - channels.forEach(channel => { - discordBot.channels - .get(channel) - .send('', richEmbeded) - .catch(console.error); - }); -} - -function lbryCall(...args) { - return new Promise(function(resolve, reject) { - lbry.cmd(...args, function(err, ...response) { - if (err) { - reject(new Error('JSONRPC call failed. Args: [' + args.join(', ') + ']')); - } else { - resolve(...response); - } - }); - }); -} diff --git a/bot/modules/commandsV2.js b/bot/modules/commandsV2.js deleted file mode 100644 index b35965a..0000000 --- a/bot/modules/commandsV2.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; -let commands = require('../../config/commands'); -const Discord = require('discord.js'); -let initialized = false; -let discordBot = null; -let commandsList = null; - -module.exports = { - init: init -}; - -function init(discordBot_) { - if (initialized) { - throw new Error('init was already called once'); - } - - discordBot = discordBot_; - - discordBot.on('message', checkForCommand); -} - -/** - * - * @param {String} message - */ -let checkForCommand = function(message) { - //build the command list ONLY on first run - let firstRun = false; - if (commandsList === null) { - firstRun = true; - commandsList = ''; - } - //for each message go through all the commands and check if there are any matches - Object.keys(commands).forEach(command => { - //during the first run also build the cache - if (firstRun) commandsList += command + ', '; - - //if a command is found - if (!message.author.bot && message.content.toLowerCase().indexOf(command.toLowerCase()) >= 0 && commands[command].operation === 'send') { - //send a message to the channel according to the config - message.channel.send('', new Discord.RichEmbed(commands[command].bundle)); - } - }); - //if the user is requesting the list of commands, then print it - if (!message.author.bot && message.content.toLowerCase().indexOf('!helpcommands') >= 0) { - let bundle = commands['!helpcommands'].bundle; - commandsList = commandsList.replace(/,\s$/g, ''); - bundle.description = '**' + commandsList + '**'; - message.channel.send('', new Discord.RichEmbed(bundle)); - } -}; diff --git a/bot/modules/example.js b/bot/modules/example.js deleted file mode 100644 index 2f57332..0000000 --- a/bot/modules/example.js +++ /dev/null @@ -1,24 +0,0 @@ -/* -// Example #1 Command(use this to make your Commands with triggers like !demo) - exports.commands = [ - "demo" // command name that will be used for next lines of code below - ] - - exports.demo = { - usage: "", //command usage like !demo <@username>, exclude !demo - description: 'description of command', //the description of command for !help command - process: function(bot,msg,suffix){ - // Here the bot,msg and suffix is available, this function can be async if needed. - } - } - -// Example #2 Function(use this to make your Functions that dont need trigger words unlike !demo) - exports.custom = [ - "myFunction" //change this to your function name - ] - - exports.myFunction = function(bot) { - // Other functions that need to be ran once on bootup! - // For example a timed function and or some init stuff.. - } -*/ diff --git a/bot/modules/hash.js b/bot/modules/hash.js deleted file mode 100644 index a545870..0000000 --- a/bot/modules/hash.js +++ /dev/null @@ -1,209 +0,0 @@ -let needle = require('needle'); -let config = require('config'); -let hasHashBotChannels = require('../helpers.js').hasHashBotChannels; -let inPrivate = require('../helpers.js').inPrivate; -let ChannelID = config.get('hashbot').mainchannel; -exports.commands = [ - 'hash' // command that is in this file, every command needs it own export as shown below -]; - -exports.custom = ['timedhash']; - -exports.timedhash = function(bot) { - setInterval(function() { - sendMiningInfo(bot); - }, 6 * 60 * 60 * 1000); - - function sendMiningInfo(bot) { - needle.get('https://explorer.lbry.io/api/v1/status', function(error, response) { - if (error || response.statusCode !== 200) { - msg.channel.send('Explorer API is not available'); - } else { - let data = response.body; - let height = Number(data.status.height); - let hashrate = data.status.hashrate; - let difficulty = Number(data.status.difficulty); - needle.get('https://whattomine.com/coins/164.json', function(error, response) { - if (error || response.statusCode !== 200) { - msg.channel.send('whattomine API is not available'); - } - let data = response.body; - let reward = Number(data.block_reward); - let block_time = Number(data.block_time); - let difficulty24 = Number(data.difficulty24); - let description = - 'Hashrate: ' + - numberWithCommas(hashrate) + - '\n' + - 'Difficulty: ' + - numberWithCommas(difficulty.toFixed(0)) + - '\n' + - 'Difficulty 24 Hour Average: ' + - numberWithCommas(difficulty24.toFixed(0)) + - '\n' + - 'Current block: ' + - numberWithCommas(height.toFixed(0)) + - '\n' + - 'Block Time: ' + - numberWithCommas(block_time.toFixed(0)) + - ' seconds \n' + - 'Block Reward: ' + - numberWithCommas(reward.toFixed(0)) + - ' LBC \n' + - 'Sources: https://explorer.lbry.io & \n' + - 'https://whattomine.com/coins/164-lbc-lbry'; - const embed = { - description: description, - color: 7976557, - author: { - name: 'LBRY Network Stats', - icon_url: 'https://i.imgur.com/yWf5USu.png' - } - }; - bot.channels.get(ChannelID).send({ embed }); - return; - }); - } - }); - function numberWithCommas(x) { - return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); - } - } -}; - -exports.hash = { - usage: '', - description: 'Displays current Hashrate of Network\n**!hash power **\n Displays potential Earnings For Given Hashrate', - process: function(bot, msg, suffix) { - let command = '!hash'; - let words = suffix - .trim() - .split(' ') - .filter(function(n) { - return n !== ''; - }); - let profitcommand = words[0]; - let myhashrate = words[1]; - if (profitcommand == 'power') { - sendProfitInfo(bot, msg, suffix); - return; - } else { - sendMiningInfo(bot, msg, suffix); - return; - } - - function sendMiningInfo(bot, msg, suffix) { - if (!inPrivate(msg) && !hasHashBotChannels(msg)) { - msg.channel.send('Please use <#' + ChannelID + '> or DMs to talk to hash bot.'); - return; - } - needle.get('https://explorer.lbry.io/api/v1/status', function(error, response) { - if (error || response.statusCode !== 200) { - msg.channel.send('Explorer API is not available'); - } else { - let data = response.body; - let height = Number(data.status.height); - let hashrate = data.status.hashrate; - let difficulty = Number(data.status.difficulty); - needle.get('https://whattomine.com/coins/164.json', function(error, response) { - if (error || response.statusCode !== 200) { - msg.channel.send('whattomine API is not available'); - } - let data = response.body; - let reward = Number(data.block_reward); - let block_time = Number(data.block_time); - let difficulty24 = Number(data.difficulty24); - let description = - 'Hashrate: ' + - numberWithCommas(hashrate) + - '\n' + - 'Difficulty: ' + - numberWithCommas(difficulty.toFixed(0)) + - '\n' + - 'Difficulty 24 Hour Average: ' + - numberWithCommas(difficulty24.toFixed(0)) + - '\n' + - 'Current block: ' + - numberWithCommas(height.toFixed(0)) + - '\n' + - 'Block Time: ' + - numberWithCommas(block_time.toFixed(0)) + - ' seconds \n' + - 'Block Reward: ' + - numberWithCommas(reward.toFixed(0)) + - ' LBC \n' + - 'Sources: https://explorer.lbry.io & \n' + - 'https://whattomine.com/coins/164-lbc-lbry'; - const embed = { - description: description, - color: 7976557, - author: { - name: 'LBRY Network Stats', - icon_url: 'https://i.imgur.com/yWf5USu.png' - } - }; - msg.channel.send({ embed }); - return; - }); - } - }); - } - function sendProfitInfo(bot, msg, suffix) { - needle.get('https://whattomine.com/coins/164.json', function(error, response) { - if (error || response.statusCode !== 200) { - msg.channel.send('whattomine API is not available'); - } else { - words = suffix - .trim() - .split(' ') - .filter(function(n) { - return n !== ''; - }); - let myhashrate = words[1]; - if (myhashrate == '' || myhashrate == null || myhashrate == undefined || myhashrate == ' ') { - myhashrate = '100'; - } - let Diff = response.body.difficulty24; - let Reward = response.body.block_reward; - let myHash = Number(myhashrate); - let LBC = myHash / 2000 * (1 / ((Diff * 2) ^ 32) * Reward) * 3600; - let LBC24 = myHash / 2000 * (1 / ((Diff * 2) ^ 32) * Reward) * 86400; - let LBC1w = myHash / 2000 * (1 / ((Diff * 2) ^ 32) * Reward) * 604800; - let LBC1m = myHash / 2000 * (1 / ((Diff * 2) ^ 32) * Reward) * 2628000; - let message = - 'With **' + - myHash + - ' Mh/s** and Average 24 hour Difficulty: **' + - Diff.toFixed(0) + - '**\n' + - 'You can potentially earn the following amounts of **LBC**: \n' + - '1 Hour = **' + - LBC.toFixed(4) + - '** \n' + - '1 Day = **' + - LBC24.toFixed(2) + - '** \n' + - '1 Week = **' + - LBC1w.toFixed(4) + - '** \n' + - '1 Month = **' + - LBC1m.toFixed(4) + - '** \n'; - const embed = { - description: message, - color: 7976557, - author: { - name: 'Hashing Power Calculator!', - icon_url: 'https://i.imgur.com/nKHVQgq.png' - } - }; - msg.channel.send({ embed }); - return; - } - }); - } - function numberWithCommas(x) { - return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); - } - } -}; diff --git a/bot/modules/ircbridge.js b/bot/modules/ircbridge.js deleted file mode 100644 index 3154fac..0000000 --- a/bot/modules/ircbridge.js +++ /dev/null @@ -1,8 +0,0 @@ -const discordIRC = require('elmadev-discord-irc').default; -const config = require('config'); -const ircconfig = config.get('irc'); -exports.custom = ['irc']; - -exports.irc = function(bot) { - discordIRC([ircconfig]); -}; diff --git a/bot/modules/lbrylink.js b/bot/modules/lbrylink.js deleted file mode 100644 index cadac2f..0000000 --- a/bot/modules/lbrylink.js +++ /dev/null @@ -1,44 +0,0 @@ -let inPrivate = require('../helpers.js').inPrivate; -let { RichEmbed } = require('discord.js'); -exports.custom = [ - 'lbrylink' //change this to your function name -]; - -exports.lbrylink = async function(bot, msg, suffix) { - bot.on('message', msg => { - if (inPrivate(msg)) { - return; - } - if (msg.content.includes('lbry://')) { - try { - // Extract the URL(s). - const urls = msg.content - .replace(new RegExp("(lbry:\\/\\/)", "g"), "https://open.lbry.io/") - .match(/\bhttps?:\/\/\S+/gi) - .filter(url => url !== "https://open.lbry.io/"); - const cleanURLs = []; - for (const i in urls) { - // Check if Username Was Supplied - const user = urls[i].match("<@.*>"); - if (user) { - const { username } = msg.mentions.users.get(user[0].slice(2, -1)); - urls[i] = urls[i].replace(user[0], `@${username}`); - } - // Push clean URLs to the array. - cleanURLs.push(urls[i]); - } - if (cleanURLs.length < 1) return; - const linkEmbed = new RichEmbed(); - linkEmbed - .setAuthor("LBRY Linker") - .setDescription("I see you tried to post a LBRY URL, here's a friendly hyperlink to share and for others to access your content with a single click:") - .setColor(7976557); - cleanURLs.forEach(url => linkEmbed.addField("Open with LBRY:", url, true)); - return msg.channel.send({embed: linkEmbed}); - } catch (e) { - console.log(e); - msg.channel.send("Something went wrong when trying to run the lbrylinker, contact a moderator."); - } - } - }); -}; diff --git a/bot/modules/moderation.js b/bot/modules/moderation.js deleted file mode 100644 index 004f6a3..0000000 --- a/bot/modules/moderation.js +++ /dev/null @@ -1,15 +0,0 @@ -/*'use strict'; -// Moderation module, handles banning and kicking and more... -let hasPerms = require('../helpers.js').hasPerms; - -exports.commands = [ - "m" -] - -exports.m = { - usage: " ", - description: 'ban: bans the user with the reason\n kick: get adress for your deposits\n', - process: function(bot,msg,suffix){ - console.log(msg.member.user); - } -}*/ diff --git a/bot/modules/price.js b/bot/modules/price.js deleted file mode 100644 index 1931fe5..0000000 --- a/bot/modules/price.js +++ /dev/null @@ -1,650 +0,0 @@ -'use strict'; -let jp = require('jsonpath'); -let moment = require('moment'); -let numeral = require('numeral'); -let request = require('request'); -let config = require('config'); -let hasPriceBotChannels = require('../helpers.js').hasPriceBotChannels; -let inPrivate = require('../helpers.js').inPrivate; -let ChannelID = config.get('pricebot').mainchannel; - -exports.commands = ['price']; - -exports.price = { - usage: ' ', - description: 'displays price of lbc', - process: function(bot, msg, suffix) { - var options = { - defaultCurrency: 'BTC', - - // supported currencies and api steps to arrive at the final value - currencies: { - USD: { - steps: ['LBCBTC', 'BTCUSD'], - format: '$0,0.00', - sign: 'USD ' - }, - GBP: { - steps: ['LBCBTC', 'BTCGBP'], - format: '£0,0.00', - sign: '£' - }, - AUD: { - steps: ['LBCBTC', 'BTCAUD'], - format: '$0,0.00', - sign: 'AUD ' - }, - BRL: { - steps: ['LBCBTC', 'BTCBRL'], - format: 'R$0,0.00', - sign: 'R$' - }, - CAD: { - steps: ['LBCBTC', 'BTCCAD'], - format: '$0,0.00', - sign: 'CAD ' - }, - CHF: { - steps: ['LBCBTC', 'BTCCHF'], - format: 'CHF 0,0.00', - sign: 'CHF' - }, - CLP: { - steps: ['LBCBTC', 'BTCCLP'], - format: '$0,0.00', - sign: 'CLP ' - }, - CNY: { - steps: ['LBCBTC', 'BTCCNY'], - format: '¥0,0.00', - sign: '¥' - }, - DKK: { - steps: ['LBCBTC', 'BTCDKK'], - format: 'kr 0,0.00', - sign: 'kr' - }, - EUR: { - steps: ['LBCBTC', 'BTCEUR'], - format: '€0,0.00', - sign: '€' - }, - HKD: { - steps: ['LBCBTC', 'BTCHKD'], - format: '$0,0.00', - sign: 'HKD ' - }, - INR: { - steps: ['LBCBTC', 'BTCINR'], - format: '₹0,0.00', - sign: '₹' - }, - ISK: { - steps: ['LBCBTC', 'BTCISK'], - format: 'kr 0,0.00', - sign: 'kr' - }, - JPY: { - steps: ['LBCBTC', 'BTCJPY'], - format: '¥0,0.00', - sign: '¥' - }, - KRW: { - steps: ['LBCBTC', 'BTCKRW'], - format: '₩0,0.00', - sign: '₩' - }, - NZD: { - steps: ['LBCBTC', 'BTCNZD'], - format: '$0,0.00', - sign: 'NZD ' - }, - PLN: { - steps: ['LBCBTC', 'BTCPLN'], - format: 'zł 0,0.00', - sign: 'zł' - }, - RUB: { - steps: ['LBCBTC', 'BTCRUB'], - format: 'RUB 0,0.00', - sign: 'RUB' - }, - SEK: { - steps: ['LBCBTC', 'BTCSEK'], - format: 'kr 0,0.00', - sign: 'kr' - }, - SGD: { - steps: ['LBCBTC', 'BTCSGD'], - format: '$0,0.00', - sign: 'SGD ' - }, - THB: { - steps: ['LBCBTC', 'BTCTHB'], - format: '฿0,0.00', - sign: '฿' - }, - TWD: { - steps: ['LBCBTC', 'BTCTWD'], - format: 'NT$0,0.00', - sign: 'NT$' - }, - MYR: { - steps: ['LBCBTC', 'BTCMYR'], - format: 'RM0,0.00', - sign: 'RM' - }, - IDR: { - steps: ['LBCBTC', 'BTCIDR'], - format: 'Rp0,0.00', - sign: 'Rp' - }, - VND: { - steps: ['LBCBTC', 'BTCVND'], - format: '₫ 0,0.00', - sign: '₫' - }, - PHP: { - steps: ['LBCBTC', 'BTCPHP'], - format: '₱ 0,0.00', - sign: '₱' - }, - BND: { - steps: ['LBCBTC', 'BTCBND'], - format: 'B$ 0,0.00', - sign: 'B$' - }, - SAR: { - steps: ['LBCBTC', 'BTCSAR'], - format: 'SR0,0.00', - sign: 'SR' - }, - MXN: { - steps: ['LBCBTC', 'BTCMXN'], - format: 'Mex$ 0,0.00', - sign: 'Mex$' - }, - TRY: { - steps: ['LBCBTC', 'BTCTRY'], - format: '₺ 0,0.00', - sign: '₺' - }, - MMK: { - steps: ['LBCBTC', 'BTCMMK'], - format: 'K 0,0.00', - sign: 'K' - }, - KHR: { - steps: ['LBCBTC', 'BTCKHR'], - format: '៛ 0,0.00', - sign: '៛' - }, - AED: { - steps: ['LBCBTC', 'BTCAED'], - format: 'د.إ0,0.00', - sign: 'د.إ' - }, - ZAR: { - steps: ['LBCBTC', 'BTCZAR'], - format: 'R 0,0.00', - sign: 'R' - }, - PGK: { - steps: ['LBCBTC', 'BTCPGK'], - format: 'K 0,0.00', - sign: 'K' - }, - EGP: { - steps: ['LBCBTC', 'BTCEGP'], - format: 'EGP 0,0.00', - sign: 'EGP' - }, - NOK: { - steps: ['LBCBTC', 'BTCNOK'], - format: 'kr0,0.00', - sign: 'kr' - }, - HUF: { - steps: ['LBCBTC', 'BTCHUF'], - format: 'ft0,0.00', - sign: 'ft' - }, - ALL: { - steps: ['LBCBTC', 'BTCALL'], - format: 'L 0,0.00', - sign: 'L' - }, - GEL: { - steps: ['LBCBTC', 'BTCGEL'], - format: 'GEL 0,0.00', - sign: 'GEL' - }, - MDL: { - steps: ['LBCBTC', 'BTCMDL'], - format: 'lei 0,0.00', - sign: 'lei' - }, - BAM: { - steps: ['LBCBTC', 'BTCBAM'], - format: 'KM 0,0.00', - sign: 'KM' - }, - BAM: { - steps: ['LBCBTC', 'BTCBAM'], - format: 'KM 0,0.00', - sign: 'KM' - }, - AZN: { - steps: ['LBCBTC', 'BTCAZN'], - format: '₼ 0,0.00', - sign: '₼' - }, - AMD: { - steps: ['LBCBTC', 'BTCAMD'], - format: '֏ 0,0.00', - sign: '֏' - }, - BYN: { - steps: ['LBCBTC', 'BTCBYN'], - format: 'Br 0,0.00', - sign: 'Br' - }, - BTN: { - steps: ['LBCBTC', 'BTCBTN'], - format: 'Nu 0,0.00', - sign: 'Nu' - }, - NPR: { - steps: ['LBCBTC', 'BTCNPR'], - format: 'रु 0,0.00', - sign: 'रु' - }, - BDT: { - steps: ['LBCBTC', 'BTCBDT'], - format: '৳ 0,0.00', - sign: '৳' - }, - PKR: { - steps: ['LBCBTC', 'BTCPKR'], - format: 'Rs 0,0.00', - sign: 'Rs' - }, - ARS: { - steps: ['LBCBTC', 'BTCARS'], - format: '$ 0,0.00', - sign: '$' - }, - PLN: { - steps: ['LBCBTC', 'BTCPLN'], - format: 'zł 0,0.00', - sign: 'zł' - }, - HRK: { - steps: ['LBCBTC', 'BTCHRK'], - format: 'kn 0,0.00', - sign: 'kn' - }, - BTC: { - steps: ['LBCBTC'], - format: '0,0[.][00000000] BTC', - sign: 'BTC' - } - }, - - // api steps - api: { - LBCBTC: { - url: 'https://bittrex.com/api/v1.1/public/getticker?market=BTC-LBC', - path: '$.result.Bid' - }, - BTCUSD: { - url: 'https://blockchain.info/ticker', - path: '$.USD.buy' - }, - BTCGBP: { - url: 'https://blockchain.info/ticker', - path: '$.GBP.buy' - }, - BTCAUD: { - url: 'https://blockchain.info/ticker', - path: '$.AUD.buy' - }, - BTCBRL: { - url: 'https://blockchain.info/ticker', - path: '$.BRL.buy' - }, - BTCCAD: { - url: 'https://blockchain.info/ticker', - path: '$.CAD.buy' - }, - BTCCHF: { - url: 'https://blockchain.info/ticker', - path: '$.CHF.buy' - }, - BTCMYR: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=MYR', - path: '$.MYR' - }, - BTCCLP: { - url: 'https://blockchain.info/ticker', - path: '$.CLP.buy' - }, - BTCCNY: { - url: 'https://blockchain.info/ticker', - path: '$.CNY.buy' - }, - BTCDKK: { - url: 'https://blockchain.info/ticker', - path: '$.DKK.buy' - }, - BTCEUR: { - url: 'https://blockchain.info/ticker', - path: '$.EUR.buy' - }, - BTCHKD: { - url: 'https://blockchain.info/ticker', - path: '$.HKD.buy' - }, - BTCINR: { - url: 'https://blockchain.info/ticker', - path: '$.INR.buy' - }, - BTCISK: { - url: 'https://blockchain.info/ticker', - path: '$.ISK.buy' - }, - BTCJPY: { - url: 'https://blockchain.info/ticker', - path: '$.JPY.buy' - }, - BTCKRW: { - url: 'https://blockchain.info/ticker', - path: '$.KRW.buy' - }, - BTCNZD: { - url: 'https://blockchain.info/ticker', - path: '$.NZD.buy' - }, - BTCPLN: { - url: 'https://blockchain.info/ticker', - path: '$.PLN.buy' - }, - BTCRUB: { - url: 'https://blockchain.info/ticker', - path: '$.RUB.buy' - }, - BTCSEK: { - url: 'https://blockchain.info/ticker', - path: '$.SEK.buy' - }, - BTCSGD: { - url: 'https://blockchain.info/ticker', - path: '$.SGD.buy' - }, - BTCTHB: { - url: 'https://blockchain.info/ticker', - path: '$.THB.buy' - }, - BTCTWD: { - url: 'https://blockchain.info/ticker', - path: '$.TWD.buy' - }, - BTCBND: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=BND', - path: '$.BND' - }, - BTCVND: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=VND', - path: '$.VND' - }, - BTCPHP: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=PHP', - path: '$.PHP' - }, - BTCSAR: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=SAR', - path: '$.SAR' - }, - BTCMXN: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=MXN', - path: '$.MXN' - }, - BTCTRY: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=TRY', - path: '$.TRY' - }, - BTCMMK: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=MMK', - path: '$.MMK' - }, - BTCKHR: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=KHR', - path: '$.KHR' - }, - BTCAED: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=AED', - path: '$.AED' - }, - BTCZAR: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=ZAR', - path: '$.ZAR' - }, - BTCPGK: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=PGK', - path: '$.PGK' - }, - BTCNOK: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=NOK', - path: '$.NOK' - }, - BTCHUF: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=HUF', - path: '$.HUF' - }, - BTCALL: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=ALL', - path: '$.ALL' - }, - BTCEGP: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=EGP', - path: '$.EGP' - }, - BTCGEL: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=GEL', - path: '$.GEL' - }, - BTCMDL: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=MDL', - path: '$.MDL' - }, - BTCBAM: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=BAM', - path: '$.BAM' - }, - BTCKZT: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=KZT', - path: '$.KZT' - }, - BTCAZN: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=AZN', - path: '$.AZN' - }, - BTCAMD: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=AMD', - path: '$.AMD' - }, - BTCBYN: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=BYN', - path: '$.BYN' - }, - BTCBTN: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=BTN', - path: '$.BTN' - }, - BTCNPR: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=NPR', - path: '$.NPR' - }, - BTCBDT: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=BDT', - path: '$.BDT' - }, - BTCPKR: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=PKR', - path: '$.PKR' - }, - BTCARS: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=ARS', - path: '$.ARS' - }, - BTCPLN: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=PLN', - path: '$.PLN' - }, - BTCHRK: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=HRK', - path: '$.HRK' - }, - BTCIDR: { - url: 'https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=IDR', - path: '$.IDR' - } - }, - - // display date/time format - dtFormat: 'Do MMM YYYY h:mma [UTC]', - - // refresh rate in milliseconds to retrieve a new price (default to 10 minutes) - refreshTime: 100000 - }; - var words = suffix - .trim() - .split(' ') - .filter(function(n) { - return n !== ''; - }); - - var currency = words.length > 0 ? words[0].toUpperCase() : options.defaultCurrency; - var amount = words.length > 1 ? parseFloat(words[1], 10) : 1; - var showHelp = isNaN(amount) || Object.keys(options.currencies).indexOf(currency) === -1; - // store the last retrieved rate - var cachedRates = {}; - var command = '!price'; - - var currencies = Object.keys(options.currencies); - for (var i = 0; i < currencies.length; i++) { - cachedRates[currencies[i]] = { - rate: 0, - time: null - }; - } - if (showHelp) { - doHelp(bot, msg, suffix); - } else { - if (!hasPriceBotChannels(msg) && !inPrivate(msg)) { - msg.channel.send('Please use <#' + ChannelID + '> or DMs to talk to price bot.'); - return; - } - doSteps(bot, currency, amount); - } - - function doHelp(bot, msg, suffix) { - if (!hasPriceBotChannels(msg) && !inPrivate(msg)) { - msg.channel.send('Please use <#' + ChannelID + '> or DMs to talk to price bot.'); - return; - } - var message = - '**' + - command + - '**: show the price of 1 LBC in ' + - options.defaultCurrency + - '\n' + - '**' + - command + - ' help**: this message\n' + - '**' + - command + - ' CURRENCY**: show the price of 1 LBC in CURRENCY. Supported values for CURRENCY are Listed Below\n' + - '**' + - command + - ' CURRENCY AMOUNT**: show the price of AMOUNT LBC in CURRENCY\n' + - '**Supported Currencies:** *usd*, *gbp*, *eur*, *aud*, *brl*, *cad*, *chf*, *clp*, *cny*, *dkk*, *hkd*, *inr*, *isk*, *jpy*, *krw*, *nzd*, *pln* ,*rub*, *sek*, *sgd*, *thb*, *twd*, *myr*, *bnd*,*vnd*, *php*, *sar*, *mxn*, *try*, *mmk*, *khr*, *aed*, *zar*, *pgk*, *egp*,*nok*, *hrk*, *huf*, *all*, *gel*, *mdl*, *bam* ,*kzt*, *azn*, *amd*, *byn*, *btn*, *npr*, *bdt*, *pkr*, *ars*, *pln*, *idr* and *btc* (case-insensitive)'; - msg.channel.send(message); - } - - function formatMessage(amount, rate, option) { - var cur = option.sign; - var value = numeral(rate.rate * amount).format(option.format); - return '*' + numeral(amount).format('0,0[.][00000000]') + ' LBC = ' + cur + ' ' + value + '*\n_last updated ' + rate.time.utc().format(options.dtFormat) + '_'; - } - - function doSteps(bot, currency, amount) { - var option = options.currencies[currency]; - var shouldReload = true; - if (cachedRates[currency]) { - var cache = cachedRates[currency]; - shouldReload = cache.time === null || moment().diff(cache.time) >= options.refreshTime; - if (!shouldReload) { - var message = formatMessage(amount, cache, option); - msg.channel.send(message); - } - } - - if (shouldReload) { - // copy the steps array - var steps = []; - for (var i = 0; i < option.steps.length; i++) { - steps.push(option.steps[i]); - } - - processSteps(bot, currency, 0, amount, steps, option); - } - } - - function processSteps(bot, currency, rate, amount, steps, option) { - if (steps.length > 0) { - var pairName = steps[0]; - if (!options.api[pairName]) { - msg.channel.send('There was a configuration error. ' + pairName + ' pair was not found.'); - return; - } - - var pair = options.api[pairName]; - request.get(pair.url, function(error, response, body) { - if (error) { - msg.channel.send(err.message ? err.message : 'The request could not be completed at this time. Please try again later.'); - return; - } - var pairRate = 0; - try { - pairRate = jp.query(JSON.parse(body), pair.path); - if (Array.isArray(pairRate) && pairRate.length > 0) { - pairRate = pairRate[0]; - } - } catch (ignored) { - // invalid response or pair rate - } - - if (pairRate > 0) { - rate = rate === 0 ? pairRate : rate * pairRate; - steps.shift(); - if (steps.length > 0) { - processSteps(bot, currency, rate, amount, steps, option); - return; - } - - // final step, cache and then response - var result = { - rate: rate, - time: moment() - }; - cachedRates[currency] = result; - msg.channel.send(formatMessage(amount, result, option)); - } else { - msg.channel.send('The rate returned for the ' + pairName + ' pair was invalid.'); - } - }); - } - } - } -}; diff --git a/bot/modules/purge.js b/bot/modules/purge.js deleted file mode 100644 index a287ae5..0000000 --- a/bot/modules/purge.js +++ /dev/null @@ -1,43 +0,0 @@ -let hasPerms = require('../helpers.js').hasPerms; -let inPrivate = require('../helpers.js').inPrivate; - -exports.commands = [ - 'purge' // command that is in this file, every command needs it own export as shown below -]; - -exports.purge = { - usage: '', - description: 'Deletes Messages', - process: function(bot, msg, suffix) { - if (inPrivate(msg)) { - msg.channel.send("You Cant Purge Message In DM's!"); - return; - } - if (hasPerms(msg)) { - if (!suffix) { - var newamount = '2'; - } else { - var amount = Number(suffix); - var adding = 1; - var newamount = amount + adding; - } - let messagecount = newamount.toString(); - msg.channel - .fetchMessages({ - limit: messagecount - }) - .then(messages => { - msg.channel.bulkDelete(messages); - // Logging the number of messages deleted on both the channel and console. - msg.channel.send('Deletion of messages successful. \n Total messages deleted including command: ' + newamount).then(message => message.delete(5000)); - console.log('Deletion of messages successful. \n Total messages deleted including command: ' + newamount); - }) - .catch(err => { - console.log('Error while doing Bulk Delete'); - console.log(err); - }); - } else { - msg.channel.send('only moderators can use this command!').then(message => message.delete(5000)); - } - } -}; diff --git a/bot/modules/releasenotes.js b/bot/modules/releasenotes.js deleted file mode 100644 index 2594486..0000000 --- a/bot/modules/releasenotes.js +++ /dev/null @@ -1,171 +0,0 @@ -let request = require('request'); -let config = require('config'); -let hasPerms = require('../helpers.js').hasPerms; -let inPrivate = require('../helpers.js').inPrivate; -let ChannelID = config.get('gitrelease').channel; - -exports.commands = [ - 'releasenotes' // command that is in this file, every command needs it own export as shown below -]; - -exports.releasenotes = { - usage: '', - description: 'gets current release notes from GITHUB', - process: function(bot, msg, suffix) { - const headers = { - 'Content-Type': 'application/json', - 'User-Agent': 'Super Agent/0.0.1' - }; - // Configure the request - const options = { - url: 'https://api.github.com/repos/lbryio/lbry-desktop/releases/latest', - method: 'GET', - headers: headers - }; - - // Start the request - let message; - request(options, function(error, response, body) { - let releasemessage = JSON.parse(body).body; - let releasename = JSON.parse(body).name; - let releasedate = JSON.parse(body).published_at; - let releaseurl = JSON.parse(body).html_url; - if (releasemessage.length < 2000) { - message = { - embed: { - title: '*Download ' + releasename + ' here!*', - description: releasemessage, - url: releaseurl, - color: 7976557, - timestamp: releasedate, - author: { - name: 'LBRY Desktop release Notes for ' + releasename, - icon_url: 'http://www.pngall.com/wp-content/uploads/2016/04/Github-PNG-Image.png' - }, - footer: { - icon_url: 'https://i.imgur.com/yWf5USu.png', - text: 'LBRY Desktop Updated ' - } - } - }; - if (inPrivate(msg)) { - msg.channel.send(message); - return; - } - if (hasPerms(msg) && suffix === 'post') { - bot.channels.get(ChannelID).send(message); - } else { - msg.channel.send(msg.author + ' Release notes sent via DM'); - msg.author.send(message); - } - } else { - message = releasemessage - .trim() - .split('###') - .filter(function(n) { - return n !== ''; - }); - let releasemessage1 = message[0]; - let releasemessage2 = message[1]; - let releasemessage3 = message[2]; - let releasemessage4 = message[3]; - let releasemessage5 = message[4]; - let message1 = { - embed: { - title: '*Download ' + releasename + ' here!*', - description: releasemessage1, - url: releaseurl, - color: 7976557, - timestamp: releasedate, - author: { - name: 'LBRY Desktop Release Notes for ' + releasename, - icon_url: 'http://www.pngall.com/wp-content/uploads/2016/04/Github-PNG-Image.png' - }, - footer: { - icon_url: 'https://i.imgur.com/yWf5USu.png', - text: 'LBRY Desktop Updated ' - } - } - }; - let message2 = { - embed: { - description: releasemessage2, - color: 7976557, - timestamp: releasedate, - author: { - icon_url: 'http://www.pngall.com/wp-content/uploads/2016/04/Github-PNG-Image.png' - }, - footer: { - icon_url: 'https://i.imgur.com/yWf5USu.png', - text: 'LBRY Desktop Updated ' - } - } - }; - let message3 = { - embed: { - description: releasemessage3, - color: 7976557, - timestamp: releasedate, - author: { - icon_url: 'http://www.pngall.com/wp-content/uploads/2016/04/Github-PNG-Image.png' - }, - footer: { - icon_url: 'https://i.imgur.com/yWf5USu.png', - text: 'LBRY Desktop Updated ' - } - } - }; - let message4 = { - embed: { - description: releasemessage4, - color: 7976557, - timestamp: releasedate, - author: { - icon_url: 'http://www.pngall.com/wp-content/uploads/2016/04/Github-PNG-Image.png' - }, - footer: { - icon_url: 'https://i.imgur.com/yWf5USu.png', - text: 'LBRY Desktop Updated ' - } - } - }; - let message5 = { - embed: { - description: releasemessage5, - color: 7976557, - timestamp: releasedate, - author: { - icon_url: 'http://www.pngall.com/wp-content/uploads/2016/04/Github-PNG-Image.png' - }, - footer: { - icon_url: 'https://i.imgur.com/yWf5USu.png', - text: 'LBRY Desktop Updated ' - } - } - }; - if (inPrivate(msg)) { - msg.channel.send(message1); - msg.channel.send(message2); - msg.channel.send(message3); - msg.channel.send(message4); - msg.channel.send(message5); - return; - } - if (hasPerms(msg) && suffix === 'post') { - bot.channels.get(ChannelID).send(message1); - bot.channels.get(ChannelID).send(message2); - bot.channels.get(ChannelID).send(message3); - bot.channels.get(ChannelID).send(message4); - bot.channels.get(ChannelID).send(message5); - } else { - msg.channel.send(msg.author + ' Release notes sent via DM'); - msg.author.send(message1); - msg.author.send(message2); - msg.author.send(message3); - msg.author.send(message4); - msg.author.send(message5); - } - } - }); - } -}; diff --git a/bot/modules/reminder.js b/bot/modules/reminder.js deleted file mode 100644 index 45e44ee..0000000 --- a/bot/modules/reminder.js +++ /dev/null @@ -1,21 +0,0 @@ -/*exports.commands = [ - "remind" // command that is in this file, every command needs it own export as shown below -] - -exports.custom = [ - "checkReminders" -] - -exports.remind = { - usage: "