novel-doomsday-resurgence/ultimate_fix.py
2026-04-06 22:06:30 +08:00

232 lines
8.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
inkos 终极修复方案
直接修复数据库中的数据错误
"""
import json
import os
import shutil
import sqlite3
import subprocess
import time
def stop_inkos():
"""停止inkos所有进程"""
print("1. 停止inkos所有进程...")
subprocess.run(["pkill", "-9", "-f", "node.*inkos"], capture_output=True)
subprocess.run(["pkill", "-9", "-f", "inkos"], capture_output=True)
time.sleep(3)
print(" ✅ inkos已停止")
def backup_data():
"""备份所有数据"""
print("2. 备份数据...")
backup_dir = f"/root/.openclaw/workspace/backups/inkos_ultimate_fix_{time.strftime('%Y%m%d_%H%M%S')}"
os.makedirs(backup_dir, exist_ok=True)
# 备份重要文件和目录
backup_items = [
"/root/.openclaw/workspace/tomato-novel/inkos.json",
"/root/.openclaw/workspace/tomato-novel/tomato-novel/books/末日重生-开局囤货十亿物资",
"/root/.openclaw/workspace/tomato-novel/books/末日重生-开局囤货十亿物资"
]
for item in backup_items:
if os.path.exists(item):
if os.path.isfile(item):
shutil.copy2(item, backup_dir)
else:
shutil.copytree(item, os.path.join(backup_dir, os.path.basename(item)), dirs_exist_ok=True)
print(f" 已备份: {os.path.basename(item)}")
print(f" 备份位置: {backup_dir}")
return backup_dir
def fix_database():
"""修复数据库文件"""
print("3. 修复数据库文件...")
# 找到并修复所有数据库文件
db_files = [
"/root/.openclaw/workspace/tomato-novel/tomato-novel/books/末日重生-开局囤货十亿物资/story/memory.db",
"/root/.openclaw/workspace/tomato-novel/books/末日重生-开局囤货十亿物资/story/memory.db"
]
for db_file in db_files:
if os.path.exists(db_file):
print(f" 检查数据库: {db_file}")
try:
# 备份数据库
shutil.copy2(db_file, f"{db_file}.backup")
# 尝试连接到数据库
conn = sqlite3.connect(db_file)
cursor = conn.cursor()
# 获取所有表名
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
tables = cursor.fetchall()
print(f" 数据库表: {[t[0] for t in tables]}")
# 查找可能包含章节数据的表
for table in tables:
table_name = table[0]
if 'chapter' in table_name.lower() or 'row' in table_name.lower():
print(f" 检查表: {table_name}")
# 获取表结构
cursor.execute(f"PRAGMA table_info({table_name});")
columns = cursor.fetchall()
print(f" 列: {[col[1] for col in columns]}")
# 查找title列
title_col = None
for col in columns:
if 'title' in col[1].lower():
title_col = col[1]
break
if title_col:
# 查找空标题的行
cursor.execute(f"SELECT rowid, {title_col} FROM {table_name} WHERE {title_col} IS NULL OR {title_col} = '' OR LENGTH(TRIM({title_col})) = 0;")
empty_titles = cursor.fetchall()
if empty_titles:
print(f" 找到 {len(empty_titles)} 个空标题")
for rowid, title in empty_titles:
# 修复空标题
new_title = f"{rowid}"
cursor.execute(f"UPDATE {table_name} SET {title_col} = ? WHERE rowid = ?", (new_title, rowid))
print(f" 修复行 {rowid}: '{new_title}'")
conn.commit()
conn.close()
print(f" ✅ 数据库修复完成: {os.path.basename(db_file)}")
except Exception as e:
print(f" ❌ 修复数据库时出错: {e}")
# 如果数据库损坏严重删除它让inkos重新创建
print(f" 删除损坏的数据库: {db_file}")
os.remove(db_file)
print(f" ✅ 已删除inkos将重新创建数据库")
def clean_state_files():
"""清理状态文件让inkos重新开始"""
print("4. 清理状态文件...")
# 删除可能损坏的状态文件
state_dirs = [
"/root/.openclaw/workspace/tomato-novel/tomato-novel/books/末日重生-开局囤货十亿物资/story/state",
"/root/.openclaw/workspace/tomato-novel/tomato-novel/books/末日重生-开局囤货十亿物资/story/runtime",
"/root/.openclaw/workspace/tomato-novel/books/末日重生-开局囤货十亿物资/story/state",
"/root/.openclaw/workspace/tomato-novel/books/末日重生-开局囤货十亿物资/story/runtime"
]
for state_dir in state_dirs:
if os.path.exists(state_dir):
# 只删除特定文件,保留章节文件
for file in os.listdir(state_dir):
if file.endswith('.json') or file.endswith('.db'):
file_path = os.path.join(state_dir, file)
try:
os.remove(file_path)
print(f" 删除: {file}")
except:
pass
print(" ✅ 状态文件已清理")
def create_simple_config():
"""创建最简单的配置"""
print("5. 创建简单配置...")
config = {
"name": "tomato-novel-fixed",
"version": "0.1.0",
"language": "zh",
"llm": {
"provider": "custom",
"baseUrl": "https://ark.cn-beijing.volces.com/api/coding/v3",
"model": "deepseek-v3.2"
},
"daemon": {
"schedule": {
"writeCron": "0 */2 * * *" # 每2小时一次
},
"maxConcurrentBooks": 1
},
"quality": {
"enforcement": "none" # 完全关闭质量检查
}
}
config_path = "/root/.openclaw/workspace/tomato-novel/inkos.json"
with open(config_path, 'w', encoding='utf-8') as f:
json.dump(config, f, ensure_ascii=False, indent=2)
print(" ✅ 简单配置已创建")
def start_inkos():
"""启动inkos"""
print("6. 启动inkos...")
os.chdir("/root/.openclaw/workspace/tomato-novel")
# 启动inkos
with open("/tmp/inkos_ultimate_start.log", "w") as log_file:
process = subprocess.Popen(
["nohup", "inkos", "up"],
stdout=log_file,
stderr=subprocess.STDOUT,
start_new_session=True
)
time.sleep(10)
# 检查是否启动成功
result = subprocess.run(["ps", "aux"], capture_output=True, text=True)
if "inkos up" in result.stdout:
pid_line = [line for line in result.stdout.split('\n') if "inkos up" in line][0]
pid = pid_line.split()[1]
print(f" ✅ inkos 已启动 (PID: {pid})")
return True
else:
print(" ❌ inkos 启动失败")
return False
def main():
"""主函数"""
print("=" * 60)
print("inkos 终极修复方案")
print("=" * 60)
stop_inkos()
backup_dir = backup_data()
fix_database()
clean_state_files()
create_simple_config()
if start_inkos():
print("\n" + "=" * 60)
print("✅ 修复完成!")
print(f"备份位置: {backup_dir}")
print("=" * 60)
print("\ninkos 已重新启动,配置为:")
print("- 质量检查: 关闭")
print("- 创作频率: 每2小时")
print("- 日志文件: /tmp/inkos_ultimate_start.log")
print("\n等待5-10分钟后使用以下命令测试:")
print(" inkos status")
print(" inkos draft 末日重生-开局囤货十亿物资")
else:
print("\n" + "=" * 60)
print("❌ 修复失败!")
print("=" * 60)
print("\n请检查:")
print("1. inkos 是否安装: which inkos")
print("2. 日志文件: tail -100 /tmp/inkos_ultimate_start.log")
print("3. 可能需要重新安装 inkos")
if __name__ == "__main__":
main()