1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* Copyright (C) 2014 Reaby |
5
|
|
|
* |
6
|
|
|
* This program is free software: you can redistribute it and/or modify |
7
|
|
|
* it under the terms of the GNU General Public License as published by |
8
|
|
|
* the Free Software Foundation, either version 3 of the License, or |
9
|
|
|
* (at your option) any later version. |
10
|
|
|
* |
11
|
|
|
* This program is distributed in the hope that it will be useful, |
12
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14
|
|
|
* GNU General Public License for more details. |
15
|
|
|
* |
16
|
|
|
* You should have received a copy of the GNU General Public License |
17
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
18
|
|
|
*/ |
19
|
|
|
|
20
|
|
|
namespace eXpansion\Bundle\MxKarma\Services; |
21
|
|
|
|
22
|
|
|
use eXpansion\Bundle\MxKarma\Entity\MxRating; |
23
|
|
|
use eXpansion\Bundle\MxKarma\Entity\MxVote; |
24
|
|
|
use eXpansion\Framework\Core\Helpers\Http; |
25
|
|
|
use eXpansion\Framework\Core\Helpers\Structures\HttpResult; |
26
|
|
|
use eXpansion\Framework\Core\Services\Application\AbstractApplication; |
27
|
|
|
use eXpansion\Framework\Core\Services\Application\Dispatcher; |
28
|
|
|
use eXpansion\Framework\Core\Services\Console; |
29
|
|
|
use eXpansion\Framework\Core\Storage\GameDataStorage; |
30
|
|
|
use eXpansion\Framework\Core\Storage\MapStorage; |
31
|
|
|
use Maniaplanet\DedicatedServer\Structures\GameInfos; |
32
|
|
|
use Maniaplanet\DedicatedServer\Structures\Map; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Description of Connection |
36
|
|
|
* |
37
|
|
|
* @author Reaby |
38
|
|
|
*/ |
39
|
|
|
class MxKarmaService |
40
|
|
|
{ |
41
|
|
|
|
42
|
|
|
const EVENT_CONNECT = "expansion.mxkarma.connect"; |
43
|
|
|
const EVENT_VOTESAVE = "expansion.mxkarma.votesave"; |
44
|
|
|
const EVENT_VOTELOAD = 'expansion.mxkarma.voteload'; |
45
|
|
|
const EVENT_DISCONNECT = 'expansion.mxkarma.disconnect'; |
46
|
|
|
|
47
|
|
|
private $address = "http://karma.mania-exchange.com/api2/"; |
48
|
|
|
private $options = [CURLOPT_HTTPHEADER => ["Content-Type:application/json"]]; |
49
|
|
|
|
50
|
|
|
private $connected = false; |
51
|
|
|
|
52
|
|
|
private $sessionKey = null; |
53
|
|
|
|
54
|
|
|
private $sessionSeed = null; |
55
|
|
|
|
56
|
|
|
/** @var MxRating */ |
57
|
|
|
private $ratings = null; |
58
|
|
|
/** |
59
|
|
|
* @var Dispatcher |
60
|
|
|
*/ |
61
|
|
|
private $dispatcher; |
62
|
|
|
/** |
63
|
|
|
* @var GameDataStorage |
64
|
|
|
*/ |
65
|
|
|
private $gameDataStorage; |
66
|
|
|
/** |
67
|
|
|
* @var MapStorage |
68
|
|
|
*/ |
69
|
|
|
private $mapStorage; |
70
|
|
|
/** |
71
|
|
|
* @var Console |
72
|
|
|
*/ |
73
|
|
|
private $console; |
74
|
|
|
|
75
|
|
|
/** @var Http */ |
76
|
|
|
private $http; |
77
|
|
|
/** |
78
|
|
|
* @var string |
79
|
|
|
*/ |
80
|
|
|
private $apiKey; |
81
|
|
|
/** |
82
|
|
|
* @var string |
83
|
|
|
*/ |
84
|
|
|
private $serverLogin; |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Connection constructor. |
88
|
|
|
* |
89
|
|
|
* @param Dispatcher $dispatcher |
90
|
|
|
* @param Http $http |
91
|
|
|
* @param GameDataStorage $gameDataStorage |
92
|
|
|
* @param MapStorage $mapStorage |
93
|
|
|
* @param Console $console |
94
|
|
|
*/ |
95
|
|
|
public function __construct( |
96
|
|
|
Dispatcher $dispatcher, |
97
|
|
|
Http $http, |
98
|
|
|
GameDataStorage $gameDataStorage, |
99
|
|
|
MapStorage $mapStorage, |
100
|
|
|
Console $console |
101
|
|
|
) { |
102
|
|
|
$this->dispatcher = $dispatcher; |
103
|
|
|
$this->http = $http; |
104
|
|
|
$this->gameDataStorage = $gameDataStorage; |
105
|
|
|
$this->mapStorage = $mapStorage; |
106
|
|
|
$this->console = $console; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* connect to MX karma |
112
|
|
|
* |
113
|
|
|
* @param string $serverLogin |
114
|
|
|
* @param string $apikey |
115
|
|
|
* @return void |
116
|
|
|
*/ |
117
|
|
|
public function connect($serverLogin, $apikey) |
118
|
|
|
{ |
119
|
|
|
$this->apiKey = $apikey; |
120
|
|
|
$this->serverLogin = $serverLogin; |
121
|
|
|
|
122
|
|
|
if (empty($this->apiKey)) { |
123
|
|
|
$this->console->writeln('MxKarma error: You need to define a api key'); |
124
|
|
|
|
125
|
|
|
return; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
if (empty($this->serverLogin)) { |
129
|
|
|
$this->console->writeln('MxKarma error: You need to define server login'); |
130
|
|
|
|
131
|
|
|
return; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
$params = [ |
135
|
|
|
"serverLogin" => $serverLogin, |
136
|
|
|
"applicationIdentifier" => "eXpansion v ".AbstractApplication::EXPANSION_VERSION, |
137
|
|
|
"testMode" => "false", |
138
|
|
|
]; |
139
|
|
|
|
140
|
|
|
$this->console->writeln('> MxKarma attempting to connect...'); |
141
|
|
|
$this->http->get( |
142
|
|
|
$this->buildUrl( |
143
|
|
|
"startSession", $params), |
144
|
|
|
[$this, "xConnect"] |
145
|
|
|
); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* @param HttpResult $result |
150
|
|
|
*/ |
151
|
|
|
public function xConnect(HttpResult $result) |
152
|
|
|
{ |
153
|
|
|
|
154
|
|
|
if ($result->hasError()) { |
155
|
|
|
$this->console->writeln('> MxKarma connection failure: $f00'.$result->getError()); |
156
|
|
|
$this->disconnect(); |
157
|
|
|
|
158
|
|
|
return; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
$data = $this->getObject($result->getResponse()); |
162
|
|
|
|
163
|
|
|
if ($data === null) { |
164
|
|
|
return; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
$this->sessionKey = $data->sessionKey; |
168
|
|
|
$this->sessionSeed = $data->sessionSeed; |
169
|
|
|
|
170
|
|
|
$outHash = hash("sha512", ($this->apiKey.$this->sessionSeed)); |
171
|
|
|
|
172
|
|
|
$params = array("sessionKey" => $this->sessionKey, "activationHash" => $outHash); |
173
|
|
|
$this->console->writeln('> MxKarma attempting to activate session...'); |
174
|
|
|
$this->http->get( |
175
|
|
|
$this->buildUrl("activateSession", $params), |
176
|
|
|
[$this, "xActivate"], |
177
|
|
|
[], |
178
|
|
|
$this->options |
179
|
|
|
); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
View Code Duplication |
public function xActivate(HttpResult $result) |
|
|
|
|
183
|
|
|
{ |
184
|
|
|
|
185
|
|
|
if ($result->hasError()) { |
186
|
|
|
$this->console->writeln('> MxKarma activation failure: $f00'.$result->getError()); |
187
|
|
|
|
188
|
|
|
return; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
$data = $this->getObject($result->getResponse()); |
192
|
|
|
|
193
|
|
|
if ($data === null) { |
194
|
|
|
return; |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
if ($data->activated) { |
198
|
|
|
$this->connected = true; |
199
|
|
|
$this->console->writeln('> MxKarma connection $0f0success!'); |
200
|
|
|
$this->dispatcher->dispatch(self::EVENT_CONNECT, []); |
201
|
|
|
} |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* loads votes from server |
206
|
|
|
* @param array $players |
207
|
|
|
* @param bool $getVotesOnly |
208
|
|
|
*/ |
209
|
|
|
public function loadVotes($players = array(), $getVotesOnly = false) |
210
|
|
|
{ |
211
|
|
|
if (!$this->connected) { |
212
|
|
|
$this->console->writeln('> MxKarma trying to load votes when not connected: $ff0aborting!'); |
213
|
|
|
|
214
|
|
|
return; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
$this->console->writeln('> MxKarma attempting to load votes...'); |
218
|
|
|
$params = array("sessionKey" => $this->sessionKey); |
219
|
|
|
$postData = [ |
220
|
|
|
"gamemode" => $this->getGameMode(), |
221
|
|
|
"titleid" => $this->gameDataStorage->getVersion()->titleId, |
222
|
|
|
"mapuid" => $this->mapStorage->getCurrentMap()->uId, |
223
|
|
|
"getvotesonly" => $getVotesOnly, |
224
|
|
|
"playerlogins" => $players, |
225
|
|
|
]; |
226
|
|
|
|
227
|
|
|
$this->http->post( |
228
|
|
|
$this->buildUrl("getMapRating", $params), |
229
|
|
|
json_encode($postData), |
230
|
|
|
array($this, "xGetRatings"), |
231
|
|
|
[], |
232
|
|
|
$this->options |
233
|
|
|
); |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
/** |
237
|
|
|
* @param Map $map |
238
|
|
|
* @param int $time time in seconds from BeginMap to EndMap |
239
|
|
|
* @param MxVote[] $votes |
240
|
|
|
*/ |
241
|
|
|
public function saveVotes(Map $map, $time, $votes) |
242
|
|
|
{ |
243
|
|
|
if (!$this->connected) { |
244
|
|
|
$this->console->writeln('> MxKarma not connected, aborting save votes'); |
245
|
|
|
|
246
|
|
|
return; |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
$params = array("sessionKey" => $this->sessionKey); |
250
|
|
|
|
251
|
|
|
$postData = array( |
252
|
|
|
"gamemode" => $this->getGameMode(), |
253
|
|
|
"titleid" => $this->gameDataStorage->getVersion()->titleId, |
254
|
|
|
"mapuid" => $map->uId, |
255
|
|
|
"mapname" => $map->name, |
256
|
|
|
"mapauthor" => $map->author, |
257
|
|
|
"isimport" => false, |
258
|
|
|
"maptime" => $time, |
259
|
|
|
"votes" => $votes, |
260
|
|
|
); |
261
|
|
|
|
262
|
|
|
$this->console->writeln('> MxKarma attempting to save votes...'); |
263
|
|
|
$this->http->post( |
264
|
|
|
$this->buildUrl("saveVotes", $params), |
265
|
|
|
json_encode($postData), |
266
|
|
|
[$this, "xSaveVotes"], |
267
|
|
|
[], |
268
|
|
|
$this->options |
269
|
|
|
); |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
/** |
273
|
|
|
* @param HttpResult $result |
274
|
|
|
*/ |
275
|
|
View Code Duplication |
public function xSaveVotes(HttpResult $result) |
|
|
|
|
276
|
|
|
{ |
277
|
|
|
|
278
|
|
|
if ($result->hasError()) { |
279
|
|
|
$this->console->writeln('> MxKarma save votes failure: $f00'.$result->getError()); |
280
|
|
|
|
281
|
|
|
return; |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
$data = $this->getObject($result->getResponse()); |
285
|
|
|
|
286
|
|
|
if ($data === null) { |
287
|
|
|
return; |
288
|
|
|
} |
289
|
|
|
$this->console->writeln('> MxKarma save votes $0f0success!'); |
290
|
|
|
$this->dispatcher->dispatch(self::EVENT_VOTESAVE, ["updated" => $data->updated]); |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* @param HttpResult $result |
295
|
|
|
* @return MxRating|null |
296
|
|
|
*/ |
297
|
|
|
public function xGetRatings(HttpResult $result) |
298
|
|
|
{ |
299
|
|
|
|
300
|
|
|
if ($result->hasError()) { |
301
|
|
|
$this->console->writeln('> MxKarma load votes failure: $f00'.$result->getError()); |
302
|
|
|
|
303
|
|
|
return null; |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
$data = $this->getObject($result->getResponse()); |
307
|
|
|
|
308
|
|
|
if ($data === null) { |
309
|
|
|
return null; |
310
|
|
|
} |
311
|
|
|
try { |
312
|
|
|
$this->ratings = new MXRating(); |
313
|
|
|
$this->ratings->append($data); |
314
|
|
|
|
315
|
|
|
$this->console->writeln('> MxKarma load $0f0success!'); |
316
|
|
|
$this->dispatcher->dispatch(self::EVENT_VOTELOAD, ["ratings" => $this->ratings]); |
317
|
|
|
|
318
|
|
|
return $this->ratings; |
319
|
|
|
} catch (\Exception $ex) { |
320
|
|
|
return null; |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
/** |
326
|
|
|
* @return string |
327
|
|
|
*/ |
328
|
|
|
public function getGameMode() |
329
|
|
|
{ |
330
|
|
|
$gamemode = ""; |
331
|
|
|
switch ($this->gameDataStorage->getGameInfos()->gameMode) { |
332
|
|
|
case GameInfos::GAMEMODE_SCRIPT: |
333
|
|
|
$gamemode = strtolower($this->gameDataStorage->getGameInfos()->scriptName); |
334
|
|
|
break; |
335
|
|
|
case GameInfos::GAMEMODE_ROUNDS: |
336
|
|
|
$gamemode = "Rounds"; |
337
|
|
|
break; |
338
|
|
|
case GameInfos::GAMEMODE_CUP: |
339
|
|
|
$gamemode = "Cup"; |
340
|
|
|
break; |
341
|
|
|
case GameInfos::GAMEMODE_TEAM: |
342
|
|
|
$gamemode = "Team"; |
343
|
|
|
break; |
344
|
|
|
case GameInfos::GAMEMODE_LAPS: |
345
|
|
|
$gamemode = "Laps"; |
346
|
|
|
break; |
347
|
|
|
case GameInfos::GAMEMODE_TIMEATTACK: |
348
|
|
|
$gamemode = "TimeAttack"; |
349
|
|
|
break; |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
return $gamemode; |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
/** |
356
|
|
|
* @param string $data json data |
357
|
|
|
* |
358
|
|
|
* @return object|null |
359
|
|
|
*/ |
360
|
|
|
public function getObject($data) |
361
|
|
|
{ |
362
|
|
|
$obj = (object)json_decode($data); |
363
|
|
|
|
364
|
|
|
if ($obj->success === false) { |
365
|
|
|
$this->handleErrors($obj); |
366
|
|
|
|
367
|
|
|
return null; |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
return $obj->data; |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
/** |
374
|
|
|
* @param object $obj |
375
|
|
|
*/ |
376
|
|
|
public function handleErrors($obj) |
377
|
|
|
{ |
378
|
|
|
switch ($obj->data->code) { |
379
|
|
|
case 1: |
380
|
|
|
$this->console->writeln('> MxKarma $fffinternal server error'); |
381
|
|
|
break; |
382
|
|
|
case 2: |
383
|
|
|
$this->console->writeln('> MxKarma $fffSession key is invalid (not activated, expired or got disabled).'); |
384
|
|
|
break; |
385
|
|
|
case 3: |
386
|
|
|
$this->console->writeln('> MxKarma $fffSome parameters are not provided.'); |
387
|
|
|
break; |
388
|
|
|
case 4: |
389
|
|
|
$this->console->writeln('> MxKarma $fffAPI key not found or suspended.'); |
390
|
|
|
$this->disconnect(); |
391
|
|
|
break; |
392
|
|
|
case 5: |
393
|
|
|
$this->console->writeln('> MxKarma $fffServer not found or suspended.'); |
394
|
|
|
$this->disconnect(); |
395
|
|
|
break; |
396
|
|
|
case 6: |
397
|
|
|
$this->console->writeln('> MxKarma $fffServer is banned.'); |
398
|
|
|
$this->disconnect(); |
399
|
|
|
break; |
400
|
|
|
case 7: |
401
|
|
|
$this->console->writeln('> MxKarma $fffCross-server call rejected.'); |
402
|
|
|
break; |
403
|
|
|
case 8: |
404
|
|
|
$this->console->writeln('> MxKarma $fffInvalid activation hash provided, session closed.'); |
405
|
|
|
$this->disconnect(); |
406
|
|
|
break; |
407
|
|
|
case 9: |
408
|
|
|
$this->console->writeln('> MxKarma $fffSession already active.'); |
409
|
|
|
$this->disconnect(); |
410
|
|
|
break; |
411
|
|
|
case 10: |
412
|
|
|
$this->console->writeln('> MxKarma $fffUnsupported Content-Type.'); |
413
|
|
|
break; |
414
|
|
|
case 11: |
415
|
|
|
$this->console->writeln('> MxKarma $fffToo many logins requested.'); |
416
|
|
|
break; |
417
|
|
|
case 12: |
418
|
|
|
$this->console->writeln('> MxKarma $fffInvalid JSON or invalid structure.'); |
419
|
|
|
break; |
420
|
|
|
case 13: |
421
|
|
|
$this->console->writeln('> MxKarma $fffMalformed vote request.'); |
422
|
|
|
break; |
423
|
|
|
case 14: |
424
|
|
|
$this->console->writeln('> MxKarma $fffno votes cast - please do not make requests if there are no votes!'); |
425
|
|
|
break; |
426
|
|
|
case 15: |
427
|
|
|
$this->console->writeln('> MxKarma $ffftoo many import votes - request a limit raise if needed'); |
428
|
|
|
break; |
429
|
|
|
case 16: |
430
|
|
|
$this->console->writeln('> MxKarma $fffImport rejected.'); |
431
|
|
|
break; |
432
|
|
|
default: |
433
|
|
|
$this->console->writeln('> MxKarma $fffUnknown api error'); |
434
|
|
|
break; |
435
|
|
|
} |
436
|
|
|
|
437
|
|
|
// Dispatcher::dispatch(new MXKarmaEvent(MXKarmaEvent::ON_ERROR, $origin, $obj->data->code, $obj->data->message)); |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
/** |
441
|
|
|
* @param string $method |
442
|
|
|
* @param array $params |
443
|
|
|
* |
444
|
|
|
* @return string |
445
|
|
|
*/ |
446
|
|
|
private function buildUrl($method, $params) |
447
|
|
|
{ |
448
|
|
|
$url = $this->address.$method; |
449
|
|
|
|
450
|
|
|
return $url."?".http_build_query($params); |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
/** |
454
|
|
|
* @return bool |
455
|
|
|
*/ |
456
|
|
|
public function isConnected() |
457
|
|
|
{ |
458
|
|
|
return $this->connected; |
459
|
|
|
} |
460
|
|
|
|
461
|
|
|
/** |
462
|
|
|
* |
463
|
|
|
*/ |
464
|
|
|
public function disconnect() |
465
|
|
|
{ |
466
|
|
|
$this->connected = false; |
467
|
|
|
$this->console->writeln('> MxKarma $f00disconnected!'); |
468
|
|
|
$this->dispatcher->dispatch(self::EVENT_DISCONNECT, []); |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
} |
472
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.