<commit_before>'use strict';

// Based on Resig's pretty date
function prettyDate(time) {
  var diff = (Date.now() - time) / 1000;
  var day_diff = Math.floor(diff / 86400);

  if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31)
    return '';

  return day_diff == 0 && (
    diff < 60 && 'just now' ||
    diff < 120 && '1 minute ago' ||
    diff < 3600 && Math.floor(diff / 60) + ' minutes ago' ||
    diff < 7200 && '1 hour ago' ||
    diff < 86400 && Math.floor(diff / 3600) + ' hours ago') ||
    day_diff == 1 && 'Yesterday' ||
    day_diff < 7 && day_diff + ' days ago' ||
    day_diff < 31 && Math.ceil(day_diff / 7) + ' weeks ago';
}

var MessageManager = {
  getMessages: function mm_getMessages(callback, filter, invert) {
    // XXX Bug 712809
    // Until there is a database for mozSms, use a fake GetMessages

    if (true) {
      GetMessagesHack(callback, filter, invert);
      return;
    }

    var request = navigator.mozSms.getMessages(filter, !invert);

    var messages = [];
    request.onsuccess = function() {
      var result = request.result;
      if (!result) {
        callback(messages);
        return;
      }

      var message = result.message;
      messages.push(message);
      result.next();
    };

    request.onerror = function() {
      alert('Error reading the database. Error code: ' + request.errorCode);
    }
  },

  send: function mm_send(number, text, callback) {
    var result = navigator.mozSms.send(number, text);
    result.onsuccess = function onsuccess(event) {
      callback(event.message);
    };
    result.onerror = function onerror(event) {
      console.log('Error sending SMS!');
      callback(null);
    };
  },

  delete: function mm_delete(id) {
    navigator.mozSms.delete(id);
  }
};

// Until there is a database to store messages on the device, return
// a fake list of messages.
var messagesHack = [];
(function() {
  var messages = [
    {
      sender: null,
      receiver: '1-977-743-6797',
      body: 'Nothing :)',
      timestamp: Date.now() - 44000000
    },
    {
      sender: '1-977-743-6797',
      body: 'Hey! What\s up?',
      timestamp: Date.now() - 50000000
    }
  ];

  for (var i = 0; i < 40; i++) {
    messages.push({
      sender: '1-488-678-3487',
      body: 'Hello world!',
      timestamp: Date.now() - 60000000
    });
  }

  messagesHack = messages;
})();

var GetMessagesHack = function gmhack(callback, filter, invert) {
  function applyFilter(msgs) {
    if (!filter)
      return msgs;

    if (filter.number) {
      msgs = msgs.filter(function(element, index, array) {
          return (filter.number && (filter.number == element.sender ||
                  filter.number == element.receiver));
      });
    }

    return msgs;
  }

  var msg = messagesHack.slice();
  if (invert)
    msg.reverse();
  callback(applyFilter(msg));
};

// Use a fake send if mozSms is not present
if (!navigator.mozSms) {
  MessageManager.send = function mm_send(number, text, callback) {
    var message = {
      sender: null,
      receiver: number,
      body: text,
      timestamp: Date.now()
    };
    window.setTimeout(function() {
      callback(message);
    }, 0);
  };
}

var MessageView = {
  init: function init() {
    if (navigator.mozSms)
      navigator.mozSms.addEventListener('received', this);

    var conversationViewEvents =
      ['mousedown', 'mouseover', 'mouseup', 'mouseleave'];
    conversationViewEvents.forEach((function(eventName) {
      this.conversationView.addEventListener(eventName, this);
    }).bind(this));

    this.searchInput.addEventListener(
      'keypress', (MessageView.searchMessageView).bind(this));
    this.searchInput.addEventListener(
      'keyup', (MessageView.searchMessageView).bind(this));

    document.getElementById('msg-new-message').addEventListener(
      'click', function newMessage() {
        ConversationView.showConversation();
      });

    window.addEventListener('transitionend', this);

    this.showConversations(
      function appready() {
        window.parent.postMessage('appready', '*');
      }
    );
  },

  get searchInput() {
    delete this.searchInput;
    return this.searchInput = document.getElementById('msg-search');
  },

  get conversationView() {
    delete this.conversationView;
    return this.conversationView = document.getElementById('msg-conversations');
  },

  openConversationView: function openConversationView() {
    var num = this.currentConversation.dataset.num;

    ConversationView.showConversation(num == '*' ? '' : num);
  },

  get view() {
    delete this.view;
    return this.view = document.getElementById('msg-conversation-list');
  },

  showConversations: function showConversations(callback) {
    var self = this;
    MessageManager.getMessages(function getMessagesCallback(messages) {
      var conversations = {};
      for (var i = 0; i < messages.length; i++) {
        var message = messages[i];
        var sender = message.sender || message.receiver;
        if (conversations[sender])
          continue;

        conversations[sender] = {
          sender: message.sender,
          receiver: message.receiver,
          body: message.body,
          timestamp: prettyDate(message.timestamp)
        };
      }

      var fragment = '';
      for (var sender in conversations) {
        var msg = self.createNewConversation(conversations[sender]);
        fragment += msg;
      }
      self.view.innerHTML = fragment;

      if (typeof callback === 'function')
        callback.call(self);
    }, null);
  },

  createNewConversation: function createNewConversation(msg) {
    var num = (msg.sender || msg.receiver);
    var name = num;

    var contacts = window.navigator.mozContacts.contacts;
    contacts.forEach(function(contact) {
      if (contact.phones[0] == num)
        name = contact.displayName;
    });

    return '
' +
            '
' +
              '' +
            '
' +
            '
' + name + '
' +
            '
' + msg.body + '
' +
            '
' + msg.timestamp + '
' +
           '
';
  },

  searchMessageView: function searchMessageView() {
    var str = this.searchInput.value;
    var conversations = this.view.childNodes;
    if (!str) {
      for (var i in conversations) {
        conversations[i].classList.remove('hide');
      }
      return;
    }

    var reg = new RegExp(str, 'i');

    for (var i in conversations) {
      if (!reg.test(conversations[i].dataset.num) &&
          !reg.test(conversations[i].dataset.name)) {
        conversations[i].classList.add('hide');
      } else {
        conversations[i].classList.remove('hide');
      }
    }
  },

  handleEvent: function handleEvent(evt) {
    switch (evt.type) {
      case 'received':
        window.setTimeout(function() {
          MessageView.showConversations();
        }, 0);
        break;
      case 'mousedown':
        this.touched = true;
        var selection = this.getSelectionFromEvent(evt);

        if (!selection)
          return;

        selection.classList.add('selected');
        this.currentConversation = selection;

        break;
      case 'mouseover':
        if (!this.touched)
          return;

        var selection = this.getSelectionFromEvent(evt);

        if (this.currentConversation === selection)
          return;

        if (this.currentConversation)
          this.currentConversation.classList.remove('selected');

        if (selection)
          selection.classList.add('selected');

        this.currentConversation = selection;

        break;
      case 'mouseup':
        delete this.touched;

        if (this.currentConversation)
          this.openConversationView();
        break;

      case 'mouseleave':
        if (!this.touched)
          return;
        delete this.touched;

        this.currentConversation.classList.remove('selected');
        delete this.currentConversation;

      case 'transitionend':
        if (!document.body.classList.contains('going-back'))
          return;

        document.body.classList.remove('going-back');
        if (this.currentConversation)
          this.currentConversation.classList.remove('selected');
        delete this.currentConversation;
    }
  },

  getSelectionFromEvent: function getSelectionFromEvent(evt) {
    var target = evt.target;
    while (target !== evt.currentTarget) {
      if (target.dataset.num)
        return target;
      target = target.parentNode;
    }
    return false;
  }
};

var ConversationView = {
  get view() {
    delete this.view;
    return this.view = document.getElementById('msg-conversation-view-msgs');
  },

  get num() {
    delete this.number;
    return this.number = document.getElementById('msg-conversation-view-num');
  },

  get title() {
    delete this.title;
    return this.title = document.getElementById('msg-conversation-view-name');
  },

  init: function cv_init() {
    if (navigator.mozSms)
      navigator.mozSms.addEventListener('received', this);

    document.getElementById('msg-conversation-view-back').addEventListener(
      'click', (this.close).bind(this));

    document.getElementById('msg-conversation-view-msg-send').addEventListener(
      'click', (this.sendMessage).bind(this));

    var windowEvents = ['keypress', 'transitionend'];
    windowEvents.forEach((function(eventName) {
      window.addEventListener(eventName, this);
    }).bind(this));
  },

  showConversation: function cv_showConversation(num) {
    var view = this.view;
    var filter = ('SmsFilter' in window) ? new SmsFilter() : {};
    filter.number = this.filter = num;

    if (!num) {
      /*
        XXX: UX did not define New Message screen.
             let's invent one.
      */
      this.num.value = '';
      this.view.innerHTML = '';
      document.body.classList.add('conversation-new-msg');
      document.body.classList.add('conversation');
      return;
    }

    document.body.classList.remove('conversation-new-msg');

    var name = num;

    var contacts = window.navigator.mozContacts.contacts;
    contacts.forEach(function(contact) {
      if (contact.phones[0] == num)
        name = contact.displayName;
    });

    this.num.value = num;

    this.title.textContent = name;
    this.title.num = num;

    MessageManager.getMessages(function mm_getMessages(messages) {
      var fragment = '';

      for (var i = 0; i < messages.length; i++) {
        var msg = messages[i];
        var uuid = msg.hasOwnProperty('uuid') ? msg.uuid : '';
        var dataId = 'data-id="' + uuid + '"';

        var dataNum = 'data-num="' + (msg.sender || msg.receiver) + '"';

        var className = 'class="' +
                        (msg.sender ? 'sender' : 'receiver') + '"';

        var time = prettyDate(msg.timestamp);
        fragment += '
' +
                      '
' +
                        '' +
                      '
' +
                      '
' + msg.body + '
' +
                      '
' + time + '
' +
                    '
';
      }

      view.innerHTML = fragment;

      /* XXX: scrollIntoView does not reveal bottom margin */
      if (view.lastChild)
        view.lastChild.scrollIntoView(false);

      document.body.classList.add('conversation');
    }, filter, true);
  },

  deleteMessage: function deleteMessage(evt) {
    var uuid = evt.target.getAttribute('data-id');
    if (!uuid)
      return;

    MessageManager.delete(uuid);
    this.showConversation(this.filter);
  },

  handleEvent: function handleEvent(evt) {
    switch (evt.type) {
      case 'keypress':
        if (evt.keyCode != evt.DOM_VK_ESCAPE)
          return;

        if (this.close())
          evt.preventDefault();
      case 'received':
        var message = evt.message;
        console.log('Received message from ' + message.sender + ': ' +
                    message.body);
        messagesHack.unshift(message);
        window.setTimeout(function() {
          ConversationView.showConversation(ConversationView.filter);
        }, 0);
        break;
      case 'transitionend':
        if (document.body.classList.contains('conversation'))
          return;

        this.view.innerHTML = '';
        break;
    }
  },
  close: function cv_close() {
    if (!document.body.classList.contains('conversation'))
      return false;
    document.body.classList.remove('conversation');
    document.body.classList.add('going-back');
    return true;
  },
  sendMessage: function cv_sendMessage() {
    var num = this.num.value;
    var text = document.getElementById('msg-conversation-view-msg-text').value;

    if (num === '' || text === '')
      return;

    MessageManager.send(num, text, function onsent(msg) {
      // There was an error. We should really do some error handling here.
      // or in send() or wherever.
      if (!msg)
        return;

      // Copy all the information from the actual message object to the
      // preliminary message object. Then update the view.
      for (var key in msg)
        message[msg] = msg[key];

      if (ConversationView.filter)
        ConversationView.showConversation(ConversationView.filter);
    });

    // Create a preliminary message object and update the view right away.
    var message = {
      sender: null,
      receiver: num,
      body: text,
      timestamp: Date.now()
    };
    messagesHack.unshift(message);

    document.getElementById('msg-conversation-view-msg-text').value = '';

    MessageView.showConversations();
    if (this.filter) {
      this.showConversation(this.filter);
      return;
    }
    this.showConversation(num);
  }
};

