<commit_before>"use strict";

eas.sync.Contacts = {

    createItem : function () {
        return Components.classes["@mozilla.org/addressbook/cardproperty;1"].createInstance(Components.interfaces.nsIAbCard);
    },

    promisifyAddressbook: function (addressbook) {
    /*
        Return obj with identical interface to promisifyCalendar. But we currently do not need a promise.
            adoptItem(card)
            modifyItem(newcard, existingcard)
            deleteItem(card)
            getItem(id)

        Avail API:
            addressBook.modifyCard(card);
            addressBook.getCardFromProperty("localId", ClientId, false);
            addressBook.deleteCards(cardsToDelete);
            card.setProperty('ServerId', ServerId);
    */
        let apiWrapper = {
            adoptItem: function (card) {
                /* add card to addressbook */
                tbSync.addNewCardFromServer(card, addressbook);
            },

            modifyItem: function (newcard, existingcard) {
                /* modify card */
                addressbook.modifyCard(newcard);
            },

            deleteItem: function (card) {
                /* remove card from addressBook */
                let cardsToDelete = Components.classes["@mozilla.org/array;1"].createInstance(Components.interfaces.nsIMutableArray);
                cardsToDelete.appendElement(card);
                addressbook.deleteCards(cardsToDelete);
            },

            getItem: function (searchId) {
                /* return array of items matching */
                let items = [];
                let card = addressbook.getCardFromProperty("ServerId", searchId, true); //3rd param enables case sensitivity

                if (card) {
                    let item = {
                        get id() {return this.card.getProperty("ServerId", "")},
                        set id(newId) {this.card.setProperty("ServerId", newId)},
                        get icalString() {return "CardData"},
                        clone: function () { return this; } //no real clone
                    };

                    //actually add the card
                    item.card = card;
                    items.push(item);
                }

                return items;
            }
        };

        return apiWrapper;
    },

/*

These need special treatment
        0x05: 'Anniversary',
        0x08: 'Birthday',
        0x09: 'Body',
        0x0A: 'BodySize',
        0x0B: 'BodyTruncated',
        0x15: 'Categories',
        0x16: 'Category',
        0x17: 'Children',
        0x18: 'Child',
        0x1D: 'Email3Address',

The following are the core properties that are used by TB:
 * - Names:
 *   - PhoneticFirstName, PhoneticLastName
 *   - SpouseName, FamilyName
 * - Home Contact:
 *   - HomeAddress, HomeAddress2,
 *   - HomePhone, HomePhoneType
 * - Work contact. Same as home, but with `Work' instead of `Home'
 * - Other Contact:
 *   - FaxNumber, FaxNumberType
 *   - PagerNumber, PagerNumberType
 *   - CellularNumber, CellularNumberType
 * - _AimScreenName
 * - Dates:
 * - WebPage1 (work), WebPage2 (home)
 * - Custom1, Custom2, Custom3, Custom4

*/

    //includes all properties, which can be mapped 1-to-1
    map_TB_properties_to_EAS_properties : {
        DisplayName: 'FileAs',
        FirstName: 'FirstName',
        LastName: 'LastName',
        //NickName: 'NickName',
        PrimaryEmail: 'Email1Address',
        SecondEmail: 'Email2Address',

/*        0x06: 'AssistantName',
        0x07: 'AssistantPhoneNumber',
        0x08: 'Business2PhoneNumber',
        0x11: 'BusinessAddressStreet',
        0x12: 'BusinessFaxNumber',
        0x14: 'CarPhoneNumber',
        0x20: 'Home2PhoneNumber',
        0x25: 'HomeAddressStreet',
        0x26: 'HomeFaxNumber',
        0x2A: 'MiddleName',
        0x2B: 'MobilePhoneNumber',
        0x2C: 'OfficeLocation',
        0x2D: 'OtherAddressCity',
        0x2E: 'OtherAddressCountry',
        0x2F: 'OtherAddressPostalCode',
        0x30: 'OtherAddressState',
        0x31: 'OtherAddressStreet',
        0x32: 'PagerNumber',
        0x33: 'RadioPhoneNumber',
        0x34: 'Spouse',
        0x35: 'Suffix',
        0x36: 'Title',
        0x37: 'WebPage',
        0x38: 'YomiCompanyName',
        0x39: 'YomiFirstName',
        0x3A: 'YomiLastName',
        0x3B: 'CompressedRTF',
        0x3C: 'Picture',
        0x3D: 'Alias',
        0x3E: 'WeightedRank',

        0x05: 'CustomerId',
        0x06: 'GovernmentId',
        0x07: 'IMAddress',
        0x08: 'IMAddress2',
        0x09: 'IMAddress3',
        0x0a: 'ManagerName',
        0x0b: 'CompanyMainPhone',
        0x0c: 'AccountName',
        0x0e: 'MMS',
        */
        HomeCity: 'HomeAddressCity',
        HomeCountry: 'HomeAddressCountry',
        HomeZipCode: 'HomeAddressPostalCode',
        HomeState: 'HomeAddressState',
        HomePhone: 'HomePhoneNumber',

        Company: 'CompanyName',
        Department: 'Department',
        JobTitle: 'JobTitle',
        WorkCity: 'BusinessAddressCity',
        WorkCountry: 'BusinessAddressCountry',
        WorkZipCode: 'BusinessAddressPostalCode',
        WorkState: 'BusinessAddressState',
        WorkPhone: 'BusinessPhoneNumber'
    },

    // --------------------------------------------------------------------------- //
    // Read WBXML and set Thunderbird item
    // --------------------------------------------------------------------------- //
    setThunderbirdItemFromWbxml: function (card, data, id, syncdata) {
        let asversion = tbSync.db.getAccountSetting(syncdata.account, "asversion");

        card.setProperty("ServerId", id);

        //we loop over all known TB properties
        for (let p=0; p < this.TB_properties.length; p++) {
            let TB_property = this.TB_properties[p];
            let EAS_property = this.map_TB_properties_to_EAS_properties[TB_property];
            let value = xmltools.checkString(data[EAS_property]);

            //do we need to manipulate the value?
            switch (EAS_property) {
                case "Email1Address":
                case "Email2Address":
                case "Email3Address":
                    let parsedInput = MailServices.headerParser.makeFromDisplayAddress(value);
                    let fixedValue =  (parsedInput && parsedInput[0] && parsedInput[0].email) ? parsedInput[0].email : value;
                    if (fixedValue != value) {
                        tbSync.dump("Parsing email display string via RFC 2231 and RFC 2047 ("+EAS_property+")", value + " -> " + fixedValue);
                        value = fixedValue;
                    }
                    break;
            }

            card.setProperty(TB_property, value);
        }

        //further manipulations
        if (tbSync.db.getAccountSetting(syncdata.account, "displayoverride") == "1") {
           card.setProperty("DisplayName", card.getProperty("FirstName", "") + " " + card.getProperty("LastName", ""));

            if (card.getProperty("DisplayName", "" ) == " " )
                card.setProperty("DisplayName", card.getProperty("Company", card.getProperty("PrimaryEmail", "")));
        }

    },

    // --------------------------------------------------------------------------- //
    //read TB event and return its data as WBXML
    // --------------------------------------------------------------------------- //
    getWbxmlFromThunderbirdItem: function (item, syncdata, isException = false) {
        let asversion = tbSync.db.getAccountSetting(syncdata.account, "asversion");
        let wbxml = tbSync.wbxmltools.createWBXML("", syncdata.type); //init wbxml with "" and not with precodes, and set initial codepage
        let nowDate = new Date();

        //loop over all known TB properties
        for (let p=0; p < this.TB_properties.length; p++) {
            let TB_property = this.TB_properties[p];
            let EAS_property = this.map_TB_properties_to_EAS_properties[TB_property];
            wbxml.atag(EAS_property, item.card.getProperty(TB_property,""));
        }

        return wbxml.getBytes();
    }

}

