diff --git a/xtrn/mrc/chat-with-mrc-stats-example.msg b/xtrn/mrc/chat-with-mrc-stats-example.msg new file mode 100644 index 0000000000000000000000000000000000000000..0c738249f2b74ad46dd5593795d09b80a65bf461 --- /dev/null +++ b/xtrn/mrc/chat-with-mrc-stats-example.msg @@ -0,0 +1,23 @@ +NHC@HOT@N@CLEAR@ +4CÚÄÄÄÄÄÄÄÄÄÄÄK¿ +C³ HYChat Menu N4K³ +CÀKÄÄÄÄÄÄÄÄÄÄÄÙ0BÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +ÛßW‰Bß4 HWJoin a Chat NBßW‰BßÛ +Û HCJY NCJoin/initiate multinode chatW…BÛ +Û HCPNC Join/start private node/node chatG BÛ +Û HCCY NCChat with Sysop: HY@SYSAVAIL-L####@NG BÛ +Û HCTY NCTalk with The Guru (AI)WŠBÛ +Û HCFY NCFinger (query) remote user/systemW BÛ +Û HCRY NCInternet Relay Chat (IRC)WˆBÛ +Û HCIY NCInterBBS Instant MessagingW‡BÛ +Û²ÄÄÄÄÄÄÄÄÄÄÄÄß4 HWToggles NBßÄÄÄÄÄÄÄÄÄÄÄÄ²Û +Û HCD NCChat availabilityW…Cstate: HY@PAGER-L3@W NBÛ +Û HCA NCNode activity alertsW‚Cstate: HY@ALERTS-L3@NG BÛ +ÛHC SY NCSplit-screen chatW…Cstate:G HY@SPLITP-L3@N BÛ +Û²ÄÄÄÄÄÄÄÄÄÄÄß4 HWMRC Stats NBßÄÄÄÄÄÄÄÄÄÄÄ²Û +ÛW HCM NCMulti-Relay ChatW‚CActivity:W…BÛ +4K 0W‚CBBSes:W„CRooms:W„CUsers:W…H4C +NBÛ²ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ²Û +Û HCQY NCQuit chat menuW“BÛ +4K C HYAnytime: C^UN4Csers online H^PN4Crivate msgH +N@EXEC:mrc-display-menu-stats@Z \ No newline at end of file diff --git a/xtrn/mrc/chat_sec-with-mrc-example.js b/xtrn/mrc/chat_sec-with-mrc-example.js new file mode 100644 index 0000000000000000000000000000000000000000..37f23aa6b0aad9e00bc47eba6fd1869529444701 --- /dev/null +++ b/xtrn/mrc/chat_sec-with-mrc-example.js @@ -0,0 +1,162 @@ +// Chat Section for any/all Synchronet command shells + +"use strict"; + +require("sbbsdefs.js", 'USER_EXPERT'); +require("nodedefs.js", 'NODE_CHAT'); +require("text.js", 'R_Chat'); + +// Over-ride these default values by creating/modifying the [chat] section in your ctrl/modopts.ini file +var options = load("modopts.js", "chat"); +if (!options) + options = load("modopts.js", "chat_sec"); +if (!options) + options = {}; +if (options.irc === undefined) + options.irc = true; +var irc_servers = ["irc.synchro.net 6667"]; +if (options.irc_server !== undefined) + irc_servers = options.irc_server.split(','); +var irc_channels = ["#Synchronet"]; +if (options.irc_channel !== undefined) + irc_channels = options.irc_channel.split(','); +if (options.irc_seclevel === undefined) + options.irc_seclevel = 90; +if (options.finger === undefined) + options.finger = true; +if (options.imsg === undefined) + options.imsg = true; + +for(var i in irc_servers) + irc_servers[i] = irc_servers[i].trim(); +for(var i in irc_channels) + irc_channels[i] = irc_channels[i].trim(); + +if(user.security.restrictions & UFLAG_C) { + write(bbs.text(R_Chat)); + exit(0); +} + +function on_or_off(on) +{ + return bbs.text(on ? On : Off); +} + +// Set continue point for main menu commands +menu: +while(bbs.online && !console.aborted) { + var str=""; + + // Display TEXT\MENU\CHAT.* if not in expert mode + if(!(user.settings & USER_EXPERT)) { + bbs.menu("chat"); + } + + // Update node status + bbs.node_action = NODE_CHAT; + bbs.nodesync(); + write(bbs.text(ChatPrompt)); + + var keys = "ACDJMPQST?\r"; // M added as a valid option for MRC + if(options.imsg && user.compare_ars(options.imsg_requirements)) + keys += "I"; + if(options.irc && user.compare_ars(options.irc_requirements)) + keys += "R"; + if(options.finger && user.compare_ars(options.finger_requirements)) + keys += "F"; + switch(console.getkeys(keys, K_UPPER)) { + case "S": + var val = user.chat_settings ^= CHAT_SPLITP; + write("\x01n\r\nPrivate split-screen chat is now: \x01h"); + writeln(on_or_off(val & CHAT_SPLITP)); + break; + case "A": + var val = user.chat_settings ^= CHAT_NOACT; + write("\x01n\r\nNode activity alerts are now: \x01h"); + writeln(on_or_off(!(val & CHAT_NOACT))); + system.node_list[bbs.node_num-1].misc ^= NODE_AOFF; + break; + case 'D': + var val = user.chat_settings ^= CHAT_NOPAGE; + write("\x01n\r\nUser chat/messaging availability is now: \x01h"); + writeln(on_or_off(!(val & CHAT_NOPAGE))); + system.node_list[bbs.node_num-1].misc ^= NODE_POFF; + break; + case 'F': + writeln(""); + load("finger.js"); + break; + case 'I': + writeln(""); + load({}, "sbbsimsg.js"); + break; + case 'R': + { + var server = irc_servers[0]; + if(irc_servers.length > 1) { + for(var i = 0; i < irc_servers.length; i++) + console.uselect(i, "IRC Server", irc_servers[i]); + var i = console.uselect(); + if(i < 0) + break; + server = irc_servers[i]; + } + if(user.security.level >= options.irc_seclevel || user.security.exemptions&UFLAG_C) { + write("\r\n\x01n\x01y\x01hIRC Server: "); + server = console.getstr(server, 40, K_EDIT|K_LINE|K_AUTODEL); + if(console.aborted || server.length < 4) + break; + } + // Optional list of channels per server (e.g. irc.synchro.net = #synchronet, #bbs) + var channel_list = irc_channels; + if(options[server] !== undefined) + channel_list = options[server].split(','); + var channel; + if(channel_list.length > 1) { + for(var i = 0; i < channel_list.length; i++) { + channel_list[i] = channel_list[i].trim(); + console.uselect(i, "IRC Channel", channel_list[i]); + } + var i = console.uselect(); + if(i < 0) + break; + channel = channel_list[i]; + } else { + write("\r\n\x01n\x01y\x01hIRC Channel: "); + channel = console.getstr(channel_list[0], 40, K_EDIT|K_LINE|K_AUTODEL); + } + if(server.indexOf(' ') < 0) + server += " 6667"; + if(!console.aborted && channel.length) { + log("IRC to " + server + " " + channel); + bbs.exec("?irc -a " + server + " " + channel); // can't be load()ed because it calls exit() + } + break; + } + case 'J': + bbs.multinode_chat(); + break; + case 'P': + bbs.private_chat(); + break; + case 'C': + if(!bbs.page_sysop() + && !deny(format(bbs.text(ChatWithGuruInsteadQ), system.guru || "The Guru"))) + bbs.page_guru(); + break; + case 'T': + bbs.page_guru(); + break; + case '?': + if(user.settings & USER_EXPERT) + bbs.menu("chat"); + break; + + case 'M': // this will directly run the MRC + bbs.exec_xtrn("MRC"); // external program + break; + + default: + break menu; + } +} diff --git a/xtrn/mrc/mrc-client.js b/xtrn/mrc/mrc-client.js index 9f9ae78dbf743e2ba21f041c603846eca32eb1fc..0efe89998d2663d69695ef9abb7b6a25af70ab23 100644 --- a/xtrn/mrc/mrc-client.js +++ b/xtrn/mrc/mrc-client.js @@ -31,49 +31,49 @@ f.close(); f = undefined; const NICK_COLOURS = [ - '\1h\1r', - '\1h\1g', - '\1h\1y', - '\1h\1b', - '\1h\1m', - '\1h\1c', - '\1h\1w', + '\x01h\x01r', + '\x01h\x01g', + '\x01h\x01y', + '\x01h\x01b', + '\x01h\x01m', + '\x01h\x01c', + '\x01h\x01w', // Low colours with reasonable contrast - '\1n\1r', - '\1n\1g', - '\1n\1y', - '\1n\1m', - '\1n\1c', - '\1n\1w' + '\x01n\x01r', + '\x01n\x01g', + '\x01n\x01y', + '\x01n\x01m', + '\x01n\x01c', + '\x01n\x01w' ]; const PIPE_COLOURS = [2, 3, 4, 5, 6, 9, 10, 11, 12, 13, 14, 15]; function pipe_to_ctrl_a(str) { - str = str.replace(/\|00/g, "\1N\1K"); - str = str.replace(/\|01/g, "\1N\1B"); - str = str.replace(/\|02/g, "\1N\1G"); - str = str.replace(/\|03/g, "\1N\1C"); - str = str.replace(/\|04/g, "\1N\1R"); - str = str.replace(/\|05/g, "\1N\1M"); - str = str.replace(/\|06/g, "\1N\1Y"); - str = str.replace(/\|07/g, "\1N\1W"); - str = str.replace(/\|08/g, "\1H\1K"); - str = str.replace(/\|09/g, "\1H\1B"); - str = str.replace(/\|10/g, "\1H\1G"); - str = str.replace(/\|11/g, "\1H\1C"); - str = str.replace(/\|12/g, "\1H\1R"); - str = str.replace(/\|13/g, "\1H\1M"); - str = str.replace(/\|14/g, "\1H\1Y"); - str = str.replace(/\|15/g, "\1H\1W"); - str = str.replace(/\|16/g, "\001" + 0); - str = str.replace(/\|17/g, "\001" + 4); - str = str.replace(/\|18/g, "\001" + 2); - str = str.replace(/\|19/g, "\001" + 6); - str = str.replace(/\|20/g, "\001" + 1); - str = str.replace(/\|21/g, "\001" + 5); - str = str.replace(/\|22/g, "\001" + 3); - str = str.replace(/\|23/g, "\001" + 7); + str = str.replace(/\|00/g, "\x01N\x01K"); + str = str.replace(/\|01/g, "\x01N\x01B"); + str = str.replace(/\|02/g, "\x01N\x01G"); + str = str.replace(/\|03/g, "\x01N\x01C"); + str = str.replace(/\|04/g, "\x01N\x01R"); + str = str.replace(/\|05/g, "\x01N\x01M"); + str = str.replace(/\|06/g, "\x01N\x01Y"); + str = str.replace(/\|07/g, "\x01N\x01W"); + str = str.replace(/\|08/g, "\x01H\x01K"); + str = str.replace(/\|09/g, "\x01H\x01B"); + str = str.replace(/\|10/g, "\x01H\x01G"); + str = str.replace(/\|11/g, "\x01H\x01C"); + str = str.replace(/\|12/g, "\x01H\x01R"); + str = str.replace(/\|13/g, "\x01H\x01M"); + str = str.replace(/\|14/g, "\x01H\x01Y"); + str = str.replace(/\|15/g, "\x01H\x01W"); + str = str.replace(/\|16/g, "\x01" + 0); + str = str.replace(/\|17/g, "\x01" + 4); + str = str.replace(/\|18/g, "\x01" + 2); + str = str.replace(/\|19/g, "\x01" + 6); + str = str.replace(/\|20/g, "\x01" + 1); + str = str.replace(/\|21/g, "\x01" + 5); + str = str.replace(/\|22/g, "\x01" + 3); + str = str.replace(/\|23/g, "\x01" + 7); return str; } @@ -82,11 +82,10 @@ function resize_nicklist(frames, nicks) { return c.length > a ? c.length : a; }, 0)) : 0; frames.nicklist.moveTo(frames.top.x + frames.top.width - 1 - maxlen - 1, 2); - frames.nicklist_divider.moveTo(frames.nicklist.x, 2); frames.nicks.moveTo(frames.nicklist.x + 1, 2); - frames.nicklist.width = maxlen + 2; + frames.nicklist.width = maxlen + (show_nicks ? 2 : 1); frames.nicks.width = maxlen + 1; - frames.output.width = frames.top.width - frames.nicklist.width; + frames.output.width = (frames.top.width - frames.nicklist.width) + 1; } function redraw_nicklist(frames, nicks, colours) { @@ -94,7 +93,7 @@ function redraw_nicklist(frames, nicks, colours) { if (show_nicks) { nicks.forEach(function (e, i) { frames.nicks.gotoxy(1, i + 1); - frames.nicks.putmsg(colours[e] + e + '\1n\1w'); + frames.nicks.putmsg(colours[e] + e + '\x01n\x01w'); }); } } @@ -107,13 +106,8 @@ function init_display() { f.output = new Frame(1, 2, 1, h - 3, BG_BLACK|LIGHTGRAY, f.top); f.divider = new Frame(1, h - 1, w, 1, BG_BLUE|WHITE, f.top); f.nicklist = new Frame(w - 2, 2, 2, h - 3, BG_BLACK|LIGHTGRAY, f.top); - f.nicklist_divider = new Frame(w - 2, 2, 1, h - 3, BG_BLACK|LIGHTGRAY, f.nicklist); f.nicks = new Frame(w - 1, 2, 1, h - 3, BG_BLACK|LIGHTGRAY, f.nicklist); f.input = new Frame(1, h, w, 1, BG_BLACK|WHITE, f.top); - for (var n = 0; n < f.nicklist_divider.height; n++) { - f.nicklist_divider.gotoxy(1, n + 1); - f.nicklist_divider.putmsg(ascii(179)); - } f.output_scroll = new ScrollBar(f.output, { autohide: true }); f.nick_scroll = new ScrollBar(f.nicks, { autohide: true }); f.output.word_wrap = true; @@ -123,6 +117,19 @@ function init_display() { return f; } +function refresh_stats(frames, stats) { + const activity = new Array( + /* 0: NUL */ "\x01H\x01KNUL", + /* 1: LOW */ "\x01H\x01YLOW", + /* 2: MED */ "\x01H\x01GMED", + /* 3: HI */ "\x01H\x01RHI" + ); + frames.divider.clear(); + frames.divider.putmsg(format("\x01w\x01hSTATS\x01b\x01h> \x01w\x01hBBSes \x01b\x01h[\x01w\x01h%d\x01b\x01h] \x01nRooms \x01b\x01h[\x01w\x01h%d\x01b\x01h] \x01nUsers \x01b\x01h[\x01w\x01h%d\x01b\x01h] \x01nLevel \x01b\x01h[%s\x01b\x01h]\x01n", stats[0], stats[1], stats[2], activity[Number(stats[3])])); + frames.divider.gotoxy(frames.divider.width - 5, 1); + frames.divider.putmsg('\x01w\x01h/help'); +} + function append_message(frames, msg) { const top = frames.output.offset.y; if (frames.output.data_height > frames.output.height) { @@ -131,23 +138,27 @@ function append_message(frames, msg) { } frames.output.gotoxy(1, frames.output.height); } - frames.output.putmsg("\1k\1h" + (new Date()).toLocaleTimeString() + "\1k\1h " + msg + '\r\n'); + frames.output.putmsg("\x01k\x01h" + getShortTime(new Date()) + "\x01n " + msg + '\r\n'); frames.output.scroll(0, -1); if (input_state == 'scroll') frames.output.scrollTo(0, top); } +function getShortTime(d) { + return format( "%02d:%02d", d.getHours(), d.getMinutes() ); +} + function display_message(frames, msg, colour) { const body = pipe_to_ctrl_a(truncsp(msg.body) || '').split(' '); - append_message(frames, body[0] + '\1n\1w: ' + body.slice(1).join(' ') + '\1n\1w'); + append_message(frames, body[0] + '\x01n\x01w ' + body.slice(1).join(' ') + '\x01n\x01w'); } function display_server_message(frames, msg) { - append_message(frames, '\1h\1w' + pipe_to_ctrl_a(truncsp(msg) || '')); + append_message(frames, '\x01h\x01w' + pipe_to_ctrl_a(truncsp(msg) || '')); } function display_title(frames, room, title) { frames.title.clear(); - frames.title.putmsg('MRC - #' + room + ' - ' + title); + frames.title.putmsg('MRC\x01b\x01h>\x01w\x01h #' + room + ' - ' + title); } function set_alias(alias) { @@ -203,25 +214,25 @@ function main() { }); session.on('help', function (cmd, help, ars) { if (!ars || user.compare_ars(ars)) { - display_server_message(frames, format('\1h\1w/\1h\1c%s \1h\1w- \1n\1w%s', cmd, help)); + display_server_message(frames, format('\x01h\x01w/\x01h\x01c%s \x01h\x01w- \x01n\x01w%s', cmd, help)); } }); session.on('local_help', function (msg) { - display_server_message(frames, '\1h\1w/\1h\1cscroll \1h\1w- \1n\1wScroll the output area'); - display_server_message(frames, '\1h\1w/\1h\1cscroll_nicks \1h\1w- \1n\1wScroll the nicklist'); - display_server_message(frames, '\1h\1w/\1h\1cnick_prefix \1h\1w- \1n\1wSet a single-character prefix for your handle, eg. /nick_prefix @'); + display_server_message(frames, '\x01h\x01w/\x01h\x01cscroll \x01h\x01w- \x01n\x01wScroll the output area'); + display_server_message(frames, '\x01h\x01w/\x01h\x01cscroll_nicks \x01h\x01w- \x01n\x01wScroll the nicklist'); + display_server_message(frames, '\x01h\x01w/\x01h\x01cnick_prefix \x01h\x01w- \x01n\x01wSet a single-character prefix for your handle, eg. /nick_prefix @'); display_server_message( frames, - '\1h\1w/\1h\1cnick_color \1h\1w- \1n\1wSet your nick color to one of ' + '\x01h\x01w/\x01h\x01cnick_color \x01h\x01w- \x01n\x01wSet your nick color to one of ' + PIPE_COLOURS.reduce(function (a, c) { a += format('|%02d%s ', c, c); return a; }, '') + ', eg. /nick_color 11' ); - display_server_message(frames, '\1h\1w/\1h\1cnick_suffix \1h\1w- \1n\1wSet an eight-character suffix for your handle, eg. /nick_suffix <poop>'); - display_server_message(frames, '\1h\1w/\1h\1ctoggle_nicks \1h\1w- \1n\1wShow/hide the nicklist'); - display_server_message(frames, '\1h\1w/\1h\1cquit \1n\1w- \1h\1wExit the program'); + display_server_message(frames, '\x01h\x01w/\x01h\x01cnick_suffix \x01h\x01w- \x01n\x01wSet an eight-character suffix for your handle, eg. /nick_suffix <poop>'); + display_server_message(frames, '\x01h\x01w/\x01h\x01ctoggle_nicks \x01h\x01w- \x01n\x01wShow/hide the nicklist'); + display_server_message(frames, '\x01h\x01w/\x01h\x01cquit \x01n\x01w- \x01h\x01wExit the program'); }); session.on('message', function (msg) { if (msg.from_user == 'SERVER') { @@ -243,6 +254,11 @@ function main() { session.on('topic', function (room, topic) { display_title(frames, room, topic); }); + session.on('stats', function (stats) { + if (input_state == 'chat') { + refresh_stats(frames, stats); + } + }); if (settings.startup.motd) session.motd(); if (settings.startup.banners) session.banners(); @@ -364,9 +380,7 @@ function main() { } else if (user_input == '' || user_input == 'q') { frames.output.scrollTo(1, frames.output.data_height - frames.output.height); frames.output_scroll.cycle(); - frames.divider.clear(); - frames.divider.gotoxy(frames.divider.width - 5, 1); - frames.divider.putmsg('/help'); + refresh_stats(frames, session.stats); input_state = 'chat'; } } @@ -378,6 +392,7 @@ function main() { } yield(); } + } main(); diff --git a/xtrn/mrc/mrc-connector.js b/xtrn/mrc/mrc-connector.js index 43d1b4ac12edaca2784c1b38ecc6d449571492fd..0c4001c2442a2abd43c3745db7ddde56eef5d076 100644 --- a/xtrn/mrc/mrc-connector.js +++ b/xtrn/mrc/mrc-connector.js @@ -86,6 +86,10 @@ function validate_message(msg) { ); } +function request_stats(sock){ + mrc_send(sock, 'CLIENT', '', 'SERVER', '', '', 'STATS'); +} + function client_receive(c, no_log) { const line = c.socket.recvline(1024, settings.timeout); if (!line || line == '') return; @@ -210,6 +214,12 @@ function mrc_receive(sock) { mrc_send(sock, 'CLIENT', '', 'SERVER', 'ALL', '', 'IMALIVE:' + SYSTEM_NAME); return; } + if (message.from_user == 'SERVER' && message.body.toUpperCase().substr(0,6) == 'STATS:') { + var fMa = new File(js.exec_dir + "mrcstats.dat"); + fMa.open("w", false); + fMa.write(message.body.substr(message.body.indexOf(':')+1).trim()); + fMa.close(); + } if (['', 'ALL', FROM_SITE].indexOf(message.to_site) > -1) { if (['', 'CLIENT', 'ALL', 'NOTME'].indexOf(message.to_user) > -1) { // Forward to all clients @@ -227,6 +237,7 @@ function main() { var mrc_sock; var die = false; + var loop = 1800; while (!die && !js.terminated) { yield(); @@ -234,6 +245,12 @@ function main() { mrc_sock = mrc_connect(settings.server, settings.port); continue; } + mswait(10); + loop += 1 + if (loop > 2000) { + request_stats(mrc_sock); + loop = 0; + } client_accept(); @@ -261,9 +278,8 @@ function main() { } } }); - + mrc_receive(mrc_sock); - } log(LOG_INFO, 'Disconnecting from MRC'); diff --git a/xtrn/mrc/mrc-display-menu-stats.js b/xtrn/mrc/mrc-display-menu-stats.js new file mode 100644 index 0000000000000000000000000000000000000000..c1b3be5230610cde44c8bd52005b68b353305d9f --- /dev/null +++ b/xtrn/mrc/mrc-display-menu-stats.js @@ -0,0 +1,49 @@ +load('sbbsdefs.js'); + +/// -- constants start -- ///////////////////////////////////////////////////// + +const PATH_TO_MRC_STATS = "../xtrn/mrc/mrcstats.dat"; +const ACTIVITY = new Array( + /* 0: NUL */ "\x01H\x01KNUL", + /* 1: LOW */ "\x01H\x01YLOW", + /* 2: MED */ "\x01H\x01GMED", + /* 3: HI */ "\x01H\x01RHI" +); +const BBSES_X = 12; +const BBSES_Y = 19; +const ROOMS_X = 23; +const ROOMS_Y = 19; +const USERS_X = 34; +const USERS_Y = 19; +const LEVEL_X = 34; +const LEVEL_Y = 18; + +const STAT_COLOR = "\x01C\x01H"; + +/// -- constants end -- /////////////////////////////////////////////////////// + +var bbses = '\x01H\x01K---'; +var rooms = '\x01H\x01K---'; +var users = '\x01H\x01K---'; +var level = '\x01H\x01K---'; + +var fMs = new File(PATH_TO_MRC_STATS); +if (fMs.open("r", true)) { + var mrcStats = fMs.readAll()[0].split(' '); + if (mrcStats.length >= 4) { + bbses = mrcStats[0]; + rooms = mrcStats[1]; + users = mrcStats[2]; + level = ACTIVITY[Number(mrcStats[3])]; + } + fMs.close(); +} + +console.gotoxy(BBSES_X, BBSES_Y); +printf("%s%s", STAT_COLOR, bbses); +console.gotoxy(ROOMS_X, ROOMS_Y); +printf("%s%s", STAT_COLOR, rooms); +console.gotoxy(USERS_X, USERS_Y); +printf("%s%s", STAT_COLOR, users); +console.gotoxy(LEVEL_X, LEVEL_Y); +printf("%s%s", STAT_COLOR, level); diff --git a/xtrn/mrc/mrc-session.js b/xtrn/mrc/mrc-session.js index 781939ac0755dd1f0a99e4e8c37f438c3c1b2263..24902697ee34932f1fcb8a06e4e52a1b7131167d 100644 --- a/xtrn/mrc/mrc-session.js +++ b/xtrn/mrc/mrc-session.js @@ -13,7 +13,8 @@ function MRC_Session(host, port, user, pass, alias) { output_buffer: [], last_ping: 0, last_send: 0, - alias: alias || user + alias: alias || user, + stats: ['-','-','-','0'] }; const callbacks = { @@ -55,26 +56,36 @@ function MRC_Session(host, port, user, pass, alias) { } function handle_message(msg) { + var uidx; if (msg.from_user == 'SERVER') { - const params = msg.body.split(':'); - switch (params[0]) { + + const cmd = msg.body.substr(0, msg.body.indexOf(':')); // cmd is everything left of the first colon (:) + const params = msg.body.substr(msg.body.indexOf(':')+1).trim(); // params are everything right of the first colon (:), including any additional colons to follow + + switch (cmd) { case 'BANNER': - emit('banner', params[1].replace(/^\s+/, '')); + emit('banner', params.replace(/^\s+/, '')); break; - case 'ROOMTOPIC': - emit('topic', params[1], params.slice(2).join(' ')); + case 'ROOMTOPIC': + const room = params.substr(0, params.indexOf(':')); // room is everything left of the first colon (:) + const topic = params.substr(params.indexOf(':')+1).trim(); // topic is everything right of the first colon (:), including any additional colons to follow + emit('topic', room, topic); break; case 'USERLIST': - state.nicks = params[1].split(','); + state.nicks = params.split(','); emit('nicks', state.nicks); break; + case 'STATS': + state.stats = params.split(' '); + emit('stats', state.stats); + break; default: emit('message', msg); break; } } else if (msg.to_user == 'SERVER') { if (msg.body == 'LOGOFF') { - const uidx = state.nicks.indexOf(msg.from_user); + uidx = state.nicks.indexOf(msg.from_user); if (uidx > -1) { state.nicks.splice(uidx, 1); emit('nicks', state.nicks); @@ -84,14 +95,12 @@ function MRC_Session(host, port, user, pass, alias) { if (msg.to_room == '' || msg.to_room == state.room) { emit('message', msg); } - if (msg.to_room == state.room - && state.nicks.indexOf(msg.from_user) < 0 - ) { + if (msg.to_room == state.room && state.nicks.indexOf(msg.from_user) < 0) { send_command('USERLIST', 'ALL'); } } else if (msg.to_user == 'NOTME') { if (msg.body.search(/left\ the\ (room|server)\.*$/ > -1)) { - const udix = state.nicks.indexOf(msg.from_user); + uidx = state.nicks.indexOf(msg.from_user); if (uidx > -1) { state.nicks.splice(uidx, 1); emit('nicks', state.nicks); @@ -177,7 +186,7 @@ function MRC_Session(host, port, user, pass, alias) { help: { help: 'Display this help message', callback: function (str) { - emit('help', 'List of available commands:'); + emit('help', 'List of available commands:', ''); for (var c in commands) { emit('help', c, commands[c].help, commands[c].ars); } @@ -215,6 +224,15 @@ function MRC_Session(host, port, user, pass, alias) { } } }, + t: { // added as shorthand for /msg + help: 'Shorthand for /msg: /t nick message goes here', + callback: function (str) { + const cmd = str.split(' '); + if (cmd.length > 1 && state.nicks.indexOf(cmd[0]) > -1) { + this.send_private_messsage(cmd[0], cmd.slice(1).join(' ')); + } + } + }, quote: { help: 'Send a raw command to the server', callback: function (str) { diff --git a/xtrn/mrc/readme.txt b/xtrn/mrc/readme.txt index fa730f8fadf5e3e829468f08cc4173f8df9600c7..93b96b8393233b8e0af81d1636732f08b25bbd1e 100644 --- a/xtrn/mrc/readme.txt +++ b/xtrn/mrc/readme.txt @@ -24,7 +24,6 @@ setup differs. Port=5000 Options=STATIC | LOOP Command=../xtrn/mrc/mrc-connector.js - JavaScriptTimeLimit=0 - In SCFG, add a new External Program with the following options, leaving all other options at their default values: @@ -34,12 +33,6 @@ setup differs. Start-up Directory: /sbbs/xtrn/mrc Command Line: ?mrc-client.js -- If you want to run from the chat menu instead of via a door, copy chat_sec.js to - /sbbs/mods and edit accordingly, adding the following and don't forget to add the - key to be used to the "keys" variable. - - bbs.exec("?../xtrn/mrc/mrc-client.js",null,"/sbbs/xtrn/mrc/"); - - Your services and BBS threads should automatically recycle once they are free to do so, but you may want to restart your BBS now to force these changes to take effect. @@ -85,6 +78,24 @@ mrc-client.ini: on startup, and whether the Message of the Day and banners are displayed. +4) MRC Stats + +MRC-Connector makes requests for server stats every 20 seconds. These stats +are displayed on the MRC-Client screen as well as stored in the mrcstats.dat +file for display elsewhere. + +The file "chat-with-mrc-stats-example.msg" is included as an exammple to +demonstrate how to display MRC stats on a menu file. The script file +"mrc-display-menu-stats.js" must be copied to the /sbbs/mods directory in order +for this msg file to work, since it calls this script directly. + +If you do decide to make use of this msg file, rename it as chat.msg and copy +it to your /sbbs/text/menu directory, replacing the old chat.msg file. Also be +sure to copy "chat_sec-with-mrc-example.js" to your /sbbs/mods directory and +rename it "chat_sec.js", in order to add M as a valid menu option for +Multi-Relay Chat. + + 4) Support - Post a message to 'echicken' in the Synchronet Sysops area on DOVE-Net