Class: Flamethrower::Campfire::Room

Inherits:
Object
  • Object
show all
Includes:
AsciiImager, RestApi
Defined in:
lib/flamethrower/campfire/room.rb

Constant Summary collapse

MAX_RECONNECT_TIMOUT_SECONDS =
20
POLL_SECONDS =
0.5
PERIODIC_UPDATE_SECONDS =
60 * 10

Constants included from AsciiImager

AsciiImager::DEFAULT_IMAGE_ASCII_SERVICE, AsciiImager::DEFAULT_IMAGE_WIDTH

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from AsciiImager

#config, #image_get

Methods included from RestApi

#campfire_get, #campfire_post, #campfire_put, #host

Constructor Details

#initialize(domain, token, params = {}) ⇒ Room

Returns a new instance of Room.



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/flamethrower/campfire/room.rb', line 16

def initialize(domain, token, params = {})
  @domain = domain
  @token = token
  @inbound_messages = Queue.new
  @outbound_messages = Queue.new
  @users_to_fetch = Queue.new
  @images_to_fetch = Queue.new
  @failed_messages = []
  @number = params['id']
  @name = params['name']
  @topic = params['topic']
  @users = []
  @joined = false
  @room_info_sent = false
  @room_alive = false
end

Instance Attribute Details

#connectionObject

Returns the value of attribute connection.



13
14
15
# File 'lib/flamethrower/campfire/room.rb', line 13

def connection
  @connection
end

#failed_messagesObject

Returns the value of attribute failed_messages.



14
15
16
# File 'lib/flamethrower/campfire/room.rb', line 14

def failed_messages
  @failed_messages
end

#inbound_messagesObject

Returns the value of attribute inbound_messages.



13
14
15
# File 'lib/flamethrower/campfire/room.rb', line 13

def inbound_messages
  @inbound_messages
end

#joinedObject

Returns the value of attribute joined.



14
15
16
# File 'lib/flamethrower/campfire/room.rb', line 14

def joined
  @joined
end

#nameObject

Returns the value of attribute name.



13
14
15
# File 'lib/flamethrower/campfire/room.rb', line 13

def name
  @name
end

#numberObject

Returns the value of attribute number.



13
14
15
# File 'lib/flamethrower/campfire/room.rb', line 13

def number
  @number
end

#outbound_messagesObject

Returns the value of attribute outbound_messages.



13
14
15
# File 'lib/flamethrower/campfire/room.rb', line 13

def outbound_messages
  @outbound_messages
end

#streamObject (readonly)

Returns the value of attribute stream.



11
12
13
# File 'lib/flamethrower/campfire/room.rb', line 11

def stream
  @stream
end

#thread_messagesObject

Returns the value of attribute thread_messages.



13
14
15
# File 'lib/flamethrower/campfire/room.rb', line 13

def thread_messages
  @thread_messages
end

#tokenObject (readonly)

Returns the value of attribute token.



11
12
13
# File 'lib/flamethrower/campfire/room.rb', line 11

def token
  @token
end

#topicObject



33
34
35
# File 'lib/flamethrower/campfire/room.rb', line 33

def topic
  @topic || "No topic"
end

#usersObject

Returns the value of attribute users.



13
14
15
# File 'lib/flamethrower/campfire/room.rb', line 13

def users
  @users
end

Instance Method Details

#alive?Boolean

Returns:

  • (Boolean)


130
131
132
# File 'lib/flamethrower/campfire/room.rb', line 130

def alive?
  @room_alive
end

#connectObject



145
146
147
148
149
150
151
# File 'lib/flamethrower/campfire/room.rb', line 145

def connect
  ::FLAMETHROWER_LOGGER.debug "Connecting to #{name} stream"
  @stream = Twitter::JSONStream.connect(:path => "/room/#{@number}/live.json", 
                              :host => "streaming.campfirenow.com", 
                              :auth => "#{@token}:x")
  setup_stream_callbacks
end

#dead?Boolean

Returns:

  • (Boolean)


134
135
136
# File 'lib/flamethrower/campfire/room.rb', line 134

def dead?
  !@room_alive
end

#fetch_imagesObject



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/flamethrower/campfire/room.rb', line 160

def fetch_images
  until @images_to_fetch.empty?
    message = @images_to_fetch.pop
    message.image_urls.each do |url|
      http = image_get(url)
      http.callback do
        case http.response_header.status
        when 200
          message.set_ascii_image(http.response)
        else
          message.mark_failed!
        end
        sort_and_dispatch_message(message)
      end
    end
  end
end

#fetch_messagesObject



153
154
155
156
157
158
# File 'lib/flamethrower/campfire/room.rb', line 153

def fetch_messages
  @stream.each_item do |item| 
    ::FLAMETHROWER_LOGGER.debug "Got json message #{item.inspect}"
    process_inbound_json_message(JSON.parse(item))
  end
end

#fetch_recent_messagesObject



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/flamethrower/campfire/room.rb', line 70

def fetch_recent_messages
  http = campfire_get("/room/#{@number}/recent.json", :limit => 10)
  http.callback do
    case http.response_header.status
    when 200
      json = JSON.parse(http.response)
      json['messages'].each do |json_message|
        process_inbound_json_message(json_message)
      end
    end
  end
end

#fetch_room_infoObject



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/flamethrower/campfire/room.rb', line 49

def fetch_room_info
  http = campfire_get("/room/#{@number}.json")
  http.callback do
    case http.response_header.status
    when 200
      old_users = @users
      @users = []
      json = JSON.parse(http.response)
      json['room']['users'].each do |user|
        @users << Flamethrower::Campfire::User.new(user)
      end
      resolve_renames(old_users, @users)
      unless @room_info_sent
        send_info
        fetch_recent_messages
      end
      @room_info_sent = true
    end
  end
end

#fetch_usersObject



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/flamethrower/campfire/room.rb', line 178

def fetch_users
  until @users_to_fetch.empty?
    message = @users_to_fetch.pop
    http = campfire_get("/users/#{message.user_id}.json")
    http.callback do
      case http.response_header.status
      when 200
        json = JSON.parse(http.response)
        user = Flamethrower::Campfire::User.new(json['user'])
        message.user = user
        @users << user
      else
        message.mark_failed!
      end
      sort_and_dispatch_message(message)
    end
  end
end

#joinObject



138
139
140
141
142
143
# File 'lib/flamethrower/campfire/room.rb', line 138

def join
  http = campfire_post("/room/#{@number}/join.json")
  http.callback do
    @joined = true if http.response_header.status == 200
  end
end

#on_errorObject



251
252
253
# File 'lib/flamethrower/campfire/room.rb', line 251

def on_error
  ::FLAMETHROWER_LOGGER.debug "There was an error connecting to #{name} stream"
end

#on_max_reconnectsObject



255
256
257
# File 'lib/flamethrower/campfire/room.rb', line 255

def on_max_reconnects
  ::FLAMETHROWER_LOGGER.debug "Failed to reconnect to #{name}, restarting room in #{MAX_RECONNECT_TIMOUT_SECONDS} seconds"
end

#on_reconnectObject



247
248
249
# File 'lib/flamethrower/campfire/room.rb', line 247

def on_reconnect
  ::FLAMETHROWER_LOGGER.debug "Reconnected to #{name} stream"
end

#pollObject



115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/flamethrower/campfire/room.rb', line 115

def poll
  unless dead?
    requeue_failed_messages
    fetch_messages
    post_messages
    fetch_users
    fetch_images
    messages_to_send = to_irc.retrieve_irc_messages
    messages_to_send.each do |m|
      ::FLAMETHROWER_LOGGER.debug "Sending irc message #{m.to_s}"
      @connection.send_message(m.to_s)
    end
  end
end

#post_messagesObject



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/flamethrower/campfire/room.rb', line 197

