<commit_before>'use strict';

const PromiseManager = require('../../core/promiseManager');
const { callApi } = require('../../util/common');

/**
 * 비공식으로 엔트리에서 사용되고 있는 언어코드 (vn, ja)의 경우 공식 언어코드로 치환한다.
 * @param {string}originalLanguage
 */
function replaceLanguageCode(originalLanguage) {
    switch (originalLanguage) {
        case 'jp':
            return 'ja';
        case 'vn':
            return 'vi';
        default:
            return originalLanguage;
    }
}

function getInitialCodeMap() {
    return {
        auto: {
            lang: Lang.Blocks.auto,
            sub: [
                'en',
                'ja',
                'zh-CN',
                'zh-TW',
                'es',
                'fr',
                'de',
                'ru',
                'pt',
                'th',
                'vi',
                'id',
                'hi',
                'ko',
            ],
        },
        ko: {
            lang: Lang.Blocks.korean,
            sub: ['en', 'ja', 'zh-CN', 'zh-TW', 'es', 'fr', 'de', 'ru', 'pt', 'th', 'vi', 'id'],
        },
        en: {
            lang: Lang.Blocks.english,
            sub: [
                'ko',
                'ja',
                'zh-CN',
                'zh-TW',
                'es',
                'fr',
                'de',
                'ru',
                'pt',
                'th',
                'vi',
                'id',
                'hi',
            ],
        },
        ja: {
            lang: Lang.Blocks.japan,
            sub: [
                'ko',
                'en',
                'zh-CN',
                'zh-TW',
                'es',
                'fr',
                'de',
                'ru',
                'pt',
                'th',
                'vi',
                'id',
                'hi',
            ],
        },
        'zh-CN': {
            lang: Lang.Blocks.chinese_simplified,
            sub: ['ko', 'en', 'ja', 'zh-TW', 'es', 'fr', 'de', 'ru', 'pt', 'th', 'vi', 'id', 'hi'],
        },
        'zh-TW': {
            lang: Lang.Blocks.chinese_traditional,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'es', 'fr', 'de', 'ru', 'pt', 'th', 'vi', 'id', 'hi'],
        },
        es: {
            lang: Lang.Blocks.spanish,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'fr', 'de', 'ru', 'th', 'vi', 'id'],
        },
        fr: {
            lang: Lang.Blocks.french,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'es', 'de', 'ru', 'th', 'vi', 'id'],
        },
        de: {
            lang: Lang.Blocks.german,
            sub: [
                'ko',
                'en',
                'ja',
                'zh-CN',
                'zh-TW',
                'es',
                'fr',
                'ru',
                'pt',
                'th',
                'vi',
                'id',
                'hi',
            ],
        },
        ru: {
            lang: Lang.Blocks.russian,
            sub: [
                'ko',
                'en',
                'ja',
                'zh-CN',
                'zh-TW',
                'es',
                'fr',
                'de',
                'pt',
                'th',
                'vi',
                'id',
                'hi',
            ],
        },
        pt: {
            lang: Lang.Blocks.portuguese,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'de', 'ru', 'hi'],
        },
        th: {
            lang: Lang.Blocks.thai,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'es', 'fr', 'de', 'ru', 'vi'],
        },
        vi: {
            lang: Lang.Blocks.vietnamese,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'es', 'fr', 'de', 'ru', 'th', 'id'],
        },
        id: {
            lang: Lang.Blocks.indonesian,
            sub: ['ko', 'en', 'zh-CN', 'zh-TW', 'es', 'fr', 'de', 'ru', 'th', 'vi'],
        },
        hi: {
            lang: Lang.Blocks.hindi,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'de', 'ru', 'pt'],
        },
    };
}

Entry.AI_UTILIZE_BLOCK.translate = {
    name: 'translate',
    imageName: 'papago.png',
    sponserText: 'Powered by Naver',
    title: {
        ko: '번역',
        en: 'translate',
        jp: '翻訳',
    },
    titleKey: 'template.translate_title_text',
    description: Lang.Msgs.expansion_translate_description,
    descriptionKey: 'Msgs.expansion_translate_description',
    isInitialized: false,
    init() {
        if (this.isInitialized) {
            return;
        }
        Entry.AI_UTILIZE_BLOCK.translate.delayKey = Entry.projectId;
        Entry.AI_UTILIZE_BLOCK.translate.isInitialized = true;
    },
    api: '/api/expansionBlock/papago/',
    sponsor: 'papagoNaver',
    sponsorLink: 'https://www.ncloud.com/product/aiService/papagoNmt',
    sponsorText: 'Powered by NAVER',
    typeMap: {
        dictionary: 'nsmt',
        artificial_intelligence: 'n2mt',
    },
    apiType: 'nsmt',
};

Entry.AI_UTILIZE_BLOCK.translate.getBlocks = function() {
    const params = {
        getType(isPython) {
            const param = {
                type: 'Dropdown',
                options: [
                    [Lang.Blocks.dictionary, 'dictionary'],
                    [Lang.Blocks.artificial_intelligence, 'artificial_intelligence'],
                ],
                value: 'dictionary',
                fontSize: 11,
                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,
                arrowColor: EntryStatic.colorSet.common.WHITE,
            };
            if (isPython) {
                param.converter = Entry.block.converters.returnStringValue;
            }
            return param;
        },
        getSourceLang(isPython) {
            const value = replaceLanguageCode(Lang.type);
            const options = [
                [Lang.Blocks.korean, 'ko'],
                [Lang.Blocks.english, 'en'],
                [Lang.Blocks.japan, 'ja'],
                [Lang.Blocks.chinese_simplified, 'zh-CN'],
                [Lang.Blocks.chinese_traditional, 'zh-TW'],
                [Lang.Blocks.spanish, 'es'],
                [Lang.Blocks.french, 'fr'],
                [Lang.Blocks.german, 'de'],
                [Lang.Blocks.russian, 'ru'],
                [Lang.Blocks.portuguese, 'pt'],
                [Lang.Blocks.thai, 'th'],
                [Lang.Blocks.vietnamese, 'vi'],
                [Lang.Blocks.indonesian, 'id'],
                [Lang.Blocks.hindi, 'hi'],
            ];
            const index = _.findIndex(options, (x) => x[1] === value);
            if (index > 0) {
                const temp = options[index];
                options[index] = options[0];
                options[0] = temp;
            }
            const param = {
                type: 'Dropdown',
                options,
                value,
                fontSize: 11,
                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,
                arrowColor: EntryStatic.colorSet.common.WHITE,
            };
            if (isPython) {
                param.converter = Entry.block.converters.returnStringValue;
            }
            return param;
        },
        getTargetLang(targetIndex = 0, isPython = false) {
            const param = {
                type: 'DropdownDynamic',
                value: null,
                menuName(value) {
                    const langCodeMap = getInitialCodeMap();
                    if (value) {
                        const convertedLangCode = replaceLanguageCode(value);
                        return langCodeMap[convertedLangCode].sub.map((code) => [
                            langCodeMap[code].lang,
                            code,
                        ]);
                    }

                    if (this._contents.options) {
                        return this._contents.options;
                    } else {
                        return langCodeMap.ko.sub.map((code) => [langCodeMap[code].lang, code]);
                    }
                },
                targetIndex,
                needDeepCopy: true,
                fontSize: 11,
                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,
                arrowColor: EntryStatic.colorSet.common.WHITE,
            };
            if (isPython) {
                param.converter = Entry.block.converters.returnStringValue;
            }
            return param;
        },
    };
    const getProjectId = function() {
        if (Entry.projectId) {
            Entry.AI_UTILIZE_BLOCK.translate.delayKey = Entry.projectId;
        }

        if (Entry.AI_UTILIZE_BLOCK.translate.delayKey) {
            return Entry.AI_UTILIZE_BLOCK.translate.delayKey;
        }

        Entry.AI_UTILIZE_BLOCK.translate.delayKey = _.uniqueId(Entry.generateHash());
        return Entry.AI_UTILIZE_BLOCK.translate.delayKey;
    };

    const translate = (params, type, defaultValue) => {
        params.projectId = getProjectId();
        const key = `translate-${type}${JSON.stringify(params)}`;
        return new PromiseManager()
            .Promise((resolve) => {
                callApi(key, {
                    url: `${Entry.AI_UTILIZE_BLOCK.translate.api}translate/${type}`,
                    params,
                })
                    .then((result) => {
                        if (result.data) {
                            return resolve(result.data.translatedText);
                        }
                        return resolve(defaultValue);
                    })
                    .catch(() => resolve(defaultValue));
            })
            .catch(() => defaultValue);
    };

    const checkLang = (query, defaultValue) => {
        const langCodeMap = getInitialCodeMap();
        return new PromiseManager()
            .Promise((resolve) => {
                callApi(`translate-detect-${query}`, {
                    url: `${Entry.AI_UTILIZE_BLOCK.translate.api}dect/langs`,
                    params: { query, projectId: getProjectId() },
                })
                    .then((result) => {
                        if (
                            result.data &&
                            result.data.langCode &&
                            langCodeMap[result.data.langCode]
                        ) {
                            return resolve(langCodeMap[result.data.langCode].lang);
                        }
                        return resolve(defaultValue);
                    })
                    .catch(() => resolve(defaultValue));
            })
            .catch(() => defaultValue);
    };

    const checkText = function(text) {
        const result = {
            result: false,
            message: Lang.Blocks.unknown_sentence,
        };

        if (!text) {
            result.message = Lang.Blocks.no_sentence;
            return result;
        }

        if (text.length > 20) {
            result.message = Lang.Blocks.sentence_over_20_charactor;
            return result;
        }

        return {
            result: true,
            message: text,
        };
    };
    return {
        translate_title: {
            skeleton: 'basic_text',
            color: EntryStatic.colorSet.common.TRANSPARENT,
            params: [
                {
                    type: 'Text',
                    text: Lang.template.translate_title_text,
                    color: EntryStatic.colorSet.common.TEXT,
                    align: 'center',
                },
            ],
            def: {
                type: 'translate_title',
            },
            class: 'translate',
            isNotFor: ['translate'],
            events: {},
        },
        get_translated_string: {
            color: EntryStatic.colorSet.block.default.AI_UTILIZE,
            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,
            skeleton: 'basic_string_field',
            statements: [],
            params: [
                params.getSourceLang(),
                {
                    type: 'Block',
                    accept: 'string',
                },
                params.getTargetLang(0),
            ],
            events: {},
            def: {
                params: [
                    params.getSourceLang().value,
                    {
                        type: 'text',
                        params: [Lang.Blocks.entry],
                    },
                    null,
                ],
                type: 'get_translated_string',
            },
            pyHelpDef: {
                params: ['A&value', 'B&value', 'C&value'],
                type: 'get_translated_string',
            },
            paramsKeyMap: {
                SOURCE: 0,
                TEXT: 1,
                TARGET: 2,
            },
            class: 'translate',
            isNotFor: ['translate'],
            func(sprite, script) {
                const textObj = checkText(script.getStringValue('TEXT', script));
                if (!textObj.result) {
                    return textObj.message;
                }

                const type = Entry.AI_UTILIZE_BLOCK.translate.apiType;
                const params = {
                    text: textObj.message,
                    target: script.getField('TARGET', script),
                    source: script.getField('SOURCE', script),
                };

                if (params.target == params.source) {
                    return params.text;
                }

                return translate(params, type, Lang.Blocks.unknown_sentence);
            },
            syntax: {
                js: [],
                py: [
                    {
                        syntax: 'Translate.do(%1, %2, %3)',
                        blockType: 'param',
                        textParams: [
                            params.getSourceLang(true),
                            {
                                type: 'Block',
                                accept: 'string',
                            },
                            params.getTargetLang(0, true),
                        ],
                    },
                ],
            },
        },
        check_language: {
            color: EntryStatic.colorSet.block.default.AI_UTILIZE,
            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,
            skeleton: 'basic_string_field',
            statements: [],
            params: [
                {
                    type: 'Block',
                    accept: 'string',
                },
            ],
            events: {},
            def: {
                params: [
                    {
                        type: 'text',
                        params: [Lang.Blocks.entry],
                    },
                ],
                type: 'check_language',
            },
            pyHelpDef: {
                params: ['A&value'],
                type: 'check_language',
            },
            paramsKeyMap: {
                TEXT: 0,
                LANG: 1,
            },
            class: 'translate',
            isNotFor: ['translate'],
            func(sprite, script) {
                const text = script.getStringValue('TEXT', script);
                const textObj = checkText(text);
                if (!textObj.result) {
                    return textObj.message;
                }

                return checkLang(textObj.message, Lang.Blocks.unknown_sentence);
            },
            syntax: {
                js: [],
                py: [
                    {
                        syntax: 'Translate.getLang(%1)',
                        params: [null],
                        blockType: 'param',
                        textParams: [
                            {
                                type: 'Block',
                                accept: 'string',
                            },
                        ],
                    },
                ],
            },
        },
    };
};
<commit_msg>papago translate limit to 3000<commit_after>'use strict';

