├── .jshintrc ├── LICENSE ├── README.md ├── apps ├── load-balancer │ └── index.js ├── repl │ └── index.js ├── sink │ └── index.js ├── voice-recognition │ ├── index.js │ └── public │ │ ├── colors.js │ │ ├── index.html │ │ ├── mesh.js │ │ └── speech.js └── website │ ├── index.js │ └── public │ ├── css │ └── styles.css │ └── index.html ├── bin └── big ├── index.js ├── lib ├── spawn.js └── start.js └── package.json /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "passfail": false, 3 | "maxerr": 100, 4 | 5 | "browser": true, 6 | "node": true, 7 | "rhino": false, 8 | "couch": true, 9 | "wsh": true, 10 | "jquery": true, 11 | "prototypejs": false, 12 | "mootools": false, 13 | "dojo": false, 14 | 15 | "devel": true, 16 | 17 | "es5": false, 18 | "strict": false, 19 | "globalstrict": false, 20 | 21 | "asi": false, 22 | "lastsemic": true, 23 | "laxbreak": true, 24 | "bitwise": false, 25 | "boss": false, 26 | "curly": true, 27 | "eqeqeq": true, 28 | "eqnull": false, 29 | "evil": false, 30 | "expr": false, 31 | "forin": false, 32 | "immed": false, 33 | "latedef": false, 34 | "loopfunc": true, 35 | "noarg": true, 36 | "regexp": true, 37 | "regexdash": false, 38 | "scripturl": true, 39 | "shadow": true, 40 | "supernew": true, 41 | "undef": true, 42 | 43 | "newcap": true, 44 | "noempty": true, 45 | "nonew": true, 46 | "nomen": false, 47 | "onevar": false, 48 | "plusplus": false, 49 | "sub": true, 50 | "trailing": true, 51 | "white": true, 52 | "indent": 2, 53 | "maxdepth": 4 54 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Marak Squires 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Big 2 | 3 | ## v.0.5.0 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npm install big -g 9 | ``` 10 | 11 | ## Starting Built-in Apps 12 | 13 | ```bash 14 | big website 15 | big load-balancer 16 | big sink 17 | big repl 18 | ``` 19 | ## Debugging 20 | 21 | To enable debugging in `big` you must set the environment variable `DEBUG`. There are two levels of debugging you'll want to inspect. 22 | 23 | ```bash 24 | export DEBUG=big::*,resource::* 25 | ``` 26 | This will enable debugging messages for all `resources` and `big` itself. 27 | 28 | ## Discovery and Event Emitter Mesh 29 | 30 | All big apps automatically create or join a new event emitter mesh when started. Each app is able to communicate to each other through the `big.mesh.emitter` Event Emitter API. 31 | 32 | Default discovery settings use `localhost` for all apps. Custom `host` and `port` options can be passed into `big.start` 33 | 34 | ## Websocket gateway 35 | 36 | If `big` is in server mode, a WebSocket gateway will be opened for incoming communication. This can be visited directly in the browser or connected to with the `mesh` resource. 37 | 38 | Authorization examples are available [here](https://github.com/bigcompany/resource-mesh/tree/master/examples/2_authorization) 39 | 40 | # Apps built with `big` 41 | 42 | ## `website` 43 | 44 | Minimal `express` based website application with built-in support for routes, sessions, static file-serving, etc. 45 | 46 | Ideal for quickly serving up static content or quickly adding custom http route logic. 47 | 48 | ## `load-balancer` 49 | 50 | Minimal `http-proxy` based HTTP load balancing for multiple websites. Will automatically add `website` apps to it's proxy table apps based on `domain`, `host`, and `port`. 51 | 52 | Ideal for routing incoming HTTP traffic to many `websites`. The `website` app will register itself automatically with the `load-balancer.` 53 | 54 | ## `sink` 55 | 56 | Event sink ( dump ) for `big.mesh.emitter`. The `sink` will capture any event emitted on the mesh network and write the event to STDOUT. 57 | 58 | Ideal for aggregating all events on the mesh to standard output ( such as a log file ). 59 | 60 | ## `repl` 61 | 62 | Simple interactive repl for communicating with the mesh network. 63 | 64 | Ideal for debugging or communicating with nodes via `big.mesh.emitter` 65 | 66 | ## `voice-recognition` 67 | 68 | Browser based Voice Recognition Gateway for communicating with the mesh network. 69 | 70 | Ideal for triggering mesh events with voice commands. 71 | -------------------------------------------------------------------------------- /apps/load-balancer/index.js: -------------------------------------------------------------------------------- 1 | var big = require('../../index'); 2 | 3 | var debug = require('debug')('big::load-balancer'); 4 | 5 | var loadbalancer = big.define('loadbalancer'); 6 | var http = require('http'), 7 | httpProxy = require('http-proxy'); 8 | 9 | var proxyTable = {}; 10 | 11 | // expose loadbalancer methods as remote 12 | 13 | 14 | loadbalancer.remote = true; 15 | 16 | loadbalancer.method('addSite', function(options){ 17 | debug('added site to load balancer'); 18 | proxyTable[options.domain] = options; 19 | }); 20 | 21 | var mesh = require('resource-mesh'); 22 | 23 | module['exports'] = function loadBalancer (opts) { 24 | 25 | big.start({ port: 8888 }, function(){ 26 | debug('Started'); 27 | 28 | /* 29 | mesh.emitter.on('loadbalancer::addSite', function (opts) { 30 | proxyTable[opts.domain] = opts; 31 | 32 | console.log("ADDING SITE"); 33 | }) 34 | */ 35 | console.log(big.resource.eventTable) 36 | 37 | var proxy = new httpProxy.createProxyServer(); 38 | http.createServer(function (req, res) { 39 | var host = req.headers.host.split(":"); 40 | host = host[0]; 41 | debug(host, proxyTable); 42 | 43 | if (typeof proxyTable[host] !== "undefined") { 44 | var target = "http://" + proxyTable[host].host + ":" + proxyTable[host].port; 45 | proxy.web(req, res, { 46 | target: target 47 | }); 48 | } else { 49 | res.end('invalid proxy target: ' + host); 50 | } 51 | 52 | }).listen(7777); 53 | 54 | debug('Load balancer started at 7777'); 55 | 56 | }); 57 | return big; 58 | }; 59 | 60 | -------------------------------------------------------------------------------- /apps/repl/index.js: -------------------------------------------------------------------------------- 1 | var big = require('../../index'); 2 | var repl = require('resource-repl').repl; 3 | var resource = require('resource'); 4 | 5 | module['exports'] = function website (opts) { 6 | opts = opts || {}; 7 | opts.port = opts.port || 8888; 8 | big.start(opts, function(err, app){ 9 | repl.start({ context: resource }); 10 | }); 11 | return big; 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /apps/sink/index.js: -------------------------------------------------------------------------------- 1 | var big = require('../../index'); 2 | 3 | var debug = require('debug')('big::sink'); 4 | 5 | var http = require('resource-http'); 6 | var mesh = require('resource-mesh'); 7 | 8 | module['exports'] = function sink (opts) { 9 | opts = opts || {}; 10 | opts.port = opts.port || 8888; 11 | opts.site = opts.site || {}; 12 | opts.site.root = opts.site.root || __dirname + "/public"; 13 | big.start(opts, function(err, app){ 14 | 15 | // start static http server 16 | http.listen({ 17 | port: 9998, 18 | root: opts.root 19 | }, function(err, app) { 20 | 21 | if (err) { 22 | throw err; 23 | } 24 | 25 | var addr = app.server.address(); 26 | 27 | // on any event, emit it as JSON to STDOUT for logging streams to capture 28 | mesh.emitter.onAny(function(data){ 29 | debug(JSON.stringify({ event: this.event, data: data }) + '\n') 30 | }); 31 | }); 32 | 33 | }); 34 | return big; 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /apps/voice-recognition/index.js: -------------------------------------------------------------------------------- 1 | var big = require('../../index'); 2 | var http = require('resource-http'); 3 | var mesh = require('resource-mesh'); 4 | var debug = require('debug')('big::voice-recognition'); 5 | var colors = require('colors'); 6 | 7 | module['exports'] = function website (opts, cb) { 8 | 9 | opts = opts || {}; 10 | opts.port = opts.port || 8888; 11 | opts.site = opts.site || {}; 12 | opts.site.port = opts.site.port || 9999; 13 | opts.site.root = opts.site.root || __dirname + "/public"; 14 | 15 | big.start(opts, function(err, app){ 16 | // start static http server 17 | http.listen({ 18 | port: opts.site.port, 19 | root: opts.site.root, 20 | view: opts.site.view 21 | }, function(err, app) { 22 | if (err) { 23 | throw err; 24 | } 25 | // after the http static server has started, 26 | // emit an event on the mesh registering it if a loadbalancer is available 27 | var addr = app.server.address(); 28 | debug('started'); 29 | 30 | var commands = { 31 | 'big server stop': function(item){ 32 | mesh.emitter.emit('voiceCommand', { event: "http::stop" }); 33 | }, 34 | 'big open *item': function(item){ 35 | //alert(item) 36 | mesh.emitter.emit('voiceCommand', item); 37 | } 38 | }; 39 | 40 | mesh.emitter.emit('addCommands', commands); 41 | 42 | mesh.emitter.on('getEvents', function(){ 43 | console.log('getEventsss') 44 | mesh.emitter.emit('addEvents', 'bar') 45 | }); 46 | var style = "yellow", decorator="blackBG"; 47 | mesh.emitter.on('hello', function(data){ 48 | console.log(('hello ' + data)[style][decorator]); 49 | }); 50 | 51 | mesh.emitter.on('voiceCommand', function (data){ 52 | switch (data.event) { 53 | case 'color': 54 | if (colors[data.color + "BG"]) { 55 | decorator = data.color + "BG"; 56 | } 57 | break; 58 | case 'text': 59 | if (colors[data.color]) { 60 | style = data.color; 61 | } 62 | break; 63 | } 64 | debug('got voice command', data); 65 | big.emit(data.event, 'foo') 66 | }); 67 | 68 | cb(null, app); 69 | }); 70 | 71 | }); 72 | return big; 73 | }; -------------------------------------------------------------------------------- /apps/voice-recognition/public/colors.js: -------------------------------------------------------------------------------- 1 | !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var o;"undefined"!=typeof window?o=window:"undefined"!=typeof global?o=global:"undefined"!=typeof self&&(o=self),o.colors=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o (sindresorhus.com) 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | THE SOFTWARE. 29 | 30 | */ 31 | 32 | var colors = {}; 33 | module['exports'] = colors; 34 | 35 | colors.themes = {}; 36 | 37 | var ansiStyles = colors.styles = require('./styles'); 38 | var defineProps = Object.defineProperties; 39 | 40 | colors.supportsColor = require('./system/supports-colors'); 41 | 42 | if (typeof colors.enabled === "undefined") { 43 | colors.enabled = colors.supportsColor; 44 | } 45 | 46 | colors.stripColors = colors.strip = function(str){ 47 | return ("" + str).replace(/\x1B\[\d+m/g, ''); 48 | }; 49 | 50 | 51 | var stylize = colors.stylize = function stylize (str, style) { 52 | return ansiStyles[style].open + str + ansiStyles[style].close; 53 | } 54 | 55 | var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; 56 | var escapeStringRegexp = function (str) { 57 | if (typeof str !== 'string') { 58 | throw new TypeError('Expected a string'); 59 | } 60 | return str.replace(matchOperatorsRe, '\\$&'); 61 | } 62 | 63 | function build(_styles) { 64 | var builder = function builder() { 65 | return applyStyle.apply(builder, arguments); 66 | }; 67 | builder._styles = _styles; 68 | // __proto__ is used because we must return a function, but there is 69 | // no way to create a function with a different prototype. 70 | builder.__proto__ = proto; 71 | return builder; 72 | } 73 | 74 | var styles = (function () { 75 | var ret = {}; 76 | ansiStyles.grey = ansiStyles.gray; 77 | Object.keys(ansiStyles).forEach(function (key) { 78 | ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); 79 | ret[key] = { 80 | get: function () { 81 | return build(this._styles.concat(key)); 82 | } 83 | }; 84 | }); 85 | return ret; 86 | })(); 87 | 88 | var proto = defineProps(function colors() {}, styles); 89 | 90 | function applyStyle() { 91 | var args = arguments; 92 | var argsLen = args.length; 93 | var str = argsLen !== 0 && String(arguments[0]); 94 | if (argsLen > 1) { 95 | for (var a = 1; a < argsLen; a++) { 96 | str += ' ' + args[a]; 97 | } 98 | } 99 | 100 | if (!colors.enabled || !str) { 101 | return str; 102 | } 103 | 104 | var nestedStyles = this._styles; 105 | 106 | var i = nestedStyles.length; 107 | while (i--) { 108 | var code = ansiStyles[nestedStyles[i]]; 109 | str = code.open + str.replace(code.closeRe, code.open) + code.close; 110 | } 111 | 112 | return str; 113 | } 114 | 115 | function applyTheme (theme) { 116 | for (var style in theme) { 117 | (function(style){ 118 | colors[style] = function(str){ 119 | return colors[theme[style]](str); 120 | }; 121 | })(style) 122 | } 123 | } 124 | 125 | colors.setTheme = function (theme) { 126 | if (typeof theme === 'string') { 127 | try { 128 | colors.themes[theme] = require(theme); 129 | applyTheme(colors.themes[theme]); 130 | return colors.themes[theme]; 131 | } catch (err) { 132 | console.log(err); 133 | return err; 134 | } 135 | } else { 136 | applyTheme(theme); 137 | } 138 | }; 139 | 140 | function init() { 141 | var ret = {}; 142 | Object.keys(styles).forEach(function (name) { 143 | ret[name] = { 144 | get: function () { 145 | return build([name]); 146 | } 147 | }; 148 | }); 149 | return ret; 150 | } 151 | 152 | var sequencer = function sequencer (map, str) { 153 | var exploded = str.split(""), i = 0; 154 | exploded = exploded.map(map); 155 | return exploded.join(""); 156 | }; 157 | 158 | // custom formatter methods 159 | colors.trap = require('./custom/trap'); 160 | colors.zalgo = require('./custom/zalgo'); 161 | 162 | // maps 163 | colors.maps = {}; 164 | colors.maps.america = require('./maps/america'); 165 | colors.maps.zebra = require('./maps/zebra'); 166 | colors.maps.rainbow = require('./maps/rainbow'); 167 | colors.maps.random = require('./maps/random') 168 | 169 | for (var map in colors.maps) { 170 | (function(map){ 171 | colors[map] = function (str) { 172 | return sequencer(colors.maps[map], str); 173 | } 174 | })(map) 175 | } 176 | 177 | defineProps(colors, init()); 178 | },{"./custom/trap":2,"./custom/zalgo":3,"./maps/america":6,"./maps/rainbow":7,"./maps/random":8,"./maps/zebra":9,"./styles":10,"./system/supports-colors":11}],2:[function(require,module,exports){ 179 | module['exports'] = function runTheTrap (text, options) { 180 | var result = ""; 181 | text = text || "Run the trap, drop the bass"; 182 | text = text.split(''); 183 | var trap = { 184 | a: ["\u0040", "\u0104", "\u023a", "\u0245", "\u0394", "\u039b", "\u0414"], 185 | b: ["\u00df", "\u0181", "\u0243", "\u026e", "\u03b2", "\u0e3f"], 186 | c: ["\u00a9", "\u023b", "\u03fe"], 187 | d: ["\u00d0", "\u018a", "\u0500" , "\u0501" ,"\u0502", "\u0503"], 188 | e: ["\u00cb", "\u0115", "\u018e", "\u0258", "\u03a3", "\u03be", "\u04bc", "\u0a6c"], 189 | f: ["\u04fa"], 190 | g: ["\u0262"], 191 | h: ["\u0126", "\u0195", "\u04a2", "\u04ba", "\u04c7", "\u050a"], 192 | i: ["\u0f0f"], 193 | j: ["\u0134"], 194 | k: ["\u0138", "\u04a0", "\u04c3", "\u051e"], 195 | l: ["\u0139"], 196 | m: ["\u028d", "\u04cd", "\u04ce", "\u0520", "\u0521", "\u0d69"], 197 | n: ["\u00d1", "\u014b", "\u019d", "\u0376", "\u03a0", "\u048a"], 198 | o: ["\u00d8", "\u00f5", "\u00f8", "\u01fe", "\u0298", "\u047a", "\u05dd", "\u06dd", "\u0e4f"], 199 | p: ["\u01f7", "\u048e"], 200 | q: ["\u09cd"], 201 | r: ["\u00ae", "\u01a6", "\u0210", "\u024c", "\u0280", "\u042f"], 202 | s: ["\u00a7", "\u03de", "\u03df", "\u03e8"], 203 | t: ["\u0141", "\u0166", "\u0373"], 204 | u: ["\u01b1", "\u054d"], 205 | v: ["\u05d8"], 206 | w: ["\u0428", "\u0460", "\u047c", "\u0d70"], 207 | x: ["\u04b2", "\u04fe", "\u04fc", "\u04fd"], 208 | y: ["\u00a5", "\u04b0", "\u04cb"], 209 | z: ["\u01b5", "\u0240"] 210 | } 211 | text.forEach(function(c){ 212 | c = c.toLowerCase(); 213 | var chars = trap[c] || [c]; 214 | var rand = Math.floor(Math.random() * chars.length); 215 | if (typeof trap[c] !== "undefined") { 216 | result += trap[c][rand]; 217 | } else { 218 | result += c; 219 | } 220 | }); 221 | return result; 222 | 223 | } 224 | 225 | },{}],3:[function(require,module,exports){ 226 | // please no 227 | module['exports'] = function zalgo(text, options) { 228 | text = text || " he is here "; 229 | var soul = { 230 | "up" : [ 231 | '̍', '̎', '̄', '̅', 232 | '̿', '̑', '̆', '̐', 233 | '͒', '͗', '͑', '̇', 234 | '̈', '̊', '͂', '̓', 235 | '̈', '͊', '͋', '͌', 236 | '̃', '̂', '̌', '͐', 237 | '̀', '́', '̋', '̏', 238 | '̒', '̓', '̔', '̽', 239 | '̉', 'ͣ', 'ͤ', 'ͥ', 240 | 'ͦ', 'ͧ', 'ͨ', 'ͩ', 241 | 'ͪ', 'ͫ', 'ͬ', 'ͭ', 242 | 'ͮ', 'ͯ', '̾', '͛', 243 | '͆', '̚' 244 | ], 245 | "down" : [ 246 | '̖', '̗', '̘', '̙', 247 | '̜', '̝', '̞', '̟', 248 | '̠', '̤', '̥', '̦', 249 | '̩', '̪', '̫', '̬', 250 | '̭', '̮', '̯', '̰', 251 | '̱', '̲', '̳', '̹', 252 | '̺', '̻', '̼', 'ͅ', 253 | '͇', '͈', '͉', '͍', 254 | '͎', '͓', '͔', '͕', 255 | '͖', '͙', '͚', '̣' 256 | ], 257 | "mid" : [ 258 | '̕', '̛', '̀', '́', 259 | '͘', '̡', '̢', '̧', 260 | '̨', '̴', '̵', '̶', 261 | '͜', '͝', '͞', 262 | '͟', '͠', '͢', '̸', 263 | '̷', '͡', ' ҉' 264 | ] 265 | }, 266 | all = [].concat(soul.up, soul.down, soul.mid), 267 | zalgo = {}; 268 | 269 | function randomNumber(range) { 270 | var r = Math.floor(Math.random() * range); 271 | return r; 272 | } 273 | 274 | function is_char(character) { 275 | var bool = false; 276 | all.filter(function (i) { 277 | bool = (i === character); 278 | }); 279 | return bool; 280 | } 281 | 282 | 283 | function heComes(text, options) { 284 | var result = '', counts, l; 285 | options = options || {}; 286 | options["up"] = options["up"] || true; 287 | options["mid"] = options["mid"] || true; 288 | options["down"] = options["down"] || true; 289 | options["size"] = options["size"] || "maxi"; 290 | text = text.split(''); 291 | for (l in text) { 292 | if (is_char(l)) { 293 | continue; 294 | } 295 | result = result + text[l]; 296 | counts = {"up" : 0, "down" : 0, "mid" : 0}; 297 | switch (options.size) { 298 | case 'mini': 299 | counts.up = randomNumber(8); 300 | counts.min = randomNumber(2); 301 | counts.down = randomNumber(8); 302 | break; 303 | case 'maxi': 304 | counts.up = randomNumber(16) + 3; 305 | counts.min = randomNumber(4) + 1; 306 | counts.down = randomNumber(64) + 3; 307 | break; 308 | default: 309 | counts.up = randomNumber(2) + 1; 310 | counts.mid = randomNumber(3) / 2; 311 | counts.down = randomNumber(2) + 1; 312 | break; 313 | } 314 | 315 | var arr = ["up", "mid", "down"]; 316 | for (var d in arr) { 317 | var index = arr[d]; 318 | for (var i = 0 ; i <= counts[index]; i++) { 319 | if (options[index]) { 320 | result = result + soul[index][randomNumber(soul[index].length)]; 321 | } 322 | } 323 | } 324 | } 325 | return result; 326 | } 327 | // don't summon him 328 | return heComes(text); 329 | } 330 | 331 | },{}],4:[function(require,module,exports){ 332 | var colors = require('./colors'), 333 | styles = require('./styles'); 334 | 335 | module['exports'] = function () { 336 | 337 | // 338 | // Extends prototype of native string object to allow for "foo".red syntax 339 | // 340 | var addProperty = function (color, func) { 341 | String.prototype.__defineGetter__(color, func); 342 | }; 343 | 344 | var sequencer = function sequencer (map, str) { 345 | return function () { 346 | var exploded = this.split(""), i = 0; 347 | exploded = exploded.map(map); 348 | return exploded.join(""); 349 | } 350 | }; 351 | 352 | var stylize = function stylize (str, style) { 353 | return styles[style].open + str + styles[style].close; 354 | } 355 | 356 | addProperty('strip', function () { 357 | return colors.strip(this); 358 | }); 359 | 360 | addProperty('stripColors', function () { 361 | return colors.strip(this); 362 | }); 363 | 364 | addProperty("trap", function(){ 365 | return colors.trap(this); 366 | }); 367 | 368 | addProperty("zalgo", function(){ 369 | return colors.zalgo(this); 370 | }); 371 | 372 | addProperty("zebra", function(){ 373 | return colors.zebra(this); 374 | }); 375 | 376 | addProperty("rainbow", function(){ 377 | return colors.rainbow(this); 378 | }); 379 | 380 | addProperty("random", function(){ 381 | return colors.random(this); 382 | }); 383 | 384 | addProperty("america", function(){ 385 | return colors.america(this); 386 | }); 387 | 388 | // 389 | // Iterate through all default styles and colors 390 | // 391 | var x = Object.keys(colors.styles); 392 | x.forEach(function (style) { 393 | addProperty(style, function () { 394 | return stylize(this, style); 395 | }); 396 | }); 397 | 398 | function applyTheme(theme) { 399 | // 400 | // Remark: This is a list of methods that exist 401 | // on String that you should not overwrite. 402 | // 403 | var stringPrototypeBlacklist = [ 404 | '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', 'charAt', 'constructor', 405 | 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf', 'charCodeAt', 406 | 'indexOf', 'lastIndexof', 'length', 'localeCompare', 'match', 'replace', 'search', 'slice', 'split', 'substring', 407 | 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight' 408 | ]; 409 | 410 | Object.keys(theme).forEach(function (prop) { 411 | if (stringPrototypeBlacklist.indexOf(prop) !== -1) { 412 | console.log('warn: '.red + ('String.prototype' + prop).magenta + ' is probably something you don\'t want to override. Ignoring style name'); 413 | } 414 | else { 415 | if (typeof(theme[prop]) === 'string') { 416 | colors[prop] = colors[theme[prop]]; 417 | addProperty(prop, function () { 418 | return colors[theme[prop]](this); 419 | }); 420 | } 421 | else { 422 | addProperty(prop, function () { 423 | var ret = this; 424 | for (var t = 0; t < theme[prop].length; t++) { 425 | ret = exports[theme[prop][t]](ret); 426 | } 427 | return ret; 428 | }); 429 | } 430 | } 431 | }); 432 | } 433 | 434 | colors.setTheme = function (theme) { 435 | if (typeof theme === 'string') { 436 | try { 437 | colors.themes[theme] = require(theme); 438 | applyTheme(colors.themes[theme]); 439 | return colors.themes[theme]; 440 | } catch (err) { 441 | console.log(err); 442 | return err; 443 | } 444 | } else { 445 | applyTheme(theme); 446 | } 447 | }; 448 | 449 | }; 450 | },{"./colors":1,"./styles":10}],5:[function(require,module,exports){ 451 | var colors = require('./colors'); 452 | module['exports'] = colors; 453 | 454 | // Remark: By default, colors will add style properties to String.prototype 455 | // 456 | // If you don't wish to extend String.prototype you can do this instead and native String will not be touched 457 | // 458 | // var colors = require('colors/safe); 459 | // colors.red("foo") 460 | // 461 | // 462 | var extendStringPrototype = require('./extendStringPrototype')(); 463 | },{"./colors":1,"./extendStringPrototype":4}],6:[function(require,module,exports){ 464 | var colors = require('../colors'); 465 | 466 | module['exports'] = (function() { 467 | return function (letter, i, exploded) { 468 | if(letter === " ") return letter; 469 | switch(i%3) { 470 | case 0: return colors.red(letter); 471 | case 1: return colors.white(letter) 472 | case 2: return colors.blue(letter) 473 | } 474 | } 475 | })(); 476 | },{"../colors":1}],7:[function(require,module,exports){ 477 | var colors = require('../colors'); 478 | 479 | module['exports'] = (function () { 480 | var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta']; //RoY G BiV 481 | return function (letter, i, exploded) { 482 | if (letter === " ") { 483 | return letter; 484 | } else { 485 | return colors[rainbowColors[i++ % rainbowColors.length]](letter); 486 | } 487 | }; 488 | })(); 489 | 490 | 491 | },{"../colors":1}],8:[function(require,module,exports){ 492 | var colors = require('../colors'); 493 | 494 | module['exports'] = (function () { 495 | var available = ['underline', 'inverse', 'grey', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta']; 496 | return function(letter, i, exploded) { 497 | return letter === " " ? letter : colors[available[Math.round(Math.random() * (available.length - 1))]](letter); 498 | }; 499 | })(); 500 | },{"../colors":1}],9:[function(require,module,exports){ 501 | var colors = require('../colors'); 502 | 503 | module['exports'] = function (letter, i, exploded) { 504 | return i % 2 === 0 ? letter : colors.inverse(letter); 505 | }; 506 | },{"../colors":1}],10:[function(require,module,exports){ 507 | /* 508 | The MIT License (MIT) 509 | 510 | Copyright (c) Sindre Sorhus (sindresorhus.com) 511 | 512 | Permission is hereby granted, free of charge, to any person obtaining a copy 513 | of this software and associated documentation files (the "Software"), to deal 514 | in the Software without restriction, including without limitation the rights 515 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 516 | copies of the Software, and to permit persons to whom the Software is 517 | furnished to do so, subject to the following conditions: 518 | 519 | The above copyright notice and this permission notice shall be included in 520 | all copies or substantial portions of the Software. 521 | 522 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 523 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 524 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 525 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 526 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 527 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 528 | THE SOFTWARE. 529 | 530 | */ 531 | 532 | var styles = {}; 533 | module['exports'] = styles; 534 | 535 | var codes = { 536 | reset: [0, 0], 537 | 538 | bold: [1, 22], 539 | dim: [2, 22], 540 | italic: [3, 23], 541 | underline: [4, 24], 542 | inverse: [7, 27], 543 | hidden: [8, 28], 544 | strikethrough: [9, 29], 545 | 546 | black: [30, 39], 547 | red: [31, 39], 548 | green: [32, 39], 549 | yellow: [33, 39], 550 | blue: [34, 39], 551 | magenta: [35, 39], 552 | cyan: [36, 39], 553 | white: [37, 39], 554 | gray: [90, 39], 555 | grey: [90, 39], 556 | 557 | bgBlack: [40, 49], 558 | bgRed: [41, 49], 559 | bgGreen: [42, 49], 560 | bgYellow: [43, 49], 561 | bgBlue: [44, 49], 562 | bgMagenta: [45, 49], 563 | bgCyan: [46, 49], 564 | bgWhite: [47, 49], 565 | 566 | // legacy styles for colors pre v1.0.0 567 | blackBG: [40, 49], 568 | redBG: [41, 49], 569 | greenBG: [42, 49], 570 | yellowBG: [43, 49], 571 | blueBG: [44, 49], 572 | magentaBG: [45, 49], 573 | cyanBG: [46, 49], 574 | whiteBG: [47, 49] 575 | 576 | }; 577 | 578 | Object.keys(codes).forEach(function (key) { 579 | var val = codes[key]; 580 | var style = styles[key] = []; 581 | style.open = '\u001b[' + val[0] + 'm'; 582 | style.close = '\u001b[' + val[1] + 'm'; 583 | }); 584 | },{}],11:[function(require,module,exports){ 585 | (function (process){ 586 | /* 587 | The MIT License (MIT) 588 | 589 | Copyright (c) Sindre Sorhus (sindresorhus.com) 590 | 591 | Permission is hereby granted, free of charge, to any person obtaining a copy 592 | of this software and associated documentation files (the "Software"), to deal 593 | in the Software without restriction, including without limitation the rights 594 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 595 | copies of the Software, and to permit persons to whom the Software is 596 | furnished to do so, subject to the following conditions: 597 | 598 | The above copyright notice and this permission notice shall be included in 599 | all copies or substantial portions of the Software. 600 | 601 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 602 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 603 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 604 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 605 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 606 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 607 | THE SOFTWARE. 608 | 609 | */ 610 | 611 | var argv = process.argv; 612 | 613 | module.exports = (function () { 614 | if (argv.indexOf('--no-color') !== -1 || 615 | argv.indexOf('--color=false') !== -1) { 616 | return false; 617 | } 618 | 619 | if (argv.indexOf('--color') !== -1 || 620 | argv.indexOf('--color=true') !== -1 || 621 | argv.indexOf('--color=always') !== -1) { 622 | return true; 623 | } 624 | 625 | if (process.stdout && !process.stdout.isTTY) { 626 | return false; 627 | } 628 | 629 | if (process.platform === 'win32') { 630 | return true; 631 | } 632 | 633 | if ('COLORTERM' in process.env) { 634 | return true; 635 | } 636 | 637 | if (process.env.TERM === 'dumb') { 638 | return false; 639 | } 640 | 641 | if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process.env.TERM)) { 642 | return true; 643 | } 644 | 645 | return false; 646 | })(); 647 | }).call(this,require('_process')) 648 | },{"_process":12}],12:[function(require,module,exports){ 649 | // shim for using process in browser 650 | 651 | var process = module.exports = {}; 652 | 653 | process.nextTick = (function () { 654 | var canSetImmediate = typeof window !== 'undefined' 655 | && window.setImmediate; 656 | var canPost = typeof window !== 'undefined' 657 | && window.postMessage && window.addEventListener 658 | ; 659 | 660 | if (canSetImmediate) { 661 | return function (f) { return window.setImmediate(f) }; 662 | } 663 | 664 | if (canPost) { 665 | var queue = []; 666 | window.addEventListener('message', function (ev) { 667 | var source = ev.source; 668 | if ((source === window || source === null) && ev.data === 'process-tick') { 669 | ev.stopPropagation(); 670 | if (queue.length > 0) { 671 | var fn = queue.shift(); 672 | fn(); 673 | } 674 | } 675 | }, true); 676 | 677 | return function nextTick(fn) { 678 | queue.push(fn); 679 | window.postMessage('process-tick', '*'); 680 | }; 681 | } 682 | 683 | return function nextTick(fn) { 684 | setTimeout(fn, 0); 685 | }; 686 | })(); 687 | 688 | process.title = 'browser'; 689 | process.browser = true; 690 | process.env = {}; 691 | process.argv = []; 692 | 693 | function noop() {} 694 | 695 | process.on = noop; 696 | process.addListener = noop; 697 | process.once = noop; 698 | process.off = noop; 699 | process.removeListener = noop; 700 | process.removeAllListeners = noop; 701 | process.emit = noop; 702 | 703 | process.binding = function (name) { 704 | throw new Error('process.binding is not supported'); 705 | } 706 | 707 | // TODO(shtylman) 708 | process.cwd = function () { return '/' }; 709 | process.chdir = function (dir) { 710 | throw new Error('process.chdir is not supported'); 711 | }; 712 | 713 | },{}]},{},[5])(5) 714 | }); -------------------------------------------------------------------------------- /apps/voice-recognition/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | big - voice recognition 5 | 6 | 7 | 13 | 22 | 23 | 24 | 25 | 158 | 159 | 160 | 161 | 162 | 197 | 198 | 220 | 221 | 222 | 223 | 224 |

