Автоматическое оповещение об изменениях статуса почтовых посылок через SMS

В последнее время я стал делать много покупок в интернет-магазинах, и нередко ловлю себя на том, что очень часто проверяю статус своих посылок (с нашей почтой не беспокоиться не получится).
Поиск готовых решений приводил только к платным сервисам. В результате было принято решение сообразить что-нибудь свое.
Под катом список используемых сервисов и подробная инструкция.

Выбор вспомогательных сервисов


Следующий шаг поисков был посвящен сервисам, предоставляющим возможность периодического выполнения различных скриптов за неимением (ах, какая досада) личного сервера. Выбор пал на Google Apps Script. В качестве ЯП используется модификация хорошо знакомого мне Javascript.
В качестве SMS-гейта был выбран SMS.ru, предоставляющий возможность отправки неограниченного количества бесплатных SMS стандартной длины (180 символов латиницы, 60 юникода) на личный номер телефона.
Функцию трекинга было решено позаимствовать у [не знаю, насколько] универсального китайского сервиса 17track.

Если у вашего оператора есть email2sms-гейт, то все упоминания SMS.ru можно пропускать.

Приготовления


До того, как приступить к написанию… кода, нам нужны:
  • аккаунты на Google (вдруг у кого нет) и SMS.ru
  • API ID от SMS.ru
  • созданный пустой проект на Google Apps Script
  • хеш, без которого 17track откажется нам выдавать статус, для каждого трек-номера


Подробно расписывать процесс регистрации, надеюсь, не нужно.

API ID для SMS.ru можно получить здесь: online.sms.ru/?panel=settings&subpanel=api


Для создания скрипта в Google Apps Script требуется, как ни странно, пройти на сайт этого сервиса.
Там нас встретит следующее окно (если оно не было отключено ранее):

Нам нужен «Пустой проект».

Хеш для 17track не придется получать, генерация теперь производится силами Google Apps Script. Готовый код для вставки в скрипт можно получить здесь.

Все нужные ингредиенты получены, можно приступать к коду.

Код


var user = ["%API ID%", "%TELNO%"];

var num = [
  ["%TRACKCODE1%", "%NAME1%"],
  ["%TRACKCODE2%", "%NAME2%"],
  ...
  ["%TRACKCODEn%", "%NAMEn%"],
];

var errors = {
  "hsErr": "Wrong hash",
  "unAllow": "You've changed parameter \"lo\" in query URL. Set it to \"www.17track.net\"",
  "hsNon": "There's no hash"
}
var success = false;

function sendSMS(text){
  UrlFetchApp.fetch("http://sms.ru/sms/send?api_id="+user[0]+"&to="+user[1]+"&text="+encodeURI(text));
}

function digest2str(digest){
  var str = '';
  var i = 0;
  for (i=0; i<digest.length; i++) {
    byte = digest[i];
    if (byte < 0)
      byte += 256;
    byteStr = byte.toString(16);
    // Ensure we have 2 chars in our byte, pad with 0
    if (byteStr.length == 1) byteStr = '0'+byteStr;
    str += byteStr;
  }   
  return str;
}

function checkStatus(){
  var i = 0;
  for(i=0; i<num.length; i++){
    var response = UrlFetchApp.fetch("http://www.17track.net/r/handlertrack.ashx?callback=&num="+num[i][0]+"&pt=0&cm=0&cc=0&_="+Math.random());
    UserProperties.setProperty("q", response.getContentText());
    var result = Utilities.jsonParse(response.getContentText());
    var sendstring = num[i][1]+": ";
    if(result["ret"] == 1){
      if(result["dat"]["f"] == "0"){
        sendstring += "Track code not found";
      }else{
        success = true;
      }
    }else{
      sendstring += errors[result["msg"]] ? errors[result["msg"]] : "Please, leave comment on habrahabr, error message: "+result["msg"];
    }
    if(success){
      if(UserProperties.getProperty(num[i][0]) != result["dat"]["z"]["b"]){
        translit = UrlFetchApp.fetch("http://translate.google.com/translate_a/t?client=t&q="+encodeURI(result["dat"]["z"]["b"]));
        translitobj = Utilities.jsonParse(translit.getContentText());
        if(translitobj[0][0][3]){
          for(z in translitobj[0]){
            sendstring += translitobj[0][z][3]+" ";
          }
        }else{
          sendstring += result["dat"]["z"]["b"];
        }
        sendSMS(sendstring);
        UserProperties.setProperty(num[i][0], result["dat"]["z"]["b"]);
        success = false;
      }
    }else{
      sendSMS(sendstring);
    }
  }
}

