Здравствуйте уважаемые хабровчане!
Хотелось бы рассказать от том как я делал смс оповещение для своего факультета.
Я учусь на первом курсеФСПО ИТМО. У нас на факультете есть так называемая диспетчерская служба которая занимается оповещением студентов об изменении в расписании, в интернете это осуществляется через страничку в контакте и твиттер.
Однажды произошёл небольшой скандал по поводу того что пол-группы не явилось на занятия из-за того, что не успели отследить изменение в расписании. В тот день у меня появилась идея создать смс оповещение с той самой Vk странички.
Да, я знаю, что для это есть специализированные сервисы, но это слишком просто…
Я новичок в Linux, в Phython и Sql и статья эта пишется по принципу «Учась учи».
Так что не серчайте сильно, если что не так, а лучше просто отпишите свои замечания в комментариях.
Немного поразмыслив я понял что мне нужно:
У меня есть домашний «сервер» на Debian который я гордо именую GrindelServer, на его базе я и собирался всё это реализовать.
Решено было начать с того что-бы просто научится отправлять смски из командной строки. Так получилось что у меня завалялось около трех 3G модемов Huawei E1150, решено было использовать один из них. В Google без труда нашёлся материал по этой теме. Вкратце нужно было перевести модем в режим «только модем» (так у них еще есть фэйковый CD привод и карт ридер), после чего настроить программу Gnokii или Gammu на работу с ним.
Я выбрал Gammu…
Не могу сказать что с Gammu было просто, но в итоге всё получилось.
Установка в Debian стандартная:
У меня поставилась версия 1.28.0
Конфиг gammu: /etc/gammurc
Модем обычно определяется как /dev/ttyUSB0, ttyUSB1, ttyUSB2. Нам нужен ttyUSB0
В конфиг достаточно добавить
Сonnectinon — это тип соединения
Всё! после этого можно проверять
Должно выдать что-то на подобии
Здесь проблем возникнуть не должно, но если они есть, то всегда есть
Cначала нужно задать права на использование модема, они понадобятся только для этого примера, так что не переживайте по тому поводу, что они сбрасываются после перезагрузки.
Теперь, если в модем вставлена симка и на ней есть деньги, можно отправить смс
Например:
Пакет gammu в данном случае нужен был только для проверки, в дальнейшем я использовал демон gammu-smsd.
Он умеет отсылать смс-ки из базы данных (подробно о нём можно почитать на сайте gammu, но обратите внимание на то, что там описывается более поздняя версия.)
Ставим:
Конфиг /etc/gammu-smsdrc
Теперь нужно создать базу.
В
После всех этих действий стоит перезапустить демон
ВНИМАНИЕ! После запуска
Пример из
Принцип следующий
ВНИМАНИЕ! В смс можно отправить только 160 латинских и 70 кириллических символов! Для отправки большего количества текста существуют «multipart sms». Gammu-smsd поддерживает их отправку, процесс описан в
Честно говоря дальше я был в полной растерянности, я никогда не писал подобных программ, весь мой опыт программирования ограничивался школьным Turbo Pascal и небольшим js проектом «Bart Chalkboard Generator»(можно найти в моём профиле).
Я даже не знал какой язык выбрать. Решено было задать вопрос в Q&A.
Спасибо большое за ответы g0lden и avalak!
В результате я выбрал Python и приступил к его изучению на Codecademy. Параллельно я искал способ реализации работы с VK API на Python. И нашёл я его на Хабре, спасибо dzhioev за это! Так же я потихоньку начал разбираться с VK api. Из-за учёбы свободного времени оставолось очень мало и продвигался я очень медленно.
Познакомившись с Python более или менее(на Codecademy я дошёл до списков и словарей), я решил что уже готов приступить к написанию своего скрипта.
Начал я с регистрации странички вконтакте от имени которой будет действовать приложение, далее нужно было зарегистрировать своё приложение. Это достаточно просто и описано в документации вконтакта, так что писать об этом не буду.
Вкратце последовательность действий скрипта такова:
Стоит пояснить про базу данных. Я добавил в базу smsd таблицы VkPosts и Groups. В VkPosts складываются id всех оправленных программой постов, так что в следующий раз можно запросить id последнего отправленного поста, соответственно самого позднего. А в groups находятся номера студентов и номера групп: группа | номер.
Теперь сам скрипт по кусочкам
Подключаем необходимые модули
Инициализируем соединение с базой, и задаём кодировку, что бы не было кракозябр
Сообщаем vk api логин, пароль, номер приложения и запрашиваем привилегии с помощью функции auth из модуля vk_auth, напоминаю модуль взят отсюда.
Получаем в переменную token токен приложения а в user_id айди пользователя чьи данный были введены.
Далее определяем ещё несколько переменных
Основная часть программы
Здесь есть небольшая загвоздка. Если текст поста больше 70 символов я отправляю вместо него — «У тебя изменилось расписание » + сслыка на пост, делаю я это потому что в одну кириллическую смс не влезет больше 70 символов(было сказано выше), а с multipart sms я ещё не разобрался.
logging.info это функция функция ведения логов настроенная в начале кода:
Вот собственно и всё! Осталось сделать скрип исполняемым
И добавить его в Cron c требуемым интервалом.
Но возможности gammu и всего выше перечисленного на этом не заканчиваются, и ваши, я уверен, тоже. Так что фантазируйте.
Мне было очень интересно всем эти заниматься, я был полностью захвачен этой идеей, я был счастлив иметь возможность все это делать и изучать, пусть не всегда было легко(иной раз хотелось всё бросить).
Спасибо, что прочли, надеюсь вам понравилось!
Удачи вам с вашими идеями!
Исходник можно взять здесь.
Хотелось бы рассказать от том как я делал смс оповещение для своего факультета.
Я учусь на первом курсе
Однажды произошёл небольшой скандал по поводу того что пол-группы не явилось на занятия из-за того, что не успели отследить изменение в расписании. В тот день у меня появилась идея создать смс оповещение с той самой Vk странички.
Да, я знаю, что для это есть специализированные сервисы, но это слишком просто…
Лирическое отступление
Я новичок в Linux, в Phython и Sql и статья эта пишется по принципу «Учась учи».
Так что не серчайте сильно, если что не так, а лучше просто отпишите свои замечания в комментариях.
С чего начать?
Немного поразмыслив я понял что мне нужно:
- Сканировать Vk страничку на предмет новых постов
- Искать в этих самых постах упоминания о какой либо группе, например 143
- Если в каком либо посте найден номер какой либо группы, то разослать этот пост на мобильники этой группы
У меня есть домашний «сервер» на Debian который я гордо именую GrindelServer, на его базе я и собирался всё это реализовать.
Решено было начать с того что-бы просто научится отправлять смски из командной строки. Так получилось что у меня завалялось около трех 3G модемов Huawei E1150, решено было использовать один из них. В Google без труда нашёлся материал по этой теме. Вкратце нужно было перевести модем в режим «только модем» (так у них еще есть фэйковый CD привод и карт ридер), после чего настроить программу Gnokii или Gammu на работу с ним.
Я выбрал Gammu…
Gammu
Не могу сказать что с Gammu было просто, но в итоге всё получилось.
Установка в Debian стандартная:
$ sudo apt-get install gammu
У меня поставилась версия 1.28.0
Конфиг gammu: /etc/gammurc
Модем обычно определяется как /dev/ttyUSB0, ttyUSB1, ttyUSB2. Нам нужен ttyUSB0
В конфиг достаточно добавить
[gammu]
port= /dev/ttyUSB0
connection = at
Сonnectinon — это тип соединения
Всё! после этого можно проверять
$ sudo gammu --identify
Должно выдать что-то на подобии
Устройство : /dev/ttyUSB0
Manufacturer : huawei
Модель : unknown (E1550)
Firmware : 11.608.12.00.143
IMEI : 123456789101112
Номер SIM (IMSI) : 123456789098765
Здесь проблем возникнуть не должно, но если они есть, то всегда есть
$ man gammu
и Google.Первая смс из консоли
Cначала нужно задать права на использование модема, они понадобятся только для этого примера, так что не переживайте по тому поводу, что они сбрасываются после перезагрузки.
$ sudo chmod 777 /dev/ttyUSB0
Теперь, если в модем вставлена симка и на ней есть деньги, можно отправить смс
Например:
$ sudo echo "Привет Grindel" | gammu sendsms TEXT +79811111111 -unicode
Автоматизация отправки смс
Пакет gammu в данном случае нужен был только для проверки, в дальнейшем я использовал демон gammu-smsd.
Он умеет отсылать смс-ки из базы данных (подробно о нём можно почитать на сайте gammu, но обратите внимание на то, что там описывается более поздняя версия.)
Ставим:
$ sudo apt-get install gammu-smsd
Конфиг /etc/gammu-smsdrc
[gammu]
port = /dev/ttyUSB0
connection = at
[smsd]
#Сервер базы данных
service = MYSQL
host = localhost
logfile = /var/log/gammu-smsd
#Пользователь базы
user = smsd
password = password
#Адрес сервера базы данных
pc = localhost
#Имя базы
database = smsd
Теперь нужно создать базу.
В
$ man gammu-smsd-tables
сказано что дамп необходимой базы находится по адресу docs/sql/mysql.sql
насколько я понял надо искать в исходниках программы, так что скачав их(версия 1.28.0) можно распаковать архив и в нем найти необходимый sql скрипт, а дальше залить его любым удобным образом, например через phpMyAdmin.(Если кто-нибудь предложит более разумный метод, буду рад!)После всех этих действий стоит перезапустить демон
$ sudo /etc/init.d/gammu-smsd restart
ВНИМАНИЕ! После запуска
gammu-smsd
, gammu --identify
станет выдавать ошибку, это нормально!Отправка смс через mysql
Пример из
$ man gammu-smsd-tables
, этот код можно исполнить в том же phpMyAdminINSERT INTO outbox (
DestinationNumber,
TextDecoded,
CreatorID,
Coding
) VALUES (
'НОМЕР ТЕЛЕФОНА',
'This is a SQL test message',
'Program',
'Default_No_Compression'
);
Принцип следующий
- DestinationNumber — это номер на который должна прийти смс
- TextDecoded — текст который должен прийти
- CreatorID — просто пометка, говорящая о там какой процесс создал эту запись
- Coding — кодировка, если смс на английском то указывается 'Default_No_Compression', если на русском то следует указать 'Unicode_No_Compression'.
ВНИМАНИЕ! В смс можно отправить только 160 латинских и 70 кириллических символов! Для отправки большего количества текста существуют «multipart sms». Gammu-smsd поддерживает их отправку, процесс описан в
$ man gammu-smsd-tables
Написание своей программы для проверки vk странички
Честно говоря дальше я был в полной растерянности, я никогда не писал подобных программ, весь мой опыт программирования ограничивался школьным Turbo Pascal и небольшим js проектом «Bart Chalkboard Generator»(можно найти в моём профиле).
Я даже не знал какой язык выбрать. Решено было задать вопрос в Q&A.
Спасибо большое за ответы g0lden и avalak!
В результате я выбрал Python и приступил к его изучению на Codecademy. Параллельно я искал способ реализации работы с VK API на Python. И нашёл я его на Хабре, спасибо dzhioev за это! Так же я потихоньку начал разбираться с VK api. Из-за учёбы свободного времени оставолось очень мало и продвигался я очень медленно.
Познакомившись с Python более или менее(на Codecademy я дошёл до списков и словарей), я решил что уже готов приступить к написанию своего скрипта.
Начал я с регистрации странички вконтакте от имени которой будет действовать приложение, далее нужно было зарегистрировать своё приложение. Это достаточно просто и описано в документации вконтакта, так что писать об этом не буду.
Разбор скрипта
Вкратце последовательность действий скрипта такова:
- Узнать id последнего отправленного программой поста
- Узнать появлялись ли новые посты после последней отправки
- Попытаться найти в каждом из новых постов хотя бы одну из групп
- Если был обнаружен номер группы то отправить смс по номерам групп(то есть отправить определённый записи в таблицу outbox базы smsd)
Стоит пояснить про базу данных. Я добавил в базу smsd таблицы VkPosts и Groups. В VkPosts складываются id всех оправленных программой постов, так что в следующий раз можно запросить id последнего отправленного поста, соответственно самого позднего. А в groups находятся номера студентов и номера групп: группа | номер.
Теперь сам скрипт по кусочкам
Подключаем необходимые модули
import vk_auth
import json
import urllib2
from urllib import urlencode
import MySQLdb
import logging
import time
import re
Инициализируем соединение с базой, и задаём кодировку, что бы не было кракозябр
db = MySQLdb.connect(host="localhost", user="Логин пользователя бд", passwd="Пароль", db="smsd")
cursor = db.cursor()
db.set_character_set('utf8')
cursor.execute('SET NAMES utf8;')
cursor.execute('SET CHARACTER SET utf8;')
cursor.execute('SET character_set_connection=utf8;')
Сообщаем vk api логин, пароль, номер приложения и запрашиваем привилегии с помощью функции auth из модуля vk_auth, напоминаю модуль взят отсюда.
token, user_id = vk_auth.auth(login, password, "3139526", "groups,wall")
Получаем в переменную token токен приложения а в user_id айди пользователя чьи данный были введены.
Далее определяем ещё несколько переменных
cursor.execute("SELECT postID FROM VKposts ORDER BY VKposts.number DESC LIMIT 0 , 1;") #Получаем id последнего отправленного поста
lastSendedPostId = cursor.fetchall()[0][0] #Кладём его в LastSendedPostId в нормальном виде
groupId = -123456 #Указываем Id группы, ВНИМАНИЕ id группы необходимо указать со знаком минус иначе vkapi решит что это id странички пользователя
cursor.execute("SELECT DISTINCT `group` FROM `groups`") #Собираем массив номеров групп
rawGroups = cursor.fetchall()
groups = []
for rawGroup in rawGroups:
groups.append(rawGroup[0])
Основная часть программы
post = call_api("wall.get", [("owner_id", groupId), ("count", "1")], token)[1] #Получаем последний пост ос стены группы
if post['id'] > lastSendedPostId and post['date'] > actualTime: #Сравниваем Id только что полученого поста с Id последнего отправленного, да можно обойтись без это строчки, но мне так проще было понять
logging.info('I have found some new posts!')
i = 0
while post['id'] > lastSendedPostId and post['date'] > actualTime: #Выбираем в цикле все новые посты
if not len(post) > 1: #Это будет верно если посты на стене внезапно закончатся
break
post['text'] = post['text'].replace('<br>', ' ') #Убираем из текста поста ненужные нам теги перевода строк
for group in groups: #Перебираем массив с номерми групп
if len(re.findall("(^| )" + str(group) + "( |$)", post['text'])) != 0: #Если в тексте поста есть больше нуля совпадение по регулярному выражению "(^| )" + номер группы + "( |$)"
logging.info("I have found %s group in %s post" % (group, post['id']))
cursor.execute("SELECT `tel` FROM `groups`WHERE `group`=%s;" % (group)) #То получаем номера телефонов этой группы
rawTels = cursor.fetchall()
tels = []
for rawTel in rawTels:
tels.append(rawTel[0])
for tel in tels: #Перебираем полученный массив телефонов
if len(post['text']) > 70: #Если длинна текста поста больше 70 то посылаем замену с указанием ссылки на пост
cursor.execute("INSERT INTO outbox(DestinationNumber, Coding, TextDecoded, CreatorID, Class)VALUES ('%s', 'Unicode_No_Compression', 'У тебя изменилось расписание vk.com/wall%s_%s', 'Python', '-1')" % (tel, groupId, post['id']))
sendedPosts.insert(0, post['id']) #Добавляем Id поста в массив
logging.info("Send Cuted %s post to %s****" % (post['id'], tel[0:8]))
else: #Если нет то тогда посылвем полный текст поста
cursor.execute("INSERT INTO outbox(DestinationNumber, Coding, TextDecoded, CreatorID, Class)VALUES ('%s', 'Unicode_No_Compression', '%s', 'Python', '-1')" % (tel, post['text']))
sendedPosts.insert(0, post['id']) #Добавляем Id поста в массив
logging.info("Send %s post to %s****" % (post['id'], tel[0:8]))
i += 1
post = call_api("wall.get", [("owner_id", groupId), ("offset", i), ("count", "1")], token)[1] #Получаем следующий пост
Здесь есть небольшая загвоздка. Если текст поста больше 70 символов я отправляю вместо него — «У тебя изменилось расписание » + сслыка на пост, делаю я это потому что в одну кириллическую смс не влезет больше 70 символов(было сказано выше), а с multipart sms я ещё не разобрался.
logging.info это функция функция ведения логов настроенная в начале кода:
logging.basicConfig(format='%(asctime)s | %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', filename='/home/NetDisk/sms/smslog.log',level=logging.DEBUG)
Вот собственно и всё! Осталось сделать скрип исполняемым
$ sudo chmod +x путь к скрипту
И добавить его в Cron c требуемым интервалом.
Но возможности gammu и всего выше перечисленного на этом не заканчиваются, и ваши, я уверен, тоже. Так что фантазируйте.
В планах
- Сбор базы данных студентов
- Создание веб интерфейса
- И еще всякие мелочёвки и фитчи
Источники
- По поводу настройки gammu было пересмотрена куча всего, так что пожалуй это будет Google и man по gammu
- Пишем модуль для авторизации в VK API, ещё раз спасибо dzhioev!
- Документация vk api
- И ещё куча вcего по мелочи в Google.
P.S.
Мне было очень интересно всем эти заниматься, я был полностью захвачен этой идеей, я был счастлив иметь возможность все это делать и изучать, пусть не всегда было легко(иной раз хотелось всё бросить).
Спасибо, что прочли, надеюсь вам понравилось!
Удачи вам с вашими идеями!
Исходник можно взять здесь.