- PVSM.RU - https://www.pvsm.ru -

Шестое чувство Facebook

Расширение для Chrome показывает, когда кто-то набирает текст

Шестое чувство Facebook - 1

Некоторые люди слишком много времени проводят в социальных сетях. Настолько много, что у них уже возникает зависимость. Один из таких — программист Александр Кирзенберг (Alexandre Kirszenberg), который к тому же любит копаться во внутренностях Facebook — в коде JavaScript, отвечающем за пользовательский интерфейс и коммуникации.

«Пару месяцев назад я задумался о маленьком статусном индикаторе, который показывает, когда один из ваших друзей набирает вам текст, — пишет [1] Александр. — Такое маленькое расширение UI выдаёт много информации о собеседнике. Если индикатор несколько раз загорается и тухнет, это говорит о нерешительности. Если он загорелся надолго, кто-то пишет вам большое эссе. И нет ничего хуже того мучительного чувства, когда индикатор тухнет и больше не загорается».

Первым делом Александр решил найти, присылает ли Facebook уведомления о том, что кто-то набирает сообщения в Facebook Messenger, даже если у вас не запущен этот Facebook Messenger. Оказалось, что присылает.

Всем френдам рассылается событие typ длинного опроса /pull. Небольшое исследование показало, что событие действительно рассылается для каждого чата, даже если получатель не открывал его и никогда не получал.

Так появилось расширение Facebook Sixth Sense [2] для браузера Chrome. Оно показывает прямо в браузере, когда кто-то набирает сообщение в Facebook.

Шестое чувство Facebook - 2

Для создания этого расширения программист использовал недокументированные Facebook API. Пришлось разбираться с кодом JavaScript, который Facebook безжалостно минифицирует, превращая в мешанину символов.

Сначала он выяснил, какие модули Facebook импортирует через программный интерфейс системы организации модулей Asynchronous Module Definition [3] для асинхронной загрузки (у Facebook собственная реализация AMD). Модули и зависимости определяются стандартной функцией __d(name, dependencies, factory). Есть также require и requireLazy для импорта модулей.

Проще всего посмотреть, как это работает, в консоли браузера (хотя Facebook строго запрещает это делать). Похоже, там работают серьёзные ребята, с ними лучше не шутить.

Шестое чувство Facebook - 3

Но мы всё-таки осмелимся.

Шестое чувство Facebook - 4

Как видим, Facebook всегда загружает последнюю версию React [4] — отличной библиотеки компонентов пользовательских интерфейсов. Facebook довольно интенсивно использует React по всему сайту. В коде Facebook более 15 000 компонентов React [5] (по состоянию на октябрь 2015 года).

В исходном коде можно поискать __d( и посмотреть список модулей, доступных для импорта. Для главной страницы там всего-то 3000 модулей.

В чате Facebook Messenger, разумеется, тоже используются компоненты React. Нам нужно перехватить нотификации о наборе текста. Для более детального изучения кода Александр Кирзенберг рекомендует использовать инструмент React Developer Tools [6].

Шестое чувство Facebook - 5

Шестое чувство Facebook - 6

После установки этого расширения в инструментах разработчика Chrome появляется новая вкладка React. На ней выделяем чат.

Шестое чувство Facebook - 7

Здесь среди различных компонентов Facebook Messenger ищем индикатор набора текста, он находится между <ChatTabComposerContainer /> и <MercuryLastMessageIndicator />.

Поиск __d('ChatTyping в кодовой базе React находит два модуля: ChatTypingIndicator.react.js и ChatTypingIndicators.react.js. Это именно то, что нам нужно, пишет Кирзенберг. Он замечает, что некоторые модули подгружаются по мере необходимости, так что ChatTypingIndicators.react.js можно обнаружить только со второго раза.

Вот его код.

function() {
  var k = c('MercuryThreadInformer').getForFBID(this.props.viewer)
    , l = c('MercuryTypingReceiver').getForFBID(this.props.viewer);
  this._subscriptions = new (c('SubscriptionsHandler'))();
  this._subscriptions.addSubscriptions(
    l.addRetroactiveListener(
      'state-changed',
      this.typingStateChanged
    ),
    k.subscribe(
      'messages-received',
      this.messagesReceived
    )
  );
},

А именно, нас интересует вызов c('MercuryTypingReceiver').

В консоли можно посмотреть, как он работает.

> MercuryTypingReceiver.getForFBID
// function (i){var j=this._getInstances();if(!j[i])j[i]=new this(i);return j[i];}
> MercuryTypingReceiver.get
// function (){return this.getForFBID(c('CurrentUser').getID());}

Для проверки, как работает статусный индикатор, Александр использовал приложение Messenger на собственном смартфоне, чтобы отправить себе на ПК соответствующие события и словить их в консоли.

Более подробно изучив код, он нашёл ещё два полезных модуля MercuryThreads и ShortProfiles. Первый получает всю информацию о треде Messenger по его идентификатору, второй делает то же самое по профилю.

В общем, после всех изысканий вот как выглядит окончательный код расширения для Chrome, всего 40 строчек.

function getUserId(fbid) {
  return fbid.split(':')[1];
}

requireLazy(
  ['MercuryTypingReceiver', 'MercuryThreads', 'ShortProfiles'],
  (MercuryTypingReceiver, MercuryThreads, ShortProfiles) => {

    MercuryTypingReceiver
      .get()
      .addRetroactiveListener('state-changed', onStateChanged);

    // Called every time a user starts or stops typing in a thread
    function onStateChanged(state) {

      // State is a dictionary that maps thread ids to the list of the
      // currently typing users ids'
      const threadIds = Object.keys(state);

      // Walk through all threads in order to retrieve a list of all
      // user ids
      const userIds = threadIds.reduce(
        (res, threadId) => res.concat(state[threadId].map(getUserId)),
        []
      );

      MercuryThreads.get().getMultiThreadMeta(threadIds, threads => {
        ShortProfiles.getMulti(userIds, users => {
          // Now that we've retrieved all the information we need
          // about the threads and the users, we send it to the
          // Chrome application to process and display it to the user.
          window.postMessage({
            type: 'update',
            threads,
            users,
            state,
          }, '*');
        });
      });

    }
  }

);

Неплохой такой хак, слегка раскрывающий внутренности Facebook.

Исходный код расширения опубликован на Github [7].

Кстати, по временным меткам из мессенджера Facebook можно даже отслеживать режим сна [8] своих френдов (исходный код [9]).

Шестое чувство Facebook - 8

Автор: alizar

Источник [10]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/126272

Ссылки в тексте:

[1] пишет: http://kirszenberg.com/facebook-sixth-sense

[2] Facebook Sixth Sense: https://chrome.google.com/webstore/detail/facebook-sixth-sense/neghghjdkheikbfclgnglicflldmejio

[3] Asynchronous Module Definition: https://github.com/amdjs/amdjs-api/blob/master/AMD.md

[4] React: https://github.com/facebook/react

[5] более 15 000 компонентов React: https://facebook.github.io/react/blog/2015/10/07/react-v0.14.html#upgrade-guide

[6] React Developer Tools: https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en

[7] опубликован на Github: https://github.com/Morhaus/facebook-sixth-sense

[8] отслеживать режим сна: https://medium.com/life-tips/how-you-can-use-facebook-to-track-your-friends-sleeping-habits-505ace7fffb6

[9] исходный код: https://github.com/sqren/fb-sleep-stats

[10] Источник: https://habrahabr.ru/post/302506/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best