const PromiseManager = require('../../core/promiseManager');
const { callApi } = require('../../util/common');

/**
 * 비공식으로 엔트리에서 사용되고 있는 언어코드 (vn, ja)의 경우 공식 언어코드로 치환한다.
 * @param {string}originalLanguage
 */
function replaceLanguageCode(originalLanguage) {
    switch (originalLanguage) {
        case 'jp':
            return 'ja';
        case 'vn':
            return 'vi';
        default:
            return originalLanguage;
    }
}

function getInitialCodeMap() {
    return {
        auto: {
            lang: Lang.Blocks.auto,
            sub: [
                'en',
                'ja',
                'zh-CN',
                'zh-TW',
                'es',
                'fr',
                'de',
                'ru',
                'pt',
                'th',
                'vi',
                'id',
                'hi',
                'ko',
            ],
        },
        ko: {
            lang: Lang.Blocks.korean,
            sub: ['en', 'ja', 'zh-CN', 'zh-TW', 'es', 'fr', 'de', 'ru', 'pt', 'th', 'vi', 'id'],
        },
        en: {
            lang: Lang.Blocks.english,
            sub: [
                'ko',
                'ja',
                'zh-CN',
                'zh-TW',
                'es',
                'fr',
                'de',
                'ru',
                'pt',
                'th',
                'vi',
                'id',
                'hi',
            ],
        },
        ja: {
            lang: Lang.Blocks.japan,
            sub: [
                'ko',
                'en',
                'zh-CN',
                'zh-TW',
                'es',
                'fr',
                'de',
                'ru',
                'pt',
                'th',
                'vi',
                'id',
                'hi',
            ],
        },
        'zh-CN': {
            lang: Lang.Blocks.chinese_simplified,
            sub: ['ko', 'en', 'ja', 'zh-TW', 'es', 'fr', 'de', 'ru', 'pt', 'th', 'vi', 'id', 'hi'],
        },
        'zh-TW': {
            lang: Lang.Blocks.chinese_traditional,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'es', 'fr', 'de', 'ru', 'pt', 'th', 'vi', 'id', 'hi'],
        },
        es: {
            lang: Lang.Blocks.spanish,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'fr', 'de', 'ru', 'th', 'vi', 'id'],
        },
        fr: {
            lang: Lang.Blocks.french,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'es', 'de', 'ru', 'th', 'vi', 'id'],
        },
        de: {
            lang: Lang.Blocks.german,
            sub: [
                'ko',
                'en',
                'ja',
                'zh-CN',
                'zh-TW',
                'es',
                'fr',
                'ru',
                'pt',
                'th',
                'vi',
                'id',
                'hi',
            ],
        },
        ru: {
            lang: Lang.Blocks.russian,
            sub: [
                'ko',
                'en',
                'ja',
                'zh-CN',
                'zh-TW',
                'es',
                'fr',
                'de',
                'pt',
                'th',
                'vi',
                'id',
                'hi',
            ],
        },
        pt: {
            lang: Lang.Blocks.portuguese,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'de', 'ru', 'hi'],
        },
        th: {
            lang: Lang.Blocks.thai,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'es', 'fr', 'de', 'ru', 'vi'],
        },
        vi: {
            lang: Lang.Blocks.vietnamese,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'es', 'fr', 'de', 'ru', 'th', 'id'],
        },
        id: {
            lang: Lang.Blocks.indonesian,
            sub: ['ko', 'en', 'zh-CN', 'zh-TW', 'es', 'fr', 'de', 'ru', 'th', 'vi'],
        },
        hi: {
            lang: Lang.Blocks.hindi,
            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'de', 'ru', 'pt'],
        },
    };
}

Entry.AI_UTILIZE_BLOCK.translate = {
    name: 'translate',
    imageName: 'papago.png',
    sponserText: 'Powered by Naver',
    title: {
        ko: '번역',
        en: 'translate',
        jp: '翻訳',
    },
    titleKey: 'template.translate_title_text',
    description: Lang.Msgs.expansion_translate_description,
    descriptionKey: 'Msgs.expansion_translate_description',
    isInitialized: false,
    init() {
        if (this.isInitialized) {
            return;
        }
        Entry.AI_UTILIZE_BLOCK.translate.delayKey = Entry.projectId;
        Entry.AI_UTILIZE_BLOCK.translate.isInitialized = true;
    },
    api: '/api/expansionBlock/papago/',
    sponsor: 'papagoNaver',
    sponsorLink: 'https://www.ncloud.com/product/aiService/papagoNmt',
    sponsorText: 'Powered by NAVER',
    typeMap: {
        dictionary: 'nsmt',
        artificial_intelligence: 'n2mt',
    },
    apiType: 'nsmt',
};

Entry.AI_UTILIZE_BLOCK.translate.getBlocks = function() {
    const params = {
        getType(isPython) {
            const param = {
                type: 'Dropdown',
                options: [
                    [Lang.Blocks.dictionary, 'dictionary'],
                    [Lang.Blocks.artificial_intelligence, 'artificial_intelligence'],
                ],
                value: 'dictionary',
                fontSize: 11,
                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,
                arrowColor: EntryStatic.colorSet.common.WHITE,
            };
            if (isPython) {
                param.converter = Entry.block.converters.returnStringValue;
            }
            return param;
        },
        getSourceLang(isPython) {
            const value = replaceLanguageCode(Lang.type);
            const options = [
                [Lang.Blocks.korean, 'ko'],
                [Lang.Blocks.english, 'en'],
                [Lang.Blocks.japan, 'ja'],
                [Lang.Blocks.chinese_simplified, 'zh-CN'],
                [Lang.Blocks.chinese_traditional, 'zh-TW'],
                [Lang.Blocks.spanish, 'es'],
                [Lang.Blocks.french, 'fr'],
                [Lang.Blocks.german, 'de'],
                [Lang.Blocks.russian, 'ru'],
                [Lang.Blocks.portuguese, 'pt'],
                [Lang.Blocks.thai, 'th'],
                [Lang.Blocks.vietnamese, 'vi'],
                [Lang.Blocks.indonesian, 'id'],
                [Lang.Blocks.hindi, 'hi'],
            ];
            const index = _.findIndex(options, (x) => x[1] === value);
            if (index > 0) {
                const temp = options[index];
                options[index] = options[0];
                options[0] = temp;
            }
            const param = {
                type: 'Dropdown',
                options,
                value,
                fontSize: 11,
                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,
                arrowColor: EntryStatic.colorSet.common.WHITE,
            };
            if (isPython) {
                param.converter = Entry.block.converters.returnStringValue;
            }
            return param;
        },
        getTargetLang(targetIndex = 0, isPython = false) {
            const param = {
                type: 'DropdownDynamic',
                value: null,
                menuName(value) {
                    const langCodeMap = getInitialCodeMap();
                    if (value) {
                        const convertedLangCode = replaceLanguageCode(value);
                        return langCodeMap[convertedLangCode].sub.map((code) => [
                            langCodeMap[code].lang,
                            code,
                        ]);
                    }

                    if (this._contents.options) {
                        return this._contents.options;
                    } else {
                        return langCodeMap.ko.sub.map((code) => [langCodeMap[code].lang, code]);
                    }
                },
                targetIndex,
                needDeepCopy: true,
                fontSize: 11,
                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,
                arrowColor: EntryStatic.colorSet.common.WHITE,
            };
            if (isPython) {
                param.converter = Entry.block.converters.returnStringValue;
            }
            return param;
        },
    };
    const getProjectId = function() {
        if (Entry.projectId) {
            Entry.AI_UTILIZE_BLOCK.translate.delayKey = Entry.projectId;
        }

        if (Entry.AI_UTILIZE_BLOCK.translate.delayKey) {
            return Entry.AI_UTILIZE_BLOCK.translate.delayKey;
        }

        Entry.AI_UTILIZE_BLOCK.translate.delayKey = _.uniqueId(Entry.generateHash());
        return Entry.AI_UTILIZE_BLOCK.translate.delayKey;
    };

    const translate = (params, type, defaultValue) => {
        params.projectId = getProjectId();
        const key = `translate-${type}${JSON.stringify(params)}`;
        return new PromiseManager()
            .Promise((resolve) => {
                callApi(key, {
                    url: `${Entry.AI_UTILIZE_BLOCK.translate.api}translate/${type}`,
                    params,
                })
                    .then((result) => {
                        if (result.data) {
                            return resolve(result.data.translatedText);
                        }
                        return resolve(defaultValue);
                    })
                    .catch(() => resolve(defaultValue));
            })
            .catch(() => defaultValue);
    };

    const checkLang = (query, defaultValue) => {
        const langCodeMap = getInitialCodeMap();
        return new PromiseManager()
            .Promise((resolve) => {
                callApi(`translate-detect-${query}`, {
                    url: `${Entry.AI_UTILIZE_BLOCK.translate.api}dect/langs`,
                    params: { query, projectId: getProjectId() },
                })
                    .then((result) => {
                        if (
                            result.data &&
                            result.data.langCode &&
                            langCodeMap[result.data.langCode]
                        ) {
                            return resolve(langCodeMap[result.data.langCode].lang);
                        }
                        return resolve(defaultValue);
                    })
                    .catch(() => resolve(defaultValue));
            })
            .catch(() => defaultValue);
    };

    const checkText = function(text) {
        const result = {
            result: false,
            message: Lang.Blocks.unknown_sentence,
        };

        if (!text) {
            result.message = Lang.Blocks.no_sentence;
            return result;
        }

        if (text.length > 3000) {
            result.message = Lang.Blocks.sentence_over_3000_charactor;
            return result;
        }

        return {
            result: true,
            message: text,
        };
    };
    return {
        translate_title: {
            skeleton: 'basic_text',
            color: EntryStatic.colorSet.common.TRANSPARENT,
            params: [
                {
                    type: 'Text',
                    text: Lang.template.translate_title_text,
                    color: EntryStatic.colorSet.common.TEXT,
                    align: 'center',
                },
            ],
            def: {
                type: 'translate_title',
            },
            class: 'translate',
            isNotFor: ['translate'],
            events: {},
        },
        get_translated_string: {
            color: EntryStatic.colorSet.block.default.AI_UTILIZE,
            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,
            skeleton: 'basic_string_field',
            statements: [],
            params: [
                params.getSourceLang(),
                {
                    type: 'Block',
                    accept: 'string',
                },
                params.getTargetLang(0),
            ],
            events: {},
            def: {
                params: [
                    params.getSourceLang().value,
                    {
                        type: 'text',
                        params: [Lang.Blocks.entry],
                    },
                    null,
                ],
                type: 'get_translated_string',
            },
            pyHelpDef: {
                params: ['A&value', 'B&value', 'C&value'],
                type: 'get_translated_string',
            },
            paramsKeyMap: {
                SOURCE: 0,
                TEXT: 1,
                TARGET: 2,
            },
            class: 'translate',
            isNotFor: ['translate'],
            func(sprite, script) {
                const textObj = checkText(script.getStringValue('TEXT', script));
                if (!textObj.result) {
                    return textObj.message;
                }

                const type = Entry.AI_UTILIZE_BLOCK.translate.apiType;
                const params = {
                    text: textObj.message,
                    target: script.getField('TARGET', script),
                    source: script.getField('SOURCE', script),
                };

                if (params.target == params.source) {
                    return params.text;
                }

                return translate(params, type, Lang.Blocks.unknown_sentence);
            },
            syntax: {
                js: [],
                py: [
                    {
                        syntax: 'Translate.do(%1, %2, %3)',
                        blockType: 'param',
                        textParams: [
                            params.getSourceLang(true),
                            {
                                type: 'Block',
                                accept: 'string',
                            },
                            params.getTargetLang(0, true),
                        ],
                    },
                ],
            },
        },
        check_language: {
            color: EntryStatic.colorSet.block.default.AI_UTILIZE,
            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,
            skeleton: 'basic_string_field',
            statements: [],
            params: [
                {
                    type: 'Block',
                    accept: 'string',
                },
            ],
            events: {},
            def: {
                params: [
                    {
                        type: 'text',
                        params: [Lang.Blocks.entry],
                    },
                ],
                type: 'check_language',
            },
            pyHelpDef: {
                params: ['A&value'],
                type: 'check_language',
            },
            paramsKeyMap: {
                TEXT: 0,
                LANG: 1,
            },
            class: 'translate',
            isNotFor: ['translate'],
            func(sprite, script) {
                const text = script.getStringValue('TEXT', script);
                const textObj = checkText(text);
                if (!textObj.result) {
                    return textObj.message;
                }

                return checkLang(textObj.message, Lang.Blocks.unknown_sentence);
            },
            syntax: {
                js: [],
                py: [
                    {
                        syntax: 'Translate.getLang(%1)',
                        params: [null],
                        blockType: 'param',
                        textParams: [
                            {
                                type: 'Block',
                                accept: 'string',
                            },
                        ],
                    },
                ],
            },
        },
    };
};
<|endoftext|>


<commit_before>/*global
 define
 */
/*jslint
 browser: true,
 white: true
 */
define([
    'jquery',
    'bluebird',
    'kb/common/html',
    'kb/common/utils',
    'kb/service/client/workspace',
    'kb_spec_common',
    'google-code-prettify',
    'datatables_bootstrap'],
    function ($, Promise, html, Utils, Workspace, specCommon, PR) {
        'use strict';

        // Just take params for now
        /* TODO: use specific arguments */
        var factory = function (config) {
            var mount, container, runtime = config.runtime;
            var dataType, moduleName, typeName, typeVersion;

            // tags used in this module.
            var table = html.tag('table'),
                tr = html.tag('tr'),
                th = html.tag('th'),
                td = html.tag('td'),
                a = html.tag('a'),
                div = html.tag('div'),
                pre = html.tag('pre'),
                ul = html.tag('ul'),
                li = html.tag('li'),
                bstable = function (cols, rows) {
                    return html.makeTable({columns: cols, rows: rows, class: 'table'});
                };

            function tabTableContent() {
                return table({
                    class: 'table table-striped table-bordered',
                    style: {width: '100%'},
                    'data-attach': 'table'});
            }

            // OVERVIEW Tab
            function overviewTab(data) {

                var typeNameDisplay = typeName;
                if(typeName.split('-').length!==2) {
                    // show latest version name
                    typeNameDisplay = data.released_type_vers[data.released_type_vers.length-1];
                }
                return table({class: 'table table-striped table-bordered',
                    style: 'margin-left: auto; margin-right: auto'}, [
                    tr([th('Name'), td(typeNameDisplay)]),
                    //tr([th('Version'), td(typeVersion)]),
                    tr([th('In module version(s)'), td(
                            bstable(['Version id', 'Created on'], data.module_vers.map(function (moduleVer) {
                                var moduleId = moduleName + '-' + moduleVer;
                                return [a({href: '#spec/module/' + moduleId}, moduleVer),
                                    Utils.niceTimestamp(parseInt(moduleVer, 10))];
                            })))]),
                    tr([th('Description'), td(pre({style: {'white-space': 'pre-wrap', 'word-wrap': 'break-word'}}, data.description))])
                ]);
                /* TODO: Add back in the kidl editor -- need to talk to Roman */
            }

            // SPEC FILE Tab
            function specFileTab(data) {
                var specText = specCommon.replaceMarkedTypeLinksInSpec(moduleName, data.spec_def, 'links-click');
                var content = div({style: {width: '100%'}}, [
                    pre({class: 'prettyprint lang-spec'}, specText)
                ]);
                return {
                    content: content,
                    widget: {
                        attach: function (node) {
                            PR.prettyPrint(null, node);
                        }
                    }
                };
            }

            // FUNCTIONS Tab
            function functionsTab(data) {
                // Build The table more functionally, using datatables.
                var tableData = data.using_func_defs.map(function (funcId) {
                    var parsed = funcId.match(/^(.+?)-(.+?)$/),
                        funcName = parsed[1],
                        funcVer = parsed[2];

                    return {
                        name: a({href: '#spec/functions/' + funcId}, funcName),
                        ver: funcVer
                    };
                });
                var tableSettings = {
                    sPaginationType: 'full_numbers',
                    iDisplayLength: 10,
                    aoColumns: [
                        {sTitle: 'Function name', mData: 'name'},
                        {sTitle: 'Function version', mData: 'ver'}
                    ],
                    aaData: tableData,
                    oLanguage: {
                        sSearch: 'Search function:',
                        sEmptyTable: 'No functions use this type'
                    }
                };

                return {
                    content: tabTableContent(),
                    widget: {
                        attach: function (node) {
                            var n = node.querySelector('[data-attach="table"]');
                            if (n !== null) {
                                $(n).dataTable(tableSettings);
                            }
                        }
                    }
                };
            }

            // USING TYPES Tab
            function usingTypesTab(data) {
                var tableData = data.using_type_defs.map(function (typeId) {
                    var parsed = typeId.match(/^(.+?)-(.+?)$/),
                        typeName = parsed[1],
                        typeVer = parsed[2];

                    return {
                        name: a({href: '#spec/type/' + typeId}, typeName),
                        ver: typeVer
                    };
                });
                var tableSettings = {
                    sPaginationType: 'full_numbers',
                    iDisplayLength: 10,
                    aoColumns: [
                        {sTitle: 'Type name', mData: 'name'},
                        {sTitle: 'Type version', mData: 'ver'}
                    ],
                    aaData: tableData,
                    oLanguage: {
                        sSearch: 'Search types:',
                        sEmptyTable: 'No types use this type'
                    }
                };

                return {
                    content: tabTableContent(),
                    widget: {
                        attach: function (node) {
                            var n = node.querySelector('[data-attach="table"]');
                            if (n !== null) {
                                $(n).dataTable(tableSettings);
                            }
                        }
                    }
                };
            }

            // SUB TYPES Tab
            function subTypesTab(data) {
                var tableData = data.used_type_defs.map(function (typeId) {
                    var parsed = typeId.match(/^(.+?)-(.+?)$/),
                        typeName = parsed[1],
                        typeVer = parsed[2];

                    return {
                        name: a({href: '#spec/type/' + typeId}, typeName),
                        ver: typeVer
                    };
                });
                var tableSettings = {
                    sPaginationType: 'full_numbers',
                    iDisplayLength: 10,
                    aoColumns: [
                        {sTitle: 'Type name', mData: 'name'},
                        {sTitle: 'Type version', mData: 'ver'}
                    ],
                    aaData: tableData,
                    oLanguage: {
                        sSearch: 'Search types:',
                        sEmptyTable: 'No types use this type'
                    }
                };
                return {
                    content: tabTableContent(),
                    widget: {
                        attach: function (node) {
                            var n = node.querySelector('[data-attach="table"]');
                            if (n !== null) {
                                $(n).dataTable(tableSettings);
                            }
                        }
                    }
                };
            }

            // VERSIONS Tab
            function versionsTab(data) {
                var tableData = data.type_vers.map(function (typeId) {
                    var parsed = typeId.match(/^(.+?)-(.+?)$/),
                        typeName = parsed[1],
                        typeVer = parsed[2];

                    return {
                        name: a({href: '#spec/type/' + typeId}, typeName),
                        ver: typeVer
                    };
                });
                var tableSettings = {
                    sPaginationType: 'full_numbers',
                    iDisplayLength: 10,
                    aoColumns: [
                        {sTitle: 'Type name', mData: 'name'},
                        {sTitle: 'Type version', mData: 'ver'}
                    ],
                    aaData: tableData,
                    oLanguage: {
                        sSearch: 'Search versions:',
                        sEmptyTable: 'No versions registered'
                    }
                };
                return {
                    content: tabTableContent(),
                    widget: {
                        attach: function (node) {
                            var n = node.querySelector('[data-attach="table"]');
                            if (n !== null) {
                                $(n).dataTable(tableSettings);
                            }
                        }
                    }
                };
            }

            function render() {
                var workspace = new Workspace(runtime.getConfig('workspace_url', {
                    token: runtime.getService('session').getAuthToken()
                }));

                return workspace.get_type_info(dataType)
                    .then(function (data) {
                        var tabs = [
                            {title: 'Overview', id: 'overview', content: overviewTab},
                            {title: 'Spec-file', id: 'spec', content: specFileTab},
                            /* Functions no longer means anything... */
                            /*{title: 'Functions', id: 'funcs', content: functionsTab},*/
                            {title: 'Using Types', id: 'types', content: usingTypesTab},
                            {title: 'Sub-types', id: 'subs', content: subTypesTab},
                            {title: 'Versions', id: 'vers', content: versionsTab}
                        ],
                            id = '_' + html.genId(),
                            widgets = [];

                        var content = div([
                            ul({id: id, class: 'nav nav-tabs'},
                                tabs.map(function (tab) {
                                    var active = (tab.id === 'overview') ? 'active' : '';
                                    return li({class: active}, a({href: '#' + tab.id + id, 'data-toggle': 'tab'}, tab.title));
                                })),
                            div({class: 'tab-content'}, tabs.map(function (tab) {
                                var active = (tab.id === 'overview') ? ' active' : '',
                                    result = tab.content(data);
                                if (typeof result === 'string') {
                                    return div({class: 'tab-pane in' + active, id: tab.id + id}, tab.content(data));
                                }
                                // This is the emerging widget pattern: Save a list of widgets
                                // and invoke them after the content is added to the dom,
                                // because they need a real node to render upon.
                                var widgetId = html.genId();
                                widgets.push({
                                    id: widgetId,
                                    widget: result.widget
                                });
                                return div({class: 'tab-pane in' + active, id: tab.id + id}, [
                                    div({id: widgetId}, [
                                        result.content
                                    ])
                                ]);
                            })
                                )
                        ]);
                        container.innerHTML = content;
                        return Promise.all(widgets.map(function (widget) {
                            var n = document.getElementById(widget.id);
                            return widget.widget.attach(n);
                        }));

                    })
                    .then(function () {
                        PR.prettyPrint();
                    });
            }

            // API

            var mount, container;

            function attach(node) {
                return Promise.try(function () {
                    mount = node;
                    container = document.createElement('div');
                    mount.appendChild(container);
                });
            }

            function detach() {
                return Promise.try(function () {
                    if (mount && container) {
                        mount.removeChild(container);
                        container.innerHTML = '';
                    }
                });
            }

            function start(params) {
                return Promise.try(function () {
                    container.innerHTML = html.loading();

                    // Parse the data type, throwing exceptions if malformed.
                    dataType = params.datatype;
                    var matched = dataType.match(/^(.+?)\.(.+?)-(.+)$/);
                    if(matched && matched.length === 4) {
                        moduleName = matched[1];
                        typeName = matched[1] + '.' + matched[2];
                        typeVersion = matched[3];
                    }

                    matched = dataType.match(/^(.+?)\.(.+?)$/);
                    if(matched && matched.length === 3) {
                        moduleName = matched[1];
                        typeName = matched[1] + '.' + matched[2];
                        typeVersion = null;
                    }

                    if (!matched) {
                        throw new Error('Invalid data type ' + dataType);
                    }

                    /* TODO: reign this puppy in... */
                    // This is a promise that isn't returned ... so it just goes off by itself.
                    return render();
                });
            }

            return {
                attach: attach,
                detach: detach,
                start: start
            };
        };

        return {
            make: function (config) {
                return factory(config);
            }
        };
    });<commit_msg>fix service url, improve title formatting<commit_after>/*global
 define
 */
/*jslint
 browser: true,
 white: true
 */
