lib/media_wiki/gateway.rb in mediawiki-gateway-0.5.2 vs lib/media_wiki/gateway.rb in mediawiki-gateway-0.6.0

- old
+ new

@@ -130,12 +130,21 @@ # # Options: # * [:overwrite] Allow overwriting existing pages # * [:summary] Edit summary for history, string # * [:token] Use this existing edit token instead requesting a new one (useful for bulk loads) + # * [:minor] Mark this edit as "minor" if true, mark this edit as "major" if false, leave major/minor status by default if not specified + # * [:notminor] Mark this edit as "major" if true + # * [:bot] Set the bot parameter (see http://www.mediawiki.org/wiki/API:Edit#Parameters). Defaults to false. def create(title, content, options={}) form_data = {'action' => 'edit', 'title' => title, 'text' => content, 'summary' => (options[:summary] || ""), 'token' => get_token('edit', title)} + if @options[:bot] or options[:bot] + form_data['bot'] = '1' + form_data['assert'] = 'bot' + end + form_data['minor'] = '1' if options[:minor] + form_data['notminor'] = '1' if options[:minor] == false or options[:notminor] form_data['createonly'] = "" unless options[:overwrite] form_data['section'] = options[:section].to_s if options[:section] make_api_request(form_data) end @@ -505,10 +514,56 @@ end else nil end end + + # Get list of interlanguage links for given article[s]. Follows redirects. Returns a hash like { 'id' => 'Yerusalem', 'en' => 'Jerusalem', ... } + # + # _article_or_pageid_ is the title or pageid of a single article + # _lllimit_ is the maximum number of langlinks to return (defaults to 500, the maximum) + # + # Example: + # langlinks = mw.langlinks('Jerusalem') + def langlinks(article_or_pageid, lllimit = 500) + form_data = {'action' => 'query', 'prop' => 'langlinks', 'lllimit' => lllimit, 'redirects' => true} + case article_or_pageid + when Fixnum + form_data['pageids'] = article_or_pageid + else + form_data['titles'] = article_or_pageid + end + xml, dummy = make_api_request(form_data) + page = xml.elements["query/pages/page"] + if valid_page? page + if xml.elements["query/redirects/r"] + # We're dealing with the redirect here. + langlinks(page.attributes["pageid"].to_i, lllimit) + else + langl = REXML::XPath.match(page, 'langlinks/ll') + if langl.nil? + nil + else + links = {} + langl.each{ |ll| links[ll.attributes["lang"]] = ll.children[0].to_s } + return links + end + end + else + nil + end + end + + # Convenience wrapper for _langlinks_ returning the title in language _lang_ (ISO code) for a given article of pageid, if it exists, via the interlanguage link + # + # Example: + # + # langlink = mw.langlink_for_lang('Tycho Brahe', 'de') + def langlink_for_lang(article_or_pageid, lang) + return langlinks(article_or_pageid)[lang] + end + # Requests image info from MediaWiki. Follows redirects. # # _file_name_or_page_id_ should be either: # * a file name (String) you want info about without File: prefix. # * or a Fixnum page id you of the file. @@ -663,10 +718,44 @@ else raise MediaWiki::Exception.new "Semantic MediaWiki extension not installed." end end + # Create a new account + # + # [options] is +Hash+ passed as query arguments. See https://www.mediawiki.org/wiki/API:Account_creation#Parameters for more information. + def create_account(options) + form_data = options.merge({ 'action' => 'createaccount' }) + res, dummy = make_api_request(form_data) + res + end + + # Sets options for currenlty logged in user + # + # [changes] a +Hash+ that will be transformed into an equal sign and pipe-separated key value parameter + # [optionname] a +String+ indicating which option to change (optional) + # [optionvalue] the new value for optionname - allows pipe characters (optional) + # [reset] a +Boolean+ indicating if all preferences should be reset to site defaults (optional) + def options(changes = {}, optionname = nil, optionvalue = nil, reset = false) + form_data = { 'action' => 'options', 'token' => get_options_token } + + if changes.present? + form_data['change'] = changes.map { |key, value| "#{key}=#{value}" }.join('|') + end + + if optionname.present? + form_data[optionname] = optionvalue + end + + if reset + form_data['reset'] = true + end + + res, dummy = make_api_request(form_data) + res + end + # Set groups for a user # # [user] Username of user to modify # [groups_to_add] Groups to add user to, as an array or a string if a single group (optional) # [groups_to_remove] Groups to remove user from, as an array or a string if a single group (optional) @@ -727,10 +816,16 @@ end token end + def get_options_token + form_data = { 'action' => 'tokens', 'type' => 'options' } + res, dummy = make_api_request(form_data) + res.elements['tokens'].attributes['optionstoken'] + end + def userrights(user, token, groups_to_add, groups_to_remove, reason) # groups_to_add and groups_to_remove can be a string or an array. Turn them into MediaWiki's pipe-delimited list format. if groups_to_add.is_a? Array groups_to_add = groups_to_add.join('|') end @@ -782,29 +877,45 @@ # 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 http_send(@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.") sleep @options[:retry_delay] make_api_request(form_data, continue_xpath, retry_count + 1) end # Check response for errors and return XML raise MediaWiki::Exception.new "Bad response: #{response}" unless response.code >= 200 and response.code < 300 doc = get_response(response.dup) - if(form_data['action'] == 'login') - login_result = doc.elements["login"].attributes['result'] + action = form_data['action'] + + # login and createaccount actions require a second request with a token received on the first request + if %w(login createaccount).include?(action) + action_result = doc.elements[action].attributes['result'] @cookies.merge!(response.cookies) - case login_result - when "Success" then # do nothing - when "NeedToken" then make_api_request(form_data.merge('lgtoken' => doc.elements["login"].attributes["token"])) - else raise Unauthorized.new "Login failed: " + login_result - end + + case action_result.downcase + when "success" then + return [doc, false] + when "needtoken" + token = doc.elements[action].attributes["token"] + if action == 'login' + return make_api_request(form_data.merge('lgtoken' => token)) + elsif action == 'createaccount' + return make_api_request(form_data.merge('token' => token)) + end + else + if action == 'login' + raise Unauthorized.new("Login failed: #{action_result}") + elsif action == 'createaccount' + raise Unauthorized.new("Account creation failed: #{action_result}") + end + end end + continue = (continue_xpath and doc.elements['query-continue']) ? REXML::XPath.first(doc, continue_xpath).value : nil return [doc, continue] end end