21 сентября 2011

Скрипт для проверки баланса в PeopleNet

В данной статье рассматривается процесс создания скрипта для проверки баланса украинского мобильного оператора PeopleNet, который обычно используется для мобильного доступа к 3G интернету. Целью статьи является популяризация написания скриптов для облегчения ежедневных задач.

Всё началось с вопроса моего друга. «Нельзя ли что-нибудь сделать с теперешним подсчетом трафика в PeopleNet? Ведь что-то же считает!» Я сразу же стал теоретизировать, что таки да, можно… И через пару ночей я засел за работу и родился скрипт, которым я хочу поделиться с вами.

Нужно ввести читателя в курс дел.

В популярном пакете «777» от PeopleNet предоставляется ежедневно трафик размером 232 МБ (как бы 7 ГБ в месяц и как бы за 77 грн). Узнать остаток доступного трафика на текущие сутки можно, отправив с 3G модема SMS на служебный номер и прочитав ответ (при помощи «фирменной» программы для Windows. Отправлять SMS в Linux, с 3G модемов как-то еще не очень получается.

Кроме того, существует страничка биллинга, называемая Системой самообслуживания клиентов. Раньше я уже писал скрипт для подобных целей. Но раньше было проще. Можно было получить информацию о потраченном трафике за каждую сессию за каждый день в течение последнего месяца. Теперь же на странице красовалось одно число — количество потраченных МБ с начала месяца. С тех пор сёрфинг в сети велся практически вслепую…

Я почти полностью переписал скрипт, избавился от множества промежуточных шагов, временных переменных и файлов, и это пошло скрипту только на пользу. Его основу составляет одна «волшебная» строчка кода, которая получает со страницы самообслуживания число потраченных с начала месяца мегабайт:

curl -s -d "X_Username=380921234567&X_Password=11223344"
↪    --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills&rp="$(expr \( $(date +%y) - 2 \) \* 12 +
↪    $(date +%m)) | grep -A 3 EVDO | tail -n 1 | grep -o
↪    '[0-9]*'

Здесь используется curl — удобная программа, которую можно в шутку назвать «веб-браузер для робота». Ее можно вызывать из своих скриптов для отсылки запросов, форм, получения и отправки страниц и файлов. Для того, чтобы получить информацию по своему номеру, вы должны изменить 380921234567 на свой номер, а 11223344 — на свой пароль для входа на страницу самообслуживания. В процессе работы будет загружена страничка размером 11,5 кБ и из нее будет выделено единственное число, которое вы и получите «на выходе». О том, что делать дальше с этим числом, мы поговорим немного позже.

Как работает этот код

Обо всех опциях команды curl вы сможете узнать, если выполните в терминале команду

curl --help

Такой подход к получению справки типичен для большинства команд в Linux.

Здесь мы используем такие ключи:

  • -s — «молчаливый» режим. Curl не будет печатать в терминале не нужную нам информацию о размере и скорости закачки указанной страницы;
  • -d и следующая строка в кавычках — данные, отсылаемые на сервер по методу POST;
  • --url и длинная строка, заканчивающаяся перед вертикальной чертой — адрес страницы, которую нужно получить. Сам ключ «--url» можно было бы и не писать, оставив только строку. Вертикальная черта передает страничку, загруженную командой curl, дальше, следующей команде, по конвейеру.

Откуда взялись параметры для ключей -d и --url?

Проследим работу системы самообслуживания. Зайдем при помощи обычного браузера на страницу http://my.people.net.ua/. Нас просят ввести номер телефона и пароль, затем нажать кнопку подтверждения. Далее нужно перейти по ссылке «Ежемесячный счет». На следующей странице выбрать нужный месяц из выпадающего списка (текущий месяц находится вверху и поэтому выбирать ничего не нужно) и нажать кнопку подтверждения. На следующей странице нужно пробежаться глазами по таблице и найти в строчке «Передача даних EVDO» нужное нам число. Теперь научим робота делать то же самое.

Для исследования страниц нам пригодится ключ -o команды curl. После этого ключа указываем название файла и страничка, указанная в ключе --url будет загружена в этот файл.

Итак, первый шаг:

curl --url "http://my.people.net.ua/" -o "take1.html"

Открываем полученный файл take1.html в текстовом редакторе (нужно хотя бы немного разбираться в html-разметке). Мы видим html-форму:

<form target="_top" action="/TSU/WWW/ACCOUNT_INFO/"method="post" name="LoginForm">
  ...
  <input value="" name="X_Username" size="9"title="Введіть номер Вашого телефону" type="text">
  ...
  <input name="X_Password" size="9"title="Введіть Ваш пароль" type="password">
  ...
  <input value="Вхід" type="submit">
  ...
</form>

Я удалил всё, не относящееся к делу, чтобы можно было сосредоточиться на нашем задании. Итак, данные формы отправляются методом POST, значит, воспользуемся ключом -d команды curl. Вот, если бы метод был GET, то можно было бы не городить огород, а дописать передаваемые данные прямо в строку адреса (примерно так: http://наш.длинный/адрес?параметр1=значение1&параметр2=значение2).

Итак, из анализа формы становится понятно, что при нажатии кнопки подтверждения данные формы отсылаются по адресу http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/ и эти данные — X_Username=номер телефона и X_Password=пароль.

Второй шаг наших раскопок:

curl -d "X_Username=380921234567&X_Password=11223344"
↪    --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/"
↪    -o "take2.html"

Просмотрев загруженную страничку, мы видим, что да, нас успешно пустили в систему самообслуживания. Теперь нас интересует ссылка:

<a href="http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO?sid=bills">Ежемесячный счет</a>

Я снова убрал всё лишнее. Попробуем:

curl --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO?sid=bills"
↪    -o "take3.html"

Получаем страничку с ошибкой. Хм, попробуем так:

curl --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills"
↪    -o "take3.html"

Теперь получаем первоначальную страничку для входа в систему самообслуживания. Нас забыли и снова предлагают ввести номер и пароль! Попробуем не городить огород, а просто объединим две команды, два адреса в один:

curl -d "X_Username=380921234567&X_Password=11223344"
↪    --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills"
↪    -o "take3a.html"

Так! Мы продвинулись дальше! Просматривая страницу, находим в ней форму для выбора месяца:

<form action="http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO"method="GET">
  <input type="hidden" name="sid" value="bills">
  <select name="rp">
    <option value="117" selected>вересень 2011 року</option>
    <option value="116">серпень 2011 року</option>
    <option value="115">липень 2011 року</option>
    <option value="114">червень 2011 року</option>
    <option value="113">травень 2011 року</option>
    <option value="112">квітень 2011 року</option>
    <option value="111">березень 2011 року</option>
    <option value="110">лютий 2011 року</option>
    <option value="109">січень 2011 року</option>
    <option value="108">грудень 2010 року</option>
    <option value="107">листопад 2010 року</option>
  </select>
  <input type="submit" value="Показати">
</form>

Я снова убрал всё лишнее из html-разметки. В зависимости от вашего «стажа» в PeopleNet длина списка у вас будет другая. Итак, адрес для отсылки формы ясен; метод, кстати — GET, значит, пишем параметры прямо в строку адреса. Имеется скрытая (hidden) переменная с именем sid и значением bills. Вторая переменная с именем rp и нужным нам значением 117. Формируем адрес:

http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills&rp=117

Пробуем снова совместить команды:

curl -d "X_Username=380921234567&X_Password=11223344"
↪    --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills&rp=117"
↪    -o "take4.html"

Да, мы продвинулись еще дальше. Правда, такого же восторга уже нет. Остается работа. И она заключается в следующем.

Во-первых, каждый месяц число в параметре rp будет меняться. Во-вторых, нам нужно проанализировать код страницы. Подберем формулу для расчета числа:

rp = ( год - 2 ) * 12 + месяц

Номер года (две последние цифры) и номер месяца (две цифры) мы можем получить соответствующими командами:

date +%y
date +%m

Если окружить команду такой оберткой — $(команда), то тогда результат работы этой команды будет представлен в виде строки и его можно будет использовать для дальнейших вычислений в более сложных командах. Для математических расчетов используем команду expr.

expr ( $(date +%y) - 2 ) * 12 + $(date +%m)

Получаем ошибку, говорящую о некорректном синтаксисе, курим маны и «экранируем» скобки, входящие в нашу формулу, а также звездочку (знак умножения), поставив перед ними бэкслэш (\):

expr \( $(date +%y) - 2 \) \* 12 + $(date +%m)

Получаем 117. Что нам и требовалось!

Теперь окружаем эту команду при помощи $(...) и подставляем ее вместо числа 117 в нашу супер-команду curl:

curl -s -d "X_Username=380921234567&X_Password=11223344"
↪    --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills&rp="$(expr \( $(date +%y) - 2 \) \*
           ↪12 + $(date +%m))

Заметьте, что кавычки закрываются после «rp=» и сразу же мы пишем обернутую команду, таким образом, результат команды (число 117) дописывается к строке.

Теперь пришло время «во-вторых» — анализ кода страницы. Вы помните, как выглядит табличка, когда вы заходили через браузер? Ищем строчку с аббревиатурой EVDO и находим такой участок html-разметки:

  <tr>
    <td>
      <i>      Передача даних EVDO</i>
    </td>
    <td class="ar4">
      <i> 224</i>
    </td>
    <td class="ar4">
      <i>0.00</i>
    </td>
  </tr>

Здесь я не стал убирать ничего. Нам нужно «научить робота» выделять вот это число — 224.

Давайте поищем на странице слово «EVDO» (в текстовом редакторе, в котором вы просматриваете эту страничку). Нашли только один раз, хорошо. Курим маны. Пользуемся командой grep. Команда grep EVDO выдает нам только строчку, в которой найдено слово EVDO, а команда grep -A 3 EVDO выдает нам эту строчку и еще три следующих за ней строки. Как раз в третьей строке находится наше число! Итак, код:

cat "take4.html" | grep -A 3 EVDO

Здесь мы при помощи команды cat выводим содержимое файла take4.html и при помощи вертикальной черты передаем его дальше по конвейеру команде grep. Получаем:

      <i>      Передача даних EVDO</i>
    </td>
    <td class="ar4">
      <i> 224</i>

Теперь «откусим» только последнюю строку при помощи команды tail:

cat "take4.html" | grep -A 3 EVDO | tail -n 1

Получаем:

      <i>�224</i>

Вы заметили некий гаденький символ перед цифрами? Так в консоль выводится символ неразрывного пробела, который непонятно зачем всунули разработчики этой странички. В старой версии скрипта я бы написал несколько команд, которые последовательно по конвейеру, удаляли бы из строки ненужные нам символы. Сначала бы заменили пробел(ы) на ничто (т. е. удалили их), затем «<i>», после «</i>», и, наконец, этот гаденький символ.

Синтаксис команды sed (для замены строк) прост:

sed -e 's/что-менять/на-что-менять/g'

Ключ g говорит, что менять нужно глобально, а не только первый попавшийся случай. Так, команда:

sed -e 's/ //g; s/<i>//g; s/<\/i>//g'

последовательно заменит все пробелы на «ничто», затем «<i>» и «</i>». А, вот, с этим символом не всё так просто. Кодировка скрипта, конечно же, UTF-8, а кодировка странички — windows-1251. Поэтому, команда sed ничего не найдет. А, если же сохранить скрипт в кодировке 1251, то мы не сможем выводить этим скриптом русские буквы. А, если, сохранить в 1251, вставить символ в скрипт, а затем открыть как UTF-8, то текстовый редактор откажется работать с этим скриптом. Да-а…

Отмечу, что ту же задачу можно было бы решить по-другому:

cut -d ">" -f 2 | cut -d "<" -f 1

Здесь сначала мы разбиваем нашу строку на части. Разделитель частей — символ «>», берем вторую часть. Затем полученную строку снова разбиваем на части, но уже символом «<» и берем первую часть.

То, что задачу можно решить как минимум двумя разными способами — тоже типично для Linux.

Всё хорошо, но число с этим символом в начале нельзя подставлять в математические выражения — получим ошибку! Покурив маны, я нашел простое и элегантное решение:

grep -o '[0-9]*'

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

Вот и всё! Получился скрипт в одну строку, который выполняет такую сложную задачу! Вот в этом и заключается сила командной строки Linux, профессионалы могут сделать в консоли всё что угодно. А новички не верят, говорят, устарело. Неправда…

Обрабатываем полученное значение

Если ваш тарифный план не подразумевает посуточную разбивку трафика (400 МБ в месяц), то на этом всё, вы можете вывести это число на экран (об этом позже). Если же в вашем тарифе существует суточный лимит (например, 232 МБ/сут., как в тарифном плане «777»; либо 300 МБ/сут., как в другом тарифном плане, названия которого я не знаю), то пойдем дальше.

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

Удобно, когда скрипт сам будет за нас записывать это число и сам будет считать остаток. Лучше всего дописать вызов этого скрипта в конец процедуры подключения к интернету; таким образом, как только вы подключитесь к интернету, так сразу, не потратив еще нисколько мегабайт, узнаете число со страницы самообслуживания. А потом, когда вы присоединяетесь к интернету в следующий раз, скрипт должен снова узнать число со страницы самообслуживания, найти разницу (потраченные МБ) и отнять от суточного лимита эту разницу. Задача ясна? Беремся?

Для начала, давайте, отведем отдельный файл для такой важной задачи — хранения количества потраченных мегабайт в начале суток. В нём будет храниться одно число. Пусть его формат будет таким:

MMDDxxxx

где: MM — месяц, DD — день, xxxx — мегабайты. Весьма компактно.

Мы можем определить текущую дату при помощи команды

date +%m%d

А выделить дату из файла можно такой командой (взять первые 4 символа из файла):

cut -c -4 файл

Параметр «-4» это сокращенная запись «с начала и до четвертого». Полностью можно было бы записать «1-4», что значит «с первого по четвертый».

Количество мегабайт выделяется из файла командой:

cut -c 5- файл

Что тоже является сокращенной формой «с пятого и до конца».

Теперь продумаем возможные ситуации.

  • Что, если нет подключения к интернету, а мы запустили скрипт? В результате работы нашей супер-команды мы получим пустую строку. Говорим «Ошибка связи».
  • Что, если файла нету? Получаем данные со страницы самообслуживания, создаем файл и заносим в него цифры. Говорим, что на сегодня осталось максимально возможное количество МБ.
  • Что, если дата в файле является устаревшей (вчера, позавчера…)? Значит, сегодня мы еще не пользовались интернетом. Получаем данные и заносим в файл. Говорим, что на сегодня осталось максимально возможное количество МБ.
  • Что, если дата сегодняшняя? Файл не меняем. Находим количество потраченных МБ. От суточного лимита отнимаем потраченные. Выдаём число.

Теперь схематично опишем алгоритм.

ПОЛУЧИТЬ «КОЛИЧЕСТВО_МБ»
ЕСЛИ [ «КОЛИЧЕСТВО_МБ» пустое ]
|ТОГДА
|  СООБЩЕНИЕ = «Ошибка связи»
|ИНАЧЕ
|  УЗНАТЬ «текущую дату» (ММДД)
|  ЕСЛИ [ файл есть ] И [ дата в файле (ММДД) совпадает с текущей (ММДД) ]
|  |ТОГДА
|  |  «ОСТАЛОСЬ» = («xxxx из файла» + «суточный лимит» - «КОЛИЧЕСТВО_МБ»)
|  |ИНАЧЕ
|  |  записать «текущую дату (ММДД)» и «КОЛИЧЕСТВО_МБ» в файл;
|  |  «ОСТАЛОСЬ» = «СУТОЧНЫЙ ЛИМИТ»
|  КОНЕЦ_ЕСЛИ
|  СООБЩЕНИЕ = «На сегодня осталось: «ОСТАЛОСЬ» МБ»
КОНЕЦ_ЕСЛИ

ВЫДАТЬ «СООБЩЕНИЕ»

Алгоритм понятен? Замечательно, если да! Теперь запишем его при помощи консольных команд на языке BASH.

Указываем, что наш СУТОЧНЫЙ ЛИМИТ равен 232 МБ:

LIM=232

В переменной PN сохраняем папку, в которую мы положили всё нужное для работы нашего скрипта — сам скрипт, файл для хранения DDMMxxxx и даже логотип PeopleNet. Папка эта называется peoplenet и лежит она в нашей домашней папке (на что указывает системная переменная $HOME), которая, конечно же разная для разных пользователей. Но, благодаря такому подходу, ничего в скрипте менять не нужно. Переменную PN мы ввели для краткости. Назовем файл для хранения DDMMxxxx просто «pn», тогда путь к нему мы можем записать так: "$PN/pn"; картинка же называется pn.png и путь к ней будет "$PN/pn.png".

PN=$HOME/peoplenet

MB=$(curl -s -d "X_Username=380922530191&X_Password=64506822"
     ↪    --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills&rp="$(expr \( $(date +%y) - 2 \) \*
                ↪12 + $(date +%m)) | grep -A 3 EVDO |
                ↪tail -n 1 | grep -o '[0-9]*')

if [ -z $MB ]
then
  MESS="Ошибка связи"
else
  DT=$(date +%m%d)
  if [ -e $PN/pn ] && [ $(cut -c -4 $PN/pn) -eq $DT ]
  then
    OM=$(expr $(cut -c 5- $PN/pn) + $LIM - $MB)
  else
    echo $DT$MB > $PN/pn; OM=$LIM
  fi
  MESS="На сегодня осталось: $OM МБ"
fi

notify-send "PeopleNet" "$MESS" -i $PN/pn.png

Немного нужно рассказать о последней команде, так? Эта команда должна выполняться на любом дистрибутиве, поддерживающем стандарты. Она выдает примерно такое вот сообщение:

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

Хотите поместить на рабочий стол значок для запуска нашего скрипта? Нажмите на рабочем столе правой кнопкой — Создать кнопку запуска… и заполните поля. Следующий рисунок показывает, как это сделал я.

Всё? Нет! Продолжение

В процессе написания статьи мне захотелось получить еще больше функционала от моего скрипта. На счету у меня сегодня «минус», но скрипт по прежнему щедро выдает мне мегабайты. Такую ситуацию надо отслеживать. Заодно можно узнать, на сколько дней хватит денег и выдать дату, когда нужно пополнить счет.

Так как страницу, загруженную из системы самообслуживания, теперь нужно будет дважды проанализировать, разобьем нашу супер-команду на две части. Запомним страницу в переменную PAGE, а затем найдем в ней всё, что нам нужно:

PAGE=$(curl -s -d "X_Username=380921234567&X_Password=11223344"
       ↪    --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills&rp="$(expr \( $(date +%y) - 2 \) \*
                  ↪12 + $(date +%m)))

MB=$(echo "$PAGE" | grep -A 3 EVDO | tail -n 1 | grep -o '[0-9]*')

Теперь посмотрим, как из текста страницы можно выделить остаток на счету. Просмотрим файл take4.html, который мы загрузили в процессе экспериментов (эта же страница будет загружена в переменную PAGE). Мы видим строки

  <tr>
    <td colspan="2">
      <b>
        <font>Поточний баланс на 14.09.2011</font>
      </b>
    </td>
    <td class="ar">
      <b>
        <font color="#a00000">-1.09</font>
      </b>
    </td>
  </tr>

Чтобы не связываться с русскими буквами в другой кодировке (хотя, при необходимости, страницу можно конвертировать), будем искать текст «14.09.2011» — это текущая дата на момент написания статьи. Дату в таком формате мы можем получить при помощи команды:

date +%d.%m.%Y

Дальше — технология отработана. Выделяем пятую строчку после найденной, а затем выделяем содержимое между символами «>» и «<». В завершение, удалим точку, чтобы перевести сумму в копейки, так как консольная команда expr работает только с целыми числами:

MONEY=$(echo "$PAGE" | grep -A 5 $(date +%d.%m.%Y) | tail -n 1 |
       ↪ cut -d ">" -f 2 | cut -d "<" -f 1 | sed -e 's/\.//')

Если число меньше нуля, выведем сообщение «Услуга недоступна. Пополните счет!»

Согласно справочнику тарифов PeopleNet, каждый день со счёта снимается сумма 2,64 грн. Давайте разделим полученный баланс на тариф и узнаем, на сколько дней нам хватит денег:

TARIFF=264
DAYS=$(expr $MONEY / $TARIFF)

Если денег меньше, чем 264, то мы получим 0. Это значит, что ночью будет снята сумма тарифа и на счету будет меньше нуля. Интернет завтра будет недоступен. Выведем сообщение «Пополните счет сегодня». Если получим 1, то выведем «Пополните счет завтра». Для других чисел выведем что-то вроде «Осталось 3 дня. Пополните 31.09.2011 г.»

Здесь есть две «проблемы». Во-первых, корректная выдача слов «день», «дня», «дней». Во-вторых, расчет даты в будущем, на расстоянии несколько дней от сегодняшней даты. На самом деле это — не проблемы. Поверьте — всё решаемо!

Во-первых, я вспомнил время, когда занимался локализацией строк в программах при помощи Gettext. Там была интересная строчка кода, которая определяет форму слова. Чтобы не рыться в старых файлах, достаточно почитать страничку Gettext в Википедии. Вот эта строка:

plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 &&
       ↪ (n%100<10 || n%100>=20) ? 1 : 2)

Как ее приспособить для нашего скрипта? Оказывается, достаточно окружить ее двойными скобками и пробелами. Теперь, если plural=0, то пишем «день», если 1 — то «дня», если 2 — то «дней». Создадим массив со словами:

day=( день дня дней )

И будем выдавать нужное слово (по номеру элемента массива) командой

${day[$plural]}

Теперь займемся расчетом дат. Google, как обычно, помогает. На этот раз мне понравилась вот эта ссылка.

Так много функционала мне не надо, поэтому я максимально сокращаю скрипт под свою задачу.

# количество секунд, прошедших с 01.01.1970 до настоящего момента
TODAY=$(date --utc +%s)

# прибавляем нужное количество секунд (в сутках их 86400)
DATESEC=$(expr $TODAY + \( $DAYS + 1 \) \* 86400)

# рассчитываем дату в будущем и выводим ее в формате ДД.ММ.ГГГГ
DATE2=$(date --utc --date "1970-01-01 $DATESEC sec" "+%d.%m.%Y")

Можно всё это собрать в одну строку:

DATE2=$(date --utc --date "1970-01-01 $(expr $(date --utc +%s) +
      ↪ \( $DAYS + 1 \) \* 86400) sec" "+%d.%m.%Y")

Теперь — весь скрипт целиком. Он исправно выполняет поставленные задачи.

#!/bin/bash
LIM=232
TARIFF=264
PN=$HOME/peoplenet

PAGE=$(curl -s -d "X_Username=380921234567&X_Password=11223344"
       ↪    --url "http://my.people.net.ua/TSU/WWW/ACCOUNT_INFO/?sid=bills&rp="$(expr \( $(date +%y) - 2 \) \*
                  ↪12 + $(date +%m)))

MB=$(echo "$PAGE" | grep -A 3 EVDO | tail -n 1 | grep -o '[0-9]*')

MONEY=$(echo "$PAGE" | grep -A 5 $(date +%d.%m.%Y) | tail -n 1 |
       ↪ cut -d ">" -f 2 | cut -d "<" -f 1 | sed -e 's/\.//')

if [ -z $MB ]
then
  MESS="Ошибка связи"
else
  if [ $MONEY -lt 0 ]
  then
    MESS="Услуга недоступна. Пополните счет!"
  else
    DAYS=$(expr $MONEY / $TARIFF)
    day=( день дня дней )
    (( plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 &&
    ↪  (n%100<10 || n%100>=20) ? 1 : 2) ))

    case "$DAYS" in
      0) MESS2="Пополните счет сегодня";;
      1) MESS2="Пополните счет завтра";;
      *) MESS2="Осталось $DAYS ${day [$plural]}. Пополните
               ↪ $(date --utc --date "1970-01-01
               ↪ $(expr $(date --utc +%s) + \( $DAYS + 1 \) \*
               ↪ 86400) sec" "+%d.%m.%Y") г.";;
    esac

    DT=$(date +%m%d)
    if [ -e $PN/pn ] && [ $(cut -c -4 $PN/pn) -eq $DT ]
    then
      OM=$(expr $(cut -c 5- $PN/pn) + $LIM - $MB)
    else
      echo $DT$MB > $PN/pn; OM=$LIM
    fi
    MESS="На сегодня осталось: $OM МБ\n""$MESS2"
  fi
fi

notify-send "PeopleNet" "$MESS" -i $PN/pn.png

По-моему, получилось неплохо.

А дальше всё зависит от ваших потребностей и фантазии. Можно, например, вести ежедневную статистику (не)потраченного трафика. Можно параллельно вести подсчет трафика и сравнивать с тем, что выдается на странице. Можно проверить, действительно ли снимают по 2,64 каждый день? И т. п. А на входе были всего два числа…

Используемая литература

Пишу я редко, как скрипты, так и статьи. Поэтому, конечно же, через время забываю разные мелочи. Лучший помощник по программированию на BASH — книга «Advanced Bash-Scripting Guide» автора Mendel Cooper. Русский перевод этой книги («Искусство программирования на языке сценариев командной оболочки», перевел Андрей Киселев) можно легко найти в интернете, например,

В работе конкретно над этой задачей также помогли следующие материалы:

P.S.

Публикация в узкой колонке блога подразумевает, что длинный код не поместится в строку, поэтому длинные строки придется переносить. Обращаю ваше внимание, что используемый здесь символ «↪» говорит, что предыдущая строка кода продолжается, но она не вместилась на строку блога. Пожалуйста, будьте внимательны, когда будете копировать себе примеры из блога!


Данный материал написан для «Первого конкурса русскоязычных статей для ОС Ubuntu 2011 года» (konkurs.ubuntu.ru)


4 комментария:

  1. Анонимный17 января, 2012 12:33

    А вот самое интересное, что не работает эта схема! Есть мысль, что такая схема будет работать на единичных сайтах/системах. Как пример - мтс, лайф, и др - в моей любимой Беларуси такие фокусы пробрасывают. И CURL сделать ничего не может - с самого начала фокуса ПОЛНЫЙ ФАТАЛ.

    ОтветитьУдалить
  2. Какой-то набор слов в комментарии :)
    Анонимный, конкретнее, пожалуйста, что у вас не работает?
    Модификацию этого скрипта (об этом я писал) я только что запустил, и он работает. И Curl может сделать всё, что может сделать пользователь через браузер, нужно лишь определиться с логикой работы. Об этом больше и говорит данная заметка.

    ОтветитьУдалить
  3. как этот скрипт использовать на windows

    ОтветитьУдалить
  4. Я не уверен, что буду использовать этот скрипт, но это круто! Автор молодец!!!

    ОтветитьУдалить