class MediawikiApi::Client

high level client for MediaWiki

Constants

FORMAT

Attributes

cookies[R]
logged_in[RW]
logged_in?[RW]

Public Class Methods

new(url, log = false) click to toggle source
# File lib/mediawiki_api/client.rb, line 19
def initialize(url, log = false)
  @cookies = HTTP::CookieJar.new

  @conn = Faraday.new(url: url) do |faraday|
    faraday.request :multipart
    faraday.request :url_encoded
    faraday.response :logger if log
    faraday.use :cookie_jar, jar: @cookies
    faraday.use FaradayMiddleware::FollowRedirects
    faraday.adapter Faraday.default_adapter
  end

  @logged_in = false
  @tokens = {}
end

Public Instance Methods

action(name, params = {}) click to toggle source
# File lib/mediawiki_api/client.rb, line 35
def action(name, params = {})
  raw_action(name, params)
rescue ApiError => e
  if e.code == 'badtoken'
    @tokens.clear # ensure fresh token on re-try
    raw_action(name, params) # no rescue this time; only re-try once.
  else
    raise # otherwise, propagate the exception
  end
end
create_account(username, password) click to toggle source
# File lib/mediawiki_api/client.rb, line 46
def create_account(username, password)
  params = { modules: 'createaccount', token_type: false }
  d = action(:paraminfo, params).data
  params = d['modules'] && d['modules'][0] && d['modules'][0]['parameters']
  if !params || !params.map
    raise CreateAccountError, 'unexpected API response format'
  end
  params = params.map{ |o| o['name'] }

  if params.include? 'requests'
    create_account_new(username, password)
  else
    create_account_old(username, password)
  end
end
create_account_new(username, password) click to toggle source
# File lib/mediawiki_api/client.rb, line 62
def create_account_new(username, password)
  # post-AuthManager
  data = action(:query, { meta: 'tokens', type: 'createaccount', token_type: false }).data
  token = data['tokens'] && data['tokens']['createaccounttoken']
  unless token
    raise CreateAccountError, 'failed to get createaccount API token'
  end

  data = action(:createaccount, {
    username: username,
    password: password,
    retype: password,
    createreturnurl: 'http://example.com', # won't be used but must be a valid URL
    createtoken: token,
    token_type: false
  }).data
  raise CreateAccountError, data['message'] if data['status'] != 'PASS'
  data
end
create_account_old(username, password, token = nil) click to toggle source
# File lib/mediawiki_api/client.rb, line 82
def create_account_old(username, password, token = nil)
  # pre-AuthManager
  params = { name: username, password: password, token_type: false }
  params[:token] = token unless token.nil?

  data = action(:createaccount, params).data

  case data['result']
  when 'Success'
    @logged_in = true
    @tokens.clear
  when 'NeedToken'
    data = create_account_old(username, password, data['token'])
  else
    raise CreateAccountError, data['result']
  end

  data
end
create_page(title, content) click to toggle source
# File lib/mediawiki_api/client.rb, line 102
def create_page(title, content)
  edit(title: title, text: content)
end
delete_page(title, reason) click to toggle source
# File lib/mediawiki_api/client.rb, line 106
def delete_page(title, reason)
  action(:delete, title: title, reason: reason)
end
edit(params = {}) click to toggle source
# File lib/mediawiki_api/client.rb, line 110
def edit(params = {})
  response = action(:edit, params)
  raise EditError, response if response.data['result'] == 'Failure'
  response
end
get_wikitext(title) click to toggle source
# File lib/mediawiki_api/client.rb, line 116
def get_wikitext(title)
  @conn.get '/w/index.php', action: 'raw', title: title
end
list(type, params = {}) click to toggle source
# File lib/mediawiki_api/client.rb, line 120
def list(type, params = {})
  subquery(:list, type, params)
end
log_in(username, password, token = nil) click to toggle source
# File lib/mediawiki_api/client.rb, line 124
def log_in(username, password, token = nil)
  params = { lgname: username, lgpassword: password, token_type: false }
  params[:lgtoken] = token unless token.nil?

  data = action(:login, params).data

  case data['result']
  when 'Success'
    @logged_in = true
    @tokens.clear
  when 'NeedToken'
    raise LoginError, "failed to log in with the returned token '#{token}'" unless token.nil?
    data = log_in(username, password, data['token'])
  else
    raise LoginError, data['result']
  end

  data
end
meta(type, params = {}) click to toggle source
# File lib/mediawiki_api/client.rb, line 144
def meta(type, params = {})
  subquery(:meta, type, params)
end
prop(type, params = {}) click to toggle source
# File lib/mediawiki_api/client.rb, line 148
def prop(type, params = {})
  subquery(:prop, type, params)
end
protect_page(title, reason, protections = 'edit=sysop|move=sysop') click to toggle source
# File lib/mediawiki_api/client.rb, line 152
def protect_page(title, reason, protections = 'edit=sysop|move=sysop')
  action(:protect, title: title, reason: reason, protections: protections)
end
query(params = {}) click to toggle source
# File lib/mediawiki_api/client.rb, line 156
def query(params = {})
  action(:query, { token_type: false, http_method: :get }.merge(params))
end
unwatch_page(title) click to toggle source
# File lib/mediawiki_api/client.rb, line 160
def unwatch_page(title)
  action(:watch, token_type: 'watch', titles: title, unwatch: true)
end
upload_image(filename, path, comment, ignorewarnings, text = nil) click to toggle source
# File lib/mediawiki_api/client.rb, line 164
def upload_image(filename, path, comment, ignorewarnings, text = nil)
  file = Faraday::UploadIO.new(path, 'image/png')
  action(:upload,
         filename: filename, file: file, comment: comment, text: text,
         ignorewarnings: ignorewarnings)
end
watch_page(title) click to toggle source
# File lib/mediawiki_api/client.rb, line 171
def watch_page(title)
  action(:watch, token_type: 'watch', titles: title)
end

Protected Instance Methods

compile_parameters(parameters) click to toggle source
# File lib/mediawiki_api/client.rb, line 177
def compile_parameters(parameters)
  parameters.each.with_object({}) do |(name, value), params|
    case value
    when false
      # omit it entirely
    when Array
      params[name] = value.join('|')
    else
      params[name] = value
    end
  end
end
get_token(type) click to toggle source
# File lib/mediawiki_api/client.rb, line 190
def get_token(type)
  unless @tokens.include?(type)
    response = query(meta: 'tokens', type: type)
    parameter_warning = /Unrecognized value for parameter 'type'/

    if response.warnings? && response.warnings.grep(parameter_warning).any?
      raise TokenError, response.warnings.join(', ')
    end

    @tokens[type] = response.data['tokens']["#{type}token"]
  end

  @tokens[type]
end
raw_action(name, params = {}) click to toggle source
# File lib/mediawiki_api/client.rb, line 221
def raw_action(name, params = {})
  name = name.to_s
  params = params.clone

  method = params.delete(:http_method) || :post
  token_type = params.delete(:token_type)
  envelope = (params.delete(:envelope) || [name]).map(&:to_s)

  params[:token] = get_token(token_type || :csrf) unless token_type == false
  params = compile_parameters(params)

  send_request(method, params.merge(action: name, format: FORMAT), envelope)
end
send_request(method, params, envelope) click to toggle source
# File lib/mediawiki_api/client.rb, line 205
def send_request(method, params, envelope)
  response = @conn.send(method, '', params)

  raise HttpError, response.status if response.status >= 400

  if response.headers.include?('mediawiki-api-error')
    raise ApiError, Response.new(response, ['error'])
  end

  Response.new(response, envelope)
end
subquery(type, subtype, params = {}) click to toggle source
# File lib/mediawiki_api/client.rb, line 217
def subquery(type, subtype, params = {})
  query(params.merge(type.to_sym => subtype, :envelope => ['query', subtype]))
end