diff --git a/.gitignore b/.gitignore index 9976cb8..755eca0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,5 @@ node_modules test/auth.json -assets docs build diff --git a/package.json b/package.json index 4884e98..14cc438 100644 --- a/package.json +++ b/package.json @@ -5,15 +5,16 @@ "main": "build/index.js", "scripts": { "docs": "node_modules/.bin/jsdoc --configure .jsdoc.json --verbose", - "prepublish": "gulp", + "pub": "gulp && npm publish", + "install": "gulp", "test": "gulp && node test/bot.js" }, "engines": { "node": ">=6.0.0" }, "repository": { - "type": "git", - "url": "git+https://github.com/pyraxo/sylphy.git" + "url": "git+https://github.com/pyraxo/sylphy.git", + "type": "git" }, "keywords": [ "discord", diff --git a/res/emoji.json b/res/emoji.json new file mode 100644 index 0000000..4398941 --- /dev/null +++ b/res/emoji.json @@ -0,0 +1 @@ +{"100":"๐Ÿ’ฏ","1234":"๐Ÿ”ข","interrobang":"โ‰๏ธ","tm":"โ„ข๏ธ","information_source":"โ„น๏ธ","left_right_arrow":"โ†”๏ธ","arrow_up_down":"โ†•๏ธ","arrow_upper_left":"โ†–๏ธ","arrow_upper_right":"โ†—๏ธ","arrow_lower_right":"โ†˜๏ธ","arrow_lower_left":"โ†™๏ธ","keyboard":"โŒจ","sunny":"โ˜€๏ธ","cloud":"โ˜๏ธ","umbrella":"โ˜”๏ธ","showman":"โ˜ƒ","comet":"โ˜„","ballot_box_with_check":"โ˜‘๏ธ","coffee":"โ˜•๏ธ","shamrock":"โ˜˜","skull_and_crossbones":"โ˜ ","radioactive_sign":"โ˜ข","biohazard_sign":"โ˜ฃ","orthodox_cross":"โ˜ฆ","wheel_of_dharma":"โ˜ธ","white_frowning_face":"โ˜น","aries":"โ™ˆ๏ธ","taurus":"โ™‰๏ธ","sagittarius":"โ™๏ธ","capricorn":"โ™‘๏ธ","aquarius":"โ™’๏ธ","pisces":"โ™“๏ธ","spades":"โ™ ๏ธ","clubs":"โ™ฃ๏ธ","hearts":"โ™ฅ๏ธ","diamonds":"โ™ฆ๏ธ","hotsprings":"โ™จ๏ธ","hammer_and_pick":"โš’","anchor":"โš“๏ธ","crossed_swords":"โš”","scales":"โš–","alembic":"โš—","gear":"โš™","scissors":"โœ‚๏ธ","white_check_mark":"โœ…","airplane":"โœˆ๏ธ","email":"โœ‰๏ธ","envelope":"โœ‰๏ธ","black_nib":"โœ’๏ธ","heavy_check_mark":"โœ”๏ธ","heavy_multiplication_x":"โœ–๏ธ","star_of_david":"โœก","sparkles":"โœจ","eight_spoked_asterisk":"โœณ๏ธ","eight_pointed_black_star":"โœด๏ธ","snowflake":"โ„๏ธ","sparkle":"โ‡๏ธ","question":"โ“","grey_question":"โ”","grey_exclamation":"โ•","exclamation":"โ—๏ธ","heavy_exclamation_mark":"โ—๏ธ","heavy_heart_exclamation_mark_ornament":"โฃ","heart":"โค๏ธ","heavy_plus_sign":"โž•","heavy_minus_sign":"โž–","heavy_division_sign":"โž—","arrow_heading_up":"โคด๏ธ","arrow_heading_down":"โคต๏ธ","wavy_dash":"ใ€ฐ๏ธ","congratulations":"ใŠ—๏ธ","secret":"ใŠ™๏ธ","copyright":"ยฉ๏ธ","registered":"ยฎ๏ธ","bangbang":"โ€ผ๏ธ","leftwards_arrow_with_hook":"โ†ฉ๏ธ","arrow_right_hook":"โ†ช๏ธ","watch":"โŒš๏ธ","hourglass":"โŒ›๏ธ","fast_forward":"โฉ","rewind":"โช","arrow_double_up":"โซ","arrow_double_down":"โฌ","black_right_pointing_double_triangle_with_vertical_bar":"โญ","black_left_pointing_double_triangle_with_vertical_bar":"โฎ","black_right_pointing_triangle_with_double_vertical_bar":"โฏ","alarm_clock":"โฐ","stopwatch":"โฑ","timer_clock":"โฒ","hourglass_flowing_sand":"โณ","double_vertical_bar":"โธ","black_square_for_stop":"โน","black_circle_for_record":"โบ","m":"โ“‚๏ธ","black_small_square":"โ–ช๏ธ","white_small_square":"โ–ซ๏ธ","arrow_forward":"โ–ถ๏ธ","arrow_backward":"โ—€๏ธ","white_medium_square":"โ—ป๏ธ","black_medium_square":"โ—ผ๏ธ","white_medium_small_square":"โ—ฝ๏ธ","black_medium_small_square":"โ—พ๏ธ","phone":"โ˜Ž๏ธ","telephone":"โ˜Ž๏ธ","point_up":"โ˜๏ธ","star_and_crescent":"โ˜ช","peace_symbol":"โ˜ฎ","yin_yang":"โ˜ฏ","relaxed":"โ˜บ๏ธ","gemini":"โ™Š๏ธ","cancer":"โ™‹๏ธ","leo":"โ™Œ๏ธ","virgo":"โ™๏ธ","libra":"โ™Ž๏ธ","scorpius":"โ™๏ธ","recycle":"โ™ป๏ธ","wheelchair":"โ™ฟ๏ธ","atom_symbol":"โš›","fleur_de_lis":"โšœ","warning":"โš ๏ธ","zap":"โšก๏ธ","white_circle":"โšช๏ธ","black_circle":"โšซ๏ธ","coffin":"โšฐ","funeral_urn":"โšฑ","soccer":"โšฝ๏ธ","baseball":"โšพ๏ธ","snowman":"โ›„๏ธ","partly_sunny":"โ›…๏ธ","thunder_cloud_and_rain":"โ›ˆ","ophiuchus":"โ›Ž","pick":"โ›","helmet_with_white_cross":"โ›‘","chains":"โ›“","no_entry":"โ›”๏ธ","shinto_shrine":"โ›ฉ","church":"โ›ช๏ธ","mountain":"โ›ฐ","umbrella_on_ground":"โ›ฑ","fountain":"โ›ฒ๏ธ","golf":"โ›ณ๏ธ","ferry":"โ›ด","boat":"โ›ต๏ธ","sailboat":"โ›ต๏ธ","skier":"โ›ท","ice_skate":"โ›ธ","person_with_ball":"โ›น","tent":"โ›บ๏ธ","fuelpump":"โ›ฝ๏ธ","fist":"โœŠ","hand":"โœ‹","raised_hand":"โœ‹","v":"โœŒ๏ธ","writing_hand":"โœ","pencil2":"โœ๏ธ","latin_cross":"โœ","x":"โŒ","negative_squared_cross_mark":"โŽ","arrow_right":"โžก๏ธ","curly_loop":"โžฐ","loop":"โžฟ","arrow_left":"โฌ…๏ธ","arrow_up":"โฌ†๏ธ","arrow_down":"โฌ‡๏ธ","black_large_square":"โฌ›๏ธ","white_large_square":"โฌœ๏ธ","star":"โญ๏ธ","o":"โญ•๏ธ","part_alternation_mark":"ใ€ฝ๏ธ","mahjong":"๐Ÿ€„๏ธ","black_joker":"๐Ÿƒ","a":"๐Ÿ…ฐ๏ธ","b":"๐Ÿ…ฑ๏ธ","o2":"๐Ÿ…พ๏ธ","parking":"๐Ÿ…ฟ๏ธ","ab":"๐Ÿ†Ž","cl":"๐Ÿ†‘","cool":"๐Ÿ†’","free":"๐Ÿ†“","id":"๐Ÿ†”","new":"๐Ÿ†•","ng":"๐Ÿ†–","ok":"๐Ÿ†—","sos":"๐Ÿ†˜","up":"๐Ÿ†™","vs":"๐Ÿ†š","koko":"๐Ÿˆ","sa":"๐Ÿˆ‚๏ธ","u7121":"๐Ÿˆš๏ธ","u6307":"๐Ÿˆฏ๏ธ","u7981":"๐Ÿˆฒ","u7a7a":"๐Ÿˆณ","u5408":"๐Ÿˆด","u6e80":"๐Ÿˆต","u6709":"๐Ÿˆถ","u6708":"๐Ÿˆท๏ธ","u7533":"๐Ÿˆธ","u5272":"๐Ÿˆน","u55b6":"๐Ÿˆบ","ideograph_advantage":"๐Ÿ‰","accept":"๐Ÿ‰‘","cyclone":"๐ŸŒ€","foggy":"๐ŸŒ","closed_umbrella":"๐ŸŒ‚","night_with_stars":"๐ŸŒƒ","sunrise_over_mountains":"๐ŸŒ„","sunrise":"๐ŸŒ…","city_sunset":"๐ŸŒ†","city_sunrise":"๐ŸŒ‡","rainbow":"๐ŸŒˆ","bridge_at_night":"๐ŸŒ‰","ocean":"๐ŸŒŠ","volcano":"๐ŸŒ‹","milky_way":"๐ŸŒŒ","earth_africa":"๐ŸŒ","earth_americas":"๐ŸŒŽ","earth_asia":"๐ŸŒ","globe_with_meridians":"๐ŸŒ","new_moon":"๐ŸŒ‘","waxing_crescent_moon":"๐ŸŒ’","first_quarter_moon":"๐ŸŒ“","moon":"๐ŸŒ”","waxing_gibbous_moon":"๐ŸŒ”","full_moon":"๐ŸŒ•","waning_gibbous_moon":"๐ŸŒ–","last_quarter_moon":"๐ŸŒ—","waning_crescent_moon":"๐ŸŒ˜","crescent_moon":"๐ŸŒ™","new_moon_with_face":"๐ŸŒš","first_quarter_moon_with_face":"๐ŸŒ›","last_quarter_moon_with_face":"๐ŸŒœ","full_moon_with_face":"๐ŸŒ","sun_with_face":"๐ŸŒž","star2":"๐ŸŒŸ","stars":"๐ŸŒ ","thermometer":"๐ŸŒก","mostly_sunny":"๐ŸŒค","sun_small_cloud":"๐ŸŒค","barely_sunny":"๐ŸŒฅ","sun_behind_cloud":"๐ŸŒฅ","partly_sunny_rain":"๐ŸŒฆ","sun_behind_rain_cloud":"๐ŸŒฆ","rain_cloud":"๐ŸŒง","snow_cloud":"๐ŸŒจ","lightning":"๐ŸŒฉ","lightning_cloud":"๐ŸŒฉ","tornado":"๐ŸŒช","tornado_cloud":"๐ŸŒช","fog":"๐ŸŒซ","wind_blowing_face":"๐ŸŒฌ","hotdog":"๐ŸŒญ","taco":"๐ŸŒฎ","burrito":"๐ŸŒฏ","chestnut":"๐ŸŒฐ","seedling":"๐ŸŒฑ","evergreen_tree":"๐ŸŒฒ","deciduous_tree":"๐ŸŒณ","palm_tree":"๐ŸŒด","cactus":"๐ŸŒต","hot_pepper":"๐ŸŒถ","tulip":"๐ŸŒท","cherry_blossom":"๐ŸŒธ","rose":"๐ŸŒน","hibiscus":"๐ŸŒบ","sunflower":"๐ŸŒป","blossom":"๐ŸŒผ","corn":"๐ŸŒฝ","ear_of_rice":"๐ŸŒพ","herb":"๐ŸŒฟ","four_leaf_clover":"๐Ÿ€","maple_leaf":"๐Ÿ","fallen_leaf":"๐Ÿ‚","leaves":"๐Ÿƒ","mushroom":"๐Ÿ„","tomato":"๐Ÿ…","eggplant":"๐Ÿ†","grapes":"๐Ÿ‡","melon":"๐Ÿˆ","watermelon":"๐Ÿ‰","tangerine":"๐ŸŠ","lemon":"๐Ÿ‹","banana":"๐ŸŒ","pineapple":"๐Ÿ","apple":"๐ŸŽ","green_apple":"๐Ÿ","pear":"๐Ÿ","peach":"๐Ÿ‘","cherries":"๐Ÿ’","strawberry":"๐Ÿ“","hamburger":"๐Ÿ”","pizza":"๐Ÿ•","meat_on_bone":"๐Ÿ–","poultry_leg":"๐Ÿ—","rice_cracker":"๐Ÿ˜","rice_ball":"๐Ÿ™","rice":"๐Ÿš","curry":"๐Ÿ›","ramen":"๐Ÿœ","spaghetti":"๐Ÿ","bread":"๐Ÿž","fries":"๐ŸŸ","sweet_potato":"๐Ÿ ","dango":"๐Ÿก","oden":"๐Ÿข","sushi":"๐Ÿฃ","fried_shrimp":"๐Ÿค","fish_cake":"๐Ÿฅ","icecream":"๐Ÿฆ","shaved_ice":"๐Ÿง","ice_cream":"๐Ÿจ","doughnut":"๐Ÿฉ","cookie":"๐Ÿช","chocolate_bar":"๐Ÿซ","candy":"๐Ÿฌ","lollipop":"๐Ÿญ","custard":"๐Ÿฎ","honey_pot":"๐Ÿฏ","cake":"๐Ÿฐ","bento":"๐Ÿฑ","stew":"๐Ÿฒ","egg":"๐Ÿณ","fork_and_knife":"๐Ÿด","tea":"๐Ÿต","sake":"๐Ÿถ","wine_glass":"๐Ÿท","cocktail":"๐Ÿธ","tropical_drink":"๐Ÿน","beer":"๐Ÿบ","beers":"๐Ÿป","baby_bottle":"๐Ÿผ","knife_fork_plate":"๐Ÿฝ","champagne":"๐Ÿพ","popcorn":"๐Ÿฟ","ribbon":"๐ŸŽ€","gift":"๐ŸŽ","birthday":"๐ŸŽ‚","jack_o_lantern":"๐ŸŽƒ","christmas_tree":"๐ŸŽ„","santa":"๐ŸŽ…","fireworks":"๐ŸŽ†","sparkler":"๐ŸŽ‡","balloon":"๐ŸŽˆ","tada":"๐ŸŽ‰","confetti_ball":"๐ŸŽŠ","tanabata_tree":"๐ŸŽ‹","crossed_flags":"๐ŸŽŒ","bamboo":"๐ŸŽ","dolls":"๐ŸŽŽ","flags":"๐ŸŽ","wind_chime":"๐ŸŽ","rice_scene":"๐ŸŽ‘","school_satchel":"๐ŸŽ’","mortar_board":"๐ŸŽ“","medal":"๐ŸŽ–","reminder_ribbon":"๐ŸŽ—","studio_microphone":"๐ŸŽ™","level_slider":"๐ŸŽš","control_knobs":"๐ŸŽ›","film_frames":"๐ŸŽž","admission_tickets":"๐ŸŽŸ","carousel_horse":"๐ŸŽ ","ferris_wheel":"๐ŸŽก","roller_coaster":"๐ŸŽข","fishing_pole_and_fish":"๐ŸŽฃ","microphone":"๐ŸŽค","movie_camera":"๐ŸŽฅ","cinema":"๐ŸŽฆ","headphones":"๐ŸŽง","art":"๐ŸŽจ","tophat":"๐ŸŽฉ","circus_tent":"๐ŸŽช","ticket":"๐ŸŽซ","clapper":"๐ŸŽฌ","performing_arts":"๐ŸŽญ","video_game":"๐ŸŽฎ","dart":"๐ŸŽฏ","slot_machine":"๐ŸŽฐ","8ball":"๐ŸŽฑ","game_die":"๐ŸŽฒ","bowling":"๐ŸŽณ","flower_playing_cards":"๐ŸŽด","musical_note":"๐ŸŽต","notes":"๐ŸŽถ","saxophone":"๐ŸŽท","guitar":"๐ŸŽธ","musical_keyboard":"๐ŸŽน","trumpet":"๐ŸŽบ","violin":"๐ŸŽป","musical_score":"๐ŸŽผ","running_shirt_with_sash":"๐ŸŽฝ","tennis":"๐ŸŽพ","ski":"๐ŸŽฟ","basketball":"๐Ÿ€","checkered_flag":"๐Ÿ","snowboarder":"๐Ÿ‚","runner":"๐Ÿƒ","running":"๐Ÿƒ","surfer":"๐Ÿ„","sports_medal":"๐Ÿ…","trophy":"๐Ÿ†","horse_racing":"๐Ÿ‡","football":"๐Ÿˆ","rugby_football":"๐Ÿ‰","swimmer":"๐ŸŠ","weight_lifter":"๐Ÿ‹","golfer":"๐ŸŒ","racing_motorcycle":"๐Ÿ","racing_car":"๐ŸŽ","cricket_bat_and_ball":"๐Ÿ","volleyball":"๐Ÿ","field_hockey_stick_and_ball":"๐Ÿ‘","ice_hockey_stick_and_puck":"๐Ÿ’","table_tennis_paddle_and_ball":"๐Ÿ“","snow_capped_mountain":"๐Ÿ”","camping":"๐Ÿ•","beach_with_umbrella":"๐Ÿ–","building_construction":"๐Ÿ—","house_buildings":"๐Ÿ˜","cityscape":"๐Ÿ™","derelict_house_building":"๐Ÿš","classical_building":"๐Ÿ›","desert":"๐Ÿœ","desert_island":"๐Ÿ","national_park":"๐Ÿž","stadium":"๐ŸŸ","house":"๐Ÿ ","house_with_garden":"๐Ÿก","office":"๐Ÿข","post_office":"๐Ÿฃ","european_post_office":"๐Ÿค","hospital":"๐Ÿฅ","bank":"๐Ÿฆ","atm":"๐Ÿง","hotel":"๐Ÿจ","love_hotel":"๐Ÿฉ","convenience_store":"๐Ÿช","school":"๐Ÿซ","department_store":"๐Ÿฌ","factory":"๐Ÿญ","izakaya_lantern":"๐Ÿฎ","lantern":"๐Ÿฎ","japanese_castle":"๐Ÿฏ","european_castle":"๐Ÿฐ","waving_white_flag":"๐Ÿณ","waving_black_flag":"๐Ÿด","rosette":"๐Ÿต","label":"๐Ÿท","badminton_racquet_and_shuttlecock":"๐Ÿธ","bow_and_arrow":"๐Ÿน","amphora":"๐Ÿบ","skin-tone-2":"๐Ÿป","skin-tone-3":"๐Ÿผ","skin-tone-4":"๐Ÿฝ","skin-tone-5":"๐Ÿพ","skin-tone-6":"๐Ÿฟ","rat":"๐Ÿ€","mouse2":"๐Ÿ","ox":"๐Ÿ‚","water_buffalo":"๐Ÿƒ","cow2":"๐Ÿ„","tiger2":"๐Ÿ…","leopard":"๐Ÿ†","rabbit2":"๐Ÿ‡","cat2":"๐Ÿˆ","dragon":"๐Ÿ‰","crocodile":"๐ŸŠ","whale2":"๐Ÿ‹","snail":"๐ŸŒ","snake":"๐Ÿ","racehorse":"๐ŸŽ","ram":"๐Ÿ","goat":"๐Ÿ","sheep":"๐Ÿ‘","monkey":"๐Ÿ’","rooster":"๐Ÿ“","chicken":"๐Ÿ”","dog2":"๐Ÿ•","pig2":"๐Ÿ–","boar":"๐Ÿ—","elephant":"๐Ÿ˜","octopus":"๐Ÿ™","shell":"๐Ÿš","bug":"๐Ÿ›","ant":"๐Ÿœ","bee":"๐Ÿ","honeybee":"๐Ÿ","beetle":"๐Ÿž","fish":"๐ŸŸ","tropical_fish":"๐Ÿ ","blowfish":"๐Ÿก","turtle":"๐Ÿข","hatching_chick":"๐Ÿฃ","baby_chick":"๐Ÿค","hatched_chick":"๐Ÿฅ","bird":"๐Ÿฆ","penguin":"๐Ÿง","koala":"๐Ÿจ","poodle":"๐Ÿฉ","dromedary_camel":"๐Ÿช","camel":"๐Ÿซ","dolphin":"๐Ÿฌ","flipper":"๐Ÿฌ","mouse":"๐Ÿญ","cow":"๐Ÿฎ","tiger":"๐Ÿฏ","rabbit":"๐Ÿฐ","cat":"๐Ÿฑ","dragon_face":"๐Ÿฒ","whale":"๐Ÿณ","horse":"๐Ÿด","monkey_face":"๐Ÿต","dog":"๐Ÿถ","pig":"๐Ÿท","frog":"๐Ÿธ","hamster":"๐Ÿน","wolf":"๐Ÿบ","bear":"๐Ÿป","panda_face":"๐Ÿผ","pig_nose":"๐Ÿฝ","feet":"๐Ÿพ","paw_prints":"๐Ÿพ","chipmunk":"๐Ÿฟ","eyes":"๐Ÿ‘€","eye":"๐Ÿ‘","ear":"๐Ÿ‘‚","nose":"๐Ÿ‘ƒ","lips":"๐Ÿ‘„","tongue":"๐Ÿ‘…","point_up_2":"๐Ÿ‘†","point_down":"๐Ÿ‘‡","point_left":"๐Ÿ‘ˆ","point_right":"๐Ÿ‘‰","facepunch":"๐Ÿ‘Š","punch":"๐Ÿ‘Š","wave":"๐Ÿ‘‹","ok_hand":"๐Ÿ‘Œ","+1":"๐Ÿ‘","thumbsup":"๐Ÿ‘","-1":"๐Ÿ‘Ž","thumbsdown":"๐Ÿ‘Ž","clap":"๐Ÿ‘","open_hands":"๐Ÿ‘","crown":"๐Ÿ‘‘","womans_hat":"๐Ÿ‘’","eyeglasses":"๐Ÿ‘“","necktie":"๐Ÿ‘”","shirt":"๐Ÿ‘•","tshirt":"๐Ÿ‘•","jeans":"๐Ÿ‘–","dress":"๐Ÿ‘—","kimono":"๐Ÿ‘˜","bikini":"๐Ÿ‘™","womans_clothes":"๐Ÿ‘š","purse":"๐Ÿ‘›","handbag":"๐Ÿ‘œ","pouch":"๐Ÿ‘","mans_shoe":"๐Ÿ‘ž","shoe":"๐Ÿ‘ž","athletic_shoe":"๐Ÿ‘Ÿ","high_heel":"๐Ÿ‘ ","sandal":"๐Ÿ‘ก","boot":"๐Ÿ‘ข","footprints":"๐Ÿ‘ฃ","bust_in_silhouette":"๐Ÿ‘ค","busts_in_silhouette":"๐Ÿ‘ฅ","boy":"๐Ÿ‘ฆ","girl":"๐Ÿ‘ง","man":"๐Ÿ‘จ","woman":"๐Ÿ‘ฉ","family":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ","man-woman-boy":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ","couple":"๐Ÿ‘ซ","man_and_woman_holding_hands":"๐Ÿ‘ซ","two_men_holding_hands":"๐Ÿ‘ฌ","two_women_holding_hands":"๐Ÿ‘ญ","cop":"๐Ÿ‘ฎ","dancers":"๐Ÿ‘ฏ","bride_with_veil":"๐Ÿ‘ฐ","person_with_blond_hair":"๐Ÿ‘ฑ","man_with_gua_pi_mao":"๐Ÿ‘ฒ","man_with_turban":"๐Ÿ‘ณ","older_man":"๐Ÿ‘ด","older_woman":"๐Ÿ‘ต","baby":"๐Ÿ‘ถ","construction_worker":"๐Ÿ‘ท","princess":"๐Ÿ‘ธ","japanese_ogre":"๐Ÿ‘น","japanese_goblin":"๐Ÿ‘บ","ghost":"๐Ÿ‘ป","angel":"๐Ÿ‘ผ","alien":"๐Ÿ‘ฝ","space_invader":"๐Ÿ‘พ","imp":"๐Ÿ‘ฟ","skull":"๐Ÿ’€","information_desk_person":"๐Ÿ’","guardsman":"๐Ÿ’‚","dancer":"๐Ÿ’ƒ","lipstick":"๐Ÿ’„","nail_care":"๐Ÿ’…","massage":"๐Ÿ’†","haircut":"๐Ÿ’‡","barber":"๐Ÿ’ˆ","syringe":"๐Ÿ’‰","pill":"๐Ÿ’Š","kiss":"๐Ÿ’‹","love_letter":"๐Ÿ’Œ","ring":"๐Ÿ’","gem":"๐Ÿ’Ž","couplekiss":"๐Ÿ’","bouquet":"๐Ÿ’","couple_with_heart":"๐Ÿ’‘","wedding":"๐Ÿ’’","heartbeat":"๐Ÿ’“","broken_heart":"๐Ÿ’”","two_hearts":"๐Ÿ’•","sparkling_heart":"๐Ÿ’–","heartpulse":"๐Ÿ’—","cupid":"๐Ÿ’˜","blue_heart":"๐Ÿ’™","green_heart":"๐Ÿ’š","yellow_heart":"๐Ÿ’›","purple_heart":"๐Ÿ’œ","gift_heart":"๐Ÿ’","revolving_hearts":"๐Ÿ’ž","heart_decoration":"๐Ÿ’Ÿ","diamond_shape_with_a_dot_inside":"๐Ÿ’ ","bulb":"๐Ÿ’ก","anger":"๐Ÿ’ข","bomb":"๐Ÿ’ฃ","zzz":"๐Ÿ’ค","boom":"๐Ÿ’ฅ","collision":"๐Ÿ’ฅ","sweat_drops":"๐Ÿ’ฆ","droplet":"๐Ÿ’ง","dash":"๐Ÿ’จ","hankey":"๐Ÿ’ฉ","poop":"๐Ÿ’ฉ","shit":"๐Ÿ’ฉ","muscle":"๐Ÿ’ช","dizzy":"๐Ÿ’ซ","speech_balloon":"๐Ÿ’ฌ","thought_balloon":"๐Ÿ’ญ","white_flower":"๐Ÿ’ฎ","moneybag":"๐Ÿ’ฐ","currency_exchange":"๐Ÿ’ฑ","heavy_dollar_sign":"๐Ÿ’ฒ","credit_card":"๐Ÿ’ณ","yen":"๐Ÿ’ด","dollar":"๐Ÿ’ต","euro":"๐Ÿ’ถ","pound":"๐Ÿ’ท","money_with_wings":"๐Ÿ’ธ","chart":"๐Ÿ’น","seat":"๐Ÿ’บ","computer":"๐Ÿ’ป","briefcase":"๐Ÿ’ผ","minidisc":"๐Ÿ’ฝ","floppy_disk":"๐Ÿ’พ","cd":"๐Ÿ’ฟ","dvd":"๐Ÿ“€","file_folder":"๐Ÿ“","open_file_folder":"๐Ÿ“‚","page_with_curl":"๐Ÿ“ƒ","page_facing_up":"๐Ÿ“„","date":"๐Ÿ“…","calendar":"๐Ÿ“†","card_index":"๐Ÿ“‡","chart_with_upwards_trend":"๐Ÿ“ˆ","chart_with_downwards_trend":"๐Ÿ“‰","bar_chart":"๐Ÿ“Š","clipboard":"๐Ÿ“‹","pushpin":"๐Ÿ“Œ","round_pushpin":"๐Ÿ“","paperclip":"๐Ÿ“Ž","straight_ruler":"๐Ÿ“","triangular_ruler":"๐Ÿ“","bookmark_tabs":"๐Ÿ“‘","ledger":"๐Ÿ“’","notebook":"๐Ÿ““","notebook_with_decorative_cover":"๐Ÿ“”","closed_book":"๐Ÿ“•","book":"๐Ÿ“–","open_book":"๐Ÿ“–","green_book":"๐Ÿ“—","blue_book":"๐Ÿ“˜","orange_book":"๐Ÿ“™","books":"๐Ÿ“š","name_badge":"๐Ÿ“›","scroll":"๐Ÿ“œ","memo":"๐Ÿ“","pencil":"๐Ÿ“","telephone_receiver":"๐Ÿ“ž","pager":"๐Ÿ“Ÿ","fax":"๐Ÿ“ ","satellite":"๐Ÿ›ฐ","loudspeaker":"๐Ÿ“ข","mega":"๐Ÿ“ฃ","outbox_tray":"๐Ÿ“ค","inbox_tray":"๐Ÿ“ฅ","package":"๐Ÿ“ฆ","e-mail":"๐Ÿ“ง","incoming_envelope":"๐Ÿ“จ","envelope_with_arrow":"๐Ÿ“ฉ","mailbox_closed":"๐Ÿ“ช","mailbox":"๐Ÿ“ซ","mailbox_with_mail":"๐Ÿ“ฌ","mailbox_with_no_mail":"๐Ÿ“ญ","postbox":"๐Ÿ“ฎ","postal_horn":"๐Ÿ“ฏ","newspaper":"๐Ÿ“ฐ","iphone":"๐Ÿ“ฑ","calling":"๐Ÿ“ฒ","vibration_mode":"๐Ÿ“ณ","mobile_phone_off":"๐Ÿ“ด","no_mobile_phones":"๐Ÿ“ต","signal_strength":"๐Ÿ“ถ","camera":"๐Ÿ“ท","camera_with_flash":"๐Ÿ“ธ","video_camera":"๐Ÿ“น","tv":"๐Ÿ“บ","radio":"๐Ÿ“ป","vhs":"๐Ÿ“ผ","film_projector":"๐Ÿ“ฝ","prayer_beads":"๐Ÿ“ฟ","twisted_rightwards_arrows":"๐Ÿ”€","repeat":"๐Ÿ”","repeat_one":"๐Ÿ”‚","arrows_clockwise":"๐Ÿ”ƒ","arrows_counterclockwise":"๐Ÿ”„","low_brightness":"๐Ÿ”…","high_brightness":"๐Ÿ”†","mute":"๐Ÿ”‡","speaker":"๐Ÿ”ˆ","sound":"๐Ÿ”‰","loud_sound":"๐Ÿ”Š","battery":"๐Ÿ”‹","electric_plug":"๐Ÿ”Œ","mag":"๐Ÿ”","mag_right":"๐Ÿ”Ž","lock_with_ink_pen":"๐Ÿ”","closed_lock_with_key":"๐Ÿ”","key":"๐Ÿ”‘","lock":"๐Ÿ”’","unlock":"๐Ÿ”“","bell":"๐Ÿ””","no_bell":"๐Ÿ”•","bookmark":"๐Ÿ”–","link":"๐Ÿ”—","radio_button":"๐Ÿ”˜","back":"๐Ÿ”™","end":"๐Ÿ”š","on":"๐Ÿ”›","soon":"๐Ÿ”œ","top":"๐Ÿ”","underage":"๐Ÿ”ž","keycap_ten":"๐Ÿ”Ÿ","capital_abcd":"๐Ÿ” ","abcd":"๐Ÿ”ก","symbols":"๐Ÿ”ฃ","abc":"๐Ÿ”ค","fire":"๐Ÿ”ฅ","flashlight":"๐Ÿ”ฆ","wrench":"๐Ÿ”ง","hammer":"๐Ÿ”จ","nut_and_bolt":"๐Ÿ”ฉ","hocho":"๐Ÿ”ช","knife":"๐Ÿ”ช","gun":"๐Ÿ”ซ","microscope":"๐Ÿ”ฌ","telescope":"๐Ÿ”ญ","crystal_ball":"๐Ÿ”ฎ","six_pointed_star":"๐Ÿ”ฏ","beginner":"๐Ÿ”ฐ","trident":"๐Ÿ”ฑ","black_square_button":"๐Ÿ”ฒ","white_square_button":"๐Ÿ”ณ","red_circle":"๐Ÿ”ด","large_blue_circle":"๐Ÿ”ต","large_orange_diamond":"๐Ÿ”ถ","large_blue_diamond":"๐Ÿ”ท","small_orange_diamond":"๐Ÿ”ธ","small_blue_diamond":"๐Ÿ”น","small_red_triangle":"๐Ÿ”บ","small_red_triangle_down":"๐Ÿ”ป","arrow_up_small":"๐Ÿ”ผ","arrow_down_small":"๐Ÿ”ฝ","om_symbol":"๐Ÿ•‰","dove_of_peace":"๐Ÿ•Š","kaaba":"๐Ÿ•‹","mosque":"๐Ÿ•Œ","synagogue":"๐Ÿ•","menorah_with_nine_branches":"๐Ÿ•Ž","clock1":"๐Ÿ•","clock2":"๐Ÿ•‘","clock3":"๐Ÿ•’","clock4":"๐Ÿ•“","clock5":"๐Ÿ•”","clock6":"๐Ÿ••","clock7":"๐Ÿ•–","clock8":"๐Ÿ•—","clock9":"๐Ÿ•˜","clock10":"๐Ÿ•™","clock11":"๐Ÿ•š","clock12":"๐Ÿ•›","clock130":"๐Ÿ•œ","clock230":"๐Ÿ•","clock330":"๐Ÿ•ž","clock430":"๐Ÿ•Ÿ","clock530":"๐Ÿ• ","clock630":"๐Ÿ•ก","clock730":"๐Ÿ•ข","clock830":"๐Ÿ•ฃ","clock930":"๐Ÿ•ค","clock1030":"๐Ÿ•ฅ","clock1130":"๐Ÿ•ฆ","clock1230":"๐Ÿ•ง","candle":"๐Ÿ•ฏ","mantelpiece_clock":"๐Ÿ•ฐ","hole":"๐Ÿ•ณ","man_in_business_suit_levitating":"๐Ÿ•ด","sleuth_or_spy":"๐Ÿ•ต","dark_sunglasses":"๐Ÿ•ถ","spider":"๐Ÿ•ท","spider_web":"๐Ÿ•ธ","joystick":"๐Ÿ•น","linked_paperclips":"๐Ÿ–‡","lower_left_ballpoint_pen":"๐Ÿ–Š","lower_left_fountain_pen":"๐Ÿ–‹","lower_left_paintbrush":"๐Ÿ–Œ","lower_left_crayon":"๐Ÿ–","raised_hand_with_fingers_splayed":"๐Ÿ–","middle_finger":"๐Ÿ–•","reversed_hand_with_middle_finger_extended":"๐Ÿ–•","spock-hand":"๐Ÿ––","desktop_computer":"๐Ÿ–ฅ","printer":"๐Ÿ–จ","three_button_mouse":"๐Ÿ–ฑ","trackball":"๐Ÿ–ฒ","frame_with_picture":"๐Ÿ–ผ","card_index_dividers":"๐Ÿ—‚","card_file_box":"๐Ÿ—ƒ","file_cabinet":"๐Ÿ—„","wastebasket":"๐Ÿ—‘","spiral_note_pad":"๐Ÿ—’","spiral_calendar_pad":"๐Ÿ—“","compression":"๐Ÿ—œ","old_key":"๐Ÿ—","rolled_up_newspaper":"๐Ÿ—ž","dagger_knife":"๐Ÿ—ก","speaking_head_in_silhouette":"๐Ÿ—ฃ","left_speech_bubble":"๐Ÿ—จ","right_anger_bubble":"๐Ÿ—ฏ","ballot_box_with_ballot":"๐Ÿ—ณ","world_map":"๐Ÿ—บ","mount_fuji":"๐Ÿ—ป","tokyo_tower":"๐Ÿ—ผ","statue_of_liberty":"๐Ÿ—ฝ","japan":"๐Ÿ—พ","moyai":"๐Ÿ—ฟ","grinning":"๐Ÿ˜€","grin":"๐Ÿ˜","joy":"๐Ÿ˜‚","smiley":"๐Ÿ˜ƒ","smile":"๐Ÿ˜„","sweat_smile":"๐Ÿ˜…","laughing":"๐Ÿ˜†","satisfied":"๐Ÿ˜†","innocent":"๐Ÿ˜‡","smiling_imp":"๐Ÿ˜ˆ","wink":"๐Ÿ˜‰","blush":"๐Ÿ˜Š","yum":"๐Ÿ˜‹","relieved":"๐Ÿ˜Œ","heart_eyes":"๐Ÿ˜","sunglasses":"๐Ÿ˜Ž","smirk":"๐Ÿ˜","neutral_face":"๐Ÿ˜","expressionless":"๐Ÿ˜‘","unamused":"๐Ÿ˜’","sweat":"๐Ÿ˜“","pensive":"๐Ÿ˜”","confused":"๐Ÿ˜•","confounded":"๐Ÿ˜–","kissing":"๐Ÿ˜—","kissing_heart":"๐Ÿ˜˜","kissing_smiling_eyes":"๐Ÿ˜™","kissing_closed_eyes":"๐Ÿ˜š","stuck_out_tongue":"๐Ÿ˜›","stuck_out_tongue_winking_eye":"๐Ÿ˜œ","stuck_out_tongue_closed_eyes":"๐Ÿ˜","disappointed":"๐Ÿ˜ž","worried":"๐Ÿ˜Ÿ","angry":"๐Ÿ˜ ","rage":"๐Ÿ˜ก","cry":"๐Ÿ˜ข","persevere":"๐Ÿ˜ฃ","triumph":"๐Ÿ˜ค","disappointed_relieved":"๐Ÿ˜ฅ","frowning":"๐Ÿ˜ฆ","anguished":"๐Ÿ˜ง","fearful":"๐Ÿ˜จ","weary":"๐Ÿ˜ฉ","sleepy":"๐Ÿ˜ช","tired_face":"๐Ÿ˜ซ","grimacing":"๐Ÿ˜ฌ","sob":"๐Ÿ˜ญ","open_mouth":"๐Ÿ˜ฎ","hushed":"๐Ÿ˜ฏ","cold_sweat":"๐Ÿ˜ฐ","scream":"๐Ÿ˜ฑ","astonished":"๐Ÿ˜ฒ","flushed":"๐Ÿ˜ณ","sleeping":"๐Ÿ˜ด","dizzy_face":"๐Ÿ˜ต","no_mouth":"๐Ÿ˜ถ","mask":"๐Ÿ˜ท","smile_cat":"๐Ÿ˜ธ","joy_cat":"๐Ÿ˜น","smiley_cat":"๐Ÿ˜บ","heart_eyes_cat":"๐Ÿ˜ป","smirk_cat":"๐Ÿ˜ผ","kissing_cat":"๐Ÿ˜ฝ","pouting_cat":"๐Ÿ˜พ","crying_cat_face":"๐Ÿ˜ฟ","scream_cat":"๐Ÿ™€","slightly_frowning_face":"๐Ÿ™","slightly_smiling_face":"๐Ÿ™‚","upside_down_face":"๐Ÿ™ƒ","face_with_rolling_eyes":"๐Ÿ™„","no_good":"๐Ÿ™…","ok_woman":"๐Ÿ™†","bow":"๐Ÿ™‡","see_no_evil":"๐Ÿ™ˆ","hear_no_evil":"๐Ÿ™‰","speak_no_evil":"๐Ÿ™Š","raising_hand":"๐Ÿ™‹","raised_hands":"๐Ÿ™Œ","person_frowning":"๐Ÿ™","person_with_pouting_face":"๐Ÿ™Ž","pray":"๐Ÿ™","rocket":"๐Ÿš€","helicopter":"๐Ÿš","steam_locomotive":"๐Ÿš‚","railway_car":"๐Ÿšƒ","bullettrain_side":"๐Ÿš„","bullettrain_front":"๐Ÿš…","train2":"๐Ÿš†","metro":"๐Ÿš‡","light_rail":"๐Ÿšˆ","station":"๐Ÿš‰","tram":"๐ŸšŠ","train":"๐Ÿš‹","bus":"๐ŸšŒ","oncoming_bus":"๐Ÿš","trolleybus":"๐ŸšŽ","busstop":"๐Ÿš","minibus":"๐Ÿš","ambulance":"๐Ÿš‘","fire_engine":"๐Ÿš’","police_car":"๐Ÿš“","oncoming_police_car":"๐Ÿš”","taxi":"๐Ÿš•","oncoming_taxi":"๐Ÿš–","car":"๐Ÿš—","red_car":"๐Ÿš—","oncoming_automobile":"๐Ÿš˜","blue_car":"๐Ÿš™","truck":"๐Ÿšš","articulated_lorry":"๐Ÿš›","tractor":"๐Ÿšœ","monorail":"๐Ÿš","mountain_railway":"๐Ÿšž","suspension_railway":"๐ŸšŸ","mountain_cableway":"๐Ÿš ","aerial_tramway":"๐Ÿšก","ship":"๐Ÿšข","rowboat":"๐Ÿšฃ","speedboat":"๐Ÿšค","traffic_light":"๐Ÿšฅ","vertical_traffic_light":"๐Ÿšฆ","construction":"๐Ÿšง","rotating_light":"๐Ÿšจ","triangular_flag_on_post":"๐Ÿšฉ","door":"๐Ÿšช","no_entry_sign":"๐Ÿšซ","smoking":"๐Ÿšฌ","no_smoking":"๐Ÿšญ","put_litter_in_its_place":"๐Ÿšฎ","do_not_litter":"๐Ÿšฏ","potable_water":"๐Ÿšฐ","non-potable_water":"๐Ÿšฑ","bike":"๐Ÿšฒ","no_bicycles":"๐Ÿšณ","bicyclist":"๐Ÿšด","mountain_bicyclist":"๐Ÿšต","walking":"๐Ÿšถ","no_pedestrians":"๐Ÿšท","children_crossing":"๐Ÿšธ","mens":"๐Ÿšน","womens":"๐Ÿšบ","restroom":"๐Ÿšป","baby_symbol":"๐Ÿšผ","toilet":"๐Ÿšฝ","wc":"๐Ÿšพ","shower":"๐Ÿšฟ","bath":"๐Ÿ›€","bathtub":"๐Ÿ›","passport_control":"๐Ÿ›‚","customs":"๐Ÿ›ƒ","baggage_claim":"๐Ÿ›„","left_luggage":"๐Ÿ›…","couch_and_lamp":"๐Ÿ›‹","sleeping_accommodation":"๐Ÿ›Œ","shopping_bags":"๐Ÿ›","bellhop_bell":"๐Ÿ›Ž","bed":"๐Ÿ›","place_of_worship":"๐Ÿ›","hammer_and_wrench":"๐Ÿ› ","shield":"๐Ÿ›ก","oil_drum":"๐Ÿ›ข","motorway":"๐Ÿ›ฃ","railway_track":"๐Ÿ›ค","motor_boat":"๐Ÿ›ฅ","small_airplane":"๐Ÿ›ฉ","airplane_departure":"๐Ÿ›ซ","airplane_arriving":"๐Ÿ›ฌ","passenger_ship":"๐Ÿ›ณ","zipper_mouth_face":"๐Ÿค","money_mouth_face":"๐Ÿค‘","face_with_thermometer":"๐Ÿค’","nerd_face":"๐Ÿค“","thinking_face":"๐Ÿค”","face_with_head_bandage":"๐Ÿค•","robot_face":"๐Ÿค–","hugging_face":"๐Ÿค—","the_horns":"๐Ÿค˜","sign_of_the_horns":"๐Ÿค˜","crab":"๐Ÿฆ€","lion_face":"๐Ÿฆ","scorpion":"๐Ÿฆ‚","turkey":"๐Ÿฆƒ","unicorn_face":"๐Ÿฆ„","cheese_wedge":"๐Ÿง€","hash":"#๏ธโƒฃ","keycap_star":"*โƒฃ","zero":"0๏ธโƒฃ","one":"1๏ธโƒฃ","two":"2๏ธโƒฃ","three":"3๏ธโƒฃ","four":"4๏ธโƒฃ","five":"5๏ธโƒฃ","six":"6๏ธโƒฃ","seven":"7๏ธโƒฃ","eight":"8๏ธโƒฃ","nine":"9๏ธโƒฃ","flag-ac":"๐Ÿ‡ฆ๐Ÿ‡จ","flag-ad":"๐Ÿ‡ฆ๐Ÿ‡ฉ","flag-ae":"๐Ÿ‡ฆ๐Ÿ‡ช","flag-af":"๐Ÿ‡ฆ๐Ÿ‡ซ","flag-ag":"๐Ÿ‡ฆ๐Ÿ‡ฌ","flag-ai":"๐Ÿ‡ฆ๐Ÿ‡ฎ","flag-al":"๐Ÿ‡ฆ๐Ÿ‡ฑ","flag-am":"๐Ÿ‡ฆ๐Ÿ‡ฒ","flag-ao":"๐Ÿ‡ฆ๐Ÿ‡ด","flag-aq":"๐Ÿ‡ฆ๐Ÿ‡ถ","flag-ar":"๐Ÿ‡ฆ๐Ÿ‡ท","flag-as":"๐Ÿ‡ฆ๐Ÿ‡ธ","flag-at":"๐Ÿ‡ฆ๐Ÿ‡น","flag-au":"๐Ÿ‡ฆ๐Ÿ‡บ","flag-aw":"๐Ÿ‡ฆ๐Ÿ‡ผ","flag-ax":"๐Ÿ‡ฆ๐Ÿ‡ฝ","flag-az":"๐Ÿ‡ฆ๐Ÿ‡ฟ","flag-ba":"๐Ÿ‡ง๐Ÿ‡ฆ","flag-bb":"๐Ÿ‡ง๐Ÿ‡ง","flag-bd":"๐Ÿ‡ง๐Ÿ‡ฉ","flag-be":"๐Ÿ‡ง๐Ÿ‡ช","flag-bf":"๐Ÿ‡ง๐Ÿ‡ซ","flag-bg":"๐Ÿ‡ง๐Ÿ‡ฌ","flag-bh":"๐Ÿ‡ง๐Ÿ‡ญ","flag-bi":"๐Ÿ‡ง๐Ÿ‡ฎ","flag-bj":"๐Ÿ‡ง๐Ÿ‡ฏ","flag-bl":"๐Ÿ‡ง๐Ÿ‡ฑ","flag-bm":"๐Ÿ‡ง๐Ÿ‡ฒ","flag-bn":"๐Ÿ‡ง๐Ÿ‡ณ","flag-bo":"๐Ÿ‡ง๐Ÿ‡ด","flag-bq":"๐Ÿ‡ง๐Ÿ‡ถ","flag-br":"๐Ÿ‡ง๐Ÿ‡ท","flag-bs":"๐Ÿ‡ง๐Ÿ‡ธ","flag-bt":"๐Ÿ‡ง๐Ÿ‡น","flag-bv":"๐Ÿ‡ง๐Ÿ‡ป","flag-bw":"๐Ÿ‡ง๐Ÿ‡ผ","flag-by":"๐Ÿ‡ง๐Ÿ‡พ","flag-bz":"๐Ÿ‡ง๐Ÿ‡ฟ","flag-ca":"๐Ÿ‡จ๐Ÿ‡ฆ","flag-cc":"๐Ÿ‡จ๐Ÿ‡จ","flag-cd":"๐Ÿ‡จ๐Ÿ‡ฉ","flag-cf":"๐Ÿ‡จ๐Ÿ‡ซ","flag-cg":"๐Ÿ‡จ๐Ÿ‡ฌ","flag-ch":"๐Ÿ‡จ๐Ÿ‡ญ","flag-ci":"๐Ÿ‡จ๐Ÿ‡ฎ","flag-ck":"๐Ÿ‡จ๐Ÿ‡ฐ","flag-cl":"๐Ÿ‡จ๐Ÿ‡ฑ","flag-cm":"๐Ÿ‡จ๐Ÿ‡ฒ","flag-cn":"๐Ÿ‡จ๐Ÿ‡ณ","cn":"๐Ÿ‡จ๐Ÿ‡ณ","flag-co":"๐Ÿ‡จ๐Ÿ‡ด","flag-cp":"๐Ÿ‡จ๐Ÿ‡ต","flag-cr":"๐Ÿ‡จ๐Ÿ‡ท","flag-cu":"๐Ÿ‡จ๐Ÿ‡บ","flag-cv":"๐Ÿ‡จ๐Ÿ‡ป","flag-cw":"๐Ÿ‡จ๐Ÿ‡ผ","flag-cx":"๐Ÿ‡จ๐Ÿ‡ฝ","flag-cy":"๐Ÿ‡จ๐Ÿ‡พ","flag-cz":"๐Ÿ‡จ๐Ÿ‡ฟ","flag-de":"๐Ÿ‡ฉ๐Ÿ‡ช","de":"๐Ÿ‡ฉ๐Ÿ‡ช","flag-dg":"๐Ÿ‡ฉ๐Ÿ‡ฌ","flag-dj":"๐Ÿ‡ฉ๐Ÿ‡ฏ","flag-dk":"๐Ÿ‡ฉ๐Ÿ‡ฐ","flag-dm":"๐Ÿ‡ฉ๐Ÿ‡ฒ","flag-do":"๐Ÿ‡ฉ๐Ÿ‡ด","flag-dz":"๐Ÿ‡ฉ๐Ÿ‡ฟ","flag-ea":"๐Ÿ‡ช๐Ÿ‡ฆ","flag-ec":"๐Ÿ‡ช๐Ÿ‡จ","flag-ee":"๐Ÿ‡ช๐Ÿ‡ช","flag-eg":"๐Ÿ‡ช๐Ÿ‡ฌ","flag-eh":"๐Ÿ‡ช๐Ÿ‡ญ","flag-er":"๐Ÿ‡ช๐Ÿ‡ท","flag-es":"๐Ÿ‡ช๐Ÿ‡ธ","es":"๐Ÿ‡ช๐Ÿ‡ธ","flag-et":"๐Ÿ‡ช๐Ÿ‡น","flag-eu":"๐Ÿ‡ช๐Ÿ‡บ","flag-fi":"๐Ÿ‡ซ๐Ÿ‡ฎ","flag-fj":"๐Ÿ‡ซ๐Ÿ‡ฏ","flag-fk":"๐Ÿ‡ซ๐Ÿ‡ฐ","flag-fm":"๐Ÿ‡ซ๐Ÿ‡ฒ","flag-fo":"๐Ÿ‡ซ๐Ÿ‡ด","flag-fr":"๐Ÿ‡ซ๐Ÿ‡ท","fr":"๐Ÿ‡ซ๐Ÿ‡ท","flag-ga":"๐Ÿ‡ฌ๐Ÿ‡ฆ","flag-gb":"๐Ÿ‡ฌ๐Ÿ‡ง","gb":"๐Ÿ‡ฌ๐Ÿ‡ง","uk":"๐Ÿ‡ฌ๐Ÿ‡ง","flag-gd":"๐Ÿ‡ฌ๐Ÿ‡ฉ","flag-ge":"๐Ÿ‡ฌ๐Ÿ‡ช","flag-gf":"๐Ÿ‡ฌ๐Ÿ‡ซ","flag-gg":"๐Ÿ‡ฌ๐Ÿ‡ฌ","flag-gh":"๐Ÿ‡ฌ๐Ÿ‡ญ","flag-gi":"๐Ÿ‡ฌ๐Ÿ‡ฎ","flag-gl":"๐Ÿ‡ฌ๐Ÿ‡ฑ","flag-gm":"๐Ÿ‡ฌ๐Ÿ‡ฒ","flag-gn":"๐Ÿ‡ฌ๐Ÿ‡ณ","flag-gp":"๐Ÿ‡ฌ๐Ÿ‡ต","flag-gq":"๐Ÿ‡ฌ๐Ÿ‡ถ","flag-gr":"๐Ÿ‡ฌ๐Ÿ‡ท","flag-gs":"๐Ÿ‡ฌ๐Ÿ‡ธ","flag-gt":"๐Ÿ‡ฌ๐Ÿ‡น","flag-gu":"๐Ÿ‡ฌ๐Ÿ‡บ","flag-gw":"๐Ÿ‡ฌ๐Ÿ‡ผ","flag-gy":"๐Ÿ‡ฌ๐Ÿ‡พ","flag-hk":"๐Ÿ‡ญ๐Ÿ‡ฐ","flag-hm":"๐Ÿ‡ญ๐Ÿ‡ฒ","flag-hn":"๐Ÿ‡ญ๐Ÿ‡ณ","flag-hr":"๐Ÿ‡ญ๐Ÿ‡ท","flag-ht":"๐Ÿ‡ญ๐Ÿ‡น","flag-hu":"๐Ÿ‡ญ๐Ÿ‡บ","flag-ic":"๐Ÿ‡ฎ๐Ÿ‡จ","flag-id":"๐Ÿ‡ฎ๐Ÿ‡ฉ","flag-ie":"๐Ÿ‡ฎ๐Ÿ‡ช","flag-il":"๐Ÿ‡ฎ๐Ÿ‡ฑ","flag-im":"๐Ÿ‡ฎ๐Ÿ‡ฒ","flag-in":"๐Ÿ‡ฎ๐Ÿ‡ณ","flag-io":"๐Ÿ‡ฎ๐Ÿ‡ด","flag-iq":"๐Ÿ‡ฎ๐Ÿ‡ถ","flag-ir":"๐Ÿ‡ฎ๐Ÿ‡ท","flag-is":"๐Ÿ‡ฎ๐Ÿ‡ธ","flag-it":"๐Ÿ‡ฎ๐Ÿ‡น","it":"๐Ÿ‡ฎ๐Ÿ‡น","flag-je":"๐Ÿ‡ฏ๐Ÿ‡ช","flag-jm":"๐Ÿ‡ฏ๐Ÿ‡ฒ","flag-jo":"๐Ÿ‡ฏ๐Ÿ‡ด","flag-jp":"๐Ÿ‡ฏ๐Ÿ‡ต","jp":"๐Ÿ‡ฏ๐Ÿ‡ต","flag-ke":"๐Ÿ‡ฐ๐Ÿ‡ช","flag-kg":"๐Ÿ‡ฐ๐Ÿ‡ฌ","flag-kh":"๐Ÿ‡ฐ๐Ÿ‡ญ","flag-ki":"๐Ÿ‡ฐ๐Ÿ‡ฎ","flag-km":"๐Ÿ‡ฐ๐Ÿ‡ฒ","flag-kn":"๐Ÿ‡ฐ๐Ÿ‡ณ","flag-kp":"๐Ÿ‡ฐ๐Ÿ‡ต","flag-kr":"๐Ÿ‡ฐ๐Ÿ‡ท","kr":"๐Ÿ‡ฐ๐Ÿ‡ท","flag-kw":"๐Ÿ‡ฐ๐Ÿ‡ผ","flag-ky":"๐Ÿ‡ฐ๐Ÿ‡พ","flag-kz":"๐Ÿ‡ฐ๐Ÿ‡ฟ","flag-la":"๐Ÿ‡ฑ๐Ÿ‡ฆ","flag-lb":"๐Ÿ‡ฑ๐Ÿ‡ง","flag-lc":"๐Ÿ‡ฑ๐Ÿ‡จ","flag-li":"๐Ÿ‡ฑ๐Ÿ‡ฎ","flag-lk":"๐Ÿ‡ฑ๐Ÿ‡ฐ","flag-lr":"๐Ÿ‡ฑ๐Ÿ‡ท","flag-ls":"๐Ÿ‡ฑ๐Ÿ‡ธ","flag-lt":"๐Ÿ‡ฑ๐Ÿ‡น","flag-lu":"๐Ÿ‡ฑ๐Ÿ‡บ","flag-lv":"๐Ÿ‡ฑ๐Ÿ‡ป","flag-ly":"๐Ÿ‡ฑ๐Ÿ‡พ","flag-ma":"๐Ÿ‡ฒ๐Ÿ‡ฆ","flag-mc":"๐Ÿ‡ฒ๐Ÿ‡จ","flag-md":"๐Ÿ‡ฒ๐Ÿ‡ฉ","flag-me":"๐Ÿ‡ฒ๐Ÿ‡ช","flag-mf":"๐Ÿ‡ฒ๐Ÿ‡ซ","flag-mg":"๐Ÿ‡ฒ๐Ÿ‡ฌ","flag-mh":"๐Ÿ‡ฒ๐Ÿ‡ญ","flag-mk":"๐Ÿ‡ฒ๐Ÿ‡ฐ","flag-ml":"๐Ÿ‡ฒ๐Ÿ‡ฑ","flag-mm":"๐Ÿ‡ฒ๐Ÿ‡ฒ","flag-mn":"๐Ÿ‡ฒ๐Ÿ‡ณ","flag-mo":"๐Ÿ‡ฒ๐Ÿ‡ด","flag-mp":"๐Ÿ‡ฒ๐Ÿ‡ต","flag-mq":"๐Ÿ‡ฒ๐Ÿ‡ถ","flag-mr":"๐Ÿ‡ฒ๐Ÿ‡ท","flag-ms":"๐Ÿ‡ฒ๐Ÿ‡ธ","flag-mt":"๐Ÿ‡ฒ๐Ÿ‡น","flag-mu":"๐Ÿ‡ฒ๐Ÿ‡บ","flag-mv":"๐Ÿ‡ฒ๐Ÿ‡ป","flag-mw":"๐Ÿ‡ฒ๐Ÿ‡ผ","flag-mx":"๐Ÿ‡ฒ๐Ÿ‡ฝ","flag-my":"๐Ÿ‡ฒ๐Ÿ‡พ","flag-mz":"๐Ÿ‡ฒ๐Ÿ‡ฟ","flag-na":"๐Ÿ‡ณ๐Ÿ‡ฆ","flag-nc":"๐Ÿ‡ณ๐Ÿ‡จ","flag-ne":"๐Ÿ‡ณ๐Ÿ‡ช","flag-nf":"๐Ÿ‡ณ๐Ÿ‡ซ","flag-ng":"๐Ÿ‡ณ๐Ÿ‡ฌ","flag-ni":"๐Ÿ‡ณ๐Ÿ‡ฎ","flag-nl":"๐Ÿ‡ณ๐Ÿ‡ฑ","flag-no":"๐Ÿ‡ณ๐Ÿ‡ด","flag-np":"๐Ÿ‡ณ๐Ÿ‡ต","flag-nr":"๐Ÿ‡ณ๐Ÿ‡ท","flag-nu":"๐Ÿ‡ณ๐Ÿ‡บ","flag-nz":"๐Ÿ‡ณ๐Ÿ‡ฟ","flag-om":"๐Ÿ‡ด๐Ÿ‡ฒ","flag-pa":"๐Ÿ‡ต๐Ÿ‡ฆ","flag-pe":"๐Ÿ‡ต๐Ÿ‡ช","flag-pf":"๐Ÿ‡ต๐Ÿ‡ซ","flag-pg":"๐Ÿ‡ต๐Ÿ‡ฌ","flag-ph":"๐Ÿ‡ต๐Ÿ‡ญ","flag-pk":"๐Ÿ‡ต๐Ÿ‡ฐ","flag-pl":"๐Ÿ‡ต๐Ÿ‡ฑ","flag-pm":"๐Ÿ‡ต๐Ÿ‡ฒ","flag-pn":"๐Ÿ‡ต๐Ÿ‡ณ","flag-pr":"๐Ÿ‡ต๐Ÿ‡ท","flag-ps":"๐Ÿ‡ต๐Ÿ‡ธ","flag-pt":"๐Ÿ‡ต๐Ÿ‡น","flag-pw":"๐Ÿ‡ต๐Ÿ‡ผ","flag-py":"๐Ÿ‡ต๐Ÿ‡พ","flag-qa":"๐Ÿ‡ถ๐Ÿ‡ฆ","flag-re":"๐Ÿ‡ท๐Ÿ‡ช","flag-ro":"๐Ÿ‡ท๐Ÿ‡ด","flag-rs":"๐Ÿ‡ท๐Ÿ‡ธ","flag-ru":"๐Ÿ‡ท๐Ÿ‡บ","ru":"๐Ÿ‡ท๐Ÿ‡บ","flag-rw":"๐Ÿ‡ท๐Ÿ‡ผ","flag-sa":"๐Ÿ‡ธ๐Ÿ‡ฆ","flag-sb":"๐Ÿ‡ธ๐Ÿ‡ง","flag-sc":"๐Ÿ‡ธ๐Ÿ‡จ","flag-sd":"๐Ÿ‡ธ๐Ÿ‡ฉ","flag-se":"๐Ÿ‡ธ๐Ÿ‡ช","flag-sg":"๐Ÿ‡ธ๐Ÿ‡ฌ","flag-sh":"๐Ÿ‡ธ๐Ÿ‡ญ","flag-si":"๐Ÿ‡ธ๐Ÿ‡ฎ","flag-sj":"๐Ÿ‡ธ๐Ÿ‡ฏ","flag-sk":"๐Ÿ‡ธ๐Ÿ‡ฐ","flag-sl":"๐Ÿ‡ธ๐Ÿ‡ฑ","flag-sm":"๐Ÿ‡ธ๐Ÿ‡ฒ","flag-sn":"๐Ÿ‡ธ๐Ÿ‡ณ","flag-so":"๐Ÿ‡ธ๐Ÿ‡ด","flag-sr":"๐Ÿ‡ธ๐Ÿ‡ท","flag-ss":"๐Ÿ‡ธ๐Ÿ‡ธ","flag-st":"๐Ÿ‡ธ๐Ÿ‡น","flag-sv":"๐Ÿ‡ธ๐Ÿ‡ป","flag-sx":"๐Ÿ‡ธ๐Ÿ‡ฝ","flag-sy":"๐Ÿ‡ธ๐Ÿ‡พ","flag-sz":"๐Ÿ‡ธ๐Ÿ‡ฟ","flag-ta":"๐Ÿ‡น๐Ÿ‡ฆ","flag-tc":"๐Ÿ‡น๐Ÿ‡จ","flag-td":"๐Ÿ‡น๐Ÿ‡ฉ","flag-tf":"๐Ÿ‡น๐Ÿ‡ซ","flag-tg":"๐Ÿ‡น๐Ÿ‡ฌ","flag-th":"๐Ÿ‡น๐Ÿ‡ญ","flag-tj":"๐Ÿ‡น๐Ÿ‡ฏ","flag-tk":"๐Ÿ‡น๐Ÿ‡ฐ","flag-tl":"๐Ÿ‡น๐Ÿ‡ฑ","flag-tm":"๐Ÿ‡น๐Ÿ‡ฒ","flag-tn":"๐Ÿ‡น๐Ÿ‡ณ","flag-to":"๐Ÿ‡น๐Ÿ‡ด","flag-tr":"๐Ÿ‡น๐Ÿ‡ท","flag-tt":"๐Ÿ‡น๐Ÿ‡น","flag-tv":"๐Ÿ‡น๐Ÿ‡ป","flag-tw":"๐Ÿ‡น๐Ÿ‡ผ","flag-tz":"๐Ÿ‡น๐Ÿ‡ฟ","flag-ua":"๐Ÿ‡บ๐Ÿ‡ฆ","flag-ug":"๐Ÿ‡บ๐Ÿ‡ฌ","flag-um":"๐Ÿ‡บ๐Ÿ‡ฒ","flag-us":"๐Ÿ‡บ๐Ÿ‡ธ","us":"๐Ÿ‡บ๐Ÿ‡ธ","flag-uy":"๐Ÿ‡บ๐Ÿ‡พ","flag-uz":"๐Ÿ‡บ๐Ÿ‡ฟ","flag-va":"๐Ÿ‡ป๐Ÿ‡ฆ","flag-vc":"๐Ÿ‡ป๐Ÿ‡จ","flag-ve":"๐Ÿ‡ป๐Ÿ‡ช","flag-vg":"๐Ÿ‡ป๐Ÿ‡ฌ","flag-vi":"๐Ÿ‡ป๐Ÿ‡ฎ","flag-vn":"๐Ÿ‡ป๐Ÿ‡ณ","flag-vu":"๐Ÿ‡ป๐Ÿ‡บ","flag-wf":"๐Ÿ‡ผ๐Ÿ‡ซ","flag-ws":"๐Ÿ‡ผ๐Ÿ‡ธ","flag-xk":"๐Ÿ‡ฝ๐Ÿ‡ฐ","flag-ye":"๐Ÿ‡พ๐Ÿ‡ช","flag-yt":"๐Ÿ‡พ๐Ÿ‡น","flag-za":"๐Ÿ‡ฟ๐Ÿ‡ฆ","flag-zm":"๐Ÿ‡ฟ๐Ÿ‡ฒ","flag-zw":"๐Ÿ‡ฟ๐Ÿ‡ผ","man-man-boy":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆ","man-man-boy-boy":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","man-man-girl":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ง","man-man-girl-boy":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","man-man-girl-girl":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง","man-woman-boy-boy":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","man-woman-girl":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง","man-woman-girl-boy":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","man-woman-girl-girl":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง","man-heart-man":"๐Ÿ‘จโ€โค๏ธโ€๐Ÿ‘จ","man-kiss-man":"๐Ÿ‘จโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ","woman-woman-boy":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ","woman-woman-boy-boy":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","woman-woman-girl":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ง","woman-woman-girl-boy":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","woman-woman-girl-girl":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง","woman-heart-woman":"๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘ฉ","woman-kiss-woman":"๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘ฉ"} diff --git a/res/i18n/en/default.json b/res/i18n/en/default.json new file mode 100644 index 0000000..066019d --- /dev/null +++ b/res/i18n/en/default.json @@ -0,0 +1,24 @@ +{ + "errors": { + "INSUFFICIENT_ARGS": "insufficient arguments supplied - {{requiredArgs}} expected, but only {{argsCount}} found.", + "NO_END_QUOTE": "you have a missing end quote.", + "ON_COOLDOWN": "please cool down! ({{time}} seconds left)", + "NO_PERMS": "you need the permissions {{perms}} to run this command!", + "NO_PERMS_BOT": "I need the permissions {{perms}} to run this command!", + "NO_PMS": "this command can't be run in PMs." + }, + "menus": { + "EXIT": "Enter {{cancel}} to exit the menu.", + "ERRORED": "the menu has closed:", + "EXITED": "you have exited the menu.", + "SELECTION": "Selection Menu", + "ERROR": "Unknown Error", + "INPUT": "Type the number of your choice into chat or '{{cancel}}' to cancel.", + "MORE_RESULTS": "And {{num}} more..." + }, + "collector": { + "timeout": "Timeout after {{time}}s", + "max": "Exceeded {{max}} tries", + "maxMatches": "Exceeded {{maxMatches}} matches" + } +} diff --git a/src/core/Client.js b/src/Client.js similarity index 81% rename from src/core/Client.js rename to src/Client.js index 3b751fd..61c6340 100644 --- a/src/core/Client.js +++ b/src/Client.js @@ -1,8 +1,8 @@ const path = require('path') const Eris = require('eris').Client -const { Commander, Router, Bridge } = require('./engine') -const { Collection } = require('../util') +const { Commander, Router, Bridge, Interpreter, Logger } = require('./core') +const { Collection } = require('./util') /** * Interface between the Discord client and plugins @@ -16,16 +16,21 @@ class Client extends Eris { * Creates a new Client instance * @arg {Object} options An object containing sylphy's and/or Eris client options * @arg {String} options.token Discord bot token + * @arg {String} [options.prefix='!'] Default prefix for commands + * @arg {String} [options.admins=[]] Array of admin IDs * @arg {String} [options.commands] Relative path to commands folder * @arg {String} [options.modules] Relative path to modules folder * @arg {String} [options.middleware] Relative path to middleware folder + * @arg {String} [options.locales] Relative path to locales folder * @arg {Boolean} [options.suppressWarnings=false] Option to suppress console warnings * @arg {Boolean} [options.noDefaults=false] Option to not use built-in plugins */ constructor (options = {}) { super(options.token, options) + this.prefix = options.prefix || '!' this.suppressWarnings = options.suppressWarnings this.noDefaults = options.noDefaults + this.admins = Array.isArray(options.admins) ? options.admins : [] this.plugins = new Collection() @@ -34,10 +39,18 @@ class Client extends Eris { .createPlugin('commands', Commander) .createPlugin('modules', Router) .createPlugin('middleware', Bridge) + .createPlugin('i18n', Interpreter) + .createPlugin('logger', Logger) + + this.logger = this.plugins.get('logger') + + this.register('i18n', path.join(__dirname, '..', 'res/i18n')) + this.register('middleware', path.join(__dirname, 'middleware')) if (options.commands) this.register('commands', options.commands) if (options.modules) this.register('modules', options.modules) if (options.middleware) this.register('middleware', options.middleware) + if (options.locales) this.register('i18n', options.locales) } } @@ -68,7 +81,7 @@ class Client extends Eris { if (!plugin) { throw new Error(`Plugin type ${type} not found`) } - plugin.register(...args) + if (typeof plugin.register === 'function') plugin.register(...args) return this } @@ -87,7 +100,7 @@ class Client extends Eris { if (!plugin) { throw new Error(`Plugin type ${type} not found`) } - plugin.unregister(...args) + if (typeof plugin.unregister === 'function') plugin.unregister(...args) return this } @@ -114,6 +127,9 @@ class Client extends Eris { if (typeof this.token !== 'string') { throw new TypeError('No bot token supplied') } + this.plugins.forEach(plugin => { + if (typeof plugin.run === 'function') plugin.run() + }) this.connect() return this } @@ -125,7 +141,7 @@ class Client extends Eris { * @private */ throwOrEmit (event, error) { - if (!this.listeners(event, true)) { + if (!this.listeners(event).length) { throw error } this.emit(event, error) diff --git a/src/core/engine/Bridge.js b/src/core/Bridge.js similarity index 83% rename from src/core/engine/Bridge.js rename to src/core/Bridge.js index adab00d..7ac5d43 100644 --- a/src/core/engine/Bridge.js +++ b/src/core/Bridge.js @@ -1,7 +1,7 @@ const path = require('path') const fs = require('fs') -const { readdirRecursive, isDir } = require('../../util') +const { readdirRecursive, isDir } = require('../util') /** * Middleware manager for commands @@ -11,13 +11,14 @@ const { readdirRecursive, isDir } = require('../../util') class Bridge { /** * Creates a new Bridge instance - * @arg {Commander} commander Commander instance + * @arg {Client} client Client instance */ - constructor (commander) { + constructor (client) { this.tasks = [] this.collectors = [] this._cached = [] - this._commander = commander + this._client = client + this._commander = client.plugins.get('commands') } /** @@ -33,8 +34,8 @@ class Bridge { throw new Error(`Folder path ${filepath} does not exist`) } this._cached.push(filepath) - const middleware = isDir(filepath) ? readdirRecursive(filepath) : require(filepath) - return this.register(middleware) + const mw = isDir(filepath) ? readdirRecursive(filepath) : require(filepath) + return this.register(mw) } case 'object': { if (Array.isArray(middleware)) { @@ -66,12 +67,10 @@ class Bridge { * Inserts new middleware to the task queue according to ascending priority (lower numbers are earlier in queue) * @arg {Middleware} middleware Middleware object */ - push (middleware) { - const priority = middleware.priority || this.tasks.length - if (!middleware.process || !middleware.process.then) { - throw new Error('Middleware must be a promise') - } - this.tasks.splice(priority, 0, middleware) + push (Middleware) { + const middleware = typeof Middleware === 'function' ? new Middleware(this) : Middleware + this.tasks.push(middleware) + this.tasks.sort((a, b) => a.priority - b.priority) } /** @@ -194,6 +193,31 @@ class Bridge { return this } + /** Starts running the bridge */ + run () { + this._client.on('messageCreate', msg => { + if (msg.author.id === this._client.user.id || msg.author.bot) return + this.handle({ + msg: msg, + client: this._client, + logger: this._client.logger, + admins: this._client.admins, + commands: this._commander, + modules: this._client.plugins.get('modules'), + middleware: this + }).catch(err => { + if (err && this._client.logger) { + this._client.logger.error('Failed to handle message in Bridge -', err) + } + }) + }) + } + + /** Stops running the bridge */ + stop () { + this._client.removeAllListeners('messageCreate') + } + /** * Context container holding a message object along with added properties and objects * @typedef {Object} Container @@ -216,7 +240,7 @@ class Bridge { } for (const task of this.tasks) { try { - const result = await task(container) + const result = await task.process(container) if (!result) return Promise.reject() container = result } catch (err) { diff --git a/src/core/engine/Commander.js b/src/core/Commander.js similarity index 95% rename from src/core/engine/Commander.js rename to src/core/Commander.js index 6f0421a..e293d75 100644 --- a/src/core/engine/Commander.js +++ b/src/core/Commander.js @@ -1,7 +1,8 @@ const path = require('path') const fs = require('fs') +const util = require('util') -const { requireAll, isDir, Collection } = require('../../util') +const { requireAll, isDir, Collection } = require('../util') /** * Commander class for command processing @@ -36,12 +37,12 @@ class Commander extends Collection { case 'object': { if (Array.isArray(commands)) { for (const command of commands) { - this.commands.attach(command) + this.attach(command) } return this } for (const group in commands) { - this.commands.attach(commands[group], group) + this.attach(commands[group], group) } return this } @@ -67,9 +68,9 @@ class Commander extends Collection { * @returns {Commander} */ attach (Command, group) { - let command = typeof Command === 'function' ? new Command(this._client) : command - if (!command.triggers) { - this._client.throwOrEmit('commander:error', new Error(`Invalid command - ${command}`)) + let command = typeof Command === 'function' ? new Command(this._client) : Command + if (!command.triggers || !command.triggers.length) { + this._client.throwOrEmit('commander:error', new Error(`Invalid command - ${util.inspect(command)}`)) return this } for (const trigger of command.triggers) { diff --git a/src/core/engine/Interpreter.js b/src/core/Interpreter.js similarity index 83% rename from src/core/engine/Interpreter.js rename to src/core/Interpreter.js index 52fd4cb..13b2cc3 100644 --- a/src/core/engine/Interpreter.js +++ b/src/core/Interpreter.js @@ -1,11 +1,9 @@ const path = require('path') const fs = require('fs') -const { requireAll, isDir, Collection } = require('../../util') +const { requireAll, isDir, Collection } = require('../util') -/** - * Locale manager and string parser - */ +/** Locale manager and string parser */ class Interpreter extends Collection { /** * Creates a new Localisations instance @@ -37,16 +35,16 @@ class Interpreter extends Collection { if (Array.isArray(strings)) { for (const pair of strings) { if (typeof pair[0] !== 'string') continue - this.set(pair[0], pair[1]) + this.set(pair[0], Object.assign(this.get(pair[0]) || {}, pair[1])) } return this } if (!loc) { for (const lang in strings) { - this.set(lang, strings[lang]) + this.set(lang, Object.assign(this.get(lang) || {}, strings[lang])) } } else { - this.set(loc, strings) + this.set(loc, Object.assign(this.get(loc) || {}, strings)) } return this } @@ -93,9 +91,9 @@ class Interpreter extends Collection { * @arg {String} [locale='en'] The locale to find * @returns {?String} */ - get (key = 'common', locale = 'en') { - if (!this.strings.has(locale)) locale = 'en' - return this.locate(key, this.strings.get(locale)) + getStrings (key = 'common', locale = 'en') { + if (!this.has(locale)) locale = 'en' + return this.locate(key, this.get(locale)) } /** @@ -116,18 +114,18 @@ class Interpreter extends Collection { /** * Parses a string, converting keys to the matching locale string, with interpolation * @arg {String} string The string to parse - * @arg {String} [group='common'] The string group to use + * @arg {String} [group='default'] The string group to use * @arg {String} [locale='en'] The locale to use * @arg {Object} [options] Object containing tags to interpolate into the string * @returns {String} */ - parse (string, group = 'common', locale = 'en', options = {}) { + parse (string, group = 'default', locale = 'en', options = {}) { if (!string) return string return string.split(' ').map(str => ( str.replace(/\{\{(.+)\}\}/gi, (matched, key) => { - const g = key.startsWith('%') ? 'common.' : group + '.' + const g = key.startsWith('%') ? 'default.' : group + '.' key = key.startsWith('%') ? key.substr(1) : key - let val = this.get(`${g}${key}`, locale) + let val = this.getStrings(`${g}${key}`, locale) return typeof val === 'string' ? this.shift(val, options) : matched }) )).join(' ') diff --git a/src/core/Logger.js b/src/core/Logger.js new file mode 100644 index 0000000..cd3dc88 --- /dev/null +++ b/src/core/Logger.js @@ -0,0 +1,121 @@ +/** Logs information to the console */ +class Logger { + /** + * Creates a new Logger instance + * @arg {Object} [options] Logger options + * @arg {String} [options.name] Option for a prefix before logging + * @arg {Boolean} [options.suppressWarnings=false] Option to suppress warnings + * @arg {Boolean} [options.timestamps=true] Option to show timestamps + */ + constructor ({ name, suppressWarnings, timestamps = true } = {}) { + this.timestamps = timestamps + this.name = name ? `- [${name}] ` : '' + + this.styles = {} + for (const code in this.codes) { + const val = this.codes[code] + this.styles[code] = this.supportsColours ? (str) => `\u001b[${val[0]}m${str}\u001b[${val[1]}m` : (str) => str + } + } + + /** + * Logs to console + * @arg {...String} args Strings to log to console + */ + log (...args) { + console.log(this.timestamp + this.name + args.join(' ')) + } + + /** + * Logs to console at `info` level + * @arg {...String} args Strings to log to console + */ + info (...args) { + console.log(`${this.timestamp}${this.name}${this.styles.green('info')} - ${args.join(' ')}`) + } + + /** + * Logs to console at `warn` level + * @arg {...String} args Strings to log to console + */ + warn (...args) { + console.log(`${this.timestamp}${this.name}${this.styles.yellow('warn')} - ${args.join(' ')}`) + } + + /** + * Logs to console at `error` level + * @arg {...(String|Error)} args Strings or errors to log to console + */ + error (...args) { + console.log(`${this.timestamp}${this.name}${this.styles.red('error')} - ${args.map(e => e instanceof Error ? e.stack : e).join(' ')}`) + } + + /** + * Logs to console at `debug` level + * @arg {...String} args Strings to log to console + */ + debug (...args) { + console.log(`${this.timestamp}${this.name}${this.styles.grey('debug')} - ${args.join(' ')}`) + } + + get codes () { + return { + reset: [0, 0], + + bold: [1, 22], + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29], + + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + grey: [90, 39], + + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49] + } + } + + /** + * Get current formatted timestamp + * @returns {String} + */ + get timestamp () { + const time = new Date().toISOString() + return this.timestamps ? `[${this.styles.grey(time.slice(time.indexOf('T') + 1).replace(/\..+/, ''))}] ` : '' + } + + /** + * Checks if the console supports colours + * @returns {Boolean} + */ + supportsColours () { + if (process.stdout && !process.stdout.isTTY) return false + if (process.platfrom === 'win32') return true + if ('COLORTERM' in process.env) return true + if (process.env.TERM === 'dumb') return false + if (['screen', 'xterm', 'vt100', 'color', 'ansi', 'cygwin', 'linux'].includes(process.env.TERM)) return true + return false + } + + stripColour (str) { + return String(str).replace(/\x1B\[\d+m/g, '') + } +} + +module.exports = Logger diff --git a/src/core/engine/Router.js b/src/core/Router.js similarity index 95% rename from src/core/engine/Router.js rename to src/core/Router.js index a9a1c76..95e5b36 100644 --- a/src/core/engine/Router.js +++ b/src/core/Router.js @@ -1,7 +1,7 @@ const path = require('path') const fs = require('fs') -const { readdirRecursive, isDir, Collection } = require('../../util') +const { readdirRecursive, isDir, Collection } = require('../util') /** * Router class for event routing @@ -55,12 +55,12 @@ class Router extends Collection { case 'object': { if (Array.isArray(modules)) { for (const module of modules) { - this.modules.attach(module) + this.attach(module) } return this } for (const key in modules) { - this.modules.attach(modules[key]) + this.attach(modules[key]) } return this } @@ -100,7 +100,7 @@ class Router extends Collection { * @returns {Router} */ record (event) { - this.bot.on(event, (...args) => { + this._client.on(event, (...args) => { const events = this.events[event] || {} for (const name in events) { const module = this.get(name) diff --git a/src/core/engine/index.js b/src/core/engine/index.js deleted file mode 100644 index 6ba9739..0000000 --- a/src/core/engine/index.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - Bridge: require('./Bridge'), - Commander: require('./Commander'), - Router: require('./Router') -} diff --git a/src/core/index.js b/src/core/index.js index 83b60eb..298f102 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -1,3 +1,7 @@ -module.exports = Object.assign(require('./engine'), { - Client: require('./Client') -}) +module.exports = { + Bridge: require('./Bridge'), + Commander: require('./Commander'), + Interpreter: require('./Interpreter'), + Logger: require('./Logger'), + Router: require('./Router') +} diff --git a/src/index.js b/src/index.js index be7f595..7c5dbf9 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,12 @@ +const Client = require('./Client') const Core = require('./core') -const Client = function Client (opts) { - return new Core.Client(opts) + +function Sylphy (opts) { + return new Client(opts) } -module.exports = Object.assign(Client, Core, require('./util')) +module.exports = Object.assign(Sylphy, Core, + require('./util'), + require('./structures'), + require('./managers') +) diff --git a/src/managers/Resolver.js b/src/managers/Resolver.js index 30d405e..c1af13e 100644 --- a/src/managers/Resolver.js +++ b/src/managers/Resolver.js @@ -1,8 +1,6 @@ const { readdirRecursive, Collection } = require('../util') -/** - * Resolver manager for resolving usages - */ +/** Resolver manager for resolving usages */ class Resolver extends Collection { /** * Creates a new Resolver instance @@ -107,7 +105,7 @@ class Resolver extends Collection { resolve (message, rawArgs, data, rawUsage = this.usage) { let args = {} - const usage = this.verify(usage) + const usage = this.verify(rawUsage) if (!usage.length) return Promise.resolve(args) const argsCount = rawArgs.length @@ -168,7 +166,7 @@ class Resolver extends Collection { if (!resolver) { return Promise.resolve({ err: 'Invalid resolver type' }) } - return resolver.resolve(rawArg, arg, message, this.bot) + return resolver.resolve(rawArg, arg, message, this._client) .catch(err => Object.assign(arg, { arg: `**\`${arg.name || 'argument'}\`**`, err: err diff --git a/src/managers/Responder.js b/src/managers/Responder.js new file mode 100644 index 0000000..a96a20c --- /dev/null +++ b/src/managers/Responder.js @@ -0,0 +1,200 @@ +const { padEnd, emojis } = require('../util') + +class Responder { + constructor (command) { + this.command = command + this.i18n = command.i18n + + /** Response methods */ + this.responseMethods = { + send: (msg, res) => res, + reply: (msg, res) => `**${msg.author.username}**, ${res}`, + success: (msg, res) => `${emojis['white_check_mark']} | **${msg.author.username}**, ${res}`, + error: (msg, res) => `${emojis['negative_squared_cross_mark']} | **${msg.author.username}**, ` + (res || '{{%ERROR}}') + } + + /** Formatter methods */ + this.formatMethods = { + bold: (res) => `**${res}**`, + italic: (res) => `*${res}*`, + underline: (res) => `__${res}__`, + strikethrough: (res) => `~~${res}~~`, + inlineCode: (res) => `\`${res}\``, + code: (res, type = '') => `\`\`\`${type}\n${res}\n\`\`\``, + emoji: (res, type) => `${emojis[type] || emojis['information_source']} | ${res}` + } + } + + create ({ msg: message, settings = {} }, data) { + let responder = Object.assign((...args) => responder.send(...args), { + command: this.command, + message: message, + settings: settings, + data: data, + _options: {}, + responseMethods: this.responseMethods, + formatMethods: this.formatMethods + }) + + const copy = ['_send', 't', 'clean', 'typing', 'format', 'file', 'embed', 'dialog', 'selection'] + copy.forEach(prop => { responder[prop] = this[prop].bind(responder) }) + + for (let method in this.responseMethods) { + responder[method] = responder._send.bind(responder, method) + } + + return responder + } + + t (content = '', tags = {}) { + const cmd = this.command + const file = cmd.name ? cmd.name.split(':')[0] : (cmd.labels ? cmd.labels[0] : 'common') + const res = cmd.i18n.parse(content, cmd.localeKey || file, this.settings.lang || 'en', tags) + return res.replace(/:(\S+):/gi, (matched, name) => emojis[name] || emojis['information_source']) + } + + _send (method, response = '', options = {}) { + const message = this.message + const formats = this._formats || [] + + Object.assign(options, this._options || {}) + + if (response instanceof Array) response = response.join('\n') + response = this.command.t(response, this.settings.lang || 'en', options) + response = this.responseMethods[method || 'send'](message, response) + + for (let format of formats) { + format = format.split(':') + response = this.formatMethods[format[0]](response, format[1]) + } + + const promise = (options.DM ? this.command.bot.getDMChannel(message.author.id) : Promise.resolve(message.channel)) + .then(channel => this.command.send(channel, response, options)) + + delete this._formats + this._options = {} + + return promise + } + + clean () { + delete this._formats + return this + } + + typing () { + return this.message.channel.sendTyping() + } + + format (formats) { + this._formats = (formats instanceof Array) ? formats : [formats] + return this + } + + file (name, file) { + this._options.file = { name, file } + return this + } + + embed (embed) { + this._options.embed = embed + return this + } + + async dialog (dialogs = [], options = {}) { + const { message, data } = this + const { tries = 10, time = 60, matches = 10, filter, cancel = 'cancel' } = options + + const args = {} + let cancelled = false + for (const dialog of dialogs) { + let prompt = dialog.prompt + const input = this.command.resolver + if (Array.isArray(prompt) && prompt.length) { + prompt[0] = `**${prompt[0]}**` + } + + let p1 = await this.send(prompt, options) + const collector = this.command.bot.engine.bridge.collect({ + channel: message.channel.id, + author: message.author.id, + tries, + time, + matches, + filter + }) + + const awaitMessage = async (msg) => { + let ans + try { + ans = await collector.next() + if (ans.content.toLowerCase() === cancel) return Promise.reject() + try { + return await input.resolve(ans, [ans.cleanContent], data, dialog.input) + } catch (err) { + const p2 = await this.format('emoji:error').send( + `${err.err || err.message || err || '{{%menus.ERROR}}'}\n\n{{%menus.EXIT}}`, + Object.assign(err, { cancel: `\`${cancel}\`` }) + ) + return awaitMessage(p2) + } + } catch (o) { + return Promise.reject(o) + } finally { + this.command.deleteMessages(msg, ans) + } + } + + try { + Object.assign(args, await awaitMessage()) + collector.stop() + } catch (err) { + if (typeof err !== 'undefined') { + this.error(`{{%menus.ERRORED}} **{{%collector.${err.reason}}}**`, { + [err.reason]: err.arg, err: `**${err.reason}**` + }) + } else { + this.success('{{%menus.EXITED}}') + } + collector.stop() + cancelled = true + break + } finally { + p1.delete() + } + } + + if (cancelled) return Promise.reject() + return Promise.resolve(args) + } + + async selection (selections = [], options = {}) { + if (!Array.isArray(selections)) return [selections, 0] + if (!selections.length) return [] + if (selections.length === 1) return [selections[0], 0] + + const { title = '{{%menus.SELECTION}}', footer = '{{%menus.INPUT}}', mapFunc } = options + const choices = (mapFunc ? selections.map(mapFunc) : selections).splice(0, 10) + + try { + const { reply } = await this.dialog([{ + prompt: [ + '```markdown', + `### ${title} ###\n`, + choices.map((c, i) => `${padEnd(`[${i + 1}]:`, 4)} ${c}`).join('\n'), + selections.length > 10 ? '{{%menus.MORE_RESULTS}}\n' : '', + Array.isArray(footer) ? footer.join('\n') : '> ' + footer, + '```' + ].join('\n'), + input: { type: 'int', name: 'reply', min: 1, max: choices.length } + }], Object.assign(options, { + num: selections.length - 10, cancel: options.cancel || 'cancel' + })) + return [selections[reply - 1], reply - 1] + } catch (err) { + return [] + } + } +} + +module.exports = Responder diff --git a/src/managers/index.js b/src/managers/index.js new file mode 100644 index 0000000..238e1a8 --- /dev/null +++ b/src/managers/index.js @@ -0,0 +1,5 @@ +module.exports = { + Resolver: require('./Resolver'), + Transmitter: require('./Transmitter'), + Responder: require('./Responder') +} diff --git a/src/middleware/checkPrivate.js b/src/middleware/checkPrivate.js new file mode 100644 index 0000000..90ab0e4 --- /dev/null +++ b/src/middleware/checkPrivate.js @@ -0,0 +1,9 @@ +module.exports = { + name: 'checkPrivate', + priority: 2, + process: container => { + const { msg } = container + container.isPrivate = !msg.guild + return Promise.resolve(container) + } +} diff --git a/src/middleware/commandLogger.js b/src/middleware/commandLogger.js new file mode 100644 index 0000000..83e9430 --- /dev/null +++ b/src/middleware/commandLogger.js @@ -0,0 +1,17 @@ +module.exports = { + name: 'commandLogger', + priority: 100, + process: container => { + const { msg, isPrivate, isCommand, logger } = container + if (!isCommand || !logger) return Promise.resolve() + + const curry = (color) => (str) => logger.styles[color](logger.styles.bold(str)) + + logger.info( + curry('magenta')(!isPrivate ? msg.guild.name : '(in PMs)') + ' > ' + + curry('green')(msg.author.username) + ': ' + + curry('blue')(msg.cleanContent.replace(/\n/g, ' ')) + ) + return Promise.resolve(container) + } +} diff --git a/src/middleware/parseMessage.js b/src/middleware/parseMessage.js new file mode 100644 index 0000000..05fa19c --- /dev/null +++ b/src/middleware/parseMessage.js @@ -0,0 +1,15 @@ +module.exports = { + name: 'parseMessage', + priority: 10, + process: container => { + const { msg, client, commands } = container + + if (!msg.content.startsWith(client.prefix)) return Promise.resolve() + + const rawArgs = msg.content.substring(client.prefix.length).split(' ') + container.trigger = rawArgs[0].toLowerCase() + container.isCommand = commands.has(container.trigger) + container.rawArgs = rawArgs.slice(1).filter(v => v) + return Promise.resolve(container) + } +} diff --git a/src/structures/Base.js b/src/structures/Base.js new file mode 100644 index 0000000..cba761b --- /dev/null +++ b/src/structures/Base.js @@ -0,0 +1,138 @@ +const { delay: promDelay } = require('../util') + +/** + * Built-in base helper class + * @abstract + * @prop {?Logger} logger Logger instance + * @prop {?Interpreter} i18n Interpreter instance + */ +class Base { + /** + * Creates a new Base instance + * @arg {Client} client Client instance + */ + constructor (client) { + this._client = client + this.logger = client.logger + this.i18n = client.plugins.get('i18n') + } + + /** + * Checks if a user has certain permissions in a channel + * @arg {external:"Eris.GuildChannel"} channel The channel to check in + * @arg {external:"Eris.User"} user The user to check + * @arg {...String} perms The permission(s) to check + * @returns {Boolean} + */ + hasPermissions (channel, user, ...perms) { + if (!channel.guild) return true + const member = channel.guild.members.get(user.id) + + if (!perms.every(p => member.permission.has(p))) return false + return perms.every(perm => + !channel.permissionOverwrites.find(p => (member.roles.includes(p.id) || p.id === user.id) && p.json[perm] === false) + ) + } + + /** + * Parses a string for localisation + * @arg {String} content The string to parse + * @arg {String} [lang='en'] The locale name + * @arg {Object} [tags] Additional interpolation tags + */ + t (content = '', lang = 'en', tags = {}) { + if (!this.i18n) return content + const file = this.name ? this.name.split(':')[0] : (this.labels ? this.labels[0] : 'common') + return this.i18n.parse(content, this.localeKey || file || null, lang, tags) + } + + /** + * Sends a message to a channel + * @arg {external:"Eris.GuildChannel"} channel The channel to send the message in + * @arg {String} content The string to send + * @arg {Object} [options] Message options + * @arg {String} [options.lang] Message locale + * @arg {Number} [options.delay=0] Delay to send the message, set to 0 for no delay + * @arg {Number} [options.deleteDelay=0] Delay to delete the message after it's sent, set to 0 for no deletion + * @arg {Object} [options.file] A file object + * @arg {String} [options.file.name] Name of file + * @arg {Buffer} [options.file.file] Buffer containing file data + * @arg {Object} [options.embed] Embed object, see {@link https://discordapp.com/developers/docs/resources/channel#embed-object|official Discord API documentation} + * @returns {Promise.} + */ + async send (chan, content, options = {}) { + const channel = typeof chan === 'string' ? this._client.getChannel(chan) : chan + if (!channel) { + const err = new Error(`Could not send message: Invalid channel - ${chan}`) + if (this.logger) this.logger.error(err) + throw err + } + + let { file = null, lang, delay = 0, deleteDelay = 0, embed } = options + if (channel.guild && !this.hasPermissions(channel, this._client.user, 'sendMessages')) { + const err = new Error('Could not send message: Insufficient permissions') + if (this.logger) this.logger.error(err) + } + + if (delay) await promDelay(delay) + + if (Array.isArray(content)) content = content.join('\n') + if (this.i18n) content = this.t(content, lang, options) + content = content.match(/(.|[\r\n]){1,2000}/g) + + try { + if (!content || !content.length) { + const msg = await channel.createMessage({ embed, content: '' }, file) + return deleteDelay ? promDelay(deleteDelay).then(() => msg.delete()) : msg + } + + let msg + for (const c of content) { + const firstMsg = await channel.createMessage(!msg ? { embed, content: c } : c, !msg ? file : null) + .then(msg => deleteDelay ? promDelay(deleteDelay).then(() => msg.delete()) : msg) + msg = firstMsg + } + + return msg + } catch (err) { + if (this.logger) this.logger.error('Could not send message -', err) + throw err + } + } + + /** + * Edits a message with updated content + * @arg {external:"Eris.Message"} message The message to edit + * @arg {String} content The content to edit the message with + * @arg {Object} [options] Options object + * @arg {String} [options.lang] Locale of content + * @arg {Number} [options.delay] Delay to edit the message + * @returns {Promise} + */ + edit (msg, content, options) { + const { lang, delay = 0 } = options + + if (Array.isArray(content)) content = content.join('\n') + if (this.i18n) content = this.t(content, lang, options) + + return (delay ? promDelay(delay) : Promise.resolve()).then(() => msg.edit(content)) + } + + /** + * Deletes multiple messages if there are sufficient permissions + * @arg {...external:"Eris.Message"} messages The messages to delete + * @returns {Promise} + */ + deleteMessages (...msgs) { + const id = this._client.user.id + return Promise.all(msgs.reduce((arr, msg) => { + if (!msg || !msg.guild) return arr + if (msg.author.id === id || msg.channel.permissionsOf(id).has('manageMessages')) { + arr.push(msg.delete) + } + return arr + }), []) + } +} + +module.exports = Base diff --git a/src/structures/Command.js b/src/structures/Command.js new file mode 100644 index 0000000..691e964 --- /dev/null +++ b/src/structures/Command.js @@ -0,0 +1,182 @@ +const { Collection } = require('../util') +const { Responder, Resolver } = require('../managers') +const Base = require('./Base') + +/** + * Built-in command class + * @extends {Base} + * @abstract + * @prop {Resolver} resolver Command resolver + * @prop {Responder} responder Command responder + * @prop {Collection} subcommands Collection of subcommands + * @prop {Map} timers Map of timer cooldowns + */ +class Command extends Base { + /** + * Creates a new Command instance + * @arg {Client} client Client instance + * @arg {...Object} args Command options + */ + constructor (client, ...args) { + super(client) + if (this.constructor === Command) { + throw new Error('Cannot instantiate abstract Command') + } + + this.resolver = new Resolver(client) + this.responder = new Responder(this) + this.subcommands = new Collection() + + const options = args.reduce((p, c) => Object.assign(c, p), {}) + this._verify(options, ...args) + + this.timers = new Map() + } + + /** + * Verifies the options passed to the constructor + * @arg {Object} args Options passed to the Command constructor + */ + _verify (args = {}) { + const { name, group = 'none', aliases = [], cooldown = 5, usage = [], options = {}, subcommands = {}, subcommand } = args + + this.triggers = typeof name === 'string' + ? [name].concat(aliases) + : (Array.isArray(aliases) && aliases.length > 0 ? aliases : []) + + if (!this.triggers.length) { + throw new Error(`${this.constructor.name} command is not named`) + } + + this.cooldown = cooldown + this.options = options + if (this.options.modOnly) { + this.options.permissions = (this.options.permissions || []).concat('manageGuild') + } + + this.group = group + this.usage = usage + this.localeKey = options.localeKey + this.resolver.load(usage) + + for (const command in subcommands) { + const name = subcommands[command].name || command + for (const alias of [name].concat(subcommands[command].aliases || [])) { + this.subcommands.set(alias, { + name, + usage: subcommands[command].usage || [], + options: subcommands[command].options || {} + }) + } + } + this.subcommand = subcommand + } + + /** + * Checks the validatiy of a command and executes it + * @arg {Container} container Container context + * @returns {Promise} + */ + execute (container) { + const responder = this.responder.create(container) + + let usage = this.usage + let process = 'handle' + + const subcmd = this.subcommand ? this.subcommand : container.rawArgs[0] + const cmd = this.subcommands.get(subcmd) + if (cmd) { + usage = cmd.usage + process = cmd.name + container.rawArgs = container.rawArgs.slice(this.subcommand ? 0 : 1) + container.trigger += ' ' + subcmd + } + + if (!this.check(container, responder, cmd)) return + + return this.resolver.resolve(container.msg, container.rawArgs, { + prefix: (container.settings || {}).prefix || this._client.prefix, + command: container.trigger + }, usage).then((args = {}) => { + container.args = args + return this[process](container, responder) + }, err => responder.error(`{{%errors.${err.message}`)).catch(this.logError.bind(this)) + } + + /** + * Checks if a command is valid, run in `execute()` + * @arg {Container} container Container context + * @arg {Responder} responder Responder instance + * @arg {Command} [subcmd] Subcommand + */ + check ({ msg, isPrivate, admins, client }, responder, subcmd) { + const isAdmin = admins.includes(msg.author.id) + const { guildOnly, permissions = [], botPerms = [] } = subcmd ? subcmd.options : this.options + const adminOnly = (subcmd && subcmd.options.adminOnly) || this.options.adminOnly + + if (adminOnly === true && !isAdmin) { + return false + } + + if (guildOnly === true && isPrivate) { + responder.format('emoji:error').send('{{%errors.NO_PMS}}') + return false + } + + if (permissions.length && !this.hasPermissions(msg.channel, msg.author, ...permissions)) { + responder.error('{{%errors.NO_PERMS}}', { + perms: permissions.map(p => `\`${p}\``).join(', ') + }) + return false + } + + if (botPerms.length && !this.hasPermissions(msg.channel, client.user, ...botPerms)) { + responder.error('{{%errors.NO_PERMS_BOT}}', { + perms: botPerms.map(p => `\`${p}\``).join(', ') + }) + return false + } + + if (isAdmin) return true + const awaitID = msg.author.id + if (this.cooldown > 0) { + const now = Date.now() / 1000 | 0 + if (!this.timers.has(awaitID)) { + this.timers.set(awaitID, now) + } else { + const diff = now - this.timers.get(awaitID) + if (diff < this.cooldown) { + responder.error('{{%errors.ON_COOLDOWN}}', { + delay: 0, + deleteDelay: 5000, + time: `**${this.cooldown - diff}**` + }) + return false + } else { + this.timers.delete(awaitID) + this.timers.set(awaitID, now) + } + } + } + return true + } + + /** + * Command handler + * @arg {Container} container Container object + * @arg {Responder} responder Responder instance + */ + async handle (container, responder) { return true } + + logError (err) { + if (err && this.logger) { + this.logger.error(`Error running ${this.triggers[0]} command`, err) + } + } + + get permissionNode () { + return `${this.group}.${this.triggers[0]}` + } +} + +module.exports = Command diff --git a/src/structures/index.js b/src/structures/index.js new file mode 100644 index 0000000..ea673ba --- /dev/null +++ b/src/structures/index.js @@ -0,0 +1,4 @@ +module.exports = { + Base: require('./Base'), + Command: require('./Command') +} diff --git a/src/util/Utils.js b/src/util/Utils.js index 6eb28a1..91b48a2 100644 --- a/src/util/Utils.js +++ b/src/util/Utils.js @@ -1,5 +1,6 @@ const path = require('path') const fs = require('fs') +const emojis = require('../../res/emoji') const colours = { blue: '#117ea6', @@ -21,7 +22,7 @@ class Utils { * @arg {Client} client Client instance */ constructor (client) { - this._client = client + Utils._client = client } /** @@ -32,6 +33,10 @@ class Utils { return fs.existsSync(fname) ? fs.statSync(fname).isDirectory() : false } + static get emojis () { + return emojis + } + /** * Pads a string on the right if it's shorter than the padding length * @arg {String} [String=''] The string to pad @@ -97,7 +102,7 @@ class Utils { static readdirRecursive (dir) { return fs.readdirSync(dir).reduce((arr, file) => { const filepath = path.join(dir, file) - arr.push(this.isDir(filepath) ? this.readdirRecursive(filepath) : require(filepath)) + arr.push(Utils.isDir(filepath) ? Utils.readdirRecursive(filepath) : require(filepath)) return arr }, []) } @@ -110,10 +115,20 @@ class Utils { static requireAll (dir) { return fs.readdirSync(dir).reduce((obj, file) => { const filepath = path.join(dir, file) - obj[file] = this.isDir(filepath) ? this.requireAll(filepath) : require(filepath) + obj[file.substring(0, path.basename(filepath, path.extname(filepath)).length)] = Utils.isDir(filepath) + ? Utils.requireAll(filepath) : require(filepath) return obj }, {}) } + + /** + * Delay Promise + * @arg {Number} time Time to delay + * @returns {Promise} + */ + static delay (time) { + return new Promise((resolve) => setTimeout(() => resolve(), time)) + } } module.exports = Utils diff --git a/test/bot.js b/test/bot.js index c545839..224507e 100644 --- a/test/bot.js +++ b/test/bot.js @@ -1,11 +1,33 @@ +const util = require('util') const Client = require('../') -const { token } = require('./auth.json') +const { token, admins } = require('./auth.json') const bot = new Client({ - token: token + token: token, + commands: 'test/commands', + locales: 'test/i18n', + prefix: '+', + admins: admins }) -bot.on('ready', () => console.log('running!')) +const logger = bot.logger + +logger.debug([ + 'Running bot\n', + 'With flashy logging' +].join('\n')) +logger.error(new Error('Testing error')) + +bot.on('commander:registered', logger.log) + +bot.on('ready', () => { + logger.info('Logged in as ' + bot.user.username) +}) bot.run() + +process.on('unhandledRejection', (reason, promise) => { + if (typeof reason === 'undefined') return + logger.error(`Unhandled rejection: ${reason} - ${util.inspect(promise)}`) +}) diff --git a/test/commands/EndCommand.js b/test/commands/EndCommand.js new file mode 100644 index 0000000..3d56699 --- /dev/null +++ b/test/commands/EndCommand.js @@ -0,0 +1,16 @@ +const { Command } = require('../../') + +module.exports = class Stop extends Command { + constructor (...args) { + super(...args, { + name: 'stop', + aliases: ['end'], + options: { localeKey: 'test' } + }) + } + + handle ({ msg }, responder) { + this.logger.debug('Ending test') + return responder.reply('{{end}}', { x: 'now' }).then(process.exit) + } +} diff --git a/test/commands/PingCommand.js b/test/commands/PingCommand.js new file mode 100644 index 0000000..de4c561 --- /dev/null +++ b/test/commands/PingCommand.js @@ -0,0 +1,4 @@ +module.exports = { + triggers: ['ping'], + execute: ({ msg }) => msg.channel.createMessage('Pong!') +} diff --git a/test/i18n/en/test.json b/test/i18n/en/test.json new file mode 100644 index 0000000..c8c3b98 --- /dev/null +++ b/test/i18n/en/test.json @@ -0,0 +1,3 @@ +{ + "end": "Ending test {{x}}" +} diff --git a/yarn.lock b/yarn.lock index cc8ea45..834fb2d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,29 +18,210 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -asap@~2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f" +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" -async@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" +arr-flatten@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.1.tgz#e5ffe54d45e19f32f216e91eb99c8ce892bb604b" -async@~1.0.0: +array-differ@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" + +array-uniq@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +babel-code-frame@^6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.20.0.tgz#b968f839090f9a8bc6d41938fb96cb84f7387b26" + dependencies: + chalk "^1.1.0" + esutils "^2.0.2" + js-tokens "^2.0.0" + +babel-core@^6.0.2, babel-core@^6.18.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.21.0.tgz#75525480c21c803f826ef3867d22c19f080a3724" + dependencies: + babel-code-frame "^6.20.0" + babel-generator "^6.21.0" + babel-helpers "^6.16.0" + babel-messages "^6.8.0" + babel-register "^6.18.0" + babel-runtime "^6.20.0" + babel-template "^6.16.0" + babel-traverse "^6.21.0" + babel-types "^6.21.0" + babylon "^6.11.0" + convert-source-map "^1.1.0" + debug "^2.1.1" + json5 "^0.5.0" + lodash "^4.2.0" + minimatch "^3.0.2" + path-is-absolute "^1.0.0" + private "^0.1.6" + slash "^1.0.0" + source-map "^0.5.0" + +babel-generator@^6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.21.0.tgz#605f1269c489a1c75deeca7ea16d43d4656c8494" + dependencies: + babel-messages "^6.8.0" + babel-runtime "^6.20.0" + babel-types "^6.21.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.2.0" + source-map "^0.5.0" + +babel-helper-function-name@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.18.0.tgz#68ec71aeba1f3e28b2a6f0730190b754a9bf30e6" + dependencies: + babel-helper-get-function-arity "^6.18.0" + babel-runtime "^6.0.0" + babel-template "^6.8.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-helper-get-function-arity@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.18.0.tgz#a5b19695fd3f9cdfc328398b47dafcd7094f9f24" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.18.0" + +babel-helper-remap-async-to-generator@^6.16.0: + version "6.20.3" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.20.3.tgz#9dd3b396f13e35ef63e538098500adc24c63c4e7" + dependencies: + babel-helper-function-name "^6.18.0" + babel-runtime "^6.20.0" + babel-template "^6.16.0" + babel-traverse "^6.20.0" + babel-types "^6.20.0" + +babel-helpers@^6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.16.0.tgz#1095ec10d99279460553e67eb3eee9973d3867e3" + dependencies: + babel-runtime "^6.0.0" + babel-template "^6.16.0" + +babel-messages@^6.8.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.8.0.tgz#bf504736ca967e6d65ef0adb5a2a5f947c8e0eb9" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" -bindings@~1.2.1, bindings@1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" +babel-plugin-transform-async-to-generator@^6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.16.0.tgz#19ec36cb1486b59f9f468adfa42ce13908ca2999" + dependencies: + babel-helper-remap-async-to-generator "^6.16.0" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.0.0" + +babel-register@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.18.0.tgz#892e2e03865078dd90ad2c715111ec4449b32a68" + dependencies: + babel-core "^6.18.0" + babel-runtime "^6.11.6" + core-js "^2.4.0" + home-or-tmp "^2.0.0" + lodash "^4.2.0" + mkdirp "^0.5.1" + source-map-support "^0.4.2" + +babel-runtime@^6.0.0, babel-runtime@^6.11.6, babel-runtime@^6.20.0, babel-runtime@^6.9.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.20.0.tgz#87300bdcf4cd770f09bf0048c64204e17806d16f" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.10.0" + +babel-template@^6.16.0, babel-template@^6.8.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.16.0.tgz#e149dd1a9f03a35f817ddbc4d0481988e7ebc8ca" + dependencies: + babel-runtime "^6.9.0" + babel-traverse "^6.16.0" + babel-types "^6.16.0" + babylon "^6.11.0" + lodash "^4.2.0" + +babel-traverse@^6.16.0, babel-traverse@^6.18.0, babel-traverse@^6.20.0, babel-traverse@^6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.21.0.tgz#69c6365804f1a4f69eb1213f85b00a818b8c21ad" + dependencies: + babel-code-frame "^6.20.0" + babel-messages "^6.8.0" + babel-runtime "^6.20.0" + babel-types "^6.21.0" + babylon "^6.11.0" + debug "^2.2.0" + globals "^9.0.0" + invariant "^2.2.0" + lodash "^4.2.0" + +babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.20.0, babel-types@^6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.21.0.tgz#314b92168891ef6d3806b7f7a917fdf87c11a4b2" + dependencies: + babel-runtime "^6.20.0" + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^1.0.1" + +babylon@^6.11.0: + version "6.14.1" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.14.1.tgz#956275fab72753ad9b3435d7afe58f8bf0a29815" -bluebird@^3.4.7, "bluebird@>= 3.0.1", bluebird@~3.4.6: +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +beeper@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" + +bluebird@~3.4.6: version "3.4.7" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" -bluebird@~2.10.2: - version "2.10.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.10.2.tgz#024a5517295308857f14f91f1106fc3b555f446b" +brace-expansion@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" buffer-shims@^1.0.0: version "1.0.0" @@ -52,7 +233,7 @@ catharsis@~0.8.8: dependencies: underscore-contrib "~0.3.0" -chalk@^1.1.3: +chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -62,78 +243,85 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -cluster@^0.7.7: - version "0.7.7" - resolved "https://registry.yarnpkg.com/cluster/-/cluster-0.7.7.tgz#e497e267cc956bd0b0513adb4aa393357d0085ef" - dependencies: - log ">= 1.2.0" - mkdirp ">= 0.0.1" - -colors@1.0.x: - version "1.0.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" +clone-stats@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" -combined-stream@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - dependencies: - delayed-stream "~1.0.0" +clone@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" -commander@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" +clone@^1.0.0, clone@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149" -commander@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -component-emitter@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" +convert-source-map@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.3.0.tgz#e9f3e9c6e2728efc2676696a70eb382f73106a67" -cookiejar@^2.0.6: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.0.tgz#86549689539b6d0e269b6637a304be508194d898" +core-js@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" 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" -cycle@1.0.x: - version "1.0.3" - resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" +dateformat@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.0.0.tgz#2743e3abb5c3fc2462e527dca445e04e9f4dee17" -debug@^2.2.0, debug@2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.5.2.tgz#50c295a53dbf1657146e0c1b21307275e90d49cb" +debug@^2.1.1, debug@^2.2.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b" dependencies: ms "0.7.2" -debug@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" +defaults@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" dependencies: - ms "0.7.1" + clone "^1.0.2" -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" +deprecated@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19" -diff@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" +detect-file@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-0.1.0.tgz#4935dedfd9488648e006b0129566e9386711ea63" + dependencies: + fs-exists-sync "^0.1.0" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" docdash@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/docdash/-/docdash-0.4.0.tgz#05c3a50d83189981699ee0c076d3a3950db7ec00" -double-ended-queue@^2.1.0-0: - version "2.1.0-0" - resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" +duplexer2@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" + dependencies: + readable-stream "~1.1.9" + +end-of-stream@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" + dependencies: + once "~1.3.0" "eris@github:abalabahaha/eris#dev": version "0.5.1" - resolved "https://codeload.github.com/abalabahaha/eris/tar.gz/ef1e706d2f7ce9f9bd12b7f36786e0825ee04f07" + resolved "https://codeload.github.com/abalabahaha/eris/tar.gz/074364ad4cf41aba57a9d73fee10bc316d35afbb" dependencies: ws "^1.1.1" optionalDependencies: @@ -144,10 +332,6 @@ 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" -escape-string-regexp@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" - espree@~3.1.7: version "3.1.7" resolved "https://registry.yarnpkg.com/espree/-/espree-3.1.7.tgz#fd5deec76a97a5120a9cd3a7cb1177a0923b11d2" @@ -155,44 +339,270 @@ espree@~3.1.7: acorn "^3.3.0" acorn-jsx "^3.0.0" -eventemitter3@^2.0.2: +esutils@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-2.0.2.tgz#20ce4891909ce9f35b088c94fab40e2c96f473ac" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +expand-tilde@^1.2.1, expand-tilde@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-1.2.2.tgz#0b81eba897e5a3d31d1c3d102f8f01441e559449" + dependencies: + os-homedir "^1.0.1" extend@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" -eyes@0.1.x: - version "0.1.8" - resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +fancy-log@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948" + dependencies: + chalk "^1.1.1" + time-stamp "^1.0.0" + +filename-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.0.tgz#996e3e80479b98b9897f15a8a58b3d084e926775" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +find-index@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4" + +findup-sync@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.4.3.tgz#40043929e7bc60adf0b7f4827c4c6e75a0deca12" + dependencies: + detect-file "^0.1.0" + is-glob "^2.0.1" + micromatch "^2.3.7" + resolve-dir "^0.1.0" -form-data@1.0.0-rc4: - version "1.0.0-rc4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.0-rc4.tgz#05ac6bc22227b43e4461f488161554699d4f8b5e" +fined@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fined/-/fined-1.0.2.tgz#5b28424b760d7598960b7ef8480dff8ad3660e97" dependencies: - async "^1.5.2" - combined-stream "^1.0.5" - mime-types "^2.1.10" + expand-tilde "^1.2.1" + lodash.assignwith "^4.0.7" + lodash.isempty "^4.2.1" + lodash.isplainobject "^4.0.4" + lodash.isstring "^4.0.1" + lodash.pick "^4.2.1" + parse-filepath "^1.0.1" + +first-chunk-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" -formidable@^1.0.17: - version "1.0.17" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.0.17.tgz#ef5491490f9433b705faa77249c99029ae348559" +flagged-respawn@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-0.3.2.tgz#ff191eddcd7088a675b2610fffc976be9b8074b5" + +for-in@^0.1.5: + version "0.1.6" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.6.tgz#c9f96e89bfad18a545af5ec3ed352a1d9e5b4dc8" + +for-own@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.4.tgz#0149b41a39088c7515f51ebe1c1386d45f935072" + dependencies: + for-in "^0.1.5" + +fs-exists-sync@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" -glob@3.2.11: - version "3.2.11" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" +gaze@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-0.5.2.tgz#40b709537d24d1d45767db5a908689dfe69ac44f" dependencies: + globule "~0.1.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob-stream@^3.1.5: + version "3.1.18" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-3.1.18.tgz#9170a5f12b790306fdfe598f313f8f7954fd143b" + dependencies: + glob "^4.3.1" + glob2base "^0.0.12" + minimatch "^2.0.1" + ordered-read-streams "^0.1.0" + through2 "^0.6.1" + unique-stream "^1.0.0" + +glob-watcher@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-0.0.6.tgz#b95b4a8df74b39c83298b0c05c978b4d9a3b710b" + dependencies: + gaze "^0.5.1" + +glob@^4.3.1: + version "4.5.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" + dependencies: + inflight "^1.0.4" inherits "2" - minimatch "0.3" + minimatch "^2.0.1" + once "^1.3.0" + +glob@~3.1.21: + version "3.1.21" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" + dependencies: + graceful-fs "~1.2.0" + inherits "1" + minimatch "~0.2.11" + +glob2base@^0.0.12: + version "0.0.12" + resolved "https://registry.yarnpkg.com/glob2base/-/glob2base-0.0.12.tgz#9d419b3e28f12e83a362164a277055922c9c0d56" + dependencies: + find-index "^0.1.1" + +global-modules@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-0.2.3.tgz#ea5a3bed42c6d6ce995a4f8a1269b5dae223828d" + dependencies: + global-prefix "^0.1.4" + is-windows "^0.2.0" + +global-prefix@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-0.1.5.tgz#8d3bc6b8da3ca8112a160d8d496ff0462bfef78f" + dependencies: + homedir-polyfill "^1.0.0" + ini "^1.3.4" + is-windows "^0.2.0" + which "^1.2.12" + +globals@^9.0.0: + version "9.14.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.14.0.tgz#8859936af0038741263053b39d0e76ca241e4034" + +globule@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/globule/-/globule-0.1.0.tgz#d9c8edde1da79d125a151b79533b978676346ae5" + dependencies: + glob "~3.1.21" + lodash "~1.0.1" + minimatch "~0.2.11" + +glogg@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5" + dependencies: + sparkles "^1.0.0" + +graceful-fs@^3.0.0: + version "3.0.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818" + dependencies: + natives "^1.1.0" graceful-fs@^4.1.9: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" +graceful-fs@~1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364" + +gulp-babel@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/gulp-babel/-/gulp-babel-6.1.2.tgz#7c0176e4ba3f244c60588a0c4b320a45d1adefce" + dependencies: + babel-core "^6.0.2" + gulp-util "^3.0.0" + object-assign "^4.0.1" + replace-ext "0.0.1" + through2 "^2.0.0" + vinyl-sourcemaps-apply "^0.2.0" + +gulp-util@^3.0.0: + version "3.0.8" + resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" + dependencies: + array-differ "^1.0.0" + array-uniq "^1.0.2" + beeper "^1.0.0" + chalk "^1.0.0" + dateformat "^2.0.0" + fancy-log "^1.1.0" + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash._reescape "^3.0.0" + lodash._reevaluate "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.template "^3.0.0" + minimist "^1.1.0" + multipipe "^0.1.2" + object-assign "^3.0.0" + replace-ext "0.0.1" + through2 "^2.0.0" + vinyl "^0.5.0" + +gulp@^3.9.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/gulp/-/gulp-3.9.1.tgz#571ce45928dd40af6514fc4011866016c13845b4" + dependencies: + archy "^1.0.0" + chalk "^1.0.0" + deprecated "^0.0.1" + gulp-util "^3.0.0" + interpret "^1.0.0" + liftoff "^2.1.0" + minimist "^1.1.0" + orchestrator "^0.3.0" + pretty-hrtime "^1.0.0" + semver "^4.1.0" + tildify "^1.0.0" + v8flags "^2.0.2" + vinyl-fs "^0.3.0" + +gulplog@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" + dependencies: + glogg "^1.0.0" has-ansi@^2.0.0: version "2.0.0" @@ -200,24 +610,150 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" +has-gulplog@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" + dependencies: + sparkles "^1.0.0" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +homedir-polyfill@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" + dependencies: + parse-passwd "^1.0.0" + +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.0.1, inherits@2: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" -isarray@~1.0.0: +inherits@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b" + +ini@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" + +interpret@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c" + +invariant@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + dependencies: + loose-envify "^1.0.0" + +is-absolute@^0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-0.2.6.tgz#20de69f3db942ef2d87b9c2da36f172235b1b5eb" + dependencies: + is-relative "^0.2.1" + is-windows "^0.2.0" + +is-buffer@^1.0.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b" + +is-dotfile@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" -isstream@0.1.x: +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-number@^2.0.2, is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-relative@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.2.1.tgz#d27f4c7d516d175fb610db84bbeef23c3bc97aa5" + dependencies: + is-unc-path "^0.1.1" + +is-unc-path@^0.1.1: version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-0.1.2.tgz#6ab053a72573c10250ff416a3814c35178af39b9" + dependencies: + unc-path-regex "^0.1.0" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" -jade@0.26.3: - version "0.26.3" - resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c" +is-windows@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" + +isarray@~1.0.0, isarray@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isexe@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" dependencies: - commander "0.6.1" - mkdirp "0.3.0" + isarray "1.0.0" + +js-tokens@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-2.0.0.tgz#79903f5563ee778cc1162e6dcf1a0027c97f9cb5" js2xmlparser@~1.0.0: version "1.0.0" @@ -244,113 +780,272 @@ jsdoc@^3.4.3: taffydb "2.6.2" underscore "~1.8.3" +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +json5@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +kind-of@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47" + dependencies: + is-buffer "^1.0.2" + klaw@~1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" optionalDependencies: graceful-fs "^4.1.9" -"log@>= 1.2.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/log/-/log-1.4.0.tgz#4ba1d890fde249b031dca03bc37eaaf325656f1c" +liftoff@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.3.0.tgz#a98f2ff67183d8ba7cfaca10548bd7ff0550b385" + dependencies: + extend "^3.0.0" + findup-sync "^0.4.2" + fined "^1.0.1" + flagged-respawn "^0.3.2" + lodash.isplainobject "^4.0.4" + lodash.isstring "^4.0.1" + lodash.mapvalues "^4.4.0" + rechoir "^0.6.2" + resolve "^1.1.7" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + +lodash._basetostring@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" + +lodash._basevalues@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + +lodash._reescape@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" + +lodash._reevaluate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + +lodash._root@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + +lodash.assignwith@^4.0.7: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz#127a97f02adc41751a954d24b0de17e100e038eb" + +lodash.escape@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" + dependencies: + lodash._root "^3.0.0" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + +lodash.isempty@^4.2.1: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" + +lodash.isplainobject@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash.mapvalues@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" + +lodash.pick@^4.2.1: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" + +lodash.restparam@^3.0.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + +lodash.template@^3.0.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" + dependencies: + lodash._basecopy "^3.0.0" + lodash._basetostring "^3.0.0" + lodash._basevalues "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + lodash.keys "^3.0.0" + lodash.restparam "^3.0.0" + lodash.templatesettings "^3.0.0" + +lodash.templatesettings@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + +lodash@^4.2.0: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +lodash@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" + +loose-envify@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.0.tgz#6b26248c42f6d4fa4b0d8542f78edfcde35642a8" + dependencies: + js-tokens "^2.0.0" lru-cache@2: version "2.7.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" +map-cache@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + marked@~0.3.6: version "0.3.6" resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7" -methods@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - -mime-db@~1.25.0: - version "1.25.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.25.0.tgz#c18dbd7c73a5dbf6f44a024dc0d165a1e7b1c392" - -mime-types@^2.1.10: - version "2.1.13" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.13.tgz#e07aaa9c6c6b9a7ca3012c69003ad25a39e92a88" +micromatch@^2.3.7: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +minimatch@^2.0.1: + version "2.0.10" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" dependencies: - mime-db "~1.25.0" + brace-expansion "^1.0.0" -mime@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" +minimatch@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" -minimatch@0.3: - version "0.3.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" +minimatch@~0.2.11: + version "0.2.14" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" dependencies: lru-cache "2" sigmund "~1.0.0" +minimist@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -"mkdirp@>= 0.0.1", mkdirp@~0.5.1, mkdirp@0.5.1: +mkdirp@^0.5.0, mkdirp@^0.5.1, 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" -mkdirp@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" -mocha@^2.2.5: - version "2.5.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58" +multipipe@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" dependencies: - commander "2.3.0" - debug "2.2.0" - diff "1.4.0" - escape-string-regexp "1.0.2" - glob "3.2.11" - growl "1.9.2" - jade "0.26.3" - mkdirp "0.5.1" - supports-color "1.2.0" - to-iso-string "0.0.2" + duplexer2 "0.0.2" -moment-timezone@^0.5.5: - version "0.5.11" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.11.tgz#9b76c03d8ef514c7e4249a7bbce649eed39ef29f" - dependencies: - moment ">= 2.6.0" +natives@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.0.tgz#e9ff841418a6b2ec7a495e939984f78f163e6e31" -moment@^2.13.0, "moment@>= 2.6.0": - version "2.17.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.17.1.tgz#fed9506063f36b10f066c8b59a144d7faebe1d82" +normalize-path@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a" -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -ms@0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" +object-assign@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" -nan@^2.3.2, nan@2: - version "2.5.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.5.0.tgz#aa8f1e34531d807e9e27755b234b4a6ec0c152a8" +object-assign@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" -node-opus@^0.2.4: - version "0.2.4" - resolved "https://registry.yarnpkg.com/node-opus/-/node-opus-0.2.4.tgz#79fb35cf0e7ad04cfb9398eb362aba0774e30a61" +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" dependencies: - bindings "~1.2.1" - nan "^2.3.2" - ogg-packet "^1.0.0" + for-own "^0.1.4" + is-extendable "^0.1.1" -ogg-packet@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ogg-packet/-/ogg-packet-1.0.0.tgz#45b885721ac8f7dd5cf22391d42106ae533ac678" +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +once@~1.3.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" dependencies: - ref-struct "*" + wrappy "1" options@>=0.0.5: version "0.0.6" @@ -360,25 +1055,85 @@ opusscript@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/opusscript/-/opusscript-0.0.1.tgz#c8f61d4301b2942ee9ddf68b075b3e373b7943dd" -pkginfo@0.3.x: - version "0.3.1" - resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" +orchestrator@^0.3.0: + version "0.3.8" + resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" + dependencies: + end-of-stream "~0.1.5" + sequencify "~0.0.7" + stream-consume "~0.1.0" + +ordered-read-streams@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz#fd565a9af8eb4473ba69b6ed8a34352cb552f126" + +os-homedir@^1.0.0, os-homedir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-tmpdir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +parse-filepath@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.1.tgz#159d6155d43904d16c10ef698911da1e91969b73" + dependencies: + is-absolute "^0.2.3" + map-cache "^0.2.0" + path-root "^0.1.1" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + +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-root-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + +path-root@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + dependencies: + path-root-regex "^0.1.0" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +pretty-hrtime@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + +private@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.6.tgz#55c6a976d0f9bafb9924851350fe47b9b5fbb7c1" 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" -promise@^7.0.3: - version "7.1.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf" +randomatic@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb" dependencies: - asap "~2.0.3" - -qs@^6.1.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.0.tgz#f403b264f23bc01228c74131b407f18d5ea5d442" + is-number "^2.0.2" + kind-of "^3.0.2" -readable-stream@^2.0.5: +readable-stream@^2.1.5: version "2.2.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e" dependencies: @@ -390,40 +1145,58 @@ readable-stream@^2.0.5: string_decoder "~0.10.x" util-deprecate "~1.0.1" -redis-commands@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.3.0.tgz#4307d8094aee1315829ab6729b37b99f62365d63" +"readable-stream@>=1.0.33-1 <1.1.0-0": + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" -redis-parser@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-2.3.0.tgz#313a47965e49ee35ab3a86c93388b403d76237f6" +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" -redis@^2.6.1: - version "2.6.3" - resolved "https://registry.yarnpkg.com/redis/-/redis-2.6.3.tgz#84305b92553c6a1f09c7c47c30b11ace7dbb7ad4" +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" dependencies: - double-ended-queue "^2.1.0-0" - redis-commands "^1.2.0" - redis-parser "^2.0.0" + resolve "^1.1.6" -ref-struct@*: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ref-struct/-/ref-struct-1.1.0.tgz#5d5ee65ad41cefc3a5c5feb40587261e479edc13" +regenerator-runtime@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.1.tgz#257f41961ce44558b18f7814af48c17559f9faeb" + +regex-cache@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" dependencies: - debug "2" - ref "1" + is-equal-shallow "^0.1.3" + is-primitive "^2.0.0" -ref@1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/ref/-/ref-1.3.3.tgz#116d1ef64f2bc56d9e54a648cea7332a36b81932" +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" dependencies: - bindings "1" - debug "2" - nan "2" + is-finite "^1.0.0" -require-all@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/require-all/-/require-all-2.1.0.tgz#109e1c3dab8a5acab2312f552d5e8d27d8de9f77" +replace-ext@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" requizzle@~0.2.1: version "0.2.1" @@ -431,19 +1204,50 @@ requizzle@~0.2.1: dependencies: underscore "~1.6.0" -rethinkdbdash@~2.3.0: - version "2.3.27" - resolved "https://registry.yarnpkg.com/rethinkdbdash/-/rethinkdbdash-2.3.27.tgz#66de1c6cf13ed89db0c81ee0f060656caddfe1a5" +resolve-dir@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-0.1.1.tgz#b219259a5602fac5c5c496ad894a6e8cc430261e" dependencies: - bluebird ">= 3.0.1" + expand-tilde "^1.2.2" + global-modules "^0.2.3" + +resolve@^1.1.6, resolve@^1.1.7: + version "1.2.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.2.0.tgz#9589c3f2f6149d1417a40becc1663db6ec6bc26c" + +semver@^4.1.0: + version "4.3.6" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" + +sequencify@~0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c" sigmund@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" -stack-trace@0.0.x: - version "0.0.9" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695" +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +source-map-support@^0.4.2: + version "0.4.8" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.8.tgz#4871918d8a3af07289182e974e32844327b2e98b" + dependencies: + source-map "^0.5.3" + +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + +sparkles@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" + +stream-consume@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.0.tgz#a41ead1a6d6081ceb79f65b061901b6d8f3d1d0f" string_decoder@~0.10.x: version "0.10.31" @@ -455,48 +1259,52 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" +strip-bom@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-1.0.0.tgz#85b8862f3844b5a6d5ec8467a93598173a36f794" + dependencies: + first-chunk-stream "^1.0.0" + is-utf8 "^0.2.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" -superagent@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-2.3.0.tgz#703529a0714e57e123959ddefbce193b2e50d115" - dependencies: - component-emitter "^1.2.0" - cookiejar "^2.0.6" - debug "^2.2.0" - extend "^3.0.0" - form-data "1.0.0-rc4" - formidable "^1.0.17" - methods "^1.1.1" - mime "^1.3.4" - qs "^6.1.0" - readable-stream "^2.0.5" - 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@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e" - taffydb@2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268" -thinky@^2.3.7: - version "2.3.8" - resolved "https://registry.yarnpkg.com/thinky/-/thinky-2.3.8.tgz#4d3d01fe0aaaa8cd97276965f40dbb4f017300f3" +through2@^0.6.1: + version "0.6.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" dependencies: - bluebird "~2.10.2" - rethinkdbdash "~2.3.0" - validator "~3.22.1" + readable-stream ">=1.0.33-1 <1.1.0-0" + xtend ">=4.0.0 <4.1.0-0" -to-iso-string@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" +through2@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +tildify@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" + dependencies: + os-homedir "^1.0.0" + +time-stamp@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.0.1.tgz#9f4bd23559c9365966f3302dbba2b07c6b99b151" + +to-fast-properties@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320" tweetnacl@^0.14.3: version "0.14.5" @@ -506,6 +1314,10 @@ ultron@1.0.x: version "1.0.2" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" +unc-path-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + underscore-contrib@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/underscore-contrib/-/underscore-contrib-0.3.0.tgz#665b66c24783f8fa2b18c9f8cbb0e2c7d48c26c7" @@ -520,49 +1332,67 @@ underscore@~1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" +unique-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" + +user-home@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" + util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -validator@~3.22.1: - version "3.22.2" - resolved "https://registry.yarnpkg.com/validator/-/validator-3.22.2.tgz#6f297ae67f7f82acc76d0afdb49f18d9a09c18c0" +v8flags@^2.0.2: + version "2.0.11" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.0.11.tgz#bca8f30f0d6d60612cc2c00641e6962d42ae6881" + dependencies: + user-home "^1.1.1" -winston-cluster@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/winston-cluster/-/winston-cluster-0.0.4.tgz#640647d0d1e24cde19c215ff9f03d87cb969c40e" +vinyl-fs@^0.3.0: + version "0.3.14" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6" + dependencies: + defaults "^1.0.0" + glob-stream "^3.1.5" + glob-watcher "^0.0.6" + graceful-fs "^3.0.0" + mkdirp "^0.5.0" + strip-bom "^1.0.0" + through2 "^0.6.1" + vinyl "^0.4.0" + +vinyl-sourcemaps-apply@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" dependencies: - cluster "^0.7.7" - mocha "^2.2.5" - promise "^7.0.3" - winston "^1.0.0" + source-map "^0.5.1" -winston-daily-rotate-file@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/winston-daily-rotate-file/-/winston-daily-rotate-file-1.4.0.tgz#71052f4c372ba7c5ae163834c5b043edd0c06be0" +vinyl@^0.4.0: + version "0.4.6" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" + dependencies: + clone "^0.2.0" + clone-stats "^0.0.1" -winston@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/winston/-/winston-1.1.2.tgz#68edd769ff79d4f9528cf0e5d80021aade67480c" +vinyl@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" dependencies: - async "~1.0.0" - colors "1.0.x" - cycle "1.0.x" - eyes "0.1.x" - isstream "0.1.x" - pkginfo "0.3.x" - stack-trace "0.0.x" + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" -winston@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/winston/-/winston-2.3.0.tgz#207faaab6fccf3fe493743dd2b03dbafc7ceb78c" +which@^1.2.12: + version "1.2.12" + resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192" dependencies: - async "~1.0.0" - colors "1.0.x" - cycle "1.0.x" - eyes "0.1.x" - isstream "0.1.x" - stack-trace "0.0.x" + isexe "^1.1.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" ws@^1.1.1: version "1.1.1" @@ -571,3 +1401,7 @@ ws@^1.1.1: options ">=0.0.5" ultron "1.0.x" +"xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" +