Created
January 16, 2015 23:25
-
-
Save voided/00334b0fd2b7a990da00 to your computer and use it in GitHub Desktop.
hubot skype adapter - with complimentary bad usage of buffers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{Robot, Adapter, TextMessage, EnterMessage, LeaveMessage, Response} = require 'hubot' | |
SkypeHostServer = require './skypehost' | |
class SkypeHost extends Adapter | |
send: (envelope, strings...) -> | |
@server.sendChat str for str in strings | |
emote: (envelope, strings...) -> | |
@server.sendEmote str for str in strings | |
reply: (envelope, strings...) -> | |
@send envelope, "#{envelope.user.name}: #{str}" for str in strings | |
run: -> | |
@server = new SkypeHostServer 8880 | |
@server.on 'chat', (user, message) => | |
console.log user, ':', message | |
@receive new TextMessage( user, message ) | |
@server.start() | |
# tell hubot we're ready | |
@emit 'connected' | |
exports.use = (robot) -> | |
new SkypeHost robot |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{EventEmitter} = require 'events' | |
net = require 'net' | |
BufferCursor = require 'buffercursor' | |
# helper for reading our encoded strings | |
BufferCursor::readString = -> | |
len = @readUInt32LE 4 | |
return @slice( len ).toString( 'utf8' ) | |
BufferCursor::writeString = (string) -> | |
len = Buffer.byteLength( string, 'utf8' ) | |
@writeUInt32LE len | |
@write string, len, 'utf8' | |
class SkypeHostServer extends EventEmitter | |
constructor: (@port) -> | |
@server = net.createServer() | |
@clients = [] | |
start: -> | |
@server.on 'connection', (client) => @newClient client | |
@server.listen @port | |
console.log 'listening on ', @port | |
sendChat: (message) -> | |
console.log '<- outgoing: ', message | |
data = new BufferCursor( new Buffer( Buffer.byteLength( message ) + 4 + 1 ) ) | |
data.writeUInt8 1 | |
data.writeString message | |
@sendData data | |
sendEmote: (message) -> | |
console.log '<- outgoing: *', message | |
data = new BufferCursor( new Buffer( Buffer.byteLength( message ) + 4 + 1 ) ) | |
data.writeUInt8 2 | |
data.writeString message | |
@sendData data | |
sendTopic: (topic) -> | |
data = new BufferCursor( new Buffer( Buffer.byteLength( message ) + 4 + 1 ) ) | |
data.writeUInt8 3 | |
data.writeString message | |
@sendData data | |
sendData: (data) -> | |
# need to seek to 0 if we want the data copy to work | |
data.seek 0 | |
packet = new BufferCursor( new Buffer( data.length + 4 ) ) | |
# write packet payload length | |
packet.writeUInt32LE data.length | |
# write payload | |
packet.copy data | |
# send packet to all our clients | |
for client in @clients | |
client.write packet.buffer | |
newClient: (client) -> | |
# add our new client to the list | |
@clients.push client | |
client.on 'readable', => @readClient client | |
client.on 'end', => | |
# client disconnected, remove from list | |
@clients.splice @clients.indexOf( client ), 1 | |
console.log @clients | |
readClient: (client) -> | |
if not @packetLen | |
# if we're here, we just finished reading a packet off the stream (or haven't read any packets) | |
# so lets try reading one | |
header = client.read 4 | |
if not header | |
# we have absolutely nothing available in our stream buffer somehow | |
return | |
# read the length from the header | |
@packetLen = header.readUInt32LE 0 | |
# try reading it | |
payload = client.read @packetLen | |
if not payload | |
# we haven't buffered the entire packet yet, we wait | |
return | |
# at this point we've read the length and the entire payload off the network | |
# we'll want to read the next packet length the next time we receive any data | |
@packetLen = null | |
@handlePayload new BufferCursor( payload ) | |
# try reading anything else we might have buffered | |
@readClient client | |
handlePayload: (payload) -> | |
type = payload.readUInt8() | |
data = payload.slice() | |
switch type | |
when 1 then @handleChat data | |
when 2 then @handleEmote data | |
when 3 then @handleTopic data | |
handleChat: (data) -> | |
user = data.readString() | |
message = data.readString() | |
@emit 'chat', user, message | |
handleEmote: (data) -> | |
user = data.readString() | |
message = data.readString() | |
@emit 'emote', user, message | |
handleTopic: (data) -> | |
topic = data.readString() | |
@emit 'topic', topic | |
module.exports = SkypeHostServer |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment