download maps asynchronously
This commit is contained in:
parent
4875c14a7d
commit
4c8b247896
@ -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;
|
||||||
|
@ -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 = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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
|
||||||
*
|
*
|
||||||
|
@ -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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user