Цели, задачи, оправдания безумства.


Все началось с того, что кто-то из хабравчан в комментариях поведал о использовании Google Translate в роли синонимайзера. Он предложил переводить текст с одного языка на другой и обратно и обещал достаточно хороший процент отличий и сохранение смысла текста. Но это не точно.

Вопросы, на которые я решил получить ответ «да»


  • Можно ли создать Telegram бота в Google Script?
  • Можно ли бесплатно использовать API Google Translate без регистрации и SMS?
  • Можно ли сделать онлайн инструмент без использования хостинга?

Как все это работает


Сначала я создал бота и получил API ключ. Я не буду писать о том, как это сделать, эта информация много раз публиковалась на хабре и легко гуглится.

Очень быстро стало понятно, что я смогу отправить http запрос на сервер Telegram. Ни о каком web hook я не думал. Не исключено, что его можно использовать через google sites, но я вообще не проверял эту мысль.

Потом я создал табличный документ с двумя листами. На первом листе хранится параметр offset, необходимый для получения сообщений боту, которые еще не были получены. На том же листе на второй строчке записывается дата последнего обновления. На втором листе расположился лог входящих сообщений с результатом работы перевода на болгарский язык и обратно.

Болгарский язык был выбран потому, что он близок к русскому, но, к сожалению, это не спасло от перевода незнакомых слов в транслит.

Через триггеры проекта в скрипте я поставил выполнение функции получения данных каждую минуту.

Функция получает последние сообщения боту, используя id последнего сообщения +1. Далее, все сообщения прогоняются через translate и отправляются обратно.


Недостатки и неприятные особенности


Естественно, выбранные «инструменты» реализации бота накладывают немало ограничений. Во-первых, бот будет отвечать на сообщения с большой задержкой (до минуты). Во-вторых, несмотря на то, что Google Translate используется внутри Google Script, ограничения по количеству запросов в секунду и общему их количеству в сутки все же есть. По понятным причинам возможность использования web hook отсутствует.

Говорить о качестве работы Google Translate в роли синонимайзера вообще не приходится. Этот способ совершенно не подходит. Возможно, имеет смысл разбивать текст на предложения, а предложения на слова.

/**
 * Получает входящие сообщения и отвечает на них
 */
function getMessages()
{
  
  var botId = 'TELEGRAM_BOT_API_KEY';
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheets = ss.getSheets();

  var offset = sheets[0].setActiveSelection('B1').setNumberFormat('@STRING@').getValue();
  
  var updates = UrlFetchApp.fetch("https://api.telegram.org/bot"+botId+"/getUpdates?offset="+ offset + '&limit=40&timeout=1');
  
  var transferLanguage = 'bg'; // Язык для синонимайзера
  var sourceLanguage = 'ru'; // Язык источника
  
  updates = JSON.parse(updates);
  Logger.log(updates);
  if (updates.ok) {
     for (var i in updates.result) {
       var update = updates.result[i];
       offset = update.update_id + 1;
       sheets[0].setActiveSelection('B1').setValue(offset);
       sheets[0].setActiveSelection('B2').setValue(new Date(update.message.date * 1000));
       // Входящее сообщение получено
       var text = update.message.text;
       
       if (text.length >= 4096) {
         text = 'Ваше сообщение слишком большое, попробуйте отправить его по частям';
       } else {
         if (text == '/start') {
           text = 'Просто вставьте текст, который необходимо уникализировать. Через несколько минут вы получите обработанный текст.';
         } else {
           Utilities.sleep(1000);
           text = LanguageApp.translate(LanguageApp.translate(text, sourceLanguage, transferLanguage), transferLanguage, sourceLanguage);
         }
         
         writeLog({
           date: new Date(update.message.date * 1000),
           inMessage: update.message.text,
           outMessage: text,
           userName: update.message.from.first_name + ' ' + update.message.from.last_name,
           userId: update.message.from.id,
           userUsername: update.message.from.username
         });
       }
       
       UrlFetchApp.fetch("https://api.telegram.org/bot"+botId+"/sendMessage", {
           'method' : 'post',
           'payload' : {
               chat_id: update.message.chat.id,
               text: text
           }
       });
    }
  }
}

