diff --git a/README.md b/README.md new file mode 100644 index 0000000..8221067 --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +
+ English + 简体中文 +
+ +# ✔[UptimeFlare](https://github.com/lyc8503/UptimeFlare) + +A more advanced, serverless, and free uptime monitoring & status page solution, powered by Cloudflare Workers, complete with a user-friendly interface. + +## ⭐Features +- Open-source, easy to deploy (in under 10 minutes, no local tools required), and free +- Monitoring capabilities + - Up to 50 checks at 1-minute intervals + - Geo-specific checks from over [310 cities](https://www.cloudflare.com/network/) worldwide + - Support for HTTP/HTTPS/TCP port monitoring + - Up to 90-day uptime history and uptime percentage tracking + - Customizable request methods, headers, and body for HTTP(s) + - Custom status code & keyword checks for HTTP(s) + - Downtime notification supporting [100+ notification channels](https://github.com/caronc/apprise/wiki) + - Customizable Webhook +- Status page + - Interactive ping (response time) chart for all types of monitors + - Responsive UI that adapts to your system theme + - Customizable status page + - Use your own domain with CNAME + - Optional password authentication (private status page) + - JSON API for fetching realtime status data + +## 👀Demo + +My status page (Online demo): https://uptimeflare.pages.dev/ + +Some screenshots: + +![Desktop, Light theme](docs/desktop.png) + +## ⚡Quickstart / 📄Documentation + +Please refer to [Wiki](https://github.com/lyc8503/UptimeFlare/wiki) + +## New features (TODOs) + +- [x] Specify region for monitors +- [x] TCP `opened` promise +- [x] Use apprise to support various notification channels +- [x] ~~Telegram example~~ +- [x] ~~[Bark](https://bark.day.app) example~~ +- [x] ~~Email notification via Cloudflare Email Workers~~ +- [x] Improve docs by providing simple examples +- [x] Notification grace period +- [ ] SSL certificate checks +- [ ] Self-host Dockerfile +- [ ] Incident timeline +- [ ] Improve `checkLocationWorkerRoute` and fix possible `proxy failed` +- [ ] Groups +- [x] Remove old incidents diff --git a/README_zh-CN.md b/README_zh-CN.md new file mode 100644 index 0000000..3e867de --- /dev/null +++ b/README_zh-CN.md @@ -0,0 +1,39 @@ +
+ English + 简体中文 +
+ +# ✔[UptimeFlare](https://github.com/lyc8503/UptimeFlare) + +一个由 Cloudflare Workers 驱动的功能丰富、Serverless 且免费的 Uptime 监控及状态页面。 + +## ⭐功能 +- 开源,易于部署(全程无需本地工具,耗时不到 10 分钟),且完全免费 +- 监控功能 + - 最多支持 50 个 1 分钟精度的检查 + - 支持指定全球 [310+ 个城市](https://www.cloudflare.com/network/) 的监控节点 + - 支持 HTTP/HTTPS/TCP 端口监控 + - 最多 90 天的 uptime 历史记录和 uptime 百分比跟踪 + - 可自定义的 HTTP(s) 请求方法、头和主体 + - 可自定义的 HTTP(s) 状态码和关键字检查 + - 支持 [100 多个通知渠道](https://github.com/caronc/apprise/wiki) 的宕机消息通知 + - 可自定义的 Webhook +- 状态页面 + - 所有类型监控的交互式 ping(响应时间)图表 + - 响应式 UI,自适应PC/手机屏幕,及亮色/暗色系统主题 + - 配置选项丰富的状态页面 + - 可使用您自己的域名与 CNAME + - 可选的密码认证(私人状态页面) + - 用于获取实时状态数据的 JSON API + +## 👀演示 + +我自己的状态页面(在线演示):https://uptimeflare.pages.dev/ + +一些截图: + +![桌面,浅色主题](docs/desktop.png) + +## ⚡快速入门 / 📄文档 + +请参阅 [Wiki](https://github.com/lyc8503/UptimeFlare/wiki) diff --git a/components/DetailBar.tsx b/components/DetailBar.tsx index bd3ce78..8a228d0 100644 --- a/components/DetailBar.tsx +++ b/components/DetailBar.tsx @@ -47,12 +47,13 @@ export default function DetailBar({ -
{dayPercent + '%'}
+
{dayPercent + '% at ' + new Date(dayStart * 1000).toLocaleDateString()}
{dayDownTime > 0 && (
{`Down for ${moment.preciseDiff(moment(0), moment(dayDownTime * 1000))}`}
)} diff --git a/components/MonitorDetail.tsx b/components/MonitorDetail.tsx index 9918c23..574badd 100644 --- a/components/MonitorDetail.tsx +++ b/components/MonitorDetail.tsx @@ -43,7 +43,7 @@ export default function MonitorDetail({ const monitorNameElement = ( {monitor.statusPageLink ? ( - + {statusIcon} {monitor.name} ) : ( diff --git a/middleware.ts b/middleware.ts new file mode 100644 index 0000000..78ec4d8 --- /dev/null +++ b/middleware.ts @@ -0,0 +1,27 @@ +import { NextResponse } from 'next/server' +import type { NextRequest } from 'next/server' +import { workerConfig } from './uptime.config' + +export async function middleware(request: NextRequest) { + // @ts-ignore + const passwordProtection = workerConfig.passwordProtection + if (passwordProtection) { + const authHeader = request.headers.get('Authorization') + let authenticated = false + const expected = 'Basic ' + btoa(passwordProtection) + + if (authHeader && authHeader.length === expected.length) { + // a simple timing-safe compare + authenticated = true; + for (let i = 0; i < authHeader.length; i++) { + if (authHeader[i] !== expected[i]) authenticated = false; + } + } + + if (!authenticated) { + return NextResponse.json( + { code: 401, message: "Not authenticated" }, { status: 401, headers: { 'WWW-Authenticate': 'Basic' } } + ) + } + } +}