<commit_before>// -*- coding: utf-8-dos -*-
// ==UserScript==
// @name        Skip matome headlines
// @namespace   http://idaemons.org/
// @description Skip headline-only pages of meta matome sites.
// @author      Akinori MUSHA
// @downloadURL https://userscripts.org/scripts/source/178704.user.js
// @updateURL   http://userscripts.org/scripts/source/178704.meta.js
// @include     http://2ch-c.net/?gt=*
// @include     http://2ch-matome.net/pickup/*/
// @include     http://a.anipo.jp/c/rss/*
// @include     http://overseas.antenam.info/items/view/*
// @include     http://www.antennash.com/?pick=*
// @include     http://baseball-mag.net/?id=*
// @include     http://besttrendnews.net/archives/*.html
// @include     http://blog-news.doorblog.jp/archives/*.html*
// @include     http://blog-ranking.doorblog.jp/archives/*.html
// @include     http://newmofu.doorblog.jp/archives/*.html*
// @include     http://newpuru.doorblog.jp/archives/*.html*
// @include     http://newyaku.blog.fc2.com/?c=pickup&id=*
// @include     http://newyaku.blog.fc2.com/blog-entry-*.html
// @include     http://afoafodayo.blog84.fc2.com/blog-entry-*.html
// @include     http://ga-t.net/rss/*
// @include     http://get2ch.net/?*
// @include     http://gurugurulog.com/archives/*.html*
// @include     http://katuru.com/rss/*.html
// @include     http://kita-kore.com/archives/*.html
// @include     http://konowaro.net/archives/*.html
// @include     http://matomeantena.com/feed/*
// @include     http://matomesakura.com/?rs=*
// @include     http://matometatta-news.net/archives/*.html
// @include     http://matomeume.com/?rs=*
// @include     http://mosi2ch.net/rss.php?d=*
// @include     http://moudamepo.com/pick.cgi?code=*
// @include     http://news-choice.net/archives/*.html
// @include     http://news-select.net/archives/*.html
// @include     http://news-three-stars.net/archives/*.html
// @include     http://newser.cc/date-*.html?order=link&ni=*
// @include     http://newspickup.com/archives/*.html
// @include     http://nullpoantenna.com/feed/*
// @include     http://rotco.jp/rss/*
// @include     http://suomi-neito.com/*/archive/*.html*
// @include     http://uhouho2ch.com/*/*.html
// @grant       none
// @license     2-clause BSDL
// @homepage    https://userscripts.org/scripts/show/178704
// @homepage    https://github.com/knu/userjs-skip_matome_headlines
// @version     1.0.12
// ==/UserScript==

(function () {
    var done = false;
    var try_redirect_1 = function (proc) {
        var url, exc;
        if (!done && (url = proc())) {
            try {
                var element = document.createElement('a');
                element.setAttribute('href', url);
                element.appendChild(document.createTextNode('Link'));
                document.body.appendChild(element);
                element.click();
                done = true;
                return true;
            } catch (exc) {}
        }
        return false;
    }, failures = 0, try_redirect = function (proc) {
        if (!try_redirect_1(proc)) {
            var id = setInterval(function () {
                if (!try_redirect_1(proc)) {
                    if (++failures < 30)
                        return;
                    alert('pickup not found.');
                }
                clearInterval(id);
            }, 1000);
        }
        return false;
    }, byQuery = function (query, property) {
        try_redirect(function () {
            var element = document.querySelector(query);
            if (!element) return null;
            return element[property || 'href'];
        });
    }, evalXPathFirst = function (query, proc) {
        var e, result, i, x;
        try {
             result = document.evaluate(query, document, null, 5, null);
        } catch (e) {
            alert(e + ": " + query);
            throw e;
        }
        while ((i = result.iterateNext())) {
            if ((x = proc(i)))
                return x;
        }
        return null;
    }, evalXPathToString = function (query) {
        var e;
        try {
            return document.evaluate(query, document, null, 2, null).stringValue;
        } catch (e) {
            alert(e + ": " + query);
            throw e;
        }
    }, byXPath = function (query) {
        try_redirect(function () {
            return evalXPathToString(query);
        });
    }, byXPathFirst = function (query, proc) {
        try_redirect(function () {
            return evalXPathFirst(query, proc);
        });
    }, xpathAnd = function () {
        var args = Array.prototype.slice.call(arguments);
        return args.join(' and ');
    }, xpathOr = function () {
        var args = Array.prototype.slice.call(arguments);
        return '(' + args.join(' or ') + ')';
    }, xpathNot = function (expr) {
        return 'not(' + expr + ')';
    }, xpathString = function (string) {
        var args = string.split(/('+)/).
            filter(function (s) { return s.length > 0 }).
            map(function (s) {
                if (s.indexOf("'") >= 0)
                    return '"' + s + '"';
                return "'" + s + "'";
            });
        switch (args.length) {
          case 0:
            return "''";
          case 1:
            return args[0];
          default:
            return 'concat(' + args.join(', ') + ')';
        }
    }, xpathContains = function (target, substring) {
        return 'contains(' + target + ', ' + substring + ')';
    }, xpathStartsWith = function (target, prefix) {
        return 'starts-with(' + target + ', ' + prefix + ')';
    }, xpathEndsWith = function (target, suffix) {
        return target + ' = concat(substring-before(' + target + ', ' + suffix + '), ' + suffix + ')';
    }, xpathUsedIn = function (target, substring) {
        return xpathAnd('string-length(normalize-space(' + substring + ')) >= 3',
                        xpathOr(xpathStartsWith('normalize-space(' + target + ')', 'normalize-space(' + substring + ')'),
                                xpathEndsWith('normalize-space(' + target + ')', 'normalize-space(' + substring + ')')));
    };

    switch (location.host) {
      case 'a.anipo.jp':
        if (location.pathname.match(/([0-9]+)$/)) {
            byQuery('tr[eid="' + RegExp.$1 + '"] th a[name="title"]');
        }
        break;
      case 'besttrendnews.net':
        byQuery('.pickuplink.select a');
        break;
      case 'get2ch.net':
      case 'moudamepo.com':
        byXPath('//a[boolean(ancestor-or-self::*[contains(concat(" ", @class), " pickup")])]/@href');
        break;
      case 'konowaro.net':
        byQuery('.pickuplink.selected a');
        break;
      case 'matomesakura.com':
      case 'matomeume.com':
        byXPath('(//text()[contains(., "PICK UP")]/following-sibling::a)[1]/@href');
        break;
      case 'newser.cc':
        byQuery('.news-link a[style]');
        break;
      default:
        var root = location.protocol + '//' + location.host + '/';

        [
          '//title/text()',
          '//h1//a/@title',
          '//h1//a/text()',
          '//h2//a/@title',
          '//h2//a/text()'
        ].forEach(function (xpath) {
            byXPathFirst('//a[' +
                         xpathAnd(xpathOr(xpathUsedIn(xpath, 'substring(@title, 1, 30)'),
                                          'boolean(descendant-or-self::text()[' + xpathUsedIn(xpath, 'substring(., 1, 30)') + '])'),
                                  xpathNot('boolean(ancestor::h1)'),
                                  xpathNot('boolean(ancestor::h2)')) +
                         ']', function (a) {
                                  var href = a.href; // resolved URL

                                  // ga-t.net: /count/123
                                  // overseas.antenam.info: /items/click/123
                                  // rotco.jp: ../link/123
                                  // suomi-neito.com: /out/123
                                  if (href.match(/\/(click|count|link|out)\/[0-9]+$/))
                                      return href;

                                  if (href.lastIndexOf(root, 0) != 0)
                                      return href;

                                  return null;
                              });
        });
        break;
    }
})();
<commit_msg>try_redirect(): Properly return true when succeeded.<commit_after>// -*- coding: utf-8-dos -*-
// ==UserScript==
// @name        Skip matome headlines
// @namespace   http://idaemons.org/
// @description Skip headline-only pages of meta matome sites.
// @author      Akinori MUSHA
// @downloadURL https://userscripts.org/scripts/source/178704.user.js
// @updateURL   http://userscripts.org/scripts/source/178704.meta.js
// @include     http://2ch-c.net/?gt=*
// @include     http://2ch-matome.net/pickup/*/
// @include     http://a.anipo.jp/c/rss/*
// @include     http://overseas.antenam.info/items/view/*
// @include     http://www.antennash.com/?pick=*
// @include     http://baseball-mag.net/?id=*
// @include     http://besttrendnews.net/archives/*.html
// @include     http://blog-news.doorblog.jp/archives/*.html*
// @include     http://blog-ranking.doorblog.jp/archives/*.html
// @include     http://newmofu.doorblog.jp/archives/*.html*
// @include     http://newpuru.doorblog.jp/archives/*.html*
// @include     http://newyaku.blog.fc2.com/?c=pickup&id=*
// @include     http://newyaku.blog.fc2.com/blog-entry-*.html
// @include     http://afoafodayo.blog84.fc2.com/blog-entry-*.html
// @include     http://ga-t.net/rss/*
// @include     http://get2ch.net/?*
// @include     http://gurugurulog.com/archives/*.html*
// @include     http://katuru.com/rss/*.html
// @include     http://kita-kore.com/archives/*.html
// @include     http://konowaro.net/archives/*.html
// @include     http://matomeantena.com/feed/*
// @include     http://matomesakura.com/?rs=*
// @include     http://matometatta-news.net/archives/*.html
// @include     http://matomeume.com/?rs=*
// @include     http://mosi2ch.net/rss.php?d=*
// @include     http://moudamepo.com/pick.cgi?code=*
// @include     http://news-choice.net/archives/*.html
// @include     http://news-select.net/archives/*.html
// @include     http://news-three-stars.net/archives/*.html
// @include     http://newser.cc/date-*.html?order=link&ni=*
// @include     http://newspickup.com/archives/*.html
// @include     http://nullpoantenna.com/feed/*
// @include     http://rotco.jp/rss/*
// @include     http://suomi-neito.com/*/archive/*.html*
// @include     http://uhouho2ch.com/*/*.html
// @grant       none
// @license     2-clause BSDL
// @homepage    https://userscripts.org/scripts/show/178704
// @homepage    https://github.com/knu/userjs-skip_matome_headlines
// @version     1.0.12
// ==/UserScript==

(function () {
    var done = false;
    var try_redirect_1 = function (proc) {
        var url, exc;
        if (!done && (url = proc())) {
            try {
                var element = document.createElement('a');
                element.setAttribute('href', url);
                element.appendChild(document.createTextNode('Link'));
                document.body.appendChild(element);
                element.click();
                done = true;
                return true;
            } catch (exc) {}
        }
        return false;
    }, failures = 0, try_redirect = function (proc) {
        if (try_redirect_1(proc)) {
            return true;
        } else {
            var id = setInterval(function () {
                if (!try_redirect_1(proc)) {
                    if (++failures < 30)
                        return;
                    alert('pickup not found.');
                }
                clearInterval(id);
            }, 1000);
            return false;
        }
    }, byQuery = function (query, property) {
        try_redirect(function () {
            var element = document.querySelector(query);
            if (!element) return null;
            return element[property || 'href'];
        });
    }, evalXPathFirst = function (query, proc) {
        var e, result, i, x;
        try {
             result = document.evaluate(query, document, null, 5, null);
        } catch (e) {
            alert(e + ": " + query);
            throw e;
        }
        while ((i = result.iterateNext())) {
            if ((x = proc(i)))
                return x;
        }
        return null;
    }, evalXPathToString = function (query) {
        var e;
        try {
            return document.evaluate(query, document, null, 2, null).stringValue;
        } catch (e) {
            alert(e + ": " + query);
            throw e;
        }
    }, byXPath = function (query) {
        try_redirect(function () {
            return evalXPathToString(query);
        });
    }, byXPathFirst = function (query, proc) {
        try_redirect(function () {
            return evalXPathFirst(query, proc);
        });
    }, xpathAnd = function () {
        var args = Array.prototype.slice.call(arguments);
        return args.join(' and ');
    }, xpathOr = function () {
        var args = Array.prototype.slice.call(arguments);
        return '(' + args.join(' or ') + ')';
    }, xpathNot = function (expr) {
        return 'not(' + expr + ')';
    }, xpathString = function (string) {
        var args = string.split(/('+)/).
            filter(function (s) { return s.length > 0 }).
            map(function (s) {
                if (s.indexOf("'") >= 0)
                    return '"' + s + '"';
                return "'" + s + "'";
            });
        switch (args.length) {
          case 0:
            return "''";
          case 1:
            return args[0];
          default:
            return 'concat(' + args.join(', ') + ')';
        }
    }, xpathContains = function (target, substring) {
        return 'contains(' + target + ', ' + substring + ')';
    }, xpathStartsWith = function (target, prefix) {
        return 'starts-with(' + target + ', ' + prefix + ')';
    }, xpathEndsWith = function (target, suffix) {
        return target + ' = concat(substring-before(' + target + ', ' + suffix + '), ' + suffix + ')';
    }, xpathUsedIn = function (target, substring) {
        return xpathAnd('string-length(normalize-space(' + substring + ')) >= 3',
                        xpathOr(xpathStartsWith('normalize-space(' + target + ')', 'normalize-space(' + substring + ')'),
                                xpathEndsWith('normalize-space(' + target + ')', 'normalize-space(' + substring + ')')));
    };

    switch (location.host) {
      case 'a.anipo.jp':
        if (location.pathname.match(/([0-9]+)$/)) {
            byQuery('tr[eid="' + RegExp.$1 + '"] th a[name="title"]');
        }
        break;
      case 'besttrendnews.net':
        byQuery('.pickuplink.select a');
        break;
      case 'get2ch.net':
      case 'moudamepo.com':
        byXPath('//a[boolean(ancestor-or-self::*[contains(concat(" ", @class), " pickup")])]/@href');
        break;
      case 'konowaro.net':
        byQuery('.pickuplink.selected a');
        break;
      case 'matomesakura.com':
      case 'matomeume.com':
        byXPath('(//text()[contains(., "PICK UP")]/following-sibling::a)[1]/@href');
        break;
      case 'newser.cc':
        byQuery('.news-link a[style]');
        break;
      default:
        var root = location.protocol + '//' + location.host + '/';

        [
          '//title/text()',
          '//h1//a/@title',
          '//h1//a/text()',
          '//h2//a/@title',
          '//h2//a/text()'
        ].forEach(function (xpath) {
            byXPathFirst('//a[' +
                         xpathAnd(xpathOr(xpathUsedIn(xpath, 'substring(@title, 1, 30)'),
                                          'boolean(descendant-or-self::text()[' + xpathUsedIn(xpath, 'substring(., 1, 30)') + '])'),
                                  xpathNot('boolean(ancestor::h1)'),
                                  xpathNot('boolean(ancestor::h2)')) +
                         ']', function (a) {
                                  var href = a.href; // resolved URL

                                  // ga-t.net: /count/123
                                  // overseas.antenam.info: /items/click/123
                                  // rotco.jp: ../link/123
                                  // suomi-neito.com: /out/123
                                  if (href.match(/\/(click|count|link|out)\/[0-9]+$/))
                                      return href;

                                  if (href.lastIndexOf(root, 0) != 0)
                                      return href;

                                  return null;
                              });
        });
        break;
    }
})();
<|endoftext|>


<commit_before>function initialize_records_form() {
    $('#diskDiameters_lbl').hide();
    $('#reelDiameters_lbl').hide();
    $('#mediaDiameters_lbl').hide();
    $('#tapeThickness_lbl').hide();
    $('#trackTypes_lbl').hide();
    $('#cassetteSize_lbl').hide();
    $("#formatVersion_lbl").hide();
    $('.new #mediaType option[value="' + selectedMediaType + '"]').attr("selected", "selected");
    showUpdateFields();
    $.mask.definitions['y'] = '[1-2,x]';
    $.mask.definitions['m'] = '[0-1,x]';
    $.mask.definitions['d'] = '[0-3,x]';
    $.mask.definitions['g'] = '[0-9,x]';
    $("#creationDate, #contentDate").mask("yggg-mg-dg", {optional: true});
    updateFormat();
    onChangeMediaType();
}
function updateFormat() {
    /// call to get base dropdown options
    if (selectedFormat) {
        url = baseUrl + 'getFormat/' + $("#mediaType").val() + '/' + selectedFormat;
    } else {
        url = baseUrl + 'getFormat/' + $("#mediaType").val();
    }
    $.ajax({
        type: "GET",
        url: url,
        success: function (response) {
            if (response != "") {
                $("#format").html(response);
            } else {
            }
        }

    }); // Ajax Call
}

function showUpdateFields() {
    $('#format').change(function () {
        var showDiskDiameter = [16, 17, 18, 19, 20, 28];
        var showMediaDiameter = [1, 2, 3, 4, 5, 24];
        var showTapeThickness = [1, 2, 3, 4, 5];
        var showTrackType = [1, 2, 3, 4, 5];
        var showCassetteSize = [59, 60, 33, 34, 35, 43, 44, 46, 47, 48, 52, 53, 54, 55, 57];
        var hideRecordingSpeedFormat = [37, 39, 40, 41];
        var hideIfFormat = [24, 25, 26];

        if (jQuery.inArray(parseInt($(this).val()), showDiskDiameter) >= 0) {
            $('#diskDiameters_lbl').show();
        } else {
            $('#diskDiameters_lbl').hide();
        }

        if (jQuery.inArray(parseInt($(this).val()), showMediaDiameter) >= 0) {
            $('#mediaDiameters_lbl').show();
        } else {
            $('#mediaDiameters_lbl').hide();
        }

        if (jQuery.inArray(parseInt($(this).val()), showTapeThickness) >= 0) {
            $('#tapeThickness_lbl').show();
        } else {
            $('#tapeThickness_lbl').hide();
        }

        if (jQuery.inArray(parseInt($(this).val()), showTrackType) >= 0) {
            $('#trackTypes_lbl').show();
        } else {
            $('#trackTypes_lbl').hide();
        }

        if (jQuery.inArray(parseInt($(this).val()), showCassetteSize) >= 0) {
            $('#cassetteSize_lbl').show();
        } else {
            $('#cassetteSize_lbl').hide();
        }

        if (jQuery.inArray(parseInt($(this).val()), hideIfFormat) >= 0) {
            $('#slides_lbl, #monoStereo_lbl, #noiceReduction_lbl').hide();
        } else {
            $('#slides_lbl, #monoStereo_lbl, #noiceReduction_lbl').show();
        }
        /// call to get base dropdown options
        $.ajax({
            type: "GET",
            url: baseUrl + 'getBase/' + $(this).val(),
            success: function (response) {
                if (response != "") {
                    $("#bases_lbl").show();
                    $("#bases").html(response);
                } else {
                    $("#bases_lbl").hide();
                }
            }

        }); // Ajax Call
        /// call to get reel diameters dropdown options
        $.ajax({
            type: "GET",
            url: baseUrl + 'getReelDiameter/' + $(this).val() + '/' + $("#mediaType").val(),
            success: function (response) {
                if (response != "") {
                    $("#reelDiameters_lbl").show();
                    $("#reelDiameters").html(response);
                } else {
                    $("#reelDiameters_lbl").hide();
                }
            }

        }); // Ajax Call
        if (jQuery.inArray(parseInt($(this).val()), hideRecordingSpeedFormat) >= 0) {
            $('#recordingSpeed_lbl').hide();
        } else {
            $('#recordingSpeed_lbl').show();
            /// call to get recording speed dropdown options
            $.ajax({
                type: "GET",
                url: baseUrl + 'getRecordingSpeed/' + $(this).val() + '/' + $("#mediaType").val(),
                success: function (response) {
                    if (response != "") {
                        $("#recordingSpeed_lbl").show();
                        $("#recordingSpeed").html(response);
                    } else {
                        $("#recordingSpeed_lbl").hide();
                    }
                }

            }); // Ajax Call
        }
        /// call to get formatversion dropdown options
        $.ajax({
            type: "GET",
            url: baseUrl + 'getFormatVersion/' + $(this).val(),
            success: function (response) {
                if (response != "") {
                    $("#formatVersion_lbl").show();
                    $("#formatVersion").html(response);
                } else {
                    $("#formatVersion_lbl").hide();
                }
            }

        }); // Ajax Call
    }).change();

}

function onChangeMediaType() {
    $(".new #mediaType").change(function () {
        console.log($(this).val());
        if ($(this).val() == 3) {
            window.location.href = baseUrl + 'video/new';
        } else if ($(this).val() == 2) {
            window.location.href = baseUrl + 'film/new';
            ;
        } else if ($(this).val() == 1) {
            window.location.href = baseUrl + 'audio/new';
            ;
        }
    });
}
    <commit_msg>bug fixing<commit_after>function initialize_records_form() {
    $('#diskDiameters_lbl').hide();
    $('#reelDiameters_lbl').hide();
    $('#mediaDiameters_lbl').hide();
    $('#tapeThickness_lbl').hide();
    $('#trackTypes_lbl').hide();
    $('#cassetteSize_lbl').hide();
    $("#formatVersion_lbl").hide();
    $('.new #mediaType option[value="' + selectedMediaType + '"]').attr("selected", "selected");
    showUpdateFields();
    $.mask.definitions['y'] = '[1-2,x]';
    $.mask.definitions['m'] = '[0-1,x]';
    $.mask.definitions['d'] = '[0-3,x]';
    $.mask.definitions['g'] = '[0-9,x]';
    $("#creationDate, #contentDate").mask("yggg-mg-dg", {optional: true});
    updateFormat();
    onChangeMediaType();
}
function updateFormat() {
    /// call to get base dropdown options
    if (selectedFormat) {
        url = baseUrl + 'getFormat/' + $("#mediaType").val() + '/' + selectedFormat;
    } else {
        url = baseUrl + 'getFormat/' + $("#mediaType").val();
    }
    $.ajax({
        type: "GET",
        url: url,
        success: function (response) {
            if (response != "") {
                $("#format").html(response);
            } else {
            }
        }

    }); // Ajax Call
}

function showUpdateFields() {
    $('#format').change(function () {
        var showDiskDiameter = [16, 17, 18, 19, 20, 28];
        var showMediaDiameter = [1, 2, 3, 4, 5, 24];
        var showTapeThickness = [1, 2, 3, 4, 5];
        var showTrackType = [1, 2, 3, 4, 5];
        var showCassetteSize = [59, 60, 33, 34, 35, 43, 44, 46, 47, 48, 52, 53, 54, 55, 57];
        var hideRecordingSpeedFormat = [37, 39, 40, 41];
        var hideIfFormat = [24, 25, 26];

        if (jQuery.inArray(parseInt($(this).val()), showDiskDiameter) >= 0) {
            $('#diskDiameters_lbl').show();
        } else {
            $('#diskDiameters_lbl').hide();
        }

        if (jQuery.inArray(parseInt($(this).val()), showMediaDiameter) >= 0) {
            $('#mediaDiameters_lbl').show();
        } else {
            $('#mediaDiameters_lbl').hide();
        }

        if (jQuery.inArray(parseInt($(this).val()), showTapeThickness) >= 0) {
            $('#tapeThickness_lbl').show();
        } else {
            $('#tapeThickness_lbl').hide();
        }

        if (jQuery.inArray(parseInt($(this).val()), showTrackType) >= 0) {
            $('#trackTypes_lbl').show();
        } else {
            $('#trackTypes_lbl').hide();
        }

        if (jQuery.inArray(parseInt($(this).val()), showCassetteSize) >= 0) {
            $('#cassetteSize_lbl').show();
        } else {
            $('#cassetteSize_lbl').hide();
        }

        if (jQuery.inArray(parseInt($(this).val()), hideIfFormat) >= 0) {
            $('#slides_lbl, #monoStereo_lbl, #noiceReduction_lbl').hide();
        } else {
            $('#slides_lbl, #monoStereo_lbl, #noiceReduction_lbl').show();
        }
        getBaseOptions();
        /// call to get reel diameters dropdown options
        $.ajax({
            type: "GET",
            url: baseUrl + 'getReelDiameter/' + $(this).val() + '/' + $("#mediaType").val(),
            success: function (response) {
                if (response != "") {
                    $("#reelDiameters_lbl").show();
                    $("#reelDiameters").html(response);
                } else {
                    $("#reelDiameters_lbl").hide();
                }
            }

        }); // Ajax Call
        if (jQuery.inArray(parseInt($(this).val()), hideRecordingSpeedFormat) >= 0) {
            $('#recordingSpeed_lbl').hide();
        } else {
            $('#recordingSpeed_lbl').show();
            /// call to get recording speed dropdown options
            $.ajax({
                type: "GET",
                url: baseUrl + 'getRecordingSpeed/' + $(this).val() + '/' + $("#mediaType").val(),
                success: function (response) {
                    if (response != "") {
                        $("#recordingSpeed_lbl").show();
                        $("#recordingSpeed").html(response);
                    } else {
                        $("#recordingSpeed_lbl").hide();
                    }
                }

            }); // Ajax Call
        }
        /// call to get formatversion dropdown options
        $.ajax({
            type: "GET",
            url: baseUrl + 'getFormatVersion/' + $(this).val(),
            success: function (response) {
                if (response != "") {
                    $("#formatVersion_lbl").show();
                    $("#formatVersion").html(response);
                } else {
                    $("#formatVersion_lbl").hide();
                }
            }

        }); // Ajax Call
    }).change();

}

function onChangeMediaType() {
    $(".new #mediaType").change(function () {
        console.log($(this).val());
        if ($(this).val() == 3) {
            window.location.href = baseUrl + 'video/new';
        } else if ($(this).val() == 2) {
            window.location.href = baseUrl + 'film/new';
            ;
        } else if ($(this).val() == 1) {
            window.location.href = baseUrl + 'audio/new';
            ;
        }
    });
}

function getBaseOptions() {
    /// call to get base dropdown options
    $.ajax({
        type: "GET",
        url: baseUrl + 'getBase/' + $('#format').val(),
        success: function (response) {
            if (response != "") {
                $("#bases_lbl").show();
                $("#bases").html(response);
            } else {
                $("#bases_lbl").hide();
            }
        }

    }); // Ajax Call
}
function onChangeBase() {
    $(".#bases").change(function () {
        getBaseOptions();
    }).change();
}
<|endoftext|>


<commit_before>import normalizeUrl from 'normalize-url'

import queryParamRules from './query-string-normalization-rules'

export const PROTOCOL_PATTERN = /^\w+:\/\//

const normalizationOpts = {
    normalizeProtocol: true, // Prepend `http://` if URL is protocol-relative
    stripFragment: true, // Remove trailing hash fragment
    stripWWW: true, // Remove any leading `www.`
    removeTrailingSlash: true,
    removeQueryParameters: [/^utm_\w+/i], // Remove each of these query params (default for now)
    removeDirectoryIndex: [/^(default|index)\.\w{2,4}$/], // Remove things like tralining `/index.js` or `/default.php`
}

/**
 * Applies our custom query-param normalization rules for specific sites, removing all
 * but specific params from the query string.
 *
 * @param {string} url
 * @returns {string}
 */
function applyQueryParamsRules(url) {
    const parsed = new URL(url)
    const rulesObj = queryParamRules.get(parsed.hostname)

    // Base case; domain doesn't have any special normalization rules
    if (!rulesObj) {
        return url
    }

    // Remove all query params that don't appear in special rules
    const rulesSet = new Set(rulesObj.rules)
    const rulesType = rulesObj.type
    if (rulesType == 'keep') {
        for (const param of parsed.searchParams.keys()) {
            if (!rulesSet.has(param)) {
                parsed.searchParams.delete(param)
            }
        }
        return parsed.href
    }
    for (const param of rulesSet) {
        parsed.searchParams.delete(param)
    }
    return parsed.href
}

/**
 * NOTE: once normalized there is no way to recreate original input.
 *
 * @param {string} url
 * @param {any} [customNormalizationOpts={}] Custom options to pass to `normalize-url` package (will override).
 * @returns {string}
 */
function normalize(url, customOpts) {
    let normalized = normalizeUrl(url, {
        ...normalizationOpts,
        ...customOpts,
    })

    normalized = applyQueryParamsRules(normalized)

    // Remove the protocol; we don't need/want it for IDs
    return normalized.replace(PROTOCOL_PATTERN, '')
}

/**
 * Safely encodes a unicode URL to base64 string. More info on the safety with URLs
 * containing unicode chars here:
 * https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22
 *
 * @param {string} url
 * @param {boolean} needsEscaping
 * @returns {string}
 */
function encode(url, needsEscaping) {
    const escaped = encodeURIComponent(url) // Grab percent-encoded unicode chars (`%`)
        .replace(
        /%([0-9A-F]{2})/g, // Convert percentage-encodings into raw bytes
        (_, p1) => String.fromCharCode(`0x${p1}`),
    )

    // Feed in escaped unicode stuff into base64 encoder
    const encoded = btoa(escaped)
    return needsEscaping ? encodeURIComponent(encoded) : encoded
}

/**
 * Essentially goes backwards from the encode function.
 *
 * @param {string} encodedUrl URL that has been encoded via this module.
 * @param {boolean} needsEscaping Essentially the inverse of the same named param on encode method.
 * @returns {string} Original normalized URL.
 */
export function decode(encodedUrl, needsEscaping = true) {
    encodedUrl = needsEscaping ? decodeURIComponent(encodedUrl) : encodedUrl

    const percentageEncoded = atob(encodedUrl)
        .split('')
        .map(char => {
            // For each raw byte char, convert to percentage-encodings
            const unicodeChar = `00${char.charCodeAt(0).toString(16)}`.slice(-2)
            return `%${unicodeChar}`
        })
        .join('')

    return decodeURIComponent(percentageEncoded)
}

/**
 * Given a URL string, should apply normalization transformations to standardize URLs
 * in a consistent manner, along with encoding to base64 for use in a Pouch doc ID.
 * Base64 encoding should be safe for use with URLs containing unicode chars.
 *
 * Note that there are some normalization schemes proposed in RFC 3986 (describes general
 * syntax for URIs), however this module should contain only those transformations that
 * make sense for the WorldBrain web extension, as Pouch doc IDs.
 *
 * @param {string} url URL string to normalize and encode.
 * @param {boolean} needsEscaping Denotes whether or not encoded URL should be run through
 *  final `encodeURIComponent` call. Generally should be done if encoding to perform a lookup,
 *  as generated doc IDs will have been auto-escaped (via `docuri` package).
 * @param {any} [customNormalizationOpts={}] Custom options to pass to `normalize-url` package (will override).
 * @returns {string} Encoded URL ready for use in PouchID.
 */
function normalizeAndEncode(
    url,
    needsEscaping = true,
    customNormalizationOpts = {},
) {
    const normalizedUrl = normalize(url, customNormalizationOpts)
    return encode(normalizedUrl, needsEscaping)
}

export default normalizeAndEncode
<commit_msg>Changed from abstract to strict equality operator<commit_after>import normalizeUrl from 'normalize-url'

import queryParamRules from './query-string-normalization-rules'

export const PROTOCOL_PATTERN = /^\w+:\/\//

const normalizationOpts = {
    normalizeProtocol: true, // Prepend `http://` if URL is protocol-relative
    stripFragment: true, // Remove trailing hash fragment
    stripWWW: true, // Remove any leading `www.`
    removeTrailingSlash: true,
    removeQueryParameters: [/^utm_\w+/i], // Remove each of these query params (default for now)
    removeDirectoryIndex: [/^(default|index)\.\w{2,4}$/], // Remove things like tralining `/index.js` or `/default.php`
}

/**
 * Applies our custom query-param normalization rules for specific sites, removing all
 * but specific params from the query string.
 *
 * @param {string} url
 * @returns {string}
 */
function applyQueryParamsRules(url) {
    const parsed = new URL(url)
    const rulesObj = queryParamRules.get(parsed.hostname)

    // Base case; domain doesn't have any special normalization rules
    if (!rulesObj) {
        return url
    }

    // Remove all query params that don't appear in special rules
    const rulesSet = new Set(rulesObj.rules)
    const rulesType = rulesObj.type
    if (rulesType === 'keep') {
        for (const param of parsed.searchParams.keys()) {
            if (!rulesSet.has(param)) {
                parsed.searchParams.delete(param)
            }
        }
        return parsed.href
    }
    for (const param of rulesSet) {
        parsed.searchParams.delete(param)
    }
    return parsed.href
}

/**
 * NOTE: once normalized there is no way to recreate original input.
 *
 * @param {string} url
 * @param {any} [customNormalizationOpts={}] Custom options to pass to `normalize-url` package (will override).
 * @returns {string}
 */
function normalize(url, customOpts) {
    let normalized = normalizeUrl(url, {
        ...normalizationOpts,
        ...customOpts,
    })

    normalized = applyQueryParamsRules(normalized)

    // Remove the protocol; we don't need/want it for IDs
    return normalized.replace(PROTOCOL_PATTERN, '')
}

/**
 * Safely encodes a unicode URL to base64 string. More info on the safety with URLs
 * containing unicode chars here:
 * https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22
 *
 * @param {string} url
 * @param {boolean} needsEscaping
 * @returns {string}
 */
function encode(url, needsEscaping) {
    const escaped = encodeURIComponent(url) // Grab percent-encoded unicode chars (`%`)
        .replace(
        /%([0-9A-F]{2})/g, // Convert percentage-encodings into raw bytes
        (_, p1) => String.fromCharCode(`0x${p1}`),
    )

    // Feed in escaped unicode stuff into base64 encoder
    const encoded = btoa(escaped)
    return needsEscaping ? encodeURIComponent(encoded) : encoded
}

/**
 * Essentially goes backwards from the encode function.
 *
 * @param {string} encodedUrl URL that has been encoded via this module.
 * @param {boolean} needsEscaping Essentially the inverse of the same named param on encode method.
 * @returns {string} Original normalized URL.
 */
export function decode(encodedUrl, needsEscaping = true) {
    encodedUrl = needsEscaping ? decodeURIComponent(encodedUrl) : encodedUrl

    const percentageEncoded = atob(encodedUrl)
        .split('')
        .map(char => {
            // For each raw byte char, convert to percentage-encodings
            const unicodeChar = `00${char.charCodeAt(0).toString(16)}`.slice(-2)
            return `%${unicodeChar}`
        })
        .join('')

    return decodeURIComponent(percentageEncoded)
}

/**
 * Given a URL string, should apply normalization transformations to standardize URLs
 * in a consistent manner, along with encoding to base64 for use in a Pouch doc ID.
 * Base64 encoding should be safe for use with URLs containing unicode chars.
 *
 * Note that there are some normalization schemes proposed in RFC 3986 (describes general
 * syntax for URIs), however this module should contain only those transformations that
 * make sense for the WorldBrain web extension, as Pouch doc IDs.
 *
 * @param {string} url URL string to normalize and encode.
 * @param {boolean} needsEscaping Denotes whether or not encoded URL should be run through
 *  final `encodeURIComponent` call. Generally should be done if encoding to perform a lookup,
 *  as generated doc IDs will have been auto-escaped (via `docuri` package).
 * @param {any} [customNormalizationOpts={}] Custom options to pass to `normalize-url` package (will override).
 * @returns {string} Encoded URL ready for use in PouchID.
 */
function normalizeAndEncode(
    url,
    needsEscaping = true,
    customNormalizationOpts = {},
) {
    const normalizedUrl = normalize(url, customNormalizationOpts)
    return encode(normalizedUrl, needsEscaping)
}

export default normalizeAndEncode
<|endoftext|>


<commit_before>/*************************************************
 * User Data Functions - by panpawn              *
 *                                               *
 *  This system includes features that store:    *
 *   - last seen data                            *
 *   - economy (bucks)                           *
 *   - tells (offline messaging)                 *
 *   - and more!                                 *
 *************************************************/
'use strict';

const fs = require('fs');
const moment = require('moment');

Gold.userData = Object.create(null);

function loadUserData() {
	fs.readFile('config/goldusers.json', 'utf8', function (err, file) {
		if (err) return;
		Gold.userData = JSON.parse(file);
	});
};
loadUserData();

try {
	Object.assign(Gold, {

		/******************************
		 * Initialize User Functions  *
		 ******************************/
		createUser: function (user) { // doesn't save unless it gets edited
			user = toId(user);
			if (Gold.userData[user] || user === 'constructor') return false;
			if (user.substr(0, 5) === 'guest') return false;

			Gold.userData[user] = { // esteemed user data
				ips: [],
				tells: Object.create(null),
				friends: [],
				badges: [],
				tellNum: 0,
				money: 0,
				lastSeen: 0,
				color: false,
				icon: false,
				vip: false,
				status: '',
				friendcode: '',
			} // we don't save blank user data objects until next save
		},
		saveData: function () {
				fs.writeFileSync('config/goldusers.json', JSON.stringify(Gold.userData));
		}.throttle(1 * 1000), // only save once/second - TOPS
		initiateUser: function (user, ip) {	// when the user connections, this runs
			user = toId(user);
			if (!Gold.userData[user]) Gold.createUser(user);

			this.addIp(user, ip);
			this.updateSeen(user); // (saves)
		},
		checkExisting: function (user) {
			user = toId(user);
			if (!Gold.userData[user]) Gold.createUser(user);
			return Gold.userData[user];
		},

		/*********************
		 * Economy Functions *
		 *********************/
		updateMoney: function (user, amount) {
			user = toId(user);
			if (isNaN(amount)) return false;
			amount = Number(amount);

			let data = this.checkExisting(user);
			data.money = Number(data.money + amount);
			this.saveData();
		},
		readMoney: function (user) {
			user = toId(user);
			let data = this.checkExisting(user);
			return data.money;
		},
		moneyCirculating: function () {
			let data = Object.keys(Gold.userData);
			// [total bucks, average bucks, number of users with at least 1 money]
			let results = [0, 0, 0];

			data.forEach(user => {
				if (Gold.userData[user].money > 0) {
					if (isNaN(Gold.userData[user].money)) return;
					results[0] += Math.round(Number(Gold.userData[user].money));
					results[2]++;
				}
			});
			results[1] = Math.round(results[0] / results[2]);

			return results;
		},
		richestUsers: function (number) { // basically the heavy lifting for the command
			number = number > Gold.moneyCirculating()[2] ? Gold.moneyCirculating()[2] : number;
			let data = Object.keys(Gold.userData);
			let userids = new Array(0);
			let tableStyle = 'background: linear-gradient(10deg, #FFF8B5, #eadf7c, #FFF8B5); color: black; border: 1px solid #635b00; padding: 2px; border-radius: 5px; text-align:center;';
			let tdStyle = 'border-radius: 5px; border: 1px solid #635b00; background: #fff8b5; color: black;';
			let returnText = `${number > 10 ? '<div class="infobox-limited">' : '<div>'}<b>The top ${number} richest users are:</b><table style="${tableStyle}" border="1" cellspacing ="0" cellpadding="3">`;
			returnText += `<tr><td style="${tdStyle}"><b>Rank</b></td><td style="${tdStyle}"><b>Name</b></td><td style="${tdStyle}"><b>Bucks</b></td></tr>`;

			function ResultsArray (id, money) {
				this.id = id;
				this.money = money;
			}

			data.forEach(user => {
				if (Gold.userData[user].money > 0) {
					userids.push(new ResultsArray(user, Gold.userData[user].money));
				}
			});

			userids.sort(function (a, b) {
				return b.money - a.money;
			});

			for (let i = 0; i < number; i++) {
				if (userids[i]) returnText += `<tr><td style="${tdStyle}">${i + 1}.</td><td style="${tdStyle}">${Gold.nameColor(userids[i].id, true)}</td><td style="${tdStyle}">${userids[i].money}</td></tr>`;
			}
			returnText += '

';

			return returnText;
		},

		/*******************
		 * Misc. Functions *
		 *******************/
		hasVip: function (user) {
			user = toId(user);
			let data = this.checkExisting(user);
			if (!data.badges) data.badges = [];
			let vip = data.badges.includes('vip');
			return vip;
		},
		modifyBadge: function (user, badgeid, action) {
			user = toId(user);
			badgeid = toId(badgeid);

			let data = this.checkExisting(user);
			if (!data.badges) data.badges = [];

			if (action === 'GIVE') {
				if (data.badges.includes(badgeid)) return false;
				data.badges.push(badgeid);
			} else if (action === 'TAKE') {
				if (!data.badges.includes(badgeid)) return false;
				data.badges.remove(badgeid);
			} else {
				return false;
			}
			this.saveData();
		},
		badgeList: function (displayall) {
			// This houses the badges of the server.  You can add/modify/remove badges
			// here the with the same format as you see.
			let badgeList = {
				'dev': {
					title: 'Developer',
					img: 'http://www.smogon.com/media/forums/images/badges/factory_foreman.png',
				}, 'admin': {
					title: 'Server Administrator',
					img: 'http://www.smogon.com/media/forums/images/badges/sop.png',
				}, 'fgs': {
					title: 'Former Gold Staff',
					img: 'http://www.smogon.com/media/forums/images/badges/forummod_alum.png',
				}, 'leader': {
					title: 'Server Leader',
					img: 'http://www.smogon.com/media/forums/images/badges/aop.png',
				}, 'mod': {
					title: 'Exceptional Staff Member',
					img: 'http://www.smogon.com/media/forums/images/badges/pyramid_king.png',
				}, 'rf': {
					title: 'Successful Room Founder',
					img: 'http://www.smogon.com/media/forums/images/badges/forumsmod.png',
				}, 'comcun': {
					title: 'Community Contributor',
					img: 'http://www.smogon.com/media/forums/images/badges/cc.png',
				}, 'art': {
					title: 'Artist',
					img: 'http://www.smogon.com/media/forums/images/badges/ladybug.png',
				}, 'vip': {
					title: 'VIP User',
					img: 'http://www.smogon.com/media/forums/images/badges/zeph.png',
				}, 'twinner': {
					title: 'Event Tournament Winner',
					img: 'http://www.smogon.com/media/forums/images/badges/spl.png',
				}, 'creator': {
					title: 'Server Creator',
					img: 'http://www.smogon.com/media/forums/images/badges/dragon.png',
				}
			};
			if (displayall) {
				let buff = [];
				Object.keys(badgeList).forEach(badge => {
					buff.push(`<img src="${badgeList[badge].img}" title="${badgeList[badge].title}">`);
				});
				return buff.join(" | ");
			}
			return badgeList;
		},
		displayBadges: function (user) {
			user = toId(user);
			let data = this.checkExisting(user), buff = [];
			if (!data.badges || data.badges.length < 0) return false;

			let badgeObj = this.badgeList();
			let badgeList = Object.keys(badgeObj);
			badgeList.forEach(badge => {
				if (data.badges.includes(badge)) buff.push(`<img src="${badgeObj[badge].img}" title="${badgeObj[badge].title}">`);
			});
			return buff.join(" ");
		},
		customColor: function (user, action, color) {
			user = toId(user);
			let data = this.checkExisting(user);
			if (!data.color) data.color = '';

			if (action === 'GIVE') {
				data.color = color;
			} else if (action === 'REMOVE') {
				data.color = false;
			} else {
				return false;
			}

			this.saveData();
		},
		customIcon: function (user, action, icon) {
			user = toId(user);
			let data = this.checkExisting(user);
			if (!data.icon) data.icon = '';

			if (action === 'GIVE') {
				data.icon = icon;
			} else if (action === 'REMOVE') {
				data.icon = false;
			} else {
				return false;
			}

			this.saveData();
		},
		addIp: function (user, ip) { // sub-function of initialize user
			user = toId(user);
			if (user.substr(0, 5) === 'guest') return false;

			let data = this.checkExisting(user);
			if (!data.ips) data.ips = [];

			if (!data.ips.includes(ip)) data.ips.push(ip);
		},
		updateSeen: function (user) {
			user = toId(user);
			if (user.substr(0, 5) === 'guest') return false;

			let data = Gold.userData[user];
			if (!data) this.createUser(user);

			data.lastSeen = Date.now();
			this.saveData();
		},
		updateFriends: function (user, friend, action) {
			user = toId(user), friend = toId(friend);
			let data = this.checkExisting(user);
			if (!data.friends) data.friends = [];

			if (action === 'ADD') {
				if (!data.friends.includes(friend))data.friends.push(friend);
			} else if (action === 'DELETE') {
				if (data.friends.includes(friend)) data.friends.remove(friend);
			} else {
				return false;
			}

			this.saveData();
		},
		createTell: function (user, reciever, message) { // heavy lifting for /tell
			let userName = user;
			reciever = toId(reciever);
			user = toId(user);
			message = Gold.emoticons.processEmoticons(Tools.escapeHTML(message)).replace(///g, '/');

			let data = this.checkExisting(reciever);
			if (!data.tells) data.tells = Object.create(null);
			let tells = data.tells;

			message = Gold.formatMessage(message); // Add PS formatting

			let date = `${moment().format('MMMM Do YYYY, h:mm A')} EST`;
			let tell = `<u>${date}</u><br />${Gold.nameColor(userName, true)} said: ${message}`;

			Gold.userData[user].tellNum++;
			tells[`${user}#${Gold.userData[user].tellNum}`] = tell;
			this.saveData();
		},
		checkTells: function (user) {
			user = toId(user);
			let reply = [];
			if (Gold.userData[user]) {
				if (Object.keys(Gold.userData[user].tells).length > 0) {
					for (let i in Gold.userData[user].tells) {
						reply.push(`|raw|${Gold.userData[user].tells[i]}`);
						delete Gold.userData[user].tells[i];
					}
				}
			}
			if (reply.length > 0) this.saveData();
			if (reply.length === 0) return false;
			return reply;
		},
	});
} catch (e) {
	let staff = Rooms('staff');
	if (staff) staff.add(`|html|<div class="broadcast-red"><b>CUSTOM PS FUNCTIONALITY HAS CRASHED:</b><br />${e.stack}<br /><br /><b>Please report this to a developer... so panpawn.`).update();
}
<commit_msg>Bug fix economy issue in richest user command<commit_after>/*************************************************
 * User Data Functions - by panpawn              *
 *                                               *
 *  This system includes features that store:    *
 *   - last seen data                            *
 *   - economy (bucks)                           *
 *   - tells (offline messaging)                 *
 *   - and more!                                 *
 *************************************************/
'use strict';

const fs = require('fs');
const moment = require('moment');

Gold.userData = Object.create(null);

function loadUserData() {
	fs.readFile('config/goldusers.json', 'utf8', function (err, file) {
		if (err) return;
		Gold.userData = JSON.parse(file);
	});
};
loadUserData();

try {
	Object.assign(Gold, {

		/******************************
		 * Initialize User Functions  *
		 ******************************/
		createUser: function (user) { // doesn't save unless it gets edited
			user = toId(user);
			if (Gold.userData[user] || user === 'constructor') return false;
			if (user.substr(0, 5) === 'guest') return false;

			Gold.userData[user] = { // esteemed user data
				ips: [],
				tells: Object.create(null),
				friends: [],
				badges: [],
				tellNum: 0,
				money: 0,
				lastSeen: 0,
				color: false,
				icon: false,
				vip: false,
				status: '',
				friendcode: '',
			} // we don't save blank user data objects until next save
		},
		saveData: function () {
				fs.writeFileSync('config/goldusers.json', JSON.stringify(Gold.userData));
		}.throttle(1 * 1000), // only save once/second - TOPS
		initiateUser: function (user, ip) {	// when the user connections, this runs
			user = toId(user);
			if (!Gold.userData[user]) Gold.createUser(user);

			this.addIp(user, ip);
			this.updateSeen(user); // (saves)
		},
		checkExisting: function (user) {
			user = toId(user);
			if (!Gold.userData[user]) Gold.createUser(user);
			return Gold.userData[user];
		},

		/*********************
		 * Economy Functions *
		 *********************/
		updateMoney: function (user, amount) {
			user = toId(user);
			if (isNaN(amount)) return false;
			amount = Number(amount);

			let data = this.checkExisting(user);
			data.money = Number(data.money + amount);
			this.saveData();
		},
		readMoney: function (user) {
			user = toId(user);
			let data = this.checkExisting(user);
			return data.money;
		},
		moneyCirculating: function () {
			let data = Object.keys(Gold.userData);
			// [total bucks, average bucks, number of users with at least 1 money]
			let results = [0, 0, 0];

			data.forEach(user => {
				if (Gold.userData[user].money > 0) {
					if (isNaN(Gold.userData[user].money)) return;
					results[0] += Math.round(Number(Gold.userData[user].money));
					results[2]++;
				}
			});
			results[1] = Math.round(results[0] / results[2]);

			return results;
		},
		richestUsers: function (number) { // basically the heavy lifting for the command
			number = number > Gold.moneyCirculating()[2] ? Gold.moneyCirculating()[2] : number;
			let data = Object.keys(Gold.userData);
			let userids = new Array(0);
			let tableStyle = 'background: linear-gradient(10deg, #FFF8B5, #eadf7c, #FFF8B5); color: black; border: 1px solid #635b00; padding: 2px; border-radius: 5px; text-align:center;';
			let tdStyle = 'border-radius: 5px; border: 1px solid #635b00; background: #fff8b5; color: black;';
			let returnText = `${number > 10 ? '<div class="infobox-limited">' : '<div>'}<b>The top ${number} richest users are:</b><table style="${tableStyle}" border="1" cellspacing ="0" cellpadding="3">`;
			returnText += `<tr><td style="${tdStyle}"><b>Rank</b></td><td style="${tdStyle}"><b>Name</b></td><td style="${tdStyle}"><b>Bucks</b></td></tr>`;

			function ResultsArray (id, money) {
				this.id = id;
				this.money = money;
			}

			data.forEach(user => {
				if (Gold.userData[user].money > 0) {
					if (Gold.userData[user].money === null || isNaN(Gold.userData[user].money)) return; // this should never happen... *coughs*
					userids.push(new ResultsArray(user, Gold.userData[user].money));
				}
			});

			userids.sort(function (a, b) {
				return b.money - a.money;
			});

			for (let i = 0; i < number; i++) {
				if (userids[i]) returnText += `<tr><td style="${tdStyle}">${i + 1}.</td><td style="${tdStyle}">${Gold.nameColor(userids[i].id, true)}</td><td style="${tdStyle}">${userids[i].money}</td></tr>`;
			}
			returnText += '

';

			return returnText;
		},

		/*******************
		 * Misc. Functions *
		 *******************/
		hasVip: function (user) {
			user = toId(user);
			let data = this.checkExisting(user);
			if (!data.badges) data.badges = [];
			let vip = data.badges.includes('vip');
			return vip;
		},
		modifyBadge: function (user, badgeid, action) {
			user = toId(user);
			badgeid = toId(badgeid);

			let data = this.checkExisting(user);
			if (!data.badges) data.badges = [];

			if (action === 'GIVE') {
				if (data.badges.includes(badgeid)) return false;
				data.badges.push(badgeid);
			} else if (action === 'TAKE') {
				if (!data.badges.includes(badgeid)) return false;
				data.badges.remove(badgeid);
			} else {
				return false;
			}
			this.saveData();
		},
		badgeList: function (displayall) {
			// This houses the badges of the server.  You can add/modify/remove badges
			// here the with the same format as you see.
			let badgeList = {
				'dev': {
					title: 'Developer',
					img: 'http://www.smogon.com/media/forums/images/badges/factory_foreman.png',
				}, 'admin': {
					title: 'Server Administrator',
					img: 'http://www.smogon.com/media/forums/images/badges/sop.png',
				}, 'fgs': {
					title: 'Former Gold Staff',
					img: 'http://www.smogon.com/media/forums/images/badges/forummod_alum.png',
				}, 'leader': {
					title: 'Server Leader',
					img: 'http://www.smogon.com/media/forums/images/badges/aop.png',
				}, 'mod': {
					title: 'Exceptional Staff Member',
					img: 'http://www.smogon.com/media/forums/images/badges/pyramid_king.png',
				}, 'rf': {
					title: 'Successful Room Founder',
					img: 'http://www.smogon.com/media/forums/images/badges/forumsmod.png',
				}, 'comcun': {
					title: 'Community Contributor',
					img: 'http://www.smogon.com/media/forums/images/badges/cc.png',
				}, 'art': {
					title: 'Artist',
					img: 'http://www.smogon.com/media/forums/images/badges/ladybug.png',
				}, 'vip': {
					title: 'VIP User',
					img: 'http://www.smogon.com/media/forums/images/badges/zeph.png',
				}, 'twinner': {
					title: 'Event Tournament Winner',
					img: 'http://www.smogon.com/media/forums/images/badges/spl.png',
				}, 'creator': {
					title: 'Server Creator',
					img: 'http://www.smogon.com/media/forums/images/badges/dragon.png',
				}
			};
			if (displayall) {
				let buff = [];
				Object.keys(badgeList).forEach(badge => {
					buff.push(`<img src="${badgeList[badge].img}" title="${badgeList[badge].title}">`);
				});
				return buff.join(" | ");
			}
			return badgeList;
		},
		displayBadges: function (user) {
			user = toId(user);
			let data = this.checkExisting(user), buff = [];
			if (!data.badges || data.badges.length < 0) return false;

			let badgeObj = this.badgeList();
			let badgeList = Object.keys(badgeObj);
			badgeList.forEach(badge => {
				if (data.badges.includes(badge)) buff.push(`<img src="${badgeObj[badge].img}" title="${badgeObj[badge].title}">`);
			});
			return buff.join(" ");
		},
		customColor: function (user, action, color) {
			user = toId(user);
			let data = this.checkExisting(user);
			if (!data.color) data.color = '';

			if (action === 'GIVE') {
				data.color = color;
			} else if (action === 'REMOVE') {
				data.color = false;
			} else {
				return false;
			}

			this.saveData();
		},
		customIcon: function (user, action, icon) {
			user = toId(user);
			let data = this.checkExisting(user);
			if (!data.icon) data.icon = '';

			if (action === 'GIVE') {
				data.icon = icon;
			} else if (action === 'REMOVE') {
				data.icon = false;
			} else {
				return false;
			}

			this.saveData();
		},
		addIp: function (user, ip) { // sub-function of initialize user
			user = toId(user);
			if (user.substr(0, 5) === 'guest') return false;

			let data = this.checkExisting(user);
			if (!data.ips) data.ips = [];

			if (!data.ips.includes(ip)) data.ips.push(ip);
		},
		updateSeen: function (user) {
			user = toId(user);
			if (user.substr(0, 5) === 'guest') return false;

			let data = Gold.userData[user];
			if (!data) this.createUser(user);

			data.lastSeen = Date.now();
			this.saveData();
		},
		updateFriends: function (user, friend, action) {
			user = toId(user), friend = toId(friend);
			let data = this.checkExisting(user);
			if (!data.friends) data.friends = [];

			if (action === 'ADD') {
				if (!data.friends.includes(friend))data.friends.push(friend);
			} else if (action === 'DELETE') {
				if (data.friends.includes(friend)) data.friends.remove(friend);
			} else {
				return false;
			}

			this.saveData();
		},
		createTell: function (user, reciever, message) { // heavy lifting for /tell
			let userName = user;
			reciever = toId(reciever);
			user = toId(user);
			message = Gold.emoticons.processEmoticons(Tools.escapeHTML(message)).replace(///g, '/');

			let data = this.checkExisting(reciever);
			if (!data.tells) data.tells = Object.create(null);
			let tells = data.tells;

			message = Gold.formatMessage(message); // Add PS formatting

			let date = `${moment().format('MMMM Do YYYY, h:mm A')} EST`;
			let tell = `<u>${date}</u><br />${Gold.nameColor(userName, true)} said: ${message}`;

			Gold.userData[user].tellNum++;
			tells[`${user}#${Gold.userData[user].tellNum}`] = tell;
			this.saveData();
		},
		checkTells: function (user) {
			user = toId(user);
			let reply = [];
			if (Gold.userData[user]) {
				if (Object.keys(Gold.userData[user].tells).length > 0) {
					for (let i in Gold.userData[user].tells) {
						reply.push(`|raw|${Gold.userData[user].tells[i]}`);
						delete Gold.userData[user].tells[i];
					}
				}
			}
			if (reply.length > 0) this.saveData();
			if (reply.length === 0) return false;
			return reply;
		},
	});
} catch (e) {
	let staff = Rooms('staff');
	if (staff) staff.add(`|html|<div class="broadcast-red"><b>CUSTOM PS FUNCTIONALITY HAS CRASHED:</b><br />${e.stack}<br /><br /><b>Please report this to a developer... so panpawn.`).update();
}
<|endoftext|>


<commit_before>var applicationMock;
var ApplicationMock = Ember.Object.extend();

var containerMock;
var ContainerMock = Ember.Object.extend({
  init: function() {
    this.registrations = {};
    this.injections = [];
  },
  register: function(name, factory, options) {
    this.registrations[name] = {
      factory: factory,
      options: options
    };
  },
  inject: function(target, property, name) {
    var registration = this.registrations[name];
    if (registration) {
      this.injections.push({
        target:   target,
        property: property,
        object:   registration.factory
      });
    }
  }
});

var authorizerMock;
var AuthorizerMock = Ember.Object.extend({
  authorize: function() {
    this.authorized = true;
  }
});
AuthorizerMock.reopenClass({
  create: function(options) {
    return (authorizerMock = this._super(options));
  }
});

var ajaxPrefilterMock;
var AjaxPrefilterMock = Ember.Object.extend({
  ajaxPrefilterCapture: function(prefilter) {
    this.registeredAjaxPrefilter = prefilter;
  }
});

module('Ember.SimpleAuth', {
  originalAjaxPrefilter: Ember.$.ajaxPrefilter,
  setup: function() {
    applicationMock       = ApplicationMock.create();
    containerMock         = ContainerMock.create();
    ajaxPrefilterMock     = AjaxPrefilterMock.create();
    Ember.$.ajaxPrefilter = Ember.$.proxy(ajaxPrefilterMock.ajaxPrefilterCapture, ajaxPrefilterMock);
  },
  teardown: function() {
    Ember.$.ajaxPrefilter = this.originalAjaxPrefilter;
    Ember.run.cancel(Ember.SimpleAuth.Session._syncPropertiesTimeout);
  }
});

test('assigns the authentication route', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { authenticationRoute: 'somewhere' });

  equal(Ember.SimpleAuth.authenticationRoute, 'somewhere', 'Ember.SimpleAuth assigns authenticationRoute when specified for setup.');
});

test('assigns the route after authentication', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { routeAfterAuthentication: 'somewhere' });

  equal(Ember.SimpleAuth.routeAfterAuthentication, 'somewhere', 'Ember.SimpleAuth assigns routeAfterAuthentication when specified for setup.');
});

test('assigns the route after session invalidation', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { routeAfterInvalidation: 'somewhere' });

  equal(Ember.SimpleAuth.routeAfterInvalidation, 'somewhere', 'Ember.SimpleAuth assigns routeAfterInvalidation when specified for setup.');
});

test('injects the session in models, views, controllers and routes', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock);

  Ember.$.each(['model', 'view', 'controller', 'view'], function(i, component) {
    var injection = Ember.$.grep(containerMock.injections, function(injection) {
      return injection.target === component;
    })[0];

    equal(injection.object.constructor, Ember.SimpleAuth.Session, 'Ember.SimpleAuth injects the session into ' + component + '.');
    equal(injection.property, 'session', 'Ember.SimpleAuth makes the session available as "session" in ' + component + '.');
  });
});

test('assigns the store and container to the session', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { store: Ember.SimpleAuth.Stores.Ephemeral });

  var session = containerMock.injections[0].object;

  equal(session.container, containerMock, 'Ember.SimpleAuth assigns the container to the session.');
  equal(session.store.constructor, Ember.SimpleAuth.Stores.Ephemeral, 'Ember.SimpleAuth assigns the correct store to the session.');
});

test('registers an AJAX prefilter that authorizes requests', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { authorizer: AuthorizerMock });

  ajaxPrefilterMock.registeredAjaxPrefilter({}, {}, {});
  ok(authorizerMock.authorized, "Ember.SimpleAuth registers an AJAX prefilter that authorizes requests that fo the the application's origin.");

  authorizerMock.authorized = false;
  ajaxPrefilterMock.registeredAjaxPrefilter({ url: 'https://a.different.domain:1234' }, {}, {});
  ok(!authorizerMock.authorized, 'Ember.SimpleAuth registers an AJAX prefilter that does not authorize cross-origin requests.');

  Ember.SimpleAuth.setup(containerMock, applicationMock, { crossOriginWhitelist: ['https://a.different.domain:1234'], authorizer: AuthorizerMock, store: Ember.SimpleAuth.Stores.Ephemeral });
  ajaxPrefilterMock.registeredAjaxPrefilter({ url: 'https://a.different.domain:1234' }, {}, {});
  ok(authorizerMock.authorized, 'Ember.SimpleAuth registers an AJAX prefilter that authorizes cross-origin requests when the origin is in the crossOriginWhitelist.');
});
<commit_msg>no need to cancel the timeout<commit_after>var applicationMock;
var ApplicationMock = Ember.Object.extend();

var containerMock;
var ContainerMock = Ember.Object.extend({
  init: function() {
    this.registrations = {};
    this.injections = [];
  },
  register: function(name, factory, options) {
    this.registrations[name] = {
      factory: factory,
      options: options
    };
  },
  inject: function(target, property, name) {
    var registration = this.registrations[name];
    if (registration) {
      this.injections.push({
        target:   target,
        property: property,
        object:   registration.factory
      });
    }
  }
});

var authorizerMock;
var AuthorizerMock = Ember.Object.extend({
  authorize: function() {
    this.authorized = true;
  }
});
AuthorizerMock.reopenClass({
  create: function(options) {
    return (authorizerMock = this._super(options));
  }
});

var ajaxPrefilterMock;
var AjaxPrefilterMock = Ember.Object.extend({
  ajaxPrefilterCapture: function(prefilter) {
    this.registeredAjaxPrefilter = prefilter;
  }
});

module('Ember.SimpleAuth', {
  originalAjaxPrefilter: Ember.$.ajaxPrefilter,
  setup: function() {
    applicationMock       = ApplicationMock.create();
    containerMock         = ContainerMock.create();
    ajaxPrefilterMock     = AjaxPrefilterMock.create();
    Ember.$.ajaxPrefilter = Ember.$.proxy(ajaxPrefilterMock.ajaxPrefilterCapture, ajaxPrefilterMock);
  },
  teardown: function() {
    Ember.$.ajaxPrefilter = this.originalAjaxPrefilter;
  }
});

test('assigns the authentication route', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { authenticationRoute: 'somewhere' });

  equal(Ember.SimpleAuth.authenticationRoute, 'somewhere', 'Ember.SimpleAuth assigns authenticationRoute when specified for setup.');
});

test('assigns the route after authentication', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { routeAfterAuthentication: 'somewhere' });

  equal(Ember.SimpleAuth.routeAfterAuthentication, 'somewhere', 'Ember.SimpleAuth assigns routeAfterAuthentication when specified for setup.');
});

test('assigns the route after session invalidation', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { routeAfterInvalidation: 'somewhere' });

  equal(Ember.SimpleAuth.routeAfterInvalidation, 'somewhere', 'Ember.SimpleAuth assigns routeAfterInvalidation when specified for setup.');
});

test('injects the session in models, views, controllers and routes', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock);

  Ember.$.each(['model', 'view', 'controller', 'view'], function(i, component) {
    var injection = Ember.$.grep(containerMock.injections, function(injection) {
      return injection.target === component;
    })[0];

    equal(injection.object.constructor, Ember.SimpleAuth.Session, 'Ember.SimpleAuth injects the session into ' + component + '.');
    equal(injection.property, 'session', 'Ember.SimpleAuth makes the session available as "session" in ' + component + '.');
  });
});

test('assigns the store and container to the session', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { store: Ember.SimpleAuth.Stores.Ephemeral });

  var session = containerMock.injections[0].object;

  equal(session.container, containerMock, 'Ember.SimpleAuth assigns the container to the session.');
  equal(session.store.constructor, Ember.SimpleAuth.Stores.Ephemeral, 'Ember.SimpleAuth assigns the correct store to the session.');
});

test('registers an AJAX prefilter that authorizes requests', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { authorizer: AuthorizerMock });

  ajaxPrefilterMock.registeredAjaxPrefilter({}, {}, {});
  ok(authorizerMock.authorized, "Ember.SimpleAuth registers an AJAX prefilter that authorizes requests that fo the the application's origin.");

  authorizerMock.authorized = false;
  ajaxPrefilterMock.registeredAjaxPrefilter({ url: 'https://a.different.domain:1234' }, {}, {});
  ok(!authorizerMock.authorized, 'Ember.SimpleAuth registers an AJAX prefilter that does not authorize cross-origin requests.');

  Ember.SimpleAuth.setup(containerMock, applicationMock, { crossOriginWhitelist: ['https://a.different.domain:1234'], authorizer: AuthorizerMock, store: Ember.SimpleAuth.Stores.Ephemeral });
  ajaxPrefilterMock.registeredAjaxPrefilter({ url: 'https://a.different.domain:1234' }, {}, {});
  ok(authorizerMock.authorized, 'Ember.SimpleAuth registers an AJAX prefilter that authorizes cross-origin requests when the origin is in the crossOriginWhitelist.');
});
<|endoftext|>


<commit_before>const { Listener } = require('discord-akairo');

class MessageReactionAddListener extends Listener {
	constructor() {
		super('messageReactionAdd', {
			eventName: 'messageReactionAdd',
			emitter: 'client',
			category: 'client'
		});
	}

	async exec(reaction, user) {
		if (reaction.emoji.name === '⭐') {
			const starboard = this.client.starboards.get(reaction.message.guild.id);
			const error = await starboard.add(reaction.message, user);
			if (error) {
				await reaction.remove(user);
				reaction.message.channel.send(`${user}, ${error}`);
			}
		}
	}
}

module.exports = MessageReactionAddListener;
<commit_msg>Add permission check<commit_after>const { Listener } = require('discord-akairo');

class MessageReactionAddListener extends Listener {
	constructor() {
		super('messageReactionAdd', {
			eventName: 'messageReactionAdd',
			emitter: 'client',
			category: 'client'
		});
	}

	async exec(reaction, user) {
		if (reaction.emoji.name === '⭐') {
			const starboard = this.client.starboards.get(reaction.message.guild.id);
			const error = await starboard.add(reaction.message, user);
			if (error) {
				if (reaction.message.channel.permissionsFor(this.client.user).has('MANAGE_MESSAGES')) {
					await reaction.remove(user);
				}
				reaction.message.channel.send(`${user}, ${error}`);
			}
		}
	}
}

module.exports = MessageReactionAddListener;
<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const makeSerializable = require("../util/makeSerializable");
const NullDependency = require("./NullDependency");

/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */

class RequireResolveHeaderDependency extends NullDependency {
	constructor(range) {
		super();

		if (!Array.isArray(range)) throw new Error("range must be valid");

		this.range = range;
	}

	serialize(context) {
		const { write } = context;

		write(this.range);

		super.serialize(context);
	}

	deserialize(context) {
		const { read } = context;

		this.range = read();

		super.deserialize(context);
	}
}

makeSerializable(
	RequireResolveHeaderDependency,
	"webpack/lib/dependencies/RequireResolveHeaderDependency"
);

RequireResolveHeaderDependency.Template = class RequireResolveHeaderDependencyTemplate extends NullDependency.Template {
	/**
	 * @param {Dependency} dependency the dependency for which the template should be applied
	 * @param {ReplaceSource} source the current replace source which can be modified
	 * @param {DependencyTemplateContext} templateContext the context object
	 * @returns {void}
	 */
	apply(dependency, source, templateContext) {
		const dep = /** @type {RequireResolveHeaderDependency} */ (dependency);
		source.replace(dep.range[0], dep.range[1] - 1, "/*require.resolve*/");
	}

	applyAsTemplateArgument(name, dep, source) {
		source.replace(dep.range[0], dep.range[1] - 1, "/*require.resolve*/");
	}
};

module.exports = RequireResolveHeaderDependency;
<commit_msg>fix deserializing of RequireResolveHeaderDependency<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const makeSerializable = require("../util/makeSerializable");
const NullDependency = require("./NullDependency");

/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */

class RequireResolveHeaderDependency extends NullDependency {
	constructor(range) {
		super();

		if (!Array.isArray(range)) throw new Error("range must be valid");

		this.range = range;
	}

	serialize(context) {
		const { write } = context;

		write(this.range);

		super.serialize(context);
	}

	static deserialize(context) {
		const obj = new RequireResolveHeaderDependency(context.read());
		obj.deserialize(context);
		return obj;
	}
}

makeSerializable(
	RequireResolveHeaderDependency,
	"webpack/lib/dependencies/RequireResolveHeaderDependency"
);

RequireResolveHeaderDependency.Template = class RequireResolveHeaderDependencyTemplate extends NullDependency.Template {
	/**
	 * @param {Dependency} dependency the dependency for which the template should be applied
	 * @param {ReplaceSource} source the current replace source which can be modified
	 * @param {DependencyTemplateContext} templateContext the context object
	 * @returns {void}
	 */
	apply(dependency, source, templateContext) {
		const dep = /** @type {RequireResolveHeaderDependency} */ (dependency);
		source.replace(dep.range[0], dep.range[1] - 1, "/*require.resolve*/");
	}

	applyAsTemplateArgument(name, dep, source) {
		source.replace(dep.range[0], dep.range[1] - 1, "/*require.resolve*/");
	}
};

module.exports = RequireResolveHeaderDependency;
<|endoftext|>


<commit_before>/**
 * @flow
 * @format
 * @lint-ignore-every LINEWRAP1
 */

import {dirname, normalize, relative, resolve} from 'path';
import {format} from 'util';

import {exists, glob, readFile} from '../utils/async';
import Builder from './builder';
import {getTestsDir} from '../constants';
import Suite from './Suite';

import type {Tests} from './Tester';
import type {SuiteResult} from './runTestSuite';

const testSuiteRegex = /(.*)[\/\\]test.js/;

async function findTestSuites(): Promise<Array<string>> {
  const testsDir = getTestsDir();
  const testSuites = await glob(format('%s/**/test.js', testsDir), {
    cwd: __dirname,
    ignore: format('%s/lsp/diagnostics/test.js', testsDir),
  });
  // On Windows, glob still uses unix dir seperators, so we need to normalize
  return testSuites.map(normalize);
}

export async function findTestsByName(
  suitesOrig: ?Set<string>,
): Promise<Set<string>> {
  let suites = null;
  if (suitesOrig != null) {
    suites = new Set();
    for (let suite of suitesOrig) {
      suite = normalize(suite.trim());
      suites.add(suite);
      suites.add(resolve(suite));
    }
  }
  const testsDir = getTestsDir();
  const testSuites = await findTestSuites();

  const result = new Set();

  process.stderr.write(format('Found %d suites\n', testSuites.length));
  for (const suiteFile of testSuites) {
    const suiteName = relative(testsDir, suiteFile).replace(
      testSuiteRegex,
      '$1',
    );
    const pathToDir = dirname(suiteFile);
    if (
      !suites ||
      suites.has(suiteName) ||
      suites.has(suiteFile) ||
      suites.has(pathToDir)
    ) {
      result.add(suiteName);
    }
  }

  return result;
}

function loadSuiteByFilename(filename: string): Suite {
  delete require.cache[require.resolve(filename)];
  const {default: suite} = (require: any)(filename);
  // I don't know why, but suite instanceof Suite doesn't seem to work when
  // using symlinks. So this is a fuzzy approximation
  if (!(suite && suite.constructor && suite.constructor.name === Suite.name)) {
    throw new Error(
      format('Test suite `%s` forgot to export default suite(...)', filename),
    );
  }
  return suite;
}

export function loadSuite(suiteName: string): Suite {
  return loadSuiteByFilename(resolve(getTestsDir(), suiteName, 'test.js'));
}

export async function findTestsByRun(
  runID: string,
  failedOnly: boolean,
): Promise<Set<string>> {
  const runDir = Builder.getDirForRun(runID);
  const runDirExists = await exists(runDir);

  if (!runID || !runDirExists) {
    process.stderr.write(
      format("Cannot find the tmp directory for run '%s'.\n", runID),
    );
    return new Set();
  }

  const results = await glob(format('%s/*/results.json', runDir), {
    cwd: __dirname,
  });

  let resultContents = await Promise.all(
    results.map(async filename => {
      const rawContents = await readFile(filename);
      try {
        return JSON.parse(rawContents);
      } catch (e) {
        throw new Error(
          format('Error parsing run %s result %s:\n%s', runID, filename, e),
        );
      }
    }),
  );

  if (failedOnly) {
    resultContents = resultContents.filter(contents => {
      const suiteResult: SuiteResult = contents.results;
      if (suiteResult.type === 'exceptional') {
        return true;
      } else if (suiteResult.type === 'normal') {
        return suiteResult.testResults.some(testResult =>
          testResult.stepResults.some(stepResult => !stepResult.passed),
        );
      }
    });
  }

  const suites = new Set(resultContents.map(contents => contents.suiteName));

  process.stderr.write(
    format(
      'Looks like run %s ran %d suites%s\n',
      runID,
      suites.size,
      failedOnly ? ' that failed' : '',
    ),
  );

  return findTestsByName(suites);
}
<commit_msg>Back out "[flow] Disable lsp/diagnostics"<commit_after>/**
 * @flow
 * @format
 * @lint-ignore-every LINEWRAP1
 */

import {dirname, normalize, relative, resolve} from 'path';
import {format} from 'util';

import {exists, glob, readFile} from '../utils/async';
import Builder from './builder';
import {getTestsDir} from '../constants';
import Suite from './Suite';

import type {Tests} from './Tester';
import type {SuiteResult} from './runTestSuite';

const testSuiteRegex = /(.*)[\/\\]test.js/;

async function findTestSuites(): Promise<Array<string>> {
  const testSuites = await glob(format('%s/**/test.js', getTestsDir()), {
    cwd: __dirname,
  });
  // On Windows, glob still uses unix dir seperators, so we need to normalize
  return testSuites.map(normalize);
}

export async function findTestsByName(
  suitesOrig: ?Set<string>,
): Promise<Set<string>> {
  let suites = null;
  if (suitesOrig != null) {
    suites = new Set();
    for (let suite of suitesOrig) {
      suite = normalize(suite.trim());
      suites.add(suite);
      suites.add(resolve(suite));
    }
  }
  const testsDir = getTestsDir();
  const testSuites = await findTestSuites();

  const result = new Set();

  process.stderr.write(format('Found %d suites\n', testSuites.length));
  for (const suiteFile of testSuites) {
    const suiteName = relative(testsDir, suiteFile).replace(
      testSuiteRegex,
      '$1',
    );
    const pathToDir = dirname(suiteFile);
    if (
      !suites ||
      suites.has(suiteName) ||
      suites.has(suiteFile) ||
      suites.has(pathToDir)
    ) {
      result.add(suiteName);
    }
  }

  return result;
}

function loadSuiteByFilename(filename: string): Suite {
  delete require.cache[require.resolve(filename)];
  const {default: suite} = (require: any)(filename);
  // I don't know why, but suite instanceof Suite doesn't seem to work when
  // using symlinks. So this is a fuzzy approximation
  if (!(suite && suite.constructor && suite.constructor.name === Suite.name)) {
    throw new Error(
      format('Test suite `%s` forgot to export default suite(...)', filename),
    );
  }
  return suite;
}

export function loadSuite(suiteName: string): Suite {
  return loadSuiteByFilename(resolve(getTestsDir(), suiteName, 'test.js'));
}

export async function findTestsByRun(
  runID: string,
  failedOnly: boolean,
): Promise<Set<string>> {
  const runDir = Builder.getDirForRun(runID);
  const runDirExists = await exists(runDir);

  if (!runID || !runDirExists) {
    process.stderr.write(
      format("Cannot find the tmp directory for run '%s'.\n", runID),
    );
    return new Set();
  }

  const results = await glob(format('%s/*/results.json', runDir), {
    cwd: __dirname,
  });

  let resultContents = await Promise.all(
    results.map(async filename => {
      const rawContents = await readFile(filename);
      try {
        return JSON.parse(rawContents);
      } catch (e) {
        throw new Error(
          format('Error parsing run %s result %s:\n%s', runID, filename, e),
        );
      }
    }),
  );

  if (failedOnly) {
    resultContents = resultContents.filter(contents => {
      const suiteResult: SuiteResult = contents.results;
      if (suiteResult.type === 'exceptional') {
        return true;
      } else if (suiteResult.type === 'normal') {
        return suiteResult.testResults.some(testResult =>
          testResult.stepResults.some(stepResult => !stepResult.passed),
        );
      }
    });
  }

  const suites = new Set(resultContents.map(contents => contents.suiteName));

  process.stderr.write(
    format(
      'Looks like run %s ran %d suites%s\n',
      runID,
      suites.size,
      failedOnly ? ' that failed' : '',
    ),
  );

  return findTestsByName(suites);
}
<|endoftext|>


<commit_before><commit_msg>just a blank text cell extension placeholder<commit_after>/*
  backgrid
  http://github.com/wyuenho/backgrid

  Copyright (c) 2012 Jimmy Yuen Ho Wong
  Licensed under the MIT @license.
*/

<|endoftext|>


<commit_before>// @flow
'use strict';
var exampleVfrCharts = [
  {
    regionName: 'Albuquerque',
    regionId: 'ALB',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: true,
    uniqueId: 0,
  },
  {
    regionName: 'Anchorage',
    regionId: 'ANC',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 1,
  },
  {
    regionName: 'Atlanta',
    regionId: 'ATL',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 2,
  },
  {
    regionName: 'Bethel',
    regionId: 'BET',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 3,
  },
  {
    regionName: 'Billings',
    regionId: 'BIL',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 4,
  },
  {
    regionName: 'Denver',
    regionId: 'DEN',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 5,
  },
  {
    regionName: 'Detroit',
    regionId: 'DET',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 6,
  },
  {
    regionName: 'Dutch Harbor',
    regionId: 'DUT',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: true,
    uniqueId: 7,
  },
  {
    regionName: 'Great Falls',
    regionId: 'GF',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 8,
  },
  {
    regionName: 'Halifax',
    regionId: 'HAL',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 9,
  },
  {
    regionName: 'Jacksonville',
    regionId: 'JAC',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 10,
  },
  {
    regionName: 'Juneau',
    regionId: 'JUN',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 11,
  },
  {
    regionName: 'Ketchikan',
    regionId: 'KET',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: true,
    uniqueId: 12,
  },
  {
    regionName: 'Kodiak',
    regionId: 'KOD',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 13,
  },
  {
    regionName: 'Klamath Falls',
    regionId: 'KF',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 14,
  },
  {
    regionName: 'Seattle',
    regionId: 'SEA',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 15,
  }
];
const getSavedCharts = () => {
  // this is where we will load our charts from disk, for now populate with this list
  return exampleVfrCharts;
};

export { getSavedCharts };
<commit_msg>Fetch chart tiles for a region, unzip them, and store in the file system<commit_after>// @flow
'use strict';

import RNFetchBlob from 'react-native-fetch-blob';
import ZipArchive from 'react-native-zip-archive';

const fs = RNFetchBlob.fs;
const servicesEndpoint = 'http://192.168.0.11:8888';

var exampleVfrCharts = [
  {
    regionName: 'Albuquerque',
    regionId: 'ALB',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: true,
    uniqueId: 0,
  },
  {
    regionName: 'Anchorage',
    regionId: 'ANC',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 1,
  },
  {
    regionName: 'Atlanta',
    regionId: 'ATL',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 2,
  },
  {
    regionName: 'Bethel',
    regionId: 'BET',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 3,
  },
  {
    regionName: 'Billings',
    regionId: 'BIL',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 4,
  },
  {
    regionName: 'Denver',
    regionId: 'DEN',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 5,
  },
  {
    regionName: 'Detroit',
    regionId: 'DET',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 6,
  },
  {
    regionName: 'Dutch Harbor',
    regionId: 'DUT',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: true,
    uniqueId: 7,
  },
  {
    regionName: 'Great Falls',
    regionId: 'GF',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 8,
  },
  {
    regionName: 'Halifax',
    regionId: 'HAL',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 9,
  },
  {
    regionName: 'Jacksonville',
    regionId: 'JAC',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 10,
  },
  {
    regionName: 'Juneau',
    regionId: 'JUN',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 11,
  },
  {
    regionName: 'Ketchikan',
    regionId: 'KET',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: true,
    uniqueId: 12,
  },
  {
    regionName: 'Kodiak',
    regionId: 'KOD',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 13,
  },
  {
    regionName: 'Klamath Falls',
    regionId: 'KF',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 14,
  },
  {
    regionName: 'Seattle',
    regionId: 'SEA',
    publicationDate: new Date('2016-01-29'),
    expirationDate: new Date('2016-12-05'),
    revisionNumber: 0,
    chartUrl: 'https://www.google.com',
    filePath: '',
    isFavorited: false,
    uniqueId: 15,
  }
];
const getSavedCharts = () => {
  // this is where we will load our charts from disk, for now populate with this list
  return exampleVfrCharts;
};

async function fetchAndProcessTiles(regionId) {
  if (!regionId || regionId === '')
    return;

  try {
    console.log(`Request tiles for reqion id: ${regionId}`);
    const response = await RNFetchBlob.fetch('GET', `${servicesEndpoint}/charts/${regionId}/zip`);

    let status = response.info().status;
    if (status !== 200) {
      console.warn(`Request for ${regionId} failed with code ${status}`);
      return;
    }

    console.log(`Saving ${regionId}.zip`);
    const zipPath = `${RNFetchBlob.fs.dirs.DocumentDir}/${regionId}.zip`;
    const responseBlob = await response.base64();
    await fs.createFile(zipPath, responseBlob, 'base64');

    const unzippedTilesPath = `${fs.dirs.DocumentDir}/${regionId}/`;
    let exists = await fs.exists(unzippedTilesPath);
    if (exists) {
      console.log(`Unzipped tiles already exist; removing them.`);
      await fs.unlink(unzippedTilesPath);
    }

    console.log(`Unzipping ${regionId}.zip`);
    await ZipArchive.unzip(zipPath, unzippedTilesPath);

    console.log(`Removing ${regionId}.zip`);
    await fs.unlink(zipPath);
  } catch(error) {
    console.warn(`Error getting chart tiles for ${regionId}: ${error}`);
  }
}

export { getSavedCharts, fetchAndProcessTiles };
<|endoftext|>


<commit_before>import navConfig from './nav.config.json';
import langs from './i18n/route.json';

const registerRoute = (navConfig) => {
  let route = [];
  Object.keys(navConfig).forEach((lang, index) => {
    let navs = navConfig[lang];
    route.push({
      path: `/${ lang }/component`,
      redirect: `/${ lang }/component/installation`,
      component: require(`./pages/${ lang }/component.vue`),
      children: []
    });
    navs.forEach(nav => {
      if (nav.groups) {
        nav.groups.forEach(group => {
          group.list.forEach(nav => {
            addRoute(nav, lang, index);
          });
        });
      } else if (nav.children) {
        nav.children.forEach(nav => {
          addRoute(nav, lang, index);
        });
      } else {
        addRoute(nav, lang, index);
      }
    });
  });
  function addRoute(page, lang, index) {
    const component = page.path === '/changelog'
      ? require(`./pages/${ lang }/changelog.vue`)
      : require(`./docs/${ lang }${page.path}.md`);
    let child = {
      path: page.path.slice(1),
      meta: {
        title: page.title || page.name,
        description: page.description,
        lang
      },
      component: component.default || component
    };

    route[index].children.push(child);
  }

  return route;
};

let route = registerRoute(navConfig);

const generateMiscRoutes = function(lang) {
  let guideRoute = {
    path: `/${ lang }/guide`, // 指南
    redirect: `/${ lang }/guide/design`,
    component: require(`./pages/${ lang }/guide.vue`),
    children: [{
      path: 'design', // 设计原则
      meta: { lang },
      component: require(`./pages/${ lang }/design.vue`)
    }, {
      path: 'nav', // 导航
      meta: { lang },
      component: require(`./pages/${ lang }/nav.vue`)
    }]
  };

  let resourceRoute = {
    path: `/${ lang }/resource`, // 资源
    meta: { lang },
    component: require(`./pages/${ lang }/resource.vue`)
  };

  let indexRoute = {
    path: `/${ lang }`, // 首页
    meta: { lang },
    name: 'home',
    component: require(`./pages/${ lang }/index.vue`)
  };

  return [guideRoute, resourceRoute, indexRoute];
};

langs.forEach(lang => {
  route = route.concat(generateMiscRoutes(lang.lang));
});

route.push({
  path: '/play',
  name: 'play',
  component: require('./play/index.vue')
});

let userLanguage = localStorage.getItem('ELEMENT_LANGUAGE') || window.navigator.language;
let defaultPath = '/en-US';
if (userLanguage.indexOf('zh-') !== -1) {
  defaultPath = '/zh-CN';
}

route = route.concat([{
  path: '/',
  redirect: defaultPath
}, {
  path: '*',
  redirect: defaultPath
}]);

export default route;
<commit_msg>Homepage: fix a navigator.language bug (#1040)<commit_after>import navConfig from './nav.config.json';
import langs from './i18n/route.json';

const registerRoute = (navConfig) => {
  let route = [];
  Object.keys(navConfig).forEach((lang, index) => {
    let navs = navConfig[lang];
    route.push({
      path: `/${ lang }/component`,
      redirect: `/${ lang }/component/installation`,
      component: require(`./pages/${ lang }/component.vue`),
      children: []
    });
    navs.forEach(nav => {
      if (nav.groups) {
        nav.groups.forEach(group => {
          group.list.forEach(nav => {
            addRoute(nav, lang, index);
          });
        });
      } else if (nav.children) {
        nav.children.forEach(nav => {
          addRoute(nav, lang, index);
        });
      } else {
        addRoute(nav, lang, index);
      }
    });
  });
  function addRoute(page, lang, index) {
    const component = page.path === '/changelog'
      ? require(`./pages/${ lang }/changelog.vue`)
      : require(`./docs/${ lang }${page.path}.md`);
    let child = {
      path: page.path.slice(1),
      meta: {
        title: page.title || page.name,
        description: page.description,
        lang
      },
      component: component.default || component
    };

    route[index].children.push(child);
  }

  return route;
};

let route = registerRoute(navConfig);

const generateMiscRoutes = function(lang) {
  let guideRoute = {
    path: `/${ lang }/guide`, // 指南
    redirect: `/${ lang }/guide/design`,
    component: require(`./pages/${ lang }/guide.vue`),
    children: [{
      path: 'design', // 设计原则
      meta: { lang },
      component: require(`./pages/${ lang }/design.vue`)
    }, {
      path: 'nav', // 导航
      meta: { lang },
      component: require(`./pages/${ lang }/nav.vue`)
    }]
  };

  let resourceRoute = {
    path: `/${ lang }/resource`, // 资源
    meta: { lang },
    component: require(`./pages/${ lang }/resource.vue`)
  };

  let indexRoute = {
    path: `/${ lang }`, // 首页
    meta: { lang },
    name: 'home',
    component: require(`./pages/${ lang }/index.vue`)
  };

  return [guideRoute, resourceRoute, indexRoute];
};

langs.forEach(lang => {
  route = route.concat(generateMiscRoutes(lang.lang));
});

route.push({
  path: '/play',
  name: 'play',
  component: require('./play/index.vue')
});

let userLanguage = localStorage.getItem('ELEMENT_LANGUAGE') || window.navigator.language || 'en-US';
let defaultPath = '/en-US';
if (userLanguage.indexOf('zh-') !== -1) {
  defaultPath = '/zh-CN';
}

route = route.concat([{
  path: '/',
  redirect: defaultPath
}, {
  path: '*',
  redirect: defaultPath
}]);

export default route;
<|endoftext|>