/**
 * Пишет в документ входящие сообщения и результат "синонимайзера"
 */
function writeLog(data)
{
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheets()[1];
  
  var lastRow = sheet.getLastRow() + 1;
  
  sheet.setActiveSelection('A' + lastRow).setNumberFormat('@STRING@').setValue(data.date);
  sheet.setActiveSelection('B' + lastRow).setNumberFormat('@STRING@').setValue(data.userUsername);
  sheet.setActiveSelection('C' + lastRow).setNumberFormat('@STRING@').setValue(data.userId);
  sheet.setActiveSelection('D' + lastRow).setNumberFormat('@STRING@').setValue(data.userName);
  sheet.setActiveSelection('E' + lastRow).setNumberFormat('@STRING@').setValue(data.inMessage);
  sheet.setActiveSelection('F' + lastRow).setNumberFormat('@STRING@').setValue(data.outMessage);

}

Что в итоге?


Мой эксперимент показал, что можно без проблем связать сервисы Google с ботом Telegram в личных целях, автоматизировать сбор информации и получать ее весьма оперативно. Можно без проблем написать парсер какого-нибудь авито и отправлять новые объявления по интересующем запросу в телеграм. В этом случае даже скорость ответа бота на сообщения не играет никакой существенной роли.

Синонимайзер, конечно, получился так себе.

Вот такой лог можно наблюдать в документе:



Если у вас есть идеи по поводу организации web hook телеграма в google script, добро пожаловать в комментарии.
Поделиться с друзьями
-->

Комментарии (10)


  1. AlexRaptor
    12.04.2017 14:02

    Поправьте название, пожалуйста.


  1. mihmig
    12.04.2017 14:46
    +1

    А Google script можно запустить автономно (не открывая браузер или Google docs)?


    1. ilyaplot
      12.04.2017 15:47

      Да, там есть crontab


      1. mihmig
        13.04.2017 14:10

        Спасибо!
        Жаль что есть только периодические задания. Сколько он может висеть в фоне?

        И складывать данные в листы Spreadsheet-ов не очень красиво. Может есть какая БД?


        1. ilyaplot
          13.04.2017 14:27

          Похоже, что 6 минут. Если я правильно понимаю, то и БД можно подключить. https://developers.google.com/apps-script/guides/jdbc
          Но для БД придется делать view. Для нужд игрушечного бота таблица — идеальный вариант хранения данных.


        1. QDeathNick
          15.04.2017 14:27

          А чем не красиво? У меня есть опыт использования такой псевдо-БД на 200000 записей. Люди вбивают первичку в одних файлах, там же скрипты всё проверяют и раскрашивают, потом всё втягивается в другой файл и собирается в итоговую табличку с графиками. Всё шустро считается и результаты на почту падают. Всё работает уже несколько лет, а сделал за пару часов.


          1. ilyaplot
            18.04.2017 10:39

            Вполне согласен. Для определенных задач хороши определенные инструменты. Не очень красиво использовать такую псевдо-бд для сайта, например, но нельзя утвержадть, что использовать этот инструмент вообще не стоит.


        1. QDeathNick
          15.04.2017 14:31

          При обновлении данных тоже срабатывает триггер, при открытии и.т.д. А какие ещё задания вам нужны?


  1. peter23
    12.04.2017 14:46
    +1

    Русский и болгарский действительно близки, но, к сожалению, Google Translate этого не учитывает. Перевод между этими языками он делает через английский, я это многократно наблюдал.


    1. ilyaplot
      12.04.2017 15:48

      Вполне возможно. Замена болгарского на другой язык дает минимальные отличия.