Автоматическая отсылка анонсов в твиттер

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

Как оказалось, делается это совсем несложно.


Я сразу решил не изобретать велосипед и воспользоваться одной из доступных библиотек для работы с твиттером. Больше всего мне глянулся twython. Импортируем его в models.py:

Copy Source | Copy HTML
  1. import twython.core as twython

Вот упрощенная модель публикаций. Я оставил только самый минимум полей:

Copy Source | Copy HTML
  1. class Post(models.Model):
  2.     title = models.CharField(max_length=100)
  3.     media = models.TextField()
  4.     published = models.BooleanField(default=False)
  5.     tweeted = models.BooleanField(default=False, editable=False)
  6.  
  7.     def __unicode__(self):
  8.         return u'%s' % self.title
  9.  
  10.     @models.permalink
  11.     def get_absolute_url(self):
  12.         return ('news.views.news_view', [str(self.id)])

У модели есть два поля — published для того, чтобы не «твитить» черновики и tweeted, чтобы каждый пост анонсировался только один раз.

Теперь сам процесс отправки анонса:

Copy Source | Copy HTML
  1. def post_to_twitter(sender, instance, **kwargs):
  2.     """
        Отправляем анонс в тви если пост опубликован но еще не затвитен
        """
  3.     if instance.published and not instance.tweeted:
  4.         try:
  5.             twitter = twython.setup(username="TWITTER_USER", password="TWITTER_PASSWORD")
  6.             long_url = "http://%s%s" % (Site.objects.get_current(), instance.get_absolute_url())
  7.             short_url = twitter.shortenURL(long_url)
  8.             twi_message = instance.title + " " + short_url
  9.             try:
  10.                 twitter.updateStatus(twi_message)
  11.                 Post.objects.filter(pk=instance.pk).update(tweeted = True)
  12.             except TwythonError:
  13.                 pass
  14.         except AuthError:
  15.             pass

Процесс отсылки в твиттер логично повесить на событие post_save:

post_save.connect(post_to_twitter, sender=Post)


Вот и все. Можно добавить всяких полезностей по-вкусу, но и в таком виде вполне себе работает.
+19
24 марта 2010, 21:00
35
Voldar 20,3

комментарии (32)

+7
zw0rk #
except:
pass

очень порочная практика
+4
Voldar #
Не спорю. Но в данном случае я не увидел смысла как-то обрабатывать исключения. Не ушел анонс в твиттер по каким-то причинам? Ну и ладно, это абсолютно не критичная функция. Добавить вменяемую обработку тут не сложно.
–1
bobry #
воспитываете дурные привычки?
0
Voldar #
Напишите, что вы предлагаете, я внесу правки в пост.
+6
glader #
Ребята имеют в виду, что нехорошо перехватывать все исключения подряд. Там могут быть как ошибки отправки, так и ошибки в коде. Поэтому лучше делать перехват конкретных исключений, кидаемых twython (я не знаю, что он кидает, надо посмотреть в код или документацию).
0
Voldar #
Спасибо, поправил.
0
bobry #
присоединяюсь
never ever use except:
+2
Deepwalker #
А что не OAuth? Не модно нынче пароли давать.
0
Voldar #
Тут задача простая, зачем усложнять? Вообще если делали через OAuth — напишите, лично мне было бы интересно потитать.
0
Deepwalker #
Я его пока только в плане аутентификации раскуривал. Но по-моему даже и было что-то на страницах хабра, или у DK.
+2
junk #
Большой минус не за OAuth, я не пользуюсь сервисами, где пароль от твитера спрашивают.

Лично делал OAuth для Django, это не сильно сложнее.
0
homm #
я не пользуюсь сервисами, где пароль от твитера спрашивают.
Даже если вы администратор этого сервиса?
+1
junk #
в твиттер заголовок и укороченную ссылку для публикуемых статей от имени пользователя.


Кажется речь идет именно о пользователях? А не об одном твит-аккаунте с которого портал публикует сообщения?

Или в чем вопрос? Стал бы я вводить пароль от твиттера в написанном мной сервисе? Да тоже нет :) мало ли базу сопрут.
0
Voldar #
Речь об одном тви-пользователе. PR-щицы публикуют на сайте статьи и апдейты отправляются в твиттер от имени «общего» аккаунта. Логин и пароль у меня settings.py прописаны — здесь я для простоты не стал это расписывать.
+1
junk #
Тогда был не прав, OAuth здесь ни к чему.
+1
fata1ex #
Напоминает кусок кода из readme какой-нибудь обертки twitter api: \
Устройте полный обзор библиотечки с примерами и разбором, это будет полезно и довольно интересно, а так…

PS. мне больше нравится python-twitter :)
0
Voldar #
Я описал то, чем пользовался. Еще использую эту библиотеку, чтобы вытаскивать твиты по хеш-тегу и показывать на сайте. Но это делается в три строки и врядли будет интересно хоть кому-то. Остальные функции мне (пока) не требовались — я же не твиттер-клиент пишу :)
0
Kastrulya0001 #
А не подскажете для вордпресса есть какой-нибудь плагин для этого? *найти не удалось.
0
Voldar #
Насчет плагина незнаю. Посмотрите библиотеки для php вот тут — apiwiki.twitter.com/Libraries#PHP, думаю на их основе не сложно плагин написать
0
vonabur #
Мы используем еще более простой путь — просто цепляем рсс-ку )
они так или иначе делаются, и не надо мудрить ни с oauth, ни с чем-то еще.
0
piumosso #
Можно подробнее?
0
vonabur #
twitterfeed.com/ — ему можно скормить рсс с сайта, и дать логин-пароль к твиттеру.
0
Mobby #
Помоему с помощью feedburner можно сделать ещё проще и легче.
Publicize -> Socialize
–8
pvasili #
Это успiх.
В Drupal штук 5 плагинов для этого уже дано существует.
+2
bosha #
Вы ошиблись темой.
–6
pvasili #
Да нет, я просто удивлен, что в движке не реализованы такие очевидные и примитивные вещи.
0
bosha #
Это не движок. Это Framework. Это разные вещи.
–7
pvasili #
Ну не стоит меня учить разнице в терминологии ;)…
Нет — значит нет.
0
lol2Fast4U #
что ты курил?
на Django ТЫ пишешь все приложение САМ, Drupal — готовый движок.
–2
pvasili #
Понял, с такими «спецами» лучше не дискутировать ;)
+1
habracut #
Немного оффтоп, но всё же.
Насчет вот этого
                instance.tweeted = True
                instance.save()


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

               Post.objects.filter(pk=instance.pk).update(tweeted = True) 

В итоге имеем «точечный» update, который к тому же исключает гипотетическую рекурсию.
0
Voldar #
Про возможную рекурсию я знаю, но здесь она возникнуть не может, поэтому не заморачивался. Но в целом ваш вариант красивее и аккуратнее, спасибо за подсказку. Поправил пост.

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