Commit eb12ee3f by Pavel Fedorov

правки в индексе, подготовка к развертыванию

1 parent 2b3ac17b
...@@ -6,26 +6,41 @@ context { ...@@ -6,26 +6,41 @@ context {
output cjm: string[] = []; output cjm: string[] = [];
output need_ask_name: boolean = true; output need_ask_name: boolean = true;
output template_id: number = 3; output template_id: number = 1;
output conversation_start: number = 0; output conversation_start: number = 0;
output conversation_begin: number = 0; output conversation_begin: number = 0;
output conversation_stop: number = 0; output conversation_stop: number = 0;
output conversation_status: string = "normal"; output conversation_status: string = "normal";
output abonent_request: string[] = []; output abonent_request: string[] = [];
output another_phone_number: string = ""; output another_phone_number: string = "";
output abonent_name: string = "";
output company_name: string = "";
output phone_suffix: string = ""; output phone_suffix: string = "";
} }
external function numbers_from_text(text: string): string;
external function dates_from_text(text: string): string;
external function part_of_the_day(): string;
external function array_size(arr: unknown): number;
external function string_trim(one_line: string): string;
external function is_empty(check: unknown): boolean;
external function performed_stage(stages: string[], stage: string): string[]; external function performed_stage(stages: string[], stage: string): string[];
external function sleep_ms(duration: number): unknown;
external function json_encode(object: unknown): string;
external function time_stamp(): number;
external function math_floor(value: number, presision: number|empty = 0): number;
external function math_round(value: number, presision: number|empty = 0): number;
external function math_ceil(value: number, presision: number|empty = 0): number;
external function phone_human(phone: string): string;
external function last_four(phone: string): string;
external function hours_now(): number;
external function check_mobile_code(phone: string): boolean;
external function countWords(message: string): number;
start node root start node root
{ {
do do
{ {
//set $cjm = external performed_stage($cjm, "root"); set $cjm = external performed_stage($cjm, "root");
//set $conversation_start = external time_stamp(); set $conversation_start = external time_stamp();
goto caller_id; goto caller_id;
} }
transitions transitions
...@@ -65,16 +80,15 @@ node caller_id ...@@ -65,16 +80,15 @@ node caller_id
} }
// Запоминаем временной штамп перед самой первой репликой // Запоминаем временной штамп перед самой первой репликой
//set $conversation_begin = external time_stamp(); set $conversation_begin = external time_stamp();
#say("greeting"); #say("greeting");
//#say("dont_understand_question");
wait *; wait *;
} }
transitions transitions
{ {
//end_conversation: goto end_conversation on true; //end_conversation: goto end_conversation on true;
canttalkrn: goto cant_talk_rn on #messageHasAnyIntent(["decline", "cant_talk_rn"]); canttalkrn: goto cant_talk_rn on #messageHasAnyIntent(["decline", "cant_talk_rn"]) || #messageHasSentiment("negative");
cantalk: goto can_talk on #messageHasAnyIntent(["accept", "can_talk"]); cantalk: goto can_talk on #messageHasAnyIntent(["accept", "can_talk"]) || #messageHasSentiment("positive");
} }
} }
...@@ -242,7 +256,7 @@ node do_before_exit ...@@ -242,7 +256,7 @@ node do_before_exit
do do
{ {
set $cjm = external performed_stage($cjm, "do_before_exit"); set $cjm = external performed_stage($cjm, "do_before_exit");
//set $conversation_stop = external time_stamp(); set $conversation_stop = external time_stamp();
exit; exit;
} }
transitions transitions
......
...@@ -119,21 +119,6 @@ ...@@ -119,21 +119,6 @@
"text": "Благодарю за Ваше обращение. Всего доброго. До свидания." "text": "Благодарю за Ваше обращение. Всего доброго. До свидания."
} }
], ],
"non_work_greetings": [
{
"text": "Вы позвонили в компанию эрброкер, мы работаем по будням с 10 до 19 часов, и, к сожалению, сейчас никто не может ответить на ваш звонок. Но я могу передать ваш запрос менеджеру"
}
],
"non_work_goodbye": [
{
"text": "Передам всё, и постараюсь чтобы менеджер связался с вами как можно быстрее. До свидания!"
}
],
"non_work_short_goodbye": [
{
"text": "Хорошо, просто передам что вы звонили. До свидания!"
}
],
"something_else": [ "something_else": [
{ {
"text": "Ещё что-нибудь?" "text": "Ещё что-нибудь?"
...@@ -205,21 +190,6 @@ ...@@ -205,21 +190,6 @@
"text": "Продиктуете ваш контактный номер телефона" "text": "Продиктуете ваш контактный номер телефона"
} }
], ],
"hello_propose": [
{
"text": "Меня зовут Аврора. Подкл+ючим домашний высокоскоростной интернет?! Воспользуйтесь эксклюзивным предложением!"
}
],
"internet_tv": [
{
"text": "Всего за 369 рублей в месяц вы получите интернет со скоростью 100 мегабит в секунду, а также 168 интерактивных тв-каналов в высоком качестве!"
}
],
"onlyou": [
{
"text": "Только для вас безлимитный высокоскоростной интернет и интерактивное телевидение с онлайн-кинотеатрами всего за 1 рубль первый месяц!"
}
],
"willcall": [ "willcall": [
{ {
"text": "Оставайтесь на связи, наш менеджер свяжется с вами в течение 15 минут" "text": "Оставайтесь на связи, наш менеджер свяжется с вами в течение 15 минут"
...@@ -334,9 +304,6 @@ ...@@ -334,9 +304,6 @@
"yes_i_am_a_robot": {}, "yes_i_am_a_robot": {},
"is_that_all": {}, "is_that_all": {},
"end_conversation": {}, "end_conversation": {},
"non_work_greetings":{},
"non_work_goodbye":{},
"non_work_short_goodbye": {},
"something_else":{}, "something_else":{},
"im_wrighting":{}, "im_wrighting":{},
"work_greetings": {}, "work_greetings": {},
...@@ -348,9 +315,6 @@ ...@@ -348,9 +315,6 @@
"check_is_shared": {}, "check_is_shared": {},
"get_phone_suffix": {}, "get_phone_suffix": {},
"get_another_phone": {}, "get_another_phone": {},
"hello_propose": {},
"internet_tv": {},
"onlyou": {},
"willcall": {}, "willcall": {},
"phone_number": {}, "phone_number": {},
"kontakt_nomer": {}, "kontakt_nomer": {},
......
const fs = require("fs");
const path = require("path");
class AudioResources
{
constructor()
{
this.resources = {};
}
getResourceKey(text, voiceInfo) {
return [
voiceInfo.lang ?? "",
voiceInfo.speaker ?? "",
voiceInfo.emotion ?? "Neutral",
voiceInfo.speed ?? 1,
voiceInfo.variation ?? 0,
text,
].join("|");
}
async appendJson(folder, pack)
{
const errors = [];
let i = 0;
for (const phrase of pack.phrases ?? []) {
i++;
// валидация
if (phrase.phrase === undefined) {
errors.push(`For ${i} phrase field 'phrase' is undefined`);
continue;
}
if (phrase.audio === undefined) {
errors.push(`For ${i} phrase field 'audio' is undefined`);
continue;
}
const audioFile = path.join(folder, phrase.audio);
if (!fs.existsSync(audioFile)) {
errors.push(`For ${i} phrase "${phrase.phrase}" file not found`);
continue;
}
phrase.voice = { ...pack.voice, ...phrase.voice };
const resourceKey = this.getResourceKey(phrase.phrase, phrase.voice ?? {});
if (resourceKey in this.resources) {
// дубликат - не ошибка
console.warn("Skip", i, "phrase because it's duplicate");
continue;
}
this.resources[resourceKey] = audioFile;
}
if(errors.length > 0)
{
console.error(`Was errors ${JSON.stringify(errors)}`)
}
}
async addFolder(folder)
{
const files = fs.readdirSync(folder);
for (const fileName of files)
{
if (path.extname(fileName) === ".json")
{
const fname = path.join(folder, fileName);
console.log(`Parsing ${fname}`);
await this.appendJson(folder, JSON.parse(fs.readFileSync(fname).toString()));
}
}
}
GetPath(text, voiceInfo)
{
const key = this.getResourceKey(text, voiceInfo);
const fpath = this.resources[key];
if (fpath === undefined)
throw new Error(`Failed to get ${key}`);
return fpath;
}
}
module.exports = AudioResources;
\ No newline at end of file
module.exports = exports = {
mobile_codes() {
return [
"900", "902", "903",
"904", "905", "906",
"908", "909", "950",
"951", "953", "960",
"961", "962", "963",
"964", "965", "966",
"967", "968", "969",
"980", "983", "986",
"901", "910", "911",
"912", "913", "914",
"915", "916", "917",
"918", "919", "978",
"981", "982", "984",
"985", "987", "988",
"989", "920", "921",
"922", "923", "924",
"925", "926", "927",
"928", "929", "930",
"931", "932", "933",
"934", "936", "937",
"938", "939", "999",
"952", "958", "977",
"991", "992", "993",
"994", "995", "996"
];
}
};
\ No newline at end of file
const dasha = require("@dasha.ai/sdk"); const dasha = require("@dasha.ai/sdk");
const AudioResources = require("./customTts.js");
const fs = require("fs"); const fs = require("fs");
const sys = require('child_process');
const shared = require("./shared");
const local_num = "4029";
const events_owner = "105";
const sip_config = "huntersales";
const preset_template_id = 1;
const logs_path = "./logs/";
const file_mime_type = "text/plain";
let txtData = "";
let abonent_phone = process.argv[2] ?? "";
let caller_phone = process.argv[3] ?? abonent_phone;
const report_file = "jobs/" + caller_phone + ".json";
const pid_file = report_file.replace( /\.json$/, '.pid' );
fs.writeFileSync(pid_file, JSON.stringify(process.pid, undefined, 2));
fs.chmod(pid_file, 0o666, (err) => { if (err) console.log(err) });
function nextInterval(iterationNum) {
var x = iterationNum;
// Максимальный период ожидания 10 минут
var msMax = 600000;
// Прогрессивный период ожидания
var msWait = x * x * 1000;
// Возвращаем мниммльное из двух значений
return Math.min(msMax, msWait);
}
async function main() { async function main() {
const app = await dasha.deploy("./app");
app.connectionProvider = async (conv) => const app_suffix = shared.pid_name();
conv.input.phone === "chat" const app_work_dir = shared.make_unique_app(app_suffix);
? dasha.chat.connect(await dasha.chat.createConsoleChat()) const app = await dasha.deploy(app_work_dir, {
: dasha.sip.connect(new dasha.sip.Endpoint("default")); // Указываем название рабочей группы
groupName: "Default",
// Указываем количество попыток соединения с
// серверами Dasha.AI при потере соединения
// до остановки приложения из-за потери связи
maxReconnectCount: 100,
// Указываем функцию вычисления ожидания до
// следующей попытки соединения с серверами
reconnectInterval: x => nextInterval(x)
});
if (app_work_dir !== './app') shared.drop_unique_app(app_suffix);
const audio = new AudioResources();
audio.addFolder("audio");
app.ttsDispatcher = (conv) => "custom";
app.customTtsProvider = async (text, voice) => {
console.log(`Tts asking for phrase with text ${text} and voice ${JSON.stringify(voice)}`);
const fname = audio.GetPath(text, voice);
console.log(`Found in file ${fname}`);
return dasha.audio.fromFile(fname);
};
process.on("SIGTERM", async () => {
console.log("\nReceived SIGTERM");
await app.stop();
app.dispose();
if (fs.existsSync(pid_file)) await fs.unlinkSync(pid_file);
let job_data = { status: "Terminated",
reason: "Received SIGTERM",
details: txtData };
fs.writeFileSync(report_file, JSON.stringify(job_data, undefined, 2),
{encoding:'utf8', mode:0o666, flag:'w'});
console.log(job_data);
});
process.on("SIGINT", async () => {
console.log("\nReceived SIGINT");
await app.stop();
app.dispose();
if (fs.existsSync(pid_file)) await fs.unlinkSync(pid_file);
let job_data = { status: "Terminated",
reason: "Received SIGINT",
details: txtData };
fs.writeFileSync(report_file, JSON.stringify(job_data, undefined, 2),
{encoding:'utf8', mode:0o666, flag:'w'});
console.log(job_data);
});
app.setExternal("numbers_from_text", async (args) => {
return await shared.cct_numbers_from_text(args.text);
});
app.setExternal("dates_from_text", async (args) => {
return await shared.cct_dates_from_text(args.text);
});
app.setExternal("part_of_the_day", (args, conv) => {
return shared.get_part_of_the_day();
});
app.setExternal("array_size", (args, conv) => {
const arr = args.arr;
return arr.length;
});
app.setExternal("string_trim", (args, conv) => {
const str = args.one_line;
return str.trim();
});
app.setExternal("is_empty", (args, conv) => {
return shared.empty(args.check);
});
await app.start();
app.setExternal("performed_stage", (args, conv) => { app.setExternal("performed_stage", (args, conv) => {
const arr = args.stages; const arr = args.stages;
const val = args.stage; const val = args.stage;
arr.push(val); arr.push(val);
return arr; return arr;
}); });
const conv = app.createConversation({ phone: process.argv[2] ?? "" });
if (conv.input.phone !== "chat") conv.on("transcription", console.log); app.setExternal("sleep_ms", async (args, conv) => {
return new Promise((resolve) => {
setTimeout(resolve, args.duration);
});
});
const logFile = await fs.promises.open("./log.txt", "w"); app.setExternal("json_encode", async (args, conv) => {
await logFile.appendFile("#".repeat(100) + "\n"); return JSON.stringify(args.object, undefined, 2);
});
app.setExternal("time_stamp", async (args, conv) => {
return Date.now();
});
app.setExternal("math_floor", async (args, conv) => {
return Math.floor(args.value, args.presision);
});
app.setExternal("math_round", async (args, conv) => {
return Math.round(args.value, args.presision);
});
app.setExternal("math_ceil", async (args, conv) => {
return Math.ceil(args.value, args.presision);
});
app.setExternal("phone_human", async (args, conv) => {
return shared.human_format(args.phone);
});
app.setExternal("last_four", async (args, conv) => {
return shared.last_four_digits(args.phone);
});
app.setExternal("check_mobile_code", async (args, conv) => {
return shared.is_mobile_code(args.phone);
});
app.setExternal("hours_now", async (args, conv) => {
let date_time_now = new Date(ts);
return date_time_now.getHours();
});
app.setExternal("countWords", (args) => {
return args.message.split(' ').length;
});
await app.start();
const input_context = { phone: abonent_phone, caller: caller_phone };
const conv = app.createConversation(input_context);
const audioChannel = conv.input.phone !== "chat";
if (audioChannel) {
conv.sip.config = sip_config;
// conv.audio.tts = 'custom';
conv.on("transcription", console.log);
} else {
await dasha.chat.createConsoleChat(conv);
}
// Устанавливаем минимальный уровень фонового шума
conv.audio.noiseVolume = 0.1;
let debugItem = 0;
// current timestamp in milliseconds
let ts = Date.now();
// Get now date info
let date_ob = new Date(ts);
let date_day = date_ob.getDate();
let month = date_ob.getMonth() + 1;
let year = date_ob.getFullYear();
let hours = date_ob.getHours();
let minutes = date_ob.getMinutes();
let seconds = date_ob.getSeconds();
let unique = ts / 1000;
if (month < 10) month = '0' + month;
if (date_day < 10) date_day = '0' + date_day;
if (hours < 10) hours = '0' + hours;
if (minutes < 10) minutes = '0' + minutes;
if (seconds < 10) seconds = '0' + seconds;
// Make date and time string for log & debug file
let solid_date = year + '' + month + '' + date_day;
let solid_time = hours + '' + minutes + '' + seconds;
let time_mark = year + '-' + month + '-' + date_day
+ ' ' + hours + ':' + minutes + ':' + seconds;
let toUser = conv.input.phone;
// Check PBX phone prefix and cut it
let check_prefix = toUser.substring(0, 4);
if (local_num == check_prefix) toUser = toUser.substring(4);
// Make log & debug files names
let txt_file_name = logs_path + 'out-' + toUser + '-'
+ local_num + '-' + solid_date + '-'
+ solid_time + '-' + unique + '.txt';
let log_file_name = logs_path + 'out-' + toUser + '-'
+ local_num + '-' + solid_date + '-'
+ solid_time + '-' + unique + '.log';
let debug_file_name = logs_path + 'out-' + toUser + '-'
+ local_num + '-' + solid_date + '-'
+ solid_time + '-' + unique + '.debug';
// Open text, log and debug files for write
const txtFile = await fs.promises.open(txt_file_name, "w");
const logFile = await fs.promises.open(log_file_name, "w");
const debugFile = await fs.promises.open(debug_file_name, "w");
caller_phone = shared.human_format(conv.input.caller);
txtData = "\t" + caller_phone + "\t-=#=-\t" + time_mark + "\n\n";
await txtFile.appendFile(txtData);
debugString = 'Initialize call to: ' + toUser + "\n";
await debugFile.appendFile(debugString);
if (audioChannel) console.log(debugString);
logString = 'Conversation started to: ' + toUser
+ "\n\nConversation replics:\n";
await logFile.appendFile(logString);
conv.on("transcription", async (entry) => { conv.on("transcription", async (entry) => {
await logFile.appendFile(`${entry.speaker}: ${entry.text}\n`); rts = entry.startTime.getTime();
dts = rts - ts;
dts_m = Math.floor(dts / 60000);
dts_s = ((dts - (dts_m * 60000)) / 1000).toFixed(1);
if (dts_m < 10) dts_m = '0' + dts_m;
if (dts_s < 10) dts_s = '0' + dts_s;
hours = entry.startTime.getHours();
minutes = entry.startTime.getMinutes();
seconds = entry.startTime.getSeconds();
if (hours < 10) hours = '0' + hours;
if (minutes < 10) minutes = '0' + minutes;
if (seconds < 10) seconds = '0' + seconds;
speaker = entry.speaker;
if (speaker === "ai") speaker = " ai";
replic = speaker + ': [' + hours + ':' + minutes + ':' + seconds + ' '
+ dts_m + ':' + dts_s + '] - ' + entry.text + "\n";
txtData = txtData + replic;
await txtFile.appendFile(replic);
await logFile.appendFile(replic);
debugItem ++;
let debugString = '"Debug Info #' + debugItem + ' dialogue": '
+ JSON.stringify(entry, undefined, 2) + "\n";
await debugFile.appendFile(debugString);
}); });
let connectionStatus = {};
if (audioChannel)
connectionStatus = { status: "Connected", reason: "", details: "" };
else
connectionStatus = { status: "Chat mode", reason: "", details: "" };
conv.on("debugLog", async (event) => { conv.on("debugLog", async (event) => {
if (event?.msg?.msgId === "FailedOpenSessionChannelMessage") {
connectionStatus = { status: "Failed",
reason: event?.msg?.reason,
details: event?.msg?.details };
}
if (event?.msg?.msgId === "RecognizedSpeechMessage") { if (event?.msg?.msgId === "RecognizedSpeechMessage") {
const logEntry = event?.msg?.results[0]?.facts; const logEntry = event?.msg?.results[0]?.facts;
await logFile.appendFile(JSON.stringify(logEntry, undefined, 2) + "\n"); await logFile.appendFile(JSON.stringify(logEntry, undefined, 2) + "\n");
debugItem ++;
let debugString = '"Debug Info #' + debugItem + ' entry": '
+ JSON.stringify(logEntry, undefined, 2) + "\n";
await debugFile.appendFile(debugString);
} }
debugItem ++;
let debugString = '"Debug Info #' + debugItem + ' event": '
+ JSON.stringify(event, undefined, 2) + "\n";
await debugFile.appendFile(debugString);
}); });
const result = await conv.execute(); const result = await conv.execute();
let close_time = new Date();
rts = close_time.getTime();
dts = rts - ts;
dts_m = Math.floor(dts / 60000);
dts_s = ((dts - (dts_m * 60000)) / 1000).toFixed(1);
if (dts_m < 10) dts_m = '0' + dts_m;
if (dts_s < 10) dts_s = '0' + dts_s;
hours = close_time.getHours();
minutes = close_time.getMinutes();
seconds = close_time.getSeconds();
if (hours < 10) hours = '0' + hours;
if (minutes < 10) minutes = '0' + minutes;
if (seconds < 10) seconds = '0' + seconds;
const conversations_statuses = {
normal: "разговор завершён",
broken: "абонент повесил трубку",
forward: "разговор переведён на другой номер"
};
try {
conversation_status_id = result.output.conversation_status;
conversation_status = conversations_statuses[conversation_status_id];
} catch(err) {
conversation_status_id = "unknown";
conversation_status = "Не определённое в сценанрии завершение разговора";
}
if (connectionStatus.status === "Failed") {
if (connectionStatus.reason === "Busy") {
conversation_status = "линия занята";
} else {
conversation_status = "абонент не взял трубку";
}
}
speaker = " sys";
replic = speaker + ': [' + hours + ':' + minutes + ':' + seconds + ' '
+ dts_m + ':' + dts_s + "] - / " + conversation_status + " /\n";
txtData = txtData + replic;
await txtFile.appendFile(replic);
await logFile.appendFile(replic);
logString = "\nConversation results:" +
JSON.stringify(result.output, undefined, 2) + "\n";
await logFile.appendFile(logString);
console.log(result.output); console.log(result.output);
let audio_url = "";
if (shared.empty(result.recordingUrl))
audio_url = "\nАудио запись разговора не доступна\n";
else
audio_url = "\nЗапись разговора доступна по ссылке:\n"
+ result.recordingUrl + "\n";
// txtData = txtData + audio_url;
await txtFile.appendFile(audio_url);
await logFile.appendFile(audio_url);
let job_data = {};
if (connectionStatus.status === "Failed")
job_data = connectionStatus;
else {
job_data = { status: connectionStatus.status,
reason: conversation_status_id,
audio: result.recordingUrl,
report: result.output,
details: txtData };
}
fs.writeFileSync(report_file, JSON.stringify(job_data, undefined, 2),
{encoding:'utf8', mode:0o666, flag:'w'});
console.log(job_data);
const conv_info = shared.get_conversation_info(app, conv);
// Close text, log and debug files
await txtFile.close();
await logFile.close();
await debugFile.close();
// Store conversation text and data
let conv_start = result.output.conversation_start;
let conv_begin = result.output.conversation_begin;
let conv_stop = result.output.conversation_stop;
if (shared.empty(conv_start)) conv_start = 0;
if (shared.empty(conv_begin)) conv_begin = 0;
if (shared.empty(conv_stop)) conv_stop = 0;
if (conv_start == 0) conv_start = ts;
if (conv_begin == 0) conv_begin = conv_start;
if (conv_stop == 0) conv_stop = Date.now();
let output_data = JSON.stringify(result.output, undefined, 2);
let template_id = result.output.template_id??preset_template_id;
let action = "store_conversations";
let request = {
owner: events_owner,
datetime_event: Math.ceil(conv_start/1000),
// src: caller_phone,
// dst: local_num,
dst: caller_phone,
src: local_num,
duration: Math.ceil((conv_stop - conv_start)/1000),
direction: "output",
billsec: Math.ceil((conv_stop - conv_begin)/1000),
app_name: conv_info.app_name,
app_name_full: conv_info.app_name_full,
app_id: conv_info.app_id,
job_id: conv_info.job_id,
report_data: output_data,
conversation: txtData,
template_id: template_id
};
console.log(txtData);
let response = await shared.ai_api_hook(action, request);
console.log(response);
if (conversation_status_id == "forward") {
var conversations_id = response.conversations_id ?? 0;
action = "force_conversations_mail";
request = {
owner: events_owner,
time: Math.ceil(conv_start/1000),
id: conversations_id,
swap: 1
};
console.log(request);
response = await shared.ai_api_hook(action, request);
console.log(response);
}
// Send text file to Google Disk
if (audioChannel)
{
shared.renew_last_log_file(txt_file_name);
shared.send_to_google_disk(txt_file_name, file_mime_type);
}
// Send log file to Google Disk
if (audioChannel)
shared.send_to_google_disk(log_file_name, file_mime_type);
// Send debug file to Google Disk
if (audioChannel)
shared.send_to_google_disk(debug_file_name, file_mime_type);
await app.stop(); await app.stop();
app.dispose(); app.dispose();
await logFile.close(); if (fs.existsSync(pid_file)) await fs.unlinkSync(pid_file);
} }
main().catch((error) => { main().catch((err) => {console.error(err)});
console.error(error);
process.exitCode = 1;
});
\ No newline at end of file
*.in
*.pid
*.out
!demo*
\ No newline at end of file
const fs = require("fs");
const url = require("url");
const axios = require("axios");
const moment = require("moment");
const strings = require("string");
const dataset = require("./dataset");
const sys = require('child_process');
const cct_api = 'http://cct.r-broker.ru/api/';
const cct_key = 'y8Bzq1C0vIwhcrl98emy04JauUlWd7glhvUo2TcWBSkdMYzrKS'
+ 'KhQNMuoU_NecQJVNLIgRA4eeDTX4QFDA6np1VI0ctrmYJkcIQK'
+ 'muMgCjKzqHVSzZ2-n_0vefeFZPCMZJz4NO8xgrPwQ1OWgn_ACt'
+ 'be9DWhSR-yi_-u2k2NcF3Heg193PSKvov9QPlShLtq_UzdQfmb'
+ 'C9uS1-bukZFdFyQ9M6mO8Qnlyzm95ouQPODwqieKjiXIFkXUIW';
const file_sender = '../../htdocs/uploadgd/up.php';
const api_hook_url = 'https://ai.r-broker.ru/api/api.php';
const api_hook_key = 'kd56h4jfhj54f62hjf6d8YgjL9';
const api_hook = api_hook_url + '?key=' + api_hook_key;
const mobile_codes = dataset.mobile_codes();
function empty (value) {
if (value === undefined) return true;
if (value === null) return true;
const str = strings(value);
if (str == "") return true;
if (str.trim() == "") return true;
return false;
}
async function cct_api_service (service, api_request) {
let post_data = JSON.stringify(api_request);
let headers = {
"Language": "ru-RU",
"Authorization": "Bearer " + cct_key,
"Content-Type": "application/json; charset=utf-8"
};
let config = { headers: headers };
let result = await axios.post(cct_api + service, post_data, config);
let wrong_data = { status: 'error', result: 'axios crashed' };
if (result.data === null) return wrong_data
if (result.data === undefined) return wrong_data;
return result.data;
}
module.exports = exports = {
empty (value) {
return empty (value);
},
async ai_api_hook (action, web_hook_data) {
let api_hook_action = api_hook + '&action=' + action;
let post_data = new url.URLSearchParams(web_hook_data);
let result = {};
let wrong_data = { status: 'error', detail: 'axios crashed' };
try {
result = await axios.post(api_hook_action, post_data);
} catch (err) {
wrong_data.detail = JSON.stringify(err, undefined, 2);
result.data = wrong_data;
}
if (empty(result.data)) return wrong_data
return result.data;
},
get_part_of_the_day() {
ts = Date.now();
let date_ob = new Date(ts);
hours = date_ob.getHours();
if (hours < 4) return 'night';
if (hours < 12) return 'morning';
if (hours < 16) return 'day';
if (hours < 24) return 'evening';
return 'night';
},
human_format(abonent_phone) {
let clean_phone = abonent_phone.replace( /[^\d]/g, '' );
var size = clean_phone.length;
var human_phone = "";
if (size < 4) return clean_phone;
if (size == 11) {
prefix = clean_phone.substring(0, 1);
if (prefix == 8) human_phone = prefix; else human_phone = "+" + prefix;
human_phone = human_phone + " (" + clean_phone.substring(1, 4);
human_phone = human_phone + ") " + clean_phone.substring(4, 7);
human_phone = human_phone + "-" + clean_phone.substring(7, 9);
human_phone = human_phone + "-" + clean_phone.substring(9, 11);
return human_phone;
}
if (size == 10) {
human_phone = "+7";
human_phone = human_phone + " (" + clean_phone.substring(0, 3);
human_phone = human_phone + ") " + clean_phone.substring(3, 6);
human_phone = human_phone + "-" + clean_phone.substring(6, 8);
human_phone = human_phone + "-" + clean_phone.substring(8, 10);
return human_phone;
}
const cuts = [ 2, 2, 3, 3 ];
const divs = [ "-", "-", ") ", "(" ];
let phone = clean_phone;
for (var i = 0; i < 4; i ++) {
if (size > cuts[i]) {
size -= cuts[i];
part = phone.substring(size, size + cuts[i]);
human_phone = divs[i] + part + human_phone;
phone = phone.substring(0, size);
} else {
var div = "";
if (divs[i] == "(") div = divs[i];
return div + phone + human_phone;
}
}
return "+" + phone + " " + human_phone;
},
last_four_digits(abonent_phone) {
let clean_phone = abonent_phone.replace( /[^\d]/g, '' );
var size = clean_phone.length;
let last_four = "";
if (size > 3) {
last_four = clean_phone.substring(size - 2, size);
size -= 2;
return clean_phone.substring(size - 2, size) + "-" + last_four;
}
return clean_phone;
},
async cct_numbers_from_text (text) {
const service = 'markers-data';
request = {
debug: false,
input: "text",
channel: "client",
distance: { "min": 0.166667, "mid": 0.166667, "max": 0.166667 },
language: "russian",
text: text,
triggers: [
{ name: "numbers", markers: [ { type: "number" } ] }
]
};
const response = await cct_api_service(service, request);
let result = "";
if (response.status !== "success") return result;
for (trigger of response.result) {
if (trigger.state === "on") {
if (trigger.name === "numbers") {
for (i in trigger.details) {
found = trigger.details[i];
for (j in found) {
element = found[j];
result = result + " " + element.value;
}
}
}
}
}
result = result.replace( /^\s+/, '' );
return result;
},
async cct_dates_from_text (text) {
const service = 'markers-data';
request = {
debug: false,
input: "text",
channel: "client",
distance: { "min": 0.166667, "mid": 0.166667, "max": 0.166667 },
language: "russian",
text: text,
triggers: [
{ name: "dates", markers: [ { type: "date time" } ] }
]
};
const response = await cct_api_service(service, request);
let result = "";
if (response.status !== "success") return result;
for (trigger of response.result) {
if (trigger.state === "on") {
if (trigger.name === "dates") {
for (i in trigger.details) {
found = trigger.details[i];
for (j in found) {
element = found[j];
pattern = element.pattern??"";
if ((pattern === "%date%") && (result === ""))
result = element.value;
}
}
}
}
}
if (result === "") return result;
moment.locale("ru");
result = moment(result, "YYYY-MM-DD").format("DD.MM.YYYY");
return result;
},
renew_last_log_file(last_text_file) {
let sysCommand = 'cat ' + last_text_file + ' >log.txt';
sys.exec(sysCommand, (error, stdout, stderr) => {
if (error) {
console.error(`error: ${error.message}`);
}
if (stderr) {
console.error(`stderr: ${stderr}`);
}
// console.log(`stdout:\n${stdout}`);
});
},
send_to_google_disk(file_name, file_mime) {
let proc = sys.spawnSync('php', [ file_sender, file_name, file_mime ]);
let exit_code = proc.status;
let look_stdout = proc.stdout.toString();
let check_error = proc.error;
let look_stderr = proc.stderr.toString();
if (check_error)
console.log("error: \n" + JSON.stringify(check_error, undefined, 2));
if (look_stderr) console.log("stderr: \n" + look_stderr);
if (look_stdout) console.log("stdout: \n" + look_stdout);
},
is_mobile_code(abonent_phone) {
let clean_phone = abonent_phone.replace( /[^\d]/g, '' );
var size = clean_phone.length;
let phone_code = "";
if (size > 6) {
phone_code = clean_phone.substring(1, 4);
}
return (mobile_codes.indexOf(phone_code)!=-1);
},
pid_name() {
pidName = process.pid;
if (pidName < 10) pidName = '0000' + pidName;
if (pidName < 100) pidName = '000' + pidName;
if (pidName < 1000) pidName = '00' + pidName;
if (pidName < 10000) pidName = '0' + pidName;
return pidName;
},
make_unique_app(app_suffix) {
let app_suffix_file = './threads/' + app_suffix + '/app.dashaapp'
if (fs.existsSync(app_suffix_file)) return './threads/' + app_suffix;
let proc = sys.spawnSync('cp', [ '-rfp', './app', './threads/' + app_suffix ]);
let exit_code = proc.status;
let exit_data = proc.stdout.toString();
let check_error = proc.error;
let look_stderr = proc.stderr.toString();
if (check_error) {
console.log('error: ' + JSON.stringify(check_error, undefined, 2));
return './app';
}
if (look_stderr) {
console.log('stderr: ' + look_stderr);
return './app';
}
app_data = fs.readFileSync('app/app.dashaapp');
app_info = JSON.parse(app_data);
let app_name = app_info.name + '-' + app_suffix;
app_info.name = app_name;
fs.writeFileSync(app_suffix_file, JSON.stringify(app_info, undefined, 2));
return './threads/' + app_suffix;
},
drop_unique_app(app_suffix) {
let proc = sys.spawnSync('rm', [ '-rf', './threads/' + app_suffix ]);
let exit_code = proc.status;
let exit_data = proc.stdout.toString();
let check_error = proc.error;
let look_stderr = proc.stderr.toString();
if (check_error) {
console.log('error: ' + JSON.stringify(check_error, undefined, 2));
return false;
}
if (look_stderr) {
console.log('stderr: ' + look_stderr);
return false;
}
return true;
},
get_conversation_info(app, conv) {
app_data = fs.readFileSync('app/app.dashaapp');
app_info = JSON.parse(app_data);
let app_name = app_info.name;
app_name_full = app.applicationName;
app_id = app.applicationId;
job_id = conv._jobId;
return {
app_name: app_name,
app_name_full: app_name_full,
app_id: app_id,
job_id: job_id
};
}
};
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!