Permalink
Browse files

Merge pull request #29 from aptivate/master

Make disqus_dev tag set disqus_url to full URL for page.
  • Loading branch information...
2 parents 4b65423 + 51eb9e0 commit 173f01fc78a3cdd18f3129a102b1322ef8f54628 @derekjamescurtis derekjamescurtis committed Jul 17, 2014
Showing with 131 additions and 71 deletions.
  1. +1 −1 .gitmodules
  2. +80 −53 disqus/templatetags/disqus_tags.py
  3. +50 −17 disqus/tests.py
View
@@ -1,3 +1,3 @@
[submodule "docs/_build/html"]
path = docs/_build/html
- url = git@github.com:arthurk/django-disqus.git
+ url = git://github.com/arthurk/django-disqus.git
@@ -1,3 +1,9 @@
+import base64
+import hashlib
+import hmac
+import simplejson
+import time
+
from django import template
from django.conf import settings
from django.contrib.sites.models import Site
@@ -6,78 +12,106 @@
register = template.Library()
-class ContextSetterNode(template.Node):
- def __init__(self, var_name, var_value):
- self.var_name = var_name
- self.var_value = var_value
-
- def _get_value(self, value, context):
- """
- Attempts to resolve the value as a variable. Failing that, it returns
- its actual value
- """
- try:
- var_value = template.Variable(value).resolve(context)
- except template.VariableDoesNotExist:
- var_value = self.var_value.var
- return var_value
-
- def render(self, context):
- if isinstance(self.var_value, (list, tuple)):
- var_value = ''.join([force_unicode(self._get_value(x, context)) for x in self.var_value])
- else:
- var_value = self._get_value(self.var_value, context)
- context[self.var_name] = var_value
- return ''
-
-def generic_setter_compiler(var_name, name, node_class, parser, token):
- """
- Returns a ContextSetterNode.
-
- For calls like {% set_this_value "My Value" %}
- """
- bits = token.split_contents()
- if(len(bits) < 2):
- message = "%s takes at least one argument" % name
- raise template.TemplateSyntaxError(message)
- return node_class(var_name, bits[1:])
-
# Set the disqus_developer variable to 0/1. Default is 0
-set_disqus_developer = curry(generic_setter_compiler, 'disqus_developer', 'set_disqus_developer', ContextSetterNode)
+@register.simple_tag(takes_context=True)
+def set_disqus_developer(context, disqus_developer):
+ context['disqus_developer'] = disqus_developer
+ return ""
# Set the disqus_identifier variable to some unique value. Defaults to page's URL
-set_disqus_identifier = curry(generic_setter_compiler, 'disqus_identifier', 'set_disqus_identifier', ContextSetterNode)
+@register.simple_tag(takes_context=True)
+def set_disqus_identifier(context, *args):
+ context['disqus_identifier'] = "".join(args)
+ return ""
# Set the disqus_url variable to some value. Defaults to page's location
-set_disqus_url = curry(generic_setter_compiler, 'disqus_url', 'set_disqus_url', ContextSetterNode)
+@register.simple_tag(takes_context=True)
+def set_disqus_url(context, *args):
+ context['disqus_url'] = "".join(args)
+ return ""
# Set the disqus_title variable to some value. Defaults to page's title or URL
-set_disqus_title = curry(generic_setter_compiler, 'disqus_title', 'set_disqus_title', ContextSetterNode)
+@register.simple_tag(takes_context=True)
+def set_disqus_title(context, disqus_title):
+ context['disqus_title'] = disqus_title
+ return ""
+
+# Set the disqus_category_id variable to some value. No default. See
+# http://help.disqus.com/customer/portal/articles/472098-javascript-configuration-variables#disqus_category_id
+@register.simple_tag(takes_context=True)
+def set_disqus_category_id(context, disqus_category_id):
+ context['disqus_category_id'] = disqus_category_id
+ return ""
def get_config(context):
"""
return the formatted javascript for any disqus config variables
"""
- conf_vars = ['disqus_developer', 'disqus_identifier', 'disqus_url', 'disqus_title']
+ conf_vars = ['disqus_developer', 'disqus_identifier', 'disqus_url',
+ 'disqus_title', 'disqus_category_id']
output = []
for item in conf_vars:
if item in context:
output.append('\tvar %s = "%s";' % (item, context[item]))
return '\n'.join(output)
-def disqus_dev():
+@register.simple_tag(takes_context=True)
+def disqus_dev(context):
"""
Return the HTML/js code to enable DISQUS comments on a local
development server if settings.DEBUG is True.
"""
if settings.DEBUG:
return """<script type="text/javascript">
var disqus_developer = 1;
- var disqus_url = '//%s/';
-</script>""" % Site.objects.get_current().domain
+ var disqus_url = '//%s%s';
+</script>""" % (Site.objects.get_current().domain, context['request'].path)
return ""
+@register.simple_tag(takes_context=True)
+def disqus_sso(context):
+ """
+ Return the HTML/js code to enable DISQUS SSO - so logged in users on
+ your site can be logged in to disqus seemlessly.
+ """
+ # we have to make it str rather than unicode or the HMAC blows up
+ DISQUS_SECRET_KEY = str(getattr(settings, 'DISQUS_SECRET_KEY', None))
+ if DISQUS_SECRET_KEY is None:
+ return "<p>You need to set DISQUS_SECRET_KEY before you can use SSO</p>"
+ DISQUS_PUBLIC_KEY = getattr(settings, 'DISQUS_PUBLIC_KEY', None)
+ if DISQUS_PUBLIC_KEY is None:
+ return "<p>You need to set DISQUS_PUBLIC_KEY before you can use SSO</p>"
+ user = context['user']
+ if user.is_anonymous():
+ return ""
+ # create a JSON packet of our data attributes
+ data = simplejson.dumps({
+ 'id': user.id,
+ 'username': user.username,
+ 'email': user.email,
+ })
+ # encode the data to base64
+ message = base64.b64encode(data)
+ # generate a timestamp for signing the message
+ timestamp = int(time.time())
+ # generate our hmac signature
+ sig = hmac.HMAC(DISQUS_SECRET_KEY, '%s %s' % (message, timestamp), hashlib.sha1).hexdigest()
+
+ # return a script tag to insert the sso message
+ return """<script type="text/javascript">
+var disqus_config = function() {
+this.page.remote_auth_s3 = "%(message)s %(sig)s %(timestamp)s";
+this.page.api_key = "%(pub_key)s";
+}
+</script>""" % dict(
+ message=message,
+ timestamp=timestamp,
+ sig=sig,
+ pub_key=DISQUS_PUBLIC_KEY,
+ )
+
+@register.inclusion_tag('disqus/num_replies.html', takes_context=True)
def disqus_num_replies(context, shortname=''):
"""
Return the HTML/js code which transforms links that end with an
@@ -90,6 +124,7 @@ def disqus_num_replies(context, shortname=''):
'config': get_config(context),
}
+@register.inclusion_tag('disqus/recent_comments.html', takes_context=True)
def disqus_recent_comments(context, shortname='', num_items=5, excerpt_length=200, hide_avatars=0, avatar_size=32):
"""
Return the HTML/js code which shows recent comments.
@@ -106,6 +141,7 @@ def disqus_recent_comments(context, shortname='', num_items=5, excerpt_length=20
'config': get_config(context),
}
+@register.inclusion_tag('disqus/show_comments.html', takes_context=True)
def disqus_show_comments(context, shortname=''):
"""
Return the HTML code to display DISQUS comments.
@@ -115,12 +151,3 @@ def disqus_show_comments(context, shortname=''):
'shortname': shortname,
'config': get_config(context),
}
-
-register.tag('set_disqus_developer', set_disqus_developer)
-register.tag('set_disqus_identifier', set_disqus_identifier)
-register.tag('set_disqus_url', set_disqus_url)
-register.tag('set_disqus_title', set_disqus_title)
-register.simple_tag(disqus_dev)
-register.inclusion_tag('disqus/num_replies.html', takes_context=True)(disqus_num_replies)
-register.inclusion_tag('disqus/recent_comments.html', takes_context=True)(disqus_recent_comments)
-register.inclusion_tag('disqus/show_comments.html', takes_context=True)(disqus_show_comments)
View
@@ -1,28 +1,61 @@
+import unittest
+
from django.conf import settings
+settings.configure()
+
+from django.contrib.sites.models import Site
from django.core.management.base import CommandError
+from django.test.utils import override_settings
+from unittest import TestCase
from disqus.api import DisqusClient
+from disqus.templatetags.disqus_tags import disqus_dev
+
+
+class FakeRequest(object):
+ def __init__(self, path):
+ self.path = path
+
+
+# mock Site
+class FakeSiteManager(object):
+ def __init__(self, domain, name):
+ self.site = Site(domain=domain, name=name)
+
+ def get_current(self):
+ return self.site
+
-__test__ = {'API_TESTS': """
+class DisqusTest(TestCase):
-First, we test if the DisqusClient class can be initialized
-and parameters that were passed are set correctly.
+ def setUp(self):
+ self.real_sites_manager = Site.objects
->>> c = DisqusClient(foo='bar', bar='foo')
->>> c.foo
-'bar'
->>> c.bar
-'foo'
->>> c.baz
-Traceback (most recent call last):
- ...
-AttributeError
+ def tearDown(self):
+ Site.objects = self.real_sites_manager
+ def test_client_init(self):
+ """
+ First, we test if the DisqusClient class can be initialized
+ and parameters that were passed are set correctly.
+ """
-When a DISQUS API method is called, the call method should be used.
+ c = DisqusClient(foo='bar', bar='foo')
+ self.assertEqual('bar', c.foo)
+ self.assertEqual('foo', c.bar)
+ with self.assertRaises(AttributeError):
+ c.baz
->>> c.get_forum_list
-<function call_method at ...>
-""",
-}
+ def test_disqus_dev_sets_full_url(self):
+ test_domain = 'example.org'
+ url_path = '/path/to/page'
+ full_url = 'http://%s%s' % (test_domain, url_path)
+ context = {'request': FakeRequest(path=url_path)}
+ # mock out Site manager
+ Site.objects = FakeSiteManager(test_domain, 'test')
+ with override_settings(DEBUG=True):
+ generated_html = disqus_dev(context)
+ self.assertIn(full_url, generated_html)
+if __name__ == '__main__':
+ unittest.main()

0 comments on commit 173f01f

Please sign in to comment.