From a594c970a2f9104a0517b6953a6683ebf9f020de Mon Sep 17 00:00:00 2001 From: elifoster Date: Thu, 1 Oct 2015 17:09:56 -0700 Subject: [PATCH] New edit and query actions. Some minor refactors to fix some stuff. We now require my new gem string-utility for edit count formatting. --- CHANGELOG.md | 11 +++++ lib/mediawiki/butt.rb | 16 ++++-- lib/mediawiki/edit.rb | 68 ++++++++++++++++++++++++-- lib/mediawiki/query.rb | 108 +++++++++++++++++++++++++++++++---------- mediawiki-butt.gemspec | 14 ++---- 5 files changed, 175 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 952875c..53d7d12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog ## Version 0 +### Version 0.3.0 +* New upload method to upload by URL. +* New create_page method. +* New get_userlists method. +* New get_usergroups method. +* New get_contrib_count method. +* Refactor get_usergroups and is_current_user_bot? to use new get_userinfo method. +* Minor refactors to make optional arguments more Ruby-like with splat arguments. +* #edit no longer prints the edit token, because that's stupid. +* #edit no longer sets the summary if it is nil. + ### Version 0.2.1 * Fix gemspec. You should actually have the new stuff now. diff --git a/lib/mediawiki/butt.rb b/lib/mediawiki/butt.rb index ee078ca..2c20468 100644 --- a/lib/mediawiki/butt.rb +++ b/lib/mediawiki/butt.rb @@ -40,7 +40,11 @@ def initialize(url, use_ssl = true) # @param header [Hash] The header hash. Optional. # @return [JSON/HTTPMessage] Parsed JSON if autoparse is true, or raw response if not. def post(params, autoparse = true, header = nil) - if header == nil + # Note that defining the header argument as a splat argument (*header) causes errors in HTTPClient. + # We must use header.nil? rather than a splat argument and defined? header due to this error. + # For those interested, the error is: undefined method `downcase' for {"Set-Cookie"=>"cookie"}:Hash (NoMethodError) + # This is obvisouly an error in HTTPClient, but we must work around it until there is a fix in the gem. + if header.nil? response = @client.post(@uri, params) else response = @client.post(@uri, params, header) @@ -54,10 +58,16 @@ def post(params, autoparse = true, header = nil) end # Returns true if the currently logged in user is in the "bot" group. This can be helpful to some developers, but it is mostly for use internally in MediaWiki::Butt. + # @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 - def is_current_user_bot? - if @logged_in == true + def is_user_bot?(*username) + if defined? username + groups = get_usergroups(username) + else groups = get_usergroups + end + + if groups != false if groups.include? "bot" return true else diff --git a/lib/mediawiki/edit.rb b/lib/mediawiki/edit.rb index c902a17..04ac479 100644 --- a/lib/mediawiki/edit.rb +++ b/lib/mediawiki/edit.rb @@ -3,23 +3,22 @@ module Edit # Performs a standard edit. It cannot create pages. Please use create_page for that. # @param title [String] The page title. # @param text [String] The new content. - # @param summary [String] The edit summary. Optional. # @param minor [Boolean] Will mark the edit as minor if true. Defaults to false. # @param bot [Boolean] Will mark the edit as bot edit if true. Defualts to true, for your convenience, bot developers. + # @param summary [String] The edit summary. Optional. # @return [String] The new revision ID, or if it failed, the error code. - def edit(title, text, summary = nil, minor = false, bot = true) + def edit(title, text, minor = false, bot = true, *summary) params = { action: 'edit', title: title, - summary: summary, text: text, nocreate: 1, format: 'json' } token = get_edit_token(title) - puts token + params[:summary] = summary if defined? summary params[:minor] = '1' if minor == true params[:bot] = '1' if bot == true params[:token] = token @@ -32,5 +31,66 @@ def edit(title, text, summary = nil, minor = false, bot = true) return response["error"]["code"] end end + + # Creates a new page. + # @param title [String] The new page's title. + # @param text [String] The new page's content. + # @param summary [String] The edit summary. Defaults to "New page". + # @param bot [Boolean] Will mark the edit as a bot edit if true. Defaults to true, for your convenience, bot developers. + # @return [String] The new page ID, or if it failed, the error code. + def create_page(title, text, summary = "New page", bot = true) + params = { + action: 'edit', + title: title, + summary: summary, + text: text, + createonly: 1, + format: 'json' + } + + token = get_edit_token(title) + + params[:bot] = '1' if bot == true + params[:token] = token + + response = post(params) + + if response["error"]["code"].nil? + return response["edit"]["pageid"] + else + return response["error"]["code"] + end + end + + # Uploads a file from a URL. + # @param url [String] The URL to the file. + # @param filename [String] The preferred filename. This can include File: at the beginning, but it will be removed through regex. Optional. If ommitted, it will be everything after the last slash in the URL. + # @return [Boolean/String] true if the upload was successful, else the warning key. + def upload(url, *filename) + params = { + action: 'upload', + url: url, + format: 'json' + } + + if defined? filename + filename = filename.sub(/$File:/, "") + else + filename = url.split('/')[-1] + end + + token = get_edit_token(filename) + + params[:filename] = filename + params[:token] = token + + response = post(params) + if response["upload"]["result"] == "Success" + return true + elsif response["upload"]["result"] == "Warning" + warnings = response["upload"]["warnings"] + return warnings.keys[0] + end + end end end diff --git a/lib/mediawiki/query.rb b/lib/mediawiki/query.rb index cfd3fd7..be4529e 100644 --- a/lib/mediawiki/query.rb +++ b/lib/mediawiki/query.rb @@ -1,3 +1,5 @@ +require 'string-utility' + module MediaWiki module Query #TODO: Actually decide on a good way to deal with meta information queries. @@ -21,28 +23,6 @@ def get_filerepo_names end return ret end - - # Gets an array of all the currently logged in user's groups. - # @return [Array/Boolean] All of the user's groups, or false if not logged in. - def get_usergroups - if @logged_in == true - params = { - action: 'query', - meta: 'userinfo', - uiprop: 'groups', - format: 'json' - } - - result = post(params) - ret = Array.new - result["query"]["userinfo"]["groups"].each do |g| - ret.push(g) - end - return ret - else - return false - end - end end module Properties @@ -133,7 +113,7 @@ def what_links_here(title, limit = 500) } if limit > 500 - if is_current_user_bot? == true + if is_user_bot? == true if limit > 5000 params[:bllimit] = 5000 else @@ -162,7 +142,7 @@ def get_category_members(category, limit = 500) params = { action: 'query', list: 'categorymembers', - #cmprop: 'title', + cmprop: 'title', format: 'json' } @@ -173,7 +153,7 @@ def get_category_members(category, limit = 500) end if limit > 500 - if is_current_user_bot? == true + if is_user_bot? == true if limit > 5000 params[:cmlimit] = 5000 else @@ -208,7 +188,7 @@ def get_random_pages(number_of_pages = 1, namespace = 0) params[:rnnamespace] = namespace if namespace != nil if namespace > 10 - if is_current_user_bot? == true + if is_user_bot? == true if limit > 20 params[:rnlimit] = 20 else @@ -228,6 +208,82 @@ def get_random_pages(number_of_pages = 1, namespace = 0) end return ret end + + # Gets user information. This method should rarely be used by normal users. + # @param prop [String] The usprop parameter. + # @param username [String] The username to get info for. Optional. Defaults to the currently logged in user if ommitted. + # @return [String/Nil] Parsed full response if successful, nil if the username is nil and the Butt is not logged in. + def get_userlists(prop, username = nil) + params = { + action: 'query', + list: 'users', + usprop: prop, + format: 'json' + } + + if username.nil? + if @logged_in == true + response = post(params) + else + return nil + end + else + params[:ususers] = username + response = post(params) + end + + return response + end + + # Gets an array of all the currently logged in user's groups. + # @param username [String] The username to get groups of. Optional. Defaults to the currently logged in user. + # @return [Array/Boolean] All of the user's groups, or false if username is nil and Butt is not logged in. + def get_usergroups(username = nil) + if username.nil? + if @logged_in == true + info = get_userlists('groups') + else + return false + end + else + info = get_userlists('groups', username) + end + + ret = Array.new + info["query"]["users"].each do |i| + i["groups"].each do |g| + ret.push(g) + end + end + return ret + end + + # Gets contribution count for the user. + # @param username [String] The username to get the contribution count of. Optional. Defaults to the currently logged in user. + # @param autoparse [Boolean] Whether to automatically format the string with commas. Defaults to true. + # @return [Boolean/Int/String] False if username is nil and Butt is not logged in. An integer value of the contribution count if autoparse is false. A formatted string version of the contribution count if autoparse is true. + def get_contrib_count(username = nil, autoparse = true) + if username.nil? + if @logged_in == true + info = get_userlists('editcount') + else + return false + end + else + info = get_userlists('editcount', username) + end + + count = nil + info["query"]["users"].each do |i| + count = i["editcount"] + end + + if autoparse == true + countstring = StringUtility.separate_with(count.to_s) + return countstring + end + return count + end end end end diff --git a/mediawiki-butt.gemspec b/mediawiki-butt.gemspec index b5da537..94e615d 100644 --- a/mediawiki-butt.gemspec +++ b/mediawiki-butt.gemspec @@ -1,13 +1,8 @@ -deps = [ - "httpclient", - "json" -] - Gem::Specification.new do |s| s.authors = ['Eli Foster', 'Eric Schneider (xbony2)'] s.name = 'mediawiki-butt' s.summary = "Interacting with the MediaWiki API" - s.version = '0.2.1' + s.version = '0.3.0' s.license = 'CC-BY-NC-ND-4.0' # Expand on this description eventually. s.description = <<-EOF @@ -31,7 +26,8 @@ Gem::Specification.new do |s| "CHANGELOG.md" ] - deps.each do |dep| - s.add_runtime_dependency(dep) - end + # TODO: Figure out what version we should require for JSON and HTTPClient + s.add_runtime_dependency("string-utility", ">= 1.0.1") + s.add_runtime_dependency("json") + s.add_runtime_dependency("httpclient") end