4 #STDERR.puts "DEBUG #{msg}"
13 def initialize(server, port, nickname, serverPort = SERVER_PORT)
16 @serverPort = serverPort
18 @messageCallback = Proc.new do |sender, message, isprivate|
19 STDERR.puts "ERROR: No message callback registered"
27 def connect(server, port)
28 @hubsocket = TCPSocket.new(server, port)
29 @server = TCPServer.new('localhost', @serverPort)
36 readsockets, _, _ = IO.select([@hubsocket, @server, *@clients])
37 readsockets.each do |socket|
38 if socket == @hubsocket then
40 elsif socket == @server then
41 clientsocket << @server.accept
42 # print the client and return for now
43 STDERR.puts "Client: #{clientsocket.peeraddr.inspect}"
45 # @clients << clientsocket
51 rescue StandardError => e
52 STDERR.puts "ERROR: #{e.to_s}"
58 def registerMessageCallback(&block)
59 @messageCallback = block
62 def sendPublicMessage(message)
63 sendMessage(@nickname, message)
66 def sendPrivateMessage(recipient, message)
67 send("To:", recipient, "From:", @nickname, "$<#{@nickname}>", message)
74 def processMessage(sender, message, isprivate)
75 @messageCallback.call(sender, message, isprivate)
78 # parses a given command
79 # errors out if expected is given and doesn't match the command
80 def parseCommand(expected = nil)
81 cmdstring = @hubsocket.gets("|")
86 debug("<- #{cmdstring.inspect}")
87 cmdstring = cmdstring.chomp("|")
88 cmd, *args = cmdstring.split(" ")
90 if cmd[0,1] == "<" and cmd[-1,1] == ">" then
91 # it's a public message
92 processMessage(cmd[1...-1], args.join(" "), false)
94 raise "Unexpected command data: #{cmdstring}" unless cmd[0,1] == "$"
96 raise "Unexpected command: #{cmdstring}" if expected != cmd unless expected.nil?
98 raise "Unknown command: #{cmdstring}" unless @commands.has_key? cmd
100 @commands[cmd].call(*args)
105 message = "$#{cmd}#{args.empty? ? "" : " "}#{args.join(" ")}|"
106 debug("-> #{message.inspect}")
107 @hubsocket.write(message)
110 def sendMessage(nick, message)
111 str = "<#{nick}> #{message}|"
112 debug("-> #{str.inspect}")
113 @hubsocket.write(str)
117 key = String.new(lock)
118 1.upto(key.size - 1) do |i|
119 key[i] = lock[i] ^ lock[i-1]
121 key[0] = lock[0] ^ lock[-1] ^ lock[-2] ^ 5
124 0.upto(key.size - 1) do |i|
125 key[i] = ((key[i]<<4) & 240) | ((key[i]>>4) & 15)
128 0.upto(key.size - 1) do |i|
129 if [0,5,36,96,124,126].include?(key[i]) then
130 key[i,1] = ("/%%DCN%03d%%/" % key[i])
138 def cmd(name, &block)
139 @commands[name] = block
144 cmd("Lock") do |lock,pk|
145 send("Key", lockToKey(lock))
146 send("ValidateNick", @nickname)
148 cmd("HubName") { |*name| @hubname = name.join(" ") }
149 cmd("Hello") do |nick|
151 send("Version", "1,0091")
153 send("MyINFO", "$ALL #{@nickname} Ruby Request Bot<RubyBot V:0.1>$", "$Bot\001$$0$")
156 cmd("MyINFO") { |*args| } # do nothing for MyINFO
157 cmd("ConnectToMe") do |*args|
158 STDERR.puts("ConnectToMe: #{args.inspect}")
159 end # also ignore this - we aren't a fileserver
160 cmd("RevConnectToMe") do |nick,remote|
161 STDERR.puts("RevConnectToMe: #{nick} #{remote}")
162 send("RevConnectToMe", remote, nick)
163 end # pretend to be passive
164 cmd("To:") do |me, from, sender, *message|
165 raise "Unexpected To: data" if from != "From:" or message[0][0,1] != "$"
166 processMessage(sender, message[1..-1].join(" "), true)
168 cmd("NickList") { |*args| } # ignore
169 cmd("OpList") { |*args| } # ignore
170 cmd("Quit") { |*args| } # ignore
171 cmd("Search") { |*args| } # ignore