slack_neuralyzer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f34f12786efe803fc3109712824067b26c27e228
4
+ data.tar.gz: 9e84e469278787d33e1438b8306110ce7c2b0c41
5
+ SHA512:
6
+ metadata.gz: 9d2c9932289e8bdbbee6e12318eaf4192b8466eac8fe6f9037acfe764a530c8a1bd1c823d1841c23302f16c39a7edb45d740f3a9978bf93b55a38316c85c267b
7
+ data.tar.gz: d88b648cc1f468161e75477b37c6265a44b72a2b02ac7c929299f7a61f72c2ce18e596621b37379f712cf38d16a1b2c5c1ab55cba369d659e88b534cb025bcba
@@ -0,0 +1,16 @@
1
+ engines:
2
+ rubocop:
3
+ enabled: true
4
+ duplication:
5
+ enabled: true
6
+ config:
7
+ languages:
8
+ - ruby
9
+ ratings:
10
+ paths:
11
+ - lib/**
12
+ - "**.rb"
13
+ exclude_paths:
14
+ - spec/**/*
15
+ - topic/**/*
16
+ - "**/vendor/**/*"
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,6 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.3
5
+ before_install: gem install bundler -v 1.11.2
6
+ script: bundle exec rspec --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in slack_neuralyzer.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Leon Ji
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all 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,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,216 @@
1
+ # Slack Neuralyzer
2
+
3
+ [![Build Status](https://travis-ci.org/mgleon08/slack_neuralyzer.svg?branch=master)](https://travis-ci.org/mgleon08/slack_neuralyzer)
4
+ [![Coverage Status](https://coveralls.io/repos/github/mgleon08/slack_neuralyzer/badge.svg?branch=master)](https://coveralls.io/github/mgleon08/slack_neuralyzer?branch=master)
5
+ [![Code Climate](https://codeclimate.com/github/mgleon08/slack_neuralyzer/badges/gpa.svg)](https://codeclimate.com/github/mgleon08/slack_neuralyzer)
6
+ [![security](https://hakiri.io/github/mgleon08/slack_neuralyzer/master.svg)](https://hakiri.io/github/mgleon08/slack_neuralyzer/master)
7
+ [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/mgleon08/slack_neuralyzer/blob/master/LICENSE.txt)
8
+
9
+ Slack Neuralyzer is a ruby gem for bulk delete messages and files on Slack channels.
10
+
11
+ The easiest way to clean up messages and files on Slack.
12
+
13
+ ![](https://media.giphy.com/media/65NO1TrKrJUT6/giphy.gif)
14
+
15
+ ## Installation
16
+
17
+ ```
18
+ $ gem install slack_neuralyzer
19
+ ```
20
+
21
+ ## Slack token
22
+
23
+ <a href='https://api.slack.com/web' target='_blank'><img src='screenshots/general_test_token.png' alt='general_test_token' width = '20%' /></a>
24
+
25
+ ##Getting Started
26
+
27
+ ![](screenshots/slack_neuralyzer_demo.gif)
28
+
29
+ ### Show all channel names
30
+
31
+ `slack_neuralyzer -t <TOKEN> -s`
32
+
33
+ ```ruby
34
+ All user direct:
35
+ 001. leon
36
+ 002. slackbot
37
+ 003. cleanerbot
38
+
39
+ All channels (public):
40
+ 001. general
41
+ 002. random
42
+
43
+ All groups (private):
44
+ 001. private_channel
45
+
46
+ All multiparty direct:
47
+ 001. mpdm-leon--cleanerbot-1
48
+ 002. mpdm-leon--slackbot-1
49
+ ```
50
+
51
+ ### Delete message(s)
52
+
53
+ >Rerun below command and use `-e | --execute` to actually delete the message(s).
54
+
55
+ * Channel
56
+
57
+ `-C | --channel` `-D | --direct` `-G | --group` `-M | --mpdirect`
58
+
59
+ ```ruby
60
+ # Delete all user messages in general channel
61
+ slack_neuralyzer -t <TOKEN> -m -C general -u all
62
+
63
+ # Delete all user messages in leon direct channel
64
+ slack_neuralyzer -t <TOKEN> -m -D leon -u all
65
+
66
+ # Delete all user messages in private_channel groups channel
67
+ slack_neuralyzer -t <TOKEN> -m -G private_channel -u all
68
+
69
+ # Delete all user messages in mpdm-leon--cleanerbot-1 multiparty direct channel
70
+ # (can `use slack_neuralyzer -t <TOKEN> -s` to see mpdirect channle name)
71
+ slack_neuralyzer -t <TOKEN> -m -M mpdm-leon--cleanerbot-1 -u all
72
+ ```
73
+
74
+ * Specific user
75
+
76
+ `-u | --user`
77
+
78
+ ```ruby
79
+ # Delete leon messages in general channel
80
+ slack_neuralyzer -t <TOKEN> -m -C general -u leon
81
+
82
+ # if you want to specific all users, you can type 'all'
83
+ slack_neuralyzer -t <TOKEN> -m -C general -u all
84
+ ```
85
+
86
+ * Specific Bot
87
+
88
+ `-b | --bot`
89
+
90
+ ```ruby
91
+ # Delete bots messages in general channel
92
+ slack_neuralyzer -t <TOKEN> -m -C general -b cleanerbot
93
+
94
+ # if you want to specific all bots, you can type 'all' (not bot users)
95
+ slack_neuralyzer -t <TOKEN> -m -C general -b all
96
+ ```
97
+
98
+ * Delete message(s) between two dates
99
+
100
+ `-A | --after` `-B | --before`
101
+
102
+ ```ruby
103
+ # Delete all user messages in general channel at 20160101 to 20161212
104
+ slack_neuralyzer -t <TOKEN> -m -C general -u all -A 20160101 -B 20161212
105
+ ```
106
+
107
+ * Delete message(s) with specified text
108
+
109
+ `-R | --regex`
110
+
111
+ ```ruby
112
+ # Delete all user messages with hello string in general channel
113
+ slack_neuralyzer -t <TOKEN> -m -C general -u all -R hello
114
+ ```
115
+
116
+ ### Delete file(s)
117
+
118
+ > File types: all, spaces, snippets, images, gdocs, docs, zips, pdfs
119
+
120
+ >Rerun below command and use `-e | --execute` to actually delete the message(s).
121
+
122
+ * Channel
123
+
124
+ `-C | --channel` `-D | --direct` `-G | --group` `-M | --mpdirect`
125
+
126
+ ```ruby
127
+ # Delete all user upload all type file in general channel
128
+ slack_neuralyzer -t <TOKEN> -f all -C general -u all
129
+
130
+ # Delete leon upload all images file in leon direct channel
131
+ slack_neuralyzer -t <TOKEN> -f images -D leon -u leon
132
+
133
+ # Delete all user upload all pdfs file in private_channel groups channel
134
+ slack_neuralyzer -t <TOKEN> -f pdfs -G private_channel -u all
135
+
136
+ # Delete all user upload all zips file in mpdm-leon--cleanerbot-1 multiparty direct channel
137
+ # (can `use slack_neuralyzer -t <TOKEN> -s` to see mpdirect channle name)
138
+ slack_neuralyzer -t <TOKEN> -f zips -M mpdm-leon--cleanerbot-1 -u all
139
+ ```
140
+
141
+ * Specific user and file type
142
+
143
+ `-u | --user` `-f | --file`
144
+
145
+ ```ruby
146
+ # Delete leon upload images file in general channel
147
+ slack_neuralyzer -t <TOKEN> -f images -C general -u leon
148
+ ```
149
+
150
+ * Delete file between two dates
151
+
152
+ `-A | --after` `-B | --before`
153
+
154
+ ```ruby
155
+ # Delete all user upload all type file in general channel at 20160101 to 20161212
156
+ slack_neuralyzer -t <TOKEN> -f all -C general -u all -A 20160101 -B 20161212
157
+ ```
158
+
159
+ ### Generate log file
160
+
161
+ `-l | --log`
162
+
163
+ ```ruby
164
+ # Generate a log file in the current directory in ./slack_neuralyzer/YYYY-MM-DDTHH:MM:SS
165
+ slack_neuralyzer -t <TOKEN> -m -C general -u all -A 20160101 -B 20161212 -l
166
+ ```
167
+
168
+
169
+ ### Rate
170
+
171
+ `-r | --rate`
172
+
173
+ ```ruby
174
+ # Delay between API calls in seconds (default:0.05)
175
+ slack_neuralyzer -t <TOKEN> -m -C general -u all -r 0.01
176
+ ```
177
+
178
+
179
+ ### Help
180
+
181
+ `-h | --help`
182
+
183
+ ```
184
+ usage:
185
+ slack_neuralyzer [options]
186
+ See https://github.com/mgleon08/slack_neuralyzer for more information.
187
+
188
+ options:
189
+ -t, --token TOKEN Slack API token (https://api.slack.com/web)
190
+ -s, --show Show all users, channels, groups and multiparty direct names
191
+ -m, --message Specifies that the delete object is messages
192
+ -f, --file TYPE Specifies that the delete object is files of a certain type (Type: all, spaces, snippets, images, gdocs, docs, zips, pdfs)
193
+ -C, --channel CHANNEL Public channel name (e.g., general, random)
194
+ -D, --direct DIRECT Direct messages channel name (e.g., leon)
195
+ -G, --group GROUP Private groups channel name
196
+ -M, --mpdirect MPDIRECT Multiparty direct messages channel name (e.g., mpdm-leon--bot-1 [--show option to see name])
197
+ -u, --user USER Delete messages/files from the specific user (if you want to specific all users, you can type 'all')
198
+ -b, --bot BOT Delete messages from the specific bot (not bot users, if you want to specific all bots, you can type 'all')
199
+ -A, --after DATE Delete messages/files after than this time (YYYYMMDD)
200
+ -B, --before DATE Delete messages/files before than this time (YYYYMMDD)
201
+ -R, --regex TEXT Delete messages with specified text (regular expression)
202
+ -e, --execute Execute the delete task
203
+ -l, --log Generate a log file in the current directory
204
+ -r, --rate RATE Delay between API calls in seconds (default:0.1)
205
+ -v, --version Show the SlackNeuralyzer version
206
+ -h, --help Show this message
207
+ ```
208
+
209
+ ## Contributing
210
+
211
+ Bug reports and pull requests are welcome on GitHub at [`https://github.com/mgleon08/slack_neuralyzer/pulls`](https://github.com/mgleon08/slack_neuralyzer/pulls)
212
+
213
+ ## Copyright & License
214
+
215
+ * Copyright (c) 2016 Leon Ji. See [LICENSE.txt](https://github.com/mgleon08/slack_neuralyzer/blob/master/LICENSE.txt) for further details.
216
+ * The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "slack_neuralyzer"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/slack_neuralyzer'
3
+
4
+ begin
5
+ args = SlackNeuralyzer::ArgsParser.new(ARGV)
6
+ logger = SlackNeuralyzer::Logger.default(args.log)
7
+ dict = SlackNeuralyzer::Dict.new(args.token)
8
+ cli = SlackNeuralyzer::Cli.new(args, dict, logger)
9
+ cli.run
10
+ rescue => e
11
+ $stderr.puts e.message
12
+ exit
13
+ end
@@ -0,0 +1,9 @@
1
+ module SlackApi
2
+ module Errors
3
+ class NotFoundError < StandardError
4
+ def initialize(message)
5
+ super("SlackAPI: #{message}")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module SlackApi
2
+ module Errors
3
+ class ResponseError < StandardError
4
+ def initialize(message)
5
+ super("SlackAPI: #{message}")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ require 'slack'
@@ -0,0 +1,26 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+
3
+ require 'optparse'
4
+ require 'time'
5
+ require 'colorize'
6
+ require 'logger'
7
+
8
+ require 'slack_api/slack_api'
9
+ require 'slack_api/errors/not_found'
10
+ require 'slack_api/errors/response'
11
+
12
+ require 'slack_neuralyzer/logger'
13
+ require 'slack_neuralyzer/multi_io'
14
+
15
+ require 'slack_neuralyzer/helper'
16
+ require 'slack_neuralyzer/colorizable'
17
+ require 'slack_neuralyzer/args_parser'
18
+ require 'slack_neuralyzer/dict'
19
+ require 'slack_neuralyzer/cli'
20
+ require 'slack_neuralyzer/cleaner/base'
21
+ require 'slack_neuralyzer/cleaner/messages'
22
+ require 'slack_neuralyzer/cleaner/files'
23
+ require 'slack_neuralyzer/errors/mutually_exclusive_arguments'
24
+ require 'slack_neuralyzer/errors/required_arguments'
25
+
26
+ require 'slack_neuralyzer/version'
@@ -0,0 +1,98 @@
1
+ module SlackNeuralyzer
2
+ class ArgsParser
3
+ attr_accessor :token, :show, :message, :file, :channel, :direct,
4
+ :group, :mpdirect, :user, :bot, :after, :before,
5
+ :execute, :log, :rate, :regex
6
+
7
+ def initialize(args)
8
+ @args = args
9
+ init_arg_groups
10
+ parse_args
11
+ validates_mutex_args
12
+ validates_required_args
13
+ end
14
+
15
+ def init_arg_groups
16
+ @arg_groups = {
17
+ 'required': [
18
+ [:token],
19
+ [:message, :file],
20
+ [:channel, :direct, :group, :mpdirect],
21
+ [:user, :bot]
22
+ ],
23
+ 'mutex': [
24
+ [:message, :file],
25
+ [:channel, :direct, :group, :mpdirect],
26
+ [:file, :bot],
27
+ [:file, :regex]
28
+ ]
29
+ }
30
+ end
31
+
32
+ def rate_limit
33
+ rate || 0.05
34
+ end
35
+
36
+ private
37
+
38
+ def parse_args
39
+ opts = OptionParser.new
40
+ opts.banner = usage_msg
41
+ opts.separator ''
42
+ opts.separator 'options:'
43
+ opts.on('-t', '--token TOKEN', 'Slack API token (https://api.slack.com/web)') { |token| self.token = token }
44
+ opts.on('-s', '--show', 'Show all users, channels, groups and multiparty direct names') { self.show = true }
45
+
46
+ opts.on('-m', '--message', 'Specifies that the delete object is messages') { self.message = true }
47
+ opts.on('-f', '--file TYPE', "Specifies that the delete object is files of a certain type (Type: all, spaces, snippets, images, gdocs, docs, zips, pdfs)") { |file| self.file = file }
48
+
49
+ opts.on('-C', '--channel CHANNEL', 'Public channel name (e.g., general, random)') { |channel| self.channel = channel }
50
+ opts.on('-D', '--direct DIRECT', 'Direct messages channel name (e.g., leon)') { |direct| self.direct = direct }
51
+ opts.on('-G', '--group GROUP', 'Private groups channel name') { |group| self.group = group }
52
+ opts.on('-M', '--mpdirect MPDIRECT', 'Multiparty direct messages channel name (e.g., mpdm-leon--bot-1 [--show option to see name])') { |mpdirect| self.mpdirect = mpdirect }
53
+
54
+ opts.on('-u', '--user USER', "Delete messages/files from the specific user (if you want to specific all users, you can type 'all')") { |user| self.user = user }
55
+ opts.on('-b', '--bot BOT', "Delete messages from the specific bot (not bot users, if you want to specific all bots, you can type 'all')") { |bot| self.bot = bot }
56
+
57
+ opts.on('-A', '--after DATE', 'Delete messages/files after than this time (YYYYMMDD)') { |after| self.after = after }
58
+ opts.on('-B', '--before DATE', 'Delete messages/files before than this time (YYYYMMDD)') { |before| self.before = before }
59
+
60
+ opts.on('-R', '--regex TEXT', 'Delete messages with specified text (regular expression)') { |regex| self.regex = regex }
61
+
62
+ opts.on('-e', '--execute', 'Execute the delete task') { self.execute = true }
63
+ opts.on('-l', '--log', 'Generate a log file in the current directory') { self.log = true }
64
+ opts.on('-r', '--rate RATE', Float, 'Delay between API calls in seconds (default:0.1)') { |rate| self.rate = rate }
65
+ opts.on('-v', '--version', 'Show the SlackNeuralyzer version') { puts("slack_neuralyzer #{SlackNeuralyzer::VERSION}"); exit }
66
+ opts.on('-h', '--help', 'Show this message') { puts(opts); exit }
67
+ opts.parse!(@args)
68
+ end
69
+
70
+ def usage_msg
71
+ <<-USAGE.freeze
72
+ usage:
73
+ slack_neuralyzer [options]
74
+ See https://github.com/mgleon08/slack_neuralyzer for more information.
75
+ USAGE
76
+ end
77
+
78
+ def validates_required_args
79
+ @arg_groups[:required].each do |opts|
80
+ filters = opts.select{ |opt| !self.public_send(opt).nil? }
81
+ raise SlackNeuralyzer::Errors::RequiredArgumentsError.new(double_dash(opts).join(', ')) if filters.empty?
82
+ return unless self.show.nil?
83
+ end
84
+ end
85
+
86
+ def validates_mutex_args
87
+ @arg_groups[:mutex].each do |opts|
88
+ return unless self.show.nil?
89
+ filters = opts.select{ |opt| !self.public_send(opt).nil? }
90
+ raise SlackNeuralyzer::Errors::MutuallyExclusiveArgumentsError.new(double_dash(filters).join(', ')) if filters.size > 1
91
+ end
92
+ end
93
+
94
+ def double_dash(arrays)
95
+ arrays.map{ |array| array.to_s.prepend('--') }
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,73 @@
1
+ module SlackNeuralyzer
2
+ module Cleaner
3
+ class Base
4
+ include Helper
5
+ include Colorizable
6
+ attr_reader :args, :dict, :channel_type, :logger
7
+
8
+ def initialize(args, dict, logger)
9
+ @args = args
10
+ @dict = dict
11
+ @logger = logger
12
+ reset_counter
13
+ parse_to_ts(args.after, args.before)
14
+ end
15
+
16
+ private
17
+
18
+ def get_user_id
19
+ user_id = args.user == 'all' ? -1 : dict.find_user_id(args.user)
20
+ raise SlackApi::Errors::NotFoundError, "#{args.user} not found." unless args.bot || user_id
21
+ user_id
22
+ end
23
+
24
+ def get_channel_id
25
+ if args.channel
26
+ @channel_type = 'channel'
27
+ channel_id = dict.find_channel_id(args.channel)
28
+ elsif args.direct
29
+ @channel_type = 'direct'
30
+ user_id = dict.find_user_id(args.direct)
31
+ channel_id = dict.find_im_id(user_id)
32
+ elsif args.group
33
+ @channel_type = 'group'
34
+ channel_id = dict.find_group_id(args.group)
35
+ elsif args.mpdirect
36
+ @channel_type = 'mpdirect'
37
+ channel_id = dict.find_mpim_id(args.mpdirect)
38
+ end
39
+ raise SlackApi::Errors::NotFoundError, "#{current_channel} not found." unless channel_id
40
+ channel_id
41
+ end
42
+
43
+ def current_channel
44
+ light_green("#{args.public_send(channel_type)} #{channel_type}")
45
+ end
46
+
47
+ def time_format(time)
48
+ light_cyan("[#{parse_to_date(time)}]")
49
+ end
50
+
51
+ def delete_format
52
+ args.execute ? '(delete) '.light_red : ''
53
+ end
54
+
55
+ def not_have_any(type)
56
+ logger.info "#{current_channel} does not have any #{type}(s)"
57
+ exit
58
+ end
59
+
60
+ def finish_text(type)
61
+ text = "\n#{light_green(counter)} #{type}(s) in #{current_channel} "
62
+ if args.execute.nil? && counter.nonzero?
63
+ text << 'will be deleted.'
64
+ text << light_red("\nNow, you can rerun the command and use `-e | --execute` to actually delete the #{type}(s).")
65
+ else
66
+ text << 'have been deleted.'
67
+ end
68
+ text << light_blue("\nThe log file has been generated in the current directory") if args.log
69
+ text
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,41 @@
1
+ module SlackNeuralyzer
2
+ module Cleaner
3
+ class Files < Base
4
+ def clean
5
+ user_id = get_user_id
6
+ channel_id = get_channel_id
7
+ clean_channel_file(channel_id, user_id)
8
+ end
9
+
10
+ private
11
+
12
+ def clean_channel_file(channel_id, user_id)
13
+ page, total_page = 0, nil
14
+ until page == total_page
15
+ page += 1
16
+ res = Slack.files_list(page: page, channel: channel_id, types: args.file, ts_from: start_time, ts_to: end_time)
17
+ raise SlackApi::Errors::ResponseError, res['error'] unless res['ok']
18
+ total_page = res['paging']['pages']
19
+ not_have_any('file') if total_page.zero?
20
+ res['files'].each do |file|
21
+ if args.user && (file['user'] == user_id || user_id == -1)
22
+ delete_file(file)
23
+ end
24
+ end
25
+ end
26
+
27
+ logger.info finish_text('file')
28
+ end
29
+
30
+ def delete_file(file)
31
+ file_time = time_format(file['timestamp'])
32
+ file_url = light_magenta("(#{file['permalink']})")
33
+ delete = delete_format
34
+ Slack.files_delete(file: file['id']) if args.execute
35
+ logger.info "#{delete}#{file_time} #{dict.find_user_name(file['user'])}: #{file['name']} #{file_url}"
36
+ increase_counter
37
+ sleep(args.rate_limit)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,83 @@
1
+ module SlackNeuralyzer
2
+ module Cleaner
3
+ class Messages < Base
4
+ def clean
5
+ user_id = get_user_id
6
+ channel_id = get_channel_id
7
+ end_point = get_history_end_point
8
+ clean_channel_messages(channel_id, user_id, end_point)
9
+ end
10
+
11
+ private
12
+
13
+ def clean_channel_messages(channel_id, user_id, end_point)
14
+ has_more = true
15
+
16
+ while has_more
17
+ res = Slack.public_send(end_point, channel: channel_id, oldest: start_time, latest: end_time)
18
+ raise SlackApi::Errors::ResponseError, res['error'] unless res['ok']
19
+ has_more = res['has_more']
20
+ messages = res['messages']
21
+ not_have_any('message') if messages.empty?
22
+
23
+ messages.each do |msg|
24
+ @end_time = msg['ts']
25
+ dict.scan_user_id_to_transform(msg['text'])
26
+ next unless msg['type'] == 'message'
27
+ next if args.regex && !match_regex(msg['text'])
28
+
29
+ if args.user && user_msg?(msg, user_id)
30
+ name = dict.find_user_name(msg['user'])
31
+ delete_message(channel_id, msg, name)
32
+ end
33
+
34
+ next unless args.bot && bot_msg?(msg)
35
+
36
+ name = dict.find_bot_name(msg['bot_id'])
37
+ if args.bot == name || args.bot == 'all'
38
+ delete_message(channel_id, msg, name)
39
+ end
40
+ end
41
+ end
42
+
43
+ logger.info finish_text('message')
44
+ end
45
+
46
+ def user_msg?(msg, user_id)
47
+ !bot_msg?(msg) && (msg['user'] == user_id || user_id == -1)
48
+ end
49
+
50
+ def bot_msg?(msg)
51
+ msg['subtype'] == 'bot_message'
52
+ end
53
+
54
+ def delete_message(channel_id, msg, name)
55
+ Slack.chat_delete(channel: channel_id, ts: msg['ts']) if args.execute
56
+ logger.info "#{delete_format}#{time_format(msg['ts'])} #{name}: #{msg['text']}"
57
+ increase_counter
58
+ sleep(args.rate_limit)
59
+ end
60
+
61
+ def get_history_end_point
62
+ if args.channel
63
+ :channels_history
64
+ elsif args.direct
65
+ :im_history
66
+ elsif args.group
67
+ :groups_history
68
+ elsif args.mpdirect
69
+ :mpim_history
70
+ end
71
+ end
72
+
73
+ def match_regex(text)
74
+ match_word = text.scan(/#{args.regex}/).flatten
75
+ return false if match_word.empty?
76
+ match_word.uniq.each do |word|
77
+ text.gsub!(/#{word}/, light_magenta(word.to_s))
78
+ end
79
+ text
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,23 @@
1
+ module SlackNeuralyzer
2
+ class Cli
3
+ attr_reader :args, :dict, :logger
4
+
5
+ def initialize(args, dict, logger)
6
+ @args = args
7
+ @dict = dict
8
+ @logger = logger
9
+ end
10
+
11
+ def run
12
+ logger.info "Running slack_neuralyzer v#{SlackNeuralyzer::VERSION}\n"
13
+ sleep(1)
14
+ if args.show
15
+ puts dict.show_all_channels
16
+ elsif args.message
17
+ Cleaner::Messages.new(args, dict, logger).clean
18
+ elsif args.file
19
+ Cleaner::Files.new(args, dict, logger).clean
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ module SlackNeuralyzer
2
+ module Colorizable
3
+ [
4
+ :light_green,
5
+ :light_cyan,
6
+ :light_red,
7
+ :light_blue,
8
+ :light_yellow,
9
+ :light_magenta
10
+ ].each do |color|
11
+ define_method(color) do |text|
12
+ text.to_s.public_send(color)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,118 @@
1
+ module SlackNeuralyzer
2
+ class Dict
3
+ include Colorizable
4
+ attr_reader :channels, :ims, :groups, :mpims, :users, :bots
5
+
6
+ def initialize(token)
7
+ Slack.token = token
8
+ @users = {}
9
+ @channels = {}
10
+ @groups = {}
11
+ @ims = {}
12
+ @mpims = {}
13
+ @bots = {}
14
+ init_all_dict
15
+ end
16
+
17
+ def show_all_channels
18
+ text = ''
19
+ text << light_blue("All user direct:\n")
20
+ text << list_names(users)
21
+ text << light_blue("\nAll channels (public):\n")
22
+ text << list_names(channels)
23
+ text << light_blue("\nAll groups (private):\n")
24
+ text << list_names(groups)
25
+ text << light_blue("\nAll multiparty direct:\n")
26
+ text << list_names(mpims)
27
+ end
28
+
29
+ [:channel, :im, :group, :mpim, :user].each do |channel|
30
+ define_method("find_#{channel}_id".to_sym) do |name|
31
+ public_send("#{channel}s").key(name)
32
+ end
33
+
34
+ define_method("find_#{channel}_name".to_sym) do |name|
35
+ public_send("#{channel}s").invert.key(name)
36
+ end
37
+ end
38
+
39
+ def scan_user_id_to_transform(text)
40
+ return text if text.nil?
41
+ scan_id = text.scan(/<@(?<bot>[[:alnum:][:punct:]]*)>/i).flatten
42
+ if scan_id.any?
43
+ scan_id.uniq.each do |id|
44
+ name = find_user_name(id)
45
+ text.gsub!(/<@#{id}>/, light_yellow("@#{name}"))
46
+ end
47
+ end
48
+ text
49
+ end
50
+
51
+ def find_bot_name(bot_id)
52
+ build_bot_name(bot_id) unless bots.invert.key(bot_id)
53
+ bots.invert.key(bot_id)
54
+ end
55
+
56
+ def build_bot_name(bot_id)
57
+ res = Slack.bots_info(bot: bot_id)
58
+ raise SlackApi::Errors::ResponseError, res['error'] unless res['ok']
59
+ @bots[bot_id] = res['bot']['name']
60
+ end
61
+
62
+ private
63
+
64
+ def init_all_dict
65
+ init_users_dict
66
+ init_channels_dict
67
+ init_groups_dict
68
+ init_ims_dict
69
+ init_mpims_dict
70
+ end
71
+
72
+ def init_users_dict
73
+ res = Slack.users_list
74
+ raise SlackApi::Errors::ResponseError, res['error'] unless res['ok']
75
+ members = res['members']
76
+ members.each { |member| @users[member['id']] = member['name'] }
77
+ end
78
+
79
+ def init_channels_dict
80
+ res = Slack.channels_list
81
+ raise SlackApi::Errors::ResponseError, res['error'] unless res['ok']
82
+ channels = res['channels']
83
+ channels.each { |channel| @channels[channel['id']] = channel['name'] }
84
+ end
85
+
86
+ def init_groups_dict
87
+ res = Slack.groups_list
88
+ raise SlackApi::Errors::ResponseError, res['error'] unless res['ok']
89
+ groups = res['groups']
90
+ groups.each do |group|
91
+ next if group['is_mpim'] != false
92
+ @groups[group['id']] = group['name']
93
+ end
94
+ end
95
+
96
+ def init_ims_dict
97
+ res = Slack.im_list
98
+ raise SlackApi::Errors::ResponseError, res['error'] unless res['ok']
99
+ ims = res['ims']
100
+ ims.each { |im| @ims[im['id']] = im['user'] }
101
+ end
102
+
103
+ def init_mpims_dict
104
+ res = Slack.mpim_list
105
+ raise SlackApi::Errors::ResponseError, res['error'] unless res['ok']
106
+ mpims = res['groups']
107
+ mpims.each { |mpim| @mpims[mpim['id']] = mpim['name'] }
108
+ end
109
+
110
+ def list_names(names)
111
+ ''.tap do |text|
112
+ names.values.each.with_index(1) do |name, index|
113
+ text << " #{index.to_s.rjust(3, '0')}. #{name}\n"
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,9 @@
1
+ module SlackNeuralyzer
2
+ module Errors
3
+ class MutuallyExclusiveArgumentsError < StandardError
4
+ def initialize(message)
5
+ super("These arguments can not be required together: #{message}")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module SlackNeuralyzer
2
+ module Errors
3
+ class RequiredArgumentsError < StandardError
4
+ def initialize(message)
5
+ super("Must required one of these arguments: #{message}")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ module SlackNeuralyzer
2
+ module Helper
3
+ attr_reader :counter, :start_time, :end_time
4
+
5
+ def parse_to_ts(start_time, end_time)
6
+ end_time ||= Time.now.to_s
7
+ @start_time = Time.parse(start_time).to_f if start_time
8
+ @end_time = Time.parse(end_time).to_f
9
+ end
10
+
11
+ def parse_to_date(ts)
12
+ Time.at(ts.to_f).strftime('%Y-%m-%d %H:%M')
13
+ end
14
+
15
+ def reset_counter
16
+ @counter = 0
17
+ end
18
+
19
+ def increase_counter
20
+ @counter += 1
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module SlackNeuralyzer
2
+ class Logger < ::Logger
3
+ class << self
4
+ def default(log)
5
+ io = [STDOUT]
6
+ io << log_file if log
7
+ logger = Logger.new(MultiIO.new(*io))
8
+ logger.level = Logger::INFO
9
+ logger.formatter = proc do |_severity, _datetime, _progname, msg|
10
+ "#{msg}\n"
11
+ end
12
+ logger
13
+ end
14
+
15
+ def log_file
16
+ time = Time.now.strftime('%Y-%m-%dT%H:%M:%S')
17
+ FileUtils.mkdir_p('./slack_neuralyzer')
18
+ log_file = File.open("./slack_neuralyzer/#{time}.log", 'a')
19
+ log_file
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ module SlackNeuralyzer
2
+ class MultiIO
3
+ def initialize(*targets)
4
+ @targets = targets
5
+ @shell_colors = {
6
+ light_red: '\\e\\[0;91;49m',
7
+ light_green: '\\e\\[0;92;49m',
8
+ light_yellow: '\\e\\[0;93;49m',
9
+ light_blue: '\\e\\[0;94;49m',
10
+ light_magenta: '\\e\\[0;95;49m',
11
+ light_cyan: '\\e\\[0;96;49m',
12
+ out_put: '\\e\\[0m'
13
+ }
14
+ end
15
+
16
+ def write(args)
17
+ @targets.each do |target|
18
+ pretty_file_text(args) if target.is_a? File
19
+ target.write(args)
20
+ end
21
+ end
22
+
23
+ def close
24
+ @targets.each(&:close)
25
+ end
26
+
27
+ def pretty_file_text(args)
28
+ @shell_colors.values.each do |color|
29
+ args.gsub!(/#{color}/, '')
30
+ end
31
+ args
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module SlackNeuralyzer
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'slack_neuralyzer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "slack_neuralyzer"
8
+ spec.version = SlackNeuralyzer::VERSION
9
+ spec.authors = ["Leon Ji"]
10
+ spec.email = ["mgleon08@gmail.com"]
11
+
12
+ spec.summary = %q{The easiest way to clean up messages and files on Slack.}
13
+ spec.description = %q{This is a ruby gem for bulk delete messages and files on Slack channels.}
14
+ spec.homepage = "https://github.com/mgleon08/slack_neuralyzer"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "bin"
19
+ spec.require_paths = ["lib"]
20
+ spec.executables = ["slack_neuralyzer"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.11"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rspec", "~> 3.0"
25
+ spec.add_development_dependency "coveralls", "~> 0.8.1"
26
+ spec.add_runtime_dependency "slack-api", "~> 1.2"
27
+ spec.add_runtime_dependency "colorize", "~> 0.8"
28
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slack_neuralyzer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Leon Ji
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: coveralls
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.8.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: slack-api
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.2'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: colorize
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.8'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.8'
97
+ description: This is a ruby gem for bulk delete messages and files on Slack channels.
98
+ email:
99
+ - mgleon08@gmail.com
100
+ executables:
101
+ - slack_neuralyzer
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".codeclimate.yml"
106
+ - ".gitignore"
107
+ - ".rspec"
108
+ - ".travis.yml"
109
+ - Gemfile
110
+ - LICENSE.txt
111
+ - README.md
112
+ - Rakefile
113
+ - bin/console
114
+ - bin/setup
115
+ - bin/slack_neuralyzer
116
+ - lib/slack_api/errors/not_found.rb
117
+ - lib/slack_api/errors/response.rb
118
+ - lib/slack_api/slack_api.rb
119
+ - lib/slack_neuralyzer.rb
120
+ - lib/slack_neuralyzer/args_parser.rb
121
+ - lib/slack_neuralyzer/cleaner/base.rb
122
+ - lib/slack_neuralyzer/cleaner/files.rb
123
+ - lib/slack_neuralyzer/cleaner/messages.rb
124
+ - lib/slack_neuralyzer/cli.rb
125
+ - lib/slack_neuralyzer/colorizable.rb
126
+ - lib/slack_neuralyzer/dict.rb
127
+ - lib/slack_neuralyzer/errors/mutually_exclusive_arguments.rb
128
+ - lib/slack_neuralyzer/errors/required_arguments.rb
129
+ - lib/slack_neuralyzer/helper.rb
130
+ - lib/slack_neuralyzer/logger.rb
131
+ - lib/slack_neuralyzer/multi_io.rb
132
+ - lib/slack_neuralyzer/version.rb
133
+ - screenshots/general_test_token.png
134
+ - screenshots/neuralyzer.gif
135
+ - screenshots/slack_neuralyzer_demo.gif
136
+ - slack_neuralyzer.gemspec
137
+ homepage: https://github.com/mgleon08/slack_neuralyzer
138
+ licenses:
139
+ - MIT
140
+ metadata: {}
141
+ post_install_message:
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 2.4.8
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: The easiest way to clean up messages and files on Slack.
161
+ test_files: []