{$key}: {$temp}
"; 243 | if ($num < (count($item) - 1)) echo ""; 244 | $num++; 245 | } 246 | 247 | 248 | echo '
├── .gitignore ├── LICENSE ├── README.md ├── app.css ├── config.example.php └── update.php /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .idea/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 LoliLin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # UpTime-Page 3 | 4 | UpTimeRobot 平台的又一款新皮肤 (误 5 | 6 | 样式来源于 [giuem/uptimerobot-page](https://github.com/giuem/uptimerobot-page) 7 | 8 | ## 使用方法 9 | 上传 ```config.php``` ```update.php``` 与 ```app.css``` 至服务器, 更改```config.php```的信息即可 10 | 11 | 本项目依靠 UpTimeRobot 进行缓存刷新, 请设置监控URL为 ```https://xx.xx/update.php``` 12 | 13 | + 请确保对文件同级目录有读取与写入权限 14 | 15 | ## Demo 16 | 17 | https://xll.li 18 | 19 |  20 | -------------------------------------------------------------------------------- /app.css: -------------------------------------------------------------------------------- 1 | /*!normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css*/html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}:root{--color-base:#2d2d55;--color-grey:#eef2f6;--color-up:#6ac259;--color-seem-down:#ffdd57;--color-down:#f05228;--color-pause:#111}html{font-size:16px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,SimSun,sans-serif}body{background:#eef2f6;background:var(--color-grey)}#app{min-height:100vh;padding:0 2em;color:#2d2d55;color:var(--color-base);display:flex;flex-flow:column}.container{margin:0 auto;max-width:600px}.content{flex:1}.card{box-shadow:0 15px 35px rgba(50,50,93,.07),0 5px 15px rgba(0,0,0,.07);padding:1.5em;background:#fff}.icon{height:1em;width:1em;display:block;background-repeat:no-repeat}.icon-status-sum{height:2em;width:2em;margin-right:1em}.icon-status-sum.up{background-image:url(data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA0MjYuNjY3IDQyNi42NjcnPjxwYXRoIGQ9J00yMTMuMzMzIDBDOTUuNTE4IDAgMCA5NS41MTQgMCAyMTMuMzMzczk1LjUxOCAyMTMuMzMzIDIxMy4zMzMgMjEzLjMzM2MxMTcuODI4IDAgMjEzLjMzMy05NS41MTQgMjEzLjMzMy0yMTMuMzMzUzMzMS4xNTcgMCAyMTMuMzMzIDB6bS0zOS4xMzQgMzIyLjkxOGwtOTMuOTM1LTkzLjkzMSAzMS4zMDktMzEuMzA5IDYyLjYyNiA2Mi42MjIgMTQwLjg5NC0xNDAuODk4IDMxLjMwOSAzMS4zMDktMTcyLjIwMyAxNzIuMjA3eicgZmlsbD0nIzZhYzI1OScvPjwvc3ZnPg==)}.icon-status-sum.down{background-image:url(data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA0MjYuNjY3IDQyNi42NjcnPjxwYXRoIGQ9J00yMTMuMzMzIDBDOTUuNTE0IDAgMCA5NS41MTQgMCAyMTMuMzMzczk1LjUxNCAyMTMuMzMzIDIxMy4zMzMgMjEzLjMzMyAyMTMuMzMzLTk1LjUxNCAyMTMuMzMzLTIxMy4zMzNTMzMxLjE1MyAwIDIxMy4zMzMgMHptMTE3LjY2MiAyNzYuNjg5bC01NC4zMDIgNTQuMzA2LTYzLjM2LTYzLjM1Ni02My4zNiA2My4zNi01NC4zMDItNTQuMzEgNjMuMzU2LTYzLjM1Ni02My4zNTYtNjMuMzYgNTQuMzAyLTU0LjMwMiA2My4zNiA2My4zNTYgNjMuMzYtNjMuMzU2IDU0LjMwMiA1NC4zMDItNjMuMzU2IDYzLjM2IDYzLjM1NiA2My4zNTZ6JyBmaWxsPScjZjA1MjI4Jy8+PC9zdmc+)}.icon-status{border-radius:100%;box-shadow:0 0 10px 1px rgba(0,0,0,.1)}.icon-uptime{height:2em;width:100%;cursor:pointer;border-left:1px solid #fff;border-right:1px solid #fff;opacity:.75}.icon-status.pause,.icon-uptime.pause{background:#111;background:var(--color-pause)}.icon-status.up,.icon-uptime.up{background:#6ac259;background:var(--color-up)}.icon-status.seem-down,.icon-uptime.seem-down{background:#ffdd57;background:var(--color-seem-down)}.icon-status.down,.icon-uptime.down{background:#f05228;background:var(--color-down)}.header{margin-bottom:3em}.header-title{margin:0;font-size:1.5em;font-weight:400;line-height:5}.summary{display:flex;align-items:center}.summary-detail{font-size:1.3em}.summary-checktime{font-size:.8em;color:#898989}.monitors{margin:0;padding:0;transition:margin .2s cubic-bezier(.4,0,.2,1)}.monitors.open{margin:1.5em 0}.monitors-header{line-height:2;display:flex;justify-content:space-between;align-items:center;padding:.75em 1.5em;border-bottom:1px solid #eaeaea;transition:background-color .15s}.monitors-header:hover{background:#eef2f6;background:var(--color-grey)}.has-children .monitors-header{cursor:pointer}.monitors-header .icon{transition:opacity .1s}.open .monitors-header .icon{opacity:0}.monitors-header-title{font-weight:700}.monitors-content-wrap{max-height:0;overflow:hidden;transition:max-height .3s ease-out;transform:translateZ(0)}.open .monitors-content-wrap{will-change:height}.open .monitors-content{will-change:contents}.monitor{padding:.75em 1.5em;border-top:1px solid #ddd}.monitor-header{display:flex;justify-content:space-between;align-items:center}.monitor-content{margin-top:1em}.monitor-uptime-range{font-size:.8em;opacity:.8;letter-spacing:-1px;margin-bottom:.8em}.monitor-uptimes{display:flex}.footer{margin:2em 0}.footer-content{font-size:.8em;display:flex;align-items:center;justify-content:space-between;padding:0 1em}.copyright,.links a{color:#888}.links a{text-decoration:none;padding:.4em .6em;margin-right:1em}.links a:hover{color:#666} -------------------------------------------------------------------------------- /config.example.php: -------------------------------------------------------------------------------- 1 | 'https://cgl.li', 16 | 'Blog' => 'https://xiaolin.in', 17 | 'Status' => 'https://xll.li', 18 | ]); 19 | define('COPYRIGHT',"XiaoLin"); -------------------------------------------------------------------------------- /update.php: -------------------------------------------------------------------------------- 1 | "https://api.uptimerobot.com/v2/getMonitors", 22 | CURLOPT_RETURNTRANSFER => true, 23 | CURLOPT_ENCODING => "", 24 | CURLOPT_MAXREDIRS => 10, 25 | CURLOPT_TIMEOUT => 30, 26 | CURLOPT_SSL_VERIFYPEER => 0, 27 | CURLOPT_SSL_VERIFYHOST => 0, 28 | CURLOPT_CUSTOMREQUEST => "POST", 29 | CURLOPT_POSTFIELDS => "api_key=" . urlencode(UPTIMEROBOT_API_KEY) . "&format=json&custom_uptime_ranges=" . strtotime('today') . '_' . time() . "&all_time_uptime_ratio=1&custom_uptime_ratios=" . urlencode(substr($times,0,-1)), 30 | CURLOPT_HTTPHEADER => array( 31 | "cache-control: no-cache", 32 | "content-type: application/x-www-form-urlencoded" 33 | ), 34 | )); 35 | 36 | $response = json_decode(curl_exec($curl),true); 37 | $count = 0; 38 | 39 | while((curl_error($curl) != "" || !is_array($response) || $response['stat'] != 'ok') && ($count < 3)) 40 | { 41 | error_log(curl_error($curl)); 42 | sleep(3); 43 | $response = json_decode(curl_exec($curl),true); 44 | $count++; 45 | } 46 | unset($count); 47 | 48 | if (!is_array($response) || $response['stat'] != 'ok') 49 | { 50 | header("HTTP/1.1 500 Internal Server Error"); 51 | die; 52 | } 53 | curl_close($curl); 54 | 55 | $list = []; 56 | foreach ($response['monitors'] as $value) 57 | { 58 | $tmp = explode('/',$value['friendly_name']); 59 | if (count($tmp) != 3) continue; 60 | $ratios = explode('-',$value['custom_uptime_ratio']); 61 | $ratios[] = $value['custom_uptime_ranges']; 62 | if (isset($list[$tmp[2]])) $list[$tmp[2]]['items'][] = [ 63 | 'name' => $tmp[0], 64 | 'status' => ($value['status'] == 2) ? "Up" : (($value['status'] == 0) ? "Pause" : (($value['status'] == 1) ? "Not checked yet" : "Down")), 65 | 'ratios' => $ratios, 66 | 'all_ratio' => $value['all_time_uptime_ratio'], 67 | 'type' => 'uptime', 68 | ]; 69 | 70 | if (!isset($list[$tmp[2]])) $list[$tmp[2]] = [ 71 | 'name' => $tmp[1], 72 | 'items' => [ 73 | [ 74 | 'name' => $tmp[0], 75 | 'status' => ($value['status'] == 2) ? "Up" : (($value['status'] == 0) ? "Pause" : (($value['status'] == 1) ? "Not checked yet" : "Down")), 76 | 'ratios' => $ratios, 77 | 'all_ratio' => $value['all_time_uptime_ratio'], 78 | 'type' => 'uptime', 79 | ], 80 | ], 81 | ]; 82 | } 83 | 84 | if (SSL_CHECKER) 85 | { 86 | $ssl = json_decode(file_get_contents(SSL_CHECKER_DATA),true); 87 | 88 | $sslStatus = &$list[]; 89 | $sslStatus['name'] = "SSL Certificates"; 90 | 91 | foreach ($ssl as $item) 92 | { 93 | $sslStatus['items'][] = [ 94 | 'name' => strtoupper($item['domain']), 95 | 'status' => ($item['isValid']) ? "Up" : "Down", 96 | 'Is valid' => ($item['isValid']) ? "Yes" : 'False', 97 | 'issuer' => $item['issuer'], 98 | 'Signature algorithm' => $item['signatureAlgorithm'], 99 | 'Additional domains' => $item['additionalDomains'], 100 | 'Expiration date' => date('Y-m-d',$item['expirationDate']), 101 | 'Fingerprint' => $item['fingerprint'], 102 | 'type' => 'ssl' 103 | ]; 104 | } 105 | } 106 | 107 | unset($tmp,$data,$item,$i,$sslStatus,$ssl,$temp,$count,$key); 108 | 109 | date_default_timezone_set('Asia/Shanghai'); 110 | 111 | ob_start(); 112 | ?> 113 | 114 | 115 | 116 |
117 | 118 | 119 |{$key}: {$temp}
"; 243 | if ($num < (count($item) - 1)) echo "