slatan 0.1.0

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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/CODE_OF_CONDUCT.md +13 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +59 -0
  9. data/Rakefile +26 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +6 -0
  12. data/lib/slatan/affiliation/channels.rb +36 -0
  13. data/lib/slatan/affiliation/self.rb +17 -0
  14. data/lib/slatan/affiliation/sub_teams.rb +17 -0
  15. data/lib/slatan/affiliation/team.rb +17 -0
  16. data/lib/slatan/affiliation/users.rb +54 -0
  17. data/lib/slatan/affiliation.rb +15 -0
  18. data/lib/slatan/buttocks.rb +75 -0
  19. data/lib/slatan/ear.rb +27 -0
  20. data/lib/slatan/heart.rb +88 -0
  21. data/lib/slatan/mouth/api.rb +19 -0
  22. data/lib/slatan/mouth/auth.rb +19 -0
  23. data/lib/slatan/mouth/channels.rb +57 -0
  24. data/lib/slatan/mouth/chat.rb +39 -0
  25. data/lib/slatan/mouth/emoji.rb +19 -0
  26. data/lib/slatan/mouth/ext/chat.rb +68 -0
  27. data/lib/slatan/mouth/ext.rb +10 -0
  28. data/lib/slatan/mouth/files.rb +19 -0
  29. data/lib/slatan/mouth/groups.rb +71 -0
  30. data/lib/slatan/mouth/im.rb +48 -0
  31. data/lib/slatan/mouth/mpim.rb +42 -0
  32. data/lib/slatan/mouth/pins.rb +28 -0
  33. data/lib/slatan/mouth/reactions.rb +38 -0
  34. data/lib/slatan/mouth/rtm.rb +19 -0
  35. data/lib/slatan/mouth/stars.rb +24 -0
  36. data/lib/slatan/mouth/team.rb +19 -0
  37. data/lib/slatan/mouth/users.rb +40 -0
  38. data/lib/slatan/mouth.rb +73 -0
  39. data/lib/slatan/spirit.rb +34 -0
  40. data/lib/slatan/template/concern.rb.erb +14 -0
  41. data/lib/slatan/utils/integer_ex.rb +17 -0
  42. data/lib/slatan/utils/string_ex.rb +11 -0
  43. data/lib/slatan/version.rb +3 -0
  44. data/lib/slatan.rb +44 -0
  45. data/slatan.gemspec +29 -0
  46. metadata +172 -0
@@ -0,0 +1,19 @@
1
+ module Slatan
2
+ module Mouth
3
+ module Emoji
4
+ @category = 'emoji'
5
+
6
+ class << self
7
+ ## @see https://api.slack.com/methods/emoji.list
8
+ def list(options={})
9
+ send('list', options)
10
+ end
11
+
12
+ private
13
+ def send(method, msg)
14
+ Mouth.send(@category, method, msg)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,68 @@
1
+ require 'slatan/affiliation'
2
+ require 'slatan/buttocks'
3
+
4
+ module Slatan
5
+ module Mouth
6
+ module Ext
7
+ module Chat
8
+ @category = 'chat'
9
+
10
+ class << self
11
+
12
+ # build postMessage to reply specific user
13
+ # @param user [string] name or id of user
14
+ # @param channel [string] channel id
15
+ # @param text [string] message
16
+ # @param options [hash] options
17
+ #
18
+ # @see https://api.slack.com/methods/chat.postMessage
19
+ def reply(user, channel, text, options={})
20
+ user = user.to_s if user.kind_of?(Symbol)
21
+ user_id = Affiliation::Users.is_id?(user) ? user : Affiliation::Users.get_id(user)
22
+ if user_id.nil?
23
+ Buttocks.error("user '#{user}' is not exist. (reply_message)")
24
+ return
25
+ end
26
+ reply_text = "<@#{user_id}>: #{text}"
27
+ send('postMessage', {
28
+ channel: channel,
29
+ text: reply_text
30
+ }.merge(options))
31
+ end
32
+
33
+ # build postMessage to reply specific multiple users
34
+ # @param users [array] name or id of users
35
+ # @param channel [string] channel id
36
+ # @param text [string] message
37
+ # @param options [hash] options
38
+ #
39
+ # @see https://api.slack.com/methods/chat.postMessage
40
+ def mreply(users, channel, text, options={})
41
+ user_ids = users.map do |user|
42
+ user = user.to_s if user.kind_of?(Symbol)
43
+ user_id = Affiliation::Users.is_id?(user) ? user : Affiliation::Users.get_id(user)
44
+ if user_id.nil?
45
+ Buttocks.error("user '#{user}' is not exist. (reply_message)")
46
+ end
47
+ user_id
48
+ end
49
+ user_ids = user_ids.compact.uniq
50
+ users_list = user_ids.reduce("") do |list, user_id|
51
+ "<@#{user_id}>: #{list}"
52
+ end
53
+ reply_text = "#{users_list}#{text}"
54
+ send('postMessage', {
55
+ channel: channel,
56
+ text: reply_text
57
+ }.merge(options))
58
+ end
59
+
60
+ private
61
+ def send(method, msg)
62
+ Mouth.send(@category, method, msg)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,10 @@
1
+ require 'slatan/mouth/ext/chat'
2
+
3
+ module Slatan
4
+ module Mouth
5
+ ## extension module of Slack API
6
+ module Ext
7
+ include Chat
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ module Slatan
2
+ module Mouth
3
+ module Files
4
+ @category = 'files'
5
+
6
+ class << self
7
+ ## @see https://api.slack.com/methods/files.upload
8
+ def upload(options={})
9
+ send('upload', options)
10
+ end
11
+
12
+ private
13
+ def send(method, msg)
14
+ Mouth.send(@category, method, msg)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,71 @@
1
+ module Slatan
2
+ module Mouth
3
+ module Groups
4
+ @category = 'groups'
5
+
6
+ class << self
7
+ ## @see https://api.slack.com/methods/groups.close
8
+ def close(channel, options={})
9
+ send('close', {
10
+ channel: channel
11
+ }.merge(options))
12
+ end
13
+
14
+ ## @see https://api.slack.com/methods/groups.history
15
+ def history(channel, options={})
16
+ send('history', {
17
+ channel: channel
18
+ }.merge(options))
19
+ end
20
+
21
+ ## @see https://api.slack.com/methods/groups.info
22
+ def info(channel, options={})
23
+ send('info', {
24
+ channel: channel
25
+ }.merge(options))
26
+ end
27
+
28
+ ## @see https://api.slack.com/methods/groups.list
29
+ def list(options={})
30
+ send('list', options)
31
+ end
32
+
33
+ ## @see https://api.slack.com/methods/groups.mark
34
+ def mark(channel, ts, options={})
35
+ send('mark', {
36
+ channel: channel,
37
+ ts: ts
38
+ }.merge(options))
39
+ end
40
+
41
+ ## @see https://api.slack.com/methods/groups.open
42
+ def open(channel, options={})
43
+ send('open', {
44
+ channel: channel
45
+ }.merge(options))
46
+ end
47
+
48
+ ## @see https://api.slack.com/methods/groups.setPurpose
49
+ def set_purpose(channel, purpose, options={})
50
+ send('setPurpose', {
51
+ channel: channel,
52
+ purpose: purpose
53
+ }.merge(options))
54
+ end
55
+
56
+ ## @see https://api.slack.com/methods/groups.setTopic
57
+ def set_topic(channel, topic, options={})
58
+ send('setTopic', {
59
+ channel: channel,
60
+ topic: topic
61
+ }.merge(options))
62
+ end
63
+
64
+ private
65
+ def send(method, msg)
66
+ Mouth.send(@category, method, msg)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,48 @@
1
+ module Slatan
2
+ module Mouth
3
+ module Im
4
+ @category = 'im'
5
+
6
+ class << self
7
+ ## @see https://api.slack.com/methods/im.close
8
+ def close(channel, options={})
9
+ send('close', {
10
+ channel: channel
11
+ }.merge(options))
12
+ end
13
+
14
+ ## @see https://api.slack.com/methods/im.history
15
+ def history(channel, options={})
16
+ send('history', {
17
+ channel: channel
18
+ }.merge(options))
19
+ end
20
+
21
+ ## @see https://api.slack.com/methods/im.list
22
+ def list(options={})
23
+ send('list', options)
24
+ end
25
+
26
+ ## @see https://api.slack.com/methods/im.mark
27
+ def mark(channel, ts, options={})
28
+ send('mark', {
29
+ channel: channel,
30
+ ts: ts
31
+ }.merge(options))
32
+ end
33
+
34
+ ## @see https://api.slack.com/methods/im.open
35
+ def open(user, options={})
36
+ send('open', {
37
+ user: user
38
+ }.merge(options))
39
+ end
40
+
41
+ private
42
+ def send(method, msg)
43
+ Mouth.send(@category, method, msg)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,42 @@
1
+ module Slatan
2
+ module Mouth
3
+ module Mpim
4
+ @category = 'mpim'
5
+
6
+ class << self
7
+ ## @see https://api.slack.com/methods/mpim.close
8
+ def close(channel, options={})
9
+ send('close', {
10
+ channel: channel
11
+ }.merge(options))
12
+ end
13
+
14
+ ## @see https://api.slack.com/methods/mpim.list
15
+ def list(options={})
16
+ send('list', options)
17
+ end
18
+
19
+ ## @see https://api.slack.com/methods/mpim.mark
20
+ def mark(channel, ts, options={})
21
+ send('mark', {
22
+ channel: channel,
23
+ ts: ts
24
+ }.merge(options))
25
+ end
26
+
27
+ ## @see https://api.slack.com/methods/mpim.open
28
+ # @param users array: array of user
29
+ def open(users, options={})
30
+ send('open', {
31
+ users: users.join(',')
32
+ }.merge(options))
33
+ end
34
+
35
+ private
36
+ def send(method, msg)
37
+ Mouth.send(@category, method, msg)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,28 @@
1
+ module Slatan
2
+ module Mouth
3
+ module Pins
4
+ @category = 'pins'
5
+
6
+ class << self
7
+ ## @see https://api.slack.com/methods/pins.add
8
+ def add(channel, options={})
9
+ send('add', {
10
+ channel: channel
11
+ }.merge(options))
12
+ end
13
+
14
+ ## @see https://api.slack.com/methods/pins.remove
15
+ def remove(channel, options={})
16
+ send('remove', {
17
+ channel: channel
18
+ }.merge(options))
19
+ end
20
+
21
+ private
22
+ def send(method, msg)
23
+ Mouth.send(@category, method, msg)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,38 @@
1
+ module Slatan
2
+ module Mouth
3
+ module Reactions
4
+ @category = 'reactions'
5
+
6
+ class << self
7
+ ## @see https://api.slack.com/methods/reactions.add
8
+ def add(name, options={})
9
+ send('add', {
10
+ name: name
11
+ }.merge(options))
12
+ end
13
+
14
+ ## @see https://api.slack.com/methods/reactions.get
15
+ def get(options={})
16
+ send('get', options)
17
+ end
18
+
19
+ ## @see https://api.slack.com/methods/reactions.list
20
+ def list(options={})
21
+ send('list', options)
22
+ end
23
+
24
+ ## @see https://api.slack.com/methods/reactions.remove
25
+ def remove(name, options={})
26
+ send('remove', {
27
+ name: name
28
+ }.merge(options))
29
+ end
30
+
31
+ private
32
+ def send(method, msg)
33
+ Mouth.send(@category, method, msg)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,19 @@
1
+ module Slatan
2
+ module Mouth
3
+ module Rtm
4
+ @category = 'rtm'
5
+
6
+ class << self
7
+ ## @see https://api.slack.com/methods/rtm.start
8
+ def start(options={})
9
+ send('start', options)
10
+ end
11
+
12
+ private
13
+ def send(method, msg)
14
+ Mouth.send(@category, method, msg)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ module Slatan
2
+ module Mouth
3
+ module Stars
4
+ @category = 'stars'
5
+
6
+ class << self
7
+ ## @see https://api.slack.com/methods/stars.add
8
+ def add(options={})
9
+ send('add', options)
10
+ end
11
+
12
+ ## @see https://api.slack.com/methods/stars.remove
13
+ def remove(options={})
14
+ send('remove', options)
15
+ end
16
+
17
+ private
18
+ def send(method, msg)
19
+ Mouth.send(@category, method, msg)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ module Slatan
2
+ module Mouth
3
+ module Team
4
+ @category = 'team'
5
+
6
+ class << self
7
+ ## @see https://api.slack.com/methods/team.info
8
+ def info(options={})
9
+ send('info', options)
10
+ end
11
+
12
+ private
13
+ def send(method, msg)
14
+ Mouth.send(@category, method, msg)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,40 @@
1
+ module Slatan
2
+ module Mouth
3
+ module Users
4
+ @category = 'users'
5
+
6
+ class << self
7
+ ## @see https://api.slack.com/methods/users.info
8
+ def info(user, options={})
9
+ send('info', {
10
+ user: user
11
+ }.merge(options))
12
+ end
13
+
14
+ ## @see https://api.slack.com/methods/users.list
15
+ def list(options={})
16
+ send('list', options)
17
+ end
18
+
19
+ ## @see https://api.slack.com/methods/users.getPresence
20
+ def get_presence(user, options={})
21
+ send('getPresence', {
22
+ user: user
23
+ }.merge(options))
24
+ end
25
+
26
+ ## @see https://api.slack.com/methods/users.setPresence
27
+ def set_presence(presence, options={})
28
+ send('setPresence', {
29
+ presence: presence
30
+ }.merge(options))
31
+ end
32
+
33
+ private
34
+ def send(method, msg)
35
+ Mouth.send(@category, method, msg)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,73 @@
1
+ require 'slatan/spirit'
2
+ require 'slatan/mouth/api'
3
+ require 'slatan/mouth/auth'
4
+ require 'slatan/mouth/channels'
5
+ require 'slatan/mouth/chat'
6
+ require 'slatan/mouth/emoji'
7
+ require 'slatan/mouth/files'
8
+ require 'slatan/mouth/groups'
9
+ require 'slatan/mouth/im'
10
+ require 'slatan/mouth/mpim'
11
+ require 'slatan/mouth/pins'
12
+ require 'slatan/mouth/reactions'
13
+ require 'slatan/mouth/rtm'
14
+ require 'slatan/mouth/stars'
15
+ require 'slatan/mouth/team'
16
+ require 'slatan/mouth/users'
17
+ require 'slatan/mouth/ext'
18
+ require 'slatan/buttocks'
19
+
20
+ require 'net/http'
21
+ require 'active_support/core_ext/object/try'
22
+ require 'json'
23
+
24
+ module Slatan
25
+ ## send and receive message to use Slack API
26
+ module Mouth
27
+ include Api
28
+ include Auth
29
+ include Channels
30
+ include Chat
31
+ include Emoji
32
+ include Files
33
+ include Groups
34
+ include Im
35
+ include Mpim
36
+ include Pins
37
+ include Reactions
38
+ include Rtm
39
+ include Stars
40
+ include Team
41
+ include Users
42
+ include Ext
43
+
44
+ class << self
45
+ def send(category, method, msg)
46
+ base_url = Spirit.slack_api_url
47
+
48
+ msg = {
49
+ as_user: true,
50
+ token: Spirit.slack_token
51
+ }.merge(msg)
52
+
53
+ uri = URI.parse("#{base_url}/#{category}.#{method}?#{URI.encode_www_form(msg)}")
54
+
55
+ Buttocks.debug("sent request: #{uri.request_uri}")
56
+
57
+ request = Net::HTTP::Post.new(uri.request_uri, {
58
+ 'Content-Type' =>'application/json'
59
+ })
60
+ http = Net::HTTP.new(uri.host, uri.port)
61
+ http.use_ssl = true
62
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
63
+ response = http.start do |h|
64
+ h.request(request)
65
+ end
66
+
67
+ body = JSON.parse(response.try(:body) || '{"ok":false, "error": " request body is empty."}', symbolize_names: true)
68
+ Buttocks.debug("received response: #{body}")
69
+ body
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,34 @@
1
+ require 'json'
2
+ require 'active_support/core_ext/object'
3
+
4
+ module Slatan
5
+ ## Class to retain configure for slatan
6
+ class Spirit
7
+ # about Slack
8
+ @slack_api_url = 'https://slack.com/api'
9
+ @slack_token = ENV['SLATAN_SLACK_TOKEN']
10
+
11
+ # about LOGGING
12
+ @log_file_path = '/tmp/slatan.log'
13
+ @log_level = 'debug'
14
+ @use_log = true
15
+
16
+ # about daemon
17
+ @pid_file_path = ENV['SLATAN_PID_FILE_PATH'].presence || '/tmp/slatan.pid'
18
+
19
+ # else
20
+ @ignore_bot_reply = true #be careful sending message loop if you set false.
21
+ @ignore_self_message = true #be careful sending message loop if you set false.
22
+
23
+ class << self
24
+ attr_accessor :slack_api_url,
25
+ :slack_token,
26
+ :log_file_path,
27
+ :log_level,
28
+ :use_log,
29
+ :pid_file_path,
30
+ :ignore_bot_reply,
31
+ :ignore_self_message
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,14 @@
1
+ require 'slatan'
2
+
3
+ class <%= class_name %>
4
+ def initialize
5
+ end
6
+
7
+ # this method receive message
8
+ def hear(msg)
9
+ # example
10
+ if msg[:type] == 'message' && msg[:text] == 'ping'
11
+ Slatan::Mouth::Chat.post_message(msg[:channel], 'pong')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ module Slatan
2
+ module Utils
3
+ module IntegerEx
4
+ refine Integer.singleton_class do
5
+ def max()
6
+ n_bytes = [42].pack('i').size
7
+ n_bits = n_bytes * 16
8
+ 2 ** (n_bits - 2) - 1
9
+ end
10
+
11
+ def min()
12
+ -(self.max()) - 1
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ module Slatan
2
+ module Utils
3
+ module StringEx
4
+ refine String do
5
+ def camelize
6
+ self.split(/_|\-/).map(&:capitalize).join
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Slatan
2
+ VERSION = "0.1.0"
3
+ end
data/lib/slatan.rb ADDED
@@ -0,0 +1,44 @@
1
+ require "slatan/version"
2
+ require "slatan/spirit"
3
+ require "slatan/heart"
4
+ require "slatan/mouth"
5
+ require "slatan/ear"
6
+ require "slatan/affiliation"
7
+ require "slatan/buttocks"
8
+
9
+ module Slatan
10
+ class << self
11
+ ## running slatan
12
+ # @param options
13
+ # daemonize: running on daemon mode(default false)
14
+ def run(options = {})
15
+ {
16
+ daemonize: false
17
+ }.merge(options)
18
+
19
+ Buttocks.init
20
+
21
+ @heart = Heart.new
22
+
23
+ begin
24
+ daemonize if options[:daemonize]
25
+ @heart.beat
26
+ rescue => e
27
+ Buttocks.fatal "#{e.backtrace.first}: #{e.message} (#{e.class})"
28
+ end
29
+ end
30
+
31
+ def daemonize
32
+ begin
33
+ Process.daemon
34
+
35
+ File.open(Spirit.pid_file_path, 'w') do |f|
36
+ f << Process.pid
37
+ end
38
+ rescue => e
39
+ Buttocks.fatal "failed to daemonize slatan.(#{e.message})"
40
+ exit
41
+ end
42
+ end
43
+ end
44
+ end
data/slatan.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'slatan/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "slatan"
8
+ spec.version = Slatan::VERSION
9
+ spec.authors = ["kudohamu"]
10
+ spec.email = ["kudohamu91086[a]gmail.com"]
11
+
12
+ spec.summary = %q{bot module for Slack}
13
+ spec.description = %q{Gem to create bot for Slack easily and flexibly.}
14
+ spec.homepage = "https://github.com/kudohamu/slatan"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "eventmachine"
23
+ spec.add_dependency "faye-websocket"
24
+ spec.add_dependency "activesupport"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.10"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rspec"
29
+ end