load(['mikrotik','packageProfile']); if ($account->mikrotik->connection_type !== 'api') return; $state = $this->routerOs->inspectAccount($account->mikrotik,$account->service_type,$account->username); $active = $state['active']; $uptime = max( $this->durationSeconds($active['uptime'] ?? ''), $this->durationSeconds($state['account']['uptime'] ?? '') ); $bytes = max( (int) ($active['bytes-in'] ?? 0) + (int) ($active['bytes-out'] ?? 0), (int) ($state['account']['bytes-in'] ?? 0) + (int) ($state['account']['bytes-out'] ?? 0) ); $updates=['remote_state'=>$state,'used_uptime_seconds'=>$uptime,'used_bytes'=>$bytes,'last_reconciled_at'=>now(),'last_sync_error'=>null]; if ($active && ! $account->first_login_at) { $updates['first_login_at']=now(); if ($account->packageProfile->validity_start === 'first_login') { $updates['validity_started_at']=now(); $updates['expires_at']=$this->expiry($account->packageProfile); } } $expires=$updates['expires_at'] ?? $account->expires_at; $expiresWithGrace = $expires?->copy()->addMinutes((int) $account->packageProfile->grace_period_minutes); $limitReached=($expiresWithGrace && now()->gte($expiresWithGrace)) || ($account->packageProfile->uptime_limit_seconds && $uptime >= $account->packageProfile->uptime_limit_seconds) || ($account->packageProfile->data_limit_bytes && $bytes >= $account->packageProfile->data_limit_bytes); if ($limitReached && $account->status === 'active') { $this->routerOs->setEnabled($account->mikrotik,$account->service_type,$account->username,false); $this->routerOs->disconnectAccount($account->mikrotik,$account->service_type,$account->username); $updates['status']='expired'; } $account->update($updates); } private function durationSeconds(string $value): int { preg_match_all('/(\d+)(w|d|h|m|s)/',$value,$m,PREG_SET_ORDER); $map=['w'=>604800,'d'=>86400,'h'=>3600,'m'=>60,'s'=>1]; return array_sum(array_map(fn($x)=>(int)$x[1]*$map[$x[2]],$m)); } private function expiry(NasPackageProfile $p) { if(!$p->validity_value||!$p->validity_unit)return null; return match($p->validity_unit){'minutes'=>now()->addMinutes($p->validity_value),'hours'=>now()->addHours($p->validity_value),'days'=>now()->addDays($p->validity_value),'months'=>now()->addMonths($p->validity_value),default=>null}; } }