Update send zulip
This commit is contained in:
parent
a363883329
commit
4e5099aea8
|
|
@ -22,4 +22,7 @@ export default class Scenario extends BaseModel {
|
||||||
|
|
||||||
@column.dateTime({ autoCreate: true, autoUpdate: true })
|
@column.dateTime({ autoCreate: true, autoUpdate: true })
|
||||||
declare updatedAt: DateTime
|
declare updatedAt: DateTime
|
||||||
|
|
||||||
|
@column()
|
||||||
|
declare send_result: boolean
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,4 +82,7 @@ export default class Station extends BaseModel {
|
||||||
|
|
||||||
@column()
|
@column()
|
||||||
declare send_wiki: boolean
|
declare send_wiki: boolean
|
||||||
|
|
||||||
|
@column()
|
||||||
|
declare is_active: boolean
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ export default class LineConnection {
|
||||||
if (!this.config.inventory)
|
if (!this.config.inventory)
|
||||||
this.outputInventory = this.outputInventory.slice(-3000) + message
|
this.outputInventory = this.outputInventory.slice(-3000) + message
|
||||||
}
|
}
|
||||||
if (message.includes('--More--')) this.writeCommand(' ')
|
if (data.toString().includes('--More--')) this.writeCommand(' ')
|
||||||
|
|
||||||
// let output = cleanData(message)
|
// let output = cleanData(message)
|
||||||
// console.log(`📨 [${this.config.port}] ${message}`)
|
// console.log(`📨 [${this.config.port}] ${message}`)
|
||||||
|
|
@ -735,19 +735,23 @@ export default class LineConnection {
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: `Bạn là chuyên gia phân tích log thiết bị mạng.
|
content: `You are a network hardware tester.
|
||||||
Hãy phân tích đoạn log sau và xuất kết quả theo đúng format:
|
Your task is to analyze router/switch logs to determine whether the device meets hardware standards for reselling.
|
||||||
Yêu cầu đầu ra đúng cấu trúc:
|
Focus ONLY on hardware-related problems or abnormal warnings.
|
||||||
issue:
|
Software or configuration issues (e.g., port up/down, admin down, invalid commands, CLI errors, licensing messages) should be ignored unless they indicate hardware failure.
|
||||||
(Tóm tắt ngắn gọn các lỗi/dấu hiệu bất thường, mỗi vấn đề 1 dòng, bỏ qua các vấn đề không quan trọng như về port up/down hay Invalid input, Incomplete command)
|
OUTPUT FORMAT (must follow exactly):
|
||||||
|
{
|
||||||
Quy tắc:
|
"issue": [ "problem 1", "problem 2", ... ],
|
||||||
Không giải thích dài dòng.
|
"summary": "short summary under 30 words"
|
||||||
tập trung vào lỗi phần cứng, cảnh báo bất thường
|
}
|
||||||
Nếu log không có lỗi → ghi rõ "No issues detected.".
|
RULES:
|
||||||
|
- Summaries must be in English.
|
||||||
Ngắn gọn, dễ đọc, đúng format
|
- Each issue must be one short line.
|
||||||
Return only json format with English.
|
- If the log contains no hardware issues, output: { "issue": ["No issues detected."], "summary": "No hardware issues found." }
|
||||||
|
- Keep responses concise, readable, and strictly in JSON format.
|
||||||
|
- Do NOT add explanations outside the JSON.
|
||||||
|
- Your job is to detect hardware faults, missing components, overheating, failing modules, PSU issues, sensor anomalies, SIM/card missing, modem errors, transceiver issues, POST/diagnostics failures, etc.
|
||||||
|
The log to analyze will be provided after this prompt.
|
||||||
|
|
||||||
Here is the log:
|
Here is the log:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,13 +73,13 @@ export default class SwitchController {
|
||||||
this.isEnable = false
|
this.isEnable = false
|
||||||
this.onData(this.portGroups, this.status)
|
this.onData(this.portGroups, this.status)
|
||||||
if (this.retryConnect <= 5) {
|
if (this.retryConnect <= 5) {
|
||||||
await this.sleep(15000)
|
|
||||||
console.log('Retry connect times', this.retryConnect)
|
|
||||||
this.retryConnect += 1
|
|
||||||
await this.reconnect()
|
|
||||||
} else {
|
|
||||||
this.retryConnect = 0
|
this.retryConnect = 0
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
await this.sleep(15000)
|
||||||
|
console.log('SWITCH Retry connect times', this.retryConnect)
|
||||||
|
this.retryConnect += 1
|
||||||
|
await this.reconnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleError(err: Error & { code?: string }) {
|
private _handleError(err: Error & { code?: string }) {
|
||||||
|
|
@ -145,7 +145,8 @@ export default class SwitchController {
|
||||||
}
|
}
|
||||||
|
|
||||||
public disconnect() {
|
public disconnect() {
|
||||||
this.socket.end()
|
// this.socket.end()
|
||||||
|
this.socket.destroy()
|
||||||
this.status = 'DISCONNECTED'
|
this.status = 'DISCONNECTED'
|
||||||
this.isEnable = false
|
this.isEnable = false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import nodeMailer from 'nodemailer'
|
import nodeMailer from 'nodemailer'
|
||||||
|
import zulip from 'zulip-js'
|
||||||
|
|
||||||
type DetectAI = {
|
type DetectAI = {
|
||||||
status: string[]
|
status: string[]
|
||||||
|
|
@ -18,6 +19,7 @@ type InputData = {
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
type SendMailResponse = string
|
type SendMailResponse = string
|
||||||
|
type SendMessageType = 'stream' | 'private'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to clean up unwanted characters from the output data.
|
* Function to clean up unwanted characters from the output data.
|
||||||
|
|
@ -247,3 +249,53 @@ export function sendMessageToMail(
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function sendMessageToZulip(
|
||||||
|
type: SendMessageType,
|
||||||
|
to: string | number | string[],
|
||||||
|
topic: string | undefined,
|
||||||
|
content: string
|
||||||
|
): Promise<any> | null {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const config = {
|
||||||
|
realm: process.env.ZULIP_REALM as string,
|
||||||
|
username: process.env.ZULIP_USERNAME as string,
|
||||||
|
apiKey: process.env.ZULIP_API_KEY as string,
|
||||||
|
}
|
||||||
|
|
||||||
|
zulip(config).then((client: any) => {
|
||||||
|
if (type === 'stream') {
|
||||||
|
client.messages
|
||||||
|
.send({
|
||||||
|
type,
|
||||||
|
to,
|
||||||
|
topic: topic || '',
|
||||||
|
content,
|
||||||
|
})
|
||||||
|
.then((response: any) => {
|
||||||
|
console.log('Message sent: ' + JSON.stringify(response))
|
||||||
|
resolve(response)
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error(error)
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
} else if (type === 'private') {
|
||||||
|
client.messages
|
||||||
|
.send({
|
||||||
|
type,
|
||||||
|
to,
|
||||||
|
content,
|
||||||
|
})
|
||||||
|
.then((response: any) => {
|
||||||
|
console.log('Message sent: ' + JSON.stringify(response))
|
||||||
|
resolve(response)
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error(error)
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { BaseSchema } from '@adonisjs/lucid/schema'
|
||||||
|
|
||||||
|
export default class extends BaseSchema {
|
||||||
|
protected tableName = 'stations'
|
||||||
|
|
||||||
|
async up() {
|
||||||
|
this.schema.alterTable(this.tableName, (table) => {
|
||||||
|
table.boolean('is_active').defaultTo(true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async down() {
|
||||||
|
this.schema.alterTable(this.tableName, (table) => {
|
||||||
|
table.dropColumn('is_active')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { BaseSchema } from '@adonisjs/lucid/schema'
|
||||||
|
|
||||||
|
export default class extends BaseSchema {
|
||||||
|
protected tableName = 'scenarios'
|
||||||
|
|
||||||
|
async up() {
|
||||||
|
this.schema.alterTable(this.tableName, (table) => {
|
||||||
|
table.boolean('send_result').defaultTo(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async down() {
|
||||||
|
this.schema.alterTable(this.tableName, (table) => {
|
||||||
|
table.dropColumn('send_result')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,7 +24,8 @@
|
||||||
"nodemailer": "^7.0.9",
|
"nodemailer": "^7.0.9",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"socket.io": "^4.8.1",
|
"socket.io": "^4.8.1",
|
||||||
"xregexp": "^5.1.2"
|
"xregexp": "^5.1.2",
|
||||||
|
"zulip-js": "^2.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@adonisjs/assembler": "^7.8.2",
|
"@adonisjs/assembler": "^7.8.2",
|
||||||
|
|
@ -1417,6 +1418,15 @@
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/runtime": {
|
||||||
|
"version": "7.28.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
|
||||||
|
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/runtime-corejs3": {
|
"node_modules/@babel/runtime-corejs3": {
|
||||||
"version": "7.28.4",
|
"version": "7.28.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.4.tgz",
|
||||||
|
|
@ -6149,6 +6159,15 @@
|
||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/ini": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ini/-/ini-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || >=20.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/interpret": {
|
"node_modules/interpret": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
|
||||||
|
|
@ -6320,6 +6339,63 @@
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/isomorphic-fetch": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": "^2.6.1",
|
||||||
|
"whatwg-fetch": "^3.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/isomorphic-form-data": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isomorphic-form-data/-/isomorphic-form-data-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-TYgVnXWeESVmQSg4GLVbalmQ+B4NPi/H4eWxqALKj63KsUrcu301YDjBqaOw3h+cbak7Na4Xyps3BiptHtxTfg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"form-data": "^2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/isomorphic-form-data/node_modules/form-data": {
|
||||||
|
"version": "2.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz",
|
||||||
|
"integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"mime-types": "^2.1.35",
|
||||||
|
"safe-buffer": "^5.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/isomorphic-form-data/node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/isomorphic-form-data/node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jest-diff": {
|
"node_modules/jest-diff": {
|
||||||
"version": "30.2.0",
|
"version": "30.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz",
|
||||||
|
|
@ -6964,6 +7040,26 @@
|
||||||
"integrity": "sha512-kbhcj2SVVR4caaVnGLJKmlk2+f+oLkjqdKeQlmUtz6nGzOpbcobwVIeSURNgraV/v3tlmGIX82OcPCl0K6RbHQ==",
|
"integrity": "sha512-kbhcj2SVVR4caaVnGLJKmlk2+f+oLkjqdKeQlmUtz6nGzOpbcobwVIeSURNgraV/v3tlmGIX82OcPCl0K6RbHQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-releases": {
|
"node_modules/node-releases": {
|
||||||
"version": "2.0.26",
|
"version": "2.0.26",
|
||||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.26.tgz",
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.26.tgz",
|
||||||
|
|
@ -8724,6 +8820,12 @@
|
||||||
"url": "https://github.com/sponsors/Borewit"
|
"url": "https://github.com/sponsors/Borewit"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tr46": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/truncatise": {
|
"node_modules/truncatise": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/truncatise/-/truncatise-0.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/truncatise/-/truncatise-0.0.8.tgz",
|
||||||
|
|
@ -9025,6 +9127,28 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/webidl-conversions": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/whatwg-fetch": {
|
||||||
|
"version": "3.6.20",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
|
||||||
|
"integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/whatwg-url": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tr46": "~0.0.3",
|
||||||
|
"webidl-conversions": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
|
|
@ -9265,6 +9389,18 @@
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zulip-js": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/zulip-js/-/zulip-js-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-kLdxzJZ/FvWHBotUJl7LXCHIkShTjy1FUk5HAWfsal1TM+hw0atCZwgasCpvFDBj01y+39ZEZXgjePaie74Xhg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.25.7",
|
||||||
|
"ini": "^5.0.0",
|
||||||
|
"isomorphic-fetch": "^3.0.0",
|
||||||
|
"isomorphic-form-data": "2.0.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,8 @@
|
||||||
"nodemailer": "^7.0.9",
|
"nodemailer": "^7.0.9",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"socket.io": "^4.8.1",
|
"socket.io": "^4.8.1",
|
||||||
"xregexp": "^5.1.2"
|
"xregexp": "^5.1.2",
|
||||||
|
"zulip-js": "^2.1.0"
|
||||||
},
|
},
|
||||||
"hotHook": {
|
"hotHook": {
|
||||||
"boundaries": [
|
"boundaries": [
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,13 @@ import { CustomServer, CustomSocket } from '../app/ultils/types.js'
|
||||||
import Line from '#models/line'
|
import Line from '#models/line'
|
||||||
import Station from '#models/station'
|
import Station from '#models/station'
|
||||||
import APCController from '#services/apc_connection'
|
import APCController from '#services/apc_connection'
|
||||||
import { appendLog, cleanData, sendMessageToMail, sleep } from '../app/ultils/helper.js'
|
import {
|
||||||
|
appendLog,
|
||||||
|
cleanData,
|
||||||
|
sendMessageToMail,
|
||||||
|
sendMessageToZulip,
|
||||||
|
sleep,
|
||||||
|
} from '../app/ultils/helper.js'
|
||||||
import SwitchController from '#services/switch_connection'
|
import SwitchController from '#services/switch_connection'
|
||||||
import redis from '@adonisjs/redis/services/main'
|
import redis from '@adonisjs/redis/services/main'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
@ -554,6 +560,7 @@ export class WebSocketIo {
|
||||||
|
|
||||||
const results = await this.waitUntilAllReady(lineIds)
|
const results = await this.waitUntilAllReady(lineIds)
|
||||||
const tableHTML = this.generateTable(results)
|
const tableHTML = this.generateTable(results)
|
||||||
|
const zulipMess = this.generateZulipMessage(results)
|
||||||
|
|
||||||
const timeZone = process.env.TIME_ZONE || 'Australia/Sydney'
|
const timeZone = process.env.TIME_ZONE || 'Australia/Sydney'
|
||||||
const dataFormat = momentTZ().tz(timeZone).format('YYYY/MM/DD, HH:mm:ss')
|
const dataFormat = momentTZ().tz(timeZone).format('YYYY/MM/DD, HH:mm:ss')
|
||||||
|
|
@ -562,14 +569,20 @@ export class WebSocketIo {
|
||||||
process.env.LINK_WIKI || 'https://logs.danielvu.com/api/wiki/page/insert?title=Dev_test'
|
process.env.LINK_WIKI || 'https://logs.danielvu.com/api/wiki/page/insert?title=Dev_test'
|
||||||
await axios.post(linkWiki, {
|
await axios.post(linkWiki, {
|
||||||
data: tableHTML,
|
data: tableHTML,
|
||||||
titleAuto: `[DPELP] Report AUTO - ${stationName} - ` + dataFormat,
|
titleAuto: `[DPELP] - ${stationName} - ` + dataFormat,
|
||||||
})
|
})
|
||||||
await sendMessageToMail(
|
await sendMessageToMail(
|
||||||
'andrew.ng@apactech.io',
|
'andrew.ng@apactech.io',
|
||||||
`[DPELP] Report AUTO - ${stationName} - ${dataFormat}`,
|
`[DPELP] - ${stationName} - ${dataFormat}`,
|
||||||
tableHTML,
|
tableHTML,
|
||||||
['ips@ipsupply.com.au', 'kay@ipsupply.com.au', 'joseph@apactech.io']
|
['ips@ipsupply.com.au', 'kay@ipsupply.com.au', 'joseph@apactech.io']
|
||||||
)
|
)
|
||||||
|
await sendMessageToZulip(
|
||||||
|
'stream',
|
||||||
|
'ATC_Report',
|
||||||
|
station.name,
|
||||||
|
`\n\n---\n[DPELP] - ${stationName} - ${dataFormat}\n` + zulipMess
|
||||||
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
}
|
}
|
||||||
|
|
@ -655,6 +668,10 @@ export class WebSocketIo {
|
||||||
clearInterval(this.intervalMap[`${lineId}`])
|
clearInterval(this.intervalMap[`${lineId}`])
|
||||||
delete this.intervalMap[`${lineId}`]
|
delete this.intervalMap[`${lineId}`]
|
||||||
}
|
}
|
||||||
|
if (this.intervalKeepConnect[`${lineId}`]) {
|
||||||
|
clearInterval(this.intervalKeepConnect[`${lineId}`])
|
||||||
|
delete this.intervalKeepConnect[`${lineId}`]
|
||||||
|
}
|
||||||
}, timeout)
|
}, timeout)
|
||||||
|
|
||||||
this.intervalMap[`${lineId}`] = interval
|
this.intervalMap[`${lineId}`] = interval
|
||||||
|
|
@ -1067,6 +1084,44 @@ export class WebSocketIo {
|
||||||
return html
|
return html
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a Zulip-compatible Markdown table string from the results array.
|
||||||
|
* Uses <br> to force line breaks within the License cell.
|
||||||
|
* @param {Array<Object>} results - The array of data objects.
|
||||||
|
* @returns {string} The Markdown table string.
|
||||||
|
*/
|
||||||
|
generateZulipMessage(results: any[]) {
|
||||||
|
let msg = ''
|
||||||
|
|
||||||
|
for (const item of results) {
|
||||||
|
if (!item) continue
|
||||||
|
|
||||||
|
const licenses = Array.isArray(item.license)
|
||||||
|
? [...new Set(item.license)]
|
||||||
|
: item.license
|
||||||
|
? [item.license]
|
||||||
|
: []
|
||||||
|
|
||||||
|
const issues = item.issues || []
|
||||||
|
|
||||||
|
msg += `**Line ${item.line || '?'} — ${item.pid || ''}${item.vid ? ` (${item.vid})` : ''} `
|
||||||
|
msg += `**SN:** **${item.sn || ''}** \n`
|
||||||
|
msg += '```' + `\n`
|
||||||
|
|
||||||
|
msg += `MAC: ${item.mac || ''} \n`
|
||||||
|
msg += `IOS: ${item.ios || ''} \n`
|
||||||
|
|
||||||
|
msg += `License: ${licenses.join(', ') || ''} \n`
|
||||||
|
msg += `Issues: \n`
|
||||||
|
if (issues.length) {
|
||||||
|
for (const i of issues) msg += `• ${i} \n`
|
||||||
|
} else msg += `• No issues detected.\n`
|
||||||
|
msg += '```\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
private async connectStation(station: Station) {
|
private async connectStation(station: Station) {
|
||||||
try {
|
try {
|
||||||
const stationConn = new StationConnection({
|
const stationConn = new StationConnection({
|
||||||
|
|
@ -1081,6 +1136,7 @@ export class WebSocketIo {
|
||||||
await stationConn.connect()
|
await stationConn.connect()
|
||||||
stationConn.writeCommand('\r\n')
|
stationConn.writeCommand('\r\n')
|
||||||
this.setTimeoutConnect(station.id, stationConn)
|
this.setTimeoutConnect(station.id, stationConn)
|
||||||
|
this.keepConnectStation(station.id)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
}
|
}
|
||||||
|
|
@ -1120,4 +1176,21 @@ export class WebSocketIo {
|
||||||
console.log('Station connect error:', err.message)
|
console.log('Station connect error:', err.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private keepConnectStation = (id: number) => {
|
||||||
|
if (this.intervalKeepConnect[`${id}`]) {
|
||||||
|
clearInterval(this.intervalKeepConnect[`${id}`])
|
||||||
|
delete this.intervalKeepConnect[`${id}`]
|
||||||
|
}
|
||||||
|
const interval = setInterval(async () => {
|
||||||
|
const station = this.stationMap.get(id)
|
||||||
|
if (station) {
|
||||||
|
await this.handleStationOperation(id, async (stationCon) => {
|
||||||
|
stationCon.writeCommand(`\r\n`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, 120000)
|
||||||
|
|
||||||
|
this.intervalKeepConnect[`${id}`] = interval
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ export default function InputHistory({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TextInput
|
<TextInput
|
||||||
|
ref={inputRef}
|
||||||
style={{
|
style={{
|
||||||
width: "30vw",
|
width: "30vw",
|
||||||
boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)",
|
boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue