flamethrower 0.0.1 → 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.
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  *.swp
2
2
  *.swo
3
3
  *.swn
4
+ *.gem
@@ -16,15 +16,17 @@ in the MOTD message. /join anyone of these and start chatting.
16
16
 
17
17
  You can also create a YAML file with domain and token specified like so:
18
18
 
19
- domain: mydomain
20
- token: aoeu1234
19
+ domain: mydomain
20
+ token: aoeu1234
21
21
 
22
22
  Then start flamethrower like so:
23
23
 
24
- flamethrower -c ~/myconfig.yml
24
+ flamethrower -c ~/myconfig.yml
25
25
 
26
26
  === A work in progress
27
27
 
28
+ TODO: Switch Net::HTTP sync calls to async EM::HttpRequest calls.
29
+
28
30
  Flamethrower is a work in progress. Right now basic messaging works, but
29
31
  it still needs a lot of love. If you find it useful and would like to see
30
32
  it do something, please submit a patch (with tests please)!. Bug reports are
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.1.0
@@ -56,4 +56,10 @@ end
56
56
  FLAMETHROWER_LOGGER = Logger.new(options['logger'] || STDOUT)
57
57
 
58
58
  server = Flamethrower::EventServer.new(options['host'], options['port'], options['domain'], options['token'])
59
+
60
+ trap("INT") do
61
+ FLAMETHROWER_LOGGER.info("Received shutdown signal, killing connections")
62
+ server.stop
63
+ end
64
+
59
65
  server.start
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{flamethrower}
8
- s.version = "0.0.1"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Blake Smith"]
12
- s.date = %q{2010-12-22}
12
+ s.date = %q{2011-01-12}
13
13
  s.default_executable = %q{flamethrower}
14
14
  s.description = %q{Flamethrower gives you the power to use your awesome irc client to talk in your campfire rooms.}
15
15
  s.email = %q{blakesmith0@gmail.com}
@@ -48,11 +48,16 @@ Gem::Specification.new do |s|
48
48
  "spec/fixtures/leave_message.json",
49
49
  "spec/fixtures/message.json",
50
50
  "spec/fixtures/paste_message.json",
51
+ "spec/fixtures/paste_message_with_pound.json",
51
52
  "spec/fixtures/room.json",
52
53
  "spec/fixtures/room_update.json",
53
54
  "spec/fixtures/rooms.json",
54
55
  "spec/fixtures/speak_message.json",
55
56
  "spec/fixtures/streaming_message.json",
57
+ "spec/fixtures/timestamp_message.json",
58
+ "spec/fixtures/upload_message.json",
59
+ "spec/fixtures/upload_url_sample",
60
+ "spec/fixtures/user.json",
56
61
  "spec/spec_helper.rb",
57
62
  "spec/unit/campfire/connection_spec.rb",
58
63
  "spec/unit/campfire/message_spec.rb",
@@ -1,7 +1,7 @@
1
1
  module Flamethrower
2
2
  module Campfire
3
3
  class Message
4
- attr_accessor :body, :user, :room, :message_type, :status, :retry_at
4
+ attr_accessor :body, :user, :room, :message_type, :status, :retry_at, :user_id
5
5
 
6
6
  RETRY_SECONDS = 15
7
7
 
@@ -9,6 +9,7 @@ module Flamethrower
9
9
  @body = params['body']
10
10
  @user = params['user']
11
11
  @room = params['room']
12
+ @user_id = params['user_id']
12
13
  @message_type = params['type']
13
14
  @status = "pending"
14
15
  end
@@ -34,6 +35,8 @@ module Flamethrower
34
35
  irc_string = ":#{@user.to_irc.to_s} PART #{@room.to_irc.name}"
35
36
  when "PasteMessage"
36
37
  irc_string = ":#{@user.to_irc.to_s} PRIVMSG #{@room.to_irc.name} :#{@body}"
38
+ else
39
+ return
37
40
  end
38
41
  Flamethrower::Irc::Message.new(irc_string)
39
42
  end
@@ -13,6 +13,7 @@ module Flamethrower
13
13
  @token = token
14
14
  @inbound_messages = Queue.new
15
15
  @outbound_messages = Queue.new
16
+ @users_to_fetch = Queue.new
16
17
  @failed_messages = []
17
18
  @number = params['id']
18
19
  @name = params['name']
@@ -52,6 +53,7 @@ module Flamethrower
52
53
  fetch_messages
53
54
  post_messages
54
55
  requeue_failed_messages
56
+ fetch_users
55
57
  messages_to_send = to_irc.retrieve_irc_messages
56
58
  messages_to_send.each do |m|
57
59
  ::FLAMETHROWER_LOGGER.debug "Sending irc message #{m.to_s}"
@@ -91,7 +93,29 @@ module Flamethrower
91
93
  ::FLAMETHROWER_LOGGER.debug "Got json message #{params.inspect}"
92
94
  params['user'] = @users.find {|u| u.number == params['user_id'] }
93
95
  params['room'] = self
94
- @inbound_messages << Flamethrower::Campfire::Message.new(params)
96
+ message = Flamethrower::Campfire::Message.new(params)
97
+ unless message.message_type == "TimestampMessage"
98
+ unless message.user
99
+ @users_to_fetch << message
100
+ else
101
+ @inbound_messages << message
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ def fetch_users
108
+ until @users_to_fetch.empty?
109
+ message = @users_to_fetch.pop
110
+ response = campfire_get("/users/#{message.user_id}.json")
111
+ case response
112
+ when Net::HTTPOK
113
+ json = JSON.parse(response.body)
114
+ user = Flamethrower::Campfire::User.new(json['user'])
115
+ message.user = user
116
+ @users << user
117
+ @inbound_messages << message
118
+ end
95
119
  end
96
120
  end
97
121
 
@@ -47,7 +47,7 @@ module Flamethrower
47
47
  private
48
48
 
49
49
  def display_message?(message)
50
- message.message_type != "TimestampMessage"
50
+ message && message.message_type != "TimestampMessage"
51
51
  end
52
52
 
53
53
  end
@@ -3,26 +3,65 @@ module Flamethrower
3
3
  include Flamethrower::Server
4
4
 
5
5
  attr_accessor :server
6
+
7
+ def unbind
8
+ @server.connections.delete(self)
9
+ end
6
10
  end
7
11
 
8
12
  class EventServer
9
- attr_reader :host, :port, :campfire_connection
13
+ attr_reader :host, :port, :campfire_connection, :connections
10
14
 
11
15
  def initialize(host, port, domain, token)
12
16
  @host = host || "0.0.0.0"
13
17
  @port = port || 6667
14
18
  @domain = domain
15
19
  @token = token
20
+ @connections = []
16
21
  end
17
22
 
18
23
  def start
19
24
  EventMachine::run do
20
25
  FLAMETHROWER_LOGGER.info "Flamethrower started at #{@host}:#{@port} on domain #{@domain}"
21
- EventMachine::start_server(@host, @port, EventConnection) do |connection|
26
+ @signature = EventMachine::start_server(@host, @port, EventConnection) do |connection|
27
+ @connections << connection
22
28
  connection.server = self
23
29
  connection.campfire_connection = Flamethrower::Campfire::Connection.new(@domain, @token, connection)
24
30
  end
25
31
  end
26
32
  end
33
+
34
+ def stop
35
+ FLAMETHROWER_LOGGER.info("Killing room threads")
36
+ @connections.each do |connection|
37
+ connection.irc_channels.map do |channel|
38
+ channel.to_campfire.kill_thread!
39
+ end
40
+ end
41
+ EventMachine.stop_server(@signature)
42
+ die_safely
43
+ end
44
+
45
+ def die_safely
46
+ FLAMETHROWER_LOGGER.info("Waiting for streams and connections to die")
47
+ if streams_alive? && connections_alive?
48
+ EventMachine.add_periodic_timer(1) { die_safely }
49
+ else
50
+ FLAMETHROWER_LOGGER.info("Done.")
51
+ EventMachine.stop
52
+ end
53
+ end
54
+
55
+ def streams_alive?
56
+ @connections.any? do |connection|
57
+ connection.irc_channels.any? do |channel|
58
+ channel.to_campfire.alive?
59
+ end
60
+ end
61
+ end
62
+
63
+ def connections_alive?
64
+ @connections.size <= 0
65
+ end
27
66
  end
28
67
  end
@@ -0,0 +1 @@
1
+ {"room_id":73541,"created_at":"2011/01/12 16:45:37 +0000","body":"#secure_asset_host: secure-assets-uat.example.com\nsecure_asset_host: assets1-uat.example.com","id":298515252,"user_id":627807,"type":"PasteMessage"}
@@ -0,0 +1 @@
1
+ {"room_id":73541,"created_at":"2010/12/14 20:09:23 +0000","body":null,"id":289361911,"user_id":489198,"type":"TimestampMessage"}
@@ -0,0 +1 @@
1
+ {"room_id":73541,"created_at":"2011/01/12 15:24:25 +0000","body":"Steak.jpeg","id":298466819,"user_id":786985,"type":"UploadMessage"}
@@ -0,0 +1 @@
1
+ The upload_message.json fixture generated this URL: https://thepoint.campfirenow.com/room/73541/uploads/1711244/Steak.jpeg
@@ -0,0 +1 @@
1
+ {"user":{"type":"Member","created_at":"2010/11/10 03:47:24 +0000","admin":true,"email_address":"bsmith@groupon.com","id":734581,"name":"blake"}}
@@ -4,6 +4,7 @@ require 'flamethrower'
4
4
  require 'server/mock_server'
5
5
  require 'json'
6
6
  require 'fakeweb'
7
+ require 'time'
7
8
 
8
9
  ::FLAMETHROWER_LOGGER = Logger.new("/dev/null") unless Object.const_defined?("FLAMETHROWER_LOGGER")
9
10
 
@@ -27,6 +27,16 @@ describe Flamethrower::Campfire::Message do
27
27
  @message.to_irc.to_s.should == ":#{@irc_user.to_s} PRIVMSG #{@channel.name} :thebody"
28
28
  end
29
29
 
30
+ it "returns if the message type is unhandled" do
31
+ json = JSON.parse(json_fixture('enter_message'))
32
+ json['type'] = "BogusMessage"
33
+ message = Flamethrower::Campfire::Message.new(json)
34
+ message.user = @campfire_user
35
+ message.room = @room
36
+ Flamethrower::Irc::Message.should_not_receive(:new)
37
+ message.to_irc.should be_nil
38
+ end
39
+
30
40
  it "converts a EnterMessage to a join irc message" do
31
41
  json = JSON.parse(json_fixture('enter_message'))
32
42
  message = Flamethrower::Campfire::Message.new(json)
@@ -57,7 +57,40 @@ describe Flamethrower::Campfire::Room do
57
57
  @room.fetch_room_info
58
58
  FakeWeb.last_request['authorization'].should == "Basic #{Base64::encode64("#{@room.token}:x").chomp}"
59
59
  end
60
+ end
61
+
62
+ describe "#fetch_users" do
63
+ it "makes a call to the campfire api to fetch user information" do
64
+ FakeWeb.register_uri(:get, "https://mytoken:x@mydomain.campfirenow.com/users/734581.json", :body => json_fixture("user"), :status => ["200", "OK"])
65
+ @room.instance_variable_get("@users_to_fetch") << Flamethrower::Campfire::Message.new(JSON.parse(json_fixture("enter_message")))
66
+ @room.fetch_users
67
+ @room.users.map(&:name).should == ["blake"]
68
+ end
69
+
70
+ it "fetches using the 'user_id' field if a streaming message" do
71
+ FakeWeb.register_uri(:get, "https://mytoken:x@mydomain.campfirenow.com/users/734581.json", :body => json_fixture("user"), :status => ["200", "OK"])
72
+ @room.instance_variable_get("@users_to_fetch") << Flamethrower::Campfire::Message.new(JSON.parse(json_fixture("enter_message")))
73
+ @room.should_receive(:campfire_get).with("/users/734581.json")
74
+ @room.fetch_users
75
+ end
76
+
77
+ context "successfully get user info" do
78
+ it "enqueues an EnterMessage into @inbound_messages for displaying in irc" do
79
+ FakeWeb.register_uri(:get, "https://mytoken:x@mydomain.campfirenow.com/users/734581.json", :body => json_fixture("user"), :status => ["200", "OK"])
80
+ @room.instance_variable_get("@users_to_fetch") << Flamethrower::Campfire::Message.new(JSON.parse(json_fixture("enter_message")))
81
+ @room.fetch_users
82
+ message = @room.inbound_messages.pop.user.number.should == 734581
83
+ end
84
+ end
60
85
 
86
+ context "fails to get user info" do
87
+ it "doesn't enqueue an EnterMessage" do
88
+ FakeWeb.register_uri(:get, "https://mytoken:x@mydomain.campfirenow.com/users/734581.json", :status => ["400", "Bad Request"])
89
+ @room.instance_variable_get("@users_to_fetch") << Flamethrower::Campfire::Message.new(JSON.parse(json_fixture("enter_message")))
90
+ @room.fetch_users
91
+ message = @room.inbound_messages.size.should == 0
92
+ end
93
+ end
61
94
  end
62
95
 
63
96
  describe "#join" do
@@ -79,45 +112,13 @@ describe Flamethrower::Campfire::Room do
79
112
  end
80
113
  end
81
114
 
82
- describe "#thread" do
83
- before do
84
- Kernel.stub(:sleep)
85
- end
86
-
87
- context "in a Thread" do
88
- it "calls connect at the start of the thread" do
89
- @room.stub(:fetch_messages)
90
- @room.stub(:post_messages)
91
- @room.should_receive(:connect).at_least(1).times
92
- @room.start_thread
93
- @room.kill_thread!
94
- end
95
-
96
- it "fetches messages from the stream" do
97
- @room.stub(:connect)
98
- @room.stub(:post_messages)
99
- @room.should_receive(:fetch_messages).at_least(1).times
100
- @room.start_thread
101
- @room.kill_thread!
102
- end
103
-
104
- it "posts messages to the campfire API" do
105
- @room.stub(:connect)
106
- @room.stub(:fetch_messages)
107
- @room.should_receive(:post_messages).at_least(1).times
108
- @room.start_thread
109
- @room.kill_thread!
110
- end
111
-
112
- end
113
- end
114
-
115
115
  describe "#fetch_messages" do
116
116
  before do
117
117
  Twitter::JSONStream.stub(:connect).and_return("stream")
118
- item = json_fixture("streaming_message")
118
+ @item = json_fixture("streaming_message")
119
+ @room.users << @user
119
120
  @room.connect
120
- @room.stream.stub(:each_item).and_yield(item)
121
+ @room.stream.stub(:each_item).and_yield(@item)
121
122
  end
122
123
 
123
124
  it "iterates over each stream item and sends to the message queue" do
@@ -132,7 +133,6 @@ describe Flamethrower::Campfire::Room do
132
133
 
133
134
  it "maps the message sender to the right user" do
134
135
  @room.users << @user2
135
- @room.users << @user
136
136
  @room.fetch_messages
137
137
  @room.inbound_messages.pop.user.should == @user
138
138
  end
@@ -141,6 +141,22 @@ describe Flamethrower::Campfire::Room do
141
141
  @room.fetch_messages
142
142
  @room.inbound_messages.pop.room.should == @room
143
143
  end
144
+
145
+ it "discards timestamp messages altogether" do
146
+ item = json_fixture("timestamp_message")
147
+ @room.stream.stub(:each_item).and_yield(item)
148
+ @room.fetch_messages
149
+ @room.instance_variable_get("@inbound_messages").size.should == 0
150
+ @room.instance_variable_get("@users_to_fetch").size.should == 0
151
+ end
152
+
153
+ it "puts messages that don't have an existing user into the users_to_fetch queue" do
154
+ enter_message = JSON.parse(json_fixture("streaming_message"))
155
+ enter_message['user_id'] = 98765
156
+ @room.stream.stub(:each_item).and_yield(enter_message.to_json)
157
+ @room.fetch_messages
158
+ @room.instance_variable_get("@users_to_fetch").size.should == 1
159
+ end
144
160
  end
145
161
 
146
162
  describe "#say" do
@@ -46,6 +46,11 @@ describe Flamethrower::Irc::Channel do
46
46
  @channel.retrieve_irc_messages.should be_empty
47
47
  end
48
48
 
49
+ it "doesn't add messages that return nil from to_irc" do
50
+ @room.inbound_messages << nil
51
+ @channel.retrieve_irc_messages.should be_empty
52
+ end
53
+
49
54
  xit "doesn't send the message if the source is the current user" do
50
55
  message = Flamethrower::Campfire::Message.new('body' => 'Hello there', 'user' => @campfire_user, 'room' => @room, 'type' => 'TextMessage')
51
56
  @room.inbound_messages << message
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flamethrower
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 0
9
8
  - 1
10
- version: 0.0.1
9
+ - 0
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Blake Smith
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-22 00:00:00 -06:00
18
+ date: 2011-01-12 00:00:00 -06:00
19
19
  default_executable: flamethrower
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -101,11 +101,16 @@ files:
101
101
  - spec/fixtures/leave_message.json
102
102
  - spec/fixtures/message.json
103
103
  - spec/fixtures/paste_message.json
104
+ - spec/fixtures/paste_message_with_pound.json
104
105
  - spec/fixtures/room.json
105
106
  - spec/fixtures/room_update.json
106
107
  - spec/fixtures/rooms.json
107
108
  - spec/fixtures/speak_message.json
108
109
  - spec/fixtures/streaming_message.json
110
+ - spec/fixtures/timestamp_message.json
111
+ - spec/fixtures/upload_message.json
112
+ - spec/fixtures/upload_url_sample
113
+ - spec/fixtures/user.json
109
114
  - spec/spec_helper.rb
110
115
  - spec/unit/campfire/connection_spec.rb
111
116
  - spec/unit/campfire/message_spec.rb