hipbot 1.0.0.rc2 → 1.0.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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.travis.yml +6 -0
  4. data/Gemfile +1 -2
  5. data/README.md +482 -88
  6. data/Rakefile +1 -1
  7. data/bin/hipbot +4 -4
  8. data/hipbot.gemspec +9 -9
  9. data/lib/hipbot.rb +28 -11
  10. data/lib/hipbot/adapter.rb +80 -0
  11. data/lib/hipbot/adapters/hipchat.rb +53 -0
  12. data/lib/hipbot/adapters/hipchat/initializer.rb +83 -0
  13. data/lib/hipbot/adapters/shell.rb +37 -0
  14. data/lib/hipbot/adapters/telnet.rb +41 -0
  15. data/lib/hipbot/bot.rb +15 -52
  16. data/lib/hipbot/cache.rb +23 -0
  17. data/lib/hipbot/callbacks/base.rb +15 -0
  18. data/lib/hipbot/callbacks/invite.rb +11 -0
  19. data/lib/hipbot/callbacks/lobby_presence.rb +13 -0
  20. data/lib/hipbot/callbacks/message.rb +11 -0
  21. data/lib/hipbot/callbacks/presence.rb +17 -0
  22. data/lib/hipbot/callbacks/private_message.rb +12 -0
  23. data/lib/hipbot/callbacks/room_message.rb +21 -0
  24. data/lib/hipbot/callbacks/room_presence.rb +28 -0
  25. data/lib/hipbot/configurable.rb +22 -0
  26. data/lib/hipbot/configuration.rb +9 -3
  27. data/lib/hipbot/helpers.rb +4 -40
  28. data/lib/hipbot/http.rb +65 -0
  29. data/lib/hipbot/match.rb +21 -9
  30. data/lib/hipbot/matchable.rb +38 -0
  31. data/lib/hipbot/message.rb +24 -9
  32. data/lib/hipbot/plugin.rb +3 -3
  33. data/lib/hipbot/reactable.rb +14 -21
  34. data/lib/hipbot/reaction.rb +27 -15
  35. data/lib/hipbot/reaction_factory.rb +38 -0
  36. data/lib/hipbot/response.rb +18 -10
  37. data/lib/hipbot/room.rb +34 -2
  38. data/lib/hipbot/storages/base.rb +78 -0
  39. data/lib/hipbot/storages/hash.rb +89 -0
  40. data/lib/hipbot/storages/mongoid.rb +18 -0
  41. data/lib/hipbot/user.rb +8 -2
  42. data/lib/hipbot/version.rb +1 -1
  43. data/spec/integration/my_hipbot.rb +24 -4
  44. data/spec/integration/{hipbot_spec.rb → my_hipbot_spec.rb} +41 -23
  45. data/spec/spec_helper.rb +14 -2
  46. data/spec/unit/adapters/hipchat_spec.rb +5 -0
  47. data/spec/unit/{hipbot_spec.rb → bot_spec.rb} +13 -12
  48. data/spec/unit/match_spec.rb +148 -0
  49. data/spec/unit/message_spec.rb +14 -7
  50. data/spec/unit/reaction_factory_spec.rb +54 -0
  51. data/spec/unit/reaction_spec.rb +99 -0
  52. data/spec/unit/storages/hash_spec.rb +75 -0
  53. data/spec/unit/user_spec.rb +0 -2
  54. metadata +64 -54
  55. data/Gemfile.lock +0 -90
  56. data/examples/cleverbot.rb +0 -23
  57. data/examples/google_images.rb +0 -35
  58. data/lib/hipbot/adapters/hipchat/connection.rb +0 -166
  59. data/lib/hipbot/adapters/hipchat/hipchat.rb +0 -13
  60. data/lib/hipbot/adapters/telnet/connection.rb +0 -17
  61. data/lib/hipbot/adapters/telnet/telnet.rb +0 -14
  62. data/lib/hipbot/collection.rb +0 -72
  63. data/lib/hipbot/patches/hipchat_client.rb +0 -230
@@ -11,10 +11,10 @@ module Hipbot
11
11
 
12
12
  attr_accessor :response
13
13
 
14
- delegate :sender, :recipients, :body, :room, :to => :response
15
- delegate :bot, :to => Hipbot
14
+ delegate :sender, :recipients, :body, :room, :reply, to: :response
15
+ delegate :bot, to: Hipbot
16
16
 
17
- Hipbot.plugins.prepend(self.instance)
17
+ Hipbot.plugins.unshift(self.instance)
18
18
  end
19
19
 
20
20
  module ClassMethods
@@ -1,17 +1,10 @@
1
1
  module Hipbot
2
2
  module Reactable
3
- def default *params, &block
4
- scope *params do
5
- default_reactions << to_reaction(block)
6
- end
7
- end
8
-
9
- def default_reactions
10
- @default_reactions ||= []
11
- end
3
+ include Cache
12
4
 
13
- def desc text = nil
14
- @description.tap{ @description = text }
5
+ attr_cache :reactions, :default_reactions, :options_stack
6
+ attr_cache :reaction_factory do
7
+ ReactionFactory.new(self)
15
8
  end
16
9
 
17
10
  def on *params, &block
@@ -20,26 +13,26 @@ module Hipbot
20
13
  end
21
14
  end
22
15
 
23
- def reactions
24
- @reactions ||= []
16
+ def default *params, &block
17
+ scope *params do
18
+ default_reactions << to_reaction(block)
19
+ end
25
20
  end
26
21
 
27
22
  def scope *params, &block
28
- options = params.last.kind_of?(Hash) ? params.pop : {}
29
- options_stack << options.merge({ regexps: params, desc: desc })
23
+ options_stack << reaction_factory.get_reaction_options(params)
30
24
  yield
31
25
  options_stack.pop
32
26
  end
33
27
 
28
+ def desc text
29
+ reaction_factory.description(text)
30
+ end
31
+
34
32
  protected
35
33
 
36
34
  def to_reaction block
37
- current_options = options_stack.inject{ |all, h| all.merge(h) }
38
- Reaction.new(self, current_options, block)
39
- end
40
-
41
- def options_stack
42
- @options_stack ||= []
35
+ reaction_factory.build(options_stack, block)
43
36
  end
44
37
  end
45
38
  end
@@ -1,23 +1,33 @@
1
1
  module Hipbot
2
2
  class Reaction < Struct.new(:plugin, :options, :block)
3
- def any_room?
3
+ include Cache
4
+
5
+ def in_any_room?
4
6
  options[:room] == true
5
7
  end
6
8
 
7
- def anything?
8
- regexps.blank?
9
+ def to_anything?
10
+ regexps.empty?
9
11
  end
10
12
 
11
- def anywhere?
13
+ def from_anywhere?
12
14
  options[:room].nil?
13
15
  end
14
16
 
17
+ def condition
18
+ options[:if] || Proc.new{ true }
19
+ end
20
+
21
+ def delete
22
+ plugin.reactions.delete(self)
23
+ end
24
+
15
25
  def desc
16
26
  options[:desc]
17
27
  end
18
28
 
19
29
  def from_all?
20
- options[:from].blank?
30
+ options[:from].nil?
21
31
  end
22
32
 
23
33
  def global?
@@ -36,30 +46,32 @@ module Hipbot
36
46
  Match.new(self, message)
37
47
  end
38
48
 
39
- def private_message_only?
49
+ def to_private_message?
40
50
  options[:room] == false
41
51
  end
42
52
 
43
- def readable_command
44
- regexps.to_s.gsub(/(?<!\\)(\/|\[|\]|\^|\\z|\$|\\)/, '')
53
+ attr_cache :readable_command do
54
+ regexps.map(&:source).join(' or ').gsub(/\^|\\z|\$|\\/, '')
45
55
  end
46
56
 
47
- def regexps
48
- options[:regexps]
57
+ attr_cache :regexps do
58
+ Array(options[:regexps]).map do |regexp|
59
+ Regexp.new(regexp.source, Regexp::IGNORECASE)
60
+ end
49
61
  end
50
62
 
51
- def rooms
52
- replace_symbols options[:room], Hipbot.rooms
63
+ attr_cache :rooms do
64
+ replace_symbols(options[:room], Hipbot.rooms)
53
65
  end
54
66
 
55
- def users
56
- replace_symbols options[:from], Hipbot.teams
67
+ attr_cache :users do
68
+ replace_symbols(options[:from], Hipbot.teams)
57
69
  end
58
70
 
59
71
  protected
60
72
 
61
73
  def replace_symbols values, replacements_hash
62
- Array(values).flat_map{ |v| replacements_hash[v].presence || v.to_s }
74
+ Array(values).flat_map{ |v| replacements_hash[v] || v }.uniq
63
75
  end
64
76
  end
65
77
  end
@@ -0,0 +1,38 @@
1
+ module Hipbot
2
+ class ReactionFactory < Struct.new(:reactable)
3
+ attr_reader :current_description
4
+ private :reactable, :current_description
5
+
6
+ def build(options_stack, block)
7
+ options = get_options(options_stack)
8
+ block ||= options.delete(:block)
9
+ @current_description = nil
10
+ Reaction.new(reactable, options, block)
11
+ end
12
+
13
+ def description(text)
14
+ @current_description = text
15
+ end
16
+
17
+ def get_reaction_options(params)
18
+ options = params.extract_options!
19
+ get_reaction_method_proc(params) do |block|
20
+ options[:block] = block
21
+ end
22
+ options[:regexps] = params if params.any?
23
+ options.merge(desc: current_description)
24
+ end
25
+
26
+ protected
27
+
28
+ def get_reaction_method_proc(params)
29
+ return unless params.last.kind_of?(Symbol)
30
+ method_name = params.pop
31
+ yield ->(*attributes){ plugin.send(method_name, *attributes) }
32
+ end
33
+
34
+ def get_options(stack)
35
+ stack.inject{ |all, h| all.merge(h) } || {}
36
+ end
37
+ end
38
+ end
@@ -2,23 +2,31 @@ module Hipbot
2
2
  class Response < Struct.new(:reaction, :message)
3
3
  include Helpers
4
4
 
5
- delegate :sender, :recipients, :body, :room, :to => :message
6
- delegate :bot, :to => Hipbot
5
+ delegate :sender, :room, to: :message
6
+ delegate :bot, to: Hipbot
7
+
8
+ def initialize *_
9
+ super
10
+ Hipbot.logger.info("RESPONSE WITH #{reaction.inspect}")
11
+ end
7
12
 
8
13
  def invoke arguments
9
- Hipbot.logger.info("REACTION #{reaction.inspect}")
10
- instance_exec(*arguments, &reaction.block)
11
- true
14
+ handle_errors do
15
+ instance_exec(*arguments, &reaction.block)
16
+ end
12
17
  rescue Exception => e
13
- Hipbot.logger.error(e)
14
- instance_exec(e, &Hipbot.error_handler)
15
- false
18
+ instance_exec(e, &Hipbot.exception_handler)
19
+ end
20
+
21
+ def reply message, room = self.room
22
+ (room || sender).send_message(message)
16
23
  end
17
24
 
18
25
  protected
19
26
 
20
- def reply message, room = self.room
21
- room.nil? ? Hipbot.send_to_user(sender, message) : Hipbot.send_to_room(room, message)
27
+ def handle_errors
28
+ error = catch(:error){ yield; false }
29
+ reply(error) if error
22
30
  end
23
31
 
24
32
  def method_missing method, *args, &block
@@ -1,5 +1,21 @@
1
1
  module Hipbot
2
2
  class Room
3
+ include Cache
4
+
5
+ attr_cache :users
6
+
7
+ def on_join user
8
+ self.users << user
9
+ end
10
+
11
+ def on_leave user
12
+ if user.myself?
13
+ self.destroy
14
+ else
15
+ self.users.delete(user)
16
+ end
17
+ end
18
+
3
19
  def set_topic topic
4
20
  Hipbot.set_topic(self, topic)
5
21
  end
@@ -8,8 +24,24 @@ module Hipbot
8
24
  Hipbot.send_to_room(self, message)
9
25
  end
10
26
 
11
- def users
12
- @users ||= []
27
+ def invite users
28
+ Hipbot.invite_to_room(self, users)
29
+ end
30
+
31
+ def kick users
32
+ Hipbot.kick_from_room(self, users)
33
+ end
34
+
35
+ def join
36
+ Hipbot.join_room(self)
37
+ end
38
+
39
+ def leave
40
+ Hipbot.leave_room(self)
41
+ end
42
+
43
+ def archived?
44
+ !!attributes[:archived]
13
45
  end
14
46
  end
15
47
  end
@@ -0,0 +1,78 @@
1
+ module Hipbot
2
+ module Storages
3
+ module Base
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ extend ClassMethods
8
+ alias_method :to_s, :name
9
+ end
10
+
11
+ def initialize attributes
12
+ raise NotImplementedError
13
+ end
14
+
15
+ def attributes
16
+ raise NotImplementedError
17
+ end
18
+
19
+ def destroy
20
+ raise NotImplementedError
21
+ end
22
+
23
+ def id
24
+ raise NotImplementedError
25
+ end
26
+
27
+ def name
28
+ raise NotImplementedError
29
+ end
30
+
31
+ def name= value
32
+ raise NotImplementedError
33
+ end
34
+
35
+ def update_attribute key, value
36
+ raise NotImplementedError
37
+ end
38
+
39
+ def update_attributes attributes
40
+ raise NotImplementedError
41
+ end
42
+
43
+ module ClassMethods
44
+ def all
45
+ raise NotImplementedError
46
+ end
47
+
48
+ def create attributes
49
+ raise NotImplementedError
50
+ end
51
+
52
+ def find id
53
+ raise NotImplementedError
54
+ end
55
+
56
+ def find_by attributes
57
+ raise NotImplementedError
58
+ end
59
+
60
+ def find_or_create_by attributes
61
+ raise NotImplementedError
62
+ end
63
+
64
+ def find_or_initialize_by attributes
65
+ raise NotImplementedError
66
+ end
67
+
68
+ def new attributes
69
+ raise NotImplementedError
70
+ end
71
+
72
+ def where attributes
73
+ raise NotImplementedError
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,89 @@
1
+ module Hipbot
2
+ module Storages
3
+ module Hash
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ extend ClassMethods
8
+
9
+ attr_accessor :attributes
10
+ alias_method :to_s, :name
11
+ end
12
+
13
+ def initialize params = {}
14
+ self.attributes = params.with_indifferent_access
15
+ end
16
+
17
+ def id
18
+ attributes[:id]
19
+ end
20
+
21
+ def name
22
+ attributes[:name]
23
+ end
24
+
25
+ def name= value
26
+ update_attribute(:name, value)
27
+ end
28
+
29
+ def update_attribute key, value
30
+ self.attributes[key] = value
31
+ end
32
+
33
+ def update_attributes hash
34
+ hash.each do |k, v|
35
+ update_attribute k, v
36
+ end
37
+ end
38
+
39
+ def destroy
40
+ self.class.collection.delete(id)
41
+ end
42
+
43
+ module ClassMethods
44
+ include Cache
45
+
46
+ def all
47
+ collection.values
48
+ end
49
+
50
+ def create params
51
+ collection[params[:id]] = new(params)
52
+ end
53
+
54
+ attr_cache :collection do
55
+ {}
56
+ end
57
+
58
+ def find_or_create_by params
59
+ find_by(params) || create(params)
60
+ end
61
+
62
+ def find_or_initialize_by params
63
+ find_by(params) || self.new(params)
64
+ end
65
+
66
+ def find_by params
67
+ where(params).first
68
+ end
69
+
70
+ def find id
71
+ where(id: id).first
72
+ end
73
+
74
+ def where param
75
+ collection.values.select do |item|
76
+ param.all?{ |k, v| item.attributes[k] == v }
77
+ end
78
+ end
79
+
80
+ # protected
81
+
82
+ # def method_missing name, *args, &block
83
+ # return all.public_send(name, *args, &block) if Array.instance_methods.include?(name)
84
+ # super
85
+ # end
86
+ end
87
+ end
88
+ end
89
+ end