Compare commits

...

138 Commits

Author SHA1 Message Date
Alexander Yakovlev 0b8e772fb6 don't print the excerpt at all
Excerpts in Russian cause weird bugs
2018-07-05 11:42:02 +07:00
Alexander Yakovlev ddc0bac972 use excerpt or strip tags 2018-07-03 10:08:11 +07:00
Alexander Yakovlev 5a49817e56 package upgrades 2018-07-03 09:35:29 +07:00
Alexander Yakovlev e2f36f65f4 Don't spam the channel with "article content is too long" 2018-07-03 09:28:25 +07:00
Benji 9940e04431 Update README.md 2018-04-04 23:29:50 +01:00
benji7425 7adcdb89cd 3.5.2 2018-02-11 00:20:50 +00:00
benji7425 792b62fc73 git subrepo pull core
subrepo:
  subdir:   "core"
  merged:   "7a3eed3"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "7a3eed3"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2018-02-11 00:17:01 +00:00
benji7425 70f078c4b2 3.5.1 2018-01-27 20:23:24 +00:00
benji7425 5122eafc74 Remove deletion of data for removed guilds on startup
This would be bad if we started up during a discord outage, as I recently learned that discord.js counts the bot as not in the guild if that guild is inaccessible
2018-01-27 20:23:21 +00:00
benji7425 6a140afbe8 git subrepo pull core
subrepo:
  subdir:   "core"
  merged:   "1f14a50"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "1f14a50"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2018-01-27 20:23:04 +00:00
benji7425 4b815523f3 3.5.0 2018-01-27 18:15:14 +00:00
benji7425 d678f9db38 Remove unused reference causing problems 2018-01-27 18:15:14 +00:00
benji7425 e514f7af91 git subrepo push core
subrepo:
  subdir:   "core"
  merged:   "bcce76f"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "bcce76f"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2018-01-27 18:05:52 +00:00
benji7425 6a9a725cac Fix help not indicating that the bot username needs to be mentioned 2018-01-27 18:05:52 +00:00
benji7425 5e0250731c Update core naming to make a little more sense 2018-01-27 17:39:52 +00:00
benji7425 78960db384 Update camo to use new tagged version 2018-01-27 17:30:26 +00:00
benji7425 f378a3a47b 3.5.0-b3 2018-01-27 02:32:02 +00:00
benji7425 ee938ff563 Remove discord-bot-core direct mongodb package dep
Camo actually just loads it itself
2018-01-27 01:29:00 +00:00
benji7425 5f2b3af2d7 Update defauly NeDB compaction schedule to hourly 2018-01-27 00:42:36 +00:00
benji7425 19677b7626 Remove auto-restart
It was a work around to reset memory usage, but as I hope mongodb support fixes that, I shall remove it. Hopefully I won't need to revert this commit and put it back!
2018-01-27 00:41:58 +00:00
benji7425 17eb0554fe Update camo to use my fork
Increases MongoDB compatibility and adds it's own method for compacting NeDB data files
2018-01-27 00:37:17 +00:00
benji7425 f1f81a9ba4 Update data deletion to require a reset command instead of guildDelete
guildDelete apparently gets called whenever Discord has an outage - we don't want to delete server data whenever there is a temporary outage!
2018-01-27 00:03:51 +00:00
benji7425 672c07f5b0 Update formatting; convert tabs to 4x spaces
I believe this is the accepted method and should increase default editor compatibility
2018-01-26 23:48:07 +00:00
benji7425 381ff1d219 v3.5.0-b2
Fix a couple of script errors
2018-01-26 00:35:41 +00:00
benji7425 1e0d8d3266 3.5.0-b1 2018-01-26 00:29:41 +00:00
benji7425 71c77d41a3 Merge branch 'mongodb-compatibility' 2018-01-25 23:02:50 +00:00
benji7425 f7c00f898c Update core client to support mongodb in addition to nedb 2018-01-25 23:02:46 +00:00
benji7425 559a61828d Install mongodb 2018-01-25 22:29:51 +00:00
benji7425 1a60292860 Update naming and formatting for core .js files 2018-01-25 21:41:17 +00:00
benji7425 1d5ba2561b git subrepo push discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "693a761"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "693a761"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2018-01-23 23:55:07 +00:00
benji7425 b77eded7c2 3.4.0
Fix YouTube feeds not posting anymore
2018-01-23 23:19:48 +00:00
benji7425 f37c114624 Update default NeDB compaction schedule to once per minute 2018-01-23 23:19:33 +00:00
benji7425 120e1f66d8 git subrepo push --force discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "109848a"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "109848a"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2018-01-23 00:53:44 +00:00
benji7425 b407f66c88 git subrepo pull (merge) discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "71586d6"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "a0387b3"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2018-01-23 00:52:11 +00:00
benji7425 7a60083945 3.4.0-b1 2018-01-23 00:36:11 +00:00
benji7425 309286b528 Disable a few unused websocket events
Hopefully will improve memory usage somewhat
2018-01-23 00:32:33 +00:00
benji7425 f996eb363b Add daily auto restart 2018-01-23 00:30:10 +00:00
benji7425 3cdf6b2b2a Add LICENSE 2018-01-20 16:22:46 +00:00
benji7425 91d200eb44 3.3.0 2018-01-14 20:18:29 +00:00
benji7425 1150911a93 git subrepo push discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "429a85c"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "429a85c"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2018-01-14 20:12:32 +00:00
benji7425 25f67948b2 Switch from 'feed-read' module to 'rss-parser' 2018-01-14 20:08:05 +00:00
benji7425 7b7645cb5e Remove some unnecessary stuff in Client.js
- Remove message sweeping - shouldn't be needed with max cache size
- Remove console spam about db compaction
2018-01-14 19:48:40 +00:00
benji7425 d452569ad1 Update feed url caching to ignore 'www.' prefix
Has caused some issues with users posting links with/without www. and the RSS feed doing the opposite
Improve regex
2018-01-14 18:31:33 +00:00
benji7425 fbf762ff16 git subrepo push discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "4bfcf1b"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "4bfcf1b"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2018-01-07 23:53:26 +00:00
benji7425 7ee7d4c704 3.2.2
asdf
2018-01-07 23:48:29 +00:00
Benji 021abe31f7 Update README.md 2018-01-03 21:06:37 +00:00
benji7425 2ff31f8ec2 Remove useless node launch argument 2018-01-03 17:01:04 +00:00
benji7425 adab6692e7 Update .gitignore 2018-01-03 03:30:58 +00:00
benji7425 84cbe10eba 3.2.1 2018-01-03 01:47:52 +00:00
benji7425 79ce4d2501 git subrepo push discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "70b150f"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "70b150f"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2018-01-03 01:47:02 +00:00
benji7425 4afadaaa26 Update d.js message caching settings 2018-01-03 01:45:47 +00:00
benji7425 a0e94ae86d Update README.md 2017-12-11 01:18:36 +00:00
benji7425 5f7fb483da 3.2.0 2017-12-11 01:11:52 +00:00
benji7425 d97468ebd2 git subrepo push discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "0bab27a"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "0bab27a"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-12-11 01:06:10 +00:00
benji7425 e953e1cdca Refactor for efficiency and improved readability 2017-12-11 01:05:43 +00:00
benji7425 2b921c84e9 git subrepo pull (merge) discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "cf92dea"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "b19d4b2"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-12-09 05:39:04 +00:00
benji7425 784ef72392 3.2.0-b3
Fix some race conditions with the 3.2 update
2017-12-09 01:38:42 +00:00
benji7425 446df2f8a7 3.2.0-b2
Fix some issues with 3.2 upgrades
2017-12-08 22:54:45 +00:00
benji7425 71f0e344e1 3.2.0-b1 2017-12-08 00:57:44 +00:00
benji7425 cafecb4e13 git subrepo push discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "900f1f5"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "900f1f5"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-12-08 00:54:42 +00:00
benji7425 94c16927d3 Add legacy json file upgrader 2017-12-08 00:54:07 +00:00
benji7425 5b054b520b Update feed error handling 2017-12-08 00:29:16 +00:00
benji7425 c48c443854 Add removal of data on startup for guilds deleted during downtime 2017-12-08 00:09:07 +00:00
benji7425 6013b0dcbf Add guild iteration for feed checking
Update default feed check interval to be 10 seconds between guilds
2017-12-08 00:09:03 +00:00
benji7425 c93fe0d6ce Fix links not being properly cached with camo integration 2017-12-07 22:48:49 +00:00
benji7425 fe9781bdfe Merge branch 'camo-integration' 2017-12-07 22:29:01 +00:00
benji7425 b2c849e8c4 git subrepo push discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "be39d24"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "be39d24"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-12-07 22:27:54 +00:00
benji7425 834898a2f2 Integrate rss bot with camo 2017-12-07 22:26:45 +00:00
benji7425 30ea6239b9 Fix various issues in core 2017-12-07 22:26:45 +00:00
benji7425 b1ac656bee Revert removal of restart on unhandled exception
Turns out maybe it is actually somewhat useful after all
2017-12-07 00:19:16 +00:00
benji7425 b6ac3b2518 git subrepo pull (merge) discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "75f5044"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "eca1499"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-12-07 00:11:14 +00:00
benji7425 18f300d46d Tidy up some feed error spam 2017-12-03 16:04:15 +00:00
benji7425 987473ffa6 Fix crash if articles contain urls with invalid host names 2017-12-03 15:53:12 +00:00
benji7425 96def786a4 Fix crash if feed used with articles without links
Didn't realise this was possible...
2017-11-27 09:35:36 +00:00
benji7425 80f49e5564 git subrepo push discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "a1a9b30"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "a1a9b30"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-11-27 00:17:15 +00:00
benji7425 c92688c80a Housekeeping 2017-11-27 00:16:54 +00:00
benji7425 73d40eafc0 3.1.3 2017-11-27 00:10:27 +00:00
benji7425 663ef8ccba Merge branch 'fix-message-length' 2017-11-27 00:09:20 +00:00
benji7425 13267db0d2 Fix changelog 2017-11-27 00:08:53 +00:00
benji7425 538732cbf4 Add pagination limit to config 2017-11-27 00:07:29 +00:00
benji7425 db86cacaa0 Add rudimentary pagination for viewing feeds 2017-11-27 00:02:39 +00:00
benji7425 21c51fbc3d Fix articles not posting if content too long for discord
Also fix incorrect name in example commands
2017-11-26 23:38:01 +00:00
benji7425 d2fa55beae Revert "Removed ignoring of certain debug message in debug.log"
This reverts commit 1e4016ffd4d78d3a85c9161ab702b97979155753 in discord-bot-core subrepo
2017-11-26 23:36:23 +00:00
benji7425 f2313c7da4 git subrepo pull discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "a25486f"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "a25486f"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-11-26 23:29:16 +00:00
benji7425 723bbb1098 Quickfix deleted channels with feeds causing reconnect loop 2017-11-14 22:28:04 +00:00
benji7425 f3c3e57e41 Fix empty RSS feed crash 2017-11-14 01:31:46 +00:00
benji7425 2e985ad5fa git subrepo push discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "5c4a0b8"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "5c4a0b8"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-11-12 20:01:35 +00:00
benji7425 8a71425dc4 3.1.0 2017-11-12 19:50:22 +00:00
benji7425 c151201384 Add removal of data on startup if the bot has left the guild 2017-11-12 19:44:19 +00:00
benji7425 446292b057 Fix wrong feed being removed when the remove-feed command used 2017-11-12 19:34:04 +00:00
benji7425 1cb65ade49 3.1.0-b1 2017-11-11 04:17:18 +00:00
benji7425 e29283af1c Add support for optional command parameters 2017-11-11 03:44:44 +00:00
benji7425 20bc117dae Add rss element content into posted message 2017-11-11 03:21:05 +00:00
benji7425 f6d1b5f7a6 Add feed validity checking before adding 2017-11-11 01:59:00 +00:00
benji7425 caf664e014 Update changelog 2017-11-11 01:35:26 +00:00
benji7425 90619bef9a Add max-old-space-size constraint of 64MB 2017-11-11 01:32:50 +00:00
benji7425 607a3804bc Add removal of data when bot kicked from guild
Along with join/leave console messages
2017-11-11 01:28:38 +00:00
benji7425 0047f31770 git subrepo pull (merge) discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "5fd4a43"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "5fd4a43"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-11-11 01:13:18 +00:00
Benji e733a8b481 Update README.md 2017-10-31 22:56:49 +00:00
benji7425 e882ffa82e 3.0.1 2017-10-19 00:20:42 +01:00
benji7425 a0571cfc11 git subrepo pull discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "8efb033"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "8efb033"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-10-19 00:14:01 +01:00
benji7425 b65d9e89cf 3.0.0 2017-10-05 23:25:19 +01:00
benji7425 9d4aad4cf9 Fix user posted links not being detected if setup done after b5 update 2017-10-05 23:06:19 +01:00
benji7425 d348d7e41f 3.0.0-b7
Fix crash restart when bot received DM
2017-10-02 11:49:58 +01:00
benji7425 7c5ef008d8 3.0.0-b6
Remove 'BODY is not RSS or ATOM' error from console logging'
2017-10-02 02:08:13 +01:00
benji7425 53fc953caa 3.0.0-b5 2017-10-02 01:00:16 +01:00
benji7425 3e268d2231 Prevent checking of feeds for guilds the bot is no longer in
Plus fix a couple related issues
2017-10-02 00:52:36 +01:00
benji7425 8980dad584 Add upgrading of json data on startup 2017-10-02 00:42:01 +01:00
benji7425 3beeea1588 git subrepo push discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "1ed6225"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "1ed6225"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-10-02 00:20:31 +01:00
benji7425 6343ae50ea Fix exception if bot mentioned without a command 2017-10-02 00:18:05 +01:00
benji7425 f4e39a69dc Re-implement help message 2017-10-02 00:09:36 +01:00
benji7425 f193393a2a Merge branch 'command-framework' 2017-10-01 23:27:51 +01:00
benji7425 b4eb3d3551 Refactor multiple areas for simplicity and readability
This is a squash commit of many commits
2017-10-01 23:20:06 +01:00
benji7425 1b2e06c2d5 I changed my mind, we're going back to promises
Require command invoke methods to return a promise
2017-09-24 22:46:58 +01:00
benji7425 b777046b0b git subrepo pull discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "9f209e1"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "9f209e1"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-09-24 22:01:23 +01:00
benji7425 328623b8dd git subrepo push discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "0bf4f9d"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "0bf4f9d"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-09-24 21:39:53 +01:00
benji7425 3fc93e06cd Update commands to use message.reply, rather than promises
The promise method was just too annoying, better to go back to .reply
2017-09-24 21:39:34 +01:00
benji7425 f00b7ec876 Fix incorrect parameter being passed to internal command handling 2017-09-24 21:39:05 +01:00
benji7425 8989daef49 Separate commands into separate files for command framework compatibility 2017-09-24 21:31:30 +01:00
benji7425 1fc45e85b4 Add client as a parameter to command invokation 2017-09-24 21:20:12 +01:00
benji7425 e249b8d45d git subrepo pull discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "180d069"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "180d069"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-09-24 21:07:35 +01:00
benji7425 4dc73a6783 3.0.0-b4 2017-09-20 23:46:29 +01:00
benji7425 a5371c4711 git subrepo pull discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "81a8c67"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "81a8c67"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-09-20 23:44:33 +01:00
benji7425 07ca4336fb Fix old package.json references that would have caused problems eventaully 2017-09-20 01:23:44 +01:00
benji7425 a19c626753 3.0.0-b3 2017-09-20 01:18:47 +01:00
benji7425 4ba9f21e69 Add some error handling 2017-09-20 01:18:44 +01:00
benji7425 d8795740f9 Fix misleading logged error if just "youtube.com" pasted in chat 2017-09-20 00:56:05 +01:00
benji7425 35ce6a56be Merge branch 'core-update' 2017-09-20 00:44:55 +01:00
benji7425 e447c1c07f Fix (actually this time) youtube feature urls not being properly converted 2017-09-20 00:43:59 +01:00
benji7425 691af2761f Fix past links not being checked when a new feed is added 2017-09-20 00:43:42 +01:00
benji7425 347aedc4ab Fix readme and changelog being gone 2017-09-20 00:07:23 +01:00
benji7425 aeba653e9f Update for proper compatibility with current core code 2017-09-20 00:04:04 +01:00
benji7425 2b0750dada git subrepo commit (merge) discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "77cb9dd"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "8e6d6ce"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-09-19 23:26:30 +01:00
benji7425 0601c29c85 Add passing in of token file 2017-09-14 21:57:15 +01:00
benji7425 1cfc7a19c3 git subrepo pull (merge) discord-bot-core
subrepo:
  subdir:   "discord-bot-core"
  merged:   "d1f015c"
