scamp 1.2.0 → 2.0.0.pre

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.
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