Начнем с главного: зачем мы написали этот пост?
Уже больше года у нас реализована возможность общения с друзьями из Facebook, не покидая ICQ. Так сложилось, что ни один неофициальный ICQ-клиент до сих пор не добавил к себе нашу серверную поддержку Facebook — при том, что возможность вроде бы удобная, полезная и легкая в реализации. Возможно, ситуация изменится после публикации короткого и понятного HOWTO по теме. Скромно можем сказать, что аналогичный функционал в других IM-сетях отсутствует (да, естественно, любой клиент может сам установить два соединения к двум разным серверам и обрабатывать два разных протокола, но мы единственные делаем практически всю работу за автора клиента).

Итак – вначале, естественно, пользователь должен «привязать» свой аккаунт на Facebook к своему номеру в ICQ.
К сожалению, это самая сложная часть процедуры, т. к. требует запуска браузера (к счастью, пользователь проходит через неё один раз в жизни). Проще всего открыть ссылку https://www.icq.com/login/ru?dest=http://lifestream.icq.com/settings/clientsettings?service=facebook&permission=xmpp в обычном браузере, но можно сделать это и в компоненте браузера внутри приложения — в меньшем окне страница, открывающаяся по ссылке, будет выглядеть красивее.
Если Facebook уже «привязан», то для того чтобы получать Facebook-контакты клиент должен на этапе логина к серверу отправить SNAC-пакет [snac-family=0x0003, snac-type=0x0002] с TLV {t=0x0008, l=1, v='\1' } внутри.
Контакты Facebook-сервер присылает в отдельном SNAC-пакете [snac-family=0x0013, snac-type=0x0008].
Клиент должен обработать этот пакет от сервера, отпарсить, добавить Facebook-контакты в локальный контакт-лист.
Дальнейшая работа с Facebook-контактами аналогична работе с обычными ICQ-контактами. Отправка сообщений и другие действия совершаются с помощью стандартных пакетов и дополнительного программирования не требуется.
Несколько слов о том, как Facebook реализовал jabber. Самое важное — статус в jabber синхронизован со статусом на сайте, если
Что касается антиспама, то он реализован на стороне Facebook и насколько мы можем судить, единственный используемый фильтр – только друзья могут отправлять сообщения друг другу.
Поскольку Facebook не поддерживает большинство операций по управлению контакт-листом, даем небольшой disclaimer относительно того, какие существуют ограничения:
Как всегда, готовы ответить на дополнительные вопросы в комментариях.
Уже больше года у нас реализована возможность общения с друзьями из Facebook, не покидая ICQ. Так сложилось, что ни один неофициальный ICQ-клиент до сих пор не добавил к себе нашу серверную поддержку Facebook — при том, что возможность вроде бы удобная, полезная и легкая в реализации. Возможно, ситуация изменится после публикации короткого и понятного HOWTO по теме. Скромно можем сказать, что аналогичный функционал в других IM-сетях отсутствует (да, естественно, любой клиент может сам установить два соединения к двум разным серверам и обрабатывать два разных протокола, но мы единственные делаем практически всю работу за автора клиента).

Итак – вначале, естественно, пользователь должен «привязать» свой аккаунт на Facebook к своему номеру в ICQ.
К сожалению, это самая сложная часть процедуры, т. к. требует запуска браузера (к счастью, пользователь проходит через неё один раз в жизни). Проще всего открыть ссылку https://www.icq.com/login/ru?dest=http://lifestream.icq.com/settings/clientsettings?service=facebook&permission=xmpp в обычном браузере, но можно сделать это и в компоненте браузера внутри приложения — в меньшем окне страница, открывающаяся по ссылке, будет выглядеть красивее.
Если Facebook уже «привязан», то для того чтобы получать Facebook-контакты клиент должен на этапе логина к серверу отправить SNAC-пакет [snac-family=0x0003, snac-type=0x0002] с TLV {t=0x0008, l=1, v='\1' } внутри.
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 ) );
}
Контакты Facebook-сервер присылает в отдельном SNAC-пакете [snac-family=0x0013, snac-type=0x0008].
Клиент должен обработать этот пакет от сервера, отпарсить, добавить Facebook-контакты в локальный контакт-лист.
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 ( ); // e.g "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 ( );
}
}
Дальнейшая работа с Facebook-контактами аналогична работе с обычными ICQ-контактами. Отправка сообщений и другие действия совершаются с помощью стандартных пакетов и дополнительного программирования не требуется.
Несколько слов о том, как Facebook реализовал jabber. Самое важное — статус в jabber синхронизован со статусом на сайте, если
- пользователь находится под Facebook-аккаунтом в ICQ, то он будет online, как для других клиентов, которые реализуют Facebook-протокол, так и в чате на сайте Facebook.
- входящие сообщения пользователь получает сразу во всех клиентах. Например, если пользователь находится на сайте Facebook и у него включена ICQ с Facebook, а также Агент с Facebook, то он получит сообщение трижды. Данная особенность находится на стороне Facebook.
Что касается антиспама, то он реализован на стороне Facebook и насколько мы можем судить, единственный используемый фильтр – только друзья могут отправлять сообщения друг другу.
Поскольку Facebook не поддерживает большинство операций по управлению контакт-листом, даем небольшой disclaimer относительно того, какие существуют ограничения:
- Facebook-контакты нельзя переименовывать, как-либо изменять или удалять
- их нельзя переносить в другую группу
- группу Facebook-контактов нельзя как-либо модифицировать (удалять, переименовывать, переносить контакты в группу и из группы)
- нельзя отправлять сообщения для Facebook-контактов находящихся offline
- Facebook-контакты могут находиться в одном из трех состояний (онлайн, оффлайн и эвей), можно использовать для них отдельные иконки, можно ромашки
- как такового числового 32-битного UIN у этих контактов нет; хотя в OSCAR-протоколе нет мест, где идентификатор передается именно как 32-битное число, вашу программу всё же стоит перепроверить
Как всегда, готовы ответить на дополнительные вопросы в комментариях.