lita-kintai 0.2.0 → 0.3.0

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: 0e5ec578207f077b2d7cb7d6f9c0bd5bec0de09c
4
- data.tar.gz: 31762b9c377b44c6629431824ffc2ff4b7e15271
3
+ metadata.gz: 5d058f92110471659693ea8060d40a4a02b85a1f
4
+ data.tar.gz: 5463d339eaa7b46964df52ca7ab34661f7e9936f
5
5
  SHA512:
6
- metadata.gz: 6d133cc94a15c8bc24570eba382a0b65af58ff3534528a674b6212b70847fd1110410e8892931cb24509be5ff9391cef9525e4011160f756d562a16673f93bae
7
- data.tar.gz: 3e8ec3f773dd2e5619591cfdcf84081083c94fc7aedbfabc5389608be9c76df8e585b32cd9c810de6ac4658ff19a50292b51c887741a9de78ed544141e07c8f2
6
+ metadata.gz: eac814178e90adb59f1c643c261c05403713936c046012cd07e4446bbfd3c83ef2b3965b165f837287b2d41068d72f64f21611536b3764648ead142ddf5a5f63
7
+ data.tar.gz: afc014be3319b2c57fb72393161be0acc2d12c92c01ef2e5669a7999a1f293b58dbd390424804f5f1d105df72381633fcb4dd2f0c80a3818931405a0106d47b8
data/lib/gmail.rb ADDED
@@ -0,0 +1,86 @@
1
+ require 'google/apis/gmail_v1'
2
+ require 'googleauth'
3
+ require 'googleauth/stores/file_token_store'
4
+
5
+ require 'fileutils'
6
+
7
+ class Gmail
8
+ OOB_URI = 'urn:ietf:wg:oauth:2.0:oob'
9
+ APPLICATION_NAME = 'Lita Kintai'
10
+ CLIENT_SECRETS_PATH = 'client_secret.json'
11
+ CREDENTIALS_PATH = File.join(Dir.home, '.credentials',
12
+ "lita-kintai.yaml")
13
+ SCOPE = [Google::Apis::GmailV1::AUTH_GMAIL_READONLY, Google::Apis::GmailV1::AUTH_GMAIL_SEND]
14
+ USER_ID = 'default'
15
+
16
+ def self.authorized?
17
+ !service.nil? && !service.authorization.nil?
18
+ end
19
+
20
+ def self.credentials_from_code(code)
21
+ authorizer.get_and_store_credentials_from_code(
22
+ user_id: USER_ID, code: code, base_url: OOB_URI)
23
+ end
24
+
25
+ def self.authorization_url
26
+ authorizer.get_authorization_url(base_url: OOB_URI)
27
+ end
28
+
29
+ def self.find_mail(query)
30
+ ids = service.list_user_messages('me', q: query)
31
+
32
+ return [] unless ids.messages
33
+ ids.messages.map do |message|
34
+ find_mail_by_id(message.id)
35
+ end
36
+ end
37
+
38
+ def self.send_message(mail)
39
+ message = Google::Apis::GmailV1::Message.new(raw: mail.to_s )
40
+ result = service.send_user_message('me', message)
41
+ end
42
+
43
+ private
44
+ def self.service
45
+ return @service if !@service.nil? && !@service.authorization.nil?
46
+
47
+ credentials = authorizer.get_credentials(USER_ID)
48
+ if credentials
49
+ @service.authorization = credentials
50
+ return @service
51
+ end
52
+
53
+ return @service
54
+ end
55
+
56
+ def self.authorizer
57
+ return @authorizer unless @authorizer.nil?
58
+
59
+ @service = Google::Apis::GmailV1::GmailService.new
60
+ @service.client_options.application_name = APPLICATION_NAME
61
+
62
+ FileUtils.mkdir_p(File.dirname(CREDENTIALS_PATH))
63
+
64
+ client_id = Google::Auth::ClientId.from_file(CLIENT_SECRETS_PATH)
65
+ token_store = Google::Auth::Stores::FileTokenStore.new(
66
+ file: CREDENTIALS_PATH)
67
+ @authorizer = Google::Auth::UserAuthorizer.new(
68
+ client_id, SCOPE, token_store)
69
+ end
70
+
71
+ def self.find_mail_by_id(id)
72
+ results = @service.get_user_message('me', id)
73
+
74
+ body = results.payload.parts ?
75
+ results.payload.parts.first.body.data :
76
+ results.payload.body.data
77
+ headers = results.payload.headers
78
+
79
+ {
80
+ subject: headers.select { |e| e.name == 'Subject'}.first.value,
81
+ from: headers.select { |e| e.name == 'From'}.first.value,
82
+ date: Time.parse(headers.select { |e| e.name == 'Date'}.first.value),
83
+ body: body.force_encoding('utf-8'),
84
+ }
85
+ end
86
+ end
data/lib/lita-kintai.rb CHANGED
@@ -4,6 +4,7 @@ Lita.load_locales Dir[File.expand_path(
4
4
  File.join("..", "..", "locales", "*.yml"), __FILE__
5
5
  )]
6
6
 
7
+ require "gmail"
7
8
  require "lita/handlers/kintai"
8
9
 
9
10
  Lita::Handlers::Kintai.template_root File.expand_path(
@@ -1,41 +1,52 @@
1
- require 'google/apis/gmail_v1'
2
- require 'googleauth'
3
- require 'googleauth/stores/file_token_store'
4
-
5
- require 'fileutils'
6
1
  require 'date'
7
-
8
2
  require 'rufus-scheduler'
3
+ require 'mail'
9
4
 
10
5
  module Lita
11
6
  module Handlers
12
7
  class Kintai < Handler
13
8
  config :query, type: String
9
+ config :mail_to, type: String, default: ''
10
+ config :mail_cc, type: String, default: ''
11
+ config :template_subject, type: String, default: ''
14
12
  config :template_header, type: String, default: ''
15
13
  config :template_footer, type: String, default: ''
14
+ config :template_info, type: String, default: ''
16
15
  config :schedule_cron, type: String, default: nil
17
16
  config :schedule_room, type: String, default: nil
18
17
 
19
18
  route /kintai/i, :kintai, command: true
19
+ route /^draft\s+(.+)/im, :draft, command: true
20
20
  route /^code\s+(.+)/, :code, command: true
21
21
 
22
22
  on :loaded, :load_on_start
23
-
24
- OOB_URI = 'urn:ietf:wg:oauth:2.0:oob'
25
- APPLICATION_NAME = 'Lita Kintai'
26
- CLIENT_SECRETS_PATH = 'client_secret.json'
27
- CREDENTIALS_PATH = File.join(Dir.home, '.credentials',
28
- "lita-kintai.yaml")
29
- SCOPE = Google::Apis::GmailV1::AUTH_GMAIL_READONLY
30
- USER_ID = 'default'
23
+ on :slack_reaction_added, :reaction_added
31
24
 
32
25
  def kintai(response)
33
- response.reply(current_kintai)
26
+ if Gmail.authorized?
27
+ register_draft(response, kintai_info)
28
+ else
29
+ response.reply(authenticate_info)
30
+ end
34
31
  end
35
32
 
36
- def send_kintai(user: user, room: room)
37
- target = Source.new(user: user, room: room)
38
- robot.send_message(target, current_kintai)
33
+ def draft(response)
34
+ info = response.matches[0][0]
35
+ register_draft(response, info)
36
+ end
37
+
38
+ def register_draft(response, info)
39
+ mail = create_kintai_mail(info)
40
+ reply = response.reply(mail_to_message(mail))
41
+ @@draft = { channel: reply["channel"], ts: reply["ts"], mail: mail }
42
+ reply
43
+ end
44
+
45
+ def code(response)
46
+ code = response.matches[0][0]
47
+ Gmail.credentials_from_code(code)
48
+
49
+ response.reply("Confirmed")
39
50
  end
40
51
 
41
52
  def load_on_start(_payload)
@@ -51,119 +62,144 @@ module Lita
51
62
  end
52
63
  end
53
64
 
54
- def code(response)
55
- code = response.matches[0][0]
56
- authorizer.get_and_store_credentials_from_code(
57
- user_id: USER_ID, code: code, base_url: OOB_URI)
65
+ def send_kintai(user: user, room: room)
66
+ if Gmail.authorized?
67
+ mail = create_kintai_mail(kintai_info)
68
+ reply = send_message(user: user, room: room, message: mail)
69
+ @@draft = { channel: reply["channel"], ts: reply["ts"], mail: mail }
70
+ reply
71
+ else
72
+ send_message(user: user, room: room, message: authenticate_info)
73
+ end
74
+ end
58
75
 
59
- response.reply("Confirmed")
76
+ def reaction_added(_payload)
77
+ case _payload[:name]
78
+ when '+1' then
79
+ if !@@draft.nil? &&
80
+ _payload[:item]["type"] == "message" &&
81
+ _payload[:item]["channel"] == @@draft[:channel] &&
82
+ _payload[:item]["ts"] == @@draft[:ts]
83
+ if Gmail.authorized?
84
+ # TODO: 成功失敗
85
+ send_mail(@@draft[:mail])
86
+ @@draft = nil
87
+ send_message(room: _payload[:item]["channel"],
88
+ message: 'Sent email.')
89
+ else
90
+ send_message(room: _payload[:item]["channel"],
91
+ message: authenticate_info)
92
+ end
93
+ end
94
+ end
60
95
  end
61
96
 
62
- def current_kintai
63
- if authorize.nil?
64
- auth_url = authorizer.get_authorization_url(base_url: OOB_URI)
65
- return <<-EOS
66
- Authenticate your Google account.
67
- Then tell me the code as follows: `code \#{your_code}`
97
+ def send_message(user: user, room: room, message: message)
98
+ target = Source.new(user: user, room: room)
99
+ robot.send_message(target, message)
100
+ end
101
+
102
+ def create_kintai_mail(info)
103
+ create_mail(
104
+ to: config.mail_to,
105
+ cc: config.mail_cc,
106
+ subject: kintai_subject,
107
+ body: kintai_body(info)
108
+ )
109
+ end
68
110
 
69
- #{auth_url}
70
- EOS
111
+ def mail_to_message(mail)
112
+ <<-EOS
113
+ To: #{mail.to}
114
+ Cc: #{mail.cc}
115
+ Subject: #{mail.subject}
116
+ #{mail.body.to_s}
117
+ EOS
118
+ end
119
+
120
+ def create_mail(to: to, cc: cc, subject: subject, body: body)
121
+ Mail.new do
122
+ to to
123
+ cc cc
124
+ subject subject
125
+ body body
71
126
  end
127
+ end
72
128
 
73
- kintai_info
129
+ def send_mail(mail)
130
+ return Gmail.send_message(mail)
74
131
  end
75
132
 
76
133
  def kintai_info
77
134
  texts = ""
78
- texts << "#{Date.today.strftime("%m/%d")} (#{%w(日 月 火 水 木 金 土)[Date.today.wday]})#{config.template_header}"
79
135
 
80
- mails = find_mail(config.query)
136
+ mails = Gmail.find_mail(config.query)
81
137
  # query の `newer:#{Date.today.strftime("%Y/%m/%d")}` 昨日のも一部返ってくる
82
138
  # `newer_than:1d` だと24h以内になるので、ここで今日のだけにする
83
139
  mails.select{ |m| m[:date] > Date.today.to_time }.each do |m|
84
140
  name = m[:from].split("\"")[1]
85
141
 
86
142
  text = m[:subject] + m[:body]
143
+ info = kintai_from_text(text)
87
144
 
88
- reason = "私用のため、"
89
- if text.match(/電車|列車/)
90
- reason = "電車遅延のため、"
91
- end
92
- if text.match(/体調|痛/)
93
- reason = "体調不良のため、"
94
- end
95
- if text.match(/健康診断|検診|健診/)
96
- reason = "健康診断のため、"
97
- end
98
-
99
- at = "出社時刻未定です。"
100
- if hm = text.match(/([0-1][0-9]|[2][0-3]):[0-5][0-9]/)
101
- at = "#{hm}頃出社予定です。"
102
- elsif min = text.match(/([0-5][0-9])分/)
103
- at = "10:#{min[1]}頃出社予定です。"
104
- end
105
-
106
- if text.match(/おやすみ|休み|有給|休暇/)
107
- reason = "本日お休みです。"
108
- at = ""
109
- end
110
-
111
- texts << "#{name}さん: #{reason}#{at}\n"
145
+ texts << "#{name}さん: #{info}\n"
112
146
  end
113
-
114
- texts << config.template_footer
147
+ texts << config.template_info
115
148
  end
116
149
 
117
- def authorize
118
- return @service if !@servise.nil? && !@servise.authorization.nil?
119
-
120
- credentials = authorizer.get_credentials(USER_ID)
121
- if credentials
122
- @service.authorization = credentials
123
- return @service
124
- end
125
-
126
- return nil
150
+ def self.kintai_from_text(text)
151
+ reason = kintai_reason(text)
152
+ time = kintai_time(text)
153
+ "#{reason}のため、#{time}です。"
127
154
  end
128
155
 
129
- def authorizer
130
- return @authorizer unless @authorizer.nil?
156
+ def kintai_subject
157
+ "#{Date.today.strftime("%m/%d")} (#{%w(日 火 水 木 金 土)[Date.today.wday]})#{config.template_subject}"
158
+ end
131
159
 
132
- @service = Google::Apis::GmailV1::GmailService.new
133
- @service.client_options.application_name = APPLICATION_NAME
160
+ def kintai_body(info)
161
+ <<-EOS
162
+ #{config.template_header}
134
163
 
135
- FileUtils.mkdir_p(File.dirname(CREDENTIALS_PATH))
164
+ #{info}
136
165
 
137
- client_id = Google::Auth::ClientId.from_file(CLIENT_SECRETS_PATH)
138
- token_store = Google::Auth::Stores::FileTokenStore.new(
139
- file: CREDENTIALS_PATH)
140
- @authorizer = Google::Auth::UserAuthorizer.new(
141
- client_id, SCOPE, token_store)
166
+ #{config.template_footer}
167
+ EOS
142
168
  end
143
169
 
144
- def find_mail(query)
145
- ids = @service.list_user_messages('me', q: query)
146
-
147
- return [] unless ids.messages
148
- ids.messages.map do |message|
149
- find_mail_by_id(message.id)
170
+ def self.kintai_reason(text)
171
+ if text.match(/電車|列車/)
172
+ return "電車遅延"
173
+ elsif text.match(/体調|痛/)
174
+ return "体調不良"
175
+ elsif text.match(/健康診断|検診|健診/)
176
+ return "健康診断"
150
177
  end
178
+ return "私用"
151
179
  end
152
180
 
153
- def find_mail_by_id(id)
154
- results = @service.get_user_message('me', id)
181
+ def self.kintai_time(text)
182
+ if hm = text.match(/([0-1][0-9]|[2][0-3]):[0-5][0-9]/)
183
+ return "#{hm}頃出社予定"
184
+ elsif min = text.match(/(([0-5])*[0-9])分/)
185
+ return "10:#{min[1].rjust(2, "0")}頃出社予定"
186
+ elsif half = text.match(/([0-1][0-9]|[2][0-3])時半/)
187
+ return "#{half[1]}:30頃出社予定"
188
+ elsif half = text.match(/(\d)時間半/)
189
+ return "#{10+half[1].to_i}:30頃出社予定"
190
+ elsif text.match(/おやすみ|休み|有給|休暇/)
191
+ return "本日お休み"
192
+ end
193
+ return "出社時刻未定"
194
+ end
155
195
 
156
- body = results.payload.parts ?
157
- results.payload.parts.first.body.data :
158
- results.payload.body.data
159
- headers = results.payload.headers
196
+ def authenticate_info
197
+ <<-EOS
198
+ Authenticate your Google account.
199
+ Then tell me the code as follows: `code \#{your_code}`
160
200
 
161
- {
162
- subject: headers.select { |e| e.name == 'Subject'}.first.value,
163
- from: headers.select { |e| e.name == 'From'}.first.value,
164
- date: Time.parse(headers.select { |e| e.name == 'Date'}.first.value),
165
- body: body.force_encoding('utf-8'),
166
- }
201
+ #{Gmail.authorization_url}
202
+ EOS
167
203
  end
168
204
 
169
205
  Lita.register_handler(self)
data/lita-kintai.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "lita-kintai"
3
- spec.version = "0.2.0"
3
+ spec.version = "0.3.0"
4
4
  spec.authors = ["Shoma SATO"]
5
5
  spec.email = ["noir.neo.04@gmail.com"]
6
6
  spec.description = "A lita handler for summarize attendance emails. Fuckin' legacy attendance management method by email!"
@@ -17,6 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.add_runtime_dependency "lita", ">= 4.7"
18
18
  spec.add_runtime_dependency "google-api-client"
19
19
  spec.add_runtime_dependency "rufus-scheduler"
20
+ spec.add_runtime_dependency "mail"
20
21
 
21
22
  spec.add_development_dependency "bundler", "~> 1.3"
22
23
  spec.add_development_dependency "pry-byebug"
@@ -9,8 +9,8 @@ describe Lita::Handlers::Kintai, lita_handler: true do
9
9
  describe '#kintai' do
10
10
  context 'when authenticated' do
11
11
  before do
12
- allow_any_instance_of(Lita::Handlers::Kintai).to receive(:authorize).and_return(Google::Apis::GmailV1::GmailService.new)
13
- allow_any_instance_of(Lita::Handlers::Kintai).to receive(:find_mail).and_return(
12
+ allow(Gmail).to receive(:authorized?).and_return(true)
13
+ allow(Gmail).to receive(:find_mail).and_return(
14
14
  [
15
15
  {
16
16
  subject: '',
@@ -22,10 +22,73 @@ describe Lita::Handlers::Kintai, lita_handler: true do
22
22
  )
23
23
  end
24
24
 
25
- it 'returns kintai list' do
25
+ xit 'returns kintai list' do
26
26
  send_command('kintai')
27
27
  expect(replies.last).not_to be_nil
28
28
  end
29
29
  end
30
30
  end
31
+
32
+ describe '#kintai_reason(text)' do
33
+ subject { Lita::Handlers::Kintai.kintai_reason(text) }
34
+
35
+ context '「電車」が含まれる時' do
36
+ let(:text) { "電車遅延のため" }
37
+ it { is_expected.to eq "電車遅延" }
38
+ end
39
+
40
+ context '「体調不良」が含まれる時' do
41
+ let(:text) { "体調不良のため" }
42
+ it { is_expected.to eq "体調不良" }
43
+ end
44
+
45
+ context '「健康診断」が含まれる時' do
46
+ let(:text) { "健康診断に行くので" }
47
+ it { is_expected.to eq "健康診断" }
48
+ end
49
+
50
+ context 'いずれにもマッチしない時' do
51
+ let(:text) { "寝坊したので" }
52
+ it { is_expected.to eq "私用" }
53
+ end
54
+ end
55
+
56
+ describe '#kintai_time(text)' do
57
+ subject { Lita::Handlers::Kintai.kintai_time(text) }
58
+
59
+ context '「HH:mm」が含まれる時' do
60
+ let(:text) { "12:00頃出社します" }
61
+ it { is_expected.to eq "12:00頃出社予定" }
62
+ end
63
+
64
+ context '「mm分」が含まれる時' do
65
+ let(:text) { "10分ほど遅れます" }
66
+ it { is_expected.to eq "10:10頃出社予定" }
67
+ end
68
+
69
+ context '「m分」が含まれる時' do
70
+ let(:text) { "5分ほど遅れます" }
71
+ it { is_expected.to eq "10:05頃出社予定" }
72
+ end
73
+
74
+ context '「HH時半」が含まれる時' do
75
+ let(:text) { "10時半ごろに出社します" }
76
+ it { is_expected.to eq "10:30頃出社予定" }
77
+ end
78
+
79
+ context '「n時間半」が含まれる時' do
80
+ let(:text) { "1時間半ほど遅れます" }
81
+ it { is_expected.to eq "11:30頃出社予定" }
82
+ end
83
+
84
+ context '「休み」が含まれる時' do
85
+ let(:text) { "お休みをいただいてます" }
86
+ it { is_expected.to eq "本日お休み" }
87
+ end
88
+
89
+ context 'いずれにもマッチしない時' do
90
+ let(:text) { "出社時刻わかり次第また連絡します" }
91
+ it { is_expected.to eq "出社時刻未定" }
92
+ end
93
+ end
31
94
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lita-kintai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shoma SATO
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-27 00:00:00.000000000 Z
11
+ date: 2017-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lita
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mail
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: bundler
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -134,6 +148,7 @@ files:
134
148
  - Gemfile
135
149
  - README.md
136
150
  - Rakefile
151
+ - lib/gmail.rb
137
152
  - lib/lita-kintai.rb
138
153
  - lib/lita/handlers/kintai.rb
139
154
  - lita-kintai.gemspec