eas.sync.Contacts.TB_properties = Object.keys(eas.sync.Contacts.map_TB_properties_to_EAS_properties);
<commit_msg>add birthday and anniversary fields to contact sync (#76)<commit_after>"use strict";

eas.sync.Contacts = {

    createItem : function (card = null) {
        let item = {
            get id() {return this.card.getProperty("ServerId", "")},
            set id(newId) {this.card.setProperty("ServerId", newId)},
            get icalString() {return "CardData"},
            clone: function () { return this; } //no real clone
        };

        //actually add the card
        item.card = card ? card : Components.classes["@mozilla.org/addressbook/cardproperty;1"].createInstance(Components.interfaces.nsIAbCard);;

        return item;
    },

    promisifyAddressbook: function (addressbook) {
    /*
        Return obj with identical interface to promisifyCalendar. But we currently do not need a promise.
            adoptItem(card)
            modifyItem(newcard, existingcard)
            deleteItem(card)
            getItem(id)

        Avail API:
            addressBook.modifyCard(card);
            addressBook.getCardFromProperty("localId", ClientId, false);
            addressBook.deleteCards(cardsToDelete);
            card.setProperty('ServerId', ServerId);
    */
        let apiWrapper = {
            adoptItem: function (item) {
                /* add card to addressbook */
                tbSync.addNewCardFromServer(item.card, addressbook);
            },

            modifyItem: function (newitem, existingitem) {
                /* modify card */
                addressbook.modifyCard(newitem.card);
            },

            deleteItem: function (item) {
                /* remove card from addressBook */
                let cardsToDelete = Components.classes["@mozilla.org/array;1"].createInstance(Components.interfaces.nsIMutableArray);
                cardsToDelete.appendElement(item.card);
                addressbook.deleteCards(cardsToDelete);
            },

            getItem: function (searchId) {
                /* return array of items matching */
                let items = [];
                let card = addressbook.getCardFromProperty("ServerId", searchId, true); //3rd param enables case sensitivity

                if (card) {
                    items.push(eas.sync.Contacts.createItem(card));
                }

                return items;
            }
        };

        return apiWrapper;
    },

/*

These need special treatment
        0x05: 'Anniversary',
        0x08: 'Birthday',

        0x09: 'Body',
        0x0A: 'BodySize',
        0x0B: 'BodyTruncated',
        0x15: 'Categories',
        0x16: 'Category',
        0x17: 'Children',
        0x18: 'Child',
        0x1D: 'Email3Address',

The following are the core properties that are used by TB:
 * - Names:
 *   - PhoneticFirstName, PhoneticLastName
 *   - SpouseName, FamilyName
 * - Home Contact:
 *   - HomeAddress, HomeAddress2,
 *   - HomePhone, HomePhoneType
 * - Work contact. Same as home, but with `Work' instead of `Home'
 * - Other Contact:
 *   - FaxNumber, FaxNumberType
 *   - PagerNumber, PagerNumberType
 *   - CellularNumber, CellularNumberType
 * - _AimScreenName
 * - Dates:
 * - WebPage1 (work), WebPage2 (home)
 * - Custom1, Custom2, Custom3, Custom4

*/

    //includes all properties, which can be mapped 1-to-1
    map_TB_properties_to_EAS_properties : {
        DisplayName: 'FileAs',
        FirstName: 'FirstName',
        LastName: 'LastName',
        //NickName: 'NickName',
        PrimaryEmail: 'Email1Address',
        SecondEmail: 'Email2Address',

/*        0x06: 'AssistantName',
        0x07: 'AssistantPhoneNumber',
        0x08: 'Business2PhoneNumber',
        0x11: 'BusinessAddressStreet',
        0x12: 'BusinessFaxNumber',
        0x14: 'CarPhoneNumber',
        0x20: 'Home2PhoneNumber',
        0x25: 'HomeAddressStreet',
        0x26: 'HomeFaxNumber',
        0x2A: 'MiddleName',
        0x2B: 'MobilePhoneNumber',
        0x2C: 'OfficeLocation',
        0x2D: 'OtherAddressCity',
        0x2E: 'OtherAddressCountry',
        0x2F: 'OtherAddressPostalCode',
        0x30: 'OtherAddressState',
        0x31: 'OtherAddressStreet',
        0x32: 'PagerNumber',
        0x33: 'RadioPhoneNumber',
        0x34: 'Spouse',
        0x35: 'Suffix',
        0x36: 'Title',
        0x37: 'WebPage',
        0x38: 'YomiCompanyName',
        0x39: 'YomiFirstName',
        0x3A: 'YomiLastName',
        0x3B: 'CompressedRTF',
        0x3C: 'Picture',
        0x3D: 'Alias',
        0x3E: 'WeightedRank',

        0x05: 'CustomerId',
        0x06: 'GovernmentId',
        0x07: 'IMAddress',
        0x08: 'IMAddress2',
        0x09: 'IMAddress3',
        0x0a: 'ManagerName',
        0x0b: 'CompanyMainPhone',
        0x0c: 'AccountName',
        0x0e: 'MMS',
        */
        HomeCity: 'HomeAddressCity',
        HomeCountry: 'HomeAddressCountry',
        HomeZipCode: 'HomeAddressPostalCode',
        HomeState: 'HomeAddressState',
        HomePhone: 'HomePhoneNumber',

        Company: 'CompanyName',
        Department: 'Department',
        JobTitle: 'JobTitle',
        WorkCity: 'BusinessAddressCity',
        WorkCountry: 'BusinessAddressCountry',
        WorkZipCode: 'BusinessAddressPostalCode',
        WorkState: 'BusinessAddressState',
        WorkPhone: 'BusinessPhoneNumber'
    },

    // --------------------------------------------------------------------------- //
    // Read WBXML and set Thunderbird item
    // --------------------------------------------------------------------------- //
    setThunderbirdItemFromWbxml: function (item, data, id, syncdata) {
        let asversion = tbSync.db.getAccountSetting(syncdata.account, "asversion");

        item.card.setProperty("ServerId", id);

        //loop over all known TB properties which map 1-to-1
        for (let p=0; p < this.TB_properties.length; p++) {
            let TB_property = this.TB_properties[p];
            let EAS_property = this.map_TB_properties_to_EAS_properties[TB_property];
            let value = xmltools.checkString(data[EAS_property]);

            //is this property part of the send data?
            if (value) {
                //do we need to manipulate the value?
                switch (EAS_property) {
                    case "Email1Address":
                    case "Email2Address":
                    case "Email3Address":
                        let parsedInput = MailServices.headerParser.makeFromDisplayAddress(value);
                        let fixedValue =  (parsedInput && parsedInput[0] && parsedInput[0].email) ? parsedInput[0].email : value;
                        if (fixedValue != value) {
                            tbSync.dump("Parsing email display string via RFC 2231 and RFC 2047 ("+EAS_property+")", value + " -> " + fixedValue);
                            value = fixedValue;
                        }
                        break;
                }

                item.card.setProperty(TB_property, value);
            } else {
                //clear
                item.card.deleteProperty(TB_property);
            }
        }

        //take care of birthday and anniversary
        let dates = [];
        dates.push(["Birthday", "BirthDay", "BirthMonth", "BirthYear"]);
        dates.push(["Anniversary", "AnniversaryDay", "AnniversaryMonth", "AnniversaryYear"]);

        for (let p=0; p < dates.length; p++) {
            let value = xmltools.checkString(data[dates[p][0]]);
            if (value == "") {
                //clear
                item.card.deleteProperty(dates[p][1]);
                item.card.deleteProperty(dates[p][2]);
                item.card.deleteProperty(dates[p][3]);
            } else {
                //set
                let dateObj = new Date(value);
                item.card.setProperty(dates[p][3], dateObj.getFullYear().toString());
                item.card.setProperty(dates[p][2], (dateObj.getMonth()+1).toString());
                item.card.setProperty(dates[p][1], dateObj.getDate().toString());
            }
        }

        //further manipulations
        if (tbSync.db.getAccountSetting(syncdata.account, "displayoverride") == "1") {
           item.card.setProperty("DisplayName", item.card.getProperty("FirstName", "") + " " + item.card.getProperty("LastName", ""));

            if (item.card.getProperty("DisplayName", "" ) == " " )
                item.card.setProperty("DisplayName", item.card.getProperty("Company", item.card.getProperty("PrimaryEmail", "")));
        }

    },

    // --------------------------------------------------------------------------- //
    //read TB event and return its data as WBXML
    // --------------------------------------------------------------------------- //
    getWbxmlFromThunderbirdItem: function (item, syncdata, isException = false) {
        let asversion = tbSync.db.getAccountSetting(syncdata.account, "asversion");
        let wbxml = tbSync.wbxmltools.createWBXML("", syncdata.type); //init wbxml with "" and not with precodes, and set initial codepage
        let nowDate = new Date();

        //loop over all known TB properties which map 1-to-1 (send empty value if not set)
        for (let p=0; p < this.TB_properties.length; p++) {
            let TB_property = this.TB_properties[p];
            let EAS_property = this.map_TB_properties_to_EAS_properties[TB_property];
            wbxml.atag(EAS_property, item.card.getProperty(TB_property,""));
        }

        //take care of birthday and anniversary
        let dates = [];
        dates.push(["Birthday", "BirthDay", "BirthMonth", "BirthYear"]);
        dates.push(["Anniversary", "AnniversaryDay", "AnniversaryMonth", "AnniversaryYear"]);

        for (let p=0; p < dates.length; p++) {
            let year = item.card.getProperty(dates[p][3], "");
            let month = item.card.getProperty(dates[p][2], "");
            let day = item.card.getProperty(dates[p][1], "");
            if (year && month && day) {
                //set
                if (month.length<2) month="0"+month;
                if (day.length<2) day="0"+day;
                wbxml.atag(dates[p][0], year + "-" + month + "-" + day + "T00:00:00.000Z");
            } else {
                //clear ??? outlook does not like empty value
                //wbxml.atag(dates[p][0], "");
            }
        }

        return wbxml.getBytes();
    }

}

eas.sync.Contacts.TB_properties = Object.keys(eas.sync.Contacts.map_TB_properties_to_EAS_properties);
<|endoftext|>


<commit_before>global.Promise = require('bluebird');

const commando = require('discord.js-commando');
const Currency = require('./currency/Currency');
const Experience = require('./currency/Experience');
const oneLine = require('common-tags').oneLine;
const path = require('path');
const Raven = require('raven');
const winston = require('winston');

const Database = require('./postgreSQL/PostgreSQL');
const Redis = require('./redis/Redis');
const SequelizeProvider = require('./postgreSQL/SequelizeProvider');
const config = require('./settings');

const database = new Database();
const redis = new Redis();
const client = new commando.Client({
	owner: config.owner,
	commandPrefix: '?',
	unknownCommandResponse: false,
	disableEveryone: true
});

let earnedRecently = [];
let gainedXPRecently = [];

Raven.config(config.ravenKey);
Raven.install();

database.start();
redis.start();

client.setProvider(new SequelizeProvider(database.db));

client.dispatcher.addInhibitor(msg => {
	const blacklist = client.provider.get('global', 'userBlacklist', []);

	if (!blacklist.includes(msg.author.id)) return false;

	return `User ${msg.author.username}#${msg.author.discriminator} (${msg.author.id}) has been blacklisted.`;
});

client.on('error', winston.error)
	.on('warn', winston.warn)
	.on('ready', () => {
		winston.info(oneLine`
			Client ready... Logged in as ${client.user.username}#${client.user.discriminator} (${client.user.id})
		`);
		Currency.leaderboard();
	})
	.on('disconnect', () => { winston.warn('Disconnected!'); })
	.on('reconnect', () => { winston.warn('Reconnecting...'); })
	.on('commandRun', (cmd, promise, msg, args) => {
		winston.info(oneLine`${msg.author.username}#${msg.author.discriminator} (${msg.author.id})
			> ${msg.guild ? `${msg.guild.name} (${msg.guild.id})` : 'DM'}
			>> ${cmd.groupID}:${cmd.memberName}
			${Object.values(args)[0] !== '' ? `>>> ${Object.values(args)}` : ''}
		`);
	})
	.on('message', async (message) => {
		const channeLocks = client.provider.get(message.guild.id, 'locks', []);

		if (channeLocks.includes(message.channel.id)) return;
		if (message.channel.type === 'dm') return;
		if (message.author.bot) return;

		if (!earnedRecently.includes(message.author.id)) {
			const hasImageAttachment = message.attachments.some(attachment => {
				return attachment.url.match(/\.(png|jpg|jpeg|gif|webp)$/);
			});
			const moneyEarned = hasImageAttachment
				? Math.ceil(Math.random() * 7) + 1
				: Math.ceil(Math.random() * 7) + 5;

			Currency.addBalance(message.author.id, moneyEarned);

			earnedRecently.push(message.author.id);
			setTimeout(() => {
				const index = earnedRecently.indexOf(message.author.id);
				earnedRecently.splice(index, 1);
			}, 8000);
		}

		if (!gainedXPRecently.includes(message.author.id)) {
			const xpEarned = Math.ceil(Math.random() * 9) + 3;
			const oldLevel = await Experience.getLevel(message.author.id);
			Experience.addExperience(message.author.id, xpEarned).then(async () => {
				const newLevel = await Experience.getLevel(message.author.id);

				if (newLevel > oldLevel) {
					Currency.addBalance(message.author.id, 100 * newLevel);
				}
			}).catch(winston.error);

			gainedXPRecently.push(message.author.id);
			setTimeout(() => {
				const index = gainedXPRecently.indexOf(message.author.id);
				gainedXPRecently.splice(index, 1);
			}, 60 * 1000);
		}
	})
	.on('commandError', (cmd, err) => {
		if (err instanceof commando.FriendlyError) return;
		winston.error(`Error in command ${cmd.groupID}:${cmd.memberName}`, err);
	})
	.on('commandBlocked', (msg, reason) => {
		winston.info(oneLine`
			Command ${msg.command ? `${msg.command.groupID}:${msg.command.memberName}` : ''}
			blocked; ${reason}
		`);
	})
	.on('commandPrefixChange', (guild, prefix) => {
		winston.info(oneLine`
			Prefix changed to ${prefix || 'the default'}
			${guild ? `in guild ${guild.name} (${guild.id})` : 'globally'}.
		`);
	})
	.on('commandStatusChange', (guild, command, enabled) => {
		winston.info(oneLine`
			Command ${command.groupID}:${command.memberName}
			${enabled ? 'enabled' : 'disabled'}
			${guild ? `in guild ${guild.name} (${guild.id})` : 'globally'}.
		`);
	})
	.on('groupStatusChange', (guild, group, enabled) => {
		winston.info(oneLine`
			Group ${group.id}
			${enabled ? 'enabled' : 'disabled'}
			${guild ? `in guild ${guild.name} (${guild.id})` : 'globally'}.
		`);
	});

client.registry
	.registerGroups([
		['info', 'Info'],
		['economy', 'Economy'],
		['social', 'Social'],
		['games', 'Games'],
		['item', 'Item'],
		['weather', 'Weather'],
		['music', 'Music'],
		['tags', 'Tags']
	])
	.registerDefaults()
	.registerCommandsIn(path.join(__dirname, 'commands'));

client.login(config.token);
<commit_msg>Fix exp<commit_after>global.Promise = require('bluebird');

const commando = require('discord.js-commando');
const Currency = require('./currency/Currency');
const Experience = require('./currency/Experience');
const oneLine = require('common-tags').oneLine;
const path = require('path');
const Raven = require('raven');
const winston = require('winston');

const Database = require('./postgreSQL/PostgreSQL');
const Redis = require('./redis/Redis');
const SequelizeProvider = require('./postgreSQL/SequelizeProvider');
const config = require('./settings');

const database = new Database();
const redis = new Redis();
const client = new commando.Client({
	owner: config.owner,
	commandPrefix: '?',
	unknownCommandResponse: false,
	disableEveryone: true
});

let earnedRecently = [];
let gainedXPRecently = [];

Raven.config(config.ravenKey);
Raven.install();

database.start();
redis.start();

client.setProvider(new SequelizeProvider(database.db));

client.dispatcher.addInhibitor(msg => {
	const blacklist = client.provider.get('global', 'userBlacklist', []);

	if (!blacklist.includes(msg.author.id)) return false;

	return `User ${msg.author.username}#${msg.author.discriminator} (${msg.author.id}) has been blacklisted.`;
});

client.on('error', winston.error)
	.on('warn', winston.warn)
	.on('ready', () => {
		winston.info(oneLine`
			Client ready... Logged in as ${client.user.username}#${client.user.discriminator} (${client.user.id})
		`);
		Currency.leaderboard();
	})
	.on('disconnect', () => { winston.warn('Disconnected!'); })
	.on('reconnect', () => { winston.warn('Reconnecting...'); })
	.on('commandRun', (cmd, promise, msg, args) => {
		winston.info(oneLine`${msg.author.username}#${msg.author.discriminator} (${msg.author.id})
			> ${msg.guild ? `${msg.guild.name} (${msg.guild.id})` : 'DM'}
			>> ${cmd.groupID}:${cmd.memberName}
			${Object.values(args)[0] !== '' ? `>>> ${Object.values(args)}` : ''}
		`);
	})
	.on('message', async (message) => {
		if (message.channel.type === 'dm') return;

		const channeLocks = client.provider.get(message.guild.id, 'locks', []);
		if (channeLocks.includes(message.channel.id)) return;
		if (message.author.bot) return;

		if (!earnedRecently.includes(message.author.id)) {
			const hasImageAttachment = message.attachments.some(attachment => {
				return attachment.url.match(/\.(png|jpg|jpeg|gif|webp)$/);
			});
			const moneyEarned = hasImageAttachment
				? Math.ceil(Math.random() * 7) + 1
				: Math.ceil(Math.random() * 7) + 5;

			Currency.addBalance(message.author.id, moneyEarned);

			earnedRecently.push(message.author.id);
			setTimeout(() => {
				const index = earnedRecently.indexOf(message.author.id);
				earnedRecently.splice(index, 1);
			}, 8000);
		}

		if (!gainedXPRecently.includes(message.author.id)) {
			const xpEarned = Math.ceil(Math.random() * 9) + 3;
			const oldLevel = await Experience.getLevel(message.author.id);
			Experience.addExperience(message.author.id, xpEarned).then(async () => {
				const newLevel = await Experience.getLevel(message.author.id);

				if (newLevel > oldLevel) {
					Currency.addBalance(message.author.id, 100 * newLevel);
				}
			}).catch(winston.error);

			gainedXPRecently.push(message.author.id);
			setTimeout(() => {
				const index = gainedXPRecently.indexOf(message.author.id);
				gainedXPRecently.splice(index, 1);
			}, 60 * 1000);
		}
	})
	.on('commandError', (cmd, err) => {
		if (err instanceof commando.FriendlyError) return;
		winston.error(`Error in command ${cmd.groupID}:${cmd.memberName}`, err);
	})
	.on('commandBlocked', (msg, reason) => {
		winston.info(oneLine`
			Command ${msg.command ? `${msg.command.groupID}:${msg.command.memberName}` : ''}
			blocked; User ${msg.author.username}#${msg.author.discriminator} (${msg.author.id}): ${reason}
		`);
	})
	.on('commandPrefixChange', (guild, prefix) => {
		winston.info(oneLine`
			Prefix changed to ${prefix || 'the default'}
			${guild ? `in guild ${guild.name} (${guild.id})` : 'globally'}.
		`);
	})
	.on('commandStatusChange', (guild, command, enabled) => {
		winston.info(oneLine`
			Command ${command.groupID}:${command.memberName}
			${enabled ? 'enabled' : 'disabled'}
			${guild ? `in guild ${guild.name} (${guild.id})` : 'globally'}.
		`);
	})
	.on('groupStatusChange', (guild, group, enabled) => {
		winston.info(oneLine`
			Group ${group.id}
			${enabled ? 'enabled' : 'disabled'}
			${guild ? `in guild ${guild.name} (${guild.id})` : 'globally'}.
		`);
	});

client.registry
	.registerGroups([
		['info', 'Info'],
		['economy', 'Economy'],
		['social', 'Social'],
		['games', 'Games'],
		['item', 'Item'],
		['weather', 'Weather'],
		['music', 'Music'],
		['tags', 'Tags']
	])
	.registerDefaults()
	.registerCommandsIn(path.join(__dirname, 'commands'));

client.login(config.token);
<|endoftext|>


<commit_before>import * as assert from "assert";
import sift, { indexOf as siftIndexOf } from "..";

describe(__filename + "#", function() {
  it("doesn't sort arrays", function() {
    var values = [9, 8, 7, 6, 5, 4, 3, 2, 1].filter(
      sift({
        $or: [3, 2, 1]
      })
    );

    assert.equal(values.length, 3);
    assert.equal(values[0], 3);
    assert.equal(values[1], 2);
    assert.equal(values[2], 1);
  });

  it("can create a custom selector, and use it", function() {
    var sifter = sift(
      { age: { $gt: 5 } },
      {
        select: function(item) {
          return item.person;
        }
      }
    );

    var people = [{ person: { age: 6 } }],
      filtered = people.filter(sifter);

    assert.equal(filtered.length, 1);
    assert.equal(filtered[0], people[0]);
  });

  it("throws an error if the operation is invalid", function() {
    var err;
    try {
      sift({ $aaa: 1 })("b");
    } catch (e) {
      err = e;
    }

    assert.equal(err.message, "Unknown operation $aaa");
  });

  it("can get the first index of a matching element", function() {
    var index = siftIndexOf({ val: { $gt: 5 } }, [
      { val: 4 },
      { val: 3 },
      { val: 6 },
      { val: 7 }
    ]);

    assert.equal(index, 2);
  });

  it("returns -1 as index if no matching element is found", function() {
    var index = siftIndexOf({ val: { $gt: 7 } }, [
      { val: 4 },
      { val: 3 },
      { val: 6 },
      { val: 7 }
    ]);

    assert.equal(index, -1);
  });

  it("can match empty arrays", function() {
    var statusQuery = {
      $or: [
        { status: { $exists: false } },
        { status: [] },
        { status: { $in: ["urgent", "completed", "today"] } }
      ]
    };

    var filtered = [
      { status: [] },
      { status: ["urgent"] },
      { status: ["nope"] }
    ].filter(sift(statusQuery));

    assert.equal(filtered.length, 2);
  });

  it("$ne: null does not hit when field is present", function() {
    var sifter = sift({ age: { $ne: null } });

    var people = [{ age: "matched" }, { missed: 1 }];
    var filtered = people.filter(sifter);

    assert.equal(filtered.length, 1);
    assert.equal(filtered[0].age, "matched");
  });

  it("$ne does not hit when field is different", function() {
    var sifter = sift({ age: { $ne: 5 } });

    var people = [{ age: 5 }],
      filtered = people.filter(sifter);

    assert.equal(filtered.length, 0);
  });

  it("$ne does hit when field exists with different value", function() {
    var sifter = sift({ age: { $ne: 4 } });

    var people = [{ age: 5 }],
      filtered = people.filter(sifter);

    assert.equal(filtered.length, 1);
  });

  it("$ne does hit when field does not exist", function() {
    var sifter = sift({ age: { $ne: 5 } });

    var people = [{}],
      filtered = people.filter(sifter);

    assert.equal(filtered.length, 1);
  });

  it("$eq matches objects that serialize to the same value", function() {
    var counter = 0;
    function Book(name) {
      this.name = name;
      this.copyNumber = counter;
      this.toJSON = function() {
        return this.name; // discard the copy when serializing.
      };
      counter += 1;
    }

    var warAndPeace = new Book("War and Peace");

    var sifter = sift({ $eq: warAndPeace });

    var books = [new Book("War and Peace")];
    var filtered = books.filter(sifter);

    assert.equal(filtered.length, 1);
  });

  it("$neq does not match objects that serialize to the same value", function() {
    var counter = 0;
    function Book(name) {
      this.name = name;
      this.copyNumber = counter;
      this.toJSON = function() {
        return this.name; // discard the copy when serializing.
      };
      counter += 1;
    }

    var warAndPeace = new Book("War and Peace");

    var sifter = sift({ $ne: warAndPeace });

    var books = [new Book("War and Peace")];
    var filtered = books.filter(sifter);

    assert.equal(filtered.length, 0);
  });

  // https://gist.github.com/jdnichollsc/00ea8cf1204b17d9fb9a991fbd1dfee6
  it("returns a period between start and end dates", function() {
    var product = {
      productTypeCode: "productTypeEnergy",
      quantities: [
        {
          period: {
            startDate: new Date("2017-01-13T05:00:00.000Z"),
            endDate: new Date("2017-01-31T05:00:00.000Z"),
            dayType: {
              normal: true,
              holiday: true
            },
            specificDays: ["monday", "wednesday", "friday"],
            loadType: {
              high: true,
              medium: false,
              low: false
            }
          },
          type: "DemandPercentage",
          quantityValue: "44"
        },
        {
          period: {
            startDate: new Date("2017-01-13T05:00:00.000Z"),
            endDate: new Date("2017-01-31T05:00:00.000Z"),
            dayType: {
              normal: true,
              holiday: true
            },
            loadType: {
              high: false,
              medium: true,
              low: false
            }
          },
          type: "Value",
          quantityValue: "22"
        }
      ]
    };

    var period = {
      startDate: new Date("2017-01-08T05:00:00.000Z"),
      endDate: new Date("2017-01-29T05:00:00.000Z"),
      dayType: {
        normal: true,
        holiday: true
      },
      loadType: {
        high: true,
        medium: false,
        low: true
      },
      specificPeriods: ["3", "4", "5-10"]
    };

    var results = product.quantities.filter(
      sift({
        $and: [
          { "period.startDate": { $lte: period.endDate } },
          { "period.endDate": { $gte: period.startDate } }
        ]
      })
    );

    assert.equal(results.length, 2);
  });
});
<commit_msg>remove deprecated tests<commit_after>import * as assert from "assert";
import sift, { indexOf as siftIndexOf } from "..";

describe(__filename + "#", function() {
  it("doesn't sort arrays", function() {
    var values = [9, 8, 7, 6, 5, 4, 3, 2, 1].filter(
      sift({
        $or: [3, 2, 1]
      })
    );

    assert.equal(values.length, 3);
    assert.equal(values[0], 3);
    assert.equal(values[1], 2);
    assert.equal(values[2], 1);
  });

  it("can create a custom selector, and use it", function() {
    var sifter = sift(
      { age: { $gt: 5 } },
      {
        select: function(item) {
          return item.person;
        }
      }
    );

    var people = [{ person: { age: 6 } }],
      filtered = people.filter(sifter);

    assert.equal(filtered.length, 1);
    assert.equal(filtered[0], people[0]);
  });

  it("throws an error if the operation is invalid", function() {
    var err;
    try {
      sift({ $aaa: 1 })("b");
    } catch (e) {
      err = e;
    }

    assert.equal(err.message, "Unknown operation $aaa");
  });

  it("can match empty arrays", function() {
    var statusQuery = {
      $or: [
        { status: { $exists: false } },
        { status: [] },
        { status: { $in: ["urgent", "completed", "today"] } }
      ]
    };

    var filtered = [
      { status: [] },
      { status: ["urgent"] },
      { status: ["nope"] }
    ].filter(sift(statusQuery));

    assert.equal(filtered.length, 2);
  });

  it("$ne: null does not hit when field is present", function() {
    var sifter = sift({ age: { $ne: null } });

    var people = [{ age: "matched" }, { missed: 1 }];
    var filtered = people.filter(sifter);

    assert.equal(filtered.length, 1);
    assert.equal(filtered[0].age, "matched");
  });

  it("$ne does not hit when field is different", function() {
    var sifter = sift({ age: { $ne: 5 } });

    var people = [{ age: 5 }],
      filtered = people.filter(sifter);

    assert.equal(filtered.length, 0);
  });

  it("$ne does hit when field exists with different value", function() {
    var sifter = sift({ age: { $ne: 4 } });

    var people = [{ age: 5 }],
      filtered = people.filter(sifter);

    assert.equal(filtered.length, 1);
  });

  it("$ne does hit when field does not exist", function() {
    var sifter = sift({ age: { $ne: 5 } });

    var people = [{}],
      filtered = people.filter(sifter);

    assert.equal(filtered.length, 1);
  });

  it("$eq matches objects that serialize to the same value", function() {
    var counter = 0;
    function Book(name) {
      this.name = name;
      this.copyNumber = counter;
      this.toJSON = function() {
        return this.name; // discard the copy when serializing.
      };
      counter += 1;
    }

    var warAndPeace = new Book("War and Peace");

    var sifter = sift({ $eq: warAndPeace });

    var books = [new Book("War and Peace")];
    var filtered = books.filter(sifter);

    assert.equal(filtered.length, 1);
  });

  it("$neq does not match objects that serialize to the same value", function() {
    var counter = 0;
    function Book(name) {
      this.name = name;
      this.copyNumber = counter;
      this.toJSON = function() {
        return this.name; // discard the copy when serializing.
      };
      counter += 1;
    }

    var warAndPeace = new Book("War and Peace");

    var sifter = sift({ $ne: warAndPeace });

    var books = [new Book("War and Peace")];
    var filtered = books.filter(sifter);

    assert.equal(filtered.length, 0);
  });

  // https://gist.github.com/jdnichollsc/00ea8cf1204b17d9fb9a991fbd1dfee6
  it("returns a period between start and end dates", function() {
    var product = {
      productTypeCode: "productTypeEnergy",
      quantities: [
        {
          period: {
            startDate: new Date("2017-01-13T05:00:00.000Z"),
            endDate: new Date("2017-01-31T05:00:00.000Z"),
            dayType: {
              normal: true,
              holiday: true
            },
            specificDays: ["monday", "wednesday", "friday"],
            loadType: {
              high: true,
              medium: false,
              low: false
            }
          },
          type: "DemandPercentage",
          quantityValue: "44"
        },
        {
          period: {
            startDate: new Date("2017-01-13T05:00:00.000Z"),
            endDate: new Date("2017-01-31T05:00:00.000Z"),
            dayType: {
              normal: true,
              holiday: true
            },
            loadType: {
              high: false,
              medium: true,
              low: false
            }
          },
          type: "Value",
          quantityValue: "22"
        }
      ]
    };

    var period = {
      startDate: new Date("2017-01-08T05:00:00.000Z"),
      endDate: new Date("2017-01-29T05:00:00.000Z"),
      dayType: {
        normal: true,
        holiday: true
      },
      loadType: {
        high: true,
        medium: false,
        low: true
      },
      specificPeriods: ["3", "4", "5-10"]
    };

    var results = product.quantities.filter(
      sift({
        $and: [
          { "period.startDate": { $lte: period.endDate } },
          { "period.endDate": { $gte: period.startDate } }
        ]
      })
    );

    assert.equal(results.length, 2);
  });
});
<|endoftext|>


<commit_before>Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
Components.utils.import("resource://cck2/CCK2.jsm");
var gAustralis = false;
try {
  Components.utils.import("resource:///modules/CustomizableUI.jsm");
  gAustralis = true;
} catch(e) {}

(function () {
  var temp = {};
  Cu.import("resource://cck2/Preferences.jsm", temp);
  var Preferences = temp.Preferences;
  let scope = {};
  Services.scriptloader.loadSubScript("chrome://cck2/content/util.js", scope);
  let {E, hide, remove, disable, errorCritical} = scope;

  var config;

  function onPageLoad(event) {
    try {
      var doc = event.target;
      var win = doc.defaultView;
      if (!doc.location) {
        return;
      }
      /* Remove the sync button from about:home */
      if ((config && config.disableSync) &&
         /^about:home/.test(doc.location.href)) {
        remove(E("sync", doc));
      }
      /* Remove the addons button from about:home */
      if ((config && config.disableAddonsManager) &&
         /^about:home/.test(doc.location.href)) {
        remove(E("addons", doc));
      }
      /* Remove the addons button from about:home */
      if ((config && config.removeSnippets) &&
         /^about:home/.test(doc.location.href)) {
        var snippets = E("snippets", doc);
        if (snippets) {
          snippets.style.display = "none";
        }
      }
      /* Remove the reset button from about:support */
      if ((config && config.disableResetFirefox) &&
         /^about:support/.test(doc.location.href)) {
        remove(E("reset-box", doc));
      }

      /* If health reporter upload is locked, remove the activation widget */
      if (Preferences.locked("datareporting.healthreport.uploadEnabled", false)) {
        if (/^https:\/\/fhr.cdn.mozilla.net\//.test(doc.location.href)) {
          var activationWidget = event.target.querySelector(".activationWidget");
          if (activationWidget) {
            remove(activationWidget);
          }
        }
      }
    } catch (e) {
      errorCritical(e);
    }
  }

  function disableSync() {
    window.XULBrowserWindow.inContentWhitelist =
      window.XULBrowserWindow.inContentWhitelist.filter(function(element) {
        return element != "about:sync-progress";
      })
    if (gSyncUI) {
      var mySyncUI = {
        init: function() {
          return;
        },
        initUI: function() {
          return;
        },
        updateUI: function() {
          hide(E("sync-setup-state"));
          hide(E("sync-syncnow-state"));
          hide(E("sync-setup"));
          hide(E("sync-syncnowitem"));
        }
      }
      gSyncUI = mySyncUI;
    }
    if (gAustralis) {
      CustomizableUI.destroyWidget("sync-button");
      CustomizableUI.removeWidgetFromArea("sync-button");
    }
    var toolbox = document.getElementById("navigator-toolbox");
    if (toolbox && toolbox.palette) {
      element = toolbox.palette.querySelector("#sync-button");
      if (element) {
        element.parentNode.removeChild(element);
      }
    }
    hide(E("sync-setup-state"));
    hide(E("sync-syncnow-state"));
    hide(E("sync-setup"));
    hide(E("sync-syncnowitem"));
  }

  function disablePrivateBrowsing() {
    disable(E("Tools:PrivateBrowsing"));
    hide(E("menu_newPrivateWindow"));
    // Because this is on a context menu, we can't use "hidden"
    if (E("context-openlinkprivate"))
      E("context-openlinkprivate").setAttribute("style", "display: none;");
    hide(E("appmenu_privateBrowsing"));
    hide(E("appmenu_newPrivateWindow"));
    hide(E("privateBrowsingItem"));
    if (gAustralis) {
      CustomizableUI.destroyWidget("privatebrowsing-button")
    }
  }

  function disableAddonsManager() {
    window.XULBrowserWindow.inContentWhitelist =
      window.XULBrowserWindow.inContentWhitelist.filter(function(element) {
        return element != "about:addons";
      })
    hide(E("appmenu_addons"));
    hide(E("menu_openAddons"));
    disable(E("Tools:Addons"));
    if (gAustralis) {
      CustomizableUI.destroyWidget("add-ons-button")
    }
  }

  function removeDeveloperTools() {
    hide(E("developer-button"));
    hide(E("webDeveloperMenu"));
    var devtoolsKeyset = document.getElementById("devtoolsKeyset");
    for (var i = 0; i < devtoolsKeyset.childNodes.length; i++) {
      devtoolsKeyset.childNodes[i].removeAttribute("command");
    }
    try {
      document.getElementById("Tools:ResponsiveUI").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:Scratchpad").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:BrowserConsole").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:BrowserToolbox").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:DevAppsMgr").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:DevToolbar").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:DevToolbox").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:DevToolbarFocus").removeAttribute("oncommand");
    } catch (e) {}
    if (gAustralis) {
      CustomizableUI.destroyWidget("developer-button")
    }
  }

  function disableErrorConsole() {
    document.getElementById("Tools:ErrorConsole").removeAttribute("oncommand");
  }

  function onPanelShowing(event) {
    hide(E("PanelUI-fxa-status"));

  }

  function startup()
  {
    try {
      window.removeEventListener("load", startup, false);
      window.XULBrowserWindow.inContentWhitelist =
        window.XULBrowserWindow.inContentWhitelist.filter(function(element) {
          return element != "about:preferences";
        })

      config = CCK2.getConfig();
      if (!config)
        return;

      if (config.disablePrivateBrowsing &&
          PrivateBrowsingUtils.isWindowPrivate(window)) {
        window.setTimeout(function() {
          Services.prompt.alert(window, "Private Browsing", "Private Browsing has been disabled by your administrator");
          window.close();
        }, 0, false);
      }
      if (config.disablePrivateBrowsing) {
        disablePrivateBrowsing();
      }
      if (config.disableSync) {
        disableSync();
      }
      E("appcontent").addEventListener("DOMContentLoaded", onPageLoad, false);

      if (config.disableAddonsManager) {
        disableAddonsManager();
      }
      if (config.removeDeveloperTools) {
        Services.tm.mainThread.dispatch(function() {
          removeDeveloperTools();
        }, Ci.nsIThread.DISPATCH_NORMAL);
      }
      if (config.disableErrorConsole) {
        disableErrorConsole();
      }
      if (config.removeSafeModeMenu) {
        hide(E("helpSafeMode"));
        try {
          hide(E("appmenu_safeMode"));
        } catch (e) {}
      }
      if (config.titlemodifier) {
        document.getElementById("main-window").setAttribute("titlemodifier", config.titlemodifier);
      }
      if (config.removeSetDesktopBackground) {
        // Because this is on a context menu, we can't use "hidden"
        if (E("context-setDesktopBackground"))
          E("context-setDesktopBackground").setAttribute("style", "display: none;");
        }
      if (config.hiddenUI) {
        for (var i=0; i < config.hiddenUI.length; i++) {
          var uiElements = document.querySelectorAll(config.hiddenUI[i]);
          if (!uiElements || uiElements.length == 0) {
            // try adding style manually...maybe this should be the default?
            var style = document.getElementById("cck2-hidden-style");
            if (!style) {
              style = document.createElementNS("http://www.w3.org/1999/xhtml", "style");
              style.setAttribute("id", "cck2-hidden-style");
              style.setAttribute("type", "text/css");
              document.getElementById("main-window").appendChild(style);
            }
            style.textContent = style.textContent + config.hiddenUI[i] + "{display: none;}";
            continue;
          }
          for (var j=0; j < uiElements.length; j++) {
            var uiElement = uiElements[j];
            hide(uiElement);
            if (uiElement.nodeName == "menuitem") {
              uiElement.removeAttribute("key");
              uiElement.removeAttribute("oncommand");
              if (uiElement.hasAttribute("command")) {
                var commandId = uiElement.getAttribute("command");
                uiElement.removeAttribute("command");
                var command = document.getElementById(commandId);
                command.removeAttribute("oncommand");
                var keys = document.querySelectorAll("key[command='" + commandId + "']")
                for (var k=0; k < keys.length; k++) {
                  keys[k].removeAttribute("command");
                }
              }
            }
          }
        }
      }
      if (config.helpMenu) {
        // We need to run this function on a delay, because we won't know
        // if the about menu is hidden for mac until after it is run.
        Services.tm.mainThread.dispatch(function() {
          var helpMenuPopup = document.getElementById("menu_HelpPopup");
          var menuitem = document.createElement("menuitem");
          menuitem.setAttribute("label", config.helpMenu.label);
          if ("accesskey" in config.helpMenu) {
            menuitem.setAttribute("accesskey", config.helpMenu.accesskey);
          }
          menuitem.setAttribute("oncommand", "openUILink(" + config.helpMenu.url.quote() + ");");
          menuitem.setAttribute("onclick", "checkForMiddleClick(this, event);");
          if (!E("aboutName") || E("aboutName").hidden) {
            // Mac
            helpMenuPopup.appendChild(menuitem);
          } else {
            helpMenuPopup.insertBefore(menuitem, E("aboutName"));
            helpMenuPopup.insertBefore(document.createElement("menuseparator"),
                                              E("aboutName"));
          }
        }, Ci.nsIThread.DISPATCH_NORMAL);
        var appMenuHelpMenuPopup = document.getElementById("appmenu_helpMenupopup");
        if (appMenuHelpMenuPopup) {
          var menuitem = document.createElement("menuitem");
          menuitem.setAttribute("label", config.helpMenu.label);
          menuitem.setAttribute("url", config.helpMenu.url);
          menuitem.addEventListener("command", function(event) {
            openUILink(this.getAttribute("url"), event, false, true);
          })
          menuitem.addEventListener("click", function(event) {
            checkForMiddleClick(this, event);
          }, false);
          appMenuHelpMenuPopup.insertBefore(menuitem, E("appmenu_about"));
          appMenuHelpMenuPopup.insertBefore(document.createElement("menuseparator"),
                                            E("appmenu_about"));
        }
      }
      if (CCK2.firstrun || CCK2.upgrade) {
        if (config.displayBookmarksToolbar || (config.bookmarks && config.bookmarks.toolbar)) {
          E("PersonalToolbar").collapsed = false;
          E("PersonalToolbar").setAttribute("collapsed", "false");
          document.persist("PersonalToolbar", "collapsed");
        }
        if (config.displayMenuBar) {
          if (typeof updateAppButtonDisplay != "undefined") {
            E("toolbar-menubar").setAttribute("autohide", "false");
            document.persist("toolbar-menubar", "autohide")
            updateAppButtonDisplay();
          }
          if (gAustralis) {
            CustomizableUI.setToolbarVisibility("toolbar-menubar", "true");
          }

        }
        CCK2.firstrun = false;
        CCK2.upgrade = false;
      }
      var panelUIPopup = document.getElementById("PanelUI-popup");
      if (panelUIPopup) {
        document.getElementById("PanelUI-popup").addEventListener("popupshowing", onPanelShowing, false);
      }
    } catch (e) {
      errorCritical(e);
    }
  }

  function shutdown()
  {
    window.removeEventListener("unload", shutdown, false);
    var appcontent = E("appcontent");
    if (appcontent) {
       appcontent.removeEventListener("DOMContentLoaded", onPageLoad, false);
    }
    var panelUIPopup = document.getElementById("PanelUI-popup");
    if (panelUIPopup) {
      document.getElementById("PanelUI-popup").removeEventListener("popupshowing", onPanelShowing, false);
    }
  }

  window.addEventListener("load", startup, false);
  window.addEventListener("unload", shutdown, false);
})();
<commit_msg>Devtools shortcuts not removed<commit_after>Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
Components.utils.import("resource://cck2/CCK2.jsm");
var gAustralis = false;
try {
  Components.utils.import("resource:///modules/CustomizableUI.jsm");
  gAustralis = true;
} catch(e) {}

(function () {
  var temp = {};
  Cu.import("resource://cck2/Preferences.jsm", temp);
  var Preferences = temp.Preferences;
  let scope = {};
  Services.scriptloader.loadSubScript("chrome://cck2/content/util.js", scope);
  let {E, hide, remove, disable, errorCritical} = scope;

  var config;

  function onPageLoad(event) {
    try {
      var doc = event.target;
      var win = doc.defaultView;
      if (!doc.location) {
        return;
      }
      /* Remove the sync button from about:home */
      if ((config && config.disableSync) &&
         /^about:home/.test(doc.location.href)) {
        remove(E("sync", doc));
      }
      /* Remove the addons button from about:home */
      if ((config && config.disableAddonsManager) &&
         /^about:home/.test(doc.location.href)) {
        remove(E("addons", doc));
      }
      /* Remove the addons button from about:home */
      if ((config && config.removeSnippets) &&
         /^about:home/.test(doc.location.href)) {
        var snippets = E("snippets", doc);
        if (snippets) {
          snippets.style.display = "none";
        }
      }
      /* Remove the reset button from about:support */
      if ((config && config.disableResetFirefox) &&
         /^about:support/.test(doc.location.href)) {
        remove(E("reset-box", doc));
      }

      /* If health reporter upload is locked, remove the activation widget */
      if (Preferences.locked("datareporting.healthreport.uploadEnabled", false)) {
        if (/^https:\/\/fhr.cdn.mozilla.net\//.test(doc.location.href)) {
          var activationWidget = event.target.querySelector(".activationWidget");
          if (activationWidget) {
            remove(activationWidget);
          }
        }
      }
    } catch (e) {
      errorCritical(e);
    }
  }

  function disableSync() {
    window.XULBrowserWindow.inContentWhitelist =
      window.XULBrowserWindow.inContentWhitelist.filter(function(element) {
        return element != "about:sync-progress";
      })
    if (gSyncUI) {
      var mySyncUI = {
        init: function() {
          return;
        },
        initUI: function() {
          return;
        },
        updateUI: function() {
          hide(E("sync-setup-state"));
          hide(E("sync-syncnow-state"));
          hide(E("sync-setup"));
          hide(E("sync-syncnowitem"));
        }
      }
      gSyncUI = mySyncUI;
    }
    if (gAustralis) {
      CustomizableUI.destroyWidget("sync-button");
      CustomizableUI.removeWidgetFromArea("sync-button");
    }
    var toolbox = document.getElementById("navigator-toolbox");
    if (toolbox && toolbox.palette) {
      element = toolbox.palette.querySelector("#sync-button");
      if (element) {
        element.parentNode.removeChild(element);
      }
    }
    hide(E("sync-setup-state"));
    hide(E("sync-syncnow-state"));
    hide(E("sync-setup"));
    hide(E("sync-syncnowitem"));
  }

  function disablePrivateBrowsing() {
    disable(E("Tools:PrivateBrowsing"));
    hide(E("menu_newPrivateWindow"));
    // Because this is on a context menu, we can't use "hidden"
    if (E("context-openlinkprivate"))
      E("context-openlinkprivate").setAttribute("style", "display: none;");
    hide(E("appmenu_privateBrowsing"));
    hide(E("appmenu_newPrivateWindow"));
    hide(E("privateBrowsingItem"));
    if (gAustralis) {
      CustomizableUI.destroyWidget("privatebrowsing-button")
    }
  }

  function disableAddonsManager() {
    window.XULBrowserWindow.inContentWhitelist =
      window.XULBrowserWindow.inContentWhitelist.filter(function(element) {
        return element != "about:addons";
      })
    hide(E("appmenu_addons"));
    hide(E("menu_openAddons"));
    disable(E("Tools:Addons"));
    if (gAustralis) {
      CustomizableUI.destroyWidget("add-ons-button")
    }
  }

  function removeDeveloperTools() {
    hide(E("developer-button"));
    hide(E("webDeveloperMenu"));
    // Need to delay this because devtools is created dynamically
    window.setTimeout(function() {
      var devtoolsKeyset = document.getElementById("devtoolsKeyset");
      if (devtoolsKeyset) {
        for (var i = 0; i < devtoolsKeyset.childNodes.length; i++) {
          devtoolsKeyset.childNodes[i].removeAttribute("command");
        }
      }
    }, 0);
    try {
      document.getElementById("Tools:ResponsiveUI").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:Scratchpad").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:BrowserConsole").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:BrowserToolbox").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:DevAppsMgr").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:DevToolbar").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:DevToolbox").removeAttribute("oncommand");
    } catch (e) {}
    try {
      document.getElementById("Tools:DevToolbarFocus").removeAttribute("oncommand");
    } catch (e) {}
    if (gAustralis) {
      CustomizableUI.destroyWidget("developer-button")
    }
  }

  function disableErrorConsole() {
    document.getElementById("Tools:ErrorConsole").removeAttribute("oncommand");
  }

  function onPanelShowing(event) {
    hide(E("PanelUI-fxa-status"));

  }

  function startup()
  {
    try {
      window.removeEventListener("load", startup, false);
      window.XULBrowserWindow.inContentWhitelist =
        window.XULBrowserWindow.inContentWhitelist.filter(function(element) {
          return element != "about:preferences";
        })

      config = CCK2.getConfig();
      if (!config)
        return;

      if (config.disablePrivateBrowsing &&
          PrivateBrowsingUtils.isWindowPrivate(window)) {
        window.setTimeout(function() {
          Services.prompt.alert(window, "Private Browsing", "Private Browsing has been disabled by your administrator");
          window.close();
        }, 0, false);
      }
      if (config.disablePrivateBrowsing) {
        disablePrivateBrowsing();
      }
      if (config.disableSync) {
        disableSync();
      }
      E("appcontent").addEventListener("DOMContentLoaded", onPageLoad, false);

      if (config.disableAddonsManager) {
        disableAddonsManager();
      }
      if (config.removeDeveloperTools) {
        Services.tm.mainThread.dispatch(function() {
          removeDeveloperTools();
        }, Ci.nsIThread.DISPATCH_NORMAL);
      }
      if (config.disableErrorConsole) {
        disableErrorConsole();
      }
      if (config.removeSafeModeMenu) {
        hide(E("helpSafeMode"));
        try {
          hide(E("appmenu_safeMode"));
        } catch (e) {}
      }
      if (config.titlemodifier) {
        document.getElementById("main-window").setAttribute("titlemodifier", config.titlemodifier);
      }
      if (config.removeSetDesktopBackground) {
        // Because this is on a context menu, we can't use "hidden"
        if (E("context-setDesktopBackground"))
          E("context-setDesktopBackground").setAttribute("style", "display: none;");
        }
      if (config.hiddenUI) {
        for (var i=0; i < config.hiddenUI.length; i++) {
          var uiElements = document.querySelectorAll(config.hiddenUI[i]);
          if (!uiElements || uiElements.length == 0) {
            // try adding style manually...maybe this should be the default?
            var style = document.getElementById("cck2-hidden-style");
            if (!style) {
              style = document.createElementNS("http://www.w3.org/1999/xhtml", "style");
              style.setAttribute("id", "cck2-hidden-style");
              style.setAttribute("type", "text/css");
              document.getElementById("main-window").appendChild(style);
            }
            style.textContent = style.textContent + config.hiddenUI[i] + "{display: none;}";
            continue;
          }
          for (var j=0; j < uiElements.length; j++) {
            var uiElement = uiElements[j];
            hide(uiElement);
            if (uiElement.nodeName == "menuitem") {
              uiElement.removeAttribute("key");
              uiElement.removeAttribute("oncommand");
              if (uiElement.hasAttribute("command")) {
                var commandId = uiElement.getAttribute("command");
                uiElement.removeAttribute("command");
                var command = document.getElementById(commandId);
                command.removeAttribute("oncommand");
                var keys = document.querySelectorAll("key[command='" + commandId + "']")
                for (var k=0; k < keys.length; k++) {
                  keys[k].removeAttribute("command");
                }
              }
            }
          }
        }
      }
      if (config.helpMenu) {
        // We need to run this function on a delay, because we won't know
        // if the about menu is hidden for mac until after it is run.
        Services.tm.mainThread.dispatch(function() {
          var helpMenuPopup = document.getElementById("menu_HelpPopup");
          var menuitem = document.createElement("menuitem");
          menuitem.setAttribute("label", config.helpMenu.label);
          if ("accesskey" in config.helpMenu) {
            menuitem.setAttribute("accesskey", config.helpMenu.accesskey);
          }
          menuitem.setAttribute("oncommand", "openUILink(" + config.helpMenu.url.quote() + ");");
          menuitem.setAttribute("onclick", "checkForMiddleClick(this, event);");
          if (!E("aboutName") || E("aboutName").hidden) {
            // Mac
            helpMenuPopup.appendChild(menuitem);
          } else {
            helpMenuPopup.insertBefore(menuitem, E("aboutName"));
            helpMenuPopup.insertBefore(document.createElement("menuseparator"),
                                              E("aboutName"));
          }
        }, Ci.nsIThread.DISPATCH_NORMAL);
        var appMenuHelpMenuPopup = document.getElementById("appmenu_helpMenupopup");
        if (appMenuHelpMenuPopup) {
          var menuitem = document.createElement("menuitem");
          menuitem.setAttribute("label", config.helpMenu.label);
          menuitem.setAttribute("url", config.helpMenu.url);
          menuitem.addEventListener("command", function(event) {
            openUILink(this.getAttribute("url"), event, false, true);
          })
          menuitem.addEventListener("click", function(event) {
            checkForMiddleClick(this, event);
          }, false);
          appMenuHelpMenuPopup.insertBefore(menuitem, E("appmenu_about"));
          appMenuHelpMenuPopup.insertBefore(document.createElement("menuseparator"),
                                            E("appmenu_about"));
        }
      }
      if (CCK2.firstrun || CCK2.upgrade) {
        if (config.displayBookmarksToolbar || (config.bookmarks && config.bookmarks.toolbar)) {
          E("PersonalToolbar").collapsed = false;
          E("PersonalToolbar").setAttribute("collapsed", "false");
          document.persist("PersonalToolbar", "collapsed");
        }
        if (config.displayMenuBar) {
          if (typeof updateAppButtonDisplay != "undefined") {
            E("toolbar-menubar").setAttribute("autohide", "false");
            document.persist("toolbar-menubar", "autohide")
            updateAppButtonDisplay();
          }
          if (gAustralis) {
            CustomizableUI.setToolbarVisibility("toolbar-menubar", "true");
          }

        }
        CCK2.firstrun = false;
        CCK2.upgrade = false;
      }
      var panelUIPopup = document.getElementById("PanelUI-popup");
      if (panelUIPopup) {
        document.getElementById("PanelUI-popup").addEventListener("popupshowing", onPanelShowing, false);
      }
    } catch (e) {
      errorCritical(e);
    }
  }

  function shutdown()
  {
    window.removeEventListener("unload", shutdown, false);
    var appcontent = E("appcontent");
    if (appcontent) {
       appcontent.removeEventListener("DOMContentLoaded", onPageLoad, false);
    }
    var panelUIPopup = document.getElementById("PanelUI-popup");
    if (panelUIPopup) {
      document.getElementById("PanelUI-popup").removeEventListener("popupshowing", onPanelShowing, false);
    }
  }

  window.addEventListener("load", startup, false);
  window.addEventListener("unload", shutdown, false);
})();
<|endoftext|>


<commit_before>'use strict';

var chai = require('chai');
var should = chai.should();
var sinon = require('sinon');
var async = require('async');
var proxyquire = require('proxyquire');
var memdown = require('memdown');

var bitcoindjs = require('../');
var DB = bitcoindjs.DB;
var Chain = bitcoindjs.Chain;
var Block = bitcoindjs.Block;

var chainData = require('./data/testnet-blocks.json');

describe('Bitcoin Chain', function() {

  describe('@constructor', function() {

    it('can create a new instance with and without `new`', function() {
      var chain = new Chain();
      chain = Chain();
    });

  });

  describe('#start', function() {
    it('should call the callback when base chain is initialized', function(done) {
      var chain = new Chain();
      chain.bitcoind = {};
      chain.bitcoind.genesisBuffer = new Buffer('0100000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000bac8b0fa927c0ac8234287e33c5f74d38d354820e24756ad709d7038fc5f31f020e7494dffff001d03e4b6720101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0420e7494d017f062f503253482fffffffff0100f2052a010000002321021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac00000000', 'hex');
      chain.initialize = function() {
        chain.emit('initialized');
      };

      chain.start(done);
    });
  });

  describe('#stop', function() {
    it('should call the callback', function(done) {
      var chain = new Chain();
      chain.stop(done);
    });
  });

  describe('#_writeBlock', function() {
    it('should update hashes and call putBlock', function(done) {
      var chain = new Chain();
      chain.db = {
        putBlock: sinon.stub().callsArg(1)
      };
      chain._writeBlock({hash: 'hash', prevHash: 'prevhash'}, function(err) {
        should.not.exist(err);
        chain.db.putBlock.callCount.should.equal(1);
        chain.cache.hashes.hash.should.equal('prevhash');
        done();
      });
    });
  });

  describe('#_validateBlock', function() {
    it('should call the callback', function(done) {
      var chain = new Chain();
      chain._validateBlock('block', function(err) {
        should.not.exist(err);
        done();
      });
    });
  });

  describe('#buildGenesisBlock', function() {
    it('can handle no options', function() {
      var db = {
        buildGenesisData: sinon.stub().returns({})
      };
      var chain = new Chain({db: db});
      var block = chain.buildGenesisBlock();
      should.exist(block);
      block.should.be.instanceof(Block);
      db.buildGenesisData.calledOnce.should.equal(true);
    });

    it('set timestamp, nonce, bits, merkleRoot and data of the genesis', function() {
      var db = {
        buildGenesisData: sinon.stub().returns({
          merkleRoot: 'merkleRoot',
          buffer: new Buffer('abcdef', 'hex')
        })
      };
      var chain = new Chain({db: db});
      var timestamp = '2015-03-20T14:46:01.118Z';
      var block = chain.buildGenesisBlock({
        timestamp: timestamp,
        nonce: 1,
        bits: 520617984
      });
      should.exist(block);
      block.should.be.instanceof(Block);
      block.timestamp.toISOString().should.equal(timestamp);
      block.nonce.should.equal(1);
      block.bits.should.equal(520617984);
      block.merkleRoot.should.equal('merkleRoot');
      block.data.should.deep.equal(new Buffer('abcdef', 'hex'));
      db.buildGenesisData.calledOnce.should.equal(true);
    });

  });

  describe('#getWeight', function() {
    var work = '000000000000000000000000000000000000000000005a7b3c42ea8b844374e9';
    var chain = new Chain();
    chain.db = {
      bitcoind: {
        getBlockIndex: sinon.stub().returns({
          chainWork: work
        })
      }
    };

    it('should give the weight as a BN', function(done) {
      chain.getWeight('hash', function(err, weight) {
        should.not.exist(err);
        weight.toString(16, 64).should.equal(work);
        done();
      });
    });

    it('should give an error if the weight is undefined', function(done) {
      chain.db.bitcoind.getBlockIndex = sinon.stub().returns(undefined);
      chain.getWeight('hash2', function(err, weight) {
        should.exist(err);
        done();
      });
    });
  });
});
<commit_msg>Fix chain unit test.<commit_after>'use strict';

var chai = require('chai');
var should = chai.should();
var sinon = require('sinon');
var async = require('async');
var proxyquire = require('proxyquire');
var memdown = require('memdown');

var bitcoindjs = require('../');
var DB = bitcoindjs.DB;
var Chain = bitcoindjs.Chain;
var Block = bitcoindjs.Block;

var chainData = require('./data/testnet-blocks.json');

describe('Bitcoin Chain', function() {

  describe('@constructor', function() {

    it('can create a new instance with and without `new`', function() {
      var chain = new Chain();
      chain = Chain();
    });

  });

  describe('#start', function() {
    it('should call the callback when base chain is initialized', function(done) {
      var chain = new Chain();
      chain.node = {};
      chain.node.bitcoind = {};
      chain.node.bitcoind.genesisBuffer = new Buffer('0100000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000bac8b0fa927c0ac8234287e33c5f74d38d354820e24756ad709d7038fc5f31f020e7494dffff001d03e4b6720101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0420e7494d017f062f503253482fffffffff0100f2052a010000002321021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac00000000', 'hex');
      chain.initialize = function() {
        chain.emit('initialized');
      };

      chain.start(done);
    });
  });

  describe('#stop', function() {
    it('should call the callback', function(done) {
      var chain = new Chain();
      chain.stop(done);
    });
  });

  describe('#_writeBlock', function() {
    it('should update hashes and call putBlock', function(done) {
      var chain = new Chain();
      chain.db = {
        putBlock: sinon.stub().callsArg(1)
      };
      chain._writeBlock({hash: 'hash', prevHash: 'prevhash'}, function(err) {
        should.not.exist(err);
        chain.db.putBlock.callCount.should.equal(1);
        chain.cache.hashes.hash.should.equal('prevhash');
        done();
      });
    });
  });

  describe('#_validateBlock', function() {
    it('should call the callback', function(done) {
      var chain = new Chain();
      chain._validateBlock('block', function(err) {
        should.not.exist(err);
        done();
      });
    });
  });

  describe('#buildGenesisBlock', function() {
    it('can handle no options', function() {
      var db = {
        buildGenesisData: sinon.stub().returns({})
      };
      var chain = new Chain({db: db});
      var block = chain.buildGenesisBlock();
      should.exist(block);
      block.should.be.instanceof(Block);
      db.buildGenesisData.calledOnce.should.equal(true);
    });

    it('set timestamp, nonce, bits, merkleRoot and data of the genesis', function() {
      var db = {
        buildGenesisData: sinon.stub().returns({
          merkleRoot: 'merkleRoot',
          buffer: new Buffer('abcdef', 'hex')
        })
      };
      var chain = new Chain({db: db});
      var timestamp = '2015-03-20T14:46:01.118Z';
      var block = chain.buildGenesisBlock({
        timestamp: timestamp,
        nonce: 1,
        bits: 520617984
      });
      should.exist(block);
      block.should.be.instanceof(Block);
      block.timestamp.toISOString().should.equal(timestamp);
      block.nonce.should.equal(1);
      block.bits.should.equal(520617984);
      block.merkleRoot.should.equal('merkleRoot');
      block.data.should.deep.equal(new Buffer('abcdef', 'hex'));
      db.buildGenesisData.calledOnce.should.equal(true);
    });

  });

  describe('#getWeight', function() {
    var work = '000000000000000000000000000000000000000000005a7b3c42ea8b844374e9';
    var chain = new Chain();
    chain.db = {
      bitcoind: {
        getBlockIndex: sinon.stub().returns({
          chainWork: work
        })
      }
    };

    it('should give the weight as a BN', function(done) {
      chain.getWeight('hash', function(err, weight) {
        should.not.exist(err);
        weight.toString(16, 64).should.equal(work);
        done();
      });
    });

    it('should give an error if the weight is undefined', function(done) {
      chain.db.bitcoind.getBlockIndex = sinon.stub().returns(undefined);
      chain.getWeight('hash2', function(err, weight) {
        should.exist(err);
        done();
      });
    });
  });
});
<|endoftext|>


<commit_before>'use strict';
'require view';
'require form';
'require uci';
'require rpc';
'require ui';
'require poll';
'require request';
'require dom';

var callPackagelist = rpc.declare({
	object: 'rpc-sys',
	method: 'packagelist',
});

var callSystemBoard = rpc.declare({
	object: 'system',
	method: 'board'
});

var callUpgradeStart = rpc.declare({
	object: 'rpc-sys',
	method: 'upgrade_start',
	params: ["keep"]
});

function install_sysupgrade(url, keep, sha256) {
	displayStatus("notice spinning", E('p', _('Downloading firmware from server to browser')));
	request.get(url, {
			headers: {
				'Content-Type': 'application/x-www-form-urlencoded'
			},
			responseType: 'blob'
		})
		.then(response => {
			var form_data = new FormData();
			form_data.append("sessionid", rpc.getSessionID());
			form_data.append("filename", "/tmp/firmware.bin");
			form_data.append("filemode", 600);
			form_data.append("filedata", response.blob());

			displayStatus("notice spinning", E('p', _('Uploading firmware from browser to device')));
			request.get(L.env.cgi_base + "/cgi-upload", {
					method: 'PUT',
					content: form_data
				})
				.then(response => response.json())
				.then(response => {
					if (response.sha256sum != sha256) {
						displayStatus("warning", [
							E('b', _('Wrong checksum')),
							E('p', _('Error during download of firmware. Please try again')),
							E('div', {
								'class': 'btn',
								'click': ui.hideModal
							}, _('Close'))
						]);
					} else {
						displayStatus('warning spinning', E('p', _('Installing the sysupgrade. Do not unpower device!')));
							L.resolveDefault(callUpgradeStart(keep), {}).then(response => {
								if (keep) {
									ui.awaitReconnect(window.location.host);
								} else {
									ui.awaitReconnect('192.168.1.1', 'openwrt.lan');
								}
							});
					}
				});
		});
}

function request_sysupgrade(server_url, data) {
	var res, req;

	if (data.request_hash) {
		req = request.get(server_url + "/api/build/" + data.request_hash)
	} else {
		req = request.post(server_url + "/api/build", {
			profile: data.board_name,
			target: data.target,
			version: data.version,
			packages: data.packages,
			diff_packages: true,
		})
	}

	req.then(response => {
		switch (response.status) {
			case 200:
				var res = response.json()
				var image;
				console.log(res)
				for (image of res.images) {
					if (image.type == "sysupgrade") {
						break;
					}
				}
				if (image.name != undefined) {
					var sysupgrade_url = server_url + "/store/" + res.bin_dir + "/" + image.name;

					var keep = E('input', {
						type: 'checkbox'
					})
					keep.checked = true;

					var fields = [
						_('Version'), res.version_number + ' ' + res.version_code,
						_('File'), E('a', {
							'href': sysupgrade_url
						}, image.name),
						_('SHA256'), image.sha256,
						_('Build Date'), res.build_at,
						_('Target'), res.target,
					];

					var table = E('div', {
						'class': 'table'
					});

					for (var i = 0; i < fields.length; i += 2) {
						table.appendChild(E('div', {
							'class': 'tr'
						}, [
							E('div', {
								'class': 'td left',
								'width': '33%'
							}, [fields[i]]),
							E('div', {
								'class': 'td left'
							}, [(fields[i + 1] != null) ? fields[i + 1] : '?'])
						]));
					}

					var modal_body = [
						table,
						E('p', {}, E('label', {
							'class': 'btn'
						}, [
							keep, ' ', _('Keep settings and retain the current configuration')
						])),
						E('div', {
							'class': 'right'
						}, [
							E('div', {
								'class': 'btn',
								'click': ui.hideModal
							}, _('Cancel')),
							' ',
							E('div', {
								'class': 'btn cbi-button-action',
								'click': function() {
									install_sysupgrade(sysupgrade_url, keep.checked, image.sha256)
								}
							}, _('Install Sysupgrade'))
						])
					]

					ui.showModal(_('Successfully created sysupgrade image'), modal_body);
				}

				break;
			case 202:
				res = response.json()
				data.request_hash = res.request_hash;
				switch (res.status) {
					case "queued":
						displayStatus("notice spinning", E('p', _('Request in build queue')));
						break;
					case "started":
						displayStatus("notice spinning", E('p', _('Building the sysupgrade image')));
						break;
				}
				setTimeout(function() {
					request_sysupgrade(server_url, data);
				}, 5000);
				break;
			case 400: // bad request
			case 422: // bad package
			case 500: // build failed
				res = response.json()
				var body = [
					E('p', {}, _(res.message)),
					E('p', {}, _("Please report the error message and request")),
					E('b', {}, _("Request to server:")),
					E('pre', {}, JSON.stringify(data, null, 4)),

				]

				if (res.stdout) {
					body.push(E('b', {}, "STDOUT:"))
					body.push(E('pre', {}, res.stdout))

				}

				if (res.stderr) {
					body.push(E('b', {}, "STDERR:"))
					body.push(E('pre', {}, res.stderr))

				}

				body = body.concat([
					E('div', {
						'class': 'right'
					}, [
						E('div', {
							'class': 'btn',
							'click': ui.hideModal
						}, _('Close'))
					])
				]);
				ui.showModal(_('Error building the sysupgrade'), body);
				break;
		}
	});
}

function check_sysupgrade(server_url, current_version, target, board_name, packages) {
	displayStatus("notice spinning", E('p', _('Searching for an available sysupgrade')));
	var current_branch = current_version.split(".").slice(0, 2).join(".");
	var candidates = [];
	fetch(server_url + "/api/latest")
		.then(response => response.json())
		.then(response => {
			if (current_version == "SNAPSHOT") {
				candidates.push("SNAPSHOT");
			} else {
				for (let version of response["latest"]) {
					var branch = version.split(".").slice(0, 2).join(".");

					// already latest version installed
					if (current_version == version) {
						break;
					}

					// warn user that a new major release would be installed
					//if (current_branch != branch) {
					//	branch["warn_branch_jump"] = true;
					//}

					candidates.unshift(version);

					// don't offer branches older than the current
					if (current_branch == branch) {
						break;
					}
				}
			}
			if (candidates) {
				var m, s, o;
				var advanced_mode = uci.get_first('attendedsysupgrade', 'client', 'advanced_mode') || 0;

				console.log(candidates);

				var mapdata = {
					request: {
						board_name: board_name,
						target: target,
						version: candidates[0],
						packages: Object.keys(packages).sort(),
					}
				}

				m = new form.JSONMap(mapdata, '');

				s = m.section(form.NamedSection, 'request', 'example', '',
					'Use defaults for the safest update');
				o = s.option(form.ListValue, 'version', 'Select firmware version');
				for (let candidate of candidates) {
					o.value(candidate, candidate);
				}

				if (advanced_mode == 1) {
					o = s.option(form.Value, 'board_name', 'Board Name / Profile');
					o = s.option(form.DynamicList, 'packages', 'Packages');
				}

				m.render()
					.then(function(form_rendered) {
						ui.showModal(_('New upgrade available'), [
							form_rendered,
							E('div', {
								'class': 'right'
							}, [
								E('div', {
									'class': 'btn',
									'click': ui.hideModal
								}, _('Cancel')),
								' ',
								E('div', {
									'class': 'btn cbi-button-action',
									'click': function() {
										m.save().then(foo => {
											request_sysupgrade(
												server_url, mapdata.request
											)
										});
									}
								}, _('Request Sysupgrade'))
							])
						]);
					});
			} else {
				ui.showModal(_('No upgrade available'), [
					E('p', {}, _("The device runs the latest firmware version")),
					E('div', {
						'class': 'right'
					}, [
						E('div', {
							'class': 'btn',
							'click': ui.hideModal
						}, _('Close'))
					])
				]);
			}
		});
}

