Upgrade.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. <?php
  2. /**
  3. * 升级
  4. *
  5. * @author mybsdc <[email protected]>
  6. * @date 2021/11/5
  7. * @time 10:52
  8. */
  9. namespace Luolongfei\App\Console;
  10. use GuzzleHttp\Client;
  11. use Luolongfei\Libs\Log;
  12. use Luolongfei\Libs\Message;
  13. class Upgrade extends Base
  14. {
  15. const TIMEOUT = 33;
  16. /**
  17. * @var Upgrade
  18. */
  19. private static $instance;
  20. /**
  21. * @var array 与发布相关的信息
  22. */
  23. public $releaseInfo = [];
  24. /**
  25. * @var string 最新版本号
  26. */
  27. public $latestVer;
  28. /**
  29. * @var string 当前版本号
  30. */
  31. public $currVer;
  32. /**
  33. * @var string 记录已推送版本的文件
  34. */
  35. public $pushedVerFile;
  36. /**
  37. * @var Client
  38. */
  39. protected $client;
  40. /**
  41. * @return Upgrade
  42. */
  43. public static function getInstance()
  44. {
  45. if (!self::$instance instanceof self) {
  46. self::$instance = new self();
  47. }
  48. return self::$instance;
  49. }
  50. private function __construct()
  51. {
  52. $this->pushedVerFile = DATA_PATH . DS . 'pushed_version.txt';
  53. $this->client = new Client([
  54. 'base_uri' => 'https://api.github.com',
  55. 'headers' => [
  56. 'Accept' => 'application/vnd.github.v3+json'
  57. ],
  58. 'cookies' => false,
  59. 'timeout' => self::TIMEOUT,
  60. 'verify' => config('verify_ssl'),
  61. 'debug' => config('debug'),
  62. ]);
  63. }
  64. private function __clone()
  65. {
  66. }
  67. /**
  68. * 是否需要升级
  69. *
  70. * @return bool
  71. */
  72. public function needToUpgrade()
  73. {
  74. try {
  75. $resp = $this->client->get('/repos/luolongfei/freenom/releases/latest', [
  76. 'timeout' => 5,
  77. ]);
  78. $resp = $resp->getBody()->getContents();
  79. $resp = (array)json_decode($resp, true);
  80. if (!isset($resp['tag_name'])
  81. || !isset($resp['body'])
  82. || !isset($resp['name'])
  83. || !isset($resp['published_at'])
  84. || !isset($resp['html_url'])) {
  85. throw new \Exception(lang('100023') . json_encode($resp, JSON_UNESCAPED_UNICODE));
  86. }
  87. $this->releaseInfo = $resp;
  88. $this->latestVer = $this->getVerNum($resp['tag_name']);
  89. $this->currVer = $this->getVerNum(FreeNom::VERSION);
  90. return version_compare($this->latestVer, $this->currVer, '>');
  91. } catch (\Exception $e) {
  92. Log::error(lang('100024') . $e->getMessage());
  93. return false;
  94. }
  95. }
  96. /**
  97. * 此版本是否已推送过
  98. *
  99. * @param $ver
  100. *
  101. * @return bool
  102. */
  103. public function isPushed($ver)
  104. {
  105. if (!file_exists($this->pushedVerFile)) {
  106. return false;
  107. }
  108. $pushedVerFile = file_get_contents($this->pushedVerFile);
  109. return stripos($pushedVerFile, $ver) !== false;
  110. }
  111. /**
  112. * 记住版本号
  113. *
  114. * @param $ver
  115. *
  116. * @return bool
  117. */
  118. public function rememberVer($ver)
  119. {
  120. return (bool)file_put_contents($this->pushedVerFile, $ver . "\n", FILE_APPEND);
  121. }
  122. /**
  123. * 生成升级送信内容
  124. *
  125. * @return string
  126. */
  127. public function genMsgContent()
  128. {
  129. if (is_chinese()) {
  130. $content = sprintf(
  131. lang('100025'),
  132. $this->friendlyDateFormat($this->releaseInfo['published_at'], 'UTC'),
  133. $this->latestVer,
  134. $this->currVer
  135. );
  136. } else {
  137. $content = sprintf(
  138. lang('100025'),
  139. $this->friendlyDateFormat($this->releaseInfo['published_at'], 'UTC'),
  140. $this->latestVer,
  141. $this->currVer
  142. );
  143. }
  144. $content .= $this->releaseInfo['body'];
  145. $content .= "\n\n" . lang('100026') . $this->releaseInfo['html_url'];
  146. $content .= "\n\n" . lang('100027');
  147. return $content;
  148. }
  149. /**
  150. * 人类友好时间
  151. *
  152. * @param string $date 传入时间
  153. * @param null|string $timezone 传入时间的时区
  154. *
  155. * @return string
  156. */
  157. public function friendlyDateFormat($date, $timezone = null)
  158. {
  159. try {
  160. $d = (new \DateTime($date, $timezone ? new \DateTimeZone($timezone) : null))->setTimezone(new \DateTimeZone('Asia/Shanghai'));
  161. $time = $d->getTimestamp();
  162. $diff = time() - $time;
  163. if ($diff < 86400) {
  164. if ($d->format('d') === date('d')) {
  165. return $diff < 60 ? lang('100028') : ($diff < 3600 ? floor($diff / 60) . lang('100029') : floor($diff / 3600) . lang('100030'));
  166. } else {
  167. return lang('100031') . $d->format('H:i');
  168. }
  169. } else {
  170. return $d->format($d->format('Y') === date('Y') ? 'Y-m-d H:i' : 'Y-m-d');
  171. }
  172. } catch (\Exception $e) {
  173. Log::error(lang('100032') . $e->getMessage());
  174. return $date;
  175. }
  176. }
  177. /**
  178. * @return bool
  179. */
  180. public function handle()
  181. {
  182. try {
  183. // 检查 Data 目录写权限
  184. if (!is_writable(DATA_PATH)) {
  185. system_log(lang('100135'));
  186. return true;
  187. }
  188. if (!$this->needToUpgrade()) {
  189. return true;
  190. }
  191. if ($this->isPushed($this->latestVer)) {
  192. return true;
  193. }
  194. if (IS_SCF) {
  195. system_log(sprintf(
  196. lang('100033'),
  197. $this->currVer,
  198. $this->latestVer,
  199. $this->releaseInfo['html_url']
  200. ));
  201. } else {
  202. system_log(sprintf(
  203. lang('100034'),
  204. $this->latestVer,
  205. $this->releaseInfo['html_url']
  206. ));
  207. $result = Message::send(
  208. $this->genMsgContent(),
  209. sprintf(lang('100035'), $this->latestVer),
  210. 4,
  211. $this->releaseInfo
  212. );
  213. if ($result) {
  214. $this->rememberVer($this->latestVer);
  215. system_log(lang('100036'));
  216. }
  217. }
  218. return true;
  219. } catch (\Exception $e) {
  220. system_log(lang('100037') . $e->getMessage());
  221. return false;
  222. }
  223. }
  224. public function doUpgrade()
  225. {
  226. // TODO 自动升级
  227. // system_log('<green>恭喜,已完成升级。</green>');
  228. }
  229. }