Major changes:
Identities are now supported, with the introduction of several overloaded methods to allow a choosen Yahoo identity to be specified.
Session.sendMessage(String to,String msg,YahooIdentity yid)
Session.sendBuzz(String to,YahooIdentity yid)
Session.createConference(String[] users,String msg,Identity yid)
The original (non-identity) versions of these methods simply use the primary identity. (Note: the *primary* identity - not necessarily the one the user logged in with!)
The former setIdentity() method has been removed, it was never supported 100% anyway, and has been replaced by the overloaded methods detailed above. Three new methods have been added to support the new identity code:
Session.getPrimaryIdentity()
Session.getLoginIdentity()
Session.activateIdentity(YahooIdentity yid,boolean activate)
The first will return the primary identity - the original account identity to which all other identities are aliases. The second returns the login identity, the account which was used to log into this session (not the most useful of things to know... but it's there just-in-case!) And finally the third changes the visibility of identities, except the primary identity.
The YahooConference class has also had a method added to allow access to the identity associated with the conference.
YahooConference.getIdentity()
A subclass of RuntimeException, so try/catch blocks are optional (but highly recommended). Thrown when an operation is attempted with an identity which is not valid for the current session - in other words, the identity is not owned by the current user. Also thrown when activate/deactivate is called on the primary identity (which Yahoo apparently does not support!)
Decoders for Swing Document objects now support fading and alterating colour text.
Thanks to John Morris, who provided examples of some useful pointers and optimisations to the Swing Document code, as well as some sample fade/alt code.
Two new accessor pairs have been added to MessageDecoderSettings in the support package, which enable respect for fade and alt tags within messages to be enabled or disabled. Default is false - decoders will not respect these tags, instead rendering text within them in the current font colour.
Typically happens when the room is 'full', this method now correctly reports the inability to login to a chatroom with a LoginRefusedException. (This one is hard to test - so let me know if you encounter problems!)
Numerous changes to the SwingTestClient, to introduce identities and make it easier to use.
ymsg.network.loginTimeout is now read each time a login() or chatLogin() is called, meaning that changes in the timeout value during the run of a program are reflected in the next login.
All main host and port values are now accessible (should you need to alter them) via properties. See README for all the properties now supported.
Trying to marry up Swing and Yahoo's strange message encoding scheme is a challenge too far at this point. The MutableMessageElement is a half-way solution which allows messages to be built up in a tree-like format, and then encoded to Yahoo's IM or chat formats.
MutableMessageElement is a Collection, specifically a List (see the java.util.List interface) which allows its children to be manipulated. Static methods are used to create new elements, which can then be nested inside one another to form the message tree.
This class is still experimental, and could be prone to widespread change.
As a result of the new MutableMessageElement class, the constants inside its parent class, 'MessageElement', have been made public. To avoid confusion, use them as statics of the MutableMessageElement class...
"MutableMessageElement.TEXT" rather than "MessageElement.TEXT"
The extra emoticons from http://help.yahoo.com/help/us/mesg/use/use-44.html have been added to the Emoticons class, plus the new Messenger v6.0 emoticons, bringing the total up to 75.
Setting the property "ymsg.network.httpProxyAuth" to the required contents of "Proxy-Authorization" will cause this header to be included in HTTP messages. This enables jYMSG to work from networks using HTTP through a proxy which needs authentication.
The static method HTTPConnectionHandler.setProxyAuthorizationProperty() can be used to set this property in a high level way. It will build the required string, but only supports Basic encoding scheme at present.
[984099] LoginRefusedException has been enhanced to better describe the nature of the login failure. The new method getStatus() returns a value from StatusConstants revealing Yahoo's reason for refusing our login. -1 is returned if the reason is unknown.
AccountLockedException has been made a subclass of LoginRefusedException, so all login refusals can now be handled in one generic exception block if distinction between different types of failure is not important. Its status value will always return as STATUS_LOCKED.
STATUS_LOCKED is returned when an account is locked; STATUS_BADUSERNAME (an alias for STATUS_NOTATHOME) when Yahoo claims not to recognise the account; and STATUS_BAD otherwise (bad password).
I got an email from someone trying to use jYMSG to access French chatrooms. It occured to me that my code doesn't offer any support for non-English rooms, and as such I've added a new method to allow other Yahoo chat servers to be queried for chat data.
YahooChatCategory.setLocalePrefix("fr");
This results in "fr.insider.msg.yahoo.com" being queried instead of "insider.msg.yahoo.com" . To clear the setting back to the default call the method with null.
Note: as the loadCategories() methods cache their data, the call to this method must be done *before* any call to loadCategories. This is a rather clunky solution: one hopes future versions of jYMSG will have better locale support, with the ability to access rooms from multiple locales from one session. (Perhaps in retrospect making parts of this class static was a mistake?)
Causes a USERSTAT packet to be sent, to which the Yahoo service will reply with packets confirming the session status and new mail count (usually zero). Doesn't appear to have any function other than to confirm what we already know about our session - but as Yahoo supports this functionality (the official Yahoo clients have it wired to their "View->Refresh" menu option) jYMSG now gives you access to it too.
[1053155] Any username passed into the login() method will be silently set to all lower case characters, in keeping with Yahoo's username scheme.
As well as an associated method in the adapter. This is called when someone declines to join a conference we have invited them to.
Bugs:
[881368] [1001334] A NullPointerException was thrown when a room element did not contain the expected attributes. Now those attributes are silently set to zero.
Both of these methods in Session used to throw plain IOExceptions on time out - these have been upgraded to the more specific subclass of java.io.InterruptedIOException, meaning that it is now possible to distinguish between timeouts and general IO problems.
chatLogin() in Session now sets its chat status to FAILED when exiting via a timeout exception.
There is now no need to call chatLogout() before moving from room to room. This was an artificial restriction that Yahoo didn't itself impose. Calling chatLogin() a second time while still logged into a room will cause Yahoo to automatically log you out of the current room before moving you to the new room. Call chatLogout() when leaving chat rooms altogether.
Strange as it may seem, jYMSG actually implements bad functionality deliberately! Yahoo does not allow identities to work with typing notifiers. All notify packets are sent in the primary identity, regardless of whether this is appropriate or not. Further, if a client sends a notify packet with an identity other than the primary identity, the Yahoo server re-writes the packet before it is passed onto the receiving client.
This raises two issues: (1) Typing notify packets sent by 'identities' will be ignored by the receiver or mis-directed to the wrong window. (2) Yahoo IM gives away the primary identity of anyone who uses this type of alias.
I've posted a bug report on the mailing list of the coder who works on the Unix port of Yahoo Messenger (the legit version!) so hopefully he might pass it on. Although I am told this is a long standing bug, so don't hold your breath. In the meantime, jYMSG will replicate Yahoo's buggy functionality, so there is no way to send notifications from specific identities. (Note: it's not just notifications that don't work - see my posting below...)
[823559] Finally (!) IOExceptions from within readPacket() will bubble up correctly to cause SessionExceptionEvent's on input streams. This happens even with the HTTPConnectionHandler, which doesn't have independent input and output streams. Exceptions are captured and queued along with other incoming packets, and then re-thrown to give the appearence they are occuring on the (virtual) input stream.
On or around June 24th 2004 Yahoo yet again changed its login protocol, this time to exploit a bug in the Trillian/Gaim implementation used as a reference by many third party Yahoo libraries, including libyahoo2 and this one. The fix was trivial for C-based libraries, as it involved tinkering with internal values of the SHA1 hash while it was being updated. Unfortunately the standard SHA1 implementation shipped with Java does not allow access to the necessary internal variables. Thanks to some quick coding by a jYMSG user though a custom SHA1 class was quickly at hand to solve the problem.
The constructors didn't appeared to work at advertised, ie. check the old pre-Java-1.3 property names for the HTTP proxy if the modern names were not set. It appears they may never have worked as documented - although Java 1.2 is so old that nobody realised. Anyway, the code has been radically cleaned up and fixed.
Yahoo chat started (?) sending login packets, type 0x98, in multiple sections. After a quick demo session I managed to deduce that the status header is the secret to knowing when single or multiple parts are being used. I've adjusted the chat login code to cache and merge packets until the final 0x98 packet arrives - hopefully this should solve the problem.
[969977] The code for receivedList has been modified to allow for multiple packets, caused by long user lists on fields suchs groups.
This has been a tricky one for me to fix, as I don't have access to an account with hundreds of friends in the groups field.
I used the same method of detecting incomplete packets as libyahoo2: look for the cookie field and if it ain't there, assume an incomplete packet. However, studying a similar problem with chat login (see above) I noticed that the status field changed to indicate an incomplete message. I'm wondering if the same thing happens for split List packets, and if so, if this will be a better way of detecting incomplete packets. IF ANYONE HAS AN EXAMPLE OUTPUT DUMP, PLEASE MAIL IT TO ME!!
[1001334] Previously the YahooUser object was created as being on-line. This has now been changed to be off-line, until the server delivers a status packet for this user.
The release of this package was brought forward by the sudden change in the Yahoo AUTH scheme (see below). A number of features I wanted to include for this release were dropped: notably the addition of some code to support fancy colour-ised texts in chatrooms which someone had kindly supplied, and a fresh look at the chat login/logout code when jumping from one room to the next.
Major changes:
Loads and manages Emote text from data in the standard Yahoo 'custom Emote' format. Also has the standard Yahoo Chat Emotes built-in, which can be optionally added to your bespoke Emotes.
Supports the sending of room and user Emote text.
Returns whether the incoming message is an Emote or not.
isMale(), isFemale() and hasWebcam() all added.
Both these methods will now timeout with an IOException if the login process takes too long to complete. The default is 60 seconds. This can be adjusted using the "ymsg.network.loginTimeout" property, which accepts the timeout period in seconds. (Set this *before* you first reference a ymsg.network class, as the value is cached.) A value of zero or below (negative) disables the timeout.
The nextTag() method failed to handle blank lines in the XML appropriately. Now fixed.
Yahoo apparently will not send back all group entries without the cookies it uses to identify users (and thereby their age!) A new overloaded version of "loadCategories" has been added which accepts a Session object (which must have been logged in first, naturally, otherwise the cookies won't be available!)
In mid-January 2004 Yahoo switched on a part of their login protocol used to authenticate users which had previously been silent. You''l be glad to hear this code now logs into Yahoo under the 'new' protocol arragement successfully...!
The implementation used by this library is not just a carbon copy of other libraries. I took time to study the workings of other libraries to write an efficient, better structured, better documented, and mpre compact solution. For example, I managed to reduce the size of the 'operation lookup' table by nearly 25%.
Support:
The decoder classes are an important part of the support API, enabling Yahoo messages to be translated into other formats, while retaining their style information. These two new classes - one an actual class and the other an interface - allow extensive control over this decoding process.
MessageDecoderSettings holds within it a list of requirements for the decoder engine. Such things as whether emoticons (smiley's) should be translated to images, or left as text. It is also possible to set default font and colour settings, as well as override styles contained within message bodies. For example, using MessageDecoderSettings it is possible to specify that all fonts be kept within a given point size range - so they cannot become too small nor too big (useful for chatrooms!)
EmoticonLoader is an interface with a single method, used by the decoder to find emoticon icons. This allows you to provide your own smiley icons, which the decoder will include when necessary (subject to emoticon decoding being switched on, naturally!). The API will cleverly substitute any missing icons with its own default ones - meaning you do not have to provide graphics for all 35 current smiley images.
By separating these configuration structures out from the body of the MessageDecoder itself, it is possible not only to re-use settings across a host of decoders, but also to alter the settings for multiple decoders in an instant.
Again, another class which resulted as a consequence of the recent intro- duction of chatroom support! This class analyses messages and looks for suspect behaviour. Currently the only things detected are repeat messages ("Help me Obi-wan, you're my only hope", "Help me Obi-wan, you're my only hope", etc.) and heavy user of caps ("I AM SHOUTING!").
An ambitious (and minimally tested) class which takes the sting out of creating Swing models for the Session. It registers itself with a session as a listener, and acts upon the session events to update any models it controls.
Creating models is tricky, and this class has had only basic testings. It appears to work okay, but without a good solid test it must be assumed to leak the occassional exception, or get mis-sync'd with the real data. (Take a look at the source if you want to see what a nightmare it is!)
Chatroom elements such as
Network:
A new event has been added to the SessionListener (and adapter). This will be fired when the user is booted from a chatroom without formally asking to leave - typically an auto-logout after a long period of inactivity.
For when chat user details get updated.
But only on the input stream. Packets of type 0x20 are treated as regular messages, and delivered to messageReceived(). So far attempts to output these packets (created by the web-based chat system when you use the 'IM' feature) has been unsuccessful.
(I have no idea why Yahoo has this alternative PM packet - given that the payload seems to be identical to regular 0x06 SERVICE_MESSAGE packets. Perhaps they are hangover from some previous implementation? Or maybe they are used to send messages to those users only on Chat, not Pager? Ideas welcome...!)
To support clients which do not use AWT, it is now possible to specify 'null' as the AWT key event source when registering a typing notifier. A new method, keyTyped(), is used to manually inform the session when a key has been pressed.
(Actually, this method will also work even if you register an AWT component, as a way of sending bogus key presses. You shouldn't have any need to use it, however, if a genuine key event source is already registered.)
This new method returns an array of sessions cookies, as set at login time. There are three constants in the NetworkConstants interface, which correspond to the positions in the array of the Y, T and C cookies.
The bug which transmitted "Is Back" regardless of what status you'd set before login (available or hidden) has finally been fixed. It now sends "Is Away" if hidden.
YMSG9BadFormatException now chains the execption which caused it.
There has been a number of changes to the way this API reports closed/ broken/lost connections. logoffReceived() in the SessionListener has had a name change to reflect its broader use. The connectionClosed() method will now be called:
A handful of problems fixed, keeping up with the 'bugs' section of the Project page.
Major changes:
New AUTH packed encoding now fixed. You can now log in once more.
Alternative test client using Swing. Log into a chat room to see a demo of how styled text and smiley's can be displayed using the support API.
A bug where user details didn't match their usernames has been fixed (maybe!). It was while I was testing this that I realised Yahoo had changed the AUTH packet (see 1 above). I've had no time to test the changes - I wanted to get a working API back out ASAP.
It's new and had minimal testing. As yet this class is 'unofficial' - I won't bother to Javadocs it just yet, as I hope it will change and expand in time for the next release. However - if you want to play with it, see the source code for details. (At the moment all it does is stop repeat messages, ie. in chat rooms...!)
Because of the deadline of Sept 24th (see below) I've had to rush this release out a little early. There are one or two minor bugs I know of, one involving receiving an unknown packet during login (seems to be a consequence of moving the protocol field in the header from 9 to 10) and there is still an outstanding issue regarding logging in with a hidden status.
*** HOWEVER *** This release has had some fairly important internal changes which, because of the deadline, I've only been able to give minimal testing to. IT IS THEREFORE ADVISED THAT BEFORE MOVING AN EXISITNG PROJECT TO V0.3, YOU TAKE A COPY OF YOUR CURRENT SOURCE TREE SO YOU CAN REVERT BACK TO V0.2 SHOULD V0.3 PROVE TOO BUG FILLED OR UNSTABLE.
I will try and get an update (0.31) out with any remaining issues sorted ASAP.
Btw: For those of you who asked, jYMSG is under the GPL license.
Also, I've decided that the 'offical' short name of the API is "jYMSG" (with a lowercase 'j', to be trendy!). As the API is no longer limited to version 9 of the protocol, I've dropped the '9' reference. I'll try and undate the docs and web site as and when... :-)
ps. If you want your project linked to on the web site, contact me via the usual channels.
Major changes:
A new test client has been created, easier to use and extend.
The use of plain String's to identify high-level data objects has been replaced with the objects themselves. So, for example, where once a Yahoo user would be represented by a String object containing their id, they are now represented by a YahooUser object itself (the getId() method can be used to determine the user's id). Likewise, where once strings were used to refer to conferences, now the full-blown YahooConference object is used instead.
The reasoning behind this is simple: some parts of the API *have* to accept and/or return high-level objects by their very nature, while some still return String's and expect you to look up the high-level object yourself from the id string. To standardise method parameters and returns, the use of high level objects has been adopted throughout.
There are only a handful of exceptions, the most important being 'from' and 'to' fields in SessionEvent have remained as String's. Some other methods to do with groups have retained their use of String too (for now!)
Chat support has been added, with the introduction of several new methods to the Session class, and a handful of event, exception and data objects specific to chat.
Exceptions and other data objects (YahooUser, YahooChatRoom, etc) no longer have public constructors. Only the API itself should be able to create instances of these classes, and why the constructors were made public in the first place is beyond me (probably oversight on my part!) as no client should be required to create its own data or exception objects.
The convertion method which used to live in SessionEvent has been deleted (as forewarned!) and replaced with a much more flexible new scheme housed in its own package "ymsg.support" which hopefully will grow to support translation of Yahoo data to and from different formats, and also handle smiley strings.
It is early days for this new package, but already it offers greater and more flexible functionality than what it replaced.
Yahoo has recently started urging users to upgrade to the latest version of their messenger software, pending a withdrawal of their server for older protocol versions. To the best of my knowledge the API should be safe in all but one regard - it shows the old version '9' as part of its packet headers. With 0.3 the API has been updated to display 10 as its version in packet headers.
(To update previous versions of the API, simply change the first byte of VERSION and HTTP_VERSION in NetworkConstants.java to be 0x0a, instead of 0x09. Or... take the NetworkConstants.class file from the 0.3 Jar and insert it into the 0.2 Jar - it should still work!)
Objects which contain lists of users now use a standard getMembers() method to access a clone of the list. The getUserAt() method of YahooGroup has been removed - it was not thread safe as the list could be updated during an iteration over the groups list of users. The prefered route now is to use getMembers() to create a snapshot of the membership, and then iterate over that cloned list instead.
Used to return a hash of users who were on the friends list. Now the hash contains *all* users which the API knows about. This includes contacts, chatroom users (past and present, throughout the lifetime of the session), etc, etc.
A new method compliments getUsers() ... simply called getUser(), it returns the YahooUser object for the requested id (or null, if unknown).
YahooUser yu = session.getUser(friend);
if(yu!=null && yu.isFriend()) // Do something
Note: YahooUser has a new method isFriend(), which returns true if that user is currently in one or more groups of the friends list.
Reads much better. ;-)
There are now three Jar files. One for the ymsg.network.* packages, one for ymsg.support package (which requires a version of Java with Swing) and finally the test client now has its own Jar file.