disqus 0.1.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ module Disqus
2
+
3
+ class BaseAuthor
4
+ attr_reader :url, :email_hash
5
+ end
6
+
7
+ class Author < BaseAuthor
8
+ attr_reader :id, :username, :display_name, :has_avatar
9
+ def initialize(id, username, display_name, url, email_hash, has_avatar)
10
+ @id, @username, @display_name, @url, @email_hash, @has_avatar = id, username, display_name, url, email_hash, has_avatar
11
+ end
12
+
13
+ # Returns the user's <tt>display_name</tt> or <tt>username</tt> if <tt>display_name</tt> is blank.
14
+ def name
15
+ @display_name.blank? ? @username : @display_name
16
+ end
17
+
18
+ end
19
+
20
+ class AnonymousAuthor < BaseAuthor
21
+ attr_reader :name
22
+ def initialize(name, url, email_hash)
23
+ @name, @url, @email_hash = name, url, email_hash
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,126 @@
1
+ module Disqus
2
+
3
+ class Forum
4
+ attr_reader :id, :shortname, :name, :created_at, :threads
5
+
6
+ def initialize(id, shortname, name, created_at, include_threads = false)
7
+ @id, @shortname, @name, @created_at = id.to_i, shortname, name, Time.parse(created_at.to_s)
8
+ @key = nil
9
+ @forum_threads = include_threads ? load_threads : []
10
+ end
11
+
12
+ def ==(other_forum)
13
+ id == other_forum.id &&
14
+ shortname == other_forum.shortname &&
15
+ name == other_forum.name &&
16
+ key == other_forum.key
17
+ end
18
+
19
+ # Returns an array of Forum objects belonging to the user indicated by the API key.
20
+ def self.list(user_api_key = nil)
21
+ opts = user_api_key ? {:api_key => user_api_key} : {}
22
+ response = Disqus::Api::get_forum_list(opts)
23
+ if response["succeeded"]
24
+ return response["message"].map{|forum| Forum.new(forum["id"], forum["shortname"], forum["name"], forum["created_at"])}
25
+ else
26
+ raise_api_error(response)
27
+ end
28
+ end
29
+
30
+ # Returns a Forum object corresponding to the given forum_id or nil if it was not found.
31
+ def self.find(forum_id, user_api_key = nil)
32
+ opts = user_api_key ? {:api_key => user_api_key} : {}
33
+ list = Forum.list(opts)
34
+ if list
35
+ list.select{|f| f.id == forum_id}.first
36
+ end
37
+ end
38
+
39
+ # Returns the forum API Key for this forum.
40
+ def key(user_api_key = nil)
41
+ @key ||= load_key(user_api_key)
42
+ end
43
+
44
+ # Returns an array of threads belonging to this forum.
45
+ def forum_threads(force_update = false)
46
+ if (@forum_threads.nil? or @forum_threads.empty? or force_update)
47
+ @forum_threads = Disqus::Thread.list(self)
48
+ end
49
+ @forum_threads
50
+ end
51
+
52
+ # Returns a thread associated with the given URL.
53
+ #
54
+ # A thread will only have an associated URL if it was automatically
55
+ # created by Disqus javascript embedded on that page.
56
+ def get_thread_by_url(url)
57
+ response = Disqus::Api::get_thread_by_url(:url => url, :forum_api_key => key)
58
+ if response["succeeded"]
59
+ t = response["message"]
60
+ Thread.new(t["id"], self, t["slug"], t["title"], t["created_at"], t["allow_comments"], t["url"], t["identifier"])
61
+ else
62
+ raise_api_error(response)
63
+ end
64
+ end
65
+
66
+ # Create or retrieve a thread by an arbitrary identifying string of your
67
+ # choice. For example, you could use your local database's ID for the
68
+ # thread. This method allows you to decouple thread identifiers from the
69
+ # URL's on which they might be appear. (Disqus would normally use a
70
+ # thread's URL to identify it, which is problematic when URL's do not
71
+ # uniquely identify a resource.) If no thread exists for the given
72
+ # identifier (paired with the forum) yet, one will be created.
73
+ #
74
+ # Returns a Thread object representing the thread that was created or
75
+ # retrieved.
76
+ def thread_by_identifier(identifier, title)
77
+ # TODO - should we separate thread retrieval from thread creation? The API to me seems confusing here.
78
+ response = Disqus::Api::thread_by_identifier(:identifier => identifier, :title => title, :forum_api_key => key)
79
+ if response["succeeded"]
80
+ t = response["message"]["thread"]
81
+ Thread.new(t["id"], self, t["slug"], t["title"], t["created_at"], t["allow_comments"], t["url"], t["identifier"])
82
+ else
83
+ raise_api_error(response)
84
+ end
85
+ end
86
+
87
+ # Sets the provided values on the thread object.
88
+ #
89
+ # Returns an empty success message.
90
+ #
91
+ # Options:
92
+ #
93
+ # * <tt>:title</tt> - the title of the thread
94
+ # * <tt>:slug</tt> - the per-forum-unique string used for identifying this thread in disqus.com URL's relating to this thread. Composed of underscore-separated alphanumeric strings.
95
+ # * <tt>:url</tt> - the URL this thread is on, if known.
96
+ # * <tt>:allow_comment</tt> - whether this thread is open to new comments
97
+ def update_thread(thread_id, opts = {})
98
+ result = Disqus::Api::update_thread(
99
+ :forum_api_key => key,
100
+ :thread_id => thread_id,
101
+ :title => opts[:title],
102
+ :slug => opts[:slug],
103
+ :url => opts[:url],
104
+ :allow_comments => opts[:allow_comments]
105
+ )
106
+ return result["succeeded"]
107
+ end
108
+
109
+ private
110
+
111
+ def raise_api_error(response)
112
+ raise "Error: #{response['code']}: #{response['message']}"
113
+ end
114
+
115
+ def load_key(user_api_key = nil)
116
+ opts = user_api_key ? {:api_key => user_api_key} : {}
117
+ response = Disqus::Api::get_forum_api_key(opts.merge(:forum_id => self.id))
118
+ if response["succeeded"]
119
+ return @key = response["message"]
120
+ else
121
+ raise_api_error(response)
122
+ end
123
+ end
124
+
125
+ end
126
+ end
@@ -0,0 +1,51 @@
1
+ module Disqus
2
+
3
+ class Post
4
+ attr_reader :id, :forum, :thread, :created_at, :message, :parent_post, :shown, :is_anonymous, :author
5
+
6
+ def initialize(id, forum, thread, created_at, message, parent_post, shown, is_anonymous, author)
7
+ @id, @forum, @thread, @created_at, @message, @parent_post, @shown, @is_anonymous, @author = id.to_i, forum, thread, Time.parse(created_at.to_s), message, parent_post, shown, is_anonymous, author
8
+ end
9
+
10
+ # Returns an array of Post objects representing all posts belonging to the
11
+ # given thread. The array is sorted by the "created_at" date descending.
12
+ def self.list(thread)
13
+ response = Disqus::Api::get_thread_posts(:thread_id =>thread.id, :forum_api_key => thread.forum.key)
14
+ if response["succeeded"]
15
+ posts = response["message"].map do |post|
16
+ author = nil
17
+ if post["is_anonymous"]
18
+ author = AnonymousAuthor.new(
19
+ post["anonymous_author"]["name"],
20
+ post["anonymous_author"]["url"],
21
+ post["anonymous_author"]["email_hash"]
22
+ )
23
+ else
24
+ author = Author.new(
25
+ post["author"]["id"].to_i,
26
+ post["author"]["username"],
27
+ post["author"]["display_name"],
28
+ post["author"]["url"],
29
+ post["author"]["email_hash"],
30
+ post["author"]["has_avatar"]
31
+ )
32
+ end
33
+ Post.new(
34
+ post["id"],
35
+ thread.forum,
36
+ thread,
37
+ post["created_at"],
38
+ post["message"],
39
+ post["parent_post"],
40
+ post["shown"],
41
+ post["is_anonymous"],
42
+ author
43
+ )
44
+ end
45
+ posts.sort!{|a,b| a.created_at <=> b.created_at}
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+
@@ -0,0 +1,73 @@
1
+ module Disqus
2
+
3
+ class Thread
4
+ attr_reader :id, :forum, :slug, :title, :created_at, :allow_comments, :url, :identifier, :forum
5
+
6
+ def initialize(id, forum, slug, title, created_at, allow_comments, url, identifier)
7
+ @id, @forum, @slug, @title, @created_at, @allow_comments, @url, @identifier = id.to_i, forum, slug, title, Time.parse(created_at.to_s), allow_comments, url, identifier
8
+ @posts = []
9
+ end
10
+
11
+ # Threads are equal if all their attributes are equal.
12
+ def ==(other_thread)
13
+ id == other_thread.id &&
14
+ forum == other_thread.forum &&
15
+ slug == other_thread.slug &&
16
+ title == other_thread.title &&
17
+ created_at == other_thread.created_at &&
18
+ allow_comments == other_thread.allow_comments &&
19
+ url == other_thread.url &&
20
+ identifier == other_thread.identifier
21
+ end
22
+
23
+ # Returns an array of Thread objects representing the threads belonging to the given Forum.
24
+ def self.list(forum, opts = {})
25
+ response = Disqus::Api::get_thread_list(opts.merge(:forum_id =>forum.id, :forum_api_key => forum.key))
26
+ if response["succeeded"]
27
+ list = response["message"].map do |thread|
28
+ Thread.new(
29
+ thread["id"],
30
+ forum,
31
+ thread["slug"],
32
+ thread["title"],
33
+ thread["created_at"],
34
+ thread["allow_comments"],
35
+ thread["url"],
36
+ thread["identifier"]
37
+ )
38
+ end
39
+ end
40
+ end
41
+
42
+ # Returns an array of posts belonging to this thread.
43
+ def posts(force_update = false)
44
+ if (@posts.nil? or @posts.empty? or force_update)
45
+ @posts = Disqus::Post.list(self)
46
+ end
47
+ @posts
48
+ end
49
+
50
+ # Sets the provided values on the thread object.
51
+ #
52
+ # Options:
53
+ #
54
+ # * :thread_id
55
+ # * :title
56
+ # * :slug
57
+ # * :url
58
+ # * :allow_comments
59
+ def update(opts = {})
60
+ result = Disqus::Api::update_thread(opts.merge(
61
+ :forum_api_key => forum.key,
62
+ :thread_id => id,
63
+ :title => title,
64
+ :slug => slug,
65
+ :url => url,
66
+ :allow_comments => allow_comments)
67
+ )
68
+ return result["succeeded"]
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,8 @@
1
+ module Disqus #:nodoc:
2
+ module Version #:nodoc:
3
+ MAJOR = 1
4
+ MINOR = 0
5
+ TINY = 0
6
+ STRING = [MAJOR, MINOR, TINY].join('.')
7
+ end
8
+ end
data/lib/disqus/widget.rb CHANGED
@@ -59,15 +59,15 @@ module Disqus
59
59
  <script type="text/javascript">
60
60
  //<[CDATA[
61
61
  (function() {
62
- var links = document.getElementsByTagName('a');
63
- var query = '?';
64
- for(var i = 0; i < links.length; i++) {
65
- if(links[i].href.indexOf('#disqus_thread') >= 0) {
66
- query += 'url' + i + '=' + encodeURIComponent(links[i].href) + '&';
67
- }
68
- }
69
- document.write('<script type="text/javascript" src="#{ROOT_PATH}get_num_replies.js' + query + '"></' + 'script>');
70
- })();
62
+ var links = document.getElementsByTagName('a');
63
+ var query = '?';
64
+ for(var i = 0; i < links.length; i++) {
65
+ if(links[i].href.indexOf('#disqus_thread') >= 0) {
66
+ query += 'url' + i + '=' + encodeURIComponent(links[i].href) + '&';
67
+ }
68
+ }
69
+ document.write('<' + 'script type="text/javascript" src="#{ROOT_PATH}get_num_replies.js' + query + '"></' + 'script>');
70
+ })();
71
71
  //]]>
72
72
  </script>
73
73
  WHIMPER
data/tasks/rcov.rake ADDED
@@ -0,0 +1,23 @@
1
+ desc "Run RCov"
2
+ task :rcov do
3
+ run_coverage Dir["test/**/*_test.rb"]
4
+ end
5
+
6
+ def run_coverage(files)
7
+ rm_f "coverage"
8
+ rm_f "coverage.data"
9
+ if files.length == 0
10
+ puts "No files were specified for testing"
11
+ return
12
+ end
13
+ files = files.join(" ")
14
+ if PLATFORM =~ /darwin/
15
+ exclude = '--exclude "gems/"'
16
+ else
17
+ exclude = '--exclude "rubygems"'
18
+ end
19
+ rcov = "rcov -Ilib:test --sort coverage --text-report #{exclude} --no-validator-links"
20
+ cmd = "#{rcov} #{files}"
21
+ puts cmd
22
+ sh cmd
23
+ end
data/test/api_test.rb ADDED
@@ -0,0 +1,80 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ApiTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ require 'disqus'
7
+ Disqus.defaults[:api_key] = DISQUS_TEST["api_key"]
8
+ end
9
+
10
+ def test_create_post
11
+ mock_post_response('create_post.json')
12
+ the_post = Disqus::Api::create_post()
13
+ assert_equal "This is a mock post", the_post["message"]["message"]
14
+ end
15
+
16
+ def test_get_forum_list
17
+ mock_get_response('get_forum_list.json')
18
+ forum_list = Disqus::Api::get_forum_list
19
+ assert_equal "Disqus Test", forum_list["message"][0]["name"]
20
+ end
21
+
22
+ def test_get_forum_api_key
23
+ mock_get_response('get_forum_api_key.json')
24
+ forum_api_key = Disqus::Api::get_forum_api_key(:forum_id => 1234, :user_api_key=>"FAKE_KEY")
25
+ assert_equal "FAKE_FORUM_API_KEY", forum_api_key["message"]
26
+ end
27
+
28
+ def test_get_thread_list
29
+ mock_get_response('get_thread_list.json')
30
+ thread_list = Disqus::Api::get_thread_list(:forum_api_key=>"FAKE_KEY")
31
+ assert_equal "this_is_the_thread_identifier", thread_list["message"].first["identifier"]
32
+ end
33
+
34
+ def test_get_num_posts
35
+ mock_get_response('get_num_posts.json')
36
+ nums = Disqus::Api::get_num_posts(:thread_ids => [123,456], :forum_api_key=>"FAKE_KEY")
37
+ assert_equal [10,12], nums["message"][nums["message"].keys.first]
38
+ end
39
+
40
+ def test_get_thread_by_url
41
+ mock_get_response('get_thread_by_url.json')
42
+ thread = Disqus::Api::get_thread_by_url(:url => "FAKE_URL", :forum_api_key=>"FAKE_KEY")
43
+ assert_equal "test_thread", thread["message"]["slug"]
44
+ end
45
+
46
+ def test_get_thread_posts
47
+ mock_get_response('get_thread_posts.json')
48
+ thread_posts = Disqus::Api::get_thread_posts(:thread_id =>1234, :forum_api_key => "FAKE_KEY")
49
+ assert_equal "This is a mock post", thread_posts["message"].first["message"]
50
+ end
51
+
52
+ def test_thread_by_identifier
53
+ mock_post_response('thread_by_identifier.json')
54
+ thread = Disqus::Api::thread_by_identifier(:identifier =>'foo_bar', :title => "Foo Bar", :forum_api_key => "FAKE_KEY")
55
+ assert_equal "Test thread", thread["message"]["thread"]["title"]
56
+ end
57
+
58
+ def test_update_thread
59
+ mock_post_response('update_thread.json')
60
+ result = Disqus::Api::thread_by_identifier(:thread_id =>123, :title => "Foo Bar", :forum_api_key => "FAKE_KEY")
61
+ assert result["succeeded"]
62
+ end
63
+
64
+ def test_comment_form
65
+ c = Disqus::Api::comment_form("myforum", "mythread")
66
+ assert_match(/myforum/, c)
67
+ assert_match(/mythread/, c)
68
+ end
69
+
70
+ private
71
+
72
+ def mock_get_response(file)
73
+ Disqus::Api.expects(:get).returns(File.read(File.dirname(__FILE__) + "/responses/#{file}"))
74
+ end
75
+
76
+ def mock_post_response(file)
77
+ Disqus::Api.expects(:post).returns(File.read(File.dirname(__FILE__) + "/responses/#{file}"))
78
+ end
79
+
80
+ end
data/test/config.yml ADDED
@@ -0,0 +1,3 @@
1
+ # This can be used to do actual calls to the API rather than use mocks during
2
+ # testing. This can be useful to verify tests against API changes.
3
+ api_key: 'YOUR DISQUS USER API KEY GOES HERE'
@@ -0,0 +1,3 @@
1
+ # This can be used to do actual calls to the API rather than use mocks during
2
+ # testing. This can be useful to verify tests against API changes.
3
+ api_key: 'YOUR DISQUS USER API KEY GOES HERE'
@@ -0,0 +1,70 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ForumTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ require 'disqus'
7
+ Disqus.defaults[:api_key] = DISQUS_TEST["api_key"]
8
+ stub_api_call(:get_forum_api_key).returns("FAKE_FORUM_API_KEY")
9
+ end
10
+
11
+ def test_forum_list
12
+ mock_api_call(:get_forum_list)
13
+ list = Disqus::Forum.list
14
+ expected = [create_forum]
15
+ assert_equal 1, list.size
16
+ assert_equal expected, list
17
+ end
18
+
19
+ def test_forum_find
20
+ mock_api_call(:get_forum_list)
21
+ forum = Disqus::Forum.find(1234)
22
+ assert_equal "disqus-test", forum.shortname
23
+ end
24
+
25
+ def test_forum_find_bad_id
26
+ mock_api_call(:get_forum_list)
27
+ forum = Disqus::Forum.find(666)
28
+ assert_equal nil, forum
29
+ end
30
+
31
+ def test_forum_find_no_forums
32
+ Disqus::Api.expects(:get_forum_list).returns({"succeeded"=>true, "code"=>"", "message" => []})
33
+ forum = Disqus::Forum.find(1234)
34
+ assert_equal nil, forum
35
+ end
36
+
37
+ def test_key
38
+ mock_api_call(:get_forum_api_key)
39
+ forum = Disqus::Forum.new(1234, "disqus-test", "Disqus Test", "2008-01-03 14:44:07.627492")
40
+ assert_equal "FAKE_FORUM_API_KEY", forum.key
41
+ end
42
+
43
+ def test_forum_threads
44
+ forum = create_forum
45
+ Disqus::Thread.expects(:list).with(forum).returns([thread = mock()])
46
+ assert_equal [thread], forum.forum_threads
47
+ end
48
+
49
+ def test_get_thread_by_url
50
+ mock_api_call(:get_thread_by_url)
51
+ forum = create_forum
52
+ thread = forum.get_thread_by_url("http://www.example.com")
53
+ expected = Disqus::Thread.new("7651269", forum, "test_thread", "Test thread", "2008-11-28T01:47", true, "FAKE_URL", nil)
54
+ assert_equal expected, thread
55
+ end
56
+
57
+ def test_thread_by_identifier
58
+ mock_api_call(:thread_by_identifier)
59
+ forum = create_forum
60
+ thread = forum.thread_by_identifier("FAKE_IDENTIFIER", "")
61
+ expected = Disqus::Thread.new("7651269", forum, "test_thread", "Test thread", "2008-11-28T01:47", true, "FAKE_URL", "FAKE_IDENTIFIER")
62
+ assert_equal expected, thread
63
+ end
64
+
65
+ def test_update_thread
66
+ Disqus::Api.expects(:update_thread).with({:thread_id => 1234, :forum_api_key => "FAKE_FORUM_API_KEY", :title => 'Title', :slug => "a_slug", :url => "http://www.example.com", :allow_comments => true}).returns({"succeeded" => true})
67
+ forum = create_forum
68
+ forum.update_thread(1234, :title => 'Title', :slug => "a_slug", :url => "http://www.example.com", :allow_comments => true)
69
+ end
70
+ end