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 +4 -4
- data/lib/slack_scratcher.rb +6 -0
- data/lib/slack_scratcher/adapter.rb +4 -1
- data/lib/slack_scratcher/adapter/base.rb +27 -0
- data/lib/slack_scratcher/adapter/elasticsearch.rb +61 -2
- data/lib/slack_scratcher/adapter/file.rb +3 -2
- data/lib/slack_scratcher/error.rb +2 -0
- data/lib/slack_scratcher/error/file_not_found.rb +2 -0
- data/lib/slack_scratcher/error/slack_api_error.rb +2 -0
- data/lib/slack_scratcher/error/token_not_set.rb +2 -0
- data/lib/slack_scratcher/error/user_not_found_error.rb +2 -0
- data/lib/slack_scratcher/helper.rb +13 -1
- data/lib/slack_scratcher/loader.rb +3 -0
- data/lib/slack_scratcher/loader/api.rb +38 -3
- data/lib/slack_scratcher/loader/base.rb +19 -0
- data/lib/slack_scratcher/loader/file.rb +30 -3
- data/lib/slack_scratcher/model.rb +2 -0
- data/lib/slack_scratcher/model/chats.rb +27 -2
- data/lib/slack_scratcher/router.rb +25 -0
- data/lib/slack_scratcher/version.rb +2 -1
- metadata +46 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d69bdc6dce5f556068fc0e2920cbc511a0197425
|
4
|
+
data.tar.gz: 1bb53fa814baaabff2bc7db34e3a04cb1a7d71a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d23b90ecb37f1babfd251c287e3adef18da56ac8a2aa40ddb075de0c48d902a83121bae2fdb90c0b67fee69e77a54624043f208c87c37ca5cdec60e839a0b86c
|
7
|
+
data.tar.gz: b5776d10ea833e60f774f3e297cbaffcdd7a72692a490a723705d4fe51347127859390b1f62b804b484d0bb4cbbd58b5a5672049649a28b53cb1e61af7124c98
|
data/lib/slack_scratcher.rb
CHANGED
@@ -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 :
|
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
|
-
|
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,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
|
-
|
@@ -2,15 +2,38 @@ require 'slack'
|
|
2
2
|
|
3
3
|
module SlackScratcher
|
4
4
|
module Loader
|
5
|
-
class
|
6
|
-
|
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
|
6
|
-
|
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,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 :
|
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?
|
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.
|
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:
|
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
|