summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--askbot/conf/minimum_reputation.py15
-rw-r--r--askbot/deps/django_authopenid/util.py12
-rw-r--r--askbot/doc/source/changelog.rst1
-rw-r--r--askbot/models/__init__.py8
-rw-r--r--askbot/models/post.py31
-rw-r--r--askbot/models/signals.py3
-rw-r--r--askbot/tasks.py26
-rw-r--r--askbot/utils/twitter.py12
-rw-r--r--askbot/views/writers.py5
9 files changed, 100 insertions, 13 deletions
diff --git a/askbot/conf/minimum_reputation.py b/askbot/conf/minimum_reputation.py
index 94d5869e..3d0fa1cd 100644
--- a/askbot/conf/minimum_reputation.py
+++ b/askbot/conf/minimum_reputation.py
@@ -230,9 +230,16 @@ settings.register(
'MIN_REP_TO_TRIGGER_EMAIL',
default=15,
description=_('Trigger email notifications'),
- help_text=_(
- 'Reduces spam as notifications wont\'t be sent '
- 'to regular users for posts of low karma users'
- )
+ help_text=_('Reduces spam')
+ )
+)
+
+settings.register(
+ livesettings.IntegerValue(
+ MIN_REP,
+ 'MIN_REP_TO_TWEET_ON_OTHERS_ACCOUNTS',
+ default=15,
+ description=_('Trigger tweets on others accounts'),
+ help_text=_('Reduces spam')
)
)
diff --git a/askbot/deps/django_authopenid/util.py b/askbot/deps/django_authopenid/util.py
index 03e70922..6e19db6a 100644
--- a/askbot/deps/django_authopenid/util.py
+++ b/askbot/deps/django_authopenid/util.py
@@ -757,14 +757,18 @@ class OAuthConnection(object):
def get_token(self):
return self.request_token
- def get_access_token(self, oauth_token=None, oauth_verifier=None):
- """returns data as returned upon visiting te access_token_url"""
+ def get_client(self, oauth_token=None, oauth_verifier=None):
token = oauth.Token(
oauth_token['oauth_token'],
oauth_token['oauth_token_secret']
)
- token.set_verifier(oauth_verifier)
- client = oauth.Client(self.consumer, token = token)
+ if oauth_verifier:
+ token.set_verifier(oauth_verifier)
+ return oauth.Client(self.consumer, token=token)
+
+ def get_access_token(self, oauth_token=None, oauth_verifier=None):
+ """returns data as returned upon visiting te access_token_url"""
+ client = self.get_client(self, oauth_token, oauth_verifier)
url = self.parameters['access_token_url']
#there must be some provider-specific post-processing
return self.send_request(client = client, url=url, method='GET')
diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst
index 0e5b3c32..faedeebf 100644
--- a/askbot/doc/source/changelog.rst
+++ b/askbot/doc/source/changelog.rst
@@ -3,6 +3,7 @@ Changes in Askbot
Development version
-------------------
+* Auto-tweet option for questions and answers
* Added Chech and Croatian translations
* Disable/enable best answer feature
* Allowed post owners repost answers and comments (this used to be mod-only function).
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index 9378b6c4..b31d9b5d 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -3690,6 +3690,12 @@ def moderate_group_joining(sender, instance=None, created=False, **kwargs):
content_object = group
)
+def tweet_new_post(sender, user=None, question=None, answer=None, form_data=None, **kwargs):
+ """seends out tweets about the new post"""
+ from askbot.tasks import tweet_new_post_task
+ post = question or answer
+ tweet_new_post_task.delay(post.id)
+
#signal for User model save changes
django_signals.pre_save.connect(make_admin_if_first_user, sender=User)
django_signals.pre_save.connect(calculate_gravatar_hash, sender=User)
@@ -3721,6 +3727,8 @@ signals.user_updated.connect(record_user_full_updated, sender=User)
signals.user_logged_in.connect(complete_pending_tag_subscriptions)#todo: add this to fake onlogin middleware
signals.user_logged_in.connect(post_anonymous_askbot_content)
signals.post_updated.connect(record_post_update_activity)
+signals.new_answer_posted.connect(tweet_new_post)
+signals.new_question_posted.connect(tweet_new_post)
#probably we cannot use post-save here the point of this is
#to tell when the revision becomes publicly visible, not when it is saved
diff --git a/askbot/models/post.py b/askbot/models/post.py
index 42905f65..2f410b27 100644
--- a/askbot/models/post.py
+++ b/askbot/models/post.py
@@ -404,6 +404,21 @@ class Post(models.Model):
if number:
self.points = int(number)
+ def as_tweet(self):
+ """a naive tweet representation of post
+ todo: add mentions to relevant people
+ """
+ url = self.get_absolute_url(no_slug=True)
+ url = askbot_settings.APP_URL + url
+ if self.post_type == 'question':
+ tweet = _('Question: ')
+ elif self.post_type == 'answer':
+ tweet = _('Answer: ')
+
+ chars_left = 140 - (len(url) + len(tweet) + 1)
+ title_str = self.thread.title[:chars_left]
+ return tweet + title_str + ' ' + url
+
def parse_post_text(self):
"""typically post has a field to store raw source text
in comment it is called .comment, in Question and Answer it is
@@ -785,11 +800,17 @@ class Post(models.Model):
if self.is_answer():
if not question_post:
question_post = self.thread._question_post()
- url = u'%(base)s%(slug)s/?answer=%(id)d#post-id-%(id)d' % {
- 'base': urlresolvers.reverse('question', args=[question_post.id]),
- 'slug': django_urlquote(slugify(self.thread.title)),
- 'id': self.id
- }
+ if no_slug:
+ url = u'%(base)s?answer=%(id)d#post-id-%(id)d' % {
+ 'base': urlresolvers.reverse('question', args=[question_post.id]),
+ 'id': self.id
+ }
+ else:
+ url = u'%(base)s%(slug)s/?answer=%(id)d#post-id-%(id)d' % {
+ 'base': urlresolvers.reverse('question', args=[question_post.id]),
+ 'slug': django_urlquote(slugify(self.thread.title)),
+ 'id': self.id
+ }
elif self.is_question():
url = urlresolvers.reverse('question', args=[self.id])
if thread:
diff --git a/askbot/models/signals.py b/askbot/models/signals.py
index f5187876..303db2a2 100644
--- a/askbot/models/signals.py
+++ b/askbot/models/signals.py
@@ -28,6 +28,9 @@ user_logged_in = django.dispatch.Signal(providing_args=['session'])
new_answer_posted = django.dispatch.Signal(
providing_args=['answer', 'user', 'form_data']
)
+new_question_posted = django.dispatch.Signal(
+ providing_args=['question', 'user', 'form_data']
+)
answer_edited = django.dispatch.Signal(
providing_args=['answer', 'user', 'form_data']
)
diff --git a/askbot/tasks.py b/askbot/tasks.py
index 92cd9a1d..8d98be2c 100644
--- a/askbot/tasks.py
+++ b/askbot/tasks.py
@@ -26,6 +26,7 @@ from django.contrib.contenttypes.models import ContentType
from django.template import Context
from django.template.loader import get_template
from django.utils.translation import ugettext as _
+from django.utils import simplejson
from celery.decorators import task
from askbot.conf import settings as askbot_settings
from askbot import const
@@ -34,10 +35,35 @@ from askbot.models import Post, Thread, User, ReplyAddress
from askbot.models.badges import award_badges_signal
from askbot.models import get_reply_to_addresses, format_instant_notification_email
from askbot import exceptions as askbot_exceptions
+from askbot.utils.twitter import Twitter
# TODO: Make exceptions raised inside record_post_update_celery_task() ...
# ... propagate upwards to test runner, if only CELERY_ALWAYS_EAGER = True
# (i.e. if Celery tasks are not deferred but executed straight away)
+@task(ignore_result=True)
+def tweet_new_post_task(post_id):
+ post = Post.objects.get(id=post_id)
+
+ is_mod = post.author.is_administrator_or_moderator()
+ if is_mod or post.author.reputation > askbot_settings.MIN_REP_TO_TWEET_ON_OTHERS_ACCOUNTS:
+ tweeters = User.objects.filter(social_sharing_mode=const.SHARE_EVERYTHING)
+ tweeters = tweeters.exclude(id=post.author.id)
+ access_tokens = tweeters.values_list('twitter_access_token', flat=True)
+ else:
+ access_tokens = list()
+
+ tweet_text = post.as_tweet()
+
+ twitter = Twitter()
+
+ for raw_token in access_tokens:
+ token = simplejson.loads(raw_token)
+ twitter.tweet(tweet_text, access_token=token)
+
+ if post.author.social_sharing_mode != const.SHARE_NOTHING:
+ token = simplejson.loads(post.author.twitter_access_token)
+ twitter.tweet(tweet_text, access_token=token)
+
@task(ignore_result = True)
def notify_author_of_published_revision_celery_task(revision):
diff --git a/askbot/utils/twitter.py b/askbot/utils/twitter.py
new file mode 100644
index 00000000..1eba6147
--- /dev/null
+++ b/askbot/utils/twitter.py
@@ -0,0 +1,12 @@
+import urllib
+from askbot.deps.django_authopenid.util import OAuthConnection
+
+class Twitter(OAuthConnection):
+ def __init__(self):
+ super(Twitter, self).__init__('twitter')
+ self.tweet_url = 'https://api.twitter.com/1.1/statuses/update.json'
+
+ def tweet(self, text, access_token=None):
+ client = self.get_client(access_token)
+ body = urllib.urlencode({'status': text})
+ return self.send_request(client, self.tweet_url, 'POST', body=body)
diff --git a/askbot/views/writers.py b/askbot/views/writers.py
index 4afd66cf..b3dd2b32 100644
--- a/askbot/views/writers.py
+++ b/askbot/views/writers.py
@@ -252,6 +252,11 @@ def ask(request):#view used to ask a new question
group_id=group_id,
language=language
)
+ signals.new_question_posted.send(None,
+ question=question,
+ user=user,
+ form_data=form.cleaned_data
+ )
return HttpResponseRedirect(question.get_absolute_url())
except exceptions.PermissionDenied, e:
request.user.message_set.create(message = unicode(e))