<commit_before>'use strict'
const express = require('express')
const bodyParser = require('body-parser')
const request = require('request')
const config = require('config')
const send = require('./send')
const Datastore = require('nedb')
const users = new Datastore({ filename: './data/users', autoload: true })
const eventSpeech = require('./speech')
const app = express()
const verifyToken = config.get('validationToken')
const mapsApiKey = config.get('mapsApiKey')

app.use(bodyParser.json())
app.set('json spaces', 2)

const Ranka = require('ranka')
const ranka = new Ranka({
  validationToken: config.get('validationToken'),
  pageAccessToken: config.get('pageAccessToken')
})
app.use('/webuild/bot/webhook', Ranka.router({
  ranka: ranka
}))

ranka.on('message', (req, res) => {
  // users.findOne({ id: recipientId }, function (err, doc) {
  //   if (doc === null) {
  //     users.insert({ id: recipientId })
  //   }
  // })
  const eventRequest = eventSpeech.getParsedRequest(req.body.message.text)
  if (eventRequest.mode === 'event') {
    upcomingEvent(req.body.sender.id, eventRequest, req, res)
  } else if (eventRequest.mode === 'repo') {
    latestRepo(req.body.sender.id, req, res)
  } else {
    req
      .sendText("Sorry, I don't understand. Do you like to send a location instead?")
      .send({
        text: 'Please share your location:',
        quick_replies: [
          {
            content_type: 'location'
          }
        ]
      }).exec()
  }
})
// app.get('/*', (req, res) => {
//   const q = req.query
//   // If the token doesn't match...
//   if (q['hub.verify_token'] !== verifyToken) {
//     res.sendStatus(401)
//   }
//   if (q['hub.mode'] === 'subscribe') {
//     res.send(q['hub.challenge'])
//   } else {
//     res.send(req.headers)
//   }
// })

/**
 * Fetches the latest 5 repositories
 * @param  {[type]} recipientId [description]
 */
function latestRepo (recipientId, req, res) {
  request('https://webuild.sg/api/v1/repos?n=5', (err, resp, body) => {
    if (!err) {
      const parsed = JSON.parse(body)
      parsed.repos.forEach((repo) => {
        res
          .sendText(`${repo.owner.login}/${repo.name}
${repo.html_url}
          `)
          .exec()
      })
    }
  })
}

function generateFbPayload (events) {
  const nomap = 'https://raw.githubusercontent.com/webuildsg/bot/master/no-map.png'
  return events.map((event) => {
    let payload = {
      title: `${event.name}`,
      'image_url': nomap,
      'subtitle': `${event.group_name} | ${event.formatted_time}`,
      'buttons': [
        {
          'type': 'web_url',
          'url': event.url,
          'title': 'View Event'
        },
        {
          'type': 'web_url',
          'url': event.group_url,
          'title': 'View Group'
        }
      ]
    }
    if (event.latitude && event.longitude) {
      payload.image_url = `https://maps.googleapis.com/maps/api/staticmap?zoom=13&size=500x500&maptype=roadmap&markers=color:red%7C${event.latitude},${event.longitude}&key=${mapsApiKey}`
      payload.buttons.unshift({
        'type': 'web_url',
        'url': `https://maps.google.com/maps?f=q&hl=en&q=${event.latitude},${event.longitude}`,
        'title': 'Get Directions'
      })
    }
    return payload
  })
}

function sendEvent (recipientId, events, req, res) {
  const eventCount = +events.meta.total_events
  if (eventCount === 0) {
    res
      .sendText('No events found :( Try another day')
      .exec()
  } else if (eventCount > 0) {
    const eventsDisplay = events.meta.total_events === 1 ? 'event' : 'events'
    var eventElements = generateFbPayload(events.events)
    res
      .sendText(`We found you ${eventCount} cool ${eventsDisplay} for you to join!`)
      .typing()
      .wait(1000)
      .sendText(`Did you say "${req.body.message.text}"?`)
      .sendAttachmentWithPayload('template', {
        template_type: 'generic',
        elements: eventElements
      })
      .exec()
  }
}

/**
 * Fetches 5 upcoming events or by event date
 * @param  {[type]} recipientId [description]
 */
function upcomingEvent (recipientId, eventRequest, req, res) {
  if (eventRequest.dates) {
    request(`https://webuild.sg/api/v1/check/${eventRequest.dates.year}-${eventRequest.dates.month + 1}-${eventRequest.dates.day}?n=5`, (err, resp, body) => {
      if (!err) {
        const parsed = JSON.parse(body)
        sendEvent(recipientId, parsed, req, res)
      }
    })
  } else {
    request('https://webuild.sg/api/v1/events?n=5', (err, resp, body) => {
      if (!err) {
        const parsed = JSON.parse(body)
        sendEvent(recipientId, parsed, req, res)
      }
    })
  }
}

app.listen(3124, () => {
  console.log('Example app listening on port 3124!')
})
<commit_msg>spelling<commit_after>'use strict'
const express = require('express')
const bodyParser = require('body-parser')
const request = require('request')
const config = require('config')
const send = require('./send')
const Datastore = require('nedb')
const users = new Datastore({ filename: './data/users', autoload: true })
const eventSpeech = require('./speech')
const app = express()
const verifyToken = config.get('validationToken')
const mapsApiKey = config.get('mapsApiKey')

app.use(bodyParser.json())
app.set('json spaces', 2)

const Ranka = require('ranka')
const ranka = new Ranka({
  validationToken: config.get('validationToken'),
  pageAccessToken: config.get('pageAccessToken')
})
app.use('/webuild/bot/webhook', Ranka.router({
  ranka: ranka
}))

ranka.on('message', (req, res) => {
  // users.findOne({ id: recipientId }, function (err, doc) {
  //   if (doc === null) {
  //     users.insert({ id: recipientId })
  //   }
  // })
  const eventRequest = eventSpeech.getParsedRequest(req.body.message.text)
  if (eventRequest.mode === 'event') {
    upcomingEvent(req.body.sender.id, eventRequest, req, res)
  } else if (eventRequest.mode === 'repo') {
    latestRepo(req.body.sender.id, req, res)
  } else {
    res
      .sendText("Sorry, I don't understand. Do you like to send a location instead?")
      .send({
        text: 'Please share your location:',
        quick_replies: [
          {
            content_type: 'location'
          }
        ]
      }).exec()
  }
})
// app.get('/*', (req, res) => {
//   const q = req.query
//   // If the token doesn't match...
//   if (q['hub.verify_token'] !== verifyToken) {
//     res.sendStatus(401)
//   }
//   if (q['hub.mode'] === 'subscribe') {
//     res.send(q['hub.challenge'])
//   } else {
//     res.send(req.headers)
//   }
// })

/**
 * Fetches the latest 5 repositories
 * @param  {[type]} recipientId [description]
 */
function latestRepo (recipientId, req, res) {
  request('https://webuild.sg/api/v1/repos?n=5', (err, resp, body) => {
    if (!err) {
      const parsed = JSON.parse(body)
      parsed.repos.forEach((repo) => {
        res
          .sendText(`${repo.owner.login}/${repo.name}
${repo.html_url}
          `)
          .exec()
      })
    }
  })
}

function generateFbPayload (events) {
  const nomap = 'https://raw.githubusercontent.com/webuildsg/bot/master/no-map.png'
  return events.map((event) => {
    let payload = {
      title: `${event.name}`,
      'image_url': nomap,
      'subtitle': `${event.group_name} | ${event.formatted_time}`,
      'buttons': [
        {
          'type': 'web_url',
          'url': event.url,
          'title': 'View Event'
        },
        {
          'type': 'web_url',
          'url': event.group_url,
          'title': 'View Group'
        }
      ]
    }
    if (event.latitude && event.longitude) {
      payload.image_url = `https://maps.googleapis.com/maps/api/staticmap?zoom=13&size=500x500&maptype=roadmap&markers=color:red%7C${event.latitude},${event.longitude}&key=${mapsApiKey}`
      payload.buttons.unshift({
        'type': 'web_url',
        'url': `https://maps.google.com/maps?f=q&hl=en&q=${event.latitude},${event.longitude}`,
        'title': 'Get Directions'
      })
    }
    return payload
  })
}

function sendEvent (recipientId, events, req, res) {
  const eventCount = +events.meta.total_events
  if (eventCount === 0) {
    res
      .sendText('No events found :( Try another day')
      .exec()
  } else if (eventCount > 0) {
    const eventsDisplay = events.meta.total_events === 1 ? 'event' : 'events'
    var eventElements = generateFbPayload(events.events)
    res
      .sendText(`We found you ${eventCount} cool ${eventsDisplay} for you to join!`)
      .typing()
      .wait(1000)
      .sendText(`Did you say "${req.body.message.text}"?`)
      .sendAttachmentWithPayload('template', {
        template_type: 'generic',
        elements: eventElements
      })
      .exec()
  }
}

/**
 * Fetches 5 upcoming events or by event date
 * @param  {[type]} recipientId [description]
 */
function upcomingEvent (recipientId, eventRequest, req, res) {
  if (eventRequest.dates) {
    request(`https://webuild.sg/api/v1/check/${eventRequest.dates.year}-${eventRequest.dates.month + 1}-${eventRequest.dates.day}?n=5`, (err, resp, body) => {
      if (!err) {
        const parsed = JSON.parse(body)
        sendEvent(recipientId, parsed, req, res)
      }
    })
  } else {
    request('https://webuild.sg/api/v1/events?n=5', (err, resp, body) => {
      if (!err) {
        const parsed = JSON.parse(body)
        sendEvent(recipientId, parsed, req, res)
      }
    })
  }
}

app.listen(3124, () => {
  console.log('Example app listening on port 3124!')
})
<|endoftext|>


<commit_before>var toString = Function.prototype.apply.bind(Object.prototype.toString);

var regexSignature  = toString(/test/);
var dateSignature   = toString(new Date());
var arraySignature  = toString([]);
var objectSignature = toString({});
var errorSignature  = toString(new Error());

/**
 * Check if input is undefined
 *
 * @param {*} item - Item to be tested for undefined
 * @returns {boolean}
 */
function isUndefined(item) {
  return item === (void 0);
}

/**
 * Check if input is null
 *
 * @param {*} item - Item to be tested for null
 * @returns {boolean}
 */
function isNull(item) {
  return item === null;
}

