/** * Created by strawmanbobi * 2016-11-27 */ // system inclusion fs = require('fs'); let crypto = require('crypto'); // global inclusion require('../mini_poem/configuration/constants'); let orm = require('orm'); let AdminAuth = require('../authentication/admin_auth.js'); let PythonCaller = require('../mini_poem/external/python_caller'); let Category = require('../model/category_dao.js'); let Brand = require('../model/brand_dao.js'); let IRProtocol = require('../model/ir_protocol_dao.js'); let City = require('../model/city_dao.js'); let RemoteIndex = require('../model/remote_index_dao.js'); let StbOperator = require('../model/stb_operator_dao.js'); let CollectRemote = require('../model/collect_remote_dao.js'); let RequestSender = require('../mini_poem/http/request.js'); let Map = require('../mini_poem/mem/map.js'); let Enums = require('../constants/enums.js'); let ErrorCode = require('../constants/error_code.js'); let Categories = require('../constants/remote_categories'); let logger = require('../mini_poem/logging/logger4js').helper; let async = require('async'); let enums = new Enums(); let errorCode = new ErrorCode(); let adminAuth = new AdminAuth(REDIS_HOST, REDIS_PORT, null, REDIS_PASSWORD); // relative XML file path let PROTOCOL_PATH = "protocol"; let contributeProtocolService = "/irext-server/contribution/contribute_protocol"; let contributeBrandsService = "/irext-server/contribution/contribute_brands"; let contributeRemoteIndexesService = "/irext-server/contribution/contribute_remote_indexes"; let createRemoteRefService = "/irext-server/remote_ref/create_remote_ref"; exports.listCategoriesWorkUnit = function (lang, from, count, callback) { let conditions = { status: enums.ITEM_VALID }; let language = "en-US"; if (undefined !== lang && null !== lang && -1 !== lang.indexOf("zh-CN")) { language = "zh-CN"; } Category.listRemoteCategories(conditions, from, count, "id", function (listCategoriesErr, categories) { if (language === "en-US" && listCategoriesErr.code === errorCode.SUCCESS.code && null !== categories) { // cover field 'name' with 'name_en' for (let i = 0; i < categories.length; i++) { if (parseInt(categories[i].id) === enums.CATEGORY_STB) { categories.splice(i, 1); i--; continue; } categories[i].name = categories[i].name_en; } } callback(listCategoriesErr, categories); }); }; exports.listBrandsWorkUnit = function (lang, categoryID, from, count, callback) { let conditions = { status: orm.gt(parseInt(enums.ITEM_INVALID)), category_id: categoryID }; let language = "en-US"; if (undefined !== lang && null !== lang && -1 !== lang.indexOf("zh-CN")) { language = "zh-CN"; } Brand.listBrands(conditions, from, count, "priority", function (listBrandsErr, brands) { if (language === "en-US" && listBrandsErr.code === errorCode.SUCCESS.code && null !== brands) { // cover field 'name' with 'name_en' for (let i = 0; i < brands.length; i++) { brands[i].name = brands[i].name_en; } } callback(listBrandsErr, brands); }); }; exports.listUnpublishedBrandsWorkUnit = function (callback) { let conditions = { status: enums.ITEM_VERIFY }; Brand.listBrands(conditions, 0, 100, "priority", function (getBrandByIDErr, brands) { callback(getBrandByIDErr, brands); }); }; exports.listProvincesWorkUnit = function (lang, callback) { let language = "en-US"; if (undefined !== lang && null !== lang && -1 !== lang.indexOf("zh-CN")) { language = "zh-CN"; } City.listProvinces(function (listProvincesErr, provinces) { if (language !== "zh-CN") { provinces = []; } callback(listProvincesErr, provinces); }); }; exports.listCitiesWorkUnit = function (lang, provincePrefix, callback) { let language = "en-US"; if (undefined !== lang && null !== lang && -1 !== lang.indexOf("zh-CN")) { language = "zh-CN"; } City.listCities(provincePrefix, function (listCitiesErr, cities) { if (language !== "zh-CN") { cities = []; } callback(listCitiesErr, cities); }); }; exports.listOperatorsWorkUnit = function (lang, cityCode, from, count, callback) { let language = "en-US"; if (undefined !== lang && null !== lang && -1 !== lang.indexOf("zh-CN")) { language = "zh-CN"; } let conditions = { city_code: cityCode, status: enums.ITEM_VALID }; StbOperator.listStbOperators(conditions, from, count, "id", function (listOperatorsErr, operators) { if (language !== "zh-CN") { operators = []; } callback(listOperatorsErr, operators); }); }; exports.listRemoteIndexesWorkUnit = function (lang, categoryID, brandID, cityCode, operatorID, from, count, callback) { let language = "en-US"; let categoryNameEn = ""; let brandNameEn = ""; let conditions; let listCollectRemotesConditions; if (undefined !== lang && null !== lang && -1 !== lang.indexOf("zh-CN")) { language = "zh-CN"; } Category.getCategoryByID(categoryID, function(getCategoryByIDErr, category) { if (null != category) { categoryNameEn = category.name_en; if (parseInt(categoryID) === enums.CATEGORY_AC || parseInt(categoryID) === enums.CATEGORY_TV || parseInt(categoryID) === enums.CATEGORY_NW || parseInt(categoryID) === enums.CATEGORY_IPTV || parseInt(categoryID) === enums.CATEGORY_DVD || parseInt(categoryID) === enums.CATEGORY_FAN || parseInt(categoryID) === enums.CATEGORY_PROJECTOR || parseInt(categoryID) === enums.CATEGORY_STEREO || parseInt(categoryID) === enums.CATEGORY_LIGHT_BULB || parseInt(categoryID) === enums.CATEGORY_BSTB || parseInt(categoryID) === enums.CATEGORY_CLEANING_ROBOT || parseInt(categoryID) === enums.CATEGORY_AIR_CLEANER || parseInt(categoryID) === enums.CATEGORY_DYSON) { Brand.getBrandByID(brandID, function (getBrandByIDErr, brand) { if (null != brand) { brandNameEn = brand.name_en; conditions = { category_id: categoryID, brand_id: brandID, status: orm.gt(enums.ITEM_INVALID) }; RemoteIndex.listRemoteIndexes(conditions, from, count, "priority", function(listRemoteIndexesErr, remoteIndexes) { if (listRemoteIndexesErr.code === errorCode.SUCCESS.code && null !== remoteIndexes) { for (let i = 0; i < remoteIndexes.length; i++) { if (language === "en-US") { // cover field 'name' with 'name_en' remoteIndexes[i].category_name = categoryNameEn; remoteIndexes[i].brand_name = brandNameEn; } remoteIndexes[i].para = 0; } } // append IRIS indexes listCollectRemotesConditions = { category_id: parseInt(categoryID), brand_id: parseInt(brandID), status: parseInt(enums.COLLECT_REMOTE_STATUS_CONFIRMED) } CollectRemote.listCollectRemotes(listCollectRemotesConditions, from, count, "update_time", function(listCollectRemotesErr, collectRemotes) { if (null != collectRemotes && collectRemotes.length > 0) { for (let i = 0; i < collectRemotes.length; i++) { collectRemotes[i].para = 1; } } remoteIndexes.push.apply(remoteIndexes, collectRemotes); callback(listRemoteIndexesErr, remoteIndexes); }); }); } else { logger.error("brand is invalid : " + brandID); callback(errorCode.INVALID_BRAND, null); } }); } else if (parseInt(categoryID) === enums.CATEGORY_STB) { if (!operatorID) { conditions = { category_id: categoryID, city_code: cityCode, status: orm.gt(enums.ITEM_INVALID) }; } else { conditions = { category_id: categoryID, city_code: cityCode, operator_id: operatorID, status: orm.gt(enums.ITEM_INVALID) }; } RemoteIndex.listRemoteIndexes(conditions, from, count, "priority", function(listRemoteIndexesErr, remoteIndexes) { for (let i = 0; i < remoteIndexes.length; i++) { if (language === "en-US") { // cover field 'name' with 'name_en' remoteIndexes[i].category_name = categoryNameEn; remoteIndexes[i].brand_name = brandNameEn; } remoteIndexes[i].para = 0; } // append IRIS indexes if (!operatorID) { listCollectRemotesConditions = { category_id: parseInt(categoryID), city_code: cityCode, status: parseInt(enums.COLLECT_REMOTE_STATUS_CONFIRMED) }; } else { listCollectRemotesConditions = { category_id: parseInt(categoryID), city_code: cityCode, operator_id: operatorID, status: parseInt(enums.COLLECT_REMOTE_STATUS_CONFIRMED) }; } CollectRemote.listCollectRemotes(listCollectRemotesConditions, from, count, "update_time", function(listCollectRemotesErr, collectRemotes) { if (null != collectRemotes && collectRemotes.length > 0) { for (let i = 0; i < collectRemotes.length; i++) { collectRemotes[i].para = 0; } } remoteIndexes.push.apply(remoteIndexes, collectRemotes); callback(listRemoteIndexesErr, remoteIndexes); }); }); } else { callback(errorCode.INVALID_CATEGORY, null); } } else { callback(errorCode.INVALID_CATEGORY, null); } }); }; exports.searchRemoteIndexesWorkUnit = function (lang, remoteMap, from, count, callback) { let language = "en-US"; if (undefined !== lang && null !== lang && -1 !== lang.indexOf("zh-CN")) { language = "zh-CN"; } let remoteIndexCollection = []; let conditions = { remote_map: orm.like("%" + remoteMap + "%") }; RemoteIndex.listRemoteIndexes(conditions, from, count, "priority", function(listRemoteIndexesErr, remoteIndexes) { if (language === "en-US") { async.eachSeries(remoteIndexes, function (remoteIndex, innerCallback) { // handle i18n for en-US let categoryID = remoteIndex.category_id; Category.getCategoryByID(categoryID, function(getCategoryErr, category) { if (errorCode.SUCCESS.code === getCategoryErr.code && null != category) { if (parseInt(categoryID) === enums.CATEGORY_AC || parseInt(categoryID) === enums.CATEGORY_TV || parseInt(categoryID) === enums.CATEGORY_NW || parseInt(categoryID) === enums.CATEGORY_IPTV || parseInt(categoryID) === enums.CATEGORY_DVD || parseInt(categoryID) === enums.CATEGORY_FAN || parseInt(categoryID) === enums.CATEGORY_PROJECTOR || parseInt(categoryID) === enums.CATEGORY_STEREO || parseInt(categoryID) === enums.CATEGORY_LIGHT_BULB || parseInt(categoryID) === enums.CATEGORY_BSTB || parseInt(categoryID) === enums.CATEGORY_CLEANING_ROBOT || parseInt(categoryID) === enums.CATEGORY_AIR_CLEANER || parseInt(categoryID) === enums.CATEGORY_DYSON) { remoteIndex.category_name = category.name_en; let brandID = remoteIndex.brand_id; Brand.getBrandByID(brandID, function(getBrandErr, brand) { if (errorCode.SUCCESS.code === getBrandErr.code && null != brand) { remoteIndex.brand_name = brand.name_en; remoteIndexCollection.push(remoteIndex); innerCallback(); } else { remoteIndexCollection.push(remoteIndex); innerCallback(); } }); } else if (parseInt(categoryID) === enums.CATEGORY_STB) { // do not add STB in en-US language case } } else { innerCallback(); } }); }, function (err) { callback(listRemoteIndexesErr, remoteIndexCollection); }); } else { callback(listRemoteIndexesErr, remoteIndexes); } }); }; exports.downloadRemoteBinCachedWorkUnit = function (adminId, token, remoteIndexID, callback) { RemoteIndex.getRemoteIndexByID(remoteIndexID, function (getRemoteIndexErr, remoteIndex) { if (errorCode.SUCCESS.code === getRemoteIndexErr.code && null != remoteIndex) { let fileName = "irda_" + remoteIndex.protocol + "_" + remoteIndex.remote + ".bin"; let localBinFileName = FILE_TEMP_PATH + "/" + fileName; let error = errorCode.SUCCESS; fs.exists(localBinFileName, function (exists) { if (exists) { logger.info("file " + localBinFileName + " already exists, serve directly"); // create remote reference of this remote index let categoryId = 0; let categoryName = ''; let brandId = 0; let brandName = ''; let name = ''; let remoteRef = null; RemoteIndex.getRemoteIndexByID(remoteIndexID, function (getRemoteIndexErr, remoteIndex) { if (errorCode.SUCCESS.code === getRemoteIndexErr.code) { categoryId = remoteIndex.category_id; brandId = remoteIndex.brand_id; Category.getCategoryByID(categoryId, function (getCategoryErr, category) { if (errorCode.SUCCESS.code === getCategoryErr.code) { categoryName = category.name; if (enums.CATEGORY_STB !== categoryId) { Brand.getBrandByID(brandId, function (getBrandErr, brand) { if (errorCode.SUCCESS.code === getBrandErr.code) { brandName = brand.name; name = brandName + categoryName; remoteRef = { "name": name, "categoryId": categoryId, "categoryName": categoryName, "brandId": brandId, "brandName": brandName, "cityCode": "", "operatorId": 0, "remoteCode": "", "subCate": remoteIndex.sub_cate, "protocol": remoteIndex.protocol, "remote": remoteIndex.remote, "remoteMap": remoteIndex.remote_map, } let queryParams = new Map(); let requestSender = new RequestSender(EXTERNAL_SERVER_ADDRESS, EXTERNAL_SERVER_PORT, createRemoteRefService, queryParams); let createRemoteRefRequest = { "id": adminId, "token": token, "remoteRef": remoteRef, }; requestSender.sendPostRequest(createRemoteRefRequest, function (createRemoteRefErr, createRemoteRefResponse) { logger.info(createRemoteRefErr); }); } }); } else { name = categoryName + "-" + remoteIndex.city_code + "-" + remoteIndex.operator_id; remoteRef = { "name": name, "categoryId": categoryId, "categoryName": categoryName, "brandId": 0, "brandName": "", "cityCode": remoteIndex.city_code, "operatorId": remoteIndex.operator_id, "remoteCode": "", "subCate": remoteIndex.sub_cate, "protocol": remoteIndex.protocol, "remote": remoteIndex.remote, "remoteMap": remoteIndex.remote_map, } let queryParams = new Map(); let requestSender = new RequestSender(EXTERNAL_SERVER_ADDRESS, EXTERNAL_SERVER_PORT, createRemoteRefService, queryParams); let createRemoteRefRequest = { "id": adminId, "token": token, "remoteRef": remoteRef, }; requestSender.sendPostRequest(createRemoteRefRequest, function (createRemoteRefErr, createRemoteRefResponse) { logger.info(createRemoteRefErr); }); } } }); } }); callback(error, localBinFileName); } else { logger.info("file " + localBinFileName + " does not exist"); error = errorCode.FAILED; callback(error, null); } }); } else { logger.error("no valid remote index found by ID " + remoteIndexID); callback(errorCode.FAILED, null); } }); }; exports.listUnpublishedRemoteIndexesWorkUnit = function (callback) { let conditions = { status: enums.ITEM_PASS }; RemoteIndex.listRemoteIndexes(conditions, 0, 1000, "priority", function (listRemoteIndexesErr, remoteIndexes) { callback(listRemoteIndexesErr, remoteIndexes); }); }; exports.listIRProtocolsWorkUnit = function (from, count, callback) { let conditions = { status: orm.gt(enums.ITEM_INVALID) }; IRProtocol.listIRProtocols(conditions, from, count, "name", function (listIRProtocolsErr, IRProtocols) { callback(listIRProtocolsErr, IRProtocols); }); }; exports.createRemoteIndexWorkUnit = function (remoteIndex, filePath, contentType, adminID, callback) { ////////////////////////////////////// // step 1, rename input remote xml file let find = '\\\\'; let re = new RegExp(find, 'g'); let unixFilePath = filePath.replace(re, '/'); let lios = unixFilePath.lastIndexOf('/'); let fileDir = unixFilePath.substring(0, lios); let subCate = remoteIndex.sub_cate; let categoryID = remoteIndex.category_id; let remoteDir = ""; let remoteXMLFilePath; let remoteBinFilePath; let protocolPath; let outputPath; let outputFilePath; let newRemoteIndex; let newACRemoteNumber; let tagType; let contributor = ""; let protocolFileName = ""; let localProtocolFileName = ""; let pythonRuntimeDir = null, pythonFile = null, userArgs = []; // verify admin let key = "admin_name_" + adminID; adminAuth.getAuthInfo(key, function (getAdminAuthErr, result) { if (errorCode.SUCCESS.code === getAdminAuthErr.code && null != result) { contributor = result; // begin creating remote index switch (parseInt(categoryID)) { case enums.CATEGORY_AC: pythonFile = "ir_status_encode.py"; break; case enums.CATEGORY_TV: case enums.CATEGORY_STB: case enums.CATEGORY_NW: case enums.CATEGORY_IPTV: case enums.CATEGORY_DVD: case enums.CATEGORY_FAN: case enums.CATEGORY_PROJECTOR: case enums.CATEGORY_STEREO: case enums.CATEGORY_LIGHT_BULB: case enums.CATEGORY_BSTB: case enums.CATEGORY_CLEANING_ROBOT: case enums.CATEGORY_AIR_CLEANER: case enums.CATEGORY_DYSON: pythonFile = "ir_command_encode.py"; break; default: logger.error("no remote category found!!"); callback(errorCode.FAILED, null); break; } logger.info("encoding python file = " + pythonFile); // process xml source file and source remote indexes if (parseInt(categoryID) === enums.CATEGORY_AC) { // TAG FORMAT encode tagType = "new_ac"; remoteXMLFilePath = fileDir + "/" + remoteIndex.remote_name + ".xml"; // logger.info("remote XML file path = " + remoteXMLFilePath); ////////////////////////////////////// // step 2, parse python run-time path, AC python file name and user arguments pythonRuntimeDir = fileDir + "/" + remoteDir; userArgs.length = 0; // python s_$category.py [remote_xml_file_abs_file] [remote_xml_file_name] [remote_xml_dir_abs_path] userArgs.push(remoteXMLFilePath); // set the xml directory as output path userArgs.push(fileDir + "/"); pythonCaller = new PythonCaller(); try { pythonCaller.call(pythonRuntimeDir, pythonFile, userArgs, function (remoteGenErr, genResult) { if (errorCode.SUCCESS.code === remoteGenErr) { ////////////////////////////////////// // step 3, if successfully created tag binary file, upload binary logger.info("remote " + remoteIndex.remote_name + " has successfully been generated"); outputPath = fileDir; newACRemoteNumber = remoteIndex.remote_name .substring(remoteIndex.remote_name.lastIndexOf('_') + 1); outputFilePath = outputPath + "/irda_" + tagType + "_" + newACRemoteNumber + ".bin"; logger.info("final tag binary output file = " + outputFilePath); fs.readFile(outputFilePath, function (readFileErr, fileData) { if (readFileErr) { logger.error("read remote code binary file error : " + readFileErr); callback(errorCode.FAILED, null); } else { logger.info("read remote binary file successfully, file size = " + fileData.length); ////////////////////////////////////// // step 3.5, check if this remote index is already // contained in remote index list by binary let fileHash = checksum(fileData); logger.info("hash of binary file = " + fileHash); let conditions = { category_id: remoteIndex.category_id, brand_id: remoteIndex.brand_id, binary_md5: fileHash }; RemoteIndex.findRemoteIndexByCondition(conditions, function (findRemoteIndexesErr, remoteIndexes) { if (errorCode.SUCCESS.code === findRemoteIndexesErr.code && null != remoteIndexes && remoteIndexes.length > 0) { logger.info("this remote is duplicated by binary value"); callback(errorCode.DUPLICATED_REMOTE_CODE, null); } else { // step 4, create remote index record in db remoteIndex.remote_name = newACRemoteNumber + ""; newRemoteIndex = { category_id: remoteIndex.category_id, category_name: remoteIndex.category_name, brand_id: remoteIndex.brand_id, brand_name: remoteIndex.brand_name, protocol: tagType, remote: remoteIndex.remote_name, remote_map: tagType + "_" + newACRemoteNumber, priority: remoteIndex.priority, sub_cate: subCate, remote_number: remoteIndex.remote_number, category_name_tw: remoteIndex.category_name_tw, brand_name_tw: remoteIndex.brand_name_tw, binary_md5: fileHash, contributor: contributor }; // see if this remote index is already in database let conditions = { //category_id: remoteIndex.category_id, //brand_id: remoteIndex.brand_id, protocol: tagType, remote: remoteIndex.remote_name, status: orm.gt(enums.ITEM_INVALID) }; RemoteIndex.findRemoteIndexByCondition(conditions, function (findRemoteIndexErr, remoteIndexes) { if (errorCode.SUCCESS.code === findRemoteIndexErr.code && remoteIndexes && remoteIndexes.length > 0) { logger.info("remote index already exists"); callback(errorCode.FAILED, null); } else { RemoteIndex.createRemoteIndex(newRemoteIndex, function (createRemoteIndexErr, createdRemoteIndex) { callback(createRemoteIndexErr, createdRemoteIndex); }); } }); } }); } }); } else { logger.info("remote " + remoteIndex.remote_name + " generating failed"); callback(errorCode.FAILED, null); } }); } catch (exception) { logger.error('failed to execute python script from application'); callback(errorCode.FAILED, null); } } else { // P-R FORMAT encode ////////////////////////////////////// // step 1.5, download specified protocol binary from local file storage protocolPath = fileDir + "/" + PROTOCOL_PATH + "/"; protocolFileName = remoteIndex.protocol_name + ".bin"; localProtocolFileName = protocolPath + remoteIndex.protocol_name + ".bin"; logger.info("protocol binary fetched from file storage, continue processing with remote file"); remoteXMLFilePath = fileDir + "/" + remoteIndex.remote_name + ".xml"; logger.info("remote XML file path = " + remoteXMLFilePath); ////////////////////////////////////// // step 2, parse python run-time path, python file name and user arguments pythonRuntimeDir = fileDir + "/" + remoteDir; userArgs.length = 0; // python s_$category.py [remote_xml_file_abs_file] [remote_xml_file_name] [remote_xml_dir_abs_path] userArgs.push(remoteXMLFilePath); userArgs.push(remoteIndex.remote_name + ".xml"); userArgs.push(fileDir + "/"); userArgs.push(categoryID); ////////////////////////////////////// // step 3, try executing remote encoding script let pythonCaller = new PythonCaller(); try { pythonCaller.call(pythonRuntimeDir, pythonFile, userArgs, function (remoteGenErr, genResult) { if (errorCode.SUCCESS.code === remoteGenErr) { ////////////////////////////////////// // step 4, try executing merge script logger.info("remote " + remoteIndex.remote_name + " has successfully been generated." + " continue merging with protocol"); pythonFile = "ir_command_merge.py"; outputPath = fileDir; remoteBinFilePath = fileDir + "/" + remoteDir + remoteIndex.protocol_name + "#" + remoteIndex.remote_name + ".bin"; userArgs.length = 0; // python ir_command_merge.py [protocol_dir_abs_path] // [remote_bin_file_abs_path] [output_$category_dir_abs_path] logger.info("protocol path = " + protocolPath + ", remote bin path = " + remoteBinFilePath + ", output = " + outputPath); userArgs.push(protocolPath); userArgs.push(remoteBinFilePath); userArgs.push(outputPath); pythonCaller.call(pythonRuntimeDir, pythonFile, userArgs, function (remoteMergeErr, mergeResult) { logger.info("merge protocol error = " + remoteMergeErr); if (errorCode.SUCCESS.code === remoteMergeErr) { outputFilePath = outputPath + "/irda_" + remoteIndex.protocol_name + "_" + remoteIndex.remote_name + ".bin"; logger.info("final output file = " + outputFilePath); fs.readFile(outputFilePath, function (readFileErr, fileData) { if (readFileErr) { logger.error("read remote code binary file error : " + readFileErr); callback(errorCode.FAILED, null); } else { logger.info("read remote binary file successfully, " + "file size = " + fileData.length); ////////////////////////////////////// // step 5, check if this remote index is already contained in remote index // list by binary let fileHash = checksum(fileData); logger.info("hash of binary file = " + fileHash); let conditions = null; if (enums.CATEGORY_STB === remoteIndex.category_id) { conditions = { category_id: remoteIndex.category_id, city_code: remoteIndex.city_code, binary_md5: fileHash }; } else { conditions = { category_id: remoteIndex.category_id, brand_id: remoteIndex.brand_id, binary_md5: fileHash }; } RemoteIndex.findRemoteIndexByCondition(conditions, function (findRemoteIndexesErr, remoteIndexes) { if (errorCode.SUCCESS.code === findRemoteIndexesErr.code && null != remoteIndexes && remoteIndexes.length > 0) { logger.info("this remote is duplicated by binary value"); callback(errorCode.DUPLICATED_REMOTE_CODE, null); } else { ////////////////////////////////////// // step 6, create remote index record in db if (remoteIndex.category_id === enums.CATEGORY_STB) { newRemoteIndex = { category_id: remoteIndex.category_id, category_name: remoteIndex.category_name, city_code: remoteIndex.city_code, city_name: remoteIndex.city_name, operator_id: remoteIndex.operator_id, operator_name: remoteIndex.operator_name, protocol: remoteIndex.protocol_name, remote: remoteIndex.remote_name, remote_map: remoteIndex.protocol_name + '_' + remoteIndex.remote_name, priority: remoteIndex.priority, sub_cate: subCate, remote_number: remoteIndex.remote_number, city_name_tw: remoteIndex.city_name_tw, operator_name_tw: remoteIndex.operator_name_tw, binary_md5: fileHash, contributor: contributor } } else { newRemoteIndex = { category_id: remoteIndex.category_id, category_name: remoteIndex.category_name, brand_id: remoteIndex.brand_id, brand_name: remoteIndex.brand_name, protocol: remoteIndex.protocol_name, remote: remoteIndex.remote_name, remote_map: remoteIndex.protocol_name + '_' + remoteIndex.remote_name, priority: remoteIndex.priority, sub_cate: subCate, remote_number: remoteIndex.remote_number, category_name_tw: remoteIndex.category_name_tw, brand_name_tw: remoteIndex.brand_name_tw, binary_md5: fileHash, contributor: contributor } } // see if this remote index is already in database let conditions = { // category_id: remoteIndex.category_id, // brand_id: remoteIndex.brand_id, protocol: remoteIndex.protocol_name, remote: remoteIndex.remote_name, status: orm.gt(enums.ITEM_INVALID) }; RemoteIndex.findRemoteIndexByCondition(conditions, function (findRemoteIndexErr, remoteIndexes) { if (errorCode.SUCCESS.code === findRemoteIndexErr.code && remoteIndexes && remoteIndexes.length > 0) { logger.info("remote index already exists"); callback(errorCode.FAILED, null); } else { RemoteIndex.createRemoteIndex(newRemoteIndex, function (createRemoteIndexErr, createdRemoteIndex) { callback(createRemoteIndexErr, createdRemoteIndex); }); } }); } }); } }); } else { callback(errorCode.FAILED, null); } }); } else { callback(errorCode.FAILED, null); } }); } catch (exception) { logger.error('failed to execute python script from application'); callback(errorCode.FAILED, null); } } } else { logger.info("invalid admin ID, return directly"); callback(errorCode.FAILED, null); } }); }; exports.deleteRemoteIndexWorkUnit = function (remoteIndex, adminID, callback) { let key = "admin_name_" + adminID; adminAuth.getAuthInfo(key, function (getAdminAuthErr, result) { if (errorCode.SUCCESS.code === getAdminAuthErr.code && null != result) { if (remoteIndex.contributor.indexOf(result) === -1) { callback(errorCode.FAILED); } else { remoteIndex.status = enums.ITEM_INVALID; RemoteIndex.updateRemoteIndex(remoteIndex.id, remoteIndex, function (deleteRemoteIndexErr, updatedRemoteIndex) { callback(deleteRemoteIndexErr); }); } } else { callback(errorCode.FAILED); } }); }; exports.verifyRemoteIndexWorkUnit = function (remoteIndex, pass, adminID, callback) { let key = "admin_name_" + adminID; adminAuth.getAuthInfo(key, function (getAdminAuthErr, result) { if (errorCode.SUCCESS.code === getAdminAuthErr.code && null != result) { if (remoteIndex.contributor.indexOf(result) === -1) { logger.info("the admin " + result + " could not change this remote index"); callback(errorCode.FAILED); return; } let status = (true === pass || 'true' === pass) ? enums.ITEM_PASS : enums.ITEM_FAILED; RemoteIndex.verifyRemoteIndex(remoteIndex.id, status, function (updateRemoteIndexErr) { callback(updateRemoteIndexErr); }); } else { callback(errorCode.FAILED); } }); }; exports.fallbackRemoteIndexWorkUnit = function (remoteIndex, adminID, callback) { let key = "admin_name_" + adminID; adminAuth.getAuthInfo(key, function (getAdminAuthErr, result) { if (errorCode.SUCCESS.code === getAdminAuthErr.code && null != result) { if (remoteIndex.contributor.indexOf(result) === -1) { logger.info("the admin " + result + " could not change this remote index"); callback(errorCode.FAILED); return; } let status = enums.ITEM_VERIFY; RemoteIndex.fallbackRemoteIndex(remoteIndex.id, status, function (updateRemoteIndexErr) { callback(updateRemoteIndexErr); }); } else { callback(errorCode.FAILED); } }); }; exports.publishRemoteIndexWorkUnit = function (callback) { callback(errorCode.SUCCESS); }; exports.createBrandWorkUnit = function (brand, adminID, callback) { let conditions = { category_id: brand.category_id, name: brand.name, status: enums.ITEM_VERIFY }; let key = "admin_name_" + adminID; adminAuth.getAuthInfo(key, function (getAdminAuthErr, result) { if (getAdminAuthErr.code === errorCode.SUCCESS.code && null != result) { brand.contributor = result; Brand.findBrandByConditions(conditions, function (findBrandErr, brands) { if (errorCode.SUCCESS.code === findBrandErr.code && null != brands && brands.length > 0) { logger.info("brand already exists"); callback(errorCode.SUCCESS); } else { Brand.createBrand(brand, function (createBrandErr, createdBrand) { callback(createBrandErr, createdBrand); }); } }); } else { callback(errorCode.FAILED, null); } }); }; exports.publishBrandsWorkUnit = function (adminID, callback) { let conditions = null; let key = "admin_name_" + adminID; adminAuth.getAuthInfo(key, function (getAdminAuthErr, result) { if (getAdminAuthErr.code === errorCode.SUCCESS.code && null != result) { conditions = { status: enums.ITEM_VERIFY }; Brand.findBrandByConditions(conditions, function (findBrandErr, brands) { if (errorCode.SUCCESS.code === findBrandErr.code && null !== brands && brands.length > 0) { logger.info("unpublished brand list has been found"); async.eachSeries(brands, function (brand, innerCallback) { brand.status = enums.ITEM_VALID; Brand.updateBrandByID(brand.id, brand, function (updateBrandErr, updatedBrand) { innerCallback(); }); }, function (err) { // send HTTP request to IRext main server let queryParams = new Map(); let requestSender = new RequestSender(EXTERNAL_SERVER_ADDRESS, EXTERNAL_SERVER_PORT, contributeBrandsService, queryParams); for (let i = 0; i < brands.length; i++) { brands[i].status = enums.ITEM_VERIFY; } let contributeBrandsRequest = { brandList: brands }; requestSender.sendPostRequest(contributeBrandsRequest, function (contributeBrandsRequestErr, contributeBrandsResponse) { logger.info(contributeBrandsRequestErr); callback(errorCode.SUCCESS); }); callback(errorCode.SUCCESS); }); } else { callback(errorCode.SUCCESS); } }); } else { callback(errorCode.FAILED); } }); }; exports.createProtocolWorkUnit = function (protocol, filePath, contentType, adminID, callback) { ////////////////////////////////////// // step 1, rename input remote xml file let find = '\\\\'; let re = new RegExp(find, 'g'); let unixFilePath = filePath.replace(re, '/'); let lios = unixFilePath.lastIndexOf('/'); let fileDir = unixFilePath.substring(0, lios); let contributor; let protocolName = protocol.protocol_name_b; let srcFile = fileDir + "/" + protocolName + ".xml"; let destFile = fileDir + "/" + protocolName + ".bin"; let protocolType = protocol.protocol_type; let localProtocolFile = ""; let pythonRuntimeDir = fileDir, pythonFile = "ir_command_protocol.py", userArgs = []; ///////////////////////////////////// // step 2, get admin name as contributor let key = "admin_name_" + adminID; adminAuth.getAuthInfo(key, function (getAdminAuthErr, result) { if (errorCode.SUCCESS.code === getAdminAuthErr.code && null != result) { contributor = result; if (enums.PROTOCOL_TYPE_G2_QUATERNARY === protocolType) { pythonFile = "ir_command_protocol.py"; } else if (enums.PROTOCOL_TYPE_G2_HEXDECIMAL === protocolType) { pythonFile = "ir_command_protocol_hex.py"; } logger.info("prepare to parse protocol"); userArgs.length = 0; // python s_$category.py [remote_xml_file_abs_file] [remote_xml_file_name] [remote_xml_dir_abs_path] userArgs.push(srcFile); userArgs.push(destFile); ////////////////////////////////////// // step 3, try executing remote encoding let pythonCaller = new PythonCaller(); try { logger.info("prepare to call python script"); pythonCaller.call(pythonRuntimeDir, pythonFile, userArgs, function (protocolGenErr, genResult) { if (errorCode.SUCCESS.code === protocolGenErr) { ////////////////////////////////////// // step 3.5, upload protocol binary file to local file storage localProtocolFile = destFile; fs.readFile(localProtocolFile, function (readFileErr, fileData) { if (readFileErr) { logger.error("read protocol binary file error : " + readFileErr); callback(errorCode.FAILED); } else { logger.info("read protocol binary successfully, file size = " + fileData.length); ////////////////////////////////////// // step 4, try register protocol to db let newProtocol = { name: protocolName, status: enums.ITEM_VALID, type: protocolType, contributor: contributor }; let conditions = { name: protocolName }; logger.info("ir_command_protocol.py called successfully, create protocol in DB"); IRProtocol.findIRProtocolByConditions(conditions, function (findIRProtocolErr, IRProtocols) { if (errorCode.SUCCESS.code === findIRProtocolErr.code && null != IRProtocols && IRProtocols.length > 0) { logger.info("protocol " + protocolName + " already exists, " + "nothing to be updated"); callback(errorCode.SUCCESS); } else { IRProtocol.createIRProtocol(newProtocol, function (createIRProtocolErr, createdIRProtocol) { callback(createIRProtocolErr); }); } }); // contribute protocol to IRext main server let queryParams = new Map(); let requestSender = new RequestSender(EXTERNAL_SERVER_ADDRESS, EXTERNAL_SERVER_PORT, contributeProtocolService, queryParams); newProtocol.status = enums.ITEM_VERIFY; let contributeProtocolRequest = { protocol: newProtocol }; let formData = { // Pass a simple key-value pair protocol: JSON.stringify(contributeProtocolRequest), protocolFile: fs.createReadStream(localProtocolFile), }; requestSender.postMultipartForm(formData, function (contributeProtocolRequestErr, contributeProtocolResponse) { logger.info(contributeProtocolRequestErr); callback(errorCode.SUCCESS); }); } }); } else { logger.error("ir_command_protocol.py called failed : " + protocolGenErr); callback(errorCode.FAILED); } }); } catch (exception) { logger.error('failed to execute python script from application'); callback(errorCode.FAILED); } } else { callback(errorCode.FAILED); } }); }; // Ultilities function checksum(str, algorithm, encoding) { return crypto .createHash(algorithm || 'md5') .update(str, 'utf8') .digest(encoding || 'hex') }