- 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:
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
@@ -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
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user