function displayStatus(type, content) {
	if (type) {
		var message = ui.showModal('', '');

		message.classList.add('alert-message');
		DOMTokenList.prototype.add.apply(message.classList, type.split(/\s+/));

		if (content)
			dom.content(message, content);
	} else {
		ui.hideModal();
	}
}

return view.extend({
	load: function() {
		return Promise.all([
			L.resolveDefault(callPackagelist(), {}),
			L.resolveDefault(callSystemBoard(), {}),
			uci.load('attendedsysupgrade')
		]);
	},
	render: function(res) {
		var packages = res[0].packages;
		var current_version = res[1].release.version;
		var target = res[1].release.target;
		var board_name = res[1].board_name;
		var auto_search = uci.get_first('attendedsysupgrade', 'client', 'auto_search') || 1;
		var server_url = uci.get_first('attendedsysupgrade', 'server', 'url');

		var view = [
			E('h2', _("Attended Sysupgrade")),
			E('p', _('The attended sysupgrade service allows to easily upgrade vanilla and custom firmware images.')),
			E('p', _('This is done by building a new firmware on demand via an online service.'))
		];

		if (auto_search == 1) {
			check_sysupgrade(server_url, current_version, target, board_name, packages)
		}

		view.push(E('p', {
			'class': 'btn cbi-button-positive',
			'click': function() {
				check_sysupgrade(server_url, current_version, target, board_name, packages)
			}
		}, _('Search for sysupgrade')));

		return view;
	},

});
<commit_msg>luci-app-attendedsysupgrade: hide branch update<commit_after>'use strict';
'require view';
'require form';
'require uci';
'require rpc';
'require ui';
'require poll';
'require request';
'require dom';

var callPackagelist = rpc.declare({
	object: 'rpc-sys',
	method: 'packagelist',
});

var callSystemBoard = rpc.declare({
	object: 'system',
	method: 'board'
});

var callUpgradeStart = rpc.declare({
	object: 'rpc-sys',
	method: 'upgrade_start',
	params: ["keep"]
});

function install_sysupgrade(url, keep, sha256) {
	displayStatus("notice spinning", E('p', _('Downloading firmware from server to browser')));
	request.get(url, {
			headers: {
				'Content-Type': 'application/x-www-form-urlencoded'
			},
			responseType: 'blob'
		})
		.then(response => {
			var form_data = new FormData();
			form_data.append("sessionid", rpc.getSessionID());
			form_data.append("filename", "/tmp/firmware.bin");
			form_data.append("filemode", 600);
			form_data.append("filedata", response.blob());

			displayStatus("notice spinning", E('p', _('Uploading firmware from browser to device')));
			request.get(L.env.cgi_base + "/cgi-upload", {
					method: 'PUT',
					content: form_data
				})
				.then(response => response.json())
				.then(response => {
					if (response.sha256sum != sha256) {
						displayStatus("warning", [
							E('b', _('Wrong checksum')),
							E('p', _('Error during download of firmware. Please try again')),
							E('div', {
								'class': 'btn',
								'click': ui.hideModal
							}, _('Close'))
						]);
					} else {
						displayStatus('warning spinning', E('p', _('Installing the sysupgrade. Do not unpower device!')));
							L.resolveDefault(callUpgradeStart(keep), {}).then(response => {
								if (keep) {
									ui.awaitReconnect(window.location.host);
								} else {
									ui.awaitReconnect('192.168.1.1', 'openwrt.lan');
								}
							});
					}
				});
		});
}

function request_sysupgrade(server_url, data) {
	var res, req;

	if (data.request_hash) {
		req = request.get(server_url + "/api/build/" + data.request_hash)
	} else {
		req = request.post(server_url + "/api/build", {
			profile: data.board_name,
			target: data.target,
			version: data.version,
			packages: data.packages,
			diff_packages: true,
		})
	}

	req.then(response => {
		switch (response.status) {
			case 200:
				var res = response.json()
				var image;
				console.log(res)
				for (image of res.images) {
					if (image.type == "sysupgrade") {
						break;
					}
				}
				if (image.name != undefined) {
					var sysupgrade_url = server_url + "/store/" + res.bin_dir + "/" + image.name;

					var keep = E('input', {
						type: 'checkbox'
					})
					keep.checked = true;

					var fields = [
						_('Version'), res.version_number + ' ' + res.version_code,
						_('File'), E('a', {
							'href': sysupgrade_url
						}, image.name),
						_('SHA256'), image.sha256,
						_('Build Date'), res.build_at,
						_('Target'), res.target,
					];

					var table = E('div', {
						'class': 'table'
					});

					for (var i = 0; i < fields.length; i += 2) {
						table.appendChild(E('div', {
							'class': 'tr'
						}, [
							E('div', {
								'class': 'td left',
								'width': '33%'
							}, [fields[i]]),
							E('div', {
								'class': 'td left'
							}, [(fields[i + 1] != null) ? fields[i + 1] : '?'])
						]));
					}

					var modal_body = [
						table,
						E('p', {}, E('label', {
							'class': 'btn'
						}, [
							keep, ' ', _('Keep settings and retain the current configuration')
						])),
						E('div', {
							'class': 'right'
						}, [
							E('div', {
								'class': 'btn',
								'click': ui.hideModal
							}, _('Cancel')),
							' ',
							E('div', {
								'class': 'btn cbi-button-action',
								'click': function() {
									install_sysupgrade(sysupgrade_url, keep.checked, image.sha256)
								}
							}, _('Install Sysupgrade'))
						])
					]

					ui.showModal(_('Successfully created sysupgrade image'), modal_body);
				}

				break;
			case 202:
				res = response.json()
				data.request_hash = res.request_hash;
				switch (res.status) {
					case "queued":
						displayStatus("notice spinning", E('p', _('Request in build queue')));
						break;
					case "started":
						displayStatus("notice spinning", E('p', _('Building the sysupgrade image')));
						break;
				}
				setTimeout(function() {
					request_sysupgrade(server_url, data);
				}, 5000);
				break;
			case 400: // bad request
			case 422: // bad package
			case 500: // build failed
				res = response.json()
				var body = [
					E('p', {}, _(res.message)),
					E('p', {}, _("Please report the error message and request")),
					E('b', {}, _("Request to server:")),
					E('pre', {}, JSON.stringify(data, null, 4)),

				]

				if (res.stdout) {
					body.push(E('b', {}, "STDOUT:"))
					body.push(E('pre', {}, res.stdout))

				}

				if (res.stderr) {
					body.push(E('b', {}, "STDERR:"))
					body.push(E('pre', {}, res.stderr))

				}

				body = body.concat([
					E('div', {
						'class': 'right'
					}, [
						E('div', {
							'class': 'btn',
							'click': ui.hideModal
						}, _('Close'))
					])
				]);
				ui.showModal(_('Error building the sysupgrade'), body);
				break;
		}
	});
}

function check_sysupgrade(server_url, current_version, target, board_name, packages) {
	displayStatus("notice spinning", E('p', _('Searching for an available sysupgrade')));
	var current_branch = current_version.split(".").slice(0, 2).join(".");
	var advanced_mode = uci.get_first('attendedsysupgrade', 'client', 'advanced_mode') || 0;
	var candidates = [];
	fetch(server_url + "/api/latest")
		.then(response => response.json())
		.then(response => {
			if (current_version == "SNAPSHOT") {
				candidates.push("SNAPSHOT");
			} else {
				for (let version of response["latest"]) {
					var branch = version.split(".").slice(0, 2).join(".");

					// already latest version installed
					if (current_version == version) {
						break;
					}

					// skip branch upgrades outside the advanced mode
					if (current_branch != branch && advanced_mode == 0) {
						continue;
					}

					candidates.unshift(version);

					// don't offer branches older than the current
					if (current_branch == branch) {
						break;
					}
				}
			}
			if (candidates) {
				var m, s, o;

				console.log(candidates);

				var mapdata = {
					request: {
						board_name: board_name,
						target: target,
						version: candidates[0],
						packages: Object.keys(packages).sort(),
					}
				}

				m = new form.JSONMap(mapdata, '');

				s = m.section(form.NamedSection, 'request', 'example', '',
					'Use defaults for the safest update');
				o = s.option(form.ListValue, 'version', 'Select firmware version');
				for (let candidate of candidates) {
					o.value(candidate, candidate);
				}

				if (advanced_mode == 1) {
					o = s.option(form.Value, 'board_name', 'Board Name / Profile');
					o = s.option(form.DynamicList, 'packages', 'Packages');
				}

				m.render()
					.then(function(form_rendered) {
						ui.showModal(_('New upgrade available'), [
							form_rendered,
							E('div', {
								'class': 'right'
							}, [
								E('div', {
									'class': 'btn',
									'click': ui.hideModal
								}, _('Cancel')),
								' ',
								E('div', {
									'class': 'btn cbi-button-action',
									'click': function() {
										m.save().then(foo => {
											request_sysupgrade(
												server_url, mapdata.request
											)
										});
									}
								}, _('Request Sysupgrade'))
							])
						]);
					});
			} else {
				ui.showModal(_('No upgrade available'), [
					E('p', {}, _("The device runs the latest firmware version")),
					E('div', {
						'class': 'right'
					}, [
						E('div', {
							'class': 'btn',
							'click': ui.hideModal
						}, _('Close'))
					])
				]);
			}
		});
}

function displayStatus(type, content) {
	if (type) {
		var message = ui.showModal('', '');

		message.classList.add('alert-message');
		DOMTokenList.prototype.add.apply(message.classList, type.split(/\s+/));

		if (content)
			dom.content(message, content);
	} else {
		ui.hideModal();
	}
}

return view.extend({
	load: function() {
		return Promise.all([
			L.resolveDefault(callPackagelist(), {}),
			L.resolveDefault(callSystemBoard(), {}),
			uci.load('attendedsysupgrade')
		]);
	},
	render: function(res) {
		var packages = res[0].packages;
		var current_version = res[1].release.version;
		var target = res[1].release.target;
		var board_name = res[1].board_name;
		var auto_search = uci.get_first('attendedsysupgrade', 'client', 'auto_search') || 1;
		var server_url = uci.get_first('attendedsysupgrade', 'server', 'url');

		var view = [
			E('h2', _("Attended Sysupgrade")),
			E('p', _('The attended sysupgrade service allows to easily upgrade vanilla and custom firmware images.')),
			E('p', _('This is done by building a new firmware on demand via an online service.'))
		];

		if (auto_search == 1) {
			check_sysupgrade(server_url, current_version, target, board_name, packages)
		}

		view.push(E('p', {
			'class': 'btn cbi-button-positive',
			'click': function() {
				check_sysupgrade(server_url, current_version, target, board_name, packages)
			}
		}, _('Search for sysupgrade')));

		return view;
	},

});
<|endoftext|>