client = new Client(); $this->version = $this->getLocalVersions(); $clientsPath = BASE_PATH . '/config/clients.json'; if (! is_file($clientsPath)) { echo 'clients.json 不存在,脚本中止。' . PHP_EOL; exit(0); } $runningUser = posix_getpwuid(posix_geteuid())['name']; $fileOwner = get_current_user(); if ($runningUser !== $fileOwner) { echo '当前用户为 ' . $runningUser . ',与文件所有者 ' . $fileOwner . ' 不符,脚本中止。' . PHP_EOL; exit(0); } $clients = json_decode(file_get_contents($clientsPath), true); foreach ($clients['clients'] as $client) { $this->getSoft($client); } } /** * 下载远程文件 */ private function getSourceFile(string $fileName, string $savePath, string $url): bool { try { if (! file_exists($savePath)) { echo '目标文件夹 ' . $savePath . ' 不存在,下載失败。' . PHP_EOL; return false; } echo '- 开始下载 ' . $fileName . '...' . PHP_EOL; $request = $this->client->get($url); echo '- 下载 ' . $fileName . ' 成功,正在保存...' . PHP_EOL; $result = file_put_contents($savePath . $fileName, $request->getBody()->getContents()); if (! $result) { echo '- 保存 ' . $fileName . ' 至 ' . $savePath . ' 失败。' . PHP_EOL; } else { echo '- 保存 ' . $fileName . ' 至 ' . $savePath . ' 成功。' . PHP_EOL; } return true; } catch (GuzzleException $e) { echo '- 下载 ' . $fileName . ' 失败...' . PHP_EOL; echo $e->getMessage() . PHP_EOL; return false; } } /** * 获取 GitHub 常规 Release * * @throws GuzzleException */ private function getLatestReleaseTagName(string $repo): string { $url = 'https://api.github.com/repos/' . $repo . '/releases/latest' . ($_ENV['github_access_token'] !== '' ? '?access_token=' . $_ENV['github_access_token'] : ''); $request = $this->client->get($url); return json_decode( $request->getBody()->getContents(), true )['tag_name']; } /** * 获取 GitHub Pre-Release * * @throws GuzzleException */ private function getLatestPreReleaseTagName(string $repo): string { $url = 'https://api.github.com/repos/' . $repo . '/releases' . ($_ENV['github_access_token'] !== '' ? '?access_token=' . $_ENV['github_access_token'] : ''); $request = $this->client->get($url); $latest = json_decode( $request->getBody()->getContents(), true )[0]; return $latest['tag_name']; } /** * 获取本地软体版本库 * * @return array */ private function getLocalVersions(): array { $fileName = 'LocalClientVersion.json'; $filePath = BASE_PATH . '/storage/' . $fileName; if (! is_file($filePath)) { echo '本地软体版本库 LocalClientVersion.json 不存在,创建文件中...' . PHP_EOL; $result = file_put_contents( $filePath, json_encode( [ 'createTime' => time(), ] ) ); if (! $result) { echo 'LocalClientVersion.json 创建失败,脚本中止。' . PHP_EOL; exit(0); } } $fileContent = file_get_contents($filePath); if (! Tools::isJson($fileContent)) { echo 'LocalClientVersion.json 文件格式异常,脚本中止。' . PHP_EOL; exit(0); } return json_decode($fileContent, true); } /** * 储存本地软体版本库 * * @param array $versions */ private function setLocalVersions(array $versions): void { $fileName = 'LocalClientVersion.json'; $filePath = BASE_PATH . '/storage/' . $fileName; file_put_contents( $filePath, json_encode( $versions ) ); } private static function getNames($name, $taskName, $tagName): array|string { return str_replace( [ '%taskName%', '%tagName%', '%tagName1%', ], [ $taskName, $tagName, substr($tagName, 1), ], $name ); } /** * @param array $task * * @throws GuzzleException */ private function getSoft(array $task): void { $savePath = $this->basePath . $task['savePath']; echo '====== ' . $task['name'] . ' 开始 ======' . PHP_EOL; $tagName = match ($task['tagMethod']) { 'github_pre_release' => self::getLatestPreReleaseTagName($task['gitRepo']), default => self::getLatestReleaseTagName($task['gitRepo']), }; if (! isset($this->version[$task['name']])) { echo '- 本地不存在 ' . $task['name'] . ',检测到当前最新版本为 ' . $tagName . PHP_EOL; } else { if ($tagName === $this->version[$task['name']]) { echo '- 检测到当前 ' . $task['name'] . ' 最新版本与本地版本一致,跳过此任务。' . PHP_EOL; echo '====== ' . $task['name'] . ' 结束 ======' . PHP_EOL; return; } echo '- 检测到当前 ' . $task['name'] . ' 最新版本为 ' . $tagName . ',本地最新版本为 ' . $this->version[$task['name']] . PHP_EOL; } $this->version[$task['name']] = $tagName; foreach ($task['downloads'] as $download) { $fileName = $download['saveName'] !== '' ? $download['saveName'] : $download['sourceName']; $fileName = self::getNames($fileName, $task['name'], $tagName); $sourceName = self::getNames($download['sourceName'], $task['name'], $tagName); $filePath = $savePath . $fileName; echo '- 正在删除旧版本文件...' . PHP_EOL; if (file_exists($filePath) && ! unlink($filePath)) { echo '- 删除旧版本文件失败,此任务跳过,请检查权限' . PHP_EOL; continue; } $downloadUrl = 'https://github.com/' . $task['gitRepo'] . '/releases/download/' . $tagName . '/' . $sourceName; if ($this->getSourceFile($fileName, $savePath, $downloadUrl)) { $this->setLocalVersions($this->version); } if ($_ENV['enable_r2_client_download']) { Cloudflare::uploadR2($fileName, file_get_contents($filePath)); unlink($filePath); } } echo '====== ' . $task['name'] . ' 结束 ======' . PHP_EOL; } }