Passed
Push — master ( b237e3...69f046 )
by Daimona
01:32
created

WikiController::getToken()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 1
dl 0
loc 15
rs 9.9666
c 0
b 0
f 0
1
<?php declare( strict_types=1 );
2
3
namespace BotRiconferme;
4
5
use BotRiconferme\Exception\EditException;
6
use BotRiconferme\Exception\LoginException;
7
use BotRiconferme\Exception\APIRequestException;
8
use BotRiconferme\Exception\MissingPageException;
9
use BotRiconferme\Request\RequestBase;
10
11
/**
12
 * Class for wiki interaction, contains some requests shorthands
13
 */
14
class WikiController {
15
	/** @var bool */
16
	private static $loggedIn = false;
17
	/** @var Logger */
18
	private $logger;
19
	/** @var string[] */
20
	private $tokens;
21
22
	public function __construct() {
23
		$this->logger = new Logger;
24
	}
25
26
	/**
27
	 * Gets the content of a wiki page
28
	 *
29
	 * @param string $title
30
	 * @return string
31
	 * @throws MissingPageException
32
	 */
33
	public function getPageContent( string $title ) : string {
34
		$this->logger->debug( "Retrieving page $title" );
35
		$params = [
36
			'action' => 'query',
37
			'titles' => $title,
38
			'prop' => 'revisions',
39
			'rvslots' => 'main',
40
			'rvprop' => 'content'
41
		];
42
43
		$req = RequestBase::newFromParams( $params );
44
		$data = $req->execute();
45
		$page = reset( $data->query->pages );
46
		if ( isset( $page->missing ) ) {
47
			throw new MissingPageException( $title );
48
		}
49
50
		return $page->revisions[0]->slots->main->{ '*' };
51
	}
52
53
	/**
54
	 * Basically a wrapper for action=edit
55
	 *
56
	 * @param array $params
57
	 * @throws EditException
58
	 */
59
	public function editPage( array $params ) {
60
		$this->login();
61
62
		$params = [
63
			'action' => 'edit',
64
			'token' => $this->getToken( 'csrf' ),
65
			'bot' => Config::getInstance()->get( 'bot-edits' )
66
		] + $params;
67
68
		$res = RequestBase::newFromParams( $params, true )->execute();
69
		if ( $res->edit->result !== 'Success' ) {
70
			throw new EditException( $res->edit->info );
71
		}
72
	}
73
74
	/**
75
	 * Login wrapper. Checks if we're already logged in and clears tokens cache
76
	 * @throws LoginException
77
	 */
78
	public function login() {
79
		if ( self::$loggedIn ) {
80
			$this->logger->debug( 'Already logged in' );
81
			return;
82
		}
83
84
		$this->logger->info( 'Logging in' );
85
86
		$params = [
87
			'action' => 'login',
88
			'lgname' => Config::getInstance()->get( 'username' ),
89
			'lgpassword' => Config::getInstance()->get( 'password' ),
90
			'lgtoken' => $this->getToken( 'login' )
91
		];
92
93
		try {
94
			$res = RequestBase::newFromParams( $params, true )->execute();
95
		} catch ( APIRequestException $e ) {
96
			throw new LoginException( $e->getMessage() );
97
		}
98
99
		if ( !isset( $res->login->result ) || $res->login->result !== 'Success' ) {
100
			throw new LoginException( 'Unknown error' );
101
		}
102
103
		self::$loggedIn = true;
104
		// Clear tokens cache
105
		$this->tokens = [];
106
		$this->logger->info( 'Login succeeded' );
107
	}
108
109
	/**
110
	 * Get a token, cached.
111
	 *
112
	 * @param string $type
113
	 * @return string
114
	 */
115
	public function getToken( string $type ) : string {
116
		if ( !isset( $this->tokens[ $type ] ) ) {
117
			$params = [
118
				'action' => 'query',
119
				'meta'   => 'tokens',
120
				'type'   => $type
121
			];
122
123
			$req = RequestBase::newFromParams( $params );
124
			$res = $req->execute();
125
126
			$this->tokens[ $type ] = $res->query->tokens->{ "{$type}token" };
127
		}
128
129
		return $this->tokens[ $type ];
130
	}
131
132
	/**
133
	 * Get the timestamp of the creation of the given page
134
	 *
135
	 * @param string $title
136
	 * @return int
137
	 */
138
	public function getPageCreationTS( string $title ) : int {
139
		$params = [
140
			'action' => 'query',
141
			'prop' => 'revisions',
142
			'titles' => $title,
143
			'rvprop' => 'timestamp',
144
			'rvslots' => 'main',
145
			'rvlimit' => 1,
146
			'rvdir' => 'newer'
147
		];
148
149
		$res = ( RequestBase::newFromParams( $params ) )->execute();
150
		$data = $res->query->pages;
151
		return strtotime( reset( $data )->revisions[0]->timestamp );
152
	}
153
154
	/**
155
	 * Sysop-level inifinite protection for a given page
156
	 *
157
	 * @param string $title
158
	 * @param string $reason
159
	 */
160
	public function protectPage( string $title, string $reason ) {
161
		$this->logger->info( "Protecting page $title" );
162
		$this->login();
163
164
		$params = [
165
			'action' => 'protect',
166
			'title' => $title,
167
			'protections' => 'edit=sysop|move=sysop',
168
			'expiry' => 'infinite',
169
			'reason' => $reason,
170
			'token' => $this->getToken( 'csrf' )
171
		];
172
173
		RequestBase::newFromParams( $params, true )->execute();
174
	}
175
}
176