upstream:
  origin:   "git@github.com:benji7425/discord-bot-core.git"
  branch:   "master"
  commit:   "c4f07d0"
git-subrepo:
  version:  "0.3.1"
  origin:   "???"
  commit:   "???"
2017-09-14 21:54:21 +01:00
benji7425 4332c66b43 Refactor some areas for simplicity 2017-09-14 14:02:38 +01:00
benji7425 b6cc8298bc Sqaush merge and adapt for template update using shared core code 2017-09-14 13:09:47 +01:00
benji7425 2a7cd67506 Update vscode file explorer excludes 2017-09-14 12:45:59 +01:00
41 changed files with 4103 additions and 454 deletions

35
.eslintrc Normal file
View File

@ -0,0 +1,35 @@
{
"env": {
"browser": true,
"node": true,
"commonjs": true,
"es6": true
},
"extends": "eslint:recommended",
"parserOptions": {
"sourceType": "module"
},
"rules": {
"indent": [
"warn",
4,
{
"SwitchCase": 1
}
],
"quotes": [
"warn",
"double"
],
"semi": [
"error",
"always"
],
"no-undef": "error",
"no-unused-vars": "warn",
"eqeqeq": [
"error",
"always"
]
}
}

8
.gitignore vendored
View File

@ -1,8 +1,6 @@
### Discord bots ####
guilds.json
token.json
log
update.sh
guilds-data/*
token.json*
# Created by https://www.gitignore.io/api/node,visualstudiocode

3
.npmrc
View File

@ -1,3 +1,2 @@
save=true
save-exact=true
cache=node_cache
save-exact=true

6
.vscode/launch.json vendored
View File

@ -8,7 +8,11 @@
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceRoot}/bootstrap.js"
"program": "${workspaceRoot}/app/index.js",
"args":[
"token.json",
"guilds.json"
]
}
]
}

View File

@ -1,9 +0,0 @@
{
"files.exclude": {
"log": true,
".npmrc": true,
"node_modules": true,
"node_cache": true,
"token.json": true
}
}

View File

@ -1,22 +1,119 @@
# Changelog
## v3.0.0-b2
## v3.5.2
### Added
- Added bot name to version command
- Added stats command
### Fixed
- Fixed reset command not being admin only
- Full and short youtube urls not being properly converted
## v3.0.0-b1
### Added
- Fancy new @bot help command
## v3.5.1
### Fixed
- Fixed reset command not working
### Updated
- Removed deletion of data for removed guilds on startup, as Discord outages can wrongly report the bot as being removed
## v3.5.0
### Added
- MongoDB support
- Reset command to clear all data for a guild
### Updated
- Removed automatic daily restart (I think it shouldn't be needed now that MongoDB support is working)
### Fixed
- Guild data being deleted on a Discord outage
## v3.4.0
### Added
- Added automatic daily restart
### Updated
- Disabled a few unused websocket events
- Update database compaction to be more frequent
### Fixed
- Fixed YouTube feeds not updating
## v3.3.0
### Updated
- Updated RSS parser to now use [rss-parser](https://www.npmjs.com/package/rss-parser) module to increase compatibility with feeds
- Updated RSS entry caching to exclude 'www.' prefix to avoid certain mis-caches
## v3.2.2
### Fixed
- Fixed a couple of edge case errors
## v3.2.1
### Fixed
- Fixed memory leak due to unconfigured discord.js caching
## v3.2.0
### Updated
- Updated data storage to use a NeDB database rather than a json file
- Updated feed checking interval to check one guild every 10 seconds (this may slow down the time it takes to post, but will improve performance)
- Improve stability of feed checking
- Tidy up some console spam
### Fixed
- Fix bot crash if feed article contains link with invalid host name
- Temporary fix for bot crash if used with a feed without links in the articles (didn't realise this was possible...)
- Attempt fix for issues caused by every feed of every guild being checked at the same time
## v3.1.3
### Added
- Add rudimentary pagination for viewing feeds when there are more than 10
### Fixed
- Fix articles not posting if contents too long for a single discord message
## v3.1.2
### Fixed
- Deleted channels with feeds sending the bot into a reconnect loop
## v3.1.1
### Fixed
- Empty RSS feed crash
## v3.1.0
### Added
- RSS element content is now included in the post the bot makes when there is a new feed
- Warning message after setup command if supplied URL does not return valid RSS
- Guild join and leave messages in the console
- Removal of guild data if the bot leaves a guild
### Updated
- Route a lot of mostly irrelevant console spam to a file instead of the console
- Updated launch command to pass max-old-space-size parameter to limit memory usage
### Fixed
- Fixed syntax error when role omitted in feed setup command; it is now properly optional
- Fixed the wrong feed sometimes being removed when using the remove-feed command
## v3.0.1
### Fixed
- Fixed nicknamed bot not responding to users on android
- Fixed "playing" message including "https://" in front of site url
## v3.0.0
### Added
- Significantly more debug logging
- Fancy new @bot help command
### Updatd
- Significant back-end updates
- Commands now invoked with an @mention to the bot
- Updated error handling for Discord API errors
- Removed "Body is not RSS or ATOM" error from being console logged
- These seem to happen quite a lot, but don't actually impair the functionality, so just cause un-necessary spam
- Removed "command not recognised" response, it caused 'fake' errors if multiple bots being run off the same token
### Fixed
- Fixed full and short youtube urls not being properly converted
- Fixed "multiple instance" issue
- Fixed a couple of occasional memory leaks
## v2.0.0-b1
### Added
- Multi-guild support
- In-chat commands for setup and configuration
@ -25,47 +122,35 @@
- Remove an existing feed
### Updated
- Make save file configurable to allow use as a module with other bots
- Update config file structure
- Now uses discord.js instead of discord.io
- YouTube links automatically handled; no more separate "YouTube mode" config item
### Fixed
- Crash if trying to view feeds list before any feeds have been set up
## v1.4.0
### Added
- Support for posting links from multiple feeds
- Tagging of separate roles for each feed being checked
### Updated
- Updated bot connection code to use my discord-bot-wrapper
### Removed
- !logsplease command removed as the OTT logging was just being annoying
## v1.3.2
### Fixed
- Fixed list posting channel messages being ignored
## v1.3.1
### Fixed
- Developer commands can now be used from any channel or PM
## v1.3.0
### Added
- Deletion of "You have successfully subscribed" messages after a short delay (configurable)
- 'Developer' commands that can only be accessed by specified users
- !cacheList developer command to view the cached URLs
@ -78,44 +163,34 @@
- The role is mentioned when the link is posted, rather than a long chain of user IDs
## v1.2.1
### Fixed
- Fixed multiple users being unsubscribed when one user unsubscribes
## v1.2.0
### Added
- Chat message/command to request a list of subscribed users
- The ability for users to 'subscribe' so they are tagged whenever a new link is posted
- Logging to a file
- Ability for user to request an upload of the logs file
### Updated
- Added basic spam reduction when logging so the same message won't get logged multiple times in a row
- Refactored a bunch of code to improve efficiency
- Updated timer logic to only ever use a single timer, and share it between posting and reconnecting
## v1.1.2
### Updated
- Updated reconnect logic to hopefully be more stable
## v1.1.1
### Added
- Reconnect timer to repeatedly try reconnect at intervals
### Updated
- Updated support for https conversion to http to hopefully be more consistent
## v1.1.0
### Added
- Added togglable YouTube mode
- Converts full URLs to YouTube share URLs
- Checks against both YouTube full and share URLs to ensure same video not posted twice
@ -126,4 +201,4 @@
- Changed expected name for bot config file to bot-config.json rather than botConfig.json
### Fixed
- New timer being created every time the bot reconnected
- New timer being created every time the bot reconnected

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Benjamin Higgins
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 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.

View File

@ -1,4 +1,4 @@
# Discord rss bot
# Discord RSS Bot
<!--summary-->
Posts the latest URLs from an RSS feed, optionally @mention-ing a role when posted
@ -18,46 +18,48 @@ Posts the latest URLs from an RSS feed, optionally @mention-ing a role when post
## Invite
By inviting this bot to your server you agree to the [terms and conditions](#privacy-statement) laid out in the privacy section of this document.
If you agree, invite to your server with [this link](https://discordapp.com/oauth2/authorize?client_id=343909688045469698&scope=bot&permissions=0x00010c00).
~~If you agree, invite to your server with this link~~.
*Temporarily unavailable due to scaling issues and the large amount of attention recently.*
## Setup
You can ask the bot for help with commands by typing `@RSS_Bot help`
You can ask the bot for help with commands by typing `@RSS Bot help`
### Add a new feed
`@RSS_Bot add-feed <url> <#channel> [@role]`
`@RSS Bot add-feed <url> <#channel> [@role]`
- *url* must be an RSS feed URL
- *#channel* must be a channel mention
- *@role* must be a role mention (make sure "Anyone can mention this role" is turned on during setup)
Example:
`@RSS_Bot add-feed http://lorem-rss.herokuapp.com/feed?unit=second&interval=30 #rss-posts @subscribers`
`@RSS Bot add-feed http://lorem-rss.herokuapp.com/feed?unit=second&interval=30 #rss-posts @subscribers`
### View feeds configured for this server
`@RSS_Bot view-feeds`
`@RSS Bot view-feeds`
This will display a list of RSS feeds configured for this server, along with a unique ID for each
### Remove a configured feed
`@RSS_Bot remove-feed <feed-id>`
`@RSS Bot remove-feed <feed-id>`
To remove a feed you will need it's unique ID, which you can find by running the above *view-feeds* command
Example:
`@RSS_Bot remove-feed ABc-123dEF`
`@RSS Bot remove-feed ABc-123dEF`
## Permissions
The bot requires certain permissions, which you are prompted for on the invite screen.
Each permission has a reason for being required, explained below.
| Permission | Reason |
|----------------------|-------------------------------------------------------------|
| Read messages | Detect when you use commands |
| Send messages | Respond when you use commands; post new RSS links |
| Read message history | Check if any new RSS links have been posted during downtime |
| Permission | Reason |
|----------------------|--------------------------------------------------------------|
| Read messages | Detect when you use commands |
| Send messages | Respond when you use commands; post new RSS links |
| Read message history | Check if any new RSS links have been posted during downtime |
| Embed links | Responses to 'help' requests use message embeds for nice formatting |
## Privacy statement
@ -78,9 +80,12 @@ Should you wish for the data stored about your server to be removed, please cont
1. Clone the repository, or download and extract the zip file (preferrably from the release page)
2. Make sure you have *npm* and *git* installed
3. Run `npm install`
4. Add *token.json* in the root folder: `{ "token": "your-token-goes-here" }`
4. Add *token.json* in the root folder (make sure to include the quotes ""): `"your-token-goes-here"`
5. Run `npm start`
**Note for git users**
If you cloned the repository with git, make sure you `git reset --hard vX.Y` to a specific version, as latest master isn't always production ready!
## Need help?
I am available for contact via my [support Discord server](https://discordapp.com/invite/SSkbwSJ). I will always do my best to respond, however I am often busy so can't always be available right away, and as this is a free service I may not always be able to resolve your query.

View File

@ -1,108 +0,0 @@
//external lib imports
const GetUrls = require("get-urls"); //for extracting urls from messages
//my imports
const DiscordUtil = require("discordjs-util");
//app component imports
const GuildData = require("./models/guild-data.js");
const FeedData = require("./models/feed-data.js");
module.exports = {
onReady(client, guildsData, config) {
return new Promise((resolve, reject) => {
parseLinksInGuilds(client.guilds, guildsData)
.then(() => checkFeedsInGuilds(client.guilds, guildsData))
.then(() => setInterval(() => checkFeedsInGuilds(client.guilds, guildsData), config.feedCheckIntervalSec * 1000)); //set up an interval to check all the feeds
});
},
onCommand(commandObj, commandsObj, params, guildData, message, config, client, botName) {
switch (commandObj.command) {
case commandsObj.addFeed.command:
return addFeed(client, guildData, message, config.maxCacheSize);
case commandsObj.removeFeed.command:
return removeFeed(guildData, message, botName);
case commandsObj.viewFeeds.command:
return viewFeeds(guildData);
}
},
onNonCommandMsg(message, guildData) {
guildData.feeds.forEach(feedData => {
if (message.channel.name === feedData.channelName)
feedData.cachedLinks.push(...GetUrls(message.content)); //spread the urlSet returned by GetUrls into the cache array
});
}
};
function addFeed(client, guildData, message, maxCacheSize) {
return new Promise((resolve, reject) => {
const feedUrl = [...GetUrls(message.content)][0];
const channel = message.mentions.channels.first();
if (!feedUrl || !channel)
reject("Please provide both a channel and an RSS feed URL. You can optionally @mention a role also.");
const role = message.mentions.roles.first();
const feedData = new FeedData({
url: feedUrl,
channelName: channel.name,
roleName: role ? role.name : null,
maxCacheSize: maxCacheSize
});
//ask the user if they're happy with the details they set up, save if yes, don't if no
DiscordUtil.ask(client, message.channel, message.member, "Are you happy with this?\n" + feedData.toString())
.then(responseMessage => {
//if they responded yes, save the feed and let them know, else tell them to start again
if (responseMessage.content.toLowerCase() === "yes") {
if (!guildData)
guildData = new GuildData({ id: message.guild.id, feeds: [] });
guildData.feeds.push(feedData);
resolve("Your new feed has been saved!");
}
else
reject("Your feed has not been saved, please add it again with the correct details");
});
});
}
function removeFeed(guildData, message, botName) {
return new Promise((resolve, reject) => {
const parameters = message.content.split(" ");
if (parameters.length !== 3)
resolve(`Please use the command as such:\n\`\`\` ${botName} remove-feed feedid\`\`\``);
else {
const idx = guildData.feeds.findIndex(feed => feed.id === parameters[2]);
if (!Number.isInteger(idx))
reject("Can't find feed with id " + parameters[2]);
else {
guildData.feeds.splice(idx, 1);
resolve("Feed removed!");
}
}
});
}
function viewFeeds(guildData) {
if (!guildData)
return Promise.reject("Guild not setup");
return Promise.resolve(guildData.feeds.map(f => f.toString()).join("\n"));
}
function checkFeedsInGuilds(guilds, guildsData) {
Object.keys(guildsData).forEach(key => guildsData[key].checkFeeds(guilds));
}
function parseLinksInGuilds(guilds, guildsData) {
const promises = [];
for (let guildId of guilds.keys()) {
const guildData = guildsData[guildId];
if (guildData)
promises.push(guildData.cachePastPostedLinks(guilds.get(guildId)));
}
return Promise.all(promises);
}

51
app/commands/add-feed.js Normal file
View File

@ -0,0 +1,51 @@
const { promisify } = require("util");
const Config = require("../config.json");
const Core = require("../../core");
const FeedData = require("../models/feed-data.js");
const GetUrls = require("get-urls");
const ShortID = require("shortid");
// @ts-ignore
const readFeed = url => promisify(require("rss-parser").parseURL)(url);
module.exports = new Core.Command({
name: "add-feed",
description: "Add an RSS feed to be posted in a channel, with an optional role to tag",
syntax: "add-feed <url> <#channel> [@role]",
admin: true,
invoke: invoke
});
function invoke({ message, params, guildData, client }) {
const feedUrl = [...GetUrls(message.content)][0],
channel = message.mentions.channels.first();
if (!feedUrl || !channel)
return Promise.reject("Please provide both a channel and an RSS feed URL. You can optionally @mention a role also.");
const role = message.mentions.roles.first(),
feedData = FeedData.create({
feedID: ShortID.generate(),
url: feedUrl,
channelID: channel.id,
roleID: role ? role.id : null,
maxCacheSize: Config.maxCacheSize
});
return new Promise((resolve, reject) => {
readFeed(feedUrl)
.then(() => {
Core.util.ask(client, message.channel, message.member, "Are you happy with this (yes/no)?\n" + feedData.toString())
.then(responseMessage => {
if (responseMessage.content.toLowerCase() === "yes") {
guildData.feeds.push(feedData);
guildData.cachePastPostedLinks(message.guild)
.then(() => resolve("Your new feed has been saved!"));
}
else
reject("Your feed has not been saved, please add it again with the correct details");
});
})
.catch(err => reject(`Unable to add the feed due to the following error:\n${err.message}`));
});
}

View File

@ -0,0 +1,18 @@
const Core = require("../../core");
module.exports = new Core.Command({
name: "remove-feed",
description: "Remove an RSS feed by it's ID",
syntax: "remove-feed <dir>",
admin: true,
invoke: invoke
});
function invoke({ message, params, guildData, client }) {
const idx = guildData.feeds.findIndex(feed => feed.feedID === params[0]);
if (!Number.isInteger(idx))
return Promise.reject("Can't find feed with id " + params[0]);
guildData.feeds.splice(idx, 1);
return Promise.resolve("Feed removed!");
}

View File

@ -0,0 +1,23 @@
const Core = require("../../core");
const Config = require("../config.json");
module.exports = new Core.Command({
name: "view-feeds",
description: "View a list of configured feeds and their associated details",
syntax: "view-feed",
admin: true,
invoke: invoke
});
function invoke({ message, params, guildData, client }) {
if (!guildData)
return Promise.reject("Guild not setup");
const startIdx = params[0] ? (params[0] - 1) * Config.viewFeedsPaginationLimit : 0;
const endIdx = startIdx + Config.viewFeedsPaginationLimit + 1;
let responseStr = guildData.feeds.map(f => f.toString()).slice(startIdx, endIdx).join("\n");
if (guildData.feeds.length > endIdx)
responseStr += `Use *view-feeds ${startIdx + 2}* to view more`;
return Promise.resolve(responseStr || "No feeds configured");
}

View File

@ -1,43 +1,6 @@
{
"generic": {
"saveFile": "./guilds.json",
"saveIntervalSec": 60,
"website": "https://benji7425.github.io",
"discordInvite": "https://discord.gg/SSkbwSJ",
"defaultDMResponse": "This bot does not have any handling for direct messages. To learn more or get help please visit %s, or join my Discord server here: %s"
},
"maxCacheSize": 100,
"feedCheckIntervalSec": 30,
"commands": {
"version": {
"command": "version",
"description": "Returns the bot version",
"syntax": "version",
"admin": false
},
"help": {
"command": "help",
"description": "Display information about commands available to you",
"syntax": "help",
"admin": false
},
"addFeed": {
"command": "add-feed",
"description": "Add an RSS feed to be posted in a channel, with an optional role to tag",
"syntax": "add-feed <url> <#channel> [@role]",
"admin": true
},
"removeFeed": {
"command": "remove-feed",
"description": "Remove an RSS feed by it's ID",
"syntax": "remove-feed <id>",
"admin": true
},
"viewFeeds": {
"command": "view-feeds",
"description": "View a list of configured feeds and their associated details",
"syntax": "view-feed",
"admin": true
}
}
"feedCheckInterval": 10000,
"charLimit": 500,
"viewFeedsPaginationLimit": 10
}

View File

@ -1,123 +1,74 @@
//node imports
const FileSystem = require("fs"); //manage files
const Util = require("util"); //various node utilities
const Core = require("../core");
const GetUrls = require("get-urls");
const GuildData = require("./models/guild-data.js");
// @ts-ignore
const Config = require("./config.json");
//external lib imports
const Discord = require("discord.js");
const JsonFile = require("jsonfile"); //save/load data to/from json
const guildsIterator = (function* () {
while (true) {
if (client.guilds.size === 0)
yield null;
else
for (let i = 0; i < client.guilds.size; i++)
yield [...client.guilds.values()][i];
}
})();
//my imports
const DiscordUtil = require("discordjs-util"); //some discordjs helper functions of mine
// @ts-ignore
const client = new Core.Client(require("../token.json"), __dirname + "/commands", GuildData);
//app components
const GuildData = require("./models/guild-data.js"); //data structure for guilds
const PackageJSON = require("../package.json"); //used to provide some info about the bot
const Bot = require("./bot.js");
client.on("beforeLogin", () =>
setInterval(doGuildIteration, Config.feedCheckInterval));
//global vars
let writeFile = null;
client.on("ready", () => {
parseLinksInGuilds().then(doGuildIteration);
require("./legacy-upgrader.js")(); //upgrade legacy json into new database format
});
//use module.exports as a psuedo "onready" function
module.exports = (client, config = null) => {
config = config || require("./config.json"); //load config file
const guildsData = FileSystem.existsSync(config.generic.saveFile) ? fromJSON(JsonFile.readFileSync(config.generic.saveFile)) : {}; //read data from file, or generate new one if file doesn't exist
client.on("message", message => {
if (message.channel.type !== "text" || !message.member)
return;
//create our writeFile function that will allow other functions to save data to json without needing access to the full guildsData or config objects
//then set an interval to automatically save data to file
writeFile = () => JsonFile.writeFile(config.generic.saveFile, guildsData, err => { if (err) DiscordUtil.dateError("Error writing file", err); });
setInterval(() => writeFile(), config.generic.saveIntervalSec * 1000);
client.guildDataModel.findOne({ guildID: message.guild.id })
.then(guildData => guildData && cacheUrlsInMessage(message, guildData));
});
//handle messages
client.on("message", message => {
if (message.author.id !== client.user.id) { //check the bot isn't triggering itself
client.bootstrap();
//check whether we need to use DM or text channel handling
if (message.channel.type === "dm")
HandleMessage.dm(client, config, message);
else if (message.channel.type === "text" && message.member)
HandleMessage.text(client, config, message, guildsData);
}
});
//INTERNAL FUNCTIONS//
function parseLinksInGuilds() {
const promises = [];
Bot.onReady(client, guildsData, config).then(() => writeFile).catch(err => DiscordUtil.dateError(err));
};
client.guildDataModel.find().then(guildDatas =>
guildDatas
.filter(guildData => client.guilds.get(guildData.guildID))
.map(guildData => ({ guildData, guild: client.guilds.get(guildData.guildID) }))
.forEach(({ guildData, guild }) => promises.push(guildData.cachePastPostedLinks(guild).catch()))
);
const HandleMessage = {
dm: (client, config, message) => {
message.reply(Util.format(config.generic.defaultDMResponse, config.generic.website, config.generic.discordInvite));
},
text: (client, config, message, guildsData) => {
const isCommand = message.content.startsWith(message.guild.me.toString());
let guildData = guildsData[message.guild.id];
if (!guildData)
guildData = guildsData[message.guild.id] = new GuildData({ id: message.guild.id });
if (isCommand) {
const userIsAdmin = message.member.permissions.has("ADMINISTRATOR");
const botName = "@" + (message.guild.me.nickname || client.user.username);
const split = message.content.toLowerCase().split(/\ +/); //split the message at whitespace
const command = split[1]; //extract the command used
const commandObj = config.commands[Object.keys(config.commands).find(x => config.commands[x].command.toLowerCase() === command)]; //find the matching command object
if (!commandObj || (!commandObj.admin && !userIsAdmin))
return;
const params = split.slice(2, split.length); //extract the parameters passed for the command
const expectedParamCount = commandObj.syntax.split(/\ +/).length - 1; //calculate the number of expected command params
let finalisedParams;
if (params.length > expectedParamCount) //if we have more params than needed
finalisedParams = params.slice(0, expectedParamCount - 1).concat([params.slice(expectedParamCount - 1, params.length).join(" ")]);
else //else we either have exactly the right amount, or not enough
finalisedParams = params;
//find which command was used and handle it
switch (command) {
case config.commands.version.command:
message.reply(`${PackageJSON.name} v${PackageJSON.version}`);
break;
case config.commands.help.command:
message.channel.send(createHelpEmbed(botName, config, userIsAdmin));
break;
default:
if (finalisedParams.length >= expectedParamCount)
Bot.onCommand(commandObj, config.commands, finalisedParams, guildData, message, config, client, botName)
.then(msg => {
message.reply(msg);
writeFile();
})
.catch(err => {
message.reply(err);
DiscordUtil.dateError(err);
});
else
message.reply(`Incorrect syntax!\n**Expected:** *${botName} ${commandObj.syntax}*\n**Need help?** *${botName} ${config.commands.help.command}*`);
break;
}
}
else
Bot.onNonCommandMsg(message, guildData);
}
};
function fromJSON(json) {
const guildsData = Object.keys(json);
guildsData.forEach(guildID => { json[guildID] = new GuildData(json[guildID]); });
return json;
return Promise.all(promises);
}
function createHelpEmbed(name, config, userIsAdmin) {
const commandsArr = Object.keys(config.commands).map(x => config.commands[x]).filter(x => userIsAdmin || !x.admin);
function doGuildIteration() {
const guild = guildsIterator.next().value;
const embed = new Discord.RichEmbed().setTitle("__Help__");
if (guild)
client.guildDataModel.findOne({ guildID: guild.id })
.then(guildData => guildData && checkGuildFeeds(guild, guildData));
}
commandsArr.forEach(command => {
embed.addField(command.command, `${command.description}\n**Usage:** *${name} ${command.syntax}*${userIsAdmin && command.admin ? "\n***Admin only***" : ""}`);
});
function checkGuildFeeds(guild, guildData) {
guildData.checkFeeds(guild)
.then(values => values.some(x => x) && guildData.save());
}
embed.addField("__Need more help?__", `[Visit my website](${config.generic.website}) or [Join my Discord](${config.generic.discordInvite})`, true);
function cacheUrlsInMessage(message, guildData) {
const anyNewLinksPosted = [];
return { embed };
guildData.feeds
.filter(feedData => message.channel.id === feedData.channelID)
.forEach(feedData => anyNewLinksPosted.push(feedData.cache(...GetUrls(message.content))));
if (anyNewLinksPosted.some(x => x))
guildData.save();
}

30
app/legacy-upgrader.js Normal file
View File

@ -0,0 +1,30 @@
// @ts-nocheck
const NewGuildData = require("./models/guild-data.js");
const NewFeedData = require("./models/feed-data.js");
const FileSystem = require("fs");
module.exports = function () {
if (!FileSystem.existsSync("./guilds.json"))
return;
const legacyJson = require("../guilds.json");
for (let guildID of Object.keys(legacyJson)) {
const guildData = NewGuildData.create({ guildID });
for (let feed of legacyJson[guildID].feeds) {
guildData.feeds.push(NewFeedData.create({
feedID: feed.id,
url: feed.url,
roleID: feed.roleID,
channelID: feed.channelID,
cachedLinks: feed.cachedLinks,
maxCacheSize: feed.maxCacheSize
}));
}
guildData.save();
}
FileSystem.rename("./guilds.json", "./guilds.json.backup");
};

View File

@ -1,89 +1,137 @@
//my imports
const DiscordUtil = require("discordjs-util");
// @ts-ignore
const Config = require("../config.json");
//external lib imports
const Dns = require("dns"); //for host resolution checking
const Url = require("url"); //for url parsing
const FeedRead = require("feed-read"); //for extracing new links from RSS feeds
const GetUrls = require("get-urls"); //for extracting urls from messages
const ShortID = require("shortid"); //to provide ids for each feed, allowing guilds to remove them
const { promisify } = require("util");
const Core = require("../../core");
const DiscordUtil = require("../../core").util;
const GetUrls = require("get-urls");
const Url = require("url");
module.exports = class FeedData {
constructor({ id, url, channelName, roleName, cachedLinks, maxCacheSize }) {
this.id = id || ShortID.generate();
this.url = url;
this.channelName = channelName;
this.roleName = roleName;
this.cachedLinks = cachedLinks || [];
this.maxCacheSize = maxCacheSize || 10;
// @ts-ignore
const readFeed = url => promisify(require("rss-parser").parseURL)(url);
const resolveDns = promisify(require("dns").resolve);
this.cachedLinks.push = (...elements) => {
const unique = elements
.map(el => normaliseUrl(el)) //normalise all the urls
.filter(el => !this.cachedLinks.includes(el)); //filter out any already cached
Array.prototype.push.apply(this.cachedLinks, unique);
module.exports = class FeedData extends Core.BaseEmbeddedData {
constructor() {
super();
if (this.cachedLinks.length > this.maxCacheSize)
this.cachedLinks.splice(0, this.cachedLinks.length - this.maxCacheSize); //remove the # of elements above the max from the beginning
};
}
this.feedID = "";
this.url = "";
this.channelID = "";
this.roleID = "";
this.cachedLinks = [];
this.maxCacheSize = 100;
/**
* Returns a promise providing all the links posted in the last 100 messages
* @param {Discord.Guild} guild The guild this feed belongs to
* @returns {Promise<string[]>} Links posted in last 100 messages
*/
updatePastPostedLinks(guild) {
const channel = guild.channels.find(ch => ch.type === "text" && ch.name === this.channelName);
// @ts-ignore
this.schema({
feedID: String,
url: String,
channelID: String,
roleID: String,
cachedLinks: [String],
maxCacheSize: Number
});
}
return new Promise((resolve, reject) => {
channel.fetchMessages({ limit: 100 })
.then(messages => {
new Map([...messages].reverse()).forEach(m => this.cachedLinks.push(...GetUrls(m.content))); //push all the links in each message into our links array
resolve(this);
})
.catch(reject);
});
}
cache(...elements) {
const newArticles = elements
.map(el => normaliseUrlForCache(el))
.filter(el => !this._isCached(el));
check(guild) {
Dns.resolve(Url.parse(this.url).host || "", err => { //check we can resolve the host, so we can throw an appropriate error if it fails
if (err)
DiscordUtil.dateError("Connection Error: Can't resolve host", err); //log our error if we can't resolve the host
else
FeedRead(this.url, (err, articles) => { //check the feed
if (err)
DiscordUtil.dateError(err);
else {
let latest = articles[0].link; //extract the latest link
latest = normaliseUrl(latest); //standardise it a bit
Array.prototype.push.apply(this.cachedLinks, newArticles);
//if we don't have it cached already, cache it and callback
if (!this.cachedLinks.includes(latest)) {
this.cachedLinks.push(latest);
this.cachedLinks.splice(0, this.cachedLinks.length - this.maxCacheSize); //seeing as new links come in at the end of the array, we need to remove the old links from the beginning
const channel = guild.channels.find(ch => ch.type === "text" && ch.name.toLowerCase() === this.channelName.toLowerCase());
const role = this.roleName ? guild.roles.find(role => role.name.toLowerCase() === this.roleName.toLowerCase()) : null;
channel.send((role ? role + " " : "") + latest);
}
}
});
});
}
return elements.length > 0;
}
toString() {
const blacklist = ["cachedLinks", "maxCacheSize"];
return `\`\`\`JavaScript\n ${JSON.stringify(this, (k, v) => !blacklist.includes(k) ? v : undefined, "\t")} \`\`\``;
}
updatePastPostedLinks(guild) {
const channel = guild.channels.get(this.channelID);
if (!channel)
return Promise.reject("Channel not found!");
return new Promise((resolve, reject) => {
channel.fetchMessages({ limit: 100 })
.then(messages => {
/* we want to push the links in oldest first, but discord.js returns messages newest first, so we need to reverse them
* discord.js returns a map, and maps don't have .reverse methods, hence needing to spread the elements into an array first */
[...messages.values()].reverse().forEach(m => this.cache(...GetUrls(m.content)));
resolve();
})
.catch(reject);
});
}
fetchLatest(guild) {
const dnsPromise = resolveDns(Url.parse(this.url).host).then(() => this._doFetchRSS(guild));
dnsPromise.catch(err => DiscordUtil.dateDebugError("Connection error: Can't resolve host", err.message || err));
return dnsPromise;
}
toString() {
const blacklist = ["cachedLinks", "maxCacheSize"];
return `\`\`\`JavaScript\n ${JSON.stringify(this, (k, v) => !blacklist.find(x => x === k) ? v : undefined, "\t")} \`\`\``;
}
_isCached(url) {
return this.cachedLinks.indexOf(normaliseUrlForCache(url)) > -1;
}
_doFetchRSS(guild) {
const feedPromise = readFeed(this.url).then(parsed => this._processLatestArticle(guild, parsed.feed.entries));
feedPromise.catch(err => DiscordUtil.dateDebugError([`Error reading feed ${this.url}`, err]));
return feedPromise;
}
_processLatestArticle(guild, entries) {
if (entries.length === 0 || !entries[0].link)
return false;
if (this._isCached(entries[0].link))
return false;
this.cache(entries[0].link);
const channel = guild.channels.get(this.channelID),
role = guild.roles.get(this.roleID);
channel.send((role || "") + formatPost(entries[0]))
.catch(err => DiscordUtil.dateDebugError(`Error posting in ${channel.id}: ${err.message || err}`));
return true;
}
};
function normaliseUrl(url) {
url = url.replace("https://", "http://"); //hacky way to treat http and https the same
function formatPost(article) {
let message = "";
if (Url.parse(url).host.startsWith("http://youtu"))
url = url.split("?")[0]; //quick way to chop off stuff like ?feature=youtube
if (article.title) message += `\n**${article.title}**`;
if (article.link) message += `\n\n${normaliseUrlForDiscord(article.link)}`;
url = url.replace(/(www.)?youtube.com\/watch\?v=/, "youtu.be/"); //convert youtube full url to short
return message;
}
return url;
}
function normaliseUrlForDiscord(url) {
const parsedUrl = Url.parse(url);
if (parsedUrl.host && parsedUrl.host.includes("youtube.com"))
url = normaliseYouTubeUrl(url, parsedUrl);
return url;
}
function normaliseYouTubeUrl(origUrl, parsedUrl) {
const videoIDParam = parsedUrl.query ? parsedUrl.query.split("&").find(x => x.startsWith("v=")) : null;
if (!videoIDParam)
return origUrl;
const videoID = videoIDParam.substring(videoIDParam.indexOf("=") + 1, videoIDParam.length);
return `http://youtu.be/${videoID}`
}
function normaliseUrlForCache(url) {
return normaliseUrlForDiscord(url).replace(/^((https?:\/\/)?(www.)?)/, "");
}

View File

@ -1,23 +1,34 @@
const Core = require("../../core");
const FeedData = require("./feed-data.js");
const Util = require("discordjs-util");
module.exports = class GuildData {
constructor({ id, feeds }) {
this.id = id;
this.feeds = (feeds || []).map(feed => new FeedData(feed));
}
module.exports = class GuildData extends Core.BaseGuildData {
constructor() {
super();
cachePastPostedLinks(guild) {
const promises = [];
this.feeds = [];
this.feeds.forEach(feed => {
promises.push(feed.updatePastPostedLinks(guild).catch(Util.dateError));
});
this.schema({
feeds: [FeedData]
});
}
return Promise.all(promises);
}
cachePastPostedLinks(guild) {
return Promise.all(
this.feeds
.filter(feed => feedIsActive(feed, guild))
.map(feed => feed.updatePastPostedLinks(guild).catch(err => null))
);
}
checkFeeds(guilds) {
this.feeds.forEach(feed => feed.check(guilds.get(this.id)));
}
};
checkFeeds(guild) {
return Promise.all(
this.feeds
.filter(feed => feedIsActive(feed, guild))
.map(feed => feed.fetchLatest(guild).catch(err => null))
);
}
};
function feedIsActive(feed, guild) {
return guild.channels.get(feed.channelID);
}

