Reedy has submitted this change and it was merged. Change subject: Initial version of script to automatically upload changelogs to mw.org ......................................................................
Initial version of script to automatically upload changelogs to mw.org Uses botclasses.php https://toolserver.org/~chris/highlight.php?d=chris%2Fclasses%2F&f=botclasses.php Change-Id: Ib50c47b4229c8f7680516e307db180a076f725ba --- A make-deploy-notes/botclasses.php A make-deploy-notes/uploadChangelog.php 2 files changed, 1,043 insertions(+), 0 deletions(-) Approvals: Reedy: Verified; Looks good to me, approved diff --git a/make-deploy-notes/botclasses.php b/make-deploy-notes/botclasses.php new file mode 100644 index 0000000..3fec204 --- /dev/null +++ b/make-deploy-notes/botclasses.php @@ -0,0 +1,959 @@ +<?php +/** + * botclasses.php - Bot classes for interacting with mediawiki. + * + * (c) 2008-2012 Chris G - http://en.wikipedia.org/wiki/User:Chris_G + * (c) 2009-2010 Fale - http://en.wikipedia.org/wiki/User:Fale + * (c) 2010 Kaldari - http://en.wikipedia.org/wiki/User:Kaldari + * (c) 2011 Gutza - http://en.wikipedia.org/wiki/User:Gutza + * (c) 2012 Sean - http://en.wikipedia.org/wiki/User:SColombo + * (c) 2012 Brain - http://en.wikipedia.org/wiki/User:Brian_McNeil + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Developers (add yourself here if you worked on the code): + * Cobi - [[User:Cobi]] - Wrote the http class and some of the wikipedia class + * Chris - [[User:Chris_G]] - Wrote the most of the wikipedia class + * Fale - [[User:Fale]] - Polish, wrote the extended and some of the wikipedia class + * Kaldari - [[User:Kaldari]] - Submitted a patch for the imagematches function + * Gutza - [[User:Gutza]] - Submitted a patch for http->setHTTPcreds(), and http->quiet + * Sean - [[User:SColombo]] - Wrote the lyricwiki class (now moved to lyricswiki.php) + * Brain - [[User:Brian_McNeil]] - Wrote wikipedia->getfileuploader() and wikipedia->getfilelocation + **/ + +/* + * Forks/Alternative versions: + * There's a couple of different versions of this code lying around. + * I'll try to list them here for reference purpopses: + * https://en.wikinews.org/wiki/User:NewsieBot/botclasses.php + */ + +/** + * This class is designed to provide a simplified interface to cURL which maintains cookies. + * @author Cobi + **/ +class http { + private $ch; + private $uid; + public $cookie_jar; + public $postfollowredirs; + public $getfollowredirs; + public $quiet=false; + + public function http_code () { + return curl_getinfo( $this->ch, CURLINFO_HTTP_CODE ); + } + + function data_encode ($data, $keyprefix = "", $keypostfix = "") { + assert( is_array($data) ); + $vars=null; + foreach($data as $key=>$value) { + if(is_array($value)) + $vars .= $this->data_encode($value, $keyprefix.$key.$keypostfix.urlencode("["), urlencode("]")); + else + $vars .= $keyprefix.$key.$keypostfix."=".urlencode($value)."&"; + } + return $vars; + } + + function __construct () { + $this->ch = curl_init(); + $this->uid = dechex(rand(0,99999999)); + curl_setopt($this->ch,CURLOPT_COOKIEJAR,'/tmp/cluewikibot.cookies.'.$this->uid.'.dat'); + curl_setopt($this->ch,CURLOPT_COOKIEFILE,'/tmp/cluewikibot.cookies.'.$this->uid.'.dat'); + curl_setopt($this->ch,CURLOPT_MAXCONNECTS,100); + curl_setopt($this->ch,CURLOPT_CLOSEPOLICY,CURLCLOSEPOLICY_LEAST_RECENTLY_USED); + $this->postfollowredirs = 0; + $this->getfollowredirs = 1; + $this->cookie_jar = array(); + } + + function post ($url,$data) { + //echo 'POST: '.$url."\n"; + $time = microtime(1); + curl_setopt($this->ch,CURLOPT_URL,$url); + curl_setopt($this->ch,CURLOPT_USERAGENT,'php wikibot classes'); + /* Crappy hack to add extra cookies, should be cleaned up */ + $cookies = null; + foreach ($this->cookie_jar as $name => $value) { + if (empty($cookies)) + $cookies = "$name=$value"; + else + $cookies .= "; $name=$value"; + } + if ($cookies != null) + curl_setopt($this->ch,CURLOPT_COOKIE,$cookies); + curl_setopt($this->ch,CURLOPT_FOLLOWLOCATION,$this->postfollowredirs); + curl_setopt($this->ch,CURLOPT_MAXREDIRS,10); + curl_setopt($this->ch, CURLOPT_HTTPHEADER, array('Expect:')); + curl_setopt($this->ch,CURLOPT_RETURNTRANSFER,1); + curl_setopt($this->ch,CURLOPT_TIMEOUT,30); + curl_setopt($this->ch,CURLOPT_CONNECTTIMEOUT,10); + curl_setopt($this->ch,CURLOPT_POST,1); +// curl_setopt($this->ch,CURLOPT_FAILONERROR,1); +// curl_setopt($this->ch,CURLOPT_POSTFIELDS, substr($this->data_encode($data), 0, -1) ); + curl_setopt($this->ch,CURLOPT_POSTFIELDS, $data); + $data = curl_exec($this->ch); +// echo "Error: ".curl_error($this->ch); +// var_dump($data); +// global $logfd; +// if (!is_resource($logfd)) { +// $logfd = fopen('php://stderr','w'); + if (!$this->quiet) + echo 'POST: '.$url.' ('.(microtime(1) - $time).' s) ('.strlen($data)." b)\n"; +// } + return $data; + } + + function get ($url) { + //echo 'GET: '.$url."\n"; + $time = microtime(1); + curl_setopt($this->ch,CURLOPT_URL,$url); + curl_setopt($this->ch,CURLOPT_USERAGENT,'php wikibot classes'); + /* Crappy hack to add extra cookies, should be cleaned up */ + $cookies = null; + foreach ($this->cookie_jar as $name => $value) { + if (empty($cookies)) + $cookies = "$name=$value"; + else + $cookies .= "; $name=$value"; + } + if ($cookies != null) + curl_setopt($this->ch,CURLOPT_COOKIE,$cookies); + curl_setopt($this->ch,CURLOPT_FOLLOWLOCATION,$this->getfollowredirs); + curl_setopt($this->ch,CURLOPT_MAXREDIRS,10); + curl_setopt($this->ch,CURLOPT_HEADER,0); + curl_setopt($this->ch,CURLOPT_RETURNTRANSFER,1); + curl_setopt($this->ch,CURLOPT_TIMEOUT,30); + curl_setopt($this->ch,CURLOPT_CONNECTTIMEOUT,10); + curl_setopt($this->ch,CURLOPT_HTTPGET,1); + //curl_setopt($this->ch,CURLOPT_FAILONERROR,1); + $data = curl_exec($this->ch); + //echo "Error: ".curl_error($this->ch); + //var_dump($data); + //global $logfd; + //if (!is_resource($logfd)) { + // $logfd = fopen('php://stderr','w'); + if (!$this->quiet) + echo 'GET: '.$url.' ('.(microtime(1) - $time).' s) ('.strlen($data)." b)\n"; + //} + return $data; + } + + function setHTTPcreds($uname,$pwd) { + curl_setopt($this->ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_setopt($this->ch, CURLOPT_USERPWD, $uname.":".$pwd); + } + + function __destruct () { + curl_close($this->ch); + @unlink('/tmp/cluewikibot.cookies.'.$this->uid.'.dat'); + } +} + +/** + * This class is interacts with wikipedia using api.php + * @author Chris G and Cobi + **/ +class wikipedia { + private $http; + private $token; + private $ecTimestamp; + public $url; + + /** + * This is our constructor. + * @return void + **/ + function __construct ($url='http://en.wikipedia.org/w/api.php',$hu=null,$hp=null) { + $this->http = new http; + $this->token = null; + $this->url = $url; + $this->ecTimestamp = null; + if ($hu!==null) + $this->http->setHTTPcreds($hu,$hp); + } + + function __set($var,$val) { + switch($var) { + case 'quiet': + $this->http->quiet=$val; + break; + default: + echo "WARNING: Unknown variable ($var)!\n"; + } + } + + /** + * Sends a query to the api. + * @param $query The query string. + * @param $post POST data if its a post request (optional). + * @return The api result. + **/ + function query ($query,$post=null,$repeat=0) { + if ($post==null) { + $ret = $this->http->get($this->url.$query); + } else { + $ret = $this->http->post($this->url.$query,$post); + } + if ($this->http->http_code() != "200") { + if ($repeat < 10) { + return $this->query($query,$post,++$repeat); + } else { + throw new Exception("HTTP Error."); + } + } + return unserialize($ret); + } + + /** + * Gets the content of a page. Returns false on error. + * @param $page The wikipedia page to fetch. + * @param $revid The revision id to fetch (optional) + * @return The wikitext for the page. + **/ + function getpage ($page,$revid=null,$detectEditConflict=false) { + $append = ''; + if ($revid!=null) + $append = '&rvstartid='.$revid; + $x = $this->query('?action=query&format=php&prop=revisions&titles='.urlencode($page).'&rvlimit=1&rvprop=content|timestamp'.$append); + foreach ($x['query']['pages'] as $ret) { + if (isset($ret['revisions'][0]['*'])) { + if ($detectEditConflict) + $this->ecTimestamp = $ret['revisions'][0]['timestamp']; + return $ret['revisions'][0]['*']; + } else + return false; + } + } + + /** + * Gets the page id for a page. + * @param $page The wikipedia page to get the id for. + * @return The page id of the page. + **/ + function getpageid ($page) { + $x = $this->query('?action=query&format=php&prop=revisions&titles='.urlencode($page).'&rvlimit=1&rvprop=content'); + foreach ($x['query']['pages'] as $ret) { + return $ret['pageid']; + } + } + + /** + * Gets the number of contributions a user has. + * @param $user The username for which to get the edit count. + * @return The number of contributions the user has. + **/ + function contribcount ($user) { + $x = $this->query('?action=query&list=allusers&format=php&auprop=editcount&aulimit=1&aufrom='.urlencode($user)); + return $x['query']['allusers'][0]['editcount']; + } + + /** + * Returns an array with all the members of $category + * @param $category The category to use. + * @param $subcat (bool) Go into sub categories? + * @return array + **/ + function categorymembers ($category,$subcat=false) { + $continue = ''; + $pages = array(); + while (true) { + $res = $this->query('?action=query&list=categorymembers&cmtitle='.urlencode($category).'&format=php&cmlimit=500'.$continue); + if (isset($x['error'])) { + return false; + } + foreach ($res['query']['categorymembers'] as $x) { + $pages[] = $x['title']; + } + if (empty($res['query-continue']['categorymembers']['cmcontinue'])) { + if ($subcat) { + foreach ($pages as $p) { + if (substr($p,0,9)=='Category:') { + $pages2 = $this->categorymembers($p,true); + $pages = array_merge($pages,$pages2); + } + } + } + return $pages; + } else { + $continue = '&cmcontinue='.urlencode($res['query-continue']['categorymembers']['cmcontinue']); + } + } + } + + /** + * Returns a list of pages that link to $page. + * @param $page + * @param $extra (defaults to null) + * @return array + **/ + function whatlinkshere ($page,$extra=null) { + $continue = ''; + $pages = array(); + while (true) { + $res = $this->query('?action=query&list=backlinks&bltitle='.urlencode($page).'&bllimit=500&format=php'.$continue.$extra); + if (isset($res['error'])) { + return false; + } + foreach ($res['query']['backlinks'] as $x) { + $pages[] = $x['title']; + } + if (empty($res['query-continue']['backlinks']['blcontinue'])) { + return $pages; + } else { + $continue = '&blcontinue='.urlencode($res['query-continue']['backlinks']['blcontinue']); + } + } + } + + /** + * Returns a list of pages that include the image. + * @param $image + * @param $extra (defaults to null) + * @return array + **/ + function whereisincluded ($image,$extre=null) { + $continue = ''; + $pages = array(); + while (true) { + $res = $this->query('?action=query&list=imageusage&iutitle='.urlencode($image).'&iulimit=500&format=php'.$continue.$extra); + if (isset($res['error'])) + return false; + foreach ($res['query']['imageusage'] as $x) { + $pages[] = $x['title']; + } + if (empty($res['query-continue']['imageusage']['iucontinue'])) + return $pages; + else + $continue = '&iucontinue='.urlencode($res['query-continue']['imageusage']['iucontinue']); + } + } + + /** + * Returns a list of pages that use the $template. + * @param $template the template we are intereste into + * @param $extra (defaults to null) + * @return array + **/ + function whatusethetemplate ($template,$extra=null) { + $continue = ''; + $pages = array(); + while (true) { + $res = $this->query('?action=query&list=embeddedin&eititle=Template:'.urlencode($template).'&eilimit=500&format=php'.$continue.$extra); + if (isset($res['error'])) { + return false; + } + foreach ($res['query']['embeddedin'] as $x) { + $pages[] = $x['title']; + } + if (empty($res['query-continue']['embeddedin']['eicontinue'])) { + return $pages; + } else { + $continue = '&eicontinue='.urlencode($res['query-continue']['embeddedin']['eicontinue']); + } + } + } + + /** + * Returns an array with all the subpages of $page + * @param $page + * @return array + **/ + function subpages ($page) { + /* Calculate all the namespace codes */ + $ret = $this->query('?action=query&meta=siteinfo&siprop=namespaces&format=php'); + foreach ($ret['query']['namespaces'] as $x) { + $namespaces[$x['*']] = $x['id']; + } + $temp = explode(':',$page,2); + $namespace = $namespaces[$temp[0]]; + $title = $temp[1]; + $continue = ''; + $subpages = array(); + while (true) { + $res = $this->query('?action=query&format=php&list=allpages&apprefix='.urlencode($title).'&aplimit=500&apnamespace='.$namespace.$continue); + if (isset($x['error'])) { + return false; + } + foreach ($res['query']['allpages'] as $p) { + $subpages[] = $p['title']; + } + if (empty($res['query-continue']['allpages']['apfrom'])) { + return $subpages; + } else { + $continue = '&apfrom='.urlencode($res['query-continue']['allpages']['apfrom']); + } + } + } + + /** + * This function takes a username and password and logs you into wikipedia. + * @param $user Username to login as. + * @param $pass Password that corrisponds to the username. + * @return array + **/ + function login ($user,$pass) { + $post = array('lgname' => $user, 'lgpassword' => $pass); + $ret = $this->query('?action=login&format=php',$post); + /* This is now required - see https://bugzilla.wikimedia.org/show_bug.cgi?id=23076 */ + if ($ret['login']['result'] == 'NeedToken') { + $post['lgtoken'] = $ret['login']['token']; + $ret = $this->query( '?action=login&format=php', $post ); + } + if ($ret['login']['result'] != 'Success') { + echo "Login error: \n"; + print_r($ret); + die(); + } else { + return $ret; + } + } + + /* crappy hack to allow users to use cookies from old sessions */ + function setLogin($data) { + $this->http->cookie_jar = array( + $data['cookieprefix'].'UserName' => $data['lgusername'], + $data['cookieprefix'].'UserID' => $data['lguserid'], + $data['cookieprefix'].'Token' => $data['lgtoken'], + $data['cookieprefix'].'_session' => $data['sessionid'], + ); + } + + /** + * Check if we're allowed to edit $page. + * See http://en.wikipedia.org/wiki/Template:Bots + * for more info. + * @param $page The page we want to edit. + * @param $user The bot's username. + * @return bool + **/ + function nobots ($page,$user=null,$text=null) { + if ($text == null) { + $text = $this->getpage($page); + } + if ($user != null) { + if (preg_match('/\{\{(nobots|bots\|allow=none|bots\|deny=all|bots\|optout=all|bots\|deny=.*?'.preg_quote($user,'/').'.*?)\}\}/iS',$text)) { + return false; + } + } else { + if (preg_match('/\{\{(nobots|bots\|allow=none|bots\|deny=all|bots\|optout=all)\}\}/iS',$text)) { + return false; + } + } + return true; + } + + /** + * This function returns the edit token for the current user. + * @return edit token. + **/ + function getedittoken () { + $x = $this->query('?action=query&prop=info&intoken=edit&titles=Main%20Page&format=php'); + foreach ($x['query']['pages'] as $ret) { + return $ret['edittoken']; + } + } + + /** + * Purges the cache of $page. + * @param $page The page to purge. + * @return Api result. + **/ + function purgeCache($page) { + return $this->query('?action=purge&titles='.urlencode($page).'&format=php'); + } + + /** + * Checks if $user has email enabled. + * Uses index.php. + * @param $user The user to check. + * @return bool. + **/ + function checkEmail($user) { + $x = $this->query('?action=query&meta=allmessages&ammessages=noemailtext|notargettext&amlang=en&format=php'); + $messages[0] = $x['query']['allmessages'][0]['*']; + $messages[1] = $x['query']['allmessages'][1]['*']; + $page = $this->http->get(str_replace('api.php','index.php',$this->url).'?title=Special:EmailUser&target='.urlencode($user)); + if (preg_match('/('.preg_quote($messages[0],'/').'|'.preg_quote($messages[1],'/').')/i',$page)) { + return false; + } else { + return true; + } + } + + /** + * Returns all the pages $page is transcluded on. + * @param $page The page to get the transclusions from. + * @param $sleep The time to sleep between requets (set to null to disable). + * @return array. + **/ + function getTransclusions($page,$sleep=null,$extra=null) { + $continue = ''; + $pages = array(); + while (true) { + $ret = $this->query('?action=query&list=embeddedin&eititle='.urlencode($page).$continue.$extra.'&eilimit=500&format=php'); + if ($sleep != null) { + sleep($sleep); + } + foreach ($ret['query']['embeddedin'] as $x) { + $pages[] = $x['title']; + } + if (isset($ret['query-continue']['embeddedin']['eicontinue'])) { + $continue = '&eicontinue='.$ret['query-continue']['embeddedin']['eicontinue']; + } else { + return $pages; + } + } + } + + /** + * Edits a page. + * @param $page Page name to edit. + * @param $data Data to post to page. + * @param $summary Edit summary to use. + * @param $minor Whether or not to mark edit as minor. (Default false) + * @param $bot Whether or not to mark edit as a bot edit. (Default true) + * @return api result + **/ + function edit ($page,$data,$summary = '',$minor = false,$bot = true,$section = null,$detectEC=false,$maxlag='') { + if ($this->token==null) { + $this->token = $this->getedittoken(); + } + $params = array( + 'title' => $page, + 'text' => $data, + 'token' => $this->token, + 'summary' => $summary, + ($minor?'minor':'notminor') => '1', + ($bot?'bot':'notbot') => '1' + ); + if ($section != null) { + $params['section'] = $section; + } + if ($this->ecTimestamp != null && $detectEC == true) { + $params['basetimestamp'] = $this->ecTimestamp; + $this->ecTimestamp = null; + } + if ($maxlag!='') { + $maxlag='&maxlag='.$maxlag; + } + return $this->query('?action=edit&format=php'.$maxlag,$params); + } + + /** + * Add a text at the bottom of a page + * @param $page The page we're working with. + * @param $text The text that you want to add. + * @param $summary Edit summary to use. + * @param $minor Whether or not to mark edit as minor. (Default false) + * @param $bot Whether or not to mark edit as a bot edit. (Default true) + * @return api result + **/ + function addtext( $page, $text, $summary = '', $minor = false, $bot = true ) + { + $data = $this->getpage( $page ); + $data.= "\n" . $text; + return $this->edit( $page, $data, $summary, $minor, $bot ); + } + + /** + * Moves a page. + * @param $old Name of page to move. + * @param $new New page title. + * @param $reason Move summary to use. + * @param $movetalk Move the page's talkpage as well. + * @return api result + **/ + function move ($old,$new,$reason,$options=null) { + if ($this->token==null) { + $this->token = $this->getedittoken(); + } + $params = array( + 'from' => $old, + 'to' => $new, + 'token' => $this->token, + 'reason' => $reason + ); + if ($options != null) { + $option = explode('|',$options); + foreach ($option as $o) { + $params[$o] = true; + } + } + return $this->query('?action=move&format=php',$params); + } + + /** + * Rollback an edit. + * @param $title Title of page to rollback. + * @param $user Username of last edit to the page to rollback. + * @param $reason Edit summary to use for rollback. + * @param $bot mark the rollback as bot. + * @return api result + **/ + function rollback ($title,$user,$reason=null,$bot=false) { + $ret = $this->query('?action=query&prop=revisions&rvtoken=rollback&titles='.urlencode($title).'&format=php'); + foreach ($ret['query']['pages'] as $x) { + $token = $x['revisions'][0]['rollbacktoken']; + break; + } + $params = array( + 'title' => $title, + 'user' => $user, + 'token' => $token + ); + if ($bot) { + $params['markbot'] = true; + } + if ($reason != null) { $params['summary'] = $reason; } + return $this->query('?action=rollback&format=php',$params); + } + + /** + * Blocks a user. + * @param $user The user to block. + * @param $reason The block reason. + * @param $expiry The block expiry. + * @param $options a piped string containing the block options. + * @return api result + **/ + function block ($user,$reason='vand',$expiry='infinite',$options=null,$retry=true) { + if ($this->token==null) { + $this->token = $this->getedittoken(); + } + $params = array( + 'expiry' => $expiry, + 'user' => $user, + 'reason' => $reason, + 'token' => $this->token + ); + if ($options != null) { + $option = explode('|',$options); + foreach ($option as $o) { + $params[$o] = true; + } + } + $ret = $this->query('?action=block&format=php',$params); + /* Retry on a failed token. */ + if ($retry and $ret['error']['code']=='badtoken') { + $this->token = $this->getedittoken(); + return $this->block($user,$reason,$expiry,$options,false); + } + return $ret; + } + + /** + * Unblocks a user. + * @param $user The user to unblock. + * @param $reason The unblock reason. + * @return api result + **/ + function unblock ($user,$reason) { + if ($this->token==null) { + $this->token = $this->getedittoken(); + } + $params = array( + 'user' => $user, + 'reason' => $reason, + 'token' => $this->token + ); + return $this->query('?action=unblock&format=php',$params); + } + + /** + * Emails a user. + * @param $target The user to email. + * @param $subject The email subject. + * @param $text The body of the email. + * @param $ccme Send a copy of the email to the user logged in. + * @return api result + **/ + function email ($target,$subject,$text,$ccme=false) { + if ($this->token==null) { + $this->token = $this->getedittoken(); + } + $params = array( + 'target' => $target, + 'subject' => $subject, + 'text' => $text, + 'token' => $this->token + ); + if ($ccme) { + $params['ccme'] = true; + } + return $this->query('?action=emailuser&format=php',$params); + } + + /** + * Deletes a page. + * @param $title The page to delete. + * @param $reason The delete reason. + * @return api result + **/ + function delete ($title,$reason) { + if ($this->token==null) { + $this->token = $this->getedittoken(); + } + $params = array( + 'title' => $title, + 'reason' => $reason, + 'token' => $this->token + ); + return $this->query('?action=delete&format=php',$params); + } + + /** + * Undeletes a page. + * @param $title The page to undelete. + * @param $reason The undelete reason. + * @return api result + **/ + function undelete ($title,$reason) { + if ($this->token==null) { + $this->token = $this->getedittoken(); + } + $params = array( + 'title' => $title, + 'reason' => $reason, + 'token' => $this->token + ); + return $this->query('?action=undelete&format=php',$params); + } + + /** + * (Un)Protects a page. + * @param $title The page to (un)protect. + * @param $protections The protection levels (e.g. 'edit=autoconfirmed|move=sysop') + * @param $expiry When the protection should expire (e.g. '1 day|infinite') + * @param $reason The (un)protect reason. + * @param $cascade Enable cascading protection? (defaults to false) + * @return api result + **/ + function protect ($title,$protections,$expiry,$reason,$cascade=false) { + if ($this->token==null) { + $this->token = $this->getedittoken(); + } + $params = array( + 'title' => $title, + 'protections' => $protections, + 'expiry' => $expiry, + 'reason' => $reason, + 'token' => $this->token + ); + if ($cascade) { + $params['cascade'] = true; + } + return $this->query('?action=protect&format=php',$params); + } + + /** + * Uploads an image. + * @param $page The destination file name. + * @param $file The local file path. + * @param $desc The upload discrption (defaults to ''). + **/ + function upload ($page,$file,$desc='') { + if ($this->token == null) { + $this->token = $this->getedittoken(); + } + $params = array( + 'filename' => $page, + 'comment' => $desc, + 'text' => $desc, + 'token' => $this->token, + 'ignorewarnings' => '1', + 'file' => '@'.$file + ); + return $this->query('?action=upload&format=php',$params); + } + + /* + $page - page + $revs - rev ids to delete (seperated with ,) + $comment - delete comment + */ + function revdel ($page,$revs,$comment) { + + if ($this->token==null) { + $this->token = $this->getedittoken(); + } + + $post = array( + 'wpEditToken' => $this->token, + 'ids' => $revs, + 'target' => $page, + 'type' => 'revision', + 'wpHidePrimary' => 1, + 'wpHideComment' => 1, + 'wpHideUser' => 0, + 'wpRevDeleteReasonList' => 'other', + 'wpReason' => $comment, + 'wpSubmit' => 'Apply to selected revision(s)' + ); + return $this->http->post(str_replace('api.php','index.php',$this->url).'?title=Special:RevisionDelete&action=submit',$post); + } + + /** + * Creates a new account. + * Uses index.php as there is no api to create accounts yet :( + * @param $username The username the new account will have. + * @param $password The password the new account will have. + * @param $email The email the new account will have. + **/ + function createaccount ($username,$password,$email=null) { + $post = array( + 'wpName' => $username, + 'wpPassword' => $password, + 'wpRetype' => $password, + 'wpEmail' => $email, + 'wpRemember' => 0, + 'wpIgnoreAntiSpoof' => 0, + 'wpCreateaccount' => 'Create account', + ); + return $this->http->post(str_replace('api.php','index.php',$this->url).'?title=Special:UserLogin&action=submitlogin&type=signup',$post); + } + + /** + * Changes a users rights. + * @param $user The user we're working with. + * @param $add A pipe-separated list of groups you want to add. + * @param $remove A pipe-separated list of groups you want to remove. + * @param $reason The reason for the change (defaults to ''). + **/ + function userrights ($user,$add,$remove,$reason='') { + // get the userrights token + $token = $this->query('?action=query&list=users&ususers='.urlencode($user).'&ustoken=userrights&format=php'); + $token = $token['query']['users'][0]['userrightstoken']; + $params = array( + 'user' => $user, + 'token' => $token, + 'add' => $add, + 'remove' => $remove, + 'reason' => $reason + ); + return $this->query('?action=userrights&format=php',$params); + } + + /** + * Gets the number of images matching a particular sha1 hash. + * @param $hash The sha1 hash for an image. + * @return The number of images with the same sha1 hash. + **/ + function imagematches ($hash) { + $x = $this->query('?action=query&list=allimages&format=php&aisha1='.$hash); + return count($x['query']['allimages']); + } + + /** BMcN 2012-09-16 + * Retrieve a media file's actual location. + * @param $page The "File:" page on the wiki which the URL of is desired. + * @return The URL pointing directly to the media file (Eg http://upload.mediawiki.org/wikipedia/en/1/1/Example.jpg) + **/ + function getfilelocation ($page) { + $x = $this->query('?action=query&format=php&prop=imageinfo&titles='.urlencode($page).'&iilimit=1&iiprop=url'); + foreach ($x['query']['pages'] as $ret ) { + if (isset($ret['imageinfo'][0]['url'])) { + return $ret['imageinfo'][0]['url']; + } else + return false; + } + } + + /** BMcN 2012-09-16 + * Retrieve a media file's uploader. + * @param $page The "File:" page + * @return The user who uploaded the topmost version of the file. + **/ + function getfileuploader ($page) { + $x = $this->query('?action=query&format=php&prop=imageinfo&titles='.urlencode($page).'&iilimit=1&iiprop=user'); + foreach ($x['query']['pages'] as $ret ) { + if (isset($ret['imageinfo'][0]['user'])) { + return $ret['imageinfo'][0]['user']; + } else + return false; + } + } +} + +/** + * This class extends the wiki class to provide an high level API for the most commons actions. + * @author Fale + **/ +class extended extends wikipedia +{ + /** + * Add a category to a page + * @param $page The page we're working with. + * @param $category The category that you want to add. + * @param $summary Edit summary to use. + * @param $minor Whether or not to mark edit as minor. (Default false) + * @param $bot Whether or not to mark edit as a bot edit. (Default true) + * @return api result + **/ + function addcategory( $page, $category, $summary = '', $minor = false, $bot = true ) + { + $data = $this->getpage( $page ); + $data.= "\n[[Category:" . $category . "]]"; + return $this->edit( $page, $data, $summary, $minor, $bot ); + } + + /** + * Find a string + * @param $page The page we're working with. + * @param $string The string that you want to find. + * @return bool value (1 found and 0 not-found) + **/ + function findstring( $page, $string ) + { + $data = $this->getpage( $page ); + if( strstr( $data, $string ) ) + return 1; + else + return 0; + } + + /** + * Replace a string + * @param $page The page we're working with. + * @param $string The string that you want to replace. + * @param $newstring The string that will replace the present string. + * @return the new text of page + **/ + function replacestring( $page, $string, $newstring ) + { + $data = $this->getpage( $page ); + return str_replace( $string, $newstring, $data ); + } + + /** + * Get a template from a page + * @param $page The page we're working with + * @param $template The name of the template we are looking for + * @return the searched (NULL if the template has not been found) + **/ + function gettemplate( $page, $template ) { + $data = $this->getpage( $page ); + $template = preg_quote( $template, " " ); + $r = "/{{" . $template . "(?:[^{}]*(?:{{[^}]*}})?)+(?:[^}]*}})?/i"; + preg_match_all( $r, $data, $matches ); + if( isset( $matches[0][0] ) ) + return $matches[0][0]; + else + return NULL; + } +} + + diff --git a/make-deploy-notes/uploadChangelog.php b/make-deploy-notes/uploadChangelog.php new file mode 100644 index 0000000..887eb0c --- /dev/null +++ b/make-deploy-notes/uploadChangelog.php @@ -0,0 +1,84 @@ +/** + * Copyright © 2013 Sam Reed + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + */ + +<?php + +if ( count( $argv ) !== 2 ) { + print "usage: $argv[0] wmf/1.22wmf6\n"; + exit(1); +} + +$version = $argv[1]; +$previousVersion = getPreviousVersion( $version ); + +if ( $previousVersion === null ) { + print "usage: $argv[0] wmf/1.22wmf6\n"; + exit(1); +} + +$escVer = escapeshellarg( $version ); +$escPrevVer = escapeshellarg( $previousVersion ); + +$output = shell_exec( "php -f ./make-deploy-notes {$escPrevVer} {$escVer}" ); + +require_once( 'botclasses.php' ); +$wiki = new wikipedia( 'https://www.mediawiki.org/w/api.php' ); + +$wiki->login( '', '' ); + +list( $major, $minor ) = getMajorMinor( $version ); +$wiki->edit( "MediaWiki 1.{$major}/wmf{$minor}/Changelog", $output, "Update changelog for $version", false, false ); + +print "Changelog updated\n"; + +/** + * @param $input string + * @return string|null + */ +function getPreviousVersion( $input ) { + $majorMinor = getMajorMinor( $input ); + if ( $majorMinor === null ) { + return null; + } + list( $major, $minor ) = $majorMinor; + if ( $minor === 1 ) { + $major--; + $minor = 12; + } else { + $minor--; + } + return "wmf/1.{$major}wmf{$minor}"; +} + +/** + * @param $input string + * @return array|null + */ +function getMajorMinor( $input ) { + $matches = array(); + if ( preg_match( "/^wmf\/1\.(\d{2})wmf(\d{1,2})/", $input, $matches ) ) { + // var_dump( $matches ); + $major = intval( $matches[1] ); + $minor = intval( $matches[2] ); + return array( $major, $minor ); + } + return null; +} -- To view, visit https://gerrit.wikimedia.org/r/67416 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ib50c47b4229c8f7680516e307db180a076f725ba Gerrit-PatchSet: 4 Gerrit-Project: mediawiki/tools/release Gerrit-Branch: master Gerrit-Owner: Reedy <[email protected]> Gerrit-Reviewer: Greg Grossmeier <[email protected]> Gerrit-Reviewer: Reedy <[email protected]> Gerrit-Reviewer: RobLa <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
