wiki:скрипт_для_проверки_баланса_в_peoplenet Сравнение версий

Различия

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

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
wiki:скрипт_для_проверки_баланса_в_peoplenet [2011/09/27 22:11]
— (текущий)
Строка 1: Строка 1:
-====== Скрипт для проверки баланса в PeopleNet ====== 
  
-{{ :​wiki:​peoplenet.png|PeopleNet}} В данной статье рассматривается процесс создания скрипта для проверки баланса украинского мобильного оператора PeopleNet, который обычно используется для мобильного доступа к 3G интернету. Целью статьи является популяризация написания скриптов для облегчения ежедневных задач. 
- 
-Всё началось с вопроса моего друга. «Нельзя ли что-нибудь сделать с теперешним подсчетом трафика в PeopleNet? Ведь что-то же считает!» Я сразу же стал теоретизировать,​ что таки да, можно… И через пару ночей я засел за работу и родился скрипт,​ которым я хочу поделиться с вами. 
-Нужно ввести читателя в курс дел. 
- 
-В популярном пакете «777» от PeopleNet предоставляется ежедневно трафик размером 232 МБ (как бы 7 ГБ в месяц и как бы за 77 грн). Узнать остаток доступного трафика на текущие сутки можно, отправив с 3G модема SMS на служебный номер и прочитав ответ (при помощи «фирменной» программы для Windows. Отправлять SMS в Linux, с 3G модемов как-то еще не очень получается. 
-Кроме того, существует страничка биллинга,​ называемая Системой самообслуживания клиентов. Раньше я уже писал скрипт для подобных целей. Но раньше было проще. Можно было получить информацию о потраченном трафике за каждую сессию за каждый день в течение последнего месяца. Теперь же на странице красовалось одно число — количество потраченных МБ с начала месяца. С тех пор сёрфинг в сети велся практически вслепую… 
- 
-Я почти полностью переписал скрипт,​ избавился от множества промежуточных шагов, временных переменных и файлов,​ и это пошло скрипту только на пользу. Его основу составляет одна «волшебная» строчка кода, которая получает со страницы самообслуживания число потраченных с начала месяца мегабайт:​ 
- 
-<code bash>​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]*'</​code>​ 
-или в с переносом строки 
-<code bash>​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]*'</​code>​ 
- 
-Здесь используется **curl** — удобная программа,​ которую можно в шутку назвать «веб-браузер для робота». Ее можно вызывать из своих скриптов для отсылки запросов,​ форм, получения и отправки страниц и файлов. Для того, чтобы получить информацию по своему номеру,​ вы должны изменить **380921234567** на свой номер, а **11223344** — на свой пароль для входа на страницу самообслуживания. В процессе работы будет загружена страничка размером 11,5 кБ и из нее будет выделено единственное число, которое вы и получите «на выходе». О том, что делать дальше с этим числом,​ мы поговорим немного позже. 
- 
-===== Как работает этот код ===== 
- 
-Обо всех опциях команды curl вы сможете узнать,​ если выполните в терминале команду 
-<​code>​curl --help</​code>​ 
-Такой подход к получению справки типичен для большинства команд в Linux. 
-Здесь мы используем такие ключи: 
-  * -s — «молчаливый» режим. Curl не будет печатать в терминале не нужную нам информацию о размере и скорости закачки указанной страницы;​ 
-  * -d и следующая строка в кавычках — данные,​ отсылаемые на сервер по методу POST; 
-  * --url и длинная строка,​ заканчивающаяся перед вертикальной чертой — адрес страницы,​ которую нужно получить. Сам ключ «--url» можно было бы и не писать,​ оставив только строку. Вертикальная черта передает страничку,​ загруженную командой curl, дальше,​ следующей команде,​ по конвейеру. 
- 
-Откуда взялись параметры для ключей **-d** и **--url**? 
-Проследим работу системы самообслуживания. Зайдем при помощи обычного браузера на страницу http://​my.people.net.ua/​. Нас просят ввести номер телефона и пароль,​ затем нажать кнопку подтверждения. Далее нужно перейти по ссылке //​«Ежемесячный счет»//​. На следующей странице выбрать нужный месяц из выпадающего списка (текущий месяц находится вверху и поэтому выбирать ничего не нужно) и нажать кнопку подтверждения. На следующей странице нужно пробежаться глазами по таблице и найти в строчке //​«Передача даних EVDO»// нужное нам число. Теперь научим робота делать то же самое. 
-Для исследования страниц нам пригодится ключ **-o** команды curl. После этого ключа указываем название файла и страничка,​ указанная в ключе **--url** будет загружена в этот файл. 
- 
-Итак, первый шаг: 
- 
-<code bash>​curl --url "​http://​my.people.net.ua/"​ -o "​take1.html"</​code>​ 
-Открываем полученный файл **take1.html** в текстовом редакторе (нужно хотя бы немного разбираться в html-разметке). Мы видим html-форму:​ 
-<file 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>​ 
-</​file>​ 
-Я удалил всё, не относящееся к делу, чтобы можно было сосредоточиться на нашем задании. Итак, данные формы отправляются методом POST, значит,​ воспользуемся ключом -d команды curl. Вот, если бы метод был GET, то можно было бы не городить огород,​ а дописать передаваемые данные прямо в строку адреса (примерно так: [[http://​наш.длинный/​адрес?​параметр1=значение1&​параметр2=значение2]]). 
- 
-Итак, из анализа формы становится понятно,​ что при нажатии кнопки подтверждения данные формы отсылаются по адресу http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO/​ и эти данные — **X_Username=номер телефона** и **X_Password=пароль**. 
- 
-Второй шаг наших раскопок:​ 
-<code bash>​curl -d "​X_Username=380921234567&​X_Password=11223344"​ --url "​http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO/"​ -o "​take2.html"</​code>​ 
- 
-Просмотрев загруженную страничку,​ мы видим, что да, нас успешно пустили в систему самообслуживания. Теперь нас интересует ссылка:​ 
-<​file><​a href="​http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO?​sid=bills">​Ежемесячный счет</​a></​file>​ 
-Я снова убрал всё лишнее. Попробуем:​ 
-<code bash>​curl --url "​http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO?​sid=bills"​ -o "​take3.html"</​code>​ 
-Получаем страничку с ошибкой. Хм, попробуем так: 
-<code bash>​curl --url "​http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO/?​sid=bills"​ -o "​take3.html"</​code>​ 
-Теперь получаем первоначальную страничку для входа в систему самообслуживания. Нас забыли и снова предлагают ввести номер и пароль! Попробуем не городить огород,​ а просто объединим две команды,​ два адреса в один: 
-curl -d "​X_Username=380921234567&​X_Password=11223344"​ --url "​http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO/?​sid=bills"​ -o "​take3a.html"​ 
-Так! Мы продвинулись дальше! Просматривая страницу,​ находим в ней форму для выбора месяца:​ 
-<file 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>​ 
-</​file>​ 
- 
-Я снова убрал всё лишнее из html-разметки. В зависимости от вашего «стажа» в PeopleNet длина списка у вас будет другая. Итак, адрес для отсылки формы ясен; метод, кстати — GET, значит,​ пишем параметры прямо в строку адреса. Имеется скрытая (hidden) переменная с именем sid и значением bills. Вторая переменная с именем rp и нужным нам значением 117. Формируем адрес: 
-[[http://​my.people.net.ua/​TSU/​WWW/​ACCOUNT_INFO/?​sid=bills&​rp=117]] 
- 
-Пробуем снова совместить команды:​ 
-<code bash>​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"</​code>​ 
-Да, мы продвинулись еще дальше. Правда,​ такого же восторга уже нет. Остается работа. И она заключается в следующем. 
- 
-Во-первых,​ каждый месяц число в параметре rp будет меняться. Во-вторых,​ нам нужно проанализировать код страницы. Подберем формулу для расчета числа: 
-<code bash>rp = ( год - 2 ) * 12 + месяц</​code>​ 
-Номер года (две последние цифры) и номер месяца (две цифры) мы можем получить соответствующими командами:​ 
-<code bash>​date +%y</​code>​ 
-<code bash>​date +%m</​code>​ 
-Если окружить команду такой оберткой — $(команда),​ то тогда результат работы этой команды будет представлен в виде строки и его можно будет использовать для дальнейших вычислений в более сложных командах. Для математических расчетов используем команду expr. 
-<code bash>​expr ( $(date +%y) - 2 ) * 12 + $(date +%m)</​code>​ 
-Получаем ошибку,​ говорящую о некорректном синтаксисе,​ курим маны и «экранируем» скобки,​ входящие в нашу формулу,​ а также звездочку (знак умножения),​ поставив перед ними бэкслэш (\): 
-<code bash>​expr \( $(date +%y) - 2 \) \* 12 + $(date +%m)</​code>​ 
-Получаем 117. Что нам и требовалось! 
-Теперь окружаем эту команду при помощи $(...) и подставляем ее вместо числа 117 в нашу супер-команду curl: 
-<code bash>​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))</​code>​ 
- 
-Заметьте,​ что кавычки закрываются после «rp=» и сразу же мы пишем обернутую команду,​ таким образом,​ результат команды (число 117) дописывается к строке. 
- 
-Теперь пришло время «во-вторых» — анализ кода страницы. Вы помните,​ как выглядит табличка,​ когда вы заходили через браузер?​ Ищем строчку с аббревиатурой EVDO и находим такой участок html-разметки:​ 
-<file html> 
-  <tr> 
-    <td> 
-      <​i>​      Передача даних EVDO</​i>​ 
-    </td> 
-    <td class="​ar4">​ 
-      <​i>​ 224</​i>​ 
-    </td> 
-    <td class="​ar4">​ 
-      <​i>​0.00</​i>​ 
-    </td> 
-  </tr> 
-</​file>​ 
-Здесь я не стал убирать ничего. Нам нужно «научить робота» выделять вот это число — **224**. 
- 
-Давайте поищем на странице слово «EVDO» (в текстовом редакторе,​ в котором вы просматриваете эту страничку). Нашли только один раз, хорошо. Курим маны. Пользуемся командой grep. Команда grep EVDO выдает нам только строчку,​ в которой найдено слово EVDO, а команда grep -A 3 EVDO выдает нам эту строчку и еще три следующих за ней строки. Как раз в третьей строке находится наше число! Итак, код: 
-cat "​take4.html"​ | grep -A 3 EVDO 
-Здесь мы при помощи команды cat выводим содержимое файла take4.html и при помощи вертикальной черты передаем его дальше по конвейеру команде grep. Получаем:​ 
-<file html> 
-      <​i>​      Передача даних EVDO</​i>​ 
-    </td> 
-    <td class="​ar4">​ 
-      <​i>​ 224</​i>​ 
-</​file>​ 
-Теперь «откусим» только последнюю строку при помощи команды tail: 
-<code bash>cat "​take4.html"​ | grep -A 3 EVDO | tail -n 1</​code>​ 
-Получаем:​ 
-<file html> ​     <​i>​�224</​i></​file>​ 
- 
-Вы заметили некий гаденький символ перед цифрами?​ Так в консоль выводится символ неразрывного пробела,​ который непонятно зачем всунули разработчики этой странички. В старой версии скрипта я бы написал несколько команд,​ которые последовательно по конвейеру,​ удаляли бы из строки ненужные нам символы. Сначала бы заменили пробел(ы) на ничто (т. е. удалили их), затем «<​i>​»,​ после «</​i>​»,​ и, наконец,​ этот гаденький символ. 
-Синтаксис команды sed (для замены строк) прост: 
-<code bash>sed -e '​s/​что-менять/​на-что-менять/​g'</​code>​ 
-Ключ g говорит,​ что менять нужно глобально,​ а не только первый попавшийся случай. Так, команда:​ 
-<code bash>sed -e 's/ //g; s/<​i>//​g;​ s/<​\/​i>//​g'</​code>​ 
- 
-последовательно заменит все пробелы на «ничто»,​ затем «<​i>​» и «</​i>​». А, вот, с этим символом не всё так просто. Кодировка скрипта,​ конечно же, UTF-8, а кодировка странички — windows-1251. Поэтому,​ команда **sed** ничего не найдет. А, если же сохранить скрипт в кодировке 1251, то мы не сможем выводить этим скриптом русские буквы. А, если, сохранить в 1251, вставить символ в скрипт,​ а затем открыть как UTF-8, то текстовый редактор откажется работать с этим скриптом. Да-а… 
- 
-Отмечу,​ что ту же задачу можно было бы решить по-другому:​ 
-<code bash>cut -d ">"​ -f 2 | cut -d "<"​ -f 1</​code>​ 
-Здесь сначала мы разбиваем нашу строку на части. Разделитель частей Всё хорошо,​ но число с этим символом в начале нельзя подставлять в математические выражения — получим ошибку! Покурив маны, я нашел простое и элегантное решение:​ 
-<code bash>​grep -o '​[0-9]*'</​code>​ 
-В переводе на русский язык это значит:​ выдать из исходной строки только символы из интервала 0-9 (цифры),​ а звездочка обозначает,​ что этих цифр может быть произвольное количество. 
- 
-Вот и всё! Получился скрипт в одну строку,​ который выполняет такую сложную задачу! Вот в этом и заключается сила командной строки Linux, профессионалы могут сделать в консоли всё что угодно. А новички не верят, говорят,​ устарело. Неправда…— символ «>», берем вторую часть. Затем полученную строку снова разбиваем на части, но уже символом «<» и берем первую часть. 
-То, что задачу можно решить как минимум двумя разными способами — тоже типично для Linux. 
- 
-===== Обрабатываем полученное значение ===== 
- 
-Если ваш тарифный план не подразумевает посуточную разбивку трафика (400 МБ в месяц),​ то на этом всё, вы можете вывести это число на экран (об этом позже). Если же в вашем тарифе существует суточный лимит (например,​ 232 МБ/​сут.,​ как в тарифном плане «777»; либо 300 МБ/​сут.,​ как в другом тарифном плане, названия которого я не знаю), то пойдем дальше. 
- 
-Идея такая. При самом первом за сутки подключении к интернету мы должны запустить наш скрипт и запомнить полученное число. При последующих подключениях за эти же сутки число будет увеличиваться,​ и тогда по разнице мы можем узнать,​ сколько мегабайт мы потратили. 
- 
-Удобно,​ когда скрипт сам будет за нас записывать это число и сам будет считать остаток. Лучше всего дописать вызов этого скрипта в конец процедуры подключения к интернету;​ таким образом,​ как только вы подключитесь к интернету,​ так сразу, не потратив еще нисколько мегабайт,​ узнаете число со страницы самообслуживания. А потом, когда вы присоединяетесь к интернету в следующий раз, скрипт должен снова узнать число со страницы самообслуживания,​ найти разницу (потраченные МБ) и отнять от суточного лимита эту разницу. Задача ясна? Беремся?​ 
- 
-Для начала,​ давайте,​ отведем отдельный файл для такой важной задачи — хранения количества потраченных мегабайт в начале суток. В нём будет храниться одно число. Пусть его формат будет таким: **MMDDxxxx** 
-где: **MM** — месяц, **DD** — день, **xxxx** — мегабайты. Весьма компактно. 
- 
-Мы можем определить текущую дату при помощи команды 
-<code bash>​date +%m%d</​code>​ 
-А выделить дату из файла можно такой командой (взять первые 4 символа из файла):​ 
-<code bash>cut -c -4 файл</​code>​ 
-Параметр «-4» это сокращенная запись «с начала и до четвертого». Полностью можно было бы записать «1-4», что значит «с первого по четвертый». 
-Количество мегабайт выделяется из файла командой:​ 
-cut -c 5- файл 
-Что тоже является сокращенной формой «с пятого и до конца». 
- 
-Теперь продумаем возможные ситуации. ​ 
-  * Что, если нет подключения к интернету,​ а мы запустили скрипт?​ В результате работы нашей супер-команды мы получим пустую строку. Говорим «Ошибка связи». 
-  * Что, если файла нету? Получаем данные со страницы самообслуживания,​ создаем файл и заносим в него цифры. Говорим,​ что на сегодня осталось максимально возможное количество МБ. 
-  * Что, если дата в файле является устаревшей (вчера,​ позавчера…)?​ Значит,​ сегодня мы еще не пользовались интернетом. Получаем данные и заносим в файл. Говорим,​ что на сегодня осталось максимально возможное количество МБ. 
-  * Что, если дата сегодняшняя?​ Файл не меняем. Находим количество потраченных МБ. От суточного лимита отнимаем потраченные. Выдаём число. 
- 
-Теперь схематично опишем алгоритм. 
-<​file>​ 
-ПОЛУЧИТЬ «КОЛИЧЕСТВО_МБ» 
-ЕСЛИ [ «КОЛИЧЕСТВО_МБ» пустое ] 
-|ТОГДА 
-|  СООБЩЕНИЕ = «Ошибка связи» 
-|ИНАЧЕ 
-|  УЗНАТЬ «текущую дату» (ММДД) 
-|  ЕСЛИ [ файл есть ] И [ дата в файле (ММДД) совпадает с текущей (ММДД) ] 
-|  |ТОГДА 
-|  |  «ОСТАЛОСЬ» = («xxxx из файла» + «суточный лимит» - «КОЛИЧЕСТВО_МБ») 
-|  |ИНАЧЕ 
-|  |  записать «текущую дату (ММДД)» и «КОЛИЧЕСТВО_МБ» в файл; 
-|  |  «ОСТАЛОСЬ» = «СУТОЧНЫЙ ЛИМИТ» 
-|  КОНЕЦ_ЕСЛИ 
-|  СООБЩЕНИЕ = «На сегодня осталось:​ «ОСТАЛОСЬ» МБ» 
-КОНЕЦ_ЕСЛИ 
- 
-ВЫДАТЬ «СООБЩЕНИЕ» 
-</​file>​ 
-Алгоритм понятен?​ Замечательно,​ если да! Теперь запишем его при помощи консольных команд на языке BASH. 
-Указываем,​ что наш СУТОЧНЫЙ ЛИМИТ равен 232 МБ: 
-<​file>​LIM=232</​file>​ 
-В переменной **PN** сохраняем папку, в которую мы положили всё нужное для работы нашего скрипта — сам скрипт,​ файл для хранения DDMMxxxx и даже логотип **PeopleNet**. Папка эта называется peoplenet и лежит она в нашей домашней папке (на что указывает системная переменная **$HOME**), которая,​ конечно же разная для разных пользователей. Но, благодаря такому подходу,​ ничего в скрипте менять не нужно. Переменную **PN** мы ввели для краткости. Назовем файл для хранения DDMMxxxx просто «**pn**», тогда путь к нему мы можем записать так: "​**$PN/​pn**";​ картинка же называется pn.png и путь к ней будет "​**$PN/​pn.png**"​. 
-<code bash> 
-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 
-</​code>​ 
- 
-Немного нужно рассказать о последней команде,​ так? Эта команда должна выполняться на любом дистрибутиве,​ поддерживающем стандарты. Она выдает примерно такое вот сообщение:​ 
- 
-{{:​wiki:​peoplenet_script_example_1.png}} 
- 
-При наведении на него мышки, оно тускнеет и пропадает,​ не мешая работать с другими окнами,​ а через несколько секунд (в зависимости от количества текста в сообщении) пропадает. 
- 
-{{:​wiki:​peoplenet_script_example_2.png}} 
- 
-Хотите поместить на рабочий стол значок для запуска нашего скрипта?​ Нажмите на рабочем столе правой кнопкой — Создать кнопку запуска… и заполните поля. Следующий рисунок показывает,​ как это сделал я. 
- 
-===== Всё? Нет! Продолжение ===== 
- 
-В процессе написания статьи мне захотелось получить еще больше функционала от моего скрипта. На счету у меня сегодня «минус»,​ но скрипт по прежнему щедро выдает мне мегабайты. Такую ситуацию надо отслеживать. Заодно можно узнать,​ на сколько дней хватит денег и выдать дату, когда нужно пополнить счет. 
- 
-Так как страницу,​ загруженную из системы самообслуживания,​ теперь нужно будет дважды проанализировать,​ разобьем нашу супер-команду на две части. Запомним страницу в переменную **PAGE**, а затем найдем в ней всё, что нам нужно: 
-<code bash> 
-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]*'​) 
-</​code>​ 
-Теперь посмотрим,​ как из текста страницы можно выделить остаток на счету. Просмотрим файл **take4.html**,​ который мы загрузили в процессе экспериментов (эта же страница будет загружена в переменную **PAGE**). Мы видим строки 
- 
-<​file>​ 
-  <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> 
-</​file>​ 
-Чтобы не связываться с русскими буквами в другой кодировке (хотя, при необходимости,​ страницу можно конвертировать),​ будем искать текст «14.09.2011» — это текущая дата на момент написания статьи. Дату в таком формате мы можем получить при помощи команды:​ 
-<code bash>​date +%d.%m.%Y</​code>​ 
-Дальше — технология отработана. Выделяем пятую строчку после найденной,​ а затем выделяем содержимое между символами «>» и «<». В завершение,​ удалим точку, чтобы перевести сумму в копейки,​ так как консольная команда expr работает только с целыми числами:​ 
-<code bash>​MONEY=$(echo "​$PAGE"​ | grep -A 5 $(date +%d.%m.%Y) | tail -n 1 | cut -d ">"​ -f 2 | cut -d "<"​ -f 1 | sed -e '​s/​\.//'​)</​code>​ 
-Если число меньше нуля, выведем сообщение //​«Услуга недоступна. Пополните счет!»//​ 
- 
-Согласно справочнику тарифов PeopleNet, каждый день со счёта снимается сумма **2,​64 грн**. Давайте разделим полученный баланс на тариф и узнаем,​ на сколько дней нам хватит денег: 
-<code bash>​TARIFF=264 
-DAYS=$(expr $MONEY / $TARIFF)</​code>​ 
-Если денег меньше,​ чем 264, то мы получим 0. Это значит,​ что ночью будет снята сумма тарифа и на счету будет меньше нуля. Интернет завтра будет недоступен. Выведем сообщение //​«Пополните счет сегодня»//​. Если получим 1, то выведем //​«Пополните счет завтра»//​. Для других чисел выведем что-то вроде //​«Осталось 3 дня. Пополните 31.09.2011 г.»// 
- 
-Здесь есть две «проблемы». Во-первых,​ корректная выдача слов// «день»//,​ //​«дня»//,​ //​«дней»//​. Во-вторых,​ расчет даты в будущем,​ на расстоянии несколько дней от сегодняшней даты. На самом деле это — не проблемы. Поверьте — всё решаемо! 
- 
-Во-первых,​ я вспомнил время, когда занимался локализацией строк в программах при помощи Gettext. Там была интересная строчка кода, которая определяет форму слова. Чтобы не рыться в старых файлах,​ достаточно почитать [[http://​ru.wikipedia.org/​wiki/​Gettext|страничку Gettext в Википедии]]. Вот эта строка:​ 
-<code bash>​plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<​10 || n%100>​=20) ? 1 : 2)</​code>​ 
-Как ее приспособить для нашего скрипта?​ Оказывается,​ достаточно окружить ее двойными скобками и пробелами. Теперь,​ если plural=**0**,​ то пишем «день»,​ если **1** — то «дня», если **2** — то «дней». Создадим массив со словами:​ 
-<code bash>​day=( день дня дней )</​code>​ 
-И будем выдавать нужное слово (по номеру элемента массива) командой 
-<code bash>​${day[$plural]}</​code>​ 
-Теперь займемся расчетом дат. Google, как обычно,​ помогает. На этот раз мне понравилась [[http://​www.unix.com/​tips-tutorials/​31944-simple-date-time-calulation-bash.html|вот эта ссылка]]. 
-Так много функционала мне не надо, поэтому я максимально сокращаю скрипт под свою задачу. 
-# количество секунд,​ прошедших с 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"​) 
-</​code>​ 
-Можно всё это собрать в одну строку:​ 
-<code bash>​DATE2=$(date --utc --date "​1970-01-01 $(expr $(date --utc +%s) + \( $DAYS + 1 \) \* 86400) sec" "​+%d.%m.%Y"​)</​code>​ 
-Теперь — весь скрипт целиком. Он исправно выполняет поставленные задачи. 
-<code 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 
-</​code>​ 
-По-моему,​ получилось неплохо. 
- 
-А дальше всё зависит от ваших потребностей и фантазии. Можно, например,​ вести ежедневную статистику (не)потраченного трафика. Можно параллельно вести подсчет трафика и сравнивать с тем, что выдается на странице. Можно проверить,​ действительно ли снимают по 2,64 каждый день? И т. п. А на входе были всего два числа… 
- 
-===== Используемая литература ===== 
-Пишу я редко, как скрипты,​ так и статьи. Поэтому,​ конечно же, через время забываю разные мелочи. Лучший помощник по программированию на BASH — книга «Advanced Bash-Scripting Guide» автора Mendel Cooper. Русский перевод этой книги («Искусство программирования на языке сценариев командной оболочки»,​ перевел Андрей Киселев) можно легко найти в интернете,​ например,​ 
-  * [[http://​www.opennet.ru/​docs/​RUS/​bash_scripting_guide/​|Версия 1.8]] на OpenNet.ru 
-  * [[http://​gordin.us/​sergo/​abs-guide/​index.html|Версия 2.5]] на gordin.us 
- 
-В работе конкретно над этой задачей также помогли следующие материалы:​ 
-  * [[http://​people.net.ua/​ru/​tariffs/​prepaid/​anonymouse/​|Анонимные тарифные планы PeopleNet]] 
-  * [[wpru>​Gettext]] — Википедия 
-  * [[http://​www.unix.com/​tips-tutorials/​31944-simple-date-time-calulation-bash.html|Simple date and time calulation in BASH - The UNIX and Linux Forums]] 
- 
-\\ \\  
- 
-^Автор^Раздел^ 
-|Бобылёв Алексей (Lexeii)|как сделать ...| 
- 
-{{tag>​Конкурс}}