Upgrade.php 6.5 KB

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