ق<?php
include('config.php');
require_once 'request.php';
date_default_timezone_set('Asia/Tehran');
#-----------------------------#
function token_panel($code_panel,$verify = true){
    $panel = select("marzban_panel","*","code_panel",$code_panel,"select");
    if (!is_array($panel) || empty($panel)) {
        return ["error" => "Panel configuration not found for the provided code."];
    }

    $url_get_token = $panel['url_panel'].'/api/admin/token';
    $username_panel = $panel['username_panel'];
    $password_panel = $panel['password_panel'];
    if($panel['datelogin'] != null && $verify){
        $date = json_decode($panel['datelogin'],true);
        if(isset($date['time']) && isset($date['access_token'])){
            $timecurrent = time();
            // استفاده از strtotime برای تبدیل تاریخ به timestamp
            $token_time = strtotime($date['time']);
            if($token_time === false){
                // اگر strtotime خطا داد، token را refresh کنیم
                $date = null;
            } else {
                $start_date = $timecurrent - $token_time;
                // token را تا 50 دقیقه معتبر در نظر می‌گیریم (نه 60 دقیقه) برای اطمینان
                if($start_date <= 3000 && $start_date >= 0){
                    return $date;
                }
            }
        }
    }
    $data_token = array(
        'username' => $username_panel,
        'password' => $password_panel
    );
    $headers = array(
            'Content-Type: application/x-www-form-urlencoded',
            'accept: application/json'
    );
    $req = new CurlRequest($url_get_token);
    $req->setHeaders($headers);
    $response = $req->post($data_token);
    if(!empty($response['error'])){
        return array("error" => $response['error']);
    }
    $body = json_decode($response['body'], true);
    if(isset($body['access_token'])){
        $time = date('Y/m/d H:i:s');
        $data = json_encode(array(
            'time' => $time,
            'access_token' => $body['access_token']
            ));
        if (isset($panel['name_panel'])) {
            update("marzban_panel","datelogin",$data,'name_panel',$panel['name_panel']);
        }
    }
    return $body;
}
#-----------------------------#

function findMarzbanPanelByName($location)
{
    $panel = select("marzban_panel", "*", "name_panel", $location, "select");
    if (!is_array($panel) || empty($panel)) {
        return null;
    }

    return $panel;
}
#-----------------------------#

function getuser($username_account,$location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/user/' . $username_account;
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->get();
    return $response;
}
#-----------------------------#

function Get_Nodes($location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/nodes';
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->get();
    return $response;
}
function Get_usage_Nodes($location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/nodes/usage';
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->get();
    return $response;
}
function Get_Node($location,$Nodeid)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/node/'.$Nodeid;
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->get();
    return $response;
}

function getusers($location,$status)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/users?status='.$status;
    if(!isset($Check_token['access_token']))return;
    $header_value = 'Bearer ';

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPGET, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Accept: application/json',
        'Authorization: ' . $header_value .  $Check_token['access_token']
    ));

    $output = curl_exec($ch);
    curl_close($ch);
    $data_user = json_decode($output, true);

    if (!is_array($data_user)) {
        return ['error' => 'Unable to decode panel response.'];
    }

    if (isset($data_user['error'])) {
        return $data_user;
    }

    if (!isset($data_user['users'])) {
        $data_user['users'] = [];
    }

    return $data_user;
}
#-----------------------------#
function getinbounds($location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    $url =  $marzban_list_get['url_panel'].'/api/inbounds';
    $header_value = 'Bearer ';

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPGET, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Accept: application/json',
        'Authorization: ' . $header_value .  $Check_token['access_token']
    ));

    $output = curl_exec($ch);
    curl_close($ch);
    $inbounds = json_decode($output, true);
    return $inbounds;
}
#-----------------------------#
function ResetUserDataUsage($username_account,$location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/user/' . $username_account.'/reset';

    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->post(array());
    return $response;
}
function revoke_sub($username_account,$location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/user/' . $username_account.'/revoke_sub';
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->post(array());
    return $response;
}
#-----------------------------#
function adduser($location,$data_limit,$username_ac,$timestamp,$note ='',$data_limit_reset = 'no_reset',$name_product = false)
{
    global $pdo,$new_marzban;
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url = $marzban_list_get['url_panel']."/api/user";
    if($marzban_list_get['inbounds'] != null and $marzban_list_get['inbounds'] != "null"){
            if($name_product != false and $name_product != "usertest"){
             $product = select("product","*","name_product",$name_product,"select"); 
             if($product == false || $product['inbounds'] == false){
                 $inbounds = json_decode($marzban_list_get['inbounds'],true);
             }else{
                 $inbounds = json_decode($product['inbounds'],true);
                 $marzban_list_get['proxies'] = $product['proxies'];
             }
            }else{
        $inbounds = json_decode($marzban_list_get['inbounds'],true);
            }
        }
    if($new_marzban){
            $data = array(
            "proxy_settings" => json_decode($marzban_list_get['proxies']),
            "data_limit" => $data_limit,
            "username" => $username_ac,
            "note" => $note,
            "data_limit_reset_strategy" => $data_limit_reset
        );
        if(isset($inbounds)){
            $data['group_ids'] = $inbounds;
        }
        // طبق freemirza: expire باید همیشه integer باشد (timestamp)
        if($name_product == "usertest"){
            if($marzban_list_get['on_hold_test'] == "0"){
                // اطمینان از اینکه expire integer است
                $data["expire"] = ($timestamp == 0 || $timestamp == "0") ? 0 : (int)$timestamp;
            }else{
                if($timestamp == 0 || $timestamp == "0"){
                    $data["expire"] = 0;
                }else{
                    $data["expire"] = 0;
                    $data["status"] = "on_hold";
                    $data["on_hold_expire_duration"] = (int)$timestamp - time();
                }
            }
        }else{
            if($marzban_list_get['conecton'] == "offconecton"){
                // اطمینان از اینکه expire integer است
                $data["expire"] = ($timestamp == 0 || $timestamp == "0") ? 0 : (int)$timestamp;
            }else{
                if($timestamp == 0 || $timestamp == "0"){
                    $data["expire"] = 0;
                }else{
                    $data["expire"] = 0;
                    $data["status"] = "on_hold";
                    $data["on_hold_expire_duration"] = (int)$timestamp - time();
                }
            }
        }
    }else{
        $data = array(
            "proxies" => json_decode($marzban_list_get['proxies']),
            "data_limit" => $data_limit,
            "username" => $username_ac,
            "note" => $note,
            "data_limit_reset_strategy" => $data_limit_reset
        );
        if(isset($inbounds)){
            $data['inbounds'] = $inbounds;
        }
        // طبق freemirza: expire باید همیشه integer باشد (timestamp)
        if($name_product == "usertest"){
            if($marzban_list_get['on_hold_test'] == "0"){
                // اطمینان از اینکه expire integer است
                $data["expire"] = ($timestamp == 0 || $timestamp == "0") ? 0 : (int)$timestamp;
            }else{
                if($timestamp == 0 || $timestamp == "0"){
                    $data["expire"] = 0;
                }else{
                    $data["expire"] = 0;
                    $data["status"] = "on_hold";
                    $data["on_hold_expire_duration"] = (int)$timestamp - time();
                }
            }
        }else{
            if($marzban_list_get['conecton'] == "offconecton"){
                // اطمینان از اینکه expire integer است
                $data["expire"] = ($timestamp == 0 || $timestamp == "0") ? 0 : (int)$timestamp;
            }else{
                if($timestamp == 0 || $timestamp == "0"){
                    $data["expire"] = 0;
                }else{
                    $data["expire"] = 0;
                    $data["status"] = "on_hold";
                    $data["on_hold_expire_duration"] = (int)$timestamp - time();
                }
            }
        }
    }
    // دقیقاً مانند freemirza: مستقیماً JSON string را برمی‌گردانیم
    $header_value = 'Bearer ';
    $payload = json_encode($data);
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Accept: application/json',
        'Authorization: ' . $header_value . $Check_token['access_token'],
        'Content-Type: application/json'
    ));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
    
    $response = curl_exec($ch);
    curl_close($ch);
    
    // دقیقاً مانند freemirza: مستقیماً response را برمی‌گردانیم
    return $response;
}
//----------------------------------
function Get_System_Stats($location){
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    $url =  $marzban_list_get['url_panel'].'/api/system';
    $header_value = 'Bearer ';

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPGET, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Accept: application/json',
        'Authorization: ' . $header_value .  $Check_token['access_token']
    ));

    $output = curl_exec($ch);
    curl_close($ch);
    $Get_System_Stats = json_decode($output, true);
    return $Get_System_Stats;
}
//----------------------------------
function removeuser($location,$username)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/user/'.$username;
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->delete();
    return $response;
}
function removenode($location,$nodeid){
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/node/'.$nodeid;
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->delete();
    return $response;
}
//----------------------------------
function Modifyuser($location,$username,array $data)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/user/'.$username;
    $headers = array(
            'accept: application/json',
            'Content-Type: application/json'
    );
    $payload = json_encode($data);
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->put($payload);
    return $response;
}
//----------------------------------

function Modifyuser_node($location,$id_node,array $data)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    $url =  $marzban_list_get['url_panel'].'/api/node/'.$id_node;
    $payload = json_encode($data);
    $ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
$headers = array();
$headers[] = 'Accept: application/json';
$headers[] = 'Authorization: Bearer '.$Check_token['access_token'];
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
curl_close($ch);
     $data_useer = json_decode($result, true);
    return $data_useer;
}
function hosts($location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    $url =  $marzban_list_get['url_panel'].'/api/hosts';
    $ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$headers = array();
$headers[] = 'Accept: application/json';
$headers[] = 'Authorization: Bearer '.$Check_token['access_token'];
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
curl_close($ch);
     $data_hosts = $result;
    return $data_hosts;
}
//----------------------------------
function reconnect_node($location,$id_node)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/node/'.$id_node.'/reconnect';
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->post(array());
    return $response;
}

function get_list_update($location,$username)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel']."/api/user/$username/sub_update?offset=0&limit=1";
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->get();
    return $response;
}