- added new ESI scope "esi-location.read_online.v1", closed #495

- added/improved "/online" status check to deleteLogData() cronjob, closed #495
- added/improved "/online" status check to $characterModel->updateLog(), closed #495
This commit is contained in:
Exodus4D
2017-06-03 14:47:16 +02:00
parent 398615cc5c
commit f94e7269ad
10 changed files with 187 additions and 176 deletions

View File

@@ -29,9 +29,6 @@ deleteEolConnections = Cron\MapUpdate->deleteEolConnections, @f
; delete expired wh connections
deleteExpiredConnections = Cron\MapUpdate->deleteExpiredConnections, @hourly
; disable character log data
deactivateLogData = Cron\CharacterUpdate->deactivateLogData, @instant
; delete character log data
deleteLogData = Cron\CharacterUpdate->deleteLogData, @instant

View File

@@ -1,7 +1,7 @@
; Environment Config
[ENVIRONMENT]
; project environment (DEVELOP, PRODUCTION).
; project environment (DEVELOP || PRODUCTION).
; This effects: DB connection, Mail-Server, SSO, CREST configurations in this file
; configuration below
SERVER = DEVELOP
@@ -34,7 +34,7 @@ CCP_SSO_SECRET_KEY =
; CCP ESI API
CCP_ESI_URL = https://esi.tech.ccp.is
CCP_ESI_DATASOURCE = singularity
CCP_ESI_SCOPES = esi-location.read_location.v1,esi-location.read_ship_type.v1,esi-ui.write_waypoint.v1,esi-ui.open_window.v1
CCP_ESI_SCOPES = esi-location.read_online.v1,esi-location.read_location.v1,esi-location.read_ship_type.v1,esi-ui.write_waypoint.v1,esi-ui.open_window.v1
CCP_ESI_SCOPES_ADMIN = esi-corporations.read_corporation_membership.v1
; SMTP settings (optional)
@@ -80,7 +80,7 @@ CCP_SSO_SECRET_KEY =
; CCP ESI API
CCP_ESI_URL = https://esi.tech.ccp.is
CCP_ESI_DATASOURCE = tranquility
CCP_ESI_SCOPES = esi-location.read_location.v1,esi-location.read_ship_type.v1,esi-ui.write_waypoint.v1,esi-ui.open_window.v1
CCP_ESI_SCOPES = esi-location.read_online.v1,esi-location.read_location.v1,esi-location.read_ship_type.v1,esi-ui.write_waypoint.v1,esi-ui.open_window.v1
CCP_ESI_SCOPES_ADMIN = esi-corporations.read_corporation_membership.v1
; SMTP settings (optional)

View File

@@ -58,7 +58,8 @@ class User extends Controller\Controller{
[
'ID' => $characterModel->_id,
'NAME' => $characterModel->name,
'TIME' => (new \DateTime())->getTimestamp()
'TIME' => (new \DateTime())->getTimestamp(),
'UPDATE_RETRY' => 0
]
];

View File

@@ -13,22 +13,15 @@ use Model;
class CharacterUpdate {
const CHARACTER_LOG_ACTIVE = 300;
const CHARACTER_LOG_INACTIVE = 300;
const CHARACTER_LOG_INACTIVE = 300;
/**
* get "active" time for character log data in seconds
* -> get default value in case of nothing found in *.ini file
* @param \Base $f3
* @return int
* max count of "inactive" character log data that will be checked for offline status
*/
protected function getCharacterLogActiveTime(\Base $f3){
$logActiveTime = (int)$f3->get('PATHFINDER.CACHE.CHARACTER_LOG_ACTIVE');
return ($logActiveTime >= 0) ? $logActiveTime : self::CHARACTER_LOG_ACTIVE;
}
const CHARACTERS_UPDATE_LOGS_MAX = 20;
/**
* get "incactive" time for character log data in seconeds
* get "inactive" time for character log data in seconds
* @param \Base $f3
* @return int
*/
@@ -37,38 +30,6 @@ class CharacterUpdate {
return ($logInactiveTime >= 0) ? $logInactiveTime : self::CHARACTER_LOG_INACTIVE;
}
/**
* set character log data as inactive in case of not changed within X seconds
* >> php index.php "/cron/deactivateLogData"
* @param \Base $f3
*/
public function deactivateLogData(\Base $f3){
DB\Database::instance()->getDB('PF');
$logActiveTime = $this->getCharacterLogActiveTime($f3);
/**
* @var $characterLogModel Model\CharacterLogModel
*/
$characterLogModel = Model\BasicModel::getNew('CharacterLogModel', 0);
// find expired character logs
$characterLogs = $characterLogModel->find([
'active = :active AND TIMESTAMPDIFF(SECOND, updated, NOW() ) > :lifetime',
':active' => 1,
':lifetime' => $logActiveTime
]);
if(is_object($characterLogs)){
foreach($characterLogs as $characterLog){
/**
* @var $characterLog Model\CharacterLogModel
*/
$characterLog->setActive(false);
$characterLog->save();
}
}
}
/**
* delete all character log data that were set to "active = 0" after X seconds of no changes
* -> see deactivateLogData()
@@ -84,11 +45,13 @@ class CharacterUpdate {
*/
$characterLogModel = Model\BasicModel::getNew('CharacterLogModel', 0);
// find expired character logs
// find character logs that were not checked recently and update
$characterLogs = $characterLogModel->find([
'active = :active AND TIMESTAMPDIFF(SECOND, updated, NOW() ) > :lifetime',
':active' => 0,
'TIMESTAMPDIFF(SECOND, updated, NOW() ) > :lifetime',
':lifetime' => $logInactiveTime
], [
'order' => 'updated asc',
'limit' => self::CHARACTERS_UPDATE_LOGS_MAX
]);
if(is_object($characterLogs)){
@@ -96,7 +59,11 @@ class CharacterUpdate {
/**
* @var $characterLog Model\CharacterLogModel
*/
$characterLog->erase();
// force characterLog as "updated" even if no changes were made
$characterLog->characterId->updateLog([
'markUpdated' => true,
'suppressHTTPErrors' => true
]);
}
}
}

View File

@@ -85,12 +85,26 @@ class AllianceModel extends BasicModel {
/**
* get all characters in this alliance
* @param array $characterIds
* @param array $options
* @return array
*/
public function getCharacters(){
public function getCharacters($characterIds = [], $options = []){
$characters = [];
$filter = ['active = ?', 1];
if( !empty($characterIds) ){
$filter[0] .= ' AND id IN (?)';
$filter[] = $characterIds;
}
$this->filter('allianceCharacters', $filter);
if($options['hasLog']){
// just characters with active log data
$this->has('allianceCharacters.characterLog', ['active = ?', 1]);
}
$this->filter('allianceCharacters', ['active = ?', 1]);
if($this->allianceCharacters){
foreach($this->allianceCharacters as $character){

View File

@@ -116,7 +116,6 @@ class CharacterLogModel extends BasicModel {
public function getData(){
$logData = (object) [];
$logData->active = $this->active;
$logData->system = (object) [];
$logData->system->id = (int)$this->systemId;
$logData->system->name = $this->systemName;
@@ -140,55 +139,12 @@ class CharacterLogModel extends BasicModel {
* @return int
*/
public function set_systemId($systemId){
if($this->systemId != $systemId){
$this->setActive(true);
}
if($systemId > 0){
$this->updateCharacterSessionLocation($systemId);
}
return $systemId;
}
/**
* setter for $shipTypeId
* @param int $shipTypeId
* @return int
*/
public function set_shipTypeId($shipTypeId){
if($this->shipTypeId != $shipTypeId){
$this->setActive(true);
}
return $shipTypeId;
}
/**
* setter for $shipId
* @param int $shipId
* @return int
*/
public function set_shipId($shipId){
if($this->shipId != $shipId){
$this->setActive(true);
}
return $shipId;
}
/**
* setter for $stationId
* @param int $stationId
* @return int
*/
public function set_stationId($stationId){
if($this->stationId != $stationId){
$this->setActive(true);
}
return $stationId;
}
/**
* Event "Hook" function
* return false will stop any further action

View File

@@ -621,87 +621,144 @@ class CharacterModel extends BasicModel {
* @return $this
*/
public function updateLog($additionalOptions = []){
$deleteLog = true;
$deleteLog = false;
$invalidResponse = false;
//check if log update is enabled for this user
if( $this->logLocation ){
// Try to pull data from API
if( $accessToken = $this->getAccessToken() ){
$locationData = self::getF3()->ccpClient->getCharacterLocationData($this->_id, $accessToken, $additionalOptions);
$onlineData = self::getF3()->ccpClient->getCharacterOnlineData($this->_id, $accessToken, $additionalOptions);
if( !empty($locationData['system']['id']) ){
// character is currently in-game
// check whether character is currently ingame online
if(is_bool($onlineData['online'])){
if($onlineData['online'] === true){
$locationData = self::getF3()->ccpClient->getCharacterLocationData($this->_id, $accessToken, $additionalOptions);
// IDs for "systemId", "stationId and "shipTypeId" that require more data
$lookupIds = [];
if( !empty($locationData['system']['id']) ){
// character is currently in-game
if( !$characterLog = $this->getLog() ){
// create new log
$characterLog = $this->rel('characterLog');
$characterLog->characterId = $this->_id;
}
// IDs for "systemId", "stationId and "shipTypeId" that require more data
$lookupIds = [];
// get current log data and modify on change
$logData = json_decode(json_encode( $characterLog->getData()), true);
if( !$characterLog = $this->getLog() ){
// create new log
$characterLog = $this->rel('characterLog');
$characterLog->characterId = $this->_id;
}
if(
empty($logData['system']['name']) ||
$logData['system']['id'] !== $locationData['system']['id']
){
// system changed -> request "system name" for current system
$lookupIds[] = $locationData['system']['id'];
}
// get current log data and modify on change
$logData = json_decode(json_encode( $characterLog->getData()), true);
if( !empty($locationData['station']['id']) ){
if(
empty($logData['station']['name']) ||
$logData['station']['id'] !== $locationData['station']['id']
){
// station changed -> request "station name" for current station
$lookupIds[] = $locationData['station']['id'];
if(
empty($logData['system']['name']) ||
$logData['system']['id'] !== $locationData['system']['id']
){
// system changed -> request "system name" for current system
$lookupIds[] = $locationData['system']['id'];
}
if( !empty($locationData['station']['id']) ){
if(
empty($logData['station']['name']) ||
$logData['station']['id'] !== $locationData['station']['id']
){
// station changed -> request "station name" for current station
$lookupIds[] = $locationData['station']['id'];
}
}else{
unset($logData['station']);
}
$logData = array_replace_recursive($logData, $locationData);
// get current ship data
$shipData = self::getF3()->ccpClient->getCharacterShipData($this->_id, $accessToken, $additionalOptions);
if( !empty($shipData['ship']['typeId']) ){
if(
empty($logData['ship']['typeName']) ||
$logData['ship']['typeId'] !== $shipData['ship']['typeId']
){
// ship changed -> request "station name" for current station
$lookupIds[] = $shipData['ship']['typeId'];
}
// "shipName"/"shipId" could have changed...
$logData = array_replace_recursive($logData, $shipData);
}else{
// ship data should never be empty -> keep current one
//unset($logData['ship']);
$invalidResponse = true;
}
if( !empty($lookupIds) ){
// get "more" information for some Ids (e.g. name)
$universeData = self::getF3()->ccpClient->getUniverseNamesData($lookupIds, $additionalOptions);
if( !empty($universeData) ){
$logData = array_replace_recursive($logData, $universeData);
}else{
// this is important! universe data is a MUST HAVE!
$deleteLog = true;
}
}
if( !$deleteLog ){
// mark log as "updated" even if no changes were made
if($additionalOptions['markUpdated'] === true){
$characterLog->touch('updated');
}
$characterLog->setData($logData);
$characterLog->save();
$this->characterLog = $characterLog;
}
}else{
// systemId should always exists
$invalidResponse = true;
}
}else{
unset($logData['station']);
// user is in-game offline
$deleteLog = true;
}
}else{
// online status request failed
$invalidResponse = true;
}
}else{
// access token request failed
$deleteLog = true;
}
}else{
// character deactivated location logging
$deleteLog = true;
}
$logData = array_replace_recursive($logData, $locationData);
if( $user = $this->getUser() ){
// Session data does not exists in CLI mode (Cronjob)
if( $sessionCharacterData = $user->getSessionCharacterData($this->id, false) ){
$updateRetry = (int)$sessionCharacterData['UPDATE_RETRY'];
$newRetry = $updateRetry;
if($invalidResponse){
$newRetry++;
// get current ship data
$shipData = self::getF3()->ccpClient->getCharacterShipData($this->_id, $accessToken, $additionalOptions);
if( !empty($shipData['ship']['typeId']) ){
if(
empty($logData['ship']['typeName']) ||
$logData['ship']['typeId'] !== $shipData['ship']['typeId']
){
// ship changed -> request "station name" for current station
$lookupIds[] = $shipData['ship']['typeId'];
}
// "shipName"/"shipId" could have changed...
$logData = array_replace_recursive($logData, $shipData);
}else{
unset($logData['ship']);
if($newRetry >= 3){
// no proper character log data (3 fails in a row))
$newRetry = 0;
$deleteLog = true;
}
}else{
// reset retry counter
$newRetry = 0;
}
if( !empty($lookupIds) ){
// get "more" information for some Ids (e.g. name)
$universeData = self::getF3()->ccpClient->getUniverseNamesData($lookupIds, $additionalOptions);
if( !empty($universeData) ){
$deleteLog = false;
$logData = array_replace_recursive($logData, $universeData);
}
}else{
$deleteLog = false;
}
if( !$deleteLog ){
$characterLog->setData($logData);
$characterLog->save();
$this->characterLog = $characterLog;
}
if($updateRetry !== $newRetry){
// update retry counter
$sessionCharacterData['UPDATE_RETRY'] = $newRetry;
$sessionCharacters = self::mergeSessionCharacterData([$sessionCharacterData]);
self::getF3()->set(User::SESSION_KEY_CHARACTERS, $sessionCharacters);
}
}
}

View File

@@ -157,9 +157,10 @@ class CorporationModel extends BasicModel {
/**
* get all characters in this corporation
* @param array $characterIds
* @param array $options
* @return CharacterModel[]
*/
public function getCharacters( $characterIds = []){
public function getCharacters($characterIds = [], $options = []){
$characters = [];
$filter = ['active = ?', 1];
@@ -170,6 +171,11 @@ class CorporationModel extends BasicModel {
$this->filter('corporationCharacters', $filter);
if($options['hasLog']){
// just characters with active log data
$this->has('corporationCharacters.characterLog', ['active = ?', 1]);
}
if($this->corporationCharacters){
foreach($this->corporationCharacters as $character){
$characters[] = $character;

View File

@@ -573,12 +573,25 @@ class MapModel extends BasicModel {
/**
* get all (private) characters for this map
* @param array $characterIds
* @param array $options
* @return CharacterModel[]
*/
private function getCharacters(){
private function getCharacters($characterIds = [], $options = []){
$characters = [];
$filter = ['active = ?', 1];
$this->filter('mapCharacters', ['active = ?', 1]);
if( !empty($characterIds) ){
$filter[0] .= ' AND id IN (?)';
$filter[] = $characterIds;
}
$this->filter('mapCharacters', $filter);
if($options['hasLog']){
// just characters with active log data
$this->has('mapCharacters.characterLog', ['active = ?', 1]);
}
if($this->mapCharacters){
foreach($this->mapCharacters as $characterMapModel){
@@ -591,9 +604,10 @@ class MapModel extends BasicModel {
/**
* get all character models that are currently online "viewing" this map
* @param array $options filter options
* @return CharacterModel[]
*/
private function getAllCharacters(){
private function getAllCharacters($options = []){
$characters = [];
if($this->isPrivate()){
@@ -607,13 +621,13 @@ class MapModel extends BasicModel {
$corporations = $this->getCorporations();
foreach($corporations as $corporation){
$characters = array_merge($characters, $corporation->getCharacters());
$characters = array_merge($characters, $corporation->getCharacters([], $options));
}
}elseif($this->isAlliance()){
$alliances = $this->getAlliances();
foreach($alliances as $alliance){
$characters = array_merge($characters, $alliance->getCharacters());
$characters = array_merge($characters, $alliance->getCharacters([], $options));
}
}
@@ -623,15 +637,16 @@ class MapModel extends BasicModel {
/**
* get data for ALL characters with map access
* -> The result of this function is cached!
* @return \stdClass[]
* @param array $options filter options
* @return \stdClass
*/
public function getCharactersData(){
public function getCharactersData($options = []){
// check if there is cached data
$charactersData = $this->getCacheData(self::DATA_CACHE_KEY_CHARACTER);
if(is_null($charactersData)){
$charactersData = [];
$characters = $this->getAllCharacters();
$characters = $this->getAllCharacters($options);
foreach($characters as $character){
$charactersData[] = $character->getData(true);
@@ -844,7 +859,7 @@ class MapModel extends BasicModel {
$mapDataAll = $this->getData();
// get data of characters which have with map access
$activeUserCharactersData = $this->getCharactersData();
$activeUserCharactersData = $this->getCharactersData(['hasLog' => true]);
// sort characters by "active" status
$sortByActiveLog = function($a, $b){

View File

@@ -128,9 +128,7 @@ EXECUTION_LIMIT = 50
; CACHE ===========================================================================================
[PATHFINDER.CACHE]
; mark characters inactive if nothing (ship/system/...) changed within X seconds (default: 5min)
CHARACTER_LOG_ACTIVE = 300
; delete character log data if "inactive" for X seconds (seconds) (default: 10min)
; delete character log data if if nothing (ship/system/...) for X seconds (seconds) (default: 5min)
CHARACTER_LOG_INACTIVE = 300
; expire time for static system data (seconds) (default: 20d)
CONSTELLATION_SYSTEMS = 1728000