UIDS = {} module Heimdall VERSION = "0.99 beta" attr_reader :VERSION class ProtocolError < StandardError end class UID def initialize @UID_prefix = "abstract" if not @UID_prefix id = (1..32).map { |x| (rand()*10).floor }.join while UIDS.has_key? id do id = (1..32).map { |x| (rand()*10).floor }.join end UIDS[@UID_prefix+id] = self @UID = id end attr_reader :UID end class UserCache def initialize @users = {} end def sync(data) data.each { |userdata| if not @users[userdata["protocol_id"]] then new_user = User.new userdata @users[new_user.protoid] = new_user else @users[userdata["protocol_id"]].modify(userdata) end } end def add(user) @users[user.protoid] = user end def get(protoid) raise ProtocolError, "user not found" if not @users[protoid] return @users[protoid] end def search(name,n,&block) @users.select(&block).take(n) end def search_by_name(name, n = 10) search(name,n) { |k,v| v.username.match? name } end def search_by_protoid(name,n = 10) search(name,n) { |k,v| k.match? name } end def filter(&block) @users.filter &block end def delete(protoid) @users.delete protoid end def bulk_delete(protoid_list) protoid_list.each { |x| @users.delete x } end end class RoomCache < UserCache def get(protoid) raise ProtocolError, "room not found" if not @users[protoid] return @users[protoid] end def sync(data) data.each { |userdata| if not @users[userdata["protocol_id"]] then new_user = Room.new userdata @users[new_user.protoid] = new_user else @users[userdata["protocol_id"]].modify(userdata) end } end end class RoomFilter def initialize(cache, room_protoid) @cache = cache @filter = room_protoid end def get(protoid) raise ProtocolError, "user not found" if not _filter[protoid] return _filter[protoid] end private def _filter @cache.filter { |k,v| v.protoid == @filter } end end class User < UID def initialize(data) @username = data["username"] @protoid = data["protocol_id"] @UID_prefix = "user" @channel = DirectChannel.new super() end def to_card() return { "username" => @username, "protoid" => @protoid } end def modify(data) @username = data["username"] end attr_reader :username attr_reader :protoid attr_reader :channel end class Room < UID def initialize(data) @name = data["name"] @protoid = data["protocol_id"] @UID_prefix = "room" @channel = RoomChannel.new @users = {} super() end def to_card() return { "name" => @name, "protoid" => @protoid } end def modify(data) @name = data["name"] end attr_reader :users attr_reader :username attr_reader :protoid attr_reader :channel end class Channel < UID def initialize @UID_prefix = "channel" @messages = MsgStack.new @read = 0 super() end def send(msg) @messages.push(msg) @read = @read+1 end def send_silent(msg) @messages.push(msg) end def get(n = 1) raise Heimdall::ProtocolError, "Invalid number of messages" if n < 0 return @messages.pull(n) end def read() messages = @messages.pull(@read) @read = 0 return messages end end class DirectChannel < Channel def initialize @UID_prefix = "dchannel" super() end end class RoomChannel < Channel def initialize @UID_prefix = "schannel" super() end undef read def get(n = 1) @read = 0 super(n) end end class Message < UID def initialize(data) @content = data["content"] @from = data["from"] @to = data["to"] @UID_prefix = "message" super() end def to_struct return { "content" => @content, "from" => @from, "to" => @to } end attr_reader :content attr_reader :from attr_reader :to end class MsgStack < UID def initialize @UID_prefix = "msgstack" @messages = [] super() end def push(msg) @messages.append(msg) end def pull(n) @messages.last n end end end