slack_scratcher 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 56b9028533b252ce83872884a332a85d344f7dc0
4
- data.tar.gz: 670049b263e5c25aa3222311033546af65dfce6b
3
+ metadata.gz: d69bdc6dce5f556068fc0e2920cbc511a0197425
4
+ data.tar.gz: 1bb53fa814baaabff2bc7db34e3a04cb1a7d71a7
5
5
  SHA512:
6
- metadata.gz: a65adf9dc0a91ad769aabfc1b7cf82133c95f19de544f3f368cdf20ab1444c2986e46928e0f1689dc05f8f0651da514c63174a71d1be2b12bff56b904247f408
7
- data.tar.gz: 3ecb3d72f1f036f4c13ae7e706c82c094d75930c2d89d7ee5f8c657e6c0dd9052142df94bb831d021ca8264682825f66a141a981cb4c7982ac89b767eb79b7e4
6
+ metadata.gz: d23b90ecb37f1babfd251c287e3adef18da56ac8a2aa40ddb075de0c48d902a83121bae2fdb90c0b67fee69e77a54624043f208c87c37ca5cdec60e839a0b86c
7
+ data.tar.gz: b5776d10ea833e60f774f3e297cbaffcdd7a72692a490a723705d4fe51347127859390b1f62b804b484d0bb4cbbd58b5a5672049649a28b53cb1e61af7124c98
@@ -5,6 +5,10 @@ require 'faraday'
5
5
 
6
6
  Dotenv.load
7
7
 
8
+ # Importing slack logs from exported fils or API to elasticsearch or
9
+ # other detastores
10
+ #
11
+ # @since 0.0.1
8
12
  module SlackScratcher
9
13
  autoload :Model, 'slack_scratcher/model'
10
14
  autoload :Loader, 'slack_scratcher/loader'
@@ -13,6 +17,8 @@ module SlackScratcher
13
17
  autoload :Error, 'slack_scratcher/error'
14
18
  autoload :Helper, 'slack_scratcher/helper'
15
19
 
20
+ # logger for SlackScratcher Library
21
+ # @return [Logger] Ruby standard logger object
16
22
  def self.logger
17
23
  @logger ||= ::Logger.new(STDOUT)
18
24
  end
@@ -1,6 +1,9 @@
1
1
  module SlackScratcher
2
+ # SlackScratcher Adapter namespace
3
+ # @since 0.0.1
2
4
  module Adapter
3
- autoload :Elasticsearch, 'slack_scratcher/adapter/elasticsearch'
5
+ autoload :Base, 'slack_scratcher/adapter/base'
4
6
  autoload :File, 'slack_scratcher/adapter/file'
7
+ autoload :Elasticsearch, 'slack_scratcher/adapter/elasticsearch'
5
8
  end
6
9
  end
@@ -0,0 +1,27 @@
1
+ module SlackScratcher
2
+ module Adapter
3
+ # Abstract adapter class for storing slack logs
4
+ # @since 0.1
5
+ class Base
6
+ # @ abstract
7
+ def initialize
8
+ fail NotImplementedError
9
+ end
10
+
11
+ # @ abstract
12
+ def send
13
+ fail NotImplementedError
14
+ end
15
+
16
+ # @ abstract
17
+ def timestamp_of_last_channel_log
18
+ fail NotImplementedError
19
+ end
20
+
21
+ # @ abstract
22
+ def ready_index
23
+ fail NotImplementedError
24
+ end
25
+ end
26
+ end
27
+ end
@@ -2,58 +2,113 @@ require 'elasticsearch'
2
2
 
3
3
  module SlackScratcher
4
4
  module Adapter
5
- class Elasticsearch
5
+ # Elasticsearch adapter for storing slack logs.
6
+ #
7
+ # @since 0.0.1
8
+ # @attr_reader [Elasticsearch::Client] client elasticsearch client
9
+ class Elasticsearch < SlackScratcher::Adapter::Base
6
10
  attr_reader :client
7
11
 
12
+ # Initialize SlackScratcher::Adapter::Elasticsearch object.
13
+ #
14
+ # @param [Array] hosts array of Elasticsearch hosts
15
+ # @param [Hash] metadata metadata for storing
16
+ # @option metadata [string] :index index for storing
17
+ # @option metadata [string] :type type for storing
18
+ #
19
+ # @example return Elasticsearch adapter object
20
+ # hosts = ['http://192.168.59.103:9200']
21
+ # metadata = {index: 'slack', type: 'log'}
22
+ # SlackScratcher::Adapter::Elastisearch.new(hosts, metadata)
23
+ #
24
+ # @return [SlackScratcher::Adapter::Elasticsearh]
25
+ # Elasticsearch adapter object
8
26
  def initialize(hosts, metadata)
