download maps asynchronously
This commit is contained in:
parent
4875c14a7d
commit
4c8b247896
@ -10,6 +10,16 @@ use ManiaControl\ManiaControl;
|
||||
* @author kremsy & steeffeen
|
||||
*/
|
||||
class AsynchronousFileReader implements TimerListener {
|
||||
/**
|
||||
* Constants
|
||||
*/
|
||||
const TIMEOUT_ERROR = 'Timed out while reading data';
|
||||
const RESPONSE_ERROR = 'Connection or response error';
|
||||
const NO_DATA_ERROR = 'No data returned';
|
||||
const INVALID_RESULT_ERROR = 'Invalid Result';
|
||||
const SOCKET_TIMEOUT = 10;
|
||||
|
||||
|
||||
/**
|
||||
* Private Properties
|
||||
*/
|
||||
@ -27,37 +37,33 @@ class AsynchronousFileReader implements TimerListener {
|
||||
|
||||
/**
|
||||
* Appends the Data
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function appendData() {
|
||||
foreach($this->sockets as $key => &$socket) {
|
||||
/** @var SocketStructure $socket */
|
||||
$socket->streamBuffer .= fread($socket->socket, 1024);
|
||||
$info = stream_get_meta_data($socket->socket);
|
||||
$socket->streamBuffer .= fread($socket->socket, 4096);
|
||||
|
||||
if (feof($socket->socket) || $info['timed_out']) {
|
||||
if (feof($socket->socket) || time() > ($socket->creationTime + self::SOCKET_TIMEOUT)) {
|
||||
fclose($socket->socket);
|
||||
unset($this->sockets[$key]);
|
||||
|
||||
if ($info['timed_out']) {
|
||||
throw new \Exception("Timed out while reading data from " . $socket->url);
|
||||
$result = array();
|
||||
$error = 0;
|
||||
if (time() > ($socket->creationTime + self::SOCKET_TIMEOUT)) {
|
||||
$error = self::TIMEOUT_ERROR;
|
||||
} else if (substr($socket->streamBuffer, 9, 3) != "200") {
|
||||
$error = self::RESPONSE_ERROR;
|
||||
} else if ($socket->streamBuffer == '') {
|
||||
$error = self::NO_DATA_ERROR;
|
||||
} else {
|
||||
$result = explode("\r\n\r\n", $socket->streamBuffer, 2);
|
||||
|
||||
if (count($result) < 2) {
|
||||
$error = self::INVALID_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (substr($socket->streamBuffer, 9, 3) != "200") {
|
||||
throw new \Exception("Connection or response error on " . $socket->url);
|
||||
}
|
||||
|
||||
if ($socket->streamBuffer == '') {
|
||||
throw new \Exception("No data returned from " . $socket->url);
|
||||
}
|
||||
|
||||
$result = explode("\r\n\r\n", $socket->streamBuffer, 2);
|
||||
|
||||
if (count($result) < 2) {
|
||||
throw new \Exception("Invalid Result");
|
||||
}
|
||||
|
||||
call_user_func($socket->function, $result[1]);
|
||||
call_user_func($socket->function, $result[1], $error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -87,7 +93,6 @@ class AsynchronousFileReader implements TimerListener {
|
||||
if (!$socket) {
|
||||
return false;
|
||||
}
|
||||
stream_set_timeout($socket, 10);
|
||||
|
||||
$query = 'GET ' . $urlData['path'] . $urlQuery . ' HTTP/1.0' . PHP_EOL;
|
||||
$query .= 'Host: ' . $urlData['host'] . PHP_EOL;
|
||||
|
@ -14,11 +14,13 @@ class SocketStructure {
|
||||
public $socket;
|
||||
public $function;
|
||||
public $url;
|
||||
public $creationTime;
|
||||
|
||||
public function __construct($url, $socket, $function) {
|
||||
$this->url = $url;
|
||||
$this->socket = $socket;
|
||||
$this->function = $function;
|
||||
$this->creationTime = time();
|
||||
$this->streamBuffer = '';
|
||||
}
|
||||
}
|
@ -107,7 +107,7 @@ class ManiaExchangeList implements CallbackListener, ManialinkPageAnswerListener
|
||||
};
|
||||
|
||||
// search for matching maps
|
||||
$this->maniaControl->mapManager->mxManager->getMapsAssync($function, $searchString, $author, $environment);
|
||||
$this->maniaControl->mapManager->mxManager->getMapsAsync($function, $searchString, $author, $environment);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -212,7 +212,7 @@ class ManiaExchangeManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Whole Maplist from MX by Mixed Uid and Id String fetch
|
||||
* Get the Whole MapList from MX by Mixed Uid and Id String fetch
|
||||
*
|
||||
* @param $string
|
||||
* @return array|null
|
||||
@ -225,33 +225,44 @@ class ManiaExchangeManager {
|
||||
// compile search URL
|
||||
$url = 'http://api.mania-exchange.com/' . $titlePrefix . '/maps/?ids=' . $string;
|
||||
|
||||
try { //FIXME exceptions get not caught here?
|
||||
$success = $this->maniaControl->fileReader->loadFile($url, function ($mapInfo) use ($titlePrefix, $url) {
|
||||
$mxMapList = json_decode($mapInfo);
|
||||
if ($mxMapList === null) {
|
||||
trigger_error('Cannot decode searched JSON data from ' . $url);
|
||||
return null;
|
||||
}
|
||||
$success = $this->maniaControl->fileReader->loadFile($url, function ($mapInfo, $error) use ($titlePrefix, $url) {
|
||||
if ($error) {
|
||||
trigger_error($error);
|
||||
return null;
|
||||
}
|
||||
|
||||
$maps = array();
|
||||
foreach($mxMapList as $map) {
|
||||
if (!empty($map)) {
|
||||
array_push($maps, new MXMapInfo($titlePrefix, $map));
|
||||
}
|
||||
}
|
||||
$mxMapList = json_decode($mapInfo);
|
||||
if ($mxMapList === null) {
|
||||
trigger_error('Cannot decode searched JSON data from ' . $url);
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->updateMapObjectsWithManiaExchangeIds($maps);
|
||||
return true;
|
||||
}, "application/json");
|
||||
} catch(\Exception $e) {
|
||||
$this->maniaControl->log("Error while fetching Map Infos" . $e->getTraceAsString());
|
||||
return false;
|
||||
}
|
||||
$maps = array();
|
||||
foreach($mxMapList as $map) {
|
||||
if (!empty($map)) {
|
||||
array_push($maps, new MXMapInfo($titlePrefix, $map));
|
||||
}
|
||||
}
|
||||
|
||||
$this->updateMapObjectsWithManiaExchangeIds($maps);
|
||||
return true;
|
||||
}, "application/json");
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
public function getMapsAssync($function, $name = '', $author = '', $env = '', $maxMapsReturned = 100, $searchOrder = self::SEARCH_ORDER_UPDATED_NEWEST) {
|
||||
/**
|
||||
* Fetch a MapList Asynchronously
|
||||
*
|
||||
* @param $function
|
||||
* @param string $name
|
||||
* @param string $author
|
||||
* @param string $env
|
||||
* @param int $maxMapsReturned
|
||||
* @param int $searchOrder
|
||||
* @return bool
|
||||
*/
|
||||
public function getMapsAsync($function, $name = '', $author = '', $env = '', $maxMapsReturned = 100, $searchOrder = self::SEARCH_ORDER_UPDATED_NEWEST) {
|
||||
if (!is_callable($function)) {
|
||||
$this->maniaControl->log("Function is not callable");
|
||||
return false;
|
||||
@ -283,105 +294,36 @@ class ManiaExchangeManager {
|
||||
$url .= '&limit=' . $maxMapsReturned;
|
||||
$url .= '&mtype=' . $mapTypes;
|
||||
|
||||
try {
|
||||
$success = $this->maniaControl->fileReader->loadFile($url, function ($mapInfo) use (&$function) {
|
||||
// Get Title Id
|
||||
$titleId = $this->maniaControl->server->titleId;
|
||||
$titlePrefix = strtolower(substr($titleId, 0, 2));
|
||||
|
||||
$mxMapList = json_decode($mapInfo);
|
||||
if ($mxMapList === null) {
|
||||
trigger_error('Cannot decode searched JSON data');
|
||||
return null;
|
||||
$fileFunc = function ($mapInfo, $error) use (&$function, $titlePrefix) {
|
||||
if ($error) {
|
||||
trigger_error($error);
|
||||
return null;
|
||||
}
|
||||
|
||||
$mxMapList = json_decode($mapInfo);
|
||||
if ($mxMapList === null) {
|
||||
trigger_error('Cannot decode searched JSON data');
|
||||
return null;
|
||||
}
|
||||
|
||||
$maps = array();
|
||||
foreach($mxMapList as $map) {
|
||||
if (!empty($map)) {
|
||||
array_push($maps, new MXMapInfo($titlePrefix, $map));
|
||||
}
|
||||
}
|
||||
|
||||
$maps = array();
|
||||
foreach($mxMapList as $map) {
|
||||
if (!empty($map)) {
|
||||
array_push($maps, new MXMapInfo($titlePrefix, $map));
|
||||
}
|
||||
}
|
||||
call_user_func($function, $maps);
|
||||
|
||||
call_user_func($function, $maps);
|
||||
return true;
|
||||
};
|
||||
|
||||
return true;
|
||||
}, "application/json");
|
||||
} catch(\Exception $e) {
|
||||
var_dump($e);
|
||||
return false;
|
||||
}
|
||||
$success = $this->maniaControl->fileReader->loadFile($url, $fileFunc, "application/json");
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a Maplist from Mania Exchange
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $author
|
||||
* @param string $env
|
||||
* @param int $maxMapsReturned
|
||||
* @param int $searchOrder
|
||||
* @return array null
|
||||
*/
|
||||
public function getMaps($name = '', $author = '', $env = '', $maxMapsReturned = 100, $searchOrder = self::SEARCH_ORDER_UPDATED_NEWEST) {
|
||||
// Get Title Id
|
||||
$titleId = $this->maniaControl->server->titleId;
|
||||
$titlePrefix = strtolower(substr($titleId, 0, 2));
|
||||
|
||||
// Get MapTypes
|
||||
$scriptInfos = $this->maniaControl->client->getModeScriptInfo();
|
||||
|
||||
$mapTypes = $scriptInfos->compatibleMapTypes;
|
||||
|
||||
// compile search URL
|
||||
$url = 'http://' . $titlePrefix . '.mania-exchange.com/tracksearch?api=on';
|
||||
|
||||
if ($env != '') {
|
||||
$url .= '&environments=' . $this->getEnvironment($env);
|
||||
}
|
||||
if ($name != '') {
|
||||
$url .= '&trackname=' . str_replace(" ", "%20", $name);
|
||||
}
|
||||
if ($author != '') {
|
||||
$url .= '&author=' . $author;
|
||||
}
|
||||
|
||||
$url .= '&priord=' . $searchOrder;
|
||||
$url .= '&limit=' . $maxMapsReturned;
|
||||
$url .= '&mtype=' . $mapTypes;
|
||||
|
||||
$mapInfo = FileUtil::loadFile($url, "application/json");
|
||||
|
||||
if ($mapInfo === false) {
|
||||
$this->error = 'Connection or response error on ' . $url;
|
||||
return array();
|
||||
} elseif ($mapInfo === -1) {
|
||||
$this->error = 'Timed out while reading data from ' . $url;
|
||||
return array();
|
||||
} elseif ($mapInfo == '') {
|
||||
if (empty($maps)) {
|
||||
$this->error = 'No data returned from ' . $url;
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
$mxMapList = json_decode($mapInfo);
|
||||
if ($mxMapList === null) {
|
||||
trigger_error('Cannot decode searched JSON data from ' . $url);
|
||||
return null;
|
||||
}
|
||||
|
||||
$maps = array();
|
||||
foreach($mxMapList as $map) {
|
||||
if (!empty($map)) {
|
||||
array_push($maps, new MXMapInfo($titlePrefix, $map));
|
||||
}
|
||||
}
|
||||
return $maps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Current Environemnt by String
|
||||
*
|
||||
|
@ -10,6 +10,7 @@ use ManiaControl\Formatter;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\ManiaExchange\ManiaExchangeList;
|
||||
use ManiaControl\ManiaExchange\ManiaExchangeManager;
|
||||
use ManiaControl\ManiaExchange\MXMapInfo;
|
||||
use ManiaControl\Players\Player;
|
||||
|
||||
/**
|
||||
@ -531,97 +532,114 @@ class MapManager implements CallbackListener {
|
||||
return;
|
||||
}
|
||||
|
||||
$url = "http://{$title}.mania-exchange.com/tracks/download/{$mapId}";
|
||||
$file = FileUtil::loadFile($url);
|
||||
if (!$file) {
|
||||
// Download error
|
||||
$this->maniaControl->chat->sendError('Download failed!', $login);
|
||||
$url = "http://{$title}.mania-exchange.com/tracks/download/{$mapId}";
|
||||
|
||||
//Download the file
|
||||
$function = function ($file, $error) use (&$login, &$mapInfo, &$mapDir, &$update) {
|
||||
if (!$file) {
|
||||
// Download error
|
||||
$this->maniaControl->chat->sendError('Download failed!', $login);
|
||||
return;
|
||||
}
|
||||
$this->processMapFile($file, $mapInfo, $mapDir, $login, $update);
|
||||
};
|
||||
$this->maniaControl->fileReader->loadFile($url, $function);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the MapFile
|
||||
*
|
||||
* @param $file
|
||||
* @param MXMapInfo $mapInfo
|
||||
* @param $mapDir
|
||||
* @param $login
|
||||
* @param $update
|
||||
*/
|
||||
private function processMapFile($file, MXMapInfo $mapInfo, $mapDir, $login, $update) {
|
||||
//Check if map is already on the server
|
||||
if ($this->getMapByUid($mapInfo->uid) != null) {
|
||||
// Download error
|
||||
$this->maniaControl->chat->sendError('Map is already on the server!', $login);
|
||||
return;
|
||||
}
|
||||
|
||||
// Save map
|
||||
$fileName = $mapInfo->id . '_' . $mapInfo->name . '.Map.Gbx';
|
||||
$fileName = FileUtil::getClearedFileName($fileName);
|
||||
|
||||
$downloadDirectory = $this->maniaControl->settingManager->getSetting($this, 'MapDownloadDirectory', 'MX');
|
||||
|
||||
$mapFileName = $downloadDirectory . '/' . $fileName;
|
||||
|
||||
//Check if it can get locally Written
|
||||
if (is_dir($mapDir)) {
|
||||
// Create download directory if necessary
|
||||
if (!is_dir($mapDir . $downloadDirectory) && !mkdir($mapDir . $downloadDirectory)) {
|
||||
trigger_error("ManiaControl doesn't have to rights to save maps in '{$mapDir}{$downloadDirectory}'.");
|
||||
$this->maniaControl->chat->sendError("ManiaControl doesn't have the rights to save maps.", $login);
|
||||
return;
|
||||
}
|
||||
|
||||
//Check if map is already on the server
|
||||
if ($this->getMapByUid($mapInfo->uid) != null) {
|
||||
// Download error
|
||||
$this->maniaControl->chat->sendError('Map is already on the server!', $login);
|
||||
$mapDir .= $downloadDirectory . '/';
|
||||
|
||||
if (!file_put_contents($mapDir . $fileName, $file)) {
|
||||
// Save error
|
||||
$this->maniaControl->chat->sendError('Saving map failed!', $login);
|
||||
return;
|
||||
}
|
||||
|
||||
// Save map
|
||||
$fileName = $mapId . '_' . $mapInfo->name . '.Map.Gbx';
|
||||
$fileName = FileUtil::getClearedFileName($fileName);
|
||||
|
||||
$downloadDirectory = $this->maniaControl->settingManager->getSetting($this, 'MapDownloadDirectory', 'MX');
|
||||
|
||||
$mapFileName = $downloadDirectory . '/' . $fileName;
|
||||
|
||||
//Check if it can get locally Written
|
||||
if (is_dir($mapDir)) {
|
||||
// Create download directory if necessary
|
||||
if (!is_dir($mapDir . $downloadDirectory) && !mkdir($mapDir . $downloadDirectory)) {
|
||||
trigger_error("ManiaControl doesn't have to rights to save maps in '{$mapDir}{$downloadDirectory}'.");
|
||||
$this->maniaControl->chat->sendError("ManiaControl doesn't have the rights to save maps.", $login);
|
||||
return;
|
||||
}
|
||||
|
||||
$mapDir .= $downloadDirectory . '/';
|
||||
|
||||
if (!file_put_contents($mapDir . $fileName, $file)) {
|
||||
// Save error
|
||||
$this->maniaControl->chat->sendError('Saving map failed!', $login);
|
||||
return;
|
||||
}
|
||||
//Write via Write File Method
|
||||
} else {
|
||||
try {
|
||||
$this->maniaControl->client->writeFileFromString($mapFileName, $file);
|
||||
} catch(\Exception $e) {
|
||||
$this->maniaControl->chat->sendError("Map is too big for a remote save.", $login);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for valid map
|
||||
//Write via Write File Method
|
||||
} else {
|
||||
try {
|
||||
$this->maniaControl->client->checkMapForCurrentServerParams($mapFileName);
|
||||
$this->maniaControl->client->writeFileFromString($mapFileName, $file);
|
||||
} catch(\Exception $e) {
|
||||
trigger_error("Couldn't check if map is valid ('{$mapFileName}'). " . $e->getMessage());
|
||||
$this->maniaControl->chat->sendError('Wrong MapType or not validated!', $login);
|
||||
$this->maniaControl->chat->sendError("Map is too big for a remote save.", $login);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add map to map list
|
||||
try {
|
||||
$this->maniaControl->client->insertMap($mapFileName);
|
||||
} catch(\Exception $e) {
|
||||
$this->maniaControl->chat->sendError("Couldn't add map to match settings!", $login);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->updateFullMapList();
|
||||
|
||||
//Update Mx MapInfo
|
||||
$this->maniaControl->mapManager->mxManager->updateMapObjectsWithManiaExchangeIds(array($mapInfo));
|
||||
|
||||
//Update last updated time
|
||||
$map = $this->maps[$mapInfo->uid];
|
||||
/** @var Map $map */
|
||||
$map->lastUpdate = time();
|
||||
|
||||
$player = $this->maniaControl->playerManager->getPlayer($login);
|
||||
|
||||
if (!$update) {
|
||||
//Message
|
||||
$message = '$<' . $player->nickname . '$> added $<' . $mapInfo->name . '$>!';
|
||||
$this->maniaControl->chat->sendSuccess($message);
|
||||
$this->maniaControl->log($message, true);
|
||||
// Queue requested Map
|
||||
$this->maniaControl->mapManager->mapQueue->addMapToMapQueue($login, $mapInfo->uid);
|
||||
} else {
|
||||
$message = '$<' . $player->nickname . '$> updated $<' . $mapInfo->name . '$>!';
|
||||
$this->maniaControl->chat->sendSuccess($message);
|
||||
$this->maniaControl->log($message, true);
|
||||
}
|
||||
}
|
||||
// TODO: add local map by filename
|
||||
|
||||
// Check for valid map
|
||||
try {
|
||||
$this->maniaControl->client->checkMapForCurrentServerParams($mapFileName);
|
||||
} catch(\Exception $e) {
|
||||
trigger_error("Couldn't check if map is valid ('{$mapFileName}'). " . $e->getMessage());
|
||||
$this->maniaControl->chat->sendError('Wrong MapType or not validated!', $login);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add map to map list
|
||||
try {
|
||||
$this->maniaControl->client->insertMap($mapFileName);
|
||||
} catch(\Exception $e) {
|
||||
$this->maniaControl->chat->sendError("Couldn't add map to match settings!", $login);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->updateFullMapList();
|
||||
|
||||
//Update Mx MapInfo
|
||||
$this->maniaControl->mapManager->mxManager->updateMapObjectsWithManiaExchangeIds(array($mapInfo));
|
||||
|
||||
//Update last updated time
|
||||
$map = $this->maps[$mapInfo->uid];
|
||||
/** @var Map $map */
|
||||
$map->lastUpdate = time();
|
||||
|
||||
$player = $this->maniaControl->playerManager->getPlayer($login);
|
||||
|
||||
if (!$update) {
|
||||
//Message
|
||||
$message = '$<' . $player->nickname . '$> added $<' . $mapInfo->name . '$>!';
|
||||
$this->maniaControl->chat->sendSuccess($message);
|
||||
$this->maniaControl->log($message, true);
|
||||
// Queue requested Map
|
||||
$this->maniaControl->mapManager->mapQueue->addMapToMapQueue($login, $mapInfo->uid);
|
||||
} else {
|
||||
$message = '$<' . $player->nickname . '$> updated $<' . $mapInfo->name . '$>!';
|
||||
$this->maniaControl->chat->sendSuccess($message);
|
||||
$this->maniaControl->log($message, true);
|
||||
}
|
||||
}
|
||||
// TODO: add local map by filename
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user