Беда, товарищи!

Дети (~10 лет) перешли на удаленное обучение, расселись по комнатам с компьютерами и не могут сосредоточиться на уроках!

Они добавлены в google families, microsoft family, время за компьютером ограничено, а взрослые сайты убраны через opendns. Но чуть что — и даже прямо во время zoom-конференции урока ребенок начинает смотреть youtube. А потом училка дает домашнее задание — посмотреть видео и написать сочинение. И видео — тоже на youtube. Без ручной модерации не обойтись.

Под катом пишем волшебный пендаль, а именно chrome plugin, который отправляет каждый открываемый сайт в telegram злому родителю, работающему в соседней комнате.

Бот


Сначала сделаем telegram-бота и канал, в который будут приходить ссылки.

  1. Открываем BotFather, пишем /newbot, получаем botId (комбинацию из ~50 символов).
  2. Создаем новый канал, добавляем нашего бота туда как администратора.
  3. Пишем что-нибудь в канал, открываем ссылку https://api.telegram.org/botbotId/getUpdates, находим там result->channel_post->chat->id.

В итоге имеем botId и chatId.

Плагин


  1. Делаем папку, в ней будет 2 файла — manifest.json и index.js.
  2. Создаем chrome plugin manifest, по минимуму это:

    {
      "manifest_version": 2,
      "name": "Url Telegram Logger",
      "version": "1.0.0",
      "content_scripts": [
        {
          "matches": [
            "<all_urls>"
          ],
          "js": ["index.js"]
        }
      ]
    }
    

    Здесь написано, что на любую страницу (matches: all urls) будет внедряться скрипт index.js.
  3. Пишем сам плагин. Так как сайты сейчас часто SPA, будем отслеживать изменение document.location.href. Это можно сделать через MutationObserver. А можно просто проверять по таймауту. Так же будем отправлять сообщение, когда сайт закрывается (жопу пореже от стула отрывать, хулиганье непослушное растет). В последнем случае мы не можем отправлять обычный асинхронный запрос (сайт закрывается, запрос отменяется). Поэтому будем использовать синхронный navigator.sendBeacon:

    const settings = {
      botId: '...',
      chatId: '...',
      userName: 'Matvey',
      pollingInterval: 10000
    }
    
    const mutedUrls = [
      'https://gmail.com',
      'https://www.eduka.lt',
      // ..все остальное, что всегда можно..
    ]
    
    const sendMessage = (type, href) => {
      if (mutedUrls.find(url => href.startsWith(url))) { return false }
      const data = new FormData()
      data.append('chat_id', settings.chatId)
      data.append('text', `${settings.userName} ${type} ${document.title} ${href}`)
      navigator.sendBeacon(
        `https://api.telegram.org/bot${settings.botId}/sendMessage`, 
        data
      )
    }
    
    let latestHref = null
    let timeout = 0
    
    const run = () => {
      if (window.location.href !== latestHref) {
        latestHref = window.location.href
        sendMessage('opened', latestHref)
      }
      timeout && clearTimeout(timeout)
      timeout = setTimeout(run, settings.pollingInterval)
    }
    
    window.addEventListener('load', run)
    window.addEventListener('unload', () => sendMessage('closed', latestHref))
    
  4. Ставим плагин в хром на компьютер жертвы (перейти на chrome://extensions/, включить Developer mode, появится кнопка Load unpacked).


Заключение


20 минут потрачено, теперь можно потратить еще 20 часов, написать бекенд, настроить прием входящих команд (/mute url, /mute 2h url etc), добавить регистрацию, платные ежемесячные подписки, slack и hangouts ботов, а потом огрести за какие-нибудь права детей и персональных данных. Эти удовольствия оставляю читателю, у меня все.