Index: trunk/tools/wikibot/wikibot.classes.php |
— | — | @@ -0,0 +1,1091 @@ |
| 2 | +<?PHP |
| 3 | + /** |
| 4 | + * @author Cobi Carter, Tisane |
| 5 | + * |
| 6 | + * This script is free software that is available under the terms of the |
| 7 | + * current version of the GNU General Public License. |
| 8 | + * |
| 9 | + * This is a configurable MediaWiki bot framework. |
| 10 | + **/ |
| 11 | + |
| 12 | + require( 'wikibot.config.php' ); |
| 13 | + |
| 14 | + function getWikibotSetting( $setting, $bot, $wiki ) { |
| 15 | + global $wikibotSetting; |
| 16 | + $permutation = 0; |
| 17 | + while ( !isset( $result ) && $permutation < 4 ) { |
| 18 | + |
| 19 | + switch ( $permutation ) { |
| 20 | + case 0: |
| 21 | + if ( isset( $wikibotSetting[$setting][$bot][$wiki] ) ) { |
| 22 | + $result = $wikibotSetting[$setting][$bot][$wiki]; |
| 23 | + } |
| 24 | + break; |
| 25 | + case 1: |
| 26 | + if ( isset( $wikibotSetting[$setting][$bot]['*'] ) ) { |
| 27 | + $result = $wikibotSetting[$setting][$bot]['*']; |
| 28 | + } |
| 29 | + case 2: |
| 30 | + if ( isset( $wikibotSetting[$setting]['*'][$wiki] ) ) { |
| 31 | + $result = $wikibotSetting[$setting]['*'][$wiki]; |
| 32 | + } |
| 33 | + break; |
| 34 | + case 3: |
| 35 | + if ( isset( $wikibotSetting[$setting]['*']['*'] ) ) { |
| 36 | + $result = $wikibotSetting[$setting]['*']['*']; |
| 37 | + } |
| 38 | + break; |
| 39 | + } |
| 40 | + $permutation++; |
| 41 | + } |
| 42 | + if ( isset( $result ) ) { |
| 43 | + return $result; |
| 44 | + } else { |
| 45 | + return false; |
| 46 | + } |
| 47 | + } |
| 48 | + |
| 49 | + /** |
| 50 | + * This class is designed to provide a simplified interface to cURL which maintains cookies. |
| 51 | + * @author Cobi |
| 52 | + **/ |
| 53 | + class http { |
| 54 | + private $ch; |
| 55 | + private $uid; |
| 56 | + public $postfollowredirs; |
| 57 | + public $getfollowredirs; |
| 58 | + |
| 59 | + /** |
| 60 | + * Our constructor function. This just does basic cURL initialization. |
| 61 | + * @return void |
| 62 | + **/ |
| 63 | + function __construct () { |
| 64 | + global $proxyhost, $proxyport; |
| 65 | + $this->ch = curl_init(); |
| 66 | + $this->uid = dechex( rand( 0, 99999999 ) ); |
| 67 | + curl_setopt( $this->ch, CURLOPT_COOKIEJAR, '/tmp/cluewikibot.cookies.' . $this->uid . '.dat' ); |
| 68 | + curl_setopt( $this->ch, CURLOPT_COOKIEFILE, '/tmp/cluewikibot.cookies.' . $this->uid . '.dat' ); |
| 69 | + curl_setopt( $this->ch, CURLOPT_MAXCONNECTS, 100 ); |
| 70 | + curl_setopt( $this->ch, CURLOPT_CLOSEPOLICY, CURLCLOSEPOLICY_LEAST_RECENTLY_USED ); |
| 71 | + curl_setopt( $this->ch, CURLOPT_USERAGENT, 'ClueBot/1.1' ); |
| 72 | + if ( isset( $proxyhost ) and isset( $proxyport ) and ( $proxyport != null ) and ( $proxyhost != null ) ) { |
| 73 | + curl_setopt( $this->ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP ); |
| 74 | + curl_setopt( $this->ch, CURLOPT_PROXY, $proxyhost ); |
| 75 | + curl_setopt( $this->ch, CURLOPT_PROXYPORT, $proxyport ); |
| 76 | + } |
| 77 | + $this->postfollowredirs = 0; |
| 78 | + $this->getfollowredirs = 1; |
| 79 | + } |
| 80 | + |
| 81 | + /** |
| 82 | + * Post to a URL. |
| 83 | + * @param $url The URL to post to. |
| 84 | + * @param $data The post-data to post, should be an array of key => value pairs. |
| 85 | + * @return Data retrieved from the POST request. |
| 86 | + **/ |
| 87 | + function post ( $url, $data ) { |
| 88 | + $time = microtime( 1 ); |
| 89 | + curl_setopt( $this->ch, CURLOPT_URL, $url ); |
| 90 | + curl_setopt( $this->ch, CURLOPT_FOLLOWLOCATION, $this->postfollowredirs ); |
| 91 | + curl_setopt( $this->ch, CURLOPT_MAXREDIRS, 10 ); |
| 92 | + curl_setopt( $this->ch, CURLOPT_HEADER, 0 ); |
| 93 | + curl_setopt( $this->ch, CURLOPT_RETURNTRANSFER, 1 ); |
| 94 | + curl_setopt( $this->ch, CURLOPT_TIMEOUT, 30 ); |
| 95 | + curl_setopt( $this->ch, CURLOPT_CONNECTTIMEOUT, 10 ); |
| 96 | + curl_setopt( $this->ch, CURLOPT_POST, 1 ); |
| 97 | + curl_setopt( $this->ch, CURLOPT_POSTFIELDS, $data ); |
| 98 | + curl_setopt( $this->ch, CURLOPT_HTTPHEADER, array( 'Expect:' ) ); |
| 99 | + $data = curl_exec( $this->ch ); |
| 100 | + # global $logfd; if (!is_resource($logfd)) $logfd = fopen('php://stderr','w'); fwrite($logfd,'POST: '.$url.' ('.(microtime(1) - $time).' s) ('.strlen($data)." b)\n"); |
| 101 | + return $data; |
| 102 | + } |
| 103 | + |
| 104 | + /** |
| 105 | + * Get a URL. |
| 106 | + * @param $url The URL to get. |
| 107 | + * @return Data retrieved from the GET request. |
| 108 | + **/ |
| 109 | + function get ( $url ) { |
| 110 | + $time = microtime( 1 ); |
| 111 | + curl_setopt( $this->ch, CURLOPT_URL, $url ); |
| 112 | + curl_setopt( $this->ch, CURLOPT_FOLLOWLOCATION, $this->getfollowredirs ); |
| 113 | + curl_setopt( $this->ch, CURLOPT_MAXREDIRS, 10 ); |
| 114 | + curl_setopt( $this->ch, CURLOPT_HEADER, 0 ); |
| 115 | + curl_setopt( $this->ch, CURLOPT_RETURNTRANSFER, 1 ); |
| 116 | + curl_setopt( $this->ch, CURLOPT_TIMEOUT, 30 ); |
| 117 | + curl_setopt( $this->ch, CURLOPT_CONNECTTIMEOUT, 10 ); |
| 118 | + curl_setopt( $this->ch, CURLOPT_HTTPGET, 1 ); |
| 119 | + $data = curl_exec( $this->ch ); |
| 120 | + # $global $logfd; if (!is_resource($logfd)) $logfd = fopen('php://stderr','w'); fwrite($logfd,'GET: '.$url.' ('.(microtime(1) - $time).' s) ('.strlen($data)." b)\n"); |
| 121 | + return $data; |
| 122 | + } |
| 123 | + |
| 124 | + /** |
| 125 | + * Our destructor. Cleans up cURL and unlinks temporary files. |
| 126 | + **/ |
| 127 | + function __destruct () { |
| 128 | + curl_close( $this->ch ); |
| 129 | + @unlink( '/tmp/cluewikibot.cookies.' . $this->uid . '.dat' ); |
| 130 | + } |
| 131 | + } |
| 132 | + |
| 133 | + /** |
| 134 | + * This class is a deprecated wrapper class which allows legacy code written for Wikipedia's query.php API to still work with wikipediaapi::. |
| 135 | + **/ |
| 136 | + class wikipediaquery { |
| 137 | + private $http; |
| 138 | + private $api; |
| 139 | + public $apiurl; |
| 140 | + public $queryurl; |
| 141 | + public $indexurl; |
| 142 | + |
| 143 | + /** |
| 144 | + * This is our constructor. |
| 145 | + * @param $myApiurl API url; used if $fromFile is false |
| 146 | + * @param $myQueryurl Query url; used if $fromFile is false |
| 147 | + * @param $myIndexurl Index url; used if $fromFile is false |
| 148 | + * @param $bot Bot name; used if $fromFile is true |
| 149 | + * @param $wiki Wiki name; used if $fromFile is true |
| 150 | + * @param $fromFile If true, load settings from wikibot.config.php |
| 151 | + * @return void |
| 152 | + **/ |
| 153 | + function __construct ( $myApiurl, $myQueryurl, $myIndexurl, $bot = '', $wiki = '', $fromFile = false ) { |
| 154 | + global $queryFunctionFile; |
| 155 | + if ( $fromFile == true ) { |
| 156 | + $this->apiurl = getWikibotSetting( 'apiurl', $bot, $wiki ); |
| 157 | + $this->queryurl = getWikibotSetting( 'queryurl', $bot, $wiki ); // Obsolete, but kept for compatibility purposes. |
| 158 | + $this->indexurl = getWikibotSetting( 'indexurl', $bot, $wiki ); |
| 159 | + } else { |
| 160 | + $this->apiurl = $myApiurl; |
| 161 | + $this->queryurl = $myQueryurl; // Obsolete, but kept for compatibility purposes. |
| 162 | + $this->indexurl = $myIndexurl; |
| 163 | + } |
| 164 | + if ( isset( $queryFunctionFile ) ) { |
| 165 | + foreach ( $queryFunctionFile as $item ) { |
| 166 | + require_once( $item ); |
| 167 | + } |
| 168 | + } |
| 169 | + global $__wp__http; |
| 170 | + if ( !isset( $__wp__http ) ) { |
| 171 | + $__wp__http = new http; |
| 172 | + } |
| 173 | + $this->http = &$__wp__http; |
| 174 | + $this->api = new wikipediaapi ( $this->apiurl, $this->queryurl, $this->indexurl ); |
| 175 | + } |
| 176 | + |
| 177 | + /** |
| 178 | + * Reinitializes the queryurl. |
| 179 | + * @private |
| 180 | + * @return void |
| 181 | + **/ |
| 182 | + private function checkurl() { |
| 183 | + $this->api->apiurl = str_replace( 'query.php', 'api.php', $this->queryurl ); |
| 184 | + } |
| 185 | + |
| 186 | + /** |
| 187 | + * Gets the content of a page. |
| 188 | + * @param $page The wikipedia page to fetch. |
| 189 | + * @return The wikitext for the page. |
| 190 | + **/ |
| 191 | + function getpage ( $page ) { |
| 192 | + $this->checkurl(); |
| 193 | + $ret = $this->api->revisions( $page, 1, 'older', true, null, true, false, false, false ); |
| 194 | + if (isset($ret[0]['*'])){ |
| 195 | + return $ret[0]['*']; |
| 196 | + } else{ |
| 197 | + return; |
| 198 | + } |
| 199 | + } |
| 200 | + |
| 201 | + /** |
| 202 | + * Gets the page id for a page. |
| 203 | + * @param $page The wikipedia page to get the id for. |
| 204 | + * @return The page id of the page. |
| 205 | + **/ |
| 206 | + function getpageid ( $page ) { |
| 207 | + $this->checkurl(); |
| 208 | + $ret = $this->api->revisions( $page, 1, 'older', false, null, true, false, false, false ); |
| 209 | + return $ret['pageid']; |
| 210 | + } |
| 211 | + |
| 212 | + /** |
| 213 | + * Gets the number of contributions a user has. |
| 214 | + * @param $user The username for which to get the edit count. |
| 215 | + * @return The number of contributions the user has. |
| 216 | + **/ |
| 217 | + function contribcount ( $user ) { |
| 218 | + $this->checkurl(); |
| 219 | + $ret = $this->api->users( $user, 1, null, true ); |
| 220 | + if ( $ret !== false ) return $ret[0]['editcount']; |
| 221 | + return false; |
| 222 | + } |
| 223 | + } |
| 224 | + |
| 225 | + /** |
| 226 | + * This class is for interacting with Wikipedia's api.php API. |
| 227 | + **/ |
| 228 | + class wikipediaapi { |
| 229 | + private $http; |
| 230 | + private $edittoken; |
| 231 | + private $tokencache; |
| 232 | + public $apiurl; |
| 233 | + public $queryurl; |
| 234 | + public $indexurl; |
| 235 | + |
| 236 | + /** |
| 237 | + * This is our constructor. |
| 238 | + * @param $myApiurl API url; used if $fromFile is false |
| 239 | + * @param $myQueryurl Query url; used if $fromFile is false |
| 240 | + * @param $myIndexurl Index url; used if $fromFile is false |
| 241 | + * @param $bot Bot name; used if $fromFile is true |
| 242 | + * @param $wiki Wiki name; used if $fromFile is true |
| 243 | + * @param $fromFile If true, load settings from wikibot.config.php |
| 244 | + * @return void |
| 245 | + **/ |
| 246 | + function __construct ( $myApiurl, $myQueryurl, $myIndexurl, $bot = '', $wiki = '', $fromFile = false ) { |
| 247 | + global $apiFunctionFile; |
| 248 | + if ( $fromFile == true ) { |
| 249 | + $this->apiurl = getWikibotSetting( 'apiurl', $bot, $wiki ); |
| 250 | + $this->queryurl = getWikibotSetting( 'queryurl', $bot, $wiki ); // Obsolete, but kept for compatibility purposes. |
| 251 | + $this->indexurl = getWikibotSetting( 'indexurl', $bot, $wiki ); |
| 252 | + } else { |
| 253 | + $this->apiurl = $myApiurl; |
| 254 | + $this->queryurl = $myQueryurl; // Obsolete, but kept for compatibility purposes. |
| 255 | + $this->indexurl = $myIndexurl; |
| 256 | + } |
| 257 | + if ( isset( $queryFunctionFile ) ) { |
| 258 | + foreach ( $apiFunctionFile as $item ) { |
| 259 | + |
| 260 | + require_once( $item ); |
| 261 | + } |
| 262 | + } |
| 263 | + global $__wp__http; |
| 264 | + if ( !isset( $__wp__http ) ) { |
| 265 | + $__wp__http = new http; |
| 266 | + } |
| 267 | + $this->http = &$__wp__http; |
| 268 | + } |
| 269 | + |
| 270 | + /** |
| 271 | + * This function takes a username and password and logs you into wikipedia. |
| 272 | + * @param $user Username to login as. |
| 273 | + * @param $pass Password that corresponds to the username. |
| 274 | + * @return void |
| 275 | + **/ |
| 276 | + function login ( $user, $pass ) { |
| 277 | + $x = unserialize( $this->http->post( $this->apiurl . '?action=login&format=php', array( 'lgname' => $user, 'lgpassword' => $pass ) ) ); |
| 278 | + if ( $x['login']['result'] == 'Success' ) |
| 279 | + return true; |
| 280 | + if ( $x['login']['result'] == 'NeedToken' ) { |
| 281 | + $x = unserialize( $this->http->post( $this->apiurl . '?action=login&format=php', array( 'lgname' => $user, 'lgpassword' => $pass, 'lgtoken' => $x['login']['token'] ) ) ); |
| 282 | + if ( $x['login']['result'] == 'Success' ) |
| 283 | + return true; |
| 284 | + } |
| 285 | + return false; |
| 286 | + } |
| 287 | + |
| 288 | + /** |
| 289 | + * This function returns the edit token. |
| 290 | + * @return Edit token. |
| 291 | + **/ |
| 292 | + function getedittoken () { |
| 293 | + $tokens = $this->gettokens( 'Main Page' ); |
| 294 | + if ( $tokens['edittoken'] == '' ) $tokens = $this->gettokens( 'Main Page', true ); |
| 295 | + $this->edittoken = $tokens['edittoken']; |
| 296 | + return $tokens['edittoken']; |
| 297 | + } |
| 298 | + |
| 299 | + /** |
| 300 | + * This function returns the various tokens for a certain page. |
| 301 | + * @param $title Page to get the tokens for. |
| 302 | + * @param $flush Optional - internal use only. Flushes the token cache. |
| 303 | + * @return An associative array of tokens for the page. |
| 304 | + **/ |
| 305 | + function gettokens ( $title, $flush = false ) { |
| 306 | + if ( !is_array( $this->tokencache ) ) $this->tokencache = array(); |
| 307 | + foreach ( $this->tokencache as $t => $data ) if ( time() - $data['timestamp'] > 6 * 60 * 60 ) unset( $this->tokencache[$t] ); |
| 308 | + if ( isset( $this->tokencache[$title] ) && ( !$flush ) ) { |
| 309 | + return $this->tokencache[$title]['tokens']; |
| 310 | + } else { |
| 311 | + $tokens = array(); |
| 312 | + $x = $this->http->get( $this->apiurl . '?action=query&format=php&prop=info&intoken=edit|delete|protect|move|block|unblock|email&titles=' . urlencode( $title ) ); |
| 313 | + $x = unserialize( $x ); |
| 314 | + foreach ( $x['query']['pages'] as $y ) { |
| 315 | + $tokens['edittoken'] = $y['edittoken']; |
| 316 | + $tokens['deletetoken'] = $y['deletetoken']; |
| 317 | + $tokens['protecttoken'] = $y['protecttoken']; |
| 318 | + $tokens['movetoken'] = $y['movetoken']; |
| 319 | + $tokens['blocktoken'] = $y['blocktoken']; |
| 320 | + $tokens['unblocktoken'] = $y['unblocktoken']; |
| 321 | + # $tokens['emailtoken'] = $y['emailtoken']; |
| 322 | + $this->tokencache[$title] = array( |
| 323 | + 'timestamp' => time(), |
| 324 | + 'tokens' => $tokens |
| 325 | + ); |
| 326 | + return $tokens; |
| 327 | + } |
| 328 | + } |
| 329 | + } |
| 330 | + |
| 331 | + /** |
| 332 | + * This function returns the recent changes for the wiki. |
| 333 | + * @param $count The number of items to return. (Default 10) |
| 334 | + * @param $namespace The namespace ID to filter items on. Null for no filtering. (Default null) |
| 335 | + * @param $dir The direction to pull items. "older" or "newer". (Default 'older') |
| 336 | + * @param $ts The timestamp to start at. Null for the beginning/end (depending on direction). (Default null) |
| 337 | + * @return Associative array of recent changes metadata. |
| 338 | + **/ |
| 339 | + function recentchanges ( $count = 10, $namespace = null, $dir = 'older', $ts = null ) { |
| 340 | + $append = ''; |
| 341 | + if ( $ts !== null ) { $append .= '&rcstart=' . urlencode( $ts ); } |
| 342 | + $append .= '&rcdir=' . urlencode( $dir ); |
| 343 | + if ( $namespace !== null ) { $append .= '&rcnamespace=' . urlencode( $namespace ); } |
| 344 | + $x = $this->http->get( $this->apiurl . '?action=query&list=recentchanges&rcprop=user|comment|flags|timestamp|title|ids|sizes&format=php&rclimit=' . $count . $append ); |
| 345 | + $x = unserialize( $x ); |
| 346 | + return $x['query']['recentchanges']; |
| 347 | + } |
| 348 | + |
| 349 | + /** |
| 350 | + * This function returns search results from Wikipedia's internal search engine. |
| 351 | + * @param $search The query string to search for. |
| 352 | + * @param $limit The number of results to return. (Default 10) |
| 353 | + * @param $offset The number to start at. (Default 0) |
| 354 | + * @param $namespace The namespace ID to filter by. Null means no filtering. (Default 0) |
| 355 | + * @param $what What to search, 'text' or 'title'. (Default 'text') |
| 356 | + * @param $redirs Whether or not to list redirects. (Default false) |
| 357 | + * @return Associative array of search result metadata. |
| 358 | + **/ |
| 359 | + function search ( $search, $limit = 10, $offset = 0, $namespace = 0, $what = 'text', $redirs = false ) { |
| 360 | + $append = ''; |
| 361 | + if ( $limit != null ) $append .= '&srlimit=' . urlencode( $limit ); |
| 362 | + if ( $offset != null ) $append .= '&sroffset=' . urlencode( $offset ); |
| 363 | + if ( $namespace != null ) $append .= '&srnamespace=' . urlencode( $namespace ); |
| 364 | + if ( $what != null ) $append .= '&srwhat=' . urlencode( $what ); |
| 365 | + if ( $redirs == true ) $append .= '&srredirects=1'; |
| 366 | + else $append .= '&srredirects=0'; |
| 367 | + $x = $this->http->get( $this->apiurl . '?action=query&list=search&format=php&srsearch=' . urlencode( $search ) . $append ); |
| 368 | + $x = unserialize( $x ); |
| 369 | + return $x['query']['search']; |
| 370 | + } |
| 371 | + |
| 372 | + /** |
| 373 | + * Retrieve entries from the WikiLog. |
| 374 | + * @param $user Username who caused the entry. Null means anyone. (Default null) |
| 375 | + * @param $title Object to which the entry refers. Null means anything. (Default null) |
| 376 | + * @param $limit Number of entries to return. (Default 50) |
| 377 | + * @param $type Type of logs. Null means any type. (Default null) |
| 378 | + * @param $start Date to start enumerating logs. Null means beginning/end depending on $dir. (Default null) |
| 379 | + * @param $end Where to stop enumerating logs. Null means whenever limit is satisfied or there are no more logs. (Default null) |
| 380 | + * @param $dir Direction to enumerate logs. "older" or "newer". (Default 'older') |
| 381 | + * @return Associative array of logs metadata. |
| 382 | + **/ |
| 383 | + function logs ( $user = null, $title = null, $limit = 50, $type = null, $start = null, $end = null, $dir = 'older' ) { |
| 384 | + $append = ''; |
| 385 | + if ( $user != null ) $append .= '&leuser=' . urlencode( $user ); |
| 386 | + if ( $title != null ) $append .= '&letitle=' . urlencode( $title ); |
| 387 | + if ( $limit != null ) $append .= '&lelimit=' . urlencode( $limit ); |
| 388 | + if ( $type != null ) $append .= '&letype=' . urlencode( $type ); |
| 389 | + if ( $start != null ) $append .= '&lestart=' . urlencode( $start ); |
| 390 | + if ( $end != null ) $append .= '&leend=' . urlencode( $end ); |
| 391 | + if ( $dir != null ) $append .= '&ledir=' . urlencode( $dir ); |
| 392 | + $x = $this->http->get( $this->apiurl . '?action=query&format=php&list=logevents&leprop=ids|title|type|user|timestamp|comment|details' . $append ); |
| 393 | + $x = unserialize( $x ); |
| 394 | + return $x['query']['logevents']; |
| 395 | + } |
| 396 | + |
| 397 | + /** |
| 398 | + * Retrieves metadata about a user's contributions. |
| 399 | + * @param $user Username whose contributions we want to retrieve. |
| 400 | + * @param $count Number of entries to return. (Default 50) |
| 401 | + * @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) |
| 402 | + * @param $dir Which direction to enumerate from, "older" or "newer". (Default 'older') |
| 403 | + * @return Associative array of contributions metadata. |
| 404 | + **/ |
| 405 | + function usercontribs ( $user, $count = 50, &$continue = null, $dir = 'older' ) { |
| 406 | + if ( $continue != null ) { |
| 407 | + $append = '&ucstart=' . urlencode( $continue ); |
| 408 | + } else { |
| 409 | + $append = ''; |
| 410 | + } |
| 411 | + $x = $this->http->get( $this->apiurl . '?action=query&format=php&list=usercontribs&ucuser=' . urlencode( $user ) . '&uclimit=' . urlencode( $count ) . '&ucdir=' . urlencode( $dir ) . $append ); |
| 412 | + $x = unserialize( $x ); |
| 413 | + $continue = $x['query-continue']['usercontribs']['ucstart']; |
| 414 | + return $x['query']['usercontribs']; |
| 415 | + } |
| 416 | + |
| 417 | + /** |
| 418 | + * Returns revision data (meta and/or actual). |
| 419 | + * @param $page Page for which to return revision data for. |
| 420 | + * @param $count Number of revisions to return. (Default 1) |
| 421 | + * @param $dir Direction to start enumerating multiple revisions from, "older" or "newer". (Default 'older') |
| 422 | + * @param $content Whether to return actual revision content, true or false. (Default false) |
| 423 | + * @param $revid Revision ID to start at. (Default null) |
| 424 | + * @param $wait Whether or not to wait a few seconds for the specific revision to become available. (Default true) |
| 425 | + * @param $getrbtok Whether or not to retrieve a rollback token for the revision. (Default false) |
| 426 | + * @param $dieonerror Whether or not to kill the process with an error if an error occurs. (Default false) |
| 427 | + * @param $redirects Whether or not to follow redirects. (Default false) |
| 428 | + * @return Associative array of revision data. |
| 429 | + **/ |
| 430 | + function revisions ( $page, $count = 1, $dir = 'older', $content = false, $revid = null, $wait = true, $getrbtok = false, $dieonerror = true, $redirects = false ) { |
| 431 | + $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':'' ) ); |
| 432 | + $x = unserialize( $x ); |
| 433 | + if ( $revid !== null ) { |
| 434 | + $found = false; |
| 435 | + if ( !isset( $x['query']['pages'] ) or !is_array( $x['query']['pages'] ) ) { |
| 436 | + if ( $dieonerror == true ) die( 'No such page.' . "\n" ); |
| 437 | + else return false; |
| 438 | + } |
| 439 | + foreach ( $x['query']['pages'] as $data ) { |
| 440 | + if ( !isset( $data['revisions'] ) or !is_array( $data['revisions'] ) ) { |
| 441 | + if ( $dieonerror == true ) die( 'No such page.' . "\n" ); |
| 442 | + else return false; |
| 443 | + } |
| 444 | + foreach ( $data['revisions'] as $data2 ) if ( $data2['revid'] == $revid ) $found = true; |
| 445 | + unset( $data, $data2 ); |
| 446 | + break; |
| 447 | + } |
| 448 | + |
| 449 | + if ( $found == false ) { |
| 450 | + if ( $wait == true ) { |
| 451 | + sleep( 1 ); |
| 452 | + return $this->revisions( $page, $count, $dir, $content, $revid, false, $getrbtok, $dieonerror ); |
| 453 | + } else { |
| 454 | + if ( $dieonerror == true ) die( 'Revision error.' . "\n" ); |
| 455 | + } |
| 456 | + } |
| 457 | + } |
| 458 | + foreach ( $x['query']['pages'] as $key => $data ) { |
| 459 | + $data['revisions']['ns'] = $data['ns']; |
| 460 | + $data['revisions']['title'] = $data['title']; |
| 461 | + $data['revisions']['currentuser'] = $x['query']['userinfo']['name']; |
| 462 | +// $data['revisions']['currentuser'] = $x['query']['userinfo']['currentuser']['name']; |
| 463 | + if ( isset( $x['query-continue'] ) ) { |
| 464 | + $data['revisions']['continue'] = $x['query-continue']['revisions']['rvstartid']; |
| 465 | + } |
| 466 | + $data['revisions']['pageid'] = $key; |
| 467 | + return $data['revisions']; |
| 468 | + } |
| 469 | + } |
| 470 | + |
| 471 | + /** |
| 472 | + * Enumerates user metadata. |
| 473 | + * @param $start The username to start enumerating from. Null means from the beginning. (Default null) |
| 474 | + * @param $limit The number of users to enumerate. (Default 1) |
| 475 | + * @param $group The usergroup to filter by. Null means no filtering. (Default null) |
| 476 | + * @param $requirestart Whether or not to require that $start be a valid username. (Default false) |
| 477 | + * @param[out] $continue This is filled with the name to continue from next query. (Default null) |
| 478 | + * @return Associative array of user metadata. |
| 479 | + **/ |
| 480 | + function users ( $start = null, $limit = 1, $group = null, $requirestart = false, &$continue = null ) { |
| 481 | + $append = ''; |
| 482 | + if ( $start != null ) $append .= '&aufrom=' . urlencode( $start ); |
| 483 | + if ( $group != null ) $append .= '&augroup=' . urlencode( $group ); |
| 484 | + $x = $this->http->get( $this->apiurl . '?action=query&list=allusers&format=php&auprop=blockinfo|editcount|registration|groups&aulimit=' . urlencode( $limit ) . $append ); |
| 485 | + $x = unserialize( $x ); |
| 486 | + $continue = $x['query-continue']['allusers']['aufrom']; |
| 487 | + if ( ( $requirestart == true ) and ( $x['query']['allusers'][0]['name'] != $start ) ) return false; |
| 488 | + return $x['query']['allusers']; |
| 489 | + } |
| 490 | + |
| 491 | + /** |
| 492 | + * Get members of a category. |
| 493 | + * @param $category Category to enumerate from. |
| 494 | + * @param $count Number of members to enumerate. (Default 500) |
| 495 | + * @param[in,out] $continue Where to continue enumerating from. This is automatically filled in when run. (Default null) |
| 496 | + * @return Associative array of category member metadata. |
| 497 | + **/ |
| 498 | + function categorymembers ( $category, $count = 500, &$continue = null ) { |
| 499 | + if ( $continue != null ) { |
| 500 | + $append = '&cmcontinue=' . urlencode( $continue ); |
| 501 | + } else { |
| 502 | + $append = ''; |
| 503 | + } |
| 504 | + $category = 'Category:' . str_ireplace( 'category:', '', $category ); |
| 505 | + $x = $this->http->get( $this->apiurl . '?action=query&list=categorymembers&cmtitle=' . urlencode( $category ) . '&format=php&cmlimit=' . $count . $append ); |
| 506 | + $x = unserialize( $x ); |
| 507 | + $continue = $x['query-continue']['categorymembers']['cmcontinue']; |
| 508 | + return $x['query']['categorymembers']; |
| 509 | + } |
| 510 | + |
| 511 | + /** |
| 512 | + * Enumerate all categories. |
| 513 | + * @param[in,out] $start Where to start enumerating. This is updated automatically with the value to continue from. (Default null) |
| 514 | + * @param $limit Number of categories to enumerate. (Default 50) |
| 515 | + * @param $dir Direction to enumerate in. 'ascending' or 'descending'. (Default 'ascending') |
| 516 | + * @param $prefix Only enumerate categories with this prefix. (Default null) |
| 517 | + * @return Associative array of category list metadata. |
| 518 | + **/ |
| 519 | + function listcategories ( &$start = null, $limit = 50, $dir = 'ascending', $prefix = null ) { |
| 520 | + $append = ''; |
| 521 | + if ( $start != null ) $append .= '&acfrom=' . urlencode( $start ); |
| 522 | + if ( $limit != null ) $append .= '&aclimit=' . urlencode( $limit ); |
| 523 | + if ( $dir != null ) $append .= '&acdir=' . urlencode( $dir ); |
| 524 | + if ( $prefix != null ) $append .= '&acprefix=' . urlencode( $prefix ); |
| 525 | + |
| 526 | + $x = $this->http->get( $this->apiurl . '?action=query&list=allcategories&acprop=size&format=php' . $append ); |
| 527 | + $x = unserialize( $x ); |
| 528 | + |
| 529 | + $start = $x['query-continue']['allcategories']['acfrom']; |
| 530 | + |
| 531 | + return $x['query']['allcategories']; |
| 532 | + } |
| 533 | + |
| 534 | + /** |
| 535 | + * Enumerate all backlinks to a page. |
| 536 | + * @param $page Page to search for backlinks to. |
| 537 | + * @param $count Number of backlinks to list. (Default 500) |
| 538 | + * @param[in,out] $continue Where to start enumerating from. This is automatically filled in. (Default null) |
| 539 | + * @param $filter Whether or not to include redirects. Acceptible values are 'all', 'redirects', and 'nonredirects'. (Default null) |
| 540 | + * @return Associative array of backlink metadata. |
| 541 | + **/ |
| 542 | + function backlinks ( $page, $count = 500, &$continue = null, $filter = null ) { |
| 543 | + if ( $continue != null ) { |
| 544 | + $append = '&blcontinue=' . urlencode( $continue ); |
| 545 | + } else { |
| 546 | + $append = ''; |
| 547 | + } |
| 548 | + if ( $filter != null ) { |
| 549 | + $append .= '&blfilterredir=' . urlencode( $filter ); |
| 550 | + } |
| 551 | + |
| 552 | + $x = $this->http->get( $this->apiurl . '?action=query&list=backlinks&bltitle=' . urlencode( $page ) . '&format=php&bllimit=' . $count . $append ); |
| 553 | + $x = unserialize( $x ); |
| 554 | + $continue = $x['query-continue']['backlinks']['blcontinue']; |
| 555 | + return $x['query']['backlinks']; |
| 556 | + } |
| 557 | + |
| 558 | + /** |
| 559 | + * Gets a list of transcludes embedded in a page. |
| 560 | + * @param $page Page to look for transcludes in. |
| 561 | + * @param $count Number of transcludes to list. (Default 500) |
| 562 | + * @param[in,out] $continue Where to start enumerating from. This is automatically filled in. (Default null) |
| 563 | + * @return Associative array of transclude metadata. |
| 564 | + **/ |
| 565 | + function embeddedin ( $page, $count = 500, &$continue = null ) { |
| 566 | + if ( $continue != null ) { |
| 567 | + $append = '&eicontinue=' . urlencode( $continue ); |
| 568 | + } else { |
| 569 | + $append = ''; |
| 570 | + } |
| 571 | + $x = $this->http->get( $this->apiurl . '?action=query&list=embeddedin&eititle=' . urlencode( $page ) . '&format=php&eilimit=' . $count . $append ); |
| 572 | + $x = unserialize( $x ); |
| 573 | + $continue = $x['query-continue']['embeddedin']['eicontinue']; |
| 574 | + return $x['query']['embeddedin']; |
| 575 | + } |
| 576 | + |
| 577 | + /** |
| 578 | + * Gets a list of pages with a common prefix. |
| 579 | + * @param $prefix Common prefix to search for. |
| 580 | + * @param $namespace Numeric namespace to filter on. (Default 0) |
| 581 | + * @param $count Number of pages to list. (Default 500) |
| 582 | + * @param[in,out] $continue Where to start enumerating from. This is automatically filled in. (Default null) |
| 583 | + * @return Associative array of page metadata. |
| 584 | + **/ |
| 585 | + function listprefix ( $prefix, $namespace = 0, $count = 500, &$continue = null ) { |
| 586 | + $append = '&apnamespace=' . urlencode( $namespace ); |
| 587 | + if ( $continue != null ) { |
| 588 | + $append .= '&apfrom=' . urlencode( $continue ); |
| 589 | + } |
| 590 | + $x = $this->http->get( $this->apiurl . '?action=query&list=allpages&apprefix=' . urlencode( $prefix ) . '&format=php&aplimit=' . $count . $append ); |
| 591 | + $x = unserialize( $x ); |
| 592 | + $continue = $x['query-continue']['allpages']['apfrom']; |
| 593 | + return $x['query']['allpages']; |
| 594 | + } |
| 595 | + |
| 596 | + /** |
| 597 | + * Edits a page. |
| 598 | + * @param $page Page name to edit. |
| 599 | + * @param $data Data to post to page. |
| 600 | + * @param $summary Edit summary to use. |
| 601 | + * @param $minor Whether or not to mark edit as minor. (Default false) |
| 602 | + * @param $bot Whether or not to mark edit as a bot edit. (Default true) |
| 603 | + * @param $wpStarttime Time in MW TS format of beginning of edit. (Default now) |
| 604 | + * @param $wpEdittime Time in MW TS format of last edit to that page. (Default correct) |
| 605 | + * @return boolean True on success, false on failure. |
| 606 | + **/ |
| 607 | + function edit ( $page, $data, $summary = '', $minor = false, $bot = true, $wpStarttime = null, $wpEdittime = null, $checkrun = true ) { |
| 608 | + global $run, $user; |
| 609 | + |
| 610 | + $wpq = new wikipediaquery( $this->apiurl, $this->queryurl, $this->indexurl ); $wpq->queryurl = str_replace( 'api.php', 'query.php', $this->apiurl ); |
| 611 | + |
| 612 | + if ( $checkrun == true ) |
| 613 | + if ( !preg_match( '/(yes|enable|true)/iS', ( ( isset( $run ) ) ? $run:$wpq->getpage( 'User:' . $user . '/Run' ) ) ) ) |
| 614 | + return false; /* Check /Run page */ |
| 615 | + |
| 616 | + $params = Array( |
| 617 | + 'action' => 'edit', |
| 618 | + 'format' => 'php', |
| 619 | + 'assert' => 'bot', |
| 620 | + 'title' => $page, |
| 621 | + 'text' => $data, |
| 622 | + 'token' => $this->getedittoken(), |
| 623 | + 'summary' => $summary, |
| 624 | + ( $minor ? 'minor':'notminor' ) => '1', |
| 625 | + ( $bot ? 'bot':'notbot' ) => '1' |
| 626 | + ); |
| 627 | + |
| 628 | + if ( $wpStarttime !== null ) $params['starttimestamp'] = $wpStarttime; |
| 629 | + if ( $wpEdittime !== null ) $params['basetimestamp'] = $wpEdittime; |
| 630 | + |
| 631 | + $x = $this->http->post( $this->apiurl, $params ); |
| 632 | + $x = unserialize( $x ); |
| 633 | + var_export( $x ); |
| 634 | + if ( $x['edit']['result'] == 'Success' ) return true; |
| 635 | + else return false; |
| 636 | + } |
| 637 | + |
| 638 | + /** |
| 639 | + * Uploads a file |
| 640 | + * @param $page Page name to edit. |
| 641 | + * @param $data Data to post to page. |
| 642 | + * @param $summary Edit summary to use. |
| 643 | + * @param $minor Whether or not to mark edit as minor. (Default false) |
| 644 | + * @param $bot Whether or not to mark edit as a bot edit. (Default true) |
| 645 | + * @param $wpStarttime Time in MW TS format of beginning of edit. (Default now) |
| 646 | + * @param $wpEdittime Time in MW TS format of last edit to that page. (Default correct) |
| 647 | + * @return boolean True on success, false on failure. |
| 648 | + **/ |
| 649 | + function uploadFromString ( $page, $data, $summary = '', $checkrun = true ) { |
| 650 | + global $run, $user; |
| 651 | + |
| 652 | + $wpq = new wikipediaquery( $this->apiurl, $this->queryurl, $this->indexurl ); $wpq->queryurl = str_replace( 'api.php', 'query.php', $this->apiurl ); |
| 653 | + |
| 654 | + /*if ($checkrun == true) |
| 655 | + if (!preg_match('/(yes|enable|true)/iS',((isset($run))?$run:$wpq->getpage('User:'.$user.'/Run')))) |
| 656 | + return false; /* Check /Run page */ |
| 657 | + |
| 658 | + |
| 659 | + /*$params = Array( |
| 660 | + 'action' => 'upload', |
| 661 | + 'filename' => $page, |
| 662 | + 'file' => $data, |
| 663 | + 'token' => $this->getedittoken(), |
| 664 | + 'comment' => $summary |
| 665 | + );*/ |
| 666 | + |
| 667 | + $params = Array( |
| 668 | + 'action' => 'upload', |
| 669 | + 'filename' => 'grokstar420', |
| 670 | + 'file' => 'foo', |
| 671 | + 'token' => $this->getedittoken(), |
| 672 | + 'text' => 'yoyo', |
| 673 | + 'comment' => 'yo' |
| 674 | + ); |
| 675 | + |
| 676 | + $x = $this->http->post( $this->apiurl, $params ); |
| 677 | + # $x = unserialize($x); |
| 678 | + # var_export($x); |
| 679 | + # if ($x['edit']['result'] == 'Success') return true; |
| 680 | + # else return false; |
| 681 | + } |
| 682 | + |
| 683 | + /** |
| 684 | + * Moves a page. |
| 685 | + * @param $old Name of page to move. |
| 686 | + * @param $new New page title. |
| 687 | + * @param $reason Move summary to use. |
| 688 | + * @return void |
| 689 | + **/ |
| 690 | + function move ( $old, $new, $reason ) { |
| 691 | + $tokens = $this->gettokens( $old ); |
| 692 | + $params = array( |
| 693 | + 'action' => 'move', |
| 694 | + 'format' => 'php', |
| 695 | + 'from' => $old, |
| 696 | + 'to' => $new, |
| 697 | + 'token' => $tokens['movetoken'], |
| 698 | + 'reason' => $reason |
| 699 | + ); |
| 700 | + |
| 701 | + $x = $this->http->post( $this->apiurl, $params ); |
| 702 | + $x = unserialize( $x ); |
| 703 | + var_export( $x ); |
| 704 | + } |
| 705 | + |
| 706 | + /** |
| 707 | + * Rollback an edit. |
| 708 | + * @param $title Title of page to rollback. |
| 709 | + * @param $user Username of last edit to the page to rollback. |
| 710 | + * @param $reason Edit summary to use for rollback. |
| 711 | + * @param $token Rollback token. If not given, it will be fetched. (Default null) |
| 712 | + * @return void |
| 713 | + **/ |
| 714 | + function rollback ( $title, $user, $reason, $token = null ) { |
| 715 | + if ( ( $token == null ) or ( $token == '' ) ) { |
| 716 | + $token = $this->revisions( $title, 1, 'older', false, null, true, true ); |
| 717 | + print_r( $token ); |
| 718 | + if ( $token[0]['user'] == $user ) { |
| 719 | + $token = $token[0]['rollbacktoken']; |
| 720 | + } else { |
| 721 | + return false; |
| 722 | + } |
| 723 | + } |
| 724 | + $params = array( |
| 725 | + 'action' => 'rollback', |
| 726 | + 'format' => 'php', |
| 727 | + 'title' => $title, |
| 728 | + 'user' => $user, |
| 729 | + 'summary' => $reason, |
| 730 | + 'token' => $token, |
| 731 | + 'markbot' => 0 |
| 732 | + ); |
| 733 | + |
| 734 | + echo 'Posting to API: '; |
| 735 | + var_export( $params ); |
| 736 | + |
| 737 | + $x = $this->http->post( $this->apiurl, $params ); |
| 738 | + $x = unserialize( $x ); |
| 739 | + var_export( $x ); |
| 740 | + return ( isset( $x['rollback']['summary'] ) ? true:false ); |
| 741 | + } |
| 742 | + |
| 743 | + /** |
| 744 | + * Inserts one or more page into the RPED table. |
| 745 | + * @return True. |
| 746 | + **/ |
| 747 | + function rpedInsert ( $page ) { |
| 748 | + $params = Array( |
| 749 | + 'action' => 'rped', |
| 750 | + 'format' => 'php', |
| 751 | + 'insert' => $page, |
| 752 | + ); |
| 753 | + |
| 754 | + $x = $this->http->post( $this->apiurl, $params ); |
| 755 | + $x = unserialize( $x ); |
| 756 | + # var_export($x); |
| 757 | + return true; |
| 758 | + } |
| 759 | + |
| 760 | + /** |
| 761 | + * Deletes one or more pages from the RPED table. |
| 762 | + * @return True. |
| 763 | + **/ |
| 764 | + function rpedDelete ( $page ) { |
| 765 | + $params = Array( |
| 766 | + 'action' => 'rped', |
| 767 | + 'format' => 'php', |
| 768 | + 'delete' => $page, |
| 769 | + ); |
| 770 | + |
| 771 | + $x = $this->http->post( $this->apiurl, $params ); |
| 772 | + $x = unserialize( $x ); |
| 773 | + # var_export($x); |
| 774 | + return true; |
| 775 | + } |
| 776 | + } |
| 777 | + |
| 778 | + /** |
| 779 | + * This class is for interacting with Wikipedia's browser interface, index.php. |
| 780 | + * Many of these functions are deprecated. |
| 781 | + **/ |
| 782 | + class wikipediaindex { |
| 783 | + private $http; |
| 784 | + private $postinterval = 0; |
| 785 | + private $lastpost; |
| 786 | + private $edittoken; |
| 787 | + public $apiurl; |
| 788 | + public $queryurl; |
| 789 | + public $indexurl; |
| 790 | + |
| 791 | + /** |
| 792 | + * This is our constructor. |
| 793 | + * @param $myApiurl API url; used if $fromFile is false |
| 794 | + * @param $myQueryurl Query url; used if $fromFile is false |
| 795 | + * @param $myIndexurl Index url; used if $fromFile is false |
| 796 | + * @param $bot Bot name; used if $fromFile is true |
| 797 | + * @param $wiki Wiki name; used if $fromFile is true |
| 798 | + * @param $fromFile If true, load settings from wikibot.config.php |
| 799 | + * @return void |
| 800 | + **/ |
| 801 | + function __construct ( $myApiurl, $myQueryurl, $myIndexurl, $bot = '', $wiki = '', $fromFile = false ) { |
| 802 | + global $indexFunctionFile; |
| 803 | + if ( $fromFile == true ) { |
| 804 | + $this->apiurl = getWikibotSetting( 'apiurl', $bot, $wiki ); |
| 805 | + $this->queryurl = getWikibotSetting( 'queryurl', $bot, $wiki ); // Obsolete, but kept for compatibility purposes. |
| 806 | + $this->indexurl = getWikibotSetting( 'indexurl', $bot, $wiki ); |
| 807 | + } else { |
| 808 | + $this->apiurl = $myApiurl; |
| 809 | + $this->queryurl = $myQueryurl; // Obsolete, but kept for compatibility purposes. |
| 810 | + $this->indexurl = $myIndexurl; |
| 811 | + } |
| 812 | + if ( isset( $indexFunctionFile ) ) { |
| 813 | + foreach ( $indexFunctionFile as $item ) { |
| 814 | + require_once( $item ); |
| 815 | + } |
| 816 | + } |
| 817 | + global $__wp__http; |
| 818 | + if ( !isset( $__wp__http ) ) { |
| 819 | + $__wp__http = new http; |
| 820 | + } |
| 821 | + $this->http = &$__wp__http; |
| 822 | + } |
| 823 | + |
| 824 | + /** |
| 825 | + * Post data to a page, nicely. |
| 826 | + * @param $page Page title. |
| 827 | + * @param $data Data to post to page. |
| 828 | + * @param $summery Edit summary. (Default '') |
| 829 | + * @param $minor Whether to mark edit as minor. (Default false) |
| 830 | + * @param $rv Revision data. If not given, it will be fetched. (Default null) |
| 831 | + * @param $bot Whether to mark edit as bot. (Default true) |
| 832 | + * @return HTML data from the page. |
| 833 | + * @deprecated |
| 834 | + * @see wikipediaapi::edit |
| 835 | + **/ |
| 836 | + function post ( $page, $data, $summery = '', $minor = false, $rv = null, $bot = true ) { |
| 837 | + global $user; |
| 838 | + global $maxlag; |
| 839 | + global $irc; |
| 840 | + global $irctechchannel; |
| 841 | + global $run; |
| 842 | + global $maxlagkeepgoing; |
| 843 | + |
| 844 | + $wpq = new wikipediaquery ( $this->apiurl, $this->queryurl, $this->indexurl ); $wpq->queryurl = str_replace( 'index.php', 'query.php', $this->indexurl ); |
| 845 | + $wpapi = new wikipediaapi ( $this->apiurl, $this->queryurl, $this->indexurl ); $wpapi->apiurl = str_replace( 'index.php', 'api.php', $this->indexurl ); |
| 846 | + |
| 847 | + if ( ( !$this->edittoken ) or ( $this->edittoken == '' ) ) $this->edittoken = $wpapi->getedittoken(); |
| 848 | + if ( $rv == null ) $rv = $wpapi->revisions( $page, 1, 'older', true ); |
| 849 | + if ( !$rv[0]['*'] ) $rv[0]['*'] = $wpq->getpage( $page ); |
| 850 | + |
| 851 | + // Fake the edit form. |
| 852 | + $now = gmdate( 'YmdHis', time() ); |
| 853 | + $token = htmlspecialchars( $this->edittoken ); |
| 854 | + $tmp = date_parse( $rv[0]['timestamp'] ); |
| 855 | + $edittime = gmdate( 'YmdHis', gmmktime( $tmp['hour'], $tmp['minute'], $tmp['second'], $tmp['month'], $tmp['day'], $tmp['year'] ) ); |
| 856 | + $html = "<input type='hidden' value=\"{$now}\" name=\"wpStarttime\" />\n"; |
| 857 | + $html .= "<input type='hidden' value=\"{$edittime}\" name=\"wpEdittime\" />\n"; |
| 858 | + $html .= "<input type='hidden' value=\"{$token}\" name=\"wpEditToken\" />\n"; |
| 859 | + $html .= '<input name="wpAutoSummary" type="hidden" value="' . md5( '' ) . '" />' . "\n"; |
| 860 | + |
| 861 | + if ( preg_match( '/' . preg_quote( '{{nobots}}', '/' ) . '/iS', $rv[0]['*'] ) ) { return false; } /* Honor the bots flags */ |
| 862 | + if ( preg_match( '/' . preg_quote( '{{bots|allow=none}}', '/' ) . '/iS', $rv[0]['*'] ) ) { return false; } |
| 863 | + if ( preg_match( '/' . preg_quote( '{{bots|deny=all}}', '/' ) . '/iS', $rv[0]['*'] ) ) { return false; } |
| 864 | + 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 */ |
| 865 | + if ( !preg_match( '/' . preg_quote( $user, '/' ) . '/iS', $rv['currentuser'] ) ) { return false; } /* We need to be logged in */ |
| 866 | +// if (preg_match('/'.preg_quote('You have new messages','/').'/iS',$rv[0]['*'])) { return false; } /* Check talk page */ |
| 867 | + if ( !preg_match( '/(yes|enable|true)/iS', ( ( isset( $run ) ) ? $run:$wpq->getpage( 'User:' . $user . '/Run' ) ) ) ) { return false; } /* Check /Run page */ |
| 868 | + |
| 869 | + $x = $this->forcepost( $page, $data, $summery, $minor, $html, $maxlag, $maxlagkeepgoing, $bot ); /* Go ahead and post. */ |
| 870 | + $this->lastpost = time(); |
| 871 | + return $x; |
| 872 | + } |
| 873 | + |
| 874 | + /** |
| 875 | + * Post data to a page. |
| 876 | + * @param $page Page title. |
| 877 | + * @param $data Data to post to page. |
| 878 | + * @param $summery Edit summary. (Default '') |
| 879 | + * @param $minor Whether to mark edit as minor. (Default false) |
| 880 | + * @param $edithtml HTML from the edit form. If not given, it will be fetched. (Default null) |
| 881 | + * @param $maxlag Maxlag for posting. (Default null) |
| 882 | + * @param $mlkg Whether to keep going after encountering a maxlag error and sleeping or not. (Default null) |
| 883 | + * @param $bot Whether to mark edit as bot. (Default true) |
| 884 | + * @return HTML data from the page. |
| 885 | + * @deprecated |
| 886 | + * @see wikipediaapi::edit |
| 887 | + **/ |
| 888 | + function forcepost ( $page, $data, $summery = '', $minor = false, $edithtml = null, $maxlag = null, $mlkg = null, $bot = true ) { |
| 889 | + $post['wpSection'] = ''; |
| 890 | + $post['wpScrolltop'] = ''; |
| 891 | + if ( $minor == true ) { $post['wpMinoredit'] = 1; } |
| 892 | + $post['wpTextbox1'] = $data; |
| 893 | + $post['wpSummary'] = $summery; |
| 894 | + if ( $edithtml == null ) { |
| 895 | + $html = $this->http->get( $this->indexurl . '?title=' . urlencode( $page ) . '&action=edit' ); |
| 896 | + } else { |
| 897 | + $html = $edithtml; |
| 898 | + } |
| 899 | + preg_match( '|\<input type\=\\\'hidden\\\' value\=\"(.*)\" name\=\"wpStarttime\" /\>|U', $html, $m ); |
| 900 | + $post['wpStarttime'] = $m[1]; |
| 901 | + preg_match( '|\<input type\=\\\'hidden\\\' value\=\"(.*)\" name\=\"wpEdittime\" /\>|U', $html, $m ); |
| 902 | + $post['wpEdittime'] = $m[1]; |
| 903 | + preg_match( '|\<input type\=\\\'hidden\\\' value\=\"(.*)\" name\=\"wpEditToken\" /\>|U', $html, $m ); |
| 904 | + $post['wpEditToken'] = $m[1]; |
| 905 | + preg_match( '|\<input name\=\"wpAutoSummary\" type\=\"hidden\" value\=\"(.*)\" /\>|U', $html, $m ); |
| 906 | + $post['wpAutoSummary'] = $m[1]; |
| 907 | + if ( $maxlag != null ) { |
| 908 | + $x = $this->http->post( $this->indexurl . '?title=' . urlencode( $page ) . '&action=submit&maxlag=' . urlencode( $maxlag ) . '&bot=' . ( ( $bot == true ) ? '1':'0' ), $post ); |
| 909 | + if ( preg_match( '/Waiting for ([^ ]*): ([0-9.-]+) seconds lagged/S', $x, $lagged ) ) { |
| 910 | + global $irc; |
| 911 | + if ( is_resource( $irc ) ) { |
| 912 | + global $irctechchannel; |
| 913 | + foreach ( explode( ',', $irctechchannel ) as $y ) { |
| 914 | + # fwrite($irc,'PRIVMSG '.$y.' :'.$lagged[1].' is lagged out by '.$lagged[2].' seconds. ('.$lagged[0].')'."\n"); |
| 915 | + } |
| 916 | + } |
| 917 | + sleep( 10 ); |
| 918 | + if ( $mlkg != true ) { return false; } |
| 919 | + else { $x = $this->http->post( $this->indexurl . '?title=' . urlencode( $page ) . '&action=submit&bot=' . ( ( $bot == true ) ? '1':'0' ), $post ); } |
| 920 | + } |
| 921 | + return $x; |
| 922 | + } else { |
| 923 | + return $this->http->post( $this->indexurl . '?title=' . urlencode( $page ) . '&action=submit&bot=' . ( ( $bot == true ) ? '1':'0' ), $post ); |
| 924 | + } |
| 925 | + } |
| 926 | + |
| 927 | + /** |
| 928 | + * Get a diff. |
| 929 | + * @param $title Page title to get the diff of. |
| 930 | + * @param $oldid Old revision ID. |
| 931 | + * @param $id New revision ID. |
| 932 | + * @param $wait Whether or not to wait for the diff to become available. (Default true) |
| 933 | + * @return Array of added data, removed data, and a rollback token if one was fetchable. |
| 934 | + **/ |
| 935 | + function diff ( $title, $oldid, $id, $wait = true ) { |
| 936 | + $deleted = ''; |
| 937 | + $added = ''; |
| 938 | + |
| 939 | + $html = $this->http->get( $this->indexurl . '?title=' . urlencode( $title ) . '&action=render&diff=' . urlencode( $id ) . '&oldid=' . urlencode( $oldid ) . '&diffonly=1' ); |
| 940 | + |
| 941 | + if ( preg_match_all( '/\&\;(oldid\=)(\d*)\\\'\>(Revision as of|Current revision as of)/USs', $html, $m, PREG_SET_ORDER ) ) { |
| 942 | + // print_r($m); |
| 943 | + if ( ( ( $oldid != $m[0][2] ) and ( is_numeric( $oldid ) ) ) or ( ( $id != $m[1][2] ) and ( is_numeric( $id ) ) ) ) { |
| 944 | + if ( $wait == true ) { |
| 945 | + sleep( 1 ); |
| 946 | + return $this->diff( $title, $oldid, $id, false ); |
| 947 | + } else { |
| 948 | + echo 'OLDID as detected: ' . $m[0][2] . ' Wanted: ' . $oldid . "\n"; |
| 949 | + echo 'NEWID as detected: ' . $m[1][2] . ' Wanted: ' . $id . "\n"; |
| 950 | + echo $html; |
| 951 | + die( 'Revision error.' . "\n" ); |
| 952 | + } |
| 953 | + } |
| 954 | + } |
| 955 | + |
| 956 | + if ( preg_match_all( '/\<td class\=(\"|\\\')diff-addedline\1\>\<div\>(.*)\<\/div\>\<\/td\>/USs', $html, $m, PREG_SET_ORDER ) ) { |
| 957 | + // print_r($m); |
| 958 | + foreach ( $m as $x ) { |
| 959 | + $added .= htmlspecialchars_decode( strip_tags( $x[2] ) ) . "\n"; |
| 960 | + } |
| 961 | + } |
| 962 | + |
| 963 | + if ( preg_match_all( '/\<td class\=(\"|\\\')diff-deletedline\1\>\<div\>(.*)\<\/div\>\<\/td\>/USs', $html, $m, PREG_SET_ORDER ) ) { |
| 964 | + // print_r($m); |
| 965 | + foreach ( $m as $x ) { |
| 966 | + $deleted .= htmlspecialchars_decode( strip_tags( $x[2] ) ) . "\n"; |
| 967 | + } |
| 968 | + } |
| 969 | + |
| 970 | + // echo $added."\n".$deleted."\n"; |
| 971 | + |
| 972 | + if ( preg_match( '/action\=rollback\&\;from\=.*\&\;token\=(.*)\"/US', $html, $m ) ) { |
| 973 | + $rbtoken = $m[1]; |
| 974 | + $rbtoken = urldecode( $rbtoken ); |
| 975 | +// echo 'rbtoken: '.$rbtoken.' -- '; print_r($m); echo "\n\n"; |
| 976 | + return array( $added, $deleted, $rbtoken ); |
| 977 | + } |
| 978 | + |
| 979 | + return array( $added, $deleted ); |
| 980 | + } |
| 981 | + |
| 982 | + /** |
| 983 | + * Rollback an edit. |
| 984 | + * @param $title Page title to rollback. |
| 985 | + * @param $user Username of last edit to the page to rollback. |
| 986 | + * @param $reason Reason to rollback. If null, default is generated. (Default null) |
| 987 | + * @param $token Rollback token to use. If null, it is fetched. (Default null) |
| 988 | + * @param $bot Whether or not to mark as bot. (Default true) |
| 989 | + * @return HTML or false if failure. |
| 990 | + * @deprecated |
| 991 | + * @see wikipediaapi::rollback |
| 992 | + **/ |
| 993 | + function rollback ( $title, $user, $reason = null, $token = null, $bot = true ) { |
| 994 | + if ( ( $token == null ) or ( !$token ) ) { |
| 995 | + $wpapi = new wikipediaapi( $this->apiurl, $this->queryurl, $this->indexurl ); $wpapi->apiurl = str_replace( 'index.php', 'api.php', $this->indexurl ); |
| 996 | + $token = $wpapi->revisions( $title, 1, 'older', false, null, true, true ); |
| 997 | + if ( $token[0]['user'] == $user ) { |
| 998 | +// echo 'Token: '; print_r($token); echo "\n\n"; |
| 999 | + $token = $token[0]['rollbacktoken']; |
| 1000 | + } else { |
| 1001 | + return false; |
| 1002 | + } |
| 1003 | + } |
| 1004 | + $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' ) ); |
| 1005 | + # global $logfd; if (!is_resource($logfd)) $logfd = fopen('php://stderr','w'); fwrite($logfd,'Rollback return: '.$x."\n"); |
| 1006 | + if ( !preg_match( '/action complete/iS', $x ) ) return false; |
| 1007 | + return $x; |
| 1008 | + } |
| 1009 | + |
| 1010 | + /** |
| 1011 | + * Move a page. |
| 1012 | + * @param $old Page title to move. |
| 1013 | + * @param $new New title to move to. |
| 1014 | + * @param $reason Move page summary. |
| 1015 | + * @return HTML page. |
| 1016 | + * @deprecated |
| 1017 | + * @see wikipediaapi::move |
| 1018 | + **/ |
| 1019 | + function move ( $old, $new, $reason ) { |
| 1020 | + $wpapi = new wikipediaapi( $this->apiurl, $this->queryurl, $this->indexurl ); $wpapi->apiurl = str_replace( 'index.php', 'api.php', $this->indexurl ); |
| 1021 | + if ( ( !$this->edittoken ) or ( $this->edittoken == '' ) ) $this->edittoken = $wpapi->getedittoken(); |
| 1022 | + |
| 1023 | + $token = htmlspecialchars( $this->edittoken ); |
| 1024 | + |
| 1025 | + $post = array |
| 1026 | + ( |
| 1027 | + 'wpOldTitle' => $old, |
| 1028 | + 'wpNewTitle' => $new, |
| 1029 | + 'wpReason' => $reason, |
| 1030 | + 'wpWatch' => '0', |
| 1031 | + 'wpEditToken' => $token, |
| 1032 | + 'wpMove' => 'Move page' |
| 1033 | + ); |
| 1034 | + return $this->http->post( $this->indexurl . '?title=Special:Movepage&action=submit', $post ); |
| 1035 | + } |
| 1036 | + |
| 1037 | + /** |
| 1038 | + * Uploads a file. |
| 1039 | + * @param $page Name of page on the wiki to upload as. |
| 1040 | + * @param $file Name of local file to upload. |
| 1041 | + * @param $desc Content of the file description page. |
| 1042 | + * @return HTML content. |
| 1043 | + **/ |
| 1044 | + function upload ( $page, $file, $desc ) { |
| 1045 | + $post = array |
| 1046 | + ( |
| 1047 | + 'wpUploadFile' => '@' . $file, |
| 1048 | + 'wpSourceType' => 'file', |
| 1049 | + 'wpDestFile' => $page, |
| 1050 | + 'wpUploadDescription' => $desc, |
| 1051 | + 'wpLicense' => '', |
| 1052 | + 'wpWatchthis' => '0', |
| 1053 | + 'wpIgnoreWarning' => '1', |
| 1054 | + 'wpUpload' => 'Upload file' |
| 1055 | + ); |
| 1056 | + return $this->http->post( $this->indexurl . '?title=Special:Upload&action=submit', $post ); |
| 1057 | + } |
| 1058 | + |
| 1059 | + /** |
| 1060 | + * Check if a user has email enabled. |
| 1061 | + * @param $user Username to check whether or not the user has email enabled. |
| 1062 | + * @return True or false depending on whether or not the user has email enabled. |
| 1063 | + **/ |
| 1064 | + function hasemail ( $user ) { |
| 1065 | + $tmp = $this->http->get( $this->indexurl . '?title=Special:EmailUser&target=' . urlencode( $user ) ); |
| 1066 | + if ( stripos( $tmp, "No e-mail address" ) !== false ) return false; |
| 1067 | + return true; |
| 1068 | + } |
| 1069 | + |
| 1070 | + /** |
| 1071 | + * Sends an email to a user. |
| 1072 | + * @param $user Username to send email to. |
| 1073 | + * @param $subject Subject of email to send. |
| 1074 | + * @param $body Body of email to send. |
| 1075 | + * @return HTML content. |
| 1076 | + **/ |
| 1077 | + function email ( $user, $subject, $body ) { |
| 1078 | + $wpapi = new wikipediaapi( $this->apiurl, $this->queryurl, $this->indexurl ); $wpapi->apiurl = str_replace( 'index.php', 'api.php', $this->indexurl ); |
| 1079 | + if ( ( !$this->edittoken ) or ( $this->edittoken == '' ) ) $this->edittoken = $wpapi->getedittoken(); |
| 1080 | + |
| 1081 | + $post = array |
| 1082 | + ( |
| 1083 | + 'wpSubject' => $subject, |
| 1084 | + 'wpText' => $body, |
| 1085 | + 'wpCCMe' => 0, |
| 1086 | + 'wpSend' => 'Send', |
| 1087 | + 'wpEditToken' => $this->edittoken |
| 1088 | + ); |
| 1089 | + |
| 1090 | + return $this->http->post( $this->indexurl . '?title=Special:EmailUser&target=' . urlencode( $user ) . '&action=submit', $post ); |
| 1091 | + } |
| 1092 | + } |
\ No newline at end of file |