<commit_before>/*
Copyright (c) 2012 Mario Pareja

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
exports.create = function () {
  var nodes = {};
  var instance = function (node, deps) {
    nodes[node] = {
      name: node,
      deps: Array.isArray(deps) ? deps : []
    };
  };

  instance.resolve = function (node) {
    var resolved = [],
      resolving = {};
    resolveDeps(node);

    function resolveDeps(node) {
      if (!alreadyResolved(node)) {
        throwIfCurrentlyResolving(node);

        markAsBeingResolved(node);

        var current = nodes[node];
        if (!current) { throw new Error('Node not found: ' + node); }
        current.deps.forEach(function (dep) {
          resolveDeps(dep);
        });

        markAsResolved(node);
      }
    }

    function markAsBeingResolved(node) {
      resolving[node] = true;
    }

    function markAsResolved(node) {
      resolved.push(node);
      delete resolving[node];
    }

    function alreadyResolved(node) {
      return resolved.some(function (n) { return n === node; });
    }

    function throwIfCurrentlyResolving(node) {
      if (resolving[node]) {
        throw new Error("Cycle detected: ['" + Object.keys(resolving).join("', '") + "'].");
      }
    }
    return resolved;
  };
  return instance;
};

<commit_msg>Support running  in a modern browser.<commit_after>/*
Copyright (c) 2012 Mario Pareja

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

var deppy, exports;
if (exports) {
  deppy = exports;
} else {
  deppy = window.deppy = {};
}

deppy.create = function () {
  var nodes = {};
  var instance = function (node, deps) {
    nodes[node] = {
      name: node,
      deps: Array.isArray(deps) ? deps : []
    };
  };

  instance.resolve = function (node) {
    var resolved = [],
      resolving = {};
    resolveDeps(node);

    function resolveDeps(node) {
      if (!alreadyResolved(node)) {
        throwIfCurrentlyResolving(node);

        markAsBeingResolved(node);

        var current = nodes[node];
        if (!current) { throw new Error('Node not found: ' + node); }
        current.deps.forEach(function (dep) {
          resolveDeps(dep);
        });

        markAsResolved(node);
      }
    }

    function markAsBeingResolved(node) {
      resolving[node] = true;
    }

    function markAsResolved(node) {
      resolved.push(node);
      delete resolving[node];
    }

    function alreadyResolved(node) {
      return resolved.some(function (n) { return n === node; });
    }

    function throwIfCurrentlyResolving(node) {
      if (resolving[node]) {
        throw new Error("Cycle detected: ['" + Object.keys(resolving).join("', '") + "'].");
      }
    }
    return resolved;
  };
  return instance;
};

<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
  PanResponder,
  View,
  Text,
  StyleSheet,
  LayoutAnimation,
  UIManager
} from 'react-native';
import timer from 'react-native-timer';

UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);

class LocalNotification extends Component {

  constructor(props) {
    super(props);

    this._panResponder = null;
    this.fullTextHeight = null;
    this.textHeightSetCurrentTouch = false;
    this.startHeight = this.props.startHeight;

    this.state = {
      topMargin: -100,
      textHeight: this.startHeight,
      isShowing: false,
    };
  }

  componentDidMount() {
    timer.setTimeout('duration', this.hideNotification.bind(this), this.props.duration);
  }

  isPress(y, x) {
    return Math.abs(y) < 4 && Math.abs(x) < 4;
  }

  hideNotification() {
    const config = {
      ...LayoutAnimation.Presets.linear,
      duration: 250,
    }
    LayoutAnimation.configureNext(config, () => {
      this.props.onNotificationHide && this.props.onNotificationHide();
    });
    this.setState({topMargin: -200});
  }

  componentWillMount() {
    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
      onPanResponderTerminationRequest: (evt, gestureState) => true,
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onShouldBlockNativeResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onPanResponderTerminate: (evt, gestureState) => {},
      onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
        Math.abs(gestureState.dx) > 100 || Math.abs(gestureState.dy) > 1,
      onPanResponderGrant: (evt, gestureState) => {
        this.textHeightSetCurrentTouch = false;
        timer.clearTimeout('duration');
      },
      onPanResponderMove: (evt, gestureState) => {
        if (this.state.textHeight < this.fullTextHeight && gestureState.dy > 0) {
          this.setState({
            textHeight: (gestureState.dy + this.startHeight) > this.fullTextHeight ? this.fullTextHeight : gestureState.dy + this.startHeight,
          });

          this.textHeightSetCurrentTouch = true;
          return;
        }
        else if(gestureState.dy < 110 && this.textHeightSetCurrentTouch) {
          this.setState({
            topMargin: gestureState.dy - (this.state.textHeight - this.startHeight),
          });
        }
        else if (gestureState.dy < 110) {
          this.setState({
            topMargin: gestureState.dy,
          });
        }
      },
      onPanResponderRelease: (evt, gestureState) => {
        if (this.isPress(gestureState.dy, gestureState.dx)) {
          this.props.onNotificationPress && this.props.onNotificationPress();
          this.hideNotification();
        }
        else {
          if (this.state.topMargin > 0) {
            LayoutAnimation.easeInEaseOut();
            this.setState({ topMargin: 0 });
          }
          else if (this.state.textHeight < this.fullTextHeight && this.state.topMargin >= 0) {
            LayoutAnimation.easeInEaseOut();
            this.setState({ textHeight: this.fullTextHeight });
          }
          else if (this.state.topMargin < 0){
            this.hideNotification();
          }
        }
      },
    });
  }

  onLayout(e) {
    if (!this.state.isShowing) {
      this.props.onNotificationWillShow && this.props.onNotificationWillShow();

      LayoutAnimation.easeInEaseOut();
      this.setState({
        topMargin: 0,
        isShowing: true,
      });

      this.fullTextHeight = e.nativeEvent.layout.height;
    }
  }

  render() {
    const isdragged = this.state.textHeight > this.startHeight;

    return (
      <View style={styles.wrapper}>
        <View {...this._panResponder.panHandlers} style={[styles.animatedView, {marginTop: -280 + this.state.topMargin + this.state.textHeight}]}>
          <View style={[styles.innerView, this.props.notificationStyle]}>
            <Text style={[styles.ellipsizeText,{ opacity: isdragged ? 0 : 1 }, this.props.ellipsizeTextStyle]} ellipsizeMode="tail" numberOfLines={2}>{this.props.text}</Text>
            <View style={[styles.textWrapper, {height: this.state.textHeight, marginTop: -1 * this.state.textHeight, opacity: isdragged ? 1 : 0}]}>
              <Text style={[styles.text, this.props.textStyle]} onLayout={(e) => this.onLayout(e)} ellipsizeMode="tail" numberOfLines={5}>{this.props.text}</Text>
            </View>
            <View style={[styles.handle, this.props.handleStyle]} />
          </View>
        </View>
      </View>
    );
  }
}

LocalNotification.propTypes = {
  text: React.PropTypes.string.isRequired,
  startHeight: React.PropTypes.number.isRequired,
  duration: React.PropTypes.number.isRequired,
  onNotificationPress: React.PropTypes.func,
  onNotificationWillShow: React.PropTypes.func,
}

LocalNotification.defaultProps = {
  text: 'Hello 👋',
  textStyle: {},
  handleStyle: {},
  notificationStyle: {},
  ellipsizeTextStyle: {},
  startHeight: 46,
  duration: 3500,
};

const styles = StyleSheet.create({
  wrapper: {
    position: 'absolute',
    top: 0,
    left: -1,
    right: -1,
    backgroundColor: 'transparent'
  },
  animatedView: {
    backgroundColor: 'transparent',
    flex: 1,
  },
  innerView: {
    backgroundColor: 'white',
    borderColor: '#ddd',
    borderBottomWidth: StyleSheet.hairlineWidth,
    borderRightWidth: StyleSheet.hairlineWidth,
    borderLeftWidth: StyleSheet.hairlineWidth,
    paddingTop: 300,
    borderBottomLeftRadius: 4,
    borderBottomRightRadius: 4,
    justifyContent: 'flex-end'
  },
  ellipsizeText: {
    position: 'absolute',
    top: 254,
    paddingVertical: 8,
    paddingHorizontal: 16,
    left: 0,
    right: 0,
    fontSize: 16
  },
  textWrapper: {
    backgroundColor: 'transparent',
    flex: 1,
    overflow: 'hidden'
  },
  text: {
    fontSize: 16,
    paddingVertical: 8,
    paddingHorizontal: 16,
  },
  handle: {
    width: 40,
    height: 4,
    borderRadius: 40,
    backgroundColor: 'rgba(0,0,0,.2)',
    marginBottom: 6,
    marginTop: 12,
    alignSelf: 'center'
  }
})

export default LocalNotification;
<commit_msg>Addding title prop to notification and move so lib handels showing multiple notifications by itself<commit_after>import React, { Component } from 'react';
import {
  PanResponder,
  View,
  Text,
  StyleSheet,
  LayoutAnimation,
  StatusBar,
  UIManager
} from 'react-native';
import timer from 'react-native-timer';

UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);

class LocalNotificationItem extends Component {

  constructor(props) {
    super(props);

    this._panResponder = null;
    this.fullTextHeight = null;
    this.textHeightSetCurrentTouch = false;
    this.startHeight = this.props.startHeight;

    this.state = {
      topMargin: -100,
      textHeight: this.startHeight,
      isShowing: false,
    };
  }

  componentDidMount() {
    timer.setTimeout('duration', this.hideNotification.bind(this), this.props.duration);
  }

  isPress(y, x) {
    return Math.abs(y) < 4 && Math.abs(x) < 4;
  }

  hideNotification() {
    const config = {
      ...LayoutAnimation.Presets.linear,
      duration: 250,
    }
    LayoutAnimation.configureNext(config, () => {
      this.props.onNotificationHide && this.props.onNotificationHide();
    });
    this.setState({topMargin: -200});
  }

  componentWillMount() {
    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
      onPanResponderTerminationRequest: (evt, gestureState) => true,
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onShouldBlockNativeResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onPanResponderTerminate: (evt, gestureState) => {},
      onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
        Math.abs(gestureState.dx) > 100 || Math.abs(gestureState.dy) > 1,
      onPanResponderGrant: (evt, gestureState) => {
        this.textHeightSetCurrentTouch = false;
        timer.clearTimeout('duration');
      },
      onPanResponderMove: (evt, gestureState) => {
        if (this.state.textHeight < this.fullTextHeight && gestureState.dy > 0) {
          this.setState({
            textHeight: (gestureState.dy + this.startHeight) > this.fullTextHeight ? this.fullTextHeight : gestureState.dy + this.startHeight,
          });

          this.textHeightSetCurrentTouch = true;
          return;
        }
        else if(gestureState.dy < 110 && this.textHeightSetCurrentTouch) {
          this.setState({
            topMargin: gestureState.dy - (this.state.textHeight - this.startHeight),
          });
        }
        else if (gestureState.dy < 110) {
          this.setState({
            topMargin: gestureState.dy,
          });
        }
      },
      onPanResponderRelease: (evt, gestureState) => {
        if (this.isPress(gestureState.dy, gestureState.dx)) {
          this.props.onNotificationPress && this.props.onNotificationPress();
          this.hideNotification();
        }
        else {
          if (this.state.topMargin > 0) {
            LayoutAnimation.easeInEaseOut();
            this.setState({ topMargin: 0 });
          }
          else if (this.state.textHeight < this.fullTextHeight && this.state.topMargin >= 0) {
            LayoutAnimation.easeInEaseOut();
            this.setState({ textHeight: this.fullTextHeight });
          }
          else if (this.state.topMargin < 0){
            this.hideNotification();
          }
        }
      },
    });
  }

  onLayout(e) {
    if (!this.state.isShowing) {
      this.props.onNotificationWillShow && this.props.onNotificationWillShow();

      LayoutAnimation.easeInEaseOut();
      this.setState({
        topMargin: 0,
        isShowing: true,
      });

      this.fullTextHeight = e.nativeEvent.layout.height;
    }
  }

  render() {
    const isdragged = this.state.textHeight > this.startHeight;
    console.log(this.props.title)
    return (
      <View style={styles.wrapper}>
        <View {...this._panResponder.panHandlers} style={[styles.animatedView, {marginTop: -280 + this.state.topMargin + this.state.textHeight}]}>
          <View style={[styles.innerView, this.props.notificationStyle]}>
            <View style={[styles.ellipsizeWrapper,{ opacity: isdragged ? 0 : 1 }]}>
              {this.props.title && (<Text style={[styles.title]} ellipsizeMode="tail" numberOfLines={1}>{this.props.title}</Text>)}
              <Text style={[styles.ellipsizeText,this.props.ellipsizeTextStyle]} ellipsizeMode="tail" numberOfLines={2}>{this.props.text}</Text>
            </View>
            <View style={[styles.textWrapper, {height: (this.state.textHeight + (this.props.title ? 22 : 0)), marginTop: -1 * (this.state.textHeight), opacity: isdragged ? 1 : 0}]}>
              {this.props.title && (<Text style={[styles.title]} ellipsizeMode="tail" numberOfLines={1}>{this.props.title}</Text>)}
              <Text style={[styles.text, this.props.textStyle]} onLayout={(e) => this.onLayout(e)} ellipsizeMode="tail" numberOfLines={5}>{this.props.text}</Text>
            </View>
            <View style={[styles.handle, this.props.handleStyle]} />
          </View>

        </View>
      </View>
    );
  }
}

LocalNotificationItem.propTypes = {
  title: React.PropTypes.string,
  text: React.PropTypes.string.isRequired,
  startHeight: React.PropTypes.number.isRequired,
  duration: React.PropTypes.number.isRequired,
  onNotificationPress: React.PropTypes.func,
  onNotificationWillShow: React.PropTypes.func,
}

LocalNotificationItem.defaultProps = {
  title: null,
  text: 'Hello 👋',
  textStyle: {},
  handleStyle: {},
  notificationStyle: {},
  ellipsizeTextStyle: {},
  startHeight: 44,
  duration: 3500,
};

const styles = StyleSheet.create({
  wrapper: {
    position: 'absolute',
    top: 0,
    left: -1,
    right: -1,
    backgroundColor: 'transparent'
  },
  animatedView: {
    backgroundColor: 'transparent',
    flex: 1,
  },
  innerView: {
    backgroundColor: 'white',
    borderColor: '#ddd',
    borderBottomWidth: StyleSheet.hairlineWidth,
    borderRightWidth: StyleSheet.hairlineWidth,
    borderLeftWidth: StyleSheet.hairlineWidth,
    paddingTop: 285,
    borderBottomLeftRadius: 4,
    borderBottomRightRadius: 4,
    justifyContent: 'flex-end'
  },
  title: {
    height: 22,
    color: 'black',
    fontWeight: 'bold',
    paddingHorizontal: 16,
    justifyContent: 'flex-end',
    paddingTop: 4,
    fontSize: 16,
  },
  ellipsizeWrapper: {
    position: 'absolute',
    top: 241,
    left: 0,
    right: 0
  },
  ellipsizeText: {
    fontSize: 16,
    paddingTop: 4,
    paddingBottom: 8,
    paddingHorizontal: 16
  },
  textWrapper: {
    backgroundColor: 'transparent',
    flex: 1,
    overflow: 'hidden',
  },
  text: {
    fontSize: 16,
    paddingTop: 4,
    paddingBottom: 8,
    paddingHorizontal: 16,
    color: '#333'
  },
  handle: {
    width: 40,
    height: 4,
    borderRadius: 40,
    backgroundColor: 'rgba(0,0,0,.2)',
    marginBottom: 6,
    marginTop: 12,
    alignSelf: 'center'
  }
})

class LocalNotification extends Component {

  constructor(props) {
    super(props);
  }

  componentWillReceiveProps(newProps) {
    newProps.notifications.length > 0 ?
      StatusBar.setHidden(true, false) :
      StatusBar.setHidden(false, true);
  }

  render() {
    return (
      <View style={{position: 'absolute', top: 0, left: 0, right: 0}}>
        {this.props.notifications.map((item, i) => (
          <LocalNotificationItem key={i} title={item.title} text={item.text} onNotificationPress={this.props.onNotificationPress} onNotificationHide={this.props.onNotificationHide} />
        ))}
      </View>
    );
  }
}

export default LocalNotification;
<|endoftext|>


<commit_before>'use strict'

var events = []
var eventsFired = {}
const EventEmitter = require('events')

class HeadRush extends EventEmitter {
    constructor(eventsProvided) {
        super()
        if (!events.length) {
            events = eventsProvided
        }
        if (!events && !eventsProvided) {
            throw new Error('Initial events need to be present to stun')
        }
    }

    stun(event) {
        if (events.indexOf(event) >= 0) {
            eventsFired[event] = true
            if (Object.keys(eventsFired).length >= events.length) {
                eventsFired = events = null
                this.emit('ready')
            }
        } else {
            throw new Error('Event stunned not present in the expected events set')
        }
    }
}

module.exports = HeadRush
<commit_msg>return a singleton instance<commit_after>'use strict'

var events = []
var eventsFired = {}
const EventEmitter = require('events')
var instance = undefined

class HeadRush extends EventEmitter {
    constructor(eventsProvided) {
        super()
        if (!events.length) {
            events = eventsProvided
        }
        if (!events && !eventsProvided) {
            throw new Error('Initial events need to be present to stun')
        }

        if(instance) return instance
        instance = this
    }

    stun(event) {
        if (events.indexOf(event) >= 0) {
            eventsFired[event] = true
            if (Object.keys(eventsFired).length >= events.length) {
                eventsFired = events = null
                this.emit('ready')
            }
        } else {
            throw new Error('Event stunned not present in the expected events set')
        }
    }
}

module.exports = HeadRush
<|endoftext|>


<commit_before>'use strict'

const Telegram = require('telegram-node-bot')
const TelegramBaseController = Telegram.TelegramBaseController
const TextCommand = Telegram.TextCommand
const tg = new Telegram.Telegram('438965853:AAGwB7Y5g8KqM3OVjkQilBuOrvCh8s9ZqmM',{workers: 1});
var ship = [
	'http://i.imgur.com/b7bzy0C.png',
	'http://i.imgur.com/hse69ui.jpg',
	'http://i.imgur.com/pyjpvhM.gif',
	'http://i.imgur.com/66j50Xz.jpg',
	'http://i.imgur.com/tCiQSlg.jpg',
	'http://i.imgur.com/DDLLoL8.gif',
	'http://i.imgur.com/LDzcDY3.jpg',
	'http://i.imgur.com/nkeMpLe.jpg',
	'http://i.imgur.com/ACaARFw.jpg',
	'http://i.imgur.com/aJkhUrE.jpg',
	'http://i.imgur.com/YBdJsaS.jpg',
	'http://i.imgur.com/KmZrtgd.jpg',
	'http://i.imgur.com/rmgCY2Q.jpg',
	'http://i.imgur.com/g00lVs9.gif',
	'http://i.imgur.com/LIIXWmD.png',
	'http://i.imgur.com/c6K9rP3.jpg',
	'http://i.imgur.com/2M8iyPt.jpg',
	'http://i.imgur.com/7XxnrTu.jpg',
	'http://i.imgur.com/AJN04yl.jpg',
	'http://i.imgur.com/rcIMpM0.gif',
	'http://i.imgur.com/60u8kye.jpg',
	'http://i.imgur.com/yUypmaC.jpg',
	'http://i.imgur.com/IflZleY.jpg',
	'http://i.imgur.com/h3mlvCq.png',
	'http://i.imgur.com/dXzZETc.png',
	'https://media.giphy.com/media/143vPc6b08locw/giphy.gif',
	'https://media0.giphy.com/media/14tFXhhNurdGp2/giphy.gif',
	'https://media4.giphy.com/media/ta83CqOoRwfwQ/giphy.gif',
	'https://media2.giphy.com/media/tDafHUBVrRKtq/giphy.gif',
	'https://media2.giphy.com/media/tDafHUBVrRKtq/giphy.gif',
]
var doit = [
	'http://i.imgur.com/RPbK0fZ.png',
	'http://i.imgur.com/TgUQfNI.jpg',
	'http://i.imgur.com/WSm116p.jpg',
]

class shipController extends TelegramBaseController {
    /**
     * @param {Scope} $
     */

    shipHandler($) {
        $.sendMessage(ship[Math.floor(Math.random()*ship.length)])
    }

    get routes() {
        return {
            'shipCommand': 'shipHandler'
        }
    }
}

class doController extends TelegramBaseController {
	doHandler($) {
		$.sendMessage(doit[Math.floor(Math.random()*doit.length)])
	}

	get routes(){
		return{
			'doCommand': 'doHandler'
		}
	}
}

tg.router
    .when(
        new TextCommand('/shipit', 'shipCommand'),
        new shipController()
    )
	.when(
		new TextCommand('/doit','doCommand'),
		new doController()
	)
<commit_msg>Added command /lorem<commit_after>'use strict'

const Telegram = require('telegram-node-bot')
const TelegramBaseController = Telegram.TelegramBaseController
const TextCommand = Telegram.TextCommand
const tg = new Telegram.Telegram('438965853:AAGwB7Y5g8KqM3OVjkQilBuOrvCh8s9ZqmM',{workers: 1});
var ship = [
	'http://i.imgur.com/b7bzy0C.png',
	'http://i.imgur.com/hse69ui.jpg',
	'http://i.imgur.com/pyjpvhM.gif',
	'http://i.imgur.com/66j50Xz.jpg',
	'http://i.imgur.com/tCiQSlg.jpg',
	'http://i.imgur.com/DDLLoL8.gif',
	'http://i.imgur.com/LDzcDY3.jpg',
	'http://i.imgur.com/nkeMpLe.jpg',
	'http://i.imgur.com/ACaARFw.jpg',
	'http://i.imgur.com/aJkhUrE.jpg',
	'http://i.imgur.com/YBdJsaS.jpg',
	'http://i.imgur.com/KmZrtgd.jpg',
	'http://i.imgur.com/rmgCY2Q.jpg',
	'http://i.imgur.com/g00lVs9.gif',
	'http://i.imgur.com/LIIXWmD.png',
	'http://i.imgur.com/c6K9rP3.jpg',
	'http://i.imgur.com/2M8iyPt.jpg',
	'http://i.imgur.com/7XxnrTu.jpg',
	'http://i.imgur.com/AJN04yl.jpg',
	'http://i.imgur.com/rcIMpM0.gif',
	'http://i.imgur.com/60u8kye.jpg',
	'http://i.imgur.com/yUypmaC.jpg',
	'http://i.imgur.com/IflZleY.jpg',
	'http://i.imgur.com/h3mlvCq.png',
	'http://i.imgur.com/dXzZETc.png',
	'https://media.giphy.com/media/143vPc6b08locw/giphy.gif',
	'https://media0.giphy.com/media/14tFXhhNurdGp2/giphy.gif',
	'https://media4.giphy.com/media/ta83CqOoRwfwQ/giphy.gif',
	'https://media2.giphy.com/media/tDafHUBVrRKtq/giphy.gif',
	'https://media2.giphy.com/media/tDafHUBVrRKtq/giphy.gif',
]
var doit = [
	'http://i.imgur.com/RPbK0fZ.png',
	'http://i.imgur.com/TgUQfNI.jpg',
	'http://i.imgur.com/WSm116p.jpg',
]