define([
    'jquery',
    'bluebird',
    'kb/common/html',
    'kb/common/utils',
    'kb/service/client/workspace',
    'kb_spec_common',
    'google-code-prettify',
    'datatables_bootstrap'],
    function ($, Promise, html, Utils, Workspace, specCommon, PR) {
        'use strict';

        // Just take params for now
        /* TODO: use specific arguments */
        var factory = function (config) {
            var mount, container, runtime = config.runtime;
            var dataType, moduleName, typeName, typeVersion;

            // tags used in this module.
            var t = html.tag,
                table = t('table'),
                tr = t('tr'),
                th = t('th'),
                td = t('td'),
                a = t('a'),
                div = t('div'),
                pre = t('pre'),
                ul = t('ul'),
                li = t('li'),
                span = t('span'),
                bstable = function (cols, rows) {
                    return html.makeTable({columns: cols, rows: rows, class: 'table'});
                };

            function tabTableContent() {
                return table({
                    class: 'table table-striped table-bordered',
                    style: {width: '100%'},
                    'data-attach': 'table'});
            }

            function renderTitle(typeName) {
                var title = [
                    'Type Specification for',
                    span({style: {textDecoration: 'underline'}}, typeName)
                ].join(' ');
                runtime.send('ui', 'setTitle', title);
            }

            // OVERVIEW Tab
            function overviewTab(data) {
                var typeNameDisplay = typeName;
                if(typeName.split('-').length!==2) {
                    // show latest version name
                    typeNameDisplay = data.released_type_vers[data.released_type_vers.length-1];
                }
                renderTitle(typeNameDisplay);
                return table({class: 'table table-striped table-bordered',
                    style: 'margin-left: auto; margin-right: auto'}, [
                    tr([th('Name'), td(typeNameDisplay)]),
                    //tr([th('Version'), td(typeVersion)]),
                    tr([th('In module version(s)'), td(
                            bstable(['Version id', 'Created on'], data.module_vers.map(function (moduleVer) {
                                var moduleId = moduleName + '-' + moduleVer;
                                return [a({href: '#spec/module/' + moduleId}, moduleVer),
                                    Utils.niceTimestamp(parseInt(moduleVer, 10))];
                            })))]),
                    tr([th('Description'), td(pre({style: {'white-space': 'pre-wrap', 'word-wrap': 'break-word'}}, data.description))])
                ]);
                /* TODO: Add back in the kidl editor -- need to talk to Roman */
            }

            // SPEC FILE Tab
            function specFileTab(data) {
                var specText = specCommon.replaceMarkedTypeLinksInSpec(moduleName, data.spec_def, 'links-click');
                var content = div({style: {width: '100%'}}, [
                    pre({class: 'prettyprint lang-spec'}, specText)
                ]);
                return {
                    content: content,
                    widget: {
                        attach: function (node) {
                            PR.prettyPrint(null, node);
                        }
                    }
                };
            }

            // FUNCTIONS Tab
            function functionsTab(data) {
                // Build The table more functionally, using datatables.
                var tableData = data.using_func_defs.map(function (funcId) {
                    var parsed = funcId.match(/^(.+?)-(.+?)$/),
                        funcName = parsed[1],
                        funcVer = parsed[2];

                    return {
                        name: a({href: '#spec/functions/' + funcId}, funcName),
                        ver: funcVer
                    };
                });
                var tableSettings = {
                    sPaginationType: 'full_numbers',
                    iDisplayLength: 10,
                    aoColumns: [
                        {sTitle: 'Function name', mData: 'name'},
                        {sTitle: 'Function version', mData: 'ver'}
                    ],
                    aaData: tableData,
                    oLanguage: {
                        sSearch: 'Search function:',
                        sEmptyTable: 'No functions use this type'
                    }
                };

                return {
                    content: tabTableContent(),
                    widget: {
                        attach: function (node) {
                            var n = node.querySelector('[data-attach="table"]');
                            if (n !== null) {
                                $(n).dataTable(tableSettings);
                            }
                        }
                    }
                };
            }

            // USING TYPES Tab
            function usingTypesTab(data) {
                var tableData = data.using_type_defs.map(function (typeId) {
                    var parsed = typeId.match(/^(.+?)-(.+?)$/),
                        typeName = parsed[1],
                        typeVer = parsed[2];

                    return {
                        name: a({href: '#spec/type/' + typeId}, typeName),
                        ver: typeVer
                    };
                });
                var tableSettings = {
                    sPaginationType: 'full_numbers',
                    iDisplayLength: 10,
                    aoColumns: [
                        {sTitle: 'Type name', mData: 'name'},
                        {sTitle: 'Type version', mData: 'ver'}
                    ],
                    aaData: tableData,
                    oLanguage: {
                        sSearch: 'Search types:',
                        sEmptyTable: 'No types use this type'
                    }
                };

                return {
                    content: tabTableContent(),
                    widget: {
                        attach: function (node) {
                            var n = node.querySelector('[data-attach="table"]');
                            if (n !== null) {
                                $(n).dataTable(tableSettings);
                            }
                        }
                    }
                };
            }

            // SUB TYPES Tab
            function subTypesTab(data) {
                var tableData = data.used_type_defs.map(function (typeId) {
                    var parsed = typeId.match(/^(.+?)-(.+?)$/),
                        typeName = parsed[1],
                        typeVer = parsed[2];

                    return {
                        name: a({href: '#spec/type/' + typeId}, typeName),
                        ver: typeVer
                    };
                });
                var tableSettings = {
                    sPaginationType: 'full_numbers',
                    iDisplayLength: 10,
                    aoColumns: [
                        {sTitle: 'Type name', mData: 'name'},
                        {sTitle: 'Type version', mData: 'ver'}
                    ],
                    aaData: tableData,
                    oLanguage: {
                        sSearch: 'Search types:',
                        sEmptyTable: 'No types use this type'
                    }
                };
                return {
                    content: tabTableContent(),
                    widget: {
                        attach: function (node) {
                            var n = node.querySelector('[data-attach="table"]');
                            if (n !== null) {
                                $(n).dataTable(tableSettings);
                            }
                        }
                    }
                };
            }

            // VERSIONS Tab
            function versionsTab(data) {
                var tableData = data.type_vers.map(function (typeId) {
                    var parsed = typeId.match(/^(.+?)-(.+?)$/),
                        typeName = parsed[1],
                        typeVer = parsed[2];

                    return {
                        name: a({href: '#spec/type/' + typeId}, typeName),
                        ver: typeVer
                    };
                });
                var tableSettings = {
                    sPaginationType: 'full_numbers',
                    iDisplayLength: 10,
                    aoColumns: [
                        {sTitle: 'Type name', mData: 'name'},
                        {sTitle: 'Type version', mData: 'ver'}
                    ],
                    aaData: tableData,
                    oLanguage: {
                        sSearch: 'Search versions:',
                        sEmptyTable: 'No versions registered'
                    }
                };
                return {
                    content: tabTableContent(),
                    widget: {
                        attach: function (node) {
                            var n = node.querySelector('[data-attach="table"]');
                            if (n !== null) {
                                $(n).dataTable(tableSettings);
                            }
                        }
                    }
                };
            }

            function render() {
                var workspace = new Workspace(runtime.getConfig('services.workspace.url', {
                    token: runtime.getService('session').getAuthToken()
                }));

                return workspace.get_type_info(dataType)
                    .then(function (data) {
                        var tabs = [
                            {title: 'Overview', id: 'overview', content: overviewTab},
                            {title: 'Spec-file', id: 'spec', content: specFileTab},
                            /* Functions no longer means anything... */
                            /*{title: 'Functions', id: 'funcs', content: functionsTab},*/
                            {title: 'Using Types', id: 'types', content: usingTypesTab},
                            {title: 'Sub-types', id: 'subs', content: subTypesTab},
                            {title: 'Versions', id: 'vers', content: versionsTab}
                        ],
                            id = '_' + html.genId(),
                            widgets = [];

                        var content = div([
                            ul({id: id, class: 'nav nav-tabs'},
                                tabs.map(function (tab) {
                                    var active = (tab.id === 'overview') ? 'active' : '';
                                    return li({class: active}, a({href: '#' + tab.id + id, 'data-toggle': 'tab'}, tab.title));
                                })),
                            div({class: 'tab-content'}, tabs.map(function (tab) {
                                var active = (tab.id === 'overview') ? ' active' : '',
                                    result = tab.content(data);
                                if (typeof result === 'string') {
                                    return div({class: 'tab-pane in' + active, id: tab.id + id}, tab.content(data));
                                }
                                // This is the emerging widget pattern: Save a list of widgets
                                // and invoke them after the content is added to the dom,
                                // because they need a real node to render upon.
                                var widgetId = html.genId();
                                widgets.push({
                                    id: widgetId,
                                    widget: result.widget
                                });
                                return div({class: 'tab-pane in' + active, id: tab.id + id}, [
                                    div({id: widgetId}, [
                                        result.content
                                    ])
                                ]);
                            })
                                )
                        ]);
                        container.innerHTML = content;
                        return Promise.all(widgets.map(function (widget) {
                            var n = document.getElementById(widget.id);
                            return widget.widget.attach(n);
                        }));

                    })
                    .then(function () {
                        PR.prettyPrint();
                    });
            }

            // API

            var mount, container;

            function attach(node) {
                return Promise.try(function () {
                    mount = node;
                    container = document.createElement('div');
                    mount.appendChild(container);
                });
            }

            function detach() {
                return Promise.try(function () {
                    if (mount && container) {
                        mount.removeChild(container);
                        container.innerHTML = '';
                    }
                });
            }

            function start(params) {
                return Promise.try(function () {
                    container.innerHTML = html.loading();

                    // Parse the data type, throwing exceptions if malformed.
                    dataType = params.datatype;
                    var matched = dataType.match(/^(.+?)\.(.+?)-(.+)$/);
                    if(matched && matched.length === 4) {
                        moduleName = matched[1];
                        typeName = matched[1] + '.' + matched[2];
                        typeVersion = matched[3];
                    }

                    matched = dataType.match(/^(.+?)\.(.+?)$/);
                    if(matched && matched.length === 3) {
                        moduleName = matched[1];
                        typeName = matched[1] + '.' + matched[2];
                        typeVersion = null;
                    }

                    if (!matched) {
                        throw new Error('Invalid data type ' + dataType);
                    }

                    /* TODO: reign this puppy in... */
                    // This is a promise that isn't returned ... so it just goes off by itself.
                    return render();
                });
            }

            return {
                attach: attach,
                detach: detach,
                start: start
            };
        };

        return {
            make: function (config) {
                return factory(config);
            }
        };
    });<|endoftext|>


<commit_before>var net = require('net');

var shortid = require('shortid');
var Discord = require('discord.io');

class Bot {
	constructor(key, disnode) {
		this.key = key;
		this.client = {};
		this.disnode = disnode;
		this.bind_onMessage = null;
		this.isRemote = false;
		this.remoteID = "";
	}

	Connect() {
		var self = this;
		return new Promise(function (resolve, reject) {

			if (self.disnode.botConfig.balancerEnabled == true) {
				if (!self.disnode.botConfig.balancerIP) {
					reject("No Load Balancer IP!");
				}
				if (!self.disnode.botConfig.balancerPORT) {
					reject("No Load Balancer Port!");
				}

				self.client.type == "REMOTE";
				self.client = new net.Socket();
				self.client.connect(self.disnode.botConfig.balancerPORT, self.disnode.botConfig.balancerIP, function () {
					self.remoteID = shortid.generate();
					self.client.write(JSON.stringify({
						type: "REGISTER",
						id: self.remoteID
					}))
					self.client.on('data', (data) => self.ParseRemoteCommand(data));
					self.isRemote = true;
					resolve("Connected to remote Load Balancer!");
					return;
				});
			} else {
				self.client = new Discord.Client({
					autorun: true,
					token: self.key
				});

				self.client.on('ready', function (event) {
					self.SetUpLocalBinds();
					resolve();
				});

			}

		});
	}

	Disconnect() {
		var self = this;
		return new Promise(function (resolve, reject) {
			self.client.disconnect();
			resolve();
		});
	}

	Restart() {
		var self = this;
		self.Disconnect().then(function (){
			self.client.connect()
		});
	}

	ParseRemoteCommand(command) {
		var self = this;
		var obj = JSON.parse(command);

		switch (obj.type) {
		case "RECV_MESSAGE":

			if (self.bind_onMessage) {
				self.bind_onMessage(obj.data);
			} else {

			}
		}
	}

	SetUpLocalBinds() {
		var self = this;
		self.client.on('message', function (user, userID, channelID, message, event) {
			if (self.bind_onMessage) {
				var _server = "DM";
				if(self.client.channels[channelID]){
						_server = self.client.channels[channelID].guild_id;
				}
				var msgObject = {
					user: user,
					userID: userID,
					channel: channelID,
					message: message,
					server: _server
				}
				self.bind_onMessage(msgObject);
			}
		});
	}

	bindOnMessage(msgFunction) {
		this.bind_onMessage = msgFunction;
	}

