scamp 1.2.0 → 2.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,29 @@
1
+ require 'simplecov'
2
+
3
+ SimpleCov.start do
4
+ add_filter "/spec/"
5
+ end
6
+
1
7
  require File.expand_path("../lib/scamp", File.dirname(__FILE__))
8
+ require File.expand_path("../lib/scamp/adapter", File.dirname(__FILE__))
9
+ require File.expand_path("../lib/scamp/message", File.dirname(__FILE__))
2
10
 
11
+ require 'mocha'
3
12
  require 'webmock/rspec'
4
13
 
5
14
  RSpec.configure do |config|
6
15
  config.mock_framework = :mocha
7
- end
16
+ end
17
+
18
+
19
+ class RspecAdapter < Scamp::Adapter
20
+ class Context;end
21
+
22
+ def speak! msg
23
+ push [Context.new, Scamp::Message.new(self, :body => msg)]
24
+ end
25
+
26
+ def connect!
27
+ # noop!
28
+ end
29
+ end
metadata CHANGED
@@ -1,136 +1,128 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scamp
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Will Jessop
8
+ - Adam Holt
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-10-11 00:00:00.000000000 Z
12
+ date: 2014-02-19 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: eventmachine
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - ~>
18
+ - - "~>"
18
19
  - !ruby/object:Gem::Version
19
- version: 1.0.0.rc.4
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ~>
25
- - !ruby/object:Gem::Version
26
- version: 1.0.0.rc.4
27
- - !ruby/object:Gem::Dependency
28
- name: yajl-ruby
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ~>
32
- - !ruby/object:Gem::Version
33
- version: '1.1'
20
+ version: '1.0'
34
21
  type: :runtime
35
22
  prerelease: false
36
23
  version_requirements: !ruby/object:Gem::Requirement
37
24
  requirements:
38
- - - ~>
25
+ - - "~>"
39
26
  - !ruby/object:Gem::Version
40
- version: '1.1'
27
+ version: '1.0'
41
28
  - !ruby/object:Gem::Dependency
42
- name: em-http-request
29
+ name: rake
43
30
  requirement: !ruby/object:Gem::Requirement
44
31
  requirements:
45
- - - ~>
32
+ - - ">="
46
33
  - !ruby/object:Gem::Version
47
- version: '1.0'
48
- type: :runtime
34
+ version: '0'
35
+ type: :development
49
36
  prerelease: false
50
37
  version_requirements: !ruby/object:Gem::Requirement
51
38
  requirements:
52
- - - ~>
39
+ - - ">="
53
40
  - !ruby/object:Gem::Version
54
- version: '1.0'
41
+ version: '0'
55
42
  - !ruby/object:Gem::Dependency
56
- name: rake
43
+ name: rspec
57
44
  requirement: !ruby/object:Gem::Requirement
58
45
  requirements:
59
- - - ~>
46
+ - - "~>"
60
47
  - !ruby/object:Gem::Version
61
- version: '0.9'
48
+ version: '2.11'
62
49
  type: :development
63
50
  prerelease: false
64
51
  version_requirements: !ruby/object:Gem::Requirement
65
52
  requirements:
66
- - - ~>
53
+ - - "~>"
67
54
  - !ruby/object:Gem::Version
68
- version: '0.9'
55
+ version: '2.11'
69
56
  - !ruby/object:Gem::Dependency
70
- name: rspec
57
+ name: mocha
71
58
  requirement: !ruby/object:Gem::Requirement
72
59
  requirements:
73
- - - ~>
60
+ - - "~>"
74
61
  - !ruby/object:Gem::Version
75
- version: '2.6'
62
+ version: '0.12'
76
63
  type: :development
77
64
  prerelease: false
78
65
  version_requirements: !ruby/object:Gem::Requirement
79
66
  requirements:
80
- - - ~>
67
+ - - "~>"
81
68
  - !ruby/object:Gem::Version
82
- version: '2.6'
69
+ version: '0.12'
83
70
  - !ruby/object:Gem::Dependency
84
- name: mocha
71
+ name: webmock
85
72
  requirement: !ruby/object:Gem::Requirement
86
73
  requirements:
87
- - - ~>
74
+ - - "~>"
88
75
  - !ruby/object:Gem::Version
89
- version: '0.10'
76
+ version: '1.8'
90
77
  type: :development
91
78
  prerelease: false
92
79
  version_requirements: !ruby/object:Gem::Requirement
93
80
  requirements:
94
- - - ~>
81
+ - - "~>"
95
82
  - !ruby/object:Gem::Version
96
- version: '0.10'
83
+ version: '1.8'
97
84
  - !ruby/object:Gem::Dependency
98
- name: webmock
85
+ name: simplecov
99
86
  requirement: !ruby/object:Gem::Requirement
100
87
  requirements:
101
- - - ~>
88
+ - - ">="
102
89
  - !ruby/object:Gem::Version
103
- version: '1.7'
90
+ version: '0'
104
91
  type: :development
105
92
  prerelease: false
106
93
  version_requirements: !ruby/object:Gem::Requirement
107
94
  requirements:
108
- - - ~>
95
+ - - ">="
109
96
  - !ruby/object:Gem::Version
110
- version: '1.7'
97
+ version: '0'
111
98
  description: Eventmachine based Campfire bot framework
112
99
  email:
113
100
  - will@willj.net
101
+ - me@adamholt.co.uk
114
102
  executables: []
115
103
  extensions: []
116
104
  extra_rdoc_files: []
117
105
  files:
118
- - .gitignore
119
- - .rspec
106
+ - ".gitignore"
107
+ - ".rspec"
120
108
  - Gemfile
121
109
  - LICENSE.md
122
110
  - README.md
123
111
  - Rakefile
124
- - examples/bot.rb
112
+ - examples/v2.rb
125
113
  - lib/scamp.rb
126
- - lib/scamp/action.rb
127
- - lib/scamp/connection.rb
114
+ - lib/scamp/adapter.rb
128
115
  - lib/scamp/matcher.rb
129
- - lib/scamp/messages.rb
130
- - lib/scamp/rooms.rb
131
- - lib/scamp/users.rb
116
+ - lib/scamp/matches.rb
117
+ - lib/scamp/message.rb
118
+ - lib/scamp/plugin.rb
132
119
  - lib/scamp/version.rb
133
120
  - scamp.gemspec
121
+ - spec/lib/adapter_spec.rb
122
+ - spec/lib/matcher_spec.rb
123
+ - spec/lib/matches_spec.rb
124
+ - spec/lib/message_spec.rb
125
+ - spec/lib/plugin_spec.rb
134
126
  - spec/lib/scamp_spec.rb
135
127
  - spec/spec_helper.rb
136
128
  homepage: https://github.com/wjessop/Scamp
@@ -142,20 +134,25 @@ require_paths:
142
134
  - lib
143
135
  required_ruby_version: !ruby/object:Gem::Requirement
144
136
  requirements:
145
- - - '>='
137
+ - - ">="
146
138
  - !ruby/object:Gem::Version
147
139
  version: '0'
148
140
  required_rubygems_version: !ruby/object:Gem::Requirement
149
141
  requirements:
150
- - - '>='
142
+ - - ">"
151
143
  - !ruby/object:Gem::Version
152
- version: '0'
144
+ version: 1.3.1
153
145
  requirements: []
154
146
  rubyforge_project:
155
- rubygems_version: 2.0.5
147
+ rubygems_version: 2.2.1
156
148
  signing_key:
157
149
  specification_version: 4
158
150
  summary: Eventmachine based Campfire bot framework
159
151
  test_files:
152
+ - spec/lib/adapter_spec.rb
153
+ - spec/lib/matcher_spec.rb
154
+ - spec/lib/matches_spec.rb
155
+ - spec/lib/message_spec.rb
156
+ - spec/lib/plugin_spec.rb
160
157
  - spec/lib/scamp_spec.rb
161
158
  - spec/spec_helper.rb
data/examples/bot.rb DELETED
@@ -1,72 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $:.unshift File.join(File.dirname(__FILE__), '../lib')
4
-
5
- require 'scamp'
6
-
7
- scamp = Scamp.new(:api_key => "YOUR API KEY", :subdomain => "37s")
8
-
9
- scamp.behaviour do
10
- # Match some regex limited to a room condition based on a room id
11
- match /^room id (.+)$/, :conditions => {:room => 401839} do
12
- # Reply in the current room
13
- say "Match some regex limited to a room condition based on a room id"
14
- end
15
-
16
- # Limit a match to a room condition based on a string
17
- match "room name check", :conditions => {:room => "Monitoring"} do
18
- say "Limit a match to a room condition based on a string"
19
- end
20
-
21
- # Limit a match to a user condition based on a string
22
- match /^user name (.+)$/, :conditions => {:user => "Will Jessop"} do
23
- say "Limit a match to a user condition based on a string"
24
- end
25
-
26
- # Limit a match to a user condition based on a string
27
- match "user id check", :conditions => {:user => 774016} do
28
- say "Limit a match to a user condition based on an ID"
29
- end
30
-
31
- # Limit a match to a room & user condition combined
32
- match /^something (.+)$/, :conditions => {:room => "Monitoring", :user => "Will Jessop"} do
33
- # Reply in the current room
34
- say "Limit a match to a room & user condition combined"
35
- end
36
-
37
- # Match text with a regex, access the captures from the match object
38
- match /^repeat (\w+), (\w+)$/ do
39
- say "You said #{matches[0]} and #{matches[1]}"
40
- end
41
-
42
- # Match text with a regex, access the named captures as a method
43
- match /^say (?<yousaid>.+)$/ do
44
- say "You said #{yousaid}"
45
- end
46
-
47
- # Simple string match, interpolating the room and user in response.
48
- match "something" do |data|
49
- # Send the response to a different room
50
- say "#{user} said something in room #{room}", "Robot Army"
51
-
52
- # Send the response to a different room, using the room ID
53
- say "#{user} said something in room #{room}", 293788
54
-
55
- # Send the response to the originating room
56
- say "#{user} said something in room #{room}"
57
- end
58
-
59
- # Play some sounds
60
- match "ohmy" do
61
- play "yeah"
62
- play "drama"
63
- end
64
-
65
- match "multi-condition match", :conditions => {:room => [401839, "Monitoring"], :user => ["Will Jessop", "Noah Lorang"]} do
66
- # Reply in the current room
67
- say "multi-condition match"
68
- end
69
- end
70
-
71
- # FIXME: this does if the room doesn't exist. Need a better error.
72
- scamp.connect!([293788, "Monitoring"])
data/lib/scamp/action.rb DELETED
@@ -1,70 +0,0 @@
1
- #
2
- # Actions are run in the context of a Scamp::Action.
3
- # This allows us to make room, user etc. methods
4
- # available on a per-message basis
5
- #
6
-
7
- # {:room_id=>401839, :created_at=>"2011/09/10 00:23:19 +0000", :body=>"something", :id=>408089344, :user_id=>774016, :type=>"TextMessage"}
8
-
9
- class Scamp
10
- class Action
11
-
12
- attr_accessor :matches, :bot
13
-
14
- def initialize(bot, action, message)
15
- @bot = bot
16
- @action = action
17
- @message = message
18
- end
19
-
20
- def matches=(match)
21
- @matches = match[1..-1]
22
- match.names.each do |name|
23
- name_s = name.to_sym
24
- self.class.send :define_method, name_s do
25
- match[name_s]
26
- end
27
- end if match.respond_to?(:names) # 1.8 doesn't support named captures
28
- end
29
-
30
- def room_id
31
- @message[:room_id]
32
- end
33
-
34
- def room
35
- bot.room_name_for @message[:room_id]
36
- end
37
-
38
- def user
39
- bot.username_for(@message[:user_id])
40
- end
41
-
42
- def user_id
43
- @message[:user_id]
44
- end
45
-
46
- def message
47
- @message[:body]
48
- end
49
-
50
- def run
51
- self.instance_eval &@action
52
- end
53
-
54
- def command_list
55
- bot.command_list
56
- end
57
-
58
- def say(msg, room_id_or_name = room_id)
59
- bot.say(msg, room_id_or_name)
60
- end
61
-
62
- def paste(msg, room_id_or_name = room_id)
63
- bot.paste(msg, room_id_or_name)
64
- end
65
-
66
- def play(sound, room_id_or_name = room_id)
67
- bot.play(sound, room_id_or_name)
68
- end
69
- end
70
- end
@@ -1,32 +0,0 @@
1
- class Scamp
2
- module Connection
3
- private
4
-
5
- def connect(api_key, room_list, &blk)
6
- EventMachine.run do
7
-
8
- # Check for rooms to join, and join them
9
- EventMachine::add_periodic_timer(5) do
10
- while id = @rooms_to_join.pop
11
- join_and_stream(id)
12
- end
13
- end
14
-
15
- populate_room_list do
16
- logger.debug "Adding #{room_list.join ', '} to list of rooms to join"
17
- @rooms_to_join = room_list.map{|c| room_id(c) }
18
-
19
- # Call a post connection block
20
- if block_given?
21
- yield
22
- end
23
- end
24
-
25
- # populate bot data separately, in case we are ignoring ourselves
26
- fetch_data_for('me')
27
-
28
- end
29
- end
30
-
31
- end
32
- end
@@ -1,35 +0,0 @@
1
- class Scamp
2
- module Messages
3
-
4
- def say(message, room_id_or_name)
5
- send_message(room_id_or_name, message, "Textmessage")
6
- end
7
-
8
- def paste(message, room_id_or_name)
9
- send_message(room_id_or_name, message, "PasteMessage")
10
- end
11
-
12
- def play(sound, room_id_or_name)
13
- send_message(room_id_or_name, sound, "SoundMessage")
14
- end
15
-
16
- private
17
-
18
- # curl -vvv -H 'Content-Type: application/json' -d '{"message":{"body":"Yeeeeeaaaaaahh", "type":"Textmessage"}}' -u API_KEY:X https://37s.campfirenow.com/room/293788/speak.json
19
- def send_message(room_id_or_name, payload, type)
20
- # post 'speak', :body => {:message => {:body => message, :type => type}}.to_json
21
- room_id = room_id(room_id_or_name)
22
- url = "https://#{subdomain}.campfirenow.com/room/#{room_id}/speak.json"
23
- http = EventMachine::HttpRequest.new(url).post :head => {'Content-Type' => 'application/json', 'authorization' => [api_key, 'X']}, :body => Yajl::Encoder.encode({:message => {:body => payload, :type => type}})
24
- http.errback { logger.error "Couldn't connect to #{url} to post message \"#{payload}\" to room #{room_id}" }
25
- http.callback {
26
- if [200,201].include? http.response_header.status
27
- logger.debug "Posted message \"#{payload}\" to room #{room_id}"
28
- else
29
- logger.error "Couldn't post message \"#{payload}\" to room #{room_id} using url #{url}, http response from the API was #{http.response_header.status}"
30
- end
31
- }
32
- end
33
-
34
- end
35
- end
data/lib/scamp/rooms.rb DELETED
@@ -1,116 +0,0 @@
1
- class Scamp
2
- module Rooms
3
- # TextMessage (regular chat message),
4
- # PasteMessage (pre-formatted message, rendered in a fixed-width font),
5
- # SoundMessage (plays a sound as determined by the message, which can be either “rimshot”, “crickets”, or “trombone”),
6
- # TweetMessage (a Twitter status URL to be fetched and inserted into the chat)
7
-
8
- def upload
9
- end
10
-
11
- def join(room_id)
12
- logger.info "Joining room #{room_id}"
13
- url = "https://#{subdomain}.campfirenow.com/room/#{room_id}/join.json"
14
- http = EventMachine::HttpRequest.new(url).post :head => {'Content-Type' => 'application/json', 'authorization' => [api_key, 'X']}
15
-
16
- http.errback { logger.error "Error joining room: #{room_id}" }
17
- http.callback {
18
- yield if block_given?
19
- }
20
- end
21
-
22
- def room_id(room_id_or_name)
23
- if room_id_or_name.is_a? Integer
24
- return room_id_or_name
25
- else
26
- return room_id_from_room_name(room_id_or_name)
27
- end
28
- end
29
-
30
- def room_name_for(room_id)
31
- data = room_cache_data(room_id)
32
- return data["name"] if data
33
- room_id.to_s
34
- end
35
-
36
- private
37
-
38
- def room_cache_data(room_id)
39
- return room_cache[room_id] if room_cache.has_key? room_id
40
- fetch_room_data(room_id)
41
- return false
42
- end
43
-
44
- def populate_room_list
45
- url = "https://#{subdomain}.campfirenow.com/rooms.json"
46
- http = EventMachine::HttpRequest.new(url).get :head => {'authorization' => [api_key, 'X']}
47
- http.errback { logger.error "Couldn't connect to url #{url} to fetch room list" }
48
- http.callback {
49
- if http.response_header.status == 200
50
- logger.debug "Fetched room list"
51
- new_rooms = {}
52
- Yajl::Parser.parse(http.response)['rooms'].each do |c|
53
- new_rooms[c["name"]] = c
54
- end
55
- # No idea why using the "rooms" accessor here doesn't
56
- # work but accessing the ivar directly does. There's
57
- # Probably a bug.
58
- @rooms = new_rooms # replace existing room list
59
- yield if block_given?
60
- else
61
- logger.error "Couldn't fetch room list with url #{url}, http response from API was #{http.response_header.status}"
62
- end
63
- }
64
- end
65
-
66
- def fetch_room_data(room_id)
67
- url = "https://#{subdomain}.campfirenow.com/room/#{room_id}.json"
68
- http = EventMachine::HttpRequest.new(url).get :head => {'authorization' => [api_key, 'X']}
69
- http.errback { logger.error "Couldn't connect to #{url} to fetch room data for room #{room_id}" }
70
- http.callback {
71
- if http.response_header.status == 200
72
- logger.debug "Fetched room data for #{room_id}"
73
- room = Yajl::Parser.parse(http.response)['room']
74
- room_cache[room["id"]] = room
75
-
76
- room['users'].each do |u|
77
- update_user_cache_with(u["id"], u)
78
- end
79
- else
80
- logger.error "Couldn't fetch room data for room #{room_id} with url #{url}, http response from API was #{http.response_header.status}"
81
- end
82
- }
83
- end
84
-
85
- def join_and_stream(id)
86
- join(id) do
87
- logger.info "Joined room #{id} successfully"
88
- fetch_room_data(id)
89
- stream(id)
90
- end
91
- end
92
-
93
- def stream(room_id)
94
- json_parser = Yajl::Parser.new :symbolize_keys => true
95
- json_parser.on_parse_complete = method(:process_message)
96
-
97
- url = "https://streaming.campfirenow.com/room/#{room_id}/live.json"
98
- # Timeout per https://github.com/igrigorik/em-http-request/wiki/Redirects-and-Timeouts
99
- http = EventMachine::HttpRequest.new(url, :connect_timeout => 20, :inactivity_timeout => 0).get :head => {'authorization' => [api_key, 'X']}
100
- http.errback { logger.error "Couldn't stream room #{room_id} at url #{url}" }
101
- http.callback { logger.info "Disconnected from #{url}"; rooms_to_join << room_id}
102
- http.stream do |chunk|
103
- begin
104
- json_parser << chunk
105
- rescue Yajl::ParseError => e
106
- logger.error "Couldn't parse room data for room #{room_id} with url #{url}, http response data was #{chunk[0..50]}..."
107
- end
108
- end
109
- end
110
-
111
- def room_id_from_room_name(room_name)
112
- logger.debug "Looking for room id for #{room_name}"
113
- rooms[room_name]["id"]
114
- end
115
- end
116
- end
data/lib/scamp/users.rb DELETED
@@ -1,51 +0,0 @@
1
- class Scamp
2
- module Users
3
- # Return the user_id if we haven't got the real name and
4
- # kick off a user data fetch
5
- def username_for(user_id)
6
- if cached_user?(user_id)
7
- user_cache[user_id]["name"]
8
- else
9
- fetch_data_for(user_id)
10
- user_id.to_s
11
- end
12
- end
13
-
14
- def is_me?(user_id)
15
- if user_cache['me']
16
- user_cache['me']['id'] == user_id
17
- else
18
- fetch_data_for('me')
19
- false
20
- end
21
- end
22
-
23
- def cached_user? user_id
24
- user_cache[user_id] != nil
25
- end
26
-
27
- private
28
-
29
- def fetch_data_for(user_id)
30
- return unless user_id
31
- url = "https://#{subdomain}.campfirenow.com/users/#{user_id}.json"
32
- http = EventMachine::HttpRequest.new(url).get(:head => {'authorization' => [api_key, 'X'], "Content-Type" => "application/json"})
33
- http.callback do
34
- if http.response_header.status == 200
35
- logger.debug "Got the data for #{user_id}"
36
- update_user_cache_with(user_id, Yajl::Parser.parse(http.response)['user'])
37
- else
38
- logger.error "Couldn't fetch user data for user #{user_id} with url #{url}, http response from API was #{http.response_header.status}"
39
- end
40
- end
41
- http.errback do
42
- logger.error "Couldn't connect to #{url} to fetch user data for user #{user_id}"
43
- end
44
- end
45
-
46
- def update_user_cache_with(user_id, data)
47
- logger.debug "Updated user cache for #{data['name']}"
48
- user_cache[user_id] = data
49
- end
50
- end
51
- end