20
bootstrap.js vendored
View File

@ -1,20 +0,0 @@
const Discord = require("discord.js");
const DiscordUtil = require("discordjs-util");
const client = new Discord.Client();
process.on("uncaughtException", (err) => {
DiscordUtil.dateError("Uncaught exception!", err);
});
client.login(require("./token.json").token);
client.on("ready", () => {
DiscordUtil.dateLog("Registered bot " + client.user.username);
require("./app/index.js")(client);
client.user.setPresence({ game: { name: "benji7425.github.io", type: 0 } });
});
client.on("disconnect", eventData => {
DiscordUtil.dateError("Bot was disconnected!", eventData.code, eventData.reason);
});

79
core/.gitignore vendored Normal file
View File

@ -0,0 +1,79 @@
### Discord bots ####
guilds.json
token.json
log
# Created by https://www.gitignore.io/api/node,visualstudiocode
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_cache
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history
# End of https://www.gitignore.io/api/node,visualstudiocode

12
core/.gitrepo Normal file
View File

@ -0,0 +1,12 @@
; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git "subrepo", and this file is maintained by the
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
;
[subrepo]
remote = git@github.com:benji7425/discord-bot-core.git
branch = master
commit = 7a3eed3eff576ed51cfdfbbad18df07d4fcf52a7
parent = 09cf5233db442fa0af452e84e90289619532418a
method = merge
cmdver = 0.3.1

2
core/.npmrc Normal file
View File

@ -0,0 +1,2 @@
save=true
save-exact=true

21
core/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Benjamin Higgins
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 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.

27
core/README.md Normal file
View File

@ -0,0 +1,27 @@
# Discord bot core
Core code for connection and command handling for my Discord bots.
This is not actually a Discord bot. To learn about some of my available Discord bots please visit [my website](https://benji7425.github.io/)
This code is included in the repo for each bot using [git subrepo](https://github.com/ingydotnet/git-subrepo), which I prefer over submodules and subtrees.
This code does not function on it's own, it simply provides common functionality my Discord bots can make use of.
To test/modify this code, it needs to be run in the context of an actual bot.
A good candidate is my [template project](https://github.com/benji7425/discord-bot-template), which should run and connect just fine, just won't do much.
## Built with
- [discord.js](https://discord.js.org/#/)
- [NeDB](https://github.com/louischatriot/nedb)
- [camo](https://github.com/scottwrobinson/camo)
## Contributing
The easiest way to get setup would be a fork of this repo, and the fork of a bot to use as a development context.
I suggest using my [template project](https://github.com/benji7425/discord-bot-template) as a development context, along with [git subrepo](https://github.com/ingydotnet/git-subrepo) to push back to your core fork.
If you are uncomfortable using git subrepo, you could just as easily copy/paste your child `core` directory back into your fork.
My [template project](https://github.com/benji7425/discord-bot-template) has more in-depth details about how to setup and test.
If you have a completed change, please submit a pull request from your `core` fork back to this repo.
Whilst this is very easy to use once you know how, I appreciate this might be a little tricky if you aren't familiar with developing in this way.
Feel free to contact me if you would like assistance. Find contact details [here](https://benji7425.github.io/contact).

View File

@ -0,0 +1,8 @@
const Camo = require("camo");
// @ts-ignore
module.exports = class BaseEmbeddedData extends Camo.EmbeddedDocument {
constructor() {
super();
}
};

9
core/base-guild-data.js Normal file
View File

@ -0,0 +1,9 @@
const Camo = require("camo");
module.exports = class BaseGuildData extends Camo.Document {
constructor() {
super();
this.guildID = String;
}
};

83
core/client.js Normal file
View File

@ -0,0 +1,83 @@
const CoreUtil = require("./util.js");
const Camo = require("camo");
const CronJob = require("cron").CronJob;
const Discord = require("discord.js");
const HandleGuildMessage = require("./handle-guild-message.js");
// @ts-ignore
const InternalConfig = require("./internal-config.json");
const RequireAll = require("require-all");
let database;
module.exports = class Client extends Discord.Client {
/**
* Construct a new Discord.Client with some added functionality
* @param {string} token bot token
* @param {string} commandsDir location of dir containing commands .js files
* @param {*} guildDataModel GuildData model to be used for app; must extend BaseGuildData
*/
constructor(token, commandsDir, guildDataModel) {
super({
messageCacheMaxSize: 16,
disabledEvents: InternalConfig.disabledEvents
});
this._token = token;
this.commandsDir = commandsDir;
this.guildDataModel = guildDataModel;
this.commands = RequireAll(this.commandsDir);
this.on("ready", this._onReady);
this.on("message", this._onMessage);
this.on("debug", this._onDebug);
this.on("guildCreate", this._onGuildCreate);
process.on("uncaughtException", err => this._onUnhandledException(this, err));
}
_onReady() {
this.user.setGame(InternalConfig.website.replace(/^https?:\/\//, ""));
CoreUtil.dateLog(`Registered bot ${this.user.username}`);
}
_onMessage(message) {
if (message.channel.type === "text" && message.member)
HandleGuildMessage(this, message, this.commands);
}
_onDebug(info) {
info = info.replace(/Authenticated using token [^ ]+/, "Authenticated using token [redacted]");
if (!InternalConfig.debugIgnores.some(x => info.startsWith(x)))
CoreUtil.dateDebug(info);
}
_onGuildCreate(guild) {
CoreUtil.dateLog(`Added to guild ${guild.name}`);
}
_onUnhandledException(client, err) {
CoreUtil.dateError("Unhandled exception!\n", err);
CoreUtil.dateLog("Destroying existing client...");
client.destroy().then(() => {
CoreUtil.dateLog("Client destroyed, recreating...");
setTimeout(() => client.login(client._token), InternalConfig.reconnectTimeout);
});
}
bootstrap() {
Camo.connect(InternalConfig.dbConnectionString).then(db => {
database = db;
const dbProtocol = InternalConfig.dbConnectionString.match(/^(.+):\/\//)[1];
CoreUtil.dateLog(`Database protocol: ${dbProtocol}`);
if (dbProtocol === "nedb") {
CoreUtil.dateLog(`Seting up NeDB collection compaction cron job; schedule: ${InternalConfig.neDBCompactionSchedule}`);
new CronJob(InternalConfig.neDBCompactionSchedule, () => database.compactCollectionFiles(), null, true);
}
this.emit("beforeLogin");
this.login(this._token);
});
}
};

15
core/command.js Normal file
View File

@ -0,0 +1,15 @@
module.exports = class Command {
constructor({ name, description, syntax, admin, invoke }) {
this.name = name;
this.description = description;
this.syntax = syntax;
this.admin = admin;
this.invoke = invoke;
const params = this.syntax.split(/ +/);
const optionalParams = params.filter(x => x.match(/^\[.+\]$/));
this.maxParamCount = params.length - 1;
this.expectedParamCount = this.maxParamCount - optionalParams.length;
}
};

30
core/commands/help.js Normal file
View File

@ -0,0 +1,30 @@
const Command = require("../command.js");
const Discord = require("discord.js");
const InternalConfig = require("../internal-config.json");
const ParentPackageJson = require("../../package.json");
module.exports = new Command({
name: "help",
description: "Display available commands with descriptions",
syntax: "help",
admin: false,
invoke
});
function invoke({ commands, isMemberAdmin, client }) {
return Promise.resolve(createHelpEmbed(ParentPackageJson.name, commands, isMemberAdmin, client.user.username));
}
function createHelpEmbed(name, commands, userIsAdmin, username) {
const commandsArr = Object.keys(commands).map(x => commands[x]).filter(x => userIsAdmin || !x.admin);
const embed = new Discord.RichEmbed().setTitle(`__${(ParentPackageJson.name + "").replace("discord-bot-", "")} help__`);
commandsArr.forEach(command => {
embed.addField(command.name, `${command.description}\n**Usage:** *@${username} ${command.syntax}*${userIsAdmin && command.admin ? "\n***Admin only***" : ""}`);
});
embed.addField("__Need more help?__", `[Visit my website](${InternalConfig.website}) or [Join my Discord](${InternalConfig.discordInvite})`, true);
return { embed };
}

31
core/commands/reset.js Normal file
View File

@ -0,0 +1,31 @@
const Command = require("../command.js");
const Util = require("../util.js");
module.exports = new Command({
name: "reset",
description: "Reset all data for this Discord server. WARNING: YOU WILL LOSE ALL YOUR SETTINGS!",
syntax: "reset",
admin: true,
invoke
});
function invoke({ guildData, client, message }) {
return new Promise((resolve, reject) => {
/* this is a very hacky way of doing this, but when using .resolve()
the guildData object gets saved back to the database straight away,
meaning it'd be deleted and instnantly re-created. Using .reject
means that .save doesn't get called by the parent. Very hacky but works. */
Util.ask(client, message.channel, message.member, "Are you sure you want to delete all the data for this server? (yes/no)")
.then(response => {
if (response.toLowerCase() === "yes")
guildData
.delete()
.then(() => reject("Data for this server successfully deleted"));
else
reject("Guild data was not deleted");
});
// .then(() => resolve("Data for this server successfully deleted"))
// .catch(() => reject("Error deleting data for this server"));
});
}

31
core/commands/stats.js Normal file
View File

@ -0,0 +1,31 @@
const Command = require("../command.js");
module.exports = new Command({
name: "stats",
description: "Show some stats about the bot",
syntax: "stats",
admin: false,
invoke
});
function invoke({ message, params, guildData, client }) {
return Promise.resolve(`
**Server count:** ${client.guilds.size}
**Cached users:** ${client.users.size}
**Uptime:** ${toHHMMSS(client.uptime)}
`);
}
function toHHMMSS(ms) {
const secsTruncated = Math.trunc(ms / 1000); // don't forget the second param
const hrs = Math.floor(secsTruncated / 3600);
const mins = Math.floor((secsTruncated - (hrs * 3600)) / 60);
const secs = secsTruncated - (hrs * 3600) - (mins * 60);
let hoursStr = hrs.toString(), minsStr = mins.toString(), secsStr = secs.toString();
if (hrs < 10) { hoursStr = "0" + hrs; }
if (mins < 10) { minsStr = "0" + mins; }
if (secs < 10) { secsStr = "0" + secs; }
return hoursStr + ":" + minsStr + ":" + secsStr;
}

15
core/commands/version.js Normal file
View File

@ -0,0 +1,15 @@
const Command = require("../command.js");
// @ts-ignore
const ParentPackageJson = require("../../package.json");
module.exports = new Command({
name: "version",
description: "Return version number",
syntax: "version",
admin: false,
invoke
});
function invoke() {
return Promise.resolve(`${(ParentPackageJson.name + "").replace("discord-bot-", "")} v${ParentPackageJson.version}`);
}

View File

@ -0,0 +1,54 @@
const RequireAll = require("require-all");
const internalCommands = RequireAll(__dirname + "/commands");
function handleGuildMessage(client, message, commands) {
if (isCommand(message))
client.guildDataModel.findOne({ guildID: message.guild.id })
.then(guildData =>
handleGuildCommand(
client,
message,
Object.assign({}, internalCommands, commands),
guildData || client.guildDataModel.create({ guildID: message.guild.id })
));
}
function handleGuildCommand(client, message, commands, guildData) {
const { botName, isMemberAdmin, params, command } = parseDetails(message, commands);
if (!command)
return;
if (params.length < command.expectedParamCount)
message.reply(`Incorrect syntax!\n**Expected:** *${botName} ${command.syntax}*\n**Need help?** *${botName} help*`);
else if (isMemberAdmin || !command.admin)
command.invoke({ message, params, guildData, client, commands, isMemberAdmin })
.then(response => {
guildData.save()
.then(() => response && message.reply(response))
.catch(() => message.reply("Error saving"));
})
.catch(err => err && message.reply(err));
}
function parseDetails(message, commands) {
const split = message.content.split(/ +/);
const commandName = Object.keys(commands).find(x =>
/**/ commands[x].name.toLowerCase() === (split[1] || "").toLowerCase());
return {
botName: "@" + (message.guild.me.nickname || message.guild.me.user.username),
isMemberAdmin: message.member.permissions.has("ADMINISTRATOR"),
params: split.slice(2, split.length),
command: commands[commandName]
};
}
function isCommand(message) {
//criteria for a command is bot being mentioned
return new RegExp(`^<@!?${/[0-9]{18}/.exec(message.guild.me.toString())[0]}>`).exec(message.content);
}
module.exports = handleGuildMessage;

14
core/index.js Normal file
View File

@ -0,0 +1,14 @@
// @ts-ignore
const InternalConfig = require("./internal-config.json");
module.exports = {
Client: require("./client.js"),
BaseGuildData: require("./base-guild-data.js"),
BaseEmbeddedData: require("./base-embedded-data.js"),
Command: require("./command.js"),
util: require("./util.js"),
details: {
website: InternalConfig.website,
discordInvite: InternalConfig.discordInvite
}
};

20
core/internal-config.json Normal file
View File

@ -0,0 +1,20 @@
{
"dbConnectionString": "nedb://guilds-data",
"neDBCompactionSchedule": "0 0 * * * *",
"website": "https://benji7425.github.io",
"discordInvite": "https://discord.gg/SSkbwSJ",
"debugIgnores": [
"[ws] [connection] Sending a heartbeat",
"[ws] [connection] Heartbeat acknowledged"
],
"disabledEvents": [
"CHANNEL_PINS_UPDATE",
"GUILD_BAN_ADD",
"GUILD_BAN_REMOVE",
"PRESENCE_UPDATE",
"TYPING_START",
"USER_NOTE_UPDATE",
"USER_SETTINGS_UPDATE"
],
"askTimeout": 60000
}

476
core/package-lock.json generated Normal file
View File

@ -0,0 +1,476 @@
{
"name": "discord-bot-core",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@types/node": {
"version": "8.9.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.9.1.tgz",
"integrity": "sha512-4JFGIC1RSoFngVsT5EZcL793/uRi/OJ3ilsp9DQUr4LZOaMhNM1pPrt9TqlXOnXj3h73hl6NF31v87eQAPXYTg=="
},
"acorn": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz",
"integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ="
},
"amdefine": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
},
"ast-types": {
"version": "0.8.15",
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.8.15.tgz",
"integrity": "sha1-ju8IJ/BN/w7IhXupJavj/qYZTlI="
},
"async": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
"integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
},
"async-limiter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg="
},
"base62": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/base62/-/base62-0.1.1.tgz",
"integrity": "sha1-e0F0wvlESXU7EcJlHAg9qEGnsIQ="
},
"binary-search-tree": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/binary-search-tree/-/binary-search-tree-0.2.5.tgz",
"integrity": "sha1-fbs7IQ/coIJFDa0jNMMErzm9x4Q=",
"requires": {
"underscore": "~1.4.4"
}
},
"bson": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz",
"integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==",
"optional": true
},
"buffer-shims": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
"integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=",
"optional": true
},
"camo": {
"version": "git+https://github.com/benji7425/camo.git#51d63d2441827b430884400f511ae911f1961727",
"from": "git+https://github.com/benji7425/camo.git#v0.12.4",
"requires": {
"depd": "1.1.0",
"lodash": "3.9.3",
"mongodb": "^2.2.34",
"nedb": "1.8.0"
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"cron": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/cron/-/cron-1.3.0.tgz",
"integrity": "sha512-K/SF7JlgMmNjcThWxkKvsHhey2EDB4CeOEWJ9aXWj3fbQJppsvTPIeyLdHfNq5IbbsMUUjRW1nr5dSO95f2E4w==",
"requires": {
"moment-timezone": "^0.5.x"
}
},
"depd": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz",
"integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM="
},
"discord.js": {
"version": "11.2.0",
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-11.2.0.tgz",
"integrity": "sha1-qt3iuGtpuQUWa4O8Sc/ENSOOGus=",
"requires": {
"long": "^3.2.0",
"prism-media": "^0.0.1",
"snekfetch": "^3.3.0",
"tweetnacl": "^1.0.0",
"ws": "^3.1.0"
}
},
"es3ify": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/es3ify/-/es3ify-0.1.4.tgz",
"integrity": "sha1-rZ+l3xrjTz8x4SEbWBiy1RB439E=",
"requires": {
"esprima-fb": "~3001.0001.0000-dev-harmony-fb",
"jstransform": "~3.0.0",
"through": "~2.3.4"
}
},
"es6-promise": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
"integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=",
"optional": true
},
"esmangle-evaluator": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/esmangle-evaluator/-/esmangle-evaluator-1.0.1.tgz",
"integrity": "sha1-Yg2GbvSGGzMR91dm1SqFcrs8YzY="
},
"esprima-fb": {
"version": "3001.1.0-dev-harmony-fb",
"resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz",
"integrity": "sha1-t303q8046gt3Qmu4vCkizmtCZBE="
},
"falafel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/falafel/-/falafel-1.2.0.tgz",
"integrity": "sha1-wY0k71CRF0pJfzGM0ksCaiXN2rQ=",
"requires": {
"acorn": "^1.0.3",
"foreach": "^2.0.5",
"isarray": "0.0.1",
"object-keys": "^1.0.6"
}
},
"foreach": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
"integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
},
"immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"inline-process-browser": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/inline-process-browser/-/inline-process-browser-1.0.0.tgz",
"integrity": "sha1-RqYbFT3TybFiSxoAYm7bT39BTyI=",
"requires": {
"falafel": "^1.0.1",
"through2": "^0.6.5"
}
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"jstransform": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/jstransform/-/jstransform-3.0.0.tgz",
"integrity": "sha1-olkats7o2XvzvoMNv6IxO4fNZAs=",
"requires": {
"base62": "0.1.1",
"esprima-fb": "~3001.1.0-dev-harmony-fb",
"source-map": "0.1.31"
}
},
"lie": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.0.2.tgz",
"integrity": "sha1-/9oh17uibzd8rYZdNkmy/Izjn+o=",
"requires": {
"es3ify": "^0.1.3",
"immediate": "~3.0.5",
"inline-process-browser": "^1.0.0",
"unreachable-branch-transform": "^0.3.0"
}
},
"localforage": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.5.5.tgz",
"integrity": "sha1-VfwcOoikf2f1+sbxIxsl/xNVZCM=",
"requires": {
"lie": "3.0.2"
}
},
"lodash": {
"version": "3.9.3",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.9.3.tgz",
"integrity": "sha1-AVnoaDL+/8bWHYUrEqlTuZSWvTI="
},
"long": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
"integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s="
},
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"requires": {
"minimist": "0.0.8"
}
},
"moment": {
"version": "2.19.3",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.19.3.tgz",
"integrity": "sha1-vbmdJw1tf9p4zA+6zoVeJ/59pp8="
},
"moment-timezone": {
"version": "0.5.14",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.14.tgz",
"integrity": "sha1-TrOP+VOLgBCLpGekWPPtQmjM/LE=",
"requires": {
"moment": ">= 2.9.0"
}
},
"mongodb": {
"version": "2.2.35",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.35.tgz",
"integrity": "sha512-3HGLucDg/8EeYMin3k+nFWChTA85hcYDCw1lPsWR6yV9A6RgKb24BkLiZ9ySZR+S0nfBjWoIUS7cyV6ceGx5Gg==",
"optional": true,
"requires": {
"es6-promise": "3.2.1",
"mongodb-core": "2.1.19",
"readable-stream": "2.2.7"
}
},
"mongodb-core": {
"version": "2.1.19",
"resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.19.tgz",
"integrity": "sha512-Jt4AtWUkpuW03kRdYGxga4O65O1UHlFfvvInslEfLlGi+zDMxbBe3J2NVmN9qPJ957Mn6Iz0UpMtV80cmxCVxw==",
"optional": true,
"requires": {
"bson": "~1.0.4",
"require_optional": "~1.0.0"
}
},
"nedb": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/nedb/-/nedb-1.8.0.tgz",
"integrity": "sha1-DjUCzYLABNU1WkPJ5VV3vXvZHYg=",
"requires": {
"async": "0.2.10",
"binary-search-tree": "0.2.5",
"localforage": "^1.3.0",
"mkdirp": "~0.5.1",
"underscore": "~1.4.4"
}
},
"object-keys": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
"integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0="
},
"parent-package-json": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/parent-package-json/-/parent-package-json-2.0.1.tgz",
"integrity": "sha1-SbVUqeLcyu1F1+GiXqjOyde7axI="
},
"prism-media": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/prism-media/-/prism-media-0.0.1.tgz",
"integrity": "sha1-o0JcnKvVDRxsAuVDlBoRiVZnvRA="
},
"private": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
"integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
"optional": true
},
"readable-stream": {
"version": "2.2.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz",
"integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=",
"optional": true,
"requires": {
"buffer-shims": "~1.0.0",
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "~1.0.0",
"process-nextick-args": "~1.0.6",
"string_decoder": "~1.0.0",
"util-deprecate": "~1.0.1"
},
"dependencies": {
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"optional": true
},
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"optional": true,
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
"recast": {
"version": "0.10.43",
"resolved": "https://registry.npmjs.org/recast/-/recast-0.10.43.tgz",
"integrity": "sha1-uV1Q9tYHYaX2JS4V2AZ4FoSRzn8=",
"requires": {
"ast-types": "0.8.15",
"esprima-fb": "~15001.1001.0-dev-harmony-fb",
"private": "~0.1.5",
"source-map": "~0.5.0"
},
"dependencies": {
"esprima-fb": {
"version": "15001.1001.0-dev-harmony-fb",
"resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz",
"integrity": "sha1-Q761fsJujPI3092LM+QlM1d/Jlk="
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
}
}
},
"require-all": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/require-all/-/require-all-2.2.0.tgz",
"integrity": "sha1-tEIMIzrAKC0P9Jsnf7iAqLXeCJQ="
},
"require_optional": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
"integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
"optional": true,
"requires": {
"resolve-from": "^2.0.0",
"semver": "^5.1.0"
}
},
"resolve-from": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
"integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=",
"optional": true
},
"safe-buffer": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="
},
"semver": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
"integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
"optional": true
},
"simple-file-writer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/simple-file-writer/-/simple-file-writer-2.0.0.tgz",
"integrity": "sha1-4oPAoghoptQhnX7aGUwe9eK1gvo="
},
"snekfetch": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/snekfetch/-/snekfetch-3.6.1.tgz",
"integrity": "sha512-aLEvf1YR440pINb0LEo/SL2Q2s/A26+YEqPlx09A0XpGH7qWp8iqIFFolVILHn2yudWXJne9QWyQu+lzDp+ksQ=="
},
"source-map": {
"version": "0.1.31",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz",
"integrity": "sha1-n3BNDWnZ4TioG63267T94z0VHGE=",
"requires": {
"amdefine": ">=0.0.4"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
},
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
},
"through2": {
"version": "0.6.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
"integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
"requires": {
"readable-stream": ">=1.0.33-1 <1.1.0-0",
"xtend": ">=4.0.0 <4.1.0-0"
},
"dependencies": {
"readable-stream": {
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
}
}
},
"tweetnacl": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.0.tgz",
"integrity": "sha1-cT2LgY2kIGh0C/aDhtBHnmb8ins="
},
"ultron": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
},
"underscore": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz",
"integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ="
},
"unreachable-branch-transform": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/unreachable-branch-transform/-/unreachable-branch-transform-0.3.0.tgz",
"integrity": "sha1-2ZzExudG0mSSiEW2EdtUsPNHTKo=",
"requires": {
"esmangle-evaluator": "^1.0.0",
"recast": "^0.10.1",
"through2": "^0.6.2"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"optional": true
},
"ws": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.2.tgz",
"integrity": "sha512-t+WGpsNxhMR4v6EClXS8r8km5ZljKJzyGhJf7goJz9k5Ye3+b5Bvno5rjqPuIBn5mnn5GBb7o8IrIWHxX1qOLQ==",
"requires": {
"async-limiter": "~1.0.0",
"safe-buffer": "~5.1.0",
"ultron": "~1.1.0"
}
},
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
}
}
}

