mirror of
https://codeberg.org/demostf/api.git
synced 2026-06-03 18:04:08 +02:00
upload framework
This commit is contained in:
parent
754b1ce108
commit
a1a9504f11
30 changed files with 1578 additions and 155 deletions
38
src/Providers/AuthProvider.php
Normal file
38
src/Providers/AuthProvider.php
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?php namespace Demostf\API\Providers;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use RandomLib\Generator;
|
||||
|
||||
class AuthProvider extends BaseProvider {
|
||||
/**
|
||||
* @var Generator
|
||||
*/
|
||||
private $generator;
|
||||
|
||||
public function __construct(Connection $db, Generator $generator) {
|
||||
parent::__construct($db);
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
public function generateToken() {
|
||||
return $this->generator->generateString(32, Generator::CHAR_ALNUM);
|
||||
}
|
||||
|
||||
public function setUser($token, \SteamId $steamid, $key) {
|
||||
apc_store($token, [
|
||||
'name' => $steamid->getNickname(),
|
||||
'steamid' => $steamid->getSteamId64(),
|
||||
'key' => $key
|
||||
]);
|
||||
}
|
||||
|
||||
public function getUser($token) {
|
||||
$found = true;
|
||||
$result = apc_fetch($token, $found);
|
||||
return ($found) ? $result : ['name' => null, 'steamid' => null, 'key' => null];
|
||||
}
|
||||
|
||||
public function logout($token) {
|
||||
apc_delete($token);
|
||||
}
|
||||
}
|
||||
70
src/Providers/BaseProvider.php
Normal file
70
src/Providers/BaseProvider.php
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<?php namespace Demostf\API\Providers;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Platforms\MySqlPlatform;
|
||||
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
|
||||
use Doctrine\DBAL\Query\QueryBuilder;
|
||||
use LessQL\Database;
|
||||
|
||||
class BaseProvider {
|
||||
/**
|
||||
* @var Connection
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* @var \LessQL\Database
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
public function __construct(Connection $connection) {
|
||||
$this->connection = $connection;
|
||||
$this->db = new Database($connection->getWrappedConnection());
|
||||
$this->dbConfig();
|
||||
}
|
||||
|
||||
private function dbConfig() {
|
||||
$platform = $this->connection->getDatabasePlatform();
|
||||
if ($platform instanceof MySqlPlatform) {
|
||||
$this->db->setIdentifierDelimiter("`");
|
||||
} else {
|
||||
$this->db->setIdentifierDelimiter('"');
|
||||
}
|
||||
|
||||
$this->db->setRewrite(function ($table) {
|
||||
$rawNames = ['chat'];
|
||||
$aliases = [
|
||||
|
||||
];
|
||||
if (isset($aliases[$table])) {
|
||||
return $aliases[$table];
|
||||
} else if (array_search($table, $rawNames) === false) {
|
||||
return $table . 's';
|
||||
} else {
|
||||
return $table;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected function query($sql, array $params = []) {
|
||||
$delimiter = $this->db->getIdentifierDelimiter();
|
||||
$platform = $this->connection->getDatabasePlatform();
|
||||
$sql = str_replace('`', $delimiter, $sql);
|
||||
|
||||
if ($platform instanceof PostgreSqlPlatform) {
|
||||
$sql = str_replace('FROM_UNIXTIME(', 'to_timestamp(', $sql);
|
||||
}
|
||||
|
||||
$query = $this->connection->prepare($sql);
|
||||
$query->execute($params);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
protected function getQueryBuilder() {
|
||||
return new QueryBuilder($this->connection);
|
||||
}
|
||||
}
|
||||
186
src/Providers/DemoProvider.php
Normal file
186
src/Providers/DemoProvider.php
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
<?php namespace Demostf\API\Providers;
|
||||
|
||||
use Demostf\API\Demo\Header;
|
||||
use Demostf\API\Demo\IDemoStore;
|
||||
use Demostf\API\Demo\StoredDemo;
|
||||
use Doctrine\DBAL\Connection;
|
||||
|
||||
class DemoProvider extends BaseProvider {
|
||||
const VERSION = 4;
|
||||
|
||||
|
||||
public function __construct(Connection $connection) {
|
||||
parent::__construct($connection);
|
||||
}
|
||||
|
||||
public function get($id) {
|
||||
$demo = $this->db->demo()->where('id', $id);
|
||||
|
||||
// sql magic
|
||||
$sql = 'WITH demokills AS (SELECT attacker_id, assister_id, victim_id FROM kills WHERE demo_id = ?)
|
||||
SELECT players.id, user_id, players.name, team, class, users.steamid, users.avatar,
|
||||
(SELECT COUNT(*) FROM demokills WHERE attacker_id=players.user_id) AS kills,
|
||||
(SELECT COUNT(*) FROM demokills WHERE assister_id=players.user_id) AS assists,
|
||||
(SELECT COUNT(*) FROM demokills WHERE victim_id=players.user_id) AS deaths
|
||||
FROM players
|
||||
INNER JOIN demos ON demos.id = players.demo_id
|
||||
INNER JOIN users ON players.user_id = users.id
|
||||
WHERE demo_id = ?
|
||||
';
|
||||
|
||||
$uploader = $demo->user()->via('uploader')->fetch();
|
||||
$demoData = $demo->fetch();
|
||||
$playerQuery = $this->query($sql, [$demoData['id'], $demoData['id']]);
|
||||
$players = $playerQuery->fetchAll(\PDO::FETCH_ASSOC);
|
||||
|
||||
$formattedDemo = $this->formatDemo($demoData);
|
||||
$formattedDemo['players'] = $players;
|
||||
$formattedDemo['uploader'] = [
|
||||
'id' => $uploader['id'],
|
||||
'steamid' => $uploader['steamid'],
|
||||
'name' => $uploader['name']
|
||||
];
|
||||
return $formattedDemo;
|
||||
}
|
||||
|
||||
public function listUploads($steamid, $page, $where = []) {
|
||||
$user = $this->db->user()->where('steamid', $steamid);
|
||||
$where['uploader'] = $user->fetch()->id;
|
||||
return $this->listDemos($page, $where);
|
||||
}
|
||||
|
||||
public function listProfile($page, $where = []) {
|
||||
$users = $this->db->user()->where('steamid', $where['players']);
|
||||
unset($where['players']);
|
||||
$userIds = [];
|
||||
foreach ($users as $user) {
|
||||
$userIds[] = $user['id'];
|
||||
}
|
||||
$in = implode(', ', array_fill(0, count($userIds), '?'));
|
||||
|
||||
$sql = 'SELECT demos.id FROM demos INNER JOIN players ON players.demo_id = demos.id
|
||||
WHERE players.user_id IN (' . $in . ') GROUP BY demos.id HAVING COUNT(user_id) = ? ORDER BY demos.id DESC LIMIT 50 OFFSET ' . ((int)$page - 1) * 50;
|
||||
|
||||
$params = $userIds;
|
||||
$params[] = count($userIds);
|
||||
|
||||
$result = $this->query($sql, $params);
|
||||
$demoIds = $result->fetchAll(\PDO::FETCH_COLUMN);
|
||||
|
||||
$demos = $this->db->demo()->where('id', $demoIds)
|
||||
->where($where)
|
||||
->orderBy('id', 'DESC');
|
||||
return $this->formatList($demos);
|
||||
}
|
||||
|
||||
public function listDemos($page, $where = []) {
|
||||
if (isset($where['players']) and is_array($where['players']) and count($where['players']) > 0) {
|
||||
return $this->listProfile($page, $where);
|
||||
}
|
||||
|
||||
$offset = ($page - 1) * 50;
|
||||
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->select('d.*')
|
||||
->from('demos', 'd')
|
||||
->leftJoin('d', 'upload_blacklist', 'b', $query->expr()->eq('uploader_id', 'uploader'))
|
||||
->where($query->expr()->isNull('b.id'));
|
||||
if (isset($where['map'])) {
|
||||
$query->where($query->expr()->eq('map', $query->createNamedParameter($where['map'])));
|
||||
}
|
||||
if (isset($where['playerCount'])) {
|
||||
$query->where($query->expr()->in('playerCount', $query->createNamedParameter($where['playerCount'], Connection::PARAM_INT_ARRAY)));
|
||||
}
|
||||
$query->orderBy('d.id', 'DESC')
|
||||
->setMaxResults(50)
|
||||
->setFirstResult($offset);
|
||||
|
||||
$demos = $query->execute()->fetchAll();
|
||||
return $this->formatList($demos);
|
||||
}
|
||||
|
||||
public function listMaps() {
|
||||
$sql = 'SELECT DISTINCT(map), COUNT(map) AS count from demos GROUP BY map ORDER BY count DESC';
|
||||
$result = $this->query($sql);
|
||||
return $result->fetchAll(\PDO::FETCH_COLUMN);
|
||||
}
|
||||
|
||||
public function getChat($demoId) {
|
||||
$chat = $this->db->chat()->where('demo_id', $demoId);
|
||||
$result = [];
|
||||
foreach ($chat as $message) {
|
||||
$result[] = [
|
||||
'message' => $message['text'],
|
||||
'user' => $message['from'],
|
||||
'time' => $message['time']
|
||||
];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function formatList($demos) {
|
||||
$result = [];
|
||||
foreach ($demos as $demo) {
|
||||
$result[] = $this->formatDemo($demo);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function formatDemo($demoData) {
|
||||
return [
|
||||
'id' => $demoData['id'],
|
||||
'url' => $demoData['url'],
|
||||
'name' => $demoData['name'],
|
||||
'server' => $demoData['server'],
|
||||
'duration' => $demoData['duration'],
|
||||
'nick' => $demoData['nick'],
|
||||
'map' => $demoData['map'],
|
||||
'time' => strtotime($demoData['created_at']),
|
||||
'red' => $demoData['red'],
|
||||
'blue' => $demoData['blu'],
|
||||
'redScore' => $demoData['scoreRed'],
|
||||
'blueScore' => $demoData['scoreBlue'],
|
||||
'playerCount' => $demoData['playerCount'],
|
||||
'uploader' => $demoData['uploader']
|
||||
];
|
||||
}
|
||||
|
||||
private function formatTeam($teamInfo) {
|
||||
if ($teamInfo === null) {
|
||||
return $teamInfo;
|
||||
}
|
||||
return [
|
||||
'id' => $teamInfo['id'],
|
||||
'profileId' => $teamInfo['profile_id'],
|
||||
'name' => $teamInfo['name'],
|
||||
'tag' => $teamInfo['tag'],
|
||||
'avatar' => $teamInfo['avatar'],
|
||||
'steam' => $teamInfo['steam'],
|
||||
'league' => $teamInfo['league'],
|
||||
'division' => $teamInfo['division']
|
||||
];
|
||||
}
|
||||
|
||||
public function getStats() {
|
||||
$demoCount = $this->db->demo()->count();
|
||||
$playerCount = $this->db->user()->count();
|
||||
|
||||
$sql = 'SELECT count(user_id) FROM players GROUP BY user_id';
|
||||
$result = $this->query($sql);
|
||||
|
||||
return [
|
||||
'demos' => $demoCount,
|
||||
'players' => $playerCount,
|
||||
'uploaders' => $result->fetchColumn()
|
||||
];
|
||||
}
|
||||
|
||||
public function demoIdByHash($hash) {
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->select('hash')
|
||||
->from('demos')
|
||||
->where($query->expr()->eq('hash', $query->createNamedParameter($hash)));
|
||||
|
||||
return $query->execute()->fetchColumn();
|
||||
}
|
||||
}
|
||||
16
src/Providers/UploadProvider.php
Normal file
16
src/Providers/UploadProvider.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php namespace Demostf\API\Providers;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use RandomLib\Generator;
|
||||
|
||||
class UploadProvider extends BaseProvider {
|
||||
/**
|
||||
* @var Generator
|
||||
*/
|
||||
private $generator;
|
||||
|
||||
public function __construct(Connection $db, Generator $generator) {
|
||||
parent::__construct($db);
|
||||
$this->generator = $generator;
|
||||
}
|
||||
}
|
||||
88
src/Providers/UserProvider.php
Normal file
88
src/Providers/UserProvider.php
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
<?php namespace Demostf\API\Providers;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use RandomLib\Generator;
|
||||
|
||||
class UserProvider extends BaseProvider {
|
||||
/**
|
||||
* @var Generator
|
||||
*/
|
||||
private $generator;
|
||||
|
||||
public function __construct(Connection $db, Generator $generator) {
|
||||
parent::__construct($db);
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
public function store(\SteamId $steamId) {
|
||||
$sql = 'INSERT INTO users(steamid, name, avatar, token)
|
||||
SELECT ?, ?, ?, ? WHERE NOT EXISTS(SELECT id FROM users WHERE steamid = ?)';
|
||||
$this->query($sql, [
|
||||
$steamId->getSteamId64(),
|
||||
$steamId->getNickname(),
|
||||
$steamId->getMediumAvatarUrl(),
|
||||
$this->generator->generateString(64),
|
||||
$steamId->getSteamId64()
|
||||
]);
|
||||
|
||||
$user = $this->db->user()->where('steamid', $steamId->getSteamId64());
|
||||
return $user->fetch()->token;
|
||||
}
|
||||
|
||||
public function get($steamid) {
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->select(['id', 'steamid', 'name', 'avatar', 'token'])
|
||||
->from('users')
|
||||
->where($query->expr()->eq('steamid', $query->createNamedParameter($steamid)));
|
||||
|
||||
return $query->execute()->fetch();
|
||||
}
|
||||
|
||||
public function search($query) {
|
||||
$sql = 'SELECT user_id, players.name, count(demo_id) AS count, steamid,
|
||||
1-(players.name <-> ?) AS sim FROM players
|
||||
INNER JOIN users ON users.id = players.user_id
|
||||
WHERE players.name % ? OR players.name ~* ?
|
||||
GROUP BY players.name, user_id, steamid
|
||||
ORDER BY count DESC
|
||||
LIMIT 100';
|
||||
$result = $this->query($sql, [$query, $query, $query]);
|
||||
$players = $result->fetchAll(\PDO::FETCH_ASSOC);
|
||||
|
||||
usort($players, function ($b, $a) {
|
||||
$countWeight = 1;
|
||||
$simWeight = 5;
|
||||
$diff = ($a['sim'] * $simWeight + $a['count'] * $countWeight) - ($b['sim'] * $simWeight + $b['count'] * $countWeight);
|
||||
if ($diff === 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return ($diff < 0) ? -1 : 1;
|
||||
}
|
||||
});
|
||||
|
||||
$result = [];
|
||||
foreach ($players as $player) {
|
||||
$id = $player['user_id'];
|
||||
if (!isset($result[$id])) {
|
||||
$result[$id] = [
|
||||
'id' => $id,
|
||||
'name' => $player['name'],
|
||||
'steamid' => $player['steamid']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$players = array_values($result);
|
||||
|
||||
return $players;
|
||||
}
|
||||
|
||||
public function byKey($key) {
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->select(['id', 'steamid', 'name', 'avatar'])
|
||||
->from('users')
|
||||
->where($query->expr()->eq('token', $query->createNamedParameter($key)));
|
||||
|
||||
return $query->execute()->fetch();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue