public
Description: Legs is a networking microframework designed to be super simple and easy and compact. Somewhat inspired by the crazy hacks in Camping, but mainly driven by wanting to build the kinds of easy tools I wish I would have had when I was younger and just getting in to coding. I hope to get it included with the reborn shoesified Hackety Hack as a networking aid, released under the Hackety Hack license: give it away, take it apart, learn-learn-learn without a 2nd thought. :)
Homepage:
Clone URL: git://github.com/Bluebie/legs.git
legs / examples / chat-server.rb
100644 111 lines (94 sloc) 3.405 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
require '../lib/legs'
 
# this is a work in progress, api's will change and break, one day there will be a functional matching
# client in shoes or something
 
Legs.start do
  def initialize
    @rooms = Hash.new { {'users' => [], 'messages' => [], 'topic' => 'No topic set'} }
    @rooms['Lobby'] = {'topic' => 'General Chit Chat', 'messages' => [], 'users' => []}
  end
  
  # returns a list of available rooms
  def rooms
    room_list = Hash.new
    @rooms.keys.each { |rn| room_list[rn] = room_object rn, :remote, :topic, :users, :messages }
    room_list
  end
  
  # joins/creates a room
  def join(room_name)
    unless @rooms.keys.include?(room_name)
      @rooms[room_name.to_s] = @rooms[room_name]
      broadcast :room_created, room_name
    end
    
# room = room_object(room_name)
#
# unless room['users'].include?(caller)
# broadcast room['users'], 'user_joined', room_name, user_object(caller)
# room['users'].push(caller)
# end
    
    room_object room_name, :remote
  end
  
  # leaves a room
  def leave(room_name)
    room = @rooms[room_name.to_s]
    room['users'].delete(caller)
    broadcast room['users'], 'user_left', room_name, user_object(caller)
    true
  end
  
  # sets the room topic message
  def topic=(room, message)
    room = @rooms[room.to_s]
    room['topic'] = message.to_s
    broadcast room['users'], 'room_changed', room_object(room, :remote, :name, :topic)
  end
  
  # sets the user's name
  def name=(name)
    caller.meta[:name] = name.to_s
    user_rooms(caller).each do |room_name|
      broadcast @rooms[room_name]['users'], 'user_changed', user_object(caller)
    end
    true
  end
  
  # returns information about ones self, clients thusly can find out their user 'id' number
  def user(object_id = nil)
    user = user_object( object_id.nil? ? caller : find_user_by_object_id(object_id) }.first )
    user['rooms'] = user_rooms(user)
    return user
  end
  
  # posts a message to a room
  def post_message(room_name, message)
    room = room_object(room_name)
    room['messages'].push(msg = {'user' => user_object(caller), 'time' => Time.now.to_i, 'message' => message.to_s} )
    trim_messages room
    broadcast room['users'], 'message', room_name.to_s, msg
    return msg
  end
  
  private
  
  # trims the message backlog
  def trim_messages room
    room = room_object(room) if room.is_a?(String)
    while room['messages'].length > 250
      room['messages'].shift
    end
  end
  
  # makes a user object suitable for sending back with meta info and stuff
  def user_object user
    object = {'id' => user.object_id}
    user.meta.each_pair do |key, value|
      object[key.to_s] = value
    end
    return object
  end
  
  def room_object room_name, target = :local, *only
    object = @rooms[room_name.to_s].dup
    object['users'].delete_if {|user| user.connected? == false }
    object['users'] = object['users'].map { |user| user_object(user) } if target == :remote
    object['topic'] = 'No topic set' if object['topic'].nil? or object['topic'].empty?
    object['name'] = room_name.to_s if target == :remote
    object.delete_if { |key, value| only.include?(key.to_sym) == false } unless only.empty?
    object
  end
  
  # returns all the room names the user is in.
  def user_rooms user
    @rooms.values.select { |room| room['users'].include?(user) }.map { |room| @rooms.index(room) }
  end
end
 
sleep