├── .github └── workflows │ ├── node.js.yml │ └── npm-publish.yml ├── .gitignore ├── README.md ├── package-lock.json ├── package.json └── src └── matrix.js /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | node-version: [10.x, 12.x, 14.x] 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - name: Use Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v1 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | - run: npm ci 28 | - run: npm run build --if-present 29 | - run: npm test 30 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: actions/setup-node@v1 16 | with: 17 | node-version: 12 18 | - run: npm ci 19 | - run: npm test 20 | 21 | publish-npm: 22 | needs: build 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v2 26 | - uses: actions/setup-node@v1 27 | with: 28 | node-version: 12 29 | registry-url: https://registry.npmjs.org/ 30 | - run: npm ci 31 | - run: npm publish 32 | env: 33 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 34 | 35 | publish-gpr: 36 | needs: build 37 | runs-on: ubuntu-latest 38 | steps: 39 | - uses: actions/checkout@v2 40 | - uses: actions/setup-node@v1 41 | with: 42 | node-version: 12 43 | registry-url: https://npm.pkg.github.com/ 44 | - run: npm ci 45 | - run: npm publish 46 | env: 47 | NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hubot adapter for Matrix 2 | 3 | This is a [Hubot](https://hubot.github.com) adapter for [Matrix](https://matrix.org/). 4 | 5 | ## Installation 6 | 7 | Use the version of this adapter appropriate to your Hubot version. 8 | 9 | * For Hubot v2, `npm i hubot-matrix@1` 10 | * For Hubot v3, `npm i hubot-matrix@2` 11 | 12 | | **hubot** | **hubot-matrix** | 13 | |----|----| 14 | | v2 | v1 | 15 | | v3 | v2 | 16 | 17 | ## Adapter configuration 18 | 19 | Set the following variables: 20 | 21 | * `HUBOT_MATRIX_HOST_SERVER` - the Matrix server to connect to (default is `https://matrix.org` if unset) 22 | * `HUBOT_MATRIX_USER` - bot login on the Matrix server - eg `@examplebotname:matrix.example.org` 23 | * `HUBOT_MATRIX_PASSWORD` - bot password on the Matrix server 24 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hubot-matrix", 3 | "version": "2.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/runtime": { 8 | "version": "7.14.8", 9 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz", 10 | "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", 11 | "requires": { 12 | "regenerator-runtime": "^0.13.4" 13 | } 14 | }, 15 | "@types/retry": { 16 | "version": "0.12.1", 17 | "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", 18 | "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" 19 | }, 20 | "ajv": { 21 | "version": "6.12.6", 22 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 23 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 24 | "requires": { 25 | "fast-deep-equal": "^3.1.1", 26 | "fast-json-stable-stringify": "^2.0.0", 27 | "json-schema-traverse": "^0.4.1", 28 | "uri-js": "^4.2.2" 29 | } 30 | }, 31 | "another-json": { 32 | "version": "0.2.0", 33 | "resolved": "https://registry.npmjs.org/another-json/-/another-json-0.2.0.tgz", 34 | "integrity": "sha1-tfQBnJc7bdXGUGotk0acttMq7tw=" 35 | }, 36 | "asn1": { 37 | "version": "0.2.4", 38 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 39 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 40 | "requires": { 41 | "safer-buffer": "~2.1.0" 42 | } 43 | }, 44 | "assert-plus": { 45 | "version": "1.0.0", 46 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 47 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 48 | }, 49 | "asynckit": { 50 | "version": "0.4.0", 51 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 52 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 53 | }, 54 | "aws-sign2": { 55 | "version": "0.7.0", 56 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 57 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 58 | }, 59 | "aws4": { 60 | "version": "1.11.0", 61 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", 62 | "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" 63 | }, 64 | "base-x": { 65 | "version": "3.0.8", 66 | "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", 67 | "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", 68 | "requires": { 69 | "safe-buffer": "^5.0.1" 70 | } 71 | }, 72 | "bcrypt-pbkdf": { 73 | "version": "1.0.2", 74 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 75 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 76 | "requires": { 77 | "tweetnacl": "^0.14.3" 78 | } 79 | }, 80 | "browser-request": { 81 | "version": "0.3.3", 82 | "resolved": "https://registry.npmjs.org/browser-request/-/browser-request-0.3.3.tgz", 83 | "integrity": "sha1-ns5bWsqJopkyJC4Yv5M975h2zBc=" 84 | }, 85 | "bs58": { 86 | "version": "4.0.1", 87 | "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", 88 | "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", 89 | "requires": { 90 | "base-x": "^3.0.2" 91 | } 92 | }, 93 | "call-bind": { 94 | "version": "1.0.2", 95 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 96 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 97 | "requires": { 98 | "function-bind": "^1.1.1", 99 | "get-intrinsic": "^1.0.2" 100 | } 101 | }, 102 | "caseless": { 103 | "version": "0.12.0", 104 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 105 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 106 | }, 107 | "combined-stream": { 108 | "version": "1.0.8", 109 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 110 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 111 | "requires": { 112 | "delayed-stream": "~1.0.0" 113 | } 114 | }, 115 | "content-type": { 116 | "version": "1.0.4", 117 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 118 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 119 | }, 120 | "core-util-is": { 121 | "version": "1.0.2", 122 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 123 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 124 | }, 125 | "dashdash": { 126 | "version": "1.14.1", 127 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 128 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 129 | "requires": { 130 | "assert-plus": "^1.0.0" 131 | } 132 | }, 133 | "delayed-stream": { 134 | "version": "1.0.0", 135 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 136 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 137 | }, 138 | "ecc-jsbn": { 139 | "version": "0.1.2", 140 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 141 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 142 | "requires": { 143 | "jsbn": "~0.1.0", 144 | "safer-buffer": "^2.1.0" 145 | } 146 | }, 147 | "extend": { 148 | "version": "3.0.2", 149 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 150 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 151 | }, 152 | "extsprintf": { 153 | "version": "1.3.0", 154 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 155 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 156 | }, 157 | "fast-deep-equal": { 158 | "version": "3.1.3", 159 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 160 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 161 | }, 162 | "fast-json-stable-stringify": { 163 | "version": "2.1.0", 164 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 165 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" 166 | }, 167 | "forever-agent": { 168 | "version": "0.6.1", 169 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 170 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 171 | }, 172 | "form-data": { 173 | "version": "2.3.3", 174 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 175 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 176 | "requires": { 177 | "asynckit": "^0.4.0", 178 | "combined-stream": "^1.0.6", 179 | "mime-types": "^2.1.12" 180 | } 181 | }, 182 | "function-bind": { 183 | "version": "1.1.1", 184 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 185 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 186 | }, 187 | "get-intrinsic": { 188 | "version": "1.1.1", 189 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", 190 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", 191 | "requires": { 192 | "function-bind": "^1.1.1", 193 | "has": "^1.0.3", 194 | "has-symbols": "^1.0.1" 195 | } 196 | }, 197 | "getpass": { 198 | "version": "0.1.7", 199 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 200 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 201 | "requires": { 202 | "assert-plus": "^1.0.0" 203 | } 204 | }, 205 | "graceful-fs": { 206 | "version": "4.2.4", 207 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", 208 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" 209 | }, 210 | "har-schema": { 211 | "version": "2.0.0", 212 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 213 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 214 | }, 215 | "har-validator": { 216 | "version": "5.1.5", 217 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", 218 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", 219 | "requires": { 220 | "ajv": "^6.12.3", 221 | "har-schema": "^2.0.0" 222 | } 223 | }, 224 | "has": { 225 | "version": "1.0.3", 226 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 227 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 228 | "requires": { 229 | "function-bind": "^1.1.1" 230 | } 231 | }, 232 | "has-symbols": { 233 | "version": "1.0.2", 234 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", 235 | "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" 236 | }, 237 | "http-signature": { 238 | "version": "1.2.0", 239 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 240 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 241 | "requires": { 242 | "assert-plus": "^1.0.0", 243 | "jsprim": "^1.2.2", 244 | "sshpk": "^1.7.0" 245 | } 246 | }, 247 | "image-size": { 248 | "version": "0.5.5", 249 | "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", 250 | "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=" 251 | }, 252 | "imurmurhash": { 253 | "version": "0.1.4", 254 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 255 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" 256 | }, 257 | "is-typedarray": { 258 | "version": "1.0.0", 259 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 260 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 261 | }, 262 | "isstream": { 263 | "version": "0.1.2", 264 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 265 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 266 | }, 267 | "jsbn": { 268 | "version": "0.1.1", 269 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 270 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 271 | }, 272 | "json-schema": { 273 | "version": "0.2.3", 274 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 275 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 276 | }, 277 | "json-schema-traverse": { 278 | "version": "0.4.1", 279 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 280 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 281 | }, 282 | "json-stringify-safe": { 283 | "version": "5.0.1", 284 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 285 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 286 | }, 287 | "jsprim": { 288 | "version": "1.4.1", 289 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 290 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 291 | "requires": { 292 | "assert-plus": "1.0.0", 293 | "extsprintf": "1.3.0", 294 | "json-schema": "0.2.3", 295 | "verror": "1.10.0" 296 | } 297 | }, 298 | "loglevel": { 299 | "version": "1.7.1", 300 | "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", 301 | "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==" 302 | }, 303 | "matrix-js-sdk": { 304 | "version": "12.1.0", 305 | "resolved": "https://registry.npmjs.org/matrix-js-sdk/-/matrix-js-sdk-12.1.0.tgz", 306 | "integrity": "sha512-/fSqOjD+mTlMD+/B3s3Ja6BfI46FnTDl43ojzGDUOsHRRmSYUmoONb83qkH5Fjm8cI2q5ZBJMsBfjuZwLVeiZw==", 307 | "requires": { 308 | "@babel/runtime": "^7.12.5", 309 | "another-json": "^0.2.0", 310 | "browser-request": "^0.3.3", 311 | "bs58": "^4.0.1", 312 | "content-type": "^1.0.4", 313 | "loglevel": "^1.7.1", 314 | "p-retry": "^4.5.0", 315 | "qs": "^6.9.6", 316 | "request": "^2.88.2", 317 | "unhomoglyph": "^1.0.6" 318 | } 319 | }, 320 | "mime-db": { 321 | "version": "1.44.0", 322 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 323 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" 324 | }, 325 | "mime-types": { 326 | "version": "2.1.27", 327 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 328 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 329 | "requires": { 330 | "mime-db": "1.44.0" 331 | } 332 | }, 333 | "node-localstorage": { 334 | "version": "1.3.1", 335 | "resolved": "https://registry.npmjs.org/node-localstorage/-/node-localstorage-1.3.1.tgz", 336 | "integrity": "sha512-NMWCSWWc6JbHT5PyWlNT2i8r7PgGYXVntmKawY83k/M0UJScZ5jirb61TLnqKwd815DfBQu+lR3sRw08SPzIaQ==", 337 | "requires": { 338 | "write-file-atomic": "^1.1.4" 339 | } 340 | }, 341 | "oauth-sign": { 342 | "version": "0.9.0", 343 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 344 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" 345 | }, 346 | "object-inspect": { 347 | "version": "1.11.0", 348 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", 349 | "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==" 350 | }, 351 | "p-retry": { 352 | "version": "4.6.1", 353 | "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", 354 | "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", 355 | "requires": { 356 | "@types/retry": "^0.12.0", 357 | "retry": "^0.13.1" 358 | } 359 | }, 360 | "parent-require": { 361 | "version": "1.0.0", 362 | "resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz", 363 | "integrity": "sha1-dGoWdjgIOoYLDu9nMssn7UbDKXc=" 364 | }, 365 | "performance-now": { 366 | "version": "2.1.0", 367 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 368 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 369 | }, 370 | "psl": { 371 | "version": "1.8.0", 372 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", 373 | "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" 374 | }, 375 | "punycode": { 376 | "version": "2.1.1", 377 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 378 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" 379 | }, 380 | "qs": { 381 | "version": "6.10.1", 382 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", 383 | "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", 384 | "requires": { 385 | "side-channel": "^1.0.4" 386 | } 387 | }, 388 | "regenerator-runtime": { 389 | "version": "0.13.9", 390 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", 391 | "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" 392 | }, 393 | "request": { 394 | "version": "2.88.2", 395 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 396 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 397 | "requires": { 398 | "aws-sign2": "~0.7.0", 399 | "aws4": "^1.8.0", 400 | "caseless": "~0.12.0", 401 | "combined-stream": "~1.0.6", 402 | "extend": "~3.0.2", 403 | "forever-agent": "~0.6.1", 404 | "form-data": "~2.3.2", 405 | "har-validator": "~5.1.3", 406 | "http-signature": "~1.2.0", 407 | "is-typedarray": "~1.0.0", 408 | "isstream": "~0.1.2", 409 | "json-stringify-safe": "~5.0.1", 410 | "mime-types": "~2.1.19", 411 | "oauth-sign": "~0.9.0", 412 | "performance-now": "^2.1.0", 413 | "qs": "~6.5.2", 414 | "safe-buffer": "^5.1.2", 415 | "tough-cookie": "~2.5.0", 416 | "tunnel-agent": "^0.6.0", 417 | "uuid": "^3.3.2" 418 | }, 419 | "dependencies": { 420 | "qs": { 421 | "version": "6.5.2", 422 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 423 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 424 | } 425 | } 426 | }, 427 | "retry": { 428 | "version": "0.13.1", 429 | "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", 430 | "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" 431 | }, 432 | "safe-buffer": { 433 | "version": "5.2.1", 434 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 435 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 436 | }, 437 | "safer-buffer": { 438 | "version": "2.1.2", 439 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 440 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 441 | }, 442 | "side-channel": { 443 | "version": "1.0.4", 444 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 445 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 446 | "requires": { 447 | "call-bind": "^1.0.0", 448 | "get-intrinsic": "^1.0.2", 449 | "object-inspect": "^1.9.0" 450 | } 451 | }, 452 | "slide": { 453 | "version": "1.1.6", 454 | "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", 455 | "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" 456 | }, 457 | "sshpk": { 458 | "version": "1.16.1", 459 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 460 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 461 | "requires": { 462 | "asn1": "~0.2.3", 463 | "assert-plus": "^1.0.0", 464 | "bcrypt-pbkdf": "^1.0.0", 465 | "dashdash": "^1.12.0", 466 | "ecc-jsbn": "~0.1.1", 467 | "getpass": "^0.1.1", 468 | "jsbn": "~0.1.0", 469 | "safer-buffer": "^2.0.2", 470 | "tweetnacl": "~0.14.0" 471 | } 472 | }, 473 | "tough-cookie": { 474 | "version": "2.5.0", 475 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 476 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 477 | "requires": { 478 | "psl": "^1.1.28", 479 | "punycode": "^2.1.1" 480 | } 481 | }, 482 | "tunnel-agent": { 483 | "version": "0.6.0", 484 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 485 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 486 | "requires": { 487 | "safe-buffer": "^5.0.1" 488 | } 489 | }, 490 | "tweetnacl": { 491 | "version": "0.14.5", 492 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 493 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 494 | }, 495 | "unhomoglyph": { 496 | "version": "1.0.6", 497 | "resolved": "https://registry.npmjs.org/unhomoglyph/-/unhomoglyph-1.0.6.tgz", 498 | "integrity": "sha512-7uvcWI3hWshSADBu4JpnyYbTVc7YlhF5GDW/oPD5AxIxl34k4wXR3WDkPnzLxkN32LiTCTKMQLtKVZiwki3zGg==" 499 | }, 500 | "uri-js": { 501 | "version": "4.4.0", 502 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", 503 | "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", 504 | "requires": { 505 | "punycode": "^2.1.0" 506 | } 507 | }, 508 | "uuid": { 509 | "version": "3.4.0", 510 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 511 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" 512 | }, 513 | "verror": { 514 | "version": "1.10.0", 515 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 516 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 517 | "requires": { 518 | "assert-plus": "^1.0.0", 519 | "core-util-is": "1.0.2", 520 | "extsprintf": "^1.2.0" 521 | } 522 | }, 523 | "write-file-atomic": { 524 | "version": "1.3.4", 525 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", 526 | "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", 527 | "requires": { 528 | "graceful-fs": "^4.1.11", 529 | "imurmurhash": "^0.1.4", 530 | "slide": "^1.1.5" 531 | } 532 | } 533 | } 534 | } 535 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hubot-matrix", 3 | "version": "2.0.1", 4 | "description": "Matrix adapter for Hubot", 5 | "main": "src/matrix.js", 6 | "scripts": { 7 | "test": "node --check src/*.js" 8 | }, 9 | "author": "David A Roberts", 10 | "license": "MIT", 11 | "dependencies": { 12 | "image-size": "^0.5.1", 13 | "matrix-js-sdk": "^12.1.0", 14 | "node-localstorage": "^1.3.0", 15 | "parent-require": "^1.0.0", 16 | "request": "^2.79.0" 17 | }, 18 | "peerDependencies": { 19 | "hubot": ">=3.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/matrix.js: -------------------------------------------------------------------------------- 1 | let Adapter, localStorage, Robot, TextMessage, User; 2 | try { 3 | ({Robot,Adapter,TextMessage,User} = require('hubot/es2015')); 4 | } catch (e) { 5 | try { 6 | ({Robot,Adapter,TextMessage,User} = require('hubot')); 7 | } catch (error) { 8 | let prequire = require('parent-require'); 9 | ({Robot,Adapter,TextMessage,User} = prequire('hubot')); 10 | } 11 | } 12 | 13 | let sdk = require('matrix-js-sdk'); 14 | let request = require('request'); 15 | let sizeOf = require('image-size'); 16 | 17 | if (localStorage == null) { 18 | let {LocalStorage} = require('node-localstorage'); 19 | localStorage = new LocalStorage('./hubot-matrix.localStorage'); 20 | } 21 | 22 | module.exports.use = (robot) => { 23 | 24 | let that; 25 | 26 | class Matrix extends Adapter { 27 | constructor() { 28 | super(...arguments); 29 | this.robot.logger.info("Constructor"); 30 | } 31 | 32 | handleUnknownDevices(err) { 33 | let that = this; 34 | return (() => { 35 | let result = []; 36 | for (var stranger in err.devices) { 37 | var devices = err.devices[stranger]; 38 | result.push((() => { 39 | let result1 = []; 40 | for (let device in devices) { 41 | let _ = devices[device]; 42 | that.robot.logger.info(`Acknowledging ${stranger}'s device ${device}`); 43 | result1.push(that.client.setDeviceKnown(stranger, device)); 44 | } 45 | return result1; 46 | })()); 47 | } 48 | return result; 49 | })(); 50 | } 51 | 52 | send(envelope, ...strings) { 53 | return (() => { 54 | let result = []; 55 | for (var str of Array.from(strings)) { 56 | that.robot.logger.info(`Sending to ${envelope.room}: ${str}`); 57 | if (/^(f|ht)tps?:\/\//i.test(str)) { 58 | result.push(that.sendURL(envelope, str)); 59 | } else { 60 | result.push(that.client.sendNotice(envelope.room, str).catch(err => { 61 | if (err.name === 'UnknownDeviceError') { 62 | that.handleUnknownDevices(err); 63 | return that.client.sendNotice(envelope.room, str); 64 | } 65 | })); 66 | } 67 | } 68 | return result; 69 | })(); 70 | } 71 | 72 | emote(envelope, ...strings) { 73 | return Array.from(strings).map((str) => 74 | that.client.sendEmoteMessage(envelope.room, str).catch(err => { 75 | if (err.name === 'UnknownDeviceError') { 76 | that.handleUnknownDevices(err); 77 | return that.client.sendEmoteMessage(envelope.room, str); 78 | } 79 | })); 80 | } 81 | 82 | reply(envelope, ...strings) { 83 | return Array.from(strings).map((str) => 84 | that.send(envelope, `${envelope.user.name}: ${str}`)); 85 | } 86 | 87 | topic(envelope, ...strings) { 88 | return Array.from(strings).map((str) => 89 | that.client.sendStateEvent(envelope.room, "m.room.topic", { 90 | topic: str 91 | }, "")); 92 | } 93 | 94 | sendURL(envelope, url) { 95 | that.robot.logger.info(`Downloading ${url}`); 96 | return request({url, encoding: null}, (error, response, body) => { 97 | if (error) { 98 | return that.robot.logger.info(`Request error: ${JSON.stringify(error)}`); 99 | } else if (response.statusCode === 200) { 100 | let info; 101 | try { 102 | let dims = sizeOf(body); 103 | that.robot.logger.info(`Image has dimensions ${JSON.stringify(dims)}, size ${body.length}`); 104 | if (dims.type === 'jpg') { dims.type = 'jpeg'; } 105 | info = { mimetype: `image/${dims.type}`, h: dims.height, w: dims.width, size: body.length }; 106 | return that.client.uploadContent(body, {name: url, type: info.mimetype, rawResponse: false, onlyContentUri: true}).done(content_uri => { 107 | return that.client.sendImageMessage(envelope.room, content_uri, info, url).catch(err => { 108 | if (err.name === 'UnknownDeviceError') { 109 | that.handleUnknownDevices(err); 110 | return that.client.sendImageMessage(envelope.room, content_uri, info, url); 111 | } 112 | }); 113 | }); 114 | } catch (error1) { 115 | error = error1; 116 | that.robot.logger.info(error.message); 117 | return that.send(envelope, ` ${url}`); 118 | } 119 | } 120 | }); 121 | } 122 | 123 | run() { 124 | that.robot.logger.info(`Run ${that.robot.name}`); 125 | let client = sdk.createClient(process.env.HUBOT_MATRIX_HOST_SERVER || 'https://matrix.org'); 126 | that.robot.matrixClient = client; 127 | return client.login('m.login.password', { 128 | user: process.env.HUBOT_MATRIX_USER || that.robot.name, 129 | password: process.env.HUBOT_MATRIX_PASSWORD 130 | }, (err, data) => { 131 | if (err) { 132 | that.robot.logger.error(err); 133 | return; 134 | } 135 | that.user_id = data.user_id; 136 | that.access_token = data.access_token; 137 | that.device_id = data.device_id; 138 | that.robot.logger.info(`Logged in ${that.user_id} on device ${that.device_id}`); 139 | that.client = sdk.createClient({ 140 | baseUrl: process.env.HUBOT_MATRIX_HOST_SERVER || 'https://matrix.org', 141 | accessToken: that.access_token, 142 | userId: that.user_id, 143 | deviceId: that.device_id, 144 | sessionStore: new sdk.WebStorageSessionStore(localStorage) 145 | }); 146 | that.client.on('sync', (state, prevState, data) => { 147 | switch (state) { 148 | case "PREPARED": 149 | that.robot.logger.info(`Synced ${that.client.getRooms().length} rooms`); 150 | // We really don't want to let people set the display name to something other than the bot 151 | // name because the bot only reacts to it's own name. 152 | const currentDisplayName = that.client.getUser(that.user_id).displayName; 153 | if (that.robot.name !== currentDisplayName) { 154 | that.robot.logger.info(`Setting display name to ${that.robot.name}`); 155 | that.client.setDisplayName(that.robot.name, ()=>{}); 156 | } 157 | return that.emit('connected'); 158 | } 159 | }); 160 | that.client.on('Room.timeline', (event, room, toStartOfTimeline) => { 161 | if ((event.getType() === 'm.room.message') && (toStartOfTimeline === false)) { 162 | that.client.setPresence("online"); 163 | let message = event.getContent(); 164 | let name = event.getSender(); 165 | let user = that.robot.brain.userForId(name); 166 | user.room = room.roomId; 167 | if (name !== that.user_id) { 168 | that.robot.logger.info(`Received message: ${JSON.stringify(message)} in room: ${user.room}, from: ${user.name} (${user.id}).`); 169 | if (message.msgtype === "m.text") { that.receive(new TextMessage(user, message.body)); } 170 | if ((message.msgtype !== "m.text") || (message.body.indexOf(that.robot.name) !== -1)) { return that.client.sendReadReceipt(event); } 171 | } 172 | } 173 | }); 174 | that.client.on('RoomMember.membership', (event, member) => { 175 | if ((member.membership === 'invite') && (member.userId === that.user_id)) { 176 | return that.client.joinRoom(member.roomId).done(() => { 177 | return that.robot.logger.info(`Auto-joined ${member.roomId}`); 178 | }); 179 | } 180 | }); 181 | return that.client.startClient(0); 182 | }); 183 | } 184 | } 185 | that = new Matrix(robot); 186 | return that; 187 | }; 188 | --------------------------------------------------------------------------------