/**
 * Check if input is a regulat expression
 *
 * @param {*} item - Item to check for regular expression
 * @returns {boolean}
 */
function isRegex(item) {
  return !!item && toString(item) === regexSignature;
}

/**
 * Check if input is an array
 *
 * @param {*} item - Item to be tested for Array
 * @returns {boolean}
 */
var isArray = (function() {
  if (Array.isArray) {
    return Array.isArray;
  }

  return function(item) {
    return toString(item) === arraySignature;
  };
})();

/**
 * Check if input is a function
 *
 * @param {*} item - Item to be tested for function
 * @returns {boolean}
 */
function isFunction(item) {
  return typeof item === 'function';
}

/**
 * Check if input is a string
 *
 * @param {*} item - Item to check for string
 * @returns {boolean}
 */
function isString(item) {
  return typeof item === 'string';
}

/**
 * Check if input is an object. Objects are:
 *  - literal object, object instances, arrays, null
 *
 * @param {*} item - Item to check for object
 * @returns {boolean}
 */
function isObject(item) {
  return typeof item === 'object';
}

/**
 * Check if input is a Date
 *
 * @param {*} item - Item to be tested for Date
 * @returns {boolean}
 */
function isDate(item) {
  return toString(item) === dateSignature;
}

/**
 * Check if item is an object literal - plain object.
 *
 * @param {*} item - Item to check for object literal
 * @returns {boolean}
 */
function isPlainObject(item) {
  return toString(item) === objectSignature;
}

/**
 * Check if input is an error
 *
 * @param {*} item - Item to check for error
 * @returns {boolean}
 */
function isError(item) {
  return toString(item) === errorSignature || item instanceof Error;
}

/**
 * Extract the type name. This uses Object.prototype.toString
 * to get the type name.
 *
 * @param {*} item - Item to get the type for
 * @returns {string} type of the object
 */
function typeName(item) {
  if (isNull(item)) {
    return 'null';
  }
  else if (isUndefined(item)) {
    return 'undefined';
  }

  return /\[.+ ([^\]]+)/.exec(toString(item))[1].toLowerCase();
}

module.exports = {
  isNull: isNull,
  isUndefined: isUndefined,
  isRegex: isRegex,
  isArray: isArray,
  isError: isError,
  isString: isString,
  isObject: isObject,
  isPlainObject: isPlainObject,
  isFunction: isFunction,
  isDate: isDate,
  typeName: typeName,
  toString: toString
};
<commit_msg>Added ability to detect buffer type<commit_after>var toString = Function.prototype.apply.bind(Object.prototype.toString);

var bufferSignature = typeof Buffer !== 'undefined' ? toString(Buffer) : "[object Uint8Array]";
var regexSignature  = toString(/test/);
var dateSignature   = toString(new Date());
var arraySignature  = toString([]);
var objectSignature = toString({});
var errorSignature  = toString(new Error());

/**
 * Checks is the input is a Buffer
 */
function isBuffer(item) {
  return toString(item) === bufferSignature;
}

/**
 * Check if input is undefined
 *
 * @param {*} item - Item to be tested for undefined
 * @returns {boolean}
 */
function isUndefined(item) {
  return item === (void 0);
}

/**
 * Check if input is null
 *
 * @param {*} item - Item to be tested for null
 * @returns {boolean}
 */
function isNull(item) {
  return item === null;
}

/**
 * Check if input is a regulat expression
 *
 * @param {*} item - Item to check for regular expression
 * @returns {boolean}
 */
function isRegex(item) {
  return !!item && toString(item) === regexSignature;
}

/**
 * Check if input is an array
 *
 * @param {*} item - Item to be tested for Array
 * @returns {boolean}
 */
var isArray = (function() {
  if (Array.isArray) {
    return Array.isArray;
  }

  return function(item) {
    return toString(item) === arraySignature;
  };
})();

/**
 * Check if input is a function
 *
 * @param {*} item - Item to be tested for function
 * @returns {boolean}
 */
function isFunction(item) {
  return typeof item === 'function';
}

/**
 * Check if input is a string
 *
 * @param {*} item - Item to check for string
 * @returns {boolean}
 */
function isString(item) {
  return typeof item === 'string';
}

/**
 * Check if input is an object. Objects are:
 *  - literal object, object instances, arrays, null
 *
 * @param {*} item - Item to check for object
 * @returns {boolean}
 */
function isObject(item) {
  return typeof item === 'object';
}

/**
 * Check if input is a Date
 *
 * @param {*} item - Item to be tested for Date
 * @returns {boolean}
 */
function isDate(item) {
  return toString(item) === dateSignature;
}

/**
 * Check if item is an object literal - plain object.
 *
 * @param {*} item - Item to check for object literal
 * @returns {boolean}
 */
function isPlainObject(item) {
  return toString(item) === objectSignature;
}

/**
 * Check if input is an error
 *
 * @param {*} item - Item to check for error
 * @returns {boolean}
 */
function isError(item) {
  return toString(item) === errorSignature || item instanceof Error;
}

/**
 * Extract the type name. This uses Object.prototype.toString
 * to get the type name.
 *
 * @param {*} item - Item to get the type for
 * @returns {string} type of the object
 */
function typeName(item) {
  if (isNull(item)) {
    return 'null';
  }
  else if (isUndefined(item)) {
    return 'undefined';
  }

  return /\[.+ ([^\]]+)/.exec(toString(item))[1].toLowerCase();
}

module.exports = {
  isNull: isNull,
  isUndefined: isUndefined,
  isRegex: isRegex,
  isArray: isArray,
  isError: isError,
  isString: isString,
  isObject: isObject,
  isPlainObject: isPlainObject,
  isFunction: isFunction,
  isDate: isDate,
  typeName: typeName,
  toString: toString
};
<|endoftext|>


<commit_before>import pathExists from "path-exists";
import logger from "./logger";
import mkdirp from "mkdirp";
import rimraf from "rimraf";
import fs from "fs";

export default class FileSystemUtilities {
  @logger.logifySync
  static mkdirSync(filePath) {
    fs.mkdirSync(filePath);
  }

  @logger.logifyAsync
  static mkdirp(filePath, callback) {
    mkdirp(filePath, callback);
  }

  @logger.logifyAsync
  static readdirSync(filePath) {
    return fs.readdirSync(filePath);
  }

  @logger.logifySync
  static existsSync(filePath) {
    return pathExists.sync(filePath);
  }

  @logger.logifyAsync
  static writeFile(filePath, fileContents, callback) {
    fs.writeFile(filePath, fileContents + "\n", callback);
  }

  @logger.logifySync
  static writeFileSync(filePath, fileContents) {
    fs.writeFileSync(filePath, fileContents + "\n");
  }

  @logger.logifySync
  static readFileSync(filePath) {
    return fs.readFileSync(filePath).toString().trim();
  }

  @logger.logifyAsync
  static rimraf(filePath, callback) {
    rimraf(filePath, callback);
  }

  @logger.logifySync
  static unlinkSync(filePath) {
    fs.unlink(filePath);
  }
}
<commit_msg>Ensure files end with newlines properly (#113)<commit_after>import pathExists from "path-exists";
import logger from "./logger";
import mkdirp from "mkdirp";
import rimraf from "rimraf";
import fs from "fs";

var ENDS_WITH_NEW_LINE = /\n$/;

function ensureEndsWithNewLine(string) {
  return ENDS_WITH_NEW_LINE.test(string) ? string : string + "\n";
}

export default class FileSystemUtilities {
  @logger.logifySync
  static mkdirSync(filePath) {
    fs.mkdirSync(filePath);
  }

  @logger.logifyAsync
  static mkdirp(filePath, callback) {
    mkdirp(filePath, callback);
  }

  @logger.logifyAsync
  static readdirSync(filePath) {
    return fs.readdirSync(filePath);
  }

  @logger.logifySync
  static existsSync(filePath) {
    return pathExists.sync(filePath);
  }

  @logger.logifyAsync
  static writeFile(filePath, fileContents, callback) {
    fs.writeFile(filePath, ensureEndsWithNewLine(fileContents), callback);
  }

  @logger.logifySync
  static writeFileSync(filePath, fileContents) {
    fs.writeFileSync(filePath, ensureEndsWithNewLine(fileContents));
  }

  @logger.logifySync
  static readFileSync(filePath) {
    return fs.readFileSync(filePath).toString().trim();
  }

  @logger.logifyAsync
  static rimraf(filePath, callback) {
    rimraf(filePath, callback);
  }

  @logger.logifySync
  static unlinkSync(filePath) {
    fs.unlink(filePath);
  }
}
<|endoftext|>


<commit_before>var Logdown = (function() {
  'use strict'

  var instances = []
  var lastUsedColorIndex
  var nextColorIndex
  // Solarized accent colors http://ethanschoonover.com/solarized
  var colors = [
    '#B58900',
    '#CB4B16',
    '#DC322F',
    '#D33682',
    '#6C71C4',
    '#268BD2',
    '#2AA198',
    '#859900'
  ]
  var disabledInstancesRegExps = []
  var enabledInstancesRegExps = [] // RegExp that matches nothing

  function Logdown(opts) {
    // enforces new
    if (!(this instanceof Logdown)) {
      return new Logdown(opts)
    }

    //
    opts = opts || {}
    this.markdown = opts.markdown || true
    this.prefix = opts.prefix || ''

    //
    instances.push(this)

    nextColorIndex = getNextColorIndex(lastUsedColorIndex, colors)
    this.prefixColor = colors[nextColorIndex]
    lastUsedColorIndex = nextColorIndex

    return this
  }

  // Static
  // ------

  Logdown.enable = function(str) {
    var regExp = prepareRegExpForPrefixSearch(str)
    enabledInstancesRegExps.push(regExp)
  }

  Logdown.disable = function(str) {
    var regExp = prepareRegExpForPrefixSearch(str)
    disabledInstancesRegExps.push(regExp)
  }

  // Public
  // ------

  Logdown.prototype.log = function(text) {
    var preparedOutput

    if (isDisabled(this)) {
      return
    }

    preparedOutput = prepareOutput(text, this)

    console.log.apply(
      console,
      [preparedOutput.parsedText].concat(preparedOutput.styles)
    )
  }

  Logdown.prototype.info = function(text) {
    var preparedOutput

    if (isDisabled(this)) {
      return
    }

    preparedOutput = prepareOutput(text, this)

    console.info.apply(
      console,
      [preparedOutput.parsedText].concat(preparedOutput.styles)
    )
  }

  Logdown.prototype.error = function(text) {
    var preparedOutput

    if (isDisabled(this)) {
      return
    }

    preparedOutput = prepareOutput(text, this)

    console.error.apply(
      console,
      [preparedOutput.parsedText].concat(preparedOutput.styles)
    )
  }

  Logdown.prototype.warn = function(text) {
    var preparedOutput

    if (isDisabled(this)) {
      return
    }

    preparedOutput = prepareOutput(text, this)

    console.warn.apply(
      console,
      [preparedOutput.parsedText].concat(preparedOutput.styles)
    )
  }

  // Private
  // -------

  function parseMarkdown(text) {
    var styles = []
    var match = getNextMatch(text)

    while (match) {
      text = text.replace(match.rule.regexp, match.rule.replacer)
      styles.push(match.rule.style)
      styles.push('')

      match = getNextMatch(text)
    }

    return {text: text, styles: styles}
  }

  function getNextMatch(text) {
    var matches = []
    var rules = [
      {
        regexp: /\*([^\*]+)\*/,
        replacer: function(match, submatch1) {
          return '%c' + submatch1 + '%c'
        },
        style: 'font-weight: bold;'
      },
      {
        regexp: /\_([^\_]+)\_/,
        replacer: function(match, submatch1) {
          return '%c' + submatch1 + '%c'
        },
        style: 'font-style: italic;'
      },
      {
        regexp: /\`([^\`]+)\`/,
        replacer: function(match, submatch1) {
          return "%c" + submatch1 + "%c";
        },
        style:
          'background: #FDF6E3;' +
          'color: #586E75;' +
          'padding: 1px 5px;' +
          'border-radius: 4px;'
      }
    ]

    //
    rules.forEach(function(rule) {
      var match = text.match(rule.regexp)
      if (match) {
        matches.push({
          rule: rule,
          match: match
        })
      }
    })
    if (matches.length === 0) {
      return null;
    }

    //
    // matches.sort(function(a, b) {
    //   return a.match.index - b.match.index
    // })

    return matches[0]
  }

  function prepareOutput(text, instance) {
    var parsedMarkdown
    var parsedText
    var styles

    if (instance.markdown) {
      parsedMarkdown = parseMarkdown(text)
      parsedText = parsedMarkdown.text
      styles = parsedMarkdown.styles
    }

    parsedText = parsedText || text
    styles = styles || []

    if (instance.prefix) {
      parsedText = '%c' + instance.prefix + '%c ' + parsedText
      styles.unshift('color:' + instance.prefixColor + '; font-weight:bold;', '')
    }

    return {
      parsedText: parsedText,
      styles: styles
    }
  }

  function isDisabled(instance) {
    var isDisabled = false
    var isEnabled = false

    disabledInstancesRegExps.forEach(function(regExp) {
      if (regExp.test(instance.prefix)) {
        isDisabled = true
        return
      }
    })

    enabledInstancesRegExps.forEach(function(regExp) {
      if (regExp.test(instance.prefix)) {
        isEnabled = true
        return
      }
    })

    return (isDisabled && !isEnabled)
  }

  function prepareRegExpForPrefixSearch(str) {
    var regExpStr = str.replace(/\*/g, '.*?')
    var regExp = new RegExp(regExpStr)

    return regExp
  }

  function getNextColorIndex(lastUsedColorIndex, colors) {
    if (lastUsedColorIndex === undefined) {
      return 0
    }

    if (lastUsedColorIndex + 1 >= colors.length) {
      return 0
    } else {
      return lastUsedColorIndex + 1
    }
  }

  return Logdown

}())
<commit_msg>Simplifies `getNextColor` logic<commit_after>var Logdown = (function() {
  'use strict'

  var instances = []
  var lastUsedColorIndex = 0
  var nextColorIndex
  // Solarized accent colors http://ethanschoonover.com/solarized
  var colors = [
    '#B58900',
    '#CB4B16',
    '#DC322F',
    '#D33682',
    '#6C71C4',
    '#268BD2',
    '#2AA198',
    '#859900'
  ]
  var disabledInstancesRegExps = []
  var enabledInstancesRegExps = [] // RegExp that matches nothing

  function Logdown(opts) {
    // enforces new
    if (!(this instanceof Logdown)) {
      return new Logdown(opts)
    }

    //
    opts = opts || {}
    this.markdown = opts.markdown || true
    this.prefix = opts.prefix || ''

    //
    instances.push(this)

    this.prefixColor = colors[lastUsedColorIndex++ % colors.length]

    return this
  }

  // Static
  // ------

  Logdown.enable = function(str) {
    var regExp = prepareRegExpForPrefixSearch(str)
    enabledInstancesRegExps.push(regExp)
  }

  Logdown.disable = function(str) {
    var regExp = prepareRegExpForPrefixSearch(str)
    disabledInstancesRegExps.push(regExp)
  }

  // Public
  // ------

  Logdown.prototype.log = function(text) {
    var preparedOutput

    if (isDisabled(this)) {
      return
    }

    preparedOutput = prepareOutput(text, this)

    console.log.apply(
      console,
      [preparedOutput.parsedText].concat(preparedOutput.styles)
    )
  }

  Logdown.prototype.info = function(text) {
    var preparedOutput

    if (isDisabled(this)) {
      return
    }

    preparedOutput = prepareOutput(text, this)

    console.info.apply(
      console,
      [preparedOutput.parsedText].concat(preparedOutput.styles)
    )
  }

  Logdown.prototype.error = function(text) {
    var preparedOutput

    if (isDisabled(this)) {
      return
    }

    preparedOutput = prepareOutput(text, this)

    console.error.apply(
      console,
      [preparedOutput.parsedText].concat(preparedOutput.styles)
    )
  }

  Logdown.prototype.warn = function(text) {
    var preparedOutput

    if (isDisabled(this)) {
      return
    }

    preparedOutput = prepareOutput(text, this)

    console.warn.apply(
      console,
      [preparedOutput.parsedText].concat(preparedOutput.styles)
    )
  }

  // Private
  // -------

  function parseMarkdown(text) {
    var styles = []
    var match = getNextMatch(text)

    while (match) {
      text = text.replace(match.rule.regexp, match.rule.replacer)
      styles.push(match.rule.style)
      styles.push('')

      match = getNextMatch(text)
    }

    return {text: text, styles: styles}
  }

  function getNextMatch(text) {
    var matches = []
    var rules = [
      {
        regexp: /\*([^\*]+)\*/,
        replacer: function(match, submatch1) {
          return '%c' + submatch1 + '%c'
        },
        style: 'font-weight: bold;'
      },
      {
        regexp: /\_([^\_]+)\_/,
        replacer: function(match, submatch1) {
          return '%c' + submatch1 + '%c'
        },
        style: 'font-style: italic;'
      },
      {
        regexp: /\`([^\`]+)\`/,
        replacer: function(match, submatch1) {
          return "%c" + submatch1 + "%c";
        },
        style:
          'background: #FDF6E3;' +
          'color: #586E75;' +
          'padding: 1px 5px;' +
          'border-radius: 4px;'
      }
    ]

    //
    rules.forEach(function(rule) {
      var match = text.match(rule.regexp)
      if (match) {
        matches.push({
          rule: rule,
          match: match
        })
      }
    })
    if (matches.length === 0) {
      return null;
    }

    //
    // matches.sort(function(a, b) {
    //   return a.match.index - b.match.index
    // })

    return matches[0]
  }

  function prepareOutput(text, instance) {
    var parsedMarkdown
    var parsedText
    var styles

    if (instance.markdown) {
      parsedMarkdown = parseMarkdown(text)
      parsedText = parsedMarkdown.text
      styles = parsedMarkdown.styles
    }

    parsedText = parsedText || text
    styles = styles || []

    if (instance.prefix) {
      parsedText = '%c' + instance.prefix + '%c ' + parsedText
      styles.unshift('color:' + instance.prefixColor + '; font-weight:bold;', '')
    }

    return {
      parsedText: parsedText,
      styles: styles
    }
  }

  function isDisabled(instance) {
    var isDisabled = false
    var isEnabled = false

    disabledInstancesRegExps.forEach(function(regExp) {
      if (regExp.test(instance.prefix)) {
        isDisabled = true
        return
      }
    })

    enabledInstancesRegExps.forEach(function(regExp) {
      if (regExp.test(instance.prefix)) {
        isEnabled = true
        return
      }
    })

    return (isDisabled && !isEnabled)
  }

  function prepareRegExpForPrefixSearch(str) {
    var regExpStr = str.replace(/\*/g, '.*?')
    var regExp = new RegExp(regExpStr)

    return regExp
  }

  return Logdown

}())
<|endoftext|>


<commit_before>var _ = require("lodash");
var url = require("url");
var path = require("path");
var http = require("http");
var leveldown = require("leveldown");
var PicoEngine = require("pico-engine-core");
var serveStatic = require("ecstatic")({root: path.resolve(__dirname, "..", "public")});
var RulesetLoader = require("./RulesetLoader");
var HttpHashRouter = require("http-hash-router");
var compiler = require("krl-compiler");

////////////////////////////////////////////////////////////////////////////////
var port = process.env.PORT || 8080;
var pico_engine_home = process.env.PICO_ENGINE_HOME || path.resolve(__dirname, "..");
////////////////////////////////////////////////////////////////////////////////

PicoEngine({
  compileAndLoadRuleset: RulesetLoader({
    rulesets_dir: path.resolve(pico_engine_home, "rulesets")
  }),
  db: {
    db: leveldown,
    location: path.join(pico_engine_home, "db")
  }
}, function(err, pe){
  if(err){
    throw err;
  }

  var logs = {};
  var logRID = "io.picolabs.logging";
  var logEntry = function(context,message){
    var eci = context.eci;
    var timestamp = (new Date()).toISOString();
    var episode = logs[eci];
    if (episode) {
      episode.logs.push(timestamp+" "+message);
    } else {
      episode = {};
      episode.key = timestamp.replace(".","-") + " - " + eci
        + ((context.event) ? " - " + context.event.eid : " - query");
      episode.logs = [timestamp+" "+message];
      logs[eci] = episode;
    }
  };
  var logEpisode = function(pico_id,context,callback){
    var eci = context.eci;
    var episode = logs[eci];
    pe.db.getEntVar(pico_id,logRID,"status",function(e,status){
      if (status) {
        pe.db.getEntVar(pico_id,logRID,"logs",function(e,data){
          data[episode.key] = episode.logs;
          pe.db.putEntVar(pico_id,logRID,"logs",data,function(e){
            callback(delete logs[eci]);
          });
        });
      } else {
        callback(delete logs[eci]);
      }
    });
  };
  pe.emitter.on("klog", function(context, val, message){
    console.log("[KLOG]", message, val);
    logEntry(context,"[KLOG] "+message+" "+val);
  });
  pe.emitter.on("debug", function(context, message){
    console.log("[DEBUG]", context, message);
    var prefix = "";
    if (/^event rec..ved/.test(message)) {
      prefix = context.event.domain + "/" + context.event.type + " ";
    } else if (/^query rec..ved/.test(message)) {
      prefix = context.query.rid + "/" + context.query.name + " ";
    }
    logEntry(context,prefix+message);
    var callback = function(outcome){};
    if (/^event finished processing$/.test(message)) {
      logEpisode(context.pico_id,context,callback);
    } else if (/^query added to pico queue: /.test(message)) {
      var pico_id = message.split(" ")[5];
      logEpisode(pico_id,context,callback);
    }
  });

  var router = HttpHashRouter();

  var jsonResp = function(res, data){
    res.writeHead(200, {"Content-Type": "application/json"});
    res.end(JSON.stringify(data, undefined, 2));
  };

  var errResp = function(res, err){
    res.statusCode = err.statusCode || 500;
    res.end(err.message);
  };

  router.set("/sky/event/:eci/:eid/:domain/:type", function(req, res, route){
    var event = {
      eci: route.params.eci,
      eid: route.params.eid,
      domain: route.params.domain,
      type: route.params.type,
      attrs: route.data
    };
    pe.signalEvent(event, function(err, response){
      if(err) return errResp(res, err);
      jsonResp(res, response);
    });
  });

  router.set("/sky/cloud/:eci/:rid/:function", function(req, res, route){
    var query = {
      eci: route.params.eci,
      rid: route.params.rid,
      name: route.params["function"],
      args: route.data
    };
    pe.runQuery(query, function(err, data){
      if(err) return errResp(res, err);
      if(_.isFunction(data)){
        data(res);
      }else{
        jsonResp(res, data);
      }
    });
  });

  router.set("/api/db-dump", function(req, res, route){
    pe.db.toObj(function(err, db_data){
      if(err) return errResp(res, err);
      jsonResp(res, db_data);
    });
  });

  router.set("/old", function(req, res, route){
    pe.db.toObj(function(err, db_data){
      if(err) return errResp(res, err);

      var html = "";
      html += "\n\n";
      html += "
http://localhost:" + server.address().port + "
\n";
      html += "
Picos
\n";
      _.each(db_data.pico, function(pico){
        html += "
\n";
        html += "
"+pico.id+"
\n";
        html += "
\n";

        html += "
Channels
\n";
        html += "
\n";
        _.each(pico.channel, function(chan){
          var rm_link = "/api/pico/"+pico.id+"/rm-channel/"+chan.id;
          html += "
"+JSON.stringify(chan)+" del
\n";
        });
        html += "
\n";

        html += "<form action=\"/api/pico/"+pico.id+"/new-channel\" method=\"GET\">\n";
        html += "<input type=\"text\" name=\"name\" placeholder=\"name...\">\n";
        html += "<input type=\"text\" name=\"type\" placeholder=\"type...\">\n";
        html += "<button type=\"submit\">add channel</button>\n";
        html += "</form>\n";

        html += "
Rulesets
\n";
        html += "
\n";
        _.each(pico.ruleset, function(d, rid){
          var rm_link = "/api/pico/"+pico.id+"/rm-ruleset/"+rid;
          html += "
"+rid+" del
\n";
          html += "
\n";
          _.each(_.get(db_data, ["pico", pico.id, rid, "vars"]),
                 function(v,k){
                   html += "
"+k+"="+JSON.stringify(v)+"
\n";
                 });
          html += "
\n";
        });
        html += "
\n";

        html += "<form action=\"/api/pico/"+pico.id+"/add-ruleset\" method=\"GET\">\n";
        html += "<input type=\"text\" name=\"rid\" placeholder=\"Ruleset id...\">\n";
        html += "<button type=\"submit\">add ruleset</button>\n";
        html += "</form>\n";

        html += "
\n";
        html += "
\n";
      });
      html += "
\n";
      html += "add pico\n";
      html += "
\n";
      html += "
Rulesets
\n";
      _.each(_.get(db_data, ["rulesets", "versions"]), function(versions, rid){
        var enabled_hash = _.get(db_data, ["rulesets", "enabled", rid, "hash"]);
        html += "
\n";
        html += "
"+rid+"
\n";
        _.each(versions, function(hashes, timestamp){
          _.each(hashes, function(is_there, hash){
            if(!is_there){
              return;
            }
            html += "
\n";
            html += timestamp + " | " + hash + " | ";
            if(hash === enabled_hash){
              html += "disable";
              html += " | ";
              if(pe.isInstalled(rid)){
                html += "uninstall";
              }else{
                html += "install";
              }
              var the_krl_src = _.get(db_data, ["rulesets", "krl", enabled_hash, "src"]);
              html += "
" + the_krl_src + "
\n";
            }else{
              html += "enable";
            }
            html += "
\n";
          });
        });
        html += "
\n";
      });
      html += "<form action=\"/api/ruleset/register\" method=\"GET\">\n";
      html += "<textarea name=\"src\"></textarea>\n";
      html += "<button type=\"submit\">register ruleset</button>\n";
      html += "</form>\n";
      html += "
\n";
      html += "raw database dump\n";
  //    html += "
\n" + JSON.stringify(db_data, undefined, 2) + "\n
\n";
      html += "\n\n";
      res.end(html);
    });
  });

  router.set("/api/owner-channel", function(req, res, route){
    pe.db.getFirstChannel(function(err, first_channel){
      if(err) return errResp(res, err);
      res.end(JSON.stringify(first_channel, undefined, 2));
    });
  });

  router.set("/api/new-pico", function(req, res, route){
    pe.db.newPico({}, function(err, new_pico){
      if(err) return errResp(res, err);
      res.end(JSON.stringify(new_pico, undefined, 2));
    });
  });

  router.set("/api/rm-pico/:id", function(req, res, route){
    pe.db.removePico(route.params.id, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/pico/:id/new-channel", function(req, res, route){
    pe.db.newChannel({
      pico_id: route.params.id,
      name: route.data.name,
      type: route.data.type
    }, function(err, new_channel){
      if(err) return errResp(res, err);
      res.end(JSON.stringify(new_channel, undefined, 2));
    });
  });

  router.set("/api/pico/:id/rm-channel/:eci", function(req, res, route){
    pe.db.removeChannel(route.params.id, route.params.eci, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/pico/:id/rm-ruleset/:rid", function(req, res, route){
    pe.db.removeRuleset(route.params.id, route.params.rid, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/pico/:id/add-ruleset", function(req, res, route){
    pe.db.addRuleset({pico_id: route.params.id, rid: route.data.rid}, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/ruleset/compile", function(req, res, route){
    var src = _.get(url.parse(req.url, true), ["query", "src"]);
    try{
      jsonResp(res, { code: compiler(src).code});
    }catch(err){
      jsonResp(res, { error: err.toString() });
    }
  });

  router.set("/api/ruleset/register", function(req, res, route){
    var src = _.get(url.parse(req.url, true), ["query", "src"]);

    pe.db.registerRuleset(src, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/ruleset/enable/:hash", function(req, res, route){
    pe.db.enableRuleset(route.params.hash, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/ruleset/install/:rid", function(req, res, route){
    pe.installRID(route.params.rid, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/ruleset/disable/:rid", function(req, res, route){
    pe.db.disableRuleset(route.params.rid, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  var server = http.createServer(function(req, res){
    router(req, res, {
      data: url.parse(req.url, true).query
    }, function(err){
      if(err){
        if(err.type === "http-hash-router.not-found"){
          serveStatic(req, res);
          return;
        }
        errResp(res, err);
      }
    });
  });

  server.listen(port, function(){
    console.log("http://localhost:" + server.address().port);
  });
});
<commit_msg>use episode_start and episode_stop to inform pico of logs<commit_after>var _ = require("lodash");
var url = require("url");
var path = require("path");
var http = require("http");
var leveldown = require("leveldown");
var PicoEngine = require("pico-engine-core");
var serveStatic = require("ecstatic")({root: path.resolve(__dirname, "..", "public")});
var RulesetLoader = require("./RulesetLoader");
var HttpHashRouter = require("http-hash-router");
var compiler = require("krl-compiler");

////////////////////////////////////////////////////////////////////////////////
var port = process.env.PORT || 8080;
var pico_engine_home = process.env.PICO_ENGINE_HOME || path.resolve(__dirname, "..");
////////////////////////////////////////////////////////////////////////////////

PicoEngine({
  compileAndLoadRuleset: RulesetLoader({
    rulesets_dir: path.resolve(pico_engine_home, "rulesets")
  }),
  db: {
    db: leveldown,
    location: path.join(pico_engine_home, "db")
  }
}, function(err, pe){
  if(err){
    throw err;
  }

  var logs = {};
  var logRID = "io.picolabs.logging";
  var logEntry = function(context,message){
    var eci = context.eci;
    var timestamp = (new Date()).toISOString();
    var episode = logs[eci];
    if (episode) {
      episode.logs.push(timestamp+" "+message);
    } else {
      console.log("[ERROR]","no episode found for",eci);
    }
  };
  var logEpisode = function(pico_id,context,callback){
    var eci = context.eci;
    var episode = logs[eci];
    if (!episode) {
      console.log("[ERROR]","no episode found for",eci);
    }
    pe.db.getEntVar(pico_id,logRID,"status",function(e,status){
      if (status) {
        pe.db.getEntVar(pico_id,logRID,"logs",function(e,data){
          data[episode.key] = episode.logs;
          pe.db.putEntVar(pico_id,logRID,"logs",data,function(e){
            callback(delete logs[eci]);
          });
        });
      } else {
        callback(delete logs[eci]);
      }
    });
  };
  pe.emitter.on("episode_start", function(context){
    console.log("EPISODE_START",context);
    var eci = context.eci;
    var timestamp = (new Date()).toISOString();
    var episode = logs[eci];
    if (episode) {
      console.log("[ERROR]","episode already exists for",eci);
    } else {
      episode = {};
      episode.key = (
        timestamp + " - " + eci
          + " - " + ((context.event) ? context.event.eid : "query")
        ).replace(/[.]/g, "-");
      episode.logs = [];
      logs[eci] = episode;
    }
  });
  pe.emitter.on("klog", function(context, val, message){
    console.log("[KLOG]", message, val);
    logEntry(context,"[KLOG] "+message+" "+val);
  });
  pe.emitter.on("debug", function(context, message){
    console.log("[DEBUG]", context, message);
    var prefix = "";
    if (/^event rec..ved/.test(message)) {
      prefix = context.event.domain + "/" + context.event.type + " ";
    } else if (/^query rec..ved/.test(message)) {
      prefix = context.query.rid + "/" + context.query.name + " ";
    }
    logEntry(context,prefix+message);
  });
  pe.emitter.on("episode_stop", function(context){
    console.log("EPISODE_STOP",context);
    var callback = function(outcome){
      console.log("[EPISODE_REMOVED]",outcome);
    };
    logEpisode(context.pico_id,context,callback);
  });

  var router = HttpHashRouter();

  var jsonResp = function(res, data){
    res.writeHead(200, {"Content-Type": "application/json"});
    res.end(JSON.stringify(data, undefined, 2));
  };

  var errResp = function(res, err){
    res.statusCode = err.statusCode || 500;
    res.end(err.message);
  };

  router.set("/sky/event/:eci/:eid/:domain/:type", function(req, res, route){
    var event = {
      eci: route.params.eci,
      eid: route.params.eid,
      domain: route.params.domain,
      type: route.params.type,
      attrs: route.data
    };
    pe.signalEvent(event, function(err, response){
      if(err) return errResp(res, err);
      jsonResp(res, response);
    });
  });

  router.set("/sky/cloud/:eci/:rid/:function", function(req, res, route){
    var query = {
      eci: route.params.eci,
      rid: route.params.rid,
      name: route.params["function"],
      args: route.data
    };
    pe.runQuery(query, function(err, data){
      if(err) return errResp(res, err);
      if(_.isFunction(data)){
        data(res);
      }else{
        jsonResp(res, data);
      }
    });
  });

  router.set("/api/db-dump", function(req, res, route){
    pe.db.toObj(function(err, db_data){
      if(err) return errResp(res, err);
      jsonResp(res, db_data);
    });
  });

  router.set("/old", function(req, res, route){
    pe.db.toObj(function(err, db_data){
      if(err) return errResp(res, err);

      var html = "";
      html += "\n\n";
      html += "
http://localhost:" + server.address().port + "
\n";
      html += "
Picos
\n";
      _.each(db_data.pico, function(pico){
        html += "
\n";
        html += "
"+pico.id+"
\n";
        html += "
\n";

        html += "
Channels
\n";
        html += "
\n";
        _.each(pico.channel, function(chan){
          var rm_link = "/api/pico/"+pico.id+"/rm-channel/"+chan.id;
          html += "
"+JSON.stringify(chan)+" del
\n";
        });
        html += "
\n";

        html += "<form action=\"/api/pico/"+pico.id+"/new-channel\" method=\"GET\">\n";
        html += "<input type=\"text\" name=\"name\" placeholder=\"name...\">\n";
        html += "<input type=\"text\" name=\"type\" placeholder=\"type...\">\n";
        html += "<button type=\"submit\">add channel</button>\n";
        html += "</form>\n";

        html += "
Rulesets
\n";
        html += "
\n";
        _.each(pico.ruleset, function(d, rid){
          var rm_link = "/api/pico/"+pico.id+"/rm-ruleset/"+rid;
          html += "
"+rid+" del
\n";
          html += "
\n";
          _.each(_.get(db_data, ["pico", pico.id, rid, "vars"]),
                 function(v,k){
                   html += "
"+k+"="+JSON.stringify(v)+"
\n";
                 });
          html += "
\n";
        });
        html += "
\n";

        html += "<form action=\"/api/pico/"+pico.id+"/add-ruleset\" method=\"GET\">\n";
        html += "<input type=\"text\" name=\"rid\" placeholder=\"Ruleset id...\">\n";
        html += "<button type=\"submit\">add ruleset</button>\n";
        html += "</form>\n";

        html += "
\n";
        html += "
\n";
      });
      html += "
\n";
      html += "add pico\n";
      html += "
\n";
      html += "
Rulesets
\n";
      _.each(_.get(db_data, ["rulesets", "versions"]), function(versions, rid){
        var enabled_hash = _.get(db_data, ["rulesets", "enabled", rid, "hash"]);
        html += "
\n";
        html += "
"+rid+"
\n";
        _.each(versions, function(hashes, timestamp){
          _.each(hashes, function(is_there, hash){
            if(!is_there){
              return;
            }
            html += "
\n";
            html += timestamp + " | " + hash + " | ";
            if(hash === enabled_hash){
              html += "disable";
              html += " | ";
              if(pe.isInstalled(rid)){
                html += "uninstall";
              }else{
                html += "install";
              }
              var the_krl_src = _.get(db_data, ["rulesets", "krl", enabled_hash, "src"]);
              html += "
" + the_krl_src + "
\n";
            }else{
              html += "enable";
            }
            html += "
\n";
          });
        });
        html += "
\n";
      });
      html += "<form action=\"/api/ruleset/register\" method=\"GET\">\n";
      html += "<textarea name=\"src\"></textarea>\n";
      html += "<button type=\"submit\">register ruleset</button>\n";
      html += "</form>\n";
      html += "
\n";
      html += "raw database dump\n";
  //    html += "
\n" + JSON.stringify(db_data, undefined, 2) + "\n
\n";
      html += "\n\n";
      res.end(html);
    });
  });

  router.set("/api/owner-channel", function(req, res, route){
    pe.db.getFirstChannel(function(err, first_channel){
      if(err) return errResp(res, err);
      res.end(JSON.stringify(first_channel, undefined, 2));
    });
  });

  router.set("/api/new-pico", function(req, res, route){
    pe.db.newPico({}, function(err, new_pico){
      if(err) return errResp(res, err);
      res.end(JSON.stringify(new_pico, undefined, 2));
    });
  });

  router.set("/api/rm-pico/:id", function(req, res, route){
    pe.db.removePico(route.params.id, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/pico/:id/new-channel", function(req, res, route){
    pe.db.newChannel({
      pico_id: route.params.id,
      name: route.data.name,
      type: route.data.type
    }, function(err, new_channel){
      if(err) return errResp(res, err);
      res.end(JSON.stringify(new_channel, undefined, 2));
    });
  });

  router.set("/api/pico/:id/rm-channel/:eci", function(req, res, route){
    pe.db.removeChannel(route.params.id, route.params.eci, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/pico/:id/rm-ruleset/:rid", function(req, res, route){
    pe.db.removeRuleset(route.params.id, route.params.rid, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/pico/:id/add-ruleset", function(req, res, route){
    pe.db.addRuleset({pico_id: route.params.id, rid: route.data.rid}, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/ruleset/compile", function(req, res, route){
    var src = _.get(url.parse(req.url, true), ["query", "src"]);
    try{
      jsonResp(res, { code: compiler(src).code});
    }catch(err){
      jsonResp(res, { error: err.toString() });
    }
  });

  router.set("/api/ruleset/register", function(req, res, route){
    var src = _.get(url.parse(req.url, true), ["query", "src"]);

    pe.db.registerRuleset(src, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/ruleset/enable/:hash", function(req, res, route){
    pe.db.enableRuleset(route.params.hash, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/ruleset/install/:rid", function(req, res, route){
    pe.installRID(route.params.rid, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  router.set("/api/ruleset/disable/:rid", function(req, res, route){
    pe.db.disableRuleset(route.params.rid, function(err){
      if(err) return errResp(res, err);
      jsonResp(res, {ok: true});
    });
  });

  var server = http.createServer(function(req, res){
    router(req, res, {
      data: url.parse(req.url, true).query
    }, function(err){
      if(err){
        if(err.type === "http-hash-router.not-found"){
          serveStatic(req, res);
          return;
        }
        errResp(res, err);
      }
    });
  });

  server.listen(port, function(){
    console.log("http://localhost:" + server.address().port);
  });
});
<|endoftext|>


<commit_before>// Copyright (c) Rotorz Limited. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root.

/** @module webreed */
<commit_msg>Correct main module name in jsdoc comment.<commit_after>// Copyright (c) Rotorz Limited. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root.

/** @module webreed-core */
<|endoftext|>


<commit_before>/* eslint-disable filenames/match-exported */
import path from "path"
import denodeify from "denodeify"
import fs from "fs-extra"
import { createFilter } from "rollup-pluginutils"
import { getHashedName } from "asset-hash"

import postcss from "postcss"

import postcssImport from "postcss-import"
import postcssSmartAsset from "postcss-smart-asset"

import postcssSugarSS from "sugarss"
import postcssScss from "postcss-scss"
import postcssSass from "postcss-sass"

var copyAsync = denodeify(fs.copy)
var writeAsync = denodeify(fs.outputFile)

const styleParser = {
  ".pcss": null,
  ".css": null,
  ".sss": postcssSugarSS,
  ".scss": postcssScss,
  ".sass": postcssSass
}

function getPostCssPlugins(prependName){
  return [ postcssImport(), postcssSmartAsset({
    url: "copy",
    useHash: true,
    prependName
  }) ]
}

/* eslint-disable max-params */
function processStyle(code, id, dest, prependName) {
  var parser = styleParser[path.extname(id)]
  return postcss(getPostCssPlugins(prependName))
    .process(code.toString(), {
      from: id,
      to: dest,
      extensions: Object.keys(styleParser),
      map: { inline: true },

      // Always uses parser... even for scss as we like to offer "normal" CSS in deployed files.
      parser
    })
    .then((result) => writeAsync(dest, result))
    .catch((error) => {
      console.error(error)
    })
}

const externalIds = {}

const defaultExclude = [ "**/*.json", "**/*.mjs", "**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx", "**/*.vue" ]

export default function rebase(options = {}) {
  const { include, exclude = defaultExclude, input, outputFolder, verbose, prependName } = options
  const filter = createFilter(include, exclude)

  return {
    name: "rollup-plugin-rebase",

    isExternal(id) {
      var baseName = `./${path.basename(id)}`
      return baseName in externalIds
    },

    resolveId(importee) {
      if (importee in externalIds) {
        // This does not yet seem to work!
        // See also: https://github.com/rollup/rollup/issues/861
        // "returning any other falsy value signals that importee should be treated as an external module
        // and not included in the bundle." -- https://github.com/rollup/rollup/wiki/Plugins#creating-plugins
        return false
      }

      return null
    },

    load(id) {
      if (!filter(id)) {
        return null
      }

      const inputStream = fs.createReadStream(id)

      return new Promise((resolve, reject) => {
        inputStream.on("readable", async () => {
          var fileSource = id
          var fileExt = path.extname(id)
          var fileName = path.basename(id).slice(0, -fileExt.length)
          var destId = await getHashedName(id)

          var fileHash = destId.slice(0, -fileExt.length)
          var destFilename = prependName ? fileName + '_' + destId : destId;
          var fileDest = path.resolve(outputFolder, destFilename)

          // Mark new file location as external to prevent further processing.
          externalIds[`./${destFilename}`] = true

          var inputFolder = path.dirname(path.resolve(input))
          var relativeToRoot = path.relative(path.dirname(fileSource), inputFolder).replace(/\\/g, "/")

          // Adjust destId so that it points to the root folder - from any
          // depth we detected inside the original project structure.
          var importId
          if (relativeToRoot.charAt(0) === ".") {
            importId = `${relativeToRoot}/${destFilename}`
          } else if (relativeToRoot === "") {
            importId = `./${destFilename}`
          } else {
            importId = `./${relativeToRoot}/${destFilename}`
          }

          if (fileExt in styleParser) {
            if (verbose) {
              console.log(`Processing ${fileSource} => ${fileDest}...`)
            }

            var fileContent = fs.readFileSync(fileSource)
            return processStyle(fileContent, fileSource, fileDest, prependName).then(() =>
              resolve({
                code: `import _${fileHash} from "${importId}"; export default _${fileHash};`,
                map: { mappings: "" }
              })
            )
          } else {
            if (verbose) {
              console.log(`Copying ${fileSource} => ${fileDest}...`)
            }

            return copyAsync(fileSource, fileDest).then(() =>
              resolve({
                code: `import _${fileHash} from "${importId}"; export default _${fileHash};`,
                map: { mappings: "" }
              })
            )
          }
        })
      })
    }
  }
}
<commit_msg>Auto fix some eslint issues<commit_after>/* eslint-disable filenames/match-exported */
import path from "path"
import denodeify from "denodeify"
import fs from "fs-extra"
import { createFilter } from "rollup-pluginutils"
import { getHashedName } from "asset-hash"

import postcss from "postcss"

import postcssImport from "postcss-import"
import postcssSmartAsset from "postcss-smart-asset"

import postcssSugarSS from "sugarss"
import postcssScss from "postcss-scss"
import postcssSass from "postcss-sass"

var copyAsync = denodeify(fs.copy)
var writeAsync = denodeify(fs.outputFile)

const styleParser = {
  ".pcss": null,
  ".css": null,
  ".sss": postcssSugarSS,
  ".scss": postcssScss,
  ".sass": postcssSass
}

function getPostCssPlugins(prependName) {
  return [ postcssImport(), postcssSmartAsset({
    url: "copy",
    useHash: true,
    prependName
  }) ]
}

/* eslint-disable max-params */
function processStyle(code, id, dest, prependName) {
  var parser = styleParser[path.extname(id)]
  return postcss(getPostCssPlugins(prependName))
    .process(code.toString(), {
      from: id,
      to: dest,
      extensions: Object.keys(styleParser),
      map: { inline: true },

      // Always uses parser... even for scss as we like to offer "normal" CSS in deployed files.
      parser
    })
    .then((result) => writeAsync(dest, result))
    .catch((error) => {
      console.error(error)
    })
}

const externalIds = {}

const defaultExclude = [ "**/*.json", "**/*.mjs", "**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx", "**/*.vue" ]

export default function rebase(options = {}) {
  const { include, exclude = defaultExclude, input, outputFolder, verbose, prependName } = options
  const filter = createFilter(include, exclude)

  return {
    name: "rollup-plugin-rebase",

    isExternal(id) {
      var baseName = `./${path.basename(id)}`
      return baseName in externalIds
    },

    resolveId(importee) {
      if (importee in externalIds) {
        // This does not yet seem to work!
        // See also: https://github.com/rollup/rollup/issues/861
        // "returning any other falsy value signals that importee should be treated as an external module
        // and not included in the bundle." -- https://github.com/rollup/rollup/wiki/Plugins#creating-plugins
        return false
      }

      return null
    },

    load(id) {
      if (!filter(id)) {
        return null
      }

      const inputStream = fs.createReadStream(id)

      return new Promise((resolve, reject) => {
        inputStream.on("readable", async() => {
          var fileSource = id
          var fileExt = path.extname(id)
          var fileName = path.basename(id).slice(0, -fileExt.length)
          var destId = await getHashedName(id)

          var fileHash = destId.slice(0, -fileExt.length)
          var destFilename = prependName ? `${fileName}_${destId}` : destId
          var fileDest = path.resolve(outputFolder, destFilename)

          // Mark new file location as external to prevent further processing.
          externalIds[`./${destFilename}`] = true

          var inputFolder = path.dirname(path.resolve(input))
          var relativeToRoot = path.relative(path.dirname(fileSource), inputFolder).replace(/\\/g, "/")

          // Adjust destId so that it points to the root folder - from any
          // depth we detected inside the original project structure.
          var importId
          if (relativeToRoot.charAt(0) === ".") {
            importId = `${relativeToRoot}/${destFilename}`
          } else if (relativeToRoot === "") {
            importId = `./${destFilename}`
          } else {
            importId = `./${relativeToRoot}/${destFilename}`
          }

          if (fileExt in styleParser) {
            if (verbose) {
              console.log(`Processing ${fileSource} => ${fileDest}...`)
            }

            var fileContent = fs.readFileSync(fileSource)
            return processStyle(fileContent, fileSource, fileDest, prependName).then(() =>
              resolve({
                code: `import _${fileHash} from "${importId}"; export default _${fileHash};`,
                map: { mappings: "" }
              })
            )
          } else {
            if (verbose) {
              console.log(`Copying ${fileSource} => ${fileDest}...`)
            }

            return copyAsync(fileSource, fileDest).then(() =>
              resolve({
                code: `import _${fileHash} from "${importId}"; export default _${fileHash};`,
                map: { mappings: "" }
              })
            )
          }
        })
      })
    }
  }
}
<|endoftext|>


<commit_before>'use strict';

require('nomoreunhandledrejections')();

const express = require('express');
const cons = require('consolidate');
const path = require('path');
const morgan = require('morgan');
const scssMiddleware = require('./middleware/scss');
const staticMiddleware = require('./middleware/static');

const workdir = process.cwd();
const httpPort = process.env.HTTP_PORT || 3000;
const app = express();

const baseViewModel = {
  title: `King's Reach – this is a custom title`
};

//
// Setup
//
app.engine('dust', cons.dust);
cons.dust.helpers = require('dustjs-helpers');
app.set('view engine', 'dust');
app.set('views', path.join(workdir, 'views'));

app.use(morgan('combined'));
app.use(scssMiddleware);
app.use('/public', staticMiddleware);

//
// Routes
//
app.get('/', async (req, res) => {
  const viewModel = Object.assign({}, baseViewModel, { test: true });
  res.render('pages/index', viewModel);
});

//
// Run
//
app.listen(httpPort, () => console.log(`Listening on port ${httpPort}`));
<commit_msg>feat: add more routes<commit_after>'use strict';

require('nomoreunhandledrejections')();

const express = require('express');
const cons = require('consolidate');
const path = require('path');
const morgan = require('morgan');
const scssMiddleware = require('./middleware/scss');
const staticMiddleware = require('./middleware/static');

const workdir = process.cwd();
const httpPort = process.env.HTTP_PORT || 3000;
const app = express();

const baseViewModel = {
  title: `King's Reach – this is a custom title`
};

//
// Setup
//
app.engine('dust', cons.dust);
cons.dust.helpers = require('dustjs-helpers');
app.set('view engine', 'dust');
app.set('views', path.join(workdir, 'views'));

app.use(morgan('combined'));
app.use(scssMiddleware);
app.use('/public', staticMiddleware);

//
// Routes
//
app.get('/', async (req, res) => {
  res.render('pages/index', baseViewModel);
});
app.get('/index', async (req, res) => {
  res.render('pages/index', baseViewModel);
});
app.get('/rules', async (req, res) => {
  res.render('pages/rules', baseViewModel);
});
app.get('/events', async (req, res) => {
  res.render('pages/events', baseViewModel);
});
app.get('/screenshots', async (req, res) => {
  res.render('pages/screenshots', baseViewModel);
});
app.get('/contact', async (req, res) => {
  res.render('pages/contact', baseViewModel);
});

//
// Run
//
app.listen(httpPort, () => console.log(`Listening on port ${httpPort}`));
<|endoftext|>


<commit_before>var dgram  = require('dgram')
  , util    = require('util')
  , net    = require('net')
  , config = require('./config')
  , fs     = require('fs')
  , events = require('events')
  , logger = require('./lib/logger')

// initialize data structures with defaults for statsd stats
var keyCounter = {};
var counters = {
  "statsd.packets_received": 0,
  "statsd.bad_lines_seen": 0
};
var timers = {
  "statsd.packet_process_time": []
};
var gauges = {};
var pctThreshold = null;
var debugInt, flushInterval, keyFlushInt, server, mgmtServer;
var startup_time = Math.round(new Date().getTime() / 1000);
var backendEvents = new events.EventEmitter();

// Load and init the backend from the backends/ directory.
function loadBackend(config, name) {
  var backendmod = require(name);

  if (config.debug) {
    l.log("Loading backend: " + name, 'debug');
  }

  var ret = backendmod.init(startup_time, config, backendEvents);
  if (!ret) {
    l.log("Failed to load backend: " + name);
    process.exit(1);
  }
};

// Flush metrics to each backend.
function flushMetrics() {
  var time_stamp = Math.round(new Date().getTime() / 1000);

  var metrics_hash = {
    counters: counters,
    gauges: gauges,
    timers: timers,
    pctThreshold: pctThreshold
  }

  // After all listeners, reset the stats
  backendEvents.once('flush', function clear_metrics(ts, metrics) {
    // Clear the counters
    for (key in metrics.counters) {
      metrics.counters[key] = 0;
    }

    // Clear the timers
    for (key in metrics.timers) {
      metrics.timers[key] = [];
    }
  });

  // Flush metrics to each backend.
  backendEvents.emit('flush', time_stamp, metrics_hash);
};

var stats = {
  messages: {
    last_msg_seen: startup_time,
    bad_lines_seen: 0,
  }
};

// Global for the logger
var l;

config.configFile(process.argv[2], function (config, oldConfig) {
  if (! config.debug && debugInt) {
    clearInterval(debugInt);
    debugInt = false;
  }

  l = new logger.Logger(config.log || {});

  if (config.debug) {
    if (debugInt !== undefined) {
      clearInterval(debugInt);
    }
    debugInt = setInterval(function () {
      l.log("Counters:\n" + util.inspect(counters) +
               "\nTimers:\n" + util.inspect(timers) +
               "\nGauges:\n" + util.inspect(gauges), 'debug');
    }, config.debugInterval || 10000);
  }

  if (server === undefined) {

    // key counting
    var keyFlushInterval = Number((config.keyFlush && config.keyFlush.interval) || 0);

    server = dgram.createSocket('udp4', function (msg, rinfo) {
      counters["statsd.packets_received"]++;
      var metrics = msg.toString().split("\n");

      for (midx in metrics) {
        if (config.dumpMessages) {
          l.log(metrics[midx].toString());
        }
        var bits = metrics[midx].toString().split(':');
        var key = bits.shift()
                      .replace(/\s+/g, '_')
                      .replace(/\//g, '-')
                      .replace(/[^a-zA-Z_\-0-9\.]/g, '');

        if (keyFlushInterval > 0) {
          if (! keyCounter[key]) {
            keyCounter[key] = 0;
          }
          keyCounter[key] += 1;
        }

        if (bits.length == 0) {
          bits.push("1");
        }

        for (var i = 0; i < bits.length; i++) {
          var sampleRate = 1;
          var fields = bits[i].split("|");
          if (fields[1] === undefined) {
              l.log('Bad line: ' + fields + ' in msg "' + metrics[midx] +'"');
              counters["statsd.bad_lines_seen"]++;
              stats['messages']['bad_lines_seen']++;
              continue;
          }
          if (fields[1].trim() == "ms") {
            if (! timers[key]) {
              timers[key] = [];
            }
            timers[key].push(Number(fields[0] || 0));
          } else if (fields[1].trim() == "g") {
            gauges[key] = Number(fields[0] || 0);
          } else {
            if (fields[2] && fields[2].match(/^@([\d\.]+)/)) {
              sampleRate = Number(fields[2].match(/^@([\d\.]+)/)[1]);
            }
            if (! counters[key]) {
              counters[key] = 0;
            }
            counters[key] += Number(fields[0] || 1) * (1 / sampleRate);
          }
        }
      }

      stats['messages']['last_msg_seen'] = Math.round(new Date().getTime() / 1000);
    });

    mgmtServer = net.createServer(function(stream) {
      stream.setEncoding('ascii');

      stream.on('data', function(data) {
        var cmdline = data.trim().split(" ");
        var cmd = cmdline.shift();

        switch(cmd) {
          case "help":
            stream.write("Commands: stats, counters, timers, gauges, delcounters, deltimers, delgauges, quit\n\n");
            break;

          case "stats":
            var now    = Math.round(new Date().getTime() / 1000);
            var uptime = now - startup_time;

            stream.write("uptime: " + uptime + "\n");

            var stat_writer = function(group, metric, val) {
              var delta;

              if (metric.match("^last_")) {
                delta = now - val;
              }
              else {
                delta = val;
              }

              stream.write(group + "." + metric + ": " + delta + "\n");
            };

            // Loop through the base stats
            for (group in stats) {
              for (metric in stats[group]) {
                stat_writer(group, metric, stats[group][metric]);
              }
            }

            backendEvents.once('status', function(writeCb) {
              stream.write("END\n\n");
            });

            // Let each backend contribute its status
            backendEvents.emit('status', function(err, name, stat, val) {
              if (err) {
                l.log("Failed to read stats for backend " +
                         name + ": " + err);
              } else {
                stat_writer(name, stat, val);
              }
            });

            break;

          case "counters":
            stream.write(util.inspect(counters) + "\n");
            stream.write("END\n\n");
            break;

          case "timers":
            stream.write(util.inspect(timers) + "\n");
            stream.write("END\n\n");
            break;

          case "gauges":
            stream.write(util.inspect(gauges) + "\n");
            stream.write("END\n\n");
            break;

          case "delcounters":
            for (index in cmdline) {
              delete counters[cmdline[index]];
              stream.write("deleted: " + cmdline[index] + "\n");
            }
            stream.write("END\n\n");
            break;

          case "deltimers":
            for (index in cmdline) {
              delete timers[cmdline[index]];
              stream.write("deleted: " + cmdline[index] + "\n");
            }
            stream.write("END\n\n");
            break;

          case "delgauges":
            for (index in cmdline) {
              delete gauges[cmdline[index]];
              stream.write("deleted: " + cmdline[index] + "\n");
            }
            stream.write("END\n\n");
            break;

          case "quit":
            stream.end();
            break;

          default:
            stream.write("ERROR\n");
            break;
        }

      });
    });

    server.bind(config.port || 8125, config.address || undefined);
    mgmtServer.listen(config.mgmt_port || 8126, config.mgmt_address || undefined);

    util.log("server is up");

    pctThreshold = config.percentThreshold || 90;
    if (!Array.isArray(pctThreshold)) {
      pctThreshold = [ pctThreshold ]; // listify percentiles so single values work the same
    }

    flushInterval = Number(config.flushInterval || 10000);
    config.flushInterval = flushInterval;

    if (config.backends) {
      for (var i = 0; i < config.backends.length; i++) {
        loadBackend(config, config.backends[i]);
      }
    } else {
      // The default backend is graphite
      loadBackend(config, './backends/graphite');
    }

    // Setup the flush timer
    var flushInt = setInterval(flushMetrics, flushInterval);

    if (keyFlushInterval > 0) {
      var keyFlushPercent = Number((config.keyFlush && config.keyFlush.percent) || 100);
      var keyFlushLog = (config.keyFlush && config.keyFlush.log) || "stdout";

      keyFlushInt = setInterval(function () {
        var key;
        var sortedKeys = [];

        for (key in keyCounter) {
          sortedKeys.push([key, keyCounter[key]]);
        }

        sortedKeys.sort(function(a, b) { return b[1] - a[1]; });

        var logMessage = "";
        var timeString = (new Date()) + "";

        // only show the top "keyFlushPercent" keys
        for (var i = 0, e = sortedKeys.length * (keyFlushPercent / 100); i < e; i++) {
          logMessage += timeString + " count=" + sortedKeys[i][1] + " key=" + sortedKeys[i][0] + "\n";
        }

        var logFile = fs.createWriteStream(keyFlushLog, {flags: 'a+'});
        logFile.write(logMessage);
        logFile.end();

        // clear the counter
        keyCounter = {};
      }, keyFlushInterval);
    }

  ;

  }
})
<commit_msg>Increments bad_lines_seen when sampleRate bit does not match regex<commit_after>var dgram  = require('dgram')
  , util    = require('util')
  , net    = require('net')
  , config = require('./config')
  , fs     = require('fs')
  , events = require('events')
  , logger = require('./lib/logger')

// initialize data structures with defaults for statsd stats
var keyCounter = {};
var counters = {
  "statsd.packets_received": 0,
  "statsd.bad_lines_seen": 0
};
var timers = {
  "statsd.packet_process_time": []
};
var gauges = {};
var pctThreshold = null;
var debugInt, flushInterval, keyFlushInt, server, mgmtServer;
var startup_time = Math.round(new Date().getTime() / 1000);
var backendEvents = new events.EventEmitter();

// Load and init the backend from the backends/ directory.
function loadBackend(config, name) {
  var backendmod = require(name);

  if (config.debug) {
    l.log("Loading backend: " + name, 'debug');
  }

  var ret = backendmod.init(startup_time, config, backendEvents);
  if (!ret) {
    l.log("Failed to load backend: " + name);
    process.exit(1);
  }
};

// Flush metrics to each backend.
function flushMetrics() {
  var time_stamp = Math.round(new Date().getTime() / 1000);

  var metrics_hash = {
    counters: counters,
    gauges: gauges,
    timers: timers,
    pctThreshold: pctThreshold
  }

  // After all listeners, reset the stats
  backendEvents.once('flush', function clear_metrics(ts, metrics) {
    // Clear the counters
    for (key in metrics.counters) {
      metrics.counters[key] = 0;
    }

    // Clear the timers
    for (key in metrics.timers) {
      metrics.timers[key] = [];
    }
  });

  // Flush metrics to each backend.
  backendEvents.emit('flush', time_stamp, metrics_hash);
};

var stats = {
  messages: {
    last_msg_seen: startup_time,
    bad_lines_seen: 0,
  }
};

// Global for the logger
var l;

config.configFile(process.argv[2], function (config, oldConfig) {
  if (! config.debug && debugInt) {
    clearInterval(debugInt);
    debugInt = false;
  }

  l = new logger.Logger(config.log || {});

  if (config.debug) {
    if (debugInt !== undefined) {
      clearInterval(debugInt);
    }
    debugInt = setInterval(function () {
      l.log("Counters:\n" + util.inspect(counters) +
               "\nTimers:\n" + util.inspect(timers) +
               "\nGauges:\n" + util.inspect(gauges), 'debug');
    }, config.debugInterval || 10000);
  }

  if (server === undefined) {

    // key counting
    var keyFlushInterval = Number((config.keyFlush && config.keyFlush.interval) || 0);

    server = dgram.createSocket('udp4', function (msg, rinfo) {
      counters["statsd.packets_received"]++;
      var metrics = msg.toString().split("\n");

      for (midx in metrics) {
        if (config.dumpMessages) {
          l.log(metrics[midx].toString());
        }
        var bits = metrics[midx].toString().split(':');
        var key = bits.shift()
                      .replace(/\s+/g, '_')
                      .replace(/\//g, '-')
                      .replace(/[^a-zA-Z_\-0-9\.]/g, '');

        if (keyFlushInterval > 0) {
          if (! keyCounter[key]) {
            keyCounter[key] = 0;
          }
          keyCounter[key] += 1;
        }

        if (bits.length == 0) {
          bits.push("1");
        }

        for (var i = 0; i < bits.length; i++) {
          var sampleRate = 1;
          var fields = bits[i].split("|");
          if (fields[1] === undefined) {
              l.log('Bad line: ' + fields + ' in msg "' + metrics[midx] +'"');
              counters["statsd.bad_lines_seen"]++;
              stats['messages']['bad_lines_seen']++;
              continue;
          }
          if (fields[1].trim() == "ms") {
            if (! timers[key]) {
              timers[key] = [];
            }
            timers[key].push(Number(fields[0] || 0));
          } else if (fields[1].trim() == "g") {
            gauges[key] = Number(fields[0] || 0);
          } else {
            if (fields[2]) {
              if (fields[2].match(/^@([\d\.]+)/)) {
                sampleRate = Number(fields[2].match(/^@([\d\.]+)/)[1]);
              } else {
                l.log('Bad line: ' + fields + ' in msg "' + metrics[midx] +'"; has invalid sample rate');
                counters["statsd.bad_lines_seen"]++;
                stats['messages']['bad_lines_seen']++;
                continue;
              }
            }
            if (! counters[key]) {
              counters[key] = 0;
            }
            counters[key] += Number(fields[0] || 1) * (1 / sampleRate);
          }
        }
      }

      stats['messages']['last_msg_seen'] = Math.round(new Date().getTime() / 1000);
    });

    mgmtServer = net.createServer(function(stream) {
      stream.setEncoding('ascii');

      stream.on('data', function(data) {
        var cmdline = data.trim().split(" ");
        var cmd = cmdline.shift();

        switch(cmd) {
          case "help":
            stream.write("Commands: stats, counters, timers, gauges, delcounters, deltimers, delgauges, quit\n\n");
            break;

          case "stats":
            var now    = Math.round(new Date().getTime() / 1000);
            var uptime = now - startup_time;

            stream.write("uptime: " + uptime + "\n");

            var stat_writer = function(group, metric, val) {
              var delta;

              if (metric.match("^last_")) {
                delta = now - val;
              }
              else {
                delta = val;
              }

              stream.write(group + "." + metric + ": " + delta + "\n");
            };

            // Loop through the base stats
            for (group in stats) {
              for (metric in stats[group]) {
                stat_writer(group, metric, stats[group][metric]);
              }
            }

            backendEvents.once('status', function(writeCb) {
              stream.write("END\n\n");
            });

            // Let each backend contribute its status
            backendEvents.emit('status', function(err, name, stat, val) {
              if (err) {
                l.log("Failed to read stats for backend " +
                         name + ": " + err);
              } else {
                stat_writer(name, stat, val);
              }
            });

            break;

          case "counters":
            stream.write(util.inspect(counters) + "\n");
            stream.write("END\n\n");
            break;

          case "timers":
            stream.write(util.inspect(timers) + "\n");
            stream.write("END\n\n");
            break;

          case "gauges":
            stream.write(util.inspect(gauges) + "\n");
            stream.write("END\n\n");
            break;

          case "delcounters":
            for (index in cmdline) {
              delete counters[cmdline[index]];
              stream.write("deleted: " + cmdline[index] + "\n");
            }
            stream.write("END\n\n");
            break;

          case "deltimers":
            for (index in cmdline) {
              delete timers[cmdline[index]];
              stream.write("deleted: " + cmdline[index] + "\n");
            }
            stream.write("END\n\n");
            break;

          case "delgauges":
            for (index in cmdline) {
              delete gauges[cmdline[index]];
              stream.write("deleted: " + cmdline[index] + "\n");
            }
            stream.write("END\n\n");
            break;

          case "quit":
            stream.end();
            break;

          default:
            stream.write("ERROR\n");
            break;
        }

      });
    });

    server.bind(config.port || 8125, config.address || undefined);
    mgmtServer.listen(config.mgmt_port || 8126, config.mgmt_address || undefined);

    util.log("server is up");

    pctThreshold = config.percentThreshold || 90;
    if (!Array.isArray(pctThreshold)) {
      pctThreshold = [ pctThreshold ]; // listify percentiles so single values work the same
    }

    flushInterval = Number(config.flushInterval || 10000);
    config.flushInterval = flushInterval;

    if (config.backends) {
      for (var i = 0; i < config.backends.length; i++) {
        loadBackend(config, config.backends[i]);
      }
    } else {
      // The default backend is graphite
      loadBackend(config, './backends/graphite');
    }

    // Setup the flush timer
    var flushInt = setInterval(flushMetrics, flushInterval);

    if (keyFlushInterval > 0) {
      var keyFlushPercent = Number((config.keyFlush && config.keyFlush.percent) || 100);
      var keyFlushLog = (config.keyFlush && config.keyFlush.log) || "stdout";

      keyFlushInt = setInterval(function () {
        var key;
        var sortedKeys = [];

        for (key in keyCounter) {
          sortedKeys.push([key, keyCounter[key]]);
        }

        sortedKeys.sort(function(a, b) { return b[1] - a[1]; });

        var logMessage = "";
        var timeString = (new Date()) + "";

        // only show the top "keyFlushPercent" keys
        for (var i = 0, e = sortedKeys.length * (keyFlushPercent / 100); i < e; i++) {
          logMessage += timeString + " count=" + sortedKeys[i][1] + " key=" + sortedKeys[i][0] + "\n";
        }

        var logFile = fs.createWriteStream(keyFlushLog, {flags: 'a+'});
        logFile.write(logMessage);
        logFile.end();

        // clear the counter
        keyCounter = {};
      }, keyFlushInterval);
    }

  ;

  }
})
<|endoftext|>


<commit_before>import { takeEvery } from 'redux-saga';
import { take, race, put, call } from 'redux-saga/effects';

const identity = i => i;
const PROMISE = '@@redux-form-saga/PROMISE';
const status = ['REQUEST', 'SUCCESS', 'FAILURE'];

function createFormAction (requestAction, types, payloadCreator = identity) {
  const actionMethods = {};
  const formAction = (payload) => ({
    type: PROMISE,
    payload
  });

  // Allow a type prefix to be passed in
  if (typeof requestAction === 'string') {
    requestAction = status.map(s => {
      let a = `${requestAction}_${s}`;
      let subAction = payload => ({
        type: a,
        payload: payloadCreator(payload)
      });

      // translate specific actionType to generic actionType
      actionMethods[s] = a;
      actionMethods[s.toLowerCase()] = subAction;

      return subAction;
    })[0];

    if (types) {
      payloadCreator = types;
    }

    types = [ actionMethods.SUCCESS, actionMethods.FAILURE ];
  }

  if (types.length !== 2) {
    throw new Error('Must include two action types: [ SUCCESS, FAILURE ]');
  }

  return Object.assign((data, dispatch) => {
    return new Promise((resolve, reject) => {
      dispatch(formAction({
        request: requestAction(data),
        defer: { resolve, reject },
        types
      }));
    });
  }, actionMethods);
};

function *handlePromiseSaga({ payload }) {
  const { request, defer, types } = payload;
  const { resolve, reject } = defer;
  const [ SUCCESS, FAIL ] = types;

  const [ winner ] = yield [
    race({
      success: take(SUCCESS),
      fail: take(FAIL),
    }),
    put(request),
  ];

    if (winner.success) {
      yield call(resolve, winner.success);
    } else {
      yield call(reject, winner.fail && winner.fail.payload ? winner.fail.payload : winner.fail);
    }
  }
}

function *formActionSaga() {
  yield call(takeEvery, PROMISE, handlePromiseSaga);
}

export {
  PROMISE,
  createFormAction,
  formActionSaga,
  handlePromiseSaga,
}

export default formActionSaga;
<commit_msg>Passing payload property to success action<commit_after>import { takeEvery } from 'redux-saga';
import { take, race, put, call } from 'redux-saga/effects';

const identity = i => i;
const PROMISE = '@@redux-form-saga/PROMISE';
const status = ['REQUEST', 'SUCCESS', 'FAILURE'];

function createFormAction (requestAction, types, payloadCreator = identity) {
  const actionMethods = {};
  const formAction = (payload) => ({
    type: PROMISE,
    payload
  });

  // Allow a type prefix to be passed in
  if (typeof requestAction === 'string') {
    requestAction = status.map(s => {
      let a = `${requestAction}_${s}`;
      let subAction = payload => ({
        type: a,
        payload: payloadCreator(payload)
      });

      // translate specific actionType to generic actionType
      actionMethods[s] = a;
      actionMethods[s.toLowerCase()] = subAction;

      return subAction;
    })[0];

    if (types) {
      payloadCreator = types;
    }

    types = [ actionMethods.SUCCESS, actionMethods.FAILURE ];
  }

  if (types.length !== 2) {
    throw new Error('Must include two action types: [ SUCCESS, FAILURE ]');
  }

  return Object.assign((data, dispatch) => {
    return new Promise((resolve, reject) => {
      dispatch(formAction({
        request: requestAction(data),
        defer: { resolve, reject },
        types
      }));
    });
  }, actionMethods);
};

function *handlePromiseSaga({ payload }) {
  const { request, defer, types } = payload;
  const { resolve, reject } = defer;
  const [ SUCCESS, FAIL ] = types;

  const [ winner ] = yield [
    race({
      success: take(SUCCESS),
      fail: take(FAIL),
    }),
    put(request),
  ];

    if (winner.success) {
      yield call(resolve, winner.success && winner.success.payload ? winner.success.payload : winner.success);
    } else {
      yield call(reject, winner.fail && winner.fail.payload ? winner.fail.payload : winner.fail);
    }
  }
}

function *formActionSaga() {
  yield call(takeEvery, PROMISE, handlePromiseSaga);
}

export {
  PROMISE,
  createFormAction,
  formActionSaga,
  handlePromiseSaga,
}

export default formActionSaga;
<|endoftext|>