Let's start with the main thing: why did we write this post?
For more than a year, we have implemented the ability to communicate with friends from Facebook without leaving ICQ. It so happened that not a single unofficial ICQ-client has yet added to our server support for Facebook - despite the fact that the opportunity seems to be convenient, useful and easy to implement. Perhaps the situation will change after the publication of a short and understandable topic HOWTO. Modestly we can say that there is no similar functionality in other IM networks (yes, of course, any client can establish two connections to two different servers and process two different protocols, but we are the only ones doing almost all the work for the client's author).

So - first, of course, the user must “link” his Facebook account to his ICQ number.
')
Unfortunately, this is the most difficult part of the procedure, because it requires launching a browser (fortunately, the user goes through it once in a lifetime). The easiest way to open the link is
https://www.icq.com/login/en?dest=http://lifestream.icq.com/settings/clientsettings?service=facebook&permission=xmpp in a regular browser, but you can do it in the component Browser inside the application - in a smaller window, the page that opens by the link will look more beautiful.
If Facebook is already “tied”, then in order to receive Facebook contacts, the client must send an SNAC packet [snac-family = 0x0003, snac-type = 0x0002] to the server with TLV {t = 0x0008, l = 1, at the login stage v = '\ 1'} inside.
public static final int ICQ_FACEBOOK_SUPPORT = 0x0302; private final BytesBuffer cs_FaceBook_create ( ) { return SNAC_Packet.newSnacPacket ( this, ICQ_FACEBOOK_SUPPORT, Garbage.getBytesBuffer ( ).putWord ( 8 ).putWord ( 1 ).writeByte ( 1 ) ); }
Contacts The Facebook server sends in a separate SNAC package [snac-family = 0x0013, snac-type = 0x0008].
The client must process this package from the server, otparsit, add Facebook-contacts to the local contact list.
private final void sc_Roster_Add_received ( final BytesBuffer packet ) { // Debug._trace ( "------sc 1308-------" ); // packet.dump ( ); try { while ( packet.available ( ) > 0 ) { String name = null; String proto = null; final String jid = packet.readPascalUTF8 ( ); // -1363121303@chat.facebook.com final int group = packet.getWord ( ); // 0001 final int id = packet.getWord ( ); // 0003 final int buddy = packet.getWord ( ); // 0000 int len = packet.getWord ( ); // 0023 while ( len > 0 ) { final int t = packet.getWord ( ); final int l = packet.checkWord ( ); if ( t == 0x0131 ) name = packet.readPascalUTF8 ( ); // eg "Alexander Peregudov" else if ( t == 0x0084 ) proto = packet.readPascalUTF8 ( ); // "facebook" magic string else { Debug._trace ( "unknown tlv type=" + t + " len=" + l ); packet.skip ( l + 2 ); } len -= 4 + l; } if ( buddy == 0 && StringCache.EqualsTo ( ASCII_CS_FACEBOOK_PROTO, proto ) ) { // Debug._trace ( "got FACEBOOK contact name='" + name + "' proto='" + proto + "' jid='" + jid + "' group=" + group + " id=" + id + " buddy=" + buddy); final ICQ_Group igroup; if ( (igroup = findGroup ( group )) != null ) igroup.add ( new ICQ_Contact ( this, id, group, jid, name, false ) ); else Debug._trace ( "WARNING! no group for " + name + ". - skipped" ); } } } catch ( final Throwable x ) { x.printStackTrace ( ); } }
Further work with Facebook contacts is similar to working with regular ICQ contacts. Sending messages and other actions are performed using standard packages and additional programming is not required.
A few words about how Facebook implemented jabber. The most important thing is that the status in jabber is synchronized with the status on the site, if
- the user is under Facebook-account in ICQ, he will be online, as for other customers who implement the Facebook-protocol, and in the chat on Facebook.
- incoming messages the user receives immediately in all clients. For example, if a user is on Facebook and ICQ is enabled on Facebook, as well as Agent on Facebook, he will receive a message three times. This feature is on the side of Facebook.
Of course, as befits the XMPP protocol, all messages go centrally through the Facebook server, while the message history is stored in the client. Sending messages happens instantly, without any delay.
As for anti-spam, it is implemented on the Facebook side and as far as we can judge, the only filter used is only friends can send messages to each other.
Since Facebook does not support the majority of contact list management operations, we give a small disclaimer as to what restrictions exist:
- Facebook contacts cannot be renamed, modified or deleted in any way.
- they cannot be transferred to another group
- Facebook group of contacts cannot be modified in any way (delete, rename, transfer contacts to and from a group)
- can not send messages to Facebook contacts being offline
Useful tips for last:
- Facebook contacts can be in one of three states (online, offline and evey), you can use separate icons for them, you can use camomiles
- as such a numeric 32-bit UIN these contacts do not have; although there are no places in the OSCAR protocol where the identifier is transmitted as a 32-bit number, your program is worth checking back
As always, we are ready to answer additional questions in the comments.