Extension:ApiMagicWord/customwikibot.classes.php
From MediaWiki.org
<?PHP /** * @author Cobi Carter - some adaptation by Eric Larcher (see http://en.wikipedia.org/wiki/User:ClueBot/Source for original version). **/ /** * This class is designed to provide a simplified interface to cURL which maintains cookies. * @author Cobi **/ # EL : replacement of http by fakehttp class fakehttp { private $ch; private $uid; public $postfollowredirs; public $getfollowredirs; /** * Our constructor function. This just does basic cURL initialization. * @return void **/ function __construct () { global $proxyhost, $proxyport; $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); if (isset($proxyhost) and isset($proxyport) and ($proxyport != null) and ($proxyhost != null)) { curl_setopt($this->ch,CURLOPT_PROXYTYPE,CURLPROXY_HTTP); curl_setopt($this->ch,CURLOPT_PROXY,$proxyhost); curl_setopt($this->ch,CURLOPT_PROXYPORT,$proxyport); } $this->postfollowredirs = 0; $this->getfollowredirs = 1; } /** * Post to a URL. * @param $url The URL to post to. * @param $data The post-data to post, should be an array of key => value pairs. * @return Data retrieved from the POST request. **/ function post ($url,$data) { $time = microtime(1); curl_setopt($this->ch,CURLOPT_URL,$url); curl_setopt($this->ch,CURLOPT_FOLLOWLOCATION,$this->postfollowredirs); 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_POST,1); curl_setopt($this->ch,CURLOPT_POSTFIELDS, $data); curl_setopt($this->ch,CURLOPT_HTTPHEADER, array('Expect:')); $data = curl_exec($this->ch); global $logfd; if (!is_resource($logfd)) $logfd = fopen('php://stderr','w'); fwrite($logfd,'POST: '.$url.' ('.(microtime(1) - $time).' s) ('.strlen($data)." b)\n"); return $data; } /** * Get a URL. * @param $url The URL to get. * @return Data retrieved from the GET request. **/ function get ($url) { $time = microtime(1); curl_setopt($this->ch,CURLOPT_URL,$url); 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); $data = curl_exec($this->ch); global $logfd; if (!is_resource($logfd)) $logfd = fopen('php://stderr','w'); fwrite($logfd,'GET: '.$url.' ('.(microtime(1) - $time).' s) ('.strlen($data)." b)\n"); return $data; } /** * Our destructor. Cleans up cURL and unlinks temporary files. **/ function __destruct () { curl_close($this->ch); @unlink('/tmp/cluewikibot.cookies.'.$this->uid.'.dat'); } } /** * This class is for interacting with Wikipedia's api.php API. **/ class wikipediaapi { # replacement of private by protected protected $http; protected $edittoken; protected $tokencache; public $apiurl = 'http://en.wikipedia.org/w/api.php'; /** * This is our constructor. * @return void **/ function __construct () { global $__wp__http; if (!isset($__wp__http)) { $__wp__http = new fakehttp; } $this->http = &$__wp__http; } /** * 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 void **/ // add format=php $x = unserialize($x) return $x ['login'] function login ($user,$pass) { $x = $this->http->post($this->apiurl.'?action=login',array('lgname' => $user, 'lgpassword' => $pass, 'format' => 'php')); $x = unserialize($x); return $x ['login']; } /** * This function is used to logout and clear session data * @return void **/ function logout () { $x = $this->http->get($this->apiurl.'?action=logout&format=php'); $x = unserialize($x); if (count($x) === 0) { $x = array( 'result' => 'Success'); } return $x; } /** * This function returns the edit token. * @return Edit token. **/ function getedittoken () { $tokens = $this->gettokens('Main Page'); if ($tokens['edittoken'] == '') $tokens = $this->gettokens('Main Page',true); $this->edittoken = $tokens['edittoken']; return $tokens['edittoken']; } /** * This function returns the various tokens for a certain page. * @param $title Page to get the tokens for. * @param $flush Optional - internal use only. Flushes the token cache. * @return An associative array of tokens for the page. **/ function gettokens ($title,$flush = false) { if (!is_array($this->tokencache)) $this->tokencache = array(); foreach ($this->tokencache as $t => $data) if (time() - $data['timestamp'] > 6*60*60) unset($this->tokencache[$t]); if (isset($this->tokencache[$title]) && (!$flush)) { return $this->tokencache[$title]['tokens']; } else { $tokens = array(); $x = $this->http->get($this->apiurl.'?action=query&format=php&prop=info&intoken=edit|delete|protect|move|block|unblock|email&titles='.urlencode($title)); $x = unserialize($x); foreach ($x['query']['pages'] as $y) { $tokens['edittoken'] = $y['edittoken']; $tokens['deletetoken'] = $y['deletetoken']; $tokens['protecttoken'] = $y['protecttoken']; $tokens['movetoken'] = $y['movetoken']; $tokens['blocktoken'] = $y['blocktoken']; $tokens['unblocktoken'] = $y['unblocktoken']; $tokens['emailtoken'] = $y['emailtoken']; $this->tokencache[$title] = array( 'timestamp' => time(), 'tokens' => $tokens ); return $tokens; } } } /** * This function returns the recent changes for the wiki. * @param $count The number of items to return. (Default 10) * @param $namespace The namespace ID to filter items on. Null for no filtering. (Default null) * @param $dir The direction to pull items. "older" or "newer". (Default 'older') * @param $ts The timestamp to start at. Null for the beginning/end (depending on direction). (Default null) * @return Associative array of recent changes metadata. **/ function recentchanges ($count = 10,$namespace = null,$dir = 'older',$ts = null) { $append = ''; if ($ts !== null) { $append .= '&rcstart='.urlencode($ts); } $append .= '&rcdir='.urlencode($dir); if ($namespace !== null) { $append .= '&rcnamespace='.urlencode($namespace); } $x = $this->http->get($this->apiurl.'?action=query&list=recentchanges&rcprop=user|comment|flags|timestamp|title|ids|sizes&format=php&rclimit='.$count.$append); $x = unserialize($x); return $x['query']['recentchanges']; } /** * This function returns search results from Wikipedia's internal search engine. * @param $search The query string to search for. * @param $limit The number of results to return. (Default 10) * @param $offset The number to start at. (Default 0) * @param $namespace The namespace ID to filter by. Null means no filtering. (Default 0) * @param $what What to search, 'text' or 'title'. (Default 'text') * @param $redirs Whether or not to list redirects. (Default false) * @return Associative array of search result metadata. **/ function search ($search,$limit = 10,$offset = 0,$namespace = 0,$what = 'text',$redirs = false) { $append = ''; if ($limit != null) $append .= '&srlimit='.urlencode($limit); if ($offset != null) $append .= '&sroffset='.urlencode($offset); if ($namespace != null) $append .= '&srnamespace='.urlencode($namespace); if ($what != null) $append .= '&srwhat='.urlencode($what); if ($redirs == true) $append .= '&srredirects=1'; else $append .= '&srredirects=0'; $x = $this->http->get($this->apiurl.'?action=query&list=search&format=php&srsearch='.urlencode($search).$append); $x = unserialize($x); return $x['query']['search']; } /** * Retrieve entries from the WikiLog. * @param $user Username who caused the entry. Null means anyone. (Default null) * @param $title Object to which the entry refers. Null means anything. (Default null) * @param $limit Number of entries to return. (Default 50) * @param $type Type of logs. Null means any type. (Default null) * @param $start Date to start enumerating logs. Null means beginning/end depending on $dir. (Default null) * @param $end Where to stop enumerating logs. Null means whenever limit is satisfied or there are no more logs. (Default null) * @param $dir Direction to enumerate logs. "older" or "newer". (Default 'older') * @return Associative array of logs metadata. **/ function logs ($user = null,$title = null,$limit = 50,$type = null,$start = null,$end = null,$dir = 'older') { $append = ''; if ($user != null) $append.= '&leuser='.urlencode($user); if ($title != null) $append.= '&letitle='.urlencode($title); if ($limit != null) $append.= '&lelimit='.urlencode($limit); if ($type != null) $append.= '&letype='.urlencode($type); if ($start != null) $append.= '&lestart='.urlencode($start); if ($end != null) $append.= '&leend='.urlencode($end); if ($dir != null) $append.= '&ledir='.urlencode($dir); $x = $this->http->get($this->apiurl.'?action=query&format=php&list=logevents&leprop=ids|title|type|user|timestamp|comment|details'.$append); $x = unserialize($x); return $x['query']['logevents']; } /** * Retrieves metadata about a user's contributions. * @param $user Username whose contributions we want to retrieve. * @param $count Number of entries to return. (Default 50) * @param[in,out] $continue Where to continue enumerating if part of a larger, split request. This is filled with the next logical continuation value. (Default null) * @param $dir Which direction to enumerate from, "older" or "newer". (Default 'older') * @return Associative array of contributions metadata. **/ function usercontribs ($user,$count = 50,&$continue = null,$dir = 'older') { if ($continue != null) { $append = '&ucstart='.urlencode($continue); } else { $append = ''; } $x = $this->http->get($this->apiurl.'?action=query&format=php&list=usercontribs&ucuser='.urlencode($user).'&uclimit='.urlencode($count).'&ucdir='.urlencode($dir).$append); $x = unserialize($x); $continue = $x['query-continue']['usercontribs']['ucstart']; return $x['query']['usercontribs']; } /** * Returns revision data (meta and/or actual). * @param $page Page for which to return revision data for. * @param $count Number of revisions to return. (Default 1) * @param $dir Direction to start enumerating multiple revisions from, "older" or "newer". (Default 'older') * @param $content Whether to return actual revision content, true or false. (Default false) * @param $revid Revision ID to start at. (Default null) * @param $wait Whether or not to wait a few seconds for the specific revision to become available. (Default true) * @param $getrbtok Whether or not to retrieve a rollback token for the revision. (Default false) * @param $dieonerror Whether or not to kill the process with an error if an error occurs. (Default false) * @param $redirects Whether or not to follow redirects. (Default false) * @return Associative array of revision data. **/ function revisions ($page,$count = 1,$dir = 'older',$content = false,$revid = null,$wait = true,$getrbtok = false,$dieonerror = true,$redirects = false) { $x = $this->http->get($this->apiurl.'?action=query&prop=revisions&titles='.urlencode($page).'&rvlimit='.urlencode($count).'&rvprop=timestamp|ids|user|comment'.(($content)?'|content':'').'&format=php&meta=userinfo&rvdir='.urlencode($dir).(($revid !== null)?'&rvstartid='.urlencode($revid):'').(($getrbtok == true)?'&rvtoken=rollback':'').(($redirects == true)?'&redirects':'')); $x = unserialize($x); if ($revid !== null) { $found = false; if (!isset($x['query']['pages']) or !is_array($x['query']['pages'])) { if ($dieonerror == true) die('No such page.'."\n"); else return false; } foreach ($x['query']['pages'] as $data) { if (!isset($data['revisions']) or !is_array($data['revisions'])) { if ($dieonerror == true) die('No such page.'."\n"); else return false; } foreach ($data['revisions'] as $data2) if ($data2['revid'] == $revid) $found = true; unset($data,$data2); break; } if ($found == false) { if ($wait == true) { sleep(1); return $this->revisions($page,$count,$dir,$content,$revid,false,$getrbtok,$dieonerror); } else { if ($dieonerror == true) die('Revision error.'."\n"); } } } foreach ($x['query']['pages'] as $key => $data) { $data['revisions']['ns'] = $data['ns']; $data['revisions']['title'] = $data['title']; $data['revisions']['currentuser'] = $x['query']['userinfo']['name']; // $data['revisions']['currentuser'] = $x['query']['userinfo']['currentuser']['name']; $data['revisions']['continue'] = $x['query-continue']['revisions']['rvstartid']; $data['revisions']['pageid'] = $key; return $data['revisions']; } } /** * Enumerates user metadata. * @param $start The username to start enumerating from. Null means from the beginning. (Default null) * @param $limit The number of users to enumerate. (Default 1) * @param $group The usergroup to filter by. Null means no filtering. (Default null) * @param $requirestart Whether or not to require that $start be a valid username. (Default false) * @param[out] $continue This is filled with the name to continue from next query. (Default null) * @return Associative array of user metadata. **/ function users ($start = null,$limit = 1,$group = null,$requirestart = false,&$continue = null) { $append = ''; if ($start != null) $append .= '&aufrom='.urlencode($start); if ($group != null) $append .= '&augroup='.urlencode($group); $x = $this->http->get($this->apiurl.'?action=query&list=allusers&format=php&auprop=blockinfo|editcount|registration|groups&aulimit='.urlencode($limit).$append); $x = unserialize($x); $continue = $x['query-continue']['allusers']['aufrom']; if (($requirestart == true) and ($x['query']['allusers'][0]['name'] != $start)) return false; return $x['query']['allusers']; } /** * Get members of a category. * @param $category Category to enumerate from. * @param $count Number of members to enumerate. (Default 500) * @param[in,out] $continue Where to continue enumerating from. This is automatically filled in when run. (Default null) * @return Associative array of category member metadata. **/ function categorymembers ($category,$count = 500,&$continue = null) { if ($continue != null) { $append = '&cmcontinue='.urlencode($continue); } else { $append = ''; } $category = 'Category:'.str_ireplace('category:','',$category); $x = $this->http->get($this->apiurl.'?action=query&list=categorymembers&cmtitle='.urlencode($category).'&format=php&cmlimit='.$count.$append); $x = unserialize($x); $continue = $x['query-continue']['categorymembers']['cmcontinue']; return $x['query']['categorymembers']; } /** * Enumerate all categories. * @param[in,out] $start Where to start enumerating. This is updated automatically with the value to continue from. (Default null) * @param $limit Number of categories to enumerate. (Default 50) * @param $dir Direction to enumerate in. 'ascending' or 'descending'. (Default 'ascending') * @param $prefix Only enumerate categories with this prefix. (Default null) * @return Associative array of category list metadata. **/ function listcategories (&$start = null,$limit = 50,$dir = 'ascending',$prefix = null) { $append = ''; if ($start != null) $append .= '&acfrom='.urlencode($start); if ($limit != null) $append .= '&aclimit='.urlencode($limit); if ($dir != null) $append .= '&acdir='.urlencode($dir); if ($prefix != null) $append .= '&acprefix='.urlencode($prefix); $x = $this->http->get($this->apiurl.'?action=query&list=allcategories&acprop=size&format=php'.$append); $x = unserialize($x); $start = $x['query-continue']['allcategories']['acfrom']; return $x['query']['allcategories']; } /** * Enumerate all backlinks to a page. * @param $page Page to search for backlinks to. * @param $count Number of backlinks to list. (Default 500) * @param[in,out] $continue Where to start enumerating from. This is automatically filled in. (Default null) * @param $filter Whether or not to include redirects. Acceptible values are 'all', 'redirects', and 'nonredirects'. (Default null) * @return Associative array of backlink metadata. **/ function backlinks ($page,$count = 500,&$continue = null,$filter = null) { if ($continue != null) { $append = '&blcontinue='.urlencode($continue); } else { $append = ''; } if ($filter != null) { $append .= '&blfilterredir='.urlencode($filter); } $x = $this->http->get($this->apiurl.'?action=query&list=backlinks&bltitle='.urlencode($page).'&format=php&bllimit='.$count.$append); $x = unserialize($x); $continue = $x['query-continue']['backlinks']['blcontinue']; return $x['query']['backlinks']; } /** * Gets a list of transcludes embedded in a page. * @param $page Page to look for transcludes in. * @param $count Number of transcludes to list. (Default 500) * @param[in,out] $continue Where to start enumerating from. This is automatically filled in. (Default null) * @return Associative array of transclude metadata. **/ function embeddedin ($page,$count = 500,&$continue = null) { if ($continue != null) { $append = '&eicontinue='.urlencode($continue); } else { $append = ''; } $x = $this->http->get($this->apiurl.'?action=query&list=embeddedin&eititle='.urlencode($page).'&format=php&eilimit='.$count.$append); $x = unserialize($x); $continue = $x['query-continue']['embeddedin']['eicontinue']; return $x['query']['embeddedin']; } /** * Gets a list of pages with a common prefix. * @param $prefix Common prefix to search for. * @param $namespace Numeric namespace to filter on. (Default 0) * @param $count Number of pages to list. (Default 500) * @param[in,out] $continue Where to start enumerating from. This is automatically filled in. (Default null) * @return Associative array of page metadata. **/ function listprefix ($prefix,$namespace = 0,$count = 500,&$continue = null) { $append = '&apnamespace='.urlencode($namespace); if ($continue != null) { $append .= '&apfrom='.urlencode($continue); } $x = $this->http->get($this->apiurl.'?action=query&list=allpages&apprefix='.urlencode($prefix).'&format=php&aplimit='.$count.$append); $x = unserialize($x); $continue = $x['query-continue']['allpages']['apfrom']; return $x['query']['allpages']; } /** * 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) * @param $wpStarttime Time in MW TS format of beginning of edit. (Default now) * @param $wpEdittime Time in MW TS format of last edit to that page. (Default correct) * @return boolean True on success, false on failure. **/ # EL : lot of change - see below... function edit ($page,$data,$summary = '',$minor = false,$bot = false,$createonly = false, $nocreate = false, $wpStarttime = null,$wpEdittime = null) { $params = Array( 'action' => 'edit', 'format' => 'php', 'title' => $page, 'text' => $data, 'token' => $this->getedittoken(), 'summary' => $summary, ($minor?'minor':'notminor') => '1', ($bot?'bot':'notbot') => '1' ); if ($createonly !== false) { $params [ 'createonly' ] = '1'; } if ($nocreate !== false) { $params [ 'nocreate' ] = '1'; } $x = $this->http->post($this->apiurl,$params); $x = unserialize($x); return $x['edit']; } /* function edit ($page,$data,$summary = '',$minor = false,$bot = true,$wpStarttime = null,$wpEdittime = null,$checkrun = true) { global $run, $user; $wpq = new wikipediaquery; $wpq->queryurl = str_replace('api.php','query.php',$this->apiurl); if ($checkrun == true) if (!preg_match('/(yes|enable|true)/iS',((isset($run))?$run:$wpq->getpage('User:'.$user.'/Run')))) return false; /* Check /Run page */ /* $params = Array( 'action' => 'edit', 'format' => 'php', 'title' => $page, 'text' => $data, 'token' => $this->getedittoken(), 'summary' => $summary, ($minor?'minor':'notminor') => '1', ($bot?'bot':'notbot') => '1' ); if ($wpStarttime !== null) $params['starttimestamp'] = $wpStarttime; if ($wpEdittime !== null) $params['basetimestamp'] = $wpEdittime; $x = $this->http->post($this->apiurl,$params); $x = unserialize($x); var_export($x); if ($x['edit']['result'] == 'Success') return true; else return false; } */ /** * Moves a page. * @param $old Name of page to move. * @param $new New page title. * @param $reason Move summary to use. * @return void **/ function move ($old,$new,$reason) { $tokens = $this->gettokens($old); $params = array( 'action' => 'move', 'format' => 'php', 'from' => $old, 'to' => $new, 'token' => $tokens['movetoken'], 'reason' => $reason ); $x = $this->http->post($this->apiurl,$params); $x = unserialize($x); var_export($x); } /** * 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 $token Rollback token. If not given, it will be fetched. (Default null) * @return void **/ function rollback ($title,$user,$reason,$token = null) { if (($token == null) or ($token == '')) { $token = $this->revisions($title,1,'older',false,null,true,true); print_r($token); if ($token[0]['user'] == $user) { $token = $token[0]['rollbacktoken']; } else { return false; } } $params = array( 'action' => 'rollback', 'format' => 'php', 'title' => $title, 'user' => $user, 'summary' => $reason, 'token' => $token, 'markbot' => 0 ); echo 'Posting to API: '; var_export($params); $x = $this->http->post($this->apiurl,$params); $x = unserialize($x); var_export($x); return (isset($x['rollback']['summary'])?true:false); } } /** * This class is for interacting with Wikipedia's browser interface, index.php. * Many of these functions are deprecated. **/ class wikipediaindex { private $http; public $indexurl = 'http://en.wikipedia.org/w/index.php'; private $postinterval = 0; private $lastpost; private $edittoken; /** * This is our constructor. * @return void **/ function __construct () { global $__wp__http; if (!isset($__wp__http)) { $__wp__http = new http; } $this->http = &$__wp__http; } /** * Post data to a page, nicely. * @param $page Page title. * @param $data Data to post to page. * @param $summery Edit summary. (Default '') * @param $minor Whether to mark edit as minor. (Default false) * @param $rv Revision data. If not given, it will be fetched. (Default null) * @param $bot Whether to mark edit as bot. (Default true) * @return HTML data from the page. * @deprecated * @see wikipediaapi::edit **/ function post ($page,$data,$summery = '',$minor = false,$rv = null,$bot = true) { global $user; global $maxlag; global $irc; global $irctechchannel; global $run; global $maxlagkeepgoing; $wpq = new wikipediaquery; $wpq->queryurl = str_replace('index.php','query.php',$this->indexurl); $wpapi = new wikipediaapi; $wpapi->apiurl = str_replace('index.php','api.php',$this->indexurl); if ((!$this->edittoken) or ($this->edittoken == '')) $this->edittoken = $wpapi->getedittoken(); if ($rv == null) $rv = $wpapi->revisions($page,1,'older',true); if (!$rv[0]['*']) $rv[0]['*'] = $wpq->getpage($page); //Fake the edit form. $now = gmdate('YmdHis', time()); $token = htmlspecialchars($this->edittoken); $tmp = date_parse($rv[0]['timestamp']); $edittime = gmdate('YmdHis', gmmktime($tmp['hour'],$tmp['minute'],$tmp['second'],$tmp['month'],$tmp['day'],$tmp['year'])); $html = "<input type='hidden' value=\"{$now}\" name=\"wpStarttime\" />\n"; $html.= "<input type='hidden' value=\"{$edittime}\" name=\"wpEdittime\" />\n"; $html.= "<input type='hidden' value=\"{$token}\" name=\"wpEditToken\" />\n"; $html.= '<input name="wpAutoSummary" type="hidden" value="'.md5('').'" />'."\n"; if (preg_match('/'.preg_quote('{{nobots}}','/').'/iS',$rv[0]['*'])) { return false; } /* Honor the bots flags */ if (preg_match('/'.preg_quote('{{bots|allow=none}}','/').'/iS',$rv[0]['*'])) { return false; } if (preg_match('/'.preg_quote('{{bots|deny=all}}','/').'/iS',$rv[0]['*'])) { return false; } if (preg_match('/'.preg_quote('{{bots|deny=','/').'(.*)'.preg_quote('}}','/').'/iS',$rv[0]['*'],$m)) { if (in_array(explode(',',$m[1]),$user)) { return false; } } /* /Honor the bots flags */ if (!preg_match('/'.preg_quote($user,'/').'/iS',$rv['currentuser'])) { return false; } /* We need to be logged in */ // if (preg_match('/'.preg_quote('You have new messages','/').'/iS',$rv[0]['*'])) { return false; } /* Check talk page */ if (!preg_match('/(yes|enable|true)/iS',((isset($run))?$run:$wpq->getpage('User:'.$user.'/Run')))) { return false; } /* Check /Run page */ $x = $this->forcepost($page,$data,$summery,$minor,$html,$maxlag,$maxlagkeepgoing,$bot); /* Go ahead and post. */ $this->lastpost = time(); return $x; } /** * Post data to a page. * @param $page Page title. * @param $data Data to post to page. * @param $summery Edit summary. (Default '') * @param $minor Whether to mark edit as minor. (Default false) * @param $edithtml HTML from the edit form. If not given, it will be fetched. (Default null) * @param $maxlag Maxlag for posting. (Default null) * @param $mlkg Whether to keep going after encountering a maxlag error and sleeping or not. (Default null) * @param $bot Whether to mark edit as bot. (Default true) * @return HTML data from the page. * @deprecated * @see wikipediaapi::edit **/ function forcepost ($page,$data,$summery = '',$minor = false,$edithtml = null,$maxlag = null,$mlkg = null,$bot = true) { $post['wpSection'] = ''; $post['wpScrolltop'] = ''; if ($minor == true) { $post['wpMinoredit'] = 1; } $post['wpTextbox1'] = $data; $post['wpSummary'] = $summery; if ($edithtml == null) { $html = $this->http->get($this->indexurl.'?title='.urlencode($page).'&action=edit'); } else { $html = $edithtml; } preg_match('|\<input type\=\\\'hidden\\\' value\=\"(.*)\" name\=\"wpStarttime\" /\>|U',$html,$m); $post['wpStarttime'] = $m[1]; preg_match('|\<input type\=\\\'hidden\\\' value\=\"(.*)\" name\=\"wpEdittime\" /\>|U',$html,$m); $post['wpEdittime'] = $m[1]; preg_match('|\<input type\=\\\'hidden\\\' value\=\"(.*)\" name\=\"wpEditToken\" /\>|U',$html,$m); $post['wpEditToken'] = $m[1]; preg_match('|\<input name\=\"wpAutoSummary\" type\=\"hidden\" value\=\"(.*)\" /\>|U',$html,$m); $post['wpAutoSummary'] = $m[1]; if ($maxlag != null) { $x = $this->http->post($this->indexurl.'?title='.urlencode($page).'&action=submit&maxlag='.urlencode($maxlag).'&bot='.(($bot == true)?'1':'0'),$post); if (preg_match('/Waiting for ([^ ]*): ([0-9.-]+) seconds lagged/S',$x,$lagged)) { global $irc; if (is_resource($irc)) { global $irctechchannel; foreach(explode(',',$irctechchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :'.$lagged[1].' is lagged out by '.$lagged[2].' seconds. ('.$lagged[0].')'."\n"); } } sleep(10); if ($mlkg != true) { return false; } else { $x = $this->http->post($this->indexurl.'?title='.urlencode($page).'&action=submit&bot='.(($bot == true)?'1':'0'),$post); } } return $x; } else { return $this->http->post($this->indexurl.'?title='.urlencode($page).'&action=submit&bot='.(($bot == true)?'1':'0'),$post); } } /** * Get a diff. * @param $title Page title to get the diff of. * @param $oldid Old revision ID. * @param $id New revision ID. * @param $wait Whether or not to wait for the diff to become available. (Default true) * @return Array of added data, removed data, and a rollback token if one was fetchable. **/ function diff ($title,$oldid,$id,$wait = true) { $deleted = ''; $added = ''; $html = $this->http->get($this->indexurl.'?title='.urlencode($title).'&action=render&diff='.urlencode($id).'&oldid='.urlencode($oldid).'&diffonly=1'); if (preg_match_all('/\&\;(oldid\=)(\d*)\\\'\>(Revision as of|Current revision as of)/USs', $html, $m, PREG_SET_ORDER)) { //print_r($m); if ((($oldid != $m[0][2]) and (is_numeric($oldid))) or (($id != $m[1][2]) and (is_numeric($id)))) { if ($wait == true) { sleep(1); return $this->diff($title,$oldid,$id,false); } else { echo 'OLDID as detected: '.$m[0][2].' Wanted: '.$oldid."\n"; echo 'NEWID as detected: '.$m[1][2].' Wanted: '.$id."\n"; echo $html; die('Revision error.'."\n"); } } } if (preg_match_all('/\<td class\=(\"|\\\')diff-addedline\1\>\<div\>(.*)\<\/div\>\<\/td\>/USs', $html, $m, PREG_SET_ORDER)) { //print_r($m); foreach ($m as $x) { $added .= htmlspecialchars_decode(strip_tags($x[2]))."\n"; } } if (preg_match_all('/\<td class\=(\"|\\\')diff-deletedline\1\>\<div\>(.*)\<\/div\>\<\/td\>/USs', $html, $m, PREG_SET_ORDER)) { //print_r($m); foreach ($m as $x) { $deleted .= htmlspecialchars_decode(strip_tags($x[2]))."\n"; } } //echo $added."\n".$deleted."\n"; if (preg_match('/action\=rollback\&\;from\=.*\&\;token\=(.*)\"/US', $html, $m)) { $rbtoken = $m[1]; $rbtoken = urldecode($rbtoken); // echo 'rbtoken: '.$rbtoken.' -- '; print_r($m); echo "\n\n"; return array($added,$deleted,$rbtoken); } return array($added,$deleted); } /** * Rollback an edit. * @param $title Page title to rollback. * @param $user Username of last edit to the page to rollback. * @param $reason Reason to rollback. If null, default is generated. (Default null) * @param $token Rollback token to use. If null, it is fetched. (Default null) * @param $bot Whether or not to mark as bot. (Default true) * @return HTML or false if failure. * @deprecated * @see wikipediaapi::rollback **/ function rollback ($title,$user,$reason = null,$token = null,$bot = true) { if (($token == null) or (!$token)) { $wpapi = new wikipediaapi; $wpapi->apiurl = str_replace('index.php','api.php',$this->indexurl); $token = $wpapi->revisions($title,1,'older',false,null,true,true); if ($token[0]['user'] == $user) { // echo 'Token: '; print_r($token); echo "\n\n"; $token = $token[0]['rollbacktoken']; } else { return false; } } $x = $this->http->get($this->indexurl.'?title='.urlencode($title).'&action=rollback&from='.urlencode($user).'&token='.urlencode($token).(($reason != null)?'&summary='.urlencode($reason):'').'&bot='.(($bot == true)?'1':'0')); global $logfd; if (!is_resource($logfd)) $logfd = fopen('php://stderr','w'); fwrite($logfd,'Rollback return: '.$x."\n"); if (!preg_match('/action complete/iS',$x)) return false; return $x; } /** * Move a page. * @param $old Page title to move. * @param $new New title to move to. * @param $reason Move page summary. * @return HTML page. * @deprecated * @see wikipediaapi::move **/ function move ($old,$new,$reason) { $wpapi = new wikipediaapi; $wpapi->apiurl = str_replace('index.php','api.php',$this->indexurl); if ((!$this->edittoken) or ($this->edittoken == '')) $this->edittoken = $wpapi->getedittoken(); $token = htmlspecialchars($this->edittoken); $post = array ( 'wpOldTitle' => $old, 'wpNewTitle' => $new, 'wpReason' => $reason, 'wpWatch' => '0', 'wpEditToken' => $token, 'wpMove' => 'Move page' ); return $this->http->post($this->indexurl.'?title=Special:Movepage&action=submit',$post); } /** * Uploads a file. * @param $page Name of page on the wiki to upload as. * @param $file Name of local file to upload. * @param $desc Content of the file description page. * @return HTML content. **/ function upload ($page,$file,$desc) { $post = array ( 'wpUploadFile' => '@'.$file, 'wpSourceType' => 'file', 'wpDestFile' => $page, 'wpUploadDescription' => $desc, 'wpLicense' => '', 'wpWatchthis' => '0', 'wpIgnoreWarning' => '1', 'wpUpload' => 'Upload file' ); return $this->http->post($this->indexurl.'?title=Special:Upload&action=submit',$post); } /** * Check if a user has email enabled. * @param $user Username to check whether or not the user has email enabled. * @return True or false depending on whether or not the user has email enabled. **/ function hasemail ($user) { $tmp = $this->http->get($this->indexurl.'?title=Special:EmailUser&target='.urlencode($user)); if (stripos($tmp,"No e-mail address") !== false) return false; return true; } /** * Sends an email to a user. * @param $user Username to send email to. * @param $subject Subject of email to send. * @param $body Body of email to send. * @return HTML content. **/ function email ($user,$subject,$body) { $wpapi = new wikipediaapi; $wpapi->apiurl = str_replace('index.php','api.php',$this->indexurl); if ((!$this->edittoken) or ($this->edittoken == '')) $this->edittoken = $wpapi->getedittoken(); $post = array ( 'wpSubject' => $subject, 'wpText' => $body, 'wpCCMe' => 0, 'wpSend' => 'Send', 'wpEditToken' => $this->edittoken ); return $this->http->post($this->indexurl.'?title=Special:EmailUser&target='.urlencode($user).'&action=submit',$post); } }
