slack_scratcher 0.1 → 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|