-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #215 from haosdent/irc
IRC prototype. I'll accept the PR, but I'll make it disable by default.. at least until we fully test it.
- Loading branch information
Showing
10 changed files
with
329 additions
and
1 deletion.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -103,6 +103,7 @@ rocketchat:[email protected] | |
rocketchat:[email protected] | ||
rocketchat:[email protected] | ||
rocketchat:[email protected] | ||
rocketchat:[email protected] | ||
ronhoffmann:[email protected] | ||
[email protected] | ||
[email protected] | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Move to [rocketchat-irc](https://github.com/haosdent/Rocket.Chat/tree/irc/packages/rocketchat-irc). |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
net = Npm.require('net') | ||
|
||
ircClientMap = {} | ||
|
||
bind = (f) -> | ||
g = Meteor.bindEnvironment (self, args...) -> f.apply(self, args) | ||
(args...) -> g @, args... | ||
|
||
async = (f, args...) -> | ||
Meteor.wrapAsync(f)(args...) | ||
|
||
class IrcClient | ||
constructor: (@loginReq) -> | ||
@user = @loginReq.user | ||
ircClientMap[@user._id] = this | ||
@ircPort = 6667 | ||
@ircHost = 'irc.freenode.net' | ||
@msgBuf = [] | ||
@isConnected = false | ||
@socket = new net.Socket | ||
@socket.setNoDelay | ||
@socket.setEncoding 'utf-8' | ||
@onConnect = bind @onConnect | ||
@onReceiveRawMessage = bind @onReceiveRawMessage | ||
@socket.on 'data', @onReceiveRawMessage | ||
@socket.on 'close', @onClose | ||
@receiveMessageRegex = /^:(\S+)!~\S+ PRIVMSG (\S+) :(.+)$/ | ||
@memberListRegex = /^:\S+ \d+ \S+ = #(\S+) :(.*)$/ | ||
@initRoomList() | ||
|
||
connect: (@loginCb) => | ||
@socket.connect @ircPort, @ircHost, @onConnect | ||
|
||
onConnect: () => | ||
console.log @user.username, 'connect success.' | ||
@socket.write "NICK #{@user.username}\r\n" | ||
@socket.write "USER #{@user.username} 0 * :Real Name\r\n" | ||
# message order could not make sure here | ||
@isConnected = true | ||
@socket.write msg for msg in @msgBuf | ||
@loginCb null, @loginReq | ||
|
||
onClose: (data) => | ||
console.log @user.username, 'connection close.' | ||
|
||
onReceiveRawMessage: (data) => | ||
data = data.toString().split('\n') | ||
for line in data | ||
line = line.trim() | ||
console.log "[#{@ircHost}:#{@ircPort}]:", line | ||
if line.indexOf('PING') == 0 | ||
@socket.write line.replace('PING :', 'PONG ') | ||
continue | ||
|
||
matchResult = @receiveMessageRegex.exec line | ||
if matchResult | ||
@onReceiveMessage matchResult[1], matchResult[2], matchResult[3] | ||
continue | ||
|
||
matchResult = @memberListRegex.exec line | ||
if matchResult | ||
@onReceiveMemberList matchResult[1], matchResult[2].split ' ' | ||
continue | ||
|
||
onReceiveMessage: (name, target, content) -> | ||
console.log '[irc] onReceiveMessage -> '.yellow, 'sourceUserName:', name, 'target:', target, 'content:', content | ||
if target[0] == '#' | ||
room = ChatRoom.findOne {name: target.substring 1} | ||
else | ||
room = ChatRoom.findOne {usernames: { $all: [target, name]}, t: 'd'}, { fields: { usernames: 1, t: 1 } } | ||
|
||
sourceUser = Meteor.users.findOne {username: message.u.username}, fields: username: 1 | ||
unless sourceUser | ||
Meteor.call 'registerUser', | ||
email: '', | ||
password: name, | ||
name: name | ||
Meteor.call 'receiveMessage', | ||
u: | ||
username: name | ||
rid: room._id | ||
msg: content | ||
|
||
onReceiveMemberList: (room, members) -> | ||
console.log '[irc] onReceiveMemberList -> '.yellow, 'room:', room, 'members:', members | ||
|
||
sendRawMessage: (msg) -> | ||
console.log '[irc] sendRawMessage -> '.yellow, msg | ||
if @isConnected | ||
@socket.write msg | ||
else | ||
@msgBuf.push msg | ||
|
||
sendMessage: (room, message) -> | ||
console.log '[irc] sendMessage -> '.yellow, 'userName:', message.u.username, 'arguments:', arguments | ||
target = '' | ||
if room.t == 'c' | ||
target = "##{room.name}" | ||
else if room.t == 'd' | ||
for name in room.usernames | ||
if message.u.username != name | ||
target = name | ||
break | ||
msg = "PRIVMSG #{target} :#{message.msg}\r\n" | ||
@sendRawMessage msg | ||
|
||
initRoomList: () -> | ||
roomsCursor = ChatRoom.find {usernames: { $in: [@user.username]}, t: 'c'}, { fields: { name: 1 }} | ||
rooms = roomsCursor.fetch() | ||
for room in rooms | ||
@joinRoom(room) | ||
|
||
joinRoom: (room) -> | ||
msg = "JOIN ##{room.name}\r\n" | ||
@sendRawMessage msg | ||
msg = "NAMES ##{room.name}\r\n" | ||
@sendRawMessage msg | ||
|
||
leaveRoom: (room) -> | ||
msg = "PART ##{room.name}\r\n" | ||
@sendRawMessage msg | ||
|
||
|
||
IrcClient.getByUid = (uid) -> | ||
return ircClientMap[uid] | ||
|
||
IrcClient.create = (login) -> | ||
unless login.user._id of ircClientMap | ||
ircClient = new IrcClient login | ||
return async ircClient.connect | ||
return login | ||
|
||
|
||
class IrcLoginer | ||
constructor: (login) -> | ||
console.log '[irc] validateLogin -> '.yellow, login | ||
return IrcClient.create login | ||
|
||
|
||
class IrcSender | ||
constructor: (message) -> | ||
room = ChatRoom.findOne message.rid, { fields: { name: 1, usernames: 1, t: 1 } } | ||
ircClient = IrcClient.getByUid message.u._id | ||
ircClient.sendMessage room, message | ||
return message | ||
|
||
|
||
class IrcRoomJoiner | ||
constructor: (user, room) -> | ||
ircClient = IrcClient.getByUid user._id | ||
ircClient.joinRoom room | ||
return room | ||
|
||
|
||
class IrcRoomLeaver | ||
constructor: (user, room) -> | ||
ircClient = IrcClient.getByUid user._id | ||
ircClient.leaveRoom room | ||
return room | ||
|
||
|
||
RocketChat.callbacks.add 'beforeValidateLogin', IrcLoginer, RocketChat.callbacks.priority.LOW | ||
RocketChat.callbacks.add 'beforeSaveMessage', IrcSender, RocketChat.callbacks.priority.LOW | ||
RocketChat.callbacks.add 'beforeJoinRoom', IrcRoomJoiner, RocketChat.callbacks.priority.LOW | ||
RocketChat.callbacks.add 'beforeLeaveRoom', IrcRoomLeaver, RocketChat.callbacks.priority.LOW |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
Package.describe({ | ||
name: 'rocketchat:irc', | ||
version: '0.0.1', | ||
summary: 'RocketChat libraries', | ||
git: '' | ||
}); | ||
|
||
Package.onUse(function(api) { | ||
api.versionsFrom('1.0'); | ||
|
||
api.use([ | ||
'coffeescript', | ||
'rocketchat:[email protected]' | ||
]); | ||
|
||
api.addFiles('irc.server.coffee', 'server'); | ||
|
||
api.export(['Irc'], ['server']); | ||
}); | ||
|
||
Package.onTest(function(api) {}); |
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
Meteor.methods | ||
receiveMessage: (message) -> | ||
if message.u?._id? | ||
else if message.u?.username? | ||
message.u = Meteor.users.findOne {username: message.u.username}, fields: username: 1 | ||
else | ||
return false | ||
|
||
room = ChatRoom.findOne message.rid, { fields: { usernames: 1, t: 1 } } | ||
|
||
if not room | ||
return false | ||
|
||
console.log '[methods] receiveMessage -> '.green, 'userId:', message.u._id, 'arguments:', arguments | ||
|
||
message.ts = new Date() | ||
|
||
if urls = message.msg.match /([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\w]+)?\??([-\+=&!:;%@\/\.\,\w]+)?#?([\w]+)?)?/g | ||
message.urls = urls | ||
|
||
message = RocketChat.callbacks.run 'beforeReceiveMessage', message | ||
|
||
### | ||
Defer other updated as their return is not interesting to the user | ||
### | ||
Meteor.defer -> | ||
|
||
### | ||
Update all the room activity tracker fields | ||
### | ||
ChatRoom.update | ||
# only subscriptions to the same room | ||
rid: message.rid | ||
, | ||
# update the last message timestamp | ||
$set: | ||
lm: message.ts | ||
# increate the messages counter | ||
$inc: | ||
msgs: 1 | ||
|
||
|
||
# increment unread couter if direct messages | ||
if room.t is 'd' | ||
### | ||
Update the other subscriptions | ||
### | ||
ChatSubscription.update | ||
# only subscriptions to the same room | ||
rid: message.rid | ||
# not the msg owner | ||
'u._id': | ||
$ne: message.u._id | ||
, | ||
$set: | ||
# alert de user | ||
alert: true | ||
# open the room for the user | ||
open: true | ||
# increment unread couter | ||
$inc: | ||
unread: 1 | ||
|
||
else | ||
message.mentions?.forEach (mention) -> | ||
console.log mention | ||
### | ||
Update all other subscriptions of mentioned users to alert their owners and incrementing | ||
the unread counter for mentions and direct messages | ||
### | ||
ChatSubscription.update | ||
# only subscriptions to the same room | ||
rid: message.rid | ||
# the mentioned user | ||
'u._id': mention._id | ||
, | ||
$set: | ||
# alert de user | ||
alert: true | ||
# open the room for the user | ||
open: true | ||
# increment unread couter | ||
$inc: | ||
unread: 1 | ||
|
||
### | ||
Update all other subscriptions to alert their owners but witout incrementing | ||
the unread counter, as it is only for mentions and direct messages | ||
### | ||
ChatSubscription.update | ||
# only subscriptions to the same room | ||
rid: message.rid | ||
# only the ones that have not been alerted yet | ||
alert: false | ||
# not the msg owner | ||
'u._id': | ||
$ne: message.u._id | ||
, | ||
$set: | ||
# alert de user | ||
alert: true | ||
# open the room for the user | ||
open: true | ||
, | ||
# make sure we alert all matching subscription | ||
multi: true | ||
|
||
### | ||
Save the message. If there was already a typing record, update it. | ||
### | ||
ChatMessage.upsert | ||
rid: message.rid | ||
t: 't' | ||
$and: [{ 'u._id': message.u._id }] | ||
, | ||
$set: message | ||
$unset: | ||
t: 1 | ||
expireAt: 1 | ||
|
||
Meteor.defer -> | ||
|
||
message._id = Random.id() | ||
RocketChat.callbacks.run 'afterReceiveMessage', message | ||
|
||
|
This file contains 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