На данный момент MESSAGING не выдается новым приложениям

Протокол XMPP является основным протоколом для использования приложениями, которые ориентированы на обмен сообщениями между пользователями социальной сети “Одноклассники”. Примерами таких приложений являются Mail.Ru Agent и ICQ, которые используют этот протокол для общения с сервером Одноклассников.

Поддерживаемые расширения

Сервер XMPP Одноклассников старается поддерживать популярные расширения протокола XMPP, поддерживая совместимость с такими программами, как Gajim, Psi и другими. Разумеется, эти приложения не могут использовать ту функциональность, которая уникальна для сервера Одноклассников, однако могут общаться с пользователями, использующими как рекомендованные клиенты, так и любые другие, использующие протокол XMPP. Общение с теми пользователями, которые находятся на сайте, также происходит прозрачным образом.

Краткий список расширений, которые целиком или частично поддерживаются сервером Одноклассников:

  • XEP-0012: Last Activity
  • XEP-0030: Service Discovery
  • XEP-0033: Extended Stanza Addressing (ограниченное использование для MUC)
  • XEP-0045: Multi-User Chat (за исключением создания новых комнат)
  • XEP-0048: Bookmarks (ограниченное использование для MUC)
  • XEP-0049: Private XML Storage (ограниченное использование для MUC)
  • XEP-0054: vcard-temp (в данный момент read-only)
  • XEP-0055: Jabber Search
  • XEP-0153: vCard-Based Avatars
  • XEP-0199: XMPP Ping
  • XEP-0203: Delayed Delivery
  • XEP-0071: XHTML-IM (временно отключено)
  • XEP-0231: Bits of Binary (временно отключено, будет использоваться для поддержки смайликов)

Обратите внимание, что часть функционала может быть отключена из-за технических работ на сервере. Приложение должно адекватно реагировать на это, используя информацию из расширения XEP-0030.

Соединение с сервером

Для соединения с сервером используется адрес “xmpp.odnoklassniki.ru” и порт 5222. После соединения не забывайте провести TLS handshake (опционально, но крайне желательно).

После включения поддержки BOSH для соединения также будут доступны порты 80 и 443.

Процедура авторизации

Использование ID и пароля (не рекомендуется)

Клиент может использовать стандартную SASL PLAIN (RFC 3920) схему авторизации, указывая в качестве имени пользователя свой ID в Одноклассниках и свой пароль на сайте. Данная схема не рекомендуется к использованию, но оставлена для поддержки тех приложений, которые не могут использовать OAuth процедуру авторизации.

Так как данный метод не поддерживает ввод CAPTCHA, то он может быть недоступен сразу для большого числа IP-адресов и большого числа ID пользователей, если с использованием этих IP-адресов или ID пользователей происходят массовые некорректные действия (рассылка спама, ошибочные попытки авторизации и т.д.).

Использование OAuth-авторизации

Для использования данного метода приложение должно быть зарегистрировано на одноклассниках как внешнее, т.е. иметь возможность авторизовывать пользователей по протоколу OAuth. Кроме того, приложение должно иметь право MESSAGING, которое можно получить по запросу в службу поддержки.

Для авторизации используется метод “X-ODKL-API-SESSION-KEY”.

C: <auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="X-ODKL-API-SESSION-KEY" >{application_id: '...', session_key: '...'}</auth>
S: <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>

В качестве application id идёт числовой идентификатор приложения, session_key — токен, полученный во время OAuth-авторизации пользователя. Обратите внимание, что данные передаются без Base64-кодировки.

Если произошла ошибка, то ответ сервера соответствует стандарту:

C: <auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="X-ODKL-API-SESSION-KEY" >{application_id: '...', session_key: '...'}</auth>
S: <failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><... /></failure>

Коды ошибок (названия элементов внутри станзы failure):

  • malformed-request
    • неправильный формат JSON
    • отсутствуют необходимые свойства (application_key / session_key)
  • temporary-auth-failure
    • временная ошибка (недоступна база данных, например)
    • неверный ключ приложения или сессии
  • account-disabled
    • пользователь не найден, либо заблокирован
  • not-authorized
    • приложению не разрешена операция MESSAGING

Отличия от стандарта

Сервер Одноклассников не является сервисом прозрачной пересылки сообщений между клиентами. Его можно рассматривать скорее как некий интерфейс доступа к базе контактов, сообщений и сервисов. Сообщения прозрачным образом пересылаются между множеством клиентов XMPP, пользователей онлайн-версии сайта и мобильных пользователей. Как следствие, имеют место следующие отличия от стандартов XMPP:

  • Сервер не возвращает идентификатор ресурса для контактов. Всё общение происходит с т.н. bare jid. Указание resource чаще всего будет игнорироваться (сообщение попадёт в базу и будет передано всем контактам).
  • Сервис MUC Одноклассников не отключает пользователей от комнаты после дисконнекта. Пользователь остаётся в комнате (в режиме offline) до явного выхода из неё. По этой причине сервер передаёт текущий список комнат в ответе расширения bookmarks вместе со флагом автосоединения.
  • Сервис MUC Одноклассников не позволяет пользователям иметь свои имена в комнатах. Для совместимости с протоколом XMPP каждому назначается имя, состоящее из имени, фамилии и уникального суффикса.
  • В сервисе MUC нельзя создавать новые комнаты стандартными средствами XMPP, так как необходимо сразу указывать приглашённых участников. Команду создания чата смотрите ниже.

Особенности взаимодействия с сервисом сообщений

  • После соединения с сервером клиенту приходят все непрочитанные сообщения. Контролировать эту политику можно указанием дополнительной опции send-unread-chat-messages в первой станзе presence:
C:
<presence xmlns="jabber:client">
  <status></status>
  <priority>0</priority>
  <option count="0" xmlns="http://www.odnoklassniki.ru/send-unread-chat-messages" />
  ...
</presence>
  • После выхода (дисконнекта, обрыва соединения) все непрочитанные сообщения будут помечены как прочитанные (в частности для того, чтобы не посылать ещё раз непрочитанные при новом соединении). Отключить эту политику можно опцией mark-chat-messages-read-on-exit:
C:
<presence xmlns="jabber:client">
  <status></status>
  <priority>0</priority>
  <option value="false" xmlns="http://www.odnoklassniki.ru/mark-chat-messages-read-on-exit" />
  ...
</presence>

Расширения протокола

Включение timestamp’ов для получаемых сообщений

Указание дополнительного feature “http://www.odnoklassniki.ru/timestamp” клиентом позволяет серверу начать передавать в сообщениях дополнительное поле с timestamp’ом всех сообщений (а не только из offline storage):

C: (ответ на запрос о возможностях)
<iq type="result" id="discover-client-capabilities" >
    <query xmlns="http://jabber.org/protocol/disco#info" node="..." >
        <identity category="client" type="..." name="..." />
            ...
            <feature var="http://www.odnoklassniki.ru/timestamp" />
            ...
        </identity>
    </query>
</iq>
 
S: (каждое входящее сообщение)
<message from="..." type="chat" to="..." id="..." >
    <timestamp xmlns="http://www.odnoklassniki.ru/timestamp" ms="1390311411632" />
    <body>...</body>
</message>

Дополнительные команды для взаимодействия с сервисом

Следующие команды доступны для приложений, авторизованных через OAuth:

Получение списка дискуссий

Команда возвращает список недавних дискуссий пользователя:

C:
<iq id="someid" type="get">
    <query xmlns="http://www.odnoklassniki.ru/recent-conversations" />
</iq>
 
S:
<iq from="odnoklassniki.ru" type="result" id="someid" to="3841108762123@odnoklassniki.ru/RUMOSODKL-0168" >
    <paging-wrapper xmlns="http://www.odnoklassniki.ru/recent-conversations" total-count="0" data-inconsistency="false" forward-marker="1351639048058" backward-marker="1374666381644">
        <conversation last-user-access-time-ms="1373975118522" has-like="false" subject="" last-event-time="2013-07-24T11:46:21Z" last-event-time-ms="1374666381644" last-user-access-time="2013-07-16T11:45:18Z" has-reply="false" type="GROUPCHAT" forbidden-by-user="false" new-messages-count="2" jid="10240590807054@chat.odnoklassniki.ru" >
            <last-message>
                <message xmlns="jabber:client" from="10240590807054@chat.odnoklassniki.ru/Иван Пятый" type="groupchat" id="WuxPo1s_PtBeeE_NgbEIYyMORKi787DP2WNYDaBFQBo" to="3841108762123@odnoklassniki.ru/RUMOSODKL-0168" >
                    <body>test</body>
                    <delay xmlns="urn:xmpp:delay" stamp-ms="1374666381644" from="10240590807054@chat.odnoklassniki.ru" stamp="2013-07-24T11:46:21Z" >Offline Storage</delay>
                </message>
            </last-message>
        </conversation>
        <conversation last-user-access-time-ms="1366879245723" has-like="false" last-event-time="2013-04-25T08:40:45Z" last-event-time-ms="1366879245723" last-user-access-time="2013-04-25T08:40:45Z" has-reply="false" type="CHAT" new-messages-count="0" jid="3841108648784@odnoklassniki.ru" >
            <last-message>
                <message xmlns="jabber:client" from="3841108648784@odnoklassniki.ru" type="chat" to="3841108762123@odnoklassniki.ru/RUMOSODKL-0168" id="AAADflPqo1AAAAN-U-xeCwoAAAE-QFoVmxgxAAAAAAAAAAA" >
                    <body>test 4</body>
                    <delay xmlns="urn:xmpp:delay" stamp-ms="1366879245723" from="odnoklassniki.ru" stamp="2013-04-25T08:40:45Z" >Offline Storage</delay>
                </message>
            </last-message>
        </conversation>
        <conversation last-user-access-time-ms="1351639048058" has-like="false" last-event-time="2012-10-30T23:17:28Z" last-event-time-ms="1351639048058" last-user-access-time="2012-10-30T23:17:28Z" has-reply="false" type="CHAT" new-messages-count="0" jid="3841108732942@odnoklassniki.ru" >
            <last-message>
                <message xmlns="jabber:client" from="3841108732942@odnoklassniki.ru" type="chat" to="3841108762123@odnoklassniki.ru/RUMOSODKL-0168" id="AAADflPr7A4AAAN-U-xeCwoAAAE6s_cfeikvAAAAAAAAAAA" >
                    <body>test 2</body>
                    <delay xmlns="urn:xmpp:delay" stamp-ms="1351639048058" from="odnoklassniki.ru" stamp="2012-10-30T23:17:28Z" >Offline Storage</delay>
                </message>
            </last-message>
        </conversation>
    </paging-wrapper>
</iq>

Создание новой комнаты мультичата

При создании чата передаётся список приглашённых участников. Тема является опциональным аргументом.

C:
<iq type="set" id="create-chat-id">
    <query xmlns="http://www.odnoklassniki.ru/create-chat">
        <subject>Some topic</subject>
        <item jid="3841108762123@odnoklassniki.ru" />
    </query>
</iq>
 
S:
<iq from="odnoklassniki.ru" type="result" id="create-chat-id" to="3841108648784@odnoklassniki.ru/RUMOSODKL-0168" >
    <item xmlns="http://www.odnoklassniki.ru/create-chat" jid="10240590676048@chat.odnoklassniki.ru" />
</iq>

Важно: создание чата конкретным соединением с помощью данной команды не означает автоматическое вступление в конференцию для данного соединения и начала приёма сообщений. Кроме IQ-ответа клиенту придёт приглашение в чат (от самого себя), которое он должен принять.

Получение истории переписки

Возвращает историю переписки с конкретным участником или в комнате чата.

C:
<iq id="someid" type="get">
    <query xmlns="http://www.odnoklassniki.ru/conversation-history-chunked" jid="10240590807054@chat.odnoklassniki.ru" start-date-ms="0" end-date-ms="9223372036854775807" count="5" first-index="1" />
</iq>
 
S:
<iq from="odnoklassniki.ru" type="result" id="someid" to="3841108762123@odnoklassniki.ru/RUMOSODKL-0168" >
    <list-chunk xmlns="http://www.odnoklassniki.ru/conversation-history-chunked" total-count="20" pager-offset="0" data-inconsistency="false" first-index="1" total-count-recognized="true" count="5" >
        <message xmlns="jabber:client" from="10240590807054@chat.odnoklassniki.ru/Екатерина Вторая" type="groupchat" id="7HHpRWFlt2inKvAKZUNds8XhpcLpaxES8TA3sbkv8yE" to="3841108762123@odnoklassniki.ru/RUMOSODKL-0168" >
            <body>тест</body>
            <delay xmlns="urn:xmpp:delay" stamp-ms="1373975155091" from="10240590807054@chat.odnoklassniki.ru" stamp="2013-07-16T11:45:55Z" >Offline Storage</delay>
        </message>
        <message xmlns="jabber:client" from="10240590807054@chat.odnoklassniki.ru/Иван Пятый" type="groupchat" id="npOwmfhn-lyHD56Ya5o7Gp3iK1PD4bAekM1llX5qbIg" to="3841108762123@odnoklassniki.ru/RUMOSODKL-0168" >
            <body>asdmkmkdc</body>
            <delay xmlns="urn:xmpp:delay" stamp-ms="1374233575394" from="10240590807054@chat.odnoklassniki.ru" stamp="2013-07-19T11:32:55Z" >Offline Storage</delay>
        </message>
        <message xmlns="jabber:client" from="10240590807054@chat.odnoklassniki.ru/Иван Пятый" type="groupchat" id="WuxPo1s_PtBeeE_NgbEIYyMORKi787DP2WNYDaBFQBo" to="3841108762123@odnoklassniki.ru/RUMOSODKL-0168" >
            <body>test</body>
            <delay xmlns="urn:xmpp:delay" stamp-ms="1374238146033" from="10240590807054@chat.odnoklassniki.ru" stamp="2013-07-19T12:49:06Z" >Offline Storage</delay>
        </message>
        <message xmlns="jabber:client" from="10240590807054@chat.odnoklassniki.ru/Иван Пятый" type="groupchat" id="WuxPo1s_PtBeeE_NgbEIYyMORKi787DP2WNYDaBFQBo" to="3841108762123@odnoklassniki.ru/RUMOSODKL-0168" >
            <body>test</body>
            <delay xmlns="urn:xmpp:delay" stamp-ms="1374238160749" from="10240590807054@chat.odnoklassniki.ru" stamp="2013-07-19T12:49:20Z" >Offline Storage</delay>
        </message>
        <message xmlns="jabber:client" from="10240590807054@chat.odnoklassniki.ru/Иван Пятый" type="groupchat" id="Z7OrBrf7hfQ-TfnPOr-3fP16hiUJ8kGTIOR_QYGX-G8" to="3841108762123@odnoklassniki.ru/RUMOSODKL-0168" >
            <body>123123</body>
            <delay xmlns="urn:xmpp:delay" stamp-ms="1374238986995" from="10240590807054@chat.odnoklassniki.ru" stamp="2013-07-19T13:03:06Z" >Offline Storage</delay>
        </message>
    </list-chunk>
</iq>

Поддержка статусов прочитанности

Сервер может уведомлять клиента о факте чтения сообщений клиентом (если клиент это поддерживает – вызовами mark-as-read, если это XMPP, или скроллингом, если получатель читает сообщение с экрана). Для этого клиент должен подписаться на события о прочитанности сообщений. При этом клиента будут уведомлять и о факте чтения сообщения получателем, и о факте чтения сообщения, если сам пользователь прочитал его с другого устройства.

C: (клиент подписывается на события)
<iq id="..." type="set">
    <pubsub xmlns="http://jabber.org/protocol/pubsub" >
        <subscribe node="http://www.odnoklassniki.ru/marked-as-read" jid="11111111@odnoklassniki.ru" />
    </pubsub>
</iq>
 
S:
<iq from="odnoklassniki.ru" type="result" id="..." to="11111111@odnoklassniki.ru/RESOURCE" >
    <pubsub xmlns="http://jabber.org/protocol/pubsub">
        <subscribe node="http://www.odnoklassniki.ru/marked-as-read" subscription="subscribed" jid="11111111@odnoklassniki.ru" />
    </pubsub>
</iq>
 
C: (отправка сообщения)
<message type="chat" to="22222222@odnoklassniki.ru" id="aadca" >
    <body>outgoing message</body>
    <active xmlns="http://jabber.org/protocol/chatstates"/>
</message>
 
S: (нотификация о прочитанности текущей дискуссии самим отправителем)
<message from="odnoklassniki.ru" to="11111111@odnoklassniki.ru" >
    <items xmlns="http://jabber.org/protocol/pubsub#event" node="http://www.odnoklassniki.ru/marked-as-read" >
        <item>
            <marked-as-read xmlns="http://www.odnoklassniki.ru/marked-as-read" conversation="22222222@odnoklassniki.ru" last-read-timestamp="1390311356319" self="true" jid="11111111@odnoklassniki.ru" />
        </item>
    </items>
</message>
 
S: (нотификация о прочитанности дискуссии получателем)
<message from="odnoklassniki.ru" to="11111111@odnoklassniki.ru" >
    <items xmlns="http://jabber.org/protocol/pubsub#event" node="http://www.odnoklassniki.ru/marked-as-read" >
        <item>
            <marked-as-read xmlns="http://www.odnoklassniki.ru/marked-as-read" conversation="22222222@odnoklassniki.ru" last-read-timestamp="1390311368177" self="false" jid="22222222@odnoklassniki.ru" />
        </item>
    </items>
</message>

В качестве conversation может выступать JID MUC чат-группы. В этом случае будут приходить только уведомления о прочитанности сообщений текущим пользователем (с других устройств).