воскресенье, 17 ноября 2013 г.

выходные и нечем заняться?

Хотите немного автоматизировать рутину?
Если да, то это предполагает наличие компа с убунтой под рукой и желание попитонировать.
Думаю многие слышали а таком сервисе как ifttt.com. Особенно ценится его возможность написывать самому смски в заданное время или по событию. Вот например, удобно просыпаться от смски с погодой на сегодня. Есть правда один нюанс: росийские номера поддерживаются не все. Про мегафон речь не идет, в отличие от остальных опсосов, у него широкий спектр услуг, среди которых есть email2sms. Но ведь у каждого параноика есть запасной телефон с симкой от tele2 для экстренных вызовов ;)
Короче, постановки задачи: хотим получать в смску в семь утра с погодой на предстоящий день.
Отлично, начнем с погоды. Я не сомневаюсь, что в любом городе есть местный сайт погоды или можно воспользоваться услугами гисметео, но пойдем религиозно-верным путем: воспользоваться яху с его yql. Это клевая штука, но для начала нам нужно узнать идентификатор своего города WOEID. Можно конечно попробовать запилить селект для этой веб консоли, но зачастую она предлагает несколько вариантов, проще поискать по карте точку и вытащить id из урла. У меня это 24553418.
Ништяк, теперь будем получать погоду в джейсоне. Для этого надо составить запрос вида
SELECT * FROM weather.forecast WHERE woeid="24553418" and u="c"
Как видно, инфы много, даже слишком. Но это ничего) Для начала попробуем это все читать в консоли, а не на сайте, а что бы не мутнеть от вида одной большой строки джейсона, воспользуемся прекрасной функцией pprint
#! /usr/bin/env python
# -*- coding: utf8 -*-
import smtplib, urllib, json
from codecs import encode
from pprint import pprint

yahooUrl = 'http://query.yahooapis.com/v1/public/yql'
query = ''
yahooParams = {'q': query, 'format': "json"}
yahooWOEID = '24553418' # it s Novosibirsk WOEID, if uou are looking for another city visit visit http://location.yahoo.com/locationmgt/"
query = 'SELECT * FROM weather.forecast WHERE woeid="%s" and u="c"' % yahooWOEID
yahooParams['q'] = query

params = urllib.urlencode(yahooParams)
yahooResponse = urllib.urlopen(yahooUrl+'?'+params)
data = json.load(yahooResponse)
yahooResponse.close()
pprint(data)
Иииха! У нас здоровенная красиво отформатированная простыня инфы? И да я в курсе прекрасной либы requests, но черт побери, ставить ее только для гет-запроса и потом прочитать ответ?! Нет, проще обойтись батарейками. Дальше? Дальше1! Отсекаем лишнее:
res = data['query']['results']['channel']['item']

nowDate = res['condition']['date']
nowT = res['condition']['temp']

today =res['forecast'][0]
highT = today['high']
lowT = today['low']

wind = data['query']['results']['channel']['wind']
windDirection = int(wind['direction'])
windSpeed = wind['speed']
Странная вещь. Направление ветра в каких то циферях. Но после непродолжительного гугления, становиться понятно, что это градусы. Ну что же переведем их в читабельный формат, что бы не ломать голову с утра пораньше.
def rozaVetrov(deg):
    res = ''
    if 0 <= deg <= 11.25: res = u'северный'
    elif 11.25 < deg <= 78.75: res = u'северо-восточный'
    elif 78.75 < deg <= 101.25: res = u'восточный'
    elif 101.25 < deg <= 168.75: res = u'юго-восточный'
    elif 168.75 < deg <= 191.25: res = u'южный'
    elif 191.25 < deg <= 258.75: res = u'юго-западный'
    elif 258.75 < deg <= 281.25: res = u'западный'
    elif 281.25 < deg <= 348.75: res = u'северо-западный'
    elif 348.75 < deg <= 360: res = u'северный'
    return res

windDirection = rozaVetrov(int(wind['direction']))
Круто, теперь можно готовиться это все к рассылке. Начнем с почты.
message = nowDate + u'\nЗа бортом: ' + nowT  + u'C\nТмакс='  + highT + u'\nТмин=' + lowT + u'\nВетер=' + windSpeed + u' км/ч\nДует: ' + windDirection
message = encode(message, "utf-8")

EMAIL_HOST = 'smtp.server.ru'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'server@server.ru'
EMAIL_HOST_PASSWORD = 'easy'

TO = ['user@server.ru']
subject = 'weather'

body = """From: server <%s>\nTo: %s\nSubject: %s\n\n%s
            """ % (EMAIL_HOST_USER, ", ".join(TO), subject, message)
def mail(to=""):
    try:
        TO.append(to)
        server = smtplib.SMTP(EMAIL_HOST, EMAIL_PORT)
        server.ehlo()
        server.starttls()
        server.ehlo()
        server.login(EMAIL_HOST_USER, EMAIL_HOST_PASSWORD)
        server.sendmail(EMAIL_HOST_USER, TO, body)
        server.quit()
        print 'success'
    except:
        import sys
        print "Unexpected error:", sys.exc_info()[0]
        raise
Надеюсь не за были поставить нужный chmod на скрипт, что бы он стал исполняемым? Интересно зачем такой странное тело? А все просто: если в топуго посылать то что есть, то в отправителе будет mail-daemon. Но мы же за красоту. И поэтому еще в принт посылаем результат отправки, который в дальнейшем будем логгировать. Наверно еще осталось освятить server.ehlo(). Если честно то я просто нагуглил это решение, потому что при подключении к яндексу по ttl у меня скрипт сразу не завелся. Это какой то замороч для успешного начала шифрования.
Если же на почту у вас ниче не приходит, поздравляю, руки у вас кривые, гуглите. А теперь воспользуемся услугами смс-шлюза sms.ru. В отличие от остальной толпы, у них есть одно преимущество - смски на свой телефон бесплатно. И еще, там не обязательно заморачиваться с get запросами и токенами сессий - просто отправь мыло куда надо. Прям как зуко - просто добавь воды. А еще  можно придумать свое буквенное мыло и вообще лепота. Именно поэтому, когда мы вновь будем вызывать функу mail() с  передадим в нее свое новую почту. Ляпота?)
А теперь займемся консолью, а именно кроном. По классике жанра, совет убунтоводам:
crontab -e
#{enter}
* * * * * /srv/www/temp/weather.py >> /srv/www/temp/cron.log 2>&1
что означает, что в каждую минуту, каждого часа, каждого.. (ну вы пояли) скрипт запустится и результат этого сохранится в лог. Можно конечно положить в openshift сервер от красной шляпы, но там какой то упоротый крон, да еще запилено виртуальное окружение. Возможно там нужно запускать через вспомогательный шелл скрипт, но как то влом сейчас разбираться. В любом случае, если я все таки буду использовать "сервер где то там" то я не буду заморачиваться над подобными масштабированными решениями а втупого куплю vps.
Если же почта не пришла смотрим в лог и гуглим ошибку. Если же все хорошо, то последовательность звездочек заменяем на
1 7 * * * /srv/www/temp/weather.py >> /srv/www/temp/cron.log 2>%1
А теперь ложимся спать и ждем смски! Доброй ночи, %username%