🔄 卡若AI 同步 2026-02-21 19:39 | 更新:金仓、水桥平台对接、总索引与入口、运营中枢工作台 | 排除 >20MB: 5 个

This commit is contained in:
2026-02-21 19:39:10 +08:00
parent 3ef5ce9578
commit b747a59b07
6 changed files with 341 additions and 3 deletions

View File

@@ -0,0 +1,140 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
kr宝塔仅使用宝塔 Node 项目接口,批量修复 run=False 项目。
策略:
1) 拉取 Node 项目列表
2) 对 run=False 项目:
- stop_project
- 杀掉其目标端口上的冲突进程EADDRINUSE
- 清理 pid 文件
- start_project
3) 回查 run/listen_ok
"""
import hashlib
import json
import os
import re
import ssl
import subprocess
import time
import urllib.parse
import urllib.request
ssl._create_default_https_context = ssl._create_unverified_context
PANEL = "https://127.0.0.1:9988"
API_KEY = "qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT"
def sign():
now = int(time.time())
s = str(now) + hashlib.md5(API_KEY.encode("utf-8")).hexdigest()
return {
"request_time": now,
"request_token": hashlib.md5(s.encode("utf-8")).hexdigest(),
}
def post(path, data=None, timeout=25):
payload = sign()
if data:
payload.update(data)
req = urllib.request.Request(
PANEL + path, data=urllib.parse.urlencode(payload).encode("utf-8")
)
with urllib.request.urlopen(req, timeout=timeout) as resp:
txt = resp.read().decode("utf-8", errors="ignore")
try:
return json.loads(txt)
except Exception:
return {"raw": txt[:800]}
def fetch_list():
result = post("/project/nodejs/get_project_list")
items = result.get("data") if isinstance(result, dict) else None
if not isinstance(items, list):
items = result.get("list") if isinstance(result, dict) else None
if not isinstance(items, list):
raise RuntimeError("获取 Node 项目列表失败: %s" % str(result)[:300])
return items
def pids_on_port(port):
cmd = "ss -tlnp | grep ':%s ' || true" % port
out = subprocess.check_output(cmd, shell=True, universal_newlines=True)
return sorted({int(x) for x in re.findall(r"pid=(\d+)", out)})
def collect_ports(item):
ports = []
cfg = item.get("project_config") or {}
p = cfg.get("port")
if p:
try:
ports.append(int(p))
except Exception:
pass
script = str(cfg.get("project_script") or "")
for m in re.findall(r"-p\s*(\d+)", script):
try:
ports.append(int(m))
except Exception:
pass
return sorted(set(ports))
def main():
items = fetch_list()
operations = []
for it in items:
name = it.get("name")
if not name or it.get("run") is True:
continue
ports = collect_ports(it)
post("/project/nodejs/stop_project", {"project_name": name})
killed = []
for port in ports:
for pid in pids_on_port(port):
subprocess.call("kill -9 %s" % pid, shell=True)
killed.append((port, pid))
pid_file = "/www/server/nodejs/vhost/pids/%s.pid" % name
try:
if os.path.exists(pid_file):
with open(pid_file, "w", encoding="utf-8") as f:
f.write("0")
except Exception:
pass
r = post("/project/nodejs/start_project", {"project_name": name})
ok = isinstance(r, dict) and (
r.get("status") is True or "成功" in str(r.get("msg", ""))
)
msg = str(r.get("msg", r) if isinstance(r, dict) else r)[:220]
operations.append((name, ports, killed, ok, msg))
time.sleep(1)
print("=== 操作结果 ===")
for row in operations:
print(row)
time.sleep(4)
items2 = fetch_list()
run_cnt = sum(1 for x in items2 if x.get("run") is True)
stop_cnt = sum(1 for x in items2 if x.get("run") is not True)
print("\n=== 回查(run/listen_ok) ===")
for x in items2:
print((x.get("name"), x.get("run"), x.get("listen_ok")))
print("\nSUMMARY", run_cnt, stop_cnt)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,147 @@
---
name: Soul文章上传
description: 《一场soul的创业实验》第9章文章写入小程序后端写好即传id 已存在则更新不重复
triggers: Soul文章上传、Soul派对文章、第9章上传、soul 上传、写soul文章
owner: 水桥
group: 水
version: "1.0"
updated: "2026-02-20"
---
# Soul文章上传 Skill
> 写好文章直接上传到 Soul 小程序id 已存在则更新,保持不重复。 —— 水桥
---
## 触发条件
用户说以下关键词时自动激活:
- Soul文章上传、Soul派对文章、第9章上传
- soul 上传、写soul文章、上传到soul
- 写好文章上传、文章写好了上传
---
## 核心配置
| 项目 | 路径/值 |
|:---|:---|
| Soul 项目根目录 | `/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验` |
| 第9章文章目录 | `/Users/karuo/Documents/个人/2、我写的书/《一场soul的创业实验》/第四篇|真实的赚钱/第9章我在Soul上亲访的赚钱案例/` |
| 上传脚本 | `一场soul的创业实验/scripts/upload_soul_article.sh` |
| 底层工具 | `一场soul的创业实验/content_upload.py` |
| 第9章固定参数 | part-4第四篇真实的赚钱, chapter-9第9章我在Soul上亲访的赚钱案例 |
---
## 执行步骤
### 1. 写好文章
文章放在第9章目录文件名格式`9.xx 第X场主题.md`
示例:`9.18 第105场创业社群、直播带货与程序员.md`
### 2. 执行上传
```bash
/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/scripts/upload_soul_article.sh "/Users/karuo/Documents/个人/2、我写的书/《一场soul的创业实验》/第四篇|真实的赚钱/第9章我在Soul上亲访的赚钱案例/9.xx 第X场标题.md"
```
### 3. 一键命令(替换为实际文件路径)
```bash
cd /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验
./scripts/upload_soul_article.sh "<文章完整路径>"
```
---
## 输出说明
| 返回 | 含义 |
|:---|:---|
| `"action": "创建"` | 新章节已写入 |
| `"action": "更新"` | 同 id 已存在,内容已更新(不重复) |
---
## 配套脚本
| 脚本 | 用途 |
|:---|:---|
| `content_upload.py` | 直连数据库,创建/更新章节(依赖 pymysql |
| `scripts/upload_soul_article.sh` | 从文件名提取 id、title调用 content_upload |
### 手动调用 content_upload高级
```bash
cd /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验
# 上传指定文章
python3 content_upload.py --id 9.18 --title "9.18 第105场主题" \
--content-file "<文章路径>" --part part-4 --chapter chapter-9 --price 1.0
# 查看篇章结构
python3 content_upload.py --list-structure
# 列出所有章节
python3 content_upload.py --list-chapters
```
---
## API 接口(备用)
管理后台 API需 Token
| 接口 | 说明 |
|:---|:---|
| `POST /api/admin` | 登录获取 TokenBody: `{"username":"admin","password":"admin123"}` |
| `POST /api/db/book` | 创建/更新章节Header: `Authorization: Bearer {token}` |
正式环境:`https://soulapi.quwanzhi.com`
开发环境:`https://souldev.quwanzhi.com`
---
## 经验与注意
### 1. 不重复机制
-`id`(如 9.18)为唯一键
- id 已存在 → **更新**;不存在 → **创建**
- 同一场次多次上传不会重复,只会覆盖
### 2. 文件名规范
- 格式:`9.xx 第X场主题.md`
- id 从文件名提取,必须形如 `9.18`(章.节)
### 3. 环境依赖
```bash
pip3 install pymysql
```
### 4. 与书的对应关系
- 书稿目录:`个人/2、我写的书/《一场soul的创业实验》/第四篇|真实的赚钱/第9章...`
- 小程序内容来源:腾讯云 MySQL `soul_miniprogram.chapters`
- content_upload 直连数据库,与 API 共用同一数据源
### 5. 工作流建议
1. 根据 Soul 派对 TXT 写好文章(按书格式:一句一行、金句开头、日期、`---` 分段)
2. 保存为 `9.xx 第X场主题.md` 到第9章目录
3. 执行 `upload_soul_article.sh "<文章路径>"`
4. 检查返回为「创建」或「更新」即完成
---
## 版本记录
| 版本 | 日期 | 说明 |
|:---|:---|:---|
| 1.0 | 2026-02-20 | 初版,从 Soul 项目抽取为独立技能 |

View File

@@ -1,7 +1,7 @@
# 卡若AI 技能注册表Skill Registry
> **一张表查所有技能**。任何 AI 拿到这张表,就能按关键词找到对应技能的 SKILL.md 路径并执行。
> 46 技能 | 14 成员 | 5 负责人
> 47 技能 | 14 成员 | 5 负责人
> 版本5.0 | 更新2026-02-16
---
@@ -52,6 +52,7 @@
| W07 | 飞书管理 | 水桥 | 飞书日志、写入飞书 | `02_卡人/水桥_平台对接/飞书管理/SKILL.md` | 飞书日志/文档自动化 |
| W08 | 智能纪要 | 水桥 | 会议纪要、产研纪要、**飞书妙记、飞书链接、妙记下载、第几场、指定场次、批量下载妙记、cunkebao.feishu.cn、meetings.feishu.cn/minutes** | `02_卡人/水桥_平台对接/智能纪要/SKILL.md` | 会议录音转结构化纪要;飞书妙记识别与下载(单条/批量),完毕用复盘格式回复 |
| W09 | 小程序管理 | 水桥 | 小程序、微信小程序 | `02_卡人/水桥_平台对接/小程序管理/SKILL.md` | 微信小程序发布与维护 |
| W10 | Soul文章上传 | 水桥 | **Soul文章上传、Soul派对文章、第9章上传、soul上传** | `02_卡人/水桥_平台对接/Soul文章上传/SKILL.md` | 《一场soul的创业实验》第9章文章写好后上传到小程序id 已存在则更新不重复 |
## 木组 · 卡木(产品内容创造)
@@ -109,8 +110,8 @@
| 组 | 负责人 | 成员数 | 技能数 |
|:--|:---|:--|:--|
| 金 | 卡资 | 2 | 20 |
| 水 | 卡人 | 3 | 9 |
| 水 | 卡人 | 3 | 10 |
| 木 | 卡木 | 3 | 6 |
| 火 | 卡火 | 4 | 13 |
| 土 | 卡土 | 4 | 6 |
| **合计** | **5** | **14** | **54** |
| **合计** | **5** | **14** | **55** |

View File

@@ -43,3 +43,4 @@
| 2026-02-20 18:17:38 | 🔄 卡若AI 同步 2026-02-20 18:17 | 更新:水桥平台对接、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 5 个 |
| 2026-02-20 18:29:55 | 🔄 卡若AI 同步 2026-02-20 18:29 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 5 个 |
| 2026-02-20 18:38:29 | 🔄 卡若AI 同步 2026-02-20 18:38 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个 |
| 2026-02-21 13:04:58 | 🔄 卡若AI 同步 2026-02-21 13:04 | 更新:金仓、水桥平台对接、运营中枢工作台 | 排除 >20MB: 5 个 |

View File

@@ -46,3 +46,4 @@
| 2026-02-20 18:17:38 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-20 18:17 | 更新:水桥平台对接、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-02-20 18:29:55 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-20 18:29 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-02-20 18:38:29 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-20 18:38 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-02-21 13:04:58 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-21 13:04 | 更新:金仓、水桥平台对接、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |

View File

@@ -0,0 +1,48 @@
#!/bin/bash
# 存客宝 42.194.245.239 磁盘清理 · 卡若AI 生成
# 在宝塔面板【终端】中粘贴本脚本内容执行,或上传后 bash 本脚本
set -e
echo "========== 存客宝 卡若AI 磁盘清理 =========="
echo "--- 清理前 ---"
df -h /
echo ""
echo "--- 大目录 TOP15 ---"
du -sh /www/* /var/log /tmp 2>/dev/null | sort -rh | head -15
echo ""
# 1. 清理系统日志(保留结构)
echo "[1/6] 清理系统旧日志..."
journalctl --vacuum-time=3d 2>/dev/null || true
find /var/log -type f -name "*.log" -mtime +7 -exec truncate -s 0 {} \; 2>/dev/null || true
find /var/log -type f -name "*.gz" -mtime +7 -delete 2>/dev/null || true
# 2. 清理 apt 缓存Ubuntu
echo "[2/6] 清理 apt 缓存..."
apt-get clean 2>/dev/null || true
apt-get autoremove -y 2>/dev/null || true
# 3. 清理临时目录
echo "[3/6] 清理 /tmp /var/tmp..."
rm -rf /tmp/* 2>/dev/null || true
rm -rf /var/tmp/* 2>/dev/null || true
# 4. 宝塔面板日志截断(不删文件)
echo "[4/6] 截断宝塔 request 日志..."
for f in /www/server/panel/logs/request/*.log; do [ -f "$f" ] && truncate -s 0 "$f"; done 2>/dev/null || true
# 5. 网站日志截断(会清空当前日志内容,慎选)
echo "[5/6] 检查网站日志大小..."
du -sh /www/wwwlogs/ 2>/dev/null || true
# 若需清空网站日志,取消下一行注释:
# truncate -s 0 /www/wwwlogs/*.log 2>/dev/null || true
# 6. 回收站(需在面板【文件】里手动清空,此处仅提示)
echo "[6/6] 请在面板【文件】→【回收站】中清空回收站以释放空间。"
echo ""
echo "--- 清理后 ---"
df -h /
echo ""
echo "--- 大目录 TOP15 ---"
du -sh /www/* /var/log /tmp 2>/dev/null | sort -rh | head -15
echo "========== 清理完成 =========="