	SendMessage(channel, msg, typing=false, tts=false) {
		var self = this;
		if (self.isRemote) {
			var msgOBJ = {
				channel: channel,
				msg: msg,
				typing: typing,
      	tts: tts
			};
			var commandObj = {
				type: "SEND_MESSAGE",
				id: self.remoteID,
				data: msgOBJ
			};

			self.client.write(JSON.stringify(commandObj));
		}else{
			return new Promise(function(resolve, reject) {
				self.client.sendMessage({
					to: channel,
					message: msg,
		 			typing: typing,
		      tts: tts
				}, function(err, resp) {
					if(err){
						reject(err);
					}else {
						resolve(resp);
					}
				});
			});
		}
	}
	SendEmbed(channel, embed){
		var self = this;
		self.client.sendMessage({
			to: channel,
			embed: embed
		});
	}
	SendCompactEmbed(channel, title, body) {
		var self = this;
		self.client.sendMessage({
			to: channel,
			embed: {
				color: 3447003,
				author: {},
				fields: [{
					name: title,
					inline: false,
					value: body,
				}],
				footer: {}
			}
		});
	}
	SetStatus(status){
		var self = this;
		self.client.setPresence({game: {name: status}});
	}

	SetUsername(name){
		var self = this;
		self.client.editUserInfo({username: name});
	}

	JoinVoiceChannel(voiceID){
		var self = this;
		this.client.joinVoiceChannel(voiceID,function(err){
			if(err){
				console.log(err);
			}else{
			}
		})
	}

  LeaveVoiceChannel(voiceID){
		var self = this;
		this.client.leaveVoiceChannel(voiceID,function(err){
			if(err){
				console.log(err);
			}else{
			}
		})
	}
		JoinUsersVoiceChannel(serverID, userID){
		var user = this.GetUserByID(serverID, userID);
		if(!user){
			return;
		}
		this.JoinVoiceChannel(user.voice_channel_id);
	}
    LeaveUsersVoiceChannel(serverID, userID) {
    var user = this.GetUserByID(serverID, userID);
		if(!user){
			return;
		}
			this.LeaveVoiceChannel(user.voice_channel_id);
  }
		GetServerByID(id){
		var servers = this.client.servers;
		return servers[id];
	}
		GetUserByID(serverId, userId){
		var server = this.GetServerByID(serverId);
		if(!server){
			return;
		}
		return server.members[userId];
	}
		GetUserRoles(serverId, userId){
		var user = this.GetUserByID(serverId, userId);
		if(!user){
			return;
		}
		return user.roles;
	}

	GetRoleById(serverId, roleId){
		var server = this.GetServerByID(serverId);
		if(!server){
			return;
		}
		return server.roles[roleId];
	}
	GetBotInfo(){
		var self = this;
		return {
			username: self.client.username,
			id: self.client.id,
			avatar: self.client.avatar,
			bot: self.client.bot,
			discriminator: self.client.discriminator,
		}
	}
	GetUserInfo(UserID){
		var self = this;
		return self.client.users[userID];
	}
}

module.exports = Bot;
<commit_msg>SendCompactEmbed Optionable Color Support.<commit_after>var net = require('net');

var shortid = require('shortid');
var Discord = require('discord.io');

class Bot {
	constructor(key, disnode) {
		this.key = key;
		this.client = {};
		this.disnode = disnode;
		this.bind_onMessage = null;
		this.isRemote = false;
		this.remoteID = "";
	}

	Connect() {
		var self = this;
		return new Promise(function (resolve, reject) {

			if (self.disnode.botConfig.balancerEnabled == true) {
				if (!self.disnode.botConfig.balancerIP) {
					reject("No Load Balancer IP!");
				}
				if (!self.disnode.botConfig.balancerPORT) {
					reject("No Load Balancer Port!");
				}

				self.client.type == "REMOTE";
				self.client = new net.Socket();
				self.client.connect(self.disnode.botConfig.balancerPORT, self.disnode.botConfig.balancerIP, function () {
					self.remoteID = shortid.generate();
					self.client.write(JSON.stringify({
						type: "REGISTER",
						id: self.remoteID
					}))
					self.client.on('data', (data) => self.ParseRemoteCommand(data));
					self.isRemote = true;
					resolve("Connected to remote Load Balancer!");
					return;
				});
			} else {
				self.client = new Discord.Client({
					autorun: true,
					token: self.key
				});

				self.client.on('ready', function (event) {
					self.SetUpLocalBinds();
					resolve();
				});

			}

		});
	}

	Disconnect() {
		var self = this;
		return new Promise(function (resolve, reject) {
			self.client.disconnect();
			resolve();
		});
	}

	Restart() {
		var self = this;
		self.Disconnect().then(function (){
			self.client.connect()
		});
	}

	ParseRemoteCommand(command) {
		var self = this;
		var obj = JSON.parse(command);

		switch (obj.type) {
		case "RECV_MESSAGE":

			if (self.bind_onMessage) {
				self.bind_onMessage(obj.data);
			} else {

			}
		}
	}

	SetUpLocalBinds() {
		var self = this;
		self.client.on('message', function (user, userID, channelID, message, event) {
			if (self.bind_onMessage) {
				var _server = "DM";
				if(self.client.channels[channelID]){
						_server = self.client.channels[channelID].guild_id;
				}
				var msgObject = {
					user: user,
					userID: userID,
					channel: channelID,
					message: message,
					server: _server
				}
				self.bind_onMessage(msgObject);
			}
		});
	}

	bindOnMessage(msgFunction) {
		this.bind_onMessage = msgFunction;
	}

	SendMessage(channel, msg, typing=false, tts=false) {
		var self = this;
		if (self.isRemote) {
			var msgOBJ = {
				channel: channel,
				msg: msg,
				typing: typing,
                tts: tts
			};
			var commandObj = {
				type: "SEND_MESSAGE",
				id: self.remoteID,
				data: msgOBJ
			};

			self.client.write(JSON.stringify(commandObj));
		}else{
			return new Promise(function(resolve, reject) {
				self.client.sendMessage({
					to: channel,
					message: msg,
		 			typing: typing,
		      tts: tts
				}, function(err, resp) {
					if(err){
						reject(err);
					}else {
						resolve(resp);
					}
				});
			});
		}
	}
	SendEmbed(channel, embed){
		var self = this;
		self.client.sendMessage({
			to: channel,
			embed: embed
		});
	}
	SendCompactEmbed(channel, title, body, color=3447003) {
		var self = this;
		self.client.sendMessage({
			to: channel,
			embed: {
				color: color,
				author: {},
				fields: [{
					name: title,
					inline: false,
					value: body,
				}],
				footer: {}
			}
		});
	}
	SetStatus(status){
		var self = this;
		self.client.setPresence({game: {name: status}});
	}

	SetUsername(name){
		var self = this;
		self.client.editUserInfo({username: name});
	}

	JoinVoiceChannel(voiceID){
		var self = this;
		this.client.joinVoiceChannel(voiceID,function(err){
			if(err){
				console.log(err);
			}else{
			}
		})
	}

  LeaveVoiceChannel(voiceID){
		var self = this;
		this.client.leaveVoiceChannel(voiceID,function(err){
			if(err){
				console.log(err);
			}else{
			}
		})
	}
		JoinUsersVoiceChannel(serverID, userID){
		var user = this.GetUserByID(serverID, userID);
		if(!user){
			return;
		}
		this.JoinVoiceChannel(user.voice_channel_id);
	}
    LeaveUsersVoiceChannel(serverID, userID) {
    var user = this.GetUserByID(serverID, userID);
		if(!user){
			return;
		}
			this.LeaveVoiceChannel(user.voice_channel_id);
  }
		GetServerByID(id){
		var servers = this.client.servers;
		return servers[id];
	}
		GetUserByID(serverId, userId){
		var server = this.GetServerByID(serverId);
		if(!server){
			return;
		}
		return server.members[userId];
	}
		GetUserRoles(serverId, userId){
		var user = this.GetUserByID(serverId, userId);
		if(!user){
			return;
		}
		return user.roles;
	}

	GetRoleById(serverId, roleId){
		var server = this.GetServerByID(serverId);
		if(!server){
			return;
		}
		return server.roles[roleId];
	}
	GetBotInfo(){
		var self = this;
		return {
			username: self.client.username,
			id: self.client.id,
			avatar: self.client.avatar,
			bot: self.client.bot,
			discriminator: self.client.discriminator,
		}
	}
	GetUserInfo(UserID){
		var self = this;
		return self.client.users[userID];
	}
}