9
27
  @client = ::Elasticsearch::Client.new hosts: hosts
10
28
  @metadata = metadata
11
29
  end
12
30
 
31
+ # Send data into elastisearch host.
32
+ #
33
+ # @see http://www.rubydoc.info/gems/elasticsearch-api/Elasticsearch/API/Actions#bulk-instance_method
34
+ # @param [Array] raw_data slack logs which parsed by loader
35
+ #
36
+ # @example Send log from loader to elastisearch adapter
37
+ # loader.each { |data| adapter.send data }
38
+ #
39
+ # @raise [Elasticsearch::Transport::Transport::Errors::BadRequest]
40
+ # It raise when request is fail
41
+ #
42
+ # @return [Hash] Deserialized Elasticsearch response
43
+ # @return [Boolean] If raw_data is empty, it returns false
13
44
  def send(raw_data)
14
45
  data = format_bulk(raw_data)
15
46
  @client.bulk data unless raw_data.empty?
47
+ false
16
48
  rescue ::Elasticsearch::Transport::Transport::Errors::BadRequest => error
17
49
  puts error
18
50
  end
19
51
 
52
+ # Get last logs' timestamp of specific channel from saved data
53
+ #
54
+ # @param [String] channel_name channel name
55
+ #
56
+ # @example Get saved last log's timestamp of general channel
57
+ # adapter.timestamp_of_last_log 'general' #=> '1426337804.820065'
58
+ #
59
+ # @return [String] Timestamp of last log
60
+ # @return [String] If there isn't saved log, it returns '0'
20
61
  def timestamp_of_last_channel_log(channel_name)
21
62
  request_body = create_body(query_for_last_log(channel_name))
22
63
  log = @client.search request_body
23
64
 
24
- return 0 if log['hits']['total'] == 0
65
+ return '0' if log['hits']['total'] == 0
25
66
  log['hits']['hits'][0]['_source']['ts']
26
67
  end
27
68
 
69
+ # Create index and set mapping for saving slack log data
70
+ #
71
+ # @example Create index and set mapping
72
+ # adapter.ready_index
73
+ #
74
+ # @return [Boolean] If there isn't any problem, it returns true
28
75
  def ready_index
29
76
  unless index?
30
77
  create_index
31
78
  put_mapping
32
79
  end
80
+
81
+ true
33
82
  end
34
83
 
35
84
  private
36
85
 
86
+ # @private
37
87
  def index
38
88
  @metadata[:index]
39
89
  end
40
90
 
91
+ # @private
41
92
  def type
42
93
  @metadata[:type]
43
94
  end
44
95
 
96
+ # @private
45
97
  def index?
46
98
  @client.indices.exists(index: index)
47
99
  end
48
100
 
101
+ # @private
49
102
  def create_index
50
103
  @client.indices.create(index: index)
51
104
  end
52
105
 
106
+ # @private
53
107
  def put_mapping
54
108
  @client.indices.put_mapping create_body(mapping)
55
109
  end
56
110
 
111
+ # @private
57
112
  def mapping
