mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-03 14:10:57 +08:00
1251 lines
38 KiB
PHP
1251 lines
38 KiB
PHP
<?php
|
||
|
||
function get_global_sp_state()
|
||
{
|
||
static $global_promotion_state;
|
||
$cacheKey = \App\Models\Setting::TORRENT_GLOBAL_STATE_CACHE_KEY;
|
||
if (!$global_promotion_state) {
|
||
$row = \Nexus\Database\NexusDB::remember($cacheKey, 600, function () use ($cacheKey) {
|
||
return \Nexus\Database\NexusDB::getOne('torrents_state', 1);
|
||
});
|
||
if (is_array($row) && isset($row['deadline']) && $row['deadline'] < date('Y-m-d H:i:s')) {
|
||
//expired
|
||
$global_promotion_state = \App\Models\Torrent::PROMOTION_NORMAL;
|
||
} elseif (is_array($row) && isset($row['begin']) && $row['begin'] > date('Y-m-d H:i:s')) {
|
||
//Not begin
|
||
$global_promotion_state = \App\Models\Torrent::PROMOTION_NORMAL;
|
||
} elseif (is_array($row)) {
|
||
$global_promotion_state = $row["global_sp_state"];
|
||
} else {
|
||
$global_promotion_state = $row;
|
||
}
|
||
}
|
||
return $global_promotion_state;
|
||
}
|
||
|
||
// IP Validation
|
||
function validip($ip)
|
||
{
|
||
if (!ip2long($ip)) //IPv6
|
||
return true;
|
||
if (!empty($ip) && $ip == long2ip(ip2long($ip)))
|
||
{
|
||
// reserved IANA IPv4 addresses
|
||
// http://www.iana.org/assignments/ipv4-address-space
|
||
$reserved_ips = array (
|
||
array('192.0.2.0','192.0.2.255'),
|
||
array('192.168.0.0','192.168.255.255'),
|
||
array('255.255.255.0','255.255.255.255')
|
||
);
|
||
|
||
foreach ($reserved_ips as $r)
|
||
{
|
||
$min = ip2long($r[0]);
|
||
$max = ip2long($r[1]);
|
||
if ((ip2long($ip) >= $min) && (ip2long($ip) <= $max)) return false;
|
||
}
|
||
return true;
|
||
}
|
||
else return false;
|
||
}
|
||
|
||
function getip($real = true) {
|
||
if (isset($_SERVER)) {
|
||
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && validip($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||
} elseif (isset($_SERVER['HTTP_CLIENT_IP']) && validip($_SERVER['HTTP_CLIENT_IP'])) {
|
||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||
} else {
|
||
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
|
||
}
|
||
} else {
|
||
if (getenv('HTTP_X_FORWARDED_FOR') && validip(getenv('HTTP_X_FORWARDED_FOR'))) {
|
||
$ip = getenv('HTTP_X_FORWARDED_FOR');
|
||
} elseif (getenv('HTTP_CLIENT_IP') && validip(getenv('HTTP_CLIENT_IP'))) {
|
||
$ip = getenv('HTTP_CLIENT_IP');
|
||
} else {
|
||
$ip = getenv('REMOTE_ADDR') ?? '';
|
||
}
|
||
}
|
||
$ip = trim(trim($ip), ",");
|
||
if ($real && str_contains($ip, ",")) {
|
||
return strstr($ip, ",", true);
|
||
}
|
||
return $ip;
|
||
}
|
||
|
||
function sql_query($query)
|
||
{
|
||
$begin = microtime(true);
|
||
global $query_name;
|
||
$result = mysql_query($query);
|
||
$end = microtime(true);
|
||
$query_name[] = [
|
||
'query' => $query,
|
||
'time' => sprintf('%.3f ms', ($end - $begin) * 1000),
|
||
];
|
||
return $result;
|
||
}
|
||
|
||
function sqlesc($value) {
|
||
if (is_null($value)) {
|
||
return 'null';
|
||
}
|
||
$value = "'" . mysql_real_escape_string($value) . "'";
|
||
return $value;
|
||
}
|
||
|
||
function hash_pad($hash) {
|
||
return str_pad($hash, 20);
|
||
}
|
||
|
||
function hash_where($name, $hash) {
|
||
// $shhash = preg_replace('/ *$/s', "", $hash);
|
||
// return "($name = " . sqlesc($hash) . " OR $name = " . sqlesc($shhash) . ")";
|
||
// return sprintf("$name in (%s, %s)", sqlesc($hash), sqlesc($shhash));
|
||
return "$name = " . sqlesc($hash);
|
||
}
|
||
|
||
//no need any more...
|
||
/*
|
||
function strip_magic_quotes($arr)
|
||
{
|
||
foreach ($arr as $k => $v)
|
||
{
|
||
if (is_array($v))
|
||
{
|
||
$arr[$k] = strip_magic_quotes($v);
|
||
} else {
|
||
$arr[$k] = stripslashes($v);
|
||
}
|
||
}
|
||
return $arr;
|
||
}
|
||
|
||
if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
|
||
{
|
||
if (!empty($_GET)) {
|
||
$_GET = strip_magic_quotes($_GET);
|
||
}
|
||
if (!empty($_POST)) {
|
||
$_POST = strip_magic_quotes($_POST);
|
||
}
|
||
if (!empty($_COOKIE)) {
|
||
$_COOKIE = strip_magic_quotes($_COOKIE);
|
||
}
|
||
}
|
||
*/
|
||
|
||
function get_langfolder_list()
|
||
{
|
||
//do not access db for speed up, or for flexibility
|
||
return array("en", "chs", "cht", "ko", "ja");
|
||
}
|
||
|
||
function printLine($line, $exist = false)
|
||
{
|
||
echo "[" . date('Y-m-d H:i:s') . "] $line<br />";
|
||
if ($exist) {
|
||
exit(0);
|
||
}
|
||
}
|
||
|
||
function nexus_dd($vars)
|
||
{
|
||
echo '<pre>';
|
||
array_map(function ($var) {
|
||
var_dump($var);
|
||
}, func_get_args());
|
||
echo '</pre>';
|
||
exit(0);
|
||
}
|
||
|
||
/**
|
||
* write log, use in both pure nexus and inside laravel
|
||
*
|
||
* @param $log
|
||
* @param string $level
|
||
*/
|
||
function do_log($log, $level = 'info', $echo = false)
|
||
{
|
||
static $env, $setLogLevel;
|
||
if (is_null($setLogLevel)) {
|
||
$setLogLevel = nexus_env('LOG_LEVEL', 'debug');
|
||
}
|
||
if (is_null($env)) {
|
||
$env = nexus_env('APP_ENV', 'production');
|
||
}
|
||
$logLevels = ['debug', 'info', 'notice', 'warning', 'error', 'critical', 'alert', 'emergency'];
|
||
$setLogLevelKey = array_search($setLogLevel, $logLevels);
|
||
$currentLogLevelKey = array_search($level, $logLevels);
|
||
if ($currentLogLevelKey === false) {
|
||
$level = 'error';
|
||
$log = "[ERROR_LOG_LEVEL] $log";
|
||
$currentLogLevelKey = array_search($level, $logLevels);
|
||
}
|
||
if ($currentLogLevelKey < $setLogLevelKey) {
|
||
return;
|
||
}
|
||
|
||
$logFile = getLogFile();
|
||
if (($fd = fopen($logFile, 'a')) === false) {
|
||
$log .= "--------Can not open $logFile";
|
||
$fd = fopen(sys_get_temp_dir() . '/nexus.log', 'a');
|
||
}
|
||
$uid = 0;
|
||
if (IN_NEXUS) {
|
||
global $CURUSER;
|
||
$user = $CURUSER;
|
||
$uid = $user['id'] ?? 0;
|
||
$passkey = $user['passkey'] ?? $_REQUEST['passkey'] ?? $_REQUEST['authkey'] ?? '';
|
||
} else {
|
||
try {
|
||
$user = \Illuminate\Support\Facades\Auth::user();
|
||
$uid = $user->id ?? 0;
|
||
$passkey = $user->passkey ?? request('passkey', request('authkey', ''));
|
||
} catch (\Throwable $exception) {
|
||
$passkey = "!IN_NEXUS:" . $exception->getMessage();
|
||
}
|
||
}
|
||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
|
||
$content = sprintf(
|
||
"[%s] [%s] [%s] [%s] [%s] [%s] %s.%s %s:%s %s%s%s %s%s",
|
||
date('Y-m-d H:i:s'),
|
||
nexus() ? nexus()->getRequestId() : 'NO_REQUEST_ID',
|
||
nexus() ? nexus()->getLogSequence() : 0,
|
||
sprintf('%.3f', microtime(true) - (nexus() ? nexus()->getStartTimestamp() : 0)),
|
||
$uid,
|
||
$passkey,
|
||
$env, strtoupper($level),
|
||
$backtrace[0]['file'] ?? '',
|
||
$backtrace[0]['line'] ?? '',
|
||
$backtrace[1]['class'] ?? '',
|
||
$backtrace[1]['type'] ?? '',
|
||
$backtrace[1]['function'] ?? '',
|
||
$log,
|
||
PHP_EOL
|
||
);
|
||
fwrite($fd, $content);
|
||
fclose($fd);
|
||
if (is_bool($echo) && $echo) {
|
||
echo $content . PHP_EOL;
|
||
}
|
||
if (nexus()) {
|
||
nexus()->incrementLogSequence();
|
||
}
|
||
}
|
||
|
||
function getLogFile($append = '')
|
||
{
|
||
static $logFiles = [];
|
||
if (isset($logFiles[$append])) {
|
||
return $logFiles[$append];
|
||
}
|
||
$config = nexus_config('nexus');
|
||
$path = getenv('NEXUS_LOG_DIR', true);
|
||
$fromEnv = true;
|
||
if ($path === false) {
|
||
$fromEnv = false;
|
||
$path = sys_get_temp_dir();
|
||
}
|
||
$logFile = rtrim($path, '/') . '/nexus.log';
|
||
if (!$fromEnv && !empty($config['log_file'])) {
|
||
$logFile = $config['log_file'];
|
||
}
|
||
$lastDotPos = strrpos($logFile, '.');
|
||
if ($lastDotPos !== false) {
|
||
$prefix = substr($logFile, 0, $lastDotPos);
|
||
$suffix = substr($logFile, $lastDotPos);
|
||
} else {
|
||
$prefix = $logFile;
|
||
$suffix = '';
|
||
}
|
||
$name = $prefix;
|
||
if ($append) {
|
||
$name .= "-$append";
|
||
}
|
||
$logFile = sprintf('%s-%s%s', $name, date('Y-m-d'), $suffix);
|
||
return $logFiles[$append] = $logFile;
|
||
|
||
}
|
||
|
||
function nexus_config($key, $default = null)
|
||
{
|
||
if (!IN_NEXUS) {
|
||
return config($key, $default);
|
||
}
|
||
static $configs;
|
||
if (is_null($configs)) {
|
||
//get all configuration from config file
|
||
// $files = glob(ROOT_PATH . 'config/*.php');
|
||
$files = [
|
||
ROOT_PATH . 'config/nexus.php',
|
||
ROOT_PATH . 'config/emoji.php',
|
||
];
|
||
foreach ($files as $file) {
|
||
$basename = basename($file);
|
||
if ($basename == 'allconfig.php') {
|
||
//exclude the NexusPHP default config file
|
||
continue;
|
||
}
|
||
$values = require $file;
|
||
$configPrefix = strstr($basename, '.php', true);
|
||
$configs[$configPrefix] = $values;
|
||
}
|
||
}
|
||
return arr_get($configs, $key, $default);
|
||
}
|
||
|
||
|
||
/**
|
||
* get setting for given name and prefix
|
||
*
|
||
* @date 2021/1/11
|
||
* @param null $name
|
||
* @param null $default
|
||
* @return mixed
|
||
*/
|
||
function get_setting($name = null, $default = null): mixed
|
||
{
|
||
static $settings;
|
||
if (is_null($settings)) {
|
||
$settings = \Nexus\Database\NexusDB::remember("nexus_settings_in_nexus", 600, function () {
|
||
//get all settings from database
|
||
return \App\Models\Setting::getFromDb();
|
||
});
|
||
}
|
||
if (is_null($name)) {
|
||
return $settings;
|
||
}
|
||
return arr_get($settings, $name, $default);
|
||
}
|
||
|
||
function get_setting_from_db($name = null, $default = null)
|
||
{
|
||
static $final;
|
||
if (is_null($final)) {
|
||
$final = \App\Models\Setting::getFromDb();
|
||
}
|
||
if (is_null($name)) {
|
||
return $final;
|
||
}
|
||
return arr_get($final, $name, $default);
|
||
}
|
||
|
||
|
||
function nexus_env($key = null, $default = null)
|
||
{
|
||
static $env;
|
||
if (is_null($env)) {
|
||
$envFile = dirname(__DIR__) . '/.env';
|
||
$env = readEnvFile($envFile);
|
||
}
|
||
if (is_null($key)) {
|
||
return $env;
|
||
}
|
||
return $env[$key] ?? $default;
|
||
}
|
||
|
||
function readEnvFile($envFile)
|
||
{
|
||
if (!file_exists($envFile)) {
|
||
if (php_sapi_name() == 'cli') {
|
||
return [];
|
||
}
|
||
throw new \RuntimeException("env file : $envFile is not exists in the root path.");
|
||
}
|
||
$env = [];
|
||
$fp = fopen($envFile, 'r');
|
||
if ($fp === false) {
|
||
throw new \RuntimeException(".env file: $envFile is not readable.");
|
||
}
|
||
while (($line = fgets($fp)) !== false) {
|
||
$line = trim($line);
|
||
if (empty($line)) {
|
||
continue;
|
||
}
|
||
$pos = strpos($line, '=');
|
||
if ($pos <= 0) {
|
||
continue;
|
||
}
|
||
if (mb_substr($line, 0, 1, 'utf-8') == '#') {
|
||
continue;
|
||
}
|
||
$lineKey = normalize_env(mb_substr($line, 0, $pos, 'utf-8'));
|
||
$lineValue = normalize_env(mb_substr($line, $pos + 1, null, 'utf-8'));
|
||
$env[$lineKey] = $lineValue;
|
||
}
|
||
return $env;
|
||
}
|
||
|
||
function normalize_env($value)
|
||
{
|
||
$value = trim($value);
|
||
$toStrip = ['\'', '"'];
|
||
if (in_array(mb_substr($value, 0, 1, 'utf-8'), $toStrip)) {
|
||
$value = mb_substr($value, 1, null, 'utf-8');
|
||
}
|
||
if (in_array(mb_substr($value, -1, null,'utf-8'), $toStrip)) {
|
||
$value = mb_substr($value, 0, -1, 'utf-8');
|
||
}
|
||
switch (strtolower($value)) {
|
||
case 'true':
|
||
return true;
|
||
case 'false':
|
||
return false;
|
||
case 'null':
|
||
return null;
|
||
default:
|
||
return $value;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Get an item from an array using "dot" notation.
|
||
*
|
||
* reference to Laravel
|
||
*
|
||
* @date 2021/1/14
|
||
* @param $array
|
||
* @param $key
|
||
* @param null $default
|
||
* @return mixed|null
|
||
*/
|
||
function arr_get($array, $key, $default = null)
|
||
{
|
||
if (strpos($key, '.') === false) {
|
||
return $array[$key] ?? $default;
|
||
}
|
||
foreach (explode('.', $key) as $segment) {
|
||
if (isset($array[$segment])) {
|
||
$array = $array[$segment];
|
||
} else {
|
||
return $default;
|
||
}
|
||
}
|
||
return $array;
|
||
}
|
||
|
||
/**
|
||
* From Laravel
|
||
*
|
||
* Set an array item to a given value using "dot" notation.
|
||
*
|
||
* If no key is given to the method, the entire array will be replaced.
|
||
*
|
||
* @param array $array
|
||
* @param string|null $key
|
||
* @param mixed $value
|
||
* @return array
|
||
*/
|
||
function arr_set(&$array, $key, $value)
|
||
{
|
||
if (is_null($key)) {
|
||
return $array = $value;
|
||
}
|
||
|
||
$keys = explode('.', $key);
|
||
|
||
foreach ($keys as $i => $key) {
|
||
if (count($keys) === 1) {
|
||
break;
|
||
}
|
||
|
||
unset($keys[$i]);
|
||
|
||
// If the key doesn't exist at this depth, we will just create an empty array
|
||
// to hold the next value, allowing us to create the arrays to hold final
|
||
// values at the correct depth. Then we'll keep digging into the array.
|
||
if (! isset($array[$key]) || ! is_array($array[$key])) {
|
||
$array[$key] = [];
|
||
}
|
||
|
||
$array = &$array[$key];
|
||
}
|
||
|
||
$array[array_shift($keys)] = $value;
|
||
|
||
return $array;
|
||
}
|
||
|
||
function isHttps(): bool
|
||
{
|
||
if (isRunningInConsole()) {
|
||
$securityLogin = get_setting("security.securelogin");
|
||
if ($securityLogin != "no") {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
return nexus()->getRequestSchema() == 'https';
|
||
}
|
||
|
||
|
||
function getSchemeAndHttpHost(bool $fromConfig = false)
|
||
{
|
||
if (isRunningInConsole() || $fromConfig) {
|
||
$host = get_setting("basic.BASEURL");
|
||
} else {
|
||
$host = nexus()->getRequestHost();
|
||
}
|
||
$isHttps = isHttps();
|
||
$protocol = $isHttps ? 'https' : 'http';
|
||
return "$protocol://" . $host;
|
||
}
|
||
|
||
function getBaseUrl()
|
||
{
|
||
$url = getSchemeAndHttpHost();
|
||
$requestUri = $_SERVER['REQUEST_URI'];
|
||
$pos = strpos($requestUri, '?');
|
||
if ($pos !== false) {
|
||
$url .= substr($requestUri, 0, $pos);
|
||
} else {
|
||
$url .= $requestUri;
|
||
}
|
||
return trim($url, '/');
|
||
}
|
||
|
||
|
||
function nexus_json_encode($data)
|
||
{
|
||
return json_encode($data, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
|
||
}
|
||
|
||
function api(...$args)
|
||
{
|
||
if (func_num_args() < 3) {
|
||
//参数少于3个时,默认为错误状态。
|
||
$ret = -1;
|
||
$msg = isset($args[0]) ? $args[0] : 'ERROR';
|
||
$data = isset($args[1]) ? $args[1] : [];
|
||
} else {
|
||
$ret = $args[0];
|
||
$msg = $args[1];
|
||
$data = $args[2];
|
||
}
|
||
if ($data instanceof \Illuminate\Http\Resources\Json\ResourceCollection || $data instanceof \Illuminate\Http\Resources\Json\JsonResource) {
|
||
$data = $data->response()->getData(true);
|
||
if (isset($data['data']) && count($data) == 1) {
|
||
//单纯的集合,无分页等其数据
|
||
$data = $data['data'];
|
||
}
|
||
}
|
||
$time = (float)number_format(microtime(true) - nexus()->getStartTimestamp(), 3);
|
||
$count = null;
|
||
$resultKey = 'ret';
|
||
$msgKey = 'msg';
|
||
$format = $_REQUEST['__format'] ?? '';
|
||
if (in_array($format, ['layui-table', 'data-table'])) {
|
||
$resultKey = 'code';
|
||
$count = $data['meta']['total'] ?? 0;
|
||
if (isset($data['data'])) {
|
||
$data = $data['data'];
|
||
}
|
||
}
|
||
$results = [
|
||
$resultKey => (int)$ret,
|
||
$msgKey => (string)$msg,
|
||
'data' => $data,
|
||
'time' => $time,
|
||
'rid' => nexus()->getRequestId(),
|
||
];
|
||
if ($format == 'layui-table') {
|
||
$results['count'] = $count;
|
||
}
|
||
if ($format == 'data-table') {
|
||
$results['draw'] = intval($_REQUEST['draw'] ?? 1);
|
||
$results['recordsTotal'] = $count;
|
||
$results['recordsFiltered'] = $count;
|
||
}
|
||
|
||
return $results;
|
||
}
|
||
|
||
function success(...$args)
|
||
{
|
||
$ret = 0;
|
||
$msg = 'OK';
|
||
$data = [];
|
||
$argumentCount = func_num_args();
|
||
if ($argumentCount == 1) {
|
||
$data = $args[0];
|
||
} elseif ($argumentCount == 2) {
|
||
$msg = $args[0];
|
||
$data = $args[1];
|
||
}
|
||
return api($ret, $msg, $data);
|
||
}
|
||
|
||
function fail(...$args)
|
||
{
|
||
$ret = -1;
|
||
$msg = 'ERROR';
|
||
$data = [];
|
||
$argumentCount = func_num_args();
|
||
if ($argumentCount == 1) {
|
||
$data = $args[0];
|
||
} elseif ($argumentCount == 2) {
|
||
$msg = $args[0];
|
||
$data = $args[1];
|
||
}
|
||
return api($ret, $msg, $data);
|
||
}
|
||
|
||
function last_query($all = false)
|
||
{
|
||
static $connection, $pdo;
|
||
if (is_null($connection)) {
|
||
if (IN_NEXUS) {
|
||
$connection = \Illuminate\Database\Capsule\Manager::connection(\Nexus\Database\NexusDB::ELOQUENT_CONNECTION_NAME);
|
||
} else {
|
||
$connection = \Illuminate\Support\Facades\DB::connection(config('database.default'));
|
||
}
|
||
$pdo = $connection->getPdo();
|
||
}
|
||
$queries = $connection->getQueryLog();
|
||
if (!$all) {
|
||
$queries = [last($queries)];
|
||
}
|
||
$queryFormatted = [];
|
||
foreach ($queries as $query) {
|
||
$sqlWithPlaceholders = str_replace(['%', '?'], ['%%', '%s'], $query['query']);
|
||
$bindings = $query['bindings'];
|
||
$realSql = $sqlWithPlaceholders;
|
||
if (count($bindings) > 0) {
|
||
$realSql = vsprintf($sqlWithPlaceholders, array_map([$pdo, 'quote'], $bindings));
|
||
}
|
||
$queryFormatted[] = $realSql;
|
||
}
|
||
if ($all) {
|
||
return nexus_json_encode($queryFormatted);
|
||
}
|
||
return $queryFormatted[0];
|
||
}
|
||
|
||
function format_datetime($datetime, $format = 'Y-m-d H:i')
|
||
{
|
||
if (empty($datetime)) {
|
||
return '';
|
||
}
|
||
try {
|
||
$carbonTime = \Carbon\Carbon::parse($datetime);
|
||
return $carbonTime->format($format);
|
||
} catch (\Exception) {
|
||
do_log("Invalid datetime: $datetime", 'error');
|
||
return $datetime;
|
||
}
|
||
}
|
||
|
||
function nexus_trans($key, $replace = [], $locale = null)
|
||
{
|
||
return \Nexus\Nexus::trans($key, $replace, $locale);
|
||
}
|
||
|
||
function isRunningInConsole(): bool
|
||
{
|
||
return !RUNNING_IN_OCTANE && php_sapi_name() == 'cli';
|
||
}
|
||
|
||
function isRunningOnWindows(): bool
|
||
{
|
||
return !RUNNING_IN_OCTANE && strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
|
||
}
|
||
|
||
function command_exists($command): bool
|
||
{
|
||
return !(trim(exec("command -v $command")) == '');
|
||
}
|
||
|
||
function get_tracker_schema_and_host($combine = false): array|string
|
||
{
|
||
global $https_announce_urls, $announce_urls;
|
||
$httpsAnnounceUrls = array_filter($https_announce_urls);
|
||
$log = "cookie: " . json_encode($_COOKIE) . ", https_announce_urls: " . json_encode($httpsAnnounceUrls);
|
||
if (
|
||
(isset($_COOKIE["c_secure_tracker_ssl"]) && $_COOKIE["c_secure_tracker_ssl"] == base64("yeah"))
|
||
|| !empty($httpsAnnounceUrls)
|
||
|| isHttps()
|
||
) {
|
||
$log .= ", c_secure_tracker_ssl = base64('yeah'): " . base64("yeah") . ", or not empty https_announce_urls, or isHttps()";
|
||
$tracker_ssl = true;
|
||
} else {
|
||
$tracker_ssl = false;
|
||
}
|
||
$log .= ", tracker_ssl: $tracker_ssl";
|
||
|
||
if ($tracker_ssl == true){
|
||
$ssl_torrent = "https://";
|
||
if ($https_announce_urls[0] != "") {
|
||
$log .= ", https_announce_urls not empty, use it";
|
||
$base_announce_url = $https_announce_urls[0];
|
||
} else {
|
||
$log .= ", https_announce_urls empty, use announce_urls[0]";
|
||
$base_announce_url = $announce_urls[0];
|
||
}
|
||
} else {
|
||
$ssl_torrent = "http://";
|
||
$base_announce_url = $announce_urls[0];
|
||
}
|
||
do_log($log);
|
||
if ($combine) {
|
||
return $ssl_torrent . $base_announce_url;
|
||
}
|
||
return compact('ssl_torrent', 'base_announce_url');
|
||
}
|
||
|
||
|
||
function get_hr_ratio($uped, $downed)
|
||
{
|
||
if ($downed > 0) {
|
||
$ratio = $uped / $downed;
|
||
$color = get_ratio_color($ratio);
|
||
if ($ratio > 10000) $ratio = 'Inf.';
|
||
else
|
||
$ratio = number_format($ratio, 3);
|
||
|
||
if ($color)
|
||
$ratio = "<font color=\"" . $color . "\">" . $ratio . "</font>";
|
||
} elseif ($uped > 0)
|
||
$ratio = 'Inf.';
|
||
else
|
||
$ratio = "---";
|
||
|
||
return $ratio;
|
||
}
|
||
|
||
function get_row_count($table, $suffix = "")
|
||
{
|
||
$r = sql_query("SELECT COUNT(*) FROM $table $suffix") or sqlerr(__FILE__, __LINE__);
|
||
$a = mysql_fetch_row($r);
|
||
return $a[0];
|
||
}
|
||
|
||
function get_user_row($id)
|
||
{
|
||
global $Cache, $CURUSER;
|
||
static $userRows = [];
|
||
static $curuserRowUpdated = false;
|
||
static $neededColumns = array(
|
||
'id', 'noad', 'class', 'enabled', 'privacy', 'avatar', 'signature', 'uploaded', 'downloaded', 'last_access', 'username', 'donor',
|
||
'donoruntil', 'leechwarn', 'warned', 'title', 'downloadpos', 'parked', 'clientselect', 'showclienterror',
|
||
);
|
||
if (isset($userRows[$id])) return $userRows[$id];
|
||
$cacheKey = 'user_'.$id.'_content';
|
||
$row = \Nexus\Database\NexusDB::remember($cacheKey, 3600, function () use ($id, $neededColumns) {
|
||
$user = \App\Models\User::query()->with(['wearing_medals'])->find($id, $neededColumns);
|
||
if (!$user) {
|
||
return null;
|
||
}
|
||
$arr = $user->toArray();
|
||
//Rainbow ID
|
||
$userRep = new \App\Repositories\UserRepository();
|
||
$metas = $userRep->listMetas($id, \App\Models\UserMeta::META_KEY_PERSONALIZED_USERNAME);
|
||
if ($metas->isNotEmpty()) {
|
||
$arr['__is_rainbow'] = 1;
|
||
} else {
|
||
$arr['__is_rainbow'] = 0;
|
||
}
|
||
$arr['__is_donor'] = is_donor($arr);
|
||
return apply_filter("user_row", $arr);
|
||
});
|
||
|
||
// if ($CURUSER && $id == $CURUSER['id']) {
|
||
// $row = array();
|
||
// foreach($neededColumns as $column) {
|
||
// $row[$column] = $CURUSER[$column];
|
||
// }
|
||
// if (!$curuserRowUpdated) {
|
||
// $Cache->cache_value('user_'.$CURUSER['id'].'_content', $row, 900);
|
||
// $curuserRowUpdated = true;
|
||
// }
|
||
// } elseif (!$row = $Cache->get_value('user_'.$id.'_content')){
|
||
// $res = sql_query("SELECT ".implode(',', $neededColumns)." FROM users WHERE id = ".sqlesc($id)) or sqlerr(__FILE__,__LINE__);
|
||
// $row = mysql_fetch_array($res);
|
||
// $Cache->cache_value('user_'.$id.'_content', $row, 900);
|
||
// }
|
||
|
||
if (!$row)
|
||
return false;
|
||
else return $userRows[$id] = $row;
|
||
}
|
||
|
||
function get_user_class()
|
||
{
|
||
if (IN_NEXUS) {
|
||
global $CURUSER;
|
||
return $CURUSER["class"] ?? '';
|
||
}
|
||
return auth()->user()->class;
|
||
}
|
||
|
||
function get_user_id()
|
||
{
|
||
if (IN_NEXUS) {
|
||
global $CURUSER;
|
||
return $CURUSER["id"] ?? 0;
|
||
}
|
||
return auth()->user()->id ?? 0;
|
||
}
|
||
|
||
function get_pure_username()
|
||
{
|
||
if (IN_NEXUS) {
|
||
global $CURUSER;
|
||
return $CURUSER["username"] ?? "";
|
||
}
|
||
return auth()->user()->username ?? "";
|
||
}
|
||
|
||
function nexus()
|
||
{
|
||
return \Nexus\Nexus::instance();
|
||
}
|
||
|
||
function site_info()
|
||
{
|
||
$setting = \App\Models\Setting::get('basic');
|
||
$siteInfo = [
|
||
'site_name' => $setting['SITENAME'],
|
||
'base_url' => getSchemeAndHttpHost(),
|
||
];
|
||
return $siteInfo;
|
||
}
|
||
|
||
function isIPV4 ($ip)
|
||
{
|
||
return filter_var($ip,FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
|
||
}
|
||
|
||
function isIPV6 ($ip)
|
||
{
|
||
return filter_var($ip,FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
|
||
}
|
||
|
||
function add_filter($name, $function, $priority = 10, $argc = 1)
|
||
{
|
||
global $hook;
|
||
$hook->addFilter($name, $function, $priority, $argc);
|
||
}
|
||
|
||
function apply_filter($name, ...$args)
|
||
{
|
||
global $hook;
|
||
// do_log("[APPLY_FILTER]: $name");
|
||
return $hook->applyFilter(...func_get_args());
|
||
}
|
||
|
||
function add_action($name, $function, $priority = 10, $argc = 1)
|
||
{
|
||
global $hook;
|
||
$hook->addAction($name, $function, $priority, $argc);
|
||
}
|
||
|
||
function do_action($name, ...$args)
|
||
{
|
||
global $hook;
|
||
// do_log("[DO_ACTION]: $name");
|
||
return $hook->doAction(...func_get_args());
|
||
}
|
||
|
||
function isIPSeedBox($ip, $uid, $withoutCache = false): bool
|
||
{
|
||
$key = "nexus_is_ip_seed_box:ip:$ip:uid:$uid";
|
||
$cacheData = \Nexus\Database\NexusDB::cache_get($key);
|
||
if (in_array($cacheData, [0, 1, '0', '1'], true) && !$withoutCache) {
|
||
do_log("$key, get result from cache: $cacheData(" . gettype($cacheData) . ")");
|
||
return (bool)$cacheData;
|
||
}
|
||
$ipObject = \PhpIP\IP::create($ip);
|
||
$ipNumeric = $ipObject->numeric();
|
||
$ipVersion = $ipObject->getVersion();
|
||
//check allow list first, not consider specific user
|
||
$checkSeedBoxAllowedSql = sprintf(
|
||
'select id from seed_box_records where `ip_begin_numeric` <= "%s" and `ip_end_numeric` >= "%s" and `version` = %s and `status` = %s and `is_allowed` = 1 limit 1',
|
||
$ipNumeric, $ipNumeric, $ipVersion, \App\Models\SeedBoxRecord::STATUS_ALLOWED
|
||
);
|
||
$res = \Nexus\Database\NexusDB::select($checkSeedBoxAllowedSql);
|
||
if (!empty($res)) {
|
||
\Nexus\Database\NexusDB::cache_put($key, 1, 300);
|
||
do_log("$key, get result from database, is_allowed = 1, false");
|
||
return false;
|
||
}
|
||
$checkSeedBoxAdminSql = sprintf(
|
||
'select id from seed_box_records where `ip_begin_numeric` <= "%s" and `ip_end_numeric` >= "%s" and `type` = %s and `version` = %s and `status` = %s and `is_allowed` = 0 limit 1',
|
||
$ipNumeric, $ipNumeric, \App\Models\SeedBoxRecord::TYPE_ADMIN, $ipVersion, \App\Models\SeedBoxRecord::STATUS_ALLOWED
|
||
);
|
||
$res = \Nexus\Database\NexusDB::select($checkSeedBoxAdminSql);
|
||
if (!empty($res)) {
|
||
\Nexus\Database\NexusDB::cache_put($key, 1, 300);
|
||
do_log("$key, get result from admin, true");
|
||
return true;
|
||
}
|
||
if ($uid !== null) {
|
||
$checkSeedBoxUserSql = sprintf(
|
||
'select id from seed_box_records where `ip_begin_numeric` <= "%s" and `ip_end_numeric` >= "%s" and `uid` = %s and `type` = %s and `version` = %s and `status` = %s and `is_allowed` = 0 limit 1',
|
||
$ipNumeric, $ipNumeric, $uid, \App\Models\SeedBoxRecord::TYPE_USER, $ipVersion, \App\Models\SeedBoxRecord::STATUS_ALLOWED
|
||
);
|
||
$res = \Nexus\Database\NexusDB::select($checkSeedBoxUserSql);
|
||
if (!empty($res)) {
|
||
\Nexus\Database\NexusDB::cache_put($key, 1, 300);
|
||
do_log("$key, get result from user, true");
|
||
return true;
|
||
}
|
||
}
|
||
\Nexus\Database\NexusDB::cache_put($key, 0, 300);
|
||
do_log("$key, no result, false");
|
||
return false;
|
||
}
|
||
|
||
function getDataTraffic(array $torrent, array $queries, array $user, $peer, $snatch, $promotionInfo)
|
||
{
|
||
if (!isset($user['__is_donor'])) {
|
||
throw new \InvalidArgumentException("user no '__is_donor' field");
|
||
}
|
||
$log = sprintf(
|
||
"torrent: %s, owner: %s, user: %s, peerUploaded: %s, peerDownloaded: %s, queriesUploaded: %s, queriesDownloaded: %s",
|
||
$torrent['id'], $torrent['owner'], $user['id'], $peer['uploaded'] ?? '', $peer['downloaded'] ?? '', $queries['uploaded'], $queries['downloaded']
|
||
);
|
||
if (!empty($peer)) {
|
||
$realUploaded = max(bcsub($queries['uploaded'], $peer['uploaded']), 0);
|
||
$realDownloaded = max(bcsub($queries['downloaded'], $peer['downloaded']), 0);
|
||
$log .= ", [PEER_EXISTS], realUploaded: $realUploaded, realDownloaded: $realDownloaded, [SP_STATE]";
|
||
$spStateGlobal = get_global_sp_state();
|
||
$spStateNormal = \App\Models\Torrent::PROMOTION_NORMAL;
|
||
if (!empty($promotionInfo) && isset($promotionInfo['__ignore_global_sp_state'])) {
|
||
$log .= ', use promotionInfo';
|
||
$spStateReal = $promotionInfo['sp_state'];
|
||
} elseif ($spStateGlobal != $spStateNormal) {
|
||
$log .= ", use global";
|
||
$spStateReal = $spStateGlobal;
|
||
} else {
|
||
$log .= ", use torrent individual";
|
||
$spStateReal = $torrent['sp_state'];
|
||
}
|
||
if (!isset(\App\Models\Torrent::$promotionTypes[$spStateReal])) {
|
||
$log .= ", spStateReal = $spStateReal, invalid, reset to: $spStateNormal";
|
||
$spStateReal = $spStateNormal;
|
||
}
|
||
$uploaderRatio = get_setting('torrent.uploaderdouble');
|
||
$log .= ", uploaderRatio: $uploaderRatio";
|
||
if ($torrent['owner'] == $user['id']) {
|
||
//uploader, use the bigger one
|
||
$upRatio = max($uploaderRatio, \App\Models\Torrent::$promotionTypes[$spStateReal]['up_multiplier']);
|
||
$log .= ", [IS_UPLOADER], upRatio: $upRatio";
|
||
} else {
|
||
$upRatio = \App\Models\Torrent::$promotionTypes[$spStateReal]['up_multiplier'];
|
||
$log .= ", [IS_NOT_UPLOADER], upRatio: $upRatio";
|
||
}
|
||
/**
|
||
* VIP do not calculate downloaded
|
||
* @since 1.7.13
|
||
*/
|
||
if ($user['class'] == \App\Models\User::CLASS_VIP) {
|
||
$downRatio = 0;
|
||
$log .= ", [IS_VIP], downRatio: $downRatio";
|
||
} else {
|
||
$downRatio = \App\Models\Torrent::$promotionTypes[$spStateReal]['down_multiplier'];
|
||
$log .= ", [IS_NOT_VIP], downRatio: $downRatio";
|
||
}
|
||
} else {
|
||
$realUploaded = $queries['uploaded'];
|
||
$realDownloaded = $queries['downloaded'];
|
||
/**
|
||
* If peer not exits, user increment = 0;
|
||
*/
|
||
$upRatio = 0;
|
||
$downRatio = 0;
|
||
$log .= ", [PEER_NOT_EXISTS], realUploaded: $realUploaded, realDownloaded: $realDownloaded, upRatio: $upRatio, downRatio: $downRatio";
|
||
}
|
||
$uploadedIncrementForUser = $realUploaded * $upRatio;
|
||
$downloadedIncrementForUser = $realDownloaded * $downRatio;
|
||
$log .= ", uploadedIncrementForUser: $uploadedIncrementForUser, downloadedIncrementForUser: $downloadedIncrementForUser";
|
||
|
||
/**
|
||
* check seed box rule
|
||
*/
|
||
$isSeedBoxRuleEnabled = get_setting('seed_box.enabled') == 'yes';
|
||
$log .= ", isSeedBoxRuleEnabled: $isSeedBoxRuleEnabled, user class: {$user['class']}, __is_donor: {$user['__is_donor']}";
|
||
if ($isSeedBoxRuleEnabled && $torrent['owner'] != $user['id'] && !($user['class'] >= \App\Models\User::CLASS_VIP || $user['__is_donor'])) {
|
||
$isIPSeedBox = isIPSeedBox($queries['ip'], $user['id']);
|
||
$log .= ", isIPSeedBox: $isIPSeedBox";
|
||
if ($isIPSeedBox) {
|
||
$isSeedBoxNoPromotion = get_setting('seed_box.no_promotion') == 'yes';
|
||
$log .= ", isSeedBoxNoPromotion: $isSeedBoxNoPromotion";
|
||
if ($isSeedBoxNoPromotion) {
|
||
$uploadedIncrementForUser = $realUploaded;
|
||
$downloadedIncrementForUser = $realDownloaded;
|
||
$log .= ", isIPSeedBox && isSeedBoxNoPromotion, increment for user = real";
|
||
}
|
||
$maxUploadedTimes = get_setting('seed_box.max_uploaded');
|
||
$maxUploadedDurationSeconds = get_setting('seed_box.max_uploaded_duration', 0) * 3600;
|
||
$torrentTTL = time() - strtotime($torrent['added']);
|
||
$timeRangeValid = ($maxUploadedDurationSeconds == 0) || ($torrentTTL < $maxUploadedDurationSeconds);
|
||
$log .= ", maxUploadedTimes: $maxUploadedTimes, maxUploadedDurationSeconds: $maxUploadedDurationSeconds, timeRangeValid: $timeRangeValid";
|
||
if ($maxUploadedTimes > 0 && $timeRangeValid) {
|
||
$log .= ", [LIMIT_UPLOADED]";
|
||
if (!empty($snatch) && isset($torrent['size']) && $snatch['uploaded'] >= $torrent['size'] * $maxUploadedTimes) {
|
||
$log .= ", snatchUploaded({$snatch['uploaded']}) >= torrentSize({$torrent['size']}) * times($maxUploadedTimes), uploadedIncrementForUser = 0";
|
||
$uploadedIncrementForUser = 0;
|
||
} else {
|
||
$log .= ", snatchUploaded({$snatch['uploaded']}) < torrentSize({$torrent['size']}) * times($maxUploadedTimes), uploadedIncrementForUser do not change to 0";
|
||
}
|
||
} else {
|
||
$log .= ", [NOT_LIMIT_UPLOADED]";
|
||
}
|
||
}
|
||
}
|
||
|
||
$result = [
|
||
'uploaded_increment' => $realUploaded,
|
||
'uploaded_increment_for_user' => $uploadedIncrementForUser,
|
||
'downloaded_increment' => $realDownloaded,
|
||
'downloaded_increment_for_user' => $downloadedIncrementForUser,
|
||
];
|
||
do_log("$log, result: " . json_encode($result), 'info');
|
||
return $result;
|
||
}
|
||
|
||
function clear_user_cache($uid, $passkey = '')
|
||
{
|
||
do_log("clear_user_cache, uid: $uid, passkey: $passkey");
|
||
\Nexus\Database\NexusDB::cache_del("user_{$uid}_content");
|
||
\Nexus\Database\NexusDB::cache_del("user_{$uid}_roles");
|
||
\Nexus\Database\NexusDB::cache_del("announce_user_passkey_$uid");//announce.php
|
||
\Nexus\Database\NexusDB::cache_del(\App\Models\Setting::DIRECT_PERMISSION_CACHE_KEY_PREFIX . $uid);
|
||
\Nexus\Database\NexusDB::cache_del("user_role_ids:$uid");
|
||
\Nexus\Database\NexusDB::cache_del("direct_permissions:$uid");
|
||
if ($passkey) {
|
||
\Nexus\Database\NexusDB::cache_del('user_passkey_'.$passkey.'_content');//announce.php
|
||
}
|
||
}
|
||
|
||
function clear_setting_cache()
|
||
{
|
||
do_log("clear_setting_cache");
|
||
\Nexus\Database\NexusDB::cache_del('nexus_settings_in_laravel');
|
||
\Nexus\Database\NexusDB::cache_del('nexus_settings_in_nexus');
|
||
$channel = nexus_env("CHANNEL_NAME_SETTING");
|
||
if (!empty($channel)) {
|
||
\Nexus\Database\NexusDB::redis()->publish($channel, "update");
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @see functions.php::get_category_row(), genrelist()
|
||
*/
|
||
function clear_category_cache()
|
||
{
|
||
do_log("clear_category_cache");
|
||
\Nexus\Database\NexusDB::cache_del('category_content');
|
||
$searchBoxList = \App\Models\SearchBox::query()->get(['id']);
|
||
foreach ($searchBoxList as $item) {
|
||
\Nexus\Database\NexusDB::cache_del("category_list_mode_{$item->id}");
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* @see functions.php::searchbox_item_list()
|
||
*/
|
||
function clear_taxonomy_cache($table)
|
||
{
|
||
do_log("clear_taxonomy_cache: $table");
|
||
$list = \App\Models\SearchBox::query()->get(['id']);
|
||
foreach ($list as $item) {
|
||
\Nexus\Database\NexusDB::cache_del("{$table}_list_mode_{$item->id}");
|
||
}
|
||
\Nexus\Database\NexusDB::cache_del("{$table}_list_mode_0");
|
||
}
|
||
|
||
function clear_staff_message_cache()
|
||
{
|
||
do_log("clear_staff_message_cache");
|
||
\App\Repositories\MessageRepository::updateStaffMessageCountCache(false);
|
||
}
|
||
|
||
/**
|
||
* @see functions.php::get_searchbox_value()
|
||
*/
|
||
function clear_search_box_cache()
|
||
{
|
||
do_log("clear_search_box_cache");
|
||
\Nexus\Database\NexusDB::cache_del("search_box_content");
|
||
}
|
||
|
||
/**
|
||
* @see functions.php::get_category_icon_row()
|
||
*/
|
||
function clear_icon_cache()
|
||
{
|
||
do_log("clear_icon_cache");
|
||
\Nexus\Database\NexusDB::cache_del("category_icon_content");
|
||
}
|
||
|
||
function clear_inbox_count_cache($uid)
|
||
{
|
||
do_log("clear_inbox_count_cache");
|
||
foreach (\Illuminate\Support\Arr::wrap($uid) as $id) {
|
||
\Nexus\Database\NexusDB::cache_del('user_'.$id.'_inbox_count');
|
||
\Nexus\Database\NexusDB::cache_del('user_'.$id.'_unread_message_count');
|
||
}
|
||
}
|
||
|
||
function clear_agent_allow_deny_cache()
|
||
{
|
||
do_log("clear_agent_allow_deny_cache");
|
||
$allowCacheKey = nexus_env("CACHE_KEY_AGENT_ALLOW", "all_agent_allows");
|
||
$denyCacheKey = nexus_env("CACHE_KEY_AGENT_DENY", "all_agent_denies");
|
||
foreach (["", ":php", ":go"] as $suffix) {
|
||
\Nexus\Database\NexusDB::cache_del($allowCacheKey . $suffix);
|
||
\Nexus\Database\NexusDB::cache_del($denyCacheKey . $suffix);
|
||
}
|
||
}
|
||
|
||
|
||
function user_can($permission, $fail = false, $uid = 0): bool
|
||
{
|
||
$log = "permission: $permission, fail: $fail, user: $uid";
|
||
static $userCanCached = [];
|
||
static $sequence = 0;
|
||
if ($uid == 0) {
|
||
$uid = get_user_id();
|
||
$log .= ", set current uid: $uid";
|
||
}
|
||
if ($uid <= 0) {
|
||
if ($fail) {
|
||
goto FAIL;
|
||
}
|
||
do_log("$log, unauthenticated, false");
|
||
return false;
|
||
}
|
||
if (!$fail && isset($userCanCached[$permission][$uid])) {
|
||
return $userCanCached[$permission][$uid];
|
||
}
|
||
$userInfo = get_user_row($uid);
|
||
$class = $userInfo['class'];
|
||
$log .= ", userClass: $class";
|
||
if ($class == \App\Models\User::CLASS_STAFF_LEADER) {
|
||
do_log("$log, CLASS_STAFF_LEADER, true");
|
||
$userCanCached[$permission][$uid] = true;
|
||
return true;
|
||
}
|
||
$userAllPermissions = \App\Repositories\ToolRepository::listUserAllPermissions($uid);
|
||
$result = isset($userAllPermissions[$permission]);
|
||
if ($sequence == 0) {
|
||
$sequence++;
|
||
$log .= ", userAllPermissions: " . json_encode($userAllPermissions);
|
||
}
|
||
$log .= ", result: $result";
|
||
if (!$fail || $result) {
|
||
do_log($log);
|
||
$userCanCached[$permission][$uid] = $result;
|
||
return $result;
|
||
}
|
||
FAIL:
|
||
do_log("$log, [FAIL]");
|
||
if (IN_NEXUS && !IN_TRACKER) {
|
||
global $lang_functions;
|
||
$requireClass = get_setting("authority.$permission");
|
||
if (isset(\App\Models\User::$classes[$requireClass])) {
|
||
stderr($lang_functions['std_sorry'],$lang_functions['std_permission_denied_only'].get_user_class_name($requireClass,false,true,true).$lang_functions['std_or_above_can_view'],false);
|
||
} else {
|
||
stderr($lang_functions['std_error'], $lang_functions['std_permission_denied']);
|
||
}
|
||
}
|
||
throw new \App\Exceptions\InsufficientPermissionException();
|
||
}
|
||
|
||
|
||
|
||
function is_donor(array $userInfo): bool
|
||
{
|
||
return $userInfo['donor'] == 'yes' && ($userInfo['donoruntil'] === null || $userInfo['donoruntil'] == '0000-00-00 00:00:00' || $userInfo['donoruntil'] >= date('Y-m-d H:i:s'));
|
||
}
|
||
|
||
/**
|
||
* @param $authkey
|
||
* @return false|int|mixed|string|null
|
||
* @throws \App\Exceptions\NexusException
|
||
* @see download.php
|
||
*/
|
||
function get_passkey_by_authkey($authkey)
|
||
{
|
||
return \Nexus\Database\NexusDB::remember("authkey2passkey:$authkey", 3600*24, function () use ($authkey) {
|
||
$arr = explode('|', $authkey);
|
||
if (count($arr) != 3) {
|
||
throw new \InvalidArgumentException("Invalid authkey: $authkey, format error");
|
||
}
|
||
$uid = $arr[1];
|
||
$torrentRep = new \App\Repositories\TorrentRepository();
|
||
$decrypted = $torrentRep->checkTrackerReportAuthKey($authkey);
|
||
if (empty($decrypted)) {
|
||
throw new \InvalidArgumentException("Invalid authkey: $authkey");
|
||
}
|
||
$userInfo = \Nexus\Database\NexusDB::remember("announce_user_passkey_$uid", 3600, function () use ($uid) {
|
||
return \App\Models\User::query()->where('id', $uid)->first(['id', 'passkey']);
|
||
});
|
||
return $userInfo->passkey;
|
||
});
|
||
}
|
||
|
||
function executeCommand($command, $format = 'string', $artisan = false, $exception = true): string|array
|
||
{
|
||
$append = " 2>&1";
|
||
if (!str_ends_with($command, $append)) {
|
||
$command .= $append;
|
||
}
|
||
if ($artisan) {
|
||
$phpPath = nexus_env('PHP_PATH') ?: 'php';
|
||
$webRoot = rtrim(ROOT_PATH, '/');
|
||
$command = "$phpPath $webRoot/artisan $command";
|
||
}
|
||
do_log("command: $command");
|
||
$result = exec($command, $output, $result_code);
|
||
$outputString = implode("\n", $output);
|
||
$log = sprintf('result_code: %s, result: %s, output: %s', $result_code, $result, $outputString);
|
||
if ($result_code != 0) {
|
||
do_log($log, "error");
|
||
if ($exception) {
|
||
throw new \RuntimeException($outputString);
|
||
}
|
||
} else {
|
||
do_log($log);
|
||
}
|
||
return $format == 'string' ? $outputString : $output;
|
||
}
|
||
|
||
function has_role_work_seeding($uid)
|
||
{
|
||
$result = apply_filter('user_has_role_work_seeding', false, $uid);
|
||
do_log("uid: $uid, result: $result");
|
||
return $result;
|
||
}
|
||
|
||
function is_danger_url($url): bool
|
||
{
|
||
$dangerScriptsPattern = "/(logout|login|ajax|announce|scrape|adduser|modtask|take.*)\.php/i";
|
||
$match = preg_match($dangerScriptsPattern, $url);
|
||
if ($match > 0) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
function get_snatch_info($torrentId, $userId)
|
||
{
|
||
return mysql_fetch_assoc(sql_query(sprintf('select * from snatched where torrentid = %s and userid = %s order by id desc limit 1', $torrentId, $userId)));
|
||
}
|
||
|
||
function fire_event(string $name, \Illuminate\Database\Eloquent\Model $model, \Illuminate\Database\Eloquent\Model $oldModel = null): void
|
||
{
|
||
$idKey = \Illuminate\Support\Str::random();
|
||
$idKeyOld = "";
|
||
\Nexus\Database\NexusDB::cache_put($idKey, serialize($model));
|
||
if ($oldModel) {
|
||
$idKeyOld = \Illuminate\Support\Str::random();
|
||
\Nexus\Database\NexusDB::cache_put($idKeyOld, serialize($oldModel));
|
||
}
|
||
executeCommand("event:fire --name=$name --idKey=$idKey --idKeyOld=$idKeyOld", "string", true, false);
|
||
}
|