Skip to content

Repository files navigation

mowen-go

墨问 OpenAPI 的 Go SDK,覆盖公开文档中的笔记、密钥重置和文件上传接口。需要 Go 1.24 或更新版本,无第三方运行时依赖。

go get github.com/lib-x/mowen-go@v0.1.0

创建笔记

从墨问获取 API Key,通过环境变量传给应用。

package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "time"

    "github.com/lib-x/mowen-go"
)

func main() {
    client, err := mowen.NewClient(os.Getenv("MOWEN_API_KEY"))
    if err != nil {
        log.Fatal(err)
    }
    ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
    defer cancel()

    note, err := client.Notes.Create(ctx, mowen.NoteCreateRequest{
        Body: mowen.Document(
            mowen.Paragraph(mowen.Text("从 Go 写入墨问", mowen.Bold())),
        ),
        Settings: &mowen.NoteCreateSettings{
            AutoPublish: false,
            Tags: []string{"Go"},
        },
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(note.NoteID)
}

Settings 可省略;显式传入时,AutoPublish: false 会保留在请求中。标签最多 10 个,每个最多 30 个字符。创建、编辑的正文根节点必须是 doc。

接口

方法 用途
client.Notes.Create(ctx, request) 创建笔记,返回笔记 ID
client.Notes.Edit(ctx, request) 编辑通过 API 创建的笔记
client.Notes.Set(ctx, request) 设置公开、私密或规则公开
client.Auth.ResetKey(ctx) 重置 API Key,返回新密钥
client.Files.Prepare(ctx, request) 获取本地上传授权表单
client.Files.Upload(ctx, request) 向授权端点投递本地文件
client.Files.UploadViaURL(ctx, request) 由墨问抓取 URL 并上传文件

每个方法都接受 context.Context。公开索引中还有查询相关的数据模型,但没有对应接口路径,因此本版本没有据此推测查询接口。

_, err := client.Notes.Edit(ctx, mowen.NoteEditRequest{
    NoteID: noteID,
    Body: mowen.Document(mowen.Paragraph(mowen.Text("修改后的正文"))),
})

err = client.Notes.Set(ctx, mowen.NoteSetRequest{
    NoteID: noteID,
    Section: mowen.NoteSectionPrivacy,
    Settings: mowen.NoteSettings{
        Privacy: &mowen.NotePrivacySet{Type: mowen.PrivacyPrivate},
    },
})

规则公开使用 PrivacyRule 和 NotePrivacyRule。ExpireAt 是秒级 Unix 时间戳字符串,"0" 表示永久;NoShare: false 表示允许分享。上游规定,规则公开但未传规则时等同于完全公开。

富文本

提供 Document、Paragraph、Text、Bold、Highlight、InlineCode、Link、Quote、Heading、CodeBlock、Image、Audio、PDF 和 NoteReference。

body := mowen.Document(
    mowen.Heading("2", mowen.Text("记录")),
    mowen.Paragraph(mowen.Text("一个链接", mowen.Link("https://mowen.cn"))),
    mowen.Image(imageFileID, "图片说明", "center"),
    mowen.Audio(audioFileID, "00:00 开始"),
    mowen.CodeBlock("fmt.Println(1)", "go"),
)

也可以直接构造 NoteAtom,其 Attrs 为 map[string]string。音频节点使用官方示例中的 audio-uuid,图片和 PDF 使用 uuid。节点包含切片和映射,调用期间不要并发修改请求数据。

文件上传

URL 上传由墨问服务器完成下载:

reply, err := client.Files.UploadViaURL(ctx, mowen.UploadViaURLRequest{
    FileType: mowen.FileTypeImage,
    URL: "https://example.com/photo.png",
    FileName: "photo.png",
})
// 成功后,reply.File.FileID 可用于图片节点。

本地上传分两步。先获取授权,再把服务返回的上传端点和表单传给 Upload:

prepared, err := client.Files.Prepare(ctx, mowen.UploadPrepareRequest{
    FileType: mowen.FileTypeImage,
    FileName: "photo.png",
})
if err != nil {
    return err
}
// 从授权结果中取得 endpoint,form 只包含需要提交的表单字段。
// OpenAPI 仅声明 prepared.Form 为字符串映射,未定义端点字段布局;
// 应按实际返回结果提取,不要将端点元数据混入表单。
_ = prepared

f, err := os.Open("photo.png")
if err != nil {
    return err
}
defer f.Close()
info, err := f.Stat()
if err != nil {
    return err
}
result, err := client.Files.Upload(ctx, mowen.UploadRequest{
    Endpoint: endpoint,
    Form: form,
    FileName: "photo.png",
    Content: f,
    Size: info.Size(),
})
// result 是 json.RawMessage,保留对象存储返回的完整 JSON。

Upload 只接受可信授权结果中的 HTTPS 端点,以已知长度流式投递,文件字段在最后,不发送墨问 API Key 或 Cookie,不跟随重定向。调用者负责关闭文件;Size 必须与要上传的字节数一致,SDK 最多读取该长度。自定义 io.Reader 若可能阻塞,调用者需提供中断它的机制。官方投递示例没有定义成功响应的字段,SDK 不假设它与 URL 上传响应相同。

上游文档给出的大小限制如下,实际校验由服务端执行:

类型 本地上传 URL 上传
图片 小于 50 MB 小于 30 MB
音频 小于 200 MB 小于 100 MB
PDF 小于 100 MB 小于 50 MB

配置、错误与重试

默认地址为 https://open.mowen.cn,每次调用默认超时 30 秒。大文件可用 WithTimeout 延长,也可通过 WithHTTPClient 配置代理或 http.RoundTripper 中间件。WithBaseURL 用于测试或代理环境。

client, err := mowen.NewClient(apiKey,
    mowen.WithTimeout(2*time.Minute),
    mowen.WithHTTPClient(&http.Client{Transport: transport}),
)

SDK 复制传入的 HTTP 客户端,禁用重定向及 Cookie Jar;自定义 Transport 由调用者负责,不能向上传端点注入凭据或自动重放写入。配置完成后可并发使用 Client;不要重新赋值其服务字段。

var apiErr *mowen.APIError
if errors.As(err, &apiErr) {
    switch apiErr.Reason {
    case mowen.ReasonRateLimit:
        // 可读取 RetryAfter,结合业务状态决定后续操作。
    case mowen.ReasonQuota:
        // 当日配额不足。
    case mowen.ReasonPermission:
        // 当前账户无权执行此操作。
    }
}
if errors.Is(err, context.DeadlineExceeded) {
    // 服务端可能已执行写入,先确认状态。
}

APIError 保留 HTTP 状态、code、reason、message、metadata、meta、details、原始响应体及请求 ID。Error() 不输出响应正文;这些诊断字段可能含私密数据,不宜直接写入日志。非 JSON 的错误响应也可通过 APIError 读取。单次响应上限为 8 MiB,超过时返回 ErrResponseTooLarge。

传输错误的 Error() 使用固定描述,原始原因可通过 errors.Is、errors.As 或 errors.Unwrap 检查;原始原因可能含签名 URL,不宜直接记录。HTTP 200 响应若缺少新密钥、笔记 ID、文件 ID 或上传授权表单等必要结果,SDK 也会返回错误。

所有接口默认不自动重试。上游没有公开幂等键协议,超时可能发生在写入成功之后;自动重试创建、上传或密钥重置会产生重复操作或失去有效凭据。各 API 文档标注每个用户、每个接口每秒 1 次,调用者还需结合自己的多实例部署协调限频和日配额。

ResetKey 成功后旧密钥立即失效。请保存返回的 APIKey 并创建新 Client;现有 Client 的密钥不会被修改。SDK 不会在初始化时重置密钥。

来源与验证

接口依据 墨问文档索引,通过 Firecrawl 抓取并核对于 2026-09-08。接口映射、来源差异及设计取舍见 设计文档。这是一份第三方 SDK。

go test -race -cover ./...
go vet ./...
go build ./...

测试使用本地 HTTP/TLS 服务,覆盖请求契约、富文本、文件投递及故障处理。测试不会调用真实账号的写入接口;未使用真实墨问凭据做端到端联调。可编译示例见 example_test.go。

许可证:MIT。

About

墨问api golang

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages