download maps asynchronously

This commit is contained in:
kremsy 2014-02-07 17:27:09 +01:00 committed by Steffen Schröder
parent 4875c14a7d
commit 4c8b247896
5 changed files with 184 additions and 217 deletions

View File

@ -10,6 +10,16 @@ use ManiaControl\ManiaControl;
* @author kremsy & steeffeen * @author kremsy & steeffeen
*/ */
class AsynchronousFileReader implements TimerListener { 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 * Private Properties
*/ */
@ -27,37 +37,33 @@ class AsynchronousFileReader implements TimerListener {
/** /**
* Appends the Data * Appends the Data
* @throws \Exception
*/ */
public function appendData() { public function appendData() {
foreach($this->sockets as $key => &$socket) { foreach($this->sockets as $key => &$socket) {
/** @var SocketStructure $socket */ /** @var SocketStructure $socket */
$socket->streamBuffer .= fread($socket->socket, 1024); $socket->streamBuffer .= fread($socket->socket, 4096);
$info = stream_get_meta_data($socket->socket);
if (feof($socket->socket) || $info['timed_out']) { if (feof($socket->socket) || time() > ($socket->creationTime + self::SOCKET_TIMEOUT)) {
fclose($socket->socket); fclose($socket->socket);
unset($this->sockets[$key]); unset($this->sockets[$key]);
if ($info['timed_out']) { $result = array();
throw new \Exception("Timed out while reading data from " . $socket->url); $error = 0;
} if (time() > ($socket->creationTime + self::SOCKET_TIMEOUT)) {
$error = self::TIMEOUT_ERROR;
if (substr($socket->streamBuffer, 9, 3) != "200") { } else if (substr($socket->streamBuffer, 9, 3) != "200") {
throw new \Exception("Connection or response error on " . $socket->url); $error = self::RESPONSE_ERROR;
} } else if ($socket->streamBuffer == '') {
$error = self::NO_DATA_ERROR;
if ($socket->streamBuffer == '') { } else {
throw new \Exception("No data returned from " . $socket->url);
}
$result = explode("\r\n\r\n", $socket->streamBuffer, 2); $result = explode("\r\n\r\n", $socket->streamBuffer, 2);
if (count($result) < 2) { if (count($result) < 2) {
throw new \Exception("Invalid Result"); $error = self::INVALID_RESULT_ERROR;
}
} }
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) { if (!$socket) {
return false; return false;
} }
stream_set_timeout($socket, 10);
$query = 'GET ' . $urlData['path'] . $urlQuery . ' HTTP/1.0' . PHP_EOL; $query = 'GET ' . $urlData['path'] . $urlQuery . ' HTTP/1.0' . PHP_EOL;
$query .= 'Host: ' . $urlData['host'] . PHP_EOL; $query .= 'Host: ' . $urlData['host'] . PHP_EOL;

View File

@ -14,11 +14,13 @@ class SocketStructure {
public $socket; public $socket;
public $function; public $function;
public $url; public $url;
public $creationTime;
public function __construct($url, $socket, $function) { public function __construct($url, $socket, $function) {
$this->url = $url; $this->url = $url;
$this->socket = $socket; $this->socket = $socket;
$this->function = $function; $this->function = $function;
$this->creationTime = time();
$this->streamBuffer = ''; $this->streamBuffer = '';
} }
} }

View File

@ -107,7 +107,7 @@ class ManiaExchangeList implements CallbackListener, ManialinkPageAnswerListener
}; };
// search for matching maps // search for matching maps
$this->maniaControl->mapManager->mxManager->getMapsAssync($function, $searchString, $author, $environment); $this->maniaControl->mapManager->mxManager->getMapsAsync($function, $searchString, $author, $environment);
} }
/** /**

View File

@ -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 * @param $string
* @return array|null * @return array|null
@ -225,8 +225,12 @@ class ManiaExchangeManager {
// compile search URL // compile search URL
$url = 'http://api.mania-exchange.com/' . $titlePrefix . '/maps/?ids=' . $string; $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, $error) use ($titlePrefix, $url) {
$success = $this->maniaControl->fileReader->loadFile($url, function ($mapInfo) use ($titlePrefix, $url) { if ($error) {
trigger_error($error);
return null;
}
$mxMapList = json_decode($mapInfo); $mxMapList = json_decode($mapInfo);
if ($mxMapList === null) { if ($mxMapList === null) {
trigger_error('Cannot decode searched JSON data from ' . $url); trigger_error('Cannot decode searched JSON data from ' . $url);
@ -243,15 +247,22 @@ class ManiaExchangeManager {
$this->updateMapObjectsWithManiaExchangeIds($maps); $this->updateMapObjectsWithManiaExchangeIds($maps);
return true; return true;
}, "application/json"); }, "application/json");
} catch(\Exception $e) {
$this->maniaControl->log("Error while fetching Map Infos" . $e->getTraceAsString());
return false;
}
return $success; 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)) { if (!is_callable($function)) {
$this->maniaControl->log("Function is not callable"); $this->maniaControl->log("Function is not callable");
return false; return false;
@ -283,11 +294,12 @@ class ManiaExchangeManager {
$url .= '&limit=' . $maxMapsReturned; $url .= '&limit=' . $maxMapsReturned;
$url .= '&mtype=' . $mapTypes; $url .= '&mtype=' . $mapTypes;
try {
$success = $this->maniaControl->fileReader->loadFile($url, function ($mapInfo) use (&$function) { $fileFunc = function ($mapInfo, $error) use (&$function, $titlePrefix) {
// Get Title Id if ($error) {
$titleId = $this->maniaControl->server->titleId; trigger_error($error);
$titlePrefix = strtolower(substr($titleId, 0, 2)); return null;
}
$mxMapList = json_decode($mapInfo); $mxMapList = json_decode($mapInfo);
if ($mxMapList === null) { if ($mxMapList === null) {
@ -305,83 +317,13 @@ class ManiaExchangeManager {
call_user_func($function, $maps); call_user_func($function, $maps);
return true; return true;
}, "application/json"); };
} catch(\Exception $e) {
var_dump($e); $success = $this->maniaControl->fileReader->loadFile($url, $fileFunc, "application/json");
return false;
}
return $success; 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 * Gets the Current Environemnt by String
* *

View File

@ -10,6 +10,7 @@ use ManiaControl\Formatter;
use ManiaControl\ManiaControl; use ManiaControl\ManiaControl;
use ManiaControl\ManiaExchange\ManiaExchangeList; use ManiaControl\ManiaExchange\ManiaExchangeList;
use ManiaControl\ManiaExchange\ManiaExchangeManager; use ManiaControl\ManiaExchange\ManiaExchangeManager;
use ManiaControl\ManiaExchange\MXMapInfo;
use ManiaControl\Players\Player; use ManiaControl\Players\Player;
/** /**
@ -532,13 +533,30 @@ class MapManager implements CallbackListener {
} }
$url = "http://{$title}.mania-exchange.com/tracks/download/{$mapId}"; $url = "http://{$title}.mania-exchange.com/tracks/download/{$mapId}";
$file = FileUtil::loadFile($url);
//Download the file
$function = function ($file, $error) use (&$login, &$mapInfo, &$mapDir, &$update) {
if (!$file) { if (!$file) {
// Download error // Download error
$this->maniaControl->chat->sendError('Download failed!', $login); $this->maniaControl->chat->sendError('Download failed!', $login);
return; 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 //Check if map is already on the server
if ($this->getMapByUid($mapInfo->uid) != null) { if ($this->getMapByUid($mapInfo->uid) != null) {
// Download error // Download error
@ -547,7 +565,7 @@ class MapManager implements CallbackListener {
} }
// Save map // Save map
$fileName = $mapId . '_' . $mapInfo->name . '.Map.Gbx'; $fileName = $mapInfo->id . '_' . $mapInfo->name . '.Map.Gbx';
$fileName = FileUtil::getClearedFileName($fileName); $fileName = FileUtil::getClearedFileName($fileName);
$downloadDirectory = $this->maniaControl->settingManager->getSetting($this, 'MapDownloadDirectory', 'MX'); $downloadDirectory = $this->maniaControl->settingManager->getSetting($this, 'MapDownloadDirectory', 'MX');
@ -623,5 +641,5 @@ class MapManager implements CallbackListener {
} }
} }
// TODO: add local map by filename // TODO: add local map by filename
}
} }