<commit_before>import _ from 'lodash';
import irc from 'irc';
import logger from 'winston';
import discord from 'discord.js';
import { ConfigurationError } from './errors';
import { validateChannelMapping } from './validators';
import { formatFromDiscordToIRC, formatFromIRCToDiscord } from './formatting';

const REQUIRED_FIELDS = ['server', 'nickname', 'channelMapping', 'discordToken'];
const NICK_COLORS = ['light_blue', 'dark_blue', 'light_red', 'dark_red', 'light_green',
  'dark_green', 'magenta', 'light_magenta', 'orange', 'yellow', 'cyan', 'light_cyan'];
const patternMatch = /{\$(.+?)}/g;

/**
 * An IRC bot, works as a middleman for all communication
 * @param {object} options - server, nickname, channelMapping, outgoingToken, incomingURL
 */
class Bot {
  constructor(options) {
    REQUIRED_FIELDS.forEach((field) => {
      if (!options[field]) {
        throw new ConfigurationError(`Missing configuration field ${field}`);
      }
    });

    validateChannelMapping(options.channelMapping);

    this.discord = new discord.Client({ autoReconnect: true });

    this.server = options.server;
    this.nickname = options.nickname;
    this.ircOptions = options.ircOptions;
    this.discordToken = options.discordToken;
    this.commandCharacters = options.commandCharacters || [];
    this.ircNickColor = options.ircNickColor !== false; // default to true
    this.channels = _.values(options.channelMapping);

    this.format = options.format || {};
    // "{$keyName}" => "variableValue"
    // nickname: discord nickname
    // displayUsername: nickname with wrapped colors
    // text: the (IRC-formatted) message content
    // discordChannel: Discord channel (e.g. #general)
    // ircChannel: IRC channel (e.g. #irc)
    // attachmentURL: the URL of the attachment (only applicable in formatURLAttachment)
    this.formatCommandPrelude = this.format.commandPrelude || 'Command sent from Discord by {$nickname}:';
    this.formatIRCText = this.format.ircText || '<{$displayUsername}> {$text}';
    this.formatURLAttachment = this.format.urlAttachment || '<{$displayUsername}> {$attachmentURL}';

    // "{$keyName}" => "variableValue"
    // author: IRC nickname
    // text: the (Discord-formatted) message content
    // withMentions: text with appropriate mentions reformatted
    // discordChannel: Discord channel (e.g. #general)
    // ircChannel: IRC channel (e.g. #irc)
    this.formatDiscord = this.format.discord || '**<{$author}>** {$withMentions}';

    this.channelMapping = {};

    // Remove channel passwords from the mapping and lowercase IRC channel names
    _.forOwn(options.channelMapping, (ircChan, discordChan) => {
      this.channelMapping[discordChan] = ircChan.split(' ')[0].toLowerCase();
    });

    this.invertedMapping = _.invert(this.channelMapping);
    this.autoSendCommands = options.autoSendCommands || [];
  }

  connect() {
    logger.debug('Connecting to IRC and Discord');
    this.discord.login(this.discordToken);

    const ircOptions = {
      userName: this.nickname,
      realName: this.nickname,
      channels: this.channels,
      floodProtection: true,
      floodProtectionDelay: 500,
      retryCount: 10,
      ...this.ircOptions
    };

    this.ircClient = new irc.Client(this.server, this.nickname, ircOptions);
    this.attachListeners();
  }

  attachListeners() {
    this.discord.on('ready', () => {
      logger.info('Connected to Discord');
    });

    this.ircClient.on('registered', (message) => {
      logger.info('Connected to IRC');
      logger.debug('Registered event: ', message);
      this.autoSendCommands.forEach((element) => {
        this.ircClient.send(...element);
      });
    });

    this.ircClient.on('error', (error) => {
      logger.error('Received error event from IRC', error);
    });

    this.discord.on('error', (error) => {
      logger.error('Received error event from Discord', error);
    });

    this.discord.on('warn', (warning) => {
      logger.warn('Received warn event from Discord', warning);
    });

    this.discord.on('message', (message) => {
      // Ignore bot messages and people leaving/joining
      this.sendToIRC(message);
    });

    this.ircClient.on('message', this.sendToDiscord.bind(this));

    this.ircClient.on('notice', (author, to, text) => {
      this.sendToDiscord(author, to, `*${text}*`);
    });

    /**
     * Notify Discord that an IRC client has joined
     * @param   channel   The channel the user joined
     * @param   user      The nickname of the user who joined
     * @param   text      undefined?
     **/
    this.ircClient.on('join', function (channel, user) {
      this.sendSpecialToDiscord(channel, `*${user}* has joined the channel`);
    });

    /**
     * Notify Discord that an IRC client has parted
     * @param   channel   The channel the user parted
     * @param   user      The nickname of the user who parted
     * @param   text      undefined?
     **/
    this.ircClient.on('part', function (channel, user) {
      this.sendSpecialToDiscord(channel, `*${user}* has left the channel`);
    });

    /**
     * Notify Discord that an IRC client has joined
     * @param   user      The nickname of the user who quit
     * @param   reason    The reason why the user quit
     * @param   channel   The channel(s?) they quit from)
     **/
    this.ircClient.on('quit', function (user, reason, channel) {
      this.sendSpecialToDiscord(String(channel), `*${user}* has quit (${reason})`);
    });

    this.ircClient.on('action', (author, to, text) => {
      this.sendToDiscord(author, to, `_${text}_`);
    });

    this.ircClient.on('invite', (channel, from) => {
      logger.debug('Received invite:', channel, from);
      if (!this.invertedMapping[channel]) {
        logger.debug('Channel not found in config, not joining:', channel);
      } else {
        this.ircClient.join(channel);
        logger.debug('Joining channel:', channel);
      }
    });

    if (logger.level === 'debug') {
      this.discord.on('debug', (message) => {
        logger.debug('Received debug event from Discord', message);
      });
    }
  }

  static getDiscordNicknameOnServer(user, guild) {
    const userDetails = guild.members.get(user.id);
    if (userDetails) {
      return userDetails.nickname || user.username;
    }
    return user.username;
  }

  parseText(message) {
    const text = message.mentions.users.reduce((content, mention) => {
      const displayName = Bot.getDiscordNicknameOnServer(mention, message.guild);
      return content.replace(`<@${mention.id}>`, `@${displayName}`)
             .replace(`<@!${mention.id}>`, `@${displayName}`)
             .replace(`<@&${mention.id}>`, `@${displayName}`);
    }, message.content);

    return text
      .replace(/\n|\r\n|\r/g, ' ')
      .replace(/<#(\d+)>/g, (match, channelId) => {
        const channel = this.discord.channels.get(channelId);
        if (channel) return `#${channel.name}`;
        return '#deleted-channel';
      })
      .replace(/<@&(\d+)>/g, (match, roleId) => {
        const role = message.guild.roles.get(roleId);
        if (role) return `@${role.name}`;
        return '@deleted-role';
      })
      .replace(/<(:\w+:)\d+>/g, (match, emoteName) => emoteName);
  }

  isCommandMessage(message) {
    return this.commandCharacters.indexOf(message[0]) !== -1;
  }

  static substitutePattern(message, patternMapping) {
    return message.replace(patternMatch, (match, varName) => patternMapping[varName] || match);
  }

  sendToIRC(message) {
    const author = message.author;
    // Ignore messages sent by the bot itself:
    if (author.id === this.discord.user.id) return;

    const channelName = `#${message.channel.name}`;
    const ircChannel = this.channelMapping[message.channel.id] ||
                                           this.channelMapping[channelName];

    logger.debug('Channel Mapping', channelName, this.channelMapping[channelName]);
    if (ircChannel) {
      const fromGuild = message.guild;
      const nickname = Bot.getDiscordNicknameOnServer(author, fromGuild);
      let text = this.parseText(message);
      let displayUsername = nickname;
      if (this.ircNickColor) {
        const colorIndex = (nickname.charCodeAt(0) + nickname.length) % NICK_COLORS.length;
        displayUsername = irc.colors.wrap(NICK_COLORS[colorIndex], nickname);
      }

      const patternMap = {
        nickname,
        displayUsername,
        text,
        discordChannel: channelName,
        ircChannel
      };

      if (this.isCommandMessage(text)) {
        const prelude = Bot.substitutePattern(this.formatCommandPrelude, patternMap);
        this.ircClient.say(ircChannel, prelude);
        this.ircClient.say(ircChannel, text);
      } else if (message.attachments && message.attachments.length) {
        message.attachments.forEach(a => {
          const urlMessage =
            `${coloredUsername} posted an attachment to ${channelName} on Discord: ${a.url}`;
          logger.debug('Sending attachment URL to IRC', ircChannel, urlMessage);
          this.ircClient.say(ircChannel, urlMessage);
        });
      } else {
        if (text !== '') {
          // Convert formatting
          text = formatFromDiscordToIRC(text);
          patternMap.text = text;

          text = Bot.substitutePattern(this.formatIRCText, patternMap);
          logger.debug('Sending message to IRC', ircChannel, text);
          this.ircClient.say(ircChannel, text);
        }

        if (message.attachments && message.attachments.size) {
          message.attachments.forEach((a) => {
            patternMap.attachmentURL = a.url;
            const urlMessage = Bot.substitutePattern(this.formatURLAttachment, patternMap);

            logger.debug('Sending attachment URL to IRC', ircChannel, urlMessage);
            this.ircClient.say(ircChannel, urlMessage);
          });
        }
      }
    }
  }

  sendToDiscord(author, channel, text) {
    const discordChannelName = this.invertedMapping[channel.toLowerCase()];
    if (discordChannelName) {
      // #channel -> channel before retrieving and select only text channels:
      const discordChannel = discordChannelName.startsWith('#') ? this.discord.channels
        .filter(c => c.type === 'text')
        .find('name', discordChannelName.slice(1)) : this.discord.channels.get(discordChannelName);

      if (!discordChannel) {
        logger.info('Tried to send a message to a channel the bot isn\'t in: ',
          discordChannelName);
        return;
      }

      // Convert text formatting (bold, italics, underscore)
      const withFormat = formatFromIRCToDiscord(text);

      const withMentions = withFormat.replace(/@[^\s]+\b/g, (match) => {
        const search = match.substring(1);
        const guild = discordChannel.guild;
        const nickUser = guild.members.find('nickname', search);
        if (nickUser) {
          return nickUser;
        }

        const user = this.discord.users.find('username', search);
        if (user) {
          return user;
        }

        const role = guild.roles.find('name', search);
        if (role && role.mentionable) {
          return role;
        }

        return match;
      });

      const patternMap = {
        author,
        text: withFormat,
        withMentions,
        discordChannel: `#${discordChannel.name}`,
        ircChannel: channel
      };

      // Add bold formatting:
      // Use custom formatting from config / default formatting with bold author
      const withAuthor = Bot.substitutePattern(this.formatDiscord, patternMap);
      logger.debug('Sending message to Discord', withAuthor, channel, '->', discordChannelName);
      discordChannel.sendMessage(withAuthor);
    }
  }

  /**
   * Sends a message to Discord exactly as it appears
   * @param   channel   The channel to send to
   * @param   text      The text to send to discord
   **/
  sendSpecialToDiscord(channel, text) {
    const discordChannelName = this.invertedMapping[channel.toLowerCase()];
    if (discordChannelName) {
    // #channel -> channel before retrieving:
      const discordChannel = this.discord.channels.get('name', discordChannelName.slice(1));

      if (!discordChannel) {
        logger.info('Tried to send a message to a channel the bot isn\'t in: ',
        discordChannelName);
        return;
      }

      logger.debug('Sending special message to Discord', text, channel, '->', discordChannelName);
      this.discord.sendMessage(discordChannel, text);
    }
  }
}

export default Bot;
<commit_msg>Fixed functions being broken<commit_after>import _ from 'lodash';
import irc from 'irc';
import logger from 'winston';
import discord from 'discord.js';
import { ConfigurationError } from './errors';
import { validateChannelMapping } from './validators';
import { formatFromDiscordToIRC, formatFromIRCToDiscord } from './formatting';

const REQUIRED_FIELDS = ['server', 'nickname', 'channelMapping', 'discordToken'];
const NICK_COLORS = ['light_blue', 'dark_blue', 'light_red', 'dark_red', 'light_green',
  'dark_green', 'magenta', 'light_magenta', 'orange', 'yellow', 'cyan', 'light_cyan'];
const patternMatch = /{\$(.+?)}/g;

/**
 * An IRC bot, works as a middleman for all communication
 * @param {object} options - server, nickname, channelMapping, outgoingToken, incomingURL
 */
class Bot {
  constructor(options) {
    REQUIRED_FIELDS.forEach((field) => {
      if (!options[field]) {
        throw new ConfigurationError(`Missing configuration field ${field}`);
      }
    });

    validateChannelMapping(options.channelMapping);

    this.discord = new discord.Client({ autoReconnect: true });

    this.server = options.server;
    this.nickname = options.nickname;
    this.ircOptions = options.ircOptions;
    this.discordToken = options.discordToken;
    this.commandCharacters = options.commandCharacters || [];
    this.ircNickColor = options.ircNickColor !== false; // default to true
    this.channels = _.values(options.channelMapping);

    this.format = options.format || {};
    // "{$keyName}" => "variableValue"
    // nickname: discord nickname
    // displayUsername: nickname with wrapped colors
    // text: the (IRC-formatted) message content
    // discordChannel: Discord channel (e.g. #general)
    // ircChannel: IRC channel (e.g. #irc)
    // attachmentURL: the URL of the attachment (only applicable in formatURLAttachment)
    this.formatCommandPrelude = this.format.commandPrelude || 'Command sent from Discord by {$nickname}:';
    this.formatIRCText = this.format.ircText || '<{$displayUsername}> {$text}';
    this.formatURLAttachment = this.format.urlAttachment || '<{$displayUsername}> {$attachmentURL}';

    // "{$keyName}" => "variableValue"
    // author: IRC nickname
    // text: the (Discord-formatted) message content
    // withMentions: text with appropriate mentions reformatted
    // discordChannel: Discord channel (e.g. #general)
    // ircChannel: IRC channel (e.g. #irc)
    this.formatDiscord = this.format.discord || '**<{$author}>** {$withMentions}';

    this.channelMapping = {};

    // Remove channel passwords from the mapping and lowercase IRC channel names
    _.forOwn(options.channelMapping, (ircChan, discordChan) => {
      this.channelMapping[discordChan] = ircChan.split(' ')[0].toLowerCase();
    });

    this.invertedMapping = _.invert(this.channelMapping);
    this.autoSendCommands = options.autoSendCommands || [];
  }

  connect() {
    logger.debug('Connecting to IRC and Discord');
    this.discord.login(this.discordToken);

    const ircOptions = {
      userName: this.nickname,
      realName: this.nickname,
      channels: this.channels,
      floodProtection: true,
      floodProtectionDelay: 500,
      retryCount: 10,
      ...this.ircOptions
    };

    this.ircClient = new irc.Client(this.server, this.nickname, ircOptions);
    this.attachListeners();
  }

  attachListeners() {
    this.discord.on('ready', () => {
      logger.info('Connected to Discord');
    });

    this.ircClient.on('registered', (message) => {
      logger.info('Connected to IRC');
      logger.debug('Registered event: ', message);
      this.autoSendCommands.forEach((element) => {
        this.ircClient.send(...element);
      });
    });

    this.ircClient.on('error', (error) => {
      logger.error('Received error event from IRC', error);
    });

    this.discord.on('error', (error) => {
      logger.error('Received error event from Discord', error);
    });

    this.discord.on('warn', (warning) => {
      logger.warn('Received warn event from Discord', warning);
    });

    this.discord.on('message', (message) => {
      // Ignore bot messages and people leaving/joining
      this.sendToIRC(message);
    });

    this.ircClient.on('message', this.sendToDiscord.bind(this));

    this.ircClient.on('notice', (author, to, text) => {
      this.sendToDiscord(author, to, `*${text}*`);
    });

    /**
     * Notify Discord that an IRC client has joined
     * @param   channel   The channel the user joined
     * @param   user      The nickname of the user who joined
     * @param   text      undefined?
     **/
    this.ircClient.on('join', (channel, user) => {
      this.sendSpecialToDiscord(channel, `*${user}* has joined the channel`);
    });

    /**
     * Notify Discord that an IRC client has parted
     * @param   channel   The channel the user parted
     * @param   user      The nickname of the user who parted
     * @param   text      undefined?
     **/
    this.ircClient.on('part', (channel, user) => {
      this.sendSpecialToDiscord(channel, `*${user}* has left the channel`);
    });

    /**
     * Notify Discord that an IRC client has joined
     * @param   user      The nickname of the user who quit
     * @param   reason    The reason why the user quit
     * @param   channel   The channel(s?) they quit from)
     **/
    this.ircClient.on('quit', (user, reason, channel) => {
      this.sendSpecialToDiscord(String(channel), `*${user}* has quit (${reason})`);
    });

    this.ircClient.on('action', (author, to, text) => {
      this.sendToDiscord(author, to, `_${text}_`);
    });

    this.ircClient.on('invite', (channel, from) => {
      logger.debug('Received invite:', channel, from);
      if (!this.invertedMapping[channel]) {
        logger.debug('Channel not found in config, not joining:', channel);
      } else {
        this.ircClient.join(channel);
        logger.debug('Joining channel:', channel);
      }
    });

    if (logger.level === 'debug') {
      this.discord.on('debug', (message) => {
        logger.debug('Received debug event from Discord', message);
      });
    }
  }

  static getDiscordNicknameOnServer(user, guild) {
    const userDetails = guild.members.get(user.id);
    if (userDetails) {
      return userDetails.nickname || user.username;
    }
    return user.username;
  }

  parseText(message) {
    const text = message.mentions.users.reduce((content, mention) => {
      const displayName = Bot.getDiscordNicknameOnServer(mention, message.guild);
      return content.replace(`<@${mention.id}>`, `@${displayName}`)
             .replace(`<@!${mention.id}>`, `@${displayName}`)
             .replace(`<@&${mention.id}>`, `@${displayName}`);
    }, message.content);

    return text
      .replace(/\n|\r\n|\r/g, ' ')
      .replace(/<#(\d+)>/g, (match, channelId) => {
        const channel = this.discord.channels.get(channelId);
        if (channel) return `#${channel.name}`;
        return '#deleted-channel';
      })
      .replace(/<@&(\d+)>/g, (match, roleId) => {
        const role = message.guild.roles.get(roleId);
        if (role) return `@${role.name}`;
        return '@deleted-role';
      })
      .replace(/<(:\w+:)\d+>/g, (match, emoteName) => emoteName);
  }

  isCommandMessage(message) {
    return this.commandCharacters.indexOf(message[0]) !== -1;
  }

  static substitutePattern(message, patternMapping) {
    return message.replace(patternMatch, (match, varName) => patternMapping[varName] || match);
  }

  sendToIRC(message) {
    const author = message.author;
    // Ignore messages sent by the bot itself:
    if (author.id === this.discord.user.id) return;

    const channelName = `#${message.channel.name}`;
    const ircChannel = this.channelMapping[message.channel.id] ||
                                           this.channelMapping[channelName];

    logger.debug('Channel Mapping', channelName, this.channelMapping[channelName]);
    if (ircChannel) {
      const fromGuild = message.guild;
      const nickname = Bot.getDiscordNicknameOnServer(author, fromGuild);
      let text = this.parseText(message);
      let displayUsername = nickname;
      if (this.ircNickColor) {
        const colorIndex = (nickname.charCodeAt(0) + nickname.length) % NICK_COLORS.length;
        displayUsername = irc.colors.wrap(NICK_COLORS[colorIndex], nickname);
      }

      const patternMap = {
        nickname,
        displayUsername,
        text,
        discordChannel: channelName,
        ircChannel
      };

      if (this.isCommandMessage(text)) {
        const prelude = Bot.substitutePattern(this.formatCommandPrelude, patternMap);
        this.ircClient.say(ircChannel, prelude);
        this.ircClient.say(ircChannel, text);
      } else if (message.attachments && message.attachments.length) {
        message.attachments.forEach(a => {
          const urlMessage =
            `${coloredUsername} posted an attachment to ${channelName} on Discord: ${a.url}`;
          logger.debug('Sending attachment URL to IRC', ircChannel, urlMessage);
          this.ircClient.say(ircChannel, urlMessage);
        });
      } else {
        if (text !== '') {
          // Convert formatting
          text = formatFromDiscordToIRC(text);
          patternMap.text = text;

          text = Bot.substitutePattern(this.formatIRCText, patternMap);
          logger.debug('Sending message to IRC', ircChannel, text);
          this.ircClient.say(ircChannel, text);
        }

        if (message.attachments && message.attachments.size) {
          message.attachments.forEach((a) => {
            patternMap.attachmentURL = a.url;
            const urlMessage = Bot.substitutePattern(this.formatURLAttachment, patternMap);

            logger.debug('Sending attachment URL to IRC', ircChannel, urlMessage);
            this.ircClient.say(ircChannel, urlMessage);
          });
        }
      }
    }
  }

  sendToDiscord(author, channel, text) {
    const discordChannelName = this.invertedMapping[channel.toLowerCase()];
    if (discordChannelName) {
      // #channel -> channel before retrieving and select only text channels:
      const discordChannel = discordChannelName.startsWith('#') ? this.discord.channels
        .filter(c => c.type === 'text')
        .find('name', discordChannelName.slice(1)) : this.discord.channels.get(discordChannelName);

      if (!discordChannel) {
        logger.info('Tried to send a message to a channel the bot isn\'t in: ',
          discordChannelName);
        return;
      }

      // Convert text formatting (bold, italics, underscore)
      const withFormat = formatFromIRCToDiscord(text);

      const withMentions = withFormat.replace(/@[^\s]+\b/g, (match) => {
        const search = match.substring(1);
        const guild = discordChannel.guild;
        const nickUser = guild.members.find('nickname', search);
        if (nickUser) {
          return nickUser;
        }

        const user = this.discord.users.find('username', search);
        if (user) {
          return user;
        }

        const role = guild.roles.find('name', search);
        if (role && role.mentionable) {
          return role;
        }

        return match;
      });

      const patternMap = {
        author,
        text: withFormat,
        withMentions,
        discordChannel: `#${discordChannel.name}`,
        ircChannel: channel
      };

      // Add bold formatting:
      // Use custom formatting from config / default formatting with bold author
      const withAuthor = Bot.substitutePattern(this.formatDiscord, patternMap);
      logger.debug('Sending message to Discord', withAuthor, channel, '->', discordChannelName);
      discordChannel.sendMessage(withAuthor);
    }
  }

  /**
   * Sends a message to Discord exactly as it appears
   * @param   channel   The channel to send to
   * @param   text      The text to send to discord
   **/
  sendSpecialToDiscord(channel, text) {
    const discordChannelName = this.invertedMapping[channel.toLowerCase()];
    if (discordChannelName) {
    // #channel -> channel before retrieving:
      const discordChannel = this.discord.channels.get('name', discordChannelName.slice(1));

      if (!discordChannel) {
        logger.info('Tried to send a message to a channel the bot isn\'t in: ',
        discordChannelName);
        return;
      }

      logger.debug('Sending special message to Discord', text, channel, '->', discordChannelName);
      this.discord.sendMessage(discordChannel, text);
    }
  }
}

export default Bot;
<|endoftext|>


<commit_before>var util = require('util');
var request = require('request');
var winston = require('winston');
var BaseTrigger = require('./baseTrigger.js').BaseTrigger;

/*
Trigger that automatically looks up users on reddit when they join.
*/

var RedditTrigger = function() {
	RedditTrigger.super_.apply(this, arguments);
};

util.inherits(RedditTrigger, BaseTrigger);

var type = "RedditTrigger";
exports.triggerType = type;
exports.create = function(name, chatBot, options) {
	var trigger = new RedditTrigger(type, name, chatBot, options);
	trigger.respectsMute = false;
	return trigger;
};

RedditTrigger.prototype._respondToEnteredMessage = function(roomId, userId) {
	return this._respond(roomId,userId);
}

RedditTrigger.prototype._respond = function(toId, message) {
	console.log(type);
	if(!this.options.redditapiurl) {
		console.log("Reddit API Url not defined! Cannot look up user!");
		return false;
	}
	var steamid = this._stripCommand(message);
	var steamid = ""+userToCheck+"";
	if (steamid) {
		var that = this;
		var steamrep={};
		winston.info("Checking reddit for " + steamid);
		request.get({method:'GET',encoding:'utf8',uri:that.options.redditapiurl+"steamid/"+steamid,json:true,followAllRedirects:true}, function(error, response, body) {
			if (error) {
				that._sendMessageAfterDelay(toId, "¯\\_(ツ)_/¯");
				winston.warn("Code " + response.statusCode + " from REDDIT for steamid " + steamid);
				return;
			}
			redditinfo = body;
			var result = that._getParsedResultForRequest(redditinfo, steamid);
			if (result) {
				that._sendMessageAfterDelay(toId, result);
			}
			else {
				that._sendMessageAfterDelay(toId, "¯\\_(ツ)_/¯");
			}
		});
			return true;
	}
	return false;
}

RedditTrigger.prototype._stripCommand = function(message) {
	if (this.options.command && message && message.toLowerCase().indexOf(this.options.command.toLowerCase() + " ") == 0) {
		return message.substring(this.options.command.length + 1);
	}
	return null;
}

RedditTrigger.prototype._getParsedResultForRequest = function(redditinput, steamid) {
	if (redditinput && redditinput.success) {
		var message="";
		if(redditinput.success && redditinput.banstatus) {
			message += ((this.chatBot.steamClient.users && steamid in this.chatBot.steamClient.users) ? (this.chatBot.steamClient.users[steamid].playerName + "/"+steamid) : steamid) + " has been BANNED from /r/SGS.";
			message += (redditinput.reddit ? ("\nReddit profile: http://www.reddit.com/user/"+redditinput.reddit) : "");
			message += "\nSteam Profile: http://steamcommunity.com/profiles/"+steamid;
			message += "\nSteamrep: http://steamrep.com/profiles/" + steamid;
			message += (redditinput.banreason ? ("\nReddit Ban Reason: " + redditinput.banreason) : "");
		} else if(redditinput.success && redditinput.flair.substr(0,3) == "mod") {
			message = "That is "+((this.chatBot.steamClient.users && steamid in this.chatBot.steamClient.users) ? (this.chatBot.steamClient.users[steamid].playerName + "/"+steamid) : steamid);
			message += " AKA /u/" + redditinput.reddit + ", moderator(?) of /r/SGS! Their (raw) flair is " + redditinput.flair;
		} else if(redditinput.success) {
			var flair = ". Their current flair level is ";
			if(redditinput.flair=="tier0")      flair+= "tier0 Black, with no recorded trades in /r/SGS.";
			else if(redditinput.flair=="tier1") flair+= "tier1 Gray, with 1+ SGS trades.";
			else if(redditinput.flair=="tier2") flair+= "tier2 Blue, with 5+ SGS trades.";
			else if(redditinput.flair=="tier3") flair+= "tier3 Red, with 10+ SGS trades.";
			else if(redditinput.flair=="tier4") flair+= "tier4 Green, with 20+ SGS trades.";
			else if(redditinput.flair=="tier5") flair+= "tier5 Purple, with 50+ SGS trades.";
			else flair += "not a level I understand. The raw data I got was '"+redditinput.flair+"'.";
			message = "That is "+((this.chatBot.steamClient.users && steamid in this.chatBot.steamClient.users) ? (this.chatBot.steamClient.users[steamid].playerName + "/"+steamid) : steamid);
			message += " AKA /u/" + redditinput.reddit + flair;
		}
		return message;
	}
	return null;
}
<commit_msg>Update redditTrigger.js<commit_after>var util = require('util');
var request = require('request');
var winston = require('winston');
var BaseTrigger = require('./baseTrigger.js').BaseTrigger;

/*
Trigger that automatically looks up users on reddit when they join.
*/

var RedditTrigger = function() {
	RedditTrigger.super_.apply(this, arguments);
};

util.inherits(RedditTrigger, BaseTrigger);

var type = "RedditTrigger";
exports.triggerType = type;
exports.create = function(name, chatBot, options) {
	var trigger = new RedditTrigger(type, name, chatBot, options);
	trigger.respectsMute = false;
	return trigger;
};

// Return true if a message was sent
RedditTrigger.prototype._respondToFriendMessage = function(userId, message) {
	return this._respond(userId, message);
}

// Return true if a message was sent
RedditTrigger.prototype._respondToChatMessage = function(roomId, chatterId, message) {
	return this._respond(roomId, message);
}

RedditTrigger.prototype._respond = function(toId, message) {
	if(!this.options.redditapiurl) {
		console.log("Reddit API Url not defined! Cannot look up user!");
		return false;
	}
	var steamid = this._stripCommand(message);
	if (steamid) {
		var that = this;
		var steamrep={};
		var steamid = steamid.replace("http://","").replace("https://","").replace("reddit.com/","").replace("www.","").replace("steamcommunity.com/profiles/","");
		var fullurl = that.options.redditapiurl + (!isNaN(steamid) ? "steamid/" + steamid : "reddit/" + steamid.replace("/u/","").replace("/user/","").replace("u/","").replace("user/",""));
		winston.info("Checking reddit for " + steamid);
		request.get({method:'GET',encoding:'utf8',uri:fullurl,json:true,followAllRedirects:true}, function(error, response, body) {
			if (error) {
				that._sendMessageAfterDelay(toId, "¯\\_(ツ)_/¯");
				winston.warn("Code " + response.statusCode + " from REDDIT for steamid " + steamid);
				return;
			}
			redditinfo = body;
			redditinfo.steamid = redditinfo.steamid.replace("http://steamcommunity.com/profiles/","");
			var result = that._getParsedResultForRequest(redditinfo, redditinfo.steamid);
			if (result) {
				that._sendMessageAfterDelay(toId, result);
			}
			else {
				that._sendMessageAfterDelay(toId, "¯\\_(ツ)_/¯");
			}
		});
			return true;
	}
	return false;
}

RedditTrigger.prototype._stripCommand = function(message) {
	if (this.options.command && message && message.toLowerCase().indexOf(this.options.command.toLowerCase() + " ") == 0) {
		return message.substring(this.options.command.length + 1);
	}
	return null;
}

RedditTrigger.prototype._getParsedResultForRequest = function(redditinput, steamid) {
	if (redditinput && redditinput.success) {
		var message="";
		if(redditinput.success && redditinput.banstatus) {
			message += ((this.chatBot.steamClient.users && steamid in this.chatBot.steamClient.users) ? (this.chatBot.steamClient.users[steamid].playerName + "/"+steamid) : steamid) + " has been BANNED from /r/SGS.";
			message += (redditinput.reddit ? ("\nReddit profile: http://www.reddit.com/user/"+redditinput.reddit) : "");
			message += "\nSteam Profile: http://steamcommunity.com/profiles/"+steamid;
			message += "\nSteamrep: http://steamrep.com/profiles/" + steamid;
			message += (redditinput.banreason ? ("\nReddit Ban Reason: " + redditinput.banreason) : "");
		} else if(redditinput.success && redditinput.flair.substr(0,3) == "mod") {
			message = "That is "+((this.chatBot.steamClient.users && steamid in this.chatBot.steamClient.users) ? (this.chatBot.steamClient.users[steamid].playerName + "/"+steamid) : steamid);
			message += " AKA /u/" + redditinput.reddit + ", moderator(?) of /r/SGS! Their (raw) flair is " + redditinput.flair;
		} else if(redditinput.success) {
			var flair = ". Their current flair level is ";
			if(redditinput.flair=="tier0")       flair+= "tier0 White, with no recorded trades in /r/SGS.";
			else if(redditinput.flair=="tier1")  flair+= "tier1 Gray, with 1+ SGS trades.";
			else if(redditinput.flair=="tier2")  flair+= "tier2 Blue, with 5+ SGS trades.";
			else if(redditinput.flair=="tier3")  flair+= "tier3 Red, with 10+ SGS trades.";
			else if(redditinput.flair=="tier4")  flair+= "tier4 Green, with 20+ SGS trades.";
			else if(redditinput.flair=="tier5")  flair+= "tier5 Purple, with 50+ SGS trades.";
			else if(redditinput.flair=="white")  flair+= "tier0 White, with no recorded trades in /r/SGS.";
			else if(redditinput.flair=="gray")   flair+= "tier1 Gray, with 1+ SGS trades.";
			else if(redditinput.flair=="blue")   flair+= "tier2 Blue, with 5+ SGS trades.";
			else if(redditinput.flair=="red")    flair+= "tier3 Red, with 10+ SGS trades.";
			else if(redditinput.flair=="green")  flair+= "tier4 Green, with 20+ SGS trades.";
			else if(redditinput.flair=="purple") flair+= "tier5 Purple, with 50+ SGS trades.";
			else flair += "not a level I understand. The raw data I got was '"+redditinput.flair+"'.";
			message = "That is "+((this.chatBot.steamClient.users && steamid in this.chatBot.steamClient.users) ? (this.chatBot.steamClient.users[steamid].playerName + "/"+steamid) : steamid);
			message += " AKA /u/" + redditinput.reddit + flair;
		}
		return message;
	}
	return null;
}
<|endoftext|>


<commit_before>import { registrar } from '/imports/lib/ethereum';
import Helpers from '/imports/lib/helpers/helperFunctions';

function updateRevealedStatus(template, bid) {
  registrar.isBidRevealed(bid, (err, isRevealed) => {
    if(err) {
      console.error('Error getting revealed status for bid');
      return;
    }
    TemplateVar.set(template, 'isRevealed', isRevealed);
    MyBids.update({ _id: bid._id }, { $set: {revealed: isRevealed} });
  })
}

Template['components_bid'].onCreated(function() {
  let template = Template.instance();
  let bid = template.data.bid;
  updateRevealedStatus(template, bid);
})

Template['components_bid'].events({
  'click .reveal-bid': function() {
    let template = Template.instance();
    let bid = template.data.bid.bid ? template.data.bid.bid : template.data.bid;
    MyBids.update({ _id: bid._id }, { $set: {revealing: true} });

    // Names.update({fullname: })
    // Any account can reveal
    let mainAccount = web3.eth.accounts[0];

    registrar.unsealBid(bid, {
      from: mainAccount,
      gas: 300000
    }, Helpers.getTxHandler({
      onDone: () => MyBids.update({ _id: bid._id }, { $set: {revealing: false} }),
      onSuccess: () => updateRevealedStatus(template, bid)
    }));
  }
})

Template['components_bid'].helpers({
  isRevealed() {
    return TemplateVar.get('isRevealed');
  },
  revealing() {
    return MyBids.findOne({_id: this.bid._id}).revealing;
  },
  canReveal() {
    return this.status == 'reveal';
  }
})
<commit_msg>Move bid 'revealing' status from db to template<commit_after>import { registrar } from '/imports/lib/ethereum';
import Helpers from '/imports/lib/helpers/helperFunctions';

function updateRevealedStatus(template, bid) {
  registrar.isBidRevealed(bid, (err, isRevealed) => {
    if(err) {
      console.error('Error getting revealed status for bid');
      return;
    }
    TemplateVar.set(template, 'isRevealed', isRevealed);
    MyBids.update({ _id: bid._id }, { $set: {revealed: isRevealed} });
  })
}

Template['components_bid'].onCreated(function() {
  let template = Template.instance();
  let bid = template.data.bid;
  updateRevealedStatus(template, bid);
  TemplateVar.set(template, 'revealing', false)
})

Template['components_bid'].events({
  'click .reveal-bid': function(e, template) {
    let bid = template.data.bid.bid ? template.data.bid.bid : template.data.bid;
    TemplateVar.set(template, 'revealing', true);
    // Names.update({fullname: })
    // Any account can reveal
    let mainAccount = web3.eth.accounts[0];

    registrar.unsealBid(bid, {
      from: mainAccount,
      gas: 300000
    }, Helpers.getTxHandler({
      onDone: () => TemplateVar.set(template, 'revealing', false),
      onSuccess: () => updateRevealedStatus(template, bid)
    }));
  }
})

Template['components_bid'].helpers({
  isRevealed() {
    return TemplateVar.get('isRevealed');
  },
  revealing() {
    return TemplateVar.get('revealing');
  },
  canReveal() {
    return this.status == 'reveal';
  }
})
<|endoftext|>


<commit_before>'use strict'

const tls = require('tls')
const assert = require('assert')
const EventEmitter = require('events').EventEmitter

const parser = require('./parser')

const TwitchBot = class TwitchBot extends EventEmitter {

  constructor({
    username,
    oauth,
    channel,
    port=443,
    silence=false
  }) {
    super()

    try {
      assert(username)
      assert(oauth)
      assert(channel)
    } catch(err) {
      throw new Error('missing required arguments')
    }

    this.username = username
    this.oauth = oauth
    this.channel = channel.toLowerCase()
    if(this.channel.charAt(0) !== '#') this.channel = '#' + this.channel

    this.irc = new tls.TLSSocket()
    this.port = port
    this.silence = silence

    this._connect()
  }

  async _connect() {
    this.irc.connect({
      host: 'irc.chat.twitch.tv',
      port: this.port
    })
    this.irc.setEncoding('utf8')
    this.irc.once('connect', () => {
      this.writeIrcMessage("PASS " + this.oauth)
      this.writeIrcMessage("NICK " + this.username)
      this.writeIrcMessage("JOIN " + this.channel)

      this.writeIrcMessage("CAP REQ :twitch.tv/membership")
      this.writeIrcMessage("CAP REQ :twitch.tv/tags")
      this.writeIrcMessage("CAP REQ :twitch.tv/commands")

      this.emit('join')
      this.listen()
    })
    this.irc.on('error', err => this.emit('error', err))
  }

  listen() {
    this.irc.on('data', data => {
      this.checkForError(data)
      if(data.includes('PRIVMSG')) {
        const chatter = parser.formatPRIVMSG(data)
        this.emit('message', chatter)
      }
      if(data.includes('CLEARCHAT')) {
        const event = parser.formatCLEARCHAT(data)
        if(event.type === 'timeout') this.emit('timeout', event)
        if(event.type === 'ban') this.emit('ban', event)
      }
    })
  }

  checkForError(event) {
    /* Login Authentication Failed */
    if(event.includes('Login authentication failed')) {
      this.irc.emit('error', {
        message: 'Login authentication failed'
      })
    }
    /* Auth formatting */
    if(event.includes('Improperly formatted auth')) {
      this.irc.emit('error', {
        message: 'Improperly formatted auth'
      })
    }
  }

  writeIrcMessage(text) {
    this.irc.write(text + "\r\n")
  }

  say(message, callback) {
    if(message.length >= 500) {
      this.cb(callback, {
        sent: false,
        message: 'Exceeded PRIVMSG character limit (500)'
      })
    } else {
      this.writeIrcMessage('PRIVMSG ' + this.channel + ' :' + message)
    }
  }

  timeout(username, duration=600, reason='') {
    this.say(`/timeout ${username} ${duration} ${reason}`)
  }

  ban(username, reason='') {
    this.say(`/ban ${username} ${reason}`)
  }

  close() {
    this.irc.destroy()
    this.emit('close')
  }

  cb(callback, obj) {
    if(callback) {
      obj.ts = new Date()
      callback(obj)
    }
  }

}

module.exports = TwitchBot<commit_msg>Added PONG responder<commit_after>'use strict'

const tls = require('tls')
const assert = require('assert')
const EventEmitter = require('events').EventEmitter

const parser = require('./parser')

const TwitchBot = class TwitchBot extends EventEmitter {

  constructor({
    username,
    oauth,
    channel,
    port=443,
    silence=false
  }) {
    super()

    try {
      assert(username)
      assert(oauth)
      assert(channel)
    } catch(err) {
      throw new Error('missing required arguments')
    }

    this.username = username
    this.oauth = oauth
    this.channel = channel.toLowerCase()
    if(this.channel.charAt(0) !== '#') this.channel = '#' + this.channel

    this.irc = new tls.TLSSocket()
    this.port = port
    this.silence = silence

    this._connect()
  }

  async _connect() {
    this.irc.connect({
      host: 'irc.chat.twitch.tv',
      port: this.port
    })
    this.irc.setEncoding('utf8')
    this.irc.once('connect', () => {
      this.writeIrcMessage("PASS " + this.oauth)
      this.writeIrcMessage("NICK " + this.username)
      this.writeIrcMessage("JOIN " + this.channel)

      this.writeIrcMessage("CAP REQ :twitch.tv/membership")
      this.writeIrcMessage("CAP REQ :twitch.tv/tags")
      this.writeIrcMessage("CAP REQ :twitch.tv/commands")

      this.emit('join')
      this.listen()
    })
    this.irc.on('error', err => this.emit('error', err))
  }

  listen() {
    this.irc.on('data', data => {
      this.checkForError(data)
      /* Twitch sends keep-alive PINGs, need to respond with PONGs */
      if(data.includes('PING :tmi.twitch.tv')) {
        this.irc.write('PONG :tmi.twitch.tv\r\n')
      }
      if(data.includes('PRIVMSG')) {
        const chatter = parser.formatPRIVMSG(data)
        this.emit('message', chatter)
      }
      if(data.includes('CLEARCHAT')) {
        const event = parser.formatCLEARCHAT(data)
        if(event.type === 'timeout') this.emit('timeout', event)
        if(event.type === 'ban') this.emit('ban', event)
      }
    })
  }

  checkForError(event) {
    /* Login Authentication Failed */
    if(event.includes('Login authentication failed')) {
      this.irc.emit('error', {
        message: 'Login authentication failed'
      })
    }
    /* Auth formatting */
    if(event.includes('Improperly formatted auth')) {
      this.irc.emit('error', {
        message: 'Improperly formatted auth'
      })
    }
  }

  writeIrcMessage(text) {
    this.irc.write(text + "\r\n")
  }

  say(message, callback) {
    if(message.length >= 500) {
      this.cb(callback, {
        sent: false,
        message: 'Exceeded PRIVMSG character limit (500)'
      })
    } else {
      this.writeIrcMessage('PRIVMSG ' + this.channel + ' :' + message)
    }
  }

  timeout(username, duration=600, reason='') {
    this.say(`/timeout ${username} ${duration} ${reason}`)
  }

  ban(username, reason='') {
    this.say(`/ban ${username} ${reason}`)
  }

  close() {
    this.irc.destroy()
    this.emit('close')
  }

  cb(callback, obj) {
    if(callback) {
      obj.ts = new Date()
      callback(obj)
    }
  }

}

module.exports = TwitchBot
<|endoftext|>


<commit_before>(function($) {
	$.fn.miller = function(settings) {
		var settings = $.extend(true, {
					url: function(id) { return id; },
					tabindex: 0,
					minWidth: 40,
					pane: {
						width: '100px',
						options: {}
					}
				},
				settings
			)
		;

		var hasFocus = false;

		if (!this.attr('tabindex')) {
			this.attr('tabindex', settings.tabindex);
		}

		this
			.addClass('miller')
			.focus(function() { hasFocus = true; })
			.blur(function() { hasFocus = false; })
		;

		var path = $('<div>', { class: 'path' })
			.appendTo(this)
		;

		var columns = $('<div>', { class: 'columns' })
			.appendTo(this)
		;

		var currentLine = null;

		$(document).keydown(function(event) {
				if (hasFocus && currentLine && (event.which == 37 || event.which == 38 || event.which == 39 || event.which == 40)) {
					var newCurrentLine = [];

					switch (event.which) {
						case 37:
							newCurrentLine = currentLine.parent().prev().prev().find('li.parentSelected');
							break;

						case 38:
							newCurrentLine = currentLine.prev();
							break;

						case 39:
							newCurrentLine = currentLine.parent().next().next().find('li:first');
							break;

						case 40:
							newCurrentLine = currentLine.next();
							break;
					}

					if (newCurrentLine.length) {
						currentLine = newCurrentLine.click();
						currentLine.parent().scrollTop(currentLine.position().top);
					}

					return false;
				}
			}
		);

		var removeNextColumns = function() {
				var line = $(this);

				var column = line.parent();

				column
					.nextAll()
						.slice(1)
							.remove()
				;

				column
					.find('li')
						.removeClass('selected parentSelected')
				;

				line.addClass(line.hasClass('parent') ? 'parentSelected' : 'selected');

				var node = $('<span>', { text: line.text(), css: { cursor: 'pointer' } })
					.click(function() {
							columns
								.children()
									.slice((($(this).index() * 2) + 4))
										.remove()
							;
							columns
								.children('ul:last')
									.find('li')
										.removeClass('parentSelected')
							;
							path
								.children()
									.slice($(this).index() + 1)
										.remove()
							;
						}
					)
					.appendTo(path)
				;

				var child = column.index();

				child -= (child - (child / 2));

				path
					.scrollLeft(node.position().left)
					.children()
						.slice(child, -1)
							.remove()
				;
			}
		;

		var buildColumn = function(lines) {
				if (lines == null) {
					$('li.parentLoading').remove();
				} else {
					var width = 0;

					var lastGrip = columns.children('div.grip:last')[0];

					if (lastGrip) {
						lastGrip = $(lastGrip);
						width = lastGrip.position().left + lastGrip.width() + columns.scrollLeft();
					}

					if (lines.length <= 0) {
						var line = $('li.parentLoading')
							.removeClass('parent')
							.addClass('selected')
						;

						var pane = $('<ul>')
							.css({ top: 0, left: width })
							.addClass('pane')
						;

						$.each(settings.pane.options, function(key, callbackGenerator) {
								var option = $('<li>', { text: key })
									.click(callbackGenerator(line.data('id')))
								;

								option.appendTo(pane);
							}
						);

						columns
							.append(pane)
							.scrollLeft(width + pane.width())
						;
					} else {
						$('li.parentLoading').addClass('parentSelected');

						var column = $('<ul>')
							.css({ top: 0, left: width })
						;

						$.each(lines, function(id, data) {
								var line = $('<li>', { text: data['name'], css: { cursor: 'pointer' } })
									.data('id', data['id'])
									.click(removeNextColumns)
									.click(getLines)
									.appendTo(column)
								;

								if (data['parent']) {
									line.addClass('parent');
								}
							}
						);

						columns
							.append(column)
							.scrollLeft(width += column.width())
							.append(
								$('<div>', { class: 'grip' })
									.css({ top: 0, left: width })
									.mousedown(function(event) {
											var x = event.pageX;
											var cursor = columns.css('cursor');

											columns
												.css('cursor', 'col-resize')
												.mousemove(function(event) {
														var delta = event.pageX - x;
														var newWidth = column.width() + delta;

														if (newWidth > settings.minWidth) {
															column
																.width(newWidth)
																.nextAll()
																	.each(function() {
																			$(this).css('left', $(this).position().left + delta + columns.scrollLeft());
																		}
																	)
															;
														}

														x = event.pageX;
													}
												)
												.mouseup(function() {
														columns
															.off('mousemove')
															.css('cursor', cursor)
														;
													}
												)
											;
										}
									)
							)
						;
					}
				}
			}
		;

		var getLines = function(event) {
				currentLine = $(event.currentTarget)
					.removeClass('parentSelected')
					.addClass('parentLoading')
				;

				$.getJSON(settings.url($(this).data('id')), buildColumn)
					.always(function() {
							currentLine
								.removeClass('parentLoading')
							;
						}
					)
					.fail(function() {})
				;

			}
		;

		$.getJSON(settings.url(), buildColumn);

		return this;
	};
})(jQuery);
<commit_msg>Optimization.<commit_after>(function($) {
	$.fn.miller = function(settings) {
		var settings = $.extend(true, {
					url: function(id) { return id; },
					tabindex: 0,
					minWidth: 40,
					pane: {
						width: '100px',
						options: {}
					}
				},
				settings
			)
		;

		var hasFocus = false;

		if (!this.attr('tabindex')) {
			this.attr('tabindex', settings.tabindex);
		}

		this
			.addClass('miller')
			.focus(function() { hasFocus = true; })
			.blur(function() { hasFocus = false; })
		;

		var path = $('<div>', { class: 'path' })
			.appendTo(this)
		;

		var columns = $('<div>', { class: 'columns' })
			.appendTo(this)
		;

		var currentLine = null;

		$(document).keydown(function(event) {
				if (hasFocus && currentLine && (event.which == 37 || event.which == 38 || event.which == 39 || event.which == 40)) {
					var newCurrentLine = [];

					switch (event.which) {
						case 37:
							newCurrentLine = currentLine.parent().prev().prev().find('li.parentSelected');
							break;

						case 38:
							newCurrentLine = currentLine.prev();
							break;

						case 39:
							newCurrentLine = currentLine.parent().next().next().find('li:first');
							break;

						case 40:
							newCurrentLine = currentLine.next();
							break;
					}

					if (newCurrentLine.length) {
						currentLine = newCurrentLine.click();
						currentLine.parent().scrollTop(currentLine.position().top);
					}

					return false;
				}
			}
		);

		var removeNextColumns = function() {
				var line = $(this);

				var column = line.parent();

				column
					.nextAll()
						.slice(1)
							.remove()
				;

				column
					.find('li')
						.removeClass('selected parentSelected')
				;

				line.addClass(line.hasClass('parent') ? 'parentSelected' : 'selected');

				var node = $('<span>', { text: line.text(), css: { cursor: 'pointer' } })
					.click(function() {
							columns
								.children()
									.slice((($(this).index() * 2) + 4))
										.remove()
							;
							columns
								.children('ul:last')
									.find('li')
										.removeClass('parentSelected')
							;
							path
								.children()
									.slice($(this).index() + 1)
										.remove()
							;
						}
					)
					.appendTo(path)
				;

				var child = column.index();

				child -= (child - (child / 2));

				path
					.scrollLeft(node.position().left)
					.children()
						.slice(child, -1)
							.remove()
				;
			}
		;

		var buildColumn = function(lines) {
				if (lines == null) {
					$('li.parentLoading').remove();
				} else {
					var width = 0;

					var lastGrip = columns.children('div.grip:last')[0];

					if (lastGrip) {
						lastGrip = $(lastGrip);
						width = lastGrip.position().left + lastGrip.width() + columns.scrollLeft();
					}

					if (lines.length <= 0) {
						var line = $('li.parentLoading')
							.removeClass('parent')
							.addClass('selected')
						;

						var id = line.data('id');

						var options = [];

						$.each(settings.pane.options, function(key, callbackGenerator) {
								options.push($('<li>', { text: key })
										.click(callbackGenerator(id))
									)
								;
							}
						);

						if (options.length) {
							var pane = $('<ul>')
								.css({ top: 0, left: width })
								.addClass('pane')
								.append(options)
								.appendTo(columns)
							;

							columns
								.scrollLeft(width + pane.width())
							;
						}
					} else {
						$('li.parentLoading').addClass('parentSelected');

						var column = $('<ul>')
							.css({ top: 0, left: width })
						;

						$.each(lines, function(id, data) {
								var line = $('<li>', { text: data['name'], css: { cursor: 'pointer' } })
									.data('id', data['id'])
									.click(removeNextColumns)
									.click(getLines)
									.appendTo(column)
								;

								if (data['parent']) {
									line.addClass('parent');
								}
							}
						);

						columns
							.append(column)
							.scrollLeft(width += column.width())
							.append(
								$('<div>', { class: 'grip' })
									.css({ top: 0, left: width })
									.mousedown(function(event) {
											var x = event.pageX;
											var cursor = columns.css('cursor');

											columns
												.css('cursor', 'col-resize')
												.mousemove(function(event) {
														var delta = event.pageX - x;
														var newWidth = column.width() + delta;

														if (newWidth > settings.minWidth) {
															column
																.width(newWidth)
																.nextAll()
																	.each(function() {
																			$(this).css('left', $(this).position().left + delta + columns.scrollLeft());
																		}
																	)
															;
														}

														x = event.pageX;
													}
												)
												.mouseup(function() {
														columns
															.off('mousemove')
															.css('cursor', cursor)
														;
													}
												)
											;
										}
									)
							)
						;
					}
				}
			}
		;

		var getLines = function(event) {
				currentLine = $(event.currentTarget)
					.removeClass('parentSelected')
					.addClass('parentLoading')
				;

				$.getJSON(settings.url($(this).data('id')), buildColumn)
					.always(function() {
							currentLine
								.removeClass('parentLoading')
							;
						}
					)
					.fail(function() {})
				;

			}
		;

		$.getJSON(settings.url(), buildColumn);

		return this;
	};
})(jQuery);
<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var $fh = require('fh-mbaas-api');

function bpmRoute() {
  var bpm = new express.Router();
  bpm.use(cors());
  bpm.use(bodyParser());

  bpm.post('/testRequest', function(req, res) {
    $fh.service({
        guid: "wbyyx52jcku3ynnqywa666ry",
        path: "/bpm/testRequest",
        method: "POST",
        headers: {
           "Content-Type" : "application/json"
        },
        "params": req.body
      }, function(err, data) {
        if (err) {
          res.json(err);
        }
        res.json(data);
      });

  });

  bpm.post('/startProcess', function(req, res) {
    $fh.service({
        guid: "wbyyx52jcku3ynnqywa666ry",
        path: "/bpm/startProcess",
        method: "POST",
        headers: {
           "Content-Type" : "application/json"
        },
        "params": req.body
      }, function(err, data) {
        if (err) {
          res.json(err);
        }
        res.json(data);
      });

  });

  bpm.post('/getProcess', function(req, res) {
      $fh.service({
          guid: "wbyyx52jcku3ynnqywa666ry",
          path: "/bpm/getProcess",
          method: "POST",
          headers: {
             "Content-Type" : "application/json"
          },
          "params": req.body
        }, function(err, data) {
          if (err) {
            res.json(err);
          }
          res.json(data);
        });

    });

  bpm.post('/loadTasks', function(req, res) {
    $fh.service({
        guid: "wbyyx52jcku3ynnqywa666ry",
        path: "/bpm/loadTasks",
        method: "POST",
        headers: {
           "Content-Type" : "application/json"
        },
        "params": req.body
      }, function(err, data) {
        if (err) {
          res.json(err);
        }
        res.json(data);
      });

  });

  bpm.post('/loadTaskContent', function(req, res) {
    $fh.service({
      "guid": "wbyyx52jcku3ynnqywa666ry",
      "path": "/bpm/loadTaskContent",
      "method": "POST",
      "headers": {
         "Content-Type" : "application/json"
      },
      "params": req.body
    }, function(err, data) {
      if (err) {
        res.json(err);
      }
      res.json(data);
    });

  });

  bpm.post('/completeTask', function(req, res) {
    $fh.service({
      "guid": "wbyyx52jcku3ynnqywa666ry",
      "path": "/bpm/completeTask",
      "method": "POST",
      "headers": {
         "Content-Type" : "application/json"
      },
      "params": req.body
    }, function(err, data) {
      if (err) {
        res.json(err);
      }
      res.json(data);
    });

  });

  bpm.post('/claimTask', function(req, res) {
    $fh.service({
      "guid": "wbyyx52jcku3ynnqywa666ry",
      "path": "/bpm/claimTask",
      "method": "POST",
      "headers": {
         "Content-Type" : "application/json"
      },
      "params": req.body
    }, function(err, data) {
      if (err) {
        res.json(err);
      }
      res.json(data);
    });

  });

  bpm.post('/startTask', function(req, res) {
    $fh.service({
      "guid": "wbyyx52jcku3ynnqywa666ry",
      "path": "/bpm/startTask",
      "method": "POST",
      "headers": {
         "Content-Type" : "application/json"
      },
      "params": req.body
    }, function(err, data) {
      if (err) {
        res.json(err);
      }
      res.json(data);
    });

  });

  bpm.post('/releaseTask', function(req, res) {
    $fh.service({
      "guid": "wbyyx52jcku3ynnqywa666ry",
      "path": "/bpm/releaseTask",
      "method": "POST",
      "headers": {
         "Content-Type" : "application/json"
      },
      "params": req.body
    }, function(err, data) {
      if (err) {
        res.json(err);
      }
      res.json(data);
    });

  });

  return bpm;
}

module.exports = bpmRoute;
<commit_msg>mapped new mBaaS<commit_after>var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var $fh = require('fh-mbaas-api');

function bpmRoute() {
  var bpm = new express.Router();
  bpm.use(cors());
  bpm.use(bodyParser());

  bpm.post('/testRequest', function(req, res) {
    $fh.service({
        guid: "i24hicsileulqzpwybj74w7c",
        path: "/bpm/testRequest",
        method: "POST",
        headers: {
           "Content-Type" : "application/json"
        },
        "params": req.body
      }, function(err, data) {
        if (err) {
          res.json(err);
        }
        res.json(data);
      });

  });

  bpm.post('/startProcess', function(req, res) {
    $fh.service({
        guid: "i24hicsileulqzpwybj74w7c",
        path: "/bpm/startProcess",
        method: "POST",
        headers: {
           "Content-Type" : "application/json"
        },
        "params": req.body
      }, function(err, data) {
        if (err) {
          res.json(err);
        }
        res.json(data);
      });

  });

  bpm.post('/getProcess', function(req, res) {
      $fh.service({
          guid: "i24hicsileulqzpwybj74w7c",
          path: "/bpm/getProcess",
          method: "POST",
          headers: {
             "Content-Type" : "application/json"
          },
          "params": req.body
        }, function(err, data) {
          if (err) {
            res.json(err);
          }
          res.json(data);
        });

    });

  bpm.post('/loadTasks', function(req, res) {
    $fh.service({
        guid: "i24hicsileulqzpwybj74w7c",
        path: "/bpm/loadTasks",
        method: "POST",
        headers: {
           "Content-Type" : "application/json"
        },
        "params": req.body
      }, function(err, data) {
        if (err) {
          res.json(err);
        }
        res.json(data);
      });

  });

  bpm.post('/loadTaskContent', function(req, res) {
    $fh.service({
      "guid": "i24hicsileulqzpwybj74w7c",
      "path": "/bpm/loadTaskContent",
      "method": "POST",
      "headers": {
         "Content-Type" : "application/json"
      },
      "params": req.body
    }, function(err, data) {
      if (err) {
        res.json(err);
      }
      res.json(data);
    });

  });

  bpm.post('/completeTask', function(req, res) {
    $fh.service({
      "guid": "i24hicsileulqzpwybj74w7c",
      "path": "/bpm/completeTask",
      "method": "POST",
      "headers": {
         "Content-Type" : "application/json"
      },
      "params": req.body
    }, function(err, data) {
      if (err) {
        res.json(err);
      }
      res.json(data);
    });

  });

  bpm.post('/claimTask', function(req, res) {
    $fh.service({
      "guid": "i24hicsileulqzpwybj74w7c",
      "path": "/bpm/claimTask",
      "method": "POST",
      "headers": {
         "Content-Type" : "application/json"
      },
      "params": req.body
    }, function(err, data) {
      if (err) {
        res.json(err);
      }
      res.json(data);
    });

  });

  bpm.post('/startTask', function(req, res) {
    $fh.service({
      "guid": "i24hicsileulqzpwybj74w7c",
      "path": "/bpm/startTask",
      "method": "POST",
      "headers": {
         "Content-Type" : "application/json"
      },
      "params": req.body
    }, function(err, data) {
      if (err) {
        res.json(err);
      }
      res.json(data);
    });

  });

  bpm.post('/releaseTask', function(req, res) {
    $fh.service({
      "guid": "i24hicsileulqzpwybj74w7c",
      "path": "/bpm/releaseTask",
      "method": "POST",
      "headers": {
         "Content-Type" : "application/json"
      },
      "params": req.body
    }, function(err, data) {
      if (err) {
        res.json(err);
      }
      res.json(data);
    });

  });

  return bpm;
}

module.exports = bpmRoute;
<|endoftext|>


<commit_before>(function($) {
 	var methods = {
		'getPath': function() {
			var path = [];

			$.each($(this).find('div.path span'), function(key, node) {
					path.push({ 'id': $(node).data('id'), 'name': $(node).text() });
				}
			);

			return path;
		},
		'setPath': function(path) {
			// Make sure path is an array
			if (!$.isArray(path) || path.length == 0) {
				return;
			}

			$.each(path, function(index, value) {
				var list = $('.columns ul').get(index);
				var $listItems = $(list).children();
				var $item = $listItems.filter(function(index) {
					return $(this).data('id') == value;
				});
				$item.click();
			});
		}
	};

	$.fn.miller = function(mixed) {
		if (methods[mixed] ) {
			return methods[mixed].apply(this, Array.prototype.slice.call(arguments, 1));
		} else {
			var miller = this;
			var hasFocus = false;
			var currentAjaxRequest = null;
			var settings = $.extend(true, {
						'url': function(id) { return id; },
						'transform': function(lines) { return lines; },
						'preloadedData': {},
						'initialPath': [],
						'tabindex': 0,
						'minWidth': 40,
						'carroussel': false,
						'toolbar': {
							'options': {}
						},
						'pane': {
							'options': {}
						}
					},
					mixed
				)
			;

			if (!miller.attr('tabindex')) {
				miller.attr('tabindex', settings.tabindex);
			}

			miller
				.addClass('miller')
				.focus(function() { hasFocus = true; })
				.blur(function() { hasFocus = false; })
			;

			var path = $('<div>', { 'class': 'path' })
				.appendTo(miller)
			;

			var columns = $('<div>', { 'class': 'columns' })
				.appendTo(miller)
			;

			var toolbar = null;

			if (!$.isEmptyObject(settings.toolbar.options)) {
				var toolbar = $('<div>', { 'class': 'toolbar' })
					.appendTo(miller)
				;
			};

			var currentLine = null;

			$(document).keypress(function(event) {
					if (hasFocus && currentLine && event.which != 37 && event.which != 38 && event.which != 39 && event.which != 40) {
						var newCurrentLine = currentLine.parent().children().filter(function() { return $(this).text().match(new RegExp('^' + String.fromCharCode(event.which))); }).first();

						if (newCurrentLine.length) {
							currentLine = newCurrentLine.click();
						}
					}
				}
			);

			$(document).keydown(function(event) {
					if (hasFocus && currentLine && (event.which == 37 || event.which == 38 || event.which == 39 || event.which == 40)) {
						var newCurrentLine = [];
						var scrollTop = currentLine.parent().scrollTop();

						switch (event.which) {
							case 37:
								newCurrentLine = currentLine.parent().prev().prev().find('li.parentSelected');
								break;

							case 38:
								newCurrentLine = currentLine.prev();

								if (!newCurrentLine.length && settings.carroussel) {
									newCurrentLine = currentLine.parent().find('li:last');
									scrollTop = newCurrentLine.position().top;
								}
								break;

							case 39:
								newCurrentLine = currentLine.parent().next().next().find('li:first');
								break;

							case 40:
								newCurrentLine = currentLine.next();

								if (!newCurrentLine.length && settings.carroussel) {
									newCurrentLine = currentLine.parent().find('li:first');
									scrollTop = 0;
								}
								break;
						}

						if (newCurrentLine.length && !newCurrentLine.parent().hasClass('pane')) {
							currentLine = newCurrentLine.click();
						}

						return false;
					}
				}
			);

			var removeNextColumns = function() {
					var line = $(this);

					var column = line.parent();

					column
						.nextAll()
							.slice(1)
								.remove()
					;

					column
						.find('li')
							.removeClass('selected parentSelected')
					;

					line.addClass(line.hasClass('parent') ? 'parentSelected' : 'selected');

					var node = $('<span>', { 'text': line.text() })
						.data('id', line.data('id'))
						.click(function() {
								columns
									.children()
										.slice((($(this).index() * 2) + 4))
											.remove()
								;
								columns
									.children('ul:last')
										.find('li')
											.removeClass('parentSelected')
								;
								path
									.children()
										.slice($(this).index() + 1)
											.remove()
								;
							}
						)
						.appendTo(path)
					;

					var child = column.index();

					child -= (child - (child / 2));

					path
						.scrollLeft(node.position().left)
						.children()
							.slice(child, -1)
								.remove()
					;
				}
			;

			var buildColumn = function(lines) {
					if (lines == null) {
						$('li.parentLoading').remove();
					} else {
						if (currentLine && toolbar) {
							toolbar.children().remove();

							$.each(settings.toolbar.options, function(key, callback) {
									$('<span>', { 'text': key })
										.click(function() { callback.call(miller, currentLine.data('id')) })
										.appendTo(toolbar)
									;
								}
							);
						}

						if (currentLine) {
							var currentColumn = currentLine.parent();
							var scroll = 0;
							var scrollTop = currentColumn.scrollTop();
							var topOfCurrentLine = currentLine.position().top;

							if (topOfCurrentLine < 0) {
								scroll = topOfCurrentLine;
							} else {
								var bottomOfCurrentLine = currentLine.position().top + currentLine.height();
								var heightOfCurrentColumn = currentColumn.height();

								if (bottomOfCurrentLine > heightOfCurrentColumn) {
									scroll = bottomOfCurrentLine - heightOfCurrentColumn;
								}
							}

							currentColumn.scrollTop(scrollTop + scroll);
						}

						var width = 0;

						var lastGrip = columns.children('div.grip:last')[0];

						if (lastGrip) {
							lastGrip = $(lastGrip);
							width = lastGrip.position().left + lastGrip.width() + columns.scrollLeft();
						}

						if (lines.length <= 0) {
							var line = $('li.parentLoading')
								.removeClass('parent')
								.addClass('selected')
							;

							if (!$.isEmptyObject(settings.pane.options)) {
								var pane = $('<ul>')
									.css({ 'top': 0, 'left': width })
									.addClass('pane')
								;

								var id = line.data('id');

								$.each(settings.pane.options, function(key, callback) {
										$('<li>', { 'text': key })
											.click(function() { callback.call(miller, currentLine.data('id')) })
											.appendTo(pane)
										;
									}
								);

								columns
									.append(pane)
									.scrollLeft(width + pane.width())
								;
							}
						} else {
							$('li.parentLoading').addClass('parentSelected');

							var column = $('<ul>')
								.css({ 'top': 0, 'left': width })
							;

							$.each(lines, function(id, data) {
									var line = $('<li>', { 'text': data['name'] })
										.data('id', data['id'])
										.click(removeNextColumns)
										.click(getLines)
										.appendTo(column)
									;

									if (data['parent']) {
										line.addClass('parent');
									}
									if (data['image']) {
										$('<img>', { 'src': data['image']})
											.prependTo(line)
										;
									}
								}
							);

							columns
								.append(column)
								.scrollLeft(width += column.width())
								.append(
									$('<div>', { 'class': 'grip' })
										.css({ 'top': 0, 'left': width })
										.mousedown(function(event) {
												var x = event.pageX;
												var cursor = columns.css('cursor');

												columns
													.css('cursor', 'col-resize')
													.mousemove(function(event) {
															var delta = event.pageX - x;
															var newWidth = column.width() + delta;

															if (newWidth > settings.minWidth) {
																column
																	.width(newWidth)
																	.nextAll()
																		.each(function() {
																				$(this).css('left', $(this).position().left + delta + columns.scrollLeft());
																			}
																		)
																;
															}

															x = event.pageX;
														}
													)
													.mouseup(function() {
															columns
																.off('mousemove')
																.css('cursor', cursor)
															;
														}
													)
												;
											}
										)
								)
							;
						}
					}
				}
			;

			var transformAndBuildColumn = function(data) {
					buildColumn(settings.transform.call(miller, data));
			};

			var getLines = function(event) {
					var id = $(this).data('id');
					currentLine = $(event.currentTarget)
						.removeClass('parentSelected')
						.addClass('parentLoading')
					;
					// First, let's check for preloadedData
					var preloadedData = getPreloadedData();
					if (preloadedData) {
						buildColumn(preloadedData);
						currentLine
							.removeClass('parentLoading')
						;
					} else {
						if (currentAjaxRequest) {
							currentAjaxRequest.abort();
						}

						currentAjaxRequest = $.getJSON(settings.url.call(miller, id), transformAndBuildColumn)
							.always(function() {
									currentLine
										.removeClass('parentLoading')
									;

									currentAjaxRequest = null;
								}
							)
							.fail(function() {})
						;
					}
				}
			;

			var getPreloadedData = function() {
					if (!$.isEmptyObject(settings.preloadedData)) {
						var currentPath = $.map(methods['getPath'].call(miller), function(value, index) {
							return value.id;
						});

						var currentObj = settings.preloadedData;
						$.each(currentPath, function(pathIndex, pathValue) {
							var children = currentObj.children;
							if (!$.isArray(children) || children.length == 0) {
								return false; // break
							}
							$.each(children, function(childIndex, childValue) {
								if (childValue.id == pathValue) {
									currentObj = childValue;
									return false; // break
								}
							});
						});
						return currentObj.children || [];
					}
					return null;
				}
			;

			var init = function() {
					var preloadedData = getPreloadedData();
					if(preloadedData) {
						buildColumn(preloadedData);
					} else {
						$.getJSON(settings.url.call(miller), transformAndBuildColumn);
					}
					methods['setPath'](settings.initialPath);
				}
			;

			init();

			return miller;
		}
	};
})(jQuery);
<commit_msg>If a ‘class’ is provided on the data, add it to the CSS of the item<commit_after>(function($) {
 	var methods = {
		'getPath': function() {
			var path = [];

			$.each($(this).find('div.path span'), function(key, node) {
					path.push({ 'id': $(node).data('id'), 'name': $(node).text() });
				}
			);

			return path;
		},
		'setPath': function(path) {
			// Make sure path is an array
			if (!$.isArray(path) || path.length == 0) {
				return;
			}

			$.each(path, function(index, value) {
				var list = $('.columns ul').get(index);
				var $listItems = $(list).children();
				var $item = $listItems.filter(function(index) {
					return $(this).data('id') == value;
				});
				$item.click();
			});
		}
	};

	$.fn.miller = function(mixed) {
		if (methods[mixed] ) {
			return methods[mixed].apply(this, Array.prototype.slice.call(arguments, 1));
		} else {
			var miller = this;
			var hasFocus = false;
			var currentAjaxRequest = null;
			var settings = $.extend(true, {
						'url': function(id) { return id; },
						'transform': function(lines) { return lines; },
						'preloadedData': {},
						'initialPath': [],
						'tabindex': 0,
						'minWidth': 40,
						'carroussel': false,
						'toolbar': {
							'options': {}
						},
						'pane': {
							'options': {}
						}
					},
					mixed
				)
			;

			if (!miller.attr('tabindex')) {
				miller.attr('tabindex', settings.tabindex);
			}

			miller
				.addClass('miller')
				.focus(function() { hasFocus = true; })
				.blur(function() { hasFocus = false; })
			;

			var path = $('<div>', { 'class': 'path' })
				.appendTo(miller)
			;

			var columns = $('<div>', { 'class': 'columns' })
				.appendTo(miller)
			;

			var toolbar = null;

			if (!$.isEmptyObject(settings.toolbar.options)) {
				var toolbar = $('<div>', { 'class': 'toolbar' })
					.appendTo(miller)
				;
			};

			var currentLine = null;

			$(document).keypress(function(event) {
					if (hasFocus && currentLine && event.which != 37 && event.which != 38 && event.which != 39 && event.which != 40) {
						var newCurrentLine = currentLine.parent().children().filter(function() { return $(this).text().match(new RegExp('^' + String.fromCharCode(event.which))); }).first();

						if (newCurrentLine.length) {
							currentLine = newCurrentLine.click();
						}
					}
				}
			);

			$(document).keydown(function(event) {
					if (hasFocus && currentLine && (event.which == 37 || event.which == 38 || event.which == 39 || event.which == 40)) {
						var newCurrentLine = [];
						var scrollTop = currentLine.parent().scrollTop();

						switch (event.which) {
							case 37:
								newCurrentLine = currentLine.parent().prev().prev().find('li.parentSelected');
								break;

							case 38:
								newCurrentLine = currentLine.prev();

								if (!newCurrentLine.length && settings.carroussel) {
									newCurrentLine = currentLine.parent().find('li:last');
									scrollTop = newCurrentLine.position().top;
								}
								break;

							case 39:
								newCurrentLine = currentLine.parent().next().next().find('li:first');
								break;

							case 40:
								newCurrentLine = currentLine.next();

								if (!newCurrentLine.length && settings.carroussel) {
									newCurrentLine = currentLine.parent().find('li:first');
									scrollTop = 0;
								}
								break;
						}

						if (newCurrentLine.length && !newCurrentLine.parent().hasClass('pane')) {
							currentLine = newCurrentLine.click();
						}

						return false;
					}
				}
			);

			var removeNextColumns = function() {
					var line = $(this);

					var column = line.parent();

					column
						.nextAll()
							.slice(1)
								.remove()
					;

					column
						.find('li')
							.removeClass('selected parentSelected')
					;

					line.addClass(line.hasClass('parent') ? 'parentSelected' : 'selected');

					var node = $('<span>', { 'text': line.text() })
						.data('id', line.data('id'))
						.click(function() {
								columns
									.children()
										.slice((($(this).index() * 2) + 4))
											.remove()
								;
								columns
									.children('ul:last')
										.find('li')
											.removeClass('parentSelected')
								;
								path
									.children()
										.slice($(this).index() + 1)
											.remove()
								;
							}
						)
						.appendTo(path)
					;

					var child = column.index();

					child -= (child - (child / 2));

					path
						.scrollLeft(node.position().left)
						.children()
							.slice(child, -1)
								.remove()
					;
				}
			;

			var buildColumn = function(lines) {
					if (lines == null) {
						$('li.parentLoading').remove();
					} else {
						if (currentLine && toolbar) {
							toolbar.children().remove();

							$.each(settings.toolbar.options, function(key, callback) {
									$('<span>', { 'text': key })
										.click(function() { callback.call(miller, currentLine.data('id')) })
										.appendTo(toolbar)
									;
								}
							);
						}

						if (currentLine) {
							var currentColumn = currentLine.parent();
							var scroll = 0;
							var scrollTop = currentColumn.scrollTop();
							var topOfCurrentLine = currentLine.position().top;

							if (topOfCurrentLine < 0) {
								scroll = topOfCurrentLine;
							} else {
								var bottomOfCurrentLine = currentLine.position().top + currentLine.height();
								var heightOfCurrentColumn = currentColumn.height();

								if (bottomOfCurrentLine > heightOfCurrentColumn) {
									scroll = bottomOfCurrentLine - heightOfCurrentColumn;
								}
							}

							currentColumn.scrollTop(scrollTop + scroll);
						}

						var width = 0;

						var lastGrip = columns.children('div.grip:last')[0];

						if (lastGrip) {
							lastGrip = $(lastGrip);
							width = lastGrip.position().left + lastGrip.width() + columns.scrollLeft();
						}

						if (lines.length <= 0) {
							var line = $('li.parentLoading')
								.removeClass('parent')
								.addClass('selected')
							;

							if (!$.isEmptyObject(settings.pane.options)) {
								var pane = $('<ul>')
									.css({ 'top': 0, 'left': width })
									.addClass('pane')
								;

								var id = line.data('id');

								$.each(settings.pane.options, function(key, callback) {
										$('<li>', { 'text': key })
											.click(function() { callback.call(miller, currentLine.data('id')) })
											.appendTo(pane)
										;
									}
								);

								columns
									.append(pane)
									.scrollLeft(width + pane.width())
								;
							}
						} else {
							$('li.parentLoading').addClass('parentSelected');

							var column = $('<ul>')
								.css({ 'top': 0, 'left': width })
							;

							$.each(lines, function(id, data) {
									var line = $('<li>', { 'text': data['name'] })
										.data('id', data['id'])
										.click(removeNextColumns)
										.click(getLines)
										.appendTo(column)
									;

									if (data['parent']) {
										line.addClass('parent');
									}
									if (data['class']) {
										line.addClass(data['class']);
									}
									if (data['image']) {
										$('<img>', { 'src': data['image']})
											.prependTo(line)
										;
									}
								}
							);

							columns
								.append(column)
								.scrollLeft(width += column.width())
								.append(
									$('<div>', { 'class': 'grip' })
										.css({ 'top': 0, 'left': width })
										.mousedown(function(event) {
												var x = event.pageX;
												var cursor = columns.css('cursor');

												columns
													.css('cursor', 'col-resize')
													.mousemove(function(event) {
															var delta = event.pageX - x;
															var newWidth = column.width() + delta;

															if (newWidth > settings.minWidth) {
																column
																	.width(newWidth)
																	.nextAll()
																		.each(function() {
																				$(this).css('left', $(this).position().left + delta + columns.scrollLeft());
																			}
																		)
																;
															}

															x = event.pageX;
														}
													)
													.mouseup(function() {
															columns
																.off('mousemove')
																.css('cursor', cursor)
															;
														}
													)
												;
											}
										)
								)
							;
						}
					}
				}
			;

			var transformAndBuildColumn = function(data) {
					buildColumn(settings.transform.call(miller, data));
			};

			var getLines = function(event) {
					var id = $(this).data('id');
					currentLine = $(event.currentTarget)
						.removeClass('parentSelected')
						.addClass('parentLoading')
					;
					// First, let's check for preloadedData
					var preloadedData = getPreloadedData();
					if (preloadedData) {
						buildColumn(preloadedData);
						currentLine
							.removeClass('parentLoading')
						;
					} else {
						if (currentAjaxRequest) {
							currentAjaxRequest.abort();
						}

						currentAjaxRequest = $.getJSON(settings.url.call(miller, id), transformAndBuildColumn)
							.always(function() {
									currentLine
										.removeClass('parentLoading')
									;

									currentAjaxRequest = null;
								}
							)
							.fail(function() {})
						;
					}
				}
			;

			var getPreloadedData = function() {
					if (!$.isEmptyObject(settings.preloadedData)) {
						var currentPath = $.map(methods['getPath'].call(miller), function(value, index) {
							return value.id;
						});

						var currentObj = settings.preloadedData;
						$.each(currentPath, function(pathIndex, pathValue) {
							var children = currentObj.children;
							if (!$.isArray(children) || children.length == 0) {
								return false; // break
							}
							$.each(children, function(childIndex, childValue) {
								if (childValue.id == pathValue) {
									currentObj = childValue;
									return false; // break
								}
							});
						});
						return currentObj.children || [];
					}
					return null;
				}
			;

			var init = function() {
					var preloadedData = getPreloadedData();
					if(preloadedData) {
						buildColumn(preloadedData);
					} else {
						$.getJSON(settings.url.call(miller), transformAndBuildColumn);
					}
					methods['setPath'](settings.initialPath);
				}
			;

			init();

			return miller;
		}
	};
})(jQuery);
<|endoftext|>


<commit_before>'use strict'

module.exports = function (config) {
  if (!config.AMQP) {
    throw new Error('AMQP config variable must be set')
  }

  var options = {
    urls: [config.AMQP],
    verbose: Boolean(config.DEBUG),
    queuePrefix: config.NODE_ENV
  }

  var amqp = require('amqp-connection-manager')
  var connection = amqp.connect(options.urls)

  connection.on('connect', function () {
    console.log('AMQP: connected to ' + options.queuePrefix)
  })
  connection.on('disconnect', function (params) {
    console.log('AMQP: disconnected', params.err)
  })

  var prepareMessage = function (onMessage) {
    return function (msg) {
      return onMessage(msg, JSON.parse(msg.content.toString()))
    }
  }

  var createChannel = function (name, setup, verbose) {
    var channelWrapper = connection.createChannel({
      name: name,
      json: true,
      setup: setup
    })

    channelWrapper.on('error', function (err) {
      console.log('AMQP channel:', name, 'error', err)
    })

    if (verbose) {
      channelWrapper.on('connect', function () {
        console.log('AMQP channel:', name, 'connected')
      })
      channelWrapper.on('close', function () {
        console.log('AMQP channel:', name, 'closed')
      })
    }

    return channelWrapper
  }

  var client = function (onMessage) {
    var channelWrapper = createChannel('client', function (channel) {
      return channel.assertQueue('', {exclusive: true, autoDelete: true}).then(function (q) {
        channelWrapper.replyTo = q.queue
        return channel.consume(q.queue, prepareMessage(onMessage), {noAck: true})
      })
    }, options.verbose)

    var orgSendToQueue = channelWrapper.sendToQueue.bind(channelWrapper)
    channelWrapper.sendToQueue = function (queueName, msg, opts, next) {
      orgSendToQueue(options.queuePrefix + '.' + queueName, msg, opts, next)
    }

    return channelWrapper
  }

  var server = function (queueName, onMessage) {
    queueName = options.queuePrefix + '.' + queueName
    return createChannel('server', function (channel) {
      return channel.assertQueue(queueName, {durable: false, expires: 60 * 1000}).then(function () {
        return channel.prefetch(1)
      }).then(function () {
        return channel.consume(queueName, prepareMessage(onMessage), {noAck: true})
      })
    }, options.verbose)
  }

  return {
    client: client,
    server: server
  }
}
<commit_msg>Require amqp once<commit_after>'use strict'

var amqp = require('amqp-connection-manager')

module.exports = function (config) {
  if (!config.AMQP) {
    throw new Error('AMQP config variable must be set')
  }

  var options = {
    urls: [config.AMQP],
    verbose: Boolean(config.DEBUG),
    queuePrefix: config.NODE_ENV
  }

  var connection = amqp.connect(options.urls)

  connection.on('connect', function () {
    console.log('AMQP: connected to ' + options.queuePrefix)
  })
  connection.on('disconnect', function (params) {
    console.log('AMQP: disconnected', params.err)
  })

  var prepareMessage = function (onMessage) {
    return function (msg) {
      return onMessage(msg, JSON.parse(msg.content.toString()))
    }
  }

  var createChannel = function (name, setup, verbose) {
    var channelWrapper = connection.createChannel({
      name: name,
      json: true,
      setup: setup
    })

    channelWrapper.on('error', function (err) {
      console.log('AMQP channel:', name, 'error', err)
    })

    if (verbose) {
      channelWrapper.on('connect', function () {
        console.log('AMQP channel:', name, 'connected')
      })
      channelWrapper.on('close', function () {
        console.log('AMQP channel:', name, 'closed')
      })
    }

    return channelWrapper
  }

  var client = function (onMessage) {
    var channelWrapper = createChannel('client', function (channel) {
      return channel.assertQueue('', {exclusive: true, autoDelete: true}).then(function (q) {
        channelWrapper.replyTo = q.queue
        return channel.consume(q.queue, prepareMessage(onMessage), {noAck: true})
      })
    }, options.verbose)

    var orgSendToQueue = channelWrapper.sendToQueue.bind(channelWrapper)
    channelWrapper.sendToQueue = function (queueName, msg, opts, next) {
      orgSendToQueue(options.queuePrefix + '.' + queueName, msg, opts, next)
    }

    return channelWrapper
  }

  var server = function (queueName, onMessage) {
    queueName = options.queuePrefix + '.' + queueName
    return createChannel('server', function (channel) {
      return channel.assertQueue(queueName, {durable: false, expires: 60 * 1000}).then(function () {
        return channel.prefetch(1)
      }).then(function () {
        return channel.consume(queueName, prepareMessage(onMessage), {noAck: true})
      })
    }, options.verbose)
  }

  return {
    client: client,
    server: server
  }
}
<|endoftext|>