Commits

firefly committed 2e4f929

Worked a bit on improving module server/client; mostly the server.

Comments (0)

Files changed (4)

 
 #### Setup remote module server #####################################
 moduleServer = new modserv.ModuleServer
-	hostname: 'localhost'
-	add: (name, func) ->
-		func.manualEnd = true
-		shell.commands[name] = func
+	hostname : 'localhost'
+	shell    : shell
 
 #### Create bot object ##############################################
 bot =

src/client/client.coffee

 			}
 
 			for name of commands
-				send {
-					type : 'register'
-					name : name
-				}
+				send { type:'register', name:name }
 
 		when 'execute'
-			console.log "Executing #{data.command}!"
+			console.log "Executing #{data.name}!"
 			ex = {}
-			ex.name      = data.command # FIXME: should be data.name?
+			ex.name      = data.name # FIXME: should be data.name?
 			ex.eid       = data.eid
 			ex.arguments = data.arguments
 
 
 			ex.output = ->
 				for arg in arguments
-					send {
-						type  : 'output'
-						eid   : @eid
-						value : arg
-					}
+					send { type:'output', eid:@eid, value:arg }
 
 			ex.end = ->
 				ex.output.apply ex, arguments
 
-				send {
-					type : 'output-end'
-					eid  : @eid
-				}
+				send { type:'output-end', eid:@eid }
 
 				@output = ->
 				@end    = ->
 addCommand = (name, func) ->
 	commands[name] = func
 
-	send {
-		type : 'register'
-		name : name
-	}
+	send { type:'register', name:name }
 
 addCommand '_echo', (exec, args...) ->
 	exec.end.apply exec, args
 
-addCommand 'testCommand', (exec) ->
+addCommand '_testCommand', (exec) ->
 	exec.end "Hello from a remote module!"
 
 addCommand '_cat', (exec) ->
 	exec.stdin.on 'end', ->
 		exec.end()
 
+addCommand '_seq', (exec, from, to) ->
+	if `to == null`
+		to   = from
+		from = 1
+	
+	for i in [from..to]
+		exec.output i
+
+	exec.end()
+
 		@socket.write "#{cmd}\r\n"
 
 #### Server #########################################################
-Server = (opts) ->
+Server = (name, opts) ->
 	@connection = conn = new Connection opts
+
+	@name     = name
+	@channels = {}
+	@users    = {}
+	
 	conn.connect()
 
 	conn.on 'PING', (sender, message) ->
 		conn.write "PONG", message
 	
 	conn.on 'PRIVMSG', (sender, target, message) ->
-		console.log "<#{sender} to #{target}> #{message}"
+		console.log "[#{target}] <#{sender}> #{message}"
 
 	conn.on 'NOTICE', (sender, target, message) ->
-		console.log "[NOTICE] <#{sender} to #{target}> #{message}"
+		console.log "[#{target}] [NOTICE] <#{sender}> #{message}"
 
 	conn.on 'JOIN', (sender, channel) ->
-		console.log "#{sender} joined channel #{channel}"
+		console.log "[#{channel}] #{sender} joined channel #{channel}"
 
 	conn.on 'PART', (sender, channel, message = "") ->
-		console.log "#{sender} parted from channel #{channel} (#{message})"
+		console.log "[#{channel}] #{sender} parted from channel #{channel} (#{message})"
 
 	conn.on 'KICK', (sender, channel, kickee, message = "") ->
-		console.log "#{sender} kicked #{kickee} from channel #{channel} (#{message})"
+		console.log "[#{channel}] #{sender} kicked #{kickee} from channel #{channel} (#{message})"
 
 	conn.on 'QUIT', (sender, message = "") ->
 		console.log "User #{sender} has quit IRC (#{message})"

src/remote-module-server.coffee

 
 bs     = require './buffered-socket'
 
+#### Module #########################################################
+Module = (uid, socket, server) ->
+	@uid    = uid
+	@socket = new bs.BufferedSocket socket
+	@server = server
+
+	self = this
+
+	@eidCounter = 0
+	@executions = {}
+	@commands   = []
+
+	@metadata = {
+		name    : '<unknown>'
+		author  : '<unknown>'
+		version : '<unknown>'
+	}
+
+	@socket.on 'data', (line) ->
+		try
+			data = JSON.parse line
+			console.log "#{self}: #{data.type}:", data
+
+		catch err
+			console.log "Got invalid data from #{self}:"
+			console.log line.toString()
+			self.send {
+				type  : 'error'
+				value : "Your request couldn't be processed."
+			}
+
+		switch data.type
+			when 'handshake'
+				console.log "Module #{self} shook hands"
+				console.log "   Module metadata:", data.metadata
+
+				for k,v of data.metadata
+					self.metadata[k] = v
+
+			when 'register'
+				console.log "Module #{self} registered command #{data.name}."
+				self.commands.push data.name
+
+				server.addCommand data.name, (exec, args...) ->
+					eid = (++self.eidCounter)
+					self.executions[eid] = exec
+
+					exec.stdin.on 'data', (data) ->
+						self.send {
+							type  : 'input'
+							eid   : eid
+							value : data
+						}
+
+					exec.stdin.on 'end', ->
+						self.send {
+							type : 'input-end'
+							eid  : eid
+						}
+
+					self.send {
+						type      : 'execute'
+						eid       : eid
+						name      : data.name
+						arguments : args
+					}
+
+			when 'output'
+				console.log "Module #{self} outputted #{data.value}."
+				self.executions[data.eid].output data.value
+
+			when 'output-end'
+				console.log "Module #{self} ended output!"
+				self.executions[data.eid].end()
+	
+	@socket.on 'end', ->
+		console.log "Module #{self} received 'end'."
+		self.server.removeModule self
+	
+	this
+
+Module::toString = ->
+	"[#{@uid}:#{@metadata.name}]"
+
+Module::send = (obj) ->
+	@socket.write JSON.stringify obj
+	@socket.write "\r\n"
+
 #### ModuleServer ###################################################
 ModuleServer = (opts) ->
 	self = this
-	assert.ok opts and opts.hostname and opts.add, "Missing required " +
-			"property in ModuleServer options; either 'hostname' or 'add'."
+	assert.ok opts and opts.hostname and opts.shell, "Missing required " +
+			"property in ModuleServer options; either 'hostname' or 'shell'."
 	
-	@addCommand = opts.add
+	@addCommand = (name, func) ->
+		func.manualEnd = true
+		opts.shell.commands[name] = func
+	
+	@removeCommand = (name) ->
+		delete opts.shell.commands[name]
 
 	@uidCounter = 0
-	@eidCounter = 0
-	@executions = {}
 	@modules    = {}
 
 	server = net.createServer (socket) ->
-		module =
-			uid    : (++self.uidCounter)
-			socket : new bs.BufferedSocket socket
-
-			send   : (obj) ->
-				@socket.write JSON.stringify obj
-				@socket.write "\r\n"
-
-			toString: -> "[#{@uid}]"
-
-		self.modules[module.uid] = module
-		self.initializeModule module
-
-		module.send {
-			type    : 'handshake'
-			version : '0.0.01'
-			uid     : module.uid
-		}
+		module = new Module (++self.uidCounter), socket, self
+		self.addModule module
 
 	server.listen opts.port or 13450
 	this
 
-ModuleServer::initializeModule = (module) ->
-	self = this
+ModuleServer::addModule = (module) ->
+	console.log "Adding module #{module}"
+	@modules[module.uid] = module
 
-	module.socket.on 'data', (line) ->
-		try
-			data = JSON.parse line
-			console.log "#{module}:#{data.type}:", data
+	module.send {
+		type    : 'handshake'
+		version : '0.0.1'
+		uid     : module.uid
+	}
 
-			switch data.type
-				when 'handshake'
-					console.log "Module #{module} shook hands"
-					console.log "   Module metadata:", data.metadata
-
-				when 'register'
-					console.log "Module #{module} registered command #{data.name}."
-
-					self.addCommand data.name, (exec, args...) ->
-						eid = (++self.eidCounter)
-						self.executions[eid] = exec
-
-						exec.stdin.on 'data', (data) ->
-							module.send {
-								type  : 'input'
-								eid   : eid
-								value : data
-							}
-
-						exec.stdin.on 'end', ->
-							module.send {
-								type : 'input-end'
-								eid  : eid
-							}
-
-						module.send {
-							type      : 'execute'
-							eid       : eid
-							command   : data.name
-							arguments : args
-						}
-
-				when 'output'
-					console.log "Module #{module} outputted #{data.value}."
-					self.executions[data.eid].output data.value
-
-				when 'output-end'
-					console.log "Module #{module} ended output!"
-					self.executions[data.eid].end()
-
-		catch err
-			console.log "Got invalid data from #{module}:"
-			console.log line
-			module.send {
-				type  : 'error'
-				value : "Your request couldn't be processed."
-			}
+ModuleServer::removeModule = (module) ->
+	console.log "Removing module #{module}"
+	@removeCommand name for name in module.commands
+	delete @modules[module.uid]
 
 #### exports ########################################################
+exports.Module       = Module
 exports.ModuleServer = ModuleServer