@ -1,18 +0,0 @@ | |||
require 'slack-mathbot/version' | |||
require 'slack-mathbot/about' | |||
require 'slack-mathbot/config' | |||
require 'slack-mathbot/hooks' | |||
require 'slack-mathbot/commands' | |||
require 'slack-mathbot/app' | |||
module SlackMathbot | |||
class << self | |||
def configure | |||
block_given? ? yield(Config) : Config | |||
end | |||
def config | |||
Config | |||
end | |||
end | |||
end |
@ -1,83 +0,0 @@ | |||
module SlackMathbot | |||
class App | |||
cattr_accessor :hooks | |||
include SlackMathbot::Hooks::Hello | |||
include SlackMathbot::Hooks::Message | |||
def initialize | |||
SlackMathbot.configure do |config| | |||
config.token = ENV['SLACK_API_TOKEN'] || fail("Missing ENV['SLACK_API_TOKEN'].") | |||
end | |||
Slack.configure do |config| | |||
config.token = SlackMathbot.config.token | |||
end | |||
end | |||
def config | |||
SlackMathbot.config | |||
end | |||
def self.instance | |||
@instance ||= SlackMathbot::App.new | |||
end | |||
def run | |||
auth! | |||
start! | |||
end | |||
def stop! | |||
client.stop | |||
end | |||
private | |||
def logger | |||
@logger ||= begin | |||
$stdout.sync = true | |||
Logger.new(STDOUT) | |||
end | |||
end | |||
def start! | |||
loop do | |||
client.start | |||
@client = nil | |||
end | |||
end | |||
def client | |||
@client ||= begin | |||
client = Slack.realtime | |||
hooks.each do |hook| | |||
client.on hook do |data| | |||
begin | |||
send hook, data | |||
rescue StandardError => e | |||
logger.error e | |||
begin | |||
Slack.chat_postMessage(channel: data['channel'], text: e.message) if data.key?('channel') | |||
rescue | |||
# ignore | |||
end | |||
end | |||
end | |||
end | |||
client | |||
end | |||
end | |||
def auth! | |||
auth = Slack.auth_test | |||
SlackMathbot.configure do |config| | |||
config.url = auth['url'] | |||
config.team = auth['team'] | |||
config.user = auth['user'] | |||
config.team_id = auth['team_id'] | |||
config.user_id = auth['user_id'] | |||
end | |||
logger.info "Welcome '#{SlackMathbot.config.user}' to the '#{SlackMathbot.config.team}' team at #{SlackMathbot.config.url}." | |||
end | |||
end | |||
end |
@ -1,27 +0,0 @@ | |||
module SlackMathbot | |||
module Commands | |||
class Base | |||
def self.send_message(channel, text) | |||
Slack.chat_postMessage(channel: channel, text: text) | |||
end | |||
def self.send_message_with_gif(channel, text, keywords) | |||
gif = begin | |||
Giphy.random(keywords) | |||
rescue StandardError => e | |||
logger.warn "Giphy.random: #{e.message}" | |||
nil | |||
end | |||
text = text + "\n" + gif.image_url.to_s if gif | |||
send_message channel, text | |||
end | |||
def self.logger | |||
@logger ||= begin | |||
$stdout.sync = true | |||
Logger.new(STDOUT) | |||
end | |||
end | |||
end | |||
end | |||
end |
@ -1,9 +0,0 @@ | |||
module SlackMathbot | |||
module Commands | |||
class Hi < Base | |||
def self.call(data, _command, _arguments) | |||
send_message_with_gif data.channel, "Hi <@#{data.user}>!", 'hi' | |||
end | |||
end | |||
end | |||
end |
@ -1,9 +0,0 @@ | |||
module SlackMathbot | |||
module Commands | |||
class Unknown < Base | |||
def self.call(data, _command, _arguments) | |||
send_message_with_gif data.channel, "Sorry <@#{data.user}>, I don't understand that command!", 'idiot' | |||
end | |||
end | |||
end | |||
end |
@ -1,13 +0,0 @@ | |||
module SlackMathbot | |||
module Config | |||
extend self | |||
attr_accessor :token | |||
attr_accessor :url | |||
attr_accessor :user | |||
attr_accessor :user_id | |||
attr_accessor :team | |||
attr_accessor :team_id | |||
attr_accessor :secret | |||
end | |||
end |
@ -1,3 +0,0 @@ | |||
require 'slack-mathbot/hooks/base' | |||
require 'slack-mathbot/hooks/hello' | |||
require 'slack-mathbot/hooks/message' |
@ -1,10 +0,0 @@ | |||
module SlackMathbot | |||
module Hooks | |||
module Base | |||
def included(caller) | |||
caller.hooks ||= [] | |||
caller.hooks << name.demodulize.underscore.to_sym | |||
end | |||
end | |||
end | |||
end |
@ -1,11 +0,0 @@ | |||
module SlackMathbot | |||
module Hooks | |||
module Hello | |||
extend Base | |||
def hello(_data) | |||
logger.info "Successfully connected to #{SlackMathbot.config.url}." | |||
end | |||
end | |||
end | |||
end |
@ -1,33 +0,0 @@ | |||
module SlackMathbot | |||
module Hooks | |||
module Message | |||
extend Base | |||
def message(data) | |||
data = Hashie::Mash.new(data) | |||
bot_name, command, arguments = parse_command(data.text) | |||
return unless bot_name == SlackMathbot.config.user | |||
klass = command_to_class(command || 'Default') | |||
klass.call data, command, arguments | |||
end | |||
private | |||
def parse_command(text) | |||
return unless text | |||
text = '= ' + text[1..text.length] if text[0] == '=' | |||
parts = text.split.reject(&:blank?) | |||
if parts && parts[0] == '=' | |||
parts[0] = SlackMathbot.config.user | |||
parts.insert 1, 'calculate' | |||
end | |||
[parts.first.downcase, parts[1].try(:downcase), parts[2..parts.length]] if parts && parts.any? | |||
end | |||
def command_to_class(command) | |||
klass = "SlackMathbot::Commands::#{command.titleize}".constantize rescue nil | |||
klass || SlackMathbot::Commands::Unknown | |||
end | |||
end | |||
end | |||
end |
@ -1 +0,0 @@ | |||
require 'slack-mathbot' |
@ -1,14 +0,0 @@ | |||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'app')) | |||
$LOAD_PATH.unshift(File.dirname(__FILE__)) | |||
require 'boot' | |||
Bundler.require :default, ENV['RACK_ENV'] | |||
Dir[File.expand_path('../initializers', __FILE__) + '/**/*.rb'].each do |file| | |||
require file | |||
end | |||
require File.expand_path('../application', __FILE__) | |||
require 'slack_mathbot' |
@ -1,5 +0,0 @@ | |||
require 'rubygems' | |||
require 'bundler/setup' | |||
require 'logger' | |||
require 'active_support' | |||
require 'active_support/core_ext' |
@ -1,3 +0,0 @@ | |||
ENV['RACK_ENV'] ||= 'development' | |||
require File.expand_path('../application', __FILE__) |
@ -1,3 +0,0 @@ | |||
Giphy::Configuration.configure do |config| | |||
config.api_key = ENV['GIPHY_API_KEY'] || 'dc6zaTOxFJmzC' # from https://github.com/Giphy/GiphyAPI | |||
end |
@ -1,13 +0,0 @@ | |||
module Slack | |||
module Request | |||
private | |||
alias_method :_request, :request | |||
def request(method, path, options) | |||
response = _request(method, path, options) | |||
fail response['error'] unless response['ok'] if response.is_a?(Hash) | |||
response | |||
end | |||
end | |||
end |
@ -0,0 +1,5 @@ | |||
require 'slack-ruby-bot' | |||
require 'slack-mathbot/version' | |||
require 'slack-mathbot/about' | |||
require 'slack-mathbot/commands' | |||
require 'slack-mathbot/app' |
@ -0,0 +1,4 @@ | |||
module SlackMathbot | |||
class App < SlackRubyBot::App | |||
end | |||
end |
@ -1,6 +1,3 @@ | |||
require 'slack-mathbot/commands/base' | |||
require 'slack-mathbot/commands/calculate' | |||
require 'slack-mathbot/commands/about' | |||
require 'slack-mathbot/commands/help' | |||
require 'slack-mathbot/commands/hi' | |||
require 'slack-mathbot/commands/unknown' |
@ -1,6 +1,6 @@ | |||
module SlackMathbot | |||
module Commands | |||
class Default < Base | |||
class Default < SlackRubyBot::Commands::Base | |||
def self.call(data, _command, _arguments) | |||
send_message_with_gif data.channel, SlackMathbot::ABOUT, 'math' | |||
end |
@ -1,6 +1,6 @@ | |||
module SlackMathbot | |||
module Commands | |||
class Calculate < Base | |||
class Calculate < SlackRubyBot::Commands::Base | |||
def self.call(data, _command, arguments) | |||
result = Dentaku::Calculator.new.evaluate(arguments.join) | |||
result = result.to_s if result |
@ -1,6 +1,6 @@ | |||
module SlackMathbot | |||
module Commands | |||
class Help < Base | |||
class Help < SlackRubyBot::Commands::Base | |||
def self.call(data, _command, _arguments) | |||
send_message_with_gif data.channel, 'See https://github.com/dblock/slack-mathbot, please.', 'help' | |||
end |
@ -1,103 +0,0 @@ | |||
--- | |||
http_interactions: | |||
- request: | |||
method: post | |||
uri: https://slack.com/api/auth.test | |||
body: | |||
encoding: UTF-8 | |||
string: token=token | |||
headers: | |||
Accept: | |||
- application/json; charset=utf-8 | |||
User-Agent: | |||
- Slack Ruby Gem 1.1.1 | |||
Content-Type: | |||
- application/x-www-form-urlencoded | |||
Accept-Encoding: | |||
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |||
response: | |||
status: | |||
code: 200 | |||
message: OK | |||
headers: | |||
Access-Control-Allow-Origin: | |||
- '*' | |||
Cache-Control: | |||
- private, no-cache, no-store, must-revalidate | |||
Content-Type: | |||
- application/json; charset=utf-8 | |||
Date: | |||
- Tue, 28 Apr 2015 12:55:23 GMT | |||
Expires: | |||
- Mon, 26 Jul 1997 05:00:00 GMT | |||
Pragma: | |||
- no-cache | |||
Server: | |||
- Apache | |||
Strict-Transport-Security: | |||
- max-age=31536000; includeSubDomains; preload | |||
Vary: | |||
- Accept-Encoding | |||
X-Accepted-Oauth-Scopes: | |||
- identify | |||
X-Content-Type-Options: | |||
- nosniff | |||
X-Oauth-Scopes: | |||
- identify,read,post,client | |||
X-Xss-Protection: | |||
- '0' | |||
Content-Length: | |||
- '128' | |||
Connection: | |||
- keep-alive | |||
body: | |||
encoding: UTF-8 | |||
string: '{"ok":true,"url":"https:\/\/math.slack.com\/","team":"calcteam","user":"calcuser","team_id":"TDEADBEEF","user_id":"UBAADFOOD"}' | |||
http_version: | |||
recorded_at: Tue, 28 Apr 2015 12:55:22 GMT | |||
- request: | |||
method: post | |||
uri: https://slack.com/api/rtm.start | |||
body: | |||
encoding: UTF-8 | |||
string: token=token | |||
headers: | |||
Accept: | |||
- application/json; charset=utf-8 | |||
User-Agent: | |||
- Slack Ruby Gem 1.1.1 | |||
Content-Type: | |||
- application/x-www-form-urlencoded | |||
Accept-Encoding: | |||
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |||
response: | |||
status: | |||
code: 200 | |||
message: OK | |||
headers: | |||
Access-Control-Allow-Origin: | |||
- '*' | |||
Content-Type: | |||
- application/json; charset=utf-8 | |||
Date: | |||
- Tue, 28 Apr 2015 21:41:33 GMT | |||
Server: | |||
- Apache | |||
Strict-Transport-Security: | |||
- max-age=31536000; includeSubDomains; preload | |||
Vary: | |||
- Accept-Encoding | |||
X-Content-Type-Options: | |||
- nosniff | |||
X-Xss-Protection: | |||
- '0' | |||
Content-Length: | |||
- '55' | |||
Connection: | |||
- keep-alive | |||
body: | |||
encoding: UTF-8 | |||
string: '{"ok":false,"error":"invalid_auth"}' | |||
http_version: | |||
recorded_at: Tue, 28 Apr 2015 21:41:33 GMT | |||
recorded_with: VCR 2.9.3 |
@ -1,59 +0,0 @@ | |||
--- | |||
http_interactions: | |||
- request: | |||
method: post | |||
uri: https://slack.com/api/users.info | |||
body: | |||
encoding: UTF-8 | |||
string: token=token&user=user | |||
headers: | |||
Accept: | |||
- application/json; charset=utf-8 | |||
User-Agent: | |||
- Slack Ruby Gem 1.1.1 | |||
Content-Type: | |||
- application/x-www-form-urlencoded | |||
Accept-Encoding: | |||
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |||
response: | |||
status: | |||
code: 200 | |||
message: OK | |||
headers: | |||
Access-Control-Allow-Origin: | |||
- '*' | |||
Cache-Control: | |||
- private, no-cache, no-store, must-revalidate | |||
Content-Type: | |||
- application/json; charset=utf-8 | |||
Date: | |||
- Wed, 29 Apr 2015 16:10:34 GMT | |||
Expires: | |||
- Mon, 26 Jul 1997 05:00:00 GMT | |||
Pragma: | |||
- no-cache | |||
Server: | |||
- Apache | |||
Strict-Transport-Security: | |||
- max-age=31536000; includeSubDomains; preload | |||
Vary: | |||
- Accept-Encoding | |||
X-Accepted-Oauth-Scopes: | |||
- read | |||
X-Content-Type-Options: | |||
- nosniff | |||
X-Oauth-Scopes: | |||
- identify,read,post,client | |||
X-Xss-Protection: | |||
- '0' | |||
Content-Length: | |||
- '448' | |||
Connection: | |||
- keep-alive | |||
body: | |||
encoding: UTF-8 | |||
string: '{"ok":true,"user":{"id":"U007","name":"username","deleted":false,"status":null,"color":"9f69e7","real_name":"","tz":"America\/Indiana\/Indianapolis","tz_label":"Eastern | |||
Daylight Time","tz_offset":-14400,"profile":{"real_name":"","real_name_normalized":"","email":"dblock@dblock.org","image_24":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=24&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F3654%2Fimg%2Favatars%2Fava_0015-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=32&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F3654%2Fimg%2Favatars%2Fava_0015-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=48&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F3654%2Fimg%2Favatars%2Fava_0015-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=72&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F3654%2Fimg%2Favatars%2Fava_0015-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=192&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F272a%2Fimg%2Favatars%2Fava_0015.png"},"is_admin":true,"is_owner":true,"is_primary_owner":true,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"has_files":false}}' | |||
http_version: | |||
recorded_at: Wed, 29 Apr 2015 16:10:34 GMT | |||
@ -1,32 +1,8 @@ | |||
require 'spec_helper' | |||
describe SlackMathbot::App do | |||
subject do | |||
def app | |||
SlackMathbot::App.new | |||
end | |||
context 'not configured' do | |||
before do | |||
@slack_api_token = ENV.delete('SLACK_API_TOKEN') | |||
end | |||
after do | |||
ENV['SLACK_API_TOKEN'] = @slack_api_token | |||
end | |||
it 'requires SLACK_API_TOKEN' do | |||
expect { subject }.to raise_error RuntimeError, "Missing ENV['SLACK_API_TOKEN']." | |||
end | |||
end | |||
context 'configured', vcr: { cassette_name: 'auth_test' } do | |||
context 'run' do | |||
before do | |||
subject.send(:auth!) | |||
end | |||
it 'succeeds auth' do | |||
expect(subject.config.url).to eq 'https://math.slack.com/' | |||
expect(subject.config.team).to eq 'calcteam' | |||
expect(subject.config.user).to eq 'calcuser' | |||
expect(subject.config.team_id).to eq 'TDEADBEEF' | |||
expect(subject.config.user_id).to eq 'UBAADFOOD' | |||
end | |||
end | |||
end | |||
it_behaves_like 'a slack ruby bot' | |||
end |
@ -1,6 +1,12 @@ | |||
require 'spec_helper' | |||
describe SlackMathbot::Commands::Help do | |||
def app | |||
SlackMathbot::App.new | |||
end | |||
before do | |||
app.config.user = 'mathbot' | |||
end | |||
it 'help' do | |||
expect(message: 'mathbot help').to respond_with_slack_message('See https://github.com/dblock/slack-mathbot, please.') | |||
end | |||
@ -1,6 +1,12 @@ | |||
require 'spec_helper' | |||
describe SlackMathbot::Commands::Hi do | |||
describe SlackRubyBot::Commands::Hi do | |||
def app | |||
SlackMathbot::App.new | |||
end | |||
before do | |||
app.config.user = 'mathbot' | |||
end | |||
it 'says hi' do | |||
expect(message: 'mathbot hi').to respond_with_slack_message('Hi <@user>!') | |||
end | |||
@ -1,11 +1,17 @@ | |||
require 'spec_helper' | |||
describe SlackMathbot::Commands::Unknown, vcr: { cassette_name: 'user_info' } do | |||
describe SlackRubyBot::Commands::Unknown, vcr: { cassette_name: 'user_info' } do | |||
def app | |||
SlackMathbot::App.new | |||
end | |||
before do | |||
app.config.user = 'mathbot' | |||
end | |||
it 'invalid command' do | |||
expect(message: 'mathbot foobar').to respond_with_slack_message("Sorry <@user>, I don't understand that command!") | |||
end | |||
it 'does not respond to sad face' do | |||
expect(SlackMathbot::Commands::Base).to_not receive(:send_message) | |||
expect(SlackRubyBot::Commands::Base).to_not receive(:send_message) | |||
SlackMathbot::App.new.send(:message, text: ':((') | |||
end | |||
end |
@ -1,12 +1,5 @@ | |||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..')) | |||
require 'rubygems' | |||
require 'rspec' | |||
require 'rack/test' | |||
require 'slack-ruby-bot/rspec' | |||
require 'config/environment' | |||
require 'slack-mathbot' | |||
Dir[File.join(File.dirname(__FILE__), 'support', '**/*.rb')].each do |file| | |||
require file | |||
end |
@ -1,31 +0,0 @@ | |||
require 'rspec/expectations' | |||
RSpec::Matchers.define :respond_with_error do |expected| | |||
match do |actual| | |||
channel, user, message = parse(actual) | |||
app = SlackMathbot::App.new | |||
SlackMathbot.config.user = 'mathbot' | |||
allow(Giphy).to receive(:random) | |||
begin | |||
expect do | |||
app.send(:message, text: message, channel: channel, user: user) | |||
end.to raise_error ArgumentError, expected | |||
rescue RSpec::Expectations::ExpectationNotMetError => e | |||
@error_message = e.message | |||
raise e | |||
end | |||
true | |||
end | |||
failure_message do |actual| | |||
_, _, message = parse(actual) | |||
@error_message || "expected for '#{message}' to fail with '#{expected}'" | |||
end | |||
private | |||
def parse(actual) | |||
actual = { message: actual } unless actual.is_a?(Hash) | |||
[actual[:channel] || 'channel', actual[:user] || 'user', actual[:message]] | |||
end | |||
end |
@ -1,20 +0,0 @@ | |||
require 'rspec/expectations' | |||
RSpec::Matchers.define :respond_with_slack_message do |expected| | |||
match do |actual| | |||
channel, user, message = parse(actual) | |||
app = SlackMathbot::App.new | |||
SlackMathbot.config.user = 'mathbot' | |||
allow(Giphy).to receive(:random) | |||
expect(SlackMathbot::Commands::Base).to receive(:send_message).with(channel, expected) | |||
app.send(:message, text: message, channel: channel, user: user) | |||
true | |||
end | |||
private | |||
def parse(actual) | |||
actual = { message: actual } unless actual.is_a?(Hash) | |||
[actual[:channel] || 'channel', actual[:user] || 'user', actual[:message]] | |||
end | |||
end |
@ -1,5 +0,0 @@ | |||
RSpec.configure do |config| | |||
config.before :all do | |||
ENV['SLACK_API_TOKEN'] ||= 'test' | |||
end | |||
end |
@ -1,4 +0,0 @@ | |||
SlackMathbot.configure do |config| | |||
config.token = 'testtoken' | |||
config.user = 'mathbot' | |||
end |
@ -1,8 +0,0 @@ | |||
require 'vcr' | |||
VCR.configure do |config| | |||
config.cassette_library_dir = 'spec/fixtures/slack' | |||
config.hook_into :webmock | |||
# config.default_cassette_options = { record: :new_episodes } | |||
config.configure_rspec_metadata! | |||
end |
@ -1,5 +1,3 @@ | |||
require File.expand_path('../config/environment', __FILE__) | |||
require 'sinatra/base' | |||
module SlackMathbot |