From: Magnus Hagander Date: Sat, 9 Dec 2017 15:44:54 +0000 (+0100) Subject: Implement automatic tweeting of news X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=06a48b477c5710bde30a913dc3ae14a549377b0e;p=pgweb.git Implement automatic tweeting of news Once a twitter account has been registered (using the twitter_register management command), the twitter_post command wills start posting all new news to twitter, once they are approved. It will only post news from the past 7 days to avoid accidentally flooding with old news. --- diff --git a/pgweb/news/forms.py b/pgweb/news/forms.py index 281a46e0..6173cc2b 100644 --- a/pgweb/news/forms.py +++ b/pgweb/news/forms.py @@ -17,4 +17,4 @@ class NewsArticleForm(forms.ModelForm): class Meta: model = NewsArticle - exclude = ('submitter', 'approved', ) + exclude = ('submitter', 'approved', 'tweeted') diff --git a/pgweb/news/management/__init__.py b/pgweb/news/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pgweb/news/management/commands/__init__.py b/pgweb/news/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pgweb/news/management/commands/twitter_post.py b/pgweb/news/management/commands/twitter_post.py new file mode 100644 index 00000000..32ffb385 --- /dev/null +++ b/pgweb/news/management/commands/twitter_post.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# +# Script to post previosly unposted news to twitter +# +# + +from django.core.management.base import BaseCommand, CommandError +from django.db import connection, transaction +from django.conf import settings + +from datetime import datetime, timedelta +import time + +from pgweb.news.models import NewsArticle + +import requests_oauthlib + +class Command(BaseCommand): + help = 'Post to twitter' + + def handle(self, *args, **options): + curs = connection.cursor() + curs.execute("SELECT pg_try_advisory_lock(62387372)") + if not curs.fetchall()[0][0]: + raise CommandError("Failed to get advisory lock, existing twitter_post process stuck?") + + articles = list(NewsArticle.objects.filter(tweeted=False, approved=True, date__gt=datetime.now()-timedelta(days=7)).order_by('date')) + if not len(articles): + return + + tw = requests_oauthlib.OAuth1Session(settings.TWITTER_CLIENT, + settings.TWITTER_CLIENTSECRET, + settings.TWITTER_TOKEN, + settings.TWITTER_TOKENSECRET) + + for a in articles: + # We hardcode 30 chars for the URL shortener. And then 10 to cover the intro and spacing. + statusstr = u"News: {0} - {1}/about/news/{2}/".format(a.title[:140-40], settings.SITE_ROOT, a.id) + r = tw.post('https://api.twitter.com/1.1/statuses/update.json', data={ + 'status': statusstr, + }) + if r.status_code != 200: + print("Failed to post to twitter: %s " % r) + else: + a.tweeted = True + a.save() + # Don't post more often than once / 30 seconds, to not trigger flooding. + time.sleep(30) diff --git a/pgweb/news/management/commands/twitter_register.py b/pgweb/news/management/commands/twitter_register.py new file mode 100644 index 00000000..46c100db --- /dev/null +++ b/pgweb/news/management/commands/twitter_register.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# +# Script to register twitter oauth privileges +# +# + +from django.core.management.base import BaseCommand, CommandError +from django.conf import settings + +import requests_oauthlib + +class Command(BaseCommand): + help = 'Register with twitter oauth' + + def handle(self, *args, **options): + if not hasattr(settings, 'TWITTER_CLIENT'): + raise CommandError("TWITTER_CLIENT must be set in settings_local.py") + if not hasattr(settings, 'TWITTER_CLIENTSECRET'): + raise CommandError("TWITTER_CLIENTSECRET must be set in settings_local.py") + if hasattr(settings, 'TWITTER_TOKEN'): + raise CommandError("TWITTER_TOKEN is already set in settings_local.py") + if hasattr(settings, 'TWITTER_TOKENSECRET'): + raise CommandError("TWITTER_TOKENSECRET is already set in settings_local.py") + + # OK, now we're good to go :) + oauth = requests_oauthlib.OAuth1Session(settings.TWITTER_CLIENT, settings.TWITTER_CLIENTSECRET) + fetch_response = oauth.fetch_request_token('https://api.twitter.com/oauth/request_token') + + authorization_url = oauth.authorization_url('https://api.twitter.com/oauth/authorize') + print 'Please go here and authorize: %s' % authorization_url + + pin = raw_input('Paste the PIN here: ') + + oauth = requests_oauthlib.OAuth1Session(settings.TWITTER_CLIENT, + settings.TWITTER_CLIENTSECRET, + resource_owner_key=fetch_response.get('oauth_token'), + resource_owner_secret=fetch_response.get('oauth_token_secret'), + verifier=pin) + oauth_tokens = oauth.fetch_access_token('https://api.twitter.com/oauth/access_token') + + print("Authorized. Please configure:") + print("TWITTER_TOKEN='%s'" % oauth_tokens.get('oauth_token')) + print("TWITTER_TOKENSECRET='%s'" % oauth_tokens.get('oauth_token_secret')) diff --git a/pgweb/news/migrations/0002_news_tweet.py b/pgweb/news/migrations/0002_news_tweet.py new file mode 100644 index 00000000..c4e37373 --- /dev/null +++ b/pgweb/news/migrations/0002_news_tweet.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('news', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='newsarticle', + name='tweeted', + field=models.BooleanField(default=True), + ), + ] diff --git a/pgweb/news/models.py b/pgweb/news/models.py index c382356c..22deee7e 100644 --- a/pgweb/news/models.py +++ b/pgweb/news/models.py @@ -8,6 +8,7 @@ class NewsArticle(models.Model): date = models.DateField(null=False, blank=False, default=date.today) title = models.CharField(max_length=200, null=False, blank=False) content = models.TextField(null=False, blank=False) + tweeted = models.BooleanField(null=False, blank=False, default=False) send_notification = True markdown_fields = ('content',)