1
0
Fork 0
mirror of https://codeberg.org/demostf/api.git synced 2026-06-03 18:04:08 +02:00

upload framework

This commit is contained in:
Robin Appelman 2017-03-20 21:51:03 +01:00
commit a1a9504f11
30 changed files with 1578 additions and 155 deletions

View file

@ -0,0 +1,77 @@
<?php namespace Demostf\API\Controllers;
use Ehesp\SteamLogin\SteamLogin;
use Demostf\API\Providers\AuthProvider;
use Demostf\API\Providers\UserProvider;
class AuthController extends BaseController {
/**
* @var UserProvider
*/
private $userProvider;
/**
* @var AuthProvider
*/
private $authProvider;
/** @var string */
private $host;
/**
* AuthController constructor.
*
* @param UserProvider $userProvider
* @param AuthProvider $authProvider
* @param string $host
*/
public function __construct(UserProvider $userProvider, AuthProvider $authProvider, string $host) {
$this->userProvider = $userProvider;
$this->authProvider = $authProvider;
$this->host = $host;
}
public function token() {
echo $this->authProvider->generateToken();
}
public function get($token) {
$userData = $this->authProvider->getUser($token);
\Flight::json([
'token' => $token,
'steamid' => $userData['steamid'],
'name' => $userData['name'],
'key' => $userData['key']
]);
}
public function login($token) {
$_SESSION['return'] = $this->query('return', 'https://' . $this->host);
$steam = new SteamLogin();
$url = $steam->url($_ENV['APP_ROOT'] . '/auth/handle/' . urlencode($token));
\Flight::redirect(str_replace('&amp;', '&', $url)); // headers make no sense
}
public function logout($token) {
$this->authProvider->logout($token);
\Flight::json([
'token' => $token,
'steamid' => null,
'name' => null,
'key' => null
]);
}
public function handle($token) {
$return = isset($_SESSION['return']) ? $_SESSION['return'] : 'http://demos.tf';
unset($_SESSION['return']);
$steam = new SteamLogin();
$steamId = $steam->validate();
if ($steamId) {
$steamIdObject = new \SteamId($steamId);
$key = $this->userProvider->store($steamIdObject);
$this->authProvider->setUser($token, $steamIdObject, $key);
}
\Flight::redirect($return);
}
}

View file

@ -0,0 +1,18 @@
<?php namespace Demostf\API\Controllers;
class BaseController {
protected function query($name, $default) {
$request = \Flight::request();
return isset($request->query[$name]) ? $request->query[$name] : $default;
}
protected function file($name) {
$request = \Flight::request();
return $request->files[$name];
}
protected function post($name, $default = null) {
$request = \Flight::request();
return isset($request->data[$name]) ? $request->data[$name] : $default;
}
}

View file

@ -0,0 +1,81 @@
<?php namespace Demostf\API\Controllers;
use Demostf\API\Providers\DemoProvider;
use Demostf\API\Providers\MatchProvider;
class DemoController extends BaseController {
/**
* @var \Providers\DemoProvider
*/
private $demoProvider;
public function __construct(DemoProvider $demoProvider) {
$this->demoProvider = $demoProvider;
}
/**
* @param string $id
*/
public function get($id) {
\Flight::json($this->demoProvider->get($id));
}
protected function getFilter() {
$map = $this->query('map', '');
$players = $this->query('players', '');
$type = $this->query('type', '');
$filter = [];
if ($map) {
$filter['map'] = $map;
}
if ($players) {
if (!is_array($players)) {
$players = explode(',', $players);
}
$players = array_filter($players);
$filter['players'] = $players;
}
switch ($type) {
case 'hl':
$filter['playerCount'] = [17, 18, 19];
break;
case '6v6':
$filter['playerCount'] = [11, 12, 13];
break;
case '4v4':
$filter['playerCount'] = [7, 8, 9];
break;
}
return $filter;
}
public function listDemos() {
$page = $this->query('page', 1);
\Flight::json($this->demoProvider->listDemos($page, $this->getFilter()));
}
public function listProfile($steamid) {
$page = $this->query('page', 1);
$where = $this->getFilter();
$where['players'][] = $steamid;
\Flight::json($this->demoProvider->listProfile($page, $where));
}
public function listUploads($steamid) {
$page = $this->query('page', 1);
\Flight::json($this->demoProvider->listUploads($steamid, $page, $this->getFilter()));
}
public function chat($demoId) {
\Flight::json($this->demoProvider->getChat($demoId));
}
public function listMaps() {
\Flight::json($this->demoProvider->listMaps());
}
public function stats() {
\Flight::json($this->demoProvider->getStats());
}
}

