lib/media_wiki/gateway.rb in mediawiki-gateway-0.4.4 vs lib/media_wiki/gateway.rb in mediawiki-gateway-0.4.5

- old
+ new

@@ -14,10 +14,11 @@ # # [url] Path to API of target MediaWiki (eg. "http://en.wikipedia.org/w/api.php") # [options] Hash of options # # Options: + # [:bot] When set to true, executes API queries with the bot parameter (see http://www.mediawiki.org/wiki/API:Edit#Parameters). Defaults to false. # [:ignorewarnings] Log API warnings and invalid page titles, instead throwing MediaWiki::APIError # [:limit] Maximum number of results returned per search (see http://www.mediawiki.org/wiki/API:Query_-_Lists#Limits), defaults to the MediaWiki default of 500. # [:loglevel] Log level to use, defaults to Logger::WARN. Set to Logger::DEBUG to dump every request and response to the log. # [:maxlag] Maximum allowed server lag (see http://www.mediawiki.org/wiki/Manual:Maxlag_parameter), defaults to 5 seconds. # [:retry_count] Number of times to try before giving up if MediaWiki returns 503 Service Unavailable, defaults to 3 (original request plus two retries). @@ -26,11 +27,12 @@ default_options = { :limit => 500, :loglevel => Logger::WARN, :maxlag => 5, :retry_count => 3, - :retry_delay => 10 + :retry_delay => 10, + :bot => false } @options = default_options.merge(options) @wiki_url = url @log = Logger.new(STDERR) @log.level = @options[:loglevel] @@ -139,10 +141,71 @@ # Same options as create, but always overwrites existing pages (and creates them if they don't exist already). def edit(title, content, options={}) create(title, content, {:overwrite => true}.merge(options)) end + # Protect/unprotect a page + # + # Arguments: + # * [title] Page title to protect, string + # * [protections] Protections to apply, hash or array of hashes + # + # Protections: + # * [:action] (required) The action to protect, string + # * [:group] (required) The group allowed to perform the action, string + # * [:expiry] The protection expiry as a GNU timestamp, string + # + # * [options] Hash of additional options + # + # Options: + # * [:cascade] Protect pages included in this page, boolean + # * [:reason] Reason for protection, string + # + # Examples: + # 1. mw.protect('Main Page', {:action => 'edit', :group => 'all'}, {:cascade => true}) + # 2. prt = [{:action => 'move', :group => 'sysop', :expiry => 'never'}, + # {:action => 'edit', :group => 'autoconfirmed', :expiry => 'next Monday 16:04:57'}] + # mw.protect('Main Page', prt, {:reason => 'awesomeness'}) + # + def protect(title, protections, options={}) + # validate and format protections + protections = [protections] if protections.is_a?(Hash) + raise ArgumentError.new("Invalid type '#{protections.class}' for protections") unless protections.is_a?(Array) + valid_prt_options = %w(action group expiry) + required_prt_options = %w(action group) + p,e = [],[] + protections.each do |prt| + existing_prt_options = [] + prt.keys.each do |opt| + if valid_prt_options.include?(opt.to_s) + existing_prt_options.push(opt.to_s) + else + raise ArgumentError.new("Unknown option '#{opt}' for protections") + end + end + required_prt_options.each{|opt| raise ArgumentError.new("Missing required option '#{opt}' for protections") unless existing_prt_options.include?(opt)} + p.push("#{prt[:action]}=#{prt[:group]}") + if prt.has_key?(:expiry) + e.push(prt[:expiry].to_s) + else + e.push('never') + end + end + + # validate options + valid_options = %w(cascade reason) + options.keys.each{|opt| raise ArgumentError.new("Unknown option '#{opt}'") unless valid_options.include?(opt.to_s)} + + # make API request + form_data = {'action' => 'protect', 'title' => title, 'token' => get_token('protect', title)} + form_data['protections'] = p.join('|') + form_data['expiry'] = e.join('|') + form_data['cascade'] = '' if options[:cascade] === true + form_data['reason'] = options[:reason].to_s if options[:reason] + make_api_request(form_data) + end + # Move a page to a new title # # [from] Old page name # [to] New page name # [options] Hash of additional options @@ -499,11 +562,11 @@ res end private - # Fetch token (type 'delete', 'edit', 'import', 'move') + # Fetch token (type 'delete', 'edit', 'import', 'move', 'protect') def get_token(type, page_titles) form_data = {'action' => 'query', 'prop' => 'info', 'intoken' => type, 'titles' => page_titles} res, dummy = make_api_request(form_data) token = res.elements["query/pages/page"].attributes[type + "token"] raise Unauthorized.new "User is not permitted to perform this operation: #{type}" if token.nil? @@ -567,9 +630,10 @@ # Returns XML document def make_api_request(form_data, continue_xpath=nil, retry_count=1) if form_data.kind_of? Hash form_data['format'] = 'xml' form_data['maxlag'] = @options[:maxlag] + form_data['bot']="1" if @options[:bot] end log.debug("REQ: #{form_data.inspect}, #{@cookies.inspect}") RestClient.post(@wiki_url, form_data, @headers.merge({:cookies => @cookies})) do |response, &block| if response.code == 503 and retry_count < @options[:retry_count] log.warn("503 Service Unavailable: #{response.body}. Retry in #{@options[:retry_delay]} seconds.")