Skip to content

Commit

Permalink
💎 Add support for the Assert API (#51)
Browse files Browse the repository at this point in the history
* New :assertion option in initialize opts
* New override_assertion parameter in post to override the assert parameter and not throw an error.
* New NotLoggedInError and NotBotError for the according assertions
* user_bot? no longer has a parameter. It now queries with an assertion rather than checking user groups.
* New logged_in? method to check if the user is currently logged in.
  • Loading branch information
elifoster authored Oct 18, 2016
1 parent e46acb5 commit 2d8bbfc
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 17 deletions.
4 changes: 2 additions & 2 deletions lib/mediawiki/auth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def login(username, password, token = nil)
header = {}
header['Set-Cookie'] = @cookie if @cookie

response = post(params, true, header)
response = post(params, true, header, true)
result = response['login']['result']

if result == 'NeedToken'
Expand Down Expand Up @@ -50,7 +50,7 @@ def logout
action: 'logout'
}

post(params)
post(params, true, nil, true)
@logged_in = false

true
Expand Down
48 changes: 39 additions & 9 deletions lib/mediawiki/butt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Butt

attr_accessor :query_limit_default
attr_accessor :use_continuation
attr_accessor :assertion

# Creates a new instance of MediaWiki::Butt.
# @param url [String] The FULL wiki URL. api.php can be omitted, but it will make harsh assumptions about
Expand All @@ -36,6 +37,10 @@ class Butt
# use that, otherwise, it will use this. Defaults to 500. It can be set to 'max' to use MW's default max for
# each API.
# @option opts [Boolean] :use_continuation Whether to use the continuation API on queries.
# @option opts [Symbol] :assertion If set to :user or :bot, will use the assert parameter in all requests.
# Setting this will open up the possibility for NotLoggedInErrors and NotBotErrors. It is important to keep in
# mind that methods that check if the user is logged in do not use the API, but check if the user has *ever*
# logged in as this Butt instance. In other words, it is a safety check for performance and not a valid API check.
def initialize(url, opts = {})
@url = url =~ /api.php$/ ? url : "#{url}/api.php"
@query_limit_default = opts[:query_limit_default] || 500
Expand All @@ -44,6 +49,9 @@ def initialize(url, opts = {})
@logged_in = false
@custom_agent = opts[:custom_agent]
@use_continuation = opts[:use_continuation]

assertion = opts[:assertion]
@assertion = assertion == :user || assertion == :bot ? assertion : nil
end

# Performs a generic HTTP POST request and provides the response. This method generally should not be used by the
Expand All @@ -52,19 +60,30 @@ def initialize(url, opts = {})
# information.
# @param autoparse [Boolean] Whether or not to provide a parsed version of the response's JSON.
# @param header [Hash] The header hash. Optional.
# @param override_assertion [Boolean] Whether to override the @assertion check. This is used in #login because
# that can never be done while already logged in.
# @since 0.1.0
# @return [Hash] Parsed JSON if autoparse is true.
# @return [HTTPMessage] Raw HTTP response if autoparse is not true.
def post(params, autoparse = true, header = nil)
def post(params, autoparse = true, header = nil, override_assertion = false)
params[:format] = 'json'
params[:assert] = @assertion.to_s if @assertion && !override_assertion && !params.key?(:assert)
header = {} if header.nil?

header['User-Agent'] = @logged_in ? "#{@name}/MediaWiki::Butt" : 'NotLoggedIn/MediaWiki::Butt'
header['User-Agent'] = @custom_agent if defined? @custom_agent

res = @client.post(@uri, params, header)

autoparse ? JSON.parse(res.body) : res
return res unless autoparse
parsed = JSON.parse(res.body)

if !override_assertion || @assertion
code = parsed.dig('error', 'code')
fail MediaWiki::Butt::NotLoggedInError.new(parsed['error']['info']) if code == 'assertuserfailed'
fail MediaWiki::Butt::NotBotError.new(parsed['error']['info']) if code == 'assertbotfailed'
end
parsed
end

# Performs a Mediawiki API query and provides the response, dealing with continuation as necessary.
Expand Down Expand Up @@ -112,18 +131,29 @@ def query_ary(params, base_response_key, property_key)
end

# Gets whether the currently logged in user is a bot.
# @param username [String] The username to check. Optional. Defaults to
# the currently logged in user if nil.
# @return [Boolean] true if logged in as a bot, false if not logged in or
# logged in as a non-bot
# @since 0.1.0 as is_current_user_bot
# @since 0.3.0 as is_user_bot?
# @since 0.4.1 as user_bot?
def user_bot?(username = nil)
groups = false
name = username || @name
groups = get_usergroups(name) if name
groups && groups.include?('bot')
def user_bot?
begin
post({ action: 'query', assert: 'bot' })
true
rescue MediaWiki::Butt::NotBotError
false
end
end

# Checks whether this instance is logged in.
# @return [Boolean] true if logged in, false if not.
def logged_in?
begin
post({ action: 'query', assert: 'user' })
true
rescue MediaWiki::Butt::NotLoggedInError
false
end
end

protected
Expand Down
2 changes: 2 additions & 0 deletions lib/mediawiki/exceptions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ class Butt
class AuthenticationError < StandardError; end
class EditError < StandardError; end
class BlockError < StandardError; end
class NotLoggedInError < StandardError; end
class NotBotError < StandardError; end
end
end
16 changes: 10 additions & 6 deletions spec/util_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,19 @@ class Butt
describe 'MediaWiki::Query' do
describe '#get_limited' do
it 'uses default maximums to limit the value' do
MW_BUTT_NO_URL.get_limited(500).must_equal(500)
MW_BUTT_NO_URL.get_limited(400).must_equal(400)
MW_BUTT_NO_URL.get_limited(600).must_equal(500)
MW_BUTT_NO_URL.stub(:user_bot?, false) do
MW_BUTT_NO_URL.get_limited(500).must_equal(500)
MW_BUTT_NO_URL.get_limited(400).must_equal(400)
MW_BUTT_NO_URL.get_limited(600).must_equal(500)
end
end

it 'uses custom user maximum values to limit the value' do
MW_BUTT_NO_URL.get_limited(400, 600).must_equal(400)
MW_BUTT_NO_URL.get_limited(600, 600).must_equal(600)
MW_BUTT_NO_URL.get_limited(700, 600).must_equal(600)
MW_BUTT_NO_URL.stub(:user_bot?, false) do
MW_BUTT_NO_URL.get_limited(400, 600).must_equal(400)
MW_BUTT_NO_URL.get_limited(600, 600).must_equal(600)
MW_BUTT_NO_URL.get_limited(700, 600).must_equal(600)
end
end

it 'limits the value while using a bot account' do
Expand Down

0 comments on commit 2d8bbfc

Please sign in to comment.