oldCode: 旧LINEWORKS/Pleasanter連携コード一式を追加

express/LINEWORKS_Pleasanter/LINEWORKS_sendMessage、いずれも過去の
Express実装。Gitea移行に伴い保管。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Kenichiro NOGI 2026-09-05 10:42:21 +09:00
parent 5abf932fa6
commit 06c28e8b5a
35 changed files with 5310 additions and 0 deletions

View File

@ -0,0 +1,836 @@
{
"name": "LINEWORKS_Pleasanter",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"body-parser": "^2.2.0",
"cors": "^2.8.5",
"express": "^5.1.0"
}
},
"node_modules/accepts": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
"integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
"license": "MIT",
"dependencies": {
"mime-types": "^3.0.0",
"negotiator": "^1.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/body-parser": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
"integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
"license": "MIT",
"dependencies": {
"bytes": "^3.1.2",
"content-type": "^1.0.5",
"debug": "^4.4.0",
"http-errors": "^2.0.0",
"iconv-lite": "^0.6.3",
"on-finished": "^2.4.1",
"qs": "^6.14.0",
"raw-body": "^3.0.0",
"type-is": "^2.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/call-bound": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/content-disposition": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
"integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
"license": "MIT",
"dependencies": {
"safe-buffer": "5.2.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/content-type": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
"license": "MIT",
"engines": {
"node": ">=6.6.0"
}
},
"node_modules/cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"license": "MIT",
"dependencies": {
"object-assign": "^4",
"vary": "^1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/debug": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"license": "MIT"
},
"node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"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",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"license": "MIT"
},
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
"license": "MIT",
"dependencies": {
"accepts": "^2.0.0",
"body-parser": "^2.2.0",
"content-disposition": "^1.0.0",
"content-type": "^1.0.5",
"cookie": "^0.7.1",
"cookie-signature": "^1.2.1",
"debug": "^4.4.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"finalhandler": "^2.1.0",
"fresh": "^2.0.0",
"http-errors": "^2.0.0",
"merge-descriptors": "^2.0.0",
"mime-types": "^3.0.0",
"on-finished": "^2.4.1",
"once": "^1.4.0",
"parseurl": "^1.3.3",
"proxy-addr": "^2.0.7",
"qs": "^6.14.0",
"range-parser": "^1.2.1",
"router": "^2.2.0",
"send": "^1.1.0",
"serve-static": "^2.2.0",
"statuses": "^2.0.1",
"type-is": "^2.0.1",
"vary": "^1.1.2"
},
"engines": {
"node": ">= 18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/finalhandler": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
"integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
"license": "MIT",
"dependencies": {
"debug": "^4.4.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"on-finished": "^2.4.1",
"parseurl": "^1.3.3",
"statuses": "^2.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/fresh": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"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",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"license": "MIT",
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
"license": "MIT",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/is-promise": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
"license": "MIT"
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/media-typer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
"integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/merge-descriptors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
"integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/mime-db": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
"license": "MIT",
"dependencies": {
"mime-db": "^1.54.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/negotiator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
"license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/path-to-regexp": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
"integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
"license": "MIT",
"engines": {
"node": ">=16"
}
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"license": "MIT",
"dependencies": {
"forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/raw-body": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
"integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.6.3",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/router": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
"integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
"license": "MIT",
"dependencies": {
"debug": "^4.4.0",
"depd": "^2.0.0",
"is-promise": "^4.0.0",
"parseurl": "^1.3.3",
"path-to-regexp": "^8.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/send": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
"integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
"license": "MIT",
"dependencies": {
"debug": "^4.3.5",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"fresh": "^2.0.0",
"http-errors": "^2.0.0",
"mime-types": "^3.0.1",
"ms": "^2.1.3",
"on-finished": "^2.4.1",
"range-parser": "^1.2.1",
"statuses": "^2.0.1"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/serve-static": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
"integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
"license": "MIT",
"dependencies": {
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"parseurl": "^1.3.3",
"send": "^1.2.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
},
"node_modules/side-channel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3",
"side-channel-list": "^1.0.0",
"side-channel-map": "^1.0.1",
"side-channel-weakmap": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-list": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-map": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-weakmap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3",
"side-channel-map": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"license": "MIT",
"engines": {
"node": ">=0.6"
}
},
"node_modules/type-is": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
"license": "MIT",
"dependencies": {
"content-type": "^1.0.5",
"media-typer": "^1.1.0",
"mime-types": "^3.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
}
}
}

View File

@ -0,0 +1,7 @@
{
"dependencies": {
"body-parser": "^2.2.0",
"cors": "^2.8.5",
"express": "^5.1.0"
}
}

View File

@ -0,0 +1,45 @@
const express = require('express');
const cors = require('cors');
const https = require('https');
const fs = require('fs');
const API_KEY = 'pgqhLFWbDFu4Byz#4afNYX2F6Fa1&$KPjved$8%sUdTQV52caip#EpIKxYUkdd4S'; // 任意のAPIキーを設定
const app = express();
app.use(cors({
origin: [
'https://neo999.next-hd.net',
'https://nextoffice.next-hd.co.jp',
], // 許可するオリジン
optionsSuccessStatus: 200
}));
// APIエンドポイント
app.post('/server', (req, res) => {
let rawBody = '';
req.on('data', (chunk) => {
rawBody += chunk; // リクエストデータをそのまま取得
});
req.on('end', () => {
// APIキーの検証
const apiKey = req.headers['x-api-key'];
if (!apiKey || apiKey !== API_KEY) {
return res.status(401).json({ error: 'APIキーが不正です' });
}
console.log('Headers:', req.headers); // ヘッダーを出力
console.log('Raw Body:', rawBody); // パースせずにそのまま出力
res.json({ message: 'リクエストを受け付けました', rawBody });
});
});
// HTTPSサーバー起動
const PORT = 30399;
const sslOptions = {
cert: fs.readFileSync('/etc/letsencrypt/live/neo999.next-hd.net/fullchain.pem'),
key: fs.readFileSync('/etc/letsencrypt/live/neo999.next-hd.net/privkey.pem')
};
https.createServer(sslOptions, app).listen(PORT, () => {
console.log(`APIサーバー起動: https://neo999.next-hd.net:${PORT}/server`);
});

View File

@ -0,0 +1,36 @@
//lwSendMessage.jsにAPIリクエストを送信するクライアントサンプル
//node実行する場合は下記が必要
const fetch = require('node-fetch');
//ブラウザスクリプトにする場合は下記から
//API-KEYは下記固定
const API_KEY = 'pgqhLFWbDFu4Byz#4afNYX2F6Fa1&$KPjved$8%sUdTQV52caip#EpIKxYUkdd4S'; // 任意のAPIキーを設定
//CORSには本番用・開発用の両方のプリザンターアドレスを登録してあるので
//どちらの環境からでも実行可能
async function sendMessageToLineworks() {
const apiUrl = 'https://neo999.next-hd.net:30309/lwSendMessage';
const body = {
botId: '10130468', //新しいBotを作ったらここでIDを変更
userId: 'k.nogi@works-nextgroup2',
messageText: 'テストメッセージ'
};
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': API_KEY // ここにAPIキーを追加
},
body: JSON.stringify(body)
});
if (response.ok) {
const result = await response.json();
console.log('APIレスポンス:', result);
} else {
console.error('APIリクエスト失敗:', await response.text());
}
}
sendMessageToLineworks();

View File

@ -0,0 +1,72 @@
//
exports.sendLineworksMessage = async (botId, userId, messageText) => {
//アクセストークンの取得
const accessToken = await getAccessToken();
if (!accessToken) return;
const apiUrl = `https://www.worksapis.com/v1.0/bots/${botId}/users/${userId}/messages`;
const body = {
'content': {
'type': 'text',
'text': messageText
}
};
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify(body)
});
if (response.ok) {
console.log('送信成功');
} else {
console.error('送信失敗', await response.text());
}
};
// アクセストークン取得
async function getAccessToken() {
const clientId = 'V58hNobcAqRcQPerySMz';
const clientSecret = 'gJ84XQtigD';
const serviceAccount = 'x94xh.serviceaccount@works-nextgroup2';
const privateKey = fs.readFileSync('./private_20250530180606.key', 'utf8');
const apiUrl = 'https://auth.worksmobile.com/oauth2/v2.0/token';
const now = Math.floor(Date.now() / 1000);
// JWT生成
const payload = {
'iss': clientId,
'sub': serviceAccount,
'iat': now,
'exp': now + 60 * 5,
'aud': apiUrl
};
const assertion = jwt.sign(payload, privateKey, { 'algorithm': 'RS256' });
const body = new URLSearchParams({
'assertion': assertion,
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'client_id': clientId,
'client_secret': clientSecret,
'scope': 'bot'
});
const response = await fetch(apiUrl, {
'method': 'POST',
'headers': { 'Content-Type': 'application/x-www-form-urlencoded' },
'body': body.toString()
});
if (response.ok) {
const data = await response.json();
return data.access_token;
} else {
console.error('アクセストークン取得失敗:', await response.text());
return null;
}
}

View File

@ -0,0 +1,142 @@
// Node.jsでLINE WORKSのBot APIを使って特定ユーザーにメッセージを送信するサンプルHTTPS対応
const express = require('express');
const bodyParser = require('body-parser');
const fetch = require('node-fetch');
const jwt = require('jsonwebtoken');
const fs = require('fs');
const https = require('https');
const cors = require('cors'); // 追加
const app = express();
app.use(cors({
origin: [
'https://neo999.next-hd.net',
'https://nextoffice.next-hd.co.jp',
], // 許可するオリジン
optionsSuccessStatus: 200
}));
//app.use(bodyParser.json());
const API_KEY = 'pgqhLFWbDFu4Byz#4afNYX2F6Fa1&$KPjved$8%sUdTQV52caip#EpIKxYUkdd4S'; // 任意のAPIキーを設定
// アクセストークン取得
async function getAccessToken() {
const clientId = 'V58hNobcAqRcQPerySMz';
const clientSecret = 'gJ84XQtigD';
const serviceAccount = 'x94xh.serviceaccount@works-nextgroup2';
const privateKey = fs.readFileSync('./private_20250530180606.key', 'utf8');
const apiUrl = 'https://auth.worksmobile.com/oauth2/v2.0/token';
const now = Math.floor(Date.now() / 1000);
// JWT生成
const payload = {
'iss': clientId,
'sub': serviceAccount,
'iat': now,
'exp': now + 60 * 5,
'aud': apiUrl
};
const assertion = jwt.sign(payload, privateKey, { 'algorithm': 'RS256' });
const body = new URLSearchParams({
'assertion': assertion,
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'client_id': clientId,
'client_secret': clientSecret,
'scope': 'bot'
});
const response = await fetch(apiUrl, {
'method': 'POST',
'headers': { 'Content-Type': 'application/x-www-form-urlencoded' },
'body': body.toString()
});
if (response.ok) {
const data = await response.json();
return data.access_token;
} else {
console.error('アクセストークン取得失敗:', await response.text());
return null;
}
}
// メッセージ送信
async function sendLineworksMessage(botId, userId, messageText) {
const accessToken = await getAccessToken();
if (!accessToken) return;
const apiUrl = `https://www.worksapis.com/v1.0/bots/${botId}/users/${userId}/messages`;
const body = {
'content': {
'type': 'text',
'text': messageText
}
};
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify(body)
});
if (response.ok) {
console.log('送信成功');
} else {
console.error('送信失敗', await response.text());
}
}
// APIエンドポイント
app.post('/lwSendMessage', async (req, res) => {
let rawBody = '';
req.on('data', (chunk) => {
rawBody += chunk; // リクエストデータをそのまま取得
});
req.on('end', () => {
// APIキーの検証
const apiKey = req.headers['x-api-key'];
if (!apiKey || apiKey !== API_KEY) {
return res.status(401).json({ error: 'APIキーが不正です' });
}
// botIdとuserIdをヘッダーから取得
const botId = req.headers['x-bot-id'];
const userId = req.headers['x-user-id'];
if (!botId || !userId) {
return res.status(400).json({ error: 'x-bot-id, x-user-idは必須です' });
}
// リクエストボディ全体をmessageTextとして使用
const messageText = rawBody;
console.log('messageText:', messageText);
if (!messageText) {
return res.status(400).json({ error: 'messageTextは必須です' });
}
try {
sendLineworksMessage(botId, userId, messageText);
res.json({ result: 'ok' });
} catch (e) {
res.status(500).json({ error: e.message });
}
});
});
// HTTPSサーバー起動
const PORT = 30309;
const sslOptions = {
cert: fs.readFileSync('/etc/letsencrypt/live/neo999.next-hd.net/fullchain.pem'),
key: fs.readFileSync('/etc/letsencrypt/live/neo999.next-hd.net/privkey.pem')
};
https.createServer(sslOptions, app).listen(PORT, () => {
console.log(`APIサーバー起動: https://neo999.next-hd.net:${PORT}/lwSendMessage`);
});

View File

@ -0,0 +1,19 @@
const { sendLineworksMessage } = require('./lineworksCore');
const API_KEY = 'pgqhLFWbDFu4Byz#4afNYX2F6Fa1&$KPjved$8%sUdTQV52caip#EpIKxYUkdd4S';
exports.lwSendMessageHandler = async (req, res) => {
const apiKey = req.headers['x-api-key'];
if (!apiKey || apiKey !== API_KEY) {
return res.status(401).json({ error: 'APIキーが不正です' });
}
const { botId, userId, messageText } = req.body;
if (!botId || !userId || !messageText) {
return res.status(400).json({ error: 'botId, userId, messageTextは必須です' });
}
try {
await sendLineworksMessage(botId, userId, messageText);
res.json({ result: 'ok' });
} catch (e) {
res.status(500).json({ error: e.message });
}
};

View File

@ -0,0 +1,197 @@
{
"name": "lineworks_sendmessage",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "lineworks_sendmessage",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"jsonwebtoken": "^9.0.2",
"node-fetch": "^2.7.0"
}
},
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
"license": "BSD-3-Clause"
},
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"license": "Apache-2.0",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/jsonwebtoken": {
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
"license": "MIT",
"dependencies": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^7.5.4"
},
"engines": {
"node": ">=12",
"npm": ">=6"
}
},
"node_modules/jwa": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz",
"integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==",
"license": "MIT",
"dependencies": {
"buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"license": "MIT",
"dependencies": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
"license": "MIT"
},
"node_modules/lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
"license": "MIT"
},
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
"license": "MIT"
},
"node_modules/lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
"license": "MIT"
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
"license": "MIT"
},
"node_modules/lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
"license": "MIT"
},
"node_modules/lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
"license": "MIT"
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"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/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"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/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-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"
}
}
}
}

View File

@ -0,0 +1,16 @@
{
"name": "lineworks_sendmessage",
"version": "1.0.0",
"main": "lwSendMessageBot.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"jsonwebtoken": "^9.0.2",
"node-fetch": "^2.7.0"
}
}

View File

@ -0,0 +1,36 @@
//lwSendMessage.jsにAPIリクエストを送信するクライアントサンプル
//node実行する場合は下記が必要
const fetch = require('node-fetch');
//ブラウザスクリプトにする場合は下記から
//API-KEYは下記固定
const API_KEY = 'pgqhLFWbDFu4Byz#4afNYX2F6Fa1&$KPjved$8%sUdTQV52caip#EpIKxYUkdd4S'; // 任意のAPIキーを設定
//CORSには本番用・開発用の両方のプリザンターアドレスを登録してあるので
//どちらの環境からでも実行可能
async function sendMessageToLineworks() {
const apiUrl = 'https://neo999.next-hd.net:30309/lwSendMessage';
const body = {
botId: '10130468', //新しいBotを作ったらここでIDを変更
userId: 'k.nogi@works-nextgroup2',
messageText: 'テストメッセージ'
};
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': API_KEY // ここにAPIキーを追加
},
body: JSON.stringify(body)
});
if (response.ok) {
const result = await response.json();
console.log('APIレスポンス:', result);
} else {
console.error('APIリクエスト失敗:', await response.text());
}
}
sendMessageToLineworks();

View File

@ -0,0 +1,27 @@
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const https = require('https');
const fs = require('fs');
const { lwSendMessageHandler } = require('./lwSendMessageLogic');
const app = express();
app.use(cors({
origin: [
'https://neo999.next-hd.net',
'https://nextoffice.next-hd.co.jp',
],
optionsSuccessStatus: 200
}));
app.use(bodyParser.json());
app.post('/lwSendMessage', lwSendMessageHandler);
const sslOptions = {
cert: fs.readFileSync('/etc/letsencrypt/live/neo999.next-hd.net/fullchain.pem'),
key: fs.readFileSync('/etc/letsencrypt/live/neo999.next-hd.net/privkey.pem')
};
https.createServer(sslOptions, app).listen(30309, () => {
console.log('APIサーバー起動: https://neo999.next-hd.net:30309/lwSendMessage');
});

3
oldCode/express/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"git.ignoreLimitWarning": true
}

15
oldCode/express/Mail.json Normal file
View File

@ -0,0 +1,15 @@
{
"SmtpHost": "smtp.sendgrid.net",
"SmtpPort": "0",
"SmtpUserName": "apikey",
"SmtpPassword": "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",
"SmtpEnableSsl": false,
"ServerCertificateValidationCallback": false,
"SecureSocketOptions": null,
"FixedFrom": null,
"AllowedFrom": null,
"SupportFrom": "\"NEXTOFFICE\" <systemadmin@next-hd.co.jp>",
"InternalDomains": "",
"Encoding": null,
"ContentEncoding": null
}

20
oldCode/express/config.js Normal file
View File

@ -0,0 +1,20 @@
const fs = require('fs');
module.exports = {
API_KEY: 'pgqhLFWbDFu4Byz#4afNYX2F6Fa1&$KPjved$8%sUdTQV52caip#EpIKxYUkdd4S',
PORT: 30309,
SSL_OPTIONS: {
cert: fs.readFileSync('/etc/letsencrypt/live/neo999.next-hd.net/fullchain.pem'),
key: fs.readFileSync('/etc/letsencrypt/live/neo999.next-hd.net/privkey.pem')
},
CORS_ORIGIN: [
'https://neo999.next-hd.net',
'https://nextoffice.next-hd.co.jp'
],
PLEASANTER: {
// HOST: 'https://neo999.next-hd.net/pleasanter',
HOST: 'https://nextoffice.next-hd.co.jp/pleasanter',
API_KEY: '6504c8a807677a3a576e10327f3c19876c55736ee45d4a845796b9e7f5e087bfd4bd0d8184863da8cf1733ca635111432ab334aea59102b06a96ee6d2c05190d'
},
LINEWORKS_BOT_SECRET: 'P/06DLKvwTMyn10QffjZv4rU+Mq/Pi'
};

View File

@ -0,0 +1,14 @@
const fs = require('fs');
module.exports = {
API_KEY: 'pgqhLFWbDFu4Byz#4afNYX2F6Fa1&$KPjved$8%sUdTQV52caip#EpIKxYUkdd4S',
PORT: 30309,
SSL_OPTIONS: {
cert: fs.readFileSync('/etc/letsencrypt/live/neo999.next-hd.net/fullchain.pem'),
key: fs.readFileSync('/etc/letsencrypt/live/neo999.next-hd.net/privkey.pem')
},
CORS_ORIGIN: [
'https://neo999.next-hd.net',
'https://nextoffice.next-hd.co.jp'
]
};

View File

@ -0,0 +1,31 @@
const express = require('express');
const https = require('https');
const cors = require('cors');
const { API_KEY, PORT, SSL_OPTIONS, CORS_ORIGIN } = require('./config.js'); // config.jsから設定をインポート
// expressとCORSの設定
const app = express();
app.use(cors({
origin: CORS_ORIGIN, // config.jsから読み込み
optionsSuccessStatus: 200
}));
// lwSendMessageモジュールの読み込み
require('./modules/lwSendMessage.js')(app);
// lineworksSurveyモジュールの読み込み
require('./modules/lineworksSurvey.js')(app);
// pdfConvertモジュールの読み込み
require('./modules/pdfConvert.js')(app);
// pdfMergeモジュールの読み込み
require('./modules/pdfMerge.js')(app);
// pdfToTextモジュールの読み込み
require('./modules/pdfToText.js')(app);
// HTTPSサーバーの起動
https.createServer(SSL_OPTIONS, app).listen(PORT, () => {
console.log(`HTTPS server is running on https://localhost:${PORT}`);
});

32
oldCode/express/index.js Normal file
View File

@ -0,0 +1,32 @@
const express = require('express');
const http = require('http');
const cors = require('cors');
const { API_KEY, PORT, SSL_OPTIONS, CORS_ORIGIN } = require('./config.js'); // config.jsから設定をインポート
// expressとCORSの設定
const app = express();
app.use(cors({
origin: CORS_ORIGIN, // config.jsから読み込み
optionsSuccessStatus: 200
}));
// lwSendMessageモジュールの読み込み
require('./modules/lwSendMessage.js')(app);
// lineworksSurveyモジュールの読み込み
require('./modules/lineworksSurvey.js')(app);
// pdfConvertモジュールの読み込み
require('./modules/pdfConvert.js')(app);
// pdfMergeモジュールの読み込み
require('./modules/pdfMerge.js')(app);
// pdfToTextモジュールの読み込み
require('./modules/pdfToText.js')(app);
// HTTPSサーバーの起動
// const PORT = PORT;
http.createServer(app).listen(PORT, '127.0.0.1', () => {
console.log(`Server running on http://127.0.0.1:${PORT}`);
});

View File

@ -0,0 +1,77 @@
const { getAccessToken } = require('./modules/lineworksAuth');
const USER_INFO_SCOPES = ['user.read', 'directory.read'];
async function main() {
const [, , identifier, domainArg] = process.argv;
if (!identifier) {
console.error('使い方: node lookupLineworksUser.js <userId|email|externalKey:xxx> [domainId]');
process.exit(1);
}
const domainId = domainArg || process.env.LINEWORKS_DOMAIN_ID || '';
const encodedIdentifier = encodeURIComponent(identifier);
const accessToken = await getAccessToken(USER_INFO_SCOPES);
const baseUrl = `https://www.worksapis.com/v1.0/users/${encodedIdentifier}`;
const apiUrl = domainId ? `${baseUrl}?domainId=${encodeURIComponent(domainId)}` : baseUrl;
const response = await fetch(apiUrl, {
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const text = await response.text();
let data;
try {
data = JSON.parse(text);
} catch {
console.error('LINE WORKS APIレスポンス解析に失敗しました:', text);
process.exit(1);
}
if (!response.ok) {
console.error('LINE WORKS APIエラー:', JSON.stringify(data, null, 2));
process.exit(1);
}
printUserInfo(data);
}
function printUserInfo(user) {
console.log('--- User Info ---');
console.log(`domainId : ${user.domainId}`);
console.log(`userId : ${user.userId}`);
console.log(`userExternalKey : ${user.userExternalKey ?? 'N/A'}`);
console.log(`email : ${user.email}`);
console.log(`name : ${formatName(user.userName)}`);
console.log(`nickName : ${user.nickName ?? 'N/A'}`);
console.log(`employeeNumber : ${user.employeeNumber ?? 'N/A'}`);
console.log(`isAdministrator : ${user.isAdministrator}`);
console.log(`isSuspended : ${user.isSuspended}`);
console.log(`isDeleted : ${user.isDeleted}`);
if (Array.isArray(user.organizations)) {
console.log('organizations:');
for (const org of user.organizations) {
console.log(` - domainId : ${org.domainId}, primary: ${org.primary}, email: ${org.email ?? 'N/A'}`);
}
}
if (Array.isArray(user.aliasEmails) && user.aliasEmails.length > 0) {
console.log(`aliasEmails : ${user.aliasEmails.join(', ')}`);
}
}
function formatName(userName = {}) {
const last = userName.lastName ?? '';
const first = userName.firstName ?? '';
return `${last} ${first}`.trim() || 'N/A';
}
main().catch((error) => {
console.error('ユーザー照会でエラーが発生しました:', error.message);
process.exit(1);
});

View File

@ -0,0 +1,77 @@
const fs = require('fs');
const path = require('path');
const jwt = require('jsonwebtoken');
let cachedToken = null;
let cachedExpiry = 0;
let cachedScopeKey = '';
const CLIENT_ID = 'tre8J_Tk8RblfsMSyZRh';
const CLIENT_SECRET = 'O5_R5gcHxg';
const SERVICE_ACCOUNT = 'wh4k8.serviceaccount@nexthd.jp';
const TOKEN_ENDPOINT = 'https://auth.worksmobile.com/oauth2/v2.0/token';
const PRIVATE_KEY_PATH = path.join(__dirname, 'private_20260307184804.key');
const TOKEN_TTL_BUFFER = 30; // seconds
const DEFAULT_SCOPES = ['bot', 'contact'];
function readPrivateKey() {
return fs.readFileSync(PRIVATE_KEY_PATH, 'utf8');
}
function makeScopeKey(scopes) {
return scopes.slice().sort().join(' ');
}
function isTokenValid(scopeKey) {
return Boolean(cachedToken)
&& cachedScopeKey === scopeKey
&& cachedExpiry > Math.floor(Date.now() / 1000) + TOKEN_TTL_BUFFER;
}
async function getAccessToken(scopes = DEFAULT_SCOPES) {
const normalizedScopes = Array.isArray(scopes) && scopes.length > 0 ? scopes : DEFAULT_SCOPES;
const scopeKey = makeScopeKey(normalizedScopes);
if (isTokenValid(scopeKey)) {
return cachedToken;
}
const now = Math.floor(Date.now() / 1000);
const payload = {
iss: CLIENT_ID,
sub: SERVICE_ACCOUNT,
iat: now,
exp: now + 5 * 60,
aud: TOKEN_ENDPOINT
};
const assertion = jwt.sign(payload, readPrivateKey(), { algorithm: 'RS256' });
const body = new URLSearchParams({
assertion,
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
scope: normalizedScopes.join(' ')
});
const response = await fetch(TOKEN_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: body.toString()
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`LINE WORKSアクセストークン取得失敗: ${errorText}`);
}
const data = await response.json();
cachedToken = data.access_token;
cachedExpiry = now + (data.expires_in || 300);
cachedScopeKey = scopeKey;
return cachedToken;
}
module.exports = {
getAccessToken
};

View File

@ -0,0 +1,77 @@
const fs = require('fs');
const path = require('path');
const jwt = require('jsonwebtoken');
let cachedToken = null;
let cachedExpiry = 0;
let cachedScopeKey = '';
const CLIENT_ID = 'V58hNobcAqRcQPerySMz';
const CLIENT_SECRET = 'gJ84XQtigD';
const SERVICE_ACCOUNT = 'x94xh.serviceaccount@works-nextgroup2';
const TOKEN_ENDPOINT = 'https://auth.worksmobile.com/oauth2/v2.0/token';
const PRIVATE_KEY_PATH = path.join(__dirname, 'private_20250530180606.key');
const TOKEN_TTL_BUFFER = 30; // seconds
const DEFAULT_SCOPES = ['bot', 'contact'];
function readPrivateKey() {
return fs.readFileSync(PRIVATE_KEY_PATH, 'utf8');
}
function makeScopeKey(scopes) {
return scopes.slice().sort().join(' ');
}
function isTokenValid(scopeKey) {
return Boolean(cachedToken)
&& cachedScopeKey === scopeKey
&& cachedExpiry > Math.floor(Date.now() / 1000) + TOKEN_TTL_BUFFER;
}
async function getAccessToken(scopes = DEFAULT_SCOPES) {
const normalizedScopes = Array.isArray(scopes) && scopes.length > 0 ? scopes : DEFAULT_SCOPES;
const scopeKey = makeScopeKey(normalizedScopes);
if (isTokenValid(scopeKey)) {
return cachedToken;
}
const now = Math.floor(Date.now() / 1000);
const payload = {
iss: CLIENT_ID,
sub: SERVICE_ACCOUNT,
iat: now,
exp: now + 5 * 60,
aud: TOKEN_ENDPOINT
};
const assertion = jwt.sign(payload, readPrivateKey(), { algorithm: 'RS256' });
const body = new URLSearchParams({
assertion,
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
scope: normalizedScopes.join(' ')
});
const response = await fetch(TOKEN_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: body.toString()
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`LINE WORKSアクセストークン取得失敗: ${errorText}`);
}
const data = await response.json();
cachedToken = data.access_token;
cachedExpiry = now + (data.expires_in || 300);
cachedScopeKey = scopeKey;
return cachedToken;
}
module.exports = {
getAccessToken
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const axios = require('axios');
app.use(bodyParser.json());
module.exports = (app) => {
// LINE WORKS Webhookエンドポイント
app.post('/nextgpt', async (req, res) => {
try {
const { source, content } = req.body;
// LINE WORKSからのメッセージ
const userMessage = content.text;
const userId = source.accountId;
console.log(`Received message: "${userMessage}" from User: "${userId}"`);
// anythingLLMにメッセージを送信して応答を取得
const llmResponse = await axios.post(process.env.ANYTHING_LLM_API, {
question: userMessage
});
const llmAnswer = llmResponse.data.answer || "申し訳ありませんが、応答を生成できませんでした。";
// LINE WORKSに応答を送信
await axios.post(
`https://apis.worksmobile.com/r/${process.env.LINEWORKS_BOT_ID}/message/push`,
{
botNo: process.env.LINEWORKS_BOT_ID,
accountId: userId,
content: {
type: "text",
text: llmAnswer
}
},
{
headers: {
"Content-Type": "application/json",
"consumerKey": process.env.LINEWORKS_API_KEY
}
}
);
console.log(`Reply sent to User: "${userId}"`);
res.status(200).send('OK');
} catch (error) {
console.error('Error:', error.message);
res.status(500).send('Internal Server Error');
}
});
};
$p.apiUpdate({ id: 186849, data: { ApiVersion: 1.1, ClassHash: { ClassU: ["遠藤 晃太", "(退職) 横井 英治"], ClassV: ["原田 朋保"], ClassW: ["宮倉 由紀"] } }, done: function (data) { console.log(data); }, });

View File

@ -0,0 +1,99 @@
const { API_KEY } = require('../config.js'); // API_KEYをインポート
const { getAccessToken } = require('./lineworksAuth');
module.exports = (app) => {
app.post('/lineworks/sendMessage', async (req, res) => {
let rawBody = '';
req.on('data', (chunk) => {
rawBody += chunk; // リクエストデータをそのまま取得
});
req.on('end', async () => {
// reqのすべてのパラメータを表示
// console.log('Request Headers:', req.headers);
// console.log('Request Body:', rawBody);
const apiKey = req.headers['x-api-key'];
if (!apiKey || apiKey !== API_KEY) {
console.log('APIキーが不正です');
return res.status(401).json({ error: 'APIキーが不正です' });
}
// botIdとuserIdをヘッダーから取得
const botId = req.headers['x-bot-id'];
const userId = req.headers['x-user-id'];
if (!botId || !userId) {
console.log('x-bot-id, x-user-idは必須です');
return res.status(400).json({ error: 'x-bot-id, x-user-idは必須です' });
}
const userIds = userId.split(';').map(id => id.trim()).filter(id => id);
// リクエストボディからメッセージテキストを取得
const messageText = rawBody;
if (!messageText) {
console.log('messageTextは必須です');
return res.status(400).json({ error: 'messageTextは必須です' });
}
try {
for (const uid of userIds) {
const result = await sendLineworksMessage(botId, uid, messageText);
if (result.success) {
console.log(`送信成功: ${uid}:`, result.message);
} else {
console.log(`送信失敗: ${uid}:`, result.message);
}
}
res.json({ result: 'ok', message: '全ユーザーに送信処理完了' });
return;
} catch (e) {
console.log('エラーが発生しました:', e.message);
res.status(500).json({ error: e.message });
}
});
});
};
// メッセージ送信
async function sendLineworksMessage(botId, userId, messageText) {
const accessToken = await getAccessToken();
if (!accessToken) {
console.log('アクセストークンの取得に失敗しました');
throw new Error('アクセストークンの取得に失敗しました');
}
// userIdに@が含まれない場合はchannelIdとして扱う
let apiUrl;
if (userId.includes('@')) {
apiUrl = `https://www.worksapis.com/v1.0/bots/${botId}/users/${userId}/messages`;
} else {
apiUrl = `https://www.worksapis.com/v1.0/bots/${botId}/channels/${userId}/messages`;
}
const body = {
'content': {
'type': 'text',
'text': messageText
}
};
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify(body)
});
if (response.ok) {
console.log('メッセージ送信成功');
return { success: true, message: '送信成功' };
} else {
const errorText = await response.text();
console.log('メッセージ送信失敗:', errorText);
return { success: false, message: `送信失敗: ${errorText}` };
}
}

View File

@ -0,0 +1,100 @@
const fs = require('fs');
const path = require('path');
const { execFile } = require('child_process');
const { v4: uuidv4 } = require('uuid');
const express = require('express'); // JSON解析用にexpressをインポート
const { API_KEY } = require('../config.js'); // API_KEYをインポート
// LibreOffice AppImageのパス
const libreofficeAppImage = './modules/LibreOffice-still.standard-x86_64.AppImage';
// tmpディレクトリのパス
const tmpDir = path.join(__dirname, 'tmp');
// tmpディレクトリが存在しない場合は作成
if (!fs.existsSync(tmpDir)) {
fs.mkdirSync(tmpDir);
}
// POSTエンドポイント
module.exports = (app) => {
app.post('/pdfConvert', express.json({ limit: '30mb' }), async (req, res) => {
try {
// APIキーのチェック
const apiKey = req.headers['x-api-key'];
if (!apiKey || apiKey !== API_KEY) {
console.log('APIキーが不正です');
return res.status(401).json({ error: 'APIキーが不正です' });
}
const { base64, fileName } = req.body;
if (!base64 || !fileName) {
return res.status(400).json({ error: 'base64とfileNameは必須です' });
}
const pdfBuffer = await convertBase64ToPdf(base64, fileName);
const safeFileName = encodeURIComponent(path.parse(fileName).name); // ファイル名をエスケープ
res.set({
'Content-Type': 'application/pdf',
'Content-Disposition': `attachment; filename="${safeFileName}.pdf"`
});
res.send(pdfBuffer);
} catch (err) {
console.error('変換エラー:', err.message);
res.status(500).json({ error: err.message });
}
});
};
// PDF変換処理
async function convertBase64ToPdf(base64Data, originalFileName) {
const tempId = uuidv4(); // 一意のIDを生成
const ext = path.extname(originalFileName) || '.tmp'; // 拡張子を取得、なければ.tmpを使用
const orgPath = path.join(tmpDir, `${tempId}${ext}`); // 一時的なファイルのパス
const pdfPath = path.join(tmpDir, `${tempId}.pdf`);
// base64データをファイルに保存
fs.writeFileSync(orgPath, Buffer.from(base64Data, 'base64'));
// LibreOfficeでPDF変換タイムアウト60秒
await new Promise((resolve, reject) => {
const child = execFile(
libreofficeAppImage,
[
'--headless',
'--convert-to', 'pdf',
'--outdir', tmpDir,
orgPath
],
(error, stdout, stderr) => {
if (error) {
console.error('stderr:', stderr);
reject(new Error(`LibreOfficeエラー: ${stderr}`));
} else {
resolve();
}
}
);
const timeout = setTimeout(() => {
child.kill('SIGTERM'); // SIGTERMを使用してプロセスを終了
reject(new Error('PDF変換がタイムアウトしました60秒経過'));
}, 60000);
child.on('exit', () => clearTimeout(timeout));
});
// PDFファイルを読み込む
if (!fs.existsSync(pdfPath)) {
throw new Error('PDF変換に失敗しました');
}
const pdfBuffer = fs.readFileSync(pdfPath);
// cleanup
try {
if (fs.existsSync(orgPath)) fs.unlinkSync(orgPath);
if (fs.existsSync(pdfPath)) fs.unlinkSync(pdfPath);
} catch (cleanupError) {
console.error('クリーンアップエラー:', cleanupError.message);
}
return pdfBuffer;
}

View File

@ -0,0 +1,97 @@
const fs = require('fs');
const path = require('path');
const { execFile } = require('child_process');
const { v4: uuidv4 } = require('uuid');
const express = require('express'); // JSON解析用にexpressをインポート
const { API_KEY } = require('../config.js'); // API_KEYをインポート
// tmpディレクトリのパス
const tmpDir = path.join(__dirname, 'tmp');
// tmpディレクトリが存在しない場合は作成
if (!fs.existsSync(tmpDir)) {
fs.mkdirSync(tmpDir);
}
// POSTエンドポイント
module.exports = (app) => {
app.post('/pdfMerge', express.json({ limit: '30mb' }), async (req, res) => {
try {
// APIキーのチェック
const apiKey = req.headers['x-api-key'];
if (!apiKey || apiKey !== API_KEY) {
console.log('APIキーが不正です');
return res.status(401).json({ error: 'APIキーが不正です' });
}
// base64_1, base64_2, fileName の3つをチェック
const { base64_1, base64_2, fileName } = req.body;
if (!base64_1 || !base64_2 || !fileName) {
return res.status(400).json({ error: 'base64_1, base64_2, fileNameは必須です' });
}
const pdfBuffer = await mergeBase64ToPdf(base64_1, base64_2, fileName);
const safeFileName = encodeURIComponent(path.parse(fileName).name); // ファイル名をエスケープ
res.set({
'Content-Type': 'application/pdf',
'Content-Disposition': `attachment; filename="${safeFileName}.pdf"`
});
res.send(pdfBuffer);
} catch (err) {
console.error('変換エラー:', err.message);
res.status(500).json({ error: err.message });
}
});
};
// PDF結合処理
async function mergeBase64ToPdf(base64Data1, base64Data2) {
const tempId = uuidv4(); // 一意のIDを生成
const orgPath1 = path.join(tmpDir, `${tempId}_1.pdf`);
const orgPath2 = path.join(tmpDir, `${tempId}_2.pdf`);
const mergedPath = path.join(tmpDir, `${tempId}_merged.pdf`);
// base64データをファイルに保存
fs.writeFileSync(orgPath1, Buffer.from(base64Data1, 'base64'));
fs.writeFileSync(orgPath2, Buffer.from(base64Data2, 'base64'));
// pdfuniteでPDF結合
await new Promise((resolve, reject) => {
const child = execFile(
'pdfunite',
[orgPath1, orgPath2, mergedPath],
(error, stdout, stderr) => {
if (error) {
console.error('stderr:', stderr);
reject(new Error(`pdfuniteエラー: ${stderr}`));
} else {
resolve();
}
}
);
const timeout = setTimeout(() => {
child.kill('SIGTERM'); // SIGTERMを使用してプロセスを終了
reject(new Error('PDF変換がタイムアウトしました60秒経過'));
}, 60000);
child.on('exit', () => clearTimeout(timeout));
});
// 結合されたPDFを読み込む
if (!fs.existsSync(mergedPath)) {
throw new Error('PDF結合に失敗しました');
}
const pdfBuffer = fs.readFileSync(mergedPath);
// cleanup
try {
if (fs.existsSync(orgPath1)) fs.unlinkSync(orgPath1);
if (fs.existsSync(orgPath2)) fs.unlinkSync(orgPath2);
if (fs.existsSync(mergedPath)) fs.unlinkSync(mergedPath);
} catch (cleanupError) {
console.error('クリーンアップエラー:', cleanupError.message);
}
return pdfBuffer;
}

View File

@ -0,0 +1,98 @@
const fs = require('fs');
const path = require('path');
const { execFile } = require('child_process');
const { v4: uuidv4 } = require('uuid');
const express = require('express'); // JSON解析用にexpressをインポート
const { API_KEY } = require('../config.js'); // API_KEYをインポート
// tmpディレクトリのパス
const tmpDir = path.join(__dirname, 'tmp');
// tmpディレクトリが存在しない場合は作成
if (!fs.existsSync(tmpDir)) {
fs.mkdirSync(tmpDir);
}
// POSTエンドポイント
module.exports = (app) => {
app.post('/pdfToText', express.json({ limit: '30mb' }), async (req, res) => {
try {
// APIキーのチェック
const apiKey = req.headers['x-api-key'];
if (!apiKey || apiKey !== API_KEY) {
console.log('APIキーが不正です');
return res.status(401).json({ error: 'APIキーが不正です' });
}
// base64, fileName の3つをチェック
const { base64, fileName } = req.body;
if (!base64 || !fileName) {
return res.status(400).json({ error: 'base64とfileNameは必須です' });
}
const txtBuffer = await pdfToTextConvert(base64, fileName);
const safeFileName = encodeURIComponent(path.parse(fileName).name); // ファイル名をエスケープ
res.set({
'Content-Type': 'text/plain',
'Content-Disposition': `attachment; filename="${safeFileName}.txt"`
});
res.send(txtBuffer);
} catch (err) {
console.error('変換エラー:', err.message);
res.status(500).json({ error: err.message });
}
});
};
// PDF テキスト変換処理
async function pdfToTextConvert(base64) {
const tempId = uuidv4(); // 一意のIDを生成
const pdfPath = path.join(tmpDir, `${tempId}.pdf`);
const outputPath = path.join(tmpDir, `${tempId}.txt`);
// base64データをファイルに保存
fs.writeFileSync(pdfPath, Buffer.from(base64, 'base64'));
// pdfuniteでテキストに変換
await new Promise((resolve, reject) => {
const child = execFile(
'pdftotext',
[
'-layout',
'-nopgbrk',
pdfPath,
outputPath
],
(error, stdout, stderr) => {
if (error) {
console.error('stderr:', stderr);
reject(error);
} else {
resolve();
}
}
);
// 60秒タイムアウト
const timeout = setTimeout(() => {
child.kill('SIGTERM'); // SIGTERMを使用してプロセスを終了
reject(new Error('テキストへの変換がタイムアウトしました60秒経過'));
}, 60000);
child.on('exit', () => clearTimeout(timeout));
});
// 変換されたテキストファイルを読み込み
if (!fs.existsSync(outputPath)) {
// cleanup
fs.unlinkSync(pdfPath);;
throw new Error('テキストへの変換に失敗しました');
}
const txtBuffer = fs.readFileSync(outputPath);
// cleanup
fs.unlinkSync(pdfPath);
fs.unlinkSync(outputPath);
return txtBuffer;
}

1154
oldCode/express/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
{
"dependencies": {
"body-parser": "^2.2.0",
"cors": "^2.8.5",
"express": "^5.1.0",
"fetch": "^1.1.0",
"fs": "^0.0.1-security",
"https": "^1.0.0",
"jsonwebtoken": "^9.0.2",
"node-fetch": "^3.3.2",
"url": "^0.11.4",
"uuid": "^11.1.0"
}
}

View File

@ -0,0 +1,170 @@
//参考スクリプト startLineworksSurvey.js
// botId = $('#Results_Class001').val();
// surveyId = $('#Results_Class002').val();
// targetId = $('#Results_Class003').val();
const WEBHOOK_URL = 'https://neo999.next-hd.net/lineworksSurvey/webhook';
const API_KEY = 'pgqhLFWbDFu4Byz#4afNYX2F6Fa1&$KPjved$8%sUdTQV52caip#EpIKxYUkdd4S';
$p.events.on_grid_load = function () {
// アンケート一括発行ボタンの作成
createSurveyAllButton();
}
function createSurveyAllButton() {
if ($('#surveyAll').length > 0) {
return;
}
//処理内容
let button = document.createElement('button');
button.type = 'button';
button.id = 'surveyAll';
button.name = 'surveyAll';
button.innerText = 'アンケート一括発行';
button.setAttribute('onclick', 'sendSurveyAll()');
$("#MainCommands button:last-child").after(button);
$('#surveyAll').button({
icon: 'ui-icon-disk'
});
}
async function sendStartRequest(botId, surveyId, targetId, resultId) {
// const botId = $('#Results_Class001').val();
// const surveyId = $('#Results_Class002').val();
// const targetId = $('#Results_Class003').val();
// const resultId = $p.id();
if (!surveyId || !targetId || !botId) {
console.log('surveyId, targetId, botId をソース内で設定してください。');
return false;
}
if (!API_KEY) {
console.log('API_KEY is empty. Check config.js / environment.');
return false;
}
const payload = { surveyId, targetId, botId, resultId };
const res = await fetch(WEBHOOK_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': API_KEY
},
body: JSON.stringify(payload)
});
const text = await res.text();
let body;
try {
body = JSON.parse(text);
} catch {
body = { raw: text };
}
if (!res.ok) {
console.log('Start request failed:', res.status, body);
process.exit(1);
}
/*
Start request success: {
result: 'ok',
sessionId: 'eef7af18-065a-4486-b5a5-9f65bca61d5a',
message: 'アンケートを開始しました'
}
*/
console.log('Start request success:', body);
return true;
}
/*
アンケート発行処理
*/
async function sendSurveyAll() {
let siteId = $p.siteId();
/*#Grid .grid-check 一覧のチェックボックスがオンのものの、data-idの値を全て取得し、配列に格納 */
let checkedIds = [];
$('#Grid .grid-check:checked').each(function () {
checkedIds.push($(this).data('id'));
}
);
console.log('Checked IDs:', checkedIds);
if (checkedIds.length === 0) {
console.log('No records selected. Please check at least one record.');
$p.clearMessage();
$p.setMessage('#Message', JSON.stringify({
Css: 'alert-warning',
Text: 'アンケートを一括発行するレコードの左端のチェックボックスをオンにしてください。'
}));
//return;
} else {
$p.apiGet({
'id': siteId,
'data': {
'View': {
'ColumnFilterHash': {
'Status': "['100']"
}
}
},
'done': function (data) {
console.log('API data:', data);
if (data.Response.TotalCount > 0) {
let records = data.Response.Data.filter(record => checkedIds.includes(record.ResultId));
$.each(records, async function (index, record) {
let resultId = record.ResultId;;
let botId = record.ClassHash.Class001;
let surveyId = record.ClassHash.Class002;
let targetId = record.ClassHash.Class003;
console.log(`Processing record ${index + 1}/${records.length}:`, { resultId, botId, surveyId, targetId });
// アンケート開始リクエストを送信
if (await sendStartRequest(botId, surveyId, targetId, resultId)) {
console.log(`Survey started for record ${resultId}. Updating status...`);
await updateSurveyRecord(resultId);
}
});
$p.clearMessage();
$p.setMessage('#Message', JSON.stringify({
Css: 'alert-success',
Text: 'アンケートを一括発行しました'
}));
setTimeout(() => {
location.reload();
}, 3000);
}
}
});
}
}
// アンケート開始後、ステータスを150に更新する関数
async function updateSurveyRecord(resultId) {
$p.apiUpdate({
'id': resultId,
'data': {
'ApiVersion': 1.1,
'Status': '150'
},
'done': function (data) {
console.log(data);
}
});
}

View File

@ -0,0 +1,86 @@
//参考スクリプト startLineworksSurvey.js
// botId = $('#Results_Class001').val();
// surveyId = $('#Results_Class002').val();
// targetId = $('#Results_Class003').val();
const WEBHOOK_URL = 'https://neo999.next-hd.net/lineworksSurvey/webhook';
const API_KEY = 'pgqhLFWbDFu4Byz#4afNYX2F6Fa1&$KPjved$8%sUdTQV52caip#EpIKxYUkdd4S';
async function sendStartRequest() {
const botId = $('#Results_Class001').val();
const surveyId = $('#Results_Class002').val();
const targetId = $('#Results_Class003').val();
const resultId = $p.id();
if (!surveyId || !targetId || !botId) {
console.error('surveyId, targetId, botId をソース内で設定してください。');
return false;
}
if (!API_KEY) {
console.error('API_KEY is empty. Check config.js / environment.');
return false;
}
const payload = { surveyId, targetId, botId, resultId };
const res = await fetch(WEBHOOK_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': API_KEY
},
body: JSON.stringify(payload)
});
const text = await res.text();
let body;
try {
body = JSON.parse(text);
} catch {
body = { raw: text };
}
if (!res.ok) {
console.error('Start request failed:', res.status, body);
process.exit(1);
}
/*
Start request success: {
result: 'ok',
sessionId: 'eef7af18-065a-4486-b5a5-9f65bca61d5a',
message: 'アンケートを開始しました'
}
*/
console.log('Start request success:', body);
return true;
}
/*
アンケート発行処理
*/
async function sendSurvey(proccessButton) {
let procNum = proccessButton[0].id.replace('Process_', '');
console.log('Process number:', procNum);
if (await sendStartRequest()) {
// プロセス実行
$p.setMessage('#Message', JSON.stringify({
Css: 'alert-success',
Text: 'アンケートを発行しました'
}));
//$p.set($('#Results_Status'), 150);
//プロセスを継続
$p.execProcess($('#Process_' + procNum));
return true;
} else {
$p.setMessage('#Message', JSON.stringify({
Css: 'alert-error',
Text: 'アンケートの発行に失敗しました'
}));
return false;
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,55 @@
'use strict';
const { API_KEY } = require('./config.js');
const WEBHOOK_URL =
process.env.LINEWORKS_SURVEY_WEBHOOK_URL ||
'https://neo999.next-hd.net/lineworksSurvey/webhook';
// ここで固定値を指定
const surveyId = '335338';
const targetId = 'kenichiro.nogi@works-nextgroup2';
const botId = '11747661';
if (!surveyId || !targetId || !botId) {
console.error('surveyId, targetId, botId をソース内で設定してください。');
process.exit(1);
}
if (!API_KEY) {
console.error('API_KEY is empty. Check config.js / environment.');
process.exit(1);
}
async function main() {
const payload = { surveyId, targetId, botId };
const res = await fetch(WEBHOOK_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': API_KEY
},
body: JSON.stringify(payload)
});
const text = await res.text();
let body;
try {
body = JSON.parse(text);
} catch {
body = { raw: text };
}
if (!res.ok) {
console.error('Start request failed:', res.status, body);
process.exit(1);
}
console.log('Start request success:', body);
}
main().catch((err) => {
console.error('Unexpected error:', err);
process.exit(1);
});

25
oldCode/express/style.css Normal file
View File

@ -0,0 +1,25 @@
#Results_ClassAField,
#Results_NumAField,
#Results_NumBField,
#Results_Class001Field,
#Results_Class002Field,
#Results_Class003Field,
#Results_Class004Field,
#Results_Class005Field,
#Results_Class006Field,
#Results_Class007Field,
#Results_Class008Field,
#Results_Class009Field,
#Results_Class010Field,
#Results_Class011Field {
width: 500px;
.field-label {
width: 300px;
margin-right: -300px;
}
.field-control>.container-normal {
margin-left: 300px;
}
}

View File

@ -0,0 +1,34 @@
const express = require('express');
const https = require('https');
const { SSL_OPTIONS } = require('./config.js');
const app = express();
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.originalUrl}`);
next();
});
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get('/webhook', (req, res) => {
console.log('GET /webhook headers:', req.headers);
res.status(200).send('ok');
});
app.head('/webhook', (req, res) => {
console.log('HEAD /webhook headers:', req.headers);
res.status(200).end();
});
app.post('/webhook', (req, res) => {
console.log('POST /webhook headers:', req.headers);
console.log('POST /webhook body:', req.body);
res.status(200).json({ message: 'Webhook received' });
});
const PORT = 30399;
https.createServer(SSL_OPTIONS, app).listen(PORT, '0.0.0.0', () => {
console.log(`Webhook HTTPS server running on https://neo999.next-hd.net:${PORT}`);
});

View File

@ -0,0 +1,25 @@
lineworksでトーク画面でアンケートを取りたい。アンケートの内容は事前にプリザンターで定義を登録できるようにしたい。
アンケートは選択式、数字入力、自由入力の3種類を選べるようにする。
アンケート結果は事前に指定したプリザンターのテーブルにレコードを登録したい。
スクリプトはNode.jsを使用。Expressでサーバーを利用。
sendMessage.jsでLineworksにトークを送る関数とAccessTyokenの取得関数は準備済み。
アンケートIDと宛先IDを指定して、最初にアンケートの開始を受け付ける処理を作成。
ユーザーからの回答をすべて受信したら、まとめてプリザンターのレコードに保存する。
スクリプト名
lineworksSurvey.js modules内に配置
関数名
getSurvey : プリザンターからアンケートの元となるデータを取得する処理
sendSurvey : ユーザーにアンケートを送る処理
getAnswer : 回答を受け取る処理
sendAnswer : プリザンターに回答を保存する処理
lwSendMessage.js sendLineworksMessage を参考にアンケートを宛先のトークに送信する処理を作成する。
index.js に追加したモジュールを追加してexpressサーバーで稼働させる
プリザンターPleasanterからデータを取得するときはFetchを利用
APIとURLはConfig.jsから取得
テーブルIDはスクリプト内で定数で指定する