├── .eslintrc.yml ├── .gitignore ├── LICENSE ├── README.md ├── bin └── gitter-export-room.js └── package.json /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | rules: 6 | accessor-pairs: error 7 | array-bracket-spacing: error 8 | array-callback-return: error 9 | arrow-body-style: 10 | - error 11 | - always 12 | arrow-parens: 13 | - error 14 | - as-needed 15 | arrow-spacing: 16 | - error 17 | - after: true 18 | before: true 19 | block-scoped-var: error 20 | block-spacing: error 21 | brace-style: error 22 | callback-return: error 23 | camelcase: error 24 | comma-spacing: 25 | - error 26 | - after: true 27 | before: false 28 | comma-style: 29 | - error 30 | - last 31 | complexity: error 32 | computed-property-spacing: 33 | - error 34 | - never 35 | consistent-return: error 36 | consistent-this: error 37 | curly: error 38 | default-case: error 39 | dot-location: 40 | - error 41 | - property 42 | dot-notation: error 43 | eol-last: error 44 | eqeqeq: error 45 | func-names: 'off' 46 | func-style: error 47 | generator-star-spacing: 'off' 48 | global-require: error 49 | guard-for-in: error 50 | handle-callback-err: error 51 | id-blacklist: error 52 | id-length: error 53 | id-match: error 54 | indent: 'off' 55 | init-declarations: 'off' 56 | jsx-quotes: error 57 | key-spacing: error 58 | keyword-spacing: 59 | - error 60 | - after: true 61 | before: true 62 | linebreak-style: 63 | - error 64 | - unix 65 | lines-around-comment: error 66 | max-depth: error 67 | max-len: error 68 | max-nested-callbacks: error 69 | max-params: error 70 | max-statements: error 71 | max-statements-per-line: error 72 | new-cap: error 73 | new-parens: error 74 | newline-after-var: 'off' 75 | newline-before-return: 'off' 76 | newline-per-chained-call: error 77 | no-alert: error 78 | no-array-constructor: error 79 | no-bitwise: error 80 | no-caller: error 81 | no-catch-shadow: error 82 | no-confusing-arrow: error 83 | no-continue: error 84 | no-div-regex: error 85 | no-duplicate-imports: error 86 | no-else-return: error 87 | no-empty-function: error 88 | no-eq-null: error 89 | no-eval: error 90 | no-extend-native: error 91 | no-extra-bind: error 92 | no-extra-label: error 93 | no-extra-parens: error 94 | no-floating-decimal: error 95 | no-implicit-coercion: error 96 | no-implicit-globals: error 97 | no-implied-eval: error 98 | no-inline-comments: error 99 | no-invalid-this: error 100 | no-iterator: error 101 | no-label-var: error 102 | no-labels: error 103 | no-lone-blocks: error 104 | no-lonely-if: error 105 | no-loop-func: error 106 | no-magic-numbers: 'off' 107 | no-mixed-requires: error 108 | no-multi-spaces: error 109 | no-multi-str: error 110 | no-multiple-empty-lines: error 111 | no-native-reassign: error 112 | no-negated-condition: error 113 | no-nested-ternary: error 114 | no-new: error 115 | no-new-func: error 116 | no-new-object: error 117 | no-new-require: error 118 | no-new-wrappers: error 119 | no-octal-escape: error 120 | no-param-reassign: 121 | - error 122 | - props: false 123 | no-path-concat: error 124 | no-plusplus: error 125 | no-process-env: 'off' 126 | no-process-exit: error 127 | no-proto: error 128 | no-restricted-globals: error 129 | no-restricted-imports: error 130 | no-restricted-modules: error 131 | no-restricted-syntax: error 132 | no-return-assign: error 133 | no-script-url: error 134 | no-self-compare: error 135 | no-sequences: error 136 | no-shadow: error 137 | no-shadow-restricted-names: error 138 | no-spaced-func: error 139 | no-sync: error 140 | no-ternary: error 141 | no-throw-literal: error 142 | no-trailing-spaces: error 143 | no-undef-init: error 144 | no-undefined: error 145 | no-underscore-dangle: error 146 | no-unmodified-loop-condition: error 147 | no-unneeded-ternary: error 148 | no-unsafe-finally: error 149 | no-unused-expressions: 'off' 150 | no-use-before-define: error 151 | no-useless-call: error 152 | no-useless-computed-key: error 153 | no-useless-concat: error 154 | no-useless-constructor: error 155 | no-useless-escape: error 156 | no-var: error 157 | no-void: error 158 | no-warning-comments: error 159 | no-whitespace-before-property: error 160 | no-with: error 161 | object-curly-spacing: 162 | - error 163 | - never 164 | object-property-newline: error 165 | object-shorthand: error 166 | one-var: 'off' 167 | one-var-declaration-per-line: error 168 | operator-assignment: error 169 | operator-linebreak: error 170 | padded-blocks: 'off' 171 | prefer-arrow-callback: error 172 | prefer-const: error 173 | prefer-reflect: error 174 | prefer-rest-params: error 175 | prefer-spread: error 176 | prefer-template: error 177 | quote-props: 'off' 178 | quotes: 179 | - error 180 | - single 181 | radix: error 182 | require-jsdoc: error 183 | require-yield: error 184 | semi: error 185 | semi-spacing: error 186 | sort-imports: error 187 | sort-vars: error 188 | space-before-blocks: error 189 | space-before-function-paren: error 190 | space-in-parens: 191 | - error 192 | - never 193 | space-infix-ops: error 194 | space-unary-ops: error 195 | spaced-comment: error 196 | strict: error 197 | template-curly-spacing: error 198 | valid-jsdoc: error 199 | vars-on-top: error 200 | wrap-iife: error 201 | wrap-regex: 'off' 202 | yield-star-spacing: error 203 | yoda: error 204 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # nyc test coverage 20 | .nyc_output 21 | 22 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 23 | .grunt 24 | 25 | # node-waf configuration 26 | .lock-wscript 27 | 28 | # Compiled binary addons (http://nodejs.org/api/addons.html) 29 | build/Release 30 | 31 | # Dependency directories 32 | node_modules 33 | jspm_packages 34 | 35 | # Optional npm cache directory 36 | .npm 37 | 38 | # Optional REPL history 39 | .node_repl_history 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Christopher Hiller <boneskull@boneskull.com> 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gitter-export-room 2 | 3 | > Export a JSON archive of a Gitter room's messages 4 | 5 | ## Install 6 | 7 | ```shell 8 | $ npm install --global gitter-export-room 9 | ``` 10 | 11 | ## Usage 12 | 13 | Use `--token` or specify `GITTER_TOKEN` env variable to authenticate. 14 | 15 | ### List user's rooms 16 | 17 | ``` 18 | $ gitter-export-room list 19 | ``` 20 | 21 | The above command shows the user's rooms and its ids 22 | 23 | ### Export room 24 | 25 | ``` 26 | $ gitter-export-room id 27 | ``` 28 | 29 | The above command will dump a bunch of JSON to STDOUT with progress to STDERR. Redirect to file if you wish. 30 | 31 | See `--help` for help. 32 | 33 | ## License 34 | 35 | Copyright 2016 Christopher Hiller. Licensed MIT 36 | 37 | 38 | -------------------------------------------------------------------------------- /bin/gitter-export-room.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict'; 4 | 5 | const Gitter = require('node-gitter'); 6 | const Promise = require('bluebird'); 7 | 8 | const PER_PAGE = 500; 9 | 10 | require('yargs') 11 | .command('list', 'Retrieve rooms and IDs', yargs => { 12 | return yargs.usage('$0 [options] list') 13 | .check(argv => { 14 | if (!argv.token) { 15 | argv.token = process.env.GITTER_TOKEN; 16 | } 17 | if (!argv.token) { 18 | return 'Please specify token via "--token " or GITTER_TOKEN ' + 19 | 'environment variable'; 20 | } 21 | return true; 22 | }); 23 | }, argv => { 24 | return new Gitter(argv.token).rooms.findAll() 25 | .then(roomList => { 26 | const rooms = roomList.map(room => { 27 | return `${room.id} : ${room.name}\n`; 28 | }); 29 | rooms.forEach(room => { 30 | process.stdout.write(room); 31 | }); 32 | }); 33 | }) 34 | .command('id', 'Retrieve by room ID', yargs => { 35 | return yargs.usage('$0 [options] id ') 36 | .example('id 3053736c7fd756bd5304c876') 37 | .demand(2, 2, 'Please specify "id "') 38 | .check(argv => { 39 | if (!argv.token) { 40 | argv.token = process.env.GITTER_TOKEN; 41 | } 42 | if (!argv.token) { 43 | return 'Please specify token via "--token " or GITTER_TOKEN ' + 44 | 'environment variable'; 45 | } 46 | if (!/^[a-zA-Z0-9]{24}$/.test(argv._[1])) { 47 | return 'Invalid room ID'; 48 | } 49 | argv.roomId = argv._[1]; 50 | return true; 51 | }); 52 | }, argv => { 53 | return new Gitter(argv.token).rooms.find(argv.roomId) 54 | .then(room => { 55 | const messages = []; 56 | return Promise.coroutine(function* (limit) { 57 | let result; 58 | let beforeId; 59 | do { 60 | result = yield room.chatMessages({ 61 | limit, 62 | beforeId 63 | }); 64 | if (result.length) { 65 | messages.push(...result); 66 | beforeId = result[0].id; 67 | process.stderr.write('.'); 68 | } 69 | } while (result.length); 70 | process.stderr.write('\n'); 71 | return messages; 72 | })(PER_PAGE); 73 | }) 74 | .then(messages => { 75 | process.stdout.write(JSON.stringify(messages, null, 2)); 76 | process.stdout.write('\n'); 77 | }) 78 | .catch(err => { 79 | throw err; 80 | }); 81 | }) 82 | .demand(1, 'Please specify "id " ') 83 | .strict() 84 | .usage('$0 [options] ') 85 | .showHelpOnFail(true) 86 | .help() 87 | .version() 88 | .options({ 89 | token: { 90 | type: 'string', 91 | describe: 'Personal OAuth Gitter token; or use GITTER_TOKEN env var', 92 | global: true 93 | } 94 | }).argv; 95 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gitter-export-room", 3 | "version": "0.3.0", 4 | "description": "", 5 | "main": "bin/gitter-export-room.js", 6 | "bin": { 7 | "gitter-export-room": "bin/gitter-export-room.js" 8 | }, 9 | "preferGlobal": true, 10 | "scripts": { 11 | "test": "eslint bin/" 12 | }, 13 | "keywords": [], 14 | "author": "Christopher Hiller (https://boneskull.com/)", 15 | "license": "MIT", 16 | "dependencies": { 17 | "bluebird": "^3.4.0", 18 | "node-gitter": "^1.2.11", 19 | "yargs": "^4.7.1" 20 | }, 21 | "engines": { 22 | "node": ">=6" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/boneskull/gitter-export-room.git" 27 | }, 28 | "devDependencies": { 29 | "eslint": "^2.11.0" 30 | } 31 | } 32 | --------------------------------------------------------------------------------