<commit_before>function (user, context, callback) {
  var namespace = 'https://sso.mozilla.com/claim/';
  var whitelist = ['']; // claim whitelist
  let isSetsEqual = (a, b) => a.size === b.size && [...a].every(value => b.has(value));

  // If you're not OIDC Conformant, stop right there as this INCREASES the profile size
  // significantly! The metadata is set by us, manually.

  if (!context.clientMetadata || !context.clientMetadata.oidc_conformant || context.clientMetadata.oidc_conformant !== 'true') {
    console.log('Client '+context.clientID+' is not OIDC conformant yet, please fix!');
    // Bare minimum conversion to help migrating clients to OIDC conformant
    //context.idToken = context.idToken || {};
    //context.idToken[namespace+'groups'] = user.groups;
    return callback(null, user, context);
  }

  // If the only scopes requested are openid or email, do not overload with custom claims
  let scopes = new Set(context.request.query.scope.split(' '));
  let whitelisted_scopes = new Set(["openid", "email"]);
  if (isSetsEqual(scopes, whitelisted_scopes)) {
    console.log('Client '+context.clientID+' only requested scope:openid or scope:email, not adding custom claims');
    return callback(null, user, context);
  }

  // CIS is our only functionality that can set app_metadata
  // Auth0 auto-integrate user.app_metadata.* into user.*
  // This rule cleans up the left overs for conciseness, clarity and size
  // (in particular this affects the id_token size, that goes onto GET queries
  // which are limited to 8k-if-not-less depending on the httpd server
  // settings)
  // Additional integration into user.app_metadata itself is at:
  // https://github.com/mozilla-iam/cis_functions/tree/master/functions/idvtoauth0

  // Fixup claims to be namespaced, for compat
  // Auth0 in the "OIDC-Conformant" mode will only allow these claims. That mode
  // enforces more than the OIDC spec in at least one regard:
  // Auth0 forbids the use of optional claims UNLESS these are namespaced by a URL.
  // See also https://auth0.com/docs/api-auth/tutorials/adoption/scope-custom-claims

  // These claims can be used directly and/or are preserved if integrated by Auth0
  // See also: https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
  var std_oidc_claims = [
    "sub",
    "name",
    "given_name",
    "family_name",
    "middle_name",
    "nickname",
    "preferred_username",
    "profile",
    "picture",
    "website",
    "email",
    "email_verified",
    "gender",
    "birthdate",
    "zoneinfo",
    "locale",
    "phone_number",
    "phone_number_verified",
    "address",
    "updated_at"
    ];

  // These are the claims Auth0 used to provide, plus some of ours
  var old_authzero_claims = [
    "groups",
    // We don't pass these to reduce the profile size. use the CIS claim instead, or the CIS API
    //"emails",
    //"dn",
    //"organizationUnits",
    //"email_aliases",
    //"_HRData",
    // This is "sub"
    // "user_id"
    // We don't use these anyway:
    //"identities"
    //"multifactor"
    //"clientID"
    //"created_at"
  ];

  // XXX This code is no longer required once we get an LDAP identity driver
  // It reintegrates LDAP groups into the user's app_metadata/profile
  if (user.app_metadata !== undefined && user.app_metadata.length > 0) {

    // Force re-integrate LDAP groups until we have a LDAP CIS publisher
    // See https://github.com/mozilla-iam/cis_functions/blob/master/functions/idvtoauth0/main.py#L87
    // which this very code below supersedes as idvauth0 code only gets triggered if a profile is being actively published
    var index = 0;
    var userApiUrl = auth0.baseUrl + '/users/';
    var ugroups = user.app_metadata.groups;

    request({
      url: userApiUrl+user.user_id,
      headers: {
        Authorization: 'Bearer ' + auth0.accessToken
      },
    },
    function(err, response, body) {
      if (!err) {
        var udata = JSON.parse(body);
        // If user has no LDAP groups, return immediately
        udata.groups = udata.groups || [];
        if (udata.groups.length === 0) {
          return cb();
        }

        // Add non-LDAP groups to new_groups
        var new_groups = [];

        for (index = 0; index < ugroups.length; ++index) {
          var cur_grp = ugroups[index];
          if (cur_grp === null) {
            console.log("CIS: Group data contained null entries in array, that's not normal");
            continue;
          }
          // Don't remove non-LDAP groups
          if (cur_grp.substr(0,14) === 'mozilliansorg_') {
            new_groups.push(cur_grp);
          } else if (cur_grp.substr(0,5) === 'hris_') {
            new_groups.push(cur_grp);
          }
        }

        // Re-add groups that are in LDAP (ie udata.groups)
        for (index = 0; index < udata.groups.length; ++index) {
            new_groups.push(udata.groups[index]);
        }
        return cb(new_groups);
      } else {
        console.log('CIS: Error while parsing user groups for user '+user.user_id+': '+err);
        return cb();
      }
      console.log('CIS: HTTP Error while parsing user groups for user '+user.user_id+': '+err);
      return cb();
    });
  } else {
    return cb();
  }

  // Ensure this is always called or the webtask will timeout
  function cb(new_groups) {
    user.app_metadata = user.app_metadata || {};
    if (new_groups !== undefined) {
      user.groups = new_groups;
      user.app_metadata.groups = new_groups;
      // Save app_metadata changes
      auth0.users.updateAppMetadata(user.user_id, user.app_metadata)
        .catch(function(err){
          console.log('CIS: Error updating app_metadata (groups) for user '+user.user_id+': '+err);
      });
    }
    // XXX NOTE WARNING XXX
    // Do NOT enable this as this will inflate the id_token
    // This feature may only be used for specific scope or endpoints, whenever auth0 let us do that
    // Import entire CIS profile to a namespaced claim
    //context.idToken[namespace+'cis'] = user.app_metadata;

    // Reduce profile size further
    // Note: do not wipe user.app_metadata as auth0 now re-overlays it in memory
//    user.app_metadata = undefined;
    user.email_aliases = undefined;
    user.dn = undefined;
    user.organizationUnits = undefined;

    // Re-map old and new profile claims to namespaced claims
    // Basically that's `groups`
    old_authzero_claims.forEach(function(claim) {
      try {
        if (whitelist.indexOf(context.clientID) < 0) {
          context.idToken[namespace+claim] = user[claim];
        }
      } catch (e) {
        console.log("Undefined claim (non-fatal): "+e);
      }
    });

    // AAI & AAL values
    user.aai = user.aai || [];
    context.idToken[namespace+'AAI'] = user.aai;
    user.aal = user.aal || "UNKNOWN";
    context.idToken[namespace+'AAL'] = user.aal;

/* WARNING  this entire block can be removed when mozillians.org / DinoPark uses it's own verification method for
 * accounts */
/* START removable block */
    var WHITELIST = ['HvN5D3R64YNNhvcHKuMKny1O0KJZOOwH', // mozillians.org account verification
                   't9bMi4eTCPpMp5Y6E1Lu92iVcqU0r1P1', // https://web-mozillians-staging.production.paas.mozilla.community Verification client
                   'jijaIzcZmFCDRtV74scMb9lI87MtYNTA', // mozillians.org Verification Client
                ];
    if (WHITELIST.indexOf(context.clientID) >= 0) {
      // Original connection method's user_id (useful when the account is a linked account, this lets you know what the actual IdP
      // was used to login
      // Default to current user_id
      var originalConnection_user_id = user.user_id;
      var targetIdentity;
      // If we have linked account, check if we have a better match
      if (user.identities && user.identities.length > 1) {
        for (var i = 0; i < user.identities.length; i++) {
          targetIdentity = user.identities[i];
          // Find the identity which corresponding to the user logging in
          if ((targetIdentity.connection === context.connection) && (targetIdentity.provider === context.connectionStrategy)) {
            // If what we find has no `profileData` structure it means the user_id is the same as the one currently
            // logging in, so we don't need to do anything.
            // If it is, then we need to reconstruct a user_id from the identity data
            if (targetIdentity.profileData !== undefined) {
              originalConnection_user_id = targetIdentity.provider + '|' + targetIdentity.user_id;
            }
            break;
          }
        }
      }
      context.idToken[namespace+'original_connection_user_id'] = originalConnection_user_id;
    }
/* END of removable block */

    // Give info about CIS API
    context.idToken[namespace+'README_FIRST'] = 'Please refer to https://github.com/mozilla-iam/person-api in order to query Mozilla IAM CIS user profile data';
    return callback(null, user, context);
  }
}
<commit_msg>Fix scope comparison logic<commit_after>function (user, context, callback) {
  var _ = require('lodash');
  var namespace = 'https://sso.mozilla.com/claim/';
  var whitelist = ['']; // claim whitelist

  // If you're not OIDC Conformant, stop right there as this INCREASES the profile size
  // significantly! The metadata is set by us, manually.

  if (!context.clientMetadata || !context.clientMetadata.oidc_conformant || context.clientMetadata.oidc_conformant !== 'true') {
    console.log('Client '+context.clientID+' is not OIDC conformant yet, please fix!');
    // Bare minimum conversion to help migrating clients to OIDC conformant
    //context.idToken = context.idToken || {};
    //context.idToken[namespace+'groups'] = user.groups;
    return callback(null, user, context);
  }

  // If the only scopes requested are openid or email, do not overload with custom claims
  let scopes_requested = context.request.query.scope.split(' ');
  let fixup_scopes = _.difference(scopes_requested, ['openid', 'email']);
  if (fixup_scopes.length > 0) {
    console.log('Client '+context.clientID+' only requested '+scopes_requested+', not adding custom claims');
    return callback(null, user, context);
  }

  // CIS is our only functionality that can set app_metadata
  // Auth0 auto-integrate user.app_metadata.* into user.*
  // This rule cleans up the left overs for conciseness, clarity and size
  // (in particular this affects the id_token size, that goes onto GET queries
  // which are limited to 8k-if-not-less depending on the httpd server
  // settings)
  // Additional integration into user.app_metadata itself is at:
  // https://github.com/mozilla-iam/cis_functions/tree/master/functions/idvtoauth0

  // Fixup claims to be namespaced, for compat
  // Auth0 in the "OIDC-Conformant" mode will only allow these claims. That mode
  // enforces more than the OIDC spec in at least one regard:
  // Auth0 forbids the use of optional claims UNLESS these are namespaced by a URL.
  // See also https://auth0.com/docs/api-auth/tutorials/adoption/scope-custom-claims

  // These claims can be used directly and/or are preserved if integrated by Auth0
  // See also: https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
  var std_oidc_claims = [
    "sub",
    "name",
    "given_name",
    "family_name",
    "middle_name",
    "nickname",
    "preferred_username",
    "profile",
    "picture",
    "website",
    "email",
    "email_verified",
    "gender",
    "birthdate",
    "zoneinfo",
    "locale",
    "phone_number",
    "phone_number_verified",
    "address",
    "updated_at"
    ];

  // These are the claims Auth0 used to provide, plus some of ours
  var old_authzero_claims = [
    "groups",
    // We don't pass these to reduce the profile size. use the CIS claim instead, or the CIS API
    //"emails",
    //"dn",
    //"organizationUnits",
    //"email_aliases",
    //"_HRData",
    // This is "sub"
    // "user_id"
    // We don't use these anyway:
    //"identities"
    //"multifactor"
    //"clientID"
    //"created_at"
  ];

  // XXX This code is no longer required once we get an LDAP identity driver
  // It reintegrates LDAP groups into the user's app_metadata/profile
  if (user.app_metadata !== undefined && user.app_metadata.length > 0) {

    // Force re-integrate LDAP groups until we have a LDAP CIS publisher
    // See https://github.com/mozilla-iam/cis_functions/blob/master/functions/idvtoauth0/main.py#L87
    // which this very code below supersedes as idvauth0 code only gets triggered if a profile is being actively published
    var index = 0;
    var userApiUrl = auth0.baseUrl + '/users/';
    var ugroups = user.app_metadata.groups;

    request({
      url: userApiUrl+user.user_id,
      headers: {
        Authorization: 'Bearer ' + auth0.accessToken
      },
    },
    function(err, response, body) {
      if (!err) {
        var udata = JSON.parse(body);
        // If user has no LDAP groups, return immediately
        udata.groups = udata.groups || [];
        if (udata.groups.length === 0) {
          return cb();
        }

        // Add non-LDAP groups to new_groups
        var new_groups = [];

        for (index = 0; index < ugroups.length; ++index) {
          var cur_grp = ugroups[index];
          if (cur_grp === null) {
            console.log("CIS: Group data contained null entries in array, that's not normal");
            continue;
          }
          // Don't remove non-LDAP groups
          if (cur_grp.substr(0,14) === 'mozilliansorg_') {
            new_groups.push(cur_grp);
          } else if (cur_grp.substr(0,5) === 'hris_') {
            new_groups.push(cur_grp);
          }
        }

        // Re-add groups that are in LDAP (ie udata.groups)
        for (index = 0; index < udata.groups.length; ++index) {
            new_groups.push(udata.groups[index]);
        }
        return cb(new_groups);
      } else {
        console.log('CIS: Error while parsing user groups for user '+user.user_id+': '+err);
        return cb();
      }
      console.log('CIS: HTTP Error while parsing user groups for user '+user.user_id+': '+err);
      return cb();
    });
  } else {
    return cb();
  }

  // Ensure this is always called or the webtask will timeout
  function cb(new_groups) {
    user.app_metadata = user.app_metadata || {};
    if (new_groups !== undefined) {
      user.groups = new_groups;
      user.app_metadata.groups = new_groups;
      // Save app_metadata changes
      auth0.users.updateAppMetadata(user.user_id, user.app_metadata)
        .catch(function(err){
          console.log('CIS: Error updating app_metadata (groups) for user '+user.user_id+': '+err);
      });
    }
    // XXX NOTE WARNING XXX
    // Do NOT enable this as this will inflate the id_token
    // This feature may only be used for specific scope or endpoints, whenever auth0 let us do that
    // Import entire CIS profile to a namespaced claim
    //context.idToken[namespace+'cis'] = user.app_metadata;

    // Reduce profile size further
    // Note: do not wipe user.app_metadata as auth0 now re-overlays it in memory
//    user.app_metadata = undefined;
    user.email_aliases = undefined;
    user.dn = undefined;
    user.organizationUnits = undefined;

    // Re-map old and new profile claims to namespaced claims
    // Basically that's `groups`
    old_authzero_claims.forEach(function(claim) {
      try {
        if (whitelist.indexOf(context.clientID) < 0) {
          context.idToken[namespace+claim] = user[claim];
        }
      } catch (e) {
        console.log("Undefined claim (non-fatal): "+e);
      }
    });

    // AAI & AAL values
    user.aai = user.aai || [];
    context.idToken[namespace+'AAI'] = user.aai;
    user.aal = user.aal || "UNKNOWN";
    context.idToken[namespace+'AAL'] = user.aal;

/* WARNING  this entire block can be removed when mozillians.org / DinoPark uses it's own verification method for
 * accounts */
/* START removable block */
    var WHITELIST = ['HvN5D3R64YNNhvcHKuMKny1O0KJZOOwH', // mozillians.org account verification
                   't9bMi4eTCPpMp5Y6E1Lu92iVcqU0r1P1', // https://web-mozillians-staging.production.paas.mozilla.community Verification client
                   'jijaIzcZmFCDRtV74scMb9lI87MtYNTA', // mozillians.org Verification Client
                ];
    if (WHITELIST.indexOf(context.clientID) >= 0) {
      // Original connection method's user_id (useful when the account is a linked account, this lets you know what the actual IdP
      // was used to login
      // Default to current user_id
      var originalConnection_user_id = user.user_id;
      var targetIdentity;
      // If we have linked account, check if we have a better match
      if (user.identities && user.identities.length > 1) {
        for (var i = 0; i < user.identities.length; i++) {
          targetIdentity = user.identities[i];
          // Find the identity which corresponding to the user logging in
          if ((targetIdentity.connection === context.connection) && (targetIdentity.provider === context.connectionStrategy)) {
            // If what we find has no `profileData` structure it means the user_id is the same as the one currently
            // logging in, so we don't need to do anything.
            // If it is, then we need to reconstruct a user_id from the identity data
            if (targetIdentity.profileData !== undefined) {
              originalConnection_user_id = targetIdentity.provider + '|' + targetIdentity.user_id;
            }
            break;
          }
        }
      }
      context.idToken[namespace+'original_connection_user_id'] = originalConnection_user_id;
    }
/* END of removable block */

    // Give info about CIS API
    context.idToken[namespace+'README_FIRST'] = 'Please refer to https://github.com/mozilla-iam/person-api in order to query Mozilla IAM CIS user profile data';
    return callback(null, user, context);
  }
}
<|endoftext|>


<commit_before>import { logger } from 'appium-support';
const log = logger.getLogger('UniversalXMLPlugin');
export default log;
<commit_msg>fix(universal-xml-plugin): fix ref to appium-support<commit_after>import { logger } from '@appium/support';
const log = logger.getLogger('UniversalXMLPlugin');
export default log;
<|endoftext|>


<commit_before>/*
       Licensed to the Apache Software Foundation (ASF) under one
       or more contributor license agreements.  See the NOTICE file
       distributed with this work for additional information
       regarding copyright ownership.  The ASF licenses this file
       to you under the Apache License, Version 2.0 (the
       "License"); you may not use this file except in compliance
       with the License.  You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

       Unless required by applicable law or agreed to in writing,
       software distributed under the License is distributed on an
       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
       KIND, either express or implied.  See the License for the
       specific language governing permissions and limitations
       under the License.
*/
/* eslint no-self-assign: 0 */
/* eslint no-unused-vars: 0 */

var Q = require('q');
var fs = require('fs');
var path = require('path');
var shell = require('shelljs');
var events = require('cordova-common').events;
var CordovaError = require('cordova-common').CordovaError;

function GenericBuilder (projectDir) {
    this.root = projectDir || path.resolve(__dirname, '../../..');
    this.binDirs = {
        ant: path.join(this.root, hasCustomRules(this.root) ? 'ant-build' : 'bin'),
        gradle: path.join(this.root, 'build', 'outputs', 'apk')
    };
}

function hasCustomRules (projectRoot) {
    return fs.existsSync(path.join(projectRoot, 'custom_rules.xml'));
}

GenericBuilder.prototype.prepEnv = function () {
    return Q();
};

GenericBuilder.prototype.build = function () {
    events.emit('log', 'Skipping build...');
    return Q(null);
};

GenericBuilder.prototype.clean = function () {
    return Q();
};

GenericBuilder.prototype.findOutputApks = function (build_type, arch) {
    var self = this;
    return Object.keys(this.binDirs).reduce(function (result, builderName) {
        var binDir = self.binDirs[builderName];
        return result.concat(findOutputApksHelper(binDir, build_type, builderName === 'ant' ? null : arch));
    }, []).sort(apkSorter);
};

GenericBuilder.prototype.readProjectProperties = function () {
    function findAllUniq (data, r) {
        var s = {};
        var m;
        while ((m = r.exec(data))) {
            s[m[1]] = 1;
        }
        return Object.keys(s);
    }

    var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
    return {
        libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
        gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
        systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
    };
};

GenericBuilder.prototype.extractRealProjectNameFromManifest = function () {
    var manifestPath = path.join(this.root, 'AndroidManifest.xml');
    var manifestData = fs.readFileSync(manifestPath, 'utf8');
    var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
    if (!m) {
        throw new CordovaError('Could not find package name in ' + manifestPath);
    }

    var packageName = m[1];
    var lastDotIndex = packageName.lastIndexOf('.');
    return packageName.substring(lastDotIndex + 1);
};

module.exports = GenericBuilder;

function apkSorter (fileA, fileB) {
    // De-prioritize unsigned builds
    var unsignedRE = /-unsigned/;
    if (unsignedRE.exec(fileA)) {
        return 1;
    } else if (unsignedRE.exec(fileB)) {
        return -1;
    }

    var timeDiff = fs.statSync(fileA).mtime - fs.statSync(fileB).mtime;
    return timeDiff === 0 ? fileA.length - fileB.length : timeDiff;
}

function findOutputApksHelper (dir, build_type, arch) {
    console.log("Directory: " + dir);
    console.log("Build Type: " + build_type);
    console.log("Arch: " + arch);

    var shellSilent = shell.config.silent;
    shell.config.silent = true;

    var ret = shell.ls(path.join(dir, build_type, '*.apk')).filter(function (candidate) {
        var apkName = path.basename(candidate);
        // Need to choose between release and debug .apk.
        if (build_type === 'debug') {
            return /-debug/.exec(apkName) && !/-unaligned|-unsigned/.exec(apkName);
        }
        if (build_type === 'release') {
            return /-release/.exec(apkName) && !/-unaligned/.exec(apkName);
        }
        return true;
    }).sort(apkSorter);

    shellSilent = shellSilent;

    if (ret.length === 0) {
        return ret;
    }
    // Assume arch-specific build if newest apk has -x86 or -arm.
    var archSpecific = !!/-x86|-arm/.exec(path.basename(ret[0]));
    // And show only arch-specific ones (or non-arch-specific)
    ret = ret.filter(function (p) {
        /* jshint -W018 */
        return !!/-x86|-arm/.exec(path.basename(p)) === archSpecific;
        /* jshint +W018 */
    });

    if (archSpecific && ret.length > 1 && arch) {
        ret = ret.filter(function (p) {
            return path.basename(p).indexOf('-' + arch) !== -1;
        });
    }

    return ret;
}
<commit_msg>CB-13530: Removing debug console.logs<commit_after>/*
       Licensed to the Apache Software Foundation (ASF) under one
       or more contributor license agreements.  See the NOTICE file
       distributed with this work for additional information
       regarding copyright ownership.  The ASF licenses this file
       to you under the Apache License, Version 2.0 (the
       "License"); you may not use this file except in compliance
       with the License.  You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

       Unless required by applicable law or agreed to in writing,
       software distributed under the License is distributed on an
       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
       KIND, either express or implied.  See the License for the
       specific language governing permissions and limitations
       under the License.
*/
/* eslint no-self-assign: 0 */
/* eslint no-unused-vars: 0 */

var Q = require('q');
var fs = require('fs');
var path = require('path');
var shell = require('shelljs');
var events = require('cordova-common').events;
var CordovaError = require('cordova-common').CordovaError;

function GenericBuilder (projectDir) {
    this.root = projectDir || path.resolve(__dirname, '../../..');
    this.binDirs = {
        ant: path.join(this.root, hasCustomRules(this.root) ? 'ant-build' : 'bin'),
        gradle: path.join(this.root, 'build', 'outputs', 'apk')
    };
}

function hasCustomRules (projectRoot) {
    return fs.existsSync(path.join(projectRoot, 'custom_rules.xml'));
}

GenericBuilder.prototype.prepEnv = function () {
    return Q();
};

GenericBuilder.prototype.build = function () {
    events.emit('log', 'Skipping build...');
    return Q(null);
};

GenericBuilder.prototype.clean = function () {
    return Q();
};

GenericBuilder.prototype.findOutputApks = function (build_type, arch) {
    var self = this;
    return Object.keys(this.binDirs).reduce(function (result, builderName) {
        var binDir = self.binDirs[builderName];
        return result.concat(findOutputApksHelper(binDir, build_type, builderName === 'ant' ? null : arch));
    }, []).sort(apkSorter);
};

GenericBuilder.prototype.readProjectProperties = function () {
    function findAllUniq (data, r) {
        var s = {};
        var m;
        while ((m = r.exec(data))) {
            s[m[1]] = 1;
        }
        return Object.keys(s);
    }

    var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
    return {
        libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
        gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
        systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
    };
};

GenericBuilder.prototype.extractRealProjectNameFromManifest = function () {
    var manifestPath = path.join(this.root, 'AndroidManifest.xml');
    var manifestData = fs.readFileSync(manifestPath, 'utf8');
    var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
    if (!m) {
        throw new CordovaError('Could not find package name in ' + manifestPath);
    }

    var packageName = m[1];
    var lastDotIndex = packageName.lastIndexOf('.');
    return packageName.substring(lastDotIndex + 1);
};

module.exports = GenericBuilder;

function apkSorter (fileA, fileB) {
    // De-prioritize unsigned builds
    var unsignedRE = /-unsigned/;
    if (unsignedRE.exec(fileA)) {
        return 1;
    } else if (unsignedRE.exec(fileB)) {
        return -1;
    }

    var timeDiff = fs.statSync(fileA).mtime - fs.statSync(fileB).mtime;
    return timeDiff === 0 ? fileA.length - fileB.length : timeDiff;
}

function findOutputApksHelper (dir, build_type, arch) {
    var shellSilent = shell.config.silent;
    shell.config.silent = true;

    var ret = shell.ls(path.join(dir, build_type, '*.apk')).filter(function (candidate) {
        var apkName = path.basename(candidate);
        // Need to choose between release and debug .apk.
        if (build_type === 'debug') {
            return /-debug/.exec(apkName) && !/-unaligned|-unsigned/.exec(apkName);
        }
        if (build_type === 'release') {
            return /-release/.exec(apkName) && !/-unaligned/.exec(apkName);
        }
        return true;
    }).sort(apkSorter);

    shellSilent = shellSilent;

    if (ret.length === 0) {
        return ret;
    }
    // Assume arch-specific build if newest apk has -x86 or -arm.
    var archSpecific = !!/-x86|-arm/.exec(path.basename(ret[0]));
    // And show only arch-specific ones (or non-arch-specific)
    ret = ret.filter(function (p) {
        /* jshint -W018 */
        return !!/-x86|-arm/.exec(path.basename(p)) === archSpecific;
        /* jshint +W018 */
    });

    if (archSpecific && ret.length > 1 && arch) {
        ret = ret.filter(function (p) {
            return path.basename(p).indexOf('-' + arch) !== -1;
        });
    }

    return ret;
}
<|endoftext|>


<commit_before>const feathersKnex = require('feathers-knex')
const { iff, iffElse } = require('feathers-hooks-common')
import { pipe, equals, length, isNil, isEmpty, map, any, find, not, prop } from 'ramda'
import * as taskRecipes from '../../tasks/data/recipes'

module.exports = function () {
  const app = this
  const db = app.get('db')

  const name = 'orders'
  const options = { Model: db, name }

  app.use(name, feathersKnex(options))
  app.service(name).hooks(hooks)
}

const hooks = {
  before: {
    create: [
      getCurrentUser,
      iff(hasNoGroupAgent, createGroupAgent),
      iff(hasNoSupplierAgent, createSupplierAgent),
      iff(hasNoRelation, createRelation),
      iff(groupHasNoAdminRelation, createGroupAdminRelation),
      iff(userIsNotMemberOfGroup, createGroupMemberRelation)
    ]
  },
  after: {
    create: [
      iffElse(hasNotCompletedGroupOrSupplierProfile, createCompleteOrderSetupWithPreReqsTaskPlan, createCompleteOrderSetupTaskPlan),
      // iffElse(groupHasNoAdminRelation, createCloseOrderTaskPlanToUser, createCloseOrderTaskPlanToAdmin)
    ],
    update: [
      // iff(updatedAdmin, updateCloseOrderTaskPlanAdmin)
    ]
  },
  error: {}
}

function getCurrentUser (hook) {
  const { agentId } = hook.params.credential
  const agentsService = hook.app.service('agents')
  return agentsService.get(agentId)
 .then(agent => {
   hook.params.agent = agent
 })
 .then(() => hook)
}

function userIsNotMemberOfGroup (hook) {
  const relationships = hook.app.service('relationships')
  const groupId = hook.data.consumerAgentId
  return relationships
    .find({ query: { sourceId: groupId, relationshipType: 'member' } })
    .then(isEmpty)
}

function createGroupMemberRelation (hook) {
  const relationships = hook.app.service('relationships')
  const groupId = hook.data.consumerAgentId
  const userId = hook.params.agent.id
  return relationships.create({
    relationshipType: 'member',
    sourceId: groupId,
    targetId: userId
  }).then(() => {
    return hook
  })
}

function groupHasNoAdminRelation (hook) {
  const relationships = hook.app.service('relationships')
  const groupId = hook.data.consumerAgentId
  return relationships
    .find({ query: { sourceId: groupId, relationshipType: 'admin' } })
    .then(isEmpty)
}

function createGroupAdminRelation (hook) {
  const relationships = hook.app.service('relationships')
  const groupId = hook.data.consumerAgentId
  const userId = hook.params.agent.id
  return relationships.create({
    relationshipType: 'admin',
    sourceId: groupId,
    targetId: userId
  }).then(() => {
    return hook
  })
}

function createGroupAgent (hook) {
  const agents = hook.app.service('agents')
  return agents.create({ type: 'group' })
  .then((agent) => {
    hook.data.consumerAgentId = agent.id
    return hook
  })
}

function hasNoGroupAgent (hook) {
  return isNil(hook.data.consumerAgentId)
}

function hasNoRelation (hook) {
  const relationships = hook.app.service('relationships')
  const supplierAgentId = hook.data.supplierAgentId
  return relationships.find({ query: { sourceId: supplierAgentId } }).then((relationship) => {
    return isEmpty(relationship)
  })
}

function createRelation (hook) {
  const relationships = hook.app.service('relationships')
  const consumerAgentId = hook.data.consumerAgentId
  const supplierAgentId = hook.data.supplierAgentId
  return relationships.create({
    relationshipType: 'supplier',
    sourceId: consumerAgentId,
    targetId: supplierAgentId
  }).then(() => {
    return hook
  })
}

const hasLengthOne = pipe(length, equals(1))

function hasOneOrder (hook) {
  const orders = hook.app.service('orders')
  const consumerAgentId = hook.data.consumerAgentId
  return orders.find({ query: { consumerAgentId } })
  .then(hasLengthOne)
}

function createPrereqTaskPlan (hook) {
  const taskPlans = hook.app.service('taskPlans')
  const taskRecipeId = taskRecipes.finishPrereqs.id

  // TODO: add beforeAll hook to get agent
  // const assigneeId = hook.params.agent.id

  const assigneeId = hook.params.credential.agentId
  const params = {
    consumerAgentId: hook.data.consumerAgentId,
    supplierAgentId: hook.data.supplierAgentId
  }
  return taskPlans.create({ taskRecipeId, params, assigneeId })
  .then(() => {
    return hook
  })
}

function createSupplierAgent (hook) {
  const agents = hook.app.service('agents')
  return agents.create({ type: 'group' })
  .then((agent) => {
    hook.data.supplierAgentId = agent.id
    return hook
  })
}

function hasNoSupplierAgent (hook) {
  return isNil(hook.data.supplierAgentId)
}

function hasNotCompletedGroupOrSupplierProfile (hook) {
  const agentId = hook.params.agent.id
  const relationshipsService = hook.app.service('relationships')
  const profilesService = hook.app.service('profiles')

  return relationshipsService.find({ query: { sourceId: agentId, relationshipType: 'admin' }})
  .then(groupRelationships => {
    const groupIds = map((relationship) => { return relationship.targetId }, groupRelationships)
    return relationshipsService.find({ query: { targetId: { $in: groupIds }, relationshipType: 'supplier' }})
    .then((supplierRelationships) => {
      const supplierIds = map((relationship) => { return relationship.sourceId }, supplierRelationships)
      return Promise.all([
        profilesService.find({ query: { agentId: { $in: groupIds }}}),
        profilesService.find({ query: { agentId: { $in: supplierIds }}})
      ])
    })
  })
  .then(profilesArray => {
    // TODO: IK: need to return true if either the 'find' for group profiles with a name OR supplier profiles with a name returns true
    return any(
      isNil,
      map((profiles) => {
        find(pipe(prop('name'), isNil, not))
      }, profilesArray)
    )
  })
}

function createCompleteOrderSetupWithPreReqsTaskPlan (hook) {
  const taskPlans = hook.app.service('taskPlans')
  const taskRecipeId = taskRecipes.completeOrderSetupWithPrereqs.id

  const assigneeId = hook.params.agent.id

  let params = {
    consumerAgentId: hook.data.consumerAgentId,
    supplierAgentId: hook.data.supplierAgentId,
    orderId: hook.result.id
  }
  return taskPlans.create({ taskRecipeId, params, assigneeId })
   .then(() => {
     return hook
   })
}

function createCompleteOrderSetupTaskPlan (hook) {
  const taskPlans = hook.app.service('taskPlans')
  const taskRecipeId = taskRecipes.completeOrderSetup.id

  const assigneeId = hook.params.agent.id

  let params = {
    consumerAgentId: hook.data.consumerAgentId,
    supplierAgentId: hook.data.supplierAgentId,
    orderId: hook.result.id
  }
  return taskPlans.create({ taskRecipeId, params, assigneeId })
   .then(() => {
     return hook
   })
}

function updatedAdmin (hook) {
  // has admin updated?
}

function updateCloseOrderTaskPlanAdmin (hook) {
  // update close order task plan associated with this order to be assigned to the new admin
}

function createCloseOrderTaskPlanToAdmin (hook) {
  const taskPlans = hook.app.service('taskPlans')
  const taskRecipeId = taskRecipes.closeOrder.id
  const assigneeId = hook.params.agent.id

  let params = {
    consumerAgentId: hook.data.consumerAgentId,
    supplierAgentId: hook.data.supplierAgentId,
    orderId: hook.result.id
  }
  return taskPlans.create({ taskRecipeId, params, assigneeId})
    .then(() => {
      return hook
    })

  // create closeOrderTaskPlan assigned to the order admin
}

function createCloseOrderTaskPlanToUser (hook) {
  console.log('close order to user')
  // create closeOrderTaskPlan assigned to the current logged in user
}
<commit_msg>remove unused functions<commit_after>const feathersKnex = require('feathers-knex')
const { iff, iffElse } = require('feathers-hooks-common')
import { pipe, equals, length, isNil, isEmpty, map, any, find, not, prop } from 'ramda'
import * as taskRecipes from '../../tasks/data/recipes'

module.exports = function () {
  const app = this
  const db = app.get('db')

  const name = 'orders'
  const options = { Model: db, name }

  app.use(name, feathersKnex(options))
  app.service(name).hooks(hooks)
}

const hooks = {
  before: {
    create: [
      getCurrentUser,
      iff(hasNoGroupAgent, createGroupAgent),
      iff(hasNoSupplierAgent, createSupplierAgent),
      iff(hasNoRelation, createRelation),
      iff(groupHasNoAdminRelation, createGroupAdminRelation),
      iff(userIsNotMemberOfGroup, createGroupMemberRelation)
    ]
  },
  after: {
    create: [
      iffElse(hasNotCompletedGroupOrSupplierProfile, createCompleteOrderSetupWithPreReqsTaskPlan, createCompleteOrderSetupTaskPlan)
    ]
  },
  error: {}
}

function getCurrentUser (hook) {
  const { agentId } = hook.params.credential
  const agentsService = hook.app.service('agents')
  return agentsService.get(agentId)
 .then(agent => {
   hook.params.agent = agent
 })
 .then(() => hook)
}

function userIsNotMemberOfGroup (hook) {
  const relationships = hook.app.service('relationships')
  const groupId = hook.data.consumerAgentId
  return relationships
    .find({ query: { sourceId: groupId, relationshipType: 'member' } })
    .then(isEmpty)
}

function createGroupMemberRelation (hook) {
  const relationships = hook.app.service('relationships')
  const groupId = hook.data.consumerAgentId
  const userId = hook.params.agent.id
  return relationships.create({
    relationshipType: 'member',
    sourceId: groupId,
    targetId: userId
  }).then(() => {
    return hook
  })
}

function groupHasNoAdminRelation (hook) {
  const relationships = hook.app.service('relationships')
  const groupId = hook.data.consumerAgentId
  return relationships
    .find({ query: { sourceId: groupId, relationshipType: 'admin' } })
    .then(isEmpty)
}

function createGroupAdminRelation (hook) {
  const relationships = hook.app.service('relationships')
  const groupId = hook.data.consumerAgentId
  const userId = hook.params.agent.id
  return relationships.create({
    relationshipType: 'admin',
    sourceId: groupId,
    targetId: userId
  }).then(() => {
    return hook
  })
}

function createGroupAgent (hook) {
  const agents = hook.app.service('agents')
  return agents.create({ type: 'group' })
  .then((agent) => {
    hook.data.consumerAgentId = agent.id
    return hook
  })
}

function hasNoGroupAgent (hook) {
  return isNil(hook.data.consumerAgentId)
}

function hasNoRelation (hook) {
  const relationships = hook.app.service('relationships')
  const supplierAgentId = hook.data.supplierAgentId
  return relationships.find({ query: { sourceId: supplierAgentId } }).then((relationship) => {
    return isEmpty(relationship)
  })
}

function createRelation (hook) {
  const relationships = hook.app.service('relationships')
  const consumerAgentId = hook.data.consumerAgentId
  const supplierAgentId = hook.data.supplierAgentId
  return relationships.create({
    relationshipType: 'supplier',
    sourceId: consumerAgentId,
    targetId: supplierAgentId
  }).then(() => {
    return hook
  })
}

const hasLengthOne = pipe(length, equals(1))

function hasOneOrder (hook) {
  const orders = hook.app.service('orders')
  const consumerAgentId = hook.data.consumerAgentId
  return orders.find({ query: { consumerAgentId } })
  .then(hasLengthOne)
}

function createPrereqTaskPlan (hook) {
  const taskPlans = hook.app.service('taskPlans')
  const taskRecipeId = taskRecipes.finishPrereqs.id

  // TODO: add beforeAll hook to get agent
  // const assigneeId = hook.params.agent.id

  const assigneeId = hook.params.credential.agentId
  const params = {
    consumerAgentId: hook.data.consumerAgentId,
    supplierAgentId: hook.data.supplierAgentId
  }
  return taskPlans.create({ taskRecipeId, params, assigneeId })
  .then(() => {
    return hook
  })
}

function createSupplierAgent (hook) {
  const agents = hook.app.service('agents')
  return agents.create({ type: 'group' })
  .then((agent) => {
    hook.data.supplierAgentId = agent.id
    return hook
  })
}

function hasNoSupplierAgent (hook) {
  return isNil(hook.data.supplierAgentId)
}

function hasNotCompletedGroupOrSupplierProfile (hook) {
  const agentId = hook.params.agent.id
  const relationshipsService = hook.app.service('relationships')
  const profilesService = hook.app.service('profiles')

  return relationshipsService.find({ query: { sourceId: agentId, relationshipType: 'admin' }})
  .then(groupRelationships => {
    const groupIds = map((relationship) => { return relationship.targetId }, groupRelationships)
    return relationshipsService.find({ query: { targetId: { $in: groupIds }, relationshipType: 'supplier' }})
    .then((supplierRelationships) => {
      const supplierIds = map((relationship) => { return relationship.sourceId }, supplierRelationships)
      return Promise.all([
        profilesService.find({ query: { agentId: { $in: groupIds }}}),
        profilesService.find({ query: { agentId: { $in: supplierIds }}})
      ])
    })
  })
  .then(profilesArray => {
    // TODO: IK: need to return true if either the 'find' for group profiles with a name OR supplier profiles with a name returns true
    return any(
      isNil,
      map((profiles) => {
        find(pipe(prop('name'), isNil, not))
      }, profilesArray)
    )
  })
}

function createCompleteOrderSetupWithPreReqsTaskPlan (hook) {
  const taskPlans = hook.app.service('taskPlans')
  const taskRecipeId = taskRecipes.completeOrderSetupWithPrereqs.id

  const assigneeId = hook.params.agent.id

  let params = {
    consumerAgentId: hook.data.consumerAgentId,
    supplierAgentId: hook.data.supplierAgentId,
    orderId: hook.result.id
  }
  return taskPlans.create({ taskRecipeId, params, assigneeId })
   .then(() => {
     return hook
   })
}

function createCompleteOrderSetupTaskPlan (hook) {
  const taskPlans = hook.app.service('taskPlans')
  const taskRecipeId = taskRecipes.completeOrderSetup.id

  const assigneeId = hook.params.agent.id

  let params = {
    consumerAgentId: hook.data.consumerAgentId,
    supplierAgentId: hook.data.supplierAgentId,
    orderId: hook.result.id
  }
  return taskPlans.create({ taskRecipeId, params, assigneeId })
   .then(() => {
     return hook
   })
}
<|endoftext|>


<commit_before>var GithubAuth = function () {};

GithubAuth.signed = false;

GithubAuth.prototype.getCookieName = function () {
  return 'gh-token*1';
}

GithubAuth.prototype.isSigned = function ()  {
  return this.signed;
}

GithubAuth.prototype.setIsSigned = function (val)  {
  this.signed = val;
}

GithubAuth.prototype.getAuthServerURL = function () {
  // Stabile version
  // return 'http://instaedit-server.herokuapp.com';

  // Dev version
  return 'http://floating-light-7013.herokuapp.com';
}

GithubAuth.prototype.storeTokenToCookies = function(token) {
  now = new Date();
  expires = new Date(now.getYear(), now.getMonth() + 1, 1);
  console.log('Storing token ' + token + ' which will expire in ' + expires);

  var expires = new Date();
  expires.setDate(expires.getDate() + expires);
  var token = escape(token) + ((expires == null) ? "" : "; expires=" + expires.toUTCString());
  document.cookie = this.getCookieName() + "=" + token;
}

GithubAuth.prototype.loadTokenFromCookies = function() {
  console.log('Looking for cookie ' + this.getCookieName());
  var i, x, y, ARRcookies = document.cookie.split(";");

  for(i = 0; i < ARRcookies.length; i++) {
    x = ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
    y = ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
    x = x.replace(/^\s+|\s+$/g,"");
    if(x == this.getCookieName()) {
        return unescape(y);
    }
  }
}

GithubAuth.prototype.checkIfSignedToGithub = function () {
  if(!instaedit.signedToGithub) {
    var self = this;
    var request = new XMLHttpRequest();

    request.open('GET', this.getAuthServerURL() + '/getCode', true);
    request.send();

    request.onloadend = function () {
      console.log(request.responseText);
      var response = JSON.parse(request.responseText);

      console.log(response);
      if(response.result == 'found') {
        var token = response.token;
        console.log(token);

        self.setGithubToken(token);
        self.setIsSigned(true);
        document.getElementById('commit').innerHTML = 'Commit';
      } else {
        console.log('Not logged yet.');
      }
    }
  }
}

GithubAuth.prototype.sendCommitRequest = function (data, code, url, cb) {
  var reqDataRaw = {};
  reqDataRaw.data = data;
  reqDataRaw.token = code;
  reqDataRaw.target = url;

  console.log('Sending data to ' + this.getAuthServerURL() + '/commit');

  var self = this;
  var url = 'https://api.github.com/repos/' + url.split('/')[3] + '/' + url.split('/')[4] + '/git/refs/heads/' + url.split('/')[5];
  jQuery.getJSON(url + "?callback=?", {}, function(response) {
    reqDataRaw.tree = response.data.object.sha;
    var reqData = JSON.stringify(reqDataRaw);

    var request = new XMLHttpRequest();
    request.open('POST', self.getAuthServerURL() + '/commit', true);
    request.setRequestHeader("Content-Type", "application/json");

    request.send(reqData);

    request.onloadend = function () {
      console.log(request.statusCode);
      if(request.status == 500) {
        cb('failed');
      } else {
        cb('success');
      }
    }
  });
}

GithubAuth.prototype.setGithubToken = function (token) {
  console.log('Received auth data.');

  this.storeTokenToCookies(token);
  instaedit.signedToGithub = true;
  instaedit.displayNotification('Succesfully logged to github with token ' + token, 'notification');
  instaedit.githubToken = token;
  document.getElementById('commit').innerHTML = 'Commit';
}

GithubAuth.prototype.init = function () {
  console.log(this.loadTokenFromCookies());
  console.log(typeof this.loadTokenFromCookies());

  if(typeof this.loadTokenFromCookies() == 'undefined') {
    document.getElementById('commit').innerHTML = 'Github login';
    instaedit.signedToGithub = false;
  } else {
    this.setIsSigned(true);
    instaedit.signedToGithub = true;
    instaedit.githubToken = this.loadTokenFromCookies();
  }
}

GithubAuth.prototype.performProcess = function () {
  window.open(this.getAuthServerURL() + '/login/', 'Instaedit github auth','width=600, height=500');
  setInterval(this.checkIfSignedToGithub(), 3000);
}
<commit_msg>Up to date with new API.<commit_after>var GithubAuth = function () {};

GithubAuth.signed = false;

GithubAuth.prototype.getCookieName = function () {
  return 'gh-token*1';
}

GithubAuth.prototype.isSigned = function ()  {
  return this.signed;
}

GithubAuth.prototype.setIsSigned = function (val)  {
  this.signed = val;
}

GithubAuth.prototype.getAuthServerURL = function () {
  // Stabile version
  // return 'http://instaedit-server.herokuapp.com';

  // Dev version
  return 'http://floating-light-7013.herokuapp.com';
}

GithubAuth.prototype.storeTokenToCookies = function(token) {
  now = new Date();
  expires = new Date(now.getYear(), now.getMonth() + 1, 1);
  console.log('Storing token ' + token + ' which will expire in ' + expires);

  var expires = new Date();
  expires.setDate(expires.getDate() + expires);
  var token = escape(token) + ((expires == null) ? "" : "; expires=" + expires.toUTCString());
  document.cookie = this.getCookieName() + "=" + token;
}

GithubAuth.prototype.loadTokenFromCookies = function() {
  console.log('Looking for cookie ' + this.getCookieName());
  var i, x, y, ARRcookies = document.cookie.split(";");

  for(i = 0; i < ARRcookies.length; i++) {
    x = ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
    y = ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
    x = x.replace(/^\s+|\s+$/g,"");
    if(x == this.getCookieName()) {
        return unescape(y);
    }
  }
}

GithubAuth.prototype.checkIfSignedToGithub = function () {
  if(!instaedit.signedToGithub) {
    var self = this;
    var request = new XMLHttpRequest();

    request.open('GET', this.getAuthServerURL() + '/getCode', true);
    request.send();

    request.onloadend = function () {
      console.log(request.responseText);
      var response = JSON.parse(request.responseText);

      console.log(response);
      if(response.result == 'found') {
        var token = response.token;
        console.log(token);

        self.setGithubToken(token);
        self.setIsSigned(true);
        document.getElementById('commit').innerHTML = 'Commit';
      } else {
        console.log('Not logged yet.');
      }
    }
  }
}

GithubAuth.prototype.sendCommitRequest = function (data, code, url, cb) {
  var reqDataRaw = {};
  reqDataRaw.data = data;
  reqDataRaw.token = code;
  reqDataRaw.target = url;

  console.log('Sending data to ' + this.getAuthServerURL() + '/commit');

  var self = this;
  var reqUrl = 'https://api.github.com/repos/' + url.split('/')[3] + '/' + url.split('/')[4] + '/git/refs/heads/' + url.split('/')[5];
  jQuery.getJSON(reqUrl + "?callback=?", {}, function(tree) {
    var reqUrl = 'https://api.github.com/repos/' + url.split('/')[3] + '/' + url.split('/')[4] + '/branches';

    jQuery.getJSON(reqUrl + "?callback=?", {}, function(commits) {
      for(var i in commits.data) {
        console.log(commits.data[i].name);
        console.log(url.split('/')[5]);
        if(commits.data[i].name == url.split('/')[5]) {
          var parent = commits.data[i].commit.sha;
        }
      }

      reqDataRaw.tree = tree.data.object.sha;
      reqDataRaw.parents = new Array();
      reqDataRaw.parents.push(parent);
      var reqData = JSON.stringify(reqDataRaw);
      console.log(reqData);

      var request = new XMLHttpRequest();
      request.open('POST', self.getAuthServerURL() + '/commit', true);
      request.setRequestHeader("Content-Type", "application/json");

      request.send(reqData);

      request.onloadend = function () {
        console.log(request.statusCode);
        if(request.status == 500) {
          cb('failed');
        } else {
          cb('success');
        }
      }
    });
  });
}

GithubAuth.prototype.setGithubToken = function (token) {
  console.log('Received auth data.');

  this.storeTokenToCookies(token);
  instaedit.signedToGithub = true;
  instaedit.displayNotification('Succesfully logged to github with token ' + token, 'notification');
  instaedit.githubToken = token;
  document.getElementById('commit').innerHTML = 'Commit';
}

GithubAuth.prototype.init = function () {
  console.log(this.loadTokenFromCookies());
  console.log(typeof this.loadTokenFromCookies());

  if(typeof this.loadTokenFromCookies() == 'undefined') {
    document.getElementById('commit').innerHTML = 'Github login';
    instaedit.signedToGithub = false;
  } else {
    this.setIsSigned(true);
    instaedit.signedToGithub = true;
    instaedit.githubToken = this.loadTokenFromCookies();
  }
}

GithubAuth.prototype.performProcess = function () {
  window.open(this.getAuthServerURL() + '/login/', 'Instaedit github auth','width=600, height=500');
  setInterval(this.checkIfSignedToGithub(), 3000);
}
<|endoftext|>


<commit_before>function replaceDeprecated() {
    // Replace deprecated tags with modern style equivalents.
    // Relies on custom css file.
    $('center').replaceWith('');
}

function cleanBasic() {
    // Delete empty tags
    $('div:empty, p:empty, ol:empty, ul:empty, table:empty').remove();

    // Try to clean/remove elements that may be common enough to exist
    $('.related-links-container, .related-links, #comments, .bottom-share-module, .bottom-share').remove();

    // Remove old deprecated tags
    $('font').children().unwrap();

    // Remove empty html tags
    $('font:empty, div:empty, p:empty, li:empty, ol:empty').remove();

    // Remove some common ids
    $.each([
        '#footer', '#header', '#content', '#main-content', '#nav',
        '#navigation', '#masthead', '#ad', '#ads', '#google-ads',
        '#googleads'
    ], removeID);
}

function removeID(k, id) {
    $(id).attr('id', '');
}

function removeClass(k, klass) {
    $(klass).removeClass(klass);
}

function removeAttributeFromTag(tag, attr) {
    $(tag).attr(attr, '');
}

function removeAttributesFromTag(tag, attrs) {
    $.each(attrs, function(k, attr){
        removeAttributeFromTag(tag, attr);
    });
}

function removeAttribute(k, attr) {
    $('[' + attr + ']').attr(attr, '');
}

// ==UserScript==
// @name         bootstrIp wikipedia
// @description  Strip down the look and html for Wikipedia, and add Bootstrap 3 styling/conventions. Also adds some basic styling and nice looking fonts from Google.
// @namespace    bootstripWikipedia
// @version      0.1
// @match        https://en.wikipedia.org/*
// @author       Chris Tabor <dxdstudio@gmail.com>
// @support      https://github.com/christabor/tampermonkey/issues
// @homepage     https://github.com/christabor/tampermonkey/
// @run-at       document-start

// @require      http://code.jquery.com/jquery-latest.js
// @resource     bootcss https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css
// @resource     gfonts https://fonts.googleapis.com/css?family=Oswald:400,300,700|Open+Sans:400,300italic,400italic,700,700italic

// ==/UserScript==

var bootcss = GM_getResourceText('bootcss');
var gfonts = GM_getResourceText('gfonts');

var temp = $('#content').html();
var search = $('#searchform');

search = search.html();

GM_addStyle(bootcss);
GM_addStyle(gfonts);

var other_styles = [
    "body {padding:1em 0; background-color:#f1f1f1;}",
    // ".container {background-color:#fff; box-shadow: 0 0 30px rgba(0, 0, 0, 0.2);}",
    "h1 {font-size: 40px; font-weight: 100;border:none;}",
    "h2 {font-size: 20px; border: none; border-top: 2px solid #fff; padding-top: 0.7em;}",
    "h3 {font-size: 16px; text-transform: uppercase;}",
    "h4 {font-size: 14px;}",
    ".subdued {font-size: 10px; opacity: 0.6;}",
    ".subdued:hover {opacity: 1;}",
    ".centered {text-align:center;}",
    "body, ul, ol, p, .btn {font-family: 'Open Sans', sans-serif;}",
    "ul, ol, dl, p {line-height: 26px; font-size: 12px;}",
    "h1, h2, h3, h4 {font-family: 'Oswald', sans-serif;}",
    "dt, dd {margin-bottom: 0.4em;}",
    ".table, table {width: auto;}",
    '.well, .alert {padding: 6px;}',
    '.well *, table {font-size: 80%;}',
    ".alert, .table {display: inline-block;}",
    ".well .pull-right {margin: 10px 0 10px 10px;}",
    ".well .pull-left {margin: 10px 10px 10px 0;}",
    "img, video {height: auto; max-width: 100%;}",

    // Wikipedia specific overrides below
    "#toc {margin: 0; width: 100%;}",
    // ".infobox, #toc {max-width: 20%;min-width: 100px;}",
    ".infobox table, #toc table, table table {width: 100%;max-width:100%;}",
    "table.ombox, table.ambox, table.cmbox {margin: 1em 0;}"
].join('\n');

// Add all customer override styles
GM_addStyle(other_styles);

