diff --git a/README.md b/README.md index 9667165..f95f454 100644 --- a/README.md +++ b/README.md @@ -76,10 +76,6 @@ services: UNIFI_IP: '192.168.1.1' # The port of your UniFi OS Console, this could be 443 or 8443 UNIFI_PORT: 443 - # The username of a local UniFi OS account - UNIFI_USERNAME: 'admin' - # The password of a local UniFi OS account - UNIFI_PASSWORD: 'password' # The API Key created on the integrations tab within UniFi OS UNIFI_TOKEN: '' # The UniFi Site ID @@ -180,8 +176,6 @@ The structure of the file should use lowercase versions of the environment varia { "unifi_ip": "192.168.1.1", "unifi_port": 443, - "unifi_username": "admin", - "unifi_password": "password", "unifi_token": "", "unifi_site_id": "default", "unifi_ssid": "", diff --git a/docker-compose.yml b/docker-compose.yml index 9be9688..db74b02 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,8 +6,6 @@ services: environment: UNIFI_IP: '192.168.1.1' UNIFI_PORT: 443 - UNIFI_USERNAME: 'admin' - UNIFI_PASSWORD: 'password' UNIFI_TOKEN: '' UNIFI_SITE_ID: 'default' UNIFI_SSID: '' diff --git a/modules/info.js b/modules/info.js index 45868a8..0325a48 100644 --- a/modules/info.js +++ b/modules/info.js @@ -134,13 +134,6 @@ module.exports = () => { */ log.info(`[UniFi] Using Controller on: ${variables.unifiIp}:${variables.unifiPort} (Site ID: ${variables.unifiSiteId}${variables.unifiSsid !== '' ? `, SSID: ${variables.unifiSsid}` : ''})`); - /** - * Check for valid UniFi username - */ - if(variables.unifiUsername.includes('@')) { - log.error('[UniFi] Incorrect username detected! UniFi Cloud credentials are not supported!'); - } - /** * Check if UniFi Token is set */ @@ -148,4 +141,9 @@ module.exports = () => { log.error('[UniFi] Integration API Key is not set within UNIFI_TOKEN environment variable!'); process.exit(1); } + + /** + * Temporary warning that guests lookup feature is unavailable + */ + log.warn('[UniFi] Guests features are temporary disabled in this version of UniFi Voucher Site (Not supported in current Integrations API). Please view and upvote: https://community.ui.com/questions/Feature-Request-Network-API-Guest-Access-Voucher-ID/d3c470e2-433d-4386-8a13-211712311202') }; diff --git a/modules/unifi.js b/modules/unifi.js index 9f84fc0..afaf986 100644 --- a/modules/unifi.js +++ b/modules/unifi.js @@ -1,77 +1,15 @@ -/** - * Import vendor modules - */ -const unifi = require('node-unifi'); - /** * Import own modules */ -const variables = require('./variables'); const log = require('./log'); const fetch = require('../utils/fetch'); -/** - * UniFi Settings - */ -const settings = { - ip: variables.unifiIp, - port: variables.unifiPort, - username: variables.unifiUsername, - password: variables.unifiPassword, - siteID: variables.unifiSiteId -}; - -/** - * Controller session - */ -let controller = null; - -/** - * Start a UniFi controller reusable session - * - * @return {Promise} - */ -const startSession = () => { - return new Promise((resolve, reject) => { - // Check if we have a current session already - if(controller !== null) { - resolve(); - return; - } - - if(settings.username.includes('@')) { - reject('[UniFi] Incorrect username detected! UniFi Cloud credentials are not supported!'); - return; - } - - // Create new UniFi controller object - controller = new unifi.Controller({ - host: settings.ip, - port: settings.port, - site: settings.siteID, - sslverify: false - }); - - // Login to UniFi Controller - controller.login(settings.username, settings.password).then(() => { - log.debug('[UniFi] Login successful!'); - resolve(); - }).catch((e) => { - // Something went wrong so clear the current controller so a user can retry - controller = null; - log.error('[UniFi] Error while logging in!'); - log.debug(e); - reject('[UniFi] Error while logging in!'); - }); - }); -} - /** * UniFi module functions * - * @type {{create: (function(*, number=, string=): Promise<*>), remove: (function(*): Promise<*>), list: (function(): Promise<*>), guests: (function(boolean=): Promise<*>)}} + * @type {{create: (function(*, number=, string=): Promise<*>), remove: (function(*): Promise<*>), list: (function(): Promise<*>), guests: (function(): Promise<*>)}} */ -const unifiModule = { +module.exports = { /** * Creates a new UniFi Voucher * @@ -171,62 +109,24 @@ const unifiModule = { /** * Returns a list with all UniFi Guests * - * @param retry * @return {Promise} */ - guests: (retry = true) => { + guests: () => { return new Promise((resolve, reject) => { // fetch('/clients', 'GET', { // filter: 'access.type.eq(\'GUEST\')', // limit: 10000 // }).then((clients) => { - // console.log(clients) + // console.log(clients); + // log.info(`[UniFi] Found ${clients.length} guest(s)`); // }).catch((e) => { - // log.error('[UniFi] Error while getting vouchers!'); + // log.error('[UniFi] Error while getting guests!'); // log.debug(e); - // reject('[UniFi] Error while getting vouchers!'); + // reject('[UniFi] Error while getting guests!'); // }); - startSession().then(() => { - controller.getGuests().then((guests) => { - log.info(`[UniFi] Found ${guests.length} guest(s)`); - resolve(guests); - }).catch((e) => { - log.error('[UniFi] Error while getting guests!'); - log.debug(e); - - // Check if token expired, if true attempt login then try again - if (e.response) { - if(e.response.status === 401 && retry) { - log.info('[UniFi] Attempting re-authentication & retry...'); - - controller = null; - unifiModule.guests(false).then((e) => { - resolve(e); - }).catch((e) => { - reject(e); - }); - } else { - // Something else went wrong lets clear the current controller so a user can retry - log.error(`[UniFi] Unexpected ${JSON.stringify({status: e.response.status, retry})} cleanup controller...`); - controller = null; - reject('[UniFi] Error while getting guests!'); - } - } else { - // Something else went wrong lets clear the current controller so a user can retry - log.error('[UniFi] Unexpected cleanup controller...'); - controller = null; - reject('[UniFi] Error while getting guests!'); - } - }); - }).catch((e) => { - reject(e); - }); + // Currently disabled! Waiting on: https://community.ui.com/questions/Feature-Request-Network-API-Guest-Access-Voucher-ID/d3c470e2-433d-4386-8a13-211712311202 + resolve([]); }); } } - -/** - * Exports the UniFi module functions - */ -module.exports = unifiModule; diff --git a/modules/variables.js b/modules/variables.js index d6a4639..5b4349a 100644 --- a/modules/variables.js +++ b/modules/variables.js @@ -14,8 +14,6 @@ const config = require('./config'); module.exports = { unifiIp: config('unifi_ip') || process.env.UNIFI_IP || '192.168.1.1', unifiPort: config('unifi_port') || process.env.UNIFI_PORT || 443, - unifiUsername: config('unifi_username') || process.env.UNIFI_USERNAME || 'admin', - unifiPassword: config('unifi_password') || process.env.UNIFI_PASSWORD || 'password', unifiToken: config('unifi_token') || process.env.UNIFI_TOKEN || '', unifiSiteId: config('unifi_site_id') || process.env.UNIFI_SITE_ID || 'default', unifiSsid: config('unifi_ssid') || process.env.UNIFI_SSID || '', diff --git a/package-lock.json b/package-lock.json index fa7ed4e..d387dbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,6 @@ "jsonwebtoken": "^9.0.2", "multer": "^2.0.2", "node-thermal-printer": "^4.5.0", - "node-unifi": "^2.5.1", "nodemailer": "^7.0.5", "pdfkit": "^0.17.1", "qrcode": "^1.5.4", @@ -33,17 +32,6 @@ "node": ">=22.0.0" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -877,15 +865,6 @@ "node": ">= 0.6" } }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -923,22 +902,6 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1301,17 +1264,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1453,14 +1405,6 @@ "node": ">=10" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1598,21 +1542,6 @@ "node": ">= 0.4" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -1628,11 +1557,6 @@ "node": ">= 0.6" } }, - "node_modules/eventemitter2": { - "version": "6.4.9", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", - "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" - }, "node_modules/express": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", @@ -1871,25 +1795,6 @@ "node": ">=8" } }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/fontkit": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz", @@ -1907,22 +1812,6 @@ "unicode-trie": "^2.0.0" } }, - "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "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.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2082,21 +1971,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -2889,64 +2763,6 @@ "write-file-queue": "0.0.1" } }, - "node_modules/node-unifi": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/node-unifi/-/node-unifi-2.5.1.tgz", - "integrity": "sha512-mYLJFNKhONaXIFU2PeQ+p1fjr6C3q/Na8XyhZXpGalOArCAJLzpAoWl1rg9ZbmuJiVqwprqCq3u9Srn23CcpuA==", - "dependencies": { - "axios": "1.6.2", - "eventemitter2": "^6.4.9", - "http-cookie-agent": "^5.0.4", - "tough-cookie": "^4.1.3", - "url": "^0.11.3", - "ws": "^8.14.2" - }, - "engines": { - "node": ">=14.18.0 <15.0.0 || >=16.0.0" - } - }, - "node_modules/node-unifi/node_modules/http-cookie-agent": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/http-cookie-agent/-/http-cookie-agent-5.0.4.tgz", - "integrity": "sha512-OtvikW69RvfyP6Lsequ0fN5R49S+8QcS9zwd58k6VSr6r57T8G29BkPdyrBcSwLq6ExLs9V+rBlfxu7gDstJag==", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0" - }, - "engines": { - "node": ">=14.18.0 <15.0.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/3846masa" - }, - "peerDependencies": { - "deasync": "^0.1.26", - "tough-cookie": "^4.0.0", - "undici": "^5.11.0" - }, - "peerDependenciesMeta": { - "deasync": { - "optional": true - }, - "undici": { - "optional": true - } - } - }, - "node_modules/node-unifi/node_modules/undici": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, - "engines": { - "node": ">=14.0" - } - }, "node_modules/nodemailer": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.5.tgz", @@ -3193,11 +3009,6 @@ "node": ">= 0.10" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -3650,24 +3461,6 @@ "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" }, - "node_modules/tldts": { - "version": "6.1.78", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.78.tgz", - "integrity": "sha512-fSgYrW0ITH0SR/CqKMXIruYIPpNu5aDgUp22UhYoSrnUQwc7SBqifEBFNce7AAcygUPBo6a/gbtcguWdmko4RQ==", - "license": "MIT", - "dependencies": { - "tldts-core": "^6.1.78" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "node_modules/tldts-core": { - "version": "6.1.78", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.78.tgz", - "integrity": "sha512-jS0svNsB99jR6AJBmfmEWuKIgz91Haya91Z43PATaeHJ24BkMoNRb/jlaD37VYjb0mYf6gRL/HOnvS1zEnYBiw==", - "license": "MIT" - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3689,18 +3482,6 @@ "node": ">=0.6" } }, - "node_modules/tough-cookie": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", - "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", - "license": "BSD-3-Clause", - "dependencies": { - "tldts": "^6.1.32" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -3777,26 +3558,12 @@ "node": ">= 0.8" } }, - "node_modules/url": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", - "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", - "dependencies": { - "punycode": "^1.4.1", - "qs": "^6.11.2" - } - }, "node_modules/url-join": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "license": "MIT" }, - "node_modules/url/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -3832,26 +3599,6 @@ "dank-do-while": "^0.1.2" } }, - "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 6a4fb21..fc03d36 100644 --- a/package.json +++ b/package.json @@ -14,12 +14,6 @@ }, "author": "Glenn de Haan", "license": "MIT", - "overrides": { - "node-unifi@^2.5.1": { - "axios": "1.11.0", - "tough-cookie": "5.1.2" - } - }, "dependencies": { "cookie-parser": "^1.4.7", "ejs": "^3.1.10", @@ -30,7 +24,6 @@ "jsonwebtoken": "^9.0.2", "multer": "^2.0.2", "node-thermal-printer": "^4.5.0", - "node-unifi": "^2.5.1", "nodemailer": "^7.0.5", "pdfkit": "^0.17.1", "qrcode": "^1.5.4",