import os import requests import frontmatter from PyInquirer import prompt
class ObsidianToYuque: def __init__(self, obsidian_dir, yuque_token, yuque_namespace): self.obsidian_dir = obsidian_dir self.yuque_token = yuque_token self.yuque_namespace = yuque_namespace self.headers = { "Content-Type": "application/json", "X-Auth-Token": self.yuque_token } self.api_base_url = "https://www.yuque.com/api/v2"
def get_all_md_files(self): """遍历 Obsidian 文件夹获取所有 Markdown 文件路径""" md_files = [] for root, _, files in os.walk(self.obsidian_dir): for file in files: if file.endswith(".md"): md_files.append(os.path.join(root, file)) return md_files
def create_repo(self, repo_name): """创建语雀知识库""" url = f"{self.api_base_url}/users/{self.yuque_namespace}/repos" payload = { "name": repo_name, "slug": repo_name.lower().replace(" ", "-"), "type": "Book", "description": f"Imported from Obsidian: {repo_name}", "public": 0 } response = requests.post(url, json=payload, headers=self.headers) if response.status_code == 200: print(f"知识库 '{repo_name}' 创建成功") return response.json()["data"]["id"] elif response.status_code == 400 and "已存在" in response.text: print(f"知识库 '{repo_name}' 已存在,继续使用") return None else: print(f"知识库创建失败: {response.text}") return None
def upload_doc(self, repo_slug, title, body): """上传文档到语雀""" url = f"{self.api_base_url}/repos/{self.yuque_namespace}/{repo_slug}/docs" payload = { "title": title, "slug": title.lower().replace(" ", "-"), "body": body } response = requests.post(url, json=payload, headers=self.headers) if response.status_code == 200: print(f"文档 '{title}' 上传成功") else: print(f"文档 '{title}' 上传失败: {response.text}")
def process_files(self): """处理所有 Markdown 文件""" md_files = self.get_all_md_files() repo_name = os.path.basename(self.obsidian_dir) repo_slug = repo_name.lower().replace(" ", "-") self.create_repo(repo_name)
for file_path in md_files: with open(file_path, "r", encoding="utf-8") as f: content = f.read() metadata, body = frontmatter.parse(content) title = metadata.get("title", os.path.basename(file_path).replace(".md", "")) self.upload_doc(repo_slug, title, body)
def main(): questions = [ { "type": "input", "name": "obsidian_dir", "message": "请输入 Obsidian 文件夹路径:" }, { "type": "input", "name": "yuque_token", "message": "请输入语雀 API Token:" }, { "type": "input", "name": "yuque_namespace", "message": "请输入语雀 Namespace (个人或团队空间标识):" } ] answers = prompt(questions)
obsidian_dir = answers["obsidian_dir"] yuque_token = answers["yuque_token"] yuque_namespace = answers["yuque_namespace"]
if not os.path.exists(obsidian_dir): print("Obsidian 文件夹路径不存在,请检查后重试!") return
uploader = ObsidianToYuque(obsidian_dir, yuque_token, yuque_namespace) uploader.process_files()
if __name__ == "__main__": main()
|