View file

@ -0,0 +1,89 @@
<?php namespace Demostf\API\Controllers;
use Demostf\API\Demo\DemoStore;
use Demostf\API\Demo\Parser;
use Demostf\API\Providers\DemoProvider;
use Demostf\API\Providers\UserProvider;
class UploadController extends BaseController {
/**
* @var \Providers\DemoProvider
*/
private $demoProvider;
/**
* @var UserProvider
*/
private $userProvider;
/**
* @var Parser
*/
private $parser;
/** @var DemoStore */
private $store;
public function __construct(DemoProvider $demoProvider, UserProvider $userProvider, Parser $parser, DemoStore $store) {
$this->demoProvider = $demoProvider;
$this->userProvider = $userProvider;
$this->parser = $parser;
$this->store = $store;
}
public function upload() {
$key = $this->post('key');
$red = $this->post('red', 'RED');
$blu = $this->post('blu', 'BLU');
$name = $this->post('name', 'Unnamed');
$demo = $this->file('demo');
$user = $this->userProvider->byKey($key);
if (!$user) {
return 'Invalid key';
}
if (!$red) {
$red = 'RED';
}
if (!$blu) {
$blu = 'BLU';
}
$size = $demo['size'];
if ($size < 1024) {
return 'Demos needs to be at least 1KB is size';
}
if ($size > 100 * 1024 * 1024) {
return 'Demos cant be more than 100MB in size';
}
$tmpPath = $demo['tmp_name'];
try {
$info = $this->parser->parseHeader($tmpPath);
} catch (\Exception $e) {
return 'Not a valid demo';
}
if ($info->getDuration() < (5 * 60)) {
return 'Demos need to be at least 5m long';
}
if ($info->getDuration() > (60 * 60)) {
return 'Demos cant be longer than one hour';
}
$hash = hash_file('md5', $tmpPath);
$existingDemo = $this->demoProvider->demoIdByHash($hash);
if ($existingDemo) {
if ($key) {
return 'STV available at: https://demos.tf/' . $existingDemo;
} else {
\Flight::redirect('https://demos.tf/' . $existingDemo);
return '';
}
}
$url = $this->store->store($tmpPath, $hash . '_' . $name);
}
}

View file

@ -0,0 +1,30 @@
<?php namespace Demostf\API\Controllers;
use Ehesp\SteamLogin\SteamLogin;
use Demostf\API\Providers\AuthProvider;
use Demostf\API\Providers\UserProvider;
class UserController extends BaseController {
/**
* @var UserProvider
*/
private $userProvider;
/**
* UserController constructor.
*
* @param UserProvider $userProvider
*/
public function __construct(UserProvider $userProvider) {
$this->userProvider = $userProvider;
}
public function get($steamid) {
\Flight::json($this->userProvider->get($steamid));
}
public function search() {
$query = $this->query('query', '');
\Flight::json($this->userProvider->search($query));
}
}

26
src/Demo/DemoStore.php Normal file
View file

@ -0,0 +1,26 @@
<?php namespace Demostf\API\Demo;
class DemoStore {
/** @var string */
private $root;
/** @var string */
private $webroot;
public function __construct(string $root, string $webroot) {
$this->root = $root;
$this->webroot = $webroot;
}
public function store(string $sourcePath, string $name): string {
rename($sourcePath, $this->generatePath($name));
return $this->getUrl($name);
}
private function generatePath(string $name): string {
return $this->root . '/' . substr($name, 0, 2) . '/' . substr($name, 2, 4) . '/' . $name;
}
private function getUrl(string $name): string {
return 'https://' . $this->webroot . '/' . substr($name, 0, 2) . '/' . substr($name, 2, 4) . '/' . $name;
}
}

156
src/Demo/Header.php Normal file
View file

@ -0,0 +1,156 @@
<?php namespace Demostf\API\Demo;
/**
* HL2 demo metadata
*/
class Header {
/**
* @var string
*/
protected $type;
/**
* @var int
*/
protected $version;
/**
* @var int
*/
protected $protocol;
/**
* @var string
*/
protected $server;
/**
* @var string
*/
protected $nick;
/**
* @var string
*/
protected $map;
/**
* @var string
*/
protected $game;
/**
* @var float
*/
protected $duration;
/**
* @var int
*/
protected $ticks;
/**
* @var int
*/
protected $frames;
/**
* @var int
*/
protected $sigon;
/**
* @param array $info
*/
public function __construct($info) {
$this->type = $info['type'];
$this->version = $info['version'];
$this->protocol = $info['protocol'];
$this->server = $info['server'];
$this->nick = $info['nick'];
$this->map = $info['map'];
$this->game = $info['game'];
$this->duration = $info['duration'];
$this->ticks = $info['ticks'];
$this->frames = $info['frames'];
$this->sigon = $info['sigon'];
}
/**
* @return float
*/
public function getDuration() {
return $this->duration;
}
/**
* @return int
*/
public function getFrames() {
return $this->frames;
}
/**
* @return string
*/
public function getGame() {
return $this->game;
}
/**
* @return string
*/
public function getMap() {
return $this->map;
}
/**
* @return string
*/
public function getNick() {
return $this->nick;
}
/**
* @return int
*/
public function getProtocol() {
return $this->protocol;
}
/**
* @return string
*/
public function getServer() {
return $this->server;
}
/**
* @return int
*/
public function getSigon() {
return $this->sigon;
}
/**
* @return int
*/
public function getTicks() {
return $this->ticks;
}
/**
* @return string
*/
public function getType() {
return $this->type;
}
/**
* @return int
*/
public function getVersion() {
return $this->version;
}
}

133
src/Demo/Parser.php Normal file
View file

@ -0,0 +1,133 @@
<?php namespace Demostf\API\Demo;
use GuzzleHttp\Client;
class Parser {
const ANALYSER_BASEURL = 'http://demoserver.azurewebsites.net';
/**
* @param string $head string containing the demo header binary data
* @return Header
* @throws \Exception
*/
public function parseString($head) {
set_error_handler(array($this, 'errorHandler'));
$info = unpack("A8type/Iversion/Iprotocol/A260server/A260nick/A260map/A260game/fduration/Iticks/Iframes/Isigon",
$head);
restore_error_handler();
if ($info['type'] !== 'HL2DEMO') {
throw new \Exception('Not an HL2 demo');
}
return new Header($info);
}
/**
* Parse demo info from a stream
*
* @param resource $stream
* @return Header
* @throws \Exception
*/
public function parseStream($stream) {
$head = fread($stream, 2048);
return $this->parseString($head);
}
/**
* Parse demo info from a local file
*
* @param string $path
* @return Header
* @throws \Exception
*/
public function parseHeader($path) {
if (!is_readable($path)) {
throw new \Exception('Unable to open demo: ' . $path);
}
$fh = fopen($path, 'rb');
return $this->parseStream($fh);
}
public function analyse(StoredDemo $storedDemo) {
$endPoint = self::ANALYSER_BASEURL . '/url';
$client = new Client();
$response = $client->post($endPoint, [
'body' => $storedDemo->getUrl()
]);
$data = $response->getBody();
return $this->handleData($data);
}
private function handleData($data) {
if (!is_array($data)) {
throw new \Exception('Error parsing demo');
}
$intervalPerTick = $data['intervalPerTick'];
$red = 0;
$blue = 0;
$chat = [];
$players = [];
foreach ($data['rounds'] as $round) {
if ($round['winner'] === 'red') {
$red++;
} else {
$blue++;
}
}
foreach ($data['chat'] as $message) {
if (isset($message['from'])) {
$chat[] = [
'time' => floor(($message['tick'] - $data['startTick']) * $intervalPerTick),
'from' => $message['from'],
'text' => $message['text']
];
}
}
foreach ($data['users'] as $player) {
$class = 0;
$classSpawns = 0;
foreach ($player['classes'] as $classId => $spawns) {
if ($spawns > $classSpawns) {
$classSpawns = $spawns;
$class = $classId;
}
}
if ($class and $player['steamId']) {//skip spectators
$players[] = [
'name' => $player['name'],
'demo_user_id' => $player['userId'],
'steam_id' => $player['steamId'],
'team' => $player['team'],
'class' => $this->getClassName($class)
];
}
}
return [
'score' => [
'red' => $red,
'blue' => $blue
],
'chat' => $chat,
'players' => $players,
'kills' => $data['deaths']
];
}
private function getClassName($classId) {
$classes = [
1 => 'scout',
2 => 'sniper',
3 => 'soldier',
4 => 'demoman',
5 => 'medic',
6 => 'heavyweapons',
7 => 'pyro',
8 => 'spy',
9 => 'engineer'
];
return isset($classes[$classId]) ? $classes[$classId] : 'Unknown';
}
}

