norman-disqus-api 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,118 @@
1
+ == Disqus Ruby Gem
2
+
3
+ The Disqus Gem helps you easily integrate the {Disqus}[http://disqus.com]
4
+ commenting system into your website. It works for any site programmed in Ruby,
5
+ and has view helpers for Rails and Merb.
6
+
7
+ Support for the Disqus Javascript widgets is stable. Disqus API support is
8
+ "beta."
9
+
10
+ === What is Disqus?
11
+
12
+ From the Disqus website:
13
+
14
+ "Disqus, pronounced "discuss", is a service and tool for web comments and
15
+ discussions. The Disqus comment system can be plugged into any website, blog,
16
+ or application. Disqus makes commenting easier and more interactive, while
17
+ connecting websites and commenters across a thriving discussion community."
18
+
19
+ "Disqus is a free service to the general public with absolutely no inline advertisements."
20
+
21
+ === Get it
22
+
23
+ ==== Stable release (does not yet include API):
24
+
25
+ gem install disqus
26
+
27
+ ==== Bleeding Edge (includes API):
28
+
29
+ gem install norman-disqus --source http://gems.github.com
30
+
31
+ === Use it:
32
+
33
+ ==== Configure it:
34
+
35
+ ===== Generic example:
36
+
37
+ Disqus::defaults[:account] = "my_disqus_account"
38
+ # Optional, only if you're using the API
39
+ Disqus::defaults[:api_key] = "my_disqus_api_key"
40
+
41
+ ===== Rails-specific example:
42
+
43
+ # in config/development.rb (or production.rb, test.rb, etc.)
44
+ config.after_initialize do
45
+ Disqus::defaults[:account] = "my_disqus_account"
46
+ # Optional, only if you're using the API
47
+ Disqus::defaults[:api_key] = "my_disqus_api_key"
48
+ end
49
+
50
+ Note that here the "after initialize" is necessary, otherwise your settings
51
+ won't be set properly.
52
+
53
+ ==== Show the comment threads widget on a post page:
54
+
55
+ # Loads the commenting system
56
+ disqus_thread
57
+
58
+ # Or if you're not using Rails/Merb:
59
+ Disqus::Widget::thread
60
+
61
+ # Sets the inner html to the comment count for any links on the page that
62
+ # have the anchor "disqus_thread". For example, "View Comments" below would
63
+ # be replaced by "1 comment" or "23 comments" etc.
64
+ # <a href="http://my.website/article-permalink#disqus_thread">View Comments</a>
65
+ # <a href="http://my.website/different-permalink#disqus_thread">View Comments</a>
66
+ disqus_comment_counts
67
+
68
+ # Or if you're not using Rails/Merb:
69
+ Disqus::Widget::comment_counts
70
+
71
+ ==== Show the combo widget on a post page:
72
+
73
+ disqus_combo(:color => "blue", :hide_mods => false, :num_items => 20)
74
+
75
+ # Or for non-Rails/Merb:
76
+ Disqus::Widget::combo(:color => "blue", :hide_mods => false, :num_items => 20)
77
+
78
+ ==== Show the comment count on a permalink:
79
+
80
+ link_to("Permalink", post_path(@post, :anchor => "disqus_thread"))
81
+ ...
82
+ disqus_comment_counts
83
+
84
+ # Or for non-Rails/Merb:
85
+ Disqus::Widget::comment_counts
86
+
87
+ ==== Work with the Disqus API:
88
+
89
+ See the Disqus::Api class for more info on the Disqus API. You can also read
90
+ the {Disqus developer info here}[http://disqus.com/docs/api/].
91
+
92
+ === Hack it:
93
+
94
+ Github repository:
95
+
96
+ http://github.com/norman/disqus
97
+
98
+ === Submit bug reports:
99
+
100
+ Please use our {Lighthouse}[http://randomba.lighthouseapp.com/projects/16065-disqus/].
101
+
102
+ === Learn more about Disqus:
103
+
104
+ {http://disqus.com}[http://disqus.com]
105
+
106
+ === Thanks to the following contributors:
107
+
108
+ * {Matt Van Horn}[http://github.com/mattvanhorn] - Disqus API
109
+ * {Quin Hoxie}[http://github.com/qhoxie] - Merb support
110
+
111
+ === Legal Stuff
112
+
113
+ The Disqus Ruby gem was not created by, nor is officially supported by
114
+ Disqus.com or Big Head Labs, Inc. Use it at your own risk and your own
115
+ responsibility under the terms of the MIT License.
116
+
117
+ Copyright (c) 2008 {Norman Clarke}[mailto:norman@randomba.org], released under
118
+ the MIT license
@@ -0,0 +1,43 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Run unit tests.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc "Build gem"
17
+ task :gem do
18
+ sh "gem build disqus.gemspec"
19
+ end
20
+
21
+ desc "Run rcov"
22
+ task :rcov do
23
+ rm_f "coverage"
24
+ rm_f "coverage.data"
25
+ if PLATFORM =~ /darwin/
26
+ exclude = '--exclude "gems"'
27
+ else
28
+ exclude = '--exclude "rubygems"'
29
+ end
30
+ rcov = "rcov --rails -Ilib:test --sort coverage --text-report #{exclude} --no-validator-links"
31
+ cmd = "#{rcov} #{Dir["test/**/*.rb"].join(" ")}"
32
+ sh cmd
33
+ end
34
+
35
+ desc 'Generate rdocs.'
36
+ Rake::RDocTask.new(:rdoc) do |rdoc|
37
+ rdoc.rdoc_dir = 'rdoc'
38
+ rdoc.title = 'Disqus'
39
+ rdoc.main = "README.rdoc"
40
+ rdoc.options << '--line-numbers' << '--inline-source' << '-c UTF-8'
41
+ rdoc.rdoc_files.include('lib/**/*.rb')
42
+ rdoc.rdoc_files.include('README.rdoc')
43
+ end
data/init.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'disqus'
2
+ require 'disqus/api'
3
+ require 'disqus/author'
4
+ require 'disqus/forum'
5
+ require 'disqus/post'
6
+ require 'disqus/thread'
@@ -0,0 +1,70 @@
1
+ require 'disqus/widget'
2
+
3
+ # == From the {Disqus Website}[http://disqus.com]:
4
+
5
+ # "Disqus, pronounced "discuss", is a service and tool for web comments and
6
+ # discussions. The Disqus comment system can be plugged into any website, blog,
7
+ # or application. Disqus makes commenting easier and more interactive, while
8
+ # connecting websites and commenters across a thriving discussion community."
9
+ #
10
+ # "Disqus is a free service to the general public with absolutely no inline
11
+ # advertisements."
12
+
13
+ # The Disqus gem helps you quickly and easily integrate Disqus's Javascript
14
+ # widgets into your Ruby-based website. Adding Disqus to your site literally
15
+ # takes only a few minutes. The Disqus gem also provides a complete
16
+ # implementation of the Disqus API for more complex applications.
17
+
18
+ # To use this code, please first create an account on Disqus[http://disqus.com].
19
+ module Disqus
20
+
21
+ @defaults = {
22
+ :api_key => "",
23
+ :account => "",
24
+ :avatar_size => 48,
25
+ :color => "grey",
26
+ :default_tab => "popular",
27
+ :hide_avatars => false,
28
+ :hide_mods => true,
29
+ :num_items => 15,
30
+ :show_powered_by => true,
31
+ :orientation => "horizontal"
32
+ }
33
+
34
+ # Disqus defaults:
35
+ # :account => "",
36
+ # :avatar_size => 48,
37
+ # :color => "grey",
38
+ # :default_tab => "popular",
39
+ # :hide_avatars => false,
40
+ # :hide_mods => true,
41
+ # :num_items => 15,
42
+ # :show_powered_by => true,
43
+ # :orientation => "horizontal"
44
+ def self.defaults
45
+ @defaults
46
+ end
47
+
48
+ # Load the view helpers if the gem is included in a Rails app.
49
+ def self.enable_rails
50
+ return if ActionView::Base.instance_methods.include? 'disqus_thread'
51
+ require 'disqus/view_helpers'
52
+ ActionView::Base.class_eval { include Disqus::ViewHelpers }
53
+ end
54
+
55
+ # Load the view helpers if the gem is included in a Merb app.
56
+ def self.enable_merb
57
+ return if Merb::Controller.instance_methods.include? 'disqus_thread'
58
+ require 'disqus/view_helpers'
59
+ Merb::Controller.class_eval { include Disqus::ViewHelpers }
60
+ end
61
+
62
+ end
63
+
64
+ if defined?(Rails) and defined?(ActionView)
65
+ Disqus::enable_rails
66
+ end
67
+
68
+ if defined?(Merb)
69
+ Disqus::enable_merb
70
+ end
@@ -0,0 +1,264 @@
1
+ require 'open-uri'
2
+ require 'rubygems'
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'uri'
6
+
7
+ module Disqus
8
+
9
+ # == Disqus API
10
+ #
11
+ # The Api class implements the Disqus API directly. It is not really
12
+ # intended to be used directly, but rather to use the domain objects of
13
+ # Forum, Thread, Post, Author and AnonymousAuthor. For full information on
14
+ # the Disqus API, please see the {Disqus developer info}[http://disqus.com/docs/api/].
15
+ #
16
+ # Each method in the Api class takes as a single argument a hash of options,
17
+ # and returns a Hash with 3 keys:
18
+ #
19
+ # * 'succeeded' - contains true or false indicating whether the API call succeeded
20
+ # * 'code' - if the API call did not succeed, this will contain an error code.
21
+ # * 'message' - contains the object being returned on success, or an error message on failure.
22
+ #
23
+ # === API Keys
24
+ #
25
+ # There are two different kinds of API keys:
26
+ #
27
+ # ==== User Keys
28
+ #
29
+ # Every Disqus account has a User Key; it is used to perform actions
30
+ # associated with that account. This can be passed in as an option, or
31
+ # configured as follows:
32
+ #
33
+ # Disqus::defaults[:api_key] = "the_user_api_key"
34
+ #
35
+ # ==== Forum Keys
36
+ #
37
+ # Every Disqus forum has a Forum Key. It can be shared among trusted
38
+ # moderators of a forum, and is used to perform actions associated with that
39
+ # forum. The creator of a forum can get the forum's key through the API.
40
+ class Api
41
+
42
+ ROOT = 'http://disqus.com/api'
43
+
44
+ class << self
45
+
46
+ # Creates a new post on the thread. Does not check against spam filters or ban list.
47
+ # This is intended to allow automated importing of comments.
48
+ #
49
+ # Returns a Hash containing a representation of the post just created:
50
+ #
51
+ # Required options hash elements:
52
+ #
53
+ # * <tt>:forum_api_key</tt> - the API key for the forum
54
+ # * <tt>:thread_id</tt> - the thread to post to
55
+ # * <tt>:message</tt> - the content of the post
56
+ # * <tt>:author_name</tt> - the post creator's name
57
+ # * <tt>:author_email</tt> - the post creator's email address
58
+ #
59
+ # Optional:
60
+ #
61
+ # * <tt>:parent_post</tt> - the id of the parent post
62
+ # * <tt>:created_at</tt> - the UTC date this post was created, in the format <tt>%Y-%m-%dT%H:%M</tt> (the current time will be used by default)
63
+ # * <tt>:author_url</tt> - the author's homepage
64
+ # * <tt>:ip_address</tt> - the author's IP address
65
+ def create_post(opts = {})
66
+ opts[:api_key] ||= Disqus::defaults[:api_key]
67
+ JSON.parse(post('create_post',
68
+ :forum_api_key => opts[:forum_api_key],
69
+ :thread_id => opts[:thread_id],
70
+ :message => opts[:message],
71
+ :author_name => opts[:author_name],
72
+ :author_email => opts[:author_email],
73
+ :parent_post => opts[:parent_post],
74
+ :created_at => opts[:created_at], #UTC timestring, format: %Y-%m-%dT%H:%M
75
+ :author_url => opts[:author_url],
76
+ :ip_address => opts[:ip_address])
77
+ )
78
+ end
79
+
80
+ # Returns an array of hashes representing all forums the user owns. The
81
+ # user is determined by the API key.
82
+ #
83
+ # Options:
84
+ #
85
+ # * <tt>:api_key</tt> - The User's API key (defaults to
86
+ # Disqus::defaults[:api_key])
87
+ def get_forum_list(opts = {})
88
+ opts[:api_key] ||= Disqus::defaults[:api_key]
89
+ JSON.parse(get('get_forum_list', :user_api_key => opts[:api_key]))
90
+ end
91
+
92
+ # Returns A string which is the Forum Key for the given forum.
93
+ #
94
+ # Required options hash elements:
95
+ #
96
+ # * <tt>:forum_id</tt> - the unique id of the forum
97
+ #
98
+ # Optional:
99
+ #
100
+ # * <tt>:api_key</tt> - The User's API key (defaults to Disqus::defaults[:api_key])
101
+ def get_forum_api_key(opts = {})
102
+ opts[:api_key] ||= Disqus::defaults[:api_key]
103
+ JSON.parse(get('get_forum_api_key', :user_api_key => opts[:api_key], :forum_id => opts[:forum_id]))
104
+ end
105
+
106
+ # Returns: An array of hashes representing all threads belonging to the
107
+ # given forum.
108
+ #
109
+ # Required options hash elements:
110
+ #
111
+ # * <tt>:forum_api_key</tt> - the API key for the forum
112
+ # * <tt>:forum_id</tt> - the unique id of the forum
113
+ def get_thread_list(opts = {})
114
+ JSON.parse(get('get_thread_list', :forum_id => opts[:forum_id], :forum_api_key => opts[:forum_api_key]))
115
+ end
116
+
117
+ # Returns a hash having thread_ids as keys and 2-element arrays as
118
+ # values.
119
+ #
120
+ # The first array element is the number of visible comments on on the
121
+ # thread; this would be useful for showing users of the site (e.g., "5
122
+ # Comments").
123
+ #
124
+ # The second array element is the total number of comments on the
125
+ # thread.
126
+ #
127
+ # These numbers are different because some forums require moderator
128
+ # approval, some messages are flagged as spam, etc.
129
+ #
130
+ # Required options hash elements:
131
+ #
132
+ # * <tt>:forum_api_key</tt> - the API key for the forum
133
+ # * <tt>:thread_ids</tt> - an array of thread IDs belonging to the given forum.
134
+ def get_num_posts(opts = {})
135
+ opts[:api_key] ||= Disqus::defaults[:api_key]
136
+ JSON.parse(get('get_num_posts', :thread_ids => opts[:thread_ids].join(","), :forum_api_key => opts[:forum_api_key]))
137
+ end
138
+
139
+ # Returns a hash representing a thread if one was found, otherwise null.
140
+ #
141
+ # It only finds threads associated with the given forum.
142
+ #
143
+ # Note that there is no one-to-one mapping between threads and URL's; a
144
+ # thread will only have an associated URL if it was automatically
145
+ # created by Disqus javascript embedded on that page. Therefore, we
146
+ # recommend using thread_by_identifier whenever possible. This method is
147
+ # provided mainly for handling comments from before your forum was using
148
+ # the API.
149
+ #
150
+ # Required options hash elements:
151
+ #
152
+ # * <tt>:forum_api_key</tt> - the API key for the forum
153
+ # * <tt>:url</tt> - the URL to check for an associated thread
154
+ def get_thread_by_url(opts = {})
155
+ JSON.parse(get('get_thread_by_url', :url => opts[:url], :forum_api_key => opts[:forum_api_key]))
156
+ end
157
+
158
+ # Returns an array of hashes representing representing all posts
159
+ # belonging to the given forum.
160
+ #
161
+ # Required options hash elements:
162
+ #
163
+ # * <tt>:forum_api_key</tt> - the API key for the forum
164
+ # * <tt>:thread_id</tt> - the ID of a thread belonging to the given forum
165
+ def get_thread_posts(opts = {})
166
+ JSON.parse(get('get_thread_posts', :thread_id => opts[:thread_id], :forum_api_key => opts[:forum_api_key]))
167
+ end
168
+
169
+ # Create or retrieve a thread by an arbitrary identifying string of your
170
+ # choice. For example, you could use your local database's ID for the
171
+ # thread. This method allows you to decouple thread identifiers from the
172
+ # URL's on which they might be appear. (Disqus would normally use a
173
+ # thread's URL to identify it, which is problematic when URL's do not
174
+ # uniquely identify a resource.) If no thread exists for the given
175
+ # identifier yet (paired with the forum), one will be created.
176
+ #
177
+ # Returns a hash with two keys:
178
+ #
179
+ # * "thread", which is a hash representing the thread corresponding to the identifier; and
180
+ # * "created", which indicates whether the thread was created as a result of this method call. If created, it will have the specified title.
181
+ #
182
+ # Required options hash elements:
183
+ #
184
+ # * <tt>:forum_api_key</tt> - the API key for the forum
185
+ # * <tt>:title</tt> - the title of the thread to possibly be created
186
+ # * <tt>:identifier</tt> - a string of your choosing
187
+ def thread_by_identifier(opts = {})
188
+ JSON.parse(post('thread_by_identifier', :forum_api_key => opts[:forum_api_key],
189
+ :identifier => opts[:identifier],
190
+ :title => opts[:title] ))
191
+ end
192
+
193
+ # Sets the provided values on the thread object.
194
+ #
195
+ # Returns an empty success message.
196
+ #
197
+ # Required options hash elements:
198
+ #
199
+ # * <tt>:forum_api_key</tt> - the API key for the forum
200
+ # * <tt>:thread_id</tt> - the ID of a thread belonging to the given forum
201
+ #
202
+ # Optional:
203
+ #
204
+ # * <tt>:title</tt> - the title of the thread
205
+ # * <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.
206
+ # * <tt>:url</tt> - the URL this thread is on, if known.
207
+ # * <tt>:allow_comment</tt> - whether this thread is open to new comments
208
+ def update_thread(opts = {})
209
+ raise opts.inspect
210
+ JSON.parse(post('update_thread',
211
+ :forum_api_key => opts[:forum_api_key],
212
+ :thread_id => opts[:thread_id],
213
+ :title => opts[:title],
214
+ :slug => opts[:slug],
215
+ :url => opts[:url],
216
+ :allow_comments => opts[:allow_comments])
217
+ )
218
+ end
219
+
220
+ # Widget to includes a comment form suitable for use with the Disqus
221
+ # API. This is different from the other widgets in that you can specify
222
+ # the thread identifier being commented on.
223
+ def comment_form(forum_shortname, thread_identifier)
224
+ url = 'http://disqus.com/api/reply.js?' +
225
+ "forum_shortname=#{escape(forum_shortname)}&" +
226
+ "thread_identifier=#{escape(thread_identifier)}"
227
+ s = '<div id="dsq-reply">'
228
+ s << '<script type="text/javascript" src="%s"></script>' % url
229
+ s << '</div>'
230
+ return s
231
+ end
232
+
233
+ private
234
+
235
+ def escape(string)
236
+ URI::encode(string, /[^a-z0-9]/i)
237
+ end
238
+
239
+ def get(*args)
240
+ open(make_url(*args)) {|u| u.read }
241
+ end
242
+
243
+ def post(*args)
244
+ url = ROOT + '/' + args.shift
245
+ post_params = {}
246
+ args.shift.each { |k, v| post_params[k.to_s]=v.to_s }
247
+ Net::HTTP.post_form(URI.parse(url),post_params)
248
+ end
249
+
250
+ def make_url(*args)
251
+ url = ROOT + '/' + args.shift + '/?'
252
+ args.shift.each { |k, v| url += "#{k}=#{escape(v.to_s)}&" }
253
+ return url.chomp('&')
254
+ end
255
+
256
+ def validate_opts!(opts)
257
+ raise ArgumentError.new("You must specify an :api_key") if !opts[:api_key]
258
+ end
259
+
260
+ end
261
+
262
+ end
263
+
264
+ end