module.exports = Bot;
<|endoftext|>


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

    //Caches for current user to save trips to the backend.
    angular.module('brewApp.services')
        .factory('UserStore', ['$q', 'Auth', 'Factory', 'Configuration', 'Helper', 'ObjectMapper', 'Store', userStore]);

    function userStore($q, Auth, Factory, Configuration, Helper, ObjectMapper, Store) {
        var base = Store.prototype, fetch = {};

        function UserStore() {
            var self = this;

            Store.call(this);

            //Manage cache for authenticated user.  Is this really where we want to do this?
            Auth.onAuthenticate('UserStore', function() { self.cache = initCache(); });

            Auth.onSignOut('UserStore', function() { self.cache = null; });
        }

        UserStore.prototype = Object.create(base);

        UserStore.prototype.getCurrentUser = function() {
            //User hasn't logged in yet, so can't get current user info from backend.
            if (!Auth.isAuthenticated()) {
                var deferred = $q.defer();

                return (deferred.reject('User is not logged in.'), deferred.promise);
            }

            return fetch.currentUser || (fetch.currentUser = base.getCurrentUser(), fetch.currentUser);
        };

        UserStore.prototype.saveRecipe = function(recipe) {
            var self = this, deferred = $q.defer();

            if (!Auth.isAuthenticated())
                return (deferred.reject('User is not logged in.'), deferred.promise);

            base.saveRecipe.call(self, recipe).then(function(data) {
                var recipeId = +data.recipeId; //Convert to number just in case we get handed a string.

                if (self.cache) {
                    recipe.recipeId = recipeId;
                    recipe.added = true;

                    self.cache.recipes.add(recipeId, recipe);
                }

                deferred.resolve(recipeId);
            });

            return deferred.promise;
        };

        UserStore.prototype.updateRecipe = function(recipe) {
            if (!Auth.isAuthenticated())
                return (deferred.reject('User is not logged in.'), deferred.promise);

            if (this.cache) {
                //If we are handed in a copy of the original recipe, then we need to update the original to keep the cache consistent.
                //There must be a better way of doing this.
                var original = this.cache.recipes.findFirst(function(r) { return r.key === +recipe.recipeId; });

                if (original && original.value != null && original.value !== recipe)
                    Helper.mapObj(recipe, original.value);
            }

            return base.updateRecipe.call(self, recipe);
        };

        UserStore.prototype.deleteRecipe = function(recipeId) {
            var self = this, deferred = $q.defer();

            if (!Auth.isAuthenticated())
                return (deferred.reject('User is not logged in.'), deferred.promise);

            base.deleteRecipe.call(self, recipeId).then(function() {
                self.getCurrentUser().then(function(currentUser) {
                    if (self.cache) {
                        var removed = self.cache.recipes.remove(+recipeId); //Convert to number just in case we get handed a string.

                        //Will it cause confusion returning this only if user is cached?
                        deferred.resolve(removed);
                    }
                    else
                        deferred.resolve();
                });
            });

            return deferred.promise;
        };

        UserStore.prototype.getCurrentUserRecipes = function() {
            var self = this, deferred = $q.defer();

            if (!Auth.isAuthenticated())
                return (deferred.reject('User is not logged in.'), deferred.promise);

            //If we've already fetched user data, then just return from cached data.
            if (self.cache && self.cache.isFetched)
                deferred.resolve(self.cache.recipes.values());
            else
                base.getCurrentUserRecipes.call(self).then(function(data) {
                    if (self.cache) {
                        self.cache.recipes.import(data,
                            function (recipe) {
                                return +recipe.recipeId; //Convert to number just in case we get handed a string.
                            },
                            function (recipe) {
                                return ObjectMapper.map(recipe, ObjectMapper.BACKEND_ARTIFACT);
                            });

                        self.cache.isFetched = true;
                    }

                    deferred.resolve(data);
                });

            return deferred.promise;
        };

        UserStore.prototype.getCurrentUserRecipeById = function(recipeId) {
            var self = this, deferred = $q.defer(), recipe;

            if (!Auth.isAuthenticated())
                return (deferred.reject('User is not logged in.'), deferred.promise);

            recipeId = +recipeId; //Convert to number just in case we get handed a string.

            if (self.cache) {
                //Need to expand this to check if we have a cached copy and fetching otherwise.
                recipe = self.cache.recipes.findFirst(function(r) { return r.key === recipeId; });
                recipe = recipe == null ? recipe : recipe.value;

                if (recipe) return (deferred.resolve(recipe), deferred.promise);
            }

            base.getCurrentUserRecipeById.call(self, recipeId).then(function(data) {
                recipe = ObjectMapper.map(data, ObjectMapper.BACKEND_ARTIFACT);

                if (self.cache) self.cache.recipes.add(recipeId, recipe);

                deferred.resolve(recipe);
            });

            return deferred.promise;
        };

        function initCache() {
            return Configuration.currentUser.cacheRecipes ? {
                recipes: new Factory.Lookup(false),
                isFetched: false
            } : null;
        }

        //Return new instance and not constructor because we want the user store to be a singleton and only have one instance caching user data.
        return new UserStore();
    }
})();
<commit_msg>Removed call to get current user in delete.<commit_after>(function() {
    'use strict';

    //Caches for current user to save trips to the backend.
    angular.module('brewApp.services')
        .factory('UserStore', ['$q', 'Auth', 'Factory', 'Configuration', 'Helper', 'ObjectMapper', 'Store', userStore]);

    function userStore($q, Auth, Factory, Configuration, Helper, ObjectMapper, Store) {
        var base = Store.prototype, fetch = {};

        function UserStore() {
            var self = this;

            Store.call(this);

            //Manage cache for authenticated user.  Is this really where we want to do this?
            Auth.onAuthenticate('UserStore', function() { self.cache = initCache(); });

            Auth.onSignOut('UserStore', function() { self.cache = null; });
        }

        UserStore.prototype = Object.create(base);

        UserStore.prototype.getCurrentUser = function() {
            //User hasn't logged in yet, so can't get current user info from backend.
            if (!Auth.isAuthenticated()) {
                var deferred = $q.defer();

                return (deferred.reject('User is not logged in.'), deferred.promise);
            }

            return fetch.currentUser || (fetch.currentUser = base.getCurrentUser(), fetch.currentUser);
        };

        UserStore.prototype.saveRecipe = function(recipe) {
            var self = this, deferred = $q.defer();

            if (!Auth.isAuthenticated())
                return (deferred.reject('User is not logged in.'), deferred.promise);

            base.saveRecipe.call(self, recipe).then(function(data) {
                var recipeId = +data.recipeId; //Convert to number just in case we get handed a string.

                if (self.cache) {
                    recipe.recipeId = recipeId;
                    recipe.added = true;

                    self.cache.recipes.add(recipeId, recipe);
                }

                deferred.resolve(recipeId);
            });

            return deferred.promise;
        };

        UserStore.prototype.updateRecipe = function(recipe) {
            if (!Auth.isAuthenticated())
                return (deferred.reject('User is not logged in.'), deferred.promise);

            if (this.cache) {
                //If we are handed in a copy of the original recipe, then we need to update the original to keep the cache consistent.
                //There must be a better way of doing this.
                var original = this.cache.recipes.findFirst(function(r) { return r.key === +recipe.recipeId; });

                if (original && original.value != null && original.value !== recipe)
                    Helper.mapObj(recipe, original.value);
            }

            return base.updateRecipe.call(self, recipe);
        };

        UserStore.prototype.deleteRecipe = function(recipeId) {
            var self = this, deferred = $q.defer();

            if (!Auth.isAuthenticated())
                return (deferred.reject('User is not logged in.'), deferred.promise);

            base.deleteRecipe.call(self, recipeId).then(function() {
                if (self.cache) {
                    var removed = self.cache.recipes.remove(+recipeId); //Convert to number just in case we get handed a string.

                    //Will it cause confusion returning this only if user is cached?
                    deferred.resolve(removed);
                }
                else
                    deferred.resolve();
            });

            return deferred.promise;
        };

        UserStore.prototype.getCurrentUserRecipes = function() {
            var self = this, deferred = $q.defer();

            if (!Auth.isAuthenticated())
                return (deferred.reject('User is not logged in.'), deferred.promise);

            //If we've already fetched user data, then just return from cached data.
            if (self.cache && self.cache.isFetched)
                deferred.resolve(self.cache.recipes.values());
            else
                base.getCurrentUserRecipes.call(self).then(function(data) {
                    if (self.cache) {
                        self.cache.recipes.import(data,
                            function (recipe) {
                                return +recipe.recipeId; //Convert to number just in case we get handed a string.
                            },
                            function (recipe) {
                                return ObjectMapper.map(recipe, ObjectMapper.BACKEND_ARTIFACT);
                            });

                        self.cache.isFetched = true;
                    }

                    deferred.resolve(data);
                });

            return deferred.promise;
        };

        UserStore.prototype.getCurrentUserRecipeById = function(recipeId) {
            var self = this, deferred = $q.defer(), recipe;

            if (!Auth.isAuthenticated())
                return (deferred.reject('User is not logged in.'), deferred.promise);

            recipeId = +recipeId; //Convert to number just in case we get handed a string.

            if (self.cache) {
                //Need to expand this to check if we have a cached copy and fetching otherwise.
                recipe = self.cache.recipes.findFirst(function(r) { return r.key === recipeId; });
                recipe = recipe == null ? recipe : recipe.value;

                if (recipe) return (deferred.resolve(recipe), deferred.promise);
            }

            base.getCurrentUserRecipeById.call(self, recipeId).then(function(data) {
                recipe = ObjectMapper.map(data, ObjectMapper.BACKEND_ARTIFACT);

                if (self.cache) self.cache.recipes.add(recipeId, recipe);

                deferred.resolve(recipe);
            });

            return deferred.promise;
        };

        function initCache() {
            return Configuration.currentUser.cacheRecipes ? {
                recipes: new Factory.Lookup(false),
                isFetched: false
            } : null;
        }

        //Return new instance and not constructor because we want the user store to be a singleton and only have one instance caching user data.
        return new UserStore();
    }
})();
<|endoftext|>


<commit_before>{
	"translatorID":"ce7a3727-d184-407f-ac12-52837f3361ff",
	"translatorType":4,
	"label":"NYTimes.com",
	"creator":"Simon Kornblith",
	"target":"^https?://(?:query\\.nytimes\\.com/search/(?:alternate/)?)query|(?:select\\.|www\\.)?nytimes\\.com/.",
	"minVersion":"1.0.0b3.r1",
	"maxVersion":"",
	"priority":100,
	"inRepository":true,
	"lastUpdated":"2011-03-21 20:48:32"
}

function detectWeb(doc, url) {
	if(doc.title.substr(0, 30) == "The New York Times: Search for") {
		var namespace = doc.documentElement.namespaceURI;
		var nsResolver = namespace ? function(prefix) {
			if (prefix == 'x') return namespace; else return null;
		} : null;

		var result = doc.evaluate('//div[@id="srchContent"]', doc, nsResolver,
		             XPathResult.ANY_TYPE, null).iterateNext();
		if(result) {
			return "multiple";
		}
	} else {
		var metaTags = doc.getElementsByTagName("meta");
		if(metaTags.namedItem("hdl") && metaTags.namedItem("byl")) {
			return "newspaperArticle";
		}
	}
}

function associateMeta(newItem, metaTags, field, zoteroField) {
	if(metaTags[field]) {
		newItem[zoteroField] = metaTags[field];
	}
}