Make sure to click "Allow" on the above bar ^^^ to enable your microphone

225 |

To get started you must say "CONNECT"

226 |
227 | 228 |
229 |
230 |
231 |
232 |
233 |
234 |

alert *text

235 |

236 | creates alert box with *text 237 |

238 |
239 | 240 |
241 |

hello *message

242 |

243 | emits the `hello` event on the mesh network with *message as data 244 |

245 |
246 | 247 |
248 |

color :color

249 |

250 | changes the background color of this page AND the console running the server 251 |

252 |
253 | 254 |
255 |

text :color

256 |

257 | changes the text color of this page AND the console running the server 258 |

259 |
260 | Protip: There are hidden voice commands available if you view the source code of this document. 261 |
262 |
263 | 264 | 265 | 266 | -------------------------------------------------------------------------------- /apps/voice-recognition/public/speech.js: -------------------------------------------------------------------------------- 1 | //! annyang 2 | //! version : 1.4.0 3 | //! author : Tal Ater @TalAter 4 | //! license : MIT 5 | //! https://www.TalAter.com/annyang/ 6 | 7 | (function (undefined) { 8 | "use strict"; 9 | 10 | /** 11 | * # Quick Tutorial, Intro and Demos 12 | * 13 | * The quickest way to get started is to visit the [annyang homepage](https://www.talater.com/annyang/). 14 | * 15 | * For a more in-depth look at annyang, read on. 16 | * 17 | * # API Reference 18 | */ 19 | 20 | // Save a reference to the global object (window in the browser) 21 | var root = this; 22 | 23 | // Get the SpeechRecognition object, while handling browser prefixes 24 | var SpeechRecognition = root.SpeechRecognition || 25 | root.webkitSpeechRecognition || 26 | root.mozSpeechRecognition || 27 | root.msSpeechRecognition || 28 | root.oSpeechRecognition; 29 | 30 | // Check browser support 31 | // This is done as early as possible, to make it as fast as possible for unsupported browsers 32 | if (!SpeechRecognition) { 33 | root.annyang = null; 34 | return undefined; 35 | } 36 | 37 | var commandsList = []; 38 | var recognition; 39 | var callbacks = { start: [], error: [], end: [], result: [], resultMatch: [], resultNoMatch: [], errorNetwork: [], errorPermissionBlocked: [], errorPermissionDenied: [] }; 40 | var autoRestart; 41 | var lastStartedAt = 0; 42 | var debugState = false; 43 | var debugStyle = 'font-weight: bold; color: #00f;'; 44 | 45 | // The command matching code is a modified version of Backbone.Router by Jeremy Ashkenas, under the MIT license. 46 | var optionalParam = /\s*\((.*?)\)\s*/g; 47 | var optionalRegex = /(\(\?:[^)]+\))\?/g; 48 | var namedParam = /(\(\?)?:\w+/g; 49 | var splatParam = /\*\w+/g; 50 | var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#]/g; 51 | var commandToRegExp = function(command) { 52 | command = command.replace(escapeRegExp, '\\$&') 53 | .replace(optionalParam, '(?:$1)?') 54 | .replace(namedParam, function(match, optional) { 55 | return optional ? match : '([^\\s]+)'; 56 | }) 57 | .replace(splatParam, '(.*?)') 58 | .replace(optionalRegex, '\\s*$1?\\s*'); 59 | return new RegExp('^' + command + '$', 'i'); 60 | }; 61 | 62 | // This method receives an array of callbacks to iterate over, and invokes each of them 63 | var invokeCallbacks = function(callbacks) { 64 | callbacks.forEach(function(callback) { 65 | callback.callback.apply(callback.context); 66 | }); 67 | }; 68 | 69 | var initIfNeeded = function() { 70 | if (!isInitialized()) { 71 | root.annyang.init({}, false); 72 | } 73 | }; 74 | 75 | var isInitialized = function() { 76 | return recognition !== undefined; 77 | }; 78 | 79 | root.annyang = { 80 | 81 | /** 82 | * Initialize annyang with a list of commands to recognize. 83 | * 84 | * ### Examples: 85 | * 86 | * var commands = {'hello :name': helloFunction}; 87 | * var commands2 = {'hi': helloFunction}; 88 | * 89 | * // initialize annyang, overwriting any previously added commands 90 | * annyang.init(commands, true); 91 | * // adds an additional command without removing the previous commands 92 | * annyang.init(commands2, false); 93 | * 94 | * As of v1.1.0 it is no longer required to call init(). Just start() listening whenever you want, and addCommands() whenever, and as often as you like. 95 | * 96 | * @param {Object} commands - Commands that annyang should listen to 97 | * @param {Boolean} [resetCommands=true] - Remove all commands before initializing? 98 | * @method init 99 | * @deprecated 100 | * @see [Commands Object](#commands-object) 101 | */ 102 | init: function(commands, resetCommands) { 103 | 104 | // resetCommands defaults to true 105 | if (resetCommands === undefined) { 106 | resetCommands = true; 107 | } else { 108 | resetCommands = !!resetCommands; 109 | } 110 | 111 | // Abort previous instances of recognition already running 112 | if (recognition && recognition.abort) { 113 | recognition.abort(); 114 | } 115 | 116 | // initiate SpeechRecognition 117 | recognition = new SpeechRecognition(); 118 | 119 | // Set the max number of alternative transcripts to try and match with a command 120 | recognition.maxAlternatives = 5; 121 | 122 | // In HTTPS, turn off continuous mode for faster results. 123 | // In HTTP, turn on continuous mode for much slower results, but no repeating security notices 124 | recognition.continuous = root.location.protocol === 'http:'; 125 | 126 | // Sets the language to the default 'en-US'. This can be changed with annyang.setLanguage() 127 | recognition.lang = 'en-US'; 128 | 129 | recognition.onstart = function() { invokeCallbacks(callbacks.start); }; 130 | 131 | recognition.onerror = function(event) { 132 | invokeCallbacks(callbacks.error); 133 | switch (event.error) { 134 | case 'network': 135 | invokeCallbacks(callbacks.errorNetwork); 136 | break; 137 | case 'not-allowed': 138 | case 'service-not-allowed': 139 | // if permission to use the mic is denied, turn off auto-restart 140 | autoRestart = false; 141 | // determine if permission was denied by user or automatically. 142 | if (new Date().getTime()-lastStartedAt < 200) { 143 | invokeCallbacks(callbacks.errorPermissionBlocked); 144 | } else { 145 | invokeCallbacks(callbacks.errorPermissionDenied); 146 | } 147 | break; 148 | } 149 | }; 150 | 151 | recognition.onend = function() { 152 | invokeCallbacks(callbacks.end); 153 | // annyang will auto restart if it is closed automatically and not by user action. 154 | if (autoRestart) { 155 | // play nicely with the browser, and never restart annyang automatically more than once per second 156 | var timeSinceLastStart = new Date().getTime()-lastStartedAt; 157 | if (timeSinceLastStart < 1000) { 158 | setTimeout(root.annyang.start, 1000-timeSinceLastStart); 159 | } else { 160 | root.annyang.start(); 161 | } 162 | } 163 | }; 164 | 165 | recognition.onresult = function(event) { 166 | invokeCallbacks(callbacks.result); 167 | var results = event.results[event.resultIndex]; 168 | var commandText; 169 | // go over each of the 5 results and alternative results received (we've set maxAlternatives to 5 above) 170 | for (var i = 0; iLast voice command: ' + commandText + ''); 176 | 177 | if (debugState) { 178 | // document.getElementById('speechActivity').innerHTML = commandText; 179 | root.console.log('Speech recognized: %c'+commandText, debugStyle); 180 | } 181 | 182 | // try and match recognized text to one of the commands on the list 183 | for (var j = 0, l = commandsList.length; j < l; j++) { 184 | var result = commandsList[j].command.exec(commandText); 185 | if (result) { 186 | var parameters = result.slice(1); 187 | if (debugState) { 188 | root.console.log('command matched: %c'+commandsList[j].originalPhrase, debugStyle); 189 | if (parameters.length) { 190 | root.console.log('with parameters', parameters); 191 | } 192 | } 193 | // execute the matched command 194 | commandsList[j].callback.apply(this, parameters); 195 | invokeCallbacks(callbacks.resultMatch); 196 | return true; 197 | } 198 | } 199 | } 200 | invokeCallbacks(callbacks.resultNoMatch); 201 | return false; 202 | }; 203 | 204 | // build commands list 205 | if (resetCommands) { 206 | commandsList = []; 207 | } 208 | if (commands.length) { 209 | this.addCommands(commands); 210 | } 211 | }, 212 | 213 | /** 214 | * Start listening. 215 | * It's a good idea to call this after adding some commands first, but not mandatory. 216 | * 217 | * Receives an optional options object which currently only supports one option: 218 | * - `autoRestart` (Boolean, default: true) Should annyang restart itself if it is closed indirectly, because of silence or window conflicts? 219 | * 220 | * ### Examples: 221 | * // Start listening, but don't restart automatically 222 | * annyang.start({ autoRestart: false }); 223 | * 224 | * @param {Object} [options] - Optional options. 225 | * @method start 226 | */ 227 | start: function(options) { 228 | initIfNeeded(); 229 | options = options || {}; 230 | if (options.autoRestart !== undefined) { 231 | autoRestart = !!options.autoRestart; 232 | } else { 233 | autoRestart = true; 234 | } 235 | lastStartedAt = new Date().getTime(); 236 | recognition.start(); 237 | }, 238 | 239 | /** 240 | * Stop listening. 241 | * 242 | * @method abort 243 | */ 244 | abort: function() { 245 | autoRestart = false; 246 | if (isInitialized) { 247 | recognition.abort(); 248 | } 249 | }, 250 | 251 | /** 252 | * Turn on output of debug messages to the console. Ugly, but super-handy! 253 | * 254 | * @param {Boolean} [newState=true] - Turn on/off debug messages 255 | * @method debug 256 | */ 257 | debug: function(newState) { 258 | if (arguments.length > 0) { 259 | debugState = !!newState; 260 | } else { 261 | debugState = true; 262 | } 263 | }, 264 | 265 | /** 266 | * Set the language the user will speak in. If this method is not called, defaults to 'en-US'. 267 | * 268 | * @param {String} language - The language (locale) 269 | * @method setLanguage 270 | * @see [Languages](#languages) 271 | */ 272 | setLanguage: function(language) { 273 | initIfNeeded(); 274 | recognition.lang = language; 275 | }, 276 | 277 | /** 278 | * Add commands that annyang will respond to. Similar in syntax to init(), but doesn't remove existing commands. 279 | * 280 | * ### Examples: 281 | * 282 | * var commands = {'hello :name': helloFunction, 'howdy': helloFunction}; 283 | * var commands2 = {'hi': helloFunction}; 284 | * 285 | * annyang.addCommands(commands); 286 | * annyang.addCommands(commands2); 287 | * // annyang will now listen to all three commands 288 | * 289 | * 290 | * @param {Object} commands - Commands that annyang should listen to 291 | * @method addCommands 292 | * @see [Commands Object](#commands-object) 293 | */ 294 | addCommands: function(commands) { 295 | var cb, 296 | command; 297 | 298 | initIfNeeded(); 299 | 300 | for (var phrase in commands) { 301 | if (commands.hasOwnProperty(phrase)) { 302 | cb = root[commands[phrase]] || commands[phrase]; 303 | if (typeof cb !== 'function') { 304 | continue; 305 | } 306 | //convert command to regex 307 | command = commandToRegExp(phrase); 308 | 309 | commandsList.push({ command: command, callback: cb, originalPhrase: phrase }); 310 | } 311 | } 312 | if (debugState) { 313 | root.console.log('Commands successfully loaded: %c'+commandsList.length, debugStyle); 314 | } 315 | }, 316 | 317 | /** 318 | * Remove existing commands. Called with a single phrase, array of phrases, or methodically. Pass no params to remove all commands. 319 | * 320 | * ### Examples: 321 | * 322 | * var commands = {'hello': helloFunction, 'howdy': helloFunction, 'hi': helloFunction}; 323 | * 324 | * // Remove all existing commands 325 | * annyang.removeCommands(); 326 | * 327 | * // Add some commands 328 | * annyang.addCommands(commands); 329 | * 330 | * // Don't respond to hello 331 | * annyang.removeCommands('hello'); 332 | * 333 | * // Don't respond to howdy or hi 334 | * annyang.removeCommands(['howdy', 'hi']); 335 | * 336 | * @param {String|Array|Undefined} [commandsToRemove] - Commands to remove 337 | * @method removeCommands 338 | */ 339 | removeCommands: function(commandsToRemove) { 340 | if (commandsToRemove === undefined) { 341 | commandsList = []; 342 | return; 343 | } 344 | commandsToRemove = Array.isArray(commandsToRemove) ? commandsToRemove : [commandsToRemove]; 345 | commandsList = commandsList.filter(function(command) { 346 | for (var i = 0; i 404 | * var commands = { 405 | * // annyang will capture anything after a splat (*) and pass it to the function. 406 | * // e.g. saying "Show me Batman and Robin" will call showFlickr('Batman and Robin'); 407 | * 'show me *term': showFlickr, 408 | * 409 | * // A named variable is a one word variable, that can fit anywhere in your command. 410 | * // e.g. saying "calculate October stats" will call calculateStats('October'); 411 | * 'calculate :month stats': calculateStats, 412 | * 413 | * // By defining a part of the following command as optional, annyang will respond 414 | * // to both: "say hello to my little friend" as well as "say hello friend" 415 | * 'say hello (to my little) friend': greeting 416 | * }; 417 | * 418 | * var showFlickr = function(term) { 419 | * var url = 'http://api.flickr.com/services/rest/?tags='+tag; 420 | * $.getJSON(url); 421 | * } 422 | * 423 | * var calculateStats = function(month) { 424 | * $('#stats').text('Statistics for '+month); 425 | * } 426 | * 427 | * var greeting = function() { 428 | * $('#greeting').text('Hello!'); 429 | * } 430 | * 431 | * 432 | * ## Languages 433 | * 434 | * While there isn't an official list of supported languages (cultures? locales?), here is a list based on [anecdotal evidence](http://stackoverflow.com/a/14302134/338039). 435 | * 436 | * * Afrikaans `af` 437 | * * Basque `eu` 438 | * * Bulgarian `bg` 439 | * * Catalan `ca` 440 | * * Arabic (Egypt) `ar-EG` 441 | * * Arabic (Jordan) `ar-JO` 442 | * * Arabic (Kuwait) `ar-KW` 443 | * * Arabic (Lebanon) `ar-LB` 444 | * * Arabic (Qatar) `ar-QA` 445 | * * Arabic (UAE) `ar-AE` 446 | * * Arabic (Morocco) `ar-MA` 447 | * * Arabic (Iraq) `ar-IQ` 448 | * * Arabic (Algeria) `ar-DZ` 449 | * * Arabic (Bahrain) `ar-BH` 450 | * * Arabic (Lybia) `ar-LY` 451 | * * Arabic (Oman) `ar-OM` 452 | * * Arabic (Saudi Arabia) `ar-SA` 453 | * * Arabic (Tunisia) `ar-TN` 454 | * * Arabic (Yemen) `ar-YE` 455 | * * Czech `cs` 456 | * * Dutch `nl-NL` 457 | * * English (Australia) `en-AU` 458 | * * English (Canada) `en-CA` 459 | * * English (India) `en-IN` 460 | * * English (New Zealand) `en-NZ` 461 | * * English (South Africa) `en-ZA` 462 | * * English(UK) `en-GB` 463 | * * English(US) `en-US` 464 | * * Finnish `fi` 465 | * * French `fr-FR` 466 | * * Galician `gl` 467 | * * German `de-DE` 468 | * * Hebrew `he` 469 | * * Hungarian `hu` 470 | * * Icelandic `is` 471 | * * Italian `it-IT` 472 | * * Indonesian `id` 473 | * * Japanese `ja` 474 | * * Korean `ko` 475 | * * Latin `la` 476 | * * Mandarin Chinese `zh-CN` 477 | * * Traditional Taiwan `zh-TW` 478 | * * Simplified China zh-CN `?` 479 | * * Simplified Hong Kong `zh-HK` 480 | * * Yue Chinese (Traditional Hong Kong) `zh-yue` 481 | * * Malaysian `ms-MY` 482 | * * Norwegian `no-NO` 483 | * * Polish `pl` 484 | * * Pig Latin `xx-piglatin` 485 | * * Portuguese `pt-PT` 486 | * * Portuguese (Brasil) `pt-BR` 487 | * * Romanian `ro-RO` 488 | * * Russian `ru` 489 | * * Serbian `sr-SP` 490 | * * Slovak `sk` 491 | * * Spanish (Argentina) `es-AR` 492 | * * Spanish (Bolivia) `es-BO` 493 | * * Spanish (Chile) `es-CL` 494 | * * Spanish (Colombia) `es-CO` 495 | * * Spanish (Costa Rica) `es-CR` 496 | * * Spanish (Dominican Republic) `es-DO` 497 | * * Spanish (Ecuador) `es-EC` 498 | * * Spanish (El Salvador) `es-SV` 499 | * * Spanish (Guatemala) `es-GT` 500 | * * Spanish (Honduras) `es-HN` 501 | * * Spanish (Mexico) `es-MX` 502 | * * Spanish (Nicaragua) `es-NI` 503 | * * Spanish (Panama) `es-PA` 504 | * * Spanish (Paraguay) `es-PY` 505 | * * Spanish (Peru) `es-PE` 506 | * * Spanish (Puerto Rico) `es-PR` 507 | * * Spanish (Spain) `es-ES` 508 | * * Spanish (US) `es-US` 509 | * * Spanish (Uruguay) `es-UY` 510 | * * Spanish (Venezuela) `es-VE` 511 | * * Swedish `sv-SE` 512 | * * Turkish `tr` 513 | * * Zulu `zu` 514 | * 515 | * ## Developing 516 | * 517 | * Prerequisities: node.js 518 | * 519 | * First, install dependencies in your local annyang copy: 520 | * 521 | * npm install 522 | * 523 | * Make sure to run the default grunt task after each change to annyang.js. This can also be done automatically by running: 524 | * 525 | * grunt watch 526 | * 527 | * You can also run a local server for testing your work with: 528 | * 529 | * grunt dev 530 | * 531 | * Point your browser to `https://localhost:8443/demo/` to see the demo page. 532 | * Since it's using self-signed certificate, you might need to click *"Proceed Anyway"*. 533 | * 534 | */ 535 | -------------------------------------------------------------------------------- /apps/website/index.js: -------------------------------------------------------------------------------- 1 | var big = require('../../index'); 2 | var http = require('resource-http'); 3 | var mesh = require('resource-mesh'); 4 | var debug = require('debug')('big::website'); 5 | 6 | module['exports'] = function website (opts, cb) { 7 | opts = opts || {}; 8 | opts.port = opts.port || 8888; 9 | big.start(opts, function(err, server){ 10 | var site = opts.site || {}; 11 | site.port = site.port || 9999; 12 | site.root = site.root || process.cwd(); 13 | site.view = site.view || process.cwd() + "/view"; 14 | site.domain = site.domain || "dev.marak.com"; 15 | 16 | http.listen(site, function(err, httpServer){ 17 | if (err) { 18 | throw err; 19 | } 20 | debug('Started'); 21 | var addr = httpServer.server.address(); 22 | 23 | mesh.emitter.on('hello', function (data) { 24 | console.log('hello', data) 25 | }); 26 | big.app = httpServer; 27 | // after the http static server has started, 28 | // emit an event on the mesh registering it if a loadbalancer is available 29 | mesh.emitter.emit('loadbalancer::addSite', { 30 | domain: site.domain, 31 | host: addr.address, 32 | port: addr.port 33 | }); 34 | cb(null, httpServer); 35 | }); 36 | 37 | }); 38 | return big; 39 | }; -------------------------------------------------------------------------------- /apps/website/public/css/styles.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigcompany/big/7ab6649dbef2d79722d3b4d538c26db6a200229c/apps/website/public/css/styles.css -------------------------------------------------------------------------------- /apps/website/public/index.html: -------------------------------------------------------------------------------- 1 | This is the website. -------------------------------------------------------------------------------- /bin/big: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var minimist = require('minimist'); 4 | 5 | var argv = require('minimist')(process.argv.slice(2)); 6 | 7 | var big = require('../'); 8 | big.spawn(argv._[0], argv); -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var big = {}; 2 | module['exports'] = big; 3 | 4 | var resource = big.resource = require('resource'); 5 | 6 | big.define = resource.define; 7 | big.emit = resource.emit; 8 | big.on = resource.on; 9 | big.onAny = resource.onAny; 10 | 11 | big.start = require('./lib/start'); 12 | big.spawn = require('./lib/spawn'); -------------------------------------------------------------------------------- /lib/spawn.js: -------------------------------------------------------------------------------- 1 | module['exports'] = function spawn (app, opts, cb) { 2 | cb = cb || function (err, res) { 3 | if (err) { 4 | console.log('An error has occurred in ' + app) 5 | console.log('big.spawn about to throw!'); 6 | throw err; 7 | } 8 | }; 9 | opts = opts || {}; 10 | 11 | // shortcut names for apps 12 | if (app === "lb") { 13 | app = "load-balancer"; 14 | } 15 | 16 | if (app === "w" || app === "web") { 17 | app = "website"; 18 | } 19 | 20 | 21 | var _app = require('../apps/' + app); 22 | _app(opts, cb); 23 | }; -------------------------------------------------------------------------------- /lib/start.js: -------------------------------------------------------------------------------- 1 | var mesh = require('resource-mesh'); 2 | var http = require('resource-http'); 3 | var debug = require('debug')('big::start'); 4 | 5 | module['exports'] = function (opts, callback) { 6 | opts = opts || {}; 7 | mesh.start(opts, function(err, server){ 8 | if(err) { 9 | throw err; 10 | } 11 | debug('Big has started'); 12 | callback(null, server); 13 | }); 14 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "big", 3 | "version": "0.5.1", 4 | "scripts": { 5 | "start": "node ./bin/big" 6 | }, 7 | "repository" : { 8 | "type" : "git", 9 | "url" : "http://github.com/bigcompany/big.git" 10 | }, 11 | "dependencies": { 12 | "resource": "0.5.x", 13 | "minimist": "*", 14 | "resource-http": "0.5.x", 15 | "resource-mesh": "0.5.x", 16 | "debug": "*" 17 | 18 | }, 19 | "main": "./lib", 20 | "bin": { 21 | "big": "./bin/big" 22 | }, 23 | "license": "MIT" 24 | } 25 | --------------------------------------------------------------------------------