def post_messages
  until @outbound_messages.empty?
    message = @outbound_messages.pop
    json = {"message" => {"body" => message.body, "type" => message.message_type}}.to_json
    ::FLAMETHROWER_LOGGER.debug "Sending #{json} to campfire API"
    http = campfire_post("/room/#{@number}/speak.json", json)
    http.callback do
      case http.response_header.status
      when 201
        message.mark_delivered!
      else
        ::FLAMETHROWER_LOGGER.debug "Failed to post to campfire API with code: #{http.response_header.status} body: #{http.response}"
        message.mark_failed!
        sort_and_dispatch_message(message)
      end
    end
  end
end

#requeue_failed_messagesObject



228
229
230
231
232
233
234
235
236
# File 'lib/flamethrower/campfire/room.rb', line 228

def requeue_failed_messages
  @failed_messages.each do |m| 
    if m.retry_at > Time.now
      m.mark_pending!
      sort_and_dispatch_message(m)
      @failed_messages.delete(m)
    end
  end
end

#resolve_renames(old_users, new_users) ⇒ Object



83
84
85
86
87
88
89
90
91
92
# File 'lib/flamethrower/campfire/room.rb', line 83

def resolve_renames(old_users, new_users)
  old_users.each do |old_user|
    user = new_users.detect {|new_user| new_user.number == old_user.number}
    if user
      unless old_user.name == user.name
        @connection.send_rename(old_user.to_irc.nickname, user.to_irc.nickname)
      end
    end
  end
end

#retrieve_messagesObject



216
217
218
219
220
221
222
223
224
225
226
# File 'lib/flamethrower/campfire/room.rb', line 216

def retrieve_messages
  Array.new.tap do |new_array|
    until @inbound_messages.empty?
      message = @inbound_messages.pop
      next unless message
      unless message.user.to_irc.nickname == @connection.current_user.nickname
        new_array << message
      end
    end
  end
end

#say(body, message_type = 'TextMessage') ⇒ Object



94
95
96
97
# File 'lib/flamethrower/campfire/room.rb', line 94

def say(body, message_type='TextMessage')
  params = {'body' => translate_nicknames(body), 'type' => message_type, 'direction' => 'outbound'}
  sort_and_dispatch_message(Flamethrower::Campfire::Message.new(params))
end

#send_infoObject



44
45
46
47
# File 'lib/flamethrower/campfire/room.rb', line 44

def send_info
  @connection.send_topic(to_irc)
  @connection.send_userlist(to_irc)
end

#send_topic(topic) ⇒ Object



37
38
39
40
41
42
# File 'lib/flamethrower/campfire/room.rb', line 37

def send_topic(topic)
  http = campfire_put("/room/#{@number}.json", {:topic => topic}.to_json)
  http.callback do
    @topic = topic if http.response_header.status == 200
  end
end

#startObject



99
100
101
102
103
104
105
# File 'lib/flamethrower/campfire/room.rb', line 99

def start
  @room_alive = true
  fetch_room_info
  connect
  @polling_timer = EventMachine.add_periodic_timer(POLL_SECONDS) { poll }
  @periodic_timer = EventMachine.add_periodic_timer(PERIODIC_UPDATE_SECONDS) { fetch_room_info }
end

#stopObject



107
108
109
110
111
112
113
# File 'lib/flamethrower/campfire/room.rb', line 107

def stop
  @stream.stop if @stream
  EventMachine.cancel_timer(@polling_timer)
  EventMachine.cancel_timer(@periodic_timer)
  @room_alive = false
  @room_info_sent = false
end

#to_ircObject



238
239
240
241
242
243
244
245
# File 'lib/flamethrower/campfire/room.rb', line 238

def to_irc
  name = "##{@name.downcase.scan(/[A-Za-z0-9]+/).join("_")}"
  @irc_channel = Flamethrower::Irc::Channel.new(name, self)
  @irc_channel.tap do |channel|
    channel.users = @users.map(&:to_irc)
    channel.topic = topic.gsub("\n", "\s")
  end
end