Files
ChouJuGEO/docs/guides/QUICK_START_GUIDE.md
T
刘国栋 8f7f082c3d feat: 重构项目结构并添加平台同步基础架构
- 重构项目目录结构,将功能模块移至 modules/ 目录
- 创建平台同步基础架构,包括发布器基类和 GitHub 发布器
- 新增 UI 状态管理模块 (modules/ui/state.py) 统一管理会话状态
- 更新依赖配置,添加平台同步所需依赖 (httpx, pyperclip)
- 整理文档结构,将所有文档分类移至 docs/ 目录
- 添加 .cursorrules 文件定义项目开发规范
- 清理根目录重复文件,保持项目结构整洁
2026-01-30 10:21:29 +08:00

12 KiB
Raw Blame History

快速开始指南:实现GitHub发布功能

这是最简单的实现示例,可以作为其他平台的基础模板

🎯 目标

实现GitHub平台的文章自动发布功能,验证整体架构可行性。

📦 步骤1:安装依赖

pip install httpx pyperclip

📝 步骤2:扩展数据库

modules/data_storage.py_init_sqlite 方法中添加:

# 平台账号表
cursor.execute("""
    CREATE TABLE IF NOT EXISTS platform_accounts (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        platform TEXT NOT NULL,
        account_type TEXT NOT NULL,
        account_name TEXT,
        api_key TEXT,
        config_json TEXT,
        is_active INTEGER DEFAULT 1,
        brand TEXT,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )
""")

# 发布记录表
cursor.execute("""
    CREATE TABLE IF NOT EXISTS publish_records (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        article_id INTEGER,
        platform TEXT NOT NULL,
        publish_method TEXT NOT NULL,
        publish_status TEXT NOT NULL,
        publish_url TEXT,
        publish_id TEXT,
        error_message TEXT,
        published_at TIMESTAMP,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )
""")

💻 步骤3:创建GitHub发布器

创建文件 platform_sync/github_publisher.py

"""
GitHub发布器 - 最简单的实现示例
"""
import base64
import httpx
from typing import Dict, Any, Optional


class GitHubPublisher:
    """GitHub发布器"""
    
    def __init__(self, api_key: str, repo_owner: str, repo_name: str):
        self.api_key = api_key
        self.repo_owner = repo_owner
        self.repo_name = repo_name
        self.base_url = "https://api.github.com"
        self.headers = {
            "Authorization": f"token {api_key}",
            "Accept": "application/vnd.github.v3+json"
        }
    
    def publish(self, content: str, title: str, file_path: Optional[str] = None) -> Dict[str, Any]:
        """
        发布内容到GitHub
        
        Args:
            content: Markdown内容
            title: 文章标题
            file_path: 文件路径(可选)
        
        Returns:
            {
                'success': bool,
                'publish_url': str,
                'publish_id': str,
                'error': str
            }
        """
        try:
            # 生成文件路径
            if not file_path:
                safe_title = title.replace(' ', '_').replace('/', '_')
                file_path = f"content/{safe_title}.md"
            
            # 编码内容
            content_bytes = content.encode('utf-8')
            content_base64 = base64.b64encode(content_bytes).decode('utf-8')
            
            # API URL
            url = f"{self.base_url}/repos/{self.repo_owner}/{self.repo_name}/contents/{file_path}"
            
            # 检查文件是否存在
            response = httpx.get(url, headers=self.headers)
            sha = None
            if response.status_code == 200:
                sha = response.json().get('sha')
            
            # 准备数据
            data = {
                "message": f"Publish: {title}",
                "content": content_base64,
                "branch": "main"
            }
            if sha:
                data["sha"] = sha
            
            # 创建或更新文件
            response = httpx.put(url, json=data, headers=self.headers)
            
            if response.status_code in [200, 201]:
                result = response.json()
                html_url = result.get('content', {}).get('html_url', '')
                return {
                    'success': True,
                    'publish_url': html_url,
                    'publish_id': result.get('content', {}).get('sha', ''),
                    'error': None
                }
            else:
                return {
                    'success': False,
                    'publish_url': '',
                    'publish_id': '',
                    'error': f"GitHub API错误: {response.text}"
                }
        except Exception as e:
            return {
                'success': False,
                'publish_url': '',
                'publish_id': '',
                'error': str(e)
            }
    
    def validate_account(self) -> bool:
        """验证GitHub账号"""
        try:
            response = httpx.get(f"{self.base_url}/user", headers=self.headers)
            return response.status_code == 200
        except:
            return False

🔧 步骤4:扩展DataStorage

modules/data_storage.pyDataStorage 类中添加:

def save_platform_account(self, platform: str, account_config: Dict[str, Any], brand: str):
    """保存平台账号"""
    if self.storage_type == "sqlite":
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute("""
            INSERT OR REPLACE INTO platform_accounts 
            (platform, account_type, account_name, api_key, config_json, brand, updated_at)
            VALUES (?, ?, ?, ?, ?, ?, ?)
        """, (
            platform,
            account_config.get('account_type', 'api'),
            account_config.get('account_name', ''),
            account_config.get('api_key', ''),
            json.dumps(account_config.get('config', {}), ensure_ascii=False),
            brand,
            datetime.now().isoformat()
        ))
        conn.commit()
        conn.close()

def get_platform_account(self, platform: str, brand: str) -> Optional[Dict[str, Any]]:
    """获取平台账号"""
    if self.storage_type == "sqlite":
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute("""
            SELECT * FROM platform_accounts 
            WHERE platform = ? AND brand = ? AND is_active = 1
        """, (platform, brand))
        row = cursor.fetchone()
        conn.close()
        
        if row:
            return {
                'api_key': row[4],
                'config': json.loads(row[5] or '{}')
            }
    return None

def save_publish_record(self, article_id: int, platform: str, publish_method: str,
                       publish_status: str, publish_url: str = '', publish_id: str = '',
                       error_message: str = ''):
    """保存发布记录"""
    if self.storage_type == "sqlite":
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute("""
            INSERT INTO publish_records 
            (article_id, platform, publish_method, publish_status, publish_url, 
             publish_id, error_message, published_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        """, (
            article_id, platform, publish_method, publish_status,
            publish_url, publish_id, error_message, datetime.now().isoformat()
        ))
        conn.commit()
        conn.close()

🎨 步骤5:添加UI(在geo_tool.py中)

modules/geo_tool.py 中添加新的Tab或功能:

# 在Tab定义中添加
tabs = st.tabs([
    "1 关键词蒸馏",
    "2 内容生成",
    "3 内容优化",
    "4 AI验证",
    "5 历史记录",
    "6 平台同步"  # 新增
])

with tabs[5]:  # 平台同步Tab
    st.header("📤 平台文章同步")
    
    # GitHub账号配置
    with st.expander("🔐 GitHub账号配置", expanded=True):
        github_api_key = st.text_input("GitHub Personal Access Token", type="password")
        github_repo_owner = st.text_input("仓库所有者(用户名)")
        github_repo_name = st.text_input("仓库名称")
        
        if st.button("保存GitHub配置"):
            if github_api_key and github_repo_owner and github_repo_name:
                storage.save_platform_account(
                    platform="GitHub",
                    account_config={
                        'account_type': 'api',
                        'api_key': github_api_key,
                        'config': {
                            'repo_owner': github_repo_owner,
                            'repo_name': github_repo_name
                        }
                    },
                    brand=brand
                )
                st.success("GitHub配置已保存!")
            else:
                st.error("请填写完整信息")
    
    # 发布功能
    st.subheader("📝 发布到GitHub")
    
    # 选择文章
    articles = storage.get_articles(brand=brand)
    if articles:
        article_options = {f"{a['keyword']} - {a['platform']}": a['id'] for a in articles}
        selected_article_key = st.selectbox("选择要发布的文章", list(article_options.keys()))
        selected_article_id = article_options[selected_article_key]
        
        if st.button("🚀 发布到GitHub", type="primary"):
            # 获取账号配置
            account_config = storage.get_platform_account("GitHub", brand)
            if not account_config:
                st.error("请先配置GitHub账号")
            else:
                # 获取文章
                article = next((a for a in articles if a['id'] == selected_article_id), None)
                if article:
                    # 创建发布器
                    from platform_sync.github_publisher import GitHubPublisher
                    publisher = GitHubPublisher(
                        api_key=account_config['api_key'],
                        repo_owner=account_config['config']['repo_owner'],
                        repo_name=account_config['config']['repo_name']
                    )
                    
                    # 发布
                    with st.spinner("正在发布到GitHub..."):
                        result = publisher.publish(
                            content=article['content'],
                            title=article['keyword']
                        )
                    
                    # 保存发布记录
                    storage.save_publish_record(
                        article_id=selected_article_id,
                        platform="GitHub",
                        publish_method="api",
                        publish_status="success" if result['success'] else "failed",
                        publish_url=result.get('publish_url', ''),
                        publish_id=result.get('publish_id', ''),
                        error_message=result.get('error', '')
                    )
                    
                    # 显示结果
                    if result['success']:
                        st.success(f"✅ 发布成功!")
                        st.markdown(f"**发布链接**: {result['publish_url']}")
                    else:
                        st.error(f"❌ 发布失败: {result.get('error', '未知错误')}")
    else:
        st.info("请先生成文章")
    
    # 发布记录
    st.subheader("📊 发布记录")
    # 这里可以显示发布历史记录

步骤6:测试

  1. 获取GitHub Token

  2. 运行测试

    streamlit run geo_tool.py
    
  3. 测试流程

    • 配置GitHub账号
    • 生成一篇文章
    • 发布到GitHub
    • 检查GitHub仓库是否成功创建文件

🎉 完成!

如果GitHub发布功能正常工作,说明架构是正确的。接下来可以:

  1. 按照相同模式实现其他7个API平台
  2. 实现一键复制功能
  3. 添加批量发布功能

📚 参考