26
core/package.json Normal file
View File

@ -0,0 +1,26 @@
{
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@types/node": "8.9.1",
"camo": "git+https://github.com/benji7425/camo.git#v0.12.4",
"cron": "1.3.0",
"discord.js": "11.2.0",
"nedb": "1.8.0",
"parent-package-json": "2.0.1",
"require-all": "2.2.0",
"simple-file-writer": "2.0.0"
},
"name": "discord-bot-core",
"repository": {
"type": "git",
"url": "git+https://github.com/benji7425/discord-bot-core.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/benji7425/discord-bot-core/issues"
},
"homepage": "https://github.com/benji7425/discord-bot-core#readme",
"description": "Core code shared amongst my Discord bots"
}

74
core/util.js Normal file
View File

@ -0,0 +1,74 @@
// @ts-ignore
const InternalConfig = require("./internal-config.json");
const Console = require("console");
const SimpleFileWriter = require("simple-file-writer");
const logWriter = new SimpleFileWriter("./console.log");
const debugLogWriter = new SimpleFileWriter("./debug.log");
function ask(client, textChannel, member, question) {
//return a promise which will resolve once the user next sends a message in this textChannel
return new Promise((resolve, reject) => {
const cancelAsk = () => {
client.removeListener("message", handler);
textChannel.send("Response to question timed out");
};
const askTimeout = setTimeout(cancelAsk, InternalConfig.askTimeout);
const handler = responseMessage => {
if (responseMessage.channel.id === textChannel.id && responseMessage.member && responseMessage.member.id === member.id) {
clearTimeout(askTimeout);
resolve(responseMessage);
}
};
client.on("message", handler);
textChannel.send(member.toString() + " " + question).catch(reject);
});
}
function dateLog(...args) {
doDateLog(Console.log, logWriter, args, "INFO");
}
function dateError(...args) {
doDateLog(Console.error, logWriter, args, "ERROR");
}
function dateDebugError(...args) {
doDateLog(null, null, args, "DEBUG ERROR");
}
function dateDebug(...args) {
doDateLog(null, null, args, "DEBUG");
}
function doDateLog(consoleMethod, fileWriter, args, prefix = "") {
args = formatArgs([`[${prefix}]`].concat(args));
if (consoleMethod !== null)
consoleMethod.apply(this, args);
if (fileWriter !== null)
fileWriter.write(formatArgsForFile(args));
debugLogWriter.write(formatArgsForFile(args));
}
function formatArgs(args) {
return [`[${new Date().toUTCString()}]`].concat(args);
}
function formatArgsForFile(args) {
return args.join(" ") + "\n";
}
module.exports = {
dateError,
dateLog,
dateDebug,
dateDebugError,
ask
};

229
core/yarn.lock Normal file
View File

@ -0,0 +1,229 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@types/node@8.9.1":
version "8.9.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.9.1.tgz#5a329d73a97f3c5a626dfe0ed8c0b831fee5357a"
async-limiter@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
async@0.2.10:
version "0.2.10"
resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
binary-search-tree@0.2.5:
version "0.2.5"
resolved "https://registry.yarnpkg.com/binary-search-tree/-/binary-search-tree-0.2.5.tgz#7dbb3b210fdca082450dad2334c304af39bdc784"
dependencies:
underscore "~1.4.4"
bson@~1.0.4:
version "1.0.9"
resolved "https://registry.yarnpkg.com/bson/-/bson-1.0.9.tgz#12319f8323b1254739b7c6bef8d3e89ae05a2f57"
buffer-shims@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
"camo@git+https://github.com/benji7425/camo.git#v0.12.4":
version "0.12.4"
resolved "git+https://github.com/benji7425/camo.git#51d63d2441827b430884400f511ae911f1961727"
dependencies:
depd "1.1.0"
lodash "3.9.3"
optionalDependencies:
mongodb "^2.2.34"
nedb "1.8.0"
core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
cron@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/cron/-/cron-1.3.0.tgz#7e459968eaf94e1a445be796ce402166c234659d"
dependencies:
moment-timezone "^0.5.x"
depd@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3"
discord.js@11.2.0:
version "11.2.0"
resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-11.2.0.tgz#aadde2b86b69b905166b83bc49cfc435238e1aeb"
dependencies:
long "^3.2.0"
prism-media "^0.0.1"
snekfetch "^3.3.0"
tweetnacl "^1.0.0"
ws "^3.1.0"
es6-promise@3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4"
immediate@~3.0.5:
version "3.0.6"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
inherits@~2.0.1:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
lie@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
dependencies:
immediate "~3.0.5"
localforage@^1.3.0:
version "1.7.2"
resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.7.2.tgz#fa4442602f806edd2bca6a54ab4e656f031f121c"
dependencies:
lie "3.1.1"
lodash@3.9.3:
version "3.9.3"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.9.3.tgz#0159e86832feffc6d61d852b12a953b99496bd32"
long@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b"
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
mkdirp@~0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
dependencies:
minimist "0.0.8"
moment-timezone@^0.5.x:
version "0.5.21"
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.21.tgz#3cba247d84492174dbf71de2a9848fa13207b845"
dependencies:
moment ">= 2.9.0"
"moment@>= 2.9.0":
version "2.22.2"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
mongodb-core@2.1.19:
version "2.1.19"
resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.19.tgz#00fbd5e5a3573763b9171cfd844e60a8f2a3a18b"
dependencies:
bson "~1.0.4"
require_optional "~1.0.0"
mongodb@^2.2.34:
version "2.2.35"
resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.35.tgz#cd1b5af8a9463e3f9a787fa5b3d05565579730f9"
dependencies:
es6-promise "3.2.1"
mongodb-core "2.1.19"
readable-stream "2.2.7"
nedb@1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/nedb/-/nedb-1.8.0.tgz#0e3502cd82c004d5355a43c9e55577bd7bd91d88"
dependencies:
async "0.2.10"
binary-search-tree "0.2.5"
localforage "^1.3.0"
mkdirp "~0.5.1"
underscore "~1.4.4"
parent-package-json@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/parent-package-json/-/parent-package-json-2.0.1.tgz#49b554a9e2dccaed45d7e1a25ea8cec9d7bb6b12"
prism-media@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/prism-media/-/prism-media-0.0.1.tgz#a3425c9cabd50d1c6c02e543941a11895667bd10"
process-nextick-args@~1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
readable-stream@2.2.7:
version "2.2.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1"
dependencies:
buffer-shims "~1.0.0"
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "~1.0.0"
process-nextick-args "~1.0.6"
string_decoder "~1.0.0"
util-deprecate "~1.0.1"
require-all@2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/require-all/-/require-all-2.2.0.tgz#b4420c233ac0282d0ff49b277fb880a8b5de0894"
require_optional@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e"
dependencies:
resolve-from "^2.0.0"
semver "^5.1.0"
resolve-from@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
safe-buffer@~5.1.0:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
semver@^5.1.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
simple-file-writer@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/simple-file-writer/-/simple-file-writer-2.0.0.tgz#e283c0a20868a6d4219d7eda194c1ef5e2b582fa"
snekfetch@^3.3.0:
version "3.6.4"
resolved "https://registry.yarnpkg.com/snekfetch/-/snekfetch-3.6.4.tgz#d13e80a616d892f3d38daae4289f4d258a645120"
string_decoder@~1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
dependencies:
safe-buffer "~5.1.0"
tweetnacl@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.0.tgz#713d8b818da42068740bf68386d0479e66fc8a7b"
ultron@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
underscore@~1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.4.4.tgz#61a6a32010622afa07963bf325203cf12239d604"
util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
ws@^3.1.0:
version "3.3.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
dependencies:
async-limiter "~1.0.0"
safe-buffer "~5.1.0"
ultron "~1.1.0"

1329
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +1,30 @@
{
"version": "3.0.0-b2",
"main": "app/index.js",
"scripts": {
"start": "node bootstrap.js"
},
"dependencies": {
"discord.js": "11.1.0",
"discordjs-util": "git+https://github.com/benji7425/discordjs-util.git",
"feed-read": "0.0.1",
"get-urls": "7.0.0",
"jsonfile": "3.0.1",
"shortid": "2.2.8"
},
"name": "discord-bot-rss-feed",
"devDependencies": {},
"repository": {
"type": "git",
"url": "git+https://github.com/benji7425/discord-bot-rss-feed.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/benji7425/discord-bot-rss-feed/issues"
},
"homepage": "https://github.com/benji7425/discord-bot-rss-feed#readme",
"description": ""
"version": "3.5.2",
"main": "app/index.js",
"scripts": {
"postinstall": "cd ./core && npm install",
"start": "node ./app/index.js --name=rss-feed"
},
"dependencies": {
"@types/node": "9.3.0",
"discord.js": "11.2.0",
"eslint": "4.16.0",
"get-urls": "7.0.0",
"jsonfile": "3.0.1",
"rss-parser": "2.12.0",
"shortid": "2.2.8"
},
"name": "discord-bot-rss-feed",
"devDependencies": {},
"repository": {
"type": "git",
"url": "git+https://github.com/benji7425/discord-bot-rss-feed.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/benji7425/discord-bot-rss-feed/issues"
},
"homepage": "https://github.com/benji7425/discord-bot-rss-feed#readme",
"description": ""
}

967
yarn.lock Normal file
View File

@ -0,0 +1,967 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@types/node@9.3.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-9.3.0.tgz#3a129cda7c4e5df2409702626892cb4b96546dd5"
acorn-jsx@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
dependencies:
acorn "^3.0.4"
acorn@^3.0.4:
version "3.3.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
acorn@^5.5.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8"
ajv-keywords@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a"
ajv@^5.3.0:
version "5.5.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
dependencies:
co "^4.6.0"
fast-deep-equal "^1.0.0"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.3.0"
ajv@^6.0.1:
version "6.5.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.2.tgz#678495f9b82f7cca6be248dd92f59bff5e1f4360"
dependencies:
fast-deep-equal "^2.0.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.1"
ansi-escapes@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30"
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
ansi-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
dependencies:
color-convert "^1.9.0"
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
dependencies:
sprintf-js "~1.0.2"
array-union@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
dependencies:
array-uniq "^1.0.1"
array-uniq@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
arrify@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
async-limiter@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
babel-code-frame@^6.22.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
dependencies:
chalk "^1.1.3"
esutils "^2.0.2"
js-tokens "^3.0.2"
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
buffer-from@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04"
caller-path@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
dependencies:
callsites "^0.2.0"
callsites@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
dependencies:
ansi-styles "^2.2.1"
escape-string-regexp "^1.0.2"
has-ansi "^2.0.0"
strip-ansi "^3.0.0"
supports-color "^2.0.0"
chalk@^2.0.0, chalk@^2.1.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
dependencies:
ansi-styles "^3.2.1"
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chardet@^0.4.0:
version "0.4.2"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
circular-json@^0.3.1:
version "0.3.3"
resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
cli-cursor@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
dependencies:
restore-cursor "^2.0.0"
cli-width@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
color-convert@^1.9.0:
version "1.9.2"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147"
dependencies:
color-name "1.1.1"
color-name@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689"
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
concat-stream@^1.6.0:
version "1.6.2"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
dependencies:
buffer-from "^1.0.0"
inherits "^2.0.3"
readable-stream "^2.2.2"
typedarray "^0.0.6"
core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
cross-spawn@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
dependencies:
lru-cache "^4.0.1"
shebang-command "^1.2.0"
which "^1.2.9"
debug@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
dependencies:
ms "2.0.0"
deep-is@~0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
del@^2.0.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
dependencies:
globby "^5.0.0"
is-path-cwd "^1.0.0"
is-path-in-cwd "^1.0.0"
object-assign "^4.0.1"
pify "^2.0.0"
pinkie-promise "^2.0.0"
rimraf "^2.2.8"
discord.js@11.2.0:
version "11.2.0"
resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-11.2.0.tgz#aadde2b86b69b905166b83bc49cfc435238e1aeb"
dependencies:
long "^3.2.0"
prism-media "^0.0.1"
snekfetch "^3.3.0"
tweetnacl "^1.0.0"
ws "^3.1.0"
doctrine@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
dependencies:
esutils "^2.0.2"
entities@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
eslint-scope@^3.7.1:
version "3.7.1"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
dependencies:
esrecurse "^4.1.0"
estraverse "^4.1.1"
eslint-visitor-keys@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
eslint@4.16.0:
version "4.16.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.16.0.tgz#934ada9e98715e1d7bbfd6f6f0519ed2fab35cc1"
dependencies:
ajv "^5.3.0"
babel-code-frame "^6.22.0"
chalk "^2.1.0"
concat-stream "^1.6.0"
cross-spawn "^5.1.0"
debug "^3.1.0"
doctrine "^2.1.0"
eslint-scope "^3.7.1"
eslint-visitor-keys "^1.0.0"
espree "^3.5.2"
esquery "^1.0.0"
esutils "^2.0.2"
file-entry-cache "^2.0.0"
functional-red-black-tree "^1.0.1"
glob "^7.1.2"
globals "^11.0.1"
ignore "^3.3.3"
imurmurhash "^0.1.4"
inquirer "^3.0.6"
is-resolvable "^1.0.0"
js-yaml "^3.9.1"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.3.0"
lodash "^4.17.4"
minimatch "^3.0.2"
mkdirp "^0.5.1"
natural-compare "^1.4.0"
optionator "^0.8.2"
path-is-inside "^1.0.2"
pluralize "^7.0.0"
progress "^2.0.0"
require-uncached "^1.0.3"
semver "^5.3.0"
strip-ansi "^4.0.0"
strip-json-comments "~2.0.1"
table "^4.0.1"
text-table "~0.2.0"
espree@^3.5.2:
version "3.5.4"
resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7"
dependencies:
acorn "^5.5.0"
acorn-jsx "^3.0.0"
esprima@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
esquery@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708"
dependencies:
estraverse "^4.0.0"
esrecurse@^4.1.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf"
dependencies:
estraverse "^4.1.0"
estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
version "4.2.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
external-editor@^2.0.4:
version "2.2.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5"
dependencies:
chardet "^0.4.0"
iconv-lite "^0.4.17"
tmp "^0.0.33"
fast-deep-equal@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
fast-deep-equal@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
fast-json-stable-stringify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
fast-levenshtein@~2.0.4:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
figures@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
dependencies:
escape-string-regexp "^1.0.5"
file-entry-cache@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
dependencies:
flat-cache "^1.2.1"
object-assign "^4.0.1"
flat-cache@^1.2.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481"
dependencies:
circular-json "^0.3.1"
del "^2.0.2"
graceful-fs "^4.1.2"
write "^0.2.1"
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
functional-red-black-tree@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
get-urls@7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/get-urls/-/get-urls-7.0.0.tgz#c480adc7d4c6cc5cbb64b531823dc63b99ec1e5a"
dependencies:
normalize-url "^1.3.0"
url-regex "^4.0.0"
glob@^7.0.3, glob@^7.0.5, glob@^7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
globals@^11.0.1:
version "11.7.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673"
globby@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
dependencies:
array-union "^1.0.1"
arrify "^1.0.0"
glob "^7.0.3"
object-assign "^4.0.1"
pify "^2.0.0"
pinkie-promise "^2.0.0"
graceful-fs@^4.1.2, graceful-fs@^4.1.6:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
has-ansi@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
dependencies:
ansi-regex "^2.0.0"
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
iconv-lite@^0.4.17:
version "0.4.23"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
dependencies:
safer-buffer ">= 2.1.2 < 3"
ignore@^3.3.3:
version "3.3.10"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
dependencies:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@^2.0.3, inherits@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
inquirer@^3.0.6:
version "3.3.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9"
dependencies:
ansi-escapes "^3.0.0"
chalk "^2.0.0"
cli-cursor "^2.1.0"
cli-width "^2.0.0"
external-editor "^2.0.4"
figures "^2.0.0"
lodash "^4.3.0"
mute-stream "0.0.7"
run-async "^2.2.0"
rx-lite "^4.0.8"
rx-lite-aggregates "^4.0.8"
string-width "^2.1.0"
strip-ansi "^4.0.0"
through "^2.3.6"
ip-regex@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd"
is-fullwidth-code-point@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
is-path-cwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
is-path-in-cwd@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
dependencies:
is-path-inside "^1.0.0"
is-path-inside@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
dependencies:
path-is-inside "^1.0.1"
is-plain-obj@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
is-promise@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
is-resolvable@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
js-tokens@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
js-yaml@^3.9.1:
version "3.12.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
json-schema-traverse@^0.3.0:
version "0.3.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
json-stable-stringify-without-jsonify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
jsonfile@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66"
optionalDependencies:
graceful-fs "^4.1.6"
levn@^0.3.0, levn@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
dependencies:
prelude-ls "~1.1.2"
type-check "~0.3.2"
lodash@^4.17.4, lodash@^4.3.0:
version "4.17.10"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
long@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b"
lru-cache@^4.0.1:
version "4.1.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c"
dependencies:
pseudomap "^1.0.2"
yallist "^2.1.2"
mimic-fn@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
minimatch@^3.0.2, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
dependencies:
brace-expansion "^1.1.7"
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
mkdirp@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
dependencies:
minimist "0.0.8"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
mute-stream@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
normalize-url@^1.3.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c"
dependencies:
object-assign "^4.0.1"
prepend-http "^1.0.0"
query-string "^4.1.0"
sort-keys "^1.0.0"
object-assign@^4.0.1, object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
dependencies:
wrappy "1"
onetime@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
dependencies:
mimic-fn "^1.0.0"
optionator@^0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
dependencies:
deep-is "~0.1.3"
fast-levenshtein "~2.0.4"
levn "~0.3.0"
prelude-ls "~1.1.2"
type-check "~0.3.2"
wordwrap "~1.0.0"
os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
path-is-inside@^1.0.1, path-is-inside@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
pify@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
pinkie-promise@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
dependencies:
pinkie "^2.0.0"
pinkie@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
pluralize@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
prepend-http@^1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
prism-media@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/prism-media/-/prism-media-0.0.1.tgz#a3425c9cabd50d1c6c02e543941a11895667bd10"
process-nextick-args@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
progress@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
punycode@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
query-string@^4.1.0:
version "4.3.4"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb"
dependencies:
object-assign "^4.1.0"
strict-uri-encode "^1.0.0"
readable-stream@^2.2.2:
version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~2.0.0"
safe-buffer "~5.1.1"
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
require-uncached@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
dependencies:
caller-path "^0.1.0"
resolve-from "^1.0.0"
resolve-from@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
restore-cursor@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
dependencies:
onetime "^2.0.0"
signal-exit "^3.0.2"
rimraf@^2.2.8:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
dependencies:
glob "^7.0.5"
rss-parser@2.12.0:
version "2.12.0"
resolved "https://registry.yarnpkg.com/rss-parser/-/rss-parser-2.12.0.tgz#d8cd173aef9c1f0d66467465092bd6f99a8ec232"
dependencies:
entities "^1.1.1"
xml2js "^0.4.17"
run-async@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
dependencies:
is-promise "^2.1.0"
rx-lite-aggregates@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
dependencies:
rx-lite "*"
rx-lite@*, rx-lite@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
"safer-buffer@>= 2.1.2 < 3":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
sax@>=0.6.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
semver@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
dependencies:
shebang-regex "^1.0.0"
shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
shortid@2.2.8:
version "2.2.8"
resolved "https://registry.yarnpkg.com/shortid/-/shortid-2.2.8.tgz#033b117d6a2e975804f6f0969dbe7d3d0b355131"
signal-exit@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
slice-ansi@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d"
dependencies:
is-fullwidth-code-point "^2.0.0"
snekfetch@^3.3.0:
version "3.6.4"
resolved "https://registry.yarnpkg.com/snekfetch/-/snekfetch-3.6.4.tgz#d13e80a616d892f3d38daae4289f4d258a645120"
sort-keys@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"
dependencies:
is-plain-obj "^1.0.0"
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
strict-uri-encode@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
string-width@^2.1.0, string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
dependencies:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
dependencies:
safe-buffer "~5.1.0"
strip-ansi@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
dependencies:
ansi-regex "^2.0.0"
strip-ansi@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
dependencies:
ansi-regex "^3.0.0"
strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
striptags@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.1.1.tgz#c8c3e7fdd6fb4bb3a32a3b752e5b5e3e38093ebd"
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
supports-color@^5.3.0:
version "5.4.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
dependencies:
has-flag "^3.0.0"
table@^4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc"
dependencies:
ajv "^6.0.1"
ajv-keywords "^3.0.0"
chalk "^2.1.0"
lodash "^4.17.4"
slice-ansi "1.0.0"
string-width "^2.1.1"
text-table@~0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
through@^2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
tlds@^1.187.0:
version "1.203.1"
resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.203.1.tgz#4dc9b02f53de3315bc98b80665e13de3edfc1dfc"
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
dependencies:
os-tmpdir "~1.0.2"
tweetnacl@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.0.tgz#713d8b818da42068740bf68386d0479e66fc8a7b"
type-check@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
dependencies:
prelude-ls "~1.1.2"
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
ultron@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
uri-js@^4.2.1:
version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
dependencies:
punycode "^2.1.0"
url-regex@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/url-regex/-/url-regex-4.1.1.tgz#a5617b22e15e26dac57ce74c3f52088bcdfec995"
dependencies:
ip-regex "^1.0.1"
tlds "^1.187.0"
util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
which@^1.2.9:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
dependencies:
isexe "^2.0.0"
wordwrap@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
write@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
dependencies:
mkdirp "^0.5.1"
ws@^3.1.0:
version "3.3.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
dependencies:
async-limiter "~1.0.0"
safe-buffer "~5.1.0"
ultron "~1.1.0"
xml2js@^0.4.17:
version "0.4.19"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7"
dependencies:
sax ">=0.6.0"
xmlbuilder "~9.0.1"
xmlbuilder@~9.0.1:
version "9.0.7"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"