BotCore.php 34.5 KB
Newer Older
1
<?php
2
require_once  __DIR__ . '/Password.php';
Luke081515's avatar
Luke081515 committed
3 4 5
/** BotCore.php
* Zentrale Datei des Cygnus-Frameworks
* Aus dieser Datei werden alle bereitgestellten Methoden des Frameworks geladen
6
* @author Freddy2001 <freddy2001@wikipedia.de>, Hgzh, Luke081515 <luke081515@tools.wmflabs.org>, MGChecker <hgasuser@gmail.com>
7
* @requires extensions: JSON
Luke081515's avatar
Luke081515 committed
8
* @version V2.1 beta
Luke081515's avatar
Luke081515 committed
9 10
* Vielen Dank an alle, die zu diesem Framework beigetragen haben
*/
11 12 13 14 15 16 17
class Core extends password {
	protected $username;
	protected $password;
	protected $curlHandle;
	protected $site;
	protected $protocol;
	protected $job;
18
	protected $assert;
19 20
	protected $mail;
	protected $mailcontent;
21
	private $version;
Luke081515's avatar
Luke081515 committed
22
	private $ua;
23

24
	/** initcurl
25
	* initialisiert curl
Luke081515's avatar
Luke081515 committed
26 27
	* Diese Methode sollte im Normallfall aufgerufen werden
	* Erstellt das Verbindungsobjekt und loggt den Bot ein
28
	* @author Hgzh
Luke081515's avatar
Luke081515 committed
29 30
	* @param $account - Name des angegebenen Accounts in Password.php
	* @param $job - Name des Jobs; dient zur Internen Speicherung der Cookies
Luke081515's avatar
Luke081515 committed
31
	* @param $pUseHTTPS - [Optional: true] falls auf false gesetzt, benutzt der Bot http statt https
32
	* @param $assert - [Optional: bot] falls auf 'user' gesetzt, kann auch ohne Flag edits gemacht werden
33
	*/
34
	public function initcurl($account, $job, $pUseHTTPS = true, $assert = 'bot') {
Luke081515's avatar
Luke081515 committed
35
		$this->version = 'Cygnus-Framework V2.1 beta';
36
		if ($assert !== 'bot' && $assert !== 'user')
MGChecker's avatar
MGChecker committed
37
			throw new Exception('assert has to be \'bot\' or \'user\'');
38
		$this->assert = $assert;
Luke081515's avatar
Luke081515 committed
39 40
		$this->start($account);
		$this->job = $job;
41
		if ($pUseHTTPS === true) 
42
			$this->protocol = 'https';
43 44 45 46 47
		else 
			$this->protocol = 'http';
		// init curl
		$curl = curl_init();
		if ($curl === false)
Luke081515's avatar
Luke081515 committed
48
			throw new Exception('Curl initialization failed.');
49 50 51
		else
			$this->curlHandle = $curl;
		$this->login();
52
		echo '\n***** Starting up....\nVersion: ' . $this->version . '\n*****';
MGChecker's avatar
MGChecker committed
53
		$this->ua = 'User:' . $this->username . ' - ' . $this->job . ' - ' . $this->version;
54
	}
55 56 57
	/** initcurlArgs
	* Benutze diese Funktion anstatt initcurl, wenn du das Passwort des Bots via args mitgeben willst
	* Ansonsten bitte initcurl benutzen
Luke081515's avatar
Luke081515 committed
58
	* Erstellt das Verbindungsobjekt und loggt den Bot ein
Luke081515's avatar
Luke081515 committed
59
	* @author Luke081515
Luke081515's avatar
Luke081515 committed
60
	* @param $job - Name des Jobs; dient zur Internen Speicherung der Cookies
Luke081515's avatar
Luke081515 committed
61
	* @param $pUseHTTPS - [Optional: true] falls auf false gesetzt, benutzt der Bot http statt https
62
	* @param $assert - [Optional: bot] falls auf 'user' gesetzt, kann auch ohne Flag edits gemacht werden
63
	*/
64 65
	public function initcurlArgs($job, $pUseHTTPS = true, $assert = 'bot') {
		if ($assert !== 'bot' && $assert !== 'user')
Luke081515's avatar
Luke081515 committed
66
			exit(1);
67
		$this->assert = $assert;
Luke081515's avatar
Luke081515 committed
68
		$this->job = $job;
69
		if ($pUseHTTPS === true) 
70
			$this->protocol = 'https';
71 72 73 74 75
		else 
			$this->protocol = 'http';
		// init curl
		$curl = curl_init();
		if ($curl === false)
Luke081515's avatar
Luke081515 committed
76
			throw new Exception('Curl initialization failed.');
77 78
		else
			$this->curlHandle = $curl;
79
		echo '\n***** Starting up....\nVersion: ' . $this->version . '\n*****';
MGChecker's avatar
MGChecker committed
80
		$this->ua = 'User:' . $this->username . ' - ' . $this->job . ' - ' . $this->version;
81
	}
Luke081515's avatar
Luke081515 committed
82
	public function __construct($account, $job, $pUseHTTPS = true) {}
83 84 85 86 87
	public function __destruct() {
		curl_close($this->curlHandle);
	}
	/** httpRequest
	* führt http(s) request durch
Luke081515's avatar
Luke081515 committed
88 89 90 91 92
	* Wird meistens benutzt um die API anzusteuern
	* @param $pArguments - API-Parameter die aufgerufen werden sollen (beginnt normalerweise mit action=)
	* @param $job - Jobname, wird benutzt um die richtigen Cookies etc zu finden. Hier einfach $this->job benutzen.
	* @param $pMethod - [optional: POST] Methode des Requests. Bei querys sollte stattdessen GET genommen werden
	* @param $pTarget - [optional: w/api.php] Verwende diesen Parameter, wenn die API deines Wikis einen anderen Einstiegspfad hat. (Special:Version)
93
	* @author Hgzh
Luke081515's avatar
Luke081515 committed
94
	* @returns Antwort der API
95
	*/
Luke081515's avatar
Luke081515 committed
96
	protected function httpRequest($arguments, $job, $method = 'POST', $target = 'w/api.php') {
97 98
		$baseURL = $this->protocol . '://' . 
				   $this->site . '/' . 
Luke081515's avatar
Luke081515 committed
99 100 101 102
				   $target;
		$method = strtoupper($method);
		if ($arguments != '') {
			if ($method === 'POST') {
103
				$requestURL = $baseURL;
Luke081515's avatar
Luke081515 committed
104 105
				$postFields = $arguments;
			} else if ($method === 'GET') {
106
				$requestURL = $baseURL . '?' .
Luke081515's avatar
Luke081515 committed
107
							  $arguments;
108
			} else 
Luke081515's avatar
Luke081515 committed
109
				throw new Exception('Unknown http request method.');
110 111
		}
		if (!$requestURL) 
Luke081515's avatar
Luke081515 committed
112
			throw new Exception('No arguments for http request found.');
113
		// set curl options
MGChecker's avatar
MGChecker committed
114
		curl_setopt($this->curlHandle, CURLOPT_USERAGENT, $this->ua);
115
		curl_setopt($this->curlHandle, CURLOPT_URL, $requestURL);
116
		curl_setopt($this->curlHandle, CURLOPT_ENCODING, 'UTF-8');
117
		curl_setopt($this->curlHandle, CURLOPT_RETURNTRANSFER, true);
Luke081515's avatar
Luke081515 committed
118 119
		curl_setopt($this->curlHandle, CURLOPT_COOKIEFILE, realpath('Cookies' . $job . '.tmp'));
		curl_setopt($this->curlHandle, CURLOPT_COOKIEJAR, realpath('Cookies' . $job . '.tmp'));
120
		// if posted, add post fields
Luke081515's avatar
Luke081515 committed
121
		if ($method === 'POST' && $postFields != '') {
122 123 124 125 126 127 128 129 130
			curl_setopt($this->curlHandle, CURLOPT_POST, 1);
			curl_setopt($this->curlHandle, CURLOPT_POSTFIELDS, $postFields);
		} else {
			curl_setopt($this->curlHandle, CURLOPT_POST, 0);
			curl_setopt($this->curlHandle, CURLOPT_POSTFIELDS, '');
		}
		// perform request
		$rqResult = curl_exec($this->curlHandle);
		if ($rqResult === false)
Luke081515's avatar
Luke081515 committed
131
			throw new Exception('Curl request failed: ' . curl_error($this->curlHandle));
132 133 134 135
		return $rqResult;
	}
	/** login
	* loggt den Benutzer ein
Luke081515's avatar
Luke081515 committed
136
	* Nicht! verwenden. Diese Methode wird nur von initcurl/initcurlargs genutzt.
137 138 139
	* @author Hgzh
	*/
	public function login() {
hgzh's avatar
hgzh committed
140 141
		// get login token
		try {
142
			$result = $this->httpRequest('action=query&format=json&meta=tokens&type=login', $this->job, 'GET');
hgzh's avatar
hgzh committed
143 144 145
		} catch (Exception $e) {
			throw $e;
		}
146
		$tree = json_decode($result, true);
hgzh's avatar
hgzh committed
147 148
		$lgToken = $tree['query']['tokens']['logintoken'];
		if ($lgToken === '')
Luke081515's avatar
Luke081515 committed
149
			throw new Exception('Could not receive login token.');	
150 151
		// perform login
		try {
Luke081515's avatar
Luke081515 committed
152 153 154
			$result = $this->httpRequest('action=login&format=json&lgname=' . urlencode($this->username) . 
				'&lgpassword=' . urlencode($this->password) . 
				'&lgtoken=' . urlencode($lgToken), $this->job);
155 156 157
		} catch (Exception $e) {
			throw $e;
		}
158
		$tree = json_decode($result, true);
159 160 161 162 163
		$lgResult = $tree['login']['result'];
		// manage result
		if ($lgResult == 'Success')
			return true;
		else
Luke081515's avatar
Luke081515 committed
164
			throw new Exception('Login failed with message ' . $lgResult);
165
	}
Luke081515's avatar
Luke081515 committed
166 167 168
	/** logout
	* Loggt den Benutzer aus
	*/
Luke081515's avatar
Luke081515 committed
169
	public function logout() {
170 171 172 173 174 175 176 177 178
		try {
			$this->httpRequest('action=logout', $this->job);
		} catch (Exception $e) {
			throw $e;		
		}
	}
	/** DO NOT USE this function
	* This is for unit-tests only
	*/
Luke081515's avatar
Luke081515 committed
179
	public function setSite($site) {
180 181 182 183 184
		$this->site = $site;
	}
	/** DO NOT USE this function
	* This is for unit-tests only
	*/
Luke081515's avatar
Luke081515 committed
185 186
	public function setUsername($username) {
		$this->username = $username;
187 188 189 190
	}
	/** DO NOT USE this function
	* This is for unit-tests only
	*/
Luke081515's avatar
Luke081515 committed
191 192
	public function setPassword($password) {
		$this->password = $password;
193 194 195
	}
	/** start
	* Sucht Logindaten aus Password.php, führt anschließend Login durch
196
	* Sollte im Normalfall nicht manuell angewendet werden, dies macht bereits initcurl
197 198
	* @author Luke081515
	*/
Luke081515's avatar
Luke081515 committed
199
	public function start($account) {
200 201 202
		$a=0;
		$Found = false;
		$this->init();
Luke081515's avatar
Luke081515 committed
203
		$LoginName = unserialize($this->getLoginName());
204 205 206
		$LoginHost = unserialize($this->getLoginHost());
		$LoginAccount = unserialize($this->getLoginAccount());
		$LoginPassword = unserialize($this->getLoginPassword());
207
		$Mail = unserialize($this->getMail());
208
		while (isset($LoginName[$a])) {
209 210 211 212 213
			if ($LoginName[$a] === $account) {
				$this->site = $LoginHost[$a];
				$this->username = $LoginAccount[$a];
				$this->password = $LoginPassword[$a];
				$this->mail = $Mail[$a];
214 215 216 217 218 219 220 221
				$Found = true;
			}
			$a++;
		}
		if (!$Found) {
			throw new Exception('Keine passenden Anmeldeinformationen vorhanden.');
		}
	}
222 223 224 225 226 227
	/** checkResult
	* Diese Methode ist fuer interne Verwendung bestimmt
	* Sie steht daher auf private
	* Sie wird aufgerufen, falls es einen Fehler gibt
	* Je nach Fehler werden entsprechende Aktionen eingeleitet
	* @author Luke081515
Luke081515's avatar
Luke081515 committed
228
	* @param $result - Fehlercode der API
229 230
	* @returns fail - Edit fehlgeschlagen, Fehlercode zeigt, das ein erneuter versuch nicht sinnvoll ist
	* @returns retry - Ein erneuter Versuch kann das Problem beheben
Luke081515's avatar
Luke081515 committed
231
	* @returns conflict - Ein Bearbeitungskonflikt ist vorhanden 
232
	*/
Luke081515's avatar
Luke081515 committed
233
	private function checkResult($result) {
234 235 236 237
		if ($result === 'maxlag' || $result === 'readonly' || $result === 'unknownerror-nocode' || $result === 'unknownerror' || $result === 'ratelimited') {
			echo '\nEdit fehlgeschlangen. Grund: $result. Versuche es erneut';
			return 'retry';
		} else if ($result === 'blocked' || $result === 'confirmemail' || $result === 'autoblocked') {
Luke081515's avatar
Luke081515 committed
238
			throw new Exception('Du kannst in der nahen Zukunft keine Aktionen ausfuehren. Grund: $result');
239
		} else if ($result === 'assertuserfailed' || $result === 'assertbotfailed') {
240
			$this->login();
241 242 243 244
			return 'retry';
		} else if ($result === 'editconflict') {
			echo '\nBearbeitungskonflikt festgestellt';
			return 'conflict';
245
		} else {
Luke081515's avatar
Luke081515 committed
246
			echo 'Aktion fehlgeschlagen. Fehlercode: $result';
247
			return 'fail';
248 249
		}
	}
250 251
	/** readPageEngine
	* Interne Methode, um die Ergebnisse einer Anfrage zum Auslesen einer Seite zu bearbeiten
252
	* @param $request – Die API-Abfrage, die den Seiteninhalt ausgibt
253
	* @author Luke081515
Luke081515's avatar
Luke081515 committed
254
	* @returns Text der Seite
255
	*/
256
	private function readPageEngine($request) {
257
		try {
258
			$page = json_decode($this->httpRequest($request, $this->job, 'GET'), true);
259 260 261
		} catch (Exception $e) {
			throw $e;
		}
262 263
		$pageID = $page['query']['pageids'][0];
		return $text['query']['pages'][$pageID]['revisions'][0]['*'];
264
	}
265 266
	/** readPage
	* Liest eine Seite aus
Luke081515's avatar
Luke081515 committed
267
	* @param $title - Titel der auszulesenden Seite
268 269 270
	* @author MGChecker
	* @returns Text der Seite
	*/
Luke081515's avatar
Luke081515 committed
271
	public function readPage($title) {
Luke081515's avatar
Luke081515 committed
272 273
		$request = 'action=query&prop=revisions&format=json&rvprop=content&rvlimit=1&rvcontentformat=text%2Fx-wiki&titles=' . urlencode($title) . 
			'&rvdir=older&rawcontinue=&indexpageids=1';
Luke081515's avatar
Luke081515 committed
274
		return $this->readPageEngine($request);
275
	}
Luke081515's avatar
Luke081515 committed
276 277
	/** readPageId
	* Liest eine Seite aus
Luke081515's avatar
Luke081515 committed
278
	* @param $pageID - ID der auszulesenden Seite
279
	* @author MGChecker
Luke081515's avatar
Luke081515 committed
280 281
	* @returns Text der Seite
	*/
282 283
	public function readPageID($pageID) {
		$request = 'action=query&prop=revisions&format=json&rvprop=content&rvlimit=1&rvcontentformat=text%2Fx-wiki&pageids=' . urlencode($pageID) . 
Luke081515's avatar
Luke081515 committed
284
			'&rvdir=older&rawcontinue=&indexpageids=1';
Luke081515's avatar
Luke081515 committed
285
		return $this->readPageEngine($request);
286
    }
Luke081515's avatar
Luke081515 committed
287 288
    /** readPageJs
	* Liest eine JavaScript-Seite aus
Luke081515's avatar
Luke081515 committed
289
	* @param $title - Titel der auszulesenden Seite
290
	* @author MGChecker
Luke081515's avatar
Luke081515 committed
291
	* @returns Text der Seite
292
	*/
Luke081515's avatar
Luke081515 committed
293
	public function readPageJs($title) {
Luke081515's avatar
Luke081515 committed
294 295
		$request = 'action=query&prop=revisions&format=json&rvprop=content&rvlimit=1&rvcontentformat=text%2Fjavascript&titles=' . urlencode($title) . 
			'&rvdir=older&rawcontinue=&indexpageids=1';
Luke081515's avatar
Luke081515 committed
296
		return $this->readPageEngine($request);
297 298 299
	}
	/** readPageCss
	* Liest eine CSS-Seite aus
Luke081515's avatar
Luke081515 committed
300
	* @param $title - Titel der auszulesenden Seite
301 302 303
	* @author MGChecker
	* @returns Text der Seite
	*/
Luke081515's avatar
Luke081515 committed
304
	public function readPageCss($title) {
Luke081515's avatar
Luke081515 committed
305 306
		$request = 'action=query&prop=revisions&format=json&rvprop=content&rvlimit=1&rvcontentformat=text%2Fcss&titles=' . urlencode($title) . 
			'&rvdir=older&rawcontinue=&indexpageids=1';
Luke081515's avatar
Luke081515 committed
307
		return $this->readPageEngine($request);
308
	}
Luke081515's avatar
Luke081515 committed
309 310
	/** readSection
	* Liest einen Abschnitt einer Seite aus
Luke081515's avatar
Luke081515 committed
311 312
	* @param $title - Titel der Auszulesenden Seite
	* @param $section Nummer des Abschnitts
313
	* @author MGChecker
Luke081515's avatar
Luke081515 committed
314
	* @returns Text des Abschnitts
315
	*/
Luke081515's avatar
Luke081515 committed
316
	public function readSection($title, $section) {
Luke081515's avatar
Luke081515 committed
317 318
		$request = 'action=query&prop=revisions&format=json&rvprop=content&rvlimit=1&rvcontentformat=text%2Fx-wiki&rvdir=older&indexpageids=1&rvsection=' . urlencode($section) . 
			'&titles=' . urlencode($title);
Luke081515's avatar
Luke081515 committed
319
		return $this->readPageEngine($request);
320
	}
321
	/** getTableOfContents
Luke081515's avatar
Luke081515 committed
322
	* Gibt das Inhaltsverzeichnis einer Seite aus
Luke081515's avatar
Luke081515 committed
323
	* @param $page - Titel der Seite
324 325 326
	* @author Luke081515
	* @returns Zwei dimensionales Array
	* @returns Erste Dimension: Der entsprechende Abschnitt
Luke081515's avatar
Luke081515 committed
327
	* @retuns Zweite Dimension: 
328 329 330
	* 	[0] => level;
	* 	[1] => Titel des Abschnitts;
	* 	[2] => Abschnittsnummer im Inhaltsverzeichnis (z.B. auch 7.5);
Luke081515's avatar
Luke081515 committed
331
	* 	[3] => Abschnittsnummer, ohne Komma, reiner int;
332
	*/
Luke081515's avatar
Luke081515 committed
333
	public function getTableOfContents($page) {
334
		try {
335
			$result = $this->httpRequest('action=parse&format=json&maxlag=5&page=' . urlencode($page) . '&prop=sections', $this->job, 'GET');
336 337 338
		} catch (Exception $e) {
			throw $e;
		}
339
		$Data = json_decode($result, true);
340
		$a=0;
341
		while (isset($Data['parse']['sections'][$a]['level'])) {
342 343 344 345
			$ret[$a][0] = $Data['parse']['sections'][$a]['level'];
			$ret[$a][1] = $Data['parse']['sections'][$a]['line'];
			$ret[$a][2] = $Data['parse']['sections'][$a]['number'];
			$ret[$a][3] = $Data['parse']['sections'][$a]['index'];
346 347 348 349
			$a++;
		}
		return $ret;
	}
350 351
	/** editPageEngine
	* Interne Methode, die die eigentliche Bearbeitung durchführt. Stattdessen eine der folgenden 6 Funktionen nutzen.
Luke081515's avatar
Luke081515 committed
352 353 354 355 356 357 358 359
	* @param $title - Seitenname
	* @param $content - Neuer Seitentext
	* @param $summary - Zusammenfassung
	* @param $botflag - Falls true wird der Edit mit Botflag markiert
	* @param $minorflag - Falls true wird der Edit als Klein markiert
	* @param $noCreate - Soll die Seite ggf neu angelegt werden? (Standard => nein)
	* @param $sectionnumber - Welcher Abschnitt soll bearbeitet werden? (Standard => ganze Seite)
	* @param $overrideNobots - Soll die NoBots Vorlage ignoriert werden?
360
	* @author Hgzh / Luke081515 / MGChecker
Luke081515's avatar
Luke081515 committed
361 362
	* @returns Unserialisierte Antwort der API, falls der Edit erfolgreich war
	*/
Luke081515's avatar
Luke081515 committed
363
	private function editPageEngine($title, $content, $summary, $botflag, $minorflag, $noCreate = 1, $sectionnumber = -1, $overrideNobots = false) {
364
		retry:
Luke081515's avatar
Luke081515 committed
365 366
		if ($overrideNobots !== true) {
			if ($this->allowBots($this->readPage($title)) === false)
367
				return 'nobots';
Luke081515's avatar
Luke081515 committed
368
		}
Luke081515's avatar
Luke081515 committed
369
		// get csrf token
hgzh's avatar
hgzh committed
370
		try {
371
			$result = $this->httpRequest('action=query&format=json&meta=tokens&type=csrf', $this->job, 'GET');
372
		} catch (Exception $e) {
hgzh's avatar
hgzh committed
373 374
			throw $e;
		}
375
		$tree  = json_decode($result, true);
hgzh's avatar
hgzh committed
376 377 378
		$token = $tree['query']['tokens']['csrftoken'];
		if ($token === '')
			throw new Exception('could not receive csrf token.');
Luke081515's avatar
Luke081515 committed
379
		// perform edit
380
		$request = 'action=edit&assert=' . $this->assert . '&format=json&bot=&title=' . urlencode($title) . 
Luke081515's avatar
Luke081515 committed
381
			'&text=' . urlencode($content) . 
382
			'&token=' . urlencode($token) . 
Luke081515's avatar
Luke081515 committed
383 384 385 386 387 388 389
			'&summary=' . urlencode($summary) .
			'&bot=' . urlencode($botflag) . 
			'&minor=' . urlencode($minorflag);
		if ($noCreate === 1)
			$request .= '&minor=' . urlencode($minorflag);
		if ($sectionnumber !== -1)
			$request .= '&section=' . urlencode($sectionnumber);
Luke081515's avatar
Luke081515 committed
390 391 392 393 394
		try {
			$result = $this->httpRequest($request, $this->job);
		} catch (Exception $e) {
			throw $e;
		}
395
		$tree = json_decode($result, true);
Luke081515's avatar
Luke081515 committed
396 397
		$editres = $tree['edit']['result'];
		// manage result
tools.freddy2001's avatar
tools.freddy2001 committed
398
		if ($editres == 'Success') {
Luke081515's avatar
Luke081515 committed
399
			if (array_key_exists('nochange', $tree['edit'])) {
400
				return array('nochange');
tools.freddy2001's avatar
tools.freddy2001 committed
401
			} else {
Luke081515's avatar
Luke081515 committed
402
				return array($tree['edit']['oldrevid'], $tree['edit']['newrevid']);
tools.freddy2001's avatar
tools.freddy2001 committed
403 404
			}
		}
405
		else {
tools.freddy2001's avatar
tools.freddy2001 committed
406
			$Code = $this->checkResult($editres);
407 408 409
			if ($Code === 'fail')
				return 'fail';
			else if ($Code === 'retry')
410
				goto retry;
411 412
			else if ($Code === 'conflict')
				return 'conflict';
413
		}
Luke081515's avatar
Luke081515 committed
414
	}
415 416
	/** editPage
	* Bearbeitet eine Seite
Luke081515's avatar
Luke081515 committed
417 418 419 420 421
	* @param $title - Seitenname
	* @param $content - Neuer Seitentext
	* @param $summary - Zusammenfassung
	* @param $noCreate - Soll die Seite ggf neu angelegt werden? (Standard => nein)
	* @param $overrideNobots - Soll trotz Verbot des Bots per Vorlage bearbeitet werden? (Standard => nein)
Luke081515's avatar
Luke081515 committed
422
	* @author Freddy2001 / Luke081515
423 424
	* @returns Unserialisierte Antwort der API, falls der Edit erfolgreich war
	*/
Luke081515's avatar
Luke081515 committed
425
	public function editPage($title, $content, $summary, $noCreate = 1, $overrideNobots = false) {
426
		if ($this->assert == 'bot')
Luke081515's avatar
Luke081515 committed
427
			$botflag = true;
428
		else
Luke081515's avatar
Luke081515 committed
429 430
			$botflag = false;
		return $this->editPageEngine($title, $content, $summary, $botflag, false, $noCreate, -1, $overrideNobots);
431 432 433
	}
	/** editPageMinor
	* Bearbeitet eine Seite als kleine Bearbeitung
Luke081515's avatar
Luke081515 committed
434 435 436 437 438
	* @param $title - Seitenname
	* @param $content - Neuer Seitentext
	* @param $summary - Zusammenfassung
	* @param $noCreate - Soll die Seite ggf neu angelegt werden? (Standard => nein)
	* @param $overrideNobots - Soll trotz Verbot des Bots per Vorlage bearbeitet werden? (Standard => nein)
Luke081515's avatar
Luke081515 committed
439
	* @author Freddy2001 / Luke081515
440 441
	* @returns Unserialisierte Antwort der API, falls der Edit erfolgreich war
	*/
Luke081515's avatar
Luke081515 committed
442
	public function editPageMinor($title, $content, $summary, $noCreate = 1, $overrideNobots = false) {
443
		if ($this->assert == 'bot')
Luke081515's avatar
Luke081515 committed
444
			$botflag = true;
445
		else
Luke081515's avatar
Luke081515 committed
446 447
			$botflag = false;
		return $this->editPageEngine($title, $content, $summary, $botflag, true, $noCreate, -1, $overrideNobots);
448
	}
Luke081515's avatar
Luke081515 committed
449
	/** editPageD
450
	* Bearbeitet eine Seite
Luke081515's avatar
Luke081515 committed
451 452 453 454 455 456 457
	* @param $title - Seitenname
	* @param $content - Neuer Seitentext
	* @param $summary - Zusammenfassung
	* @param $botflag - Falls true wird der Edit mit Botflag markiert
	* @param $minorflag - Falls true wird der Edit als Klein markiert
	* @param $noCreate - Soll die Seite ggf neu angelegt werden? (Standard => nein)
	* @param $overrideNobots - Soll trotz Verbot des Bots per Vorlage bearbeitet werden? (Standard => nein)
Luke081515's avatar
Luke081515 committed
458
	* @author MGChecker / Luke081515
Luke081515's avatar
Luke081515 committed
459 460
	* @returns Unserialisierte Antwort der API, falls der Edit erfolgreich war
	*/
Luke081515's avatar
Luke081515 committed
461 462
	public function editPageD($title, $content, $summary, $botflag, $minorflag, $noCreate = 1, $overrideNobots = false) {
		return $this->editPageEngine($title, $content, $summary, $botflag, $minorflag, $noCreate, -1, $overrideNobots);
Luke081515's avatar
Luke081515 committed
463
	}
Luke081515's avatar
Luke081515 committed
464 465
	/** editSection
	* Bearbeitet einen Abschnitt
Luke081515's avatar
Luke081515 committed
466 467 468 469 470 471
	* @param $title - Seitenname
	* @param $content - Neuer Seitentext
	* @param $summary - Zusammenfassung
	* @param $sectionnumber - Nummer des Abschnitts
	* @param $noCreate - Soll die Seite ggf neu angelegt werden? (Standard => nein)
	* @param $overrideNobots - Soll trotz Verbot des Bots per Vorlage bearbeitet werden? (Standard => nein)
Luke081515's avatar
Luke081515 committed
472
	* @author Freddy2001 / MGChecker / Luke081515
Luke081515's avatar
Luke081515 committed
473
	* @returns Unserialisierte Antwort der API, falls der Edit erfolgreich war
474
	*/
Luke081515's avatar
Luke081515 committed
475
	public function editSection($title, $content, $summary, $sectionnumber, $noCreate = 1, $overrideNobots = false) {
476
		if ($this->assert == 'bot')
Luke081515's avatar
Luke081515 committed
477
			$botflag = true;
478
		else
Luke081515's avatar
Luke081515 committed
479 480
			$botflag = false;
		if ($sectionnumber < 0)
481
			throw new Exception('You selected a invalid section number. To edit a whole page, use editPage().');
Luke081515's avatar
Luke081515 committed
482
		return $this->editPageEngine($title, $content, $summary, $botflag, false, $noCreate, $sectionnumber, $overrideNobots);
483 484 485
	}
	/** editSectionMinor
	* Bearbeitet einen Abschnitt
Luke081515's avatar
Luke081515 committed
486 487 488 489 490 491
	* @param $title - Seitenname
	* @param $content - Neuer Seitentext
	* @param $summary - Zusammenfassung
	* @param $sectionnumber - Nummer des Abschnitts
	* @param $noCreate - Soll die Seite ggf neu angelegt werden? (Standard => nein)
	* @param $overrideNobots - Soll trotz Verbot des Bots per Vorlage bearbeitet werden? (Standard => nein)
Luke081515's avatar
Luke081515 committed
492
	* @author Freddy2001 / MGChecker / Luke081515
493 494
	* @returns Unserialisierte Antwort der API, falls der Edit erfolgreich war
	*/
Luke081515's avatar
Luke081515 committed
495
	public function editSectionMinor($title, $content, $summary, $sectionnumber, $noCreate = 1, $overrideNobots = false) {
496
		if ($this->assert == 'bot')
Luke081515's avatar
Luke081515 committed
497
			$botflag = true;
498
		else
Luke081515's avatar
Luke081515 committed
499 500
			$botflag = false;
		if ($sectionnumber < 0)
501
			throw new Exception('You selected a invalid section number. To edit a whole page, use editPageMinor().');
Luke081515's avatar
Luke081515 committed
502
		return $this->editPageEngine($title, $content, $summary, $botflag, true, $noCreate, $sectionnumber, $overrideNobots);
503
	}
Luke081515's avatar
Luke081515 committed
504 505
	/** editSectionD
	* Bearbeitet eine Seite (Auswahl weitere Parameter moeglich)
Luke081515's avatar
Luke081515 committed
506 507 508 509 510 511 512 513
	* @param $title - Seitenname
	* @param $content - Neuer Seitentext
	* @param $summary - Zusammenfassung
	* @param $botflag - Falls true wird der Edit mit Botflag markiert
	* @param $minorflag - Falls true wird der Edit als Klein markiert
	* @param $sectionnumber - Nummer des Abschnitts
	* @param $noCreate - Soll die Seite ggf neu angelegt werden? (Standard => nein)
	* @param $overrideNobots - Soll trotz Verbot des Bots per Vorlage bearbeitet werden? (Standard => nein)
Luke081515's avatar
Luke081515 committed
514
	* @author MGChecker / Luke081515
Luke081515's avatar
Luke081515 committed
515 516
	* @returns Unserialisierte Antwort der API, falls der Edit erfolgreich war
	*/
Luke081515's avatar
Luke081515 committed
517 518
	public function editSectionD($title, $content, $summary, $sectionnumber, $botflag, $minorflag, $noCreate = 1, $overrideNobots = false) {
		if ($sectionnumber < 0)
519
			throw new Exception('You selected a invalid section number. To edit a whole page, use editPageD().');
Luke081515's avatar
Luke081515 committed
520
		return $this->editPageEngine($title, $content, $summary, $botflag,  $minorflag, $noCreate, $sectionnumber, $overrideNobots);
521
	}
Luke081515's avatar
Luke081515 committed
522
	/** movePage
Luke081515's avatar
Luke081515 committed
523
	* Verschiebt eine Seite
Luke081515's avatar
Luke081515 committed
524 525
	* @param $startLemma - Alter Titel der Seite
	* @param $targetLemma - Neuer Titel der Seite
Luke081515's avatar
Luke081515 committed
526 527 528
	* @param - $bot (default: 0) - Botflag setzen?
	* @param - $movetalk (default: 1) - Diskussionsseite mitverschieben?
	* @param - $noredirect - (default: 1) - Weiterleitung erstellen?
Luke081515's avatar
Luke081515 committed
529
	* @param $reason - Grund der Verschiebung, der im Log vermerkt wird
Luke081515's avatar
Luke081515 committed
530 531
	* @returns Serialisierte Antwort der API-Parameter
	*/
Luke081515's avatar
Luke081515 committed
532
	public function movePage($startLemma, $targetLemma, $reason, $bot = 0, $movetalk = 1, $noredirect = 1) {
533
		$data = 'action=query&format=json&meta=tokens&type=csrf';
hgzh's avatar
hgzh committed
534 535 536 537 538
		try {
			$result = $this->httpRequest($data, $this->job, 'GET');
		} catch (Exception $e) {
			throw $e;
		}
539
		$answer = json_decode($result, true);
hgzh's avatar
hgzh committed
540
		$token = $answer['query']['tokens']['csrftoken'];
Luke081515's avatar
Luke081515 committed
541 542 543 544 545 546 547 548
		$data = 'action=move&format=json&assert=' . $this->assert . 
			'&from=' . urlencode($startLemma) . 
			'&to=' . urlencode($targetLemma) . 
			'&reason=' . urlencode($reason) . 
			'&bot=' . $bot . 
			'&movetalk=' . $movetalk . 
			'&noredirect=' . $noredirect . 
			'&token=' . urlencode($token);
549 550 551 552 553
		try {
			$result = $this->httpRequest($data, $this->job);
		} catch (Exception $e) {
			throw $e;
		}
554
		return serialize(json_decode($result, true));
555 556 557 558 559
	}
	/** getCatMembers
	* Liest alle Seiten der Kategorie aus, auch Seiten die in Unterkategorien der angegebenen Kategorie kategorisiert sind
	* Funktioniert bis zu 5000 Unterkategorien pro Katgorie (nicht 5000 Unterkategorien insgesamt)
	* Erfordert Botflag, da Limit auf 5000 gesetzt, (geht zwar sonst auch, aber nur mit Warnung)
Luke081515's avatar
Luke081515 committed
560
	* @author Luke081515
Luke081515's avatar
Luke081515 committed
561 562 563
	* @param $kat - Kategorie die analyisiert werden soll.
	* @param $onlySubCats - [optional: false] Falls true, werden nur die Unterkategorien, nicht die Titel der Seiten weitergegeben
	* @param $excludeWls - [optional: false] Falls true, werden keine Kategorien mit Weiterleitungen weitergegeben
Luke081515's avatar
Luke081515 committed
564
	* @returns false, falls keine Seiten vorhanden, ansonsten serialisiertes Array mit Seitentiteln
565
	*/
Luke081515's avatar
Luke081515 committed
566
	public function getCatMembers($kat, $onlySubCats = false, $excludeWls = false) {
567
		$b=0;
568
		$subCat[0] = $kat;
569
		try {
Luke081515's avatar
Luke081515 committed
570 571
			$result = $this->httpRequest('action=query&list=categorymembers&format=json&cmtitle=' . urlencode($kat) . 
				'&cmprop=title&cmtype=subcat&cmlimit=5000&cmsort=sortkey&cmdir=ascending&rawcontinue=', $this->job, 'GET');
572 573 574
		} catch (Exception $e) {
			throw $e;
		}
575
		$answer = json_decode($result, true);
576
		$a=0;
577
		if (isset($answer['query']['categorymembers'][$a]['title'])) {
578
			$Sub = true;
579
			while (isset($answer['query']['categorymembers'][$a]['title'])) {
580
				$subCat[$b] = $answer['query']['categorymembers'][$a]['title'];	
581 582 583 584
				$b++;
				$a++;
			}
		}
Luke081515's avatar
Luke081515 committed
585 586
		$b = 0;
		$c = 0;
Luke081515's avatar
Luke081515 committed
587
		if ($onlySubCats === true)
588
			return $subCat;
Luke081515's avatar
Luke081515 committed
589
		if ($excludeWls === false) {	
590
			while (isset($subCat[$b]))
591 592
			{
				try {
Luke081515's avatar
Luke081515 committed
593 594
					$result = $this->httpRequest('action=query&list=categorymembers&format=json&cmtitle=' . urlencode($subCat[$b]) . 
						'&cmprop=title&cmtype=page&cmlimit=5000&cmsort=sortkey&cmdir=ascending&rawcontinue=', $this->job, 'GET');
595 596 597
				} catch (Exception $e) {
					throw $e;
				}
598
				$answer = json_decode($result, true);
599
				$Cont = false;
600 601
				if (isset($answer['query-continue']['categorymembers']['cmcontinue'])) {
					$Continue = $answer['query-continue']['categorymembers']['cmcontinue'];
602 603 604 605
					$Cont = true;
				}
				while ($Cont === true) {
					$a=0;
606 607 608
					if (isset($answer['query']['categorymembers'][$a]['title'])) {
						while (isset($answer['query']['categorymembers'][$a]['title'])) {
							$page[$c] = $answer['query']['categorymembers'][$a]['title'];	
609 610 611 612 613
							$c++;
							$a++;
						}
					} else  {}
					try {
614 615
						$result = $this->httpRequest('action=query&list=categorymembers&format=json&cmcontinue=' . $Continue 
						. '&cmtitle=' . urlencode($subCat[$b]) 
616 617 618 619
						. '&cmprop=title&cmtype=page&cmlimit=5000&cmsort=sortkey&cmdir=ascending&rawcontinue=', $this->job, 'GET');
					} catch (Exception $e) {
						throw $e;
					}
620 621 622
					$answer = json_decode($result, true);
					if (isset($answer['query-continue']['categorymembers']['cmcontinue'])) {
						$Continue = $answer['query-continue']['categorymembers']['cmcontinue'];
623 624 625 626
						$Cont = true;
					} else
						$Cont = false;
				}
627
				$a=0;
628 629 630
				if (isset($answer['query']['categorymembers'][$a]['title']) === true) {
					while (isset($answer['query']['categorymembers'][$a]['title'])) {
						$page[$c] = $answer['query']['categorymembers'][$a]['title'];	
631 632 633
						$c++;
						$a++;
					}
634 635 636 637
				} else {}
				$b++;
			}
		} else {
638
			while (isset($subCat[$b])) {
639
				try {
Luke081515's avatar
Luke081515 committed
640 641
					$result = $this->httpRequest('action=query&format=json&generator=categorymembers&gcmtitle=' . urlencode($subCat[$b]) . 
						'&prop=info&gcmlimit=5000&rawcontinue=&redirects', $this->job, 'GET');
642 643 644
				} catch (Exception $e) {
					throw $e;
				}
645
				$answer = json_decode($result, true);
646
				$Cont = false;
647 648
				if (isset($answer['query-continue']['categorymembers']['gcmcontinue'])) {
					$Continue = $answer['query-continue']['categorymembers']['gcmcontinue'];
649 650
					$Cont = true;
				}
651 652
				while ($Cont === true) {
					$a=0;
653 654 655
					if (isset($answer['query']['pages'][$a]['title'])) {
						while (isset($answer['query']['pages'][$a]['title'])) {
							$page[$c] = $answer['query']['pages'][$a]['title'];	
656 657 658 659 660
							$c++;
							$a++;
						}
					} else  {}
					try {
Luke081515's avatar
Luke081515 committed
661 662 663
						$result = $this->httpRequest('action=query&format=json&generator=categorymembers&gcmtitle=' . urlencode($subCat[$b]) . 
							'&gmcontinue=' . $Continue . 
							'&prop=info&gcmlimit=5000&rawcontinue=&redirects', $this->job, 'GET');
664 665 666
					} catch (Exception $e) {
						throw $e;
					}
667 668 669
					$answer = json_decode($result, true);
					if (isset($answer['query-continue']['pages']['gcmcontinue'])) {
						$Continue = $answer['query-continue']['pages']['gcmcontinue'];
670 671 672 673 674
						$Cont = true;
					} else
						$Cont = false;
				}
				$a=0;
675 676 677
				if (isset($answer['query']['pages'][$a]['title'])) {
					while (isset($answer['query']['pages'][$a]['title'])) {
						$page[$c] = $answer['query']['pages'][$a]['title'];	
678 679 680 681 682 683
						$c++;
						$a++;
					}
				} else {}
				$b++;
			}
684
		}
685
		if (!isset($page[0]))
686
				return false;
687
		else
688
			return serialize($page);
689 690 691 692 693
	}
	/** getPageCats
	* Liest alle Kategorien einer Seite aus
	* Funktioniert bis zu 500 Kategorien einer Seite
	* Erfordert Botflag, da Limit auf 5000 gesetzt
Luke081515's avatar
Luke081515 committed
694
	* @author Luke081515
695
	* @param $page - Seite die analyisiert werden soll
Luke081515's avatar
Luke081515 committed
696
	* @returns Alle Kategorien als serialisiertes Array
697
	*/
698
	public function getPageCats($page) {
699
		try {
Luke081515's avatar
Luke081515 committed
700 701 702
			$cats = $this->httpRequest('action=query&prop=categories&format=json&cllimit=5000&titles=' . urlencode($Page) . 
				'&cldir=ascending&rawcontinue=&indexpageids=1', $this->job, 'GET');
			$cats = json_decode($cats, true);
703 704 705
		} catch (Exception $e) {
			throw $e;
		}
706
		$pageID = $cats['query']['pageids'][0];
707
		$a=0;
708 709
		while (isset($cats['query']['pages'][$pageID]['categories'][$a])) {
			$catResults[$a] = $cats['query']['pages'][$pageID]['categories'][$a];
710
			$a++;
711
		}
712
		if (!isset($catResults[0]))
713
			return false;
714
		return serialize($catResults);
715 716 717 718
	}
	/** getAllEmbedings
	* Liest alle Einbindungen einer Vorlage aus
	* Erfordert Botflag, da Limit auf 5000 gesetzt
Luke081515's avatar
Luke081515 committed
719 720 721
	* @author Luke081515
	* @param Vorlage, deren Einbindungen aufgelistet werden sollen
	* @returns false, falls keine Einbindungen vorhanden, ansonsten serialisiertes Array mit Seitentiteln
722
	*/
Luke081515's avatar
Luke081515 committed
723
	public function getAllEmbedings($templ) {
724 725 726
		$b=0;
		$Again = true;
		while ($Again === true) {
727 728 729 730
			if (isset($Continue))
				$data = 'action=query&list=embeddedin&format=json&eititle=' . urlencode($templ) . 
					'&einamespace=0&eicontinue=' . urlencode($Continue) . 
					'&eidir=ascending&eilimit=5000&rawcontinue=';
731
			else
732
				$data = 'action=query&list=embeddedin&format=json&eititle=' . urlencode($templ) . '&einamespace=0&eidir=ascending&eilimit=5000&rawcontinue=';
733 734 735 736 737
			try {
				$result = $this->httpRequest($data, $this->job, 'GET');
			} catch (Exception $e) {
				throw $e;
			}
738
			$answer = json_decode($result, true);
739
			$a=0;
740 741
			if (isset($answer['query-continue']['embeddedin']['eicontinue'])) {
				$Continue = $answer['query-continue']['embeddedin']['eicontinue'];
742 743 744 745
				$Again = true;
			}
			else
				$Again = false;
746 747 748
			if (isset($answer['query']['embeddedin'][$a]['title'])) {
				while (isset($answer['query']['embeddedin'][$a]['title'])) {
					$page[$b] = $answer['query']['embeddedin'][$a]['title'];
749 750 751 752 753 754
					$b++;
					$a++;
				}
			} else
				return false;
		}
755
		return serialize($page);
756 757 758 759
	}
	/** getAllPages
	* Liest alle Seiten eines Namensraumes aus
	* Erfordert Botflag, da Limit auf 5000 gesetzt (geht zwar sonst auch, aber nur mit Warnung)
Luke081515's avatar
Luke081515 committed
760 761 762
	* @author Luke081515
	* @param Nummer des Namensraumes, von dem die Seiten ausgelesen werden
	* @returns false, falls keine Seiten im Namensraum vorhanden, ansonsten serialisiertes Array mit Seitentiteln
763
	*/
Luke081515's avatar
Luke081515 committed
764
	public function getAllPages($namespace) {
765 766 767
		$b=0;
		$Again = true;
		while ($Again === true) {
768 769
			if (isset($Continue))
				$data = 'action=query&list=allpages&format=json&apcontinue=' . $Continue . '&apnamespace=' . $namespace . '&aplimit=5000&apdir=ascending&rawcontinue=';
770
			else
771
				$data = 'action=query&list=allpages&format=json&apnamespace=' . $namespace . '&aplimit=5000&apdir=ascending&rawcontinue=';
772 773 774 775 776
			try {
				$result = $this->httpRequest($data, $this->job, 'GET');
			} catch (Exception $e) {
				throw $e;
			}
777
			$answer = json_decode($result, true);
778
			$a=0;
779 780
			if (isset($answer['query-continue']['allpages']['apcontinue'])) {
				$Continue = $answer['query-continue']['allpages']['apcontinue'];
781 782 783
				$Again = true;
			} else
				$Again = false;
784 785 786
			if (isset($answer['query']['allpages'][$a]['title'])) {
				while (isset($answer['query']['allpages'][$a]['title'])) {
					$page[$b] = $answer['query']['allpages'][$a]['title'];
787 788 789 790 791 792
					$b++;
					$a++;
				}
			} else
				return false;
		}
793
		return serialize($page);
794
	}
795 796
	/** getPageID
	* Gibt zu der angegebenen Seite die ID an
797
	* @author Luke081515
Luke081515's avatar
Luke081515 committed
798
	* @param $page - Name der Seite
Luke081515's avatar
Luke081515 committed
799
	* @returns int: PageID, bool: false falls Seite nicht vorhanden
800
	*/
Luke081515's avatar
Luke081515 committed
801
	public function getPageID($page) {
802
		$data = 'action=query&format=json&maxlag=5&prop=info&indexpageids=1&titles=' . urlencode($page);
803 804 805 806 807
		try {
			$result = $this->httpRequest($data, $this->job, 'GET');
		} catch (Exception $e) {
			throw $e;
		}
808
		if (strpos ($result, 'missing') !== false)
809
			return false;
810
		$answer = json_decode($result, true);
Luke081515's avatar
Luke081515 committed
811
		return $tree['query']['pageids'][0];
812
	}
813
	/** getLinks
Luke081515's avatar