View 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);
}
}

View 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);
}
}

View 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();
}
}

View 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;
}
}

View 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();
}
}

64
src/app.php Normal file
View file

@ -0,0 +1,64 @@
<?php namespace Demostf\API;
use Flight;
require_once __DIR__ . '/init.php';
$connectionParams = array(
'dbname' => getenv('DB_DATABASE'),
'user' => getenv('DB_USERNAME'),
'password' => getenv('DB_PASSWORD'),
'host' => getenv('DB_HOST'),
'port' => getenv('DB_PORT'),
'driver' => getenv('DB_TYPE'),
);
if ($connectionParams['driver'] === 'pgsql') {
$connectionParams['driver'] = 'pdo_pgsql';
}
$db = \Doctrine\DBAL\DriverManager::getConnection($connectionParams);
$host = getenv('BASE_HOST');
$demoProvider = new Providers\DemoProvider($db);
$factory = new \RandomLib\Factory;
$generator = $factory->getMediumStrengthGenerator();
$authProvider = new Providers\AuthProvider($db, $generator);
$userProvider = new Providers\UserProvider($db, $generator);
$demoController = new Controllers\DemoController($demoProvider);
$authController = new Controllers\AuthController($userProvider, $authProvider, $host);
$userController = new Controllers\UserController($userProvider);
Flight::route('/*', function () {
header('Access-Control-Allow-Origin: *');
return true;
});
Flight::route('/auth/*', function () {
session_start();
return true;
});
Flight::route('/', function () {
echo 'hello world!';
});
Flight::route('/maps', [$demoController, 'listMaps']);
Flight::route('/stats', [$demoController, 'stats']);
Flight::route('/demos', [$demoController, 'listDemos']);
Flight::route('/demos/@id', [$demoController, 'get']);
Flight::route('/demos/@id/chat', [$demoController, 'chat']);
Flight::route('/profiles/@steamid', [$demoController, 'listProfile']);
Flight::route('/uploads/@steamid', [$demoController, 'listUploads']);
Flight::route('/users/search', [$userController, 'search']);
Flight::route('/users/@steamid', [$userController, 'get']);
Flight::route('/auth/token', [$authController, 'token']);
Flight::route('/auth/get/@token', [$authController, 'get']);
Flight::route('/auth/handle/@token', [$authController, 'handle']);
Flight::route('/auth/login/@token', [$authController, 'login']);
Flight::route('/auth/logout/@token', [$authController, 'logout']);
Flight::start();

6
src/init.php Normal file
View file

@ -0,0 +1,6 @@
<?php
$autoloader = require __DIR__ . '/../vendor/autoload.php';
if (!getenv('DB_TYPE')) {
Dotenv::load(__DIR__ . '/../');
}

3
src/public/index.php Normal file
View file

@ -0,0 +1,3 @@
<?php
require '../app.php';

3
src/public/upload.php Normal file
View file

@ -0,0 +1,3 @@
<?php
require __DIR__ . '/../upload.php';

26
src/upload.php Normal file
View file

@ -0,0 +1,26 @@
<?php namespace Demostf\API;
require_once __DIR__ . '/init.php';
$connectionParams = array(
'dbname' => getenv('DB_DATABASE'),
'user' => getenv('DB_USERNAME'),
'password' => getenv('DB_PASSWORD'),
'host' => getenv('DB_HOST'),
'driver' => getenv('DB_TYPE'),
);
if ($connectionParams['driver'] === 'pgsql') {
$connectionParams['driver'] = 'pdo_pgsql';
}
$db = \Doctrine\DBAL\DriverManager::getConnection($connectionParams);
$host = getenv('BASE_HOST');
$storeRoot = getenv('DEMO_ROOT');
$demoProvider = new Providers\DemoProvider($db);
$factory = new \RandomLib\Factory;
$generator = $factory->getMediumStrengthGenerator();
$userProvider = new Providers\UserProvider($db, $generator);
$store = new Demo\DemoStore($storeRoot, 'static.' . $host);
$uploadController = new Controllers\UploadController($demoProvider, $userProvider, new Demo\Parser(), $store);
$uploadController->upload();