<commit_before>var pretty = require('cloud/prettyprint.js').pretty;
var _ = require('underscore');
var Vampire = Parse.Object.extend("Vampire");
var Image = require("parse-image");

// Use Parse.Cloud.define to define as many cloud functions as you want.
// For example:
Parse.Cloud.define("hello", function(request, response) {
  response.success("Hello world!");
});

var create_thumbnail = function(portrait, input_image, size) {
    return input_image.data().then(function (data) {
        var image = new Image;
        return image.setData(data);
    }).then(function(image) {
        return image.scale({
            width: size,
            height: size
        });
    }).then(function(image) {
        return image.setFormat("JPEG");
    }).then(function(image) {
        return image.data();
    }).then(function(buffer) {
        var base64 = buffer.toString("base64");
        var cropped = new Parse.File("thumbnail_" + size + ".jpg", { base64: base64 });
        return cropped.save();
    }).then(function(cropped) {
        portrait.set("thumb_" + size, cropped);
    });
}

Parse.Cloud.beforeSave("CharacterPortrait", function(request, response) {
    var portrait = request.object;
    var THUMBNAIL_SIZES = [32, 64,128, 256];
    var needed_sizes = [];

    if (portrait.dirty("original")) {
        _.each(THUMBNAIL_SIZES, function (size) {
            portrait.set("thumb_" + size, undefined);
        });
    }

    _.each(THUMBNAIL_SIZES, function (size) {
        if (!portrait.get("thumb_" + size)) {
            needed_sizes.push(size);
        }
    })

    if (0 == needed_sizes.length) {
        response.success();
        return;
    }

    Parse.Cloud.httpRequest({
        url: portrait.get("original").url()
    }).then(function(response) {
        var image = new Image();
        return image.setData(response.buffer);
    }).then(function(image) {
        // Crop the image to the smaller of width or height.
        var size = Math.min(image.width(), image.height());
        return image.crop({
            left: (image.width() - size) / 2,
            top: (image.height() - size) / 2,
            width: size,
            height: size
        });
    }).then(function(image) {
        var promises = [];
        _.each(THUMBNAIL_SIZES, function(size) {
            promises.push(create_thumbnail(portrait, image, size))
        })
        return Parse.Promise.when(promises);
    }).then(function() {
        response.success();
    }, function(error) {
        response.error(error);
    });
});

var get_vampire_change_acl = function(vampire) {
    var daString = vampire.get("acl_to_json");
    if (_.isUndefined(daString)) {
        var acl = new Parse.ACL;
        acl.setPublicReadAccess(false);
        acl.setPublicWriteAccess(false);
        acl.setReadAccess(vampire.get("owner"), true);
        acl.setWriteAccess(vampire.get("owner"), false);
        return acl;
    }
    var acl = new Parse.ACL;
    var given_permissions_by_id = JSON.parse(daString);
    _.each(given_permissions_by_id, function (permissions, key) {
        acl.setReadAccess(key, true);
        acl.setWriteAccess(key, false);
    });
    acl.setPublicReadAccess(false);
    acl.setPublicWriteAccess(false);
    return acl;
}

Parse.Cloud.beforeSave("Vampire", function(request, response) {
    var tracked_texts = ["clan", "state", "archetype", "faction", "title", "sect"];
    var v = request.object;
    var serverData = _.clone(v._serverData);
    var desired_changes = _.intersection(tracked_texts, v.dirtyKeys());
    if (0 === desired_changes.length) {
        response.success();
        return;
    }
    // TODO: Update the history permissions if troupes has changed
    Parse.Cloud.useMasterKey();
    var new_values = {};
    _.each(v.dirtyKeys(), function(k) {
        new_values[k] = v.get(k);
    })
    var vToFetch = new Vampire({id: v.id});
    vToFetch.fetch().then(function(vampire) {
        return Parse.Object.saveAll(_.map(_.pairs(new_values), function(a) {
            var attribute = a[0], val = a[1];
            var vc = new Parse.Object("VampireChange");
            vc.set({
                "name": attribute,
                "category": "core",
                "old_text": serverData[attribute],
                "new_text": val,
                "owner": vampire,
                "type": serverData[attribute] === undefined ? "core_define" : "core_update",
                "instigator": request.user
            });
            var acl = get_vampire_change_acl(vampire);
            vc.setACL(acl);
            return vc;
        }));
    }).then(function () {
        return response.success();
    }).fail(function (error) {
        console.log(error.message);
        response.error();
    })
});

var isMeaningfulChange = function (vc) {
    var changed = true;
    if ("update" == vc.get("type")) {
        changed = false;
        if (vc.get("old_value") != vc.get("value")) {
            changed = true;
        }
        if (vc.get("old_cost") != vc.get("cost")) {
            changed = true;
        }
        if (vc.get("old_text") != vc.get("name")) {
            changed = true;
        }
        if (vc.get("free_value") != vc.get("old_free_value")) {
            changed = true;
        }
    }

    return changed;
}

Parse.Cloud.beforeSave("SimpleTrait", function(request, response) {
    Parse.Cloud.useMasterKey();
    var vc = new Parse.Object("VampireChange");
    var modified_trait = request.object;
    var serverData = modified_trait._serverData;
    vc.set({
        "name": modified_trait.get("name"),
        "category": modified_trait.get("category"),
        "owner": modified_trait.get("owner"),
        "old_value": serverData.value,
        "value": modified_trait.get("value"),
        "type": serverData.value === undefined ? "define" : "update",
        "old_free_value": serverData.free_value,
        "free_value": modified_trait.get("free_value"),
        "old_cost": serverData.cost,
        "cost": modified_trait.get("cost"),
        "old_text": serverData.name,
        "simple_trait_id": modified_trait.id,
        "instigator": request.user
    });

    if (!isMeaningfulChange(vc)) {
        console.log("Update does not actually encode a change");
        response.success();
        return;
    }

    var vToFetch = new Vampire({id: vc.get("owner").id});
    vToFetch.fetch().then(function(vampire) {
        var acl = get_vampire_change_acl(vampire);
        vc.setACL(acl);

        return vc.save();
    }).then(function () {
        response.success();
    }, function (error) {
        console.log(error.message);
        console.log("Failed to save change for", request.object.id, "because of", pretty(error));
        response.error();
    });
});

Parse.Cloud.beforeDelete("SimpleTrait", function(request, response) {
    Parse.Cloud.useMasterKey();
    var vc = new Parse.Object("VampireChange");
    var trait = request.object;
    var serverData = trait._serverData;
    vc.set({
        "name": trait.get("name"),
        "category": trait.get("category"),
        "owner": trait.get("owner"),
        "old_value": serverData.value,
        "value": trait.get("value"),
        "old_free_value": serverData.free_value,
        "free_value": trait.get("free_value"),
        "type": "remove",
        "old_cost": serverData.cost,
        "simple_trait_id": trait.id,
        "instigator": request.user
    });
    var vToFetch = new Vampire({id: vc.get("owner").id});
    vToFetch.fetch().then(function(vampire) {
        var acl = get_vampire_change_acl(vampire);
        vc.setACL(acl);
        return vc.save();
    }).then(function () {
        response.success();
    }, function (error) {
        console.log("Failed to save delete for" + request.object.id + "because of" + pretty(error));
        response.error();
    });
});

Parse.Cloud.define("removeRedundantHistory", function(request, response) {
    Parse.Cloud.useMasterKey();
    var allHistory = new Parse.Query("VampireChange");
    var redundant = [];
    allHistory.each(function (vc) {
        if (!isMeaningfulChange(vc)) {
            vc.set("marked_redundant", true);
            redundant.push(vc);
        }
    }).then(function() {
        return Parse.Object.destroyAll(redundant);
    }).then(function () {
        response.success();
    }, function(error) {
        response.error(error);
    });
})

Parse.Cloud.define("update_vampire_change_permissions_for", function(request, response) {
    var character_id = request.params.character;
    var tmp = new Vampire({id: character_id});
    tmp.fetch().then(function (v) {
        var acl = get_vampire_change_acl(v);
        Parse.Cloud.useMasterKey();
        return new Parse.Query("VampireChange").equalTo("owner", v).each(function (vc) {
            vc.setACL(acl);
            return vc.save();
        });
    }).then(function() {
        response.success("Successfully updated permissions.");
    }, function(error) {
        if (error.code === Parse.Error.AGGREGATE_ERROR) {
            for (var i = 0; i < error.errors.length; i++) {
                response.error("Couldn't fix " + error.errors[i].object.id + "due to " + error.errors[i].message);
            }
        } else {
            response.error("Update permissions because of " + error.message);
        }
        console.log(pretty(error));
    });
});

Parse.Cloud.define("leave_troupe", function(request, response) {

})

Parse.Cloud.job("fixcharacterownerships", function(request, response) {
    Parse.Cloud.useMasterKey();
    var allCharacters = new Parse.Query("Vampire");
    allCharacters.each(function (character) {
        var acl = new Parse.ACL;
        acl.setPublicReadAccess(false);
        acl.setPublicWriteAccess(false);
        acl.setWriteAccess(character.get("owner"), true);
        acl.setReadAccess(character.get("owner"), true);
        character.setACL(acl);
        return character.save();
    }).then(function() {
        response.success();
    }, function(error) {
        if (error.code === Parse.Error.AGGREGATE_ERROR) {
            for (var i = 0; i < error.errors.length; i++) {
                response.error("Couldn't fix " + error.errors[i].object.id + "due to " + error.errors[i].message);
            }
        } else {
            response.error("Delete fix because of " + error.message);
        }
        console.log(pretty(error));
    })
})

Parse.Cloud.job("fixcharacterchangeownerships", function(request, response) {
    Parse.Cloud.useMasterKey();
    var allCharacters = new Parse.Query("Vampire");
    allCharacters.each(function (character) {
        var allChanges = new Parse.Query("VampireChange");
        allChanges.equalTo("owner", character);
        return allChanges.each(function (change) {
            var acl = get_vampire_change_acl(character);
            change.setACL(acl);
            return change.save();
        })
    }).then(function() {
        response.success();
    }, function(error) {
        if (error.code === Parse.Error.AGGREGATE_ERROR) {
            for (var i = 0; i < error.errors.length; i++) {
                response.error("Couldn't fix " + error.errors[i].object.id + "due to " + error.errors[i].message);
            }
        } else {
            response.error("Delete fix because of " + error.message);
        }
        console.log(pretty(error));
    })
})

Parse.Cloud.job("deletetestcharacters", function(request, response) {
    Parse.Cloud.useMasterKey();
    var allTestCharacters = new Parse.Query("Vampire");
    var ids = [];
    var subids = [];
    allTestCharacters.startsWith("name", "karmacharactertest");
    allTestCharacters.each(function (v) {
        ids.push(v);
    });
    new Parse.Query("SimpleTrait").containedIn("owner", ids).each(function (vc) {
        return vc.destroy();
    }).then(function () {
         return new Parse.Query("VampireCreation").containedIn("owner", ids).each(function (vc) {
            return vc.destroy();
        });
    }).then(function() {
         return new Parse.Query("ExperienceNotation").containedIn("owner", ids).each(function (vc) {
            return vc.destroy();
        });
    }).then(function() {
         return new Parse.Query("VampireChange").containedIn("owner", ids).each(function (vc) {
            return vc.destroy();
        });
    }).then(function() {
        return Parse.Object.destroyAll(ids);
    }).then(function() {
        response.success();
    }).fail(function(error) {
        if (error.code === Parse.Error.AGGREGATE_ERROR) {
            for (var i = 0; i < error.errors.length; i++) {
                response.error("Couldn't delete " + error.errors[i].object.id + "due to " + error.errors[i].message);
            }
        } else {
            response.error("Delete aborted because of " + error.message);
        }
        console.log(pretty(error));
    });
})<commit_msg>Add missing administrator permissions<commit_after>var pretty = require('cloud/prettyprint.js').pretty;
var _ = require('underscore');
var Vampire = Parse.Object.extend("Vampire");
var Image = require("parse-image");

// Use Parse.Cloud.define to define as many cloud functions as you want.
// For example:
Parse.Cloud.define("hello", function(request, response) {
  response.success("Hello world!");
});

var create_thumbnail = function(portrait, input_image, size) {
    return input_image.data().then(function (data) {
        var image = new Image;
        return image.setData(data);
    }).then(function(image) {
        return image.scale({
            width: size,
            height: size
        });
    }).then(function(image) {
        return image.setFormat("JPEG");
    }).then(function(image) {
        return image.data();
    }).then(function(buffer) {
        var base64 = buffer.toString("base64");
        var cropped = new Parse.File("thumbnail_" + size + ".jpg", { base64: base64 });
        return cropped.save();
    }).then(function(cropped) {
        portrait.set("thumb_" + size, cropped);
    });
}

Parse.Cloud.beforeSave("CharacterPortrait", function(request, response) {
    var portrait = request.object;
    var THUMBNAIL_SIZES = [32, 64,128, 256];
    var needed_sizes = [];

    if (portrait.dirty("original")) {
        _.each(THUMBNAIL_SIZES, function (size) {
            portrait.set("thumb_" + size, undefined);
        });
    }

    _.each(THUMBNAIL_SIZES, function (size) {
        if (!portrait.get("thumb_" + size)) {
            needed_sizes.push(size);
        }
    })

    if (0 == needed_sizes.length) {
        response.success();
        return;
    }

    Parse.Cloud.httpRequest({
        url: portrait.get("original").url()
    }).then(function(response) {
        var image = new Image();
        return image.setData(response.buffer);
    }).then(function(image) {
        // Crop the image to the smaller of width or height.
        var size = Math.min(image.width(), image.height());
        return image.crop({
            left: (image.width() - size) / 2,
            top: (image.height() - size) / 2,
            width: size,
            height: size
        });
    }).then(function(image) {
        var promises = [];
        _.each(THUMBNAIL_SIZES, function(size) {
            promises.push(create_thumbnail(portrait, image, size))
        })
        return Parse.Promise.when(promises);
    }).then(function() {
        response.success();
    }, function(error) {
        response.error(error);
    });
});

var get_vampire_change_acl = function(vampire) {
    var daString = vampire.get("acl_to_json");
    if (_.isUndefined(daString)) {
        var acl = new Parse.ACL;
        acl.setPublicReadAccess(false);
        acl.setPublicWriteAccess(false);
        acl.setReadAccess(vampire.get("owner"), true);
        acl.setWriteAccess(vampire.get("owner"), false);
        return acl;
    }
    var acl = new Parse.ACL;
    var given_permissions_by_id = JSON.parse(daString);
    _.each(given_permissions_by_id, function (permissions, key) {
        acl.setReadAccess(key, true);
        acl.setWriteAccess(key, false);
    });
    acl.setPublicReadAccess(false);
    acl.setPublicWriteAccess(false);
    return acl;
}

Parse.Cloud.beforeSave("Vampire", function(request, response) {
    var tracked_texts = ["clan", "state", "archetype", "faction", "title", "sect"];
    var v = request.object;
    var serverData = _.clone(v._serverData);
    var desired_changes = _.intersection(tracked_texts, v.dirtyKeys());
    if (0 === desired_changes.length) {
        response.success();
        return;
    }
    // TODO: Update the history permissions if troupes has changed
    Parse.Cloud.useMasterKey();
    var new_values = {};
    _.each(v.dirtyKeys(), function(k) {
        new_values[k] = v.get(k);
    })
    var vToFetch = new Vampire({id: v.id});
    vToFetch.fetch().then(function(vampire) {
        return Parse.Object.saveAll(_.map(_.pairs(new_values), function(a) {
            var attribute = a[0], val = a[1];
            var vc = new Parse.Object("VampireChange");
            vc.set({
                "name": attribute,
                "category": "core",
                "old_text": serverData[attribute],
                "new_text": val,
                "owner": vampire,
                "type": serverData[attribute] === undefined ? "core_define" : "core_update",
                "instigator": request.user
            });
            var acl = get_vampire_change_acl(vampire);
            vc.setACL(acl);
            return vc;
        }));
    }).then(function () {
        return response.success();
    }).fail(function (error) {
        console.log(error.message);
        response.error();
    })
});

var isMeaningfulChange = function (vc) {
    var changed = true;
    if ("update" == vc.get("type")) {
        changed = false;
        if (vc.get("old_value") != vc.get("value")) {
            changed = true;
        }
        if (vc.get("old_cost") != vc.get("cost")) {
            changed = true;
        }
        if (vc.get("old_text") != vc.get("name")) {
            changed = true;
        }
        if (vc.get("free_value") != vc.get("old_free_value")) {
            changed = true;
        }
    }

    return changed;
}

Parse.Cloud.beforeSave("SimpleTrait", function(request, response) {
    Parse.Cloud.useMasterKey();
    var vc = new Parse.Object("VampireChange");
    var modified_trait = request.object;
    var serverData = modified_trait._serverData;
    vc.set({
        "name": modified_trait.get("name"),
        "category": modified_trait.get("category"),
        "owner": modified_trait.get("owner"),
        "old_value": serverData.value,
        "value": modified_trait.get("value"),
        "type": serverData.value === undefined ? "define" : "update",
        "old_free_value": serverData.free_value,
        "free_value": modified_trait.get("free_value"),
        "old_cost": serverData.cost,
        "cost": modified_trait.get("cost"),
        "old_text": serverData.name,
        "simple_trait_id": modified_trait.id,
        "instigator": request.user
    });

    if (!isMeaningfulChange(vc)) {
        console.log("Update does not actually encode a change");
        response.success();
        return;
    }

    var vToFetch = new Vampire({id: vc.get("owner").id});
    vToFetch.fetch().then(function(vampire) {
        var acl = get_vampire_change_acl(vampire);
        vc.setACL(acl);

        return vc.save();
    }).then(function () {
        response.success();
    }, function (error) {
        console.log(error.message);
        console.log("Failed to save change for", request.object.id, "because of", pretty(error));
        response.error();
    });
});

Parse.Cloud.beforeDelete("SimpleTrait", function(request, response) {
    Parse.Cloud.useMasterKey();
    var vc = new Parse.Object("VampireChange");
    var trait = request.object;
    var serverData = trait._serverData;
    vc.set({
        "name": trait.get("name"),
        "category": trait.get("category"),
        "owner": trait.get("owner"),
        "old_value": serverData.value,
        "value": trait.get("value"),
        "old_free_value": serverData.free_value,
        "free_value": trait.get("free_value"),
        "type": "remove",
        "old_cost": serverData.cost,
        "simple_trait_id": trait.id,
        "instigator": request.user
    });
    var vToFetch = new Vampire({id: vc.get("owner").id});
    vToFetch.fetch().then(function(vampire) {
        var acl = get_vampire_change_acl(vampire);
        vc.setACL(acl);
        return vc.save();
    }).then(function () {
        response.success();
    }, function (error) {
        console.log("Failed to save delete for" + request.object.id + "because of" + pretty(error));
        response.error();
    });
});

Parse.Cloud.define("removeRedundantHistory", function(request, response) {
    Parse.Cloud.useMasterKey();
    var allHistory = new Parse.Query("VampireChange");
    var redundant = [];
    allHistory.each(function (vc) {
        if (!isMeaningfulChange(vc)) {
            vc.set("marked_redundant", true);
            redundant.push(vc);
        }
    }).then(function() {
        return Parse.Object.destroyAll(redundant);
    }).then(function () {
        response.success();
    }, function(error) {
        response.error(error);
    });
})

Parse.Cloud.define("update_vampire_change_permissions_for", function(request, response) {
    var character_id = request.params.character;
    var tmp = new Vampire({id: character_id});
    tmp.fetch().then(function (v) {
        var acl = get_vampire_change_acl(v);
        Parse.Cloud.useMasterKey();
        return new Parse.Query("VampireChange").equalTo("owner", v).each(function (vc) {
            vc.setACL(acl);
            return vc.save();
        });
    }).then(function() {
        response.success("Successfully updated permissions.");
    }, function(error) {
        if (error.code === Parse.Error.AGGREGATE_ERROR) {
            for (var i = 0; i < error.errors.length; i++) {
                response.error("Couldn't fix " + error.errors[i].object.id + "due to " + error.errors[i].message);
            }
        } else {
            response.error("Update permissions because of " + error.message);
        }
        console.log(pretty(error));
    });
});

Parse.Cloud.define("leave_troupe", function(request, response) {

})

Parse.Cloud.job("fixcharacterownerships", function(request, response) {
    Parse.Cloud.useMasterKey();
    var allCharacters = new Parse.Query("Vampire");
    allCharacters.each(function (character) {
        var acl = new Parse.ACL;
        acl.setPublicReadAccess(false);
        acl.setPublicWriteAccess(false);
        acl.setWriteAccess(character.get("owner"), true);
        acl.setReadAccess(character.get("owner"), true);
        character.setACL(acl);
        return character.save();
    }).then(function() {
        response.success();
    }, function(error) {
        if (error.code === Parse.Error.AGGREGATE_ERROR) {
            for (var i = 0; i < error.errors.length; i++) {
                response.error("Couldn't fix " + error.errors[i].object.id + "due to " + error.errors[i].message);
            }
        } else {
            response.error("Delete fix because of " + error.message);
        }
        console.log(pretty(error));
    })
})

Parse.Cloud.job("fixcharacterchangeownerships", function(request, response) {
    Parse.Cloud.useMasterKey();
    var allCharacters = new Parse.Query("Vampire");
    allCharacters.each(function (character) {
        var allChanges = new Parse.Query("VampireChange");
        allChanges.equalTo("owner", character);
        return allChanges.each(function (change) {
            var acl = get_vampire_change_acl(character);
            change.setACL(acl);
            return change.save();
        })
    }).then(function() {
        response.success();
    }, function(error) {
        if (error.code === Parse.Error.AGGREGATE_ERROR) {
            for (var i = 0; i < error.errors.length; i++) {
                response.error("Couldn't fix " + error.errors[i].object.id + "due to " + error.errors[i].message);
            }
        } else {
            response.error("Delete fix because of " + error.message);
        }
        console.log(pretty(error));
    })
})

var add_administrator_to_everything = function(model) {
    var acl = model.getACL();
    if (_.isUndefined(acl)) {
        // Not completely defined for some reason
        return Parse.Promise.as([]);
    }
    acl.setRoleReadAccess("Administrator", true);
    acl.setRoleWriteAccess("Administrator", true);
    model.setACL(acl);
    return model.save();
}

Parse.Cloud.job("add_administrator_to_many_things", function (request, response) {
    Parse.Cloud.useMasterKey();
    new Parse.Query("SimpleTrait").each(add_administrator_to_everything).then(function () {
         return new Parse.Query("VampireCreation").each(add_administrator_to_everything);
    }).then(function() {
         return new Parse.Query("ExperienceNotation").each(add_administrator_to_everything);
    }).then(function() {
         return new Parse.Query("VampireChange").each(add_administrator_to_everything);
    }).then(function() {
        response.success();
    }).fail(function(error) {
        if (error.code === Parse.Error.AGGREGATE_ERROR) {
            for (var i = 0; i < error.errors.length; i++) {
                response.error("Couldn't delete " + error.errors[i].object.id + "due to " + error.errors[i].message);
            }
        } else {
            response.error("Add administrator broken of " + error.message);
        }
        console.log(pretty(error));
    });
});

Parse.Cloud.job("deletetestcharacters", function(request, response) {
    Parse.Cloud.useMasterKey();
    var allTestCharacters = new Parse.Query("Vampire");
    var ids = [];
    var subids = [];
    allTestCharacters.startsWith("name", "karmacharactertest");
    allTestCharacters.each(function (v) {
        ids.push(v);
    });
    new Parse.Query("SimpleTrait").containedIn("owner", ids).each(function (vc) {
        return vc.destroy();
    }).then(function () {
         return new Parse.Query("VampireCreation").containedIn("owner", ids).each(function (vc) {
            return vc.destroy();
        });
    }).then(function() {
         return new Parse.Query("ExperienceNotation").containedIn("owner", ids).each(function (vc) {
            return vc.destroy();
        });
    }).then(function() {
         return new Parse.Query("VampireChange").containedIn("owner", ids).each(function (vc) {
            return vc.destroy();
        });
    }).then(function() {
        return Parse.Object.destroyAll(ids);
    }).then(function() {
        response.success();
    }).fail(function(error) {
        if (error.code === Parse.Error.AGGREGATE_ERROR) {
            for (var i = 0; i < error.errors.length; i++) {
                response.error("Couldn't delete " + error.errors[i].object.id + "due to " + error.errors[i].message);
            }
        } else {
            response.error("Delete aborted because of " + error.message);
        }
        console.log(pretty(error));
    });
})<|endoftext|>


<commit_before>// Use AV.Cloud.define to define as many cloud functions as you want.
// For example:
AV.Cloud.define("hello", function(request, response) {
  response.success("Hello world!");
});<commit_msg>hello<commit_after>// Use AV.Cloud.define to define as many cloud functions as you want.
// For example:
AV.Cloud.define("hello", function(request, response) {
	var name = request.params.name;
	if (name) {
		response.success('Hello ' + name +'!');
	} else {
		response.error('what your name?')
	}
});<|endoftext|>


<commit_before>/* Emoticons Plugin
 * This is a chat-plugin for Emoticons
 * You will need a line in parser to actually
 * parse this so that it works. (See command-parser.js)
 * Credits: panpawn, jd
 */

var fs = require('fs');
var path = require('path');
var serialize = require('node-serialize');
var emotes = {};

if (typeof Gold === 'undefined') global.Gold = {};

Gold.emoticons = {
	chatEmotes: {},
	processEmoticons: function(text) {
		var patterns = [],
		metachars = /[[\]{}()*+?.\\|^$\-,&#\s]/g,
		self = this;
		for (var i in this.chatEmotes) {
			if (this.chatEmotes.hasOwnProperty(i)) {
				patterns.push('(' + i.replace(metachars, "\\$&") + ')');
			}
		}
		return text.replace(new RegExp(patterns.join('|'), 'g'), function(match) {
			return typeof self.chatEmotes[match] != 'undefined' ?
				'' :
				match;
		});
	},
	processChatData: function(user, room, connection, message) {
		var match = false;
		for (var i in this.chatEmotes) {
			if (message.indexOf(i) >= 0) {
				match = true;
			}
		}
		switch (Users.ShadowBan.checkBanned(user) && match) {
			case true:
				origmsg = message;
				message = Tools.escapeHTML(message);
				message = this.processEmoticons(message);
				user.sendTo(room, '|html|' +
					user.getIdentity(room).substr(0,1) + '<button class="astext" name="parseCommand" value="/user ' +
					user.name + '">' + '' + Tools.escapeHTML(user.name) + ':</button> ' + message + '
'
				);
				room.update();
				Users.ShadowBan.addMessage(user, "To " + room, origmsg);
				break;
			case false:
				if (!room.emoteStatus && room.type === 'chat' || !room.type === 'battle') {
					kitty = message = this.processEmoticons(message);
					var message = Tools.escapeHTML(kitty);
					return (message);
					return;
				} else if (room.emoteStatus || room.type === 'battle') {
					if (!match || message.charAt(0) === '!') return true;
					message = Tools.escapeHTML(message);
					message = this.processEmoticons(message);
					if (user.hiding) {
						room.addRaw(' <button class="astext" name="parseCommand" value="/user ' +
						user.name + '">' + '' + Tools.escapeHTML(user.name) + ':</button> ' + message + '
');
						room.update();
					}
					room.addRaw(user.getIdentity(room).substr(0,1) + '<button class="astext" name="parseCommand" value="/user ' +
					user.name + '">' + '' + Tools.escapeHTML(user.name) + ':</button> ' + message + '
');
					room.update();
					return false;
				}
				break;
		}
	}
};

//commands

function loadEmotes() {
	try {
		emotes = serialize.unserialize(fs.readFileSync('config/emotes.json', 'utf8'));
		Object.merge(Gold.emoticons.chatEmotes, emotes);
	} catch (e) {}
}
setTimeout(function(){loadEmotes();},1000);

function saveEmotes() {
	try {
		fs.writeFileSync('config/emotes.json',serialize.serialize(emotes));
		Object.merge(Gold.emoticons.chatEmotes, emotes);
	} catch (e) {}
}

exports.commands = {
	emotes: 'ezemote',
	temotes: 'ezemote',
	temote: 'ezemote',
	emote: 'ezemote',
	ec: 'ezemote',
	ezemote: function (target, room, user) {
		if (!target) target = "help";
		var parts = target.split(',');
		for (var u in parts) parts[u] = parts[u].trim();

		try {
			switch (toId(parts[0])) {
				case 'add':
					if (!this.can('ban')) return this.sendReply("Access denied.");
					if (!(parts[2] || parts[3])) return this.sendReply("Usage: /ezemote add, [emote], [link]");
					var emoteName = parts[1];
					if (Gold.emoticons.chatEmotes[emoteName]) return this.sendReply("ERROR - the emote: " + emoteName + " already exists.");
					var link = parts.splice(2, parts.length).join(',');
					var fileTypes = [".gif",".png",".jpg"];
					if (fileTypes.indexOf(link.substr(-4)) < 0) return this.sendReply("ERROR: the emote you are trying to add must be a gif, png, or jpg.");
					emotes[emoteName] = Gold.emoticons.chatEmotes[emoteName] = link;
					saveEmotes();
					this.sendReply("The emote " + emoteName + " has been added.");
					this.logModCommand(user.name + " added the emote " + emoteName);
					Rooms.rooms.staff.add(Tools.escapeHTML(user.name) + " added the emote " + emoteName);
					room.update();
					break;
				case 'rem':
				case 'remove':
				case 'del':
				case 'delete':
					if (!this.can('ban')) return this.sendReply("Access denied.");
					if (!parts[1]) return this.sendReplyBox("/ezemote remove, [emote]");
					var emoteName = parts[1];
					if (!Gold.emoticons.chatEmotes[emoteName]) return this.sendReply("ERROR - the emote: " + emoteName + " does not exist.");
					delete Gold.emoticons.chatEmotes[emoteName];
					delete emotes[emoteName];
					saveEmotes();
					this.sendReply("The emote " + emoteName + " was removed.");
					this.logModCommand("The emote " + emoteName + " was removed by " + user.name);
					Rooms.rooms.staff.add("The emote " + emoteName + " was removed by " + Tools.escapeHTML(user.name));
					room.update();
					break;
				case 'list':
					if (!this.canBroadcast()) return;
					if (this.broadcasting) return this.sendReply("ERROR: this command is too spammy to broadcast.  Use / instead of ! to see it for yourself.");
					var output = "There's a total of " + Object.size(emotes) + " emotes added with this command:
";
					for (var e in emotes) {
						output += e + "
";
					}
					this.sendReplyBox(output);
					break;
				case 'view':
					if (!this.canBroadcast()) return;
					//if (this.broadcasting) return this.sendReply("ERROR: this command is too spammy to broadcast.  Use / instead of ! to see it for yourself.");
					var name = Object.keys(Gold.emoticons.chatEmotes);
					emoticons = [];
					var len = name.length;
					while (len--) {
						emoticons.push((Gold.emoticons.processEmoticons(name[(name.length - 1) - len]) + ' ' + name[(name.length - 1) - len]));
					}
					this.sendReplyBox("List of emoticons (" + Object.size(emotes) + "):

" + emoticons.join(' ').toString());
					break;
				case 'object':
					if (!this.canBroadcast()) return;
					if (this.broadcasting) return this.sendReply("ERROR: this command is too spammy to broadcast.  Use / instead of ! to see it for yourself.");
					this.sendReplyBox("Gold.emoticons.chatEmotes = " + fs.readFileSync('config/emotes.json','utf8'));
					break;
				case 'status':
					if (!this.canBroadcast()) return;
					if (!parts[1]) {
						switch (room.emoteStatus) {
							case true:
								this.sendReply("Chat emotes are currently enabled in this room.");
								break;
							case false:
								this.sendReply("Chat emotes are currently disabled in this room.");
								break;
						}
					} else {
						switch (toId(parts[1])) {
							case 'on':
							case 'enable':
								if (!this.can('declare', null, room)) return this.sendReply("Access denied.");
								if (room.type === 'battle') return this.sendReply("Chat emoticons are already enabled in battle rooms by default and cannot be turned off.");
								if (room.emoteStatus) return this.sendReply("Chat emoticons are already enabled in this room.");
								room.emoteStatus = true;
								room.chatRoomData.emoteStatus = room.emoteStatus;
								Rooms.global.writeChatRoomData();
								//room.add(Tools.escapeHTML(user.name) + ' has enabled chat emoticons in this room.');
								this.add("|raw|
Chat Emoticons have been enabled!
Everyone in this room may use chat emoticons.");
								this.privateModCommand("(" + user.name + " has enabled chat emoticons in this room)");
								break;
							case 'off':
							case 'disable':
								if (!this.can('declare', null, room)) return this.sendReply("Access denied.");
								if (room.type === 'battle') return this.sendReply("Chat emoticons are already enabled in battle rooms by default and cannot be turned off.");
								if (!room.emoteStatus) return this.sendReply("Chat emoticons are already disabled in this room.");
								room.emoteStatus = false;
								room.chatRoomData.emoteStatus = room.emoteStatus;
								Rooms.global.writeChatRoomData();
								//room.add(Tools.escapeHTML(user.name) + " has disabled chat emoticons in this room.");
								this.add("|raw|
Chat Emoticons have been disabled!
No one in this room may use chat emoticons.");
								this.privateModCommand("(" + user.name + " has disabled chat emoticons in this room)");
								break;
							default:
								this.sendReply("Usage: /ezemote status, [on / off] - Enables or disables the current chat emoticon status.  Requires #, &, ~.");
						}
					}
					break;
				case 'help':
				default:
					if (!this.canBroadcast()) return;
					this.sendReplyBox(
						"
" +
							"EZ-Emoticon Commands:
" +
							"(By: panpawn)
" +
							"/ezemote add, [emote], [link] - Adds a chat emoticon. Requires @, &, ~.
" +
							"/ezemote remove, [emote] - Removes a chat emoticon. Requires @, &, ~.
" +
							"/ezemote status, [on / off] - Enables or disables the status of chat emoticons in the respected room. Requires #, &, ~.
" +
							"/ezemote status - Views the current status of chat emoticons.
" +
							"/ezemote list - Shows the chat emoticons in a list form.
" +
							"/ezemote view - Shows all of the current chat emoticons with the respected image.
" +
							"/ezemote object - Shows the object of Gold.emoticons.chatEmotes. (Mostly for development usage)
" +
							"/ezemote help - Shows this help command.
" +
						"
"
					);
			}
		} catch (e) {
			try {
				Rooms.rooms.development.add(e.stack);
			} catch (e) {
				console.log("ERROR!  The EZ-Emote script has crashed!\n" + e.stack);
			}
		}
	}
};<commit_msg>Add in room.update(); for style purposes<commit_after>/* Emoticons Plugin
 * This is a chat-plugin for Emoticons
 * You will need a line in parser to actually
 * parse this so that it works. (See command-parser.js)
 * Credits: panpawn, jd
 */

var fs = require('fs');
var path = require('path');
var serialize = require('node-serialize');
var emotes = {};

if (typeof Gold === 'undefined') global.Gold = {};

Gold.emoticons = {
	chatEmotes: {},
	processEmoticons: function(text) {
		var patterns = [],
		metachars = /[[\]{}()*+?.\\|^$\-,&#\s]/g,
		self = this;
		for (var i in this.chatEmotes) {
			if (this.chatEmotes.hasOwnProperty(i)) {
				patterns.push('(' + i.replace(metachars, "\\$&") + ')');
			}
		}
		return text.replace(new RegExp(patterns.join('|'), 'g'), function(match) {
			return typeof self.chatEmotes[match] != 'undefined' ?
				'' :
				match;
		});
	},
	processChatData: function(user, room, connection, message) {
		var match = false;
		for (var i in this.chatEmotes) {
			if (message.indexOf(i) >= 0) {
				match = true;
			}
		}
		switch (Users.ShadowBan.checkBanned(user) && match) {
			case true:
				origmsg = message;
				message = Tools.escapeHTML(message);
				message = this.processEmoticons(message);
				user.sendTo(room, '|html|' +
					user.getIdentity(room).substr(0,1) + '<button class="astext" name="parseCommand" value="/user ' +
					user.name + '">' + '' + Tools.escapeHTML(user.name) + ':</button> ' + message + '
'
				);
				room.update();
				Users.ShadowBan.addMessage(user, "To " + room, origmsg);
				break;
			case false:
				if (!room.emoteStatus && room.type === 'chat' || !room.type === 'battle') {
					kitty = message = this.processEmoticons(message);
					var message = Tools.escapeHTML(kitty);
					return (message);
					return;
				} else if (room.emoteStatus || room.type === 'battle') {
					if (!match || message.charAt(0) === '!') return true;
					message = Tools.escapeHTML(message);
					message = this.processEmoticons(message);
					if (user.hiding) {
						room.addRaw(' <button class="astext" name="parseCommand" value="/user ' +
						user.name + '">' + '' + Tools.escapeHTML(user.name) + ':</button> ' + message + '
');
						room.update();
					}
					room.addRaw(user.getIdentity(room).substr(0,1) + '<button class="astext" name="parseCommand" value="/user ' +
					user.name + '">' + '' + Tools.escapeHTML(user.name) + ':</button> ' + message + '
');
					room.update();
					return false;
				}
				break;
		}
	}
};

//commands

function loadEmotes() {
	try {
		emotes = serialize.unserialize(fs.readFileSync('config/emotes.json', 'utf8'));
		Object.merge(Gold.emoticons.chatEmotes, emotes);
	} catch (e) {}
}
setTimeout(function(){loadEmotes();},1000);

function saveEmotes() {
	try {
		fs.writeFileSync('config/emotes.json',serialize.serialize(emotes));
		Object.merge(Gold.emoticons.chatEmotes, emotes);
	} catch (e) {}
}

exports.commands = {
	emotes: 'ezemote',
	temotes: 'ezemote',
	temote: 'ezemote',
	emote: 'ezemote',
	ec: 'ezemote',
	ezemote: function (target, room, user) {
		if (!target) target = "help";
		var parts = target.split(',');
		for (var u in parts) parts[u] = parts[u].trim();

		try {
			switch (toId(parts[0])) {
				case 'add':
					if (!this.can('ban')) return this.sendReply("Access denied.");
					if (!(parts[2] || parts[3])) return this.sendReply("Usage: /ezemote add, [emote], [link]");
					var emoteName = parts[1];
					if (Gold.emoticons.chatEmotes[emoteName]) return this.sendReply("ERROR - the emote: " + emoteName + " already exists.");
					var link = parts.splice(2, parts.length).join(',');
					var fileTypes = [".gif",".png",".jpg"];
					if (fileTypes.indexOf(link.substr(-4)) < 0) return this.sendReply("ERROR: the emote you are trying to add must be a gif, png, or jpg.");
					emotes[emoteName] = Gold.emoticons.chatEmotes[emoteName] = link;
					saveEmotes();
					this.sendReply("The emote " + emoteName + " has been added.");
					this.logModCommand(user.name + " added the emote " + emoteName);
					Rooms.rooms.staff.add(Tools.escapeHTML(user.name) + " added the emote " + emoteName);
					room.update();
					break;
				case 'rem':
				case 'remove':
				case 'del':
				case 'delete':
					if (!this.can('ban')) return this.sendReply("Access denied.");
					if (!parts[1]) return this.sendReplyBox("/ezemote remove, [emote]");
					var emoteName = parts[1];
					if (!Gold.emoticons.chatEmotes[emoteName]) return this.sendReply("ERROR - the emote: " + emoteName + " does not exist.");
					delete Gold.emoticons.chatEmotes[emoteName];
					delete emotes[emoteName];
					saveEmotes();
					this.sendReply("The emote " + emoteName + " was removed.");
					this.logModCommand("The emote " + emoteName + " was removed by " + user.name);
					Rooms.rooms.staff.add("The emote " + emoteName + " was removed by " + Tools.escapeHTML(user.name));
					room.update();
					break;
				case 'list':
					if (!this.canBroadcast()) return;
					if (this.broadcasting) return this.sendReply("ERROR: this command is too spammy to broadcast.  Use / instead of ! to see it for yourself.");
					var output = "There's a total of " + Object.size(emotes) + " emotes added with this command:
";
					for (var e in emotes) {
						output += e + "
";
					}
					this.sendReplyBox(output);
					break;
				case 'view':
					if (!this.canBroadcast()) return;
					//if (this.broadcasting) return this.sendReply("ERROR: this command is too spammy to broadcast.  Use / instead of ! to see it for yourself.");
					var name = Object.keys(Gold.emoticons.chatEmotes);
					emoticons = [];
					var len = name.length;
					while (len--) {
						emoticons.push((Gold.emoticons.processEmoticons(name[(name.length - 1) - len]) + ' ' + name[(name.length - 1) - len]));
					}
					this.sendReplyBox("List of emoticons (" + Object.size(emotes) + "):

" + emoticons.join(' ').toString());
					break;
				case 'object':
					if (!this.canBroadcast()) return;
					if (this.broadcasting) return this.sendReply("ERROR: this command is too spammy to broadcast.  Use / instead of ! to see it for yourself.");
					this.sendReplyBox("Gold.emoticons.chatEmotes = " + fs.readFileSync('config/emotes.json','utf8'));
					break;
				case 'status':
					if (!this.canBroadcast()) return;
					if (!parts[1]) {
						switch (room.emoteStatus) {
							case true:
								this.sendReply("Chat emotes are currently enabled in this room.");
								break;
							case false:
								this.sendReply("Chat emotes are currently disabled in this room.");
								break;
						}
					} else {
						switch (toId(parts[1])) {
							case 'on':
							case 'enable':
								if (!this.can('declare', null, room)) return this.sendReply("Access denied.");
								if (room.type === 'battle') return this.sendReply("Chat emoticons are already enabled in battle rooms by default and cannot be turned off.");
								if (room.emoteStatus) return this.sendReply("Chat emoticons are already enabled in this room.");
								room.emoteStatus = true;
								room.chatRoomData.emoteStatus = room.emoteStatus;
								Rooms.global.writeChatRoomData();
								//room.add(Tools.escapeHTML(user.name) + ' has enabled chat emoticons in this room.');
								this.add("|raw|
Chat Emoticons have been enabled!
Everyone in this room may use chat emoticons.");
								room.update();
								this.privateModCommand("(" + user.name + " has enabled chat emoticons in this room)");
								break;
							case 'off':
							case 'disable':
								if (!this.can('declare', null, room)) return this.sendReply("Access denied.");
								if (room.type === 'battle') return this.sendReply("Chat emoticons are already enabled in battle rooms by default and cannot be turned off.");
								if (!room.emoteStatus) return this.sendReply("Chat emoticons are already disabled in this room.");
								room.emoteStatus = false;
								room.chatRoomData.emoteStatus = room.emoteStatus;
								Rooms.global.writeChatRoomData();
								//room.add(Tools.escapeHTML(user.name) + " has disabled chat emoticons in this room.");
								this.add("|raw|
Chat Emoticons have been disabled!
No one in this room may use chat emoticons.");
								room.update();
								this.privateModCommand("(" + user.name + " has disabled chat emoticons in this room)");
								break;
							default:
								this.sendReply("Usage: /ezemote status, [on / off] - Enables or disables the current chat emoticon status.  Requires #, &, ~.");
						}
					}
					break;
				case 'help':
				default:
					if (!this.canBroadcast()) return;
					this.sendReplyBox(
						"
" +
							"EZ-Emoticon Commands:
" +
							"(By: panpawn)
" +
							"/ezemote add, [emote], [link] - Adds a chat emoticon. Requires @, &, ~.
" +
							"/ezemote remove, [emote] - Removes a chat emoticon. Requires @, &, ~.
" +
							"/ezemote status, [on / off] - Enables or disables the status of chat emoticons in the respected room. Requires #, &, ~.
" +
							"/ezemote status - Views the current status of chat emoticons.
" +
							"/ezemote list - Shows the chat emoticons in a list form.
" +
							"/ezemote view - Shows all of the current chat emoticons with the respected image.
" +
							"/ezemote object - Shows the object of Gold.emoticons.chatEmotes. (Mostly for development usage)
" +
							"/ezemote help - Shows this help command.
" +
						"
"
					);
			}
		} catch (e) {
			try {
				Rooms.rooms.development.add(e.stack);
			} catch (e) {
				console.log("ERROR!  The EZ-Emote script has crashed!\n" + e.stack);
			}
		}
	}
};<|endoftext|>


<commit_before>/* EZ-Emote plugin
 * These are commands that make it easier for people to actually
 * add / remove emotes without having to manaully do so every time
 * By: panpawn (inspired by jd's ez-tc plugin)
 */

var fs = require('fs');
var serialize = require('node-serialize');
var emotes = {};

function loadEmotes() {
	try {
		emotes = serialize.unserialize(fs.readFileSync('config/emotes.json', 'utf8'));
		Object.merge(Core.emoticons, emotes);
	} catch (e) {};
}
setTimeout(function(){loadEmotes();},1000);

function saveEmotes() {
	try {
		fs.writeFileSync('config/emotes.json',serialize.serialize(emotes));
		Object.merge(Core.emoticons, emotes);
	} catch (e) {};
}

exports.commands = {
	emotes: 'ezemote',
	temotes: 'ezemote',
	temote: 'ezemote',
	emote: 'ezemote',
	ec: 'ezemote',
	ezemote: function (target, room, user) {
		if (!target) target = 'help';
		var parts = target.split(',');
		for (var u in parts) parts[u] = parts[u].trim();
		try {
			switch (toId(parts[0])) {
				case 'add':
					if (!this.can('ban')) return this.sendReply("Access denied.")
					if (!(parts[2] || parts[3])) return this.sendReply("Usage: /ezemote add, [emote], [link]");
					var emoteName = parts[1];
					if (Core.emoticons[emoteName]) return this.sendReply("ERROR - the emote: " + emoteName + " already exists.");
					var link = parts.splice(2, parts.length).join(',');
					//if (link != ".gif" || link != ".png" || link != ".jpg") return this.sendReply("ERROR: the emote you are trying to add must be a gif, png, or jpg.");
					emotes[emoteName] = Core.emoticons[emoteName] = link;
					saveEmotes();
					this.sendReply("The emote " + emoteName + " has been added.");
					this.logModCommand(user.name + " added the emote " + emoteName);
					Rooms.rooms.staff.add(user.name + " added the emote " + emoteName);
					break;
				case 'rem':
				case 'remove':
				case 'del':
				case 'delete':
					if (!this.can('ban')) return this.sendReply("Access denied.");
					if (!parts[1]) return this.sendReplyBox("/ezemote remove, [emote]");
					var emoteName = parts[1];
					if (!Core.emoticons[emoteName]) return this.sendReply("ERROR - the emote: " + emoteName + " does not exist.");
					delete Core.emoticons[emoteName];
					delete emotes[emoteName];
					saveEmotes();
					this.sendReply("The emote " + emoteName + " was removed.");
					this.logModCommand("The emote " + emoteName + " was removed by " + user.name);
					Rooms.rooms.staff.add("The emote " + emoteName + " was removed by " + user.name);
					break;
				case 'list':
					if (!this.canBroadcast()) return;
					if (this.broadcasting) return this.sendReply("ERROR: this command is too spammy to broadcast.  Use / instead of ! to see it for yourself.");
					var output = "There's a total of " + Object.size(emotes) + " emotes added with this command:
";
					for (var e in emotes) {
						output += e + "
";
					}
					this.sendReplyBox(output);
					break;
				case 'view':
					if (!this.canBroadcast()) return;
					//if (this.broadcasting) return this.sendReply("ERROR: this command is too spammy to broadcast.  Use / instead of ! to see it for yourself.");
					if (!Core.settings.emoteStatus) {
						return this.sendReplyBox("Sorry, chat emotes have been disabled. :(");
					} else {
						var name = Object.keys(Core.emoticons),
						emoticons = [];
						var len = name.length;
						while (len--) {
							emoticons.push((Core.processEmoticons(name[(name.length - 1) - len]) + ' ' + name[(name.length - 1) - len]));
						}
						this.sendReplyBox("List of emoticons (" + Object.size(emotes) + "):

" + emoticons.join(' ').toString());
					}
					break;
				case 'object':
					if (!this.canBroadcast()) return;
					if (this.broadcasting) return this.sendReply("ERROR: this command is too spammy to broadcast.  Use / instead of ! to see it for yourself.");
					this.sendReplyBox("Core.emoticons = " + fs.readFileSync('config/emotes.json','utf8'));
					break;
				case 'status':
					if (!this.can('pban')) return this.sendReply("Access denied.");
					if (!parts[1]) {
						switch (room.emoteStatus) {
							case true:
								this.sendReply("Chat emotes are currently enabled.");
								break;
							case false:
								this.sendReply("Chat emotes are currently disabled.");
								break;
						}
					} else {
						switch (toId(parts[1])) {
							case 'on':
							case 'enable':
								if (!this.can('pban')) return this.sendReply("Access denied.");
								room.emoteStatus = true;
								room.chatRoomData.emoteStatus = room.emoteStatus;
								Rooms.global.writeChatRoomData();
								room.add(Tools.escapeHTML(user.name) + ' has enabled chat emotes.');
								this.logModCommand(Tools.escapeHTML(user.name) + ' has enabled chat emotes.');
								break;
							case 'off':
							case 'disable':
								if (!this.can('pban')) return this.sendReply("Access denied.");
								room.emoteStatus = false;
								room.chatRoomData.emoteStatus = room.emoteStatus;
								Rooms.global.writeChatRoomData();
								room.add(Tools.escapeHTML(user.name) + " has disabled chat emotes.");
								this.logModCommand(Tools.escapeHTML(user.name) + " has disabled chat emotes.");
								break;
							default:
								if (!this.can('pban')) return this.sendReply("Access denied.");
								this.sendReply("Usage: /ezemote status - views the current emote status OR /ezemote status, [off / on] - Turns emotes on / off.  Requires &, ~.");
						}
					}
					break;
				case 'help':
				default:
					if (!this.canBroadcast()) return;
					this.sendReplyBox(
						"
" +
							"EZ-Emote Commands:
" +
							"(By: panpawn)
" +
							"/ezemote add, [emote], [link] - Adds an emote. Requires @, &, ~.
" +
							"/ezemote remove, [emote] - Removes an emote. Requires @, &, ~.
" +
							"/ezemote status - Views the current status of emotes.  Requires &, ~.
" +
							"/ezemote status, [on / off] - Enables or disables the status of emotes. Requires &, ~.
" +
							"/ezemote list - Shows the emotes that were added with this command.
" +
							"/ezemote view - Shows all of the current emotes with their respected image.
" +
							"/ezemote object - Shows the object of Core.emoticons. (Mostly for development usage)
" +
							"/ezemote help - Shows this help command.
" +
						"
	"
					);
			}
		} catch (e) {
			console.log("ERROR!  The EZ-Emote script has crashed!");
		}
	}
};
<commit_msg>Update ez-emotes.js<commit_after>/* EZ-Emote plugin
 * These are commands that make it easier for people to actually
 * add / remove emotes without having to manaully do so every time
 * By: panpawn (inspired by jd's ez-tc plugin)
 */

var fs = require('fs');
var serialize = require('node-serialize');
var emotes = {};

function loadEmotes() {
	try {
		emotes = serialize.unserialize(fs.readFileSync('config/emotes.json', 'utf8'));
		Object.merge(Core.emoticons, emotes);
	} catch (e) {};
}
setTimeout(function(){loadEmotes();},1000);

function saveEmotes() {
	try {
		fs.writeFileSync('config/emotes.json',serialize.serialize(emotes));
		Object.merge(Core.emoticons, emotes);
	} catch (e) {};
}

exports.commands = {
	emotes: 'ezemote',
	temotes: 'ezemote',
	temote: 'ezemote',
	emote: 'ezemote',
	ec: 'ezemote',
	ezemote: function (target, room, user) {
		if (!target) target = 'help';
		var parts = target.split(',');
		for (var u in parts) parts[u] = parts[u].trim();
		try {
			switch (toId(parts[0])) {
				case 'add':
					if (!this.can('ban')) return this.sendReply("Access denied.")
					if (!(parts[2] || parts[3])) return this.sendReply("Usage: /ezemote add, [emote], [link]");
					var emoteName = parts[1];
					if (Core.emoticons[emoteName]) return this.sendReply("ERROR - the emote: " + emoteName + " already exists.");
					var link = parts.splice(2, parts.length).join(',');
					//if (link != ".gif" || link != ".png" || link != ".jpg") return this.sendReply("ERROR: the emote you are trying to add must be a gif, png, or jpg.");
					emotes[emoteName] = Core.emoticons[emoteName] = link;
					saveEmotes();
					this.sendReply("The emote " + emoteName + " has been added.");
					this.logModCommand(user.name + " added the emote " + emoteName);
					Rooms.rooms.staff.add(user.name + " added the emote " + emoteName);
					break;
				case 'rem':
				case 'remove':
				case 'del':
				case 'delete':
					if (!this.can('ban')) return this.sendReply("Access denied.");
					if (!parts[1]) return this.sendReplyBox("/ezemote remove, [emote]");
					var emoteName = parts[1];
					if (!Core.emoticons[emoteName]) return this.sendReply("ERROR - the emote: " + emoteName + " does not exist.");
					delete Core.emoticons[emoteName];
					delete emotes[emoteName];
					saveEmotes();
					this.sendReply("The emote " + emoteName + " was removed.");
					this.logModCommand("The emote " + emoteName + " was removed by " + user.name);
					Rooms.rooms.staff.add("The emote " + emoteName + " was removed by " + user.name);
					break;
				case 'list':
					if (!this.canBroadcast()) return;
					if (this.broadcasting) return this.sendReply("ERROR: this command is too spammy to broadcast.  Use / instead of ! to see it for yourself.");
					var output = "There's a total of " + Object.size(emotes) + " emotes added with this command:
";
					for (var e in emotes) {
						output += e + "
";
					}
					this.sendReplyBox(output);
					break;
				case 'view':
					if (!this.canBroadcast()) return;
					//if (this.broadcasting) return this.sendReply("ERROR: this command is too spammy to broadcast.  Use / instead of ! to see it for yourself.");
					if (!Core.settings.emoteStatus) {
						return this.sendReplyBox("Sorry, chat emotes have been disabled. :(");
					} else {
						var name = Object.keys(Core.emoticons),
						emoticons = [];
						var len = name.length;
						while (len--) {
							emoticons.push((Core.processEmoticons(name[(name.length - 1) - len]) + ' ' + name[(name.length - 1) - len]));
						}
						this.sendReplyBox("List of emoticons (" + Object.size(emotes) + "):

" + emoticons.join(' ').toString());
					}
					break;
				case 'object':
					if (!this.canBroadcast()) return;
					if (this.broadcasting) return this.sendReply("ERROR: this command is too spammy to broadcast.  Use / instead of ! to see it for yourself.");
					this.sendReplyBox("Core.emoticons = " + fs.readFileSync('config/emotes.json','utf8'));
					break;
				case 'status':
					if (!this.can('pban')) return this.sendReply("Access denied.");
					if (!parts[1]) {
						switch (room.emoteStatus) {
							case true:
								this.sendReply("Chat emotes are currently enabled in this room.");
								break;
							case false:
								this.sendReply("Chat emotes are currently disabled in this room.");
								break;
						}
					} else {
						switch (toId(parts[1])) {
							case 'on':
							case 'enable':
								if (!this.can('declare', null, room)) return this.sendReply("Access denied.");
								room.emoteStatus = true;
								room.chatRoomData.emoteStatus = room.emoteStatus;
								Rooms.global.writeChatRoomData();
								room.add(Tools.escapeHTML(user.name) + ' has enabled chat emotes in this room.');
								this.logModCommand(Tools.escapeHTML(user.name) + ' has enabled chat emotes in this room.');
								break;
							case 'off':
							case 'disable':
								if (!this.can('declare', null, room)) return this.sendReply("Access denied.");
								room.emoteStatus = false;
								room.chatRoomData.emoteStatus = room.emoteStatus;
								Rooms.global.writeChatRoomData();
								room.add(Tools.escapeHTML(user.name) + " has disabled chat emotes in this room.");
								this.logModCommand(Tools.escapeHTML(user.name) + " has disabled chat emotes in this room.");
								break;
							default:
								iif (!this.can('declare', null, room)) return this.sendReply("Access denied.");
								this.sendReply("Usage: /ezemote status - views the current emote status OR /ezemote status, [off / on] - Turns emotes on / off.  Requires &, ~.");
						}
					}
					break;
				case 'help':
				default:
					if (!this.canBroadcast()) return;
					this.sendReplyBox(
						"
" +
							"EZ-Emote Commands:
" +
							"(By: panpawn)
" +
							"/ezemote add, [emote], [link] - Adds an emote. Requires @, &, ~.
" +
							"/ezemote remove, [emote] - Removes an emote. Requires @, &, ~.
" +
							"/ezemote status - Views the current status of emotes.  Requires #, &, ~.
" +
							"/ezemote status, [on / off] - Enables or disables the status of emotes. Requires #, &, ~.
" +
							"/ezemote list - Shows the emotes that were added with this command.
" +
							"/ezemote view - Shows all of the current emotes with their respected image.
" +
							"/ezemote object - Shows the object of Core.emoticons. (Mostly for development usage)
" +
							"/ezemote help - Shows this help command.
" +
						"
	"
					);
			}
		} catch (e) {
			console.log("ERROR!  The EZ-Emote script has crashed!");
		}
	}
};
<|endoftext|>


<commit_before>import { connect } from 'react-redux';
import { getAdminsSelected } from 'pages/country/widget/widget-selectors';
import Component from './widget-component';

const mapStateToProps = ({ location, countryData }) => {
  const {
    isCountriesLoading,
    isRegionsLoading,
    isSubRegionsLoading,
    isGeostoreLoading
  } = countryData;
  const adminData = {
    location: location.payload,
    countries: countryData.countries,
    regions: countryData.regions,
    subRegions: countryData.subRegions
  };
  return {
    isMetaLoading:
      isCountriesLoading ||
      isRegionsLoading ||
      isSubRegionsLoading ||
      isGeostoreLoading,
    locationNames: getAdminsSelected(adminData)
  };
};

export default connect(mapStateToProps, null)(Component);
<commit_msg>allow all widgets to access active filter key<commit_after>import { connect } from 'react-redux';
import {
  getAdminsSelected,
  getActiveAdmin
} from 'pages/country/widget/widget-selectors';
import Component from './widget-component';

const mapStateToProps = ({ location, countryData }) => {
  const {
    isCountriesLoading,
    isRegionsLoading,
    isSubRegionsLoading,
    isGeostoreLoading
  } = countryData;
  const adminData = {
    location: location.payload,
    countries: countryData.countries,
    regions: countryData.regions,
    subRegions: countryData.subRegions
  };
  return {
    isMetaLoading:
      isCountriesLoading ||
      isRegionsLoading ||
      isSubRegionsLoading ||
      isGeostoreLoading,
    locationNames: getAdminsSelected(adminData),
    activeLocation: getActiveAdmin({ location: location.payload })
  };
};

export default connect(mapStateToProps, null)(Component);
<|endoftext|>


<commit_before>angular.module('md.data.table').factory('$mdTableRepeat', function () {
  'use strict';

  var cache = {};

  function Repeat(ngRepeat) {
    this._tokens = ngRepeat.split(' ');
    this._iterator = 0;

    this.item = this.current();
    while(this.hasNext() && this.getNext() !== 'in') {
      this.item += this.current();
    }

    this.items = this.getNext();
    while(this.hasNext() && ['|', 'track'].indexOf(this.getNext()) === -1) {
      this.items += this.current();
    }

    this.orderBy = undefined;
    if(this.hasNext() && this.getNext() === 'orderBy:') {
      this.orderBy = this.getNext();
    }

    this.trackBy = undefined;
    if(this.hasNext()) {
      this.trackBy = this.getNext() === 'by' ? this.getNext() : this.current();
    }
  }

  Repeat.prototype.current = function () {
    return this._tokens[this._iterator];
  };

  Repeat.prototype.getNext = function() {
    return this._tokens[++this._iterator];
  };

  Repeat.prototype.getValue = function() {
    return this._tokens.join(' ');
  };

  Repeat.prototype.hasNext = function () {
    return this._iterator < this._tokens.length - 1;
  };

  Repeat.prototype.insertOrderBy = function (property) {
    this.orderBy = property;
    this._iterator = this.trackBy ? this._tokens.indexOf(this.trackBy) : this._tokens.length;
    this._tokens.splice(this._iterator, 0, '|', 'orderBy:', property);
    return this._tokens.join(' ');
  };

  function parse(ngRepeat) {
    if(!cache.hasOwnProperty(ngRepeat)) {
      return (cache[ngRepeat] = new Repeat(ngRepeat));
    }

    return cache[ngRepeat];
  }

  return {
    parse: parse
  };

});<commit_msg>commenting out unused code<commit_after>angular.module('md.data.table').factory('$mdTableRepeat', function () {
  'use strict';

  var cache = {};

  function Repeat(ngRepeat) {
    this._tokens = ngRepeat.split(' ');
    this._iterator = 0;

    this.item = this.current();
    while(this.hasNext() && this.getNext() !== 'in') {
      this.item += this.current();
    }

    this.items = this.getNext();
    while(this.hasNext() && ['|', 'track'].indexOf(this.getNext()) === -1) {
      this.items += this.current();
    }

    // this.orderBy = undefined;
    // if(this.hasNext() && this.getNext() === 'orderBy:') {
    //   this.orderBy = this.getNext();
    // }
    //
    // this.trackBy = undefined;
    // if(this.hasNext()) {
    //   this.trackBy = this.getNext() === 'by' ? this.getNext() : this.current();
    // }
  }

  Repeat.prototype.current = function () {
    return this._tokens[this._iterator];
  };

  Repeat.prototype.getNext = function() {
    return this._tokens[++this._iterator];
  };

  Repeat.prototype.getValue = function() {
    return this._tokens.join(' ');
  };

  Repeat.prototype.hasNext = function () {
    return this._iterator < this._tokens.length - 1;
  };

  // Repeat.prototype.insertOrderBy = function (property) {
  //   this.orderBy = property;
  //   this._iterator = this.trackBy ? this._tokens.indexOf(this.trackBy) : this._tokens.length;
  //   this._tokens.splice(this._iterator, 0, '|', 'orderBy:', property);
  //   return this._tokens.join(' ');
  // };

  function parse(ngRepeat) {
    if(!cache.hasOwnProperty(ngRepeat)) {
      return (cache[ngRepeat] = new Repeat(ngRepeat));
    }

    return cache[ngRepeat];
  }

  return {
    parse: parse
  };

});<|endoftext|>


<commit_before>(function() {
    'use strict';

    /**
     * Controller for the imls app home view
     */
    /* ngInject */
    function MuseumController($cookies, $log, $scope, $state, $stateParams, $timeout, $window, resize,
                              Config, ACS, ACSGraphs, MapStyle, Museum) {
        var ctl = this;

        var MAP_SLIDE_TRANSITION_MS = 400;
        var ONE_MILE_IN_M = 1609.344;

        var vis = null;
        var map = null;
        var searchPolygon = null;
        var searchPolygonStyle = angular.extend({}, MapStyle.circle, {
            dashArray: '8',
        });

        initialize();

        function initialize() {
            ctl.acsRadiusOptions = [{
                value: ONE_MILE_IN_M,
                label: '1 Mile Radius'
            }, {
                value: ONE_MILE_IN_M * 3,
                label: '3 Mile Radius'
            }, {
                value: ONE_MILE_IN_M * 5,
                label: '5 Mile Radius'
            }];
            ctl.acsRadius = ctl.acsRadiusOptions[0].value;
            ctl.mapExpanded = false;
            ctl.activeTab = 'people';

            ctl.onBackButtonClicked = onBackButtonClicked;
            ctl.onRadiusChanged = onRadiusChanged;
            ctl.onStartDrawPolygon = onStartDrawPolygon;
            ctl.onStartDrawCircle = onStartDrawCircle;
            ctl.onPrintClicked = onPrintClicked;

            $scope.$on('imls:vis:ready', onVisReady);

            resize($scope).call(ACSGraphs.updateCharts);
        }

        function onVisReady(event, newVis, newMap) {
            vis = newVis;
            map = newMap;

            map.on('draw:created', onDrawCreated);

            Museum.detail($stateParams.museum).then(setMuseum).catch(function (error) {
                $log.error('Error loading museum', $stateParams.museum, error);
            });
        }

        function setMuseum(rows) {
            ctl.museum = rows[0];
            Museum.byTypeInState(ctl.museum.gstate).then(function (response) {
                ctl.nearbyInState = response;
            });
            $log.info(ctl.museum);
            onRadiusChanged();
        }

        function onPrintClicked() {
            $window.print();
        }

        function onRadiusChanged() {
            var center = L.latLng(ctl.museum.latitude, ctl.museum.longitude);
            // Initialize charts with data in a 1 mi radius
            setACSSearchRadius(center, ctl.acsRadius);
            ACS.getRadius(center.lng, center.lat, ctl.acsRadius).then(onACSDataComplete, onACSDataError);
            Museum.byTypeInRadius(center.lng, center.lat, ctl.acsRadius).then(function (data) {
                ctl.nearbyInArea = data;
            });

        }

        function onStartDrawPolygon() {
            clearSearchPolygon();
            var polygonDrawOptions = {};
            new L.Draw.Polygon(map, polygonDrawOptions).enable();
            setMapExpanded(true);
        }

        function onStartDrawCircle() {
            clearSearchPolygon();
            var circleDrawOptions = {};
            new L.Draw.Circle(map, circleDrawOptions).enable();
            setMapExpanded(true);
        }

        function onDrawCreated(event) {
            var layer = event.layer;
            var acsRequest;
            var nearbyRequest;
            if (event.layerType === 'polygon') {
                var points = layer.toGeoJSON().geometry.coordinates[0];
                $log.info(points);
                acsRequest = ACS.getPolygon(points);
                nearbyRequest = Museum.byTypeInPolygon(points);
                setACSSearchPolygon(_.map(points, function (p) { return [p[1], p[0]]; }));
                setMapExpanded(false);
            } else if (event.layerType === 'circle') {
                var latlng = layer.getLatLng();
                var radius = layer.getRadius();
                acsRequest = ACS.getRadius(latlng.lng, latlng.lat, radius);
                nearbyRequest = Museum.byTypeInRadius(latlng.lng, latlng.lat, radius);
                setACSSearchRadius(latlng, radius);
                setMapExpanded(false);
            }
            acsRequest.then(onACSDataComplete, onACSDataError);
            nearbyRequest.then(function (data) {
                ctl.nearbyInArea = data;
            });
        }

        function setMapExpanded(isExpanded) {
            ctl.mapExpanded = !!(isExpanded);
            $timeout(function () {
                map.invalidateSize();
                // TODO: Figure out how to properly refit bounds to searchPolygon once
                // the slide transition completes
            }, MAP_SLIDE_TRANSITION_MS);
        }

        function onACSDataComplete(data) {
            ctl.acsData = data;
        }

        function onACSDataError(error) {
            $log.error('ACS Data Load:', error);
        }

        function setACSSearchPolygon(points) {
            clearSearchPolygon();
            searchPolygon = L.polygon(points, searchPolygonStyle);
            map.addLayer(searchPolygon);
            map.fitBounds(searchPolygon.getBounds());
        }

        function setACSSearchRadius(center, radius) {
            clearSearchPolygon();
            searchPolygon = L.circle(center, radius, searchPolygonStyle);
            map.addLayer(searchPolygon);
            map.fitBounds(searchPolygon.getBounds());
        }

        function setLastPositionCookie() {
            if (!ctl.museum) {
                return;
            }
            $cookies.putObject(Config.cookies.LAST_SEARCHED, {
                text: ctl.museum.commonname || '',
                position: {
                    x: ctl.museum.longitude,
                    y: ctl.museum.latitude
                }
            }, {
                // Set expiry to 12hrs from set time
                expires: new Date(new Date().getTime() + 12 * 3600 * 1000)
            });
        }

        function onBackButtonClicked() {
            setLastPositionCookie();
            $state.go('home');
        }

        function clearSearchPolygon() {
            if (searchPolygon) {
                map.removeLayer(searchPolygon);
                searchPolygon = null;
            }
        }
    }

    angular.module('imls.views.museum')
    .controller('MuseumController', MuseumController);

})();
<commit_msg>Closes #43: New analysis bounds are cutoff when map resizes<commit_after>(function() {
    'use strict';

    /**
     * Controller for the imls app home view
     */
    /* ngInject */
    function MuseumController($cookies, $log, $scope, $state, $stateParams, $timeout, $window, resize,
                              Config, ACS, ACSGraphs, MapStyle, Museum) {
        var ctl = this;

        var MAP_SLIDE_TRANSITION_MS = 400;
        var ONE_MILE_IN_M = 1609.344;

        var vis = null;
        var map = null;
        var searchPolygon = null;
        var searchPolygonStyle = angular.extend({}, MapStyle.circle, {
            dashArray: '8',
        });

        initialize();

        function initialize() {
            ctl.acsRadiusOptions = [{
                value: ONE_MILE_IN_M,
                label: '1 Mile Radius'
            }, {
                value: ONE_MILE_IN_M * 3,
                label: '3 Mile Radius'
            }, {
                value: ONE_MILE_IN_M * 5,
                label: '5 Mile Radius'
            }];
            ctl.acsRadius = ctl.acsRadiusOptions[0].value;
            ctl.mapExpanded = false;
            ctl.activeTab = 'people';

            ctl.onBackButtonClicked = onBackButtonClicked;
            ctl.onRadiusChanged = onRadiusChanged;
            ctl.onStartDrawPolygon = onStartDrawPolygon;
            ctl.onStartDrawCircle = onStartDrawCircle;
            ctl.onPrintClicked = onPrintClicked;

            $scope.$on('imls:vis:ready', onVisReady);

            resize($scope).call(ACSGraphs.updateCharts);
        }

        function onVisReady(event, newVis, newMap) {
            vis = newVis;
            map = newMap;

            map.on('draw:created', onDrawCreated);

            Museum.detail($stateParams.museum).then(setMuseum).catch(function (error) {
                $log.error('Error loading museum', $stateParams.museum, error);
            });
        }

        function setMuseum(rows) {
            ctl.museum = rows[0];
            Museum.byTypeInState(ctl.museum.gstate).then(function (response) {
                ctl.nearbyInState = response;
            });
            $log.info(ctl.museum);
            onRadiusChanged();
        }

        function onPrintClicked() {
            $window.print();
        }

        function onRadiusChanged() {
            var center = L.latLng(ctl.museum.latitude, ctl.museum.longitude);
            // Initialize charts with data in a 1 mi radius
            setACSSearchRadius(center, ctl.acsRadius);
            ACS.getRadius(center.lng, center.lat, ctl.acsRadius).then(onACSDataComplete, onACSDataError);
            Museum.byTypeInRadius(center.lng, center.lat, ctl.acsRadius).then(function (data) {
                ctl.nearbyInArea = data;
            });

        }

        function onStartDrawPolygon() {
            clearSearchPolygon();
            var polygonDrawOptions = {};
            new L.Draw.Polygon(map, polygonDrawOptions).enable();
            setMapExpanded(true);
        }

        function onStartDrawCircle() {
            clearSearchPolygon();
            var circleDrawOptions = {};
            new L.Draw.Circle(map, circleDrawOptions).enable();
            setMapExpanded(true);
        }

        function onDrawCreated(event) {
            var layer = event.layer;
            var acsRequest;
            var nearbyRequest;
            if (event.layerType === 'polygon') {
                var points = layer.toGeoJSON().geometry.coordinates[0];
                $log.info(points);
                acsRequest = ACS.getPolygon(points);
                nearbyRequest = Museum.byTypeInPolygon(points);
                setACSSearchPolygon(_.map(points, function (p) { return [p[1], p[0]]; }), {
                    resetBounds: false
                });
                setMapExpanded(false);
            } else if (event.layerType === 'circle') {
                var latlng = layer.getLatLng();
                var radius = layer.getRadius();
                acsRequest = ACS.getRadius(latlng.lng, latlng.lat, radius);
                nearbyRequest = Museum.byTypeInRadius(latlng.lng, latlng.lat, radius);
                setACSSearchRadius(latlng, radius, { resetBounds: false });
                setMapExpanded(false);
            }
            acsRequest.then(onACSDataComplete, onACSDataError);
            nearbyRequest.then(function (data) {
                ctl.nearbyInArea = data;
            });
        }

        function setMapExpanded(isExpanded) {
            ctl.mapExpanded = !!(isExpanded);
            $timeout(function () {
                map.invalidateSize();
                if (searchPolygon) {
                    map.fitBounds(searchPolygon.getBounds());
                }
            }, MAP_SLIDE_TRANSITION_MS * 1.5);
        }

        function onACSDataComplete(data) {
            ctl.acsData = data;
        }

        function onACSDataError(error) {
            $log.error('ACS Data Load:', error);
        }

        function setACSSearchPolygon(points, options) {
            var defaults = { resetBounds: true };
            var opts = angular.extend({}, defaults, options);
            clearSearchPolygon();
            searchPolygon = L.polygon(points, searchPolygonStyle);
            map.addLayer(searchPolygon);
            if (opts.resetBounds) {
                map.fitBounds(searchPolygon.getBounds());
            }
        }

        function setACSSearchRadius(center, radius, options) {
            var defaults = { resetBounds: true };
            var opts = angular.extend({}, defaults, options);
            clearSearchPolygon();
            searchPolygon = L.circle(center, radius, searchPolygonStyle);
            map.addLayer(searchPolygon);
            if (opts.resetBounds) {
                map.fitBounds(searchPolygon.getBounds());
            }
        }

        function setLastPositionCookie() {
            if (!ctl.museum) {
                return;
            }
            $cookies.putObject(Config.cookies.LAST_SEARCHED, {
                text: ctl.museum.commonname || '',
                position: {
                    x: ctl.museum.longitude,
                    y: ctl.museum.latitude
                }
            }, {
                // Set expiry to 12hrs from set time
                expires: new Date(new Date().getTime() + 12 * 3600 * 1000)
            });
        }

        function onBackButtonClicked() {
            setLastPositionCookie();
            $state.go('home');
        }

        function clearSearchPolygon() {
            if (searchPolygon) {
                map.removeLayer(searchPolygon);
                searchPolygon = null;
            }
        }
    }

    angular.module('imls.views.museum')
    .controller('MuseumController', MuseumController);

})();
<|endoftext|>


<commit_before>/**
 * Created by epotignano on 13/4/16.
 */

import React, { Component, PropTypes} from 'react';
import moment from 'moment';
import DayPicker,{DateUtils} from 'react-day-picker';
import "react-day-picker/lib/style.css";
import "../styles/dayPicker.scss";
import { connect } from "react-redux";
import _ from 'lodash';
import Loader from '../components/Loader';
import { GetAppointments, SelectNewDate, GetClosestAppointments } from '../actions/Appointments';
import MomentLocaleUtils from 'react-day-picker/moment';

import WeekDisplayer from './WeekDisplayer';

const currentYear = (new Date()).getFullYear();
const fromMonth = new Date(currentYear, 0, 1, 0, 0);
const toMonth = new Date(currentYear + 10, 11, 31, 23, 59);
import 'moment/locale/es';

//Pasar esto a un state si se requiere poder cambiar de idioma.
const locale = 'es';
function getFirstAppointmentAvailableForLocation(locations, idLocalidad) {
  let _appointment;
  locations.some((localidad)=>{
    if(idLocalidad == localidad.id_localidad){
      _appointment = localidad.turnos[0];
      return true;
    }
  })

  return _appointment;

}

function filterAppointmentsForWeek(selectedDay, appointments, range) {
  return _.filter(appointments, function ProcessAppointment(appointment) {
    if( (range.min.utc() <= moment(appointment.fecha_hora_inicio).utc())  &&  (moment(appointment.fecha_hora_inicio).utc() <= range.max.utc())) {
      return appointment
    }
  });
}

function smallerThanToday(day) {
    return new Date() >= day;
}

class AvailabilityDisplayer extends Component {

  constructor(props) {
    super(props);
    this.state = {
      displayDay : moment(),
      appointmentsForWeek : this.calculateAvailableAppointmentsForWeek(moment(), this.props.availability, true),
      selectedDate: moment()
    };
  }

  renderWeekDisplayer(selectedDate, appointments){

    const { idLocalidad, institution, availability, appointment, doctor, doctorUsername, dispatch } = this.props;
    const { loadingAppointmentsForLocation } = appointment;

    if(loadingAppointmentsForLocation == idLocalidad){
      return (<Loader inverted={true} loaderText="Leyendo turnos"/>);
    }
    var _datesToUse;

    appointment.responsable_servicio.localidades.some((localidad) =>{
      if(idLocalidad == localidad.localidad.id){
        _datesToUse = localidad.turnos
      }
    });

    var _appointmentsForWeek = this.calculateAvailableAppointmentsForWeek(selectedDate, _datesToUse, true);
    if(!this.state.showClosestAppointment){
      if(_appointmentsForWeek.length) {
        return (<WeekDisplayer appointmentsForWeek={_appointmentsForWeek}
                         selectedDay={selectedDate}
                         institution={institution} idLocalidad={idLocalidad}  doctor={doctor}/>)
      } else if(!appointment.loadingAppointments &&
        !appointment.loadingDoctorData &&
        !_appointmentsForWeek.length && appointment.readSuccess
      ) {
        GetClosestAppointments(doctorUsername, idLocalidad).then((data) => {
          let _closest =  getFirstAppointmentAvailableForLocation(data.data, idLocalidad);
          this.setState({
            showClosestAppointment: true,
            closestAppointment : _closest,
            availability : _closest
          });
        });
      }
    }else{
      if(this.state.closestAppointment.fecha_hora_inicio){
        return (
 {
          this.setNewDate(this.state.closestAppointment.fecha_hora_inicio)
      }}>

         Proximo turno disponible {moment(this.state.closestAppointment.fecha_hora_inicio).format("dddd DD/MMM/YYYY")}

)
      } else {
        return (

Aún no se han registrado turnos en esta localidad

)
      }
    }

  }

  calculateAvailableAppointmentsForWeek(selectedDate, appointments, initial) {
     const { dispatch } = this.props;
      let min = selectedDate;
      let max = moment(selectedDate).add(6, 'd');
      if(initial) {
        return filterAppointmentsForWeek(selectedDate, appointments ,{min, max})
      }
  }

  setNewDate(day) {
    var _day = moment(day);
    const { appointment, idLocalidad, dispatch } = this.props;

    this.setState({
      selectedDate : _day,
      month: _day.toDate(),
      showClosestAppointment: false
    });

    dispatch(SelectNewDate(_day, appointment.doctorUsername, idLocalidad));
  }

  render() {
    const { availability, appointment, idLocalidad, doctor } = this.props;
    return(

            <DayPicker
              locale={locale}
              localeUtils={MomentLocaleUtils}
              className="Availability"
              initialMonth={ this.state.month }
              disabledDays={DateUtils.isPastDay}
              onDayClick={ (e, day, { disabled, selected }) => {
                  if(!disabled){
                    this.setNewDate(day);
                  }
                }
              }
            />

              { this.renderWeekDisplayer(this.state.selectedDate, availability)}

    )
  }
}

AvailabilityDisplayer.propTypes = {
  availability : PropTypes.any,
  institution: PropTypes.object,
  idLocalidad: PropTypes.any,
  doctorUsername: PropTypes.string,
  doctor: PropTypes.any
};

function mapStateToProps(state) {
  const { appointment } = state;
  return {
    appointment
  }
}

export default connect(mapStateToProps)(AvailabilityDisplayer);
<commit_msg>Loader for closest appointments<commit_after>/**
 * Created by epotignano on 13/4/16.
 */

import React, { Component, PropTypes} from 'react';
import moment from 'moment';
import DayPicker,{DateUtils} from 'react-day-picker';
import "react-day-picker/lib/style.css";
import "../styles/dayPicker.scss";
import { connect } from "react-redux";
import _ from 'lodash';
import Loader from '../components/Loader';
import { GetAppointments, SelectNewDate, GetClosestAppointments } from '../actions/Appointments';
import MomentLocaleUtils from 'react-day-picker/moment';

import WeekDisplayer from './WeekDisplayer';

const currentYear = (new Date()).getFullYear();
const fromMonth = new Date(currentYear, 0, 1, 0, 0);
const toMonth = new Date(currentYear + 10, 11, 31, 23, 59);
import 'moment/locale/es';

//Pasar esto a un state si se requiere poder cambiar de idioma.
const locale = 'es';
function getFirstAppointmentAvailableForLocation(locations, idLocalidad) {
  let _appointment;
  locations.some((localidad)=>{
    if(idLocalidad == localidad.id_localidad){
      _appointment = localidad.turnos[0];
      return true;
    }
  })

  return _appointment;

}

function filterAppointmentsForWeek(selectedDay, appointments, range) {
  return _.filter(appointments, function ProcessAppointment(appointment) {
    if( (range.min.utc() <= moment(appointment.fecha_hora_inicio).utc())  &&  (moment(appointment.fecha_hora_inicio).utc() <= range.max.utc())) {
      return appointment
    }
  });
}

function smallerThanToday(day) {
    return new Date() >= day;
}

class AvailabilityDisplayer extends Component {

  constructor(props) {
    super(props);
    this.state = {
      displayDay : moment(),
      appointmentsForWeek : this.calculateAvailableAppointmentsForWeek(moment(), this.props.availability, true),
      selectedDate: moment()
    };
  }

  renderWeekDisplayer(selectedDate, appointments){

    const { idLocalidad, institution, availability, appointment, doctor, doctorUsername, dispatch } = this.props;
    const { loadingAppointmentsForLocation, loadingAppointments } = appointment;

    if(loadingAppointmentsForLocation == idLocalidad || loadingAppointments){
      return (<Loader inverted={true} loaderText="Leyendo turnos"/>);
    }
    var _datesToUse;

    appointment.responsable_servicio.localidades.some((localidad) =>{
      if(idLocalidad == localidad.localidad.id){
        _datesToUse = localidad.turnos
      }
    });

    var _appointmentsForWeek = this.calculateAvailableAppointmentsForWeek(selectedDate, _datesToUse, true);
    if(!this.state.showClosestAppointment){
      if(_appointmentsForWeek.length) {
        return (<WeekDisplayer appointmentsForWeek={_appointmentsForWeek}
                         selectedDay={selectedDate}
                         institution={institution} idLocalidad={idLocalidad}  doctor={doctor}/>)
      } else if(!appointment.loadingAppointments &&
        !appointment.loadingDoctorData &&
        !_appointmentsForWeek.length && appointment.readSuccess
      ) {
        GetClosestAppointments(doctorUsername, idLocalidad).then((data) => {
          let _closest =  getFirstAppointmentAvailableForLocation(data.data, idLocalidad);
          this.setState({
            showClosestAppointment: true,
            closestAppointment : _closest,
            availability : _closest
          });
        });

        return (<Loader inverted={true} loaderText="Leyendo turnos próximos disponibles"></Loader>)
      }
    }else{
      if(this.state.closestAppointment.fecha_hora_inicio){
        return (
 {
          this.setNewDate(this.state.closestAppointment.fecha_hora_inicio)
      }}>

         Proximo turno disponible {moment(this.state.closestAppointment.fecha_hora_inicio).format("dddd DD/MMM/YYYY")}

)
      } else {
        return (

Aún no se han registrado turnos en esta localidad

)
      }
    }

  }

  calculateAvailableAppointmentsForWeek(selectedDate, appointments, initial) {
     const { dispatch } = this.props;
      let min = selectedDate;
      let max = moment(selectedDate).add(6, 'd');
      if(initial) {
        return filterAppointmentsForWeek(selectedDate, appointments ,{min, max})
      }
  }

  setNewDate(day) {
    var _day = moment(day);
    const { appointment, idLocalidad, dispatch } = this.props;

    this.setState({
      selectedDate : _day,
      month: _day.toDate(),
      showClosestAppointment: false
    });

    dispatch(SelectNewDate(_day, appointment.doctorUsername, idLocalidad));
  }

  render() {
    const { availability, appointment, idLocalidad, doctor } = this.props;
    return(

            <DayPicker
              locale={locale}
              localeUtils={MomentLocaleUtils}
              className="Availability"
              initialMonth={ this.state.month }
              disabledDays={DateUtils.isPastDay}
              onDayClick={ (e, day, { disabled, selected }) => {
                  if(!disabled){
                    this.setNewDate(day);
                  }
                }
              }
            />

              { this.renderWeekDisplayer(this.state.selectedDate, availability)}

    )
  }
}

AvailabilityDisplayer.propTypes = {
  availability : PropTypes.any,
  institution: PropTypes.object,
  idLocalidad: PropTypes.any,
  doctorUsername: PropTypes.string,
  doctor: PropTypes.any
};

function mapStateToProps(state) {
  const { appointment } = state;
  return {
    appointment
  }
}

export default connect(mapStateToProps)(AvailabilityDisplayer);
<|endoftext|>