diff --git a/lib/const.js b/lib/const.js index 20a35cc..ae4e9c3 100644 --- a/lib/const.js +++ b/lib/const.js @@ -30,10 +30,10 @@ exports.keyboards = { exports.inlineKeyboards = { open: [[{text: '✅', callback_data: 'CloseTicket'}, {text: '➡️', callback_data: 'AssignTicket'}, {text: '*️⃣', callback_data: 'ChangeStatus'}]], close: [[{text: '✔', callback_data: 'OpenTicket'}, {text: '➡️', callback_data: 'AssignTicket'}, {text: '*️⃣', callback_data: 'ChangeStatus'}]], - confirmOpen: [[{text: 'Открыть заявку', callback_data: 'ConfirmOpen'}, {text: 'Отмена', callback_data: 'RefreshStatus'}]], - confirmClose: [[{text: 'Закрыть заявку', callback_data: 'ConfirmClose'}, {text: 'Отмена', callback_data: 'RefreshStatus'}]], + confirmOpen: [[{text: 'Открыть заявку', callback_data: 'ConfirmOpen'}, {text: 'Отмена', callback_data: 'RefreshTicket'}]], + confirmClose: [[{text: 'Закрыть заявку', callback_data: 'ConfirmClose'}, {text: 'Отмена', callback_data: 'RefreshTicket'}]], userAddComment: [[{text: '❓ Добавить комментарий', callback_data: 'UserAddComment'}]], - changeStatus: [[{text: 'В ожидание', callback_data: 'WaitingStatus'}, {text: 'В работу', callback_data: 'WorkingStatus'}], [{text: 'Открыть тему', callback_data: 'OpenThread'}, {text: 'Отмена', callback_data: 'RefreshStatus'}]], + changeStatus: [[{text: 'В ожидание', callback_data: 'WaitingStatus'}, {text: 'В работу', callback_data: 'WorkingStatus'}], [{text: 'Открыть тему', callback_data: 'OpenThread'}, {text: 'Отмена', callback_data: 'RefreshTicket'}]], configUserGroups: [ [{text: 'Add new group', callback_data: 'AddNewGroup'}, {text: 'Add new user in group', callback_data: 'AddNewUser'}], [{text: 'Remove group', callback_data: 'RemoveGroup'}, {text: 'Remove user', callback_data: 'RemoveUser'}, {text: 'Exit', callback_data: 'ExitConfig'}] diff --git a/lib/glpiParse.js b/lib/glpiParse.js index 4d76d90..58c9b79 100644 --- a/lib/glpiParse.js +++ b/lib/glpiParse.js @@ -13,34 +13,29 @@ const glpiUrl = conf.glpiConfig.apiurl.replace("apirest.php", ""); exports.parseTickets = async (bot, messageData) => { let listTickets = await glpm.getAllItems('Ticket', 5); for(let i = 4; i >= 0; i--){ + let ticketId; try{ - let ticketId; if(!listTickets[i]) break; ticketId = listTickets[i].id; if(ticketId <= messageData.ticket) continue; - if(listTickets[i].users_id_recipient != conf.glpiConfig.user_id){ - let usersArray = await glpm.getUsers(ticketId); - let authorEmail; - if(!usersArray[0]) continue; - if(usersArray[0].hasOwnProperty('alternative_email') && usersArray[0].alternative_email){ - authorEmail = usersArray[0].alternative_email; + let userRecipient = listTickets[i].users_id_recipient; + let ticketAuthor = "Unknown"; + if(userRecipient != conf.glpiConfig.user_id){ + if(userRecipient != 0){ + let temp = await glpm.getItem("User", userRecipient); + ticketAuthor = temp.firstname + ' ' + temp.realname; }else{ - let temp = await glpm.getItem("User", usersArray[0].users_id); - authorEmail = temp.firstname + ' ' + temp.realname; - } - let text = await htmlToText(listTickets[i].content); - let messageText = `🟢 ЗАЯВКА №${ticketId}\n\n`; - messageText += `Автор заявки: ${authorEmail}\n`; - messageText += `Проблема: ${listTickets[i].name}\nОписание: `; - messageText += text; - if(messageText.length > 600){ - messageText = `${messageText.substring(0, 500)} + '\n\nЧитать дальше`; + let usersArray = await glpm.getUsers(ticketId); + if(usersArray[0].hasOwnProperty('alternative_email')){ + ticketAuthor = usersArray[0].alternative_email; + } } + let messageText = await parseMessageText(listTickets[i], ticketAuthor, "🟢"); let messg = await bot.telegram.sendMessage(conf.supportChatId, messageText, { parse_mode: 'HTML', reply_markup: { inline_keyboard: cns.inlineKeyboards.open } }); - await editMessageText(bot, messg.message_id, messageText, cns.inlineKeyboards.open); + //await editMessageText(bot, messg.message_id, messageText, cns.inlineKeyboards.open); messageData.data[ticketId] = { messageId: messg.message_id, status: 1 @@ -49,20 +44,21 @@ exports.parseTickets = async (bot, messageData) => { await createThread(bot, messageData, ticketId, title); await sleep(1000); } - messageData.ticket = ticketId; - fs.writeFileSync(dir + "/../data/messageData.json", JSON.stringify(messageData, null, 3)); }catch(e){ - fs.appendFileSync(dir + "/../logs/logs.json", JSON.stringify("*** parseTickets:\n" + e, null, 3)); + fs.appendFileSync(dir + "/../logs/logs.txt", e.stack); } + messageData.ticket = ticketId; + fs.writeFileSync(dir + "/../data/messageData.json", JSON.stringify(messageData, null, 3)); } } exports.parseComments = async (bot, messageData) => { let listComments = await glpm.getAllItems('ITILFollowup', 5); for (let i = 4; i >= 0; i--) { + let commentId; try{ if(!listComments[i]) break; - let commentId = listComments[i].id; + commentId = listComments[i].id; if(commentId <= messageData.comment) continue; if(listComments[i].users_id != conf.glpiConfig.user_id){ let ticketId = listComments[i].items_id; @@ -84,13 +80,12 @@ exports.parseComments = async (bot, messageData) => { messageText = `${messageText.substring(0, 2400)} + '\n\nЧитать дальше`; } await bot.telegram.sendMessage(conf.supportChatId, messageText, {parse_mode: "HTML", message_thread_id: messageData.data[ticketId].threadId}); - await sleep(1000); } - messageData.comment = commentId; - fs.writeFileSync(dir + "/../data/messageData.json", JSON.stringify(messageData, null, 3)); }catch(e){ - fs.appendFileSync(dir + "/../logs/logs.json", JSON.stringify("*** parseComments:\n" + e, null, 3)); + fs.appendFileSync(dir + "/../logs/logs.txt", e.stack); } + messageData.comment = commentId; + fs.writeFileSync(dir + "/../data/messageData.json", JSON.stringify(messageData, null, 3)); } } @@ -98,76 +93,52 @@ exports.refreshStatus = async (bot, messageData) => { let listTickets = await glpm.getAllItems('Ticket', 100); for(let i = 99; i >= 0; i--){ try{ - let ticketId = listTickets[i].id; - if(!listTickets[i] || !messageData.data.hasOwnProperty(ticketId)) continue; - let td = messageData.data[ticketId]; - if(td.status != listTickets[i].status){ - let usersArray = await glpm.getUsers(ticketId); - let message = await htmlToText(listTickets[i].content); - let authorEmail; - if(!usersArray[0]) authorEmail == "Unknown"; - else if(usersArray[0].hasOwnProperty('alternative_email') && usersArray[0].alternative_email){ - authorEmail = usersArray[0].alternative_email; - }else if(usersArray[0].users_id == conf.glpiConfig.user_id){ - await editTicketStatus(bot, messageData, message); - continue; - }else{ - let temp = await glpm.getItem("User", usersArray[0].users_id); - authorEmail = temp.firstname + ' ' + temp.realname; - } - let color = await getTicketColor(listTickets[i].status); - let messageText = `${color} ЗАЯВКА №${ticketId}\n\n`; - messageText += `Автор заявки: ${authorEmail}\n`; - messageText += `Проблема: ${listTickets[i].name}\nОписание: `; - messageText += message; - if(messageText.length > 600){ - messageText = `${messageText.substring(0, 500)} + '\n\nЧитать дальше`; - } - let inKeyboard = await getKeyboardFromStatus(listTickets[i].status); - if(td.hasOwnProperty('threadId')){ - if(listTickets[i].status == 5 || listTickets[i].status == 6){ - await closeThread(bot, messageData, ticketId); - }else{ - let title = `${color} ${ticketId} - ${listTickets[i].name}`; - await bot.telegram.editForumTopic(conf.supportChatId, td.threadId, { name: title }); - } - } - await editMessageText(bot, td.messageId, messageText, inKeyboard); - await editMessageText(bot, td.pinMessageId, messageText, inKeyboard); - messageData.data[ticketId].status = listTickets[i].status; - }else if(td.hasOwnProperty('threadId') && (listTickets[i].status == 5 || listTickets[i].status == 6)){ - await closeThread(bot, messageData, ticketId); - } + if(!listTickets[i] || !messageData.data.hasOwnProperty(listTickets[i].id)) continue; + await this.editTicketStatus(bot, messageData, listTickets[i].id, true); }catch(e){ - fs.appendFileSync(dir + "/../logs/logs.json", JSON.stringify("*** refreshStatus:\n" + e, null, 3)); + fs.appendFileSync(dir + "/../logs/logs.txt", e.stack); } } fs.writeFileSync(dir + "/../data/messageData.json", JSON.stringify(messageData, null, 3)); } -exports.editTicketStatus = async (bot, messageData, message) => { +exports.editTicketStatus = async (bot, messageData, ticketId, fastRequests) => { try{ - let ticketId = message.text.split('№')[1].split('\n')[0]; let ticket = await glpm.getItem('Ticket', ticketId); let inKeyboard = await getKeyboardFromStatus(ticket.status); if(messageData.data[ticketId].status != ticket.status){ - messageData.data[ticketId].status = ticket.status; let color = await getTicketColor(ticket.status); - let title = ticket.name; - if(messageData.data[ticketId].hasOwnProperty('userChatId')){ - title = `${title.split(' - ')[1]} - ${title.split(' - ')[2]}`; + let ticketAuthor = "Unknown"; + if(ticket.users_id_recipient != 0){ + let temp = await glpm.getItem("User", ticket.users_id_recipient); + ticketAuthor = temp.firstname + ' ' + temp.realname; + }else{ + let usersArray = await glpm.getUsers(ticketId); + if(usersArray[0].hasOwnProperty('alternative_email')){ + ticketAuthor = usersArray[0].alternative_email; + } } - title = `${color} ${ticketId} - ${title}`; + let messageText = await parseMessageText(ticket, ticketAuthor, color); if(messageData.data[ticketId].hasOwnProperty('threadId')){ - await bot.telegram.editForumTopic(conf.supportChatId, messageData.data[ticketId].threadId, { name: title }); + if(ticket.status == 5 || ticket.status == 6){ + await closeThread(bot, messageData, ticketId); + }else{ + let title = `${color} ${ticketId} - ${ticket.name}`; + await bot.telegram.editForumTopic(conf.supportChatId, messageData.data[ticketId].threadId, { name: title }); + await editMessageText(bot, messageData.data[ticketId].pinMessageId, messageText, inKeyboard); + } + await sleep(1000); + } + await editMessageText(bot, messageData.data[ticketId].messageId, messageText, inKeyboard); + messageData.data[ticketId].status = ticket.status; + fs.writeFileSync(dir + "/../data/messageData.json", JSON.stringify(messageData, null, 3)); + }else if(!fastRequests){ + await editMessageMarkup(bot, messageData.data[ticketId].messageId, inKeyboard); + if(messageData.data[ticketId].hasOwnProperty('threadId')){ + await editMessageMarkup(bot, messageData.data[ticketId].pinMessageId, inKeyboard); } - let messageText = await parseMessageText(message, messageData, ticketId); - await editMessageText(bot, messageData.data[ticketId].messageId, messageText, inKeyboard); - await editMessageText(bot, messageData.data[ticketId].pinMessageId, messageText, inKeyboard); } - await editMessageMarkup(bot, message.message_id, inKeyboard); - fs.writeFileSync(dir + "/../data/messageData.json", JSON.stringify(messageData, null, 3)); }catch(e){ - fs.appendFileSync(dir + "/../logs/logs.json", JSON.stringify("*** editTicketStatus:\n" + e, null, 3)); + fs.appendFileSync(dir + "/../logs/logs.txt", e.stack); } } \ No newline at end of file diff --git a/lib/glpm.js b/lib/glpm.js index f388993..e233162 100644 --- a/lib/glpm.js +++ b/lib/glpm.js @@ -26,7 +26,7 @@ exports.createTicket = async (title, description) => { }); return response.data.id; }catch(e){ - fs.appendFileSync(__dirname + "/../logs/logs.json", JSON.stringify("*** createTicket:\n" + e, null, 3)); + fs.appendFileSync(__dirname + "/../logs/logs.txt", e.stack); } } @@ -51,7 +51,7 @@ exports.changeStatusTicket = async (ticketId, statusId) => { }); return response; }catch(e){ - fs.appendFileSync(__dirname + "/../logs/logs.json", JSON.stringify("*** changeStatusTicket:\n" + e, null, 3)); + fs.appendFileSync(__dirname + "/../logs/logs.txt", e.stack); } } @@ -77,7 +77,7 @@ exports.assignTicket = async (ticketId, userId) => { }); return response.data; }catch(e){ - fs.appendFileSync(__dirname + "/../logs/logs.json", JSON.stringify("*** assignTicket:\n" + e, null, 3)); + fs.appendFileSync(__dirname + "/../logs/logs.txt", e.stack); } } @@ -96,7 +96,7 @@ exports.getItem = async(item, id) => { // ITILFollowup = комментари }); return response.data; }catch(e){ - fs.appendFileSync(__dirname + "/../logs/logs.json", JSON.stringify("*** getItem:\n" + e, null, 3)); + fs.appendFileSync(__dirname + "/../logs/logs.txt", e.stack); } } @@ -115,7 +115,7 @@ exports.getAllItems = async(item, cnt) => { }); return response.data; }catch(e){ - fs.appendFileSync(__dirname + "/../logs/logs.json", JSON.stringify("*** getAllItems:\n" + e, null, 3)); + fs.appendFileSync(__dirname + "/../logs/logs.txt", e.stack); } } @@ -141,7 +141,7 @@ exports.addComment = async(ticketId, comment) => { }); return response.data; }catch(e){ - fs.appendFileSync(__dirname + "/../logs/logs.json", JSON.stringify("*** addComment:\n" + e, null, 3)); + fs.appendFileSync(__dirname + "/../logs/logs.txt", e.stack); } } @@ -166,7 +166,7 @@ exports.removeComment = async(ticketId, commentId) => { }); return response.data; }catch(e){ - fs.appendFileSync(__dirname + "/../logs/logs.json", JSON.stringify("*** removeComment:\n" + e, null, 3)); + fs.appendFileSync(__dirname + "/../logs/logs.txt", e.stack); } } @@ -174,7 +174,7 @@ exports.getUsers = async(ticketId) => { try{ const session = await glpi.initSession(); let token = session.data.session_token; - const response = await axios(`${conf.glpiConfig.apiurl}/Ticket/${ticketId}/Ticket_User`, { + const response = await axios(`${conf.glpiConfig.apiurl}/Ticket/${ticketId}/Ticket_User`, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -185,6 +185,6 @@ exports.getUsers = async(ticketId) => { }); return response.data; }catch(e){ - fs.appendFileSync(__dirname + "/../logs/logs.json", JSON.stringify("*** getUsers:\n" + e, null, 3)); + fs.appendFileSync(__dirname + "/../logs/logs.txt", e.stack); } } \ No newline at end of file diff --git a/lib/utils.js b/lib/utils.js index c56759a..e2ff455 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -17,6 +17,7 @@ exports.htmlToText = async (text) => { delete textArray[i]; } } + // text.replace(/(\.\s)+/g, '. '); let messageText = ''; for(let k in textArray){ if(textArray[k][0] != '>' && textArray[k].trim() && textArray[k].indexOf('ts@krtech.ru писал') == -1 && textArray[k].indexOf('cellpadding="0"') == -1){ @@ -25,24 +26,33 @@ exports.htmlToText = async (text) => { } return messageText.replace(/\[.*?\]/g, ''); }catch(e){ - fs.appendFileSync(dir + "/../logs/logs.json", JSON.stringify("*** htmlToText:\n" + e, null, 3)); + fs.appendFileSync(dir + "/../logs/logs.txt", e.stack); } } -exports.parseMessageText = async (message, messageData, ticketId) => { - try{ - let color = await this.getTicketColor(messageData.data[ticketId].status); - text = message.text.split('\n'); - messageText = `${color} ЗАЯВКА №${ticketId}\n\n`; - for(let i = 2; i < text.length; i++){ - if(text[i].indexOf(':') >= 0) messageText += `${text[i].replace(':', ':')}\n`; - } - if(text[text.length - 1].indexOf("Читать дальше") >= 0){ - messageText = `${messageText.replace('Читать дальше', '')}\nЧитать дальше`; - } +exports.parseMessageText = async (ticket, ticketAuthor, color) => { + try{ + let messageText = `${color} ЗАЯВКА №${ticket.id}\n\n`; + if(ticket.users_id_recipient == conf.glpiConfig.user_id){ + let text = html.convert(he.decode(ticket.content), {preserveNewlines: true}); + let halfText = text.split("\nОписание: "); + let headers = halfText[0].split("\n"); + for(let i = 0; i < headers.length; i++){ + messageText += `${headers[i].split(": ")[0]}: ${headers[i].split(": ")[1]}\n`; + } + messageText += `Описание: ${halfText[1]}`; + }else{ + let text = await this.htmlToText(ticket.content); + messageText += `Автор заявки: ${ticketAuthor}\n`; + messageText += `Проблема: ${ticket.name}\nОписание: `; + messageText += text; + if(messageText.length > 600){ + messageText = `${messageText.substring(0, 500)} + '\n\nЧитать дальше`; + } + } return messageText; }catch(e){ - fs.appendFileSync(dir + "/../logs/logs.json", JSON.stringify("*** parseMessageText:\n" + e, null, 3)); + fs.appendFileSync(dir + "/../logs/logs.txt", e.stack); } } @@ -66,7 +76,7 @@ exports.createThread = async (bot, messageData, ticketId, title) => { messageData.data[ticketId].pinMessageId = msg.message_id; fs.writeFileSync(dir + "/../data/messageData.json", JSON.stringify(messageData, null, 3)); }catch(e){ - fs.appendFileSync(dir + "/../logs/logs.json", JSON.stringify("*** createThread:\n" + e, null, 3)); + fs.appendFileSync(dir + "/../logs/logs.txt", e.stack); } } @@ -105,7 +115,7 @@ exports.editMessageText = async (bot, messageId, messageText, keyboard) => { reply_markup: {inline_keyboard: keyboard} }); }catch(e){ - //fs.appendFileSync(dir + "/../logs/logs.json", JSON.stringify(e, null, 3)); + //fs.appendFileSync(dir + "/../logs/logs.txt", e.stack); } } @@ -113,7 +123,7 @@ exports.editMessageMarkup = async (bot, messageId, keyboard) => { try{ await bot.telegram.editMessageReplyMarkup(conf.supportChatId, messageId, undefined, {inline_keyboard: keyboard}); }catch(e){ - //fs.appendFileSync(dir + "/../logs/logs.json", JSON.stringify(e, null, 3)); + //fs.appendFileSync(dir + "/../logs/logs.txt", e.stack); } } diff --git a/package.json b/package.json index 1003a85..764b4b4 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "nodemonConfig": { "ignore": [ "./data/messageData.json", - "./logs/logs.json" + "./logs/logs.txt" ], "delay": "10" } diff --git a/telegram_support.service b/telegram_support.service index ded8ed6..59eb37a 100644 --- a/telegram_support.service +++ b/telegram_support.service @@ -1,6 +1,6 @@ [Service] User=root -ExecStart=node /root/telegram_support_bot/telegram_support_bot.js +ExecStart=node /home/telegram_support_bot/telegram_support_bot.js Restart=always [Install] diff --git a/telegram_support_bot.js b/telegram_support_bot.js index 1fc158a..6e6e0b8 100644 --- a/telegram_support_bot.js +++ b/telegram_support_bot.js @@ -146,9 +146,8 @@ bot.on('text', async (ctx) => { }catch{} if(!ticketData.hasOwnProperty(ctx.chat.id) && ticketId){ if(!messageData.data[ticketId].hasOwnProperty('threadId')){ - let ticket = await glpm.getItem('Ticket', ticketId); - let title = `🟢 ${ticketId} - ${ticket.name}`; - await createThread(bot, messageData, ticketId, title); + await ctx.reply("Эта заявка уже закрыта. Создайте, пожалуйста, новую"); + return; } if(!ctx.chat.last_name) ctx.chat.last_name = ''; let userName = ctx.chat.first_name + ' ' + ctx.chat.last_name; @@ -278,7 +277,7 @@ function createAction(action, keyboard, status){ let td = messageData.data[ticketId]; if(status || action == 'OpenThread'){ await glpm.changeStatusTicket(ticketId, status); - await editTicketStatus(bot, messageData, message); + await editTicketStatus(bot, messageData, ticketId); if(status == 6){ if(td.hasOwnProperty('userChatId')){ try{ @@ -312,15 +311,16 @@ function createAction(action, keyboard, status){ } }); }catch(e){ - fs.appendFileSync(dir + "/logs/logs.json", JSON.stringify(e, null, 3)); + fs.appendFileSync(dir + "/logs/logs.txt", e.stack); } } // Обработчик для кнопки "Отмена" -bot.action('RefreshStatus', async (ctx) => { +bot.action('RefreshTicket', async (ctx) => { let message = ctx.update.callback_query.message; - await editTicketStatus(bot, messageData, message); + let ticketId = message.text.split('№')[1].split('\n')[0]; + await editTicketStatus(bot, messageData, ticketId); }); // Обработчик для кнопки с подсказкой о добавлении комментария @@ -357,7 +357,7 @@ bot.action('ConfirmConfig', async (ctx) => { let jsonData = JSON.stringify(conf, null, 3); fs.writeFileSync(dir + "/data/conf.json", jsonData); createAssignActions(); - await deleteMessage(ctx.update.callback_query, configData.id); + await deleteMessage(conf.supportChatId, configData.id); configData = {}; await editMessageMarkup(bot, messageId, cns.inlineKeyboards.configUserGroups); } @@ -370,7 +370,7 @@ bot.action('ExitConfig', async (ctx) => { }); bot.action('CancellConfirm', async (ctx) => { - await deleteMessage(conf.supportChatId, configData.id); + await deleteMessage(ctx.update.callback_query, configData.id); configData = {}; let message = ctx.update.callback_query.message; await editMessageMarkup(bot, message.message_id, cns.inlineKeyboards.configUserGroups); @@ -390,7 +390,7 @@ bot.action('AssignTicket', async (ctx) => { keyboard[keyboard.length-1].push({text: key, callback_data: 'ButtonFor_' + key}); row++; } - keyboard[keyboard.length-1].push({text: 'Отмена', callback_data: 'RefreshStatus'}); + keyboard[keyboard.length-1].push({text: 'Отмена', callback_data: 'RefreshTicket'}); await editMessageMarkup(bot, message.message_id, keyboard); }); @@ -409,7 +409,7 @@ function createAssignActions(){ if(message.text.indexOf("⚫") < 0){ await glpm.changeStatusTicket(ticketId, 2); } - await editTicketStatus(bot, messageData, message); + await editTicketStatus(bot, messageData, ticketId); if(messageData.data[ticketId].hasOwnProperty('threadId')){ await closeThread(bot, messageData, ticketId); } @@ -436,7 +436,7 @@ bot.launch(); counter = 0; } }catch(e){ - fs.appendFileSync(dir + "/logs/logs.json", JSON.stringify(e, null, 3)); + fs.appendFileSync(dir + "/logs/logs.txt", e.stack); } await sleep(10000); counter++;