function scrape(doc, url) {
	var namespace = null;
	var nsResolver = namespace ? function(prefix) {
			if (prefix == 'x') return namespace; else return null;
	} : null;

	var newItem = new Zotero.Item("newspaperArticle");
	newItem.publicationTitle = "The New York Times";
	newItem.ISSN = "0362-4331";

	var metaTags = new Object();
	if(url != undefined) {
		newItem.url = url;
		var metaTagRe = /<meta[^>]*>/gi;
		var nameRe = /name="([^"]+)"/i;
		var contentRe = /content="([^"]+)"/i;
		var m = doc.match(metaTagRe);

		if(!m) {
			return;
		}

		for(var i=0; i<m.length; i++) {
			var name = nameRe.exec(m[i]);
			var content = contentRe.exec(m[i]);
			if(name && content) {
				metaTags[name[1]] = content[1];
			}
		}

		if(!metaTags["hdl"]) {
			return;
		}
		// We want to get everything on one page
		newItem.attachments.push({url:url.replace(/\.html\??([^/]*)(pagewanted=[^&]*)?([^/]*)$/,".html?pagewanted=all&$1$2"), title:"New York Times Snapshot",
	 	                          mimeType:"text/html"});
	} else {
		newItem.url = doc.location.href;
		var metaTagHTML = doc.getElementsByTagName("meta");
		for(var i=0; i<metaTagHTML.length; i++) {
			var key = metaTagHTML[i].getAttribute("name");
			var value = metaTagHTML[i].getAttribute("content");
			if(key && value) {
				metaTags[key] = value;
			}
		}
		// Get everything on one page is possible
		var singlePage = false;
		if (!newItem.url.match(/\?pagewanted=all/)
				&& (singlePage = doc.evaluate('//ul[@id="toolsList"]/li[@class="singlePage"]/a', doc, nsResolver,
		             XPathResult.ANY_TYPE, null).iterateNext())) {
			newItem.attachments.push({url:singlePage.href, title:"New York Times Snapshot",
	 		                          mimeType:"text/html"});
		} else {
			newItem.attachments.push({document:doc, title:"New York Times Snapshot"});
		}
	}

	associateMeta(newItem, metaTags, "dat", "date");
	associateMeta(newItem, metaTags, "hdl", "title");
	associateMeta(newItem, metaTags, "dsk", "section");
	associateMeta(newItem, metaTags, "articleid", "accessionNumber");

	if (metaTags["pdate"]) {
		newItem.date = metaTags["pdate"].replace(/(\d{4})(\d{2})(\d{2})/,"$1-$2-$3");
	}

	if(metaTags["byl"]) {
		var author = Zotero.Utilities.trimInternal(metaTags["byl"]);
		if(author.substr(0, 3).toLowerCase() == "by ") {
			author = author.substr(3);
		}

		var authors = author.split(" and ");
		for each(var author in authors) {
			// fix capitalization
			var words = author.split(" ");
			for(var i in words) {
				words[i] = words[i][0].toUpperCase()+words[i].substr(1).toLowerCase();
			}
			author = words.join(" ");

			if(words[0] == "The") {
				newItem.creators.push({lastName:author, creatorType:"author", fieldMode:true});
			} else {
				newItem.creators.push(Zotero.Utilities.cleanAuthor(author, "author"));
			}
		}
	}

	if(metaTags["keywords"]) {
		var keywords = metaTags["keywords"];
		newItem.tags = keywords.split(",");
		for(var i in newItem.tags) {
			newItem.tags[i] = newItem.tags[i].replace("  ", ", ");
		}
	}

	// Remove pagewanted from URL in item (keeping other pieces, in case they might matter)
	newItem.url = newItem.url.replace(/\?([^/]*)pagewanted=[^&]*/,'');

	newItem.complete();
}

function doWeb(doc, url) {
	if(doc.title.substr(0, 30) == "The New York Times: Search for") {
		var namespace = doc.documentElement.namespaceURI;
		var nsResolver = namespace ? function(prefix) {
			if (prefix == 'x') return namespace; else return null;
		} : null;

		var result = doc.evaluate('//div[@id="srchContent"]', doc, nsResolver,
		             XPathResult.ANY_TYPE, null).iterateNext();
		var items = Zotero.Utilities.getItemArray(doc, result, '^http://(?:select\.|www\.)nytimes.com/.*\.html(\\?|$)');
		items = Zotero.selectItems(items);

		if(!items) {
			return true;
		}

		var urls = new Array();
		for(var i in items) {
			urls.push(i);
		}

		Zotero.Utilities.HTTP.doGet(urls, function(text, response, url) { scrape(text, url) }, function() { Zotero.done(); }, null);

		Zotero.wait();
	} else {
		scrape(doc);
	}
}<commit_msg>correct fix for NYTimes regexp<commit_after>{
	"translatorID":"ce7a3727-d184-407f-ac12-52837f3361ff",
	"translatorType":4,
	"label":"NYTimes.com",
	"creator":"Simon Kornblith",
	"target":"^https?://(?:(?:query\\.nytimes\\.com/search/(?:alternate/)?)query|(?:select\\.|www\\.)?nytimes\\.com/.)",
	"minVersion":"1.0.0b3.r1",
	"maxVersion":"",
	"priority":100,
	"inRepository":true,
	"lastUpdated":"2011-03-21 20:48:32"
}

function detectWeb(doc, url) {
	if(doc.title.substr(0, 30) == "The New York Times: Search for") {
		var namespace = doc.documentElement.namespaceURI;
		var nsResolver = namespace ? function(prefix) {
			if (prefix == 'x') return namespace; else return null;
		} : null;

		var result = doc.evaluate('//div[@id="srchContent"]', doc, nsResolver,
		             XPathResult.ANY_TYPE, null).iterateNext();
		if(result) {
			return "multiple";
		}
	} else {
		var metaTags = doc.getElementsByTagName("meta");
		if(metaTags.namedItem("hdl") && metaTags.namedItem("byl")) {
			return "newspaperArticle";
		}
	}
}

function associateMeta(newItem, metaTags, field, zoteroField) {
	if(metaTags[field]) {
		newItem[zoteroField] = metaTags[field];
	}
}

function scrape(doc, url) {
	var namespace = null;
	var nsResolver = namespace ? function(prefix) {
			if (prefix == 'x') return namespace; else return null;
	} : null;

	var newItem = new Zotero.Item("newspaperArticle");
	newItem.publicationTitle = "The New York Times";
	newItem.ISSN = "0362-4331";

	var metaTags = new Object();
	if(url != undefined) {
		newItem.url = url;
		var metaTagRe = /<meta[^>]*>/gi;
		var nameRe = /name="([^"]+)"/i;
		var contentRe = /content="([^"]+)"/i;
		var m = doc.match(metaTagRe);

		if(!m) {
			return;
		}

		for(var i=0; i<m.length; i++) {
			var name = nameRe.exec(m[i]);
			var content = contentRe.exec(m[i]);
			if(name && content) {
				metaTags[name[1]] = content[1];
			}
		}

		if(!metaTags["hdl"]) {
			return;
		}
		// We want to get everything on one page
		newItem.attachments.push({url:url.replace(/\.html\??([^/]*)(pagewanted=[^&]*)?([^/]*)$/,".html?pagewanted=all&$1$2"), title:"New York Times Snapshot",
	 	                          mimeType:"text/html"});
	} else {
		newItem.url = doc.location.href;
		var metaTagHTML = doc.getElementsByTagName("meta");
		for(var i=0; i<metaTagHTML.length; i++) {
			var key = metaTagHTML[i].getAttribute("name");
			var value = metaTagHTML[i].getAttribute("content");
			if(key && value) {
				metaTags[key] = value;
			}
		}
		// Get everything on one page is possible
		var singlePage = false;
		if (!newItem.url.match(/\?pagewanted=all/)
				&& (singlePage = doc.evaluate('//ul[@id="toolsList"]/li[@class="singlePage"]/a', doc, nsResolver,
		             XPathResult.ANY_TYPE, null).iterateNext())) {
			newItem.attachments.push({url:singlePage.href, title:"New York Times Snapshot",
	 		                          mimeType:"text/html"});
		} else {
			newItem.attachments.push({document:doc, title:"New York Times Snapshot"});
		}
	}

	associateMeta(newItem, metaTags, "dat", "date");
	associateMeta(newItem, metaTags, "hdl", "title");
	associateMeta(newItem, metaTags, "dsk", "section");
	associateMeta(newItem, metaTags, "articleid", "accessionNumber");

	if (metaTags["pdate"]) {
		newItem.date = metaTags["pdate"].replace(/(\d{4})(\d{2})(\d{2})/,"$1-$2-$3");
	}

	if(metaTags["byl"]) {
		var author = Zotero.Utilities.trimInternal(metaTags["byl"]);
		if(author.substr(0, 3).toLowerCase() == "by ") {
			author = author.substr(3);
		}

		var authors = author.split(" and ");
		for each(var author in authors) {
			// fix capitalization
			var words = author.split(" ");
			for(var i in words) {
				words[i] = words[i][0].toUpperCase()+words[i].substr(1).toLowerCase();
			}
			author = words.join(" ");

			if(words[0] == "The") {
				newItem.creators.push({lastName:author, creatorType:"author", fieldMode:true});
			} else {
				newItem.creators.push(Zotero.Utilities.cleanAuthor(author, "author"));
			}
		}
	}

	if(metaTags["keywords"]) {
		var keywords = metaTags["keywords"];
		newItem.tags = keywords.split(",");
		for(var i in newItem.tags) {
			newItem.tags[i] = newItem.tags[i].replace("  ", ", ");
		}
	}

	// Remove pagewanted from URL in item (keeping other pieces, in case they might matter)
	newItem.url = newItem.url.replace(/\?([^/]*)pagewanted=[^&]*/,'');

	newItem.complete();
}

function doWeb(doc, url) {
	if(doc.title.substr(0, 30) == "The New York Times: Search for") {
		var namespace = doc.documentElement.namespaceURI;
		var nsResolver = namespace ? function(prefix) {
			if (prefix == 'x') return namespace; else return null;
		} : null;

		var result = doc.evaluate('//div[@id="srchContent"]', doc, nsResolver,
		             XPathResult.ANY_TYPE, null).iterateNext();
		var items = Zotero.Utilities.getItemArray(doc, result, '^http://(?:select\.|www\.)nytimes.com/.*\.html(\\?|$)');
		items = Zotero.selectItems(items);

		if(!items) {
			return true;
		}

		var urls = new Array();
		for(var i in items) {
			urls.push(i);
		}

		Zotero.Utilities.HTTP.doGet(urls, function(text, response, url) { scrape(text, url) }, function() { Zotero.done(); }, null);

		Zotero.wait();
	} else {
		scrape(doc);
	}
}<|endoftext|>