Advertisement
sparkychild

Untitled

Apr 28th, 2015
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 38.06 KB | None | 0 0
  1. var sys = require('sys');
  2. var https = require('https');
  3. var url = require('url');
  4.  
  5. const ACTION_COOLDOWN = 3 * 1000;
  6. const FLOOD_MESSAGE_NUM = 5;
  7. const FLOOD_PER_MSG_MIN = 500; // this is the minimum time between messages for legitimate spam. It's used to determine what "flooding" is caused by lag
  8. const FLOOD_MESSAGE_TIME = 6 * 1000;
  9. const MIN_CAPS_LENGTH = 8;
  10. const MIN_CAPS_PROPORTION = 0.8;
  11.  
  12. settings = {};
  13. try {
  14. settings = JSON.parse(fs.readFileSync('settings.json'));
  15. if (!Object.keys(settings).length && settings !== {}) settings = {};
  16. } catch (e) {} // file doesn't exist [yet]
  17.  
  18. messages = {};
  19. try {
  20. messages = JSON.parse(fs.readFileSync('messages.json'));
  21. if (!Object.keys(messages).length && messages !== {}) messages = {};
  22. } catch (e) {} // file doesn't exist [yet]
  23.  
  24. quotes = {};
  25. try {
  26. quotes = JSON.parse(fs.readFileSync('quotes.json'));
  27. if (!Object.keys(quotes).length && quotes !== {}) quotes = {};
  28. } catch (e) {} // file doesn't exist [yet]
  29.  
  30. exports.parse = {
  31. actionUrl: url.parse('https://play.pokemonshowdown.com/~~' + config.serverid + '/action.php'),
  32. room: 'lobby',
  33. 'settings': settings,
  34. 'messages': messages,
  35. 'quotes': quotes,
  36. chatData: {},
  37. ranks: {},
  38. msgQueue: [],
  39.  
  40. data: function(data, connection) {
  41. if (data.substr(0, 1) === 'a') {
  42. data = JSON.parse(data.substr(1));
  43. if (data instanceof Array) {
  44. for (var i = 0, len = data.length; i < len; i++) {
  45. this.splitMessage(data[i], connection);
  46. }
  47. } else {
  48. this.splitMessage(data, connection);
  49. }
  50. }
  51. },
  52. splitMessage: function(message, connection) {
  53. if (!message) return;
  54.  
  55. var room = 'lobby';
  56. if (message.indexOf('\n') < 0) return this.message(message, connection, room);
  57.  
  58. var spl = message.split('\n');
  59.  
  60. if (spl[0].charAt(0) === '>') {
  61. if (spl[1].substr(1, 4) === 'init') return ok('joined ' + spl[2].substr(7));
  62. if (spl[1].substr(1, 10) === 'tournament') return;
  63. room = spl.shift().substr(1);
  64. }
  65.  
  66. for (var i = 0, len = spl.length; i < len; i++) {
  67. this.message(spl[i], connection, room);
  68. }
  69. },
  70. message: function(message, connection, room) {
  71. var spl = message.split('|');
  72. if (!spl[1]) {
  73. if (/was promoted to Room (Driver|Moderator|Owner)/i.test(spl[0])) this.say(connection, room, 'Congratulations on the promotion ' + spl[0].substr(0, spl[0].indexOf("was") - 1) + '! ^-^');
  74. if (/was promoted to Room Voice/i.test(spl[0])) this.say(connection, room, 'Welcome to THA, ' + spl[0].substr(0, spl[0].indexOf("was") - 1) + '! :3');
  75. if (/was muted by (Flowerbless~|DanceBoTTT|BriyellaBot)/i.test(spl[0])) {
  76. this.say(connection, room, 'Sorry, bot moderation is being worked on... here ya go! ^-^');
  77. this.say(connection, room, '/unmute ' + spl[0].substr(0, spl[0].indexOf("was") - 1));
  78. }
  79. spl = spl[0].split('>');
  80. if (spl[1]) this.room = spl[1];
  81. return;
  82. }
  83.  
  84. switch (spl[1]) {
  85. case 'challstr':
  86. info('received challstr, logging in...');
  87. var id = spl[2];
  88. var str = spl[3];
  89.  
  90. var requestOptions = {
  91. hostname: this.actionUrl.hostname,
  92. port: this.actionUrl.port,
  93. path: this.actionUrl.pathname,
  94. agent: false
  95. };
  96.  
  97. if (!config.pass) {
  98. requestOptions.method = 'GET';
  99. requestOptions.path += '?act=getassertion&userid=' + toId(config.nick) + '&challengekeyid=' + id + '&challenge=' + str;
  100. } else {
  101. requestOptions.method = 'POST';
  102. var data = 'act=login&name=' + config.nick + '&pass=' + config.pass + '&challengekeyid=' + id + '&challenge=' + str;
  103. requestOptions.headers = {
  104. 'Content-Type': 'application/x-www-form-urlencoded',
  105. 'Content-Length': data.length
  106. };
  107. }
  108.  
  109. var req = https.request(requestOptions, function(res) {
  110. res.setEncoding('utf8');
  111. var data = '';
  112. res.on('data', function(chunk) {
  113. data += chunk;
  114. });
  115. res.on('end', function() {
  116. if (data === ';') {
  117. error('failed to log in; nick is registered - invalid or no password given');
  118. process.exit(-1);
  119. }
  120. if (data.length < 50) {
  121. error('failed to log in: ' + data);
  122. process.exit(-1);
  123. }
  124.  
  125. if (data.indexOf('heavy load') !== -1) {
  126. error('the login server is under heavy load; trying again in one minute');
  127. setTimeout(function() {
  128. this.message(message);
  129. }.bind(this), 60 * 1000);
  130. return;
  131. }
  132.  
  133. if (data.substr(0, 16) === '<!DOCTYPE html>') {
  134. error('Connection error 522; trying agian in one minute');
  135. setTimeout(function() {
  136. this.message(message);
  137. }.bind(this), 60 * 1000);
  138. return;
  139. }
  140.  
  141. try {
  142. data = JSON.parse(data.substr(1));
  143. if (data.actionsuccess) {
  144. data = data.assertion;
  145. } else {
  146. error('could not log in; action was not successful: ' + JSON.stringify(data));
  147. process.exit(-1);
  148. }
  149. } catch (e) {}
  150. send(connection, '|/trn ' + config.nick + ',0,' + data);
  151. }.bind(this));
  152. }.bind(this));
  153.  
  154. req.on('error', function(err) {
  155. error('login error: ' + sys.inspect(err));
  156. });
  157.  
  158. if (data) req.write(data);
  159. req.end();
  160. break;
  161. case 'updateuser':
  162. if (spl[2] !== config.nick) return;
  163.  
  164. if (spl[3] !== '1') {
  165. error('failed to log in, still guest');
  166. process.exit(-1);
  167. }
  168.  
  169. ok('logged in as ' + spl[2] + '^-^');
  170.  
  171. this.msgQueue.push('|/blockchallenges');
  172. for (var i = 0, len = config.rooms.length; i < len; i++) {
  173. var room = toId(config.rooms[i]);
  174. if (room === 'lobby' && config.serverid === 'showdown') continue;
  175. this.msgQueue.push('|/join ' + room);
  176. }
  177. for (var i = 0, len = config.privaterooms.length; i < len; i++) {
  178. var room = toId(config.privaterooms[i]);
  179. if (room === 'lobby' && config.serverid === 'showdown') continue;
  180. this.msgQueue.push('|/join ' + room);
  181. }
  182. this.msgDequeue = setInterval(function() {
  183. var msg = this.msgQueue.shift();
  184. if (msg) return send(connection, msg);
  185. clearInterval(this.msgDequeue);
  186. this.msgDequeue = null;
  187. }.bind(this), 750);
  188. setInterval(this.cleanChatData.bind(this), 30 * 60 * 1000);
  189. break;
  190. case 'c':
  191. var by = spl[2];
  192. spl = spl.splice(3).join('|');
  193. this.processChatData(toId(by), room, connection, spl);
  194. this.chatMessage(spl, by, room, connection);
  195. if (toId(by) === toId(config.nick) && ' +%@#~'.indexOf(by.charAt(0)) > -1) this.ranks[room] = by.charAt(0);
  196. break;
  197. case 'c:':
  198. var by = spl[3];
  199. spl = spl.splice(4).join('|');
  200. this.processChatData(toId(by), room, connection, spl);
  201. this.chatMessage(spl, by, room, connection);
  202. if (toId(by) === toId(config.nick) && ' +%@#~'.indexOf(by.charAt(0)) > -1) this.ranks[room] = by.charAt(0);
  203. break;
  204. case 'pm':
  205. var by = spl[2];
  206. spl = spl.splice(4).join('|');
  207. if (toId(by) === toId(config.nick) && ' +%@#~'.indexOf(by.charAt(0)) > -1) this.ranks[room] = by.charAt(0);
  208. this.chatMessage(spl, by, ',' + by, connection);
  209. break;
  210. case 'N':
  211. var by = spl[2];
  212. this.updateSeen(spl[3], spl[1], toId(by));
  213. if (toId(by) !== toId(config.nick) || ' +%@&#~'.indexOf(by.charAt(0)) === -1) return;
  214. this.ranks[toId(this.room === '' ? 'lobby' : this.room)] = by.charAt(0);
  215. this.room = '';
  216. break;
  217. case 'J':
  218. case 'j':
  219. var by = spl[2];
  220. this.updateSeen(by, spl[1], (this.room === '' ? 'lobby' : this.room));
  221. if (toId(by) === toId(config.nick) && ' +%@&#~'.indexOf(by.charAt(0)) > -1) this.ranks[room] = by.charAt(0);
  222. if (['goddessbriyella', 'themansavage', 'omegaxis14'].indexOf(toId(by)) > -1) {
  223. this.say(connection, room, '/w ' + toId(by) + ', **#warn** __is a new command that has been made for Moderators and Room Owners. To use the command, **PM Slowbro Bot** with this syntax:__ #warn **[user]**, **[warn reason]**');
  224. this.say(connection, room, '/w ' + toId(by) + ', __This command is not to be abused and is for purely moderation purposes, thanks!^-^ ~Alpha-Kun__');
  225. }
  226. /* if (toId(by) == 'goddessbriyella') this.say(connection, room, 'Haaii Briyella!^-^ I missed you ;~;');
  227. if (toId(by) == 'themansavage') this.say(connection, room, 'Hey Butch :3');
  228. if (toId(by) == 'omegaxis14') this.say(connection, room, '**om**e**g**a o3o hai :3');
  229. if (toId(by) == 'starbloom') this.say(connection, room, 'Haaii Kat^-^ How are you? :3');
  230. */
  231. break;
  232. case 'l':
  233. case 'L':
  234. var by = spl[2];
  235. this.updateSeen(by, spl[1], (this.room === '' ? 'lobby' : this.room));
  236. this.room = '';
  237. break;
  238. case 'raw':
  239. if (/[3-9] ?days/i.test(spl[2])) this.say(connection, room, 'zarel pls ;-;');
  240. break;
  241. case 'tournament':
  242. if (/end\|\{"results":\[\[/i.test(spl[2])) this.say(connection, room, 'Good job ' + spl[2].substr(spl[2].indexOf("results") + 12, spl[2].indexOf("\"\],\[")) + ' on winning the tournament!^~^');
  243. break;
  244. }
  245. },
  246. chatMessage: function(message, by, room, connection) {
  247. var now = Date.now();
  248. var cmdrMessage = '["' + room + '|' + by + '|' + message + '"]';
  249. message = message.trim();
  250. // auto accept invitations to rooms
  251. if (room.charAt(0) === ',' && message.substr(0, 8) === '/invite ' && this.hasRank(by, '%@&~') && !(config.serverid === 'showdown' && toId(message.substr(8)) === 'lobby')) {
  252. this.say(connection, '', '/join ' + message.substr(8));
  253. }
  254. if (message.substr(0, config.commandcharacter.length) !== config.commandcharacter || toId(by) === toId(config.nick)) return;
  255.  
  256. message = message.substr(config.commandcharacter.length);
  257. var index = message.indexOf(' ');
  258. var arg = '';
  259. if (index > -1) {
  260. var cmd = message.substr(0, index);
  261. arg = message.substr(index + 1).trim();
  262. } else {
  263. var cmd = message;
  264. }
  265.  
  266. if (Commands[cmd]) {
  267. var failsafe = 0;
  268. while (typeof Commands[cmd] !== "function" && failsafe++ < 10) {
  269. cmd = Commands[cmd];
  270. }
  271. if (typeof Commands[cmd] === "function") {
  272. cmdr(cmdrMessage);
  273. Commands[cmd].call(this, arg, by, room, connection);
  274. } else {
  275. error("invalid command type for " + cmd + ": " + (typeof Commands[cmd]));
  276. }
  277. }
  278. /* if (config.allowmute && this.hasRank(this.ranks[room] || ' ', '%@&#~') && config.whitelist.indexOf(user) === -1) {
  279. var useDefault = !(this.settings['modding'] && this.settings['modding'][room]);
  280. // moderation for abusing bot commands
  281. for (cmd in Commands)
  282. var isAbusing = (this.chatData.commandFlooding[room][cmd].times.length >= 6 && (time - this.chatData.commandFlooding[room][cmd].times[this.chatData.commandFlooding[room][cmd].times.length - 10]) < 30 * 1000
  283. && (time - this.chatData.commandFlooding[room][cmd].times[this.chatData.commandFlooding[room][cmd].times.length - 6]) > (6 * 30 * 1000));
  284. if ((useDefault || this.settings['modding'][room]['flooding'] !== 0) && isAbusing) this.say(connection, room, '/wall Please stop abusing bot commands, they have all been set to # until things settle down again.');
  285. } */
  286. },
  287. say: function(connection, room, text) {
  288. if (room.charAt(0) !== ',') {
  289. var str = (room !== 'lobby' ? room : '') + '|' + text;
  290. send(connection, str);
  291. } else {
  292. room = room.substr(1);
  293. var str = '|/pm ' + room + ', ' + text;
  294. send(connection, str);
  295. }
  296. },
  297. shorten: function(link) {
  298. var BitlyAPI = require("node-bitlyapi");
  299. var Bitly = new BitlyAPI({
  300. client_id: "Something",
  301. client_secret: "Something"
  302. });
  303. var self = this;
  304. Bitly.setAccessToken("c8a15558cbf4a555391b974849d7684e211fb707");
  305. Bitly.shortenLink(link, function(err, results) {
  306. var resObject = eval("(" + results + ")");
  307. console.log('url: ' + resObject.data.url);
  308. bitLink += resObject.data.url;
  309. console.log('bitLink: ' + bitLink);
  310. });
  311. },
  312. hasRank: function(user, rank) {
  313. var hasRank = (rank.split('').indexOf(user.charAt(0)) !== -1) || (config.excepts.indexOf(toId(user)) !== -1);
  314. return hasRank;
  315. },
  316. canUse: function(cmd, room, user) {
  317. var canUse = false;
  318. var ranks = ' +%@&#~';
  319. if (!this.settings[cmd] || !this.settings[cmd][room]) {
  320. canUse = this.hasRank(user, ranks.substr(ranks.indexOf((cmd === 'autoban' || cmd === 'banword') ? '#' : config.defaultrank)));
  321. } else if (this.settings[cmd][room] === true) {
  322. canUse = true;
  323. } else if (ranks.indexOf(this.settings[cmd][room]) > -1) {
  324. canUse = this.hasRank(user, ranks.substr(ranks.indexOf(this.settings[cmd][room])));
  325. }
  326. return canUse;
  327. },
  328. sendMail: function(user, room) {
  329. if (!this.messages || !this.messages[user]) return false;
  330. if (this.messages[user]) {
  331. console.log(user + ' has mail.');
  332. return true;
  333. }
  334. },
  335. processChatData: function(user, room, connection, msg, by) {
  336. var botName = msg.toLowerCase().indexOf(toId(config.nick));
  337.  
  338. if (toId(user.substr(1)) === toId(config.nick)) {
  339. this.ranks[room] = user.charAt(0);
  340. return;
  341. }
  342. var by = user;
  343. user = toId(user);
  344. var user = toId(by);
  345.  
  346. if (!user || room.charAt(0) === ',') return;
  347. room = toId(room);
  348. msg = msg.trim().replace(/[ \u0000\u200B-\u200F]+/g, ' '); // removes extra spaces and null characters so messages that should trigger stretching do so
  349.  
  350. this.updateSeen(user, 'c', room);
  351. var now = Date.now();
  352. if (!this.chatData[user]) this.chatData[user] = {
  353. zeroTol: 0,
  354. lastSeen: '',
  355. seenAt: now
  356. };
  357.  
  358. var userData = this.chatData[user];
  359. if (!this.chatData[user][room]) this.chatData[user][room] = {
  360. times: [],
  361. points: 0,
  362. lastAction: 0
  363. };
  364.  
  365. var roomData = userData[room];
  366. roomData.times.push(now);
  367. this.chatData[user][room].times.push(now);
  368.  
  369. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  370. /////// Regex /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  371. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  372.  
  373. //Greetings & Farewells
  374. if (/(good)? ?(night|nite) (everyone|guys|friends|all)/i.test(msg) && toId(config.nick) !== toId(by)) this.say(connection, room, 'Goodnight ' + by + '^-^');
  375. if (/i(\'?m| am).*go.*to (bed|sleep)/i.test(msg) && toId(config.nick) !== toId(by)) this.say(connection, room, 'Goodnight ' + by + '^-^');
  376. if (/i(\'?m| am).*go.*to (eat)/i.test(msg) && toId(config.nick) !== toId(by)) this.say(connection, room, 'omnomnom Have a nice meal ' + by + '^-^');
  377. if (/(hey|hi|hello|ha+?i+) (everyone|guys|friends|all)/i.test(msg) && toId(config.nick) !== toId(by)) this.say(connection, room, 'Haaii ' + by + '^-^');
  378. if (/(bye|g2g|gtg|ba+?i+) (everyone|guys|friends|all)/i.test(msg) && toId(config.nick) !== toId(by)) this.say(connection, room, 'Baaii ' + by + '~');
  379. if (/g2g/i.test(msg) && toId(config.nick) !== toId(by)) this.say(connection, room, 'Baaii ' + by + '~');
  380. if (/how(\'re)? (r|are|is) (u|you|chu)?/i.test(msg)) this.say(connection, room, 'I am good, how about you ' + by + '? :o');
  381.  
  382.  
  383. //Miscellaneous
  384. if (/(why are there )?so many bots( in here)?\??/i.test(msg)) this.say(connection, room, 'Sorry if I\'m intruding, I\'ll try and be as quiet as possible! >~<');
  385. if (/(mashiro|mashy|goddess ?mashiro)/i.test(msg) && isAfk == true) this.say(connection, room, '/w ' + by + ', Mashiro-chan is AFK right now, leave a PM or check back in a bit, thanks^-^');
  386. if (/(why are there )?so many goddess(es)?( in here)?\??/i.test(msg)) this.say(connection, room, 'Mashiro is just a Briyella wannabe o3o');
  387. if (/(9[0-9]|100)% compatible/i.test(msg)) {
  388. var rand = ~~(2 * Math.random()) + 1;
  389. if (rand == 1) this.say(connection, room, '__it was meant to be :O__');
  390. if (rand == 2) this.say(connection, room, '/me plays wedding music');
  391. }
  392. if (/(1| )[0-9]% compatible/i.test(msg)) this.say(connection, room, '__rip ;-;__');
  393. if (/I(\'?m| am) back/i.test(msg)) this.say(connection, room, 'Hi back, I am Slowbro Bot o3o');
  394. if (/I(\'?m| am) tired/i.test(msg)) this.say(connection, room, 'Hi tired, I am Slowbro Bot o3o');
  395. if (/I(\'?m| am) hungry/i.test(msg)) this.say(connection, room, 'Hi hungry, I am Slowbro Bot o3o');
  396. if (/(cut|kick|punch(es)?|hit|hurt|slap|stab)s? (goddess)? ?mash(y|iro)/i.test(msg)) this.say(connection, room, 'D-don\'t hurt my creator..!! >~<');
  397. if (/\brip\b/i.test(msg) && toId(by) !== toId('mashibot')) {
  398. var rand = ~~(13 * Math.random()) + 1;
  399. if (rand == 1) this.say(connection, room, '__rip in pepperoni ;-;__');
  400. if (rand == 2) this.say(connection, room, '__rip in pieces ;-;__');
  401. if (rand == 3) this.say(connection, room, '__rip in pepsi ;-;__');
  402. if (rand == 4) this.say(connection, room, '__rip in PixelMoniac ;-;__');
  403. if (rand == 5) this.say(connection, room, '__rip in pizza ;-;__');
  404. if (rand == 6) this.say(connection, room, '__rip in pringles ;-;__');
  405. if (rand == 7) this.say(connection, room, '__rip in pretzels ;-;__');
  406. if (rand == 8) this.say(connection, room, '__rip in pistachios ;-;__');
  407. if (rand == 9) this.say(connection, room, '__rip in pasta ;-;__');
  408. if (rand == 10) this.say(connection, room, '__rip in peaches ;-;__');
  409. if (rand == 11) this.say(connection, room, '__rip in pumpkins ;-;__');
  410. if (rand == 12) this.say(connection, room, '__rip in papayas ;-;__');
  411. if (rand == 13) this.say(connection, room, '__rip in potatoes ;-;__');
  412. }
  413. if (/\bej\b/i.test(msg) && toId(by) !== toId('mashibot')) {
  414. var rand = ~~(13 * Math.random()) + 1;
  415. if (rand == 1) this.say(connection, room, '__andy saks__');
  416. if (rand == 2) this.say(connection, room, '__pindakaas__');
  417. if (rand == 3) this.say(connection, room, '__IK WIL KOEKJES__');
  418. if (rand == 4) this.say(connection, room, '__slooowbrooo__');
  419. if (rand == 5) this.say(connection, room, '__plalalalala__');
  420. if (rand == 6) this.say(connection, room, '__lolololol__');
  421. if (rand == 7) this.say(connection, room, '__keukenrol__');
  422. if (rand == 8) this.say(connection, room, '__banaan__');
  423. if (rand == 9) this.say(connection, room, '__ontbijtkoek__');
  424. if (rand == 10) this.say(connection, room, '__I like turltes__');
  425. }
  426. // if (/(rekt|burn)/i.test(msg)) this.say(connection, room, '!data Rawst Berry');
  427.  
  428. //Favorite Pokemon
  429. if (/what(\'s| is)? (goddess ?)?mash(i|y|iro)?(chan|bot)?\'?s? fav(e|ou?rite)? poke(mon)?\??/i.test(msg)) this.say(connection, room, '!data Ninetales');
  430. if (/what(\'s| is)? (goddess ?)?bri(yella)?\'?s? fav(e|ou?rite)? poke(mon)?\??/i.test(msg)) this.say(connection, room, '!data Vespiquen');
  431. if (/what(\'s| is)? omega-?(xis14)?\'?s? fav(e|ou?rite)? poke(mon)?\??/i.test(msg)) this.say(connection, room, '!data Mew');
  432. if (/what(\'s| is)? (the|butch) ?mansavage\'?s? fav(e|ou?rite)? poke(mon)?\??/i.test(msg) || /what(\'s| is)? butch\'?s? fav(ou?rite)? poke(mon)?\??/i.test(msg)) this.say(connection, room, '!data Rhyperior');
  433.  
  434. //League Names
  435. if (/(does)? ?(some|any)(one|1|body) play (league( of legends)?|lol)/i.test(msg)) this.say(connection, room, 'Add Mashiro-chan on League if you want to play: LeInfiniti');
  436. if (/what(\'s| is)? jess(ilina| league)?\'?s? (league( of legends)?|lol)( name)?/i.test(msg)) this.say(connection, room, 'Jess\'s League name is: namegohere');
  437.  
  438. //osu! room
  439. if (/(pronounce|say) osu/i.test(msg)) {
  440. if (room !== 'osu') return false;
  441. this.say(connection, room, 'osu! is pronounced like \"os\", not \"osu\". This is because when a \'u\' follows an \'s\' in Japanese, the \'u\' is silent.');
  442. }
  443. if (/what(\'s| is)? osu/i.test(msg)) {
  444. if (room !== 'osu') return false;
  445. this.say(connection, room, 'osu! is a Japanese rhythm game where the player hits notes in time with the beat of the music. There are 5 different game modes, the most popular being standard osu! and osu! mania.');
  446. }
  447.  
  448. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  449. /////// /me Regex /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  450. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  451. var botSearch = toId(msg);
  452. if (botSearch.toLowerCase().indexOf(toId(config.nick)) > -1 && toId(by) !== toId(config.nick)) {
  453. if (/^\/me/i.test(msg) && user !== botName) {
  454. if (/(pet|stroke)s?/i.test(msg)) {
  455. this.say(connection, room, '/me purr'); return;}
  456.  
  457. if (/licks?/i.test(msg)) {
  458. this.say(connection, room, '/me squirms ;~;'); return;}
  459.  
  460. if (/(kiss(es)?|kissu)/i.test(msg)) {
  461. this.say(connection, room, '/me blushes deeply');
  462. this.say(connection, room, 'o////o'); return;}
  463.  
  464. if (/(eat|nom|nibble)s?/i.test(msg)) {
  465. this.say(connection, room, 'nuuu dun eat me ;~;');
  466. this.say(connection, room, '/me hides'); return;}
  467.  
  468. if (/(hit|stab|punch|kick|hurt)s?/i.test(msg)) {
  469. this.say(connection, room, '/me cries in pain ;-;'); return;}
  470.  
  471. if (/(hug|glomp|squeeze)s?/i.test(msg)) {
  472. this.say(connection, room, '/me squee~ :3'); return;}
  473.  
  474. if (/(cuddle|snuggle)s?/i.test(msg)) {
  475. this.say(connection, room, '/me cuddles ' + by + ' back warmly<3'); return;}
  476.  
  477. if (/pokes?/i.test(msg)) {
  478. this.say(connection, room, 'oww!! >~<'); return;}
  479.  
  480. if (/(gives? food|a cookie)/i.test(msg)) {
  481. this.say(connection, room, '/me noms :3'); return;}
  482.  
  483. if (/(tickle)s?/i.test(msg)) {
  484. this.say(connection, room, '/me giggles and squirms');
  485. this.say(connection, room, 'Staaahhhpp!! ;~;'); return;}
  486. }
  487. }
  488.  
  489. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  490. /////// Moderation Detection //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  491. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  492.  
  493. /* // this deals with punishing rulebreakers, but note that the bot can't think, so it might make mistakes
  494. if (config.allowmute && this.hasRank(this.ranks[room] || ' ', '%@&#~') && config.whitelist.indexOf(user) === -1) {
  495. var useDefault = !(this.settings['modding'] && this.settings['modding'][room]);
  496. var pointVal = 0;
  497. var muteMessage = '';
  498. var warnMessage = '';
  499.  
  500. // moderation for flooding (more than x lines in y seconds)
  501. var times = roomData.times;
  502. var timesLen = times.length;
  503. var isFlooding = (timesLen >= FLOOD_MESSAGE_NUM && (now - times[timesLen - FLOOD_MESSAGE_NUM]) < FLOOD_MESSAGE_TIME &&
  504. (now - times[timesLen - FLOOD_MESSAGE_NUM]) > (FLOOD_PER_MSG_MIN * FLOOD_MESSAGE_NUM));
  505. if ((useDefault || !('flooding' in modSettings)) && isFlooding) {
  506. if (pointVal < 2) {
  507. pointVal = 2;
  508. muteMessage = ', Please stop flooding the chat! ;~;';
  509. }
  510. } */
  511.  
  512. // moderation for caps (over x% of the letters in a line of y characters are capital)
  513. /* var capsMatch = msg.replace(/[^A-Za-z]/g, '').match(/[A-Z]/g);
  514. if ((useDefault || !('caps' in modSettings)) && capsMatch && toId(msg).length > MIN_CAPS_LENGTH && (capsMatch.length >= ~~(toId(msg).length * MIN_CAPS_PROPORTION))) {
  515. if (pointVal < 1) {
  516. pointVal = 1;
  517. muteMessage = ', Don\'t be so loud wtf ;-;';
  518. }
  519. }
  520. // moderation for stretching (over x consecutive characters in the message are the same)
  521. var stretchMatch = /(.)\1{7,}/gi.test(msg) || /(..+)\1{4,}/gi.test(msg); // matches the same character (or group of characters) 8 (or 5) or more times in a row
  522. if ((useDefault || !('stretching' in modSettings)) && stretchMatch) {
  523. if (pointVal < 1) {
  524. pointVal = 1;
  525. muteMessage = ', This isn\'t yoga, no streching please ._.';
  526. }
  527. }
  528.  
  529. if (pointVal > 0 && !(now - this.chatData[user][room].lastAction < ACTION_COOLDOWN)) {
  530. var cmd = 'mute';
  531. // defaults to the next punishment in config.punishVals instead of repeating the same action (so a second warn-worthy
  532. // offence would result in a mute instead of a warn, and the third an hourmute, etc)
  533. if (this.chatData[user][room].points >= pointVal && pointVal < 4) {
  534. this.chatData[user][room].points++;
  535. cmd = config.punishvals[this.chatData[user][room].points] || cmd;
  536. } else { // if the action hasn't been done before (is worth more points) it will be the one picked
  537. cmd = config.punishvals[pointVal] || cmd;
  538. this.chatData[user][room].points = pointVal; // next action will be one level higher than this one (in most cases)
  539. }
  540. if (config.privaterooms.indexOf(room) >= 0 && cmd === 'warn') cmd = 'mute'; // can't warn in private rooms
  541. // if the bot has % and not @, it will default to hourmuting as its highest level of punishment instead of roombanning
  542. if (this.chatData[user][room].points >= 4 && !this.hasRank(this.ranks[room] || ' ', '@&#~')) cmd = 'hourmute';
  543. if (this.chatData[user].zeroTol > 4) { // if zero tolerance users break a rule they get an instant roomban or hourmute
  544. muteMessage = ', Automated response: zero tolerance user';
  545. cmd = this.hasRank(this.ranks[room] || ' ', '@&#~') ? 'roomban' : 'hourmute';
  546. }
  547. if (this.chatData[user][room].points >= 2) this.chatData[user].zeroTol++; // getting muted or higher increases your zero tolerance level (warns do not)
  548. this.chatData[user][room].lastAction = now;
  549. if (this.chatData[user][room].points <= 2) this.say(connection, room, user + ', ' + warnMessage);
  550. if (this.chatData[user][room].points >= 3) this.say(connection, room, '/' + cmd + ' ' + user + muteMessage);
  551. }
  552. } */
  553. },
  554. cleanChatData: function() {
  555.  
  556. var chatData = this.chatData;
  557. for (var user in chatData) {
  558. for (var room in chatData[user]) {
  559. var roomData = chatData[user][room];
  560. if (!Object.isObject(roomData)) continue;
  561.  
  562. if (!roomData.times || !roomData.times.length) {
  563. delete chatData[user][room];
  564. continue;
  565. }
  566. var newTimes = [];
  567. var now = Date.now();
  568. var times = roomData.times;
  569. for (var i = 0, len = times.length; i < len; i++) {
  570. if (now - times[i] < 5 * 1000) newTimes.push(times[i]);
  571. }
  572. newTimes.sort(function(a, b) {
  573. return a - b;
  574. });
  575. roomData.times = newTimes;
  576. if (roomData.points > 0 && roomData.points < 4) roomData.points--;
  577. }
  578. }
  579. },
  580. updateSeen: function(user, type, detail) {
  581. if (type !== 'n' && config.rooms.indexOf(detail) === -1 || config.privaterooms.indexOf(toId(detail)) > -1) return;
  582. var now = Date.now();
  583. if (!this.chatData[user]) this.chatData[user] = {
  584. zeroTol: 0,
  585. lastSeen: '',
  586. seenAt: now
  587. };
  588. if (!detail) return;
  589. var userData = this.chatData[user];
  590. var msg = '';
  591. switch (type) {
  592. case 'j':
  593. case 'J':
  594. msg += 'joining ';
  595. break;
  596. case 'l':
  597. case 'L':
  598. msg += 'leaving ';
  599. break;
  600. case 'c':
  601. case 'c:':
  602. msg += 'chatting in ';
  603. break;
  604. case 'N':
  605. msg += 'changing nick to ';
  606. if (detail.charAt(0) !== ' ') detail = detail.substr(1);
  607. break;
  608. }
  609. msg += detail.trim() + '.';
  610. userData.lastSeen = msg;
  611. userData.seenAt = now;
  612. },
  613. getTimeAgo: function(time) {
  614. time = ~~((Date.now() - time) / 1000);
  615.  
  616. var seconds = time % 60;
  617. var times = [];
  618. if (seconds) times.push(seconds + (seconds === 1 ? ' second' : ' seconds'));
  619. if (time >= 60) {
  620. time = ~~((time - seconds) / 60);
  621. var minutes = time % 60;
  622. if (minutes) times.unshift(minutes + (minutes === 1 ? ' minute' : ' minutes'));
  623. if (time >= 60) {
  624. time = ~~((time - minutes) / 60);
  625. hours = time % 24;
  626. if (hours) times.unshift(hours + (hours === 1 ? ' hour' : ' hours'));
  627. if (time >= 24) {
  628. days = ~~((time - hours) / 24);
  629. if (days) times.unshift(days + (days === 1 ? ' day' : ' days'));
  630. }
  631. }
  632. }
  633. if (!times.length) return '0 seconds';
  634. return times.join(', ');
  635. },
  636. writeSettings: (function() {
  637. var writing = false;
  638. var writePending = false; // whether or not a new write is pending
  639. var finishWriting = function() {
  640. writing = false;
  641. if (writePending) {
  642. writePending = false;
  643. this.writeSettings();
  644. }
  645. };
  646. return function() {
  647. if (writing) {
  648. writePending = true;
  649. return;
  650. }
  651. writing = true;
  652. var data = JSON.stringify(this.settings);
  653. fs.writeFile('settings.json.0', data, function() {
  654. // rename is atomic on POSIX, but will throw an error on Windows
  655. fs.rename('settings.json.0', 'settings.json', function(err) {
  656. if (err) {
  657. // This should only happen on Windows.
  658. fs.writeFile('settings.json', data, finishWriting);
  659. return;
  660. }
  661. finishWriting();
  662. });
  663. });
  664. };
  665. })(),
  666. writeMessages: (function() {
  667. var writing = false;
  668. var writePending = false; // whether or not a new write is pending
  669. var finishWriting = function() {
  670. writing = false;
  671. if (writePending) {
  672. writePending = false;
  673. this.writeMessages();
  674. }
  675. };
  676. return function() {
  677. if (writing) {
  678. writePending = true;
  679. return;
  680.  
  681. }
  682. writing = true;
  683. var data = JSON.stringify(this.messages);
  684. fs.writeFile('messages.json.0', data, function() {
  685. // rename is atomic on POSIX, but will throw an error on Windows
  686. fs.rename('messages.json.0', 'messages.json', function(err) {
  687. if (err) {
  688. // This should only happen on Windows.
  689. fs.writeFile('messages.json', data, finishWriting);
  690. return;
  691. }
  692. finishWriting();
  693. });
  694. });
  695. };
  696. })(),
  697. writeQuotes: (function() {
  698. var writing = false;
  699. var writePending = false; // whether or not a new write is pending
  700. var finishWriting = function() {
  701. writing = false;
  702. if (writePending) {
  703. writePending = false;
  704. this.writeQuotes();
  705. }
  706. };
  707. return function() {
  708. if (writing) {
  709. writePending = true;
  710. return;
  711.  
  712. }
  713. writing = true;
  714. var data = JSON.stringify(this.quotes);
  715. fs.writeFile('quotes.json.0', data, function() {
  716. // rename is atomic on POSIX, but will throw an error on Windows
  717. fs.rename('quotes.json.0', 'quotes.json', function(err) {
  718. if (err) {
  719. // This should only happen on Windows.
  720. fs.writeFile('quotes.json', data, finishWriting);
  721. return;
  722. }
  723. finishWriting();
  724. });
  725. });
  726. };
  727. })(),
  728. uncacheTree: function(root) {
  729. var uncache = [require.resolve(root)];
  730. do {
  731. var newuncache = [];
  732. for (var i = 0; i < uncache.length; ++i) {
  733. if (require.cache[uncache[i]]) {
  734. newuncache.push.apply(newuncache,
  735. require.cache[uncache[i]].children.map(function(module) {
  736. return module.filename;
  737. })
  738. );
  739. delete require.cache[uncache[i]];
  740. }
  741. }
  742. uncache = newuncache;
  743. } while (uncache.length > 0);
  744. },
  745. getDocMeta: function(id, callback) {
  746. https.get('https://www.googleapis.com/drive/v2/files/' + id + '?key=' + config.googleapikey, function(res) {
  747. var data = '';
  748. res.on('data', function(part) {
  749. data += part;
  750. });
  751. res.on('end', function(end) {
  752. var json = JSON.parse(data);
  753. if (json) {
  754. callback(null, json);
  755. } else {
  756. callback('Invalid response', data);
  757. }
  758. });
  759. });
  760. },
  761. getDocCsv: function(meta, callback) {
  762. https.get('https://docs.google.com/spreadsheet/pub?key=' + meta.id + '&output=csv', function(res) {
  763. var data = '';
  764. res.on('data', function(part) {
  765. data += part;
  766. });
  767. res.on('end', function(end) {
  768. callback(data);
  769. });
  770. });
  771. }
  772. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement