obsidian发布一键发布typecho
2024-11-28 21:28
怎么说了,obsidan 的编辑的体验还是很不错的,如果可以直接发布到博客会方便些
拾月的文章,网上看到这个博主很早之前就这么弄,很有参考价值,tks!于是也大致这么弄了下,修改小部分内容。
思路:主要就是通过 xmlrpc 这个 api 来上传文章METAWEBLOG_API = 'http://xxxx/index.php/action/xmlrpc'
补充
- 上传结构
这个分类这里是 list,数组形式的;
post_type 里面 post 是文章,还有一个 page 应该是页面
倒数第 2 个是是否允许评论 - cid 与 slug
slug 好像是一个自定义软连接,不是太会弄,忽略掉了。
cid 是 typecho 的一个由博客生成的 int 类型数字,代表了某一篇文章,拾月的 blog 里面用到了来控制更新,我大致也是这么弄的,但是我使用本地 json 文件控制的。 - 图床
用的 picList,很方便,可以用 alist 作为图床,alist 要有外部地址即可!
😄👍还是可以的,可以直接在本地发。
代码
用的插件那个 python_scipter, 代码如下:
# 脚本1
#!/usr/local/bin/python3
# -*- coding: UTF-8 -*-
import xmlrpc.client
import datetime
import json
import time
import re
import sys
import os
from post_img_alist import *
#import yaml
# 个人信息配置
BLOG_USERNAME = '' # 博客用户名
BLOG_PASSWORD = '' # 博客密码
OB_VAULT = '' # Obsidian的vault目录
PICTURE_PATH = r"" # 本地保证图片的目录,即我的Obsidian附件目录
METAWEBLOG_API = 'http://xxxx/index.php/action/xmlrpc' # 博客metaweblog api地址
JSON_FILE_PATH = r"cid.json" # 保存文件名和cid的json文件路径 我写的绝对路径
def save_cid(filename, cid):
"""
将文件名和对应的 CID 保存到本地 JSON 文件中。
如果 JSON 文件不存在,会创建一个新文件。
如果已存在,则追加新的数据。
"""
data = {}
# 如果文件已存在,先读取现有数据
if os.path.exists(JSON_FILE_PATH):
with open(JSON_FILE_PATH, "r", encoding="utf-8") as f:
try:
data = json.load(f)
except json.JSONDecodeError:
data = {} # 如果文件内容为空或损坏,初始化为空字典
# 更新数据
data[filename] = cid
# 保存到 JSON 文件
with open(JSON_FILE_PATH, "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
def get_cid(filename):
"""
从本地 JSON 文件中读取指定文件名的 CID。
如果不存在对应的文件名,返回 0。
"""
# 如果文件不存在,直接返回 0
if not os.path.exists(JSON_FILE_PATH):
return 0
# 读取 JSON 文件
with open(JSON_FILE_PATH, "r", encoding="utf-8") as f:
try:
data = json.load(f)
except json.JSONDecodeError:
return 0 # 如果文件内容为空或损坏,返回 0
# 返回 CID 或 0
return data.get(filename, 0)
def custom_replace_func(match_ct):
Name = str(match_ct).split("/")[-1]
fileName = PICTURE_PATH+"\\"+Name
isOk,web_url = post_upload(fileName)
if isOk:
return web_url
else:
return str(f"![1-img](![[{match_ct}]])")
def process_md_content(md_content):
"""
处理 Markdown 内容,提取被 ![2-img](![3-img](![[ 和 ]])) 包裹的内容,并替换为自定义内容。
:param md_content: 原始 Markdown 内容
:param custom_replace_func: 自定义替换函数,接受一个字符串参数,返回替换后的内容
:return: 替换后的 Markdown 内容
"""
# 定义匹配模式
pattern = r"!\[\[(.*?)\]\]"
# 使用正则提取所有被 ![2-img](![3-img](![[ 和 ]])) 包裹的内容
matches = re.findall(pattern, md_content)
# 遍历提取的内容,并使用自定义函数替换
for idx,match in enumerate(matches):
# 获取自定义替换内容
replacement = custom_replace_func(match)
# 将原内容替换为新的内容
md_content = md_content.replace(f"![4-img](![[{match}]])", f"![{idx}-img]({replacement})")
return md_content
def read_md(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
file_name = os.path.splitext(os.path.basename(file_path))[0]
content = process_md_content(content)
return content, file_name
# JSON文件路径,全局使用
json_file_path_record = r"file_record.json"
def write_to_json_file(full_path, cid):
"""
向 JSON 文件中写入数据。检查 full_path 是否已存在,若不存在则新增。
:param full_path: 文件完整路径 (键)
:param cid: 文件对应的 CID (值)
"""
# 初始化数据存储
data = {}
# 如果 JSON 文件存在,读取内容
if os.path.exists(json_file_path_record):
try:
with open(json_file_path_record, 'r', encoding='utf-8') as file:
data = json.load(file)
except Exception as e:
# 如果文件读取失败,打印错误,但继续初始化空数据
print(f"读取 JSON 文件失败: {e}")
data = {}
# 检查 full_path 是否已存在
if full_path in data:
print(f"路径 {full_path} 已存在,跳过写入。")
return
# 添加新的 full_path 和 cid
data[full_path] = cid
# 写入更新后的数据到 JSON 文件
try:
with open(json_file_path_record, 'w', encoding='utf-8') as file:
json.dump(data, file, ensure_ascii=False, indent=4)
print(f"已成功写入 {full_path} 和 {cid} 到文件。")
except Exception as e:
print(f"写入 JSON 文件失败: {e}")
# 创建文章,若文件已经存在,则自动更新,
# 入参:file要发布的文件,post_type发布类型(post-文章,page:页面)
def new_post(file_path):
content,filaName = read_md(file_path)
# slug = data['meta']['slug']
# cid = get_cid(slug)
cid = get_cid(filaName)
# 构建发布内容
struct = {
'title': filaName,
'dateCreated': datetime.datetime.now(),
#'wp_slug': slug,
'categories': ['生活随记'], # 分类
#'mt_keywords': data['meta']['blogtags'], # 标签
'post_type': 'post',
'mt_allow_comments': True,
'description': content,
}
client = xmlrpc.client.ServerProxy(METAWEBLOG_API)
if int(cid) > 0:
try:
result = client.metaWeblog.editPost(cid, BLOG_USERNAME, BLOG_PASSWORD, struct, True)
print('\n文章已存在(cid={cid}),更新成功,信息如下:\n'.format(cid=cid))
for key, value in struct.items():
if key != 'description': print(key, ': ', value)
print('\n')
except Exception as e:
print(e)
else:
cid = client.metaWeblog.newPost('',BLOG_USERNAME, BLOG_PASSWORD, struct, True)
if cid != 0:
save_cid(str(filaName), str(cid))
print('\n发布成功(cid={cid}),信息如下:\n'.format(cid=cid))
for key, value in struct.items():
if key != 'description': print(key, ': ', value)
print('\n')
write_to_json_file(file_path, cid)
#还要保存下文件路径和cid的映射关系;
python_script = sys.argv[0]
file_path = sys.argv[2]
vault_path = sys.argv[1]
abs_file_path = os.path.abspath(os.path.join(vault_path, file_path))
#filepath = r"typcho测试草稿.md"
new_post(abs_file_path)
import requests
import json
import os
localImg_url_jsonPath = r"xxx.json"
def write_localimg(local_path, network_path):
# Initialize an empty dictionary to store the data
data = {}
# Check if the JSON file exists
if os.path.exists(localImg_url_jsonPath):
try:
# Load existing data from the JSON file
with open(localImg_url_jsonPath, 'r', encoding='utf-8') as file:
data = json.load(file)
except Exception as e:
# Handle JSON file read/parsing errors
data = {}
# Add or update the mapping for the given local path
data[local_path] = network_path
# Write the updated data back to the JSON file
with open(localImg_url_jsonPath, 'w', encoding='utf-8') as file:
json.dump(data, file, ensure_ascii=False, indent=4)
def check_localimg(image_url):
# Check if the JSON file exists
if not os.path.exists(localImg_url_jsonPath):
return False, ""
try:
# Load the JSON file
with open(localImg_url_jsonPath, 'r', encoding='utf-8') as file:
data = json.load(file)
# Check if the local image path exists in the JSON
if image_url in data:
return True, data[image_url]
else:
return False, ""
except Exception as e:
# Handle JSON file read/parsing errors
return False, ""
def post_upload(image_url):
is_have,web_url = check_localimg(image_url)
if is_have:
return True, web_url
url = "http://127.0.0.1:36677/upload?xxxxx" # alist的上传链接
headers = {'Content-Type': 'apication/json'}
payload = {"list": [image_url]}
try:
response = requests.post(url, headers=headers, data=json.dumps(payload))
if response.status_code == 200:
result = response.json()
success = result.get("success", False)
uploaded_url = result.get("result", [])
uploaded_url = uploaded_url[0]
write_localimg(image_url, uploaded_url)
return success, uploaded_url
else:
return False, []
except Exception as e:
return False, []
if __name__ == "__main__":
img_url = r"xxFigure_1.png"
success, uploaded_url = post_upload(img_url)
print(success, uploaded_url)