window.addEventListener('load', (ConversationView.init).bind(ConversationView));
window.addEventListener('load', (MessageView.init).bind(MessageView));

<commit_msg>gjslint<commit_after>'use strict';

// Based on Resig's pretty date
function prettyDate(time) {
  var diff = (Date.now() - time) / 1000;
  var day_diff = Math.floor(diff / 86400);

  if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31)
    return '';

  return day_diff == 0 && (
    diff < 60 && 'just now' ||
    diff < 120 && '1 minute ago' ||
    diff < 3600 && Math.floor(diff / 60) + ' minutes ago' ||
    diff < 7200 && '1 hour ago' ||
    diff < 86400 && Math.floor(diff / 3600) + ' hours ago') ||
    day_diff == 1 && 'Yesterday' ||
    day_diff < 7 && day_diff + ' days ago' ||
    day_diff < 31 && Math.ceil(day_diff / 7) + ' weeks ago';
}

var MessageManager = {
  getMessages: function mm_getMessages(callback, filter, invert) {
    // XXX Bug 712809
    // Until there is a database for mozSms, use a fake GetMessages

    if (true) {
      GetMessagesHack(callback, filter, invert);
      return;
    }

    var request = navigator.mozSms.getMessages(filter, !invert);

    var messages = [];
    request.onsuccess = function() {
      var result = request.result;
      if (!result) {
        callback(messages);
        return;
      }

      var message = result.message;
      messages.push(message);
      result.next();
    };

    request.onerror = function() {
      alert('Error reading the database. Error code: ' + request.errorCode);
    }
  },

  send: function mm_send(number, text, callback) {
    // Use a fake send if mozSms is not present
    if (!navigator.mozSms) {
      var message = {
        sender: null,
        receiver: number,
        body: text,
        timestamp: Date.now()
      };

      window.setTimeout(function() {
        callback(message);
      }, 0);

      return;
    }

    var result = navigator.mozSms.send(number, text);
    result.onsuccess = function onsuccess(event) {
      callback(event.message);
    };
    result.onerror = function onerror(event) {
      console.log('Error sending SMS!');
      callback(null);
    };
  },

  delete: function mm_delete(id) {
    navigator.mozSms.delete(id);
  }
};

// Until there is a database to store messages on the device, return
// a fake list of messages.
var messagesHack = [];
(function() {
  var messages = [
    {
      sender: null,
      receiver: '1-977-743-6797',
      body: 'Nothing :)',
      timestamp: Date.now() - 44000000
    },
    {
      sender: '1-977-743-6797',
      body: 'Hey! What\s up?',
      timestamp: Date.now() - 50000000
    }
  ];

  for (var i = 0; i < 40; i++) {
    messages.push({
      sender: '1-488-678-3487',
      body: 'Hello world!',
      timestamp: Date.now() - 60000000
    });
  }

  messagesHack = messages;
})();

var GetMessagesHack = function gmhack(callback, filter, invert) {
  function applyFilter(msgs) {
    if (!filter)
      return msgs;

    if (filter.number) {
      msgs = msgs.filter(function(element, index, array) {
          return (filter.number && (filter.number == element.sender ||
                  filter.number == element.receiver));
      });
    }

    return msgs;
  }

  var msg = messagesHack.slice();
  if (invert)
    msg.reverse();
  callback(applyFilter(msg));
};

var MessageView = {
  init: function init() {
    if (navigator.mozSms)
      navigator.mozSms.addEventListener('received', this);

    var conversationViewEvents =
      ['mousedown', 'mouseover', 'mouseup', 'mouseleave'];
    conversationViewEvents.forEach((function(eventName) {
      this.conversationView.addEventListener(eventName, this);
    }).bind(this));

    this.searchInput.addEventListener(
      'keypress', (MessageView.searchMessageView).bind(this));
    this.searchInput.addEventListener(
      'keyup', (MessageView.searchMessageView).bind(this));

    document.getElementById('msg-new-message').addEventListener(
      'click', function newMessage() {
        ConversationView.showConversation();
      });

    window.addEventListener('transitionend', this);

    this.showConversations(
      function appready() {
        window.parent.postMessage('appready', '*');
      }
    );
  },

  get searchInput() {
    delete this.searchInput;
    return this.searchInput = document.getElementById('msg-search');
  },

  get conversationView() {
    delete this.conversationView;
    return this.conversationView = document.getElementById('msg-conversations');
  },

  openConversationView: function openConversationView() {
    var num = this.currentConversation.dataset.num;

    ConversationView.showConversation(num == '*' ? '' : num);
  },

  get view() {
    delete this.view;
    return this.view = document.getElementById('msg-conversation-list');
  },

  showConversations: function showConversations(callback) {
    var self = this;
    MessageManager.getMessages(function getMessagesCallback(messages) {
      var conversations = {};
      for (var i = 0; i < messages.length; i++) {
        var message = messages[i];
        var sender = message.sender || message.receiver;
        if (conversations[sender])
          continue;

        conversations[sender] = {
          sender: message.sender,
          receiver: message.receiver,
          body: message.body,
          timestamp: prettyDate(message.timestamp)
        };
      }

      var fragment = '';
      for (var sender in conversations) {
        var msg = self.createNewConversation(conversations[sender]);
        fragment += msg;
      }
      self.view.innerHTML = fragment;

      if (typeof callback === 'function')
        callback.call(self);
    }, null);
  },

  createNewConversation: function createNewConversation(msg) {
    var num = (msg.sender || msg.receiver);
    var name = num;

    var contacts = window.navigator.mozContacts.contacts;
    contacts.forEach(function(contact) {
      if (contact.phones[0] == num)
        name = contact.displayName;
    });

    return '
' +
            '
' +
              '' +
            '
' +
            '
' + name + '
' +
            '
' + msg.body + '
' +
            '
' + msg.timestamp + '
' +
           '
';
  },

  searchMessageView: function searchMessageView() {
    var str = this.searchInput.value;
    var conversations = this.view.childNodes;
    if (!str) {
      for (var i in conversations) {
        conversations[i].classList.remove('hide');
      }
      return;
    }

    var reg = new RegExp(str, 'i');

    for (var i in conversations) {
      if (!reg.test(conversations[i].dataset.num) &&
          !reg.test(conversations[i].dataset.name)) {
        conversations[i].classList.add('hide');
      } else {
        conversations[i].classList.remove('hide');
      }
    }
  },

  handleEvent: function handleEvent(evt) {
    switch (evt.type) {
      case 'received':
        window.setTimeout(function() {
          MessageView.showConversations();
        }, 0);
        break;
      case 'mousedown':
        this.touched = true;
        var selection = this.getSelectionFromEvent(evt);

        if (!selection)
          return;

        selection.classList.add('selected');
        this.currentConversation = selection;

        break;
      case 'mouseover':
        if (!this.touched)
          return;

        var selection = this.getSelectionFromEvent(evt);

        if (this.currentConversation === selection)
          return;

        if (this.currentConversation)
          this.currentConversation.classList.remove('selected');

        if (selection)
          selection.classList.add('selected');

        this.currentConversation = selection;

        break;
      case 'mouseup':
        delete this.touched;

        if (this.currentConversation)
          this.openConversationView();
        break;

      case 'mouseleave':
        if (!this.touched)
          return;
        delete this.touched;

        this.currentConversation.classList.remove('selected');
        delete this.currentConversation;

      case 'transitionend':
        if (!document.body.classList.contains('going-back'))
          return;

        document.body.classList.remove('going-back');
        if (this.currentConversation)
          this.currentConversation.classList.remove('selected');
        delete this.currentConversation;
    }
  },

  getSelectionFromEvent: function getSelectionFromEvent(evt) {
    var target = evt.target;
    while (target !== evt.currentTarget) {
      if (target.dataset.num)
        return target;
      target = target.parentNode;
    }
    return false;
  }
};

var ConversationView = {
  get view() {
    delete this.view;
    return this.view = document.getElementById('msg-conversation-view-msgs');
  },

  get num() {
    delete this.number;
    return this.number = document.getElementById('msg-conversation-view-num');
  },

  get title() {
    delete this.title;
    return this.title = document.getElementById('msg-conversation-view-name');
  },

  init: function cv_init() {
    if (navigator.mozSms)
      navigator.mozSms.addEventListener('received', this);

    document.getElementById('msg-conversation-view-back').addEventListener(
      'click', (this.close).bind(this));

    document.getElementById('msg-conversation-view-msg-send').addEventListener(
      'click', (this.sendMessage).bind(this));

    var windowEvents = ['keypress', 'transitionend'];
    windowEvents.forEach((function(eventName) {
      window.addEventListener(eventName, this);
    }).bind(this));
  },

  showConversation: function cv_showConversation(num) {
    var view = this.view;
    var filter = ('SmsFilter' in window) ? new SmsFilter() : {};
    filter.number = this.filter = num;

    if (!num) {
      /*
        XXX: UX did not define New Message screen.
             let's invent one.
      */
      this.num.value = '';
      this.view.innerHTML = '';
      document.body.classList.add('conversation-new-msg');
      document.body.classList.add('conversation');
      return;
    }

    document.body.classList.remove('conversation-new-msg');

    var name = num;

    var contacts = window.navigator.mozContacts.contacts;
    contacts.forEach(function(contact) {
      if (contact.phones[0] == num)
        name = contact.displayName;
    });

    this.num.value = num;

    this.title.textContent = name;
    this.title.num = num;

    MessageManager.getMessages(function mm_getMessages(messages) {
      var fragment = '';

      for (var i = 0; i < messages.length; i++) {
        var msg = messages[i];
        var uuid = msg.hasOwnProperty('uuid') ? msg.uuid : '';
        var dataId = 'data-id="' + uuid + '"';

        var dataNum = 'data-num="' + (msg.sender || msg.receiver) + '"';

        var className = 'class="' +
                        (msg.sender ? 'sender' : 'receiver') + '"';

        var time = prettyDate(msg.timestamp);
        fragment += '
' +
                      '
' +
                        '' +
                      '
' +
                      '
' + msg.body + '
' +
                      '
' + time + '
' +
                    '
';
      }

      view.innerHTML = fragment;

      /* XXX: scrollIntoView does not reveal bottom margin */
      if (view.lastChild)
        view.lastChild.scrollIntoView(false);

      document.body.classList.add('conversation');
    }, filter, true);
  },

  deleteMessage: function deleteMessage(evt) {
    var uuid = evt.target.getAttribute('data-id');
    if (!uuid)
      return;

    MessageManager.delete(uuid);
    this.showConversation(this.filter);
  },

  handleEvent: function handleEvent(evt) {
    switch (evt.type) {
      case 'keypress':
        if (evt.keyCode != evt.DOM_VK_ESCAPE)
          return;

        if (this.close())
          evt.preventDefault();
      case 'received':
        var message = evt.message;
        console.log('Received message from ' + message.sender + ': ' +
                    message.body);
        messagesHack.unshift(message);
        window.setTimeout(function() {
          ConversationView.showConversation(ConversationView.filter);
        }, 0);
        break;
      case 'transitionend':
        if (document.body.classList.contains('conversation'))
          return;

        this.view.innerHTML = '';
        break;
    }
  },
  close: function cv_close() {
    if (!document.body.classList.contains('conversation'))
      return false;
    document.body.classList.remove('conversation');
    document.body.classList.add('going-back');
    return true;
  },
  sendMessage: function cv_sendMessage() {
    var num = this.num.value;
    var text = document.getElementById('msg-conversation-view-msg-text').value;

    if (num === '' || text === '')
      return;

    MessageManager.send(num, text, function onsent(msg) {
      // There was an error. We should really do some error handling here.
      // or in send() or wherever.
      if (!msg)
        return;

      // Copy all the information from the actual message object to the
      // preliminary message object. Then update the view.
      for (var key in msg)
        message[msg] = msg[key];

      if (ConversationView.filter)
        ConversationView.showConversation(ConversationView.filter);
    });

    // Create a preliminary message object and update the view right away.
    var message = {
      sender: null,
      receiver: num,
      body: text,
      timestamp: Date.now()
    };
    messagesHack.unshift(message);

    document.getElementById('msg-conversation-view-msg-text').value = '';

    MessageView.showConversations();
    if (this.filter) {
      this.showConversation(this.filter);
      return;
    }
    this.showConversation(num);
  }
};

window.addEventListener('load', (ConversationView.init).bind(ConversationView));
window.addEventListener('load', (MessageView.init).bind(MessageView));

<|endoftext|>


<commit_before>var http = require('http'),
    util = require('util'),
    express = require('express'),
    bodyParser = require('body-parser'),
    async = require('async'),
    Singularity = require('singularity-client');

var port = process.env.PORT || 3000,
    host = process.env.HOST || 'localhost',
    serverBaseUrl = util.format("http://%s:%s", host, port),
    hookPathPrefix = "/webhook",
    hookBaseUrl = serverBaseUrl + hookPathPrefix,
    singularityPort = process.env.SINGULARITY_PORT || 7099,
    singularityHost = process.env.SINGULARITY_HOST || host,
    singularityBase = process.env.SINGULARITY_BASE || '/singularity',
    singularityUrl = util.format("http://%s:%s%s", singularityHost, singularityPort, singularityBase);

var singularity = new Singularity({
    singularity: {
        baseUrl: singularityUrl,
        connectTimeout: 5000
    }
});

if (process.env.DEBUG) {
    var debugEvents = ["connect", "success", "failure"]

    debugEvents.forEach(function(evt) {
        singularity.hub.on(evt, function(msg) {
          console.log(evt.toUpperCase(), msg);
        });
    });
}

var app = express();

app.use(bodyParser.json());
app.post(hookPathPrefix + '/:hook', function (req, res) {
    var type = req.params.hook.toUpperCase();

    console.log('------------------------------------------------------------------------')
    console.log('-- Callback for %s', type);
    console.log('--');
    console.log(JSON.stringify(JSON.parse(req.body), null, 2));
    console.log('------------------------------------------------------------------------');

    res.sendStatus(200);
});

function addWebhook(webhook, callback) {
    var hookUrl = hookBaseUrl + "/" + webhook;
    console.log("== adding Webhook %s for request type %s", hookUrl, webhook);

    singularity.webhooks.create(webhook, hookBaseUrl, function(err, data) {
        console.log("== response for request type %s: %s", webhook, data);
        callback(err);
    });
}

function deleteWebhook(webhook, callback) {
    var hookUrl = hookBaseUrl + "/" + webhook;
    console.log("== removing Webhook %s for request type %s", hookUrl, webhook);

    singularity.webhooks.delete(webhook, hookBaseUrl, function(err, data) {
        console.log("== response for request type %s: %s", webhook, data);
        callback(null); // always return safely
    });
}

var hooks = [ 'task', 'deploy', 'request' ];

process.on('SIGINT', function() {
    console.log("");

    // unregister hooks with singularity
    async.each(hooks, deleteWebhook, function() {
        process.exit();
    });
});

server = app.listen(port, host, function () {
    console.log('========================================================================');
    console.log('== QUEEQUEG - Singularity webhook debugger listening at %s', serverBaseUrl);
    console.log('==');
    console.log('== using singularity at %s', singularityUrl);

    // register hooks with singulariy
    async.each(hooks, addWebhook, function(err) {
        if (err) throw err;
        console.log("== All hooks enabled");
    });
});
<commit_msg>express is parsing the json, we don't have to<commit_after>var http = require('http'),
    util = require('util'),
    express = require('express'),
    bodyParser = require('body-parser'),
    async = require('async'),
    Singularity = require('singularity-client');

var port = process.env.PORT || 3000,
    host = process.env.HOST || 'localhost',
    serverBaseUrl = util.format("http://%s:%s", host, port),
    hookPathPrefix = "/webhook",
    hookBaseUrl = serverBaseUrl + hookPathPrefix,
    singularityPort = process.env.SINGULARITY_PORT || 7099,
    singularityHost = process.env.SINGULARITY_HOST || host,
    singularityBase = process.env.SINGULARITY_BASE || '/singularity',
    singularityUrl = util.format("http://%s:%s%s", singularityHost, singularityPort, singularityBase);

var singularity = new Singularity({
    singularity: {
        baseUrl: singularityUrl,
        connectTimeout: 5000
    }
});

if (process.env.DEBUG) {
    var debugEvents = ["connect", "success", "failure"]

    debugEvents.forEach(function(evt) {
        singularity.hub.on(evt, function(msg) {
          console.log(evt.toUpperCase(), msg);
        });
    });
}

var app = express();

app.use(bodyParser.json());
app.post(hookPathPrefix + '/:hook', function (req, res) {
    var type = req.params.hook.toUpperCase();

    console.log('------------------------------------------------------------------------')
    console.log('-- Callback for %s', type);
    console.log('--');
    console.log(JSON.stringify(req.body, null, 2));
    console.log('------------------------------------------------------------------------');

    res.sendStatus(200);
});

function addWebhook(webhook, callback) {
    var hookUrl = hookBaseUrl + "/" + webhook;
    console.log("== adding Webhook %s for request type %s", hookUrl, webhook);

    singularity.webhooks.create(webhook, hookBaseUrl, function(err, data) {
        console.log("== response for request type %s: %s", webhook, data);
        callback(err);
    });
}

function deleteWebhook(webhook, callback) {
    var hookUrl = hookBaseUrl + "/" + webhook;
    console.log("== removing Webhook %s for request type %s", hookUrl, webhook);

    singularity.webhooks.delete(webhook, hookBaseUrl, function(err, data) {
        console.log("== response for request type %s: %s", webhook, data);
        callback(null); // always return safely
    });
}

var hooks = [ 'task', 'deploy', 'request' ];

process.on('SIGINT', function() {
    console.log("");

    // unregister hooks with singularity
    async.each(hooks, deleteWebhook, function() {
        process.exit();
    });
});

server = app.listen(port, host, function () {
    console.log('========================================================================');
    console.log('== QUEEQUEG - Singularity webhook debugger listening at %s', serverBaseUrl);
    console.log('==');
    console.log('== using singularity at %s', singularityUrl);

    // register hooks with singulariy
    async.each(hooks, addWebhook, function(err) {
        if (err) throw err;
        console.log("== All hooks enabled");
    });
});
<|endoftext|>


<commit_before>/* @flow weak */
import generateCSSDeclaration from './generateCSSDeclaration'
import warning from './warning'

export default function cssifyObject(style) {
  let css = ''

  for (const property in style) {
    warning(
      typeof style[property] === 'string' || typeof style[property] === 'number',
      `The invalid value \`${style[property]}\` has been used as \`${property}\`.`
    )

    // prevents the semicolon after
    // the last rule declaration
    if (css) {
      css += ';'
    }

    css += generateCSSDeclaration(property, style[property])
  }

  return css
}
<commit_msg>skip undefined values in cssifyObject<commit_after>/* @flow weak */
import generateCSSDeclaration from './generateCSSDeclaration'

export default function cssifyObject(style) {
  let css = ''

  for (const property in style) {
    if (style[property] !== 'string' && typeof style[property] !== 'number') {
      continue
    }

    // prevents the semicolon after
    // the last rule declaration
    if (css) {
      css += ';'
    }

    css += generateCSSDeclaration(property, style[property])
  }

  return css
}
<|endoftext|>


<commit_before>define(['state'], function (state) {
	var callstack = [];

    var getCallstack = function () {
        return callstack;
    };

    var executeScript = function (script, locals) {
        if (callstack.length !== 0) {
            throw 'Existing callstack is not empty';
        }

        callstack = [{
            script: script,
            index: 0,
            locals: locals || {},
        }];

        executeNext();
    };

    var nestedExecuteNextCount = 0;

    var executeNext = function () {
        if (callstack.length === 0) return;

        // An "if" script is inside a child frame. The parent frame is the one
        // with the local variables and any "return" script.
        var parentFrameIndex = getParentFrameIndex();
        var parentFrame = callstack[parentFrameIndex];
        var frame = callstack[callstack.length - 1];

        if (parentFrame.finished) {
            var framesToRemove = callstack.length - parentFrameIndex;
            callstack.splice(-framesToRemove);
            executeNext();
            return;
        }

        if (frame.index === frame.script.length) {
            callstack.pop();
            executeNext();
            return;
        }

        var script = frame.script[frame.index++];

        var go = function () {
            script.command.execute({
                parameters: script.parameters,
                locals: parentFrame.locals,
                onReturn: function (result) {
                    parentFrame.finished = true;
                    parentFrame.onReturn(result);
                },
                complete: function () {
                    executeNext();
                }
            });
        };

        if (nestedExecuteNextCount < 1000) {
            nestedExecuteNextCount++;
            go();
            nestedExecuteNextCount--;
        }
        else {
            setTimeout(function () {
                go();
            }, 0);
        }
    };

    var getParentFrameIndex = function () {
        var frameIndex = callstack.length - 1;
        while (true) {
            if (callstack[frameIndex].locals) return frameIndex;
            frameIndex--;
            if (frameIndex === -1) {
                throw 'Could not find parent frame';
            }
        }
    };

    var getParentFrame = function () {
        return callstack[getParentFrameIndex()];
    };

    var evaluateExpression = function (expr, complete) {
        if (!expr.tree) {
            throw 'Not an expression: ' + expr;
        }
        var frame = callstack[callstack.length - 1];
        frame.expressionStack = [{
           tree: expr.tree,
           complete: function (result) {
                complete(result);
           }
        }];

        evaluateNext();
    };

    var evaluateExpressions = function (exprs, complete) {
        var index = 0;
        var results = [];
        var go = function () {
            if (index === exprs.length) {
                complete(results);
            }
            else {
                evaluateExpression(exprs[index], function (result) {
                    results.push(result);
                    index++;
                    go();
                });
            }
        };
        go();
    };

    var evaluateNext = function () {
        var frame = callstack[callstack.length - 1];
        var expressionFrame = frame.expressionStack[frame.expressionStack.length - 1];
        var tree = expressionFrame.tree;
        switch (tree.type) {
            case 'Literal':
                expressionFrame.complete(tree.value);
                break;
            case 'Identifier':
                var locals = getParentFrame().locals;
                if (tree.name in locals) {
                    expressionFrame.complete(locals[tree.name]);
                }
                else if (state.isElement(tree.name)) {
                    expressionFrame.complete({
                        'type': 'element',
                        'name': tree.name
                    });
                }
                else {
                    throw 'Unknown variable ' + tree.name;
                }

                break;
            case 'BinaryExpression':
                frame.expressionStack.push({
                    tree: tree.left,
                    complete: function (leftResult) {
                        frame.expressionStack.push({
                            tree: tree.right,
                            complete: function (rightResult) {
                                expressionFrame.complete(binaryOperator(tree.operator, leftResult, rightResult));
                            }
                        });
                        evaluateNext();
                    }
                });
                evaluateNext();
                break;
            case 'CallExpression':
                if (tree.callee.type !== 'Identifier') {
                    throw 'Function name must be an identifier';
                }
                var index = 0;
                var args = [];
                var evaluateArgs = function () {
                    if (index == tree.arguments.length) {
                        callFunction(tree.callee.name, args, function (result) {
                            expressionFrame.complete(result);
                        });
                        return;
                    }
                    frame.expressionStack.push({
                        tree: tree.arguments[index],
                        complete: function (result) {
                            index++;
                            args.push(result);
                            evaluateArgs();
                        }
                    });
                    evaluateNext();
                };
                evaluateArgs();

                break;
            case 'MemberExpression':
                if (tree.computed) {
                    throw 'Unsupported expression';
                }
                if (tree.property.type !== 'Identifier') {
                    throw 'Attribute name must be an identifier';
                }
                frame.expressionStack.push({
                    tree: tree.object,
                    complete: function (result) {
                        if (result.type !== 'element') {
                            throw 'Expected element, got ' + result;
                        }
                        expressionFrame.complete(state.get(result.name, tree.property.name));
                    }
                });
                evaluateNext();
                break;
            case 'UnaryExpression':
                if (tree.operator != 'not') {
                    throw 'Unrecognised operator: ' + tree.operator;
                }
                frame.expressionStack.push({
                    tree: tree.argument,
                    complete: function (result) {
                        expressionFrame.complete(!result);
                    }
                });
                evaluateNext();
                break;
            default:
                throw 'Unknown expression tree type: ' + tree.type;
        }
    };

    var binaryOperator = function (operator, left, right) {
        switch (operator) {
            case '=':
                return left === right;
            case '!=':
            case '<>':
                return left !== right;
            case '<':
                return left < right;
            case '>':
                return left > right;
            case '+':
                return left + right;
            case '-':
                return left - right;
            case '*':
                return left * right;
            case '/':
                return left / right;
            case 'and':
                return left && right;
            case 'or':
                return left || right;
            default:
                throw 'Undefined operator ' + operator;
        }
    };

    var asyncFunctions = {
        'GetInput': function (args, complete) {
            // TODO: Override input handler

            setTimeout(function () {
                complete("test");
            }, 200);
        }
    };

    var functions = {
        // String Functions
        'Left': function (args, complete) {
            var input = args[0];
            var length = args[1];
            return input.substring(0, length);
        },
        'Right': function (args, complete) {
            var input = args[0];
            var length = args[1];
            return input.substring(input.length - length - 1);
        },
        'Mid': function (args, complete) {
            var input = args[0];
            var start = args[1];
            if (args.length > 2) {
                var length = args[2];
                return input.substr(start - 1, length);
            }
            return input.substr(start - 1);
        },
        'UCase': function (args, complete) {
            var input = args[0];
            return input.toUpperCase();
        },
        'LCase': function (args, complete) {
            var input = args[0];
            return input.toLowerCase();
        },
        'LengthOf': function (args, complete) {
            var input = args[0];
            if (typeof input === 'undefined' || input === null) return 0;
            return input.length;
        },
        'CapFirst': function (args, complete) {
            var input = args[0];
            return input.substring(0, 1).toUpperCase() + input.substring(1);
        },
        'Instr': function (args, complete) {
            var input, search;
            if (args.length > 2) {
                var start = args[0];
                input = args[1];
                search = args[2];
                return input.indexOf(search, start - 1) + 1;
            }
            input = args[0];
            search = args[1];
            return input.indexOf(search) + 1;
        },
        'InstrRev': function (args, complete) {
            var input, search;
            if (args.length > 2) {
                var start = args[0];
                input = args[1];
                search = args[2];
                return input.lastIndexOf(search, start - 1) + 1;
            }
            input = args[0];
            search = args[1];
            return input.lastIndexOf(search) + 1;
        },
        'StartsWith': function (args, complete) {
            var input = args[0];
            var search = args[1];
            return input.indexOf(search) === 0;
        },
        'EndsWith': function (args, complete) {
            var input = args[0];
            var search = args[1];
            return input.indexOf(search) === input.length - search.length;
        },
        'Split': function (args, complete) {
            var input = args[0];
            var splitChar = args[1];
            return input.split(splitChar);
        },
        'Join': function (args, complete) {
            var input = args[0];
            var joinChar = args[1];
            return input.join(joinChar);
        },
        'IsNumeric': function (args, complete) {
            var input = args[0];
            return !isNaN(parseFloat(input)) && isFinite(input);
        },
        'Replace': function (args, complete) {
            var input = args[0];
            var oldString = args[1];
            var newString = args[2];
            return input.split(oldString).join(newString);
        },
        'Trim': function (args, complete) {
            var input = args[0];
            return input.trim();
        },
        'LTrim': function (args, complete) {
            var input = args[0];
            return input.replace(/^\s+/,"");
        },
        'RTrim': function (args, complete) {
            var input = args[0];
            return input.replace(/\s+$/,"");
        },
        'Asc': function (args, complete) {
            var input = args[0];
            return input.charCodeAt(0);
        },
        'Chr': function (args, complete) {
            var input = args[0];
            return String.fromCharCode(input);
        }
    };

    var callFunction = function (name, args, complete) {
        var fn;

        if (state.functionExists(name)) {
            fn = state.getFunctionDefinition(name);
            var argumentValues = {};
            if (fn.parameters) {
                for (var i = 0; i < fn.parameters.length; i++) {
                    if (i >= args.length) break;
                    argumentValues[fn.parameters[i]] = args[i];
                }
            }
            callstack.push({
                script: fn.script,
                locals: argumentValues,
                index: 0,
                onReturn: complete
            });
            executeNext();
            return;
        }

        fn = functions[name];
        if (!fn) {
            fn = asyncFunctions[name];
            if (!fn) {
                // TODO: Throw
                //throw 'Unrecognised function ' + name;
                console.log('Unrecognised function ' + name);
                complete();
                return;
            }
            fn(args, complete);
        }

        complete(fn(args));
    };

    return {
        executeScript: executeScript,
        evaluateExpressions: evaluateExpressions,
        evaluateExpression: evaluateExpression,
        getCallstack: getCallstack,
        executeNext: executeNext,
        callFunction: callFunction
    }
});<commit_msg>More helpful console messages when expression evaluation fails<commit_after>define(['state'], function (state) {
	var callstack = [];

    var getCallstack = function () {
        return callstack;
    };

    var executeScript = function (script, locals) {
        if (callstack.length !== 0) {
            throw 'Existing callstack is not empty';
        }

        callstack = [{
            script: script,
            index: 0,
            locals: locals || {},
        }];

        executeNext();
    };

    var nestedExecuteNextCount = 0;

    var executeNext = function () {
        if (callstack.length === 0) return;

        // An "if" script is inside a child frame. The parent frame is the one
        // with the local variables and any "return" script.
        var parentFrameIndex = getParentFrameIndex();
        var parentFrame = callstack[parentFrameIndex];
        var frame = callstack[callstack.length - 1];

        if (parentFrame.finished) {
            var framesToRemove = callstack.length - parentFrameIndex;
            callstack.splice(-framesToRemove);
            executeNext();
            return;
        }

        if (frame.index === frame.script.length) {
            callstack.pop();
            executeNext();
            return;
        }

        var script = frame.script[frame.index++];

        var go = function () {
            script.command.execute({
                parameters: script.parameters,
                locals: parentFrame.locals,
                onReturn: function (result) {
                    parentFrame.finished = true;
                    parentFrame.onReturn(result);
                },
                complete: function () {
                    executeNext();
                }
            });
        };

        if (nestedExecuteNextCount < 1000) {
            nestedExecuteNextCount++;
            go();
            nestedExecuteNextCount--;
        }
        else {
            setTimeout(function () {
                go();
            }, 0);
        }
    };

    var getParentFrameIndex = function () {
        var frameIndex = callstack.length - 1;
        while (true) {
            if (callstack[frameIndex].locals) return frameIndex;
            frameIndex--;
            if (frameIndex === -1) {
                throw 'Could not find parent frame';
            }
        }
    };

    var getParentFrame = function () {
        return callstack[getParentFrameIndex()];
    };

    var evaluateExpression = function (expr, complete) {
        if (!expr.tree) {
            throw 'Not an expression: ' + expr;
        }
        var frame = callstack[callstack.length - 1];
        frame.expressionStack = [{
           expr: expr.expr,
           tree: expr.tree,
           complete: function (result) {
                complete(result);
           }
        }];

        evaluateNext();
    };

    var evaluateExpressions = function (exprs, complete) {
        var index = 0;
        var results = [];
        var go = function () {
            if (index === exprs.length) {
                complete(results);
            }
            else {
                evaluateExpression(exprs[index], function (result) {
                    results.push(result);
                    index++;
                    go();
                });
            }
        };
        go();
    };

    var lastExpr = null;

    var evaluateNext = function () {
        var frame = callstack[callstack.length - 1];
        var expressionFrame = frame.expressionStack[frame.expressionStack.length - 1];
        var tree = expressionFrame.tree;
        if (expressionFrame.expr) lastExpr = expressionFrame.expr;
        try {
            switch (tree.type) {
                case 'Literal':
                    expressionFrame.complete(tree.value);
                    break;
                case 'Identifier':
                    var locals = getParentFrame().locals;
                    if (tree.name in locals) {
                        expressionFrame.complete(locals[tree.name]);
                    }
                    else if (state.isElement(tree.name)) {
                        expressionFrame.complete({
                            'type': 'element',
                            'name': tree.name
                        });
                    }
                    else {
                        throw 'Unknown variable ' + tree.name;
                    }

                    break;
                case 'BinaryExpression':
                    frame.expressionStack.push({
                        tree: tree.left,
                        complete: function (leftResult) {
                            frame.expressionStack.push({
                                tree: tree.right,
                                complete: function (rightResult) {
                                    expressionFrame.complete(binaryOperator(tree.operator, leftResult, rightResult));
                                }
                            });
                            evaluateNext();
                        }
                    });
                    evaluateNext();
                    break;
                case 'CallExpression':
                    if (tree.callee.type !== 'Identifier') {
                        throw 'Function name must be an identifier';
                    }
                    var index = 0;
                    var args = [];
                    var evaluateArgs = function () {
                        if (index == tree.arguments.length) {
                            callFunction(tree.callee.name, args, function (result) {
                                expressionFrame.complete(result);
                            });
                            return;
                        }
                        frame.expressionStack.push({
                            tree: tree.arguments[index],
                            complete: function (result) {
                                index++;
                                args.push(result);
                                evaluateArgs();
                            }
                        });
                        evaluateNext();
                    };
                    evaluateArgs();

                    break;
                case 'MemberExpression':
                    if (tree.computed) {
                        throw 'Unsupported expression';
                    }
                    if (tree.property.type !== 'Identifier') {
                        throw 'Attribute name must be an identifier';
                    }
                    frame.expressionStack.push({
                        tree: tree.object,
                        complete: function (result) {
                            if (result.type !== 'element') {
                                throw 'Expected element, got ' + result;
                            }
                            expressionFrame.complete(state.get(result.name, tree.property.name));
                        }
                    });
                    evaluateNext();
                    break;
                case 'UnaryExpression':
                    if (tree.operator != 'not') {
                        throw 'Unrecognised operator: ' + tree.operator;
                    }
                    frame.expressionStack.push({
                        tree: tree.argument,
                        complete: function (result) {
                            expressionFrame.complete(!result);
                        }
                    });
                    evaluateNext();
                    break;
                default:
                    throw 'Unknown expression tree type: ' + tree.type;
            }
        }
        catch (e) {
            if (lastExpr) {
                console.log('Error evaluating expression: ' + lastExpr);
                console.log(e);
                lastExpr = null;
            }

            throw e;
        }
    };

    var binaryOperator = function (operator, left, right) {
        switch (operator) {
            case '=':
                return left === right;
            case '!=':
            case '<>':
                return left !== right;
            case '<':
                return left < right;
            case '>':
                return left > right;
            case '+':
                return left + right;
            case '-':
                return left - right;
            case '*':
                return left * right;
            case '/':
                return left / right;
            case 'and':
                return left && right;
            case 'or':
                return left || right;
            default:
                throw 'Undefined operator ' + operator;
        }
    };

    var asyncFunctions = {
        'GetInput': function (args, complete) {
            // TODO: Override input handler

            setTimeout(function () {
                complete("test");
            }, 200);
        }
    };

    var functions = {
        // String Functions
        'Left': function (args, complete) {
            var input = args[0];
            var length = args[1];
            return input.substring(0, length);
        },
        'Right': function (args, complete) {
            var input = args[0];
            var length = args[1];
            return input.substring(input.length - length - 1);
        },
        'Mid': function (args, complete) {
            var input = args[0];
            var start = args[1];
            if (args.length > 2) {
                var length = args[2];
                return input.substr(start - 1, length);
            }
            return input.substr(start - 1);
        },
        'UCase': function (args, complete) {
            var input = args[0];
            return input.toUpperCase();
        },
        'LCase': function (args, complete) {
            var input = args[0];
            return input.toLowerCase();
        },
        'LengthOf': function (args, complete) {
            var input = args[0];
            if (typeof input === 'undefined' || input === null) return 0;
            return input.length;
        },
        'CapFirst': function (args, complete) {
            var input = args[0];
            return input.substring(0, 1).toUpperCase() + input.substring(1);
        },
        'Instr': function (args, complete) {
            var input, search;
            if (args.length > 2) {
                var start = args[0];
                input = args[1];
                search = args[2];
                return input.indexOf(search, start - 1) + 1;
            }
            input = args[0];
            search = args[1];
            return input.indexOf(search) + 1;
        },
        'InstrRev': function (args, complete) {
            var input, search;
            if (args.length > 2) {
                var start = args[0];
                input = args[1];
                search = args[2];
                return input.lastIndexOf(search, start - 1) + 1;
            }
            input = args[0];
            search = args[1];
            return input.lastIndexOf(search) + 1;
        },
        'StartsWith': function (args, complete) {
            var input = args[0];
            var search = args[1];
            return input.indexOf(search) === 0;
        },
        'EndsWith': function (args, complete) {
            var input = args[0];
            var search = args[1];
            return input.indexOf(search) === input.length - search.length;
        },
        'Split': function (args, complete) {
            var input = args[0];
            var splitChar = args[1];
            return input.split(splitChar);
        },
        'Join': function (args, complete) {
            var input = args[0];
            var joinChar = args[1];
            return input.join(joinChar);
        },
        'IsNumeric': function (args, complete) {
            var input = args[0];
            return !isNaN(parseFloat(input)) && isFinite(input);
        },
        'Replace': function (args, complete) {
            var input = args[0];
            var oldString = args[1];
            var newString = args[2];
            return input.split(oldString).join(newString);
        },
        'Trim': function (args, complete) {
            var input = args[0];
            return input.trim();
        },
        'LTrim': function (args, complete) {
            var input = args[0];
            return input.replace(/^\s+/,"");
        },
        'RTrim': function (args, complete) {
            var input = args[0];
            return input.replace(/\s+$/,"");
        },
        'Asc': function (args, complete) {
            var input = args[0];
            return input.charCodeAt(0);
        },
        'Chr': function (args, complete) {
            var input = args[0];
            return String.fromCharCode(input);
        }
    };

    var callFunction = function (name, args, complete) {
        var fn;

        if (state.functionExists(name)) {
            fn = state.getFunctionDefinition(name);
            var argumentValues = {};
            if (fn.parameters) {
                for (var i = 0; i < fn.parameters.length; i++) {
                    if (i >= args.length) break;
                    argumentValues[fn.parameters[i]] = args[i];
                }
            }
            callstack.push({
                script: fn.script,
                locals: argumentValues,
                index: 0,
                onReturn: complete
            });
            executeNext();
            return;
        }

        fn = functions[name];
        if (!fn) {
            fn = asyncFunctions[name];
            if (!fn) {
                // TODO: Throw
                //throw 'Unrecognised function ' + name;
                console.log('Unrecognised function ' + name);
                complete();
                return;
            }
            fn(args, complete);
        }

        complete(fn(args));
    };

    return {
        executeScript: executeScript,
        evaluateExpressions: evaluateExpressions,
        evaluateExpression: evaluateExpression,
        getCallstack: getCallstack,
        executeNext: executeNext,
        callFunction: callFunction
    }
});<|endoftext|>


<commit_before>import request from 'request'
import tzCodes from '../../timezones.json'
import htmlToText from 'html-to-text'
import assign from 'object-assign'
import countdown from 'countdown'

let debug = require('debug')('wololobot:streamtime')

// timezones.json contains offset from UTC, this converts to offset from local
// timezone.
let utcOffset = new Date().getTimezoneOffset()
for (var key in tzCodes) {
  tzCodes[key] = tzCodes[key] + utcOffset
}

const exAssign = (a, b) => (a !== void 0 && a !== null) ? a : b

const parseTimezone = str => {
  // Timezone is in UTC+|-00[[:]00] format
  let match = /UTC([+-])(\d{2})(?::?(\d{2))/.exec(str)
  let offset = 0
  if (match !== null) {
    offset = parseInt(match[2]) * 60
    if (match[2] !== void 0) {
      offset += parseInt(match[3])
    }
    offset *= (match[1] === '-') ? -1 : 1
  } else{
    // Timezone is a timezone code
    match = /[A-Z]{1,5}/.exec(str)
    if (match !== null) {
      offset = tzCodes[match[0]]
    }
    offset = -exAssign(offset, 0)
  }
  return offset
}

const parseMonth = str => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug',
  'Sep', 'Nov', 'Dec'].indexOf(str.substring(0, 3))

const invDate = usr => `@${usr} Couldn't parse time - Use \`!streamtime `+
                       `overwrite_time YYYY-MM-DD hh:mm [AM|PM] [timezone]`

const parseSchedule = str => {
  let lines = str.split('\n')
  let tz
  // First line could be a timezone definition
  if (lines[0].toLowerCase().indexOf('all times in ') === 0) {
    tz = parseTimezone(lines[0].substring(13))
    lines = lines.slice(1, lines.length)
  } else {
    tz = 0
  }
  let streams = Array()
  let regexes = [
    /(\d+)(?:st|nd|rd|th)? +([A-Za-z]+)( +\d{4})? *: *(\d+)(?::(\d+))?(AM|PM)?(?: *- *(\d+)(?::(\d+))?(AM|PM)?)?(?: *\| *(.+))/, // ZeroEmpires format
    / *-* *([A-Za-z]+) +(\d+) *(\d{4})? *: *(.*?) +at +(\d+):(\d+) *(AM|PM) *\(([A-Za-z]+)\) *\(.*?\)/ // Resonance22 format
  ]
  lines.forEach(line => {
    let desc, start, end
    let match = regexes[0].exec(line)
    if (match !== null) {
      let day = match[1]
      let month = parseMonth(match[2])
      let year = exAssign(match[3], new Date().getFullYear())
      let startHour = parseInt(match[4])
      let startMin = exAssign(match[5], 0)
      // 12PM = Noon, 12AM = Midnight
      if (match[6] === 'PM') {
        startHour = (startHour + 12) % 24
      } else if (match[6] === 'AM' && startHour == 12) {
        startHour = 0
      }
      start = new Date(year, month, day, startHour, startMin)
      // Add offset due to timezone
      start.setMinutes(start.getMinutes() + tz)
      if (match[7] !== void 0) {
        let endHour = parseInt(match[7])
        let endMin = exAssign(match[8], 0)
        if (match[9] === 'PM') {
          endHour = (endHour + 12) % 24
        } else if (match[9] === 'AM' && endHour == 12) {
          endHour = 0
        }
        end = new Date(year, month, day, endHour, endMin)
        end.setMinutes(start.getMinutes() + tz)
        if (end < start) {
          // Assume the stream is over midnight (not 2+ midnights though)
          end.setDate(end.getDate() + 1)
        }
      }
      desc = match[10]
    } else {
      let match = regexes[1].exec(line)
      if (match !== null) {
        let month = parseMonth(match[1])
        let day = match[2]
        let year = exAssign(match[3], new Date().getFullYear())
        desc = match[4]
        let startHour = parseInt(match[5])
        let startMin = match[6]
        if (match[7] === 'PM') {
          startHour = (startHour + 12) % 24
        } else if (match[7] === 'AM' && startHour == 12) {
          startHour = 0
        }
        start = new Date(year, month, day, startHour, startMin)
        tz = parseTimezone(match[8])
        start.setMinutes(start.getMinutes() + tz)
      }
    }
    if (start !== undefined) {
      streams.push([start, end, desc])
    }
  })
  return streams
}

export default function(opts) {

  opts = assign({
    schedImage: 'http://static-cdn.jtvnw.net/jtv_user_pictures/panel-23728458-image-15fb69742e4863a7-320.jpeg' // Use ZeroEmpires' schedule image by default
  , lateBy: 5 // Minutes for which the 'Should have started' message is shown
  , updateInterval: 5 * 60 * 1000 // Interval (in ms) in which the streamtimes are updated
  }, opts)
  const { db } = opts

  let overwrite = {
    msg: null,
    time: null
  }
  let tableExists = false

  db.schema.hasTable('streamtime_overwrites').then(ex => {
    tableExists = ex
    if (!tableExists) {
      db.schema.createTable('streamtime_overwrites', t=> {
        t.integer('id').primary()
        t.string('value', 255)
      }).then(() => {
        // 1 = Message, 2 = Time
        db('streamtime_overwrites').insert([ { id: 1, value: null }
                                           , { id: 2, value: null } ])
        .then(() => {
          debug('Created table for !streamtime overwrites')
          tableExists = true
        })
      }).catch(e => { throw e })
    } else {
      db('streamtime_overwrites').select('value').orderBy('id').then(o => {
        overwrite.msg = o[0].value
        overwrite.time = (o[1].value === null) ? null
                                             : new Date(parseInt(o[1].value))
      })
    }
  })

  let streams = []
  let foundPanel = false

  function setOverwriteMsg(value) {
    if (!tableExists) {
      return null
    }
    overwrite.msg = value
    db('streamtime_overwrites')
      .update({ value: value })
      .where({ id: 1 })
      .catch(e => { throw e })
  }

  function setOverwriteTime(value) {
    if (!tableExists) {
      return null
    }
    overwrite.time = value
    db('streamtime_overwrites')
      .update({ value: (value !== null) ? value.getTime() : value})
      .where({ id: 2 })
      .catch(e => { throw e })
  }

  function getTimes() {
    return new Promise((resolve, reject) => {
      request(
        { uri: `https://api.twitch.tv/api/channels/${opts.channel}/panels`
        , json: true },
        (err, res, panels = []) => {
          if (err) {
            reject(err)
          } else {
            foundPanel = panels.some(panel => {
              if (panel.data.title.toLowerCase() === 'schedule' || panel.data.image === opts.schedImage) {
                streams = parseSchedule(htmlToText.fromString(panel.html_description
                  , { ignoreHref: true, ignoreImage: true , wordwrap: null }))
                return true
              }
            })
            resolve()
          }
        }
      )
    })
  }

  function getNext() {
    let next = Infinity
    let now = new Date()
    streams.some(stream => {
      let start = new Date(stream[0])
      start.setMinutes(start.getMinutes() + opts.lateBy)
      if (start < next && start > now) {
        next = stream
      }
    })
    if (next === Infinity) {
      return null
    }
    return next
  }

  getTimes()
  setInterval(getTimes, opts.updateInterval);

  return function(bot) {

    bot.command('!streamtime overwrite', { rank: 'mod' }, (message, extra) => {
      if ([ '_time', '_discard' ].indexOf(extra) !== -1) {
        return
      }
      let msg = message.trailing.slice(21).trim()
      if (msg.length === 0) {
        return bot.send(`@${message.user} Usage: !streamtime overwrite `+
                        `<message> (use $time$ to include a countdown to the `+
                        `next stream)`)
      }
      setOverwriteMsg(msg)
      debug(`Message overwritten by ${message.user} with ${msg}`)
      bot.send(`@${message.user} !streamtime has been overwritten`)
    })

    bot.command('!streamtime overwrite_time'
                , { rank: 'mod' }
                , (message) => {
      let spl = message.trailing.slice(26).trim().split(' ')
      if (spl.length < 3 || spl.length > 4) {
        return bot.send(invDate(message.user))
      }
      let year, month, day, hour, min
      let spl2 = spl[0].split('-')
      if (spl2.length !== 3) {
        return bot.send(invDate(message.user))
      }
      [year, month, day] = spl2
      let spl3 = spl[1].split(':')
      if (spl3.length === 1) {
        hour = parseInt(spl[1])
        min = 0
      } else if (spl3.length === 2) {
        debug(spl3);
        [hour, min] = spl3.map(i => parseInt(i))
      } else {
        return bot.send(invDate(message.user))
      }
      debug(hour, min)
      if (spl[2] === 'PM') {
        hour = (hour + 12) % 24
      } else if (spl[2] === 'AM' && hour == 12) {
        hour = 0
      } else if (spl[2] !== 'AM') {
        min += parseTimezone(spl[2])
      }
      if (spl.length === 4) {
        min += parseTimezone(spl[3])
      }
      debug(hour, min)
      let time = new Date(year, parseInt(month) - 1, day, hour, min)
      if (isNaN(time.getTime())) {
        return bot.send(invDate(message.user))
      }
      setOverwriteTime(time)
      bot.send(`@${message.user} Time for the next stream has been ` +
               `overwritten (next stream is now in `+
               `${countdown(overwrite.time).toString()}).`)
      debug(`Time to next stream overwritten by ${message.user} with ${time}`)
    })

    bot.command('!streamtime overwrite_discard'
                , { rank: 'mod' }
                , (message) => {
      setOverwriteMsg(null)
      setOverwriteTime(null)
      bot.send(`@${message.user} Overwrite has been discarded.`)
      debug(`Overwrite discarded by ${message.user}`)
    })

    bot.command('!streamtime update'
                , { throttle: 10000 }
                , (message) => {
      getTimes().then(() => bot.send(`@${message.user} Updated.`))
    })

    bot.command('!streamtime', (message, extra) => {
      if ([ 'overwrite', 'overwrite_time', 'overwrite_discard', 'update' ]
          .indexOf(extra) !== -1) {
        return
      }
      if (bot.isLive && additional !== 'next') {
        return bot.send("It's live! F5!")
      }
      let next = getNext()
      if (overwrite.msg !== null) {
        let msg = overwrite.msg
        if (overwrite.time !== null) {
          let now = new Date()
          if (overwrite.time < now &&
              overwrite.time > now.setMinutes(now.getMinutes - 5)) {
            return bot.send('The stream should have started a second ago!')
          }
          msg = msg.replace('$time$', countdown(overwrite.time).toString())
        } else if (next !== null) {
          msg = msg.replace('$time$', countdown(next[0]).toString())
        }
        return bot.send(msg)
      } else if (overwrite.time !== null) {
        return bot.send(`Stream in ${countdown(overwrite.time).toString()}.`)
      }
      if (next === null) {
        return bot.send(`There are currently no scheduled streams :/`)
      }
      if (next[0] < new Date()) {
        return bot.send('The stream should have started a second ago!')
      }
      let desc = exAssign(next[2], 'Stream')
      return bot.send(`${desc} in ${countdown(next[0]).toString()}`)
    })

  }

}
<commit_msg>Account for panels with only title images<commit_after>import request from 'request'
import tzCodes from '../../timezones.json'
import htmlToText from 'html-to-text'
import assign from 'object-assign'
import countdown from 'countdown'

