ircanywhere / irc-factory

A rebuilt irc-factory from simple-irc-socket and irc-message. Get support at #ircanywhere on freenode
https://ircanywhere.com
MIT License
60 stars 14 forks source link

Added Quake-style colouring and message splitting #9

Closed Jazcash closed 10 years ago

Jazcash commented 10 years ago

So I'm still just a JS newbie, but I added this to my own project and figured it'd be worth offering it to you just in case you wanted it. Again, I'm a newbie so if you do like it, feel free to refactor the code or change whatever you like.

The colour support is essentially just an easier way for irc-factory users to print coloured IRC messages like so:

^1Hello ^16World would write Hello in red with an empty space and then World in red and bold following it. The colour codes are a caret symbol (^) followed by a number using these conventions: http://wiki.swiftirc.net/index.php?title=Colours#List_of_colours_available

16 is bold, 17 is italic, 18 is strike-through, 19 is underlined and 20 is reset. Text with background is defined by separating two colour numbers with a comma like so: ^0,1Hello - prints Hello in white with a black background (^foreground,background).


The message splitting just splits messages that are too long (457+ characters in the Webirc client I was testing with) into multiple lines or trims them with ... depending on which flag is passed to irc.privmsg. If no flag is passed at all, it just attempts to print it but may cause a request too long error from the server and disconnect the bot if the message is too long. Maybe you'd want to make one of the aforementioned options default instead of allowing messages that are too long?


Anyway, like I said, I just wanted to give you the option of using these if you wanted to, don't feel you have to!

rickihastings commented 10 years ago

Hi, thanks for the pull request!

I like the idea of both of these changes actually. I'm very interested in the splitting and have been meaning to implement it. It would be nice to add a test for the splitting functionality to make sure the message is being trimmed at the correct position.

Out of curiosity where does the 457 come from, I know the max is 512 but that will include :nick!user@host PRIVMSG #chan : prefix stuff, which is variable length depending on who is sending the command?

The colour codes are interesting and would definitely be of use in my ircanywhere project. I'm concerned about how you actually write ^16Hello World to someone without having the colour parsed, say if you were describing to someone how to write in colours perhaps, maybe we could add the ability to escape the ^, with \^16Hello World so it would just output the string normally?

Jazcash commented 10 years ago

Yeah I believe the maximum message limit does include the prefix so I guess the code could use some changing there to get it exactly perfect. I was just ball-parking the number with a bit of trial an error to stop the bot being kicked from my channel. One idea would be passing a character limit number to the bot on initialisation and it trims/splits all messages longer than that limit. I say this because I'm not sure if the maximum size of a message is 512 by default or if that can be changed by a server owner. Anyway, it shouldn't be too difficult to get the full message length, including prefix.

Escape characters would be a good idea! Is possible by changing the regex for matching colour codes to [^\\]\^[0-9]{1}[0-5]?,[0-9]{1}[0-5]?|[^\\]\^((20|1([0-9]?)|[0-9])|[0-9]) (Just my bad regex skills, this could possibly be a lot neater). Then changing the .slice(1) to .slice(2) to account for the weird extra character it picks up at the start.

Just tested this and it works, but the extra character it picks up is causing it to remove a character sometimes, will try and improve the regex a bit.

Update: Ok think I got it. Just added \\* to the start of the regex to account for a possible slash then it simply checks the first char of each code in a message string and if it matches a backslash it will leave it alone. Feel free to give it a try. Will work with just one backslash if you're passing it to the bot from IRC, but needs two if you're making the bot print a message through the code.

Update 2: Heh, silly me, forgot to break out of the current style code (gonna start calling it this instead because they're not just for colours) so it continues with the replacement, will fix after I refactor the whole thing. Might have to wait till tomorrow, little busy with some other stuff atm.

rickihastings commented 10 years ago

Yeah, I've seen other clients do things such as monitor the client's hostname, so on connect we get told what our hostname is resolving to (I'm not sure if this is currently available) and if the ircd changes we can listen and update it. Then we can successfully work out how big the prefix would be, allowing us to cut the message off at the correct point.

Escaping colour codes looks good yeah, one thing I'm concerned about is running that huge regex call every time a privmsg is sent, for most cases this isn't much overhead but in an ircanywhere process with a lot of connections it's a decent bit of processing time wasted. Maybe we could look for a visible ^ in the string (can do this with lodash or charCodeAt easily) and then proceed to parse the colour codes.

Once we're happy with this I can look at it locally and do some tests, if it looks good I'll merge it and then commit the tests with it.

Jazcash commented 10 years ago

Yeah, I was concerned about how much the regex would effect it too. I tried spamming some commands comprising solely of colours with the max message limit and I noticed little to no difference in lag compared to normal messages. Ofc, I only use irc-factory for a single client and with many I do imagine it would take a toll if they were used very frequently and talking to multiple users/channels at once.

I'll play around a bit at doing it without regex but feel free to do the same as I might take a while (not used lodash or many other popular node libraries before) ^_^

rickihastings commented 10 years ago

Yeah, I think doing it with regex is fine, but I think it could maybe be simplified. Although my main concern is just doing a straight up check if colour codes need to be parsed at all, by checking for a ^ if so you can use the regex to further parse it, or just leave it alone.

rickihastings commented 10 years ago

I'm just doing some testing on the code you've written. I've wrote a test for the colour parsing which looks to be producing the correct results.

As for the truncating, the outgoing format of the message will be PRIVMSG #chan :target, the nick!user@host isn't sent outgoing so we can ignore that. I can work out at what point the message needs to be cut off by calculating the size of PRIVMSG #chan : which is fine. Although it gets cut off in the middle of words.

I've altered the code (but not commited anything yet) to do something like;

var rawPrefix = 'PRIVMSG ' + target + ' :',
    cutOff = 512 - rawPrefix.length,
    splitmsg = message.match(new RegExp('.{1,' + cutOff + '}', 'g'));

I think we maybe need to look into cutting the last word off if it's been broken and then appending it to the next string. I can go ahead and merge this and make the changes, unless you want to finish it off.

Jazcash commented 10 years ago

Glad to have helped! :)