disqussion 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +9 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +80 -0
- data/HISTORY.mkd +5 -0
- data/LICENSE.mkd +20 -0
- data/README.mkd +139 -0
- data/Rakefile +23 -0
- data/disqussion.gemspec +37 -0
- data/lib/disqussion/api.rb +21 -0
- data/lib/disqussion/client/.DS_Store +0 -0
- data/lib/disqussion/client/applications.rb +20 -0
- data/lib/disqussion/client/blacklists.rb +4 -0
- data/lib/disqussion/client/categories.rb +4 -0
- data/lib/disqussion/client/exports.rb +4 -0
- data/lib/disqussion/client/forums.rb +122 -0
- data/lib/disqussion/client/imports.rb +4 -0
- data/lib/disqussion/client/posts.rb +217 -0
- data/lib/disqussion/client/reactions.rb +79 -0
- data/lib/disqussion/client/reports.rb +4 -0
- data/lib/disqussion/client/threads.rb +199 -0
- data/lib/disqussion/client/trends.rb +23 -0
- data/lib/disqussion/client/users.rb +103 -0
- data/lib/disqussion/client/utils.rb +90 -0
- data/lib/disqussion/client/whitelists.rb +4 -0
- data/lib/disqussion/client.rb +46 -0
- data/lib/disqussion/configuration.rb +121 -0
- data/lib/disqussion/connection.rb +36 -0
- data/lib/disqussion/error.rb +51 -0
- data/lib/disqussion/request.rb +38 -0
- data/lib/disqussion/version.rb +3 -0
- data/lib/disqussion/view_helpers.rb +9 -0
- data/lib/disqussion/widget.rb +183 -0
- data/lib/disqussion.rb +25 -0
- data/lib/faraday/response/raise_http_4xx.rb +41 -0
- data/lib/faraday/response/raise_http_5xx.rb +20 -0
- data/spec/disqussion/api_spec.rb +63 -0
- data/spec/disqussion/client/.DS_Store +0 -0
- data/spec/disqussion/client/applications_spec.rb +24 -0
- data/spec/disqussion/client/forums_spec.rb +80 -0
- data/spec/disqussion/client/posts_spec.rb +154 -0
- data/spec/disqussion/client/reactions_spec.rb +63 -0
- data/spec/disqussion/client/threads_spec.rb +128 -0
- data/spec/disqussion/client/trends_spec.rb +24 -0
- data/spec/disqussion/client/users_spec.rb +33 -0
- data/spec/disqussion/client_spec.rb +15 -0
- data/spec/disqussion_spec.rb +101 -0
- data/spec/faraday/response_spec.rb +30 -0
- data/spec/fixtures/applications/listUsage.json +129 -0
- data/spec/fixtures/forums/create.json +12 -0
- data/spec/fixtures/forums/details.json +12 -0
- data/spec/fixtures/forums/listCategories.json +21 -0
- data/spec/fixtures/forums/listPosts.json +859 -0
- data/spec/fixtures/forums/listThreads.json +533 -0
- data/spec/fixtures/posts/approve.json +6 -0
- data/spec/fixtures/posts/create.json +6 -0
- data/spec/fixtures/posts/details.json +35 -0
- data/spec/fixtures/posts/highlight.json +6 -0
- data/spec/fixtures/posts/list.json +247 -0
- data/spec/fixtures/posts/remove.json +6 -0
- data/spec/fixtures/posts/report.json +6 -0
- data/spec/fixtures/posts/restore.json +6 -0
- data/spec/fixtures/posts/spam.json +6 -0
- data/spec/fixtures/posts/unhighlight.json +6 -0
- data/spec/fixtures/posts/vote.json +6 -0
- data/spec/fixtures/reactions/domains.json +4 -0
- data/spec/fixtures/reactions/ips.json +131 -0
- data/spec/fixtures/reactions/threads.json +4 -0
- data/spec/fixtures/reactions/users.json +124 -0
- data/spec/fixtures/threads/close.json +4 -0
- data/spec/fixtures/threads/create.json +22 -0
- data/spec/fixtures/threads/details.json +24 -0
- data/spec/fixtures/threads/list.json +531 -0
- data/spec/fixtures/threads/listMostLiked.json +530 -0
- data/spec/fixtures/threads/listPosts.json +87 -0
- data/spec/fixtures/threads/open.json +8 -0
- data/spec/fixtures/threads/remove.json +4 -0
- data/spec/fixtures/threads/restore.json +4 -0
- data/spec/fixtures/threads/vote.json +4 -0
- data/spec/fixtures/trends/listTreads.json +283 -0
- data/spec/fixtures/users/details.json +19 -0
- data/spec/fixtures/users/follow.json +4 -0
- data/spec/helper.rb +47 -0
- metadata +348 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module Disqussion
|
3
|
+
class Client
|
4
|
+
# @private
|
5
|
+
module Utils
|
6
|
+
private
|
7
|
+
|
8
|
+
# Take a single user ID or screen name and merge it into an options hash with the correct key
|
9
|
+
#
|
10
|
+
# @param user_id_or_username [Integer, String] A Disqus user ID or username.
|
11
|
+
# @param options [Hash] A customizable set of options.
|
12
|
+
# @return [Hash]
|
13
|
+
def merge_user_into_options!(user_id_or_username, options={})
|
14
|
+
case user_id_or_username
|
15
|
+
when Fixnum
|
16
|
+
options[:user] = user_id_or_username
|
17
|
+
when String
|
18
|
+
options[:"user:username"] = user_id_or_username
|
19
|
+
end
|
20
|
+
options
|
21
|
+
end
|
22
|
+
|
23
|
+
# Take a single user ID or screen name and merge it into an options hash with the correct key
|
24
|
+
#
|
25
|
+
# @param user_id_or_username [Integer, String] A Disqus user ID or username.
|
26
|
+
# @param options [Hash] A customizable set of options.
|
27
|
+
# @return [Hash]
|
28
|
+
def merge_target_into_options!(user_id_or_username, options={})
|
29
|
+
case user_id_or_username
|
30
|
+
when Fixnum
|
31
|
+
options[:target] = user_id_or_username
|
32
|
+
when String
|
33
|
+
options[:"target:username"] = user_id_or_username
|
34
|
+
end
|
35
|
+
options
|
36
|
+
end
|
37
|
+
|
38
|
+
# Take a multiple user IDs and screen names and merge them into an options hash with the correct keys
|
39
|
+
#
|
40
|
+
# @param users_id_or_usernames [Array] An array of Disqus user IDs or usernames.
|
41
|
+
# @param options [Hash] A customizable set of options.
|
42
|
+
# @return [Hash]
|
43
|
+
def merge_users_into_options!(user_ids_or_usernames, options={})
|
44
|
+
user_ids, usernames = [], []
|
45
|
+
user_ids_or_usernames.flatten.each do |user_id_or_username|
|
46
|
+
case user_id_or_username
|
47
|
+
when Fixnum
|
48
|
+
user_ids << user_id_or_username
|
49
|
+
when String
|
50
|
+
usernames << user_id_or_username
|
51
|
+
end
|
52
|
+
end
|
53
|
+
options[:user_id] = user_ids.join(',') unless user_ids.empty?
|
54
|
+
options[:username] = usernames.join(',') unless usernames.empty?
|
55
|
+
options
|
56
|
+
end
|
57
|
+
|
58
|
+
# Take a single owner ID or owner screen name and merge it into an options hash with the correct key
|
59
|
+
# (for Disqus API endpoints that want :owner_id and :owner_username)
|
60
|
+
#
|
61
|
+
# @param owner_id_or_owner_username [Integer, String] A Disqus user ID or username.
|
62
|
+
# @param options [Hash] A customizable set of options.
|
63
|
+
# @return [Hash]
|
64
|
+
def merge_owner_into_options!(owner_id_or_owner_username, options={})
|
65
|
+
case owner_id_or_owner_username
|
66
|
+
when Fixnum
|
67
|
+
options[:owner_id] = owner_id_or_owner_username
|
68
|
+
when String
|
69
|
+
options[:owner_username] = owner_id_or_owner_username
|
70
|
+
end
|
71
|
+
options
|
72
|
+
end
|
73
|
+
|
74
|
+
# Take a single list ID or slug and merge it into an options hash with the correct key
|
75
|
+
#
|
76
|
+
# @param list_id_or_slug [Integer, String] A Disqus list ID or slug.
|
77
|
+
# @param options [Hash] A customizable set of options.
|
78
|
+
# @return [Hash]
|
79
|
+
def merge_list_into_options!(list_id_or_username, options={})
|
80
|
+
case list_id_or_username
|
81
|
+
when Fixnum
|
82
|
+
options[:list_id] = list_id_or_username
|
83
|
+
when String
|
84
|
+
options[:slug] = list_id_or_username
|
85
|
+
end
|
86
|
+
options
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Disqussion
|
2
|
+
# Wrapper for the Disqussion REST API
|
3
|
+
#
|
4
|
+
# @note All methods have been separated into client classes and follow the same grouping used in {http://disqus.com/api/docs/ the Disqus API Documentation}.
|
5
|
+
# @see http://docs.disqus.com/developers/api/
|
6
|
+
class Client < API
|
7
|
+
require 'disqussion/client/applications.rb'
|
8
|
+
require 'disqussion/client/blacklists.rb'
|
9
|
+
require 'disqussion/client/categories.rb'
|
10
|
+
require 'disqussion/client/exports.rb'
|
11
|
+
require 'disqussion/client/forums.rb'
|
12
|
+
require 'disqussion/client/imports.rb'
|
13
|
+
require 'disqussion/client/posts.rb'
|
14
|
+
require 'disqussion/client/reactions.rb'
|
15
|
+
require 'disqussion/client/reports.rb'
|
16
|
+
require 'disqussion/client/threads.rb'
|
17
|
+
require 'disqussion/client/trends.rb'
|
18
|
+
require 'disqussion/client/users.rb'
|
19
|
+
require 'disqussion/client/utils.rb'
|
20
|
+
require 'disqussion/client/whitelists.rb'
|
21
|
+
|
22
|
+
alias :api_endpoint :endpoint
|
23
|
+
|
24
|
+
include Disqussion::Client::Utils
|
25
|
+
|
26
|
+
['applications',
|
27
|
+
'blacklists',
|
28
|
+
'categories',
|
29
|
+
'exports',
|
30
|
+
'forums',
|
31
|
+
'imports',
|
32
|
+
'posts',
|
33
|
+
'reactions',
|
34
|
+
'reports',
|
35
|
+
'threads',
|
36
|
+
'trends',
|
37
|
+
'users',
|
38
|
+
'whitelists'].each do |classname|
|
39
|
+
class_eval <<-END
|
40
|
+
def self.#{classname}
|
41
|
+
Disqussion::#{classname.capitalize}.new
|
42
|
+
end
|
43
|
+
END
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'disqussion/version'
|
3
|
+
|
4
|
+
module Disqussion
|
5
|
+
# Defines constants and methods related to configuration
|
6
|
+
module Configuration
|
7
|
+
# An array of valid keys in the options hash when configuring a {Disqussion::API}
|
8
|
+
VALID_OPTIONS_KEYS = [
|
9
|
+
:adapter,
|
10
|
+
:endpoint,
|
11
|
+
:api_key,
|
12
|
+
:api_secret,
|
13
|
+
:developer,
|
14
|
+
:container_id,
|
15
|
+
:avatar_size,
|
16
|
+
:color,
|
17
|
+
:default_tab,
|
18
|
+
:hide_avatars,
|
19
|
+
:hide_mods,
|
20
|
+
:num_items,
|
21
|
+
:show_powered_by,
|
22
|
+
:orientation,
|
23
|
+
:format,
|
24
|
+
:proxy,
|
25
|
+
:user_agent].freeze
|
26
|
+
|
27
|
+
# An array of valid request/response formats
|
28
|
+
#
|
29
|
+
# @note only json for now
|
30
|
+
VALID_FORMATS = [:json].freeze
|
31
|
+
|
32
|
+
# The adapter that will be used to connect if none is set
|
33
|
+
#
|
34
|
+
# @note The default faraday adapter is Net::HTTP.
|
35
|
+
DEFAULT_ADAPTER = if defined?(EventMachine) && EM.reactor_running?
|
36
|
+
EMSynchrony
|
37
|
+
else
|
38
|
+
Faraday.default_adapter
|
39
|
+
end
|
40
|
+
|
41
|
+
# By default, don't set an application key
|
42
|
+
DEFAULT_API_KEY = nil
|
43
|
+
|
44
|
+
# By default, don't set an application secret
|
45
|
+
DEFAULT_API_SECRET = nil
|
46
|
+
|
47
|
+
# The endpoint that will be used to connect if none is set
|
48
|
+
#
|
49
|
+
# @note This is configurable in case you want to use HTTP instead of HTTPS, specify a different API version, or use a Disqussion-compatible endpoint.
|
50
|
+
# @see http://status.net/wiki/Disqussion-compatible_API
|
51
|
+
# @see http://en.blog.wordpress.com/2009/12/12/disqussion-api/
|
52
|
+
# @see http://staff.tumblr.com/post/287703110/api
|
53
|
+
# @see http://developer.typepad.com/typepad-disqussion-api/disqussion-api.html
|
54
|
+
DEFAULT_API_VERSION = '3.0'.freeze
|
55
|
+
DEFAULT_ENDPOINT = "https://disqus.com/api/#{DEFAULT_API_VERSION}/".freeze
|
56
|
+
|
57
|
+
# The response format appended to the path and sent in the 'Accept' header if none is set
|
58
|
+
#
|
59
|
+
# @note JSON is preferred over XML because it is more concise and faster to parse.
|
60
|
+
DEFAULT_FORMAT = :json
|
61
|
+
|
62
|
+
# By default, don't use a proxy server
|
63
|
+
DEFAULT_PROXY = nil
|
64
|
+
|
65
|
+
# The user agent that will be sent to the API endpoint if none is set
|
66
|
+
DEFAULT_USER_AGENT = "Disqussion Ruby Gem #{Disqussion::VERSION}".freeze
|
67
|
+
|
68
|
+
DEFAULT_DEVELOPER = false
|
69
|
+
DEFAULT_CONTAINER_ID = 'disqus_thread'
|
70
|
+
DEFAULT_AVATAR_SIZE = 48
|
71
|
+
DEFAULT_COLOR = "grey"
|
72
|
+
DEFAULT_DEFAULT_TAB = "popular"
|
73
|
+
DEFAULT_HIDE_AVATARS = false
|
74
|
+
DEFAULT_HIDE_MODS = true
|
75
|
+
DEFAULT_NUM_ITEMS = 15
|
76
|
+
DEFAULT_SHOW_POWERED_BY = true
|
77
|
+
DEFAULT_ORIENTATION = "horizontal"
|
78
|
+
|
79
|
+
# @private
|
80
|
+
attr_accessor *VALID_OPTIONS_KEYS
|
81
|
+
|
82
|
+
# When this module is extended, set all configuration options to their default values
|
83
|
+
def self.extended(base)
|
84
|
+
base.reset
|
85
|
+
end
|
86
|
+
|
87
|
+
# Convenience method to allow configuration options to be set in a block
|
88
|
+
def configure
|
89
|
+
yield self
|
90
|
+
end
|
91
|
+
|
92
|
+
# Create a hash of options and their values
|
93
|
+
def options
|
94
|
+
options = {}
|
95
|
+
VALID_OPTIONS_KEYS.each{|k| options[k] = send(k) }
|
96
|
+
options
|
97
|
+
end
|
98
|
+
|
99
|
+
# Reset all configuration options to defaults
|
100
|
+
def reset
|
101
|
+
self.adapter = DEFAULT_ADAPTER
|
102
|
+
self.endpoint = DEFAULT_ENDPOINT
|
103
|
+
self.api_key = DEFAULT_API_KEY
|
104
|
+
self.api_secret = DEFAULT_API_SECRET
|
105
|
+
self.developer = DEFAULT_DEVELOPER
|
106
|
+
self.container_id = DEFAULT_CONTAINER_ID
|
107
|
+
self.avatar_size = DEFAULT_AVATAR_SIZE
|
108
|
+
self.color = DEFAULT_COLOR
|
109
|
+
self.default_tab = DEFAULT_DEFAULT_TAB
|
110
|
+
self.hide_avatars = DEFAULT_HIDE_AVATARS
|
111
|
+
self.hide_mods = DEFAULT_HIDE_MODS
|
112
|
+
self.num_items = DEFAULT_NUM_ITEMS
|
113
|
+
self.show_powered_by = DEFAULT_SHOW_POWERED_BY
|
114
|
+
self.orientation = DEFAULT_ORIENTATION
|
115
|
+
self.format = DEFAULT_FORMAT
|
116
|
+
self.proxy = DEFAULT_PROXY
|
117
|
+
self.user_agent = DEFAULT_USER_AGENT
|
118
|
+
self
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'faraday_middleware'
|
2
|
+
require 'faraday/response/raise_http_4xx'
|
3
|
+
require 'faraday/response/raise_http_5xx'
|
4
|
+
|
5
|
+
module Disqussion
|
6
|
+
# @private
|
7
|
+
module Connection
|
8
|
+
private
|
9
|
+
|
10
|
+
def connection(raw=false)
|
11
|
+
options = {
|
12
|
+
:headers => {'Accept' => "application/#{format}", 'User-Agent' => user_agent},
|
13
|
+
:proxy => proxy,
|
14
|
+
:ssl => {:verify => false},
|
15
|
+
:url => api_endpoint,
|
16
|
+
}
|
17
|
+
|
18
|
+
Faraday.new(options) do |builder|
|
19
|
+
builder.use Faraday::Request::Multipart
|
20
|
+
builder.use Faraday::Request::UrlEncoded
|
21
|
+
builder.use Faraday::Response::RaiseHttp4xx
|
22
|
+
builder.use Faraday::Response::Rashify unless raw
|
23
|
+
unless raw
|
24
|
+
case format.to_s.downcase
|
25
|
+
when 'json'
|
26
|
+
builder.use Faraday::Response::ParseJson
|
27
|
+
when 'xml'
|
28
|
+
builder.use Faraday::Response::ParseXml
|
29
|
+
end
|
30
|
+
end
|
31
|
+
builder.use Faraday::Response::RaiseHttp5xx
|
32
|
+
builder.adapter(adapter)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Disqussion
|
2
|
+
# Custom error class for rescuing from all Disqus errors
|
3
|
+
class Error < StandardError
|
4
|
+
attr_reader :http_headers
|
5
|
+
|
6
|
+
def initialize(message, http_headers)
|
7
|
+
@http_headers = Hash[http_headers]
|
8
|
+
super message
|
9
|
+
end
|
10
|
+
|
11
|
+
def ratelimit_reset
|
12
|
+
Time.at(@http_headers.values_at('x-ratelimit-reset', 'X-RateLimit-Reset').detect{|value| value}.to_i)
|
13
|
+
end
|
14
|
+
|
15
|
+
def ratelimit_limit
|
16
|
+
@http_headers.values_at('x-ratelimit-limit', 'X-RateLimit-Limit').detect{|value| value}.to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
def ratelimit_remaining
|
20
|
+
@http_headers.values_at('x-ratelimit-remaining', 'X-RateLimit-Remaining').detect{|value| value}.to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
def retry_after
|
24
|
+
[(ratelimit_reset - Time.now).ceil, 0].max
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Raised when Disqus returns the HTTP status code 400
|
29
|
+
class BadRequest < Error; end
|
30
|
+
|
31
|
+
# Raised when Disqus returns the HTTP status code 401
|
32
|
+
class Unauthorized < Error; end
|
33
|
+
|
34
|
+
# Raised when Disqus returns the HTTP status code 403
|
35
|
+
class Forbidden < Error; end
|
36
|
+
|
37
|
+
# Raised when Disqus returns the HTTP status code 404
|
38
|
+
class NotFound < Error; end
|
39
|
+
|
40
|
+
# Raised when Disqus returns the HTTP status code 406
|
41
|
+
class NotAcceptable < Error; end
|
42
|
+
|
43
|
+
# Raised when Disqus returns the HTTP status code 500
|
44
|
+
class InternalServerError < Error; end
|
45
|
+
|
46
|
+
# Raised when Disqus returns the HTTP status code 502
|
47
|
+
class BadGateway < Error; end
|
48
|
+
|
49
|
+
# Raised when Disqus returns the HTTP status code 503
|
50
|
+
class ServiceUnavailable < Error; end
|
51
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Disqussion
|
2
|
+
# Defines HTTP request methods
|
3
|
+
module Request
|
4
|
+
# Perform an HTTP GET request
|
5
|
+
def get(path, options={}, raw=false)
|
6
|
+
request(:get, path, options, raw)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Perform an HTTP POST request
|
10
|
+
def post(path, options={}, raw=false)
|
11
|
+
request(:post, path, options, raw)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
# Perform an HTTP request
|
17
|
+
def request(method, path, options, raw=false)
|
18
|
+
# identify our request
|
19
|
+
# @see: http://docs.disqus.com/help/52/
|
20
|
+
options ||= {}
|
21
|
+
options.merge!(:api_secret => self.api_secret) unless options.has_key?(:api_secret)
|
22
|
+
response = connection(raw).send(method) do |request|
|
23
|
+
case method
|
24
|
+
when :get
|
25
|
+
request.url(formatted_path(path), options)
|
26
|
+
when :post
|
27
|
+
request.path = formatted_path(path)
|
28
|
+
request.body = options unless options.empty?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
raw ? response : response.body
|
32
|
+
end
|
33
|
+
|
34
|
+
def formatted_path(path)
|
35
|
+
[path, format].compact.join('.')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# Shortcuts to access the widgets as simple functions as opposed to using
|
2
|
+
# their full qualified names.
|
3
|
+
%w[combo comment_counts popular_threads recent_comments thread top_commenters].each do |method|
|
4
|
+
eval(<<-EOM)
|
5
|
+
def disqus_#{method}(options = {})
|
6
|
+
Disqus::Widget.#{method}(options)
|
7
|
+
end
|
8
|
+
EOM
|
9
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
module EventMachine
|
2
|
+
module Disqus
|
3
|
+
# Disqus Widget generator.
|
4
|
+
#
|
5
|
+
# All of the methods accept various options, and "account" is required for
|
6
|
+
# all of them. You can avoid having to pass in the account each time by
|
7
|
+
# setting it in the defaults like this:
|
8
|
+
#
|
9
|
+
# Disqus::defaults[:account] = "my_account"
|
10
|
+
class Widget
|
11
|
+
|
12
|
+
VALID_COLORS = ['blue', 'grey', 'green', 'red', 'orange']
|
13
|
+
VALID_NUM_ITEMS = 5..20
|
14
|
+
VALID_DEFAULT_TABS = ['people', 'recent', 'popular']
|
15
|
+
VALID_AVATAR_SIZES = [24, 32, 48, 92, 128]
|
16
|
+
VALID_ORIENTATIONS = ['horizontal', 'vertical']
|
17
|
+
|
18
|
+
ROOT_PATH = 'http://disqus.com/forums/%s/'
|
19
|
+
THREAD = ROOT_PATH + 'embed.js'
|
20
|
+
COMBO = ROOT_PATH + 'combination_widget.js?num_items=%d&color=%s&default_tab=%s'
|
21
|
+
RECENT = ROOT_PATH + 'recent_comments_widget.js?num_items=%d&avatar_size=%d'
|
22
|
+
POPULAR = ROOT_PATH + 'popular_threads_widget.js?num_items=%d'
|
23
|
+
TOP = ROOT_PATH + 'top_commenters_widget.js?num_items=%d&avatar_size=%d&orientation=%s'
|
24
|
+
class << self
|
25
|
+
|
26
|
+
# Show the main Disqus thread widget.
|
27
|
+
# Options:
|
28
|
+
# * <tt>account:</tt> Your Discus account (required).
|
29
|
+
def thread(opts = {})
|
30
|
+
opts = Disqus::defaults.merge(opts)
|
31
|
+
opts[:view_thread_text] ||= "View the discussion thread"
|
32
|
+
validate_opts!(opts)
|
33
|
+
s = ''
|
34
|
+
if opts[:developer]
|
35
|
+
s << '<script type="text/javascript">var disqus_developer = 1;</script>'
|
36
|
+
end
|
37
|
+
s << '<div id="disqus_thread"></div>'
|
38
|
+
s << '<script type="text/javascript" src="' + THREAD + '"></script>'
|
39
|
+
s << '<noscript><a href="http://%s.disqus.com/?url=ref">'
|
40
|
+
s << opts[:view_thread_text]
|
41
|
+
s << '</a></noscript>'
|
42
|
+
if opts[:show_powered_by]
|
43
|
+
s << '<a href="http://disqus.com" class="dsq-brlink">blog comments '
|
44
|
+
s << 'powered by <span class="logo-disqus">Disqus</span></a>'
|
45
|
+
end
|
46
|
+
s % [opts[:account], opts[:account]]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Loads Javascript to show the number of comments for the page.
|
50
|
+
#
|
51
|
+
# The Javascript sets the inner html to the comment count for any links
|
52
|
+
# on the page that have the anchor "disqus_thread". For example, "View
|
53
|
+
# Comments" below would be replaced by "1 comment" or "23 comments" etc.
|
54
|
+
#
|
55
|
+
# <a href="http://my.website/article-permalink#disqus_thread">View Comments</a>
|
56
|
+
# <a href="http://my.website/different-permalink#disqus_thread">View Comments</a>
|
57
|
+
# Options:
|
58
|
+
# * <tt>account:</tt> Your Discus account (required).
|
59
|
+
def comment_counts(opts = {})
|
60
|
+
opts = Disqus::defaults.merge(opts)
|
61
|
+
validate_opts!(opts)
|
62
|
+
s = <<-WHIMPER
|
63
|
+
<script type="text/javascript">
|
64
|
+
//<![CDATA[
|
65
|
+
(function() {
|
66
|
+
var links = document.getElementsByTagName('a');
|
67
|
+
var query = '?';
|
68
|
+
for(var i = 0; i < links.length; i++) {
|
69
|
+
if(links[i].href.indexOf('#disqus_thread') >= 0) {
|
70
|
+
query += 'url' + i + '=' + encodeURIComponent(links[i].href) + '&';
|
71
|
+
}
|
72
|
+
}
|
73
|
+
document.write('<' + 'script type="text/javascript" src="#{ROOT_PATH}get_num_replies.js' + query + '"></' + 'script>');
|
74
|
+
})();
|
75
|
+
//]]>
|
76
|
+
</script>
|
77
|
+
WHIMPER
|
78
|
+
s % opts[:account]
|
79
|
+
end
|
80
|
+
|
81
|
+
# Show the top commenters Disqus thread widget.
|
82
|
+
# Options:
|
83
|
+
# * <tt>account:</tt> Your Discus account (required).
|
84
|
+
# * <tt>header:</tt> HTML snipper with header (default h2) tag and text.
|
85
|
+
# * <tt>show_powered_by:</tt> Show or hide the powered by Disqus text.
|
86
|
+
# * <tt>num_items:</tt>: How many items to show.
|
87
|
+
# * <tt>hide_mods:</tt> Don't show moderators.
|
88
|
+
# * <tt>hide_avatars:</tt> Don't show avatars.
|
89
|
+
# * <tt>avatar_size:</tt> Avatar size.
|
90
|
+
def top_commenters(opts = {})
|
91
|
+
opts = Disqus::defaults.merge(opts)
|
92
|
+
opts[:header] ||= '<h2 class="dsq-widget-title">Top Commenters</h2>'
|
93
|
+
validate_opts!(opts)
|
94
|
+
s = '<div id="dsq-topcommenters" class="dsq-widget">'
|
95
|
+
s << opts[:header]
|
96
|
+
s << '<script type="text/javascript" src="'
|
97
|
+
s << TOP
|
98
|
+
s << '&hide_avatars=1' if opts[:hide_avatars]
|
99
|
+
s << '&hide_mods=1' if opts[:hide_mods]
|
100
|
+
s << '"></script>'
|
101
|
+
s << '</div>'
|
102
|
+
if opts[:show_powered_by]
|
103
|
+
s << '<a href="http://disqus.com">Powered by Disqus</a>'
|
104
|
+
end
|
105
|
+
s % [opts[:account], opts[:num_items], opts[:avatar_size], opts[:orientation]]
|
106
|
+
end
|
107
|
+
|
108
|
+
# Show the popular threads Disqus widget.
|
109
|
+
# Options:
|
110
|
+
# * <tt>account:</tt> Your Discus account (required).
|
111
|
+
# * <tt>header:</tt> HTML snipper with header (default h2) tag and text.
|
112
|
+
# * <tt>num_items:</tt>: How many items to show.
|
113
|
+
# * <tt>hide_mods:</tt> Don't show moderators.
|
114
|
+
def popular_threads(opts = {})
|
115
|
+
opts = Disqus::defaults.merge(opts)
|
116
|
+
opts[:header] ||= '<h2 class="dsq-widget-title">Popular Threads</h2>'
|
117
|
+
validate_opts!(opts)
|
118
|
+
s = '<div id="dsq-popthreads" class="dsq-widget">'
|
119
|
+
s << opts[:header]
|
120
|
+
s << '<script type="text/javascript" src="'
|
121
|
+
s << POPULAR
|
122
|
+
s << '&hide_mods=1' if opts[:hide_mods]
|
123
|
+
s << '"></script>'
|
124
|
+
s << '</div>'
|
125
|
+
s << '<a href="http://disqus.com">Powered by Disqus</a>' if opts[:show_powered_by]
|
126
|
+
s % [opts[:account], opts[:num_items]]
|
127
|
+
end
|
128
|
+
|
129
|
+
# Show the recent comments Disqus widget.
|
130
|
+
# Options:
|
131
|
+
# * <tt>account:</tt> Your Discus account (required).
|
132
|
+
# * <tt>header:</tt> HTML snipper with header (default h2) tag and text.
|
133
|
+
# * <tt>num_items:</tt>: How many items to show.
|
134
|
+
# * <tt>hide_avatars:</tt> Don't show avatars.
|
135
|
+
# * <tt>avatar_size:</tt> Avatar size.
|
136
|
+
def recent_comments(opts = {})
|
137
|
+
opts = Disqus::defaults.merge(opts)
|
138
|
+
opts[:header] ||= '<h2 class="dsq-widget-title">Recent Comments</h2>'
|
139
|
+
validate_opts!(opts)
|
140
|
+
s = '<div id="dsq-recentcomments" class="dsq-widget">'
|
141
|
+
s << opts[:header]
|
142
|
+
s << '<script type="text/javascript" src="'
|
143
|
+
s << RECENT
|
144
|
+
s << '&hide_avatars=1' if opts[:hide_avatars]
|
145
|
+
s << '"></script>'
|
146
|
+
s << '</div>'
|
147
|
+
if opts[:show_powered_by]
|
148
|
+
s << '<a href="http://disqus.com">Powered by Disqus</a>'
|
149
|
+
end
|
150
|
+
s % [opts[:account], opts[:num_items], opts[:avatar_size]]
|
151
|
+
end
|
152
|
+
|
153
|
+
# Show the Disqus combo widget. This is a three-tabbed box with links
|
154
|
+
# popular threads, top posters, and recent threads.
|
155
|
+
# Options:
|
156
|
+
# * <tt>:account:</tt> Your Discus account (required).
|
157
|
+
# * <tt>:num_items:</tt> How many items to show.
|
158
|
+
# * <tt>:hide_mods:</tt> Don't show moderators.
|
159
|
+
# * <tt>:default_tab:</tt> Should be 'people', 'recent', or 'popular'.
|
160
|
+
def combo(opts = {})
|
161
|
+
opts = Disqus::defaults.merge(opts)
|
162
|
+
validate_opts!(opts)
|
163
|
+
s = '<script type="text/javascript" src="'
|
164
|
+
s << COMBO
|
165
|
+
s << '&hide_mods=1' if opts[:hide_mods]
|
166
|
+
s << '"></script>'
|
167
|
+
s % [opts[:account], opts[:num_items], opts[:color], opts[:default_tab]]
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
def validate_opts!(opts)
|
173
|
+
raise ArgumentError.new("You must specify an :account") if !opts[:account]
|
174
|
+
raise ArgumentError.new("Invalid color") if opts[:color] && !VALID_COLORS.include?(opts[:color])
|
175
|
+
raise ArgumentError.new("Invalid num_items") if opts[:num_items] && !VALID_NUM_ITEMS.include?(opts[:num_items])
|
176
|
+
raise ArgumentError.new("Invalid default_tab") if opts[:default_tab] && !VALID_DEFAULT_TABS.include?(opts[:default_tab])
|
177
|
+
raise ArgumentError.new("Invalid avatar size") if opts[:avatar_size] && !VALID_AVATAR_SIZES.include?(opts[:avatar_size])
|
178
|
+
raise ArgumentError.new("Invalid orientation") if opts[:orientation] && !VALID_ORIENTATIONS.include?(opts[:orientation])
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
data/lib/disqussion.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'disqussion/error'
|
2
|
+
require 'disqussion/configuration'
|
3
|
+
require 'disqussion/api'
|
4
|
+
require 'disqussion/client'
|
5
|
+
|
6
|
+
module Disqussion
|
7
|
+
extend Configuration
|
8
|
+
|
9
|
+
# Alias for Disqussion::Client.new
|
10
|
+
#
|
11
|
+
# @return [Disqussion::Client]
|
12
|
+
def self.client(options={})
|
13
|
+
Disqussion::Client.new(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Delegate to Disqussion::Client
|
17
|
+
def self.method_missing(method, *args, &block)
|
18
|
+
return super unless client.respond_to?(method)
|
19
|
+
client.send(method, *args, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.respond_to?(method, include_private = false)
|
23
|
+
client.respond_to?(method, include_private) || super(method, include_private)
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
# @private
|
4
|
+
module Faraday
|
5
|
+
# @private
|
6
|
+
class Response::RaiseHttp4xx < Response::Middleware
|
7
|
+
def on_complete(env)
|
8
|
+
case env[:status].to_i
|
9
|
+
when 400
|
10
|
+
raise Disqussion::BadRequest.new(error_message(env), env[:response_headers])
|
11
|
+
when 401
|
12
|
+
raise Disqussion::Unauthorized.new(error_message(env), env[:response_headers])
|
13
|
+
when 403
|
14
|
+
raise Disqussion::Forbidden.new(error_message(env), env[:response_headers])
|
15
|
+
when 404
|
16
|
+
raise Disqussion::NotFound.new(error_message(env), env[:response_headers])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def error_message(env)
|
23
|
+
"#{env[:method].to_s.upcase} #{env[:url].to_s}: #{env[:status]}#{error_body(env[:body])}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def error_body(body)
|
27
|
+
if body.nil?
|
28
|
+
nil
|
29
|
+
elsif body['error']
|
30
|
+
": #{body['error']}"
|
31
|
+
elsif body['errors']
|
32
|
+
first = body['errors'].to_a.first
|
33
|
+
if first.kind_of? Hash
|
34
|
+
": #{first['message'].chomp}"
|
35
|
+
else
|
36
|
+
": #{first.chomp}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
# @private
|
4
|
+
module Faraday
|
5
|
+
# @private
|
6
|
+
class Response::RaiseHttp5xx < Response::Middleware
|
7
|
+
def on_complete(env)
|
8
|
+
case env[:status].to_i
|
9
|
+
when 500
|
10
|
+
raise Disqussion::InternalServerError.new(error_message(env, "Something is technically wrong."), env[:response_headers])
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def error_message(env, body=nil)
|
17
|
+
"#{env[:method].to_s.upcase} #{env[:url].to_s}: #{[env[:status].to_s + ':', body].compact.join(' ')} Check http://status.disqus.com/ for updates on the status of the Disqus service."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|