let debug = require('debug')('wololobot:streamtime')

// timezones.json contains offset from UTC, this converts to offset from local
// timezone.
let utcOffset = new Date().getTimezoneOffset()
for (var key in tzCodes) {
  tzCodes[key] = tzCodes[key] + utcOffset
}

const exAssign = (a, b) => (a !== void 0 && a !== null) ? a : b

const parseTimezone = str => {
  // Timezone is in UTC+|-00[[:]00] format
  let match = /UTC([+-])(\d{2})(?::?(\d{2))/.exec(str)
  let offset = 0
  if (match !== null) {
    offset = parseInt(match[2]) * 60
    if (match[2] !== void 0) {
      offset += parseInt(match[3])
    }
    offset *= (match[1] === '-') ? -1 : 1
  } else{
    // Timezone is a timezone code
    match = /[A-Z]{1,5}/.exec(str)
    if (match !== null) {
      offset = tzCodes[match[0]]
    }
    offset = -exAssign(offset, 0)
  }
  return offset
}

const parseMonth = str => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug',
  'Sep', 'Nov', 'Dec'].indexOf(str.substring(0, 3))

const invDate = usr => `@${usr} Couldn't parse time - Use \`!streamtime `+
                       `overwrite_time YYYY-MM-DD hh:mm [AM|PM] [timezone]`

const parseSchedule = str => {
  let lines = str.split('\n')
  let tz
  // First line could be a timezone definition
  if (lines[0].toLowerCase().indexOf('all times in ') === 0) {
    tz = parseTimezone(lines[0].substring(13))
    lines = lines.slice(1, lines.length)
  } else {
    tz = 0
  }
  let streams = Array()
  let regexes = [
    /(\d+)(?:st|nd|rd|th)? +([A-Za-z]+)( +\d{4})? *: *(\d+)(?::(\d+))?(AM|PM)?(?: *- *(\d+)(?::(\d+))?(AM|PM)?)?(?: *\| *(.+))/, // ZeroEmpires format
    / *-* *([A-Za-z]+) +(\d+) *(\d{4})? *: *(.*?) +at +(\d+):(\d+) *(AM|PM) *\(([A-Za-z]+)\) *\(.*?\)/ // Resonance22 format
  ]
  lines.forEach(line => {
    let desc, start, end
    let match = regexes[0].exec(line)
    if (match !== null) {
      let day = match[1]
      let month = parseMonth(match[2])
      let year = exAssign(match[3], new Date().getFullYear())
      let startHour = parseInt(match[4])
      let startMin = exAssign(match[5], 0)
      // 12PM = Noon, 12AM = Midnight
      if (match[6] === 'PM') {
        startHour = (startHour + 12) % 24
      } else if (match[6] === 'AM' && startHour == 12) {
        startHour = 0
      }
      start = new Date(year, month, day, startHour, startMin)
      // Add offset due to timezone
      start.setMinutes(start.getMinutes() + tz)
      if (match[7] !== void 0) {
        let endHour = parseInt(match[7])
        let endMin = exAssign(match[8], 0)
        if (match[9] === 'PM') {
          endHour = (endHour + 12) % 24
        } else if (match[9] === 'AM' && endHour == 12) {
          endHour = 0
        }
        end = new Date(year, month, day, endHour, endMin)
        end.setMinutes(start.getMinutes() + tz)
        if (end < start) {
          // Assume the stream is over midnight (not 2+ midnights though)
          end.setDate(end.getDate() + 1)
        }
      }
      desc = match[10]
    } else {
      let match = regexes[1].exec(line)
      if (match !== null) {
        let month = parseMonth(match[1])
        let day = match[2]
        let year = exAssign(match[3], new Date().getFullYear())
        desc = match[4]
        let startHour = parseInt(match[5])
        let startMin = match[6]
        if (match[7] === 'PM') {
          startHour = (startHour + 12) % 24
        } else if (match[7] === 'AM' && startHour == 12) {
          startHour = 0
        }
        start = new Date(year, month, day, startHour, startMin)
        tz = parseTimezone(match[8])
        start.setMinutes(start.getMinutes() + tz)
      }
    }
    if (start !== undefined) {
      streams.push([start, end, desc])
    }
  })
  return streams
}

export default function(opts) {

  opts = assign({
    schedImage: 'http://static-cdn.jtvnw.net/jtv_user_pictures/panel-23728458-image-15fb69742e4863a7-320.jpeg' // Use ZeroEmpires' schedule image by default
  , lateBy: 5 // Minutes for which the 'Should have started' message is shown
  , updateInterval: 5 * 60 * 1000 // Interval (in ms) in which the streamtimes are updated
  }, opts)
  const { db } = opts

  let overwrite = {
    msg: null,
    time: null
  }
  let tableExists = false

  db.schema.hasTable('streamtime_overwrites').then(ex => {
    tableExists = ex
    if (!tableExists) {
      db.schema.createTable('streamtime_overwrites', t=> {
        t.integer('id').primary()
        t.string('value', 255)
      }).then(() => {
        // 1 = Message, 2 = Time
        db('streamtime_overwrites').insert([ { id: 1, value: null }
                                           , { id: 2, value: null } ])
        .then(() => {
          debug('Created table for !streamtime overwrites')
          tableExists = true
        })
      }).catch(e => { throw e })
    } else {
      db('streamtime_overwrites').select('value').orderBy('id').then(o => {
        overwrite.msg = o[0].value
        overwrite.time = (o[1].value === null) ? null
                                             : new Date(parseInt(o[1].value))
      })
    }
  })

  let streams = []
  let foundPanel = false

  function setOverwriteMsg(value) {
    if (!tableExists) {
      return null
    }
    overwrite.msg = value
    db('streamtime_overwrites')
      .update({ value: value })
      .where({ id: 1 })
      .catch(e => { throw e })
  }

  function setOverwriteTime(value) {
    if (!tableExists) {
      return null
    }
    overwrite.time = value
    db('streamtime_overwrites')
      .update({ value: (value !== null) ? value.getTime() : value})
      .where({ id: 2 })
      .catch(e => { throw e })
  }

  function getTimes() {
    return new Promise((resolve, reject) => {
      request(
        { uri: `https://api.twitch.tv/api/channels/${opts.channel}/panels`
        , json: true },
        (err, res, panels = []) => {
          if (err) {
            reject(err)
          } else {
            foundPanel = panels.some(panel => {
              if ((panel.data.title !== void 0 &&
                  panel.data.title.toLowerCase() === 'schedule') ||
                  panel.data.image === opts.schedImage) {
                streams = parseSchedule(htmlToText.fromString(panel.html_description
                  , { ignoreHref: true, ignoreImage: true , wordwrap: null }))
                return true
              }
            })
            resolve()
          }
        }
      )
    })
  }

  function getNext() {
    let next = Infinity
    let now = new Date()
    streams.some(stream => {
      let start = new Date(stream[0])
      start.setMinutes(start.getMinutes() + opts.lateBy)
      if (start < next && start > now) {
        next = stream
      }
    })
    if (next === Infinity) {
      return null
    }
    return next
  }

  getTimes()
  setInterval(getTimes, opts.updateInterval);

  return function(bot) {

    bot.command('!streamtime overwrite', { rank: 'mod' }, (message, extra) => {
      if ([ '_time', '_discard' ].indexOf(extra) !== -1) {
        return
      }
      let msg = message.trailing.slice(21).trim()
      if (msg.length === 0) {
        return bot.send(`@${message.user} Usage: !streamtime overwrite `+
                        `<message> (use $time$ to include a countdown to the `+
                        `next stream)`)
      }
      setOverwriteMsg(msg)
      debug(`Message overwritten by ${message.user} with ${msg}`)
      bot.send(`@${message.user} !streamtime has been overwritten`)
    })

    bot.command('!streamtime overwrite_time'
                , { rank: 'mod' }
                , (message) => {
      let spl = message.trailing.slice(26).trim().split(' ')
      if (spl.length < 3 || spl.length > 4) {
        return bot.send(invDate(message.user))
      }
      let year, month, day, hour, min
      let spl2 = spl[0].split('-')
      if (spl2.length !== 3) {
        return bot.send(invDate(message.user))
      }
      [year, month, day] = spl2
      let spl3 = spl[1].split(':')
      if (spl3.length === 1) {
        hour = parseInt(spl[1])
        min = 0
      } else if (spl3.length === 2) {
        debug(spl3);
        [hour, min] = spl3.map(i => parseInt(i))
      } else {
        return bot.send(invDate(message.user))
      }
      debug(hour, min)
      if (spl[2] === 'PM') {
        hour = (hour + 12) % 24
      } else if (spl[2] === 'AM' && hour == 12) {
        hour = 0
      } else if (spl[2] !== 'AM') {
        min += parseTimezone(spl[2])
      }
      if (spl.length === 4) {
        min += parseTimezone(spl[3])
      }
      debug(hour, min)
      let time = new Date(year, parseInt(month) - 1, day, hour, min)
      if (isNaN(time.getTime())) {
        return bot.send(invDate(message.user))
      }
      setOverwriteTime(time)
      bot.send(`@${message.user} Time for the next stream has been ` +
               `overwritten (next stream is now in `+
               `${countdown(overwrite.time).toString()}).`)
      debug(`Time to next stream overwritten by ${message.user} with ${time}`)
    })

    bot.command('!streamtime overwrite_discard'
                , { rank: 'mod' }
                , (message) => {
      setOverwriteMsg(null)
      setOverwriteTime(null)
      bot.send(`@${message.user} Overwrite has been discarded.`)
      debug(`Overwrite discarded by ${message.user}`)
    })

    bot.command('!streamtime update'
                , { throttle: 10000 }
                , (message) => {
      getTimes().then(() => bot.send(`@${message.user} Updated.`))
    })

    bot.command('!streamtime', (message, extra) => {
      if ([ 'overwrite', 'overwrite_time', 'overwrite_discard', 'update' ]
          .indexOf(extra) !== -1) {
        return
      }
      if (bot.isLive && additional !== 'next') {
        return bot.send("It's live! F5!")
      }
      let next = getNext()
      if (overwrite.msg !== null) {
        let msg = overwrite.msg
        if (overwrite.time !== null) {
          let now = new Date()
          if (overwrite.time < now &&
              overwrite.time > now.setMinutes(now.getMinutes - 5)) {
            return bot.send('The stream should have started a second ago!')
          }
          msg = msg.replace('$time$', countdown(overwrite.time).toString())
        } else if (next !== null) {
          msg = msg.replace('$time$', countdown(next[0]).toString())
        }
        return bot.send(msg)
      } else if (overwrite.time !== null) {
        return bot.send(`Stream in ${countdown(overwrite.time).toString()}.`)
      }
      if (next === null) {
        return bot.send(`There are currently no scheduled streams :/`)
      }
      if (next[0] < new Date()) {
        return bot.send('The stream should have started a second ago!')
      }
      let desc = exAssign(next[2], 'Stream')
      return bot.send(`${desc} in ${countdown(next[0]).toString()}`)
    })

  }

}
<|endoftext|>


<commit_before>import {Socket} from "deps/phoenix/web/static/js/phoenix";

angular.module('controllers', [])

.controller('DashCtrl', ['$scope', 'Restangular', 'poller', '$ionicModal', '$filter', function($scope, Restangular, poller, $ionicModal, $filter) {
  $scope.switches = Restangular.all('switches').getList().$object;

  var socket = new Socket("/socket");
  socket.connect();
  var channel = socket.channel("switches:lobby", {});
  channel.join().receive("ok", function(dt) {
    // wait for magic
  }).receive("error", function(dt) {
    // fallback to polling
    // poller.get(Restangular.all('switches'), {
    //     action: 'getList',
    //     delay: 3000
    // }).promise.then(null, null, function(switches){
    //   $scope.switches = switches;
    // });
  });

  channel.on("update", function(dt) {
    var switchItem = $filter('filter')($scope.switches, {id: dt.id})[0];
    $scope.$apply(function(){
      _.extend(switchItem,dt);
    });
  });

  $ionicModal.fromTemplateUrl('templates/edit-switch-modal.html', {
    scope: $scope
  }).then(function(modal) {
    $scope.switch_modal = modal;
  });

  $scope.editSwitch = function(switchItem) {
    $scope.edit_switch = switchItem;
    $scope.switch_modal.show();
    // $scope.data = { response: switchItem.name };
    // $ionicPopup.prompt({
    //   title: 'Edit',
    //   template: 'Rename Switch',
    //   inputType: 'text',
    //   scope: $scope
    // }).then(function() {
    //   switchItem.name = $scope.data.response;
    //   $scope.updateSwitch(switchItem);
    // });
  };
  $scope.updateSwitch = function(switchItem) {
    switchItem.save();
    $scope.switch_modal.hide();
  };
}]);
<commit_msg>move socket and channel to scope<commit_after>import {Socket} from "deps/phoenix/web/static/js/phoenix";

angular.module('controllers', [])

.controller('DashCtrl', ['$scope', 'Restangular', 'poller', '$ionicModal', '$filter', function($scope, Restangular, poller, $ionicModal, $filter) {
  $scope.switches = Restangular.all('switches').getList().$object;

  $scope.socket = new Socket("/socket");
  $scope.socket.connect();
  $scope.channel = $scope.socket.channel("switches:lobby", {});
  $scope.channel.join().receive("ok", function(dt) {
    // wait for magic
  }).receive("error", function(dt) {
    // fallback to polling
    // poller.get(Restangular.all('switches'), {
    //     action: 'getList',
    //     delay: 3000
    // }).promise.then(null, null, function(switches){
    //   $scope.switches = switches;
    // });
  });

  $scope.channel.on("update", function(dt) {
    var switchItem = $filter('filter')($scope.switches, {id: dt.id})[0];
    $scope.$apply(function(){
      _.extend(switchItem,dt);
    });
  });

  $ionicModal.fromTemplateUrl('templates/edit-switch-modal.html', {
    scope: $scope
  }).then(function(modal) {
    $scope.switch_modal = modal;
  });

  $scope.editSwitch = function(switchItem) {
    $scope.edit_switch = switchItem;
    $scope.switch_modal.show();
    // $scope.data = { response: switchItem.name };
    // $ionicPopup.prompt({
    //   title: 'Edit',
    //   template: 'Rename Switch',
    //   inputType: 'text',
    //   scope: $scope
    // }).then(function() {
    //   switchItem.name = $scope.data.response;
    //   $scope.updateSwitch(switchItem);
    // });
  };
  $scope.updateSwitch = function(switchItem) {
    switchItem.save();
    $scope.switch_modal.hide();
  };
}]);
<|endoftext|>


<commit_before>var pagination = require('hexo-pagination');
var _ = require('lodash');

hexo.extend.generator.register('category', function(locals){
  var config = this.config;
  var categories = locals.data.categories;
  if (config.category_generator) {
    var perPage = config.category_generator.per_page;
  } else {
    var perPage = 10;
  }
  var paginationDir = config.pagination_dir || 'page';
  var result = [];

  _.each(categories, function(data, title) {
    _.each(data, function(data, lang) {
      result = result.concat({
        path: lang + '/' + data.slug + '/index.html',
        data: {
          posts: getCategoryByName(locals.categories, data.category).posts
        },
        layout: ['archive', 'index']
      });
    });
  });

  return result;
});

function getCategoryByName(categories, name) {
  return categories.toArray().filter(function(category){
    return category.name == name;
  })[0];
}
<commit_msg>Use category layout if available in the category generator<commit_after>var pagination = require('hexo-pagination');
var _ = require('lodash');

hexo.extend.generator.register('category', function(locals){
  var config = this.config;
  var categories = locals.data.categories;
  if (config.category_generator) {
    var perPage = config.category_generator.per_page;
  } else {
    var perPage = 10;
  }
  var paginationDir = config.pagination_dir || 'page';
  var result = [];

  _.each(categories, function(data, title) {
    _.each(data, function(data, lang) {
      result = result.concat({
        path: lang + '/' + data.slug + '/index.html',
        data: {
          posts: getCategoryByName(locals.categories, data.category).posts
        },
        layout: ['category', 'archive', 'index']
      });
    });
  });

  return result;
});

function getCategoryByName(categories, name) {
  return categories.toArray().filter(function(category){
    return category.name == name;
  })[0];
}
<|endoftext|>


<commit_before>import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {Modal, Button} from 'react-bootstrap'
import EtherDisplay from "./EtherDisplay"

class FundOrderResultModal extends Component {

    render() {
        if (this.props.transaction===null) {
            return

        }

        let verifyUrl = 'https://etherchain.org/tx/' + this.props.transaction.hash

        const modal = (
            <Modal bsSize="small" show={this.props.showModal} onHide={this.props.onClose}>
                <Modal.Header closeButton>
                    <Modal.Title>Funding successfull</Modal.Title>
                </Modal.Header>
                <Modal.Body>

Sent <EtherDisplay wei={this.props.transaction.value}/>.

Verify on etherchain.org

                </Modal.Body>
                <Modal.Footer>
                    <Button onClick={this.props.onClose}>Close</Button>
                </Modal.Footer>
            </Modal>
        )

        return modal
    }
}

FundOrderResultModal.propTypes = {
    //order: PropTypes.object.isRequired,
    //onWithdraw: PropTypes.func.isRequired,
    showModal: PropTypes.bool.isRequired,
    onClose: PropTypes.func.isRequired,
}

export default FundOrderResultModal<commit_msg>Display dummy funding result data when transaction details could not be retrieved. This seems only to happen with testrpc running with -b.<commit_after>import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {Modal, Button, Alert} from 'react-bootstrap'
import EtherDisplay from "./EtherDisplay"

class FundOrderResultModal extends Component {

    render() {
        if (this.props.transaction===null) {
            return <Modal bsSize="small" show={this.props.showModal} onHide={this.props.onClose}>
                <Modal.Header closeButton>
                    <Modal.Title>Funding successfull</Modal.Title>
                </Modal.Header>
                <Modal.Body>
                    <Alert bsStyle="warning">
                        Got empty transaction result. This is most likely a bug in testRPC when running with -b option (background mining).
                    </Alert>

Sent XXX eth.

Verify on etherchain.org

                </Modal.Body>
                <Modal.Footer>
                    <Button onClick={this.props.onClose}>Close</Button>
                </Modal.Footer>
            </Modal>

        }

        let verifyUrl = 'https://etherchain.org/tx/' + this.props.transaction.hash

        const modal = (
            <Modal bsSize="small" show={this.props.showModal} onHide={this.props.onClose}>
                <Modal.Header closeButton>
                    <Modal.Title>Funding successfull</Modal.Title>
                </Modal.Header>
                <Modal.Body>

Sent <EtherDisplay wei={this.props.transaction.value}/>.

Verify on etherchain.org

                </Modal.Body>
                <Modal.Footer>
                    <Button onClick={this.props.onClose}>Close</Button>
                </Modal.Footer>
            </Modal>
        )

        return modal
    }
}

FundOrderResultModal.propTypes = {
    showModal: PropTypes.bool.isRequired,
    onClose: PropTypes.func.isRequired,
}

export default FundOrderResultModal<|endoftext|>