Также можно не возиться с sms.ru, если у вашего оператора есть email2sms-гейт. Например, инструкции для Мегафон Удмуртия. Если есть, обнаружить на сайте оператора можно поиском по слову «e-mail». Убрана транслитерация (если у кого-то гейт не умеет клеить сообщения, сообщите, сделаю версию с транслитерацией). Название кода складывается в тему сообщения.
Код
var user = [
  "%EMAIL1%",
  "%EMAIL2%",
  ...
  "%EMAILn%"
];
var num = [
  ["%TRACKCODE1%", "%NAME1%"],
  ["%TRACKCODE2%", "%NAME2%"],
  ...
  ["%TRACKCODEn%", "%NAMEn%"],
];
var errors = {
  "hsErr": "Wrong hash",
  "unAllow": "You've changed parameter \"lo\" in query URL. Set it to \"www.17track.net\"",
  "hsNon": "There's no hash"
}
var success = false;

function sendSMS(code, text){
  var i = 0;
  for(i=0; i<user.length; i++){
    MailApp.sendEmail(user[i],
                   code,
                   text);
  }
}

function digest2str(digest){
  var str = '';
  var i = 0;
  for (i=0; i<digest.length; i++) {
    byte = digest[i];
    if (byte < 0)
      byte += 256;
    byteStr = byte.toString(16);
    if (byteStr.length == 1) byteStr = '0'+byteStr;
    str += byteStr;
  }   
  return str;
}

function checkStatus(){
  var i = 0;
  for(i=0; i<num.length; i++){
    hashstr = num[i][0]+"{EDFCE98B-1CE6-4D87-8C4A-870D140B62BA}0{EDFCE98B-1CE6-4D87-8C4A-870D140B62BA}www.17track.net";
    dig = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, hashstr);
    hs = digest2str(dig);
    var response = UrlFetchApp.fetch("http://s1.17track.net/Rest/HandlerTrackPost.ashx?lo=www.17track.net&num="+num[i][0]+"&hs="+hs);
    UserProperties.setProperty("q", response.getContentText());
    var result = Utilities.jsonParse(response.getContentText().replace(/^\((.*)\)$/, "$1"));
    var code = num[i][1]
    var sendstring = "";
    if(result["ret"] == 1){
      if(result["dat"]["f"] == "0"){
        sendstring += "Track code not found";
      }else{
        success = true;
      }
    }else{
      sendstring += errors[result["msg"]] ? errors[result["msg"]] : "Please, leave comment on habrahabr, error message: "+result["msg"];
    }
    if(success){
      if(UserProperties.getProperty(num[i][0]) != result["dat"]["z"]["b"]){
        sendstring += result["dat"]["z"]["b"];
        sendSMS(code, sendstring);
        UserProperties.setProperty(num[i][0], result["dat"]["z"]["b"]);
        success = false;
      }
    }else{
      sendSMS(code, sendstring);
    }
  }
}


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

В код остается подставить API ID, номер телефона и пары трекинг-номер/хеш. Теперь нужно настроить периодическое выполнение этого скрипта. Для этого идем в «Ресурсы->Триггеры текущего проекта», нажимаем «Добавить триггер» и настраиваем по образу и подобию (промежуток можно выбрать свой):


Результатом будут такие сообщения на мобильный телефон при обнаружении изменений в статусе:


Вопросы и предложения с альтернативами, исправлениями и оптимизациями принимаются.

P.S.: благодарю неизвестного (или это я просто не нашел?) хабраюзера за предоставленный инвайт.

UPD:
  1. Функциональные изменения: добавлено присвоение своих имен посылкам (отображаются вместо трек-кодов) и отлов ошибок (известны только две ошибки, если ошибка неизвестна, ее код придет в SMS, сообщите его здесь, мне в личку или через skype/twitter, ID в профиле).
  2. «Внутренние» изменения: обработка ответа сервиса сделана как нормальный JSON, а не костыльными RegExp.

Если изменить параметр ol из запроса на «17track.net» (вместо «www.17track.net»), почему-то приходит ошибка по поводу хеша. Странные они, эти китайцы.
Оказалось, при генерации хеша еще и домен используется.

UPD2:
У меня сломался скрипт, потому что наша (российская) почта вдруг стала выдавать результаты на русском (недавно только на английском писала, EMS пишет статус по-русски (в результате не влазит в одно сообщение). Теперь идет транслитерация при помощи Google Translate (опять нелегально пользуем ресурсы)

UPD3:
Теперь у нас есть страничка генерации готового кода для вставки в скрипт. Все благодарности z0rg.

UPD4:
Генерация хеша производится скриптом

UPD5:
Если статус латиницей, Google Translate отдавал пустую строку с транслитерацией. fix.

UPD6:
Если трек-код не существует или еще не зарегистрирован, скрипт падал с ошибкой и сообщения не приходило. fix.
Спасибо за сообщение об ошибке -=INFINITY=- с 4pda.ru

UPD7:
Более изящная проверка кода на существование, проверка на новизну статуса по его тексту (иногда дата не отдается, спасибо Dudka), исправление проблем с транслитерацией (при наличии в тексте статуса нескольких предложений получалось забирать только первое, спасибо почте Беларуси и kakawajazz).

UPD8:
Версия для оповещения на E-Mail (включая email@sms-гейты)

UPD9:
Починил скрипт для работы с обновленным 17track, спасибо rocket за указание.
Метки:
Поделиться публикацией
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 89
  • +1
    Хороший способ быть в курсе происходящего, вы молодец.
    И спасибо за оба ресурса. Они однозначно пригодятся не только мне.
    • +1
      За ресурсы нужно благодарить не меня, а корпорацию Google и некое ООО «Вектра».
      Да и делалось все, включая статью, исключительно ради себя.
      • 0
        Спасибо за статью. Я тоже just for fun сделал в конце прошлого года на своем сервере трекер посылок Укрпочты (Украина), так как много покупаю из-за границы (Китай и т.п.) и продаю на аукционе Aukro.ua. Попробую прикрутить ваши наработки + предложения в комментариях к своему трекингу. Только у меня немного другой способ оповещения — по email. Так, думаю, проще — пришел домой, посмотрел, что нового, или в мобилке настроить клиента при желании.

        Из проблем, с которыми столкнулся при написании, могу отметить следующие:
        1. Много времени ушло на опознание статусов посылки (нужно много посылок для тестирования).
        2. Попал на изменение адреса странички и технологии работы официального трекинга Укрпочты. В «новом» трекинге не написаны названия многих почтовых отделений, поэтому параллельно пользуюсь «старым», пока он жив.
        3. Абсолютный игнор писем с проблемами и предложениями Укрпочтой.

        Что получил в итоге (в построении сайтов «с нуля» был не силен, использовал до этого Drupal):
        1. Немного подучил PHP для быдло-кодинга ))). До этого использовал в основном готовые тексты скриптов с внесением небольшых изменений
        2. Познакомился с шаблонизатором Smarty
        3. Познакомился с Bootstrap
        4. Познакомился с многими людьми в соцсетях, получал обратную связь
        5. Около десяти новых посылок для отслеживания в день добавляются мной и знакомыми

        Адрес сайта приводить не буду, так как там присутствует гугло-реклама (сервер и домен нужно на что-то содержать) и хабрапользователи могут счесть за рекламу )) Да и сервер выдержит ли )). Если есть желание посмотреть, пишите в личку.
        • 0
          Лично для меня этот рассказ интереса не представляет, но можете оформить свою «историю успеха» как пост, кое-кто точно оценит.
    • 0
      Дело хорошее, но я как-то раз нашел ресурс post-tracker.ru и до сих пор пользуюсь.
      • 0
        Проверил только что: код, за которым слежу в данный момент не находит: «В почтовых системах нет данных об этом трек-коде», да мой вариант бесплатен. Да и в любом случае, удовлетворение какое-то, что ли, от проделанной работы. Самодельным пользоваться приятней.
        • 0
          Там нет чешской почты, что для меня крайне критично (живу в Чехии). Отправлял им данные для добавления данной почты — пока молчат.
          • 0
            С моим, судя по всему, аналогично: 17track утверждает, что данных с нашей стороны (России) нет, выдает то, что сообщает японская сторона, а с EMS японским post-tracker не дружит.
            • 0
              Я только что попробовал 17track — работает отлично с чешской почтой.
              • 0
                Этот трекер я узнал из оповещения об отправке посылки одним китайским интернет-магазином, который вряд ли будет делить пользователей по странам и использовать разные шаблоны. Не думал, что он сможет пригодиться когда-нибудь таким образом.
        • 0
          Если у вас андроид с постоянным подключением к интернет, то рекомендую Trackchecker
          • 0
            Аппарат с Android и постоянно включенная передача данных — вещи, которые я совмещать не имею возможности. Но приложение не находил, возможно, им и стал бы пользоваться, не найдя других вариантов.
            • 0
              Да, приложение отличное, но китайские треки видит только когда они приходят в мою страну.
              • 0
                Отлично видит Китайские треки. Может неправильно настраиваете? Для того чтобы видеть треки в пути по Китаю, попробуйте добавить для трека почтовый сервис «SAO (cn)»
              • 0
                Ему бы ещё синхронизацию треков между устройствами.
                Использую эту и RPTracker (последний умеет треки хранить в гугл-аккаунте)
              • 0
                Осталось получить настоящий API доступ на 17track и можно делать сервис уведомлений по SMS, по посылкам (шлюз имеется с копеечным тарифом).
                • 0
                  API (по крайней мере алгоритмы генерации хеша) выдернуть легко, я пытался, проблема в том, что Google Apps Script отказался переваривать вырванный JS, хотя в браузере (вставлял на страницу хабра) он отрабатывал нормально. Сейчас выдерну еще раз, скину на pastebin.
                  • 0
                    pastebin.com/nAknzDgg
                    Такие дела. А можно не париться и подключать 17track.net/scripts/hs.js (похоже, он нужен), тем более что так есть некоторая гарантия, что ничего не сломается при смене алгоритма генерации хеша.
                    • 0
                      странное у них хеширование, да еще и на клиентской стороне
                      • 0
                        Иначе как бы хеш можно было получить просто функцией на JS в браузере? Еще, если вы заметили, в адресе запроса JSON есть параметр lo=www.17track.net , который по идее заполняется из домена страницы (не помню имя самой переменной). Если убрать этот параметр, придет JSON с ошибкой, вроде что-то типа «NotAllowed». Однако если подставить нужный вариант, никаких проверок даже по реферреру не будет произведено.
                        Восток — дело тонкое. Нам понять этого не дано.
                        • 0
                          Можно получать хеш Ajax'ом, если это вообще необходимо делать на JS стороне или заранее генерировать на серверной стороне в шаблоне и вбивать в переменную в коде JS. Я если честно не особо улавливаю суть, почему это дело переложили на клиентскую сторону.
                          • 0
                            Ajax'ом они запрашивают результаты трекинга, используя хеш, сгенерированный у клиента. Выглядит как мелочь для отпугивания не шибко настоичивых повадившихся использовать их ресурсы без просмотра рекламы (там ведь реклама, да, за теми анимациями загрузки?). А сильно настойчивым мешать бессмысленно.
                            • 0
                              Я не вижу рекламу, у меня блочит Outpost скорее всего. Странные они, китайцы)
                              • 0
                                А у меня AdBlock и hosts на уровне смарта, работающего хотспотом. Потому и спрашиваю.
                            • 0
                              маньяки сделали это, чтобы запутать «роботов»…
                              Я одно время разбирался, как у них (17трек) устроено получение «хэша» по треку.
                              Они там прикрутили 3des шифрование на клиентской стороне (если ничего не путаю). обфусцировали конечно «слегка» код, занимающийся шифрованием…
                              К сожалению повторить процесс получения хэша на делфе мне за разумное время не удалось, и я забросил это занятие.
                              • 0
                                Если обфускация — это «упаковка», то она хорошо вскрывается Dragonfly'ем Opera'ы. Смотрите ссылку на pastebin выше. Как домой попаду, надо будет переписать на чем другом попробовать.
                                • 0
                                  Смотрел. Там все еще немного обфусцированный (изменены имена функций и переменных) алгоритм шифрования (3des) из какого-то попадающегося в инете js-модуля. Который мне тоже попадался, когда я с этим 17треком разбирался.
                                  В итоге плюнул, написал им, что мол нет ли у них апи и как они с почтой Китая работают…
                                  Ответили, что апи нет, может будет когда-нибудь, и что с почтой китая у них договор есть…
                                  • 0
                                    Если переписывать, например, на PHP, надо всего лишь подправить мелочи синтаксиса на местные и подобрать альтернативы стандартным функциям. У Си (с которым я, к сожалению, плохо дружу) тоже синтаксис похож.
                                    • 0
                                      А если делать сервис (не понимаю, что мешает для себя один раз сгенерить хеш на странице для каждого номера и сидеть, ждать вместо того, чтобы постоянно смотреть на страницу трекинга), то подключить скрипт прямо с их сайта и не надо изобретать ничего.
                                  • 0
                                    Хочу обрадовать вас. Разобрался с шифрованием этим. Его реализация на PHP:
                                        $track = "EM*********JP";
                                        $array = array($track, 0, "www.17track.net");
                                        $string = join($array, "{EDFCE98B-1CE6-4D87-8C4A-870D140B62BA}");
                                        echo hash('md5', $string);
                                    

                                    От правильных ботов (ну кто, кроме меня, бота на JS будет писать?) не спасет, а себе на JS задачу усложнили.
                      • –2
                        А у меня не заработало( не пойму в чем может быть дело, написал автору в личку, прошу помочь.
                      • 0
                        gdeposylka.ru/
                        Вот этот сервис довольно универсальный кстати. Кормится практически любыми кодами.
                        • 0
                          На 17track отдается JSON, который куда проще парсить, чем HTML. Или в качестве замены моему велосипеду с СМС его предлагаете?
                          • 0
                            Да, я именно как полную замену, в т.ч. смс. просто всегда удивляли люди, которые тратят кучу времени и делают велосипед не погуглив сначало.

                            Нет, конечно если все задумано в целях самообразования то вопросов тут нет :)
                            • 0
                              в целях смообразования очень даже неплохо.
                              а гдепосылка денег за смс уведомление требует, или я ошибаюсь?
                              • 0
                                да, 2 рубля за 1 сообщение.
                                • 0
                                  Ничего себе, я отправляю в 30 раз дешевле, можно и еще дешевле. Только вот не знаю какой сервис пока замутить, если только предлагать api для использования рассылки.
                                  • 0
                                    ну они скорее не за смс берут, а вообще за сервис… но 2р за сообщение, согласен, многовато…
                                    • 0
                                      В сторону посмотрите: bytehand.com
                                      0,40 р за смс — начальный, после внесения 10К — 0,20 р. за смс
                                      • 0
                                        Зачем мне в его сторону смотреть, если дешевле этого сервиса отправляю?
                                        • 0
                                          API и упрощение рассылок. Или вы не этого хотели?
                                          • 0
                                            Наверное, я не так выразился, у меня есть возможность отправлять смски по smpp протоколу, на основе этого я мог бы сделать API если это кому-то интересно. Мне ни к чему чужое API и шлюз для рассылок.
                                    • +1
                                      А тут бесплатно. И таки да, самообразование тоже имеет место.
                            • 0
                              кстати, альтернатива 17track может послужить sao.cn.
                              там так же ajax запрос шлется, получается json в ответе. И нет нужды со всякими хэшами морочиться.
                              пример get запроса:
                              sao.cn/track?id=[TRACKNO]&timeout=180&mailType=null&lang=EN&srcId=null&srcMode=null&dstId=null&dstMode=null&input=null
                              где [TRACKNO] = проверяемый трек-номер. Возможно можно обойтись и без других параметров.
                              сервис, конечно, не идеальный, но так же берет инфу с почты китая без капчи…
                              • 0
                                Опять же, мой трек-номер пролетел в режиме авто (EMS Japan). При ручном выборе страны отправления находит, но опять же лишняя возня.
                              • 0
                                А еще смс-ки можно отправлять средствами календаря Google (описание тут).
                                • 0
                                  Лишние костыли, которых здесь и так уже многовато.
                                  • 0
                                    И из того поста я как раз и подчерпнул идею.
                                  • 0
                                    у меня почемуто приходит [Opject] [Opject]

                                    А при запуске ошибка:

                                    TypeError: Не удается прочитать свойство «1» объекта null. (строка 18, файл Код)

                                    18: if(UserProperties.getProperty(num[i][0]) != result[1]){

                                    Проверил хеши по два раза, посылка у 17track отслеживается
                                    • 0
                                      Сдается мне, вы что-то напутали с объявлением объекта с трек-кодами. Покажите ваш код с объектом num (трек-коды можете заменить чем-нибудь).
                                      • 0
                                        var apiID = «99af**************9bb8»;
                                        var phone = «89***********01»;
                                        var num = [
                                        [«RB**********CN», «21************************fe6»],
                                        [«RT**********HK», «e9************************3cd»]
                                        ];

                                        function sendSMS(text){
                                        UrlFetchApp.fetch(«sms.ru/sms/send?api_id=»+apiID+"&to="+phone+"&text="+encodeURI(text));
                                        }

                                        function checkStatus(){

                                        for(i=0; i
                                    • 0
                                      Ох, у меня тоже скрипт сломался. Боюсь, китайцы приняли хабраэффект за DDoS и забанили Гугл. Придется к другим сервисам присасываться.
                                      • 0
                                        Ан нет, просто ошибками кидался, сейчас все хорошо. Сейчас попытаюсь ловлю ошибок прикрутить.
                                    • 0
                                      UPD (подробности внизу поста)
                                      • 0
                                        UPD2 (транслитерация статуса, подробней внизу поста)
                                        Пользуясь случаем, передаю привет нашей почте, EMS-посылка за семь дней добралась из Японии до таможни в Москве.
                                        • 0
                                          UPD3 (Благодаря z0rg теперь получать хеши проще).
                                          А я пойду все-таки спать.
                                          • 0
                                            UPD4 (Хеш теперь генерируется скриптом)
                                            • 0
                                              UPD5
                                              • 0
                                                UPD6 (Исправление падения скрипта при несуществующем коде)
                                                • +1
                                                  У меня в дате последнего статуса 17track.net возвращал null, из-за этого были проблемы.
                                                  Поправил так
                                                   if(success){
                                                        var lasttdate=((result["dat"]["z"]["a"]==null)?"null":result["dat"]["z"]["a"]);
                                                        if(UserProperties.getProperty(num[i][0]) != lasttdate){
                                                          translit = UrlFetchApp.fetch("http://translate.google.com/translate_a/t?client=t&q="+encodeURI(result["dat"]["z"]["b"]));
                                                          translitobj = Utilities.jsonParse(translit.getContentText());
                                                          sendstring += translitobj[0][0][3] ? translitobj[0][0][3] : result["dat"]["z"]["b"];
                                                          sendSMS(sendstring);        
                                                          UserProperties.setProperty(num[i][0], lasttdate);
                                                          success = false;
                                                        }
                                                  
                                                  • 0
                                                    Чтоб не городить лишнего кода, сделал проверку по тексту статуса.
                                                  • 0
                                                    UPD7 Более изящная проверка кода на существование, проверка на новизну статуса по его тексту (иногда дата не отдается, спасибо Dudka), исправление проблем с транслитерацией (при наличии в тексте статуса нескольких предложений получалось забирать только первое, спасибо почте Беларуси и kakawajazz).
                                                    • 0
                                                      UPD8 Версия для оповещения на E-Mail (включая email2sms-гейты)
                                                      • 0
                                                        Походу 17track поменял механизм выдачи — не отдает данные по всем трекам
                                                        • 0
                                                          ({"ret":1,"msg":"Ok","dat":{"c":"RB335828484HK","d":8011,"e":18031,"f":1,"g":1,"h":1,"i":-1,"j":998,"k":4899,"l":9,"m":29,"v":"9999-12-31T00:00:00","w":"9999-12-31T00:00:00","x":[{"a":"22-Aug-2013","b":"The item (RB335828484HK) was in transit within its destination country on 22-Aug-2013."}],"y":[{"a":"22 August 2013 06:08","b":"Обработка, 443962, САМАРА МСЦ УОПО, Прибыло в сортировочный центр"},{"a":"22 August 2013 03:26","b":"Обработка, 443982, САМАРА PI-2, Покинуло место международного обмена"},{"a":"21 August 2013 11:19","b":"Таможенное оформление завершено, 443982, САМАРА PI-2, Выпущено таможней"},{"a":"21 August 2013 09:11","b":"Передано таможне, 443982, САМАРА PI-2"},{"a":"20 August 2013 21:59","b":"Импорт, 443982, САМАРА PI-2, АФИПСИП, ТАХТАМУКАЙСКИЙ РАЙОН, АДЫГЕЯ РЕСПУБЛИКА"}],"z":{"a":"22 August 2013 06:08","b":"Обработка, 443962, САМАРА МСЦ УОПО, Прибыло в сортировочный центр"}}})
                                                          Что не отдает?
                                                          • 0
                                                            У меня почему то так
                                                            • 0
                                                              Все ок, увидел у себя проблему
                                                      • 0
                                                        & у вас повылазили вместо амперсандов в ссылке
                                                        • 0
                                                          Код RB631253292CN — Please leave comment on HabraHabr.
                                                          Оставляю.
                                                          • 0
                                                            Если ошибка — «abN», то я сам ничего не могу с этим сделать.
                                                            • 0
                                                              Победил так:
                                                              ...
                                                              if(UserProperties.getProperty("'"+num[i][0]+"'") != result[«dat»][«z»][«b»]){
                                                              ...
                                                              UserProperties.setProperty("'"+num[i][0]+"'", result[«dat»][«z»][«b»]);
                                                              ...
                                                              • 0
                                                                Хм… От этого abN пропасть не должна — она на стороне сервера. Причина явно какая-то другая. Причём в последнее время эта ошибка приходит только от трек-кода, посылка с которым с конца августа уже получена.
                                                                • 0
                                                                  Да, верно. Но как работает без кавычек — не представляю.
                                                                  Без кавычек у меня вообще статус не приходил. С ними — пришел, но ошибки abN все равно периодически прилетают.
                                                                  Поспешил, буду дальше смотреть.
                                                                  • 0
                                                                    Индекс элемента в массиве в моем случае — RB631253292CN, а в вашем — 'RB631253292CN'. Чему тут не работать, не представляю.
                                                                    • 0
                                                                      Мне это понятно, но факт остается фактом — без кавычек у меня не работал.
                                                          • 0
                                                            В общем я остановился на варианте с фильтрацией abN — сейчас сообщения приходят только по делу, при изменении статуса.

                                                            Приложу весь код
                                                            var user = ["...", "..."];
                                                            
                                                            var num = [
                                                              ["...", "..."]
                                                            ];
                                                            
                                                            var errors = {
                                                              "hsErr": "Wrong hash",
                                                              "unAllow": "You've changed parameter \"lo\" in query URL. Set it to \"www.17track.net\"",
                                                              "hsNon": "There's no hash"
                                                            }
                                                            var success = false;
                                                            
                                                            function sendSMS(text){
                                                              UrlFetchApp.fetch("http://sms.ru/sms/send?api_id="+user[0]+"&to="+user[1]+"&text="+encodeURI(text));
                                                            }
                                                            
                                                            function digest2str(digest){
                                                              var str = '';
                                                              var i = 0;
                                                              for (i=0; i<digest.length; i++) {
                                                                byte = digest[i];
                                                                if (byte < 0)
                                                                  byte += 256;
                                                                byteStr = byte.toString(16);
                                                                // Ensure we have 2 chars in our byte, pad with 0
                                                                if (byteStr.length == 1) byteStr = '0'+byteStr;
                                                                str += byteStr;
                                                              }   
                                                              return str;
                                                            }
                                                            
                                                            function checkStatus(){
                                                              var i = 0;
                                                              for(i=0; i<num.length; i++){
                                                                hashstr = num[i][0]+"{EDFCE98B-1CE6-4D87-8C4A-870D140B62BA}0{EDFCE98B-1CE6-4D87-8C4A-870D140B62BA}www.17track.net";
                                                                dig = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, hashstr);
                                                                hs = digest2str(dig);
                                                                var response = UrlFetchApp.fetch("http://s1.17track.net/Rest/HandlerTrackPost.ashx?lo=www.17track.net&num="+num[i][0]+"&hs="+hs);    
                                                                UserProperties.setProperty("q", response.getContentText());
                                                                var result = Utilities.jsonParse(response.getContentText().replace(/^\((.*)\)$/, "$1"));
                                                                var sendstring = num[i][1]+": ";
                                                                if(result["msg"]!="abN"){
                                                                  if(result["ret"] == 1){
                                                                    if(result["dat"]["f"] == "0"){
                                                                      sendstring += "Track code not found";
                                                                    }else{
                                                                      success = true;
                                                                    }
                                                                  }else{
                                                                    sendstring += errors[result["msg"]] ? errors[result["msg"]] : "Please, leave comment on habrahabr, error message: "+result["msg"];
                                                                  }
                                                                
                                                                  if(success){        
                                                                    if(result["dat"]["z"]!=null){
                                                                      if(UserProperties.getProperty("'"+num[i][0]+"'") != result["dat"]["z"]["b"]){
                                                                        //if(true){
                                                                        translit = UrlFetchApp.fetch("http://translate.google.com/translate_a/t?client=t&q="+encodeURI(result["dat"]["z"]["b"]));
                                                                        translitobj = Utilities.jsonParse(translit.getContentText());
                                                                        if(translitobj[0][0][3]){
                                                                          for(z in translitobj[0]){
                                                                            sendstring += translitobj[0][z][3]+" ";
                                                                          }
                                                                        }else{
                                                                          sendstring += result["dat"]["z"]["b"];
                                                                        }
                                                                        sendSMS(sendstring);
                                                                        UserProperties.setProperty("'"+num[i][0]+"'", result["dat"]["z"]["b"]);
                                                                        success = false;
                                                                      }
                                                                    }
                                                                  }else{
                                                                    sendSMS(sendstring);
                                                                  }
                                                                }
                                                              }
                                                            }
                                                            

                                                            • 0
                                                              Проблемы при первом запуске
                                                              1) пришло всего 2 уведомления из 6 посылок…
                                                              2) если в 17track destination посылки стоит unknown, то статус посылки приходит неактуальный. На сайте 17track можно вручную выставить destination. Можно ли как-то в вашем скрипте принудительно указывать страну destination?
                                                              • 0
                                                                В техподдержке sms.ru ответили, что sms бесплатно отправляется самому себе если оно укладывается в 160 символов (без склейки). Как-то странно, что никто в комментах выше не отписался о таком нюансе, мешающем полноценно использовать сервис отслеживания посылок. У меня в посылках 4 из 6 статус длиннее 160 символов в транслите.
                                                                • 0
                                                                  Насчет кол-ва символов в посте приведен способ с email2sms
                                                                  По поводу страны:
                                                                  Шаблон для кода будет следующий:
                                                                  ["%TRACKCODE%", "%NAME%", "%COUNTRYID%"]

                                                                  где %COUNTRYID% — идентификатор страны у 17track, список здесь: pastebin.com/mrJxgvgt
                                                                  Плюс строку
                                                                  var response = UrlFetchApp.fetch("http://s1.17track.net/Rest/HandlerTrackPost.ashx?lo=www.17track.net&num="+num[i][0]+"&hs="+hs);

                                                                  заменить на
                                                                  var response = UrlFetchApp.fetch("http://s1.17track.net/Rest/HandlerTrackPost.ashx?lo=www.17track.net&num="+num[i][0]+"&hs="+hs+"&pt="+num[i][2]);
                                                              • 0
                                                                Спустя неделю работы сервиса напоролся на ошибку «abN». Возвращает такое для всех трэков. Причем, если реквестить s1.17track.net/Rest/HandlerTrackPost.ashx через другой IP, то статусы возвращаются нормально. Походу, у них настроен автоматический бан по IP. Нужно прикручивать динамический прокси.
                                                                • 0
                                                                  Походу сломался сервис 17track.net — там у них на сайте недавно случился мощный редизайн. Ждём новых поделок API.
                                                                  • 0
                                                                    Поправил, пробуйте. Тестировать не на чем.
                                                                  • 0
                                                                    Поправил под себя, у меня версия из топика не работала. Кому интересно проверяйте.
                                                                    Нужен еще апи ключ из яндекс транслейт

                                                                    pastie.org/9795905

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