Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slack Events API対応 #39

Merged
merged 7 commits into from
Aug 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ end

gem "slack-ruby-client"
gem "async-websocket", '~> 0.8.0' # dependency of slack-ruby-client RTM

gem "rack", "~> 2.2"
1 change: 1 addition & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,7 @@ DEPENDENCIES
mongo
nokogiri
puma
rack (~> 2.2)
rubyzip
sinatra
slack-ruby-client
Expand Down
5 changes: 4 additions & 1 deletion bin/init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
# XXX using string hash key for backword compatibility...
config = {
'slack' => {
'token' => nil
'token' => nil,
'team_id' => nil,
'use_events_api' => false,
'signing_secret' => nil,
},
'aws' => {
'access_key_id' => nil,
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ services:
container_name: slack-patron-logger
volumes:
- .:/usr/local/slack-patron
ports:
- "127.0.0.1:9293:9293"
restart: always

viewer:
Expand Down
4 changes: 4 additions & 0 deletions lib/slack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@
c.start_method = :rtm_connect
c.store_class = Slack::RealTime::Stores::Starter
end

Slack::Events.configure do |c|
c.signing_secret = config['slack']['use_events_api'] ? config['slack']['signing_secret'] : nil
end
84 changes: 84 additions & 0 deletions lib/slack_events_receiver.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
require 'rack'

class SlackEventsReceiver
attr_reader :logger

def initialize(team_id)
@team_id = team_id
raise ArgumentError unless @team_id and @team_id.start_with? 'T'
end

def start!(logger)
@logger = logger

Rack::Server.start(
app: lambda do |env|
req = Rack::Request.new(env)

begin
Slack::Events::Request.new(req).verify!
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

参考: https://github.com/slack-ruby/slack-ruby-client/pull/369

process(req.body)
rescue Slack::Events::Request::MissingSigningSecret,
Slack::Events::Request::InvalidSignature,
Slack::Events::Request::TimestampExpired => e
warn 'bad request: %s' % e
[400, {}, '']
end
end,
Port: 9293,
)
end

def process(body)
# https://api.slack.com/apis/connections/events-api

data = JSON.parse(body.read)
type = data['type']

case type
when 'url_verification'
[200, { 'content-type': 'text/plain' }, data['challenge']]
when 'event_callback'
process_event data['event'] if data['team_id'] == @team_id
[204, {}, '']
else
[400, {}, '']
end
end

def process_event(event)
type = event['type']
event.delete 'type'

case type
when 'message'
# https://api.slack.com/events/message
return if logger.is_private_channel(event['channel'])
return if logger.is_direct_message(event['channel'])

puts 'new message'

logger.insert_message(event)

when 'team_join'
puts 'new user has joined'
logger.update_users

when 'user_change'
puts 'user data has changed'
logger.update_users

when 'channel_created'
puts 'channel has created'
logger.update_channels

when 'channel_rename'
puts 'channel has renamed'
logger.update_channels

when 'emoji_changed'
puts 'emoji has changed'
logger.update_emojis
end
end
end
67 changes: 9 additions & 58 deletions lib/slack_logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
require './lib/slack'
require './lib/db'

config = YAML.load_file('./config.yml')

class SlackLogger
attr_reader :client

Expand All @@ -19,6 +17,11 @@ def is_direct_message(channel_name)
channel_name[0] == 'D'
end

alias :_insert_message :insert_message # FIXME!!!
def insert_message(message)
_insert_message(message)
end

def update_users
users = client.users_list['members']
replace_users(users)
Expand Down Expand Up @@ -50,61 +53,9 @@ def fetch_history(target, channel)
end
end

# realtime events
def log_realtime
realtime = Slack::RealTime::Client.new

realtime.on :message do |m|
if is_private_channel(m['channel'])
next
end
if is_direct_message(m['channel'])
next
end

puts m
insert_message(m)
end

realtime.on :team_join do |e|
puts "new user has joined"
update_users
end

realtime.on :user_change do |e|
puts "user data has changed"
update_users
end

realtime.on :channel_created do |c|
puts "channel has created"
update_channels
end

realtime.on :channel_rename do |c|
puts "channel has renamed"
update_channels
end

realtime.on :emoji_changed do |c|
puts "emoji has changed"
update_emojis
end

# if connection closed, restart the realtime logger
realtime.on :close do
puts "websocket disconnected"
log_realtime
end

realtime.start!
end

def start
def start(receiver)
begin
realtime_thread = Thread.new {
log_realtime
}
receiver_thread = Thread.new { receiver.start!(self) }

update_emojis
update_users
Expand All @@ -119,9 +70,9 @@ def start
end

# realtime event is joined and dont exit current thread
realtime_thread.join
receiver_thread.join
ensure
realtime_thread.kill
receiver_thread.kill
end
end
end
50 changes: 50 additions & 0 deletions lib/slack_rtm_receiver.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
class SlackRTMReceiver
def start!(logger)
realtime = Slack::RealTime::Client.new

realtime.on :message do |m|
if logger.is_private_channel(m['channel'])
next
end
if logger.is_direct_message(m['channel'])
next
end

puts 'new message'
logger.insert_message(m)
end

realtime.on :team_join do |e|
puts "new user has joined"
logger.update_users
end

realtime.on :user_change do |e|
puts "user data has changed"
logger.update_users
end

realtime.on :channel_created do |c|
puts "channel has created"
logger.update_channels
end

realtime.on :channel_rename do |c|
puts "channel has renamed"
logger.update_channels
end

realtime.on :emoji_changed do |c|
puts "emoji has changed"
logger.update_emojis
end

# if connection closed, restart the realtime logger
realtime.on :close do
puts "websocket disconnected"
start! logger
end

realtime.start!
end
end
9 changes: 8 additions & 1 deletion logger/logger.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
require './lib/slack'

require './lib/slack_logger'
require './lib/slack_events_receiver'
require './lib/slack_rtm_receiver'

config = YAML.load_file('./config.yml')

SlackLogger.new.start
receiver = config['slack']['use_events_api'] ? SlackEventsReceiver.new(config['slack']['team_id']) : SlackRTMReceiver.new
SlackLogger.new.start receiver