// Gut the outer elements, keep the main content and search.
$('body').empty().append('

' + temp + '

');
$('#firstHeading').append(search);
$('#toc').appendTo('#left-col');

// Initial cleanup
cleanBasic();
replaceDeprecated();

// Add all subdued items
$('#siteSub, .mw-editsection').addClass('subdued');

// Misc cleanup/style changes
$('#toc').addClass('pull-left well').closest('div').addClass('clearfix');
$('.vertical-navbox').addClass('pull-right well').closest('div').addClass('clearfix');
$('.infobox').addClass('well');

$('.mw-editsection').html('edit').addClass('btn btn-xs btn-default');
$('.hatnote').addClass('alert alert-info subdued');
$('table.ombox-notice').addClass('alert');

// Input related stuff
$('#simpleSearch').wrap('<form id="mainsearch" class="pull-right"></form>').attr('id', '');
$('input, textarea, select').addClass('input-sm form-control');

$('form').addClass('form form-inline');
$('button, input[type="submit"]').addClass('btn btn-xs btn-primary');
$('.plainlinks li a').addClass('btn btn-xs btn-default');

// Table stuff
$('table').addClass('table table-striped').removeClass('wikitable');

// Images etc
$('.gallery img').addClass('img-thumbnail');

// Convert close button images to character
$('[alt="close"]').replaceWith('×');

var toRemove = [
    '#mw-hidden-catlinks',
    '.mw-editsection-bracket',
    '#siteSub', '#mw-navigation', '#jump-to-nav', '#footer'
]
$('#searchInput').unwrap();
$(toRemove.join(' ')).remove();

$('.tright').addClass('pull-right inline-pad');
$('.lright').addClass('left-right inline-pad');

// List styling
$('.hlist').find('ul').addClass('list-inline');

// Add bs3 style labels.
$('.mw-editsection a, .NavToggle').addClass('label label-default').css({
    'font-size': '10px',
    'text-transform': 'uppercase',
    'color': 'white',
    'margin': '1px 4px'
});

// Remove ALL inline css -- use with caution!
// $('*').attr('style', '');
<commit_msg>Update wikipedia bootstrap script<commit_after>function replaceDeprecated() {
    // Replace deprecated tags with modern style equivalents.
    // Relies on custom css file.
    $('center').replaceWith('');
}

function cleanBasic() {
    // Delete empty tags
    $('div:empty, p:empty, ol:empty, ul:empty, table:empty').remove();

    // Try to clean/remove elements that may be common enough to exist
    $('.related-links-container, .related-links, #comments, .bottom-share-module, .bottom-share').remove();

    // Remove old deprecated tags
    $('font').children().unwrap();

    // Remove empty html tags
    $('font:empty, div:empty, p:empty, li:empty, ol:empty').remove();

    // Remove some common ids
    $.each([
        '#footer', '#header', '#content', '#main-content', '#nav',
        '#navigation', '#masthead', '#ad', '#ads', '#google-ads',
        '#googleads'
    ], removeID);
}

function removeID(k, id) {
    $(id).attr('id', '');
}

function removeClass(k, klass) {
    $(klass).removeClass(klass);
}

function removeAttributeFromTag(tag, attr) {
    $(tag).attr(attr, '');
}

function removeAttributesFromTag(tag, attrs) {
    $.each(attrs, function(k, attr){
        removeAttributeFromTag(tag, attr);
    });
}

function removeAttribute(k, attr) {
    $('[' + attr + ']').attr(attr, '');
}

// ==UserScript==
// @name         bootstrIp wikipedia
// @description  Strip down the look and html for Wikipedia, and add Bootstrap 3 styling/conventions. Also adds some basic styling and nice looking fonts from Google.
// @namespace    bootstripWikipedia
// @version      0.1
// @match        https://en.wikipedia.org/*
// @author       Chris Tabor <dxdstudio@gmail.com>
// @support      https://github.com/christabor/tampermonkey/issues
// @homepage     https://github.com/christabor/tampermonkey/
// @run-at       document-end
// @require      http://code.jquery.com/jquery-latest.js
// @resource     bootcss https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css
// @resource     gfonts https://fonts.googleapis.com/css?family=Oswald:400,300,700|Open+Sans:400,300italic,400italic,700,700italic

// ==/UserScript==

var bootcss = GM_getResourceText('bootcss');
var gfonts = GM_getResourceText('gfonts');

var temp = $('#content').html();
var search = $('#searchform');

search = search.html();

GM_addStyle(bootcss);
GM_addStyle(gfonts);

var other_styles = [
    "body {padding:1em 0; background-color:#f1f1f1;}",
    // ".container {background-color:#fff; box-shadow: 0 0 30px rgba(0, 0, 0, 0.2);}",
    "h1 {font-size: 40px; font-weight: 100;border:none;}",
    "h2 {font-size: 20px; border: none; border-top: 2px solid #fff; padding-top: 0.7em;}",
    "h3 {font-size: 16px; text-transform: uppercase;}",
    "h4 {font-size: 14px;}",
    ".subdued {font-size: 10px; opacity: 0.6;}",
    ".subdued:hover {opacity: 1;}",
    ".centered {text-align:center;}",
    "body, ul, ol, p, .btn {font-family: 'Open Sans', sans-serif;}",
    "ul, ol, dl {line-height: 12px; font-size: 12px;}",
    "li, dd {margin-bottom: 6px;}",
    "p {line-height: 26px; font-size: 12px;}",
    "h1, h2, h3, h4 {font-family: 'Oswald', sans-serif;}",
    "dt, dd {margin-bottom: 0.4em;}",
    ".table, table {width: auto;}",
    '.alert {padding: 8px;}',
    ".well {border: none; padding: 10px;}",
    '.well *, table {font-size: 80%;}',
    ".alert, .table {display: inline-block;}",
    ".well .pull-right {margin: 10px 0 10px 10px;}",
    ".well .pull-left {margin: 10px 10px 10px 0;}",
    "img, video {height: auto; max-width: 100%;}",

    // Wikipedia specific overrides below
    "#toc {margin: 0; width: 100%; border: none;}",
    "div.thumbinner, html .thumbimage {border:none;}",
    // ".infobox, #toc {max-width: 20%;min-width: 100px;}",
    "div.reflist ol.references, .refbegin li {font-size: 9px;}",
    ".infobox table, #toc table, table table {width: 100%;max-width:100%;}",
    "table.ombox, table.ambox, table.cmbox {margin: 1em 0;}"
].join('\n');

// Add all customer override styles
GM_addStyle(other_styles);

// Gut the outer elements, keep the main content and search.
$('body').empty().append('

' + temp + '

');
$('#firstHeading').append(search);
$('#toc').appendTo('#left-col');

// Initial cleanup
cleanBasic();
replaceDeprecated();

// Add all subdued items
$('#siteSub, .mw-editsection').addClass('subdued');

// Misc cleanup/style changes
$('#toc').addClass('pull-left well').closest('div').addClass('clearfix');
$('.vertical-navbox').addClass('pull-right well').closest('div').addClass('clearfix');
$('.infobox').addClass('well');

$('.mw-editsection').html('edit').addClass('btn btn-xs btn-default');
$('.hatnote').addClass('alert alert-info subdued');
$('table.ombox-notice').addClass('alert');

// Input related stuff
$('#simpleSearch').wrap('<form id="mainsearch" class="pull-right"></form>').attr('id', '');
$('input, textarea, select').addClass('input-sm form-control');

$('form').addClass('form form-inline');
$('button, input[type="submit"]').addClass('btn btn-xs btn-primary');
$('.plainlinks li a').addClass('btn btn-xs btn-default');

// Table stuff
$('table').addClass('table table-striped').removeClass('wikitable');

// Images etc
$('.gallery img, .thumbimage img').addClass('img-thumbnail');

// Convert close button images to character
$('[alt="close"]').replaceWith('×');

var toRemove = [
    '#mw-hidden-catlinks',
    '.mw-editsection-bracket',
    '#siteSub', '#mw-navigation', '#jump-to-nav', '#footer'
]
$('#searchInput').unwrap();
$(toRemove.join(' ')).remove();

$('.tright').addClass('pull-right inline-pad');
$('.lright').addClass('left-right inline-pad');

// List styling
$('.hlist').find('ul').addClass('list-inline');

// Add bs3 style labels.
$('.mw-editsection a, .NavToggle').addClass('label label-default').css({
    'font-size': '10px',
    'text-transform': 'uppercase',
    'color': 'white',
    'margin': '1px 4px'
});

// Remove ALL inline css -- use with caution!
// $('*').attr('style', '');
<|endoftext|>


<commit_before>import { observer as globalObserver } from '../../common/utils/observer';
import { getToken } from '../../common/utils/storageManager';

const log = (type, ...args) => {
    if (type === 'warn') {
        console.warn(...args); // eslint-disable-line no-console
    } else {
        console.log(...args); // eslint-disable-line no-console
    }
    const date = new Date();
    const timestamp = `${date.toISOString().split('T')[0]} ${date.toTimeString().slice(0, 8)} ${
        date.toTimeString().split(' ')[1]
    }`;
    globalObserver.emit('bot.notify', { type, timestamp, message: args.join(':') });
};

const notify = ({ className, message, position = 'left', sound = 'silent' }) => {
    log(className, message);

    $.notify(message, { position: `bottom ${position}`, className });
    if (sound !== 'silent') {
        $(`#${sound}`)
            .get(0)
            .play();
    }
};

export class TrackJSError extends Error {
    constructor(type, message, optCustomData) {
        super(message);
        this.name = type;
        this.code = type;
        this.data = optCustomData;
    }
}

const notifyError = error => {
    if (!error) {
        return;
    }

    let message;
    let code;

    if (typeof error === 'string') {
        code = 'Unknown';
        message = error;
    } else if (error.error) {
        if (error.error.error) {
            ({ message } = error.error.error);
            ({ code } = error.error.error);
        } else {
            ({ message } = error.error);
            ({ code } = error.error);
        }
    } else {
        ({ message } = error);
        ({ code } = error);
    }

    // Exceptions:
    if (message === 'Cannot read property \'open_time\' of undefined') {
        // SmartCharts error workaround, don't log nor show.
        return;
    }

    notify({ className: 'error', message, position: 'right' });

    if (trackJs) {
        trackJs.console.log(error);
        trackJs.track(code || error.name);
    }
};

const waitForNotifications = () => {
    const notifList = ['success', 'info', 'warn', 'error'];

    globalObserver.register('Notify', notify);

    globalObserver.register('Error', notifyError);

    notifList.forEach(className =>
        globalObserver.register(`ui.log.${className}`, message => notify({ className, message, position: 'right' }))
    );
};

const logHandler = () => {
    const token = $('.account-id')
        .first()
        .attr('value');
    const userId = getToken(token).accountName;

    if (trackJs) {
        trackJs.configure({ userId });
    }

    waitForNotifications();
};

export default logHandler;
<commit_msg>track error if isProduction<commit_after>import { observer as globalObserver } from '../../common/utils/observer';
import { getToken } from '../../common/utils/storageManager';
import { isProduction } from '../../common/utils/tools';

const log = (type, ...args) => {
    if (type === 'warn') {
        console.warn(...args); // eslint-disable-line no-console
    } else {
        console.log(...args); // eslint-disable-line no-console
    }
    const date = new Date();
    const timestamp = `${date.toISOString().split('T')[0]} ${date.toTimeString().slice(0, 8)} ${
        date.toTimeString().split(' ')[1]
    }`;
    globalObserver.emit('bot.notify', { type, timestamp, message: args.join(':') });
};

const notify = ({ className, message, position = 'left', sound = 'silent' }) => {
    log(className, message);

    $.notify(message, { position: `bottom ${position}`, className });
    if (sound !== 'silent') {
        $(`#${sound}`)
            .get(0)
            .play();
    }
};

export class TrackJSError extends Error {
    constructor(type, message, optCustomData) {
        super(message);
        this.name = type;
        this.code = type;
        this.data = optCustomData;
    }
}

const notifyError = error => {
    if (!error) {
        return;
    }

    let message;
    let code;

    if (typeof error === 'string') {
        code = 'Unknown';
        message = error;
    } else if (error.error) {
        if (error.error.error) {
            ({ message } = error.error.error);
            ({ code } = error.error.error);
        } else {
            ({ message } = error.error);
            ({ code } = error.error);
        }
    } else {
        ({ message } = error);
        ({ code } = error);
    }

    // Exceptions:
    if (message === 'Cannot read property \'open_time\' of undefined') {
        // SmartCharts error workaround, don't log nor show.
        return;
    }

    notify({ className: 'error', message, position: 'right' });

    if (trackJs) {
        trackJs.console.log(error);
        if (isProduction()) {
            trackJs.track(code || error.name);
        }
    }
};

const waitForNotifications = () => {
    const notifList = ['success', 'info', 'warn', 'error'];

    globalObserver.register('Notify', notify);

    globalObserver.register('Error', notifyError);

    notifList.forEach(className =>
        globalObserver.register(`ui.log.${className}`, message => notify({ className, message, position: 'right' }))
    );
};

const logHandler = () => {
    const token = $('.account-id')
        .first()
        .attr('value');
    const userId = getToken(token).accountName;

    if (trackJs) {
        trackJs.configure({ userId });
    }

    waitForNotifications();
};

export default logHandler;
<|endoftext|>


<commit_before>'use strict';

(function() {

    angular
        .module('simpleArmoryApp')
        .controller('CalendarCtrl' , CalendarCtrl);

    function CalendarCtrl($scope, AchievementsService, $sce) {

    	 AchievementsService.getAchievements().then(function(achievements){

		   	$scope.totalForMonth = 23;
    		$scope.totalPoints = '(15 points)';

			buildMonths(achievements);

			// Select the last month
			$scope.selectedMonth = $scope.months[$scope.months.length - 1];
        });

    	$scope.leftOneMonth = function() {

    		if ($scope.selectedMonth.index > 0) {
    			$scope.selectedMonth = $scope.months[$scope.selectedMonth.index - 1];
    			$scope.selectionChanged();
    		}
    	};

    	$scope.rightOneMonth = function() {

    		if ($scope.selectedMonth.index < $scope.months.length - 1) {
    			$scope.selectedMonth = $scope.months[$scope.selectedMonth.index + 1];
    			$scope.selectionChanged();
    		}
    	};

    	$scope.selectionChanged = function() {
    		var cc = $('.curCalendar');
    		cc.removeClass('curCalendar');
    		cc.hide();

			var newCC = $('#calendar' + $scope.selectedMonth.value);
			newCC.addClass('curCalendar');
			newCC.show();
    	};

    	function buildMonths(achievements) {
    		var monthnames = [,'January','February','March','April','May','June',
    						   'July','August','September','October','November','December'];
			var months = [];
			var today = new Date();
			var achByMonths = {};

			var calendarHtml = '';

			// build a lookup of month to achievement list
			angular.forEach(achievements, function(supercat) {
				angular.forEach(supercat.categories, function(cat) {
					angular.forEach(cat.zones, function(zone) {
						angular.forEach(zone.achievements, function(ach) {
							if (ach.completed) {
								var dt = new Date(ach.completed);
								var monthid = ''+dt.getFullYear()+((dt.getMonth() < 9)?'0':'')+(dt.getMonth()+1);

								if (!achByMonths[monthid]) {
									achByMonths[monthid] = new Array(31);
								}
								if (!achByMonths[monthid][dt.getDate()]) {
									achByMonths[monthid][dt.getDate()] = [];
								}

								achByMonths[monthid][dt.getDate()].push(ach);

								achByMonths[monthid].hasAchievements = true;
							}
						});
					});
				});
			});

			var index = 0;
			var foundFirstMonth = false;
			for (var year = 2008; year <= today.getFullYear(); year++) {
				for (var month = 1; month <= 12; month++) {
					var monthid = '' + year + ((month < 10)?'0':'') + month;
					var thisMonth = (year === today.getFullYear()) && (month === (today.getMonth()+1));

					// if we're still trying to find the first month, don't include a bunch of months that don't have achievements
					if (!foundFirstMonth && (!achByMonths[monthid] || !achByMonths[monthid].hasAchievements)) {
						continue;
					}
					foundFirstMonth = true;

					// Add the months to the list of months
					months.push({
						value:monthid,
						text:monthnames[month] + ' ' + year,
						index: index++
					});

					// build up the table information
					var rowData = buildRows(month, year, achByMonths);

					// Add the table to the html
					calendarHtml += '
';
					calendarHtml += rowData.rows;
					calendarHtml += '
';

					// Stop once we get to this month
					if (thisMonth) {
						break;
					}
				}
			}

			$scope.tableHtml = $sce.trustAsHtml(calendarHtml);
    		$scope.months = months;
    	}

    	function buildRows(month, year, achByMonths) {
			var rows = '';
		    var total = 0;
		    var points = 0;
		    var d;

		    // tmp
		    var name = 'kevinc';

			var lookup = '' + year + ((month < 10)?'0':'') + month;

		    for (var day = 1; day <= 31; day++) {
		        d = new Date(year, month - 1, day);
		        if (d.getDate() !== day) {
		        	break;
		        }
		        if ((day === 1) || (d.getDay() === 0)) {
		        	rows += '
';
		        }
		        if ((day === 1) && (d.getDay() > 0)) {
		        	rows += '	';
		        }
		        rows += '' + day;

		        // TODO: build out achieve data
		        if (achByMonths[lookup] && achByMonths[lookup][day]) {
		        	var  achievs = achByMonths[lookup][day];
		        	achievs.sort(achievementDaySort);

			        rows += '
'
			        angular.forEach(achievs, function(ach) {
			            rows += '' +
			        			'';

			            total++;
						points += ach.points;
					});
			        rows += '
';
		        }

		        rows += '	';
		        if (d.getDay() === 6) {
		        	rows += '
';
		        }
		    }
		    if (d.getDay() < 6) {
		    	rows += '	';
		    }

		    rows += '
';

		    return { 'rows': rows, 'total': total, 'points'	: points };
    	}
    }

    function achievementDaySort(achieve1, achieve2) {
		if (achieve1.completed === achieve2.completed) {
			return (parseInt(achieve1.id,10) < parseInt(achieve2.id,10)) ? -1 : 1;
		}

		return (achieve1.completed < achieve2.completed) ? -1 : 1;
	}

})();<commit_msg>Using character name for achievement mouseover<commit_after>'use strict';

(function() {

    angular
        .module('simpleArmoryApp')
        .controller('CalendarCtrl' , CalendarCtrl);

    function CalendarCtrl($scope, AchievementsService, $sce, $routeParams) {

    	 AchievementsService.getAchievements().then(function(achievements){

		   	$scope.totalForMonth = 23;
    		$scope.totalPoints = '(15 points)';

			buildMonths(achievements, $routeParams.character);

			// Select the last month
			$scope.selectedMonth = $scope.months[$scope.months.length - 1];
        });

    	$scope.leftOneMonth = function() {

    		if ($scope.selectedMonth.index > 0) {
    			$scope.selectedMonth = $scope.months[$scope.selectedMonth.index - 1];
    			$scope.selectionChanged();
    		}
    	};

    	$scope.rightOneMonth = function() {

    		if ($scope.selectedMonth.index < $scope.months.length - 1) {
    			$scope.selectedMonth = $scope.months[$scope.selectedMonth.index + 1];
    			$scope.selectionChanged();
    		}
    	};

    	$scope.selectionChanged = function() {
    		var cc = $('.curCalendar');
    		cc.removeClass('curCalendar');
    		cc.hide();

			var newCC = $('#calendar' + $scope.selectedMonth.value);
			newCC.addClass('curCalendar');
			newCC.show();
    	};

    	function buildMonths(achievements, charname) {
    		var monthnames = [,'January','February','March','April','May','June',
    						   'July','August','September','October','November','December'];
			var months = [];
			var today = new Date();
			var achByMonths = {};

			var calendarHtml = '';

			// build a lookup of month to achievement list
			angular.forEach(achievements, function(supercat) {
				angular.forEach(supercat.categories, function(cat) {
					angular.forEach(cat.zones, function(zone) {
						angular.forEach(zone.achievements, function(ach) {
							if (ach.completed) {
								var dt = new Date(ach.completed);
								var monthid = ''+dt.getFullYear()+((dt.getMonth() < 9)?'0':'')+(dt.getMonth()+1);

								if (!achByMonths[monthid]) {
									achByMonths[monthid] = new Array(31);
								}
								if (!achByMonths[monthid][dt.getDate()]) {
									achByMonths[monthid][dt.getDate()] = [];
								}

								achByMonths[monthid][dt.getDate()].push(ach);

								achByMonths[monthid].hasAchievements = true;
							}
						});
					});
				});
			});

			var index = 0;
			var foundFirstMonth = false;
			for (var year = 2008; year <= today.getFullYear(); year++) {
				for (var month = 1; month <= 12; month++) {
					var monthid = '' + year + ((month < 10)?'0':'') + month;
					var thisMonth = (year === today.getFullYear()) && (month === (today.getMonth()+1));

					// if we're still trying to find the first month, don't include a bunch of months that don't have achievements
					if (!foundFirstMonth && (!achByMonths[monthid] || !achByMonths[monthid].hasAchievements)) {
						continue;
					}
					foundFirstMonth = true;

					// Add the months to the list of months
					months.push({
						value:monthid,
						text:monthnames[month] + ' ' + year,
						index: index++
					});

					// build up the table information
					var rowData = buildRows(month, year, achByMonths, charname);

					// Add the table to the html
					calendarHtml += '
';
					calendarHtml += rowData.rows;
					calendarHtml += '
';

					// Stop once we get to this month
					if (thisMonth) {
						break;
					}
				}
			}

			$scope.tableHtml = $sce.trustAsHtml(calendarHtml);
    		$scope.months = months;
    	}

    	function buildRows(month, year, achByMonths, charname) {
			var rows = '';
		    var total = 0;
		    var points = 0;
		    var d;
		    var prettyName = charname.charAt(0).toUpperCase() + charname.slice(1);
			var lookup = '' + year + ((month < 10)?'0':'') + month;

		    for (var day = 1; day <= 31; day++) {
		        d = new Date(year, month - 1, day);
		        if (d.getDate() !== day) {
		        	break;
		        }
		        if ((day === 1) || (d.getDay() === 0)) {
		        	rows += '
';
		        }
		        if ((day === 1) && (d.getDay() > 0)) {
		        	rows += '	';
		        }
		        rows += '' + day;

		        // TODO: build out achieve data
		        if (achByMonths[lookup] && achByMonths[lookup][day]) {
		        	var  achievs = achByMonths[lookup][day];
		        	achievs.sort(achievementDaySort);

			        rows += '
'
			        angular.forEach(achievs, function(ach) {
			            rows += '' +
			        			'';

			            total++;
						points += ach.points;
					});
			        rows += '
';
		        }

		        rows += '	';
		        if (d.getDay() === 6) {
		        	rows += '
';
		        }
		    }
		    if (d.getDay() < 6) {
		    	rows += '	';
		    }

		    rows += '
';

		    return { 'rows': rows, 'total': total, 'points'	: points };
    	}
    }

    function achievementDaySort(achieve1, achieve2) {
		if (achieve1.completed === achieve2.completed) {
			return (parseInt(achieve1.id,10) < parseInt(achieve2.id,10)) ? -1 : 1;
		}

		return (achieve1.completed < achieve2.completed) ? -1 : 1;
	}

})();<|endoftext|>