Skip to content
Snippets Groups Projects
Commit c1ef853a authored by Craig Hendricks's avatar Craig Hendricks
Browse files

MCR Change List on 3/3/2025:

 Enhancements:
 
 - Enhanced mention handling: user can use the /mentions command or
   press the UP hotkey to reset the mention counter to zero (0) and 
   also review all previous mentions for the current session.

 - User can press the PGUP hotkey as a shortcut key for /scroll
   
 - Seconds are included in the timestamp in widescreen (132 column) mode.

 - Passwords get masked when using trust commands (identify, register, 
   roompass, update password, & roomconfig password).

 
 Fixes:
 
 - Added an IAMHERE immediately after connecting before joining a room. 
   This fixes auto-joining the lobby (or the configured room) on startup.
   In addition, mrc-session now also passes user's terminal size, security 
   level, IP address, and sysop's name to the MRC server on startup. 

 - The to_site property in messages from the server no longer needs to be 
   considered when allowing an incoming message from mrc-connector to 
   mrc-client. This resolves the issue of messages from ddial users not 
   appearing in mrc-client, as well as other types of messagea 
   (e.g.: !weather <city name> $).
     
 - Fixed user list (nick list) refresh when someone joins a room or their
   client session times out.
   
 - Stats on the status line no longer wait for user input to get updated.
   
 - Commands not strictly defined in mrc-session are no longer stopped from 
   being sent out to the server. This means server commands are no longer 
   required to be issued with /quote (but it will still work for things like 
   /quote help for the server command list).
   
 - The HOME, END, INSERT, and PAGEDN keys no longer send an empty message
   if accidentally pressed.
 
 - mrc-connector.js now announces a user's departure immediately before
   sending the LOGOFF command.
   
 - Fixed an issue in mrc-client.js where the new_alias function saved
   the new default alias string, but didn't actually use the new alias
   string for the current session.
      
 
 New Features:
 
 - Basic twit filter implemented. Hides messages from problematic chatters.
   Usage:
   -  /twit add nameoftwit    Filters out nameoftwit's messages.
   -  /twit del nameoftwit    nameoftwit's messages are re-allowed.
   -  /twit list              Lists twits the user has added.
   -  /twit clear             Empty's the user's twit list.
   Twit names are saved per-user to mrc-client.ini (separated by ~ character)
   and remembered in future sessions.

 - User can press the LEFT and RIGHT arrow hotkeys to change their outgoing 
   message color. The selected color is indicated by the > symbol to the left 
   of the inputline, and gets saved and reused in future sessions.

 - Added "commands" option under [startup] in mrc-client.ini. This is a 
   comma-separated list of commands defined by the sysop to execute when a 
   user enters MRC. For example, including "chatters" will automatically
   display chatters in the current room on startup after displaying the motd 
   screen and joining the room (requested by Amessyroom of Too Lazy BBS).

 - Local system messages for the user get displayed in the chat window (e.g.:
   email notifications, new echomail posts & replies, etc.). This way the user
   doesn't need to wait until leaving MRC to be notified of such things.

 - Added /r as a shortcut to reply to the last private message.

 - User can use the CTRL+D shortcut to clear the inputline, rather than 
   having to repeatedly press backspace.
 
 - Optional "MRC for Synchronet" splash on startup. Sysop can customize it 
   by editing the mrc-splash.msg file, or just disable it entirely by setting 
   splash = false in mrc-client.ini.

   
 Housekeeping:

 - Massive reorganization of the /help information. All help info on local 
   commands is now contained in external msg files. Redundant and obsolete 
   commands have been removed, and text has been added to bring awareness
   to additional server command availability by typing /quote help
   
 - "banners" is not a command that the server expects to receive from clients
   in the USER context, so the banners definition in mrc-session.js, the 
   associated function call in mrc-client.js, and the associated setting 
   in mrc-session.ini have been removed. 
   
 - Updated readme.txt file, including info on the toggle_nicks setting that
   was missed in the previous update.


Known issue:

 - Strings starting with semicolons do not go out, because they are recognized
   by InputLine.js as sysop command prefixes. Maybe the "submit" command can
   be overridden to bypass this.
         

 Acknowledgements:
 
  Big thanks to StingRay, cr1mson, paulie420, and MeaTLoTioN for testing
  and providing helpful feedback, and as always to StackFault for insight.
parent 340dea55
No related branches found
No related tags found
No related merge requests found
Pipeline #8634 failed
......@@ -5,10 +5,15 @@ ping_interval = 60
[startup]
room = lobby
motd = true
banners = true
commands =
splash = true
[aliases]
[client]
;change this to true if you want show the nick list on connect.
show_nicks=false
[theme]
[msg_color]
[show_nicks]
[twit_list]
This diff is collapsed.
......@@ -28,8 +28,8 @@ f = undefined;
if (!settings.ssl)
settings.ssl=false;
const PROTOCOL_VERSION = '1.3.1';
const MAX_LINE = 256;
const PROTOCOL_VERSION = '1.3.2';
const MAX_LINE = 512;
const FROM_SITE = system.name.replace(/ /g, "_");
const SYSTEM_NAME = system_info.system_name || system.name;
......@@ -221,8 +221,10 @@ function mrc_receive(sock) {
line = sock.recvline(MAX_LINE, settings.timeout);
if (!line || line == '') break;
latency_tracker.forEach(function(m) {
if (m.line===line.trim()) {
if (m.line===line.trim() ||
(m.line.indexOf("~STATS") >= 0 && line.indexOf("~STATS") >= 0 ) ) {
client_send({ from_user: "SERVER", to_user: 'CLIENT', body: 'LATENCY:' + (Date.now() - m.time) });
log(LOG_DEBUG, 'Latency: ' + (Date.now() - m.time) );
latency_tracker = [];
}
});
......@@ -239,14 +241,12 @@ function mrc_receive(sock) {
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
client_send(message);
} else {
// Send to this user
client_send(message, message.to_user);
}
if (['', 'CLIENT', 'ALL', 'NOTME'].indexOf(message.to_user) > -1) {
// Forward to all clients
client_send(message);
} else {
// Send to this user
client_send(message, message.to_user);
}
yield();
}
......@@ -274,6 +274,7 @@ function main() {
Object.keys(clients).forEach(function (e, i) {
if (!clients[e].socket.is_connected) {
mrc_send(mrc_sock, clients[e].username, "", "NOTME", "", "", "|07- |12" + clients[e].username + " |04has left chat|08.");
mrc_send(mrc_sock, clients[e].username, '', 'SERVER', '', '', 'LOGOFF');
client_send({ from_user: clients[e].username, to_user: 'SERVER', body: 'LOGOFF' }); // Notify local clients
delete clients[e];
......
NB__[ HWList of available commandsN: B]_____________________________
WH/CinfoNHK:N View information about a BBSHK:N H/CinfoN H#
WH/Ct Kor W/CmsgK:N Send a direct messageHK:NH/CtN HnickN HBmessage
WH/CrNHK:N Reply to last direct messageHK:N H/CrB message
WH/CjoinNHK:N Move to a new roomHK:W/CjoinN Hroom_name
WH/CtopicNHK:N Change room topic:H/CtopicW topic
WH/CroomsNHK:N List available rooms
WH/CusersNHK:N List users
WH/CwhoonNHK:N List users and BBSes
WH/CmotdNHK:N Display the Message of the Day
WH/Cscroll Kor CPGUPK:N Scroll the chat window
WH/Cmentions Kor CUPK:N Reset mention counter and review mentions
WH/Cscroll_nicksN HK:N Scroll the nicklist
WH/Ctoggle_nicksN HK:N Show/hide the nicklist
WH/Ctoggle_statsN HK:N Toggle MRC stats view
WH/CthemeNHK:N Select a theme HK..........N seeHK:N H/ChelpN Htheme
WH/CtwitNHK:N Twit List management HK....N seeHK:N H/ChelpN Htwit
WH/CquitNHK:N Exit the program
WHCLEFTK/CRIGHTWK:N Change your text color HK..N seeHK:N H/ChelpN Hnick
WHCCTRLK+CDNHK:N Clear the input line
NFor a list of additional HSERVERN commands, see H/CquoteN Hhelp
\ No newline at end of file
NB__[ HWNick customization optionsN: B]_____________________________
HW/Cnick_prefix K:W NSet a single-character prefix for your handle
Neg.H /Cnick_prefixN H@
WH/Cnick_colorN HK:W NSet your nick color
HNG02HW NC03HW NR04HW NM05HW NY06HW B09W G10W C11W R12M 13W Y14W 15
WH/Cnick_suffix K:W NSet an eight-character suffix for your handle
Neg.H N/HCnick_suffix W<afilz>
N You can include pipe color codes in your nick_prefix and
N nick_suffix. Get as creative as you want!
HB NExample: HB@CUserNameB<GaFiLZB>
NB__[ HWHow to set a custom themeN: B]______________________________
N Usage:
WH/Ctheme NHnameoftheme
N
\ No newline at end of file
NB__[ HWHow to use the twit listN: B]_______________________________
N Basic twit list implemented! Hides messages from problematic
N chatters.
N Usage:
WH/Ctwit NHadd HBnameoftwit K:W NFilters out nameoftwit's messages
WH/Ctwit NHdel HBnameoftwit K:W Nnameoftwit's messages are re-allowed
WH/Ctwit NHlist K:W NLists twits the user has added
WH/Ctwit NHclear K:W NEmpty's the user's twit list
......@@ -16,7 +16,10 @@ function MRC_Session(host, port, user, pass, alias) {
alias: alias || user,
stats: ['-','-','-','0'],
mention_count: 0,
latency: '-'
latency: '-',
msg_color: 7,
twit_list: [],
last_private_msg_from: ""
};
const callbacks = {
......@@ -41,10 +44,10 @@ function MRC_Session(host, port, user, pass, alias) {
function send_message(to_user, to_room, body) {
if (body.length + state.alias.length + 1 > 250) {
word_wrap(body, 250 - 1 - state.alias.length).split(/\n/).forEach(function (e) {
send(to_user, '', to_room, state.alias + ' ' + e);
send(to_user, '', to_room, state.alias + ' ' + format("|%02d", state.msg_color) + e);
});
} else {
send(to_user, '', to_room, state.alias + ' ' + body);
send(to_user, '', to_room, state.alias + ' ' + format("|%02d", state.msg_color) + body);
}
}
......@@ -80,7 +83,7 @@ function MRC_Session(host, port, user, pass, alias) {
break;
case 'STATS':
state.stats = params.split(' ');
emit('stats'); //, state.stats);
emit('stats');
break;
case 'LATENCY':
state.latency = params;
......@@ -90,6 +93,10 @@ function MRC_Session(host, port, user, pass, alias) {
emit('message', msg);
break;
}
if (msg.body.search(/just joined room/) > -1 ||
msg.body.search(/session has timed-out/) > -1) {
send_command('USERLIST', 'ALL');
}
} else if (msg.to_user == 'SERVER') {
if (msg.body == 'LOGOFF') {
uidx = state.nicks.indexOf(msg.from_user);
......@@ -97,8 +104,13 @@ function MRC_Session(host, port, user, pass, alias) {
state.nicks.splice(uidx, 1);
emit('nicks', state.nicks);
}
}
}
} else if (msg.to_user == '' || user.toLowerCase() == msg.to_user.toLowerCase()) {
if (user.toLowerCase() == msg.to_user.toLowerCase()) {
state.last_private_msg_from = msg.from_user;
}
if (msg.to_room == '' || msg.to_room == state.room) {
emit('message', msg);
}
......@@ -112,9 +124,9 @@ function MRC_Session(host, port, user, pass, alias) {
state.nicks.splice(uidx, 1);
emit('nicks', state.nicks);
}
} else if (msg.body.search(/just joined room/) > -1) {
send_command('USERLIST', 'ALL');
}
} /*else if (msg.body.search(/just joined room/) > -1) {
send_command('USERLIST', 'ALL'); // moved above to msg.from_user == 'SERVER'
}*/
emit('message', msg);
}
}
......@@ -122,6 +134,10 @@ function MRC_Session(host, port, user, pass, alias) {
this.send_room_message = function (msg) {
send_message('', state.room, msg);
}
this.send_notme = function (msg) {
send("NOTME", "", "", msg);
}
this.send_private_messsage = function (user, msg) {
msg = '|11(|03Private|11)|07 ' + msg;
......@@ -140,7 +156,11 @@ function MRC_Session(host, port, user, pass, alias) {
password: pass,
alias: state.alias
}) + '\r\n');
this.send_command('IAMHERE');
mswait(20);
this.send_command('USERLIST', 'ALL');
mswait(20);
this.send_command('STATS', 'ALL');
}
......@@ -181,50 +201,53 @@ function MRC_Session(host, port, user, pass, alias) {
}
const commands = {
banners: {
help: 'List of banners from server' // Doesn't do anything?
},
chatters: {
help: 'List current users'
},
bbses: {
help: 'List connected BBSs',
command: 'CONNECTED'
},
// This section has been cleaned up significantly.
//
// Server commands no longer need to be strictly defined
// here.
//
// Some commands are still defined if they have specific
// function calls attached to them in mrc-client.js
// (e.g. /motd) and or are local command shortcuts
// (e.g. /t and /r).
//
// Any command not defined here (or in mrc-client.js) will
// be assumed to be a server command. The server will
// inform the user if a command is invalid.
//
// The "help" properties are no longer needed, since
// help is contained in external .msg file. They have been
// left commended out to provide reference.
//
help: {
help: 'Display this help message',
//help: 'Display this help message',
callback: function (str) {
emit('help', 'List of available commands:', '');
for (var c in commands) {
emit('help', c, commands[c].help, commands[c].ars);
}
emit('local_help');
emit('local_help', str);
}
},
info: {
help: 'View information about a BBS (/info #)',
//help: 'View information about a BBS (/info #)',
callback: function (str) {
this.send_command('INFO ' + str);
}
},
join: {
help: 'Move to a new room: /join room_name',
join: {
//help: 'Move to a new room: /join room_name',
callback: function (str) { // validate valid room name?
str = str.replace(/^#/, '');
str = str.replace(/^#/, '');
this.send_command(format('NEWROOM:%s:%s', state.room, str));
state.room = str;
state.nicks = [];
this.send_command('USERLIST', 'ALL');
}
},
meetups: {
help: 'Display information about upcoming meetups'
},
motd: {
help: 'Display the Message of the Day'
//help: 'Display the Message of the Day'
},
msg: {
help: 'Send a private message: /msg nick message goes here',
msg: { // This is largely overtaken by /t, but we'll still handle it.
//help: 'Send a private message: /msg nick message goes here',
callback: function (str) {
const cmd = str.split(' ');
if (cmd.length > 1 && state.nicks.indexOf(cmd[0]) > -1) {
......@@ -232,8 +255,8 @@ function MRC_Session(host, port, user, pass, alias) {
}
}
},
t: { // added as shorthand for /msg
help: 'Shorthand for /msg: /t nick message goes here',
t: {
//help: 'Send a private message: /t nick message goes here',
callback: function (str) {
const cmd = str.split(' ');
if (cmd.length > 1 && state.nicks.indexOf(cmd[0]) > -1) {
......@@ -241,70 +264,41 @@ function MRC_Session(host, port, user, pass, alias) {
}
}
},
r: {
//help: 'Reply to last private message: /r message goes here',
callback: function (str) {
if (state.last_private_msg_from) {
this.send_private_messsage(state.last_private_msg_from, str);
}
}
},
quote: {
help: 'Send a raw command to the server',
//help: 'Send a raw command to the server',
callback: function (str) {
this.send_command(str);
}
},
quit: {
help: 'Quit the program',
//help: 'Quit the program',
callback: function () {
handle.close();
emit('disconnect');
handle.close();
}
},
rooms: {
help: 'List available rooms',
//help: 'List available rooms',
command: 'LIST'
},
stats: {
help: 'Return anonymous server stats',
//help: 'Return anonymous server stats',
command: 'statistics'
},
topic: {
help: 'Change the topic of the current room',
//help: 'Change the topic of the current room',
callback: function (str) {
this.send_command(format('NEWTOPIC:%s:%s', state.room, str));
}
},
users: {
help: 'Display list of users'
},
whoon: {
help: 'Display list of users and BBSs'
},
afk: {
help: "Set yourself AFK (Shortcut for STATUS AFK)",
callback: function (str) {
this.send_command('AFK ' + str);
}
},
register: {
help: "Register handle on server (MRC Trust)",
callback: function (str) {
this.send_command('REGISTER ' + str);
}
},
identify: {
help: "Identify as a registered user (MRC Trust)",
callback: function (str) {
this.send_command('IDENTIFY ' + str);
}
},
update: {
help: "Update user registration (MRC Trust)",
callback: function (str) {
this.send_command('UPDATE ' + str);
}
},
trust: {
help: "MRC Trust Info (MRC Trust)",
callback: function (str) {
this.send_command('TRUST ' + str);
}
}
}
};
Object.keys(commands).forEach(function (e) {
......@@ -312,11 +306,11 @@ function MRC_Session(host, port, user, pass, alias) {
this[e] = commands[e].callback;
} else if (commands[e].command) {
this[e] = function () {
this.send_command(commands[e].command.toUpperCase());
this.send_command(commands[e].command);
}
} else {
this[e] = function () {
this.send_command(e.toUpperCase());
this.send_command(e);
}
}
}, this);
......
NHK.N HK.N . HK~N HK~N HK~N HK.N HK~N HK~N HK.N HK~N HK~N HK~N HK~N HK.N HK~N HK~N HK~N . HK.N HK.
N HK.N HK.N . H.N HB88888b.d88b.N HB888d888 .d8888b W.N .HK .N HK.
.N .HK W.K NB.W B8H88N HB"888N HB"88b NB8H88P"NB dH88P"NB.HK W.N . HK.
N.HK W.K NB.W B.W B8H88N B8H88 NB8H88 NB8H88NB8H88NB.W B.HK W.N .
HK . N.HK W.K NB.W B8H88N B8H88 NB8H88 NB8H88NBY8H8b.NB.HK W.N . HK.
. .N . H.N B8H88N B8H88 NB8H88 NB8H88NB"Y8H888 W.N . HK.N HK.
` .N HK.N HK=N==H=========================N==HK=N HK.N HK. '
NHK-=[N HCMNCulti HRNCelay HCNChat forW HCSynchronetN HK]=-
......@@ -60,7 +60,6 @@ colour codes are permitted:
http://wiki.mysticbbs.com/doku.php?id=displaycodes#color_codes_pipe_colors
I may write a CTRL-A to pipe converter at some later date.
mrc-connector.ini:
......@@ -77,11 +76,16 @@ mrc-client.ini:
above instructions while editing '/sbbs/ctrl/services.ini'.
- The 'ping_interval' setting should be left at the default value unless you
have a good reason for changing it.
- The values in the [startup] section determine which room the client joins
on startup, and whether the Message of the Day and banners are displayed.
- Change show_nicks in the [client] section to always display the nick list
when connecting to the MRC server.
- The values in the [startup] section control the following:
room: Which room the client joins on startup.
motd: Whether the Message of the Day is displayed.
commands: Any additional commands to execute, eg: "chatters" to display
the list of active users in the room on startup. Use commas
to separate multiple commands.
splash: Whether the "Multi Relay Chat for Synchronet" splash is shown
on startup.
- The [aliases], [theme], [msg_color], [show_nicks], and [twit_list] sections
are for user settings which get added or updated any time a user uses them.
4) MRC Stats
......@@ -123,19 +127,35 @@ see "Yes" next to your BBS in the SSL column.
6) Themes
MRC comes with several customizable theme files. These can be added/edited as
the system wishes. The client automatically detects any available theme files
the sysop wishes. The client automatically detects any available theme files
matching the pattern:
mrc-theme-<theme_name>.ini
Available themes are listed in /help. User selects a theme by typing
Available themes are listed in /help theme. User selects a theme by typing
/theme <name>, and the selected theme gets saved to settings for future
sessions.
If a theme file is not available, the classic blue theme gets used by default.
To customize the splash that gets shown on startup, edit the mrc-splash.msg
file. Or just disable it by setting splash = false in mrc-client.ini
7) Support
7) Known issues
- Outgoing messages beginning with a semicolon do not get sent out to the MRC
server. For example, a winking face emoticon: ;) or ;-)
This is because the ; character is used by the inputline.js library to
indicate the start of a sysop command. In the case of the MRC client, such
text is simply ignored and does not get sent over.
As a workround, you may simply insert a space in front of the message you
want to send that starts with a semicolon.
8) Support
- Post a message to 'echicken' in the Synchronet Sysops area on DOVE-Net
- Find me on irc.synchro.net in #synchronet
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment