<commit_before>var checksum = require('crc-32');
var dns = require('native-dns');
var winston = require('winston');
winston.cli();

if (process.argv.length < 4) {
  console.log('Usage: renamed <domain name> <public IP of server> <alt IP of server>');
  process.exit();
}
var rootTLD = process.argv[2].toLowerCase();
var myip = process.argv[3];
var altip = process.argv[4];
var sessionDigestKey = require('uuid').v4();

var createChecksum = function (client, server) {
  var str = client + '-' + server + '-' + sessionDigestKey;
  str = str.replace(/\./g, 'a').replace(/:/g, 'b');
  return Math.abs(checksum.str(str));
};

// Return [client,server] if query is valid, or false if not.
var validateQuery = function (query) {
  query = query.replace(/a/g, '.').replace(/b/g, ':');
  var parts = query.split('-');
  if (parts.length != 3) {
    return false;
  }
  var client = parts[0];
  var server = parts[1];
  var expectedChecksum = createChecksum(client, server);
  if (parts[2] === '' + expectedChecksum) {
    return [client, server];
  } else {
    return false;
  }
};

var setRootAuthority = function(resp, noA) {
  resp.authority.push(dns.NS({
    name: rootTLD,
    data: 'ns1.' + rootTLD,
    ttl: 5
  }));
  resp.authority.push(dns.NS({
    name: rootTLD,
    data: 'ns2.' + rootTLD,
    ttl: 5
  }));
  if (!noA) {
    resp.answer.push(dns.A({
      name: 'ns1.' + rootTLD,
      address: myip,
      ttl: 5
    }));
    resp.answer.push(dns.A({
      name: 'ns2.' + rootTLD,
      address: altip,
      ttl: 5
    }));
  }
  resp.authority.push(dns.SOA({
    name: rootTLD,
    primary: 'ns1.' + rootTLD,
    admin: 'measurement.' + rootTLD,
    serial: new Date().valueOf(),
    refresh: 5,
    retry: 5,
    expiration: 5,
    minimum: 5,
    ttl: 5
  }));
};

var setDelegatedAuthority = function(delegee, resp) {
  resp.authority.push(dns.NS({
    name: delegee,
    data: 'ns1.' + delegee,
    ttl: 5
  }));
  resp.authority.push(dns.NS({
    name: delegee,
    data: 'ns2.' + delgee,
    ttl: 5
  }));
  resp.authority.push(dns.SOA({
    name: delegee,
    primary: 'ns1.' + delegee,
    admin: 'measurement.' + rootTLD,
    serial: new Date().valueOf(),
    refresh: 5,
    retry: 5,
    expiration: 5,
    minimum: 5,
    ttl: 5
  }));
};

var matchServer = function (client) {
  var server = ['208.67.220.220', '208.67.222.222']; //todo: roundrobin.
  return server;
};

var createPrefix = function (client, server) {
  var checksum = createChecksum(client, server);
  var prefix = client + '-' + server + '-' + checksum;
  return prefix.replace(/\./g, 'a').replace(/:/g, 'b');
};

// make a query to populate a server cache, so it can answer non-recursively
// despite not being authoritative
var fillCache = function (prefix, server, cb) {
  var question = dns.Question({
    name: prefix,
    type: 'A'
  });
  var req = dns.Request({
    question: question,
    server: { address: server, port: 53, type: 'udp'},
    timeout: 1000
  });
  req.on('end', cb);
  req.send();
};

var handler = function (req, resp) {
  if (req.question.length === 0) {
    return;
  }
  var query = req.question[0].name.toLowerCase();
  var addr = req.address.address;
  var prefix, resolvers;

  if (req.question[0].type != 1 && req.question[0].type != 2 && req.question[0].type != 255) {
    winston.info(addr + ' [' + req.question[0].type + '] ' + query);
  } else if (req.question[0].type == 2) { // NS request
    winston.info(addr + ' [NS] ' + query);
    setRootAuthority(resp);
    resp.send();
    return;
  } else if (req.question[0].type == 1 || req.question[0].type == 255) { // A/ANY request
    var lookuptype = (req.question[0].type == 255) ? 'ANY' : 'A';
    winston.info(addr + ' [' + lookuptype + '] ' + query);
    // Failures
    if (query.indexOf(rootTLD) === -1) {
      resp.answer.push(dns.A({
        name: query,
        address: myip,
        ttl: 5
      }));
      resp.send();
      return;
    // Initial query
    } else if (query === "ns1." + rootTLD || query === "ns2." + rootTLD) {
      setRootAuthority(resp);
      resp.send();
      return;
    } else if (query === rootTLD) {
      // TODO: record attempt at connectivity
      resolvers = matchServer(addr);
      prefix = createPrefix(addr, resolvers[0]);
      var delegatedCN = prefix + '.' + rootTLD;
      resp.header.ra = false;
      resp.answer.push(dns.CNAME({
        name: query,
        ttl: 5,
        data: 'resolve.' + delegatedCN
      }));
      setDelegatedAuthority(prefix, resp);
      resp.additional.push(dns.A({
        name: 'ns1.' + delegatedCN,
        address: resolvers[0],
        ttl: 5
      }));
      resp.additional.push(dns.A({
        name: 'ns2.' + delegatedCN,
        address: resolvers[1],
        ttl: 5
      }));
      fillCache('precache.' + delegatedCN, resolvers[0], function() {
        resp.send();
      });
      return;
    }

    // Successful indicaton of connectivity
    prefix = query.split(rootTLD)[0];
    prefix = prefix.substr(0, prefix.length - 1);
    var host = '';
    if (prefix.indexOf('.') > 0) {
      host = prefix.split('.');
      prefix = host[1];
      host = host[0];
    } else if (prefix.indexOf('success-') === 0) {
      host = 'success';
      prefix = prefix.substr(8);
    }
    var parts = validateQuery(prefix);
    if (parts === false) {
      resp.answer.push(dns.A({
        name: query,
        address: myip,
        ttl: 5
      }));
      resp.send();
      return;
    } else if (host === 'ns1' || host === 'ns2') {
      setDelegatedAuthority(prefix, resp);
      resolvers = matchServer(parts[0]);
      resp.answer.push(dns.A({
        name: 'ns1.' + prefix + '.' + rootTLD,
        address: resolvers[0],
        ttl: 5
      }));
      resp.answer.push(dns.A({
        name: 'ns2.' + prefix + '.' + rootTLD,
        address: resolvers[1],
        ttl: 5
      }));
      resp.send();
      return;
    } else if (host === 'precache') {
      // "poison" the cache of the authoritative resolver.
      resp.answer.push(dns.A({
        name: query,
        address: myip,
        ttl: 5
      }));
      resp.additional.push(dns.CNAME({
        name: "resolve." + prefix + '.' + rootTLD,
        ttl: 20,
        data: "success-" + prefix + '.' + rootTLD
      }));
      resp.send();
      return;
    } else if (host === 'success') {
      winston.info('Induced Connectivity between ' + parts[0] + ' and ' + parts[1] + ' via cache poisoning [seen by ' + addr + ']');
      resp.answer.push(dns.A({
        name: query,
        address: addr,
        ttl: 5
      }));
      resp.send();
      return;
    } else {
      // Queries for the cname are owned by the appropriate delegee.
      if (addr == parts[0]) {
        setDelegatedAuthority(prefix, resp);
        resolvers = matchServer(parts[0]);
        resp.additional.push(dns.A({
          name: 'ns1.' + prefix + '.' + rootTLD,
          address: resolvers[0],
          ttl: 5
        }));
        resp.additional.push(dns.A({
          name: 'ns2.' + prefix + '.' + rootTLD,
          address: resolvers[1],
          ttl: 5
        }));
        resp.send();
        return;
      } else {
        // TODO: Log success of client-server. query.
        // TODO: See if it's been made recently by same server, indicating response dropped.
        winston.info('Induced Connectivity between ' + parts[0] + ' and ' + parts[1] + ' [exposed as ' + addr + ']');
      /*
      resp.answer.push(dns.CNAME({
        name: query,
        ttl: 5,
        data: 'www.google.com'
      }));
      */
        resp.answer.push(dns.A({
          name: query,
          address: addr,
          ttl: 5
        }));
        resp.send();
        return;
      }
    }
  }
};

var server1 = dns.createServer();
server1.on('request', handler);
server1.on('error', function (err) {
  console.warn(err.stack);
});
var server2 = dns.createServer();
server2.on('request', handler);
server2.on('error', function (err) {
  console.warn(err.stack);
});

server1.serve(53, myip);
server2.serve(53, altip);
winston.info('Running for', rootTLD, myip, altip);
winston.info('Session Key is', sessionDigestKey);
<commit_msg>finish common delegated NS response<commit_after>var checksum = require('crc-32');
var dns = require('native-dns');
var winston = require('winston');
winston.cli();

if (process.argv.length < 4) {
  console.log('Usage: renamed <domain name> <public IP of server> <alt IP of server>');
  process.exit();
}
var rootTLD = process.argv[2].toLowerCase();
var myip = process.argv[3];
var altip = process.argv[4];
var sessionDigestKey = require('uuid').v4();

var createChecksum = function (client, server) {
  var str = client + '-' + server + '-' + sessionDigestKey;
  str = str.replace(/\./g, 'a').replace(/:/g, 'b');
  return Math.abs(checksum.str(str));
};

// Return [client,server] if query is valid, or false if not.
var validateQuery = function (query) {
  query = query.replace(/a/g, '.').replace(/b/g, ':');
  var parts = query.split('-');
  if (parts.length != 3) {
    return false;
  }
  var client = parts[0];
  var server = parts[1];
  var expectedChecksum = createChecksum(client, server);
  if (parts[2] === '' + expectedChecksum) {
    return [client, server];
  } else {
    return false;
  }
};

var setRootAuthority = function(resp, noA) {
  resp.authority.push(dns.NS({
    name: rootTLD,
    data: 'ns1.' + rootTLD,
    ttl: 5
  }));
  resp.authority.push(dns.NS({
    name: rootTLD,
    data: 'ns2.' + rootTLD,
    ttl: 5
  }));
  if (!noA) {
    resp.answer.push(dns.A({
      name: 'ns1.' + rootTLD,
      address: myip,
      ttl: 5
    }));
    resp.answer.push(dns.A({
      name: 'ns2.' + rootTLD,
      address: altip,
      ttl: 5
    }));
  }
  resp.authority.push(dns.SOA({
    name: rootTLD,
    primary: 'ns1.' + rootTLD,
    admin: 'measurement.' + rootTLD,
    serial: new Date().valueOf(),
    refresh: 5,
    retry: 5,
    expiration: 5,
    minimum: 5,
    ttl: 5
  }));
};

var setDelegatedAuthority = function(prefix, resp) {
  var delegatedCN = prefix + '.' + rootTLD;
  resp.authority.push(dns.NS({
    name: delegatedCN,
    data: 'ns1.' + delegatedCN,
    ttl: 5
  }));
  resp.authority.push(dns.NS({
    name: delegatedCN,
    data: 'ns2.' + delegatedCN,
    ttl: 5
  }));
  resp.authority.push(dns.SOA({
    name: delegatedCN,
    primary: 'ns1.' + delegatedCN,
    admin: 'measurement.' + rootTLD,
    serial: new Date().valueOf(),
    refresh: 5,
    retry: 5,
    expiration: 5,
    minimum: 5,
    ttl: 5
  }));
};

var matchServer = function (client) {
  var server = ['208.67.220.220', '208.67.222.222']; //todo: roundrobin.
  return server;
};

var createPrefix = function (client, server) {
  var checksum = createChecksum(client, server);
  var prefix = client + '-' + server + '-' + checksum;
  return prefix.replace(/\./g, 'a').replace(/:/g, 'b');
};

// make a query to populate a server cache, so it can answer non-recursively
// despite not being authoritative
var fillCache = function (prefix, server, cb) {
  var question = dns.Question({
    name: prefix,
    type: 'A'
  });
  var req = dns.Request({
    question: question,
    server: { address: server, port: 53, type: 'udp'},
    timeout: 1000
  });
  req.on('end', cb);
  req.send();
};

var handler = function (req, resp) {
  if (req.question.length === 0) {
    return;
  }
  var query = req.question[0].name.toLowerCase();
  var addr = req.address.address;
  var prefix, resolvers;

  if (req.question[0].type != 1 && req.question[0].type != 2 && req.question[0].type != 255) {
    winston.info(addr + ' [' + req.question[0].type + '] ' + query);
  } else if (req.question[0].type == 2) { // NS request
    winston.info(addr + ' [NS] ' + query);
    setRootAuthority(resp);
    resp.send();
    return;
  } else if (req.question[0].type == 1 || req.question[0].type == 255) { // A/ANY request
    var lookuptype = (req.question[0].type == 255) ? 'ANY' : 'A';
    winston.info(addr + ' [' + lookuptype + '] ' + query);
    // Failures
    if (query.indexOf(rootTLD) === -1) {
      resp.answer.push(dns.A({
        name: query,
        address: myip,
        ttl: 5
      }));
      resp.send();
      return;
    // Initial query
    } else if (query === "ns1." + rootTLD || query === "ns2." + rootTLD) {
      setRootAuthority(resp);
      resp.send();
      return;
    } else if (query === rootTLD) {
      // TODO: record attempt at connectivity
      resolvers = matchServer(addr);
      prefix = createPrefix(addr, resolvers[0]);
      var delegatedCN = prefix + '.' + rootTLD;
      resp.header.ra = false;
      resp.answer.push(dns.CNAME({
        name: query,
        ttl: 5,
        data: 'resolve.' + delegatedCN
      }));
      setDelegatedAuthority(prefix, resp);
      resp.additional.push(dns.A({
        name: 'ns1.' + delegatedCN,
        address: resolvers[0],
        ttl: 5
      }));
      resp.additional.push(dns.A({
        name: 'ns2.' + delegatedCN,
        address: resolvers[1],
        ttl: 5
      }));
      fillCache('precache.' + delegatedCN, resolvers[0], function() {
        resp.send();
      });
      return;
    }

    // Successful indicaton of connectivity
    prefix = query.split(rootTLD)[0];
    prefix = prefix.substr(0, prefix.length - 1);
    var host = '';
    if (prefix.indexOf('.') > 0) {
      host = prefix.split('.');
      prefix = host[1];
      host = host[0];
    } else if (prefix.indexOf('success-') === 0) {
      host = 'success';
      prefix = prefix.substr(8);
    }
    var parts = validateQuery(prefix);
    if (parts === false) {
      resp.answer.push(dns.A({
        name: query,
        address: myip,
        ttl: 5
      }));
      resp.send();
      return;
    } else if (host === 'ns1' || host === 'ns2') {
      setDelegatedAuthority(prefix, resp);
      resolvers = matchServer(parts[0]);
      resp.answer.push(dns.A({
        name: 'ns1.' + prefix + '.' + rootTLD,
        address: resolvers[0],
        ttl: 5
      }));
      resp.answer.push(dns.A({
        name: 'ns2.' + prefix + '.' + rootTLD,
        address: resolvers[1],
        ttl: 5
      }));
      resp.send();
      return;
    } else if (host === 'precache') {
      // "poison" the cache of the authoritative resolver.
      resp.answer.push(dns.A({
        name: query,
        address: myip,
        ttl: 5
      }));
      resp.additional.push(dns.CNAME({
        name: "resolve." + prefix + '.' + rootTLD,
        ttl: 20,
        data: "success-" + prefix + '.' + rootTLD
      }));
      resp.send();
      return;
    } else if (host === 'success') {
      winston.info('Induced Connectivity between ' + parts[0] + ' and ' + parts[1] + ' via cache poisoning [seen by ' + addr + ']');
      resp.answer.push(dns.A({
        name: query,
        address: addr,
        ttl: 5
      }));
      resp.send();
      return;
    } else {
      // Queries for the cname are owned by the appropriate delegee.
      if (addr == parts[0]) {
        setDelegatedAuthority(prefix, resp);
        resolvers = matchServer(parts[0]);
        resp.additional.push(dns.A({
          name: 'ns1.' + prefix + '.' + rootTLD,
          address: resolvers[0],
          ttl: 5
        }));
        resp.additional.push(dns.A({
          name: 'ns2.' + prefix + '.' + rootTLD,
          address: resolvers[1],
          ttl: 5
        }));
        resp.send();
        return;
      } else {
        // TODO: Log success of client-server. query.
        // TODO: See if it's been made recently by same server, indicating response dropped.
        winston.info('Induced Connectivity between ' + parts[0] + ' and ' + parts[1] + ' [exposed as ' + addr + ']');
      /*
      resp.answer.push(dns.CNAME({
        name: query,
        ttl: 5,
        data: 'www.google.com'
      }));
      */
        resp.answer.push(dns.A({
          name: query,
          address: addr,
          ttl: 5
        }));
        resp.send();
        return;
      }
    }
  }
};

var server1 = dns.createServer();
server1.on('request', handler);
server1.on('error', function (err) {
  console.warn(err.stack);
});
var server2 = dns.createServer();
server2.on('request', handler);
server2.on('error', function (err) {
  console.warn(err.stack);
});

server1.serve(53, myip);
server2.serve(53, altip);
winston.info('Running for', rootTLD, myip, altip);
winston.info('Session Key is', sessionDigestKey);
<|endoftext|>


<commit_before>import fs from 'fs';
import path from 'path';

import etch from 'etch';
import until from 'test-until';

import {cloneRepository, buildRepository, setUpLocalAndRemoteRepositories} from '../helpers';
import StatusBarTileController from '../../lib/controllers/status-bar-tile-controller';

describe('StatusBarTileController', function() {
  let atomEnvironment, workspace, workspaceElement, commandRegistry, notificationManager;

  beforeEach(function() {
    atomEnvironment = global.buildAtomEnvironment();
    workspace = atomEnvironment.workspace;
    commandRegistry = atomEnvironment.commands;
    notificationManager = atomEnvironment.notifications;

    workspaceElement = atomEnvironment.views.getView(workspace);
  });

  afterEach(function() {
    atomEnvironment.destroy();
  });

  describe('branches', function() {
    it('indicates the current branch and toggles visibility of the branch menu when clicked', async function() {
      const workdirPath = await cloneRepository('three-files');
      const repository = await buildRepository(workdirPath);

      const controller = new StatusBarTileController({workspace, repository, commandRegistry});
      await controller.getLastModelDataRefreshPromise();
      await etch.getScheduler().getNextUpdatePromise();

      const branchView = controller.refs.branchView;
      assert.equal(branchView.element.textContent, 'master');

      // FIXME: Remove this guard when 1.13 is on stable.
      if (parseFloat(atom.getVersion() >= 1.13)) {
        assert.isUndefined(document.querySelectorAll('.github-BranchMenuView')[0]);
        branchView.element.click();
        assert.isDefined(document.querySelectorAll('.github-BranchMenuView')[0]);
        branchView.element.click();
        assert.isUndefined(document.querySelectorAll('.github-BranchMenuView')[0]);
      }
    });

    describe('the branch menu', function() {
      describe('checking out an existing branch', function() {
        it('can check out existing branches with no conflicts', async function() {
          const workdirPath = await cloneRepository('three-files');
          const repository = await buildRepository(workdirPath);

          // create branch called 'branch'
          await repository.git.exec(['branch', 'branch']);

          const controller = new StatusBarTileController({workspace, repository, commandRegistry});
          await controller.getLastModelDataRefreshPromise();
          await etch.getScheduler().getNextUpdatePromise();

          const branchMenuView = controller.branchMenuView;
          const {list} = branchMenuView.refs;

          const branches = Array.from(list.options).map(option => option.value);
          assert.deepEqual(branches, ['branch', 'master']);
          assert.equal(await repository.getCurrentBranch(), 'master');
          assert.equal(list.selectedOptions[0].value, 'master');

          list.selectedIndex = branches.indexOf('branch');
          list.onchange();
          assert.equal(await repository.getCurrentBranch(), 'branch');
          assert.equal(list.selectedOptions[0].value, 'branch');

          list.selectedIndex = branches.indexOf('master');
          list.onchange();
          assert.equal(await repository.getCurrentBranch(), 'master');
          assert.equal(list.selectedOptions[0].value, 'master');
        });

        it('displays an error message if checkout fails', async function() {
          const {localRepoPath} = await setUpLocalAndRemoteRepositories('three-files');
          const repository = await buildRepository(localRepoPath);
          await repository.git.exec(['branch', 'branch']);

          // create a conflict
          fs.writeFileSync(path.join(localRepoPath, 'a.txt'), 'a change');

          await repository.git.exec(['commit', '-a', '-m', 'change on master']);
          await repository.checkout('branch');
          fs.writeFileSync(path.join(localRepoPath, 'a.txt'), 'a change that conflicts');

          const controller = new StatusBarTileController({workspace, repository, commandRegistry, notificationManager});
          await controller.getLastModelDataRefreshPromise();
          await etch.getScheduler().getNextUpdatePromise();

          const branchMenuView = controller.branchMenuView;
          const {list} = branchMenuView.refs;

          const branches = Array.from(list.options).map(option => option.value);
          assert.equal(await repository.getCurrentBranch(), 'branch');
          assert.equal(list.selectedOptions[0].value, 'branch');

          sinon.stub(notificationManager, 'addError');

          list.selectedIndex = branches.indexOf('master');
          list.onchange();
          await etch.getScheduler().getNextUpdatePromise();
          assert.equal(await repository.getCurrentBranch(), 'branch');
          await assert.async.equal(list.selectedOptions[0].value, 'branch');
          await assert.async.isTrue(notificationManager.addError.called);
          const notificationArgs = notificationManager.addError.args[0];
          assert.equal(notificationArgs[0], 'Checkout aborted');
          assert.match(notificationArgs[1].description, /Local changes to the following would be overwritten/);
        });
      });

      describe('checking out newly created branches', function() {
        it('can check out newly created branches', async function() {
          const workdirPath = await cloneRepository('three-files');
          const repository = await buildRepository(workdirPath);

          const controller = new StatusBarTileController({workspace, repository, commandRegistry});
          await controller.getLastModelDataRefreshPromise();
          await etch.getScheduler().getNextUpdatePromise();

          const branchMenuView = controller.branchMenuView;
          const {list, newBranchButton} = branchMenuView.refs;

          const branches = Array.from(list.options).map(option => option.value);
          assert.deepEqual(branches, ['master']);
          assert.equal(await repository.getCurrentBranch(), 'master');
          assert.equal(list.selectedOptions[0].value, 'master');

          assert.isDefined(branchMenuView.refs.list);
          assert.isUndefined(branchMenuView.refs.editor);
          newBranchButton.click();
          await etch.getScheduler().getNextUpdatePromise();
          assert.isUndefined(branchMenuView.refs.list);
          assert.isDefined(branchMenuView.refs.editor);

          branchMenuView.refs.editor.setText('new-branch');
          await newBranchButton.onclick();
          repository.refresh();
          await controller.getLastModelDataRefreshPromise();
          await etch.getScheduler().getNextUpdatePromise();

          assert.isUndefined(branchMenuView.refs.editor);
          assert.isDefined(branchMenuView.refs.list);

          assert.equal(await repository.getCurrentBranch(), 'new-branch');
          assert.equal(branchMenuView.refs.list.selectedOptions[0].value, 'new-branch');
        });

        it('displays an error message if branch already exists', async function() {
          const workdirPath = await cloneRepository('three-files');
          const repository = await buildRepository(workdirPath);

          await repository.git.exec(['checkout', '-b', 'branch']);

          const controller = new StatusBarTileController({workspace, repository, commandRegistry, notificationManager});
          await controller.getLastModelDataRefreshPromise();
          await etch.getScheduler().getNextUpdatePromise();

          const branchMenuView = controller.branchMenuView;
          const {list, newBranchButton} = branchMenuView.refs;

          sinon.stub(notificationManager, 'addError');

          const branches = Array.from(branchMenuView.refs.list.options).map(option => option.value);
          assert.deepEqual(branches, ['branch', 'master']);
          assert.equal(await repository.getCurrentBranch(), 'branch');
          assert.equal(list.selectedOptions[0].value, 'branch');

          await newBranchButton.onclick();

          branchMenuView.refs.editor.setText('master');
          await newBranchButton.onclick();
          await assert.async.isTrue(notificationManager.addError.called);
          const notificationArgs = notificationManager.addError.args[0];
          assert.equal(notificationArgs[0], 'Cannot create branch');
          assert.match(notificationArgs[1].description, /already exists/);

          assert.equal(await repository.getCurrentBranch(), 'branch');
          assert.equal(branchMenuView.refs.list.selectedOptions[0].value, 'branch');
        });
      });
    });
  });

  describe('pushing and pulling', function() {
    it('indicates the ahead and behind counts and toggles visibility of the push pull menu when clicked', async function() {
      const {localRepoPath} = await setUpLocalAndRemoteRepositories();
      const repository = await buildRepository(localRepoPath);

      const controller = new StatusBarTileController({workspace, repository, commandRegistry});
      await controller.getLastModelDataRefreshPromise();
      await etch.getScheduler().getNextUpdatePromise();

      const pushPullView = controller.refs.pushPullView;
      const {aheadCount, behindCount} = pushPullView.refs;
      assert.equal(aheadCount.textContent, '');
      assert.equal(behindCount.textContent, '');

      await repository.git.exec(['reset', '--hard', 'head~2']);
      repository.refresh();
      await controller.getLastModelDataRefreshPromise();
      await etch.getScheduler().getNextUpdatePromise();
      assert.equal(aheadCount.textContent, '');
      assert.equal(behindCount.textContent, '2');

      await repository.git.commit('new local commit', {allowEmpty: true});
      repository.refresh();
      await controller.getLastModelDataRefreshPromise();
      await etch.getScheduler().getNextUpdatePromise();
      assert.equal(aheadCount.textContent, '1');
      assert.equal(behindCount.textContent, '2');

      // FIXME: Remove this guard when 1.13 is on stable.
      if (parseFloat(atom.getVersion() >= 1.13)) {
        assert.isUndefined(document.querySelectorAll('.github-PushPullMenuView')[0]);
        pushPullView.element.click();
        assert.isDefined(document.querySelectorAll('.github-PushPullMenuView')[0]);
        pushPullView.element.click();
        assert.isUndefined(document.querySelectorAll('.github-PushPullMenuView')[0]);
      }
    });

    describe('the push/pull menu', function() {
      it('disables the fetch and pull buttons when there is no remote tracking branch and displays informative message', async function() {
        const {localRepoPath} = await setUpLocalAndRemoteRepositories();
        const repository = await buildRepository(localRepoPath);
        await repository.git.exec(['checkout', '-b', 'new-branch']);

        const controller = new StatusBarTileController({workspace, repository, commandRegistry});
        await controller.getLastModelDataRefreshPromise();
        await etch.getScheduler().getNextUpdatePromise();

        const pushPullMenuView = controller.pushPullMenuView;
        const {pushButton, pullButton, fetchButton, message} = pushPullMenuView.refs;

        assert.isTrue(pullButton.disabled);
        assert.isTrue(fetchButton.disabled);
        assert.match(message.innerHTML, /No remote detected.*Pushing will set up a remote tracking branch/);

        pushButton.dispatchEvent(new MouseEvent('click'));
        await until(async fail => {
          try {
            repository.refresh();
            await controller.getLastModelDataRefreshPromise();
            await etch.getScheduler().getNextUpdatePromise();

            assert.isFalse(pullButton.disabled);
            assert.isFalse(fetchButton.disabled);
            assert.equal(message.textContent, '');
            return true;
          } catch (err) {
            return fail(err);
          }
        });
      });

      it('displays an error message if push fails and allows force pushing if meta key is pressed', async function() {
        const {localRepoPath} = await setUpLocalAndRemoteRepositories();
        const repository = await buildRepository(localRepoPath);
        await repository.git.exec(['reset', '--hard', 'head~2']);
        await repository.git.commit('another commit', {allowEmpty: true});

        const controller = new StatusBarTileController({workspace, repository, commandRegistry, notificationManager});
        await controller.getLastModelDataRefreshPromise();
        await etch.getScheduler().getNextUpdatePromise();

        const pushPullMenuView = controller.pushPullMenuView;
        const {pushButton, pullButton} = pushPullMenuView.refs;

        sinon.stub(notificationManager, 'addError');

        assert.equal(pushButton.textContent, 'Push (1)');
        assert.equal(pullButton.textContent, 'Pull (2)');

        pushButton.dispatchEvent(new MouseEvent('click'));
        await controller.getLastModelDataRefreshPromise();
        await etch.getScheduler().getNextUpdatePromise();

        await assert.async.isTrue(notificationManager.addError.called);
        const notificationArgs = notificationManager.addError.args[0];
        assert.equal(notificationArgs[0], 'Push rejected');
        assert.match(notificationArgs[1].description, /Try pulling before pushing again/);

        pushButton.dispatchEvent(new MouseEvent('click', {metaKey: true}));
        repository.refresh();
        await controller.getLastModelDataRefreshPromise();

        await assert.async.equal(pushButton.textContent, 'Push ');
        await assert.async.equal(pullButton.textContent, 'Pull ');
      });
    });

    describe('fetch and pull commands', function() {
      it('fetches when github:fetch is triggered', async function() {
        const {localRepoPath} = await setUpLocalAndRemoteRepositories('multiple-commits', {remoteAhead: true});
        const repository = await buildRepository(localRepoPath);

        const controller = new StatusBarTileController({workspace, repository, commandRegistry});
        await controller.getLastModelDataRefreshPromise();

        sinon.spy(repository, 'fetch');

        commandRegistry.dispatch(workspaceElement, 'github:fetch');

        assert.isTrue(repository.fetch.called);
      });

      it('pulls when github:pull is triggered', async function() {
        const {localRepoPath} = await setUpLocalAndRemoteRepositories('multiple-commits', {remoteAhead: true});
        const repository = await buildRepository(localRepoPath);

        const controller = new StatusBarTileController({workspace, repository, commandRegistry});
        await controller.getLastModelDataRefreshPromise();

        sinon.spy(repository, 'pull');

        commandRegistry.dispatch(workspaceElement, 'github:pull');

        assert.isTrue(repository.pull.called);
      });

      it('pushes when github:push is triggered', async function() {
        const {localRepoPath} = await setUpLocalAndRemoteRepositories();
        const repository = await buildRepository(localRepoPath);

        const controller = new StatusBarTileController({workspace, repository, commandRegistry});
        await controller.getLastModelDataRefreshPromise();

        sinon.spy(repository, 'push');

        commandRegistry.dispatch(workspaceElement, 'github:push');

        assert.isTrue(repository.push.calledWith('master', sinon.match({force: false, setUpstream: false})));
      });

      it('force pushes when github:force-push is triggered', async function() {
        const {localRepoPath} = await setUpLocalAndRemoteRepositories();
        const repository = await buildRepository(localRepoPath);

        const controller = new StatusBarTileController({workspace, repository, commandRegistry});
        await controller.getLastModelDataRefreshPromise();

        sinon.spy(repository, 'push');

        commandRegistry.dispatch(workspaceElement, 'github:force-push');

        assert.isTrue(repository.push.calledWith('master', sinon.match({force: true, setUpstream: false})));
      });
    });
  });

  describe('changed files', function() {
    it('shows the changed files count view when the repository data is loaded', async function() {
      const workdirPath = await cloneRepository('three-files');
      const repository = await buildRepository(workdirPath);

      const toggleGitPanel = sinon.spy();
      const controller = new StatusBarTileController({workspace, repository, toggleGitPanel, commandRegistry});
      await controller.getLastModelDataRefreshPromise();
      await etch.getScheduler().getNextUpdatePromise();

      const changedFilesCountView = controller.refs.changedFilesCountView;

      assert.equal(changedFilesCountView.element.textContent, '0 files');

      fs.writeFileSync(path.join(workdirPath, 'a.txt'), 'a change\n');
      fs.unlinkSync(path.join(workdirPath, 'b.txt'));
      repository.refresh();
      await repository.stageFiles(['a.txt']);
      repository.refresh();
      await controller.getLastModelDataRefreshPromise();
      await etch.getScheduler().getNextUpdatePromise();

      assert.equal(changedFilesCountView.element.textContent, '2 files');

      changedFilesCountView.element.click();
      assert(toggleGitPanel.calledOnce);
    });
  });
});
<commit_msg>A passing BranchView test<commit_after>import fs from 'fs';
import path from 'path';

import React from 'react';
import until from 'test-until';
import {mount} from 'enzyme';

import {cloneRepository, buildRepository, setUpLocalAndRemoteRepositories} from '../helpers';
import StatusBarTileController from '../../lib/controllers/status-bar-tile-controller';
import BranchView from '../../lib/views/branch-view';

describe('StatusBarTileController', function() {
  let atomEnvironment;
  let workspace, workspaceElement, commandRegistry, notificationManager, tooltips;
  let component;

  beforeEach(function() {
    atomEnvironment = global.buildAtomEnvironment();
    workspace = atomEnvironment.workspace;
    commandRegistry = atomEnvironment.commands;
    notificationManager = atomEnvironment.notifications;
    tooltips = atomEnvironment.tooltips;

    workspaceElement = atomEnvironment.views.getView(workspace);

    component = (
      <StatusBarTileController
        workspace={workspace}
        commandRegistry={commandRegistry}
        notificationManager={notificationManager}
        tooltips={tooltips}
      />
    );
  });

  afterEach(function() {
    atomEnvironment.destroy();
  });

  describe('branches', function() {
    it('indicates the current branch', async function() {
      const workdirPath = await cloneRepository('three-files');
      const repository = await buildRepository(workdirPath);

      const wrapper = mount(React.cloneElement(component, {repository}));
      await wrapper.instance().refreshModelData();

      assert.equal(wrapper.find(BranchView).prop('branchName'), 'master');
    });

    function getTooltipNode(wrapper, selector) {
      const ts = tooltips.findTooltips(wrapper.find(selector).node.element);
      assert.lengthOf(ts, 1);
      ts[0].show();
      return ts[0].getTooltipElement();
    }

    describe('the branch menu', function() {
      function selectOption(tip, value) {
        const selects = Array.from(tip.getElementsByTagName('select'));
        assert.lengthOf(selects, 1);
        const select = selects[0];
        select.value = value;

        const event = new Event('change', {bubbles: true, cancelable: true});
        select.dispatchEvent(event);
      }

      describe('checking out an existing branch', function() {
        it('can check out existing branches with no conflicts', async function() {
          const workdirPath = await cloneRepository('three-files');
          const repository = await buildRepository(workdirPath);

          // create branch called 'branch'
          await repository.git.exec(['branch', 'branch']);

          const wrapper = mount(React.cloneElement(component, {repository}));
          await wrapper.instance().refreshModelData();

          const tip = getTooltipNode(wrapper, BranchView);

          const branches = Array.from(tip.getElementsByTagName('option'), e => e.innerHTML);
          assert.deepEqual(branches, ['branch', 'master']);

          assert.equal(await repository.getCurrentBranch(), 'master');
          assert.equal(tip.querySelector('select').value, 'master');

          selectOption(tip, 'branch');
          assert.equal(await repository.getCurrentBranch(), 'branch');
          await wrapper.instance().refreshModelData();
          await assert.async.equal(tip.querySelector('select').value, 'branch');

          selectOption(tip, 'master');
          assert.equal(await repository.getCurrentBranch(), 'master');
          await wrapper.instance().refreshModelData();
          await assert.async.equal(tip.querySelector('select').value, 'master');
        });

        it('displays an error message if checkout fails', async function() {
          const {localRepoPath} = await setUpLocalAndRemoteRepositories('three-files');
          const repository = await buildRepository(localRepoPath);
          await repository.git.exec(['branch', 'branch']);

          // create a conflict
          fs.writeFileSync(path.join(localRepoPath, 'a.txt'), 'a change');

          await repository.git.exec(['commit', '-a', '-m', 'change on master']);
          await repository.checkout('branch');
          fs.writeFileSync(path.join(localRepoPath, 'a.txt'), 'a change that conflicts');

          const controller = new StatusBarTileController({workspace, repository, commandRegistry, notificationManager});
          await controller.getLastModelDataRefreshPromise();
          await etch.getScheduler().getNextUpdatePromise();

          const branchMenuView = controller.branchMenuView;
          const {list} = branchMenuView.refs;

          const branches = Array.from(list.options).map(option => option.value);
          assert.equal(await repository.getCurrentBranch(), 'branch');
          assert.equal(list.selectedOptions[0].value, 'branch');

          sinon.stub(notificationManager, 'addError');

          list.selectedIndex = branches.indexOf('master');
          list.onchange();
          await etch.getScheduler().getNextUpdatePromise();
          assert.equal(await repository.getCurrentBranch(), 'branch');
          await assert.async.equal(list.selectedOptions[0].value, 'branch');
          await assert.async.isTrue(notificationManager.addError.called);
          const notificationArgs = notificationManager.addError.args[0];
          assert.equal(notificationArgs[0], 'Checkout aborted');
          assert.match(notificationArgs[1].description, /Local changes to the following would be overwritten/);
        });
      });

      describe('checking out newly created branches', function() {
        it('can check out newly created branches', async function() {
          const workdirPath = await cloneRepository('three-files');
          const repository = await buildRepository(workdirPath);

          const controller = new StatusBarTileController({workspace, repository, commandRegistry});
          await controller.getLastModelDataRefreshPromise();
          await etch.getScheduler().getNextUpdatePromise();

          const branchMenuView = controller.branchMenuView;
          const {list, newBranchButton} = branchMenuView.refs;

          const branches = Array.from(list.options).map(option => option.value);
          assert.deepEqual(branches, ['master']);
          assert.equal(await repository.getCurrentBranch(), 'master');
          assert.equal(list.selectedOptions[0].value, 'master');

          assert.isDefined(branchMenuView.refs.list);
          assert.isUndefined(branchMenuView.refs.editor);
          newBranchButton.click();
          await etch.getScheduler().getNextUpdatePromise();
          assert.isUndefined(branchMenuView.refs.list);
          assert.isDefined(branchMenuView.refs.editor);

          branchMenuView.refs.editor.setText('new-branch');
          await newBranchButton.onclick();
          repository.refresh();
          await controller.getLastModelDataRefreshPromise();
          await etch.getScheduler().getNextUpdatePromise();

          assert.isUndefined(branchMenuView.refs.editor);
          assert.isDefined(branchMenuView.refs.list);

          assert.equal(await repository.getCurrentBranch(), 'new-branch');
          assert.equal(branchMenuView.refs.list.selectedOptions[0].value, 'new-branch');
        });

        it('displays an error message if branch already exists', async function() {
          const workdirPath = await cloneRepository('three-files');
          const repository = await buildRepository(workdirPath);

          await repository.git.exec(['checkout', '-b', 'branch']);

          const controller = new StatusBarTileController({workspace, repository, commandRegistry, notificationManager});
          await controller.getLastModelDataRefreshPromise();
          await etch.getScheduler().getNextUpdatePromise();

          const branchMenuView = controller.branchMenuView;
          const {list, newBranchButton} = branchMenuView.refs;

          sinon.stub(notificationManager, 'addError');

          const branches = Array.from(branchMenuView.refs.list.options).map(option => option.value);
          assert.deepEqual(branches, ['branch', 'master']);
          assert.equal(await repository.getCurrentBranch(), 'branch');
          assert.equal(list.selectedOptions[0].value, 'branch');

          await newBranchButton.onclick();

          branchMenuView.refs.editor.setText('master');
          await newBranchButton.onclick();
          await assert.async.isTrue(notificationManager.addError.called);
          const notificationArgs = notificationManager.addError.args[0];
          assert.equal(notificationArgs[0], 'Cannot create branch');
          assert.match(notificationArgs[1].description, /already exists/);

          assert.equal(await repository.getCurrentBranch(), 'branch');
          assert.equal(branchMenuView.refs.list.selectedOptions[0].value, 'branch');
        });
      });
    });
  });

  describe('pushing and pulling', function() {
    it('indicates the ahead and behind counts and toggles visibility of the push pull menu when clicked', async function() {
      const {localRepoPath} = await setUpLocalAndRemoteRepositories();
      const repository = await buildRepository(localRepoPath);

      const controller = new StatusBarTileController({workspace, repository, commandRegistry});
      await controller.getLastModelDataRefreshPromise();
      await etch.getScheduler().getNextUpdatePromise();

      const pushPullView = controller.refs.pushPullView;
      const {aheadCount, behindCount} = pushPullView.refs;
      assert.equal(aheadCount.textContent, '');
      assert.equal(behindCount.textContent, '');

      await repository.git.exec(['reset', '--hard', 'head~2']);
      repository.refresh();
      await controller.getLastModelDataRefreshPromise();
      await etch.getScheduler().getNextUpdatePromise();
      assert.equal(aheadCount.textContent, '');
      assert.equal(behindCount.textContent, '2');

      await repository.git.commit('new local commit', {allowEmpty: true});
      repository.refresh();
      await controller.getLastModelDataRefreshPromise();
      await etch.getScheduler().getNextUpdatePromise();
      assert.equal(aheadCount.textContent, '1');
      assert.equal(behindCount.textContent, '2');

      // FIXME: Remove this guard when 1.13 is on stable.
      if (parseFloat(atom.getVersion() >= 1.13)) {
        assert.isUndefined(document.querySelectorAll('.github-PushPullMenuView')[0]);
        pushPullView.element.click();
        assert.isDefined(document.querySelectorAll('.github-PushPullMenuView')[0]);
        pushPullView.element.click();
        assert.isUndefined(document.querySelectorAll('.github-PushPullMenuView')[0]);
      }
    });

    describe('the push/pull menu', function() {
      it('disables the fetch and pull buttons when there is no remote tracking branch and displays informative message', async function() {
        const {localRepoPath} = await setUpLocalAndRemoteRepositories();
        const repository = await buildRepository(localRepoPath);
        await repository.git.exec(['checkout', '-b', 'new-branch']);

        const controller = new StatusBarTileController({workspace, repository, commandRegistry});
        await controller.getLastModelDataRefreshPromise();
        await etch.getScheduler().getNextUpdatePromise();

        const pushPullMenuView = controller.pushPullMenuView;
        const {pushButton, pullButton, fetchButton, message} = pushPullMenuView.refs;

        assert.isTrue(pullButton.disabled);
        assert.isTrue(fetchButton.disabled);
        assert.match(message.innerHTML, /No remote detected.*Pushing will set up a remote tracking branch/);

        pushButton.dispatchEvent(new MouseEvent('click'));
        await until(async fail => {
          try {
            repository.refresh();
            await controller.getLastModelDataRefreshPromise();
            await etch.getScheduler().getNextUpdatePromise();

            assert.isFalse(pullButton.disabled);
            assert.isFalse(fetchButton.disabled);
            assert.equal(message.textContent, '');
            return true;
          } catch (err) {
            return fail(err);
          }
        });
      });

      it('displays an error message if push fails and allows force pushing if meta key is pressed', async function() {
        const {localRepoPath} = await setUpLocalAndRemoteRepositories();
        const repository = await buildRepository(localRepoPath);
        await repository.git.exec(['reset', '--hard', 'head~2']);
        await repository.git.commit('another commit', {allowEmpty: true});

        const controller = new StatusBarTileController({workspace, repository, commandRegistry, notificationManager});
        await controller.getLastModelDataRefreshPromise();
        await etch.getScheduler().getNextUpdatePromise();

        const pushPullMenuView = controller.pushPullMenuView;
        const {pushButton, pullButton} = pushPullMenuView.refs;

        sinon.stub(notificationManager, 'addError');

        assert.equal(pushButton.textContent, 'Push (1)');
        assert.equal(pullButton.textContent, 'Pull (2)');

        pushButton.dispatchEvent(new MouseEvent('click'));
        await controller.getLastModelDataRefreshPromise();
        await etch.getScheduler().getNextUpdatePromise();

        await assert.async.isTrue(notificationManager.addError.called);
        const notificationArgs = notificationManager.addError.args[0];
        assert.equal(notificationArgs[0], 'Push rejected');
        assert.match(notificationArgs[1].description, /Try pulling before pushing again/);

        pushButton.dispatchEvent(new MouseEvent('click', {metaKey: true}));
        repository.refresh();
        await controller.getLastModelDataRefreshPromise();

        await assert.async.equal(pushButton.textContent, 'Push ');
        await assert.async.equal(pullButton.textContent, 'Pull ');
      });
    });

    describe('fetch and pull commands', function() {
      it('fetches when github:fetch is triggered', async function() {
        const {localRepoPath} = await setUpLocalAndRemoteRepositories('multiple-commits', {remoteAhead: true});
        const repository = await buildRepository(localRepoPath);

        const controller = new StatusBarTileController({workspace, repository, commandRegistry});
        await controller.getLastModelDataRefreshPromise();

        sinon.spy(repository, 'fetch');

        commandRegistry.dispatch(workspaceElement, 'github:fetch');

        assert.isTrue(repository.fetch.called);
      });

      it('pulls when github:pull is triggered', async function() {
        const {localRepoPath} = await setUpLocalAndRemoteRepositories('multiple-commits', {remoteAhead: true});
        const repository = await buildRepository(localRepoPath);

        const controller = new StatusBarTileController({workspace, repository, commandRegistry});
        await controller.getLastModelDataRefreshPromise();

        sinon.spy(repository, 'pull');

        commandRegistry.dispatch(workspaceElement, 'github:pull');

        assert.isTrue(repository.pull.called);
      });

      it('pushes when github:push is triggered', async function() {
        const {localRepoPath} = await setUpLocalAndRemoteRepositories();
        const repository = await buildRepository(localRepoPath);

        const controller = new StatusBarTileController({workspace, repository, commandRegistry});
        await controller.getLastModelDataRefreshPromise();

        sinon.spy(repository, 'push');

        commandRegistry.dispatch(workspaceElement, 'github:push');

        assert.isTrue(repository.push.calledWith('master', sinon.match({force: false, setUpstream: false})));
      });

      it('force pushes when github:force-push is triggered', async function() {
        const {localRepoPath} = await setUpLocalAndRemoteRepositories();
        const repository = await buildRepository(localRepoPath);

        const controller = new StatusBarTileController({workspace, repository, commandRegistry});
        await controller.getLastModelDataRefreshPromise();

        sinon.spy(repository, 'push');

        commandRegistry.dispatch(workspaceElement, 'github:force-push');

        assert.isTrue(repository.push.calledWith('master', sinon.match({force: true, setUpstream: false})));
      });
    });
  });

  describe('changed files', function() {
    it('shows the changed files count view when the repository data is loaded', async function() {
      const workdirPath = await cloneRepository('three-files');
      const repository = await buildRepository(workdirPath);

      const toggleGitPanel = sinon.spy();
      const controller = new StatusBarTileController({workspace, repository, toggleGitPanel, commandRegistry});
      await controller.getLastModelDataRefreshPromise();
      await etch.getScheduler().getNextUpdatePromise();

      const changedFilesCountView = controller.refs.changedFilesCountView;

      assert.equal(changedFilesCountView.element.textContent, '0 files');

      fs.writeFileSync(path.join(workdirPath, 'a.txt'), 'a change\n');
      fs.unlinkSync(path.join(workdirPath, 'b.txt'));
      repository.refresh();
      await repository.stageFiles(['a.txt']);
      repository.refresh();
      await controller.getLastModelDataRefreshPromise();
      await etch.getScheduler().getNextUpdatePromise();

      assert.equal(changedFilesCountView.element.textContent, '2 files');

      changedFilesCountView.element.click();
      assert(toggleGitPanel.calledOnce);
    });
  });
});
<|endoftext|>


<commit_before>var irc = require('irc');
var env = require('./config.js');
var fs = require('fs');
var Bot = require('node-telegram-bot');
var moment = require('moment');
var filename = '';

var meeting_time = moment().format('hh:mm A');
var meeting_date = moment().format('DD MMM YY');
var meeting_link ='https://kerala.etherpad-mozilla.org/'+ moment().format('DDMMMYY');
var meeting_logs =' logs.mozillakerala.org/'+ moment().format('DDMMMYY');
var wstream;

filename = './logs/' + moment().format('DDMMMYY') + '.txt';
console.log(filename);

//options for logging
var options = {
    encoding: 'utf8',
    flags: 'a'
};

wstream = fs.createWriteStream(filename, options);

//reading meeting status in sync
var meeting_status = fs.readFileSync('./mod', 'ascii');

//setting up irc configs
var client = new irc.Client(env.server, env.nick, {
    channels: [
    env.channel
  ]
});

//listening for messages from IRC
client.addListener('message', function (from, to, message) {
    console.log(from + ': ' + message);
    if (meeting_status == 'off')
        return;
    bot.sendMessage({
        chat_id: env.tg_chatId,
        text: from + ': ' + message
    })

    add_log(from + ': ' + message + '\n')
});

//log errors
client.addListener('error', function (message) {
    console.log('error: ', message);
});

var bot = new Bot({
    token: env.tgbot_token
}).on('message', function (message) {
    //if message is not text (stickers , image.....) then do nothing
    if (!message.text) {
        return;
    }

    var command = (message.text.split('/')[1]);

    if (command) {
        //remove bot name from the command
        command = (command.replace(env.tgbot_name, '')).toLowerCase();
    }

    switch (command) {
    case 'startmeeting':
        startmeeting(message.from.id);
        //exit from the function so that the /startmeeting is not send to the IRC
        return;

    case 'stopmeeting':
        stopmeeting(message.from.id);
        return;

    case 'status':
        send_status();
        return;

    default:
        send(message);

    }
}).start();

//send Message to IRC
function send(message) {
    var msg;
    if (meeting_status == 'off')
        return;
    if (message.reply_to_message) {

        msg = message.from.first_name + '(in reply to ' + message.reply_to_message.from.first_name + '): ' + message.text;

    } else {

        msg = message.from.first_name + ': ' + message.text;

    }

    client.say(env.channel, msg);
    msg += '\n';
    add_log(msg);
    console.log(message);

}

function startmeeting(from) {

    if (from !== env.admin_id) {
        return;
    }

    meeting_status = 'on';

    //start logging to file
    filename = './logs/' + moment().format('DDMMMYY') + '.txt';

    wstream = fs.createWriteStream(filename, options);

    fs.writeFile('./mod', 'on', 'ascii', function (err) {
        //if error retry startmeeting
        if (err) {
            startmeeting(from);
        } else {

            meeting_time = moment().format('hh:mm A');
            meeting_date = moment().format('DD MMM YY');
            meeting_link ='https://kerala.etherpad-mozilla.org/' + moment().format('DDMMMYY');

            var meeting_msg = strformat("A Meeting was just started by admin at %time% on %date%\n\nThe agenda of the meeting is at %datelink%\n\nYou better be civil from now onwards because I'm logging everything you say.\n\nI'll tell you where to find the log after the meeting ends.", {
                time:meeting_time ,
                date: meeting_date,
                datelink:meeting_link
            });

            bot.sendMessage({
                chat_id: env.tg_chatId,
                text: meeting_msg
            })

            send({from:{first_name:'Admin'},text:meeting_msg});

        }
    });

}

function stopmeeting(from) {

    if (from !== env.admin_id) {
        return;
    }

    meeting_status = 'off';

    //write status to mod file
    fs.writeFile('./mod', 'off', 'ascii', function (err) {
        //if error retry stopmeeting
        if (err) {
            startmeeting(from);
        } else {

                        var meeting_msg = strformat("The meeting that Admin started and chaired from %time% %date% has ended.\nYou can find the public logs of the meeting at %loglink%", {
                time:meeting_time ,
                date: meeting_date,
                loglink:meeting_logs
            });

            send({from:{first_name:'Admin'},text:meeting_msg});

            bot.sendMessage({
                chat_id: env.tg_chatId,
                text: meeting_msg
            })

            //stop logging to file
            wstream.end();
        }
    });
}

function send_status() {
    bot.sendMessage({
        chat_id: env.tg_chatId,
        parse_mode: 'Markdown',
        text: 'Meeting mode *' + meeting_status.toUpperCase() + '*'
    })
}

function add_log(msg) {

    wstream.write(msg);

}

function strformat(str, obj) {

    for (key in obj) {

        str = str.replace(new RegExp('%' + key + '%', 'g'), obj[key]);

    }

    return str;
}<commit_msg>Change etherpad Link<commit_after>var irc = require('irc');
var env = require('./config.js');
var fs = require('fs');
var Bot = require('node-telegram-bot');
var moment = require('moment');
var filename = '';

var meeting_time = moment().format('hh:mm A');
var meeting_date = moment().format('DD MMM YY');
var meeting_link ='https://public.etherpad-mozilla.org/kerala-'+ moment().format('DDMMMYY');
var meeting_logs =' logs.mozillakerala.org/'+ moment().format('DDMMMYY');
var wstream;

filename = './logs/' + moment().format('DDMMMYY') + '.txt';
console.log(filename);

//options for logging
var options = {
    encoding: 'utf8',
    flags: 'a'
};

wstream = fs.createWriteStream(filename, options);

//reading meeting status in sync
var meeting_status = fs.readFileSync('./mod', 'ascii');

//setting up irc configs
var client = new irc.Client(env.server, env.nick, {
    channels: [
    env.channel
  ]
});

//listening for messages from IRC
client.addListener('message', function (from, to, message) {
    console.log(from + ': ' + message);
    if (meeting_status == 'off')
        return;
    bot.sendMessage({
        chat_id: env.tg_chatId,
        text: from + ': ' + message
    })

    add_log(from + ': ' + message + '\n')
});

//log errors
client.addListener('error', function (message) {
    console.log('error: ', message);
});

var bot = new Bot({
    token: env.tgbot_token
}).on('message', function (message) {
    //if message is not text (stickers , image.....) then do nothing
    if (!message.text) {
        return;
    }

    var command = (message.text.split('/')[1]);

    if (command) {
        //remove bot name from the command
        command = (command.replace(env.tgbot_name, '')).toLowerCase();
    }

    switch (command) {
    case 'startmeeting':
        startmeeting(message.from.id);
        //exit from the function so that the /startmeeting is not send to the IRC
        return;

    case 'stopmeeting':
        stopmeeting(message.from.id);
        return;

    case 'status':
        send_status();
        return;

    default:
        send(message);

    }
}).start();

//send Message to IRC
function send(message) {
    var msg;
    if (meeting_status == 'off')
        return;
    if (message.reply_to_message) {

        msg = message.from.first_name + '(in reply to ' + message.reply_to_message.from.first_name + '): ' + message.text;

    } else {

        msg = message.from.first_name + ': ' + message.text;

    }

    client.say(env.channel, msg);
    msg += '\n';
    add_log(msg);
    console.log(message);

}

function startmeeting(from) {

    if (from !== env.admin_id) {
        return;
    }

    meeting_status = 'on';

    //start logging to file
    filename = './logs/' + moment().format('DDMMMYY') + '.txt';

    wstream = fs.createWriteStream(filename, options);

    fs.writeFile('./mod', 'on', 'ascii', function (err) {
        //if error retry startmeeting
        if (err) {
            startmeeting(from);
        } else {

            meeting_time = moment().format('hh:mm A');
            meeting_date = moment().format('DD MMM YY');
            meeting_link ='https://kerala.etherpad-mozilla.org/' + moment().format('DDMMMYY');

            var meeting_msg = strformat("A Meeting was just started by admin at %time% on %date%\n\nThe agenda of the meeting is at %datelink%\n\nYou better be civil from now onwards because I'm logging everything you say.\n\nI'll tell you where to find the log after the meeting ends.", {
                time:meeting_time ,
                date: meeting_date,
                datelink:meeting_link
            });

            bot.sendMessage({
                chat_id: env.tg_chatId,
                text: meeting_msg
            })

            send({from:{first_name:'Admin'},text:meeting_msg});

        }
    });

}

function stopmeeting(from) {

    if (from !== env.admin_id) {
        return;
    }

    meeting_status = 'off';

    //write status to mod file
    fs.writeFile('./mod', 'off', 'ascii', function (err) {
        //if error retry stopmeeting
        if (err) {
            startmeeting(from);
        } else {

                        var meeting_msg = strformat("The meeting that Admin started and chaired from %time% %date% has ended.\nYou can find the public logs of the meeting at %loglink%", {
                time:meeting_time ,
                date: meeting_date,
                loglink:meeting_logs
            });

            send({from:{first_name:'Admin'},text:meeting_msg});

            bot.sendMessage({
                chat_id: env.tg_chatId,
                text: meeting_msg
            })

            //stop logging to file
            wstream.end();
        }
    });
}

function send_status() {
    bot.sendMessage({
        chat_id: env.tg_chatId,
        parse_mode: 'Markdown',
        text: 'Meeting mode *' + meeting_status.toUpperCase() + '*'
    })
}

function add_log(msg) {

    wstream.write(msg);

}

function strformat(str, obj) {

    for (key in obj) {

        str = str.replace(new RegExp('%' + key + '%', 'g'), obj[key]);

    }

    return str;
}
<|endoftext|>


<commit_before>exports.filter = function (server, session, callback) {
	var orbisScriptVariable = {};

	var orbisAttr = function (data) {
		data = data.replace(/\n/g, '');
		data = data.replace(//gim, '');

		var re = /orbis-attr="(.*?)"/gim;
		var finded = re.exec(data);
		if (finded == null) {
			callback(200, data);
			return;
		}

		data = data.replace(finded[0], orbisScriptVariable.attr[finded[1]] == null ? '' : orbisScriptVariable.attr[finded[1]]);
		orbisAttr(data);
	}

	var orbisScript = function (data, script) {
		data = data.replace(/\n/g, '');
		data = data.replace(//gim, '');

		var re = /');
				orbisTag(data);
			});
		} else if (role == 'auth') {
			global.module.filter.orbis.auth.parse(server, session, finded[0], function (auth, result) {
				if (auth == false) data = data.replace(/<body.*?<\/?body>/gim, '' + result + '');
				else data = data.replace(finded[0], result);
				orbisTag(data);
			});
		} else if (role == 'template') {
			global.module.filter.orbis.template.parse(server, session, finded[0], function (result) {
				data = data.replace(finded[0], result);
				orbisTag(data);
			});
		} else if (role == 'query') {
			global.module.filter.orbis.query.parse(server, session, finded[0], function (result) {
				data = data.replace(finded[0], result);
				orbisTag(data);
			});
		} else if (role == 'session') {
			global.module.filter.orbis.session.parse(server, session, finded[0], function (result) {
				data = data.replace(finded[0], result);
				orbisTag(data);
			});
		} else {
			data = data.replace(finded[0], '');
			orbisTag(data);
		}
	};

	var fs = require('fs');
	data = fs.readFileSync(server.vhost.DIR + server.path) + '';
	orbisTag(data);
}<commit_msg>0.1.8<commit_after>exports.filter = function (server, session, callback) {
	var orbisScriptVariable = {};

	var orbisAttr = function (data) {
		data = data.replace(/\n/g, '');
		data = data.replace(//gim, '');

		var re = /orbis-attr="(.*?)"/gim;
		var finded = re.exec(data);
		if (finded == null) {
			callback(200, data);
			return;
		}

		var attrs = orbisScriptVariable.attr[finded[1]];
		if (attrs == null || typeof attrs != 'object') {
			if (typeof attrs == 'string') data = data.replace(finded[0], attrs);
			else data = data.replace(finded[0], '');
		} else {
			var replacement = '';
			Object.keys(attrs).forEach(function (key) {
				if (typeof attrs[key] == 'string')
					replacement += key.replace(/"/gi, '') + '="' + attrs[key].replace(/"/gi, '') + '" ';
			});
			data = data.replace(finded[0], replacement);
		}
		orbisAttr(data);
	}

	var orbisScript = function (data, script) {
		data = data.replace(/\n/g, '');
		data = data.replace(//gim, '');

		var re = /');
				orbisTag(data);
			});
		} else if (role == 'auth') {
			global.module.filter.orbis.auth.parse(server, session, finded[0], function (auth, result) {
				if (auth == false) data = data.replace(/<body.*?<\/?body>/gim, '' + result + '');
				else data = data.replace(finded[0], result);
				orbisTag(data);
			});
		} else if (role == 'template') {
			global.module.filter.orbis.template.parse(server, session, finded[0], function (result) {
				data = data.replace(finded[0], result);
				orbisTag(data);
			});
		} else if (role == 'query') {
			global.module.filter.orbis.query.parse(server, session, finded[0], function (result) {
				data = data.replace(finded[0], result);
				orbisTag(data);
			});
		} else if (role == 'session') {
			global.module.filter.orbis.session.parse(server, session, finded[0], function (result) {
				data = data.replace(finded[0], result);
				orbisTag(data);
			});
		} else {
			data = data.replace(finded[0], '');
			orbisTag(data);
		}
	};

	var fs = require('fs');
	data = fs.readFileSync(server.vhost.DIR + server.path) + '';
	orbisTag(data);
}<|endoftext|>


<commit_before>var restring = require('restring'),
    jsonify = require('jsonify'),
    http = require('http'),
    incrementalEval = require('incremental-eval'),
    liveRequire = require('live-require'),
    CodeMirror = require('codemirror');

// load JS support for CodeMirror
require('./js/javascript')(CodeMirror);

function xhr(opts, callback) {
    var o = '';
    http.get(opts, function(res) {
        res.on('data', function(buf) { o += buf; })
            .on('end', function(buf) { callback(o); });
    });
}

function mistakes(__div, clientId) {
    var __s = {}, authCode;
    function __runCodes() {
        var __r = incrementalEval(__editor.getValue(), {
                require: function(x) {
                    return liveRequire(x, __runCodes);
                }
            }),
            __res = '';
        for (var __i = 0; __i < __r.length; __i++) {
            if (__r[__i] !== undefined &&
                !(__r[__i] instanceof SyntaxError)) {
                __res += restring(__r[__i]) + '\n';
            } else {
                __res += '\n';
            }
        }
        __result.setValue(__res);
    }

    function __saveAsGist(editor) {
        var content = editor.getValue(),
            h = new window.XMLHttpRequest();

        document.body.className = 'loading';

        h.onload = function() {
            document.body.className = '';
            var d = (JSON.parse(h.responseText));
            window.location.hash = '#' + d.id;
        };

        h.onerror = function() {
            document.body.className = '';
            document.getElementById('save-button').innerHTML = 'gist could not be saved';
            window.setTimeout(function() {
                document.getElementById('save-button').innerHTML = 's';
            }, 2000);
        };

        if (location.hash && localStorage.github_token) {
            h.open('PATCH', 'https://api.github.com/gists/' + location.hash.replace('#', ''), true);
        } else {
            h.open('POST', 'https://api.github.com/gists', true);
        }
        __setAuthorizationHeader(h);
        h.send(JSON.stringify({
            description: "Gist from mistakes.io",
            public: true,
            files: {
                "index.js": {
                    content: content
                }
            }
        }));
    }

    document.getElementById('save-button').onclick = function() {
        __saveAsGist(__editor);
        return false;
    };

    var __loginButton = document.getElementById('login-button');

    function __setClientId(_) {
        __loginButton.setAttribute('href',
            'https://github.com/login/oauth/authorize?client_id=' + _ + '&scope=gist');
    }

    function __setAuthorizationHeader(h) {
        if (localStorage.github_token) {
            h.setRequestHeader('Authorization', 'token ' + localStorage.github_token);
        }
    }

    function __authHeaders() {
        return localStorage.github_token ? {
            Authorization: 'token ' + localStorage.github_token
        } : {};
    }

    function __setAuthCode(_, gatekeeper) {
        xhr({
            host: gatekeeper,
            path: '/authenticate/' + _,
            port: 80
        }, function(res) {
            try {
                var data = JSON.parse(res);
                localStorage.github_token = data.token;
                __confirmToken(true);
            } catch(e) {
                localStorage.github_token = undefined;
                killToken();
            }
        });
    }

    function killTokenUrl() {
        if (location.href.indexOf('?code') !== -1) location.href = location.href.replace(/\?code=.*$/, '');
    }

    function __confirmToken(first) {
        if (!localStorage.github_token) return;
        xhr({ path: '/user?access_token=' + localStorage.github_token,
            host: 'api.github.com',
            port: 443,
            scheme: 'https'
        }, function(res) {
            try {
                var user = JSON.parse(res);
                if (!user.name) throw new Error('no name');
                __loginButton.innerHTML = 'logout (' + user.login + ')';
                __loginButton.onclick = function() {
                    localStorage.removeItem('github_token');
                    killTokenUrl();
                    return false;
                };
                if (first) killTokenUrl();
            } catch(e) {
                localStorage.removeItem('github_token');
                if (first) killTokenUrl();
            }
        });
    }

    function __showGistButton(id) {
        var button = document.getElementById('gist-button');
        button.style.display = 'inline';
        button.href = 'http://gist.github.com/' + id;
    }

    function __showIframeButton(id) {
        var button = document.getElementById('iframe-button');
        button.style.display = 'inline';
        button.href = window.location;
    }

    function __gist(id) {
        // Ignore files that are clearly not javascript files.
        //
        // * Have an extension and it is not .txt or .js
        // * Say 'readme'
        function isjs(x) {
            if (x.match(/readme/gi)) return false;
            var n = x.split('.'),
                ext = n[n.length - 1];
            if (n.length > 1 && ext !== 'js' && ext !== 'txt') return false;
            return true;
        }
        if (id.indexOf('.js') !== -1) {
            xhr({ path: '/local/' + id }, function (res) {
                return __content(res);
            });
        } else {
            document.body.className = 'loading';
            xhr({ path: '/gists/' + id,
                host: 'api.github.com',
                port: 443,
                scheme: 'https'
            }, function(res) {
                document.body.className = '';
                __showGistButton(id);
                var r = jsonify.parse(res);
                for (var k in r.files) {
                    if (isjs(k)) return __content(r.files[k].content);
                }
            });
        }
    }

    function __content(x) {
        if (arguments.length) {
            __editor.setValue(x);
            return __s;
        } else {
            return __editor.getValue();
        }
    }

    var __left = __div.appendChild(document.createElement('div')),
        __right = __div.appendChild(document.createElement('div')),
        __code = __left.appendChild(document.createElement('textarea')),
        __results = __right.appendChild(document.createElement('textarea'));

    __left.className = 'left';
    __right.className = 'right';
    __code.className = 'code';
    __results.className = 'results';

    if (window !== window.top) __showIframeButton();

    CodeMirror.keyMap.tabSpace = {
        Tab: function(cm) {
            var spaces = Array(cm.getOption('indentUnit') + 1).join(' ');
            cm.replaceSelection(spaces, 'end', '+input');
        },
        fallthrough: ['default']
    };

    var __editor = CodeMirror.fromTextArea(__code, {
        mode: 'javascript',
        matchBrackets: true,
        tabSize: 2,
        autofocus: (window === window.top),
        extraKeys: {
            'Ctrl-S': __saveAsGist,
            'Cmd-S': __saveAsGist
        },
        keyMap: 'tabSpace',
        smartIndent: true
    });

    __editor.on('change', __runCodes);

    var __result = CodeMirror.fromTextArea(__results, {
        mode: 'javascript',
        tabSize: 2,
        readOnly: true
    });

    __editor.setOption("theme", 'mistakes');
    __result.setOption("theme", 'mistakes');

    __s.gist = __gist;
    __s.content = __content;
    __s.clientId = __setClientId;
    __s.authCode = __setAuthCode;

    __confirmToken();

    return __s;
}

module.exports = mistakes;
<commit_msg>Fix mistype<commit_after>var restring = require('restring'),
    jsonify = require('jsonify'),
    http = require('http'),
    incrementalEval = require('incremental-eval'),
    liveRequire = require('live-require'),
    CodeMirror = require('codemirror');

// load JS support for CodeMirror
require('./js/javascript')(CodeMirror);

function xhr(opts, callback) {
    var o = '';
    http.get(opts, function(res) {
        res.on('data', function(buf) { o += buf; })
            .on('end', function(buf) { callback(o); });
    });
}

function mistakes(__div, clientId) {
    var __s = {}, authCode;
    function __runCodes() {
        var __r = incrementalEval(__editor.getValue(), {
                require: function(x) {
                    return liveRequire(x, __runCodes);
                }
            }),
            __res = '';
        for (var __i = 0; __i < __r.length; __i++) {
            if (__r[__i] !== undefined &&
                !(__r[__i] instanceof SyntaxError)) {
                __res += restring(__r[__i]) + '\n';
            } else {
                __res += '\n';
            }
        }
        __result.setValue(__res);
    }

    function __saveAsGist(editor) {
        var content = editor.getValue(),
            h = new window.XMLHttpRequest();

        document.body.className = 'loading';

        h.onload = function() {
            document.body.className = '';
            var d = (JSON.parse(h.responseText));
            window.location.hash = '#' + d.id;
        };

        h.onerror = function() {
            document.body.className = '';
            document.getElementById('save-button').innerHTML = 'gist could not be saved';
            window.setTimeout(function() {
                document.getElementById('save-button').innerHTML = 's';
            }, 2000);
        };

        if (location.hash && localStorage.github_token) {
            h.open('PATCH', 'https://api.github.com/gists/' + location.hash.replace('#', ''), true);
        } else {
            h.open('POST', 'https://api.github.com/gists', true);
        }
        __setAuthorizationHeader(h);
        h.send(JSON.stringify({
            description: "Gist from mistakes.io",
            public: true,
            files: {
                "index.js": {
                    content: content
                }
            }
        }));
    }

    document.getElementById('save-button').onclick = function() {
        __saveAsGist(__editor);
        return false;
    };

    var __loginButton = document.getElementById('login-button');

    function __setClientId(_) {
        __loginButton.setAttribute('href',
            'https://github.com/login/oauth/authorize?client_id=' + _ + '&scope=gist');
    }

    function __setAuthorizationHeader(h) {
        if (localStorage.github_token) {
            h.setRequestHeader('Authorization', 'token ' + localStorage.github_token);
        }
    }

    function __authHeaders() {
        return localStorage.github_token ? {
            Authorization: 'token ' + localStorage.github_token
        } : {};
    }

    function __setAuthCode(_, gatekeeper) {
        xhr({
            host: gatekeeper,
            path: '/authenticate/' + _,
            port: 80
        }, function(res) {
            try {
                var data = JSON.parse(res);
                localStorage.github_token = data.token;
                __confirmToken(true);
            } catch(e) {
                localStorage.github_token = undefined;
                killTokenUrl();
            }
        });
    }

    function killTokenUrl() {
        if (location.href.indexOf('?code') !== -1) location.href = location.href.replace(/\?code=.*$/, '');
    }

    function __confirmToken(first) {
        if (!localStorage.github_token) return;
        xhr({ path: '/user?access_token=' + localStorage.github_token,
            host: 'api.github.com',
            port: 443,
            scheme: 'https'
        }, function(res) {
            try {
                var user = JSON.parse(res);
                if (!user.name) throw new Error('no name');
                __loginButton.innerHTML = 'logout (' + user.login + ')';
                __loginButton.onclick = function() {
                    localStorage.removeItem('github_token');
                    killTokenUrl();
                    return false;
                };
                if (first) killTokenUrl();
            } catch(e) {
                localStorage.removeItem('github_token');
                if (first) killTokenUrl();
            }
        });
    }

    function __showGistButton(id) {
        var button = document.getElementById('gist-button');
        button.style.display = 'inline';
        button.href = 'http://gist.github.com/' + id;
    }

    function __showIframeButton(id) {
        var button = document.getElementById('iframe-button');
        button.style.display = 'inline';
        button.href = window.location;
    }

    function __gist(id) {
        // Ignore files that are clearly not javascript files.
        //
        // * Have an extension and it is not .txt or .js
        // * Say 'readme'
        function isjs(x) {
            if (x.match(/readme/gi)) return false;
            var n = x.split('.'),
                ext = n[n.length - 1];
            if (n.length > 1 && ext !== 'js' && ext !== 'txt') return false;
            return true;
        }
        if (id.indexOf('.js') !== -1) {
            xhr({ path: '/local/' + id }, function (res) {
                return __content(res);
            });
        } else {
            document.body.className = 'loading';
            xhr({ path: '/gists/' + id,
                host: 'api.github.com',
                port: 443,
                scheme: 'https'
            }, function(res) {
                document.body.className = '';
                __showGistButton(id);
                var r = jsonify.parse(res);
                for (var k in r.files) {
                    if (isjs(k)) return __content(r.files[k].content);
                }
            });
        }
    }

    function __content(x) {
        if (arguments.length) {
            __editor.setValue(x);
            return __s;
        } else {
            return __editor.getValue();
        }
    }

    var __left = __div.appendChild(document.createElement('div')),
        __right = __div.appendChild(document.createElement('div')),
        __code = __left.appendChild(document.createElement('textarea')),
        __results = __right.appendChild(document.createElement('textarea'));

    __left.className = 'left';
    __right.className = 'right';
    __code.className = 'code';
    __results.className = 'results';

    if (window !== window.top) __showIframeButton();

    CodeMirror.keyMap.tabSpace = {
        Tab: function(cm) {
            var spaces = Array(cm.getOption('indentUnit') + 1).join(' ');
            cm.replaceSelection(spaces, 'end', '+input');
        },
        fallthrough: ['default']
    };

    var __editor = CodeMirror.fromTextArea(__code, {
        mode: 'javascript',
        matchBrackets: true,
        tabSize: 2,
        autofocus: (window === window.top),
        extraKeys: {
            'Ctrl-S': __saveAsGist,
            'Cmd-S': __saveAsGist
        },
        keyMap: 'tabSpace',
        smartIndent: true
    });

    __editor.on('change', __runCodes);

    var __result = CodeMirror.fromTextArea(__results, {
        mode: 'javascript',
        tabSize: 2,
        readOnly: true
    });

    __editor.setOption("theme", 'mistakes');
    __result.setOption("theme", 'mistakes');

    __s.gist = __gist;
    __s.content = __content;
    __s.clientId = __setClientId;
    __s.authCode = __setAuthCode;

    __confirmToken();

    return __s;
}

module.exports = mistakes;
<|endoftext|>