unrealircd.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. module.exports.connected = connected;
  2. module.exports.processMessage = processMessage;
  3. module.exports.processSender = processSender;
  4. module.exports.setHandlers = setHandlers;
  5. module.exports.setSettings = setSettings;
  6. var handlers = {
  7. sendHandler: null,
  8. findServer: null,
  9. findUser: null,
  10. killUser: null,
  11. newServer: null,
  12. newUser: null,
  13. parseUmodes: null,
  14. getChannel: null,
  15. quitUser: null
  16. };
  17. var settings = {
  18. ID: null,
  19. password: null,
  20. name: null,
  21. description: null,
  22. version: null,
  23. me: null
  24. };
  25. var prefixes = {
  26. '~': 'q',
  27. '&': 'a',
  28. '@': 'o',
  29. '%': 'h',
  30. '+': 'v'
  31. };
  32. function parseModePrefix(text){
  33. var modes = [];
  34. for(var i=0; i<text.length; i++){
  35. var c = text.charAt(i);
  36. if(c in prefixes){
  37. modes[prefixes[c]] = true;
  38. } else break;
  39. }
  40. var uid = text.substring(i);
  41. var user = handlers.findUser(uid);
  42. if(!user){
  43. handlers.killUser(uid);
  44. return null;
  45. }
  46. return { 'user': user, 'modes': modes };
  47. }
  48. function connected(){
  49. ircSend(null, settings.ID, 'PASS', [settings.password]);
  50. ircSend(null, settings.ID, 'PROTOCTL', ['NICKv2', 'VHP', 'UMODE2', 'NICKIP', 'SJOIN', 'SJOIN2', 'SJ3', 'NOQUIT', 'TKLEXT', 'MLOCK', 'SID']);
  51. ircSend(null, settings.ID, 'PROTOCTL', ['EAUTH=' + settings.name + ',,,' + settings.version]);
  52. ircSend(null, settings.ID, 'PROTOCTL', ['SID=' + settings.ID]);
  53. ircSend(null, settings.ID, 'SERVER', [settings.name, '1', settings.description]);
  54. }
  55. /*
  56. this.sender = {
  57. 'nick': '',
  58. 'ident': '',
  59. 'host': '',
  60. 'server': false,
  61. 'user': false
  62. };
  63. */
  64. function processSender(sender){
  65. if(sender.nick){
  66. if(server = handlers.findServer(sender.nick)){
  67. sender.nick = server.name;
  68. sender.server = server;
  69. } else if(user = handlers.findUser(sender.nick)){
  70. sender.nick = user.name
  71. sender.ident = user.ident;
  72. sender.host = user.host;
  73. sender.user = user;
  74. } else {
  75. handlers.killUser(sender.nick);
  76. return false;
  77. }
  78. }
  79. return sender;
  80. }
  81. function processMessage(msg){
  82. if(!msg) return;
  83. if(msg.command in cmdBinds){
  84. cmdBinds[msg.command](msg);
  85. } else {
  86. console.log('Unhandled cmd: '+msg.command);
  87. console.log(msg);
  88. }
  89. }
  90. function setHandlers(newHandlers){
  91. handlers = newHandlers;
  92. }
  93. function setSettings(newSettings){
  94. settings = newSettings;
  95. }
  96. function ircSend(tags, from, cmd, args){
  97. handlers.send(tags, from, cmd, args);
  98. }
  99. var cmdBinds = {
  100. 'PROTOCTL': function(msg){
  101. console.log(msg);
  102. },
  103. 'SERVER': function(msg){
  104. var expr = /^([^-]+)-([^-]+)-([^ ]+) (.*)$/;
  105. var match = expr.exec(msg.args[2]);
  106. if(match){
  107. handlers.newServer(msg.args[0], match[3], match[4], msg.args[1], settings.me);
  108. } else {
  109. throw 'Unknown SERVER message';
  110. }
  111. },
  112. 'MD': function(msg){
  113. },
  114. 'SMOD': function(msg){
  115. },
  116. 'EOS': function(msg){
  117. },
  118. 'SINFO': function(msg){
  119. console.log(msg);
  120. },
  121. 'SID': function(msg){
  122. handlers.newServer(msg.args[0], msg.args[2], msg.args[3], msg.args[1], msg.sender);
  123. },
  124. 'UID': function(msg){ // nick, distance, TS, ident, host, uid, account, umodes, vhost, cloakedHost, ip, realname, uplink
  125. handlers.newUser(msg.args[0], msg.args[1], msg.args[2], msg.args[3], msg.args[4], msg.args[5], msg.args[6], handlers.parseUmodes(msg.args[7]), msg.args[8], msg.args[9], msg.args[10], msg.args[11], msg.sender.server);
  126. },
  127. 'SJOIN': function(msg){
  128. var channel = handlers.getChannel(msg.args[1]);
  129. channel.setTS(msg.args[0]);
  130. var modeArgs = [];
  131. for(var i=3; i<msg.args.length - 1; i++){
  132. modeArgs.push(msg.args[i]);
  133. }
  134. channel.addModes(msg.args[2], modeArgs);
  135. var members = msg.text.split(' ');
  136. for(var i=0; i<members.length; i++){
  137. var member = members[i];
  138. var c = member.charAt(0);
  139. if(c == '&'){ // +b
  140. channel.addBan(member.substring(1));
  141. } else if(c == '"'){ // +e
  142. channel.addExcept(member.substring(1));
  143. } else if(c == '\''){ // +I
  144. channel.addInvex(member.substring(1));
  145. } else {
  146. var udata = parseModePrefix(member);
  147. if(!udata) return;
  148. console.log(udata.user.name + ' joined ' + msg.args[1]);
  149. channel.joinUser(udata.user);
  150. channel.setStatusModes(udata.user, udata.modes);
  151. }
  152. }
  153. console.log(channel);
  154. },
  155. 'SWHOIS': function(msg){
  156. },
  157. 'TKL': function(msg){
  158. },
  159. 'METADATA': function(msg){
  160. },
  161. 'NETINFO': function(msg){
  162. console.log(msg);
  163. },
  164. 'SASL': function(msg){
  165. },
  166. 'PING': function(msg){
  167. msg.reply(null, 'PONG', msg.args);
  168. },
  169. 'QUIT': function(msg){
  170. handlers.quitUser(msg.sender.user);
  171. },
  172. 'PART': function(msg){
  173. var channel = handlers.getChannel(msg.args[0]);
  174. channel.removeUser(msg.sender.user);
  175. }
  176. };