ceiling_cat 0.0.2 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
1
  # General
2
- %w{version setup connection errors event user room plugins/base services/campfire storage/base storage/yaml}.each do |file|
2
+ %w{version setup connection errors event user room plugins/base services/campfire storage/base storage/hash storage/yaml}.each do |file|
3
3
  require "ceiling_cat/#{file}"
4
4
  end
@@ -23,7 +23,7 @@ module CeilingCat
23
23
  end
24
24
 
25
25
  def type # assume that all messages are just text unless the specific room type overrides it.
26
- :chat
26
+ @type || :chat
27
27
  end
28
28
  end
29
29
  end
@@ -53,7 +53,7 @@ module CeilingCat
53
53
  end
54
54
 
55
55
  def self.store
56
- CeilingCat::Setup.config.storage
56
+ CeilingCat::Setup.config ? CeilingCat::Setup.config.storage : CeilingCat::Storage::Hash
57
57
  end
58
58
 
59
59
  def body
@@ -3,11 +3,11 @@ module CeilingCat
3
3
  class CallAndResponse < CeilingCat::Plugin::Base
4
4
  def handle
5
5
  if event.type == :chat
6
- super
7
6
  if match = self.class.list.find{|car| body =~ Regexp.new(Regexp.escape(car[:call]),true) }
8
7
  reply match[:response]
9
8
  return nil
10
9
  end
10
+ super
11
11
  end
12
12
 
13
13
  end
@@ -43,7 +43,7 @@ module CeilingCat
43
43
  end
44
44
 
45
45
  def add
46
- message = body_without_nick_or_command("add call").split
46
+ message = body_without_nick_or_command("add call")
47
47
  call, response = message.split("|")
48
48
  if self.class.add(:call => call.strip,:response => response.strip)
49
49
  reply "Call and Response added."
@@ -67,7 +67,7 @@ module CeilingCat
67
67
  store["call_and_responses"] = (store["call_and_responses"] + [{:call => opts[:call], :response => opts[:response]}]).uniq
68
68
  end
69
69
 
70
- def self.remove(phrase)
70
+ def self.remove(call)
71
71
  store["call_and_responses"] ||= []
72
72
  store["call_and_responses"] = store["call_and_responses"].reject{|car| car[:call].downcase == call.downcase }
73
73
  end
@@ -12,7 +12,9 @@ module CeilingCat
12
12
  if room.connection.config.service.downcase == "campfire" && event.type == :entrance
13
13
  user_count = room.connection.total_user_count
14
14
  max_users = room.connection.config.max_users || 100
15
- room.plugin("notifo").new(@event).deliver("#{user_count} of #{max_users} max connections to Campfire.") if room.plugin_installed?("notifo") && user_count > max_users-2
15
+ if room.plugin_installed?("notifo") && user_count > max_users-2
16
+ room.plugin("notifo").new(@event).deliver("#{user_count} of #{max_users} max connections to Campfire.")
17
+ end
16
18
  end
17
19
  super
18
20
  end
@@ -1,6 +1,6 @@
1
1
  module CeilingCat
2
2
  class NotADateError < CeilingCatError; end
3
-
3
+
4
4
  module Plugin
5
5
  class Days < CeilingCat::Plugin::Base
6
6
  def self.commands
@@ -62,8 +62,7 @@ module CeilingCat
62
62
  end
63
63
  end
64
64
 
65
- store["holidays"] ||= []
66
- store["holidays"] = (store["holidays"] + dates).uniq
65
+ store["holidays"] = (holidays + dates).uniq
67
66
  end
68
67
 
69
68
  def self.remove_from_holidays(days)
@@ -75,13 +74,12 @@ module CeilingCat
75
74
  end
76
75
  end
77
76
 
78
- store["holidays"] ||= []
79
- store["holidays"] = store["holidays"] - dates
77
+ store["holidays"] = holidays - dates
80
78
  end
81
79
 
82
80
  def self.is_a_holiday?(date=Date.today)
83
81
  if is_a_date?(date)
84
- store["holidays"].include? Date.parse(date.to_s)
82
+ holidays.include? Date.parse(date.to_s)
85
83
  else
86
84
  raise NotADateError
87
85
  end
@@ -2,7 +2,7 @@ module CeilingCat
2
2
  module Plugin
3
3
  class Greeter < CeilingCat::Plugin::Base
4
4
  def handle
5
- message = []
5
+ messages = []
6
6
 
7
7
  if event.type == :entrance
8
8
  members = room.users_in_room(:type => "member")
@@ -12,7 +12,7 @@ module CeilingCat
12
12
  elsif user.is_registered?
13
13
  messages << "Nice to see you again #{user.name}"
14
14
  end
15
- reply message unless message.empty?
15
+ reply messages unless messages.empty?
16
16
  elsif event.type == :chat
17
17
  super
18
18
  end
@@ -18,14 +18,19 @@ module CeilingCat
18
18
  :body => { :to => user, :msg => message },
19
19
  :basic_auth => {:username => store["notifo_credentials"][:username], :password => store["notifo_credentials"][:api_secret]})
20
20
  end
21
- else
22
- debugger
23
- puts "here"
24
21
  end
25
22
  end
26
23
 
24
+ def self.active?
25
+ if store["notifo_credentials"] && store["notifo_credentials"][:username].present? && store["notifo_credentials"][:api_secret].present? && Array(store["notifo_users"]).size > 0
26
+ true
27
+ else
28
+ false
29
+ end
30
+ end
31
+
27
32
  def active?
28
- store["notifo_credentials"] && store["notifo_credentials"][:username].present? && store["notifo_credentials"][:api_secret].present? && Array(store["notifo_users"]).size > 0
33
+ self.class.active?
29
34
  end
30
35
 
31
36
  def self.name
@@ -40,6 +45,11 @@ module CeilingCat
40
45
  store["notifo_users"] ||= []
41
46
  store["notifo_users"] = (Array(store["notifo_users"]) + Array(users)).uniq
42
47
  end
48
+
49
+ def self.remove_users(users)
50
+ store["notifo_users"] ||= []
51
+ store["notifo_users"] = (Array(store["notifo_users"]) - Array(users)).uniq
52
+ end
43
53
 
44
54
  def self.set_credentials(username, api_secret)
45
55
  store["notifo_credentials"] = {:username => username, :api_secret => api_secret}
@@ -53,8 +63,7 @@ module CeilingCat
53
63
 
54
64
  def remove_users
55
65
  users = body_without_nick_or_command("remove notifo users").split(" ")
56
- store["notifo_users"] ||= []
57
- store["notifo_users"] = store["notifo_users"] - users
66
+ self.class.remove_users(users)
58
67
  reply "#{users.join(" ")} removed from notifo alerts."
59
68
  end
60
69
 
@@ -43,10 +43,6 @@ module CeilingCat
43
43
  @connection.storage
44
44
  end
45
45
 
46
- def debug_mode?
47
- !store["debug_mode"].nil? && store["debug_mode"] == "true"
48
- end
49
-
50
46
  def plugin_descriptions(show_private=false)
51
47
  messages = []
52
48
  plugins.each do |plugin|
@@ -4,7 +4,7 @@ module CeilingCat
4
4
  module Campfire
5
5
  class Connection < CeilingCat::Connection
6
6
  def initialize(config)
7
- @config=config
7
+ super
8
8
  @config.ssl ||= "true"
9
9
  end
10
10
 
@@ -4,11 +4,11 @@ module CeilingCat
4
4
 
5
5
  def type
6
6
  case @type
7
- when "EnterMessage"
7
+ when "EnterMessage", :entrance
8
8
  :entrance
9
- when "TextMessage"
9
+ when "TextMessage", :chat
10
10
  :chat
11
- when "LeaveMessage", "KickMessage"
11
+ when "LeaveMessage", "KickMessage", :exit
12
12
  :exit
13
13
  end
14
14
  end
@@ -1,24 +1,25 @@
1
1
  module CeilingCat
2
2
  module Campfire
3
3
  class Room < CeilingCat::Room
4
+ attr_accessor :campfire_room
4
5
 
5
6
  def initialize(opts={})
6
7
  super
7
8
  @campfire_room = @connection.campfire.find_room_by_name(opts[:room_name])
8
9
  end
9
-
10
+
10
11
  def watch
11
12
  puts "Watching room..."
12
13
  setup_interrupts
13
14
  begin
14
15
  loop do
15
16
  begin
16
- Timeout::timeout(60) do
17
+ Timeout::timeout(300) do
17
18
  @campfire_room.listen do |event|
18
19
  begin
19
20
  if event[:type] != "TimestampMessage"
20
21
  user = CeilingCat::User.new(event[:user][:name], :id => event[:user][:id], :role => event[:user][:type])
21
-
22
+
22
23
  unless is_me?(user) # Otherwise CC will talk to itself
23
24
  event = CeilingCat::Campfire::Event.new(self,event[:body], user, :type => event[:type])
24
25
  event.handle
@@ -26,19 +27,20 @@ module CeilingCat
26
27
  end
27
28
  end
28
29
  rescue => e
29
- say "An error occurred with Campfire: #{e}" if debug_mode?
30
30
  raise e
31
31
  end
32
32
  end
33
33
  end
34
34
  rescue Timeout::Error
35
- puts "timeout! trying again..."
36
- retry
35
+ retry # Reconnect regularly to keep CC talking with Campfire
37
36
  end
38
37
  end
39
38
  rescue Faraday::Error::ParsingError
40
39
  puts "Error parsing response. Campfire may be down."
41
40
  break
41
+ rescue HTTP::Parser::Error
42
+ puts "Trouble parsing the HTTP response."
43
+ retry
42
44
  rescue ReloadException => e
43
45
  retry
44
46
  rescue NoMethodError => e
@@ -49,22 +51,21 @@ module CeilingCat
49
51
  retry
50
52
  rescue StandardError => e
51
53
  puts e.class
52
- debugger if debug_mode?
53
54
  e.backtrace.each do |line|
54
55
  puts "Backtrace: #{line}"
55
56
  end
56
57
  retry
57
58
  end
58
59
  end
59
-
60
+
60
61
  def is_me?(user)
61
62
  user.id == me.id
62
63
  end
63
-
64
+
64
65
  def me
65
66
  @me ||= CeilingCat::User.new(@connection.campfire.me[:name], :id => @connection.campfire.me[:id], :role => @connection.campfire.me[:type])
66
67
  end
67
-
68
+
68
69
  def users_in_room(opts={})
69
70
  if opts[:reload] || @users_in_room.nil?
70
71
  puts "Requesting user list"
@@ -83,13 +84,13 @@ module CeilingCat
83
84
  end
84
85
  end
85
86
  end
86
-
87
+
87
88
  def say(something_to_say)
88
89
  Array(something_to_say).each do |line|
89
90
  @campfire_room.speak(line)
90
91
  end
91
92
  end
92
-
93
+
93
94
  def setup_interrupts
94
95
  trap('INT') do
95
96
  puts "Leaving room...."
@@ -0,0 +1,29 @@
1
+ module CeilingCat
2
+ module Storage
3
+ class Hash < CeilingCat::Storage::Base
4
+ class << self
5
+
6
+ # Stores +v+ in the hash.
7
+ def []=(k, v)
8
+ internal[k] = v
9
+ end
10
+
11
+ # Returns the value at key +k+.
12
+ def [](k)
13
+ internal[k]
14
+ end
15
+
16
+ private
17
+ # The hash the data is being stored in.
18
+ def internal
19
+ @internal ||= {}
20
+ end
21
+
22
+ def clear
23
+ @internal = nil
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module CeilingCat
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -4,20 +4,25 @@ namespace :plugin do
4
4
  raise "You need to set a name! `rake plugin:create name=[plugin_name]`" unless ENV["name"]
5
5
  name = ENV["name"].downcase
6
6
  file = File.join("plugins", "#{name}.rb")
7
+ test_file = File.join("spec", "plugins", "#{name}_spec.rb")
7
8
 
8
- unless File.exists? file
9
- contents = plugin_base(name)
10
- File.open(file, 'w') {|f| f.write(contents) }
11
- puts "Plugin '#{name}' created at #{file}."
12
- puts "Make sure you require it in your Chatfile and add it to your config.plugins so it runs."
13
- else
14
- puts "A plugin named '#{name}' already exists. Try another name."
9
+ unless File.exists?(file) || File.exists?(test_file)
10
+ contents = plugin_base(name)
11
+ File.open(file, 'w') {|f| f.write(contents) }
12
+
13
+ test_contents = plugin_test_base(name).gsub('\#','#')
14
+ File.open(test_file, 'w') {|f| f.write(test_contents) }
15
+
16
+ puts "Plugin '#{name}' created at #{file}."
17
+ puts "Make sure you require it in your Chatfile and add it to your config.plugins so it runs."
18
+ else
19
+ puts "A plugin named '#{name}' already exists. Try another name."
20
+ end
15
21
  end
16
22
  end
17
- end
18
23
 
19
- def plugin_base(name)
20
- %Q{module CeilingCat
24
+ def plugin_base(name)
25
+ %Q{module CeilingCat
21
26
  module Plugin
22
27
  class #{name.camelize} < CeilingCat::Plugin::Base
23
28
  # See lib/ceiling_cat/plugins/base.rb for the methods available by default.
@@ -56,6 +61,84 @@ def plugin_base(name)
56
61
  end
57
62
  end
58
63
  }
64
+ end
65
+
66
+ def plugin_test_base(name)
67
+ %Q{require 'plugins/#{name}'
68
+
69
+ describe "#{name.camelize}" do
70
+ before(:each) do
71
+ CeilingCat::Storage::Hash.send "clear" # Clear the calls and response each time.
72
+
73
+ user = "user"
74
+ token = "1234abcd"
75
+ plugins = [CeilingCat::Plugin::#{name.camelize}]
76
+
77
+ FakeWeb.register_uri(:get, "https://\#{token}:X@\#{user}.campfirenow.com/rooms.json", :body => fixture('campfire/rooms.json'), :status => ["200"])
78
+ FakeWeb.register_uri(:get, "https://\#{token}:X@\#{user}.campfirenow.com/users/me.json", :body => fixture('campfire/me.json'), :status => ["200"])
79
+
80
+ @connection = CeilingCat::Campfire::Connection.new(OpenStruct.new({:service => 'campfire', :username => user, :token => token, :room => 'Room 1', :plugins => plugins}))
81
+ @room = CeilingCat::Campfire::Room.new(:connection => @connection, :room_name => @connection.config.room)
82
+ end
83
+
84
+ describe "base methods" do
85
+ # Tests for any methods that run outside of a command
86
+ end
87
+
88
+ describe "commands" do
89
+ # Tests for commands
90
+ describe "from a guest user" do
91
+ before(:each) do
92
+ @guest_user = CeilingCat::User.new("Guest", :id => 12345, :role => "guest")
93
+ end
94
+
95
+ describe "calling the 'default' command" do
96
+ it "should not do or say anything" do
97
+ event = CeilingCat::Event.new(@room,"!#{name}", @guest_user)
98
+ @room.should_not_receive(:say)
99
+ CeilingCat::Plugin::#{name.camelize}.new(event).handle
100
+ end
101
+ end
102
+ end
103
+
104
+ describe "from a registered user" do
105
+ before(:each) do
106
+ @registered_user = CeilingCat::User.new("Guest", :id => 12345, :role => "member")
107
+ end
108
+
109
+ describe "calling the 'default' command" do
110
+ it "should call the 'default' method" do
111
+ event = CeilingCat::Event.new(@room,"!#{name}", @registered_user)
112
+ @room.should_receive(:say).with("You've created the '#{name.capitalize}' plugin. Now make it do something awesome!")
113
+ CeilingCat::Plugin::#{name.camelize}.new(event).handle
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ describe 'entrance and exit' do
120
+ # Tests for things to run when a user enters or exits the room
121
+ describe "entering the room" do
122
+ before(:each) do
123
+ @registered_user = CeilingCat::User.new("Guest", :id => 12345, :role => "member", :type => :entrance)
124
+ end
125
+
126
+ it "should do something" do
127
+ end
128
+ end
129
+
130
+ describe "exiting the room" do
131
+ before(:each) do
132
+ @registered_user = CeilingCat::User.new("Guest", :id => 12345, :role => "member", :type => :exit)
133
+ end
134
+
135
+ it "should do something" do
136
+ end
137
+ end
138
+ end
139
+ end
140
+ }
141
+ end
59
142
  end
60
143
 
61
144
  class String
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ceiling_cat
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 6
10
+ version: 0.0.6
11
11
  platform: ruby
12
12
  authors:
13
13
  - Chris Warren
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-18 00:00:00 Z
18
+ date: 2011-08-25 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: tinder
@@ -65,6 +65,50 @@ dependencies:
65
65
  version: 0.1.8
66
66
  type: :runtime
67
67
  version_requirements: *id003
68
+ - !ruby/object:Gem::Dependency
69
+ name: rspec
70
+ prerelease: false
71
+ requirement: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - "="
75
+ - !ruby/object:Gem::Version
76
+ hash: 23
77
+ segments:
78
+ - 2
79
+ - 6
80
+ - 0
81
+ version: 2.6.0
82
+ type: :development
83
+ version_requirements: *id004
84
+ - !ruby/object:Gem::Dependency
85
+ name: ruby-debug
86
+ prerelease: false
87
+ requirement: &id005 !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ type: :development
97
+ version_requirements: *id005
98
+ - !ruby/object:Gem::Dependency
99
+ name: fakeweb
100
+ prerelease: false
101
+ requirement: &id006 !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ hash: 3
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ type: :development
111
+ version_requirements: *id006
68
112
  description: Ceiling Cat is watching you chat. A Campfire chat bot!
69
113
  email:
70
114
  - chris@zencoder.com
@@ -92,9 +136,9 @@ files:
92
136
  - lib/ceiling_cat/plugins/call_and_response.rb
93
137
  - lib/ceiling_cat/plugins/campfire_account_monitor.rb
94
138
  - lib/ceiling_cat/plugins/days.rb
95
- - lib/ceiling_cat/plugins/general.rb
96
139
  - lib/ceiling_cat/plugins/greeter.rb
97
140
  - lib/ceiling_cat/plugins/notifo.rb
141
+ - lib/ceiling_cat/storage/hash.rb
98
142
  - lib/ceiling_cat/storage/yaml.rb
99
143
  - lib/ceiling_cat/services/campfire.rb
100
144
  - lib/ceiling_cat/services/campfire/connection.rb
@@ -104,7 +148,7 @@ files:
104
148
  homepage: http://zencoder.com
105
149
  licenses: []
106
150
 
107
- post_install_message: " ********************************************************************************\n Run `ceiling_cat setup` to create a Chatfile and a Rakefile - everything you\n need to start watching your chats and making ceiling_cat do your bidding!\n \n Run `rake plugin:create name=plugin_name` to generate a new plugin.\n\n Update your Chatfile with your credentials and you'll be ready to go!\n ********************************************************************************\n"
151
+ post_install_message: " ********************************************************************************\n Run `ceiling_cat setup` to create a Chatfile and a Rakefile - everything you\n need to start watching your chats and making ceiling_cat do your bidding!\n\n Update your Chatfile with your credentials and you'll be ready to go!\n\n Want Ceiling Cat to do something special just for you?\n Run `rake plugin:create name=plugin_name` to generate a new plugin.\n ********************************************************************************\n"
108
152
  rdoc_options: []
109
153
 
110
154
  require_paths:
@@ -1,56 +0,0 @@
1
- module CeilingCat
2
- module Plugin
3
- class General < CeilingCat::Plugin::Base
4
- # See lib/ceiling_cat/plugins/base.rb for the methods available by default.
5
- # Plugins are run in the order they are listed in the Chatfile.
6
- # When a plugin returns anything other than nil the plugin execution chain is halted.
7
- # If you want your plugin to do something but let the remaining plugins execute, return nil at the end of your method.
8
-
9
- # handle manages a plugin's entire interaction with an event.
10
- # If you only want to execute commands - "![command]" - leave handle alone (or remove it and define commands below)
11
- def handle
12
- super
13
- end
14
-
15
- # If you want the plugin to run when certain text is sent use commands instead of handle.
16
- # Ceiling Cat will watch for "![command]" or "[name]: [command" and execute the method for that command.
17
- def self.commands
18
- [{:command => "debugger", :description => "Load the debugger", :method => "run_debug", :public => false},
19
- {:command => "enable debug", :description => "Enable debuggers", :method => "enable_debug", :public => false},
20
- {:command => "disable debug", :description => "Disable debuggers", :method => "disable_debug", :public => false}]
21
- end
22
-
23
- def self.description
24
- "General tasks for development"
25
- end
26
-
27
- def self.name
28
- "General"
29
- end
30
-
31
- def self.public?
32
- false
33
- end
34
-
35
- def run_debug
36
- if room.debug_mode?
37
- reply "Opening debugger in terminal"
38
- debugger
39
- else
40
- reply "Debugging is disabled - !enable debug to activate it."
41
- end
42
- end
43
-
44
- def enable_debug
45
- store["debug_mode"] ||= "true"
46
- reply "debugging enabled"
47
- end
48
-
49
- def disable_debug
50
- store["debug_mode"] ||= "false"
51
- reply "debugging disabled"
52
- end
53
- end
54
- end
55
- end
56
-