Как подружить Google Диск и Google Календарь? Пробуем GAS на вкус

Корзина покупателя GASПредлагаю читателям «Хабрахабра» историю о том, как мне удалось повысить свою покупательскую способность в кризисное время при помощи Google Apps Script (GAS). Под катом вы найдете нестандартный пример использования и узнаете о возможностях работы со службами Google Drive и Google Calendar.

Началось все с того, что цена импортируемых товаров в России неуклонно росла вверх. Работая IT-специалистом в крупной ритейл-сети, у меня возникла идея о том, как можно воспользоваться преимуществом наличия доступа к товарной базе, не нарушая установленных правил компании и тем более закона. Наибольший интерес с точки зрения экономии личных денежных средств представляют так называемые «промоакции» (тарифы со скидкой). Необходимо было организовать ежедневную выгрузку «промоакций» на интересующие товары и реализовать возможность своевременного получения уведомлений о наличии скидок на Android-смартфон.

Очевидно, что существует множество вариантов реализации необходимого функционала. Рассматривались варианты создания консольного приложения на любом языке (например Java), выполняющего подключение к базе данных и дальнейшую отправку SMS через HTTP API любого из существующих бесплатных сервисов рассылки. Однако, мне хотелось по максимуму использовать уже имеющиеся инструменты, в том числе корпоративный сервис от Google (Почта, Диск, Календарь и т.д.).

Для достижения желаемого результата необходимо было решить следующие задачи:

  1. Выгрузить данные о промоакциях в файл;
  2. Обработать файл, добавить событие в Google Календарь и настроить SMS-оповещение;
  3. Запланировать выполнение задач на ежедневное автоматическое выполнение.

Chapter 1. SQLless


Есть цель, есть дистанция. Остальное — детали.

Первый пункт сводится к написанию не сложного SQL-запроса, который выгружает актуальные на день промоакции для обозначенного в запросе списка товаров. Чтобы максимально упростить данный этап и не писать ни строчки кода, было решено использовать «родные» утилиты для работы с БД от производителя.Поддержка выгрузки в CSV присутствует «из коробки», что полностью отвечает требованиям к поставленной задаче. Достаточно было составить корректный SQL-запрос и создать на его основе конфигурационный файл для утилиты выгрузки из базы данных. В результате мы имеем конфигурационный файл, при запуске которого получаем на выходе готовый CSV-файл с актуальными на день промоакциями.


Chapter 2. Fifty shades of GAS


Основной задачей на этом этапе являлось добавление информацию из CSV-файла в Google Календарь. Google Apps Script (GAS) предоставляет доступ к API множества сервисов Google (Диск, Почта, Календарь, Документы и др.) с помощью языка, базирующегося на JavaScript. Таким образом, вы можете например автоматизировать ежедневную отправку каких-либо логов или других файлов с вашего Google Диск на Google Почта. Это всего лишь один из множества возможных примеров использования.

Я не люблю искать сложных путей, поэтому CSV-файл при выгрузке мы будем сохранять прямо в синхронизированной на компьютере папке Google Drive. Благодаря этому изящному решению, файл практически сразу после сохранения доступен нам из GAS. Остается прочитать файл, добавить событие в Google Календарь и включить для него SMS-уведомление.
Я напишу ровно 30 строк кода. Считайте вслух...


function addTarifsFromCSVtoCalendar() {  
  var csvFiles = DriveApp.getFilesByName("TarifNotifier.csv");  
  if(csvFiles.hasNext()) {    
    var csvFile = csvFiles.next();    
    var lastModDate = csvFile.getLastUpdated();    
    var currentDate = new Date();
    lastModDate.setHours(0,0,0,0);
    currentDate.setHours(0,0,0,0);    
    if (lastModDate.getTime() == currentDate.getTime()) {
      var csvData = csvFile.getBlob().getDataAsString("windows-1251");
      var csv2DArray = Utilities.parseCsv(csvData, ',');      
      var calendars = CalendarApp.getCalendarsByName("Скидки");
      if(calendars.length == 0) {
        var calendar = CalendarApp.createCalendar("Скидки");    
      } else 
        var calendar = calendars[0];      
      var events = calendar.getEventsForDay(currentDate);
      for (var i=0; i<events.length; i++) events[i].deleteEvent();
      startTime = new Date();
      endTime = new Date();
      startTime.setHours(09,30,0,0);      
      endTime.setHours(22,0,0,0);      
      for (var i=0; i<csv2DArray.length; i++) {
        var event = calendar.createEvent(csv2DArray[i][0] + ' - ' + csv2DArray[i][1], startTime, endTime);
        event.setDescription(csv2DArray[i]);
        event.addSmsReminder(30);
      }      
    } else Logger.log("No updated data!");
  }
}

Итак, разберем, что же это за код и как он работает:

var csvFiles = DriveApp.getFilesByName("TarifNotifier.csv");
if(csvFiles.hasNext()) {    
   var csvFile = csvFiles.next();
   ...
}

Обращаемся через API Google Drive к файлу с именем TarifNotifier.csv. Поскольку в различных директориях могут храниться файлы с одинаковым именем, переменной csvFiles будет передана ссылка на массив всех файлов с именем TarifNotifier.csv. Но мы-то знаем, что у нас только один файл с таким именем, поэтому просто обращаемся к самому первому элементу из массива при его наличии.

var lastModDate = csvFile.getLastUpdated();    
var currentDate = new Date();
lastModDate.setHours(0,0,0,0);
currentDate.setHours(0,0,0,0);
if (lastModDate.getTime() == currentDate.getTime()) {
   ...
}

Проверяем дату последнего обновления CSV-файл и сверяем ее с текущей датой. Метод setHours(0,0,0,0) используется для обнуления времени в переменных, что позволит нам учитывать при сравнении только дату. Промоакции изменяются только 1 раз в день, поэтому если CSV-файл не был обновлен «сегодня», то это означает что новых интересующих нас промоакций в магазине не появилось.

var csvData = csvFile.getBlob().getDataAsString("windows-1251");
var csv2DArray = Utilities.parseCsv(csvData, ',');  

Считываем данные из CSV-файла и разбираем их в двумерный массив. Это нам понадобится для того, чтобы выводить каждый товар отдельным событием в календаре.

var calendars = CalendarApp.getCalendarsByName("Скидки");
if(calendars.length == 0) {
   var calendar = CalendarApp.createCalendar("Скидки");    
} else 
   var calendar = calendars[0];      
var events = calendar.getEventsForDay(currentDate);
for (var i=0; i<events.length; i++) events[i].deleteEvent();

Проверяем наличие календаря с именем «Скидки» и если он не существует, то создаем новый. Опять же, поскольку календарей с одинаковым именем может быть несколько, то в переменную calendars будет передана ссылка на массив. Мы же уже обусловливались, что календарь с именем «Скидки» у нас один? Так вот, он один. На случай если скрипт уже был запущен ранее в этот день, очищаем календарь от всех событий за текущий день, чтобы избежать дублирования.

startTime = new Date();
startTime.setHours(09,30,0,0);
endTime = new Date();
endTime.setHours(22,0,0,0);
for (var i=0; i<csv2DArray.length; i++) {
   var event = calendar.createEvent(csv2DArray[i][0] + ' - ' + csv2DArray[i][1], startTime, endTime);
   event.setDescription(csv2DArray[i]);
   event.addSmsReminder(30);
}      

Собственно то, ради чего все и начиналось. Для каждой строки CSV-файла (для каждого товара) создаем новое событие в календаре с 09:30 до 22:00 (время работы магазина) и устанавливаем для него SMS-уведомление, которое должно срабатывать ровно за 30 минут до начала события.

Chapter 3. Schedueler's list


Этот список — само добро. Этот список — сама жизнь. А по краям его — сплошная пропасть.

Для получения желаемого результата, осталась самая малость — запланировать задачи на ежедневное выполнение:
  1. Планируем ежедневный запуск выгрузки CSV-файла на Google Диск в 07:30 через Windows Task Scheduler;
  2. Воспользуемся встроенным в Google Apps Script планировщиком «Триггеры проекта», чтобы настроить ежедневный запуск нашей функции addTarifsFromCSVtoCalendar() с 08:00 до 09:00 (Google не позволяет указать точное время запуска).



В результате информация о свежих промо-тарифах ежедневно обновляется в календаре Android-телефона к 9 утра. В это же время на телефон, привязанный к учетной записи Google, приходит SMS-уведомление.


Кризис и санкции теперь не так страшны!

При наличии вашего интереса к данной теме, в следующих статьях могу поделиться другими примерами использования Google Apps Script:

  • Как работать с Google Почта при помощи GAS?
  • Перенос графика работы сотрудников из Excel в Google Календарь.

Ссылки


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

    0
    А где же ссылка в паблик?)
      +2
      Да вот не хотелось бы мне пополнять ряды безработных :)
        0
        Ну почему же? Мне кажется, это наоборот прекрасный сервис от магазина мог бы быть. «Добавь себе наш календарь и будь в курсе о скидках». Я был бы рад, если бы мой локальный магазин предоставлял такую услугу.
          0
          Магазин, если захочет, да.

          А так человек по тонкому льду ходит. Преступного ничего нет, но нарушение рабочей этики — налицо. Заметим, в контексте рынка ценных бумаг это называется «инсайд» и уже является уголовным преступлением.
            0
            Можно ж предложить работодателю такую идею.

            А про инсайт я вообще не понял. Это же публичная информация про промо акции. Какой к черт инсайт?
              0
              у человека есть доступ к будущим акциям (читай — прямой доступ к БД), а не к публичным на сайте магазина.
                0
                Доступ то может и есть, но чтобы не нарушать даже этики компании запрос смотрит только на сегодняшние уже выставленные в магазин цены по 1-5 интересующим товарам. Т.е. полный аналог похода в магазин и просмотра выставленных ценников. Продавцы в зале владеют этой информацией намного раньше.
                0
                Она совсем публичная, или контекстная? Можете ли вы иметь ту же информацию в том же объёме, не будучи сотрудником?
                  0
                  Да конечно, просто зайдя в магазин. Здесь больше интереса в учебном плане, нежели в ценности информации.
        0
        Обновил статью. Теперь мы еще и научились читать CSV-файлы в массив, средствами GAS.

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

        Самое читаемое