1
0
Fork 0
mirror of https://codeberg.org/demostf/api.git synced 2026-06-03 18:04:08 +02:00
This commit is contained in:
Robin Appelman 2019-01-23 18:56:44 +01:00
commit c29fe61ad1
24 changed files with 1242 additions and 50 deletions

1191
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -45,7 +45,7 @@ class DemoController extends BaseController {
* @param string $id * @param string $id
*/ */
public function get($id) { public function get($id) {
$this->json($this->demoProvider->get(intval($id, 10))); $this->json($this->demoProvider->get(\intval($id, 10)));
} }
protected function getFilter() { protected function getFilter() {
@ -61,7 +61,7 @@ class DemoController extends BaseController {
$filter['backend'] = $backend; $filter['backend'] = $backend;
} }
if ($players) { if ($players) {
if (!is_array($players)) { if (!\is_array($players)) {
$players = explode(',', $players); $players = explode(',', $players);
} }
$players = array_filter($players); $players = array_filter($players);
@ -96,7 +96,7 @@ class DemoController extends BaseController {
public function listDemos() { public function listDemos() {
$page = $this->query('page', 1); $page = $this->query('page', 1);
$order = $this->query('order', 'DESC') === 'ASC' ? 'ASC' : 'DESC'; $order = 'ASC' === $this->query('order', 'DESC') ? 'ASC' : 'DESC';
$this->json($this->demoListProvider->listDemos((int) $page, $this->getFilter(), $order)); $this->json($this->demoListProvider->listDemos((int) $page, $this->getFilter(), $order));
} }
@ -122,16 +122,16 @@ class DemoController extends BaseController {
$path = (string) $this->post('path', ''); $path = (string) $this->post('path', '');
$url = (string) $this->post('url', ''); $url = (string) $this->post('url', '');
$editKey = (string) $this->post('key', ''); $editKey = (string) $this->post('key', '');
if ($editKey !== $this->editKey || $editKey === '') { if ($editKey !== $this->editKey || '' === $editKey) {
throw new \InvalidArgumentException('Invalid key'); throw new \InvalidArgumentException('Invalid key');
} }
$demo = $this->demoProvider->get((int) $id); $demo = $this->demoProvider->get((int) $id);
$existingHash = $demo->getHash(); $existingHash = $demo->getHash();
if ($existingHash === '' || $existingHash === $hash) { if ('' === $existingHash || $existingHash === $hash) {
$this->demoProvider->setDemoUrl((int) $id, $backend, $url, $path); $this->demoProvider->setDemoUrl((int) $id, $backend, $url, $path);
if ($demo->getBackend() === 'static') { if ('static' === $demo->getBackend()) {
$this->store->remove($demo); $this->store->remove($demo);
} }
} else { } else {

View file

@ -1,7 +1,8 @@
<?php <?php
declare(strict_types=1);
/** /**
* @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
*
* @license GNU AGPL version 3 or any later version * @license GNU AGPL version 3 or any later version
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -16,12 +17,10 @@
* *
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/ */
namespace Demostf\API\Controllers; namespace Demostf\API\Controllers;
class TempController extends BaseController { class TempController extends BaseController {
private $webRoot; private $webRoot;
@ -31,6 +30,7 @@ class TempController extends BaseController {
public function register(string $key, string $path): string { public function register(string $key, string $path): string {
apcu_store($key, $path); apcu_store($key, $path);
return $this->webRoot . $key; return $this->webRoot . $key;
} }

View file

@ -31,7 +31,7 @@ class UploadController extends BaseController {
try { try {
$result = $this->uploadProvider->upload($key, $red, $blu, $name, $demoFile); $result = $this->uploadProvider->upload($key, $red, $blu, $name, $demoFile);
if ($result === 'Invalid key') { if ('Invalid key' === $result) {
\Flight::response()->status(401)->write($result)->send(); \Flight::response()->status(401)->write($result)->send();
} else { } else {
echo $result; echo $result;

View file

@ -79,7 +79,7 @@ class DemoPlayer implements \JsonSerializable {
return $this->deaths; return $this->deaths;
} }
public static function fromRow($row): DemoPlayer { public static function fromRow($row): self {
return new self( return new self(
$row['id'], $row['id'],
$row['user_id'], $row['user_id'],

View file

@ -34,11 +34,11 @@ class SteamUser implements \JsonSerializable {
return [ return [
'id' => $this->getId(), 'id' => $this->getId(),
'steamid' => $this->getSteamId(), 'steamid' => $this->getSteamId(),
'name' => $this->getName() 'name' => $this->getName(),
]; ];
} }
public static function fromRow(array $row): SteamUser { public static function fromRow(array $row): self {
return new self( return new self(
(int) $row['id'], (int) $row['id'],
$row['steamid'], $row['steamid'],

View file

@ -53,7 +53,7 @@ class User implements \JsonSerializable {
]; ];
} }
public static function fromRow(array $row): User { public static function fromRow(array $row): self {
return new self( return new self(
(int) $row['id'], (int) $row['id'],
$row['steamid'], $row['steamid'],

View file

@ -149,7 +149,7 @@ class Demo implements \JsonSerializable {
$this->uploaderUser = $uploaderUser; $this->uploaderUser = $uploaderUser;
} }
public static function fromRow($row): Demo { public static function fromRow($row): self {
return new self( return new self(
(int) $row['id'], (int) $row['id'],
$row['url'], $row['url'],

View file

@ -52,7 +52,7 @@ class DemoSaver {
$upload->getBlue(), $upload->getBlue(),
$demo->getRedScore(), $demo->getRedScore(),
$demo->getBlueScore(), $demo->getBlueScore(),
count($demo->getPlayers()), \count($demo->getPlayers()),
$upload->getUploaderId(), $upload->getUploaderId(),
$upload->getHash(), $upload->getHash(),
$storedDemo->getBackend(), $storedDemo->getBackend(),

View file

@ -19,8 +19,8 @@ class DemoStore {
public function store(string $sourcePath, string $name): StoredDemo { public function store(string $sourcePath, string $name): StoredDemo {
$target = $this->generatePath($name); $target = $this->generatePath($name);
if (!is_dir(dirname($target))) { if (!is_dir(\dirname($target))) {
mkdir(dirname($target), 0777, true); mkdir(\dirname($target), 0777, true);
} }
rename($sourcePath, $target); rename($sourcePath, $target);
chmod($target, 0755); chmod($target, 0755);

View file

@ -17,7 +17,7 @@ class HeaderParser {
'A8type/Iversion/Iprotocol/A260server/A260nick/A260map/A260game/fduration/Vticks/Vframes/Vsigon', 'A8type/Iversion/Iprotocol/A260server/A260nick/A260map/A260game/fduration/Vticks/Vframes/Vsigon',
$head $head
); );
if (!isset($info['type']) || $info['type'] !== 'HL2DEMO') { if (!isset($info['type']) || 'HL2DEMO' !== $info['type']) {
throw new \InvalidArgumentException('Not an HL2 demo'); throw new \InvalidArgumentException('Not an HL2 demo');
} }
@ -52,7 +52,7 @@ class HeaderParser {
if (!is_readable($path)) { if (!is_readable($path)) {
throw new \InvalidArgumentException('Unable to open demo: ' . $path); throw new \InvalidArgumentException('Unable to open demo: ' . $path);
} }
$fh = fopen($path, 'rb'); $fh = fopen($path, 'r');
return $this->parseStream($fh); return $this->parseStream($fh);
} }

View file

@ -35,7 +35,7 @@ class Parser {
public function analyse(string $path): ParsedDemo { public function analyse(string $path): ParsedDemo {
$data = $this->rawParser->parse($path); $data = $this->rawParser->parse($path);
if (is_array($data)) { if (\is_array($data)) {
return $this->handleData($data); return $this->handleData($data);
} else { } else {
throw new \InvalidArgumentException('Error parsing demo'); throw new \InvalidArgumentException('Error parsing demo');
@ -55,7 +55,7 @@ class Parser {
throw new \Exception("Error while parsing demo, no rounds field found\n" . json_encode($data)); throw new \Exception("Error while parsing demo, no rounds field found\n" . json_encode($data));
} }
foreach ($data['rounds'] as $round) { foreach ($data['rounds'] as $round) {
if ($round['winner'] === 'red') { if ('red' === $round['winner']) {
++$red; ++$red;
} else { } else {
++$blue; ++$blue;
@ -89,15 +89,15 @@ class Parser {
if (!isset($activityMap[$kill->getAttackerDemoId()])) { if (!isset($activityMap[$kill->getAttackerDemoId()])) {
$activityMap[$kill->getAttackerDemoId()] = 0; $activityMap[$kill->getAttackerDemoId()] = 0;
} }
$activityMap[$kill->getAttackerDemoId()]++; ++$activityMap[$kill->getAttackerDemoId()];
if (!isset($activityMap[$kill->getAssisterDemoId()])) { if (!isset($activityMap[$kill->getAssisterDemoId()])) {
$activityMap[$kill->getAssisterDemoId()] = 0; $activityMap[$kill->getAssisterDemoId()] = 0;
} }
$activityMap[$kill->getAssisterDemoId()]++; ++$activityMap[$kill->getAssisterDemoId()];
if (!isset($activityMap[$kill->getVictimDemoId()])) { if (!isset($activityMap[$kill->getVictimDemoId()])) {
$activityMap[$kill->getVictimDemoId()] = 0; $activityMap[$kill->getVictimDemoId()] = 0;
} }
$activityMap[$kill->getVictimDemoId()]++; ++$activityMap[$kill->getVictimDemoId()];
} }
foreach ($data['users'] as $player) { foreach ($data['users'] as $player) {
@ -113,7 +113,7 @@ class Parser {
$class = $classId; $class = $classId;
} }
} }
if ($player['steamId'] && $player['steamId'] !== 'BOT') {//skip spectators if ($player['steamId'] && 'BOT' !== $player['steamId']) {//skip spectators
$players[] = new ParsedPlayer( $players[] = new ParsedPlayer(
$player['name'], $player['name'],
$player['userId'], $player['userId'],
@ -152,7 +152,7 @@ class Parser {
* @return string The converted 64bit numeric SteamID * @return string The converted 64bit numeric SteamID
*/ */
public static function convertSteamIdToCommunityId(string $steamId): string { public static function convertSteamIdToCommunityId(string $steamId): string {
if ($steamId === 'STEAM_ID_LAN' || $steamId === 'BOT') { if ('STEAM_ID_LAN' === $steamId || 'BOT' === $steamId) {
throw new \InvalidArgumentException("Cannot convert SteamID \"$steamId\" to a community ID."); throw new \InvalidArgumentException("Cannot convert SteamID \"$steamId\" to a community ID.");
} }
if (preg_match('/^STEAM_[0-1]:[0-1]:[0-9]+$/', $steamId)) { if (preg_match('/^STEAM_[0-1]:[0-1]:[0-9]+$/', $steamId)) {

View file

@ -33,8 +33,8 @@ class RawParser {
$response = $client->post($this->parserUrl, [ $response = $client->post($this->parserUrl, [
'body' => stream_for($url), 'body' => stream_for($url),
'headers' => [ 'headers' => [
'Content-Type' => 'application/octet-stream' 'Content-Type' => 'application/octet-stream',
] ],
]); ]);
$result = json_decode($response->getBody()->getContents(), true); $result = json_decode($response->getBody()->getContents(), true);
$this->tempController->unregister($key); $this->tempController->unregister($key);
@ -45,7 +45,7 @@ class RawParser {
} }
} catch (RequestException $e) { } catch (RequestException $e) {
$this->tempController->unregister($key); $this->tempController->unregister($key);
if (strpos($e->getMessage(), 'cURL error 52') !== false) { if (false !== strpos($e->getMessage(), 'cURL error 52')) {
throw new \Exception('Failed to parse demo, can\'t reach demo parser'); throw new \Exception('Failed to parse demo, can\'t reach demo parser');
} }
throw new \Exception('Failed to parse demo, ' . $e->getMessage() . ' ' . $url); throw new \Exception('Failed to parse demo, ' . $e->getMessage() . ' ' . $url);

View file

@ -51,7 +51,7 @@ class BaseProvider {
]; ];
if (isset($aliases[$table])) { if (isset($aliases[$table])) {
return $aliases[$table]; return $aliases[$table];
} elseif (array_search($table, $rawNames, true) === false) { } elseif (false === array_search($table, $rawNames, true)) {
return $table . 's'; return $table . 's';
} else { } else {
return $table; return $table;

View file

@ -30,7 +30,7 @@ class DemoListProvider extends BaseProvider {
->groupBy('demo_id') ->groupBy('demo_id')
->having($query->expr()->eq( ->having($query->expr()->eq(
'COUNT(user_id)', 'COUNT(user_id)',
$query->createNamedParameter(count($userIds, \PDO::PARAM_INT)) $query->createNamedParameter(\count($userIds, \PDO::PARAM_INT))
)) ))
->orderBy('demo_id', 'desc') ->orderBy('demo_id', 'desc')
->setMaxResults(50) ->setMaxResults(50)
@ -54,7 +54,7 @@ class DemoListProvider extends BaseProvider {
* @return Demo[] * @return Demo[]
*/ */
public function listDemos(int $page, array $where = [], string $order = 'DESC') { public function listDemos(int $page, array $where = [], string $order = 'DESC') {
if (isset($where['players']) and is_array($where['players']) and count($where['players']) > 0) { if (isset($where['players']) and \is_array($where['players']) and \count($where['players']) > 0) {
return $this->listProfile($page, $where); return $this->listProfile($page, $where);
} }

View file

@ -56,7 +56,7 @@ class UploadProvider extends BaseProvider {
public function upload(string $key, string $red, string $blu, string $name, string $demoFile): string { public function upload(string $key, string $red, string $blu, string $name, string $demoFile): string {
$user = $this->userProvider->byKey($key); $user = $this->userProvider->byKey($key);
if (!$user || ($this->uploadKey !== '' && $this->uploadKey !== $key)) { if (!$user || ('' !== $this->uploadKey && $this->uploadKey !== $key)) {
return 'Invalid key'; return 'Invalid key';
} }
@ -106,7 +106,7 @@ class UploadProvider extends BaseProvider {
public function validateParsed(Header $header, ParsedDemo $parsedDemo) { public function validateParsed(Header $header, ParsedDemo $parsedDemo) {
$rounds = $parsedDemo->getRedScore() + $parsedDemo->getBlueScore(); $rounds = $parsedDemo->getRedScore() + $parsedDemo->getBlueScore();
if ($rounds === 0 && $header->getDuration() < (5 * 60)) { if (0 === $rounds && $header->getDuration() < (5 * 60)) {
return 'Demos must be at least 5 minutes long'; return 'Demos must be at least 5 minutes long';
} }

View file

@ -65,7 +65,7 @@ class UserProvider extends BaseProvider {
->setMaxResults(1); ->setMaxResults(1);
$result = $query->execute()->fetch(); $result = $query->execute()->fetch();
if (is_array($result)) { if (\is_array($result)) {
return $result; return $result;
} else { } else {
return null; return null;
@ -74,6 +74,7 @@ class UserProvider extends BaseProvider {
/** /**
* @param string $search * @param string $search
*
* @return SteamUser[] * @return SteamUser[]
*/ */
public function search(string $search): array { public function search(string $search): array {
@ -102,7 +103,7 @@ class UserProvider extends BaseProvider {
$countWeight = 1; $countWeight = 1;
$simWeight = 5; $simWeight = 5;
$diff = ($a['sim'] * $simWeight + $a['count'] * $countWeight) - ($b['sim'] * $simWeight + $b['count'] * $countWeight); $diff = ($a['sim'] * $simWeight + $a['count'] * $countWeight) - ($b['sim'] * $simWeight + $b['count'] * $countWeight);
if ($diff === 0) { if (0 === $diff) {
return 0; return 0;
} else { } else {
return ($diff < 0) ? -1 : 1; return ($diff < 0) ? -1 : 1;

View file

@ -18,7 +18,7 @@ $connectionParams = [
'port' => getenv('DB_PORT'), 'port' => getenv('DB_PORT'),
'driver' => getenv('DB_TYPE'), 'driver' => getenv('DB_TYPE'),
]; ];
if ($connectionParams['driver'] === 'pgsql') { if ('pgsql' === $connectionParams['driver']) {
$connectionParams['driver'] = 'pdo_pgsql'; $connectionParams['driver'] = 'pdo_pgsql';
} }
$db = \Doctrine\DBAL\DriverManager::getConnection($connectionParams); $db = \Doctrine\DBAL\DriverManager::getConnection($connectionParams);

View file

@ -52,7 +52,7 @@ abstract class ControllerTest extends TestCase {
} }
protected function assertResponseData($expected) { protected function assertResponseData($expected) {
if (!is_string($expected)) { if (!\is_string($expected)) {
$expected = json_encode($expected); $expected = json_encode($expected);
} }

View file

@ -26,8 +26,8 @@ class DemoStoreTest extends TestCase {
$this->assertStringEqualsFile($storedDemo->getPath(), 'foobar'); $this->assertStringEqualsFile($storedDemo->getPath(), 'foobar');
unlink($storedDemo->getPath()); unlink($storedDemo->getPath());
rmdir(dirname($storedDemo->getPath())); rmdir(\dirname($storedDemo->getPath()));
rmdir(dirname($storedDemo->getPath(), 2)); rmdir(\dirname($storedDemo->getPath(), 2));
rmdir($targetDir); rmdir($targetDir);
} }
} }

View file

@ -36,7 +36,7 @@ class ParserTest extends TestCase {
$expectedRaw = json_decode(file_get_contents(__DIR__ . '/../data/product-analyse.json'), true); $expectedRaw = json_decode(file_get_contents(__DIR__ . '/../data/product-analyse.json'), true);
$expectedChat = $expectedRaw['chat']; $expectedChat = $expectedRaw['chat'];
$this->assertCount(count($expectedChat), $result->getChat()); $this->assertCount(\count($expectedChat), $result->getChat());
$this->assertEquals($expectedChat[0]['text'], $result->getChat()[0]->getMessage()); $this->assertEquals($expectedChat[0]['text'], $result->getChat()[0]->getMessage());
$this->assertEquals($expectedChat[0]['time'], $result->getChat()[0]->getTime()); $this->assertEquals($expectedChat[0]['time'], $result->getChat()[0]->getTime());
$this->assertEquals($expectedChat[0]['from'], $result->getChat()[0]->getUser()); $this->assertEquals($expectedChat[0]['from'], $result->getChat()[0]->getUser());
@ -45,7 +45,7 @@ class ParserTest extends TestCase {
$this->assertEquals($expectedRaw['score']['blue'], $result->getBlueScore()); $this->assertEquals($expectedRaw['score']['blue'], $result->getBlueScore());
$expectedPlayers = $expectedRaw['players']; $expectedPlayers = $expectedRaw['players'];
$this->assertCount(count($expectedPlayers), $result->getPlayers()); $this->assertCount(\count($expectedPlayers), $result->getPlayers());
$this->assertEquals($expectedPlayers[0]['name'], $result->getPlayers()[0]->getName()); $this->assertEquals($expectedPlayers[0]['name'], $result->getPlayers()[0]->getName());
$this->assertEquals($expectedPlayers[0]['demo_user_id'], $result->getPlayers()[0]->getDemoUserId()); $this->assertEquals($expectedPlayers[0]['demo_user_id'], $result->getPlayers()[0]->getDemoUserId());
$this->assertEquals($expectedPlayers[0]['team'], $result->getPlayers()[0]->getTeam()); $this->assertEquals($expectedPlayers[0]['team'], $result->getPlayers()[0]->getTeam());
@ -53,7 +53,7 @@ class ParserTest extends TestCase {
$this->assertEquals(Parser::convertSteamIdToCommunityId($expectedPlayers[0]['steam_id']), $result->getPlayers()[0]->getSteamId()); $this->assertEquals(Parser::convertSteamIdToCommunityId($expectedPlayers[0]['steam_id']), $result->getPlayers()[0]->getSteamId());
$expectedKills = $expectedRaw['kills']; $expectedKills = $expectedRaw['kills'];
$this->assertCount(count($expectedKills), $result->getKills()); $this->assertCount(\count($expectedKills), $result->getKills());
$this->assertEquals((int) $expectedKills[0]['killer'], $result->getKills()[0]->getAttackerDemoId()); $this->assertEquals((int) $expectedKills[0]['killer'], $result->getKills()[0]->getAttackerDemoId());
$this->assertEquals((int) $expectedKills[0]['assister'], $result->getKills()[0]->getAssisterDemoId()); $this->assertEquals((int) $expectedKills[0]['assister'], $result->getKills()[0]->getAssisterDemoId());
$this->assertEquals((int) $expectedKills[0]['victim'], $result->getKills()[0]->getVictimDemoId()); $this->assertEquals((int) $expectedKills[0]['victim'], $result->getKills()[0]->getVictimDemoId());

View file

@ -297,7 +297,7 @@ class UploadProviderTest extends TestCase {
$result = $this->uploadProvider->upload($token, 'RED', 'BLU', 'foodemo', $this->tmpDir . '/foo.dem'); $result = $this->uploadProvider->upload($token, 'RED', 'BLU', 'foodemo', $this->tmpDir . '/foo.dem');
$this->assertStringStartsWith('STV available at: http://example.com/', $result); $this->assertStringStartsWith('STV available at: http://example.com/', $result);
$demoId = (int) substr($result, strlen('STV available at: http://example.com/')); $demoId = (int) substr($result, \strlen('STV available at: http://example.com/'));
$demo = $this->demoProvider->get($demoId, true); $demo = $this->demoProvider->get($demoId, true);

View file

@ -21,7 +21,7 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase {
'port' => getenv('DB_PORT'), 'port' => getenv('DB_PORT'),
'driver' => getenv('DB_TYPE'), 'driver' => getenv('DB_TYPE'),
]; ];
if ($connectionParams['driver'] === 'pgsql') { if ('pgsql' === $connectionParams['driver']) {
$connectionParams['driver'] = 'pdo_pgsql'; $connectionParams['driver'] = 'pdo_pgsql';
} }
$this->database = DriverManager::getConnection($connectionParams); $this->database = DriverManager::getConnection($connectionParams);

View file

@ -4,16 +4,16 @@ declare(strict_types=1);
$_SERVER['SCRIPT_NAME'] = ''; $_SERVER['SCRIPT_NAME'] = '';
if ($_SERVER['REQUEST_URI'] === '/upload') { if ('/upload' === $_SERVER['REQUEST_URI']) {
require __DIR__ . '/../src/public/upload.php'; require __DIR__ . '/../src/public/upload.php';
} elseif ($_SERVER['REQUEST_URI'] === '/reset') { } elseif ('/reset' === $_SERVER['REQUEST_URI']) {
// allow the api tests to reset the database // allow the api tests to reset the database
/** @var \Demostf\API\Container $container */ /** @var \Demostf\API\Container $container */
$container = require __DIR__ . '/../src/init.php'; $container = require __DIR__ . '/../src/init.php';
$connection = $container->getConnection(); $connection = $container->getConnection();
clearDatabase($connection); clearDatabase($connection);
} elseif ($_SERVER['REQUEST_URI'] === '/testuser') { } elseif ('/testuser' === $_SERVER['REQUEST_URI']) {
// allow the api tests to create a test user // allow the api tests to create a test user
/** @var \Demostf\API\Container $container */ /** @var \Demostf\API\Container $container */
$container = require __DIR__ . '/../src/init.php'; $container = require __DIR__ . '/../src/init.php';