class shipController extends TelegramBaseController {
    /**
     * @param {Scope} $
     */

    shipHandler($) {
        $.sendMessage(ship[Math.floor(Math.random()*ship.length)])
    }

    get routes() {
        return {
            'shipCommand': 'shipHandler'
        }
    }
}

class doController extends TelegramBaseController {
	doHandler($) {
		$.sendMessage(doit[Math.floor(Math.random()*doit.length)])
	}

	get routes(){
		return{
			'doCommand': 'doHandler'
		}
	}
}

class loremController extends TelegramBaseController {
	loremHandler($) {
		var var1 = Math.floor(Math.random()*(1080 - 400)+400)
		var var2 = Math.floor(Math.random()*(400 - 200)+200)
		$.sendMessage('lorempixel.com/'+var1+'/'+var2)
		$.sendMessage('Dieses moderne und zugleich zeitlose Bild schafft es, durch seine Komposition die Einstellung des Künstlers zu der gezeigten Thematik in vielschichtiger Weise wiederzugeben.')
	}

	get routes() {
		return{
			'loremCommand': 'loremHandler'
		}
	}
}

tg.router
    .when(
        new TextCommand('/shipit', 'shipCommand'),
        new shipController()
    )
	.when(
		new TextCommand('/doit','doCommand'),
		new doController()
	)
	.when(
		new TextCommand('/lorem','loremCommand'),
		new loremController()
	)
<|endoftext|>


<commit_before>'use strict';
var bodyParser = require('body-parser');
var express = require('express');
var gitHubWebHook = require('express-github-webhook');

var commentOnClosedIssue = require('./lib/commentOnClosedIssue');
var Settings = require('./lib/Settings');

Settings.loadRepositoriesSettings('./config.json')
.then(function (repositoryNames) {
    var webHookHandler = gitHubWebHook({
        path: Settings.listenPath,
        secret: Settings.secret
    });

    var app = express();
    app.use(bodyParser.json());
    app.use(webHookHandler);

    repositoryNames.forEach(function (repositoryName) {
        console.log('Listening to', repositoryName);
        webHookHandler.on(repositoryName, function (event, jsonResponse) {
            console.log('Received event to repository:', repositoryName);
            console.log('event:', event);
            console.log('jsonResponse:', jsonResponse);
            //var repository = Settings.repositories[repositoryName];
            if (event === 'issues' &&
                jsonResponse.action === 'closed') {
                commentOnClosedIssue(jsonResponse, {
                    'User-Agent': 'cesium-concierge',
                    Authorization: 'token ' + Settings.get(repositoryName, 'gitHubToken')
                }).then(function (status) {
                    console.log('GitHub API returned with:', status);
                }).catch(function (e) {
                    console.log('commentOnClosedIssue got an error:', e);
                });
            }
        });
    });

    webHookHandler.on('error', function (err, req, res) { // eslint-disable-line no-unused-vars
        console.log('WebHookHandler got error:', err);
    });

    // Start server on port specified by env.PORT
    app.listen(Settings.port, function () {
        console.log('cesium-concierge listening on port', Settings.port);
    });
})
.catch(function (err) {
    console.log('Could not parse environment settings:', err);
    process.exit(1);
});
<commit_msg>Improvev logging, fix Settings usage.<commit_after>'use strict';
var bodyParser = require('body-parser');
var express = require('express');
var gitHubWebHook = require('express-github-webhook');

var commentOnClosedIssue = require('./lib/commentOnClosedIssue');
var Settings = require('./lib/Settings');

Settings.loadRepositoriesSettings('./config.json')
.then(function (repositoryNames) {
    var webHookHandler = gitHubWebHook({
        path: Settings.listenPath,
        secret: Settings.secret
    });

    var app = express();
    app.use(bodyParser.json());
    app.use(webHookHandler);

    repositoryNames.forEach(function (repositoryName) {
        console.log(new Date(Date.now()).toISOString() + ' Listening to', repositoryName);
        webHookHandler.on(repositoryName, function (event, jsonResponse) {
            console.log(new Date(Date.now()).toISOString() + ' Received event to repository:', repositoryName);
            console.log(new Date(Date.now()).toISOString() + ' event:', event);
            console.log(new Date(Date.now()).toISOString() + ' jsonResponse:', jsonResponse);
            //var repository = Settings.repositories[repositoryName];
            if (event === 'issues' &&
                jsonResponse.action === 'closed') {
                commentOnClosedIssue(jsonResponse, {
                    'User-Agent': 'cesium-concierge',
                    Authorization: 'token ' + Settings.repositories[repositoryName].gitHubToken
                }).then(function (status) {
                    console.log(new Date(Date.now()).toISOString() + ' GitHub API returned with:', status);
                }).catch(function (e) {
                    console.log(new Date(Date.now()).toISOString() + ' commentOnClosedIssue got an error:', e);
                });
            }
        });
    });

    webHookHandler.on('error', function (err, req, res) { // eslint-disable-line no-unused-vars
        console.log(new Date(Date.now()).toISOString() + ' WebHookHandler got error:', err);
    });

    // Start server on port specified by env.PORT
    app.listen(Settings.port, function () {
        console.log(new Date(Date.now()).toISOString() + ' cesium-concierge listening on port', Settings.port);
    });
})
.catch(function (err) {
    console.log('Could not parse environment settings:', err);
    process.exit(1);
});
<|endoftext|>


<commit_before>module.exports = kyu

// Initiate kyu apps
// (object) -> object
function kyu (options) {
  if (!options) {
    return { }
  }

  var _model = options.model
  var _update = options.update
  var _render = options.render

  var app = {
    model: _model,
    update: update,
    render: render,
    map: map
  }

  function newMsg (msg, nextMsgVal) {
    if (msg.next === null) {
      return {
        val: msg.val,
        next: {
          val: nextMsgVal,
          next: null
        }
      }
    } else {
      return {
        val: msg.val,
        next: newMsg(msg.next, nextMsgVal)
      }
    }
  }

  function update (msg) {
    app.model = _update(msg, app.model)

    if (typeof options.onUpdate === 'function') {
      options.onUpdate()
    }
  }

  function render () {
    return _render(app.model, app.update, app.map, null)
  }

  function map (msgVal, msg) {
    if (!msg) {
      return {
        val: msgVal,
        next: null
      }
    } else {
      return newMsg(msg, msgVal)
    }
  }

  return app
}
<commit_msg>Refactor<commit_after>module.exports = kyu

// Initiate kyu apps
// (object) -> object
function kyu (options) {
  if (!options) {
    return { }
  }

  var _model = options.model
  var _update = options.update
  var _render = options.render

  var app = {
    model: _model,
    update: update,
    render: render,
    map: map
  }

  // Update the app's model and run custom command
  // (object)
  function update (msg) {
    app.model = _update(msg, app.model)

    if (typeof options.onUpdate === 'function') {
      options.onUpdate()
    }
  }

  // Get current view
  // () -> any
  function render () {
    return _render(app.model, app.update, app.map, null)
  }

  // Add new msg
  // (number/string, object) -> object
  function map (msgVal, msg) {
    if (!msg) {
      return {
        val: msgVal,
        next: null
      }
    } else if (!msg.next) {
      return {
        val: msg.val,
        next: {
          val: msgVal,
          next: null
        }
      }
    } else {
      return {
        val: msg.val,
        next: map(msgVal, msg.next)
      }
    }
  }

  return app
}
<|endoftext|>


<commit_before>'use strict'

var isObj = require('isobj')

var Flatten = module.exports = function (obj, options) {
  options = options || {}
  var blacklist = options.blacklist || []
  var separator = options.separator == null ? '.' : options.separator

  var isBlacklisted = function (obj) {
    return blacklist.some(function (type) {
      return obj instanceof type
    })
  }

  var result = {}

  (function iterator (obj, prefix) {
    var n = 0
    var keys = Object.keys(obj)
    var len = keys.length
    var key, val

    for (; n < len; n++) {
      key = keys[n]
      val = obj[key]

      if (isObj(val) && !isBlacklisted(val)) {
        iterator(val, prefix + key + separator)
        continue
      }

      result[prefix + key] = val
    }
  })(obj, '')

  return result
}
<commit_msg>standard: remove unused variable<commit_after>'use strict'

var isObj = require('isobj')

module.exports = function flatten (obj, options) {
  options = options || {}
  var blacklist = options.blacklist || []
  var separator = options.separator == null ? '.' : options.separator

  var isBlacklisted = function (obj) {
    return blacklist.some(function (type) {
      return obj instanceof type
    })
  }

  var result = {}

  (function iterator (obj, prefix) {
    var n = 0
    var keys = Object.keys(obj)
    var len = keys.length
    var key, val

    for (; n < len; n++) {
      key = keys[n]
      val = obj[key]

      if (isObj(val) && !isBlacklisted(val)) {
        iterator(val, prefix + key + separator)
        continue
      }

      result[prefix + key] = val
    }
  })(obj, '')

  return result
}
<|endoftext|>


<commit_before>/*
 * MIT License http://opensource.org/licenses/MIT
 * Author: Ben Holloway @bholloway
 */
'use strict';

var path              = require('path'),
    fs                = require('fs'),
    loaderUtils       = require('loader-utils'),
    rework            = require('rework'),
    visit             = require('rework-visit'),
    convert           = require('convert-source-map'),
    camelcase         = require('camelcase'),
    defaults          = require('lodash.defaults'),
    SourceMapConsumer = require('source-map').SourceMapConsumer;

var findFile           = require('./lib/find-file'),
    absoluteToRelative = require('./lib/sources-absolute-to-relative'),
    adjustSourceMap    = require('adjust-sourcemap-loader/lib/process');

var PACKAGE_NAME = require('./package.json').name;

/**
 * A webpack loader that resolves absolute url() paths relative to their original source file.
 * Requires source-maps to do any meaningful work.
 * @param {string} content Css content
 * @param {object} sourceMap The source-map
 * @returns {string|String}
 */
function resolveUrlLoader(content, sourceMap) {
  /* jshint validthis:true */

  // details of the file being processed
  var loader   = this,
      filePath = path.dirname(loader.resourcePath);

  // webpack 1: prefer loader query, else options object
  // webpack 2; prefer loader options
  var options = defaults(loaderUtils.getOptions(loader), loader.options[camelcase(PACKAGE_NAME)], {
    absolute : false,
    sourceMap: false,
    fail     : false,
    silent   : false,
    keepQuery: false,
    debug    : false,
    root     : null
  });

  // validate root directory
  var resolvedRoot = (typeof options.root === 'string') && path.resolve(options.root) || undefined,
      isValidRoot  = resolvedRoot && fs.existsSync(resolvedRoot);
  if (options.root && !isValidRoot) {
    return handleException('"root" option does not resolve to a valid path');
  }

  // loader result is cacheable
  loader.cacheable();

  // incoming source-map
  var sourceMapConsumer, contentWithMap, sourceRoot;
  if (sourceMap) {

    // support non-standard string encoded source-map (per less-loader)
    if (typeof sourceMap === 'string') {
      try {
        sourceMap = JSON.parse(sourceMap);
      }
      catch (exception) {
        return handleException('source-map error', 'cannot parse source-map string (from less-loader?)');
      }
    }

    // Note the current sourceRoot before it is removed
    //  later when we go back to relative paths, we need to add it again
    sourceRoot = sourceMap.sourceRoot;

    // leverage adjust-sourcemap-loader's codecs to avoid having to make any assumptions about the sourcemap
    //  historically this is a regular source of breakage
    var absSourceMap;
    try {
      absSourceMap = adjustSourceMap(this, {format: 'absolute'}, sourceMap);
    }
    catch (exception) {
      return handleException('source-map error', exception.message);
    }

    // prepare the adjusted sass source-map for later look-ups
    sourceMapConsumer = new SourceMapConsumer(absSourceMap);

    // embed source-map in css for rework-css to use
    contentWithMap = content + convert.fromObject(absSourceMap).toComment({multiline: true});
  }
  // absent source map
  else {
    contentWithMap = content;
  }

  // process
  //  rework-css will throw on css syntax errors
  var useMap = loader.sourceMap || options.sourceMap,
      reworked;
  try {
    reworked = rework(contentWithMap, {source: loader.resourcePath})
      .use(reworkPlugin)
      .toString({
        sourcemap        : useMap,
        sourcemapAsObject: useMap
      });
  }
    //  fail gracefully
  catch (exception) {
    return handleException('CSS error', exception);
  }

  // complete with source-map
  if (useMap) {

    // source-map sources seem to be relative to the file being processed
    absoluteToRelative(reworked.map.sources, path.resolve(filePath, sourceRoot || '.'));

    // Set source root again
    reworked.map.sourceRoot = sourceRoot;

    // need to use callback when there are multiple arguments
    loader.callback(null, reworked.code, reworked.map);
  }
  // complete without source-map
  else {
    return reworked;
  }

  /**
   * Push an error for the given exception and return the original content.
   * @param {string} label Summary of the error
   * @param {string|Error} [exception] Optional extended error details
   * @returns {string} The original CSS content
   */
  function handleException(label, exception) {
    var rest = (typeof exception === 'string') ? [exception] :
               (exception instanceof Error) ? [exception.message, exception.stack.split('\n')[1].trim()] :
               [];
    var message = '  resolve-url-loader cannot operate: ' + [label].concat(rest).filter(Boolean).join('\n  ');
    if (options.fail) {
      loader.emitError(message);
    }
    else if (!options.silent) {
      loader.emitWarning(message);
    }
    return content;
  }

  /**
   * Plugin for css rework that follows SASS transpilation
   * @param {object} stylesheet AST for the CSS output from SASS
   */
  function reworkPlugin(stylesheet) {
    var URL_STATEMENT_REGEX = /(url\s*\()\s*(?:(['"])((?:(?!\2).)*)(\2)|([^'"](?:(?!\)).)*[^'"]))\s*(\))/g;

    // visit each node (selector) in the stylesheet recursively using the official utility method
    //  each node may have multiple declarations
    visit(stylesheet, function visitor(declarations) {
      if (declarations) {
        declarations
          .forEach(eachDeclaration);
      }
    });

    /**
     * Process a declaration from the syntax tree.
     * @param declaration
     */
    function eachDeclaration(declaration) {
      var isValid = declaration.value && (declaration.value.indexOf('url') >= 0),
          directory;
      if (isValid) {

        // reverse the original source-map to find the original sass file
        var startPosApparent = declaration.position.start,
            startPosOriginal = sourceMapConsumer && sourceMapConsumer.originalPositionFor(startPosApparent);

        // we require a valid directory for the specified file
        directory = startPosOriginal && startPosOriginal.source && path.dirname(startPosOriginal.source);
        if (directory) {

          // allow multiple url() values in the declaration
          //  split by url statements and process the content
          //  additional capture groups are needed to match quotations correctly
          //  escaped quotations are not considered
          declaration.value = declaration.value
            .split(URL_STATEMENT_REGEX)
            .map(eachSplitOrGroup)
            .join('');
        }
        // source-map present but invalid entry
        else if (sourceMapConsumer) {
          throw new Error('source-map information is not available at url() declaration');
        }
      }

      /**
       * Encode the content portion of url() statements.
       * There are 4 capture groups in the split making every 5th unmatched.
       * @param {string} token A single split item
       * @param i The index of the item in the split
       * @returns {string} Every 3 or 5 items is an encoded url everything else is as is
       */
      function eachSplitOrGroup(token, i) {
        var BACKSLASH_REGEX = /\\/g;

        // we can get groups as undefined under certain match circumstances
        var initialised = token || '';

        // the content of the url() statement is either in group 3 or group 5
        var mod = i % 7;
        if ((mod === 3) || (mod === 5)) {

          // split into uri and query/hash and then find the absolute path to the uri
          var split    = initialised.split(/([?#])/g),
              uri      = split[0],
              absolute = uri && findFile(options).absolute(directory, uri, resolvedRoot),
              query    = options.keepQuery ? split.slice(1).join('') : '';

          // use the absolute path (or default to initialised)
          if (options.absolute) {
            return absolute && absolute.replace(BACKSLASH_REGEX, '/').concat(query) || initialised;
          }
          // module relative path (or default to initialised)
          else {
            var relative     = absolute && path.relative(filePath, absolute),
                rootRelative = relative && loaderUtils.urlToRequest(relative, '~');
            return (rootRelative) ? rootRelative.replace(BACKSLASH_REGEX, '/').concat(query) : initialised;
          }
        }
        // everything else, including parentheses and quotation (where present) and media statements
        else {
          return initialised;
        }
      }
    }
  }
}

module.exports = resolveUrlLoader;
<commit_msg>#60 precedence of explicit sourceMap option<commit_after>/*
 * MIT License http://opensource.org/licenses/MIT
 * Author: Ben Holloway @bholloway
 */
'use strict';

var path              = require('path'),
    fs                = require('fs'),
    loaderUtils       = require('loader-utils'),
    rework            = require('rework'),
    visit             = require('rework-visit'),
    convert           = require('convert-source-map'),
    camelcase         = require('camelcase'),
    defaults          = require('lodash.defaults'),
    SourceMapConsumer = require('source-map').SourceMapConsumer;

var findFile           = require('./lib/find-file'),
    absoluteToRelative = require('./lib/sources-absolute-to-relative'),
    adjustSourceMap    = require('adjust-sourcemap-loader/lib/process');

var PACKAGE_NAME = require('./package.json').name;

/**
 * A webpack loader that resolves absolute url() paths relative to their original source file.
 * Requires source-maps to do any meaningful work.
 * @param {string} content Css content
 * @param {object} sourceMap The source-map
 * @returns {string|String}
 */
function resolveUrlLoader(content, sourceMap) {
  /* jshint validthis:true */

  // details of the file being processed
  var loader   = this,
      filePath = path.dirname(loader.resourcePath);

  // webpack 1: prefer loader query, else options object
  // webpack 2; prefer loader options
  var options = defaults(loaderUtils.getOptions(loader), loader.options[camelcase(PACKAGE_NAME)], {
    absolute : false,
    sourceMap: loader.sourceMap,
    fail     : false,
    silent   : false,
    keepQuery: false,
    debug    : false,
    root     : null
  });

  // validate root directory
  var resolvedRoot = (typeof options.root === 'string') && path.resolve(options.root) || undefined,
      isValidRoot  = resolvedRoot && fs.existsSync(resolvedRoot);
  if (options.root && !isValidRoot) {
    return handleException('"root" option does not resolve to a valid path');
  }

  // loader result is cacheable
  loader.cacheable();

  // incoming source-map
  var sourceMapConsumer, contentWithMap, sourceRoot;
  if (sourceMap) {

    // support non-standard string encoded source-map (per less-loader)
    if (typeof sourceMap === 'string') {
      try {
        sourceMap = JSON.parse(sourceMap);
      }
      catch (exception) {
        return handleException('source-map error', 'cannot parse source-map string (from less-loader?)');
      }
    }

    // Note the current sourceRoot before it is removed
    //  later when we go back to relative paths, we need to add it again
    sourceRoot = sourceMap.sourceRoot;

    // leverage adjust-sourcemap-loader's codecs to avoid having to make any assumptions about the sourcemap
    //  historically this is a regular source of breakage
    var absSourceMap;
    try {
      absSourceMap = adjustSourceMap(this, {format: 'absolute'}, sourceMap);
    }
    catch (exception) {
      return handleException('source-map error', exception.message);
    }

    // prepare the adjusted sass source-map for later look-ups
    sourceMapConsumer = new SourceMapConsumer(absSourceMap);

    // embed source-map in css for rework-css to use
    contentWithMap = content + convert.fromObject(absSourceMap).toComment({multiline: true});
  }
  // absent source map
  else {
    contentWithMap = content;
  }

  // process
  //  rework-css will throw on css syntax errors
  var reworked;
  try {
    reworked = rework(contentWithMap, {source: loader.resourcePath})
      .use(reworkPlugin)
      .toString({
        sourcemap        : options.sourceMap,
        sourcemapAsObject: options.sourceMap
      });
  }
    //  fail gracefully
  catch (exception) {
    return handleException('CSS error', exception);
  }

  // complete with source-map
  if (options.sourceMap) {

    // source-map sources seem to be relative to the file being processed
    absoluteToRelative(reworked.map.sources, path.resolve(filePath, sourceRoot || '.'));

    // Set source root again
    reworked.map.sourceRoot = sourceRoot;

    // need to use callback when there are multiple arguments
    loader.callback(null, reworked.code, reworked.map);
  }
  // complete without source-map
  else {
    return reworked;
  }

  /**
   * Push an error for the given exception and return the original content.
   * @param {string} label Summary of the error
   * @param {string|Error} [exception] Optional extended error details
   * @returns {string} The original CSS content
   */
  function handleException(label, exception) {
    var rest = (typeof exception === 'string') ? [exception] :
               (exception instanceof Error) ? [exception.message, exception.stack.split('\n')[1].trim()] :
               [];
    var message = '  resolve-url-loader cannot operate: ' + [label].concat(rest).filter(Boolean).join('\n  ');
    if (options.fail) {
      loader.emitError(message);
    }
    else if (!options.silent) {
      loader.emitWarning(message);
    }
    return content;
  }

  /**
   * Plugin for css rework that follows SASS transpilation
   * @param {object} stylesheet AST for the CSS output from SASS
   */
  function reworkPlugin(stylesheet) {
    var URL_STATEMENT_REGEX = /(url\s*\()\s*(?:(['"])((?:(?!\2).)*)(\2)|([^'"](?:(?!\)).)*[^'"]))\s*(\))/g;

    // visit each node (selector) in the stylesheet recursively using the official utility method
    //  each node may have multiple declarations
    visit(stylesheet, function visitor(declarations) {
      if (declarations) {
        declarations
          .forEach(eachDeclaration);
      }
    });

    /**
     * Process a declaration from the syntax tree.
     * @param declaration
     */
    function eachDeclaration(declaration) {
      var isValid = declaration.value && (declaration.value.indexOf('url') >= 0),
          directory;
      if (isValid) {

        // reverse the original source-map to find the original sass file
        var startPosApparent = declaration.position.start,
            startPosOriginal = sourceMapConsumer && sourceMapConsumer.originalPositionFor(startPosApparent);

        // we require a valid directory for the specified file
        directory = startPosOriginal && startPosOriginal.source && path.dirname(startPosOriginal.source);
        if (directory) {

          // allow multiple url() values in the declaration
          //  split by url statements and process the content
          //  additional capture groups are needed to match quotations correctly
          //  escaped quotations are not considered
          declaration.value = declaration.value
            .split(URL_STATEMENT_REGEX)
            .map(eachSplitOrGroup)
            .join('');
        }
        // source-map present but invalid entry
        else if (sourceMapConsumer) {
          throw new Error('source-map information is not available at url() declaration');
        }
      }

      /**
       * Encode the content portion of url() statements.
       * There are 4 capture groups in the split making every 5th unmatched.
       * @param {string} token A single split item
       * @param i The index of the item in the split
       * @returns {string} Every 3 or 5 items is an encoded url everything else is as is
       */
      function eachSplitOrGroup(token, i) {
        var BACKSLASH_REGEX = /\\/g;

        // we can get groups as undefined under certain match circumstances
        var initialised = token || '';

        // the content of the url() statement is either in group 3 or group 5
        var mod = i % 7;
        if ((mod === 3) || (mod === 5)) {

          // split into uri and query/hash and then find the absolute path to the uri
          var split    = initialised.split(/([?#])/g),
              uri      = split[0],
              absolute = uri && findFile(options).absolute(directory, uri, resolvedRoot),
              query    = options.keepQuery ? split.slice(1).join('') : '';

          // use the absolute path (or default to initialised)
          if (options.absolute) {
            return absolute && absolute.replace(BACKSLASH_REGEX, '/').concat(query) || initialised;
          }
          // module relative path (or default to initialised)
          else {
            var relative     = absolute && path.relative(filePath, absolute),
                rootRelative = relative && loaderUtils.urlToRequest(relative, '~');
            return (rootRelative) ? rootRelative.replace(BACKSLASH_REGEX, '/').concat(query) : initialised;
          }
        }
        // everything else, including parentheses and quotation (where present) and media statements
        else {
          return initialised;
        }
      }
    }
  }
}

module.exports = resolveUrlLoader;
<|endoftext|>


<commit_before>'use strict';

var React = require('react-native');
var { StyleSheet, Text, View, TextInput, Animated } = React;

var FloatingLabel = React.createClass({
  getInitialState: function() {
    var initialPadding = 9;
    var initialOpacity = 0;

    if (this.props.visible) {
      initialPadding = 5;
      initialOpacity = 1;
    }

    return {
      paddingAnim: new Animated.Value(initialPadding),
      opacityAnim: new Animated.Value(initialOpacity)
    };
  },

  componentWillReceiveProps: function(newProps) {
    Animated.timing(this.state.paddingAnim, {
      toValue: newProps.visible ? 5 : 9,
      duration: 230
    }).start();

    return Animated.timing(this.state.opacityAnim, {
      toValue: newProps.visible ? 1 : 0,
      duration: 230
    }).start();
  },

  render: function() {
    return(
      <Animated.View style={[styles.floatingLabel, {paddingTop: this.state.paddingAnim, opacity: this.state.opacityAnim}]}>
        {this.props.children}
      </Animated.View>
    );
  }
});

var TextFieldHolder = React.createClass({
  getInitialState: function() {
    return {
      marginAnim: new Animated.Value(this.props.withValue ? 10 : 0)
    };
  },

  componentWillReceiveProps: function(newProps) {
    return Animated.timing(this.state.marginAnim, {
      toValue: newProps.withValue ? 10 : 0,
      duration: 230
    }).start();
  },

  render: function() {
    return(
      <Animated.View style={{marginTop: this.state.marginAnim}}>
        {this.props.children}
      </Animated.View>
    );
  }
});

var FloatLabelTextField = React.createClass({
  getInitialState: function() {
    return {
      focussed: false,
      text: this.props.value
    };
  },

  getAdditionalStyle: function(name) {
    if (this.props.style && this.props.style[name])
    {
      return this.props.style[name];
    }

    return {};
  },

  render: function() {
    return(
      <View style={[styles.container, this.getAdditionalStyle('container')]}>
        <View style={[styles.viewContainer, this.getAdditionalStyle('viewContainer')]}>
          <View style={[styles.fieldContainer, this.getAdditionalStyle('fieldContainer')]}>
            <FloatingLabel visible={this.state.text}>
              <Text style={[styles.fieldLabel,
                            this.getAdditionalStyle('fieldLabel'),
                            this.labelStyle()]}>{this.placeHolderValue()}</Text>
            </FloatingLabel>
            <TextFieldHolder withValue={this.state.text}>
              <TextInput
                placeholder={this.props.placeHolder}
                style={[styles.valueText, this.getAdditionalStyle('valueText')]}
                value={this.state.text}
                onFocus={this.setFocus}
                onBlur={this.unsetFocus}
                onChangeText={this.setText}
                secureTextEntry={this.props.secureTextEntry}
                keyboardType={this.props.keyboardType}
              />
            </TextFieldHolder>
          </View>
        </View>
      </View>
    );
  },
  setFocus: function() {
    this.setState({
      focussed: true
    });
    try {
      return this.props.onFocus();
    } catch (_error) {}
  },

  unsetFocus: function() {
    this.setState({
      focussed: false
    });
    try {
      return this.props.onBlur();
    } catch (_error) {}
  },

  labelStyle: function() {
    if (this.state.focussed) {
      return  this.props.style && this.props.style.focussed ? this.props.style.focussed : styles.focussed;
    }
  },

  placeHolderValue: function() {
    if (this.state.text) {
      return this.props.placeHolder;
    }
  },

  setText: function(value) {
    this.setState({
      text: value
    });
    try {
      return this.props.onChangeTextValue(value);
    } catch (_error) {}
  },

  withMargin: function() {
    if (this.state.text) {
      return styles.withMargin;
    }
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    height: 45,
    justifyContent: 'center'
  },
  viewContainer: {
    flex: 1,
    flexDirection: 'row'
  },
  floatingLabel: {
    position: 'absolute',
    top: 0,
    left: 0
  },
  fieldLabel: {
    height: 10,
    fontSize: 9,
    color: '#B1B1B1',
    paddingLeft: 15
  },
  fieldContainer: {
    flex: 1,
    justifyContent: 'center',
    position: 'relative',
    borderBottomWidth: 1 / 2,
    borderColor: '#C8C7CC',
    backgroundColor: 'white',
    paddingLeft: 15
  },
  valueText: {
    height: 20,
    fontSize: 16,
    color: '#111111'
  },
  withMargin: {
    marginTop: 10
  },
  focussed: {
    color: "#1482fe"
  }
});

module.exports = FloatLabelTextField;
<commit_msg>standardize placeholder casing, add onChange<commit_after>'use strict';

var React = require('react-native');
var { StyleSheet, Text, View, TextInput, Animated } = React;

var FloatingLabel = React.createClass({
  getInitialState: function() {
    var initialPadding = 9;
    var initialOpacity = 0;

    if (this.props.visible) {
      initialPadding = 5;
      initialOpacity = 1;
    }

    return {
      paddingAnim: new Animated.Value(initialPadding),
      opacityAnim: new Animated.Value(initialOpacity)
    };
  },

  componentWillReceiveProps: function(newProps) {
    Animated.timing(this.state.paddingAnim, {
      toValue: newProps.visible ? 5 : 9,
      duration: 230
    }).start();

    return Animated.timing(this.state.opacityAnim, {
      toValue: newProps.visible ? 1 : 0,
      duration: 230
    }).start();
  },

  render: function() {
    return(
      <Animated.View style={[styles.floatingLabel, {paddingTop: this.state.paddingAnim, opacity: this.state.opacityAnim}]}>
        {this.props.children}
      </Animated.View>
    );
  }
});

var TextFieldHolder = React.createClass({
  getInitialState: function() {
    return {
      marginAnim: new Animated.Value(this.props.withValue ? 10 : 0)
    };
  },

  componentWillReceiveProps: function(newProps) {
    return Animated.timing(this.state.marginAnim, {
      toValue: newProps.withValue ? 10 : 0,
      duration: 230
    }).start();
  },

  render: function() {
    return(
      <Animated.View style={{marginTop: this.state.marginAnim}}>
        {this.props.children}
      </Animated.View>
    );
  }
});

var FloatLabelTextField = React.createClass({
  getInitialState: function() {
    return {
      focussed: false,
      text: this.props.value
    };
  },

  getAdditionalStyle: function(name) {
    if (this.props.style && this.props.style[name])
    {
      return this.props.style[name];
    }

    return {};
  },

  render: function() {
    return(
      <View style={[styles.container, this.getAdditionalStyle('container')]}>
        <View style={[styles.viewContainer, this.getAdditionalStyle('viewContainer')]}>
          <View style={[styles.fieldContainer, this.getAdditionalStyle('fieldContainer')]}>
            <FloatingLabel visible={this.state.text}>
              <Text style={[styles.fieldLabel,
                            this.getAdditionalStyle('fieldLabel'),
                            this.labelStyle()]}>{this.placeHolderValue()}</Text>
            </FloatingLabel>
            <TextFieldHolder withValue={this.state.text}>
              <TextInput
                placeholder={this.props.placeholder}
                style={[styles.valueText, this.getAdditionalStyle('valueText')]}
                value={this.state.text}
                onFocus={this.setFocus}
                onBlur={this.unsetFocus}
                onChangeText={this.setText}
                onChange={this.props.onChange}
                secureTextEntry={this.props.secureTextEntry}
                keyboardType={this.props.keyboardType}
                autoCapitalize={this.props.autoCapitalize}
              />
            </TextFieldHolder>
          </View>
        </View>
      </View>
    );
  },

  setFocus: function() {
    this.setState({
      focussed: true
    });
    try {
      return this.props.onFocus();
    } catch (_error) {}
  },

  unsetFocus: function() {
    this.setState({
      focussed: false
    });
    try {
      return this.props.onBlur();
    } catch (_error) {}
  },

  labelStyle: function() {
    if (this.state.focussed) {
      return  this.props.style && this.props.style.focussed ? this.props.style.focussed : styles.focussed;
    }
  },

  placeHolderValue: function() {
    if (this.state.text) {
      return this.props.placeholder;
    }
  },

  setText: function(value) {
    this.setState({
      text: value
    });
    try {
      return this.props.onChangeTextValue(value);
    } catch (_error) {}
  },

  withMargin: function() {
    if (this.state.text) {
      return styles.withMargin;
    }
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    height: 45,
    justifyContent: 'center'
  },
  viewContainer: {
    flex: 1,
    flexDirection: 'row'
  },
  floatingLabel: {
    position: 'absolute',
    top: 0,
    left: 0
  },
  fieldLabel: {
    height: 10,
    fontSize: 9,
    color: '#B1B1B1',
    paddingLeft: 15
  },
  fieldContainer: {
    flex: 1,
    justifyContent: 'center',
    position: 'relative',
    borderBottomWidth: 1 / 2,
    borderColor: '#C8C7CC',
    backgroundColor: 'white',
    paddingLeft: 15
  },
  valueText: {
    height: 20,
    fontSize: 16,
    color: '#111111'
  },
  withMargin: {
    marginTop: 10
  },
  focussed: {
    color: "#1482fe"
  }
});

module.exports = FloatLabelTextField;
<|endoftext|>


<commit_before>const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const session = require('express-session');
const passport = require('passport');
const FitbitStrategy = require( 'passport-fitbit-oauth2' ).FitbitOAuth2Strategy;
const app = express();
require('dotenv').config()

app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({
  secret: process.env.PASSPORT_SECRET,
  resave: false,
  saveUninitialized: true
 }));

app.use(passport.initialize());
app.use(passport.session());

// Serve static files from the React app
// app.use(express.static(path.join(__dirname, 'client/build')));

//passport-fitbit-oauth2 routing
passport.use(new FitbitStrategy({
    clientID: process.env.FITBIT_OAUTH2_CLIENT_ID,
    clientSecret: process.env.FITBIT_OAUTH2_SECRET,
    // callbackURL: "https://serene-green.herokuapp.com/auth/fitbit/callback"
    callbackURL: "http://localhost:5000/auth/fitbit/callback"
  },
  function onSuccessfulLogin(token, refreshToken, profile, done) {

      // This is a great place to find or create a user in the database
      // This function happens once after a successful login

      // Whatever you pass to `done` gets passed to `serializeUser`
      console.log(profile.displayName);
      done(null, {token, profile});
    }
  ));

passport.serializeUser(function(user, done) {
  // console.log('serializeUser', user);
  done(null, user);
});

passport.deserializeUser(function(obj, done) {
  // console.log('deserializeUser', obj);
  done(null, obj);
});

app.get('/auth/fitbit/success', function(req, res, next) {
  // res.send(req.user);
  res.send('Successful login!')
});

app.get('/auth/fitbit/failure', function(req, res, next) {
  // res.send(req.user);
  res.send('Try again...')
});

app.get('/auth/fitbit/success', function(req, res, next) {
  // res.send(req.user);
  res.send('Successful login!')
});

app.get('/auth/fitbit',
  passport.authenticate('fitbit', {scope: ['activity','heartrate','location','profile']}
));

app.get('/auth/fitbit/callback',
  passport.authenticate('fitbit', {
    successRedirect: '/auth/fitbit/success',
    failureRedirect: '/auth/fitbit/failure'
   }
));

// The "catchall" handler: for any request that doesn't
// match one above, send back React's index.html file.
// app.get('*', (req, res) => {
//   console.log('catchall');
//   // res.sendFile(path.join(__dirname+'/client/build/index.html'));
//   res.send('welcome');
// });

const port = process.env.PORT || 5000;
app.listen(port);

console.log(`Listening on ${port}`);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  const err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
// if (app.get('env') === 'development') {
//   app.use(function(err, req, res, next) {
//     res.status(err.status || 500);
//     res.render('error', {
//       message: err.message,
//       error: err
//     });
//   });
// }
//
// // production error handler
// // no stacktraces leaked to user
// app.use(function(err, req, res, next) {
//   res.status(err.status || 500);
//   res.render('error', {
//     message: err.message,
//     error: {}
//   });
// });
<commit_msg>switch Fitbit Strategy to herokuapp callback<commit_after>const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const session = require('express-session');
const passport = require('passport');
const FitbitStrategy = require( 'passport-fitbit-oauth2' ).FitbitOAuth2Strategy;
const app = express();
require('dotenv').config()

app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({
  secret: process.env.PASSPORT_SECRET,
  resave: false,
  saveUninitialized: true
 }));

app.use(passport.initialize());
app.use(passport.session());

// Serve static files from the React app
// app.use(express.static(path.join(__dirname, 'client/build')));

//passport-fitbit-oauth2 routing
passport.use(new FitbitStrategy({
    clientID: process.env.FITBIT_OAUTH2_CLIENT_ID,
    clientSecret: process.env.FITBIT_OAUTH2_SECRET,
    callbackURL: "https://serene-server.herokuapp.com/auth/fitbit/callback"
    // callbackURL: "http://localhost:5000/auth/fitbit/callback"
  },
  function onSuccessfulLogin(token, refreshToken, profile, done) {

      // This is a great place to find or create a user in the database
      // This function happens once after a successful login

      // Whatever you pass to `done` gets passed to `serializeUser`
      console.log(profile.displayName);
      done(null, {token, profile});
    }
  ));

passport.serializeUser(function(user, done) {
  // console.log('serializeUser', user);
  done(null, user);
});

passport.deserializeUser(function(obj, done) {
  // console.log('deserializeUser', obj);
  done(null, obj);
});

app.get('/auth/fitbit/success', function(req, res, next) {
  // res.send(req.user);
  res.send('Successful login!')
});

app.get('/auth/fitbit/failure', function(req, res, next) {
  // res.send(req.user);
  res.send('Try again...')
});

app.get('/auth/fitbit/success', function(req, res, next) {
  // res.send(req.user);
  res.send('Successful login!')
});

app.get('/auth/fitbit',
  passport.authenticate('fitbit', {scope: ['activity','heartrate','location','profile']}
));

app.get('/auth/fitbit/callback',
  passport.authenticate('fitbit', {
    successRedirect: '/auth/fitbit/success',
    failureRedirect: '/auth/fitbit/failure'
   }
));

// The "catchall" handler: for any request that doesn't
// match one above, send back React's index.html file.
// app.get('*', (req, res) => {
//   console.log('catchall');
//   // res.sendFile(path.join(__dirname+'/client/build/index.html'));
//   res.send('welcome');
// });

const port = process.env.PORT || 5000;
app.listen(port);

console.log(`Listening on ${port}`);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  const err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
// if (app.get('env') === 'development') {
//   app.use(function(err, req, res, next) {
//     res.status(err.status || 500);
//     res.render('error', {
//       message: err.message,
//       error: err
//     });
//   });
// }
//
// // production error handler
// // no stacktraces leaked to user
// app.use(function(err, req, res, next) {
//   res.status(err.status || 500);
//   res.render('error', {
//     message: err.message,
//     error: {}
//   });
// });
<|endoftext|>


<commit_before>'use strict';

var fs = require( 'fs' );
var checker = require( 'license-checker' );
var customFormatJSON = require( './customFormatExample.json' );

exports.getTermsFile = function( licenses, fileName ) {
  if (licenses.typeof !== Object) {
    throw new TypeError('licenses argument should be an object');
  }
  fs.readFile( fileName, 'utf8', function( err, fileContents ) {
    if ( err && err.fileNotFound || err && err.code === 'ENOENT' ) {
      throw new Error('File not found - you must add the ' + fileName + ' file to your project.');
    } else if ( err ) {
      throw new Error(err);
    } else {
      var licenseOutput = exports.addExceptions( licenses );
      var exceptionsContent = '## Exceptions';
      var removeOldExceptions = fileContents.split( exceptionsContent )[0];
      var newTerms = removeOldExceptions + licenseOutput;

      fs.writeFile( fileName, newTerms, 'utf8' );
    }

  });
}

exports.addExceptions = function( licenses ) {

  var formattedData = '## Exceptions\n\n Source code or other assets that are excluded from the terms. This list includes dependencies that may be licensed differently (not CC0-1.0) or are not in the public domain.\n\n';

  var licenseList = Object.keys( licenses ).map(
    function( license ) {
      return licenses[license];
    }
  );

  for ( var i = 0; i < licenseList.length; i++ ) {
    var licenseType = String( licenseList[i].licenses );
    // remove asterisk from license
    licenseType = licenseType.replace( /\*$/, '' );
    var repo = licenseList[i].repository;
    var name = licenseList[i].name;
    if ( repo == undefined ) {
      repo = 'https://www.npmjs.com/package/' + name;
    }
    var markItDown = '- [' + name + '](' + repo + '): ' + licenseType + '\n';
    formattedData += markItDown;
  }

  return formattedData;
}

exports.init = function(fileName) {
  if (fileName === undefined) {
    fileName = 'TERMS.md';
  }
  checker.init( {
    start: './',
    exclude: 'CC0-1.0, Public domain, public domain, Public Domain',
    // @todo fix path to be relative to node modules folder not project folder, write test!!!
    customPath: 'customFormatExample.json' // for this module
    // has to point to node_modules path for anything installing this
    // customPath: './node_modules/license-exceptions/customFormatExample.json'
    // customPath: customFormatJSON

  }, function( json, err ) {
    if ( err ) {
      // Handle error
      console.log( err );
    } else {
      exports.getTermsFile( json, fileName );
    }
  } );
};
<commit_msg>fix getTermsFile typeof check for licenses obj<commit_after>'use strict';

var fs = require( 'fs' );
var checker = require( 'license-checker' );
var customFormatJSON = require( './customFormatExample.json' );

exports.getTermsFile = function( licenses, fileName ) {
  if (typeof licenses !== 'object') {
    throw new TypeError('licenses argument should be an object');
  }
  fs.readFile( fileName, 'utf8', function( err, fileContents ) {
    if ( err && err.fileNotFound || err && err.code === 'ENOENT' ) {
      throw new Error('File not found - you must add the ' + fileName + ' file to your project.');
    } else if ( err ) {
      throw new Error(err);
    } else {
      var licenseOutput = exports.addExceptions( licenses );
      var exceptionsContent = '## Exceptions';
      var removeOldExceptions = fileContents.split( exceptionsContent )[0];
      var newTerms = removeOldExceptions + licenseOutput;

      fs.writeFile( fileName, newTerms, 'utf8' );
    }

  });
}

exports.addExceptions = function( licenses ) {

  var formattedData = '## Exceptions\n\n Source code or other assets that are excluded from the terms. This list includes dependencies that may be licensed differently (not CC0-1.0) or are not in the public domain.\n\n';

  var licenseList = Object.keys( licenses ).map(
    function( license ) {
      return licenses[license];
    }
  );

  for ( var i = 0; i < licenseList.length; i++ ) {
    var licenseType = String( licenseList[i].licenses );
    // remove asterisk from license
    licenseType = licenseType.replace( /\*$/, '' );
    var repo = licenseList[i].repository;
    var name = licenseList[i].name;
    if ( repo == undefined ) {
      repo = 'https://www.npmjs.com/package/' + name;
    }
    var markItDown = '- [' + name + '](' + repo + '): ' + licenseType + '\n';
    formattedData += markItDown;
  }

  return formattedData;
}

exports.init = function(fileName) {
  if (fileName === undefined) {
    fileName = 'TERMS.md';
  }
  checker.init( {
    start: './',
    exclude: 'CC0-1.0, Public domain, public domain, Public Domain',
    // @todo fix path to be relative to node modules folder not project folder, write test!!!
    customPath: 'customFormatExample.json' // for this module
    // has to point to node_modules path for anything installing this
    // customPath: './node_modules/license-exceptions/customFormatExample.json'
    // customPath: customFormatJSON

  }, function( json, err ) {
    if ( err ) {
      // Handle error
      console.log( err );
    } else {
      exports.getTermsFile( json, fileName );
    }
  } );
};
<|endoftext|>


<commit_before>/**
 * Created by zhaosc on 9/1/16.
 */
/**
 * init SSE
 * @param {Number} retry - retry time default 15000 ms
 * @return {Function}
 * */
module.exports = function InitSSE({retry}) {
    retry = retry || 15000;

    /**
     * add push function to res
     * @param {Response} res - express res or standard http response
     * */
    return function sse(res) {
        res.socket.setKeepAlive(true);
        res.socket.setTimeout(0);
        res.setHeader('Content-Type', 'text/event-stream');
        res.setHeader('Cache-Control', 'no-cache');
        res.setHeader('Connection', 'keep-alive');
        res.statusCode = 200;

        // export push to send server-side-events
        res.push = function push(data, event, id) {
            if (typeof data == 'object') {
                data = JSON.stringify(data);
            }
            if (event) {
                res.write('event: ' + event + '\n')
            }
            if (id !== undefined) {
                res.write('id: ' + id + '\n')
            }
            res.write("data: " + data + "\n\n");
        };

        // write 2kB of padding (for IE) and a reconnection timeout
        // then use res.sse to send to the client

        // res.write(':' + Array(2049).join(' ') + '\n');
        res.write('retry: ' + retry + '\n\n');

        // keep the connection open by sending a comment
        var keepAlive = setInterval(function () {
            if (res.finished) {
                clearInterval(keepAlive);
                return
            }
            res.write(':keep-alive\n');
        }, 20000);

        // cleanup on close
        res.on('close', function close() {
            clearInterval(keepAlive);
        });
    };
};<commit_msg>add save write for write after end<commit_after>/**
 * Created by zhaosc on 9/1/16.
 */
/**
 * init SSE
 * @param {Number} retry - retry time default 15000 ms
 * @return {Function}
 * */
module.exports = function InitSSE({retry}) {
    retry = retry || 15000;

    /**
     * add push function to res
     * @param {Response} res - express res or standard http response
     * */
    return function sse(res) {
        res.socket.setKeepAlive(true);
        res.socket.setTimeout(0);
        res.setHeader('Content-Type', 'text/event-stream');
        res.setHeader('Cache-Control', 'no-cache');
        res.setHeader('Connection', 'keep-alive');
        res.statusCode = 200;

        // export push to send server-side-events
        res.push = function push(data, event, id) {
            if (typeof data == 'object') {
                data = JSON.stringify(data);
            }
            if (event) {
                saveWrite(res, 'event: ' + event + '\n');
            }
            if (id !== undefined) {
                saveWrite(res, 'id: ' + id + '\n');
            }
            saveWrite(res, 'data: ' + data + '\n\n');
        };

        // write 2kB of padding (for IE) and a reconnection timeout
        // then use res.sse to send to the client

        // res.write(':' + Array(2049).join(' ') + '\n');
        res.write('retry: ' + retry + '\n\n');

        // keep the connection open by sending a comment
        var keepAlive = setInterval(function () {
            if (res.finished) {
                clearInterval(keepAlive);
                return
            }
            res.write(':keep-alive\n');
        }, 20000);

        // cleanup on close
        res.on('close', function close() {
            clearInterval(keepAlive);
        });
    };
};

function saveWrite(res, str) {
    if(res.finished) {
        return false;
    }
    res.write(str);
}<|endoftext|>


<commit_before>let Discord = require('discord.io');
let config = require('./config.js');
let lame = require('lame');
let youtubeDL = require('youtube-dl');
let ffmpeg = require('fluent-ffmpeg');

let bot = new Discord.Client({
  token: config.token,
  autorun: true
});

bot.on('ready', function() {
  console.log(bot.username + " - (" + bot.id + ")");
  bot.joinVoiceChannel("219530331357839370");
});

bot.on('message', function(user, userID, channelID, message, event) {
  //  If the message starts with roll, take the first instance of the dice regex and give the result
  //  TODO: error checking
  if (message.startsWith('!roll ')) {
    //  TODO: use matching group so we can switch on the command part
    let diceRegex = /!roll (\d*)(d)(\d+)( for .*)?/;
    let requestedRole = diceRegex.exec(message);
    //  If the numebr of rolls wasn't defined, set it to 1
    let numberOfRolls = requestedRole[1] ? requestedRole[1] : 1;
    let dieType = requestedRole[3];
    //  If there is no reason supplied make the explanation for the roll blank.
    let reason = requestedRole[4] ? requestedRole[4] : '';
    let sum = 0;
    let rolls = [];
    for (let i = 0; i < numberOfRolls; i++) {
      let roll = Math.ceil(Math.random() * dieType);
      rolls.push(roll);
      sum += roll;
    }
    let response = `@${user} rolled ${numberOfRolls} d${dieType} ` +
      `for a total of ${sum}${reason}.  Rolls were ${rolls}.`;
    bot.sendMessage({
      to: channelID,
      message: response
    });
  }
  if (message.startsWith('@play ')) {
    // TODO: vlaidate URL with https://gist.github.com/dperini/729294 ?
    // get the url
    let url = message.substr(6);
    console.log(`url: ${url}`);
    let m4aStream = youtubeDL(url,
      ['--format=m4a']);
    m4aStream.on('info', function(info) {
      console.log('Downloading video in m4a format.');
      var mp3Stream = ffmpeg(m4aStream)
        .noVideo()
        .withAudioCodec('libmp3lame')
        .format('mp3')
        .stream()
        .on('start', function(commandLine) {
          console.log('Converting m4a to mp3.  Spawned Ffmpeg with command: ' + commandLine);
        }); // Mp3 stream
      let mp3Decoder = new lame.Decoder();
      let handleStream = function handleStream(error, stream) {
        stream.send(mp3Decoder);
      };
      mp3Stream.pipe(mp3Decoder);
      mp3Decoder.on('format', function(format) {
        console.log('MP3 decoding started.  Format');
        console.log(format);
        bot.getAudioContext(
          {channel: "219530331357839370", stereo: true}, handleStream);
      });
    });
  }
});

//  Handle ctrl + c and shutdown cleanly
process.on('SIGINT', function() {
  console.log('RYAN got interrupt');
  bot.disconnect();
  process.exit();
});
<commit_msg>Audio at 100% speed via file<commit_after>let Discord = require('discord.io');
let config = require('./config.js');
let lame = require('lame');
let youtubeDL = require('youtube-dl');
let ffmpeg = require('fluent-ffmpeg');
let fs = require('fs');

let bot = new Discord.Client({
  token: config.token,
  autorun: true
});

bot.on('ready', function() {
  console.log(bot.username + " - (" + bot.id + ")");
  bot.joinVoiceChannel("140673738298359809");
});

bot.on('message', function(user, userID, channelID, message, event) {
  //  If the message starts with roll, take the first instance of the dice regex and give the result
  //  TODO: error checking
  if (message.startsWith('!roll ')) {
    //  TODO: use matching group so we can switch on the command part
    let diceRegex = /!roll (\d*)(d)(\d+)( for .*)?/;
    let requestedRole = diceRegex.exec(message);
    //  If the numebr of rolls wasn't defined, set it to 1
    let numberOfRolls = requestedRole[1] ? requestedRole[1] : 1;
    let dieType = requestedRole[3];
    //  If there is no reason supplied make the explanation for the roll blank.
    let reason = requestedRole[4] ? requestedRole[4] : '';
    let sum = 0;
    let rolls = [];
    for (let i = 0; i < numberOfRolls; i++) {
      let roll = Math.ceil(Math.random() * dieType);
      rolls.push(roll);
      sum += roll;
    }
    let response = `@${user} rolled ${numberOfRolls} d${dieType} ` +
      `for a total of ${sum}${reason}.  Rolls were ${rolls}.`;
    bot.sendMessage({
      to: channelID,
      message: response
    });
  }
  if (message.startsWith('@play ')) {
    // TODO: vlaidate URL with https://gist.github.com/dperini/729294 ?
    // get the url
    let url = message.substr(6);
    console.log(`url: ${url}`);
    let ytDL = youtubeDL(url,
      ['-x', '--extract-audio', '--audio-format=mp3']);
    ytDL.on('info', function(info) {
      console.log('Downloading video in mp3 format.');
      // var mp3Stream = ffmpeg(m4aStream)
      //   .noVideo()
      //   .withAudioCodec('libmp3lame')
      //   .format('mp3')
      //   .stream()
      //   .on('start', function(commandLine) {
      //     console.log('Converting m4a to mp3.  Spawned Ffmpeg with command: ' + commandLine);
      //   }); // Mp3 stream
      // let mp3Decoder = new lame.Decoder();
      // mp3Stream.pipe(mp3Decoder);
      // mp3Decoder.on('format', function(format) {
      //   console.log('MP3 decoding started.  Format');
      //   console.log(format);
      //   bot.getAudioContext(
      //     {channel: "219530331357839370", stereo: true}, handleStream);
      // });
      ytDL.pipe(fs.createWriteStream('test.mp3'));
    });
    ytDL.on('end', () => {
      console.log('There will be no more data.');
      bot.getAudioContext(
          {channel: "140673738298359809", stereo: true}, (error, stream) => {
            stream.playAudioFile('test.mp3');
          });
    });
  }
});

//  Handle ctrl + c and shutdown cleanly
process.on('SIGINT', function() {
  console.log('RYAN got interrupt');
  bot.disconnect();
  process.exit();
});
<|endoftext|>


<commit_before>var tilebelt = require('tilebelt');

/**
 * Given a geometry, create cells and return them in a format easily readable
 * by any software that reads GeoJSON.
 *
 * @alias geojson
 * @param {Object} geom GeoJSON geometry
 * @param {Object} limits an object with min_zoom and max_zoom properties
 * specifying the minimum and maximum level to be tiled.
 * @returns {Object} FeatureCollection of cells formatted as GeoJSON Features
 */
exports.geojson = function (geom, limits) {
    return {
        type: 'FeatureCollection',
        features: getTiles(geom, limits).map(tileToFeature)
    };
};

function tileToFeature(t) {
    return {
        type: 'Feature',
        geometry: tilebelt.tileToGeoJSON(t),
        properties: {}
    };
}

/**
 * Given a geometry, create cells and return them in their raw form,
 * as an array of cell identifiers.
 *
 * @alias tiles
 * @param {Object} geom GeoJSON geometry
 * @param {Object} limits an object with min_zoom and max_zoom properties
 * specifying the minimum and maximum level to be tiled.
 * @returns {Array<Array<number>>} An array of tiles given as [x, y, z] arrays
 */
exports.tiles = getTiles;

/**
 * Given a geometry, create cells and return them as
 * [quadkey](http://msdn.microsoft.com/en-us/library/bb259689.aspx) indexes.
 *
 * @alias indexes
 * @param {Object} geom GeoJSON geometry
 * @param {Object} limits an object with min_zoom and max_zoom properties
 * specifying the minimum and maximum level to be tiled.
 * @returns {Array<String>} An array of tiles given as quadkeys.
 */
exports.indexes = function (geom, limits) {
    return getTiles(geom, limits).map(tilebelt.tileToQuadkey);
};

function getTiles(geom, limits) {
    var locked, i, tile, id,
        coords = geom.coordinates,
        tileHash = {};

    if (geom.type === 'Point') {
        locked = [tilebelt.pointToTile(coords[0], coords[1], limits.max_zoom)];

    } else if (geom.type === 'MultiPoint') {
        locked = [];
        for (i = 0; i < coords.length; i++) {
            tile = tilebelt.pointToTile(coords[i][0], coords[i][1], limits.max_zoom);
            id = toID(tile[0], tile[1], tile[2]);
            if (!tileHash[id]) {
                tileHash[id] = true;
                locked.push(tile);
            }
        }
    } else if (geom.type === 'LineString') {
        lineCover(tileHash, coords, limits.max_zoom);

    } else if (geom.type === 'MultiLineString') {
        for (i = 0; i < coords.length; i++) {
            lineCover(tileHash, coords[i], limits.max_zoom);
        }
    } else if (geom.type === 'Polygon') {
        polygonCover(tileHash, coords, limits.max_zoom);

    } else if (geom.type === 'MultiPolygon') {
        for (i = 0; i < coords.length; i++) {
            polygonCover(tileHash, coords[i], limits.max_zoom);
        }
    } else {
        throw new Error('Geometry type not implemented');
    }

    if (!locked) {
        if (limits.min_zoom !== limits.max_zoom) {
            tileHash = mergeTiles(tileHash, limits);
        }
        locked = hashToArray(tileHash);
    }

    return locked;
}

function mergeTiles(tileHash, limits) {
    var mergedTileHash = {};

    for (var z = limits.max_zoom; z > limits.min_zoom; z--) {

        var keys = Object.keys(tileHash);
        var parentTileHash = {};

        for (var i = 0; i < keys.length; i++) {
            var id1 = +keys[i],
                t = fromID(id1);

            if (t[0] % 2 === 0 && t[1] % 2 === 0) {
                var id2 = toID(t[0] + 1, t[1], z),
                    id3 = toID(t[0], t[1] + 1, z),
                    id4 = toID(t[0] + 1, t[1] + 1, z);

                if (tileHash[id2] && tileHash[id3] && tileHash[id4]) {
                    tileHash[id1] = false;
                    tileHash[id2] = false;
                    tileHash[id3] = false;
                    tileHash[id4] = false;

                    var parentId = toID(t[0] / 2, t[1] / 2, z - 1);
                    (z - 1 === limits.min_zoom ? mergedTileHash : parentTileHash)[parentId] = true;
                }
            }
        }

        for (i = 0; i < keys.length; i++) {
            if (tileHash[keys[i]]) {
                mergedTileHash[+keys[i]] = true;
            }
        }

        tileHash = parentTileHash;
    }

    return mergedTileHash;
}

function polygonCover(tileHash, geom, max_zoom) {
    var intersections = [];

    for (var i = 0; i < geom.length; i++) {
        var ring = [];
        lineCover(tileHash, geom[i], max_zoom, ring);

        for (var j = 0, len = ring.length, k = len - 1; j < len; k = j++) {
            var m = (j + 1) % len;
            var y = ring[j][1];

            // add interesction if it's not local extremum or duplicate
            if ((y > ring[k][1] || y > ring[m][1]) && // not local minimum
                (y < ring[k][1] || y < ring[m][1]) && // not local maximum
                y !== ring[m][1]) intersections.push(ring[j]);
        }
    }

    intersections.sort(compareTopLeft); // sort by y, then x

    for (i = 0; i < intersections.length; i += 2) {
        // fill tiles between pairs of intersections
        for (var x = intersections[i][0] + 1; x < intersections[i + 1][0]; x++) {
            tileHash[toID(x, intersections[i][1], max_zoom)] = true;
        }
    }
}

function compareTopLeft(a, b) {
    return (a[1] - b[1]) || (a[0] - b[0]);
}

function lineCover(tileHash, coords, max_zoom, ring) {
    var prevX, prevY;

    for (var i = 0; i < coords.length - 1; i++) {
        var start = tilebelt.pointToTileFraction(coords[i][0], coords[i][1], max_zoom),
            stop = tilebelt.pointToTileFraction(coords[i + 1][0], coords[i + 1][1], max_zoom),
            x0 = start[0],
            y0 = start[1],
            x1 = stop[0],
            y1 = stop[1],
            dx = x1 - x0,
            dy = y1 - y0;

        if (dy === 0 && dx === 0) continue;

        var sx = dx > 0 ? 1 : -1,
            sy = dy > 0 ? 1 : -1,
            x = Math.floor(x0),
            y = Math.floor(y0),
            tMaxX = dx === 0 ? Infinity : Math.abs(((dx > 0 ? 1 : 0) + x - x0) / dx),
            tMaxY = dy === 0 ? Infinity : Math.abs(((dy > 0 ? 1 : 0) + y - y0) / dy),
            tdx = Math.abs(sx / dx),
            tdy = Math.abs(sy / dy);

        if (x !== prevX || y !== prevY) {
            tileHash[toID(x, y, max_zoom)] = true;
            if (ring && y !== prevY) ring.push([x, y, max_zoom]);
            prevX = x;
            prevY = y;
        }

        while (tMaxX < 1 || tMaxY < 1) {
            if (tMaxX < tMaxY) {
                tMaxX += tdx;
                x += sx;
            } else {
                tMaxY += tdy;
                y += sy;
            }
            tileHash[toID(x, y, max_zoom)] = true;
            if (ring && y !== prevY) ring.push([x, y, max_zoom]);
            prevX = x;
            prevY = y;
        }
    }

    if (ring && ring[ring.length - 1][1] === ring[0][1]) ring.pop();
}

function hashToArray(hash) {
    var keys = Object.keys(hash);
    var tiles = [];
    for (var i = 0; i < keys.length; i++) {
        tiles.push(fromID(+keys[i]));
    }
    return tiles;
}

function toID(x, y, z) {
    var dim = 2 * (1 << z);
    return ((dim * y + x) * 32) + z;
}

function fromID(id) {
    var z = id % 32,
        dim = 2 * (1 << z),
        xy = ((id - z) / 32),
        x = xy % dim,
        y = ((xy - x) / dim) % dim;
    return [x, y, z];
}
<commit_msg>more tidying up<commit_after>var tilebelt = require('tilebelt');

/**
 * Given a geometry, create cells and return them in a format easily readable
 * by any software that reads GeoJSON.
 *
 * @alias geojson
 * @param {Object} geom GeoJSON geometry
 * @param {Object} limits an object with min_zoom and max_zoom properties
 * specifying the minimum and maximum level to be tiled.
 * @returns {Object} FeatureCollection of cells formatted as GeoJSON Features
 */
exports.geojson = function (geom, limits) {
    return {
        type: 'FeatureCollection',
        features: getTiles(geom, limits).map(tileToFeature)
    };
};

function tileToFeature(t) {
    return {
        type: 'Feature',
        geometry: tilebelt.tileToGeoJSON(t),
        properties: {}
    };
}

/**
 * Given a geometry, create cells and return them in their raw form,
 * as an array of cell identifiers.
 *
 * @alias tiles
 * @param {Object} geom GeoJSON geometry
 * @param {Object} limits an object with min_zoom and max_zoom properties
 * specifying the minimum and maximum level to be tiled.
 * @returns {Array<Array<number>>} An array of tiles given as [x, y, z] arrays
 */
exports.tiles = getTiles;

/**
 * Given a geometry, create cells and return them as
 * [quadkey](http://msdn.microsoft.com/en-us/library/bb259689.aspx) indexes.
 *
 * @alias indexes
 * @param {Object} geom GeoJSON geometry
 * @param {Object} limits an object with min_zoom and max_zoom properties
 * specifying the minimum and maximum level to be tiled.
 * @returns {Array<String>} An array of tiles given as quadkeys.
 */
exports.indexes = function (geom, limits) {
    return getTiles(geom, limits).map(tilebelt.tileToQuadkey);
};

function getTiles(geom, limits) {
    var tiles, i, tile, id,
        coords = geom.coordinates,
        maxZoom = limits.max_zoom,
        tileHash = {};

    if (geom.type === 'Point') {
        tiles = [tilebelt.pointToTile(coords[0], coords[1], maxZoom)];

    } else if (geom.type === 'MultiPoint') {
        tiles = [];
        for (i = 0; i < coords.length; i++) {
            tile = tilebelt.pointToTile(coords[i][0], coords[i][1], maxZoom);
            id = toID(tile[0], tile[1], tile[2]);
            if (!tileHash[id]) {
                tileHash[id] = true;
                tiles.push(tile);
            }
        }
    } else if (geom.type === 'LineString') {
        lineCover(tileHash, coords, maxZoom);

    } else if (geom.type === 'MultiLineString') {
        for (i = 0; i < coords.length; i++) {
            lineCover(tileHash, coords[i], maxZoom);
        }
    } else if (geom.type === 'Polygon') {
        polygonCover(tileHash, coords, maxZoom);

    } else if (geom.type === 'MultiPolygon') {
        for (i = 0; i < coords.length; i++) {
            polygonCover(tileHash, coords[i], maxZoom);
        }
    } else {
        throw new Error('Geometry type not implemented');
    }

    if (!tiles) {
        if (limits.min_zoom !== maxZoom) tileHash = mergeTiles(tileHash, limits);
        tiles = hashToArray(tileHash);
    }

    return tiles;
}

function mergeTiles(tileHash, limits) {
    var mergedTileHash = {};

    for (var z = limits.max_zoom; z > limits.min_zoom; z--) {

        var keys = Object.keys(tileHash);
        var parentTileHash = {};

        for (var i = 0; i < keys.length; i++) {
            var id1 = +keys[i],
                t = fromID(id1);

            if (t[0] % 2 === 0 && t[1] % 2 === 0) {
                var id2 = toID(t[0] + 1, t[1], z),
                    id3 = toID(t[0], t[1] + 1, z),
                    id4 = toID(t[0] + 1, t[1] + 1, z);

                if (tileHash[id2] && tileHash[id3] && tileHash[id4]) {
                    tileHash[id1] = false;
                    tileHash[id2] = false;
                    tileHash[id3] = false;
                    tileHash[id4] = false;

                    var parentId = toID(t[0] / 2, t[1] / 2, z - 1);
                    (z - 1 === limits.min_zoom ? mergedTileHash : parentTileHash)[parentId] = true;
                }
            }
        }

        for (i = 0; i < keys.length; i++) {
            if (tileHash[keys[i]]) mergedTileHash[+keys[i]] = true;
        }

        tileHash = parentTileHash;
    }

    return mergedTileHash;
}

function polygonCover(tileHash, geom, maxZoom) {
    var intersections = [];

    for (var i = 0; i < geom.length; i++) {
        var ring = [];
        lineCover(tileHash, geom[i], maxZoom, ring);

        for (var j = 0, len = ring.length, k = len - 1; j < len; k = j++) {
            var m = (j + 1) % len;
            var y = ring[j][1];

            // add interesction if it's not local extremum or duplicate
            if ((y > ring[k][1] || y > ring[m][1]) && // not local minimum
                (y < ring[k][1] || y < ring[m][1]) && // not local maximum
                y !== ring[m][1]) intersections.push(ring[j]);
        }
    }

    intersections.sort(compareTiles); // sort by y, then x

    for (i = 0; i < intersections.length; i += 2) {
        // fill tiles between pairs of intersections
        for (var x = intersections[i][0] + 1; x < intersections[i + 1][0]; x++) {
            tileHash[toID(x, intersections[i][1], maxZoom)] = true;
        }
    }
}

function compareTiles(a, b) {
    return (a[1] - b[1]) || (a[0] - b[0]);
}

function lineCover(tileHash, coords, maxZoom, ring) {
    var prevX, prevY;

    for (var i = 0; i < coords.length - 1; i++) {
        var start = tilebelt.pointToTileFraction(coords[i][0], coords[i][1], maxZoom),
            stop = tilebelt.pointToTileFraction(coords[i + 1][0], coords[i + 1][1], maxZoom),
            x0 = start[0],
            y0 = start[1],
            x1 = stop[0],
            y1 = stop[1],
            dx = x1 - x0,
            dy = y1 - y0;

        if (dy === 0 && dx === 0) continue;

        var sx = dx > 0 ? 1 : -1,
            sy = dy > 0 ? 1 : -1,
            x = Math.floor(x0),
            y = Math.floor(y0),
            tMaxX = dx === 0 ? Infinity : Math.abs(((dx > 0 ? 1 : 0) + x - x0) / dx),
            tMaxY = dy === 0 ? Infinity : Math.abs(((dy > 0 ? 1 : 0) + y - y0) / dy),
            tdx = Math.abs(sx / dx),
            tdy = Math.abs(sy / dy);

        if (x !== prevX || y !== prevY) {
            tileHash[toID(x, y, maxZoom)] = true;
            if (ring && y !== prevY) ring.push([x, y, maxZoom]);
            prevX = x;
            prevY = y;
        }

        while (tMaxX < 1 || tMaxY < 1) {
            if (tMaxX < tMaxY) {
                tMaxX += tdx;
                x += sx;
            } else {
                tMaxY += tdy;
                y += sy;
            }
            tileHash[toID(x, y, maxZoom)] = true;
            if (ring && y !== prevY) ring.push([x, y, maxZoom]);
            prevX = x;
            prevY = y;
        }
    }

    if (ring && y === ring[0][1]) ring.pop();
}

function hashToArray(hash) {
    var keys = Object.keys(hash);
    var tiles = [];
    for (var i = 0; i < keys.length; i++) {
        tiles.push(fromID(+keys[i]));
    }
    return tiles;
}

function toID(x, y, z) {
    var dim = 2 * (1 << z);
    return ((dim * y + x) * 32) + z;
}

function fromID(id) {
    var z = id % 32,
        dim = 2 * (1 << z),
        xy = ((id - z) / 32),
        x = xy % dim,
        y = ((xy - x) / dim) % dim;
    return [x, y, z];
}
<|endoftext|>