58
113
  {
59
114
  type => {
@@ -72,6 +127,7 @@ module SlackScratcher
72
127
  }
73
128
  end
74
129
 
130
+ # @private
75
131
  def query_for_last_log(channel_name)
76
132
  {
77
133
  size: 1,
@@ -85,6 +141,7 @@ module SlackScratcher
85
141
  }
86
142
  end
87
143
 
144
+ # @private
88
145
  def create_body(body = {})
89
146
  {
90
147
  index: index,
@@ -93,10 +150,12 @@ module SlackScratcher
93
150
  }
94
151
  end
95
152
 
153
+ # @private
96
154
  def format_bulk(data)
97
155
  { body: data.map { |log| format_log(log) } }
98
156
  end
99
157
 
158
+ # @private
100
159
  def format_log(log)
101
160
  { index:
102
161
  {
@@ -1,7 +1,8 @@
1
1
  module SlackScratcher
2
2
  module Adapter
3
- class File
4
-
3
+ # File adapter for storing slack logs.
4
+ # @note Not yet implemented
5
+ class File < SlackScratcher::Adapter::Base
5
6
  end
6
7
  end
7
8
  end
@@ -1,4 +1,6 @@
1
1
  module SlackScratcher
2
+ # SlackScratcher Error namespace
3
+ # @since 0.0.1
2
4
  module Error
3
5
  autoload :UserNotFoundError, 'slack_scratcher/error/user_not_found_error'
4
6
  autoload :SlackApiError, 'slack_scratcher/error/slack_api_error'
@@ -1,5 +1,7 @@
1
1
  module SlackScratcher
2
2
  module Error
3
+ # Error which represent FileNotFound
4
+ # since 0.0.1
3
5
  class FileNotFound < StandardError
4
6
  end
5
7
  end
@@ -1,5 +1,7 @@
1
1
  module SlackScratcher
2
2
  module Error
3
+ # Error which represent SlackApiError
4
+ # since 0.0.1
3
5
  class SlackApiError < StandardError
4
6
  end
5
7
  end
@@ -1,5 +1,7 @@
1
1
  module SlackScratcher
2
2
  module Error
3
+ # Error which represent TokenNotSet
4
+ # since 0.0.1
3
5
  class TokenNotSet < StandardError
4
6
  end
5
7
  end
@@ -1,5 +1,7 @@
1
1
  module SlackScratcher
2
2
  module Error
3
+ # Error which represent UserNotFoundError
4
+ # since 0.0.1
3
5
  class UserNotFoundError < StandardError
4
6
  end
5
7
  end
@@ -1,8 +1,20 @@
1
1
  module SlackScratcher
2
+ # SlackScratcher helper module
3
+ # @since 0.0.1
2
4
  module Helper
5
+ # Index data for searching by specific column
6
+ #
7
+ # @param [Array<Hash>] dataset Dataset
8
+ # @param [String] column column key for indexing
9
+ #
10
+ # @example Index name column
11
+ # data = [{name: 'foo', value: 10}, {name: 'bar', value: 20}]
12
+ # indexed_data = helper.index_data(data, :name)
13
+ # indexed_data['foo'][:value] == 10 #=> true
14
+ #
15
+ # @return [Hash] indexed hash
3
16
  def self.index_data(dataset, column)
4
17
  dataset.map { |data| { data[column] => data } }.inject({}, :merge)
5
18
  end
6
19
  end
7
20
  end
8
-
@@ -1,5 +1,8 @@
1
1
  module SlackScratcher
2
+ # SlackScratcher Loader namespace
3
+ # @since 0.0.1
2
4
  module Loader
5
+ autoload :Base, 'slack_scratcher/loader/base'
3
6
  autoload :File, 'slack_scratcher/loader/file'
4
7
  autoload :Api, 'slack_scratcher/loader/api'
5
8
  end
@@ -2,15 +2,38 @@ require 'slack'
2
2
 
3
3
  module SlackScratcher
4
4
  module Loader
5
- class Api
6
- include Enumerable
7
-
5
+ # Loader class for importing latest slack logs through Slack API
6
+ #
7
+ # @since 0.1
8
+ class Api < SlackScratcher::Loader::Base
9
+ # Duration of waiting between API call
8
10
  WAIT_TIME = 1
9
11
 
12
+ # Initialize SlackScratcher::Loader::Api object.
13
+ #
14
+ # @see https://api.slack.com/web
15
+ #
16
+ # @param [String] token Slack API token. It also can be set by using
17
+ # ENV['SLACK_TOKEN']
18
+ #
19
+ # @example Create File loader obect
20
+ # token = '123456789'
21
+ # SlackScratcher::Loader::Api.new token
22
+ #
23
+ # @return [SlackScratcher::Loader::Api] Api loader object
10
24
  def initialize(token = nil)
11
25
  authenticate_slack(token)
12
26
  end
13
27
 
28
+ # Iterate all log data which is parsed from Slack API.
29
+ #
30
+ # @param [SlackScratcher::Adapter::Base] adapter Datastore adapter
31
+ # for getting when to starting fetch log
32
+ #
33
+ # @example Iterate all logs for priniting contents
34
+ # loader.each { |data| puts data }
35
+ #
36
+ # return [Boolean] If there isn't any ploblem, it returns true
14
37
  def each(adapter)
15
38
  @users || set_users
16
39
 
@@ -24,11 +47,13 @@ module SlackScratcher
24
47
 
25
48
  private
26
49
 
50
+ # @private
27
51
  def set_users
28
52
  @users = users
29
53
  SlackScratcher.logger.info "* Users list refreshed"
30
54
  end
31
55
 
56
+ # @private
32
57
  def check_users(logs)
33
58
  logs
34
59
  .select { |log| log.key? 'user' }
@@ -36,6 +61,7 @@ module SlackScratcher
36
61
  .any? { |user| @users[user].nil? }
37
62
  end
38
63
 
64
+ # @private
39
65
  def parse_log(channel, from)
40
66
  logs = channel_history(channel[:id], from)
41
67
  if check_users(logs)
@@ -44,17 +70,20 @@ module SlackScratcher
44
70
  SlackScratcher::Model::Chats.new(logs, channel, @users).refined_data
45
71
  end
46
72
 
73
+ # @private
47
74
  def authenticate_slack(token)
48
75
  token ||= ENV['SLACK_TOKEN']
49
76
  fail SlackScratcher::Error::TokenNotSet unless token
50
77
  Slack.configure { |config| config.token = token }
51
78
  end
52
79
 
80
+ # @private
53
81
  def channels
54
82
  response = validate_response(Slack.channels_list)
55
83
  index_channels response['channels']
56
84
  end
57
85
 
86
+ # @private
58
87
  def active_channels
59
88
  wait
60
89
 
@@ -62,14 +91,17 @@ module SlackScratcher
62
91
  index_channels filter_active_channels(response['channels'])
63
92
  end
64
93
 
94
+ # @private
65
95
  def filter_active_channels(data)
66
96
  data.select { |channel| channel['is_archived'] == false }
67
97
  end
68
98
 
99
+ # @private
69
100
  def index_channels(data)
70
101
  data.map { |channel| { id: channel['id'], name: channel['name'] } }
71
102
  end
72
103
 
104
+ # @private
73
105
  def users
74
106
  wait
75
107
 
@@ -77,6 +109,7 @@ module SlackScratcher
77
109
  SlackScratcher::Helper.index_data user_list, 'id'
78
110
  end
79
111
 
112
+ # @private
80
113
  def channel_history(channel_id, from, to = Time.now)
81
114
  wait
82
115
 
@@ -90,12 +123,14 @@ module SlackScratcher
90
123
  validate_response Slack.channels_history(attrs), :messages
91
124
  end
92
125
 
126
+ # @private
93
127
  def validate_response(response, key = nil)
94
128
  fail SlackScratcher::Error::ApiError unless response['ok'] == true
95
129
  return response unless key
96
130
  response[key.to_s]
97
131
  end
98
132
 
133
+ # @private
99
134
  def wait
100
135
  sleep WAIT_TIME
101
136
  end
@@ -0,0 +1,19 @@
1
+ module SlackScratcher
2
+ module Loader
3
+ # Abstract loader class for importing slack log data
4
+ # @since 0.1
5
+ class Base
6
+ include Enumerable
7
+
8
+ # @ abstract
9
+ def initialize
10
+ fail NotImplementedError
11
+ end
12
+
13
+ # @ abstract
14
+ def each
15
+ fail NotImplementedError
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,9 +2,19 @@ require 'oj'
2
2
 
3
3
  module SlackScratcher
4
4
  module Loader
5
- class File
6
- include Enumerable
7
-
5
+ # Loader class for importing slack log data from exported data.
6
+ #
7
+ # @since 0.0.1
8
+ class File < SlackScratcher::Loader::Base
9
+ # Initialize SlackScratcher::Loader::File object.
10
+ #
11
+ # @param [String] target_dir Directory which unarchived log data
12
+ #
13
+ # @example Create File loader obect
14
+ # target_dir = '~/tmp/my_slack-2015-03-16/'
15
+ # SlackScratcher::Loader::File.new target_dir
16
+ #
17
+ # @return [SlackScratcher::Loader::File] File loader object
8
18
  def initialize(target_dir)
9
19
  fail ArgumentError unless ::File.directory?(target_dir)
10
20
 
@@ -13,6 +23,14 @@ module SlackScratcher
13
23
  @channels = channels
14
24
  end
15
25
 
26
+ # Iterate all log data which is parsed from log file in log directory
27
+ #
28
+ # @param [NilClass] _ Not use
29
+ #
30
+ # @example Iterate all logs for priniting contents
31
+ # loader.each { |data| puts data }
32
+ #
33
+ # return [Boolean] If there isn't any ploblem, it returns true
16
34
  def each(_ = nil)
17
35
  files.each do |file|
18
36
  yield parse_log_file(file), file
@@ -23,18 +41,22 @@ module SlackScratcher
23
41
 
24
42
  private
25
43
 
44
+ # @private
26
45
  def get_channel_dir(path)
27
46
  ::File.dirname(path).split('/').last
28
47
  end
29
48
 
49
+ # @private
30
50
  def users
31
51
  load "#{@target}/users.json", 'id'
32
52
  end
33
53
 
54
+ # @private
34
55
  def channels
35
56
  load "#{@target}/channels.json", 'name'
36
57
  end
37
58
 
59
+ # @private
38
60
  def load(target, index_column)
39
61
  fail SlackScratcher::Error::FileNotFound unless ::File.exist? target
40
62
 
@@ -42,27 +64,32 @@ module SlackScratcher
42
64
  SlackScratcher::Helper.index_data channels, index_column
43
65
  end
44
66
 
67
+ # @private
45
68
  def channel_info(log_file)
46
69
  name = get_channel_dir(log_file)
47
70
  { name: name, id: @channels[name]['id'] }
48
71
  end
49
72
 
73
+ # @private
50
74
  def parse_log_file(log_file)
51
75
  channel = channel_info(log_file)
52
76
  logs = Oj.load(::File.read(log_file))
53
77
  SlackScratcher::Model::Chats.new(logs, channel, @users).refined_data
54
78
  end
55
79
 
80
+ # @private
56
81
  def files
57
82
  channel_dirs.inject([]) do |arr, channel|
58
83
  arr + log_files(channel)
59
84
  end
60
85
  end
61
86
 
87
+ # @private
62
88
  def channel_dirs
63
89
  Dir["#{@target}/*/"]
64
90
  end
65
91
 
92
+ # @private
66
93
  def log_files(channel)
67
94
  Dir["#{channel}*.json"]
68
95
  end
@@ -1,4 +1,6 @@
1
1
  module SlackScratcher
2
+ # SlackScratcher model namespace
3
+ # @since 0.0.1
2
4
  module Model
3
5
  autoload :Chats, 'slack_scratcher/model/chats'
4
6
  end
@@ -1,8 +1,26 @@
1
1
  module SlackScratcher
2
2
  module Model
3
+ # Chats model for processing chat data
4
+ #
5
+ # @since 0.0.1
6
+ # @attr_reader [Array] data Original data
7
+ # @attr_reader [Array] refined_data data which is processed
3
8
  class Chats
4
- attr_reader :refined_data, :data
5
-
9
+ attr_reader :data, :refined_data
10
+
11
+ # Initialize SlackScratcher::Model::Chats object. This class is
12
+ # used in Loaders
13
+ #
14
+ # @see SlackScratcher::Loader::File
15
+ # @see SlackScratcher::Loader::Api
16
+ #
17
+ # @param [Array] Data chatting data from loader
18
+ # @param [Hash] channel Hash which have Channel informaiton
19
+ # @option channel [string] :id Channel's unique id
20
+ # @option channel [string] :name Channel's name
21
+ # @param [Hash] users Information of all user
22
+ #
23
+ # @return [SlackScratcher::Model::Chats] Chats model object
6
24
  def initialize(data, channel, users)
7
25
  if !data.is_a?(Array) || !users.is_a?(Hash) || !channel.is_a?(Hash)
8
26
  fail ArgumentError
@@ -17,12 +35,14 @@ module SlackScratcher
17
35
 
18
36
  private
19
37
 
38
+ # @private
20
39
  def refine
21
40
  @data
22
41
  .map { |log| refine_data(log) }
23
42
  .select { |log| !log['uid'].nil? }
24
43
  end
25
44
 
45
+ # @private
26
46
  def refine_data(log)
27
47
  user = find_user(log) unless user
28
48
 
@@ -38,10 +58,12 @@ module SlackScratcher
38
58
  log
39
59
  end
40
60
 
61
+ # @private
41
62
  def create_uid(log)
42
63
  "#{log['datetime']}-#{log['channel_id']}-#{log['username']}"
43
64
  end
44
65
 
66
+ # @private
45
67
  def refine_text(text)
46
68
  text = ":#{text}" if text.is_a?(Symbol)
47
69
 
@@ -50,6 +72,7 @@ module SlackScratcher
50
72
  .gsub(%r{<(http(s)?://.*?)>}) { $1 }
51
73
  end
52
74
 
75
+ # @private
53
76
  def find_user(log)
54
77
  return bot_user(log) if log.key?('username')
55
78
 
@@ -61,12 +84,14 @@ module SlackScratcher
61
84
  unknown_user
62
85
  end
63
86
 
87
+ # @private
64
88
  def undefined_user
65
89
  user = { 'name' => '_unknown_' }
66
90
  user['profile'] = { 'image_32' => '' }
67
91
  user
68
92
  end
69
93
 
94
+ # @private
70
95
  def bot_user(log)
71
96
  user = { 'name' => log['username'] }
72
97
  user['profile'] = { 'image_32' => log['icons']['image_48'] }
@@ -1,26 +1,51 @@
1
1
  module SlackScratcher
2
+ # Slack log router. This import log data from loader, and route them
3
+ # to adapter
4
+ #
5
+ # @since 0.0.1
2
6
  class Router
7
+ # Initalize SlackScratcher::Router object
8
+ #
9
+ # @param [SlackScratcher::Loader::Base] loader
10
+ # @param [SlackScratcher::Adapter::Base] adapter
11
+ #
12
+ # @example Initialize router object
13
+ # SlackScratcher::Router.new(loader, adapter)
14
+ #
15
+ # @return [SlackScratcher::Router] Router object
3
16
  def initialize(loader, adapter)
4
17
  @loader = loader
5
18
  @adapter = adapter
6
19
  end
7
20
 
21
+ # Route logs to adapter
22
+ #
23
+ # @return [Boolean] There isn't any problem, it returns true
8
24
  def route
9
25
  ready
10
26
  _route
27
+ true
11
28
  end
12
29
 
30
+ # Run loop to route logs in real time
31
+ #
32
+ # @return [Boolean] If loop interrupted, it return false
13
33
  def route_loop
14
34
  ready
15
35
  loop { _route }
36
+ rescue Interrupt => error
37
+ SlackScratcher.logger.info error
38
+ false
16
39
  end
17
40
 
18
41
  private
19
42
 
43
+ # @private
20
44
  def ready
21
45
  @adapter.ready_index
22
46
  end
23
47
 
48
+ # @private
24
49
  def _route
25
50
  @loader.each(@adapter) do |data, metadata|
26
51
  if data.empty?
@@ -1,3 +1,4 @@
1
1
  module SlackScratcher
2
- VERSION = '0.1'
2
+ # Current version of SlackScratcher
3
+ VERSION = '0.2'
3
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slack_scratcher
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daekwon Kim
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: guard
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +150,20 @@ dependencies:
136
150
  - - ">="
137
151
  - !ruby/object:Gem::Version
138
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: codeclimate-test-reporter
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
139
167
  - !ruby/object:Gem::Dependency
140
168
  name: rubocop
141
169
  requirement: !ruby/object:Gem::Requirement
@@ -151,7 +179,21 @@ dependencies:
151
179
  - !ruby/object:Gem::Version
152
180
  version: '0'
153
181
  - !ruby/object:Gem::Dependency
154
- name: codeclimate-test-reporter
182
+ name: inch
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: yard
155
197
  requirement: !ruby/object:Gem::Requirement
156
198
  requirements:
157
199
  - - ">="
@@ -174,6 +216,7 @@ extra_rdoc_files: []
174
216
  files:
175
217
  - lib/slack_scratcher.rb
176
218
  - lib/slack_scratcher/adapter.rb
219
+ - lib/slack_scratcher/adapter/base.rb
177
220
  - lib/slack_scratcher/adapter/elasticsearch.rb
178
221
  - lib/slack_scratcher/adapter/file.rb
179
222
  - lib/slack_scratcher/error.rb
@@ -184,6 +227,7 @@ files:
184
227
  - lib/slack_scratcher/helper.rb
185
228
  - lib/slack_scratcher/loader.rb
186
229
  - lib/slack_scratcher/loader/api.rb
230
+ - lib/slack_scratcher/loader/base.rb
187
231
  - lib/slack_scratcher/loader/file.rb
188
232
  - lib/slack_scratcher/model.rb
189
233
  - lib/slack_scratcher/model/chats.rb