├── .gitignore ├── README.md ├── app.json ├── archer.jpg ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # slack-archiver 2 | 3 | A simple bot for archiving slack channels to s3. I've called him archer the archive bot. 4 | 5 | Each channel that this bot is in will have all conversations written to a text file in the s3 bucket. So there's a text file per channel, with the naming format as __archive.txt 6 | 7 | A preface: This is primarily geared towards community groups where there are tons of people and not enough cash to pay for slack. If you're a business, I highly suggest you just pay them and let them handle archives. 8 | 9 | ## Installation: 10 | 11 | -Navigate to the integrations page for your team. On the desktop app you can click the team name in the top left and then "Configure Integrations" 12 | -Add a "Bot" integration. I like to call mine "Archer the archiver". There is a archer.jpg icon you can use in this repo. 13 | -Copy the "API Token" there. 14 | -Set the following environment variables on the host 15 | - AWS_ACCESS_KEY 16 | - AWS_SECRET_KEY 17 | - AWS_REGION 18 | - SLACK_TOKEN (this is the API Token from earlier) 19 | - TEAM_PREFIX 20 | - BUCKET_NAME 21 | 22 | Run via `node ./index.js` OR `npm start` 23 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Slack Archive Bot", 3 | "description": "A bot for backing up all messages", 4 | } 5 | -------------------------------------------------------------------------------- /archer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zachgoldstein/slack-archiver/9bf0f716d9a0e1d4814ea8398075e8b84b9d0d7b/archer.jpg -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var Slack = require('slack-client'); 2 | var AWS = require('aws-sdk'); 3 | 4 | var awsAccessKey = process.env.AWS_ACCESS_KEY 5 | if (!awsAccessKey) { 6 | console.log("Cannot find AWS access key, please set env var AWS_ACCESS_KEY") 7 | process.exit() 8 | } 9 | var awsAccessSecret = process.env.AWS_SECRET_KEY 10 | if (!awsAccessSecret) { 11 | console.log("Cannot find AWS secret key, please set env var AWS_SECRET_KEY") 12 | process.exit() 13 | } 14 | var awsRegion = process.env.AWS_REGION 15 | if (!awsRegion) { 16 | console.log("Cann ot find aws region, please set env var AWS_REGION") 17 | process.exit() 18 | } 19 | var slackToken = process.env.SLACK_TOKEN 20 | if (!slackToken) { 21 | console.log("Cannot find slack token, , please set env var SLACK_TOKEN") 22 | process.exit() 23 | } 24 | var teamPrefix = process.env.TEAM_PREFIX 25 | if (!teamPrefix) { 26 | console.log("Cannot find slack team prefix, please set env var TEAM_PREFIX") 27 | process.exit() 28 | } 29 | var bucketName = process.env.BUCKET_NAME 30 | if (!bucketName) { 31 | console.log("Cannot find AWS bucket name, , please set env var BUCKET_NAME") 32 | process.exit() 33 | } 34 | 35 | AWS.config.update({accessKeyId: awsAccessKey, secretAccessKey: awsAccessSecret}); 36 | AWS.config.update({region: awsRegion}) 37 | 38 | var s3 = new AWS.S3({params: {Bucket: bucketName}}); 39 | var slack = new Slack(slackToken, true, true); 40 | 41 | slack.on('error', function (err) { 42 | if (err) { 43 | console.log("An error occurred, ",err); 44 | } 45 | }); 46 | 47 | slack.on('open', function () { 48 | var channels = Object.keys(slack.channels) 49 | .map(function (k) { return slack.channels[k]; }) 50 | .filter(function (c) { return c.is_member; }) 51 | .map(function (c) { return c.name; }); 52 | 53 | console.log('Welcome to Slack. You are ' + slack.self.name + ' of ' + slack.team.name); 54 | 55 | if (channels.length > 0) { 56 | console.log('You are in: ' + channels.join(', ')); 57 | } 58 | else { 59 | console.log('You are not in any channels.'); 60 | } 61 | 62 | channel = slack.getChannelGroupOrDMByName("#bots") 63 | channel.send("Archiving messages from channels: " + channels.join(', ')); 64 | console.log("Notified #bots channel of archiving") 65 | }); 66 | 67 | slack.on('message', function(message) { 68 | var channel = slack.getChannelGroupOrDMByID(message.channel); 69 | var user = slack.getUserByID(message.user); 70 | 71 | var displayMsg = ""; 72 | 73 | if (message.type === 'message') { 74 | if (!user) { 75 | displayMsg = ( new Date().toISOString() + " - " + channel.name + ':' + message.text + " \r\n" ); 76 | } else { 77 | displayMsg = ( new Date().toISOString() + " - " + channel.name + ':' + user.name + ':' + message.text + " \r\n" ); 78 | } 79 | } 80 | 81 | var currentArchive = ''; 82 | 83 | var params = { 84 | Bucket: bucketName, 85 | Key: teamPrefix + "_" + channel.name + '_archive.txt', 86 | } 87 | 88 | s3.getObject(params, function(err, data) { 89 | if (err) { 90 | console.log(err, err.stack); // an error occurred 91 | } else { 92 | currentArchive = data.Body.toString("utf-8", 0, data.Body.length); 93 | } 94 | 95 | currentArchive += displayMsg; 96 | 97 | console.log("putting archive ",currentArchive); 98 | 99 | params.Body = currentArchive; 100 | 101 | s3.upload(params, function(err, data) { 102 | if (err) { 103 | console.log("Error uploading data: ", err); 104 | } else { 105 | console.log("Successfully uploaded data to " + params.Bucket); 106 | } 107 | }); 108 | 109 | console.log("done putting archive!"); 110 | }); 111 | 112 | }); 113 | slack.login(); 114 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slack-archive-bot", 3 | "version": "0.1.0", 4 | "description": "A bot to archive public slack messages", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "dependencies": { 10 | "slack-client": "1.4.0", 11 | "aws-sdk": "2.1.26" 12 | }, 13 | "engines": { 14 | "node": "0.10.x" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/zachgoldstein/slack-archiver" 19 | }, 20 | "keywords": [ 21 | "slack", 22 | "archive", 23 | "awesome" 24 | ], 25 | "author": "Zach Goldstein", 26 | "license": "MIT" 27 | } 28 | --------------------------------------------------------------------------------