├── .gitignore ├── header.png ├── index.js ├── package-lock.json ├── package.json └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | node_modules -------------------------------------------------------------------------------- /header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trevorhere/reddit_thread_messenger/093cb0e221cd816dd16413f37b36198792d692a5/header.png -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const snoowrap = require('snoowrap'); 3 | const { URLSearchParams } = require('url'); 4 | const FormData = require('form-data'); 5 | const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); 6 | const { REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET, REDDIT_USER, REDDIT_PASS } = process.env; 7 | 8 | const r = new snoowrap({ 9 | userAgent: `reddit-app:v0.1 (by /u/${REDDIT_USER})`, 10 | clientId: REDDIT_CLIENT_ID, 11 | clientSecret: REDDIT_CLIENT_SECRET, 12 | username: REDDIT_USER, 13 | password: REDDIT_PASS, 14 | }); 15 | 16 | const threadId = 'your_thread_id_here'; 17 | const messageSubject = 'your_message_subject_here'; 18 | const messageContent = `your_message_content_here`; 19 | 20 | async function main() { 21 | const usernames = await getUsersFromPost(threadId); 22 | console.log(`retrieved ${usernames.size} usernames`); 23 | const token = await getAccessToken(); 24 | await sendMessages(usernames, token); 25 | } 26 | 27 | async function getUsersFromPost(threadId) { 28 | try { 29 | 30 | const submission = await r.getSubmission(threadId); 31 | const comments = await submission.expandReplies({ limit: Infinity, depth: Infinity }); 32 | const usernames = new Set(); 33 | 34 | comments.comments.forEach(comment => { 35 | usernames.add(comment.author.name); 36 | }); 37 | 38 | return usernames; 39 | 40 | } catch (error) { 41 | console.error(`Failed to fetch comments: ${error.message}`); 42 | } 43 | } 44 | 45 | async function sendMessages(usernames, access_token) { 46 | usernames.forEach(async (username) => { 47 | try { 48 | const result = await sendMessage(username, access_token) 49 | console.log(`message sent to: ${username}: ${result}`); 50 | } catch (error) { 51 | console.error(`Failed to send message to ${username}: ${error.message}`); 52 | } 53 | }); 54 | 55 | } 56 | 57 | async function sendMessage(to, access_token) { 58 | 59 | const body = new FormData(); 60 | body.append('to', `/u/${to}`); 61 | body.append("subject", messageSubject); 62 | body.append("text", messageContent); 63 | 64 | const response = await fetch('https://oauth.reddit.com/api/compose', { 65 | method: 'POST', 66 | headers: { 67 | ...body.getHeaders(), 68 | 'Authorization': `Bearer ${access_token}`, 69 | }, 70 | body: body 71 | }); 72 | 73 | if (!response.ok) { 74 | const errorBody = await response.text(); 75 | throw new Error(`Failed to send message: ${response.status} ${response.statusText} - ${errorBody}`); 76 | } 77 | 78 | const data = await response.json(); 79 | return data.success 80 | } 81 | 82 | async function getAccessToken() { 83 | const params = new URLSearchParams(); 84 | params.append('grant_type', 'password'); 85 | params.append('username', REDDIT_USER); 86 | params.append('password', REDDIT_PASS); 87 | 88 | const response = await fetch('https://www.reddit.com/api/v1/access_token', { 89 | method: 'POST', 90 | body: params, 91 | headers: { 92 | 'Authorization': 'Basic ' + Buffer.from(`${REDDIT_CLIENT_ID}:${REDDIT_CLIENT_SECRET}`).toString('base64'), 93 | 'Content-Type': 'application/x-www-form-urlencoded', 94 | }, 95 | }); 96 | 97 | if (!response.ok) { 98 | throw new Error(`Error getting access token: ${response.statusText}`); 99 | } 100 | 101 | 102 | const data = await response.json(); 103 | console.log('access token retrieved'); 104 | return data.access_token; 105 | } 106 | 107 | main() 108 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reddit_messager", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "reddit_messager", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "dotenv": "^16.4.5", 13 | "form-data": "^4.0.0", 14 | "node-fetch": "^2.7.0", 15 | "snoowrap": "^1.23.0", 16 | "url": "^0.11.3" 17 | } 18 | }, 19 | "node_modules/ajv": { 20 | "version": "6.12.6", 21 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 22 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 23 | "dependencies": { 24 | "fast-deep-equal": "^3.1.1", 25 | "fast-json-stable-stringify": "^2.0.0", 26 | "json-schema-traverse": "^0.4.1", 27 | "uri-js": "^4.2.2" 28 | }, 29 | "funding": { 30 | "type": "github", 31 | "url": "https://github.com/sponsors/epoberezkin" 32 | } 33 | }, 34 | "node_modules/asn1": { 35 | "version": "0.2.6", 36 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", 37 | "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", 38 | "dependencies": { 39 | "safer-buffer": "~2.1.0" 40 | } 41 | }, 42 | "node_modules/assert-plus": { 43 | "version": "1.0.0", 44 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 45 | "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", 46 | "engines": { 47 | "node": ">=0.8" 48 | } 49 | }, 50 | "node_modules/async-limiter": { 51 | "version": "1.0.1", 52 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", 53 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" 54 | }, 55 | "node_modules/asynckit": { 56 | "version": "0.4.0", 57 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 58 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 59 | }, 60 | "node_modules/aws-sign2": { 61 | "version": "0.7.0", 62 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 63 | "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", 64 | "engines": { 65 | "node": "*" 66 | } 67 | }, 68 | "node_modules/aws4": { 69 | "version": "1.12.0", 70 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", 71 | "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" 72 | }, 73 | "node_modules/bcrypt-pbkdf": { 74 | "version": "1.0.2", 75 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 76 | "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", 77 | "dependencies": { 78 | "tweetnacl": "^0.14.3" 79 | } 80 | }, 81 | "node_modules/bluebird": { 82 | "version": "3.7.2", 83 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 84 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 85 | }, 86 | "node_modules/call-bind": { 87 | "version": "1.0.7", 88 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 89 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 90 | "dependencies": { 91 | "es-define-property": "^1.0.0", 92 | "es-errors": "^1.3.0", 93 | "function-bind": "^1.1.2", 94 | "get-intrinsic": "^1.2.4", 95 | "set-function-length": "^1.2.1" 96 | }, 97 | "engines": { 98 | "node": ">= 0.4" 99 | }, 100 | "funding": { 101 | "url": "https://github.com/sponsors/ljharb" 102 | } 103 | }, 104 | "node_modules/caseless": { 105 | "version": "0.12.0", 106 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 107 | "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" 108 | }, 109 | "node_modules/combined-stream": { 110 | "version": "1.0.8", 111 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 112 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 113 | "dependencies": { 114 | "delayed-stream": "~1.0.0" 115 | }, 116 | "engines": { 117 | "node": ">= 0.8" 118 | } 119 | }, 120 | "node_modules/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": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" 124 | }, 125 | "node_modules/dashdash": { 126 | "version": "1.14.1", 127 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 128 | "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", 129 | "dependencies": { 130 | "assert-plus": "^1.0.0" 131 | }, 132 | "engines": { 133 | "node": ">=0.10" 134 | } 135 | }, 136 | "node_modules/define-data-property": { 137 | "version": "1.1.4", 138 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 139 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 140 | "dependencies": { 141 | "es-define-property": "^1.0.0", 142 | "es-errors": "^1.3.0", 143 | "gopd": "^1.0.1" 144 | }, 145 | "engines": { 146 | "node": ">= 0.4" 147 | }, 148 | "funding": { 149 | "url": "https://github.com/sponsors/ljharb" 150 | } 151 | }, 152 | "node_modules/delayed-stream": { 153 | "version": "1.0.0", 154 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 155 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 156 | "engines": { 157 | "node": ">=0.4.0" 158 | } 159 | }, 160 | "node_modules/dotenv": { 161 | "version": "16.4.5", 162 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", 163 | "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", 164 | "engines": { 165 | "node": ">=12" 166 | }, 167 | "funding": { 168 | "url": "https://dotenvx.com" 169 | } 170 | }, 171 | "node_modules/ecc-jsbn": { 172 | "version": "0.1.2", 173 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 174 | "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", 175 | "dependencies": { 176 | "jsbn": "~0.1.0", 177 | "safer-buffer": "^2.1.0" 178 | } 179 | }, 180 | "node_modules/es-define-property": { 181 | "version": "1.0.0", 182 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 183 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 184 | "dependencies": { 185 | "get-intrinsic": "^1.2.4" 186 | }, 187 | "engines": { 188 | "node": ">= 0.4" 189 | } 190 | }, 191 | "node_modules/es-errors": { 192 | "version": "1.3.0", 193 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 194 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 195 | "engines": { 196 | "node": ">= 0.4" 197 | } 198 | }, 199 | "node_modules/extend": { 200 | "version": "3.0.2", 201 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 202 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 203 | }, 204 | "node_modules/extsprintf": { 205 | "version": "1.3.0", 206 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 207 | "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", 208 | "engines": [ 209 | "node >=0.6.0" 210 | ] 211 | }, 212 | "node_modules/fast-deep-equal": { 213 | "version": "3.1.3", 214 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 215 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 216 | }, 217 | "node_modules/fast-json-stable-stringify": { 218 | "version": "2.1.0", 219 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 220 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" 221 | }, 222 | "node_modules/forever-agent": { 223 | "version": "0.6.1", 224 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 225 | "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", 226 | "engines": { 227 | "node": "*" 228 | } 229 | }, 230 | "node_modules/form-data": { 231 | "version": "4.0.0", 232 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 233 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 234 | "dependencies": { 235 | "asynckit": "^0.4.0", 236 | "combined-stream": "^1.0.8", 237 | "mime-types": "^2.1.12" 238 | }, 239 | "engines": { 240 | "node": ">= 6" 241 | } 242 | }, 243 | "node_modules/function-bind": { 244 | "version": "1.1.2", 245 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 246 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 247 | "funding": { 248 | "url": "https://github.com/sponsors/ljharb" 249 | } 250 | }, 251 | "node_modules/get-intrinsic": { 252 | "version": "1.2.4", 253 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 254 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 255 | "dependencies": { 256 | "es-errors": "^1.3.0", 257 | "function-bind": "^1.1.2", 258 | "has-proto": "^1.0.1", 259 | "has-symbols": "^1.0.3", 260 | "hasown": "^2.0.0" 261 | }, 262 | "engines": { 263 | "node": ">= 0.4" 264 | }, 265 | "funding": { 266 | "url": "https://github.com/sponsors/ljharb" 267 | } 268 | }, 269 | "node_modules/getpass": { 270 | "version": "0.1.7", 271 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 272 | "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", 273 | "dependencies": { 274 | "assert-plus": "^1.0.0" 275 | } 276 | }, 277 | "node_modules/gopd": { 278 | "version": "1.0.1", 279 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 280 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 281 | "dependencies": { 282 | "get-intrinsic": "^1.1.3" 283 | }, 284 | "funding": { 285 | "url": "https://github.com/sponsors/ljharb" 286 | } 287 | }, 288 | "node_modules/har-schema": { 289 | "version": "2.0.0", 290 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 291 | "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", 292 | "engines": { 293 | "node": ">=4" 294 | } 295 | }, 296 | "node_modules/har-validator": { 297 | "version": "5.1.5", 298 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", 299 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", 300 | "deprecated": "this library is no longer supported", 301 | "dependencies": { 302 | "ajv": "^6.12.3", 303 | "har-schema": "^2.0.0" 304 | }, 305 | "engines": { 306 | "node": ">=6" 307 | } 308 | }, 309 | "node_modules/harmony-reflect": { 310 | "version": "1.6.2", 311 | "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", 312 | "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==" 313 | }, 314 | "node_modules/has-property-descriptors": { 315 | "version": "1.0.2", 316 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 317 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 318 | "dependencies": { 319 | "es-define-property": "^1.0.0" 320 | }, 321 | "funding": { 322 | "url": "https://github.com/sponsors/ljharb" 323 | } 324 | }, 325 | "node_modules/has-proto": { 326 | "version": "1.0.3", 327 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 328 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", 329 | "engines": { 330 | "node": ">= 0.4" 331 | }, 332 | "funding": { 333 | "url": "https://github.com/sponsors/ljharb" 334 | } 335 | }, 336 | "node_modules/has-symbols": { 337 | "version": "1.0.3", 338 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 339 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 340 | "engines": { 341 | "node": ">= 0.4" 342 | }, 343 | "funding": { 344 | "url": "https://github.com/sponsors/ljharb" 345 | } 346 | }, 347 | "node_modules/hasown": { 348 | "version": "2.0.1", 349 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", 350 | "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", 351 | "dependencies": { 352 | "function-bind": "^1.1.2" 353 | }, 354 | "engines": { 355 | "node": ">= 0.4" 356 | } 357 | }, 358 | "node_modules/http-signature": { 359 | "version": "1.2.0", 360 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 361 | "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", 362 | "dependencies": { 363 | "assert-plus": "^1.0.0", 364 | "jsprim": "^1.2.2", 365 | "sshpk": "^1.7.0" 366 | }, 367 | "engines": { 368 | "node": ">=0.8", 369 | "npm": ">=1.3.7" 370 | } 371 | }, 372 | "node_modules/is-typedarray": { 373 | "version": "1.0.0", 374 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 375 | "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" 376 | }, 377 | "node_modules/isstream": { 378 | "version": "0.1.2", 379 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 380 | "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" 381 | }, 382 | "node_modules/jsbn": { 383 | "version": "0.1.1", 384 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 385 | "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" 386 | }, 387 | "node_modules/json-schema": { 388 | "version": "0.4.0", 389 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", 390 | "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" 391 | }, 392 | "node_modules/json-schema-traverse": { 393 | "version": "0.4.1", 394 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 395 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 396 | }, 397 | "node_modules/json-stringify-safe": { 398 | "version": "5.0.1", 399 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 400 | "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" 401 | }, 402 | "node_modules/jsprim": { 403 | "version": "1.4.2", 404 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", 405 | "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", 406 | "dependencies": { 407 | "assert-plus": "1.0.0", 408 | "extsprintf": "1.3.0", 409 | "json-schema": "0.4.0", 410 | "verror": "1.10.0" 411 | }, 412 | "engines": { 413 | "node": ">=0.6.0" 414 | } 415 | }, 416 | "node_modules/lodash": { 417 | "version": "4.17.21", 418 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 419 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 420 | }, 421 | "node_modules/mime-db": { 422 | "version": "1.52.0", 423 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 424 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 425 | "engines": { 426 | "node": ">= 0.6" 427 | } 428 | }, 429 | "node_modules/mime-types": { 430 | "version": "2.1.35", 431 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 432 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 433 | "dependencies": { 434 | "mime-db": "1.52.0" 435 | }, 436 | "engines": { 437 | "node": ">= 0.6" 438 | } 439 | }, 440 | "node_modules/node-fetch": { 441 | "version": "2.7.0", 442 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", 443 | "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", 444 | "dependencies": { 445 | "whatwg-url": "^5.0.0" 446 | }, 447 | "engines": { 448 | "node": "4.x || >=6.0.0" 449 | }, 450 | "peerDependencies": { 451 | "encoding": "^0.1.0" 452 | }, 453 | "peerDependenciesMeta": { 454 | "encoding": { 455 | "optional": true 456 | } 457 | } 458 | }, 459 | "node_modules/oauth-sign": { 460 | "version": "0.9.0", 461 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 462 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 463 | "engines": { 464 | "node": "*" 465 | } 466 | }, 467 | "node_modules/object-inspect": { 468 | "version": "1.13.1", 469 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", 470 | "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", 471 | "funding": { 472 | "url": "https://github.com/sponsors/ljharb" 473 | } 474 | }, 475 | "node_modules/performance-now": { 476 | "version": "2.1.0", 477 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 478 | "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" 479 | }, 480 | "node_modules/promise-chains": { 481 | "version": "0.3.12", 482 | "resolved": "https://registry.npmjs.org/promise-chains/-/promise-chains-0.3.12.tgz", 483 | "integrity": "sha512-LgK0acA/djbxbJhN+ooR3+VChzgDr4wTYhhBlxJCUQCO2zsD37/SuHBxeWcB+/vlwag2NEr+kFz03/VBHs+zPw==", 484 | "dependencies": { 485 | "harmony-reflect": "^1.4.3" 486 | } 487 | }, 488 | "node_modules/psl": { 489 | "version": "1.9.0", 490 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", 491 | "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" 492 | }, 493 | "node_modules/punycode": { 494 | "version": "2.3.1", 495 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 496 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 497 | "engines": { 498 | "node": ">=6" 499 | } 500 | }, 501 | "node_modules/qs": { 502 | "version": "6.5.3", 503 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", 504 | "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", 505 | "engines": { 506 | "node": ">=0.6" 507 | } 508 | }, 509 | "node_modules/request": { 510 | "version": "2.88.2", 511 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 512 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 513 | "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", 514 | "dependencies": { 515 | "aws-sign2": "~0.7.0", 516 | "aws4": "^1.8.0", 517 | "caseless": "~0.12.0", 518 | "combined-stream": "~1.0.6", 519 | "extend": "~3.0.2", 520 | "forever-agent": "~0.6.1", 521 | "form-data": "~2.3.2", 522 | "har-validator": "~5.1.3", 523 | "http-signature": "~1.2.0", 524 | "is-typedarray": "~1.0.0", 525 | "isstream": "~0.1.2", 526 | "json-stringify-safe": "~5.0.1", 527 | "mime-types": "~2.1.19", 528 | "oauth-sign": "~0.9.0", 529 | "performance-now": "^2.1.0", 530 | "qs": "~6.5.2", 531 | "safe-buffer": "^5.1.2", 532 | "tough-cookie": "~2.5.0", 533 | "tunnel-agent": "^0.6.0", 534 | "uuid": "^3.3.2" 535 | }, 536 | "engines": { 537 | "node": ">= 6" 538 | } 539 | }, 540 | "node_modules/request-promise": { 541 | "version": "4.2.6", 542 | "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", 543 | "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", 544 | "deprecated": "request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", 545 | "dependencies": { 546 | "bluebird": "^3.5.0", 547 | "request-promise-core": "1.1.4", 548 | "stealthy-require": "^1.1.1", 549 | "tough-cookie": "^2.3.3" 550 | }, 551 | "engines": { 552 | "node": ">=0.10.0" 553 | }, 554 | "peerDependencies": { 555 | "request": "^2.34" 556 | } 557 | }, 558 | "node_modules/request-promise-core": { 559 | "version": "1.1.4", 560 | "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", 561 | "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", 562 | "dependencies": { 563 | "lodash": "^4.17.19" 564 | }, 565 | "engines": { 566 | "node": ">=0.10.0" 567 | }, 568 | "peerDependencies": { 569 | "request": "^2.34" 570 | } 571 | }, 572 | "node_modules/request/node_modules/form-data": { 573 | "version": "2.3.3", 574 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 575 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 576 | "dependencies": { 577 | "asynckit": "^0.4.0", 578 | "combined-stream": "^1.0.6", 579 | "mime-types": "^2.1.12" 580 | }, 581 | "engines": { 582 | "node": ">= 0.12" 583 | } 584 | }, 585 | "node_modules/safe-buffer": { 586 | "version": "5.2.1", 587 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 588 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 589 | "funding": [ 590 | { 591 | "type": "github", 592 | "url": "https://github.com/sponsors/feross" 593 | }, 594 | { 595 | "type": "patreon", 596 | "url": "https://www.patreon.com/feross" 597 | }, 598 | { 599 | "type": "consulting", 600 | "url": "https://feross.org/support" 601 | } 602 | ] 603 | }, 604 | "node_modules/safer-buffer": { 605 | "version": "2.1.2", 606 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 607 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 608 | }, 609 | "node_modules/set-function-length": { 610 | "version": "1.2.1", 611 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", 612 | "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", 613 | "dependencies": { 614 | "define-data-property": "^1.1.2", 615 | "es-errors": "^1.3.0", 616 | "function-bind": "^1.1.2", 617 | "get-intrinsic": "^1.2.3", 618 | "gopd": "^1.0.1", 619 | "has-property-descriptors": "^1.0.1" 620 | }, 621 | "engines": { 622 | "node": ">= 0.4" 623 | } 624 | }, 625 | "node_modules/side-channel": { 626 | "version": "1.0.6", 627 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 628 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 629 | "dependencies": { 630 | "call-bind": "^1.0.7", 631 | "es-errors": "^1.3.0", 632 | "get-intrinsic": "^1.2.4", 633 | "object-inspect": "^1.13.1" 634 | }, 635 | "engines": { 636 | "node": ">= 0.4" 637 | }, 638 | "funding": { 639 | "url": "https://github.com/sponsors/ljharb" 640 | } 641 | }, 642 | "node_modules/snoowrap": { 643 | "version": "1.23.0", 644 | "resolved": "https://registry.npmjs.org/snoowrap/-/snoowrap-1.23.0.tgz", 645 | "integrity": "sha512-8FIGWr20Gc+d/C3NRrNPp5VQFNb+eGaQyvIkM5KUL71pYpRM231fkRdLNydMrdtLNRDrTZeZApHHCb8Uk/QuTQ==", 646 | "dependencies": { 647 | "bluebird": "^3.5.5", 648 | "lodash": "^4.17.15", 649 | "promise-chains": "^0.3.11", 650 | "request": "^2.88.2", 651 | "request-promise": "^4.2.6", 652 | "ws": "^3.3.1" 653 | }, 654 | "engines": { 655 | "node": ">=4.0.0" 656 | } 657 | }, 658 | "node_modules/sshpk": { 659 | "version": "1.18.0", 660 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", 661 | "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", 662 | "dependencies": { 663 | "asn1": "~0.2.3", 664 | "assert-plus": "^1.0.0", 665 | "bcrypt-pbkdf": "^1.0.0", 666 | "dashdash": "^1.12.0", 667 | "ecc-jsbn": "~0.1.1", 668 | "getpass": "^0.1.1", 669 | "jsbn": "~0.1.0", 670 | "safer-buffer": "^2.0.2", 671 | "tweetnacl": "~0.14.0" 672 | }, 673 | "bin": { 674 | "sshpk-conv": "bin/sshpk-conv", 675 | "sshpk-sign": "bin/sshpk-sign", 676 | "sshpk-verify": "bin/sshpk-verify" 677 | }, 678 | "engines": { 679 | "node": ">=0.10.0" 680 | } 681 | }, 682 | "node_modules/stealthy-require": { 683 | "version": "1.1.1", 684 | "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", 685 | "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", 686 | "engines": { 687 | "node": ">=0.10.0" 688 | } 689 | }, 690 | "node_modules/tough-cookie": { 691 | "version": "2.5.0", 692 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 693 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 694 | "dependencies": { 695 | "psl": "^1.1.28", 696 | "punycode": "^2.1.1" 697 | }, 698 | "engines": { 699 | "node": ">=0.8" 700 | } 701 | }, 702 | "node_modules/tr46": { 703 | "version": "0.0.3", 704 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 705 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 706 | }, 707 | "node_modules/tunnel-agent": { 708 | "version": "0.6.0", 709 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 710 | "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", 711 | "dependencies": { 712 | "safe-buffer": "^5.0.1" 713 | }, 714 | "engines": { 715 | "node": "*" 716 | } 717 | }, 718 | "node_modules/tweetnacl": { 719 | "version": "0.14.5", 720 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 721 | "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" 722 | }, 723 | "node_modules/ultron": { 724 | "version": "1.1.1", 725 | "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", 726 | "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" 727 | }, 728 | "node_modules/uri-js": { 729 | "version": "4.4.1", 730 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 731 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 732 | "dependencies": { 733 | "punycode": "^2.1.0" 734 | } 735 | }, 736 | "node_modules/url": { 737 | "version": "0.11.3", 738 | "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", 739 | "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", 740 | "dependencies": { 741 | "punycode": "^1.4.1", 742 | "qs": "^6.11.2" 743 | } 744 | }, 745 | "node_modules/url/node_modules/punycode": { 746 | "version": "1.4.1", 747 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 748 | "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" 749 | }, 750 | "node_modules/url/node_modules/qs": { 751 | "version": "6.12.0", 752 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", 753 | "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==", 754 | "dependencies": { 755 | "side-channel": "^1.0.6" 756 | }, 757 | "engines": { 758 | "node": ">=0.6" 759 | }, 760 | "funding": { 761 | "url": "https://github.com/sponsors/ljharb" 762 | } 763 | }, 764 | "node_modules/uuid": { 765 | "version": "3.4.0", 766 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 767 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 768 | "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", 769 | "bin": { 770 | "uuid": "bin/uuid" 771 | } 772 | }, 773 | "node_modules/verror": { 774 | "version": "1.10.0", 775 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 776 | "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", 777 | "engines": [ 778 | "node >=0.6.0" 779 | ], 780 | "dependencies": { 781 | "assert-plus": "^1.0.0", 782 | "core-util-is": "1.0.2", 783 | "extsprintf": "^1.2.0" 784 | } 785 | }, 786 | "node_modules/webidl-conversions": { 787 | "version": "3.0.1", 788 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 789 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 790 | }, 791 | "node_modules/whatwg-url": { 792 | "version": "5.0.0", 793 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 794 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 795 | "dependencies": { 796 | "tr46": "~0.0.3", 797 | "webidl-conversions": "^3.0.0" 798 | } 799 | }, 800 | "node_modules/ws": { 801 | "version": "3.3.3", 802 | "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", 803 | "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", 804 | "dependencies": { 805 | "async-limiter": "~1.0.0", 806 | "safe-buffer": "~5.1.0", 807 | "ultron": "~1.1.0" 808 | } 809 | }, 810 | "node_modules/ws/node_modules/safe-buffer": { 811 | "version": "5.1.2", 812 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 813 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 814 | } 815 | } 816 | } 817 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reddit_messager", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "dotenv": "^16.4.5", 14 | "form-data": "^4.0.0", 15 | "node-fetch": "^2.7.0", 16 | "snoowrap": "^1.23.0", 17 | "url": "^0.11.3" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ![header image]() 2 | 3 | # Reddit Thread Messenger 4 | 5 | This Node.js application allows you to message all users participating in a Reddit thread. It utilizes the Reddit API to retrieve usernames from a specified thread and sends them a message with a predefined subject and content. 6 | 7 | ## Usage 8 | 9 | This repo was put together to make it easier for the author to do product validation. Steps taken for this usecase: 10 | 1. Find reddit thread related to the product you are seeking to validate 11 | 2. Send message to users. Example message: 12 | 13 | ``` 14 | hey, there. sorry to bug you, just wanted to ask a quick question if that's alright..i'm building a [thing you are building]. [Statement about the value add of the thing you're building] .. after reading a few of your recent comments, it looks like you might be able to give insight on the validity of this product. I would love to hear your thoughts if you have them or, if you're interested we could [offer of value to the potential user]? .. thanks for your time, and have a good one!` 15 | ``` 16 | 3. Use reddit's message UI to continue conversations/further engage potential users. 17 | 18 | ## Instructions 19 | 20 | Follow these steps to set up and use the Reddit Message Sender: 21 | 22 | 1. **Obtain Reddit API Credentials** 23 | - Create a Reddit account if you don't have one. 24 | - Go to the Reddit [App Preferences page](https://www.reddit.com/prefs/apps) and create a new app. 25 | - Obtain the client ID and client secret generated for your app. 26 | 27 | 2. **Set Up Environment Variables** 28 | - Create a `.env` file in the project root directory. 29 | - Define the following environment variables in the `.env` file: 30 | ```plaintext 31 | REDDIT_CLIENT_ID=your_client_id_here 32 | REDDIT_CLIENT_SECRET=your_client_secret_here 33 | REDDIT_USER=your_reddit_username 34 | REDDIT_PASS=your_reddit_password 35 | ``` 36 | 37 | 3. **Set Thread ID, Message Subject, and Content** 38 | - Replace placeholders in the `index.js` file with your thread ID, message subject, and message content: 39 | ```javascript 40 | const threadId = 'your_thread_id_here'; 41 | const messageSubject = 'your_message_subject_here'; 42 | const messageContent = `your_message_content_here`; 43 | ``` 44 | 45 | 4. **Install Dependencies** 46 | - Run `npm install` to install required dependencies. 47 | 48 | 5. **Run the Application** 49 | - Execute `node index.js` to run the application and send one set of messages. 50 | - The program will retrieve usernames from the specified thread and send them the message. 51 | 52 | ## Example 53 | 54 | Here's how you can set up the necessary parameters in the `index.js` file: 55 | 56 | ```javascript 57 | // Set the thread ID 58 | const threadId = 'abc123'; // Replace with your thread ID 59 | 60 | // Set the message subject and content 61 | const messageSubject = 'Greetings from Reddit Bot'; 62 | const messageContent = `Hello there! You're receiving this message from our Reddit bot.`; 63 | 64 | --------------------------------------------------------------------------------