Files
private-cloud/private-console/work_unit/code_manage_logic.js
2025-10-29 08:59:13 +08:00

1080 lines
58 KiB
JavaScript

/**
* 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')
}