fix: delete extra file

This commit is contained in:
mei
2026-04-05 10:38:19 +08:00
parent 6190a8853a
commit 202f53915f
4 changed files with 6 additions and 470 deletions
+6 -78
View File
@@ -1,4 +1,4 @@
# goodBaby
# goodBaby v2
摇篮系统
@@ -6,82 +6,10 @@
## 他会做什么
1. 接受 singnal 请求
2. 当定时器超时(过长时间没有收到请求)时,触发 `trigger` 函数
3. 发送消息到QQ(依赖[CatBot](https://github.com/ssdomei232/CatBot))
4. 发送邮件
5. 将 Github 上的遗言仓库设置为 public
6. 发送一条 Bilibili 动态
7. 当倒计时小于48小时时,向用钉钉机器人发消息提醒你
船新版本正在开发...
## 配置
将支持:
> [!TIP]
> 更详细的配置注解请前往 [Wiki 页面](https://github.com/ssdomei232/goodBaby/wiki)
参照 config.example.json 修改 config.json
```json
{
"signal_secret": "xxx", // 发送 signal请求时需要的密钥
"debug": false, // debug 模式
"disconnect_duration": 80, // 失连时间,超出后会触发系统(小时)
"bili_msg": "摇篮系统测试", // 哔哩哔哩动态的附加消息
"mail_config": {
"host": "smtp.example.com",
"port": 465,
"user": "xxx",
"pass": "xxx",
"mail_list": ["xxx@example.com", "xxx1@example.com"],// 要发送的邮箱
"mail_title": "摇篮系统已触发", // 邮件标题
"mail_content": "这是摇篮系统的邮件内容。" // 要附加的邮件内容
}, // 邮件配置
"basic": {
"name": "xx", // 你的名字
"qq_number": "123", // 你的QQ号
"nickname": "xx_123", // 网名
"age": 16, // 你的年龄
"cause_stop": "自杀" // 你最可能的死因
},
"github_config": {
"owner": "example", // github用户名
"repos": ["example-repo1", "example-repo2"], // 要公开的 github 仓库
"token": "ghp_xxxx" // github token
},
"dingtalk_bot": {
"access_token": "xxx",
"secret": "xxx"
}, // 钉钉机器人(用于提醒发送signal和bilibili过期提醒)
"onebot_config": {
"url": "http://localhost:5700",
"token": "xxx",
"send_groups": [12345678, 87654321], // 要发送到的Onebot群组
"msg": "这是OneBot的消息内容。" // Onebot消息
}
}
```
## 运行
```bash
mkdir goodbaby
cd goodbaby
wget https://raw.githubusercontent.com/ssdomei232/goodBaby/refs/heads/main/docker-compose.yml
docker compose up -d
docker logs goodbaby ## 扫码登陆后才能使用
```
在日志中找到 Bilibili 的登陆二维码或在文件管理中找到`tmp/qrcode.png`,打开Bilibili APP 扫码登陆
> [!NOTE]
> 只有在登陆 Bilibili 后程序才会正常运行
## 使用
访问你开放的端口(默认为8088),进入WebUI,输入你的密钥,点击保存(密钥会存储到浏览器的localStorage中),此时你可以在WebUI查看倒计时和发送Signal
## Todo list
- [ ] 熔断机制
- [ ] Webhook 自定义请求
- [ ] 保存定时器状态
* WebUI
* 更多通知渠道
* 更灵活的设置
-200
View File
@@ -1,200 +0,0 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
background-color: #f8fafc;
color: #334155;
min-height: 100vh;
padding: 20px;
line-height: 1.6;
}
.container {
max-width: 640px;
margin: 0 auto;
background: white;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
overflow: hidden;
}
header {
text-align: center;
background: #f1f5f9;
padding: 32px 24px;
border-bottom: 1px solid #e2e8f0;
}
header h1 {
font-size: 1.875rem;
font-weight: 600;
color: #1e293b;
letter-spacing: -0.025em;
}
.card {
padding: 32px;
border-bottom: 1px solid #e2e8f0;
}
.card:last-child {
border-bottom: none;
}
.card h2 {
color: #1e293b;
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 24px;
display: flex;
align-items: center;
gap: 10px;
}
.form-group {
display: flex;
flex-direction: column;
gap: 16px;
}
.form-group label {
font-weight: 500;
color: #334155;
font-size: 0.875rem;
}
.form-group input {
padding: 12px 16px;
border: 1px solid #cbd5e1;
border-radius: 6px;
font-size: 1rem;
transition: border-color 0.2s, box-shadow 0.2s;
background: #f8fafc;
}
.form-group input:focus {
outline: none;
border-color: #94a3b8;
box-shadow: 0 0 0 3px rgba(148, 163, 184, 0.1);
}
.status-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.timer-display {
font-size: 2rem;
font-weight: 600;
color: #1e293b;
font-family: monospace;
}
.progress-bar {
width: 100%;
height: 8px;
background: #e2e8f0;
border-radius: 4px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: #3b82f6;
width: 0%;
transition: width 0.3s ease;
}
.controls {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
.btn-primary, .btn-secondary, .btn-danger {
padding: 12px 24px;
border: none;
border-radius: 6px;
font-size: 0.95rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
text-align: center;
}
.btn-primary {
background: #3b82f6;
color: white;
}
.btn-primary:hover {
background: #2563eb;
}
.btn-secondary {
background: #64748b;
color: white;
}
.btn-secondary:hover {
background: #475569;
}
.btn-danger {
background: #ef4444;
color: white;
padding: 12px 24px;
font-weight: 500;
}
.btn-danger:hover {
background: #dc2626;
}
.hint {
font-size: 0.875rem;
color: #64748b;
margin-top: 4px;
}
footer {
text-align: center;
padding: 24px;
color: #64748b;
font-size: 0.875rem;
background: #f1f5f9;
}
.notification {
position: fixed;
top: 20px;
right: 20px;
padding: 12px 20px;
border-radius: 6px;
color: white;
font-size: 0.875rem;
transform: translateX(200%);
transition: transform 0.3s ease;
z-index: 1000;
max-width: 300px;
word-wrap: break-word;
}
.notification.success {
background: #22c55e;
}
.notification.error {
background: #ef4444;
}
.notification.show {
transform: translateX(0);
}
-136
View File
@@ -1,136 +0,0 @@
class TimerController {
constructor() {
this.secret = localStorage.getItem('timerSecret') || '';
this.baseURL = window.location.origin;
this.initElements();
this.bindEvents();
this.updateSecretDisplay();
// 自动刷新状态
this.startAutoRefresh();
}
initElements() {
this.secretInput = document.getElementById('secret');
this.saveSecretBtn = document.getElementById('save-secret');
this.refreshStatusBtn = document.getElementById('refresh-status');
this.sendSignalBtn = document.getElementById('send-signal');
this.remainingTimeEl = document.getElementById('remaining-time');
this.progressFillEl = document.getElementById('progress-fill');
this.notificationEl = document.getElementById('notification');
}
bindEvents() {
this.saveSecretBtn.addEventListener('click', () => this.saveSecret());
this.refreshStatusBtn.addEventListener('click', () => this.fetchStatus());
this.sendSignalBtn.addEventListener('click', () => this.sendSignal());
// 回车键保存密钥
this.secretInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
this.saveSecret();
}
});
}
saveSecret() {
const secret = this.secretInput.value.trim();
if (!secret) {
this.showNotification('请输入密钥', 'error');
return;
}
this.secret = secret;
localStorage.setItem('timerSecret', secret);
this.updateSecretDisplay();
this.showNotification('密钥已保存', 'success');
this.fetchStatus(); // 保存后自动刷新状态
}
updateSecretDisplay() {
if (this.secret) {
this.secretInput.placeholder = '密钥已保存';
this.secretInput.value = '';
} else {
this.secretInput.placeholder = '输入您的访问密钥';
}
}
async fetchStatus() {
try {
const response = await fetch(`${this.baseURL}/timer/status`);
const data = await response.json();
if (data.code === 200) {
this.displayTime(data.remaining_time);
} else {
this.showNotification('获取状态失败', 'error');
}
} catch (error) {
console.error('Error fetching status:', error);
this.showNotification('网络错误,请稍后重试', 'error');
}
}
displayTime(seconds) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = Math.floor(seconds % 60);
this.remainingTimeEl.textContent =
`${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
// 更新进度条(假设最大时间为24小时)
const maxTime = 24 * 3600; // 24小时
const progress = Math.min(100, (seconds / maxTime) * 100);
this.progressFillEl.style.width = `${100 - progress}%`;
}
async sendSignal() {
if (!this.secret) {
this.showNotification('请先设置密钥', 'error');
return;
}
try {
const response = await fetch(`${this.baseURL}/signal?secret=${encodeURIComponent(this.secret)}`);
const data = await response.json();
if (data.code === 200) {
this.showNotification('信号发送成功!', 'success');
setTimeout(() => this.fetchStatus(), 1000); // 1秒后刷新状态
} else {
this.showNotification(`操作失败: ${data.message}`, 'error');
}
} catch (error) {
console.error('Error sending signal:', error);
this.showNotification('网络错误,请稍后重试', 'error');
}
}
showNotification(message, type) {
this.notificationEl.textContent = message;
this.notificationEl.className = `notification ${type} show`;
setTimeout(() => {
this.notificationEl.classList.remove('show');
}, 3000);
}
startAutoRefresh() {
// 每30秒自动刷新一次状态
setInterval(() => {
if (this.secret) {
this.fetchStatus();
}
}, 30000);
// 页面加载完成后立即获取一次状态
setTimeout(() => this.fetchStatus(), 1000);
}
}
// 初始化应用
document.addEventListener('DOMContentLoaded', () => {
new TimerController();
});
-56
View File
@@ -1,56 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GoodBaby</title>
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<div class="container">
<header>
<h1>GoodBaby</h1>
</header>
<main>
<section class="card">
<h2>访问设置</h2>
<div class="form-group">
<label for="secret">密钥</label>
<input type="password" id="secret" placeholder="输入您的访问密钥">
<button id="save-secret" class="btn-secondary">保存</button>
</div>
</section>
<section class="card">
<h2>状态信息</h2>
<div class="status-container">
<div class="timer-display">
<span id="remaining-time">--:--:--</span>
</div>
<div class="progress-bar">
<div id="progress-fill" class="progress-fill"></div>
</div>
<button id="refresh-status" class="btn-primary">刷新状态</button>
</div>
</section>
<section class="card">
<h2>执行操作</h2>
<div class="controls">
<button id="send-signal" class="btn-danger">发送信号</button>
<p class="hint">点击按钮重置定时器</p>
</div>
</section>
</main>
<footer>
<p>© 2026 GoodBaby</p>
</footer>
</div>
<div id="notification" class="notification"></div>
<script src="/static/js/script.js"></script>
</body>
</html>