壁纸源协议
🎯 协议概述
小树壁纸源协议 v3.0 是一个模块化、高性能的壁纸源配置系统。通过将配置拆分为多个文件并使用不压缩的 TAR 格式打包,实现了快速加载和易维护性。
核心特性
- 模块化设计:配置文件按功能拆分,便于管理
- 不压缩 TAR 格式:
.ltws格式提供极速加载体验 - 内置变量系统:支持时间、随机数等动态变量
- 全面验证:内置字段验证和质量检查
- 无外部资源:所有图标必须使用 Base64 或外部 URL
📁 文件结构
开发目录结构
- source.toml
- config.toml
- categories.toml
- example_api.toml
- another_api.toml
打包后的 .ltws 文件结构
- source.toml
- config.toml
- categories.toml
- manifest.json
- example_api.toml
- another_api.toml
📋 源数据文件 (source.toml) - 完整字段说明
源数据文件是壁纸源的入口点,定义了基本信息和文件引用。
必需字段
scheme = "littletree_wallpaper_source_v3"
identifier = "com.example.wallpaper_source"
name = "壁纸源名称"
version = "1.0.0"
categories = "categories.toml"
apis = ["apis/*.toml"]完整字段说明
| 字段 | 必填 | 类型 | 默认值 | 说明 | 示例 |
|---|---|---|---|---|---|
scheme | ✅ | 字符串 | - | 协议版本标识 | "littletree_wallpaper_source_v3" |
identifier | ✅ | 字符串 | - | 全局唯一标识符 | "com.example.nature" |
name | ✅ | 字符串 | - | 壁纸源显示名称 | "自然壁纸源" |
version | ✅ | 字符串 | - | 语义化版本 | "1.0.0" |
categories | ✅ | 字符串 | - | 分类文件路径 | "categories.toml" |
apis | ✅ | 数组 | - | API 文件匹配模式 | ["apis/*.toml"] |
config | ❌ | 字符串 | "config.toml" | 配置文件路径 | "config.toml" |
description | ❌ | 字符串 | "" | 简短描述 | "提供高质量自然风景壁纸" |
details | ❌ | 字符串 | "" | 详细说明(Markdown) | "# 详细说明\n支持 Markdown" |
logo | ❌ | 字符串 | "" | 图标(Base64 或 URL) | "data:image/svg+xml;base64,..." |
footer_text | ❌ | 字符串 | "" | 底部文本 | "© 2025 壁纸源" |
字段详细说明
1. scheme (必填)
协议版本标识符,必须是 "littletree_wallpaper_source_v3"。
2. identifier (必填)
壁纸源的全局唯一标识符,遵循反向域名格式:
- 格式:
com.组织名.源名称 - 只能包含小写字母、数字、点号和下划线
- 示例:
"com.example.nature","com.littletree.bing_daily"
3. name (必填)
壁纸源的显示名称,在客户端中可见:
- 建议长度:2-32个字符
- 支持中文、英文等
- 示例:
"自然壁纸源","Bing 每日壁纸"
4. version (必填)
语义化版本号,格式为 "主版本.次版本.修订号":
- 主版本:不兼容的API修改
- 次版本:向下兼容的功能性新增
- 修订号:向下兼容的问题修正
- 示例:
"1.0.0","2.1.3"
5. categories (必填)
分类定义文件的路径,支持相对路径:
- 必须指向一个有效的
.toml文件 - 示例:
"categories.toml","definitions/categories.toml"
6. apis (必填)
API 文件匹配模式列表,支持 glob 模式:
- 至少包含一个模式
- 支持多个模式组合
- 示例:
["apis/*.toml"],["apis/bing.toml", "apis/nature.toml"]
7. config (可选)
配置文件路径,默认为 "config.toml":
- 如果不存在此字段或文件不存在,使用默认配置
- 支持相对路径
- 示例:
"config.toml","configs/main.toml"
8. description (可选)
壁纸源的简短描述,建议长度≤100字符:
- 在客户端中显示
- 简明扼要地说明功能
- 示例:
"提供高质量自然风景壁纸"
9. details (可选)
详细的说明文档,支持 Markdown 格式:
- 更详细的功能介绍
- 使用说明
- 更新日志等
- 示例:
details = """ # 自然壁纸源 ## 特性 - 每日更新高质量壁纸 - 支持多种分辨率 - 无版权问题 ## 使用说明 在设置中选择壁纸源即可使用。 """
10. logo (可选)
壁纸源图标,必须使用 Base64 编码或外部 URL:
- 不允许本地文件路径
- 推荐使用 SVG 格式的 Base64 编码
- 建议尺寸:64×64 或 128×128 像素
- Base64 示例:
"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSIzMiIgY3k9IjMyIiByPSIzMCIgZmlsbD0iIzQyYjdkZSIvPjwvc3ZnPgo=" - URL 示例:
"https://example.com/logo.svg"
11. footer_text (可选)
显示在壁纸详情页面底部的文本:
- 可用于版权声明、来源说明等
- 示例:
"© 2025 自然壁纸 | 图片来自 Bing"
完整示例
# source.toml
scheme = "littletree_wallpaper_source_v3"
identifier = "com.nature.wallpapers"
name = "自然壁纸源"
version = "1.0.0"
# 必需的文件引用
categories = "categories.toml"
apis = ["apis/*.toml"]
# 可选配置
config = "config.toml"
description = "提供高质量自然风景壁纸,每日更新"
# Base64 编码的图标(SVG格式)
logo = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSI1MCIgY3k9IjUwIiByPSI0MCIgc3R5bGU9ImZpbGw6IzQyYjdkZSIvPjwvc3ZnPgo="
# 详细说明(Markdown格式)
details = """
# 自然壁纸源
## 功能特性
- **每日更新**:每天提供新的自然风景壁纸
- **多分辨率**:支持 1080p、2K、4K 等分辨率
- **高质量**:所有图片均经过精选,确保画质
- **无广告**:纯净的壁纸体验
## 使用说明
1. 在客户端中启用本壁纸源
2. 进入「自然」分类查看壁纸
3. 点击喜欢的壁纸设置为桌面
## 更新日志
### v1.0.0 (2025-01-15)
- 初始版本发布
- 支持自然风景壁纸
- 添加每日更新功能
"""
footer_text = "© 2025 自然壁纸源 | 发现世界之美"注意事项
1. 标识符唯一性
identifier 字段必须全局唯一,避免与其他壁纸源冲突。
2. 文件路径
所有文件路径都是相对于 source.toml 所在目录:
my_source/
├── source.toml # 当前文件
├── config.toml # config = "config.toml"
├── categories.toml # categories = "categories.toml"
└── apis/ # apis = ["apis/*.toml"]
└── *.toml3. 图标规范
- 不允许:
logo = "icon.png"(本地文件) - 允许:
logo = "data:image/svg+xml;base64,..."(Base64) - 允许:
logo = "https://example.com/icon.svg"(外部URL)
4. 版本管理
遵循语义化版本规范:
1.0.0→ 初始版本1.0.1→ 修复小问题,向下兼容1.1.0→ 新增功能,向下兼容2.0.0→ 重大更新,可能不兼容
5. 默认值说明
config字段默认值为"config.toml"- 如果配置文件不存在,客户端会使用内置默认配置
- 其他可选字段默认值为空字符串
""
验证规则
必填字段验证
# 验证示例
☑ scheme 必须是 "littletree_wallpaper_source_v3"
☑ identifier 格式正确(com.xxx.xxx)
☑ name 长度在 2-32 字符之间
☑ version 符合语义化版本格式
☑ categories 文件存在
☑ apis 数组非空且匹配到至少一个文件可选字段验证
# 验证示例(如果存在)
☑ config 文件存在(如果指定)
☑ description 长度 ≤ 100 字符
☑ logo 是有效的 Base64 或 URL
☑ details 是有效的字符串
☑ footer_text 长度 ≤ 200 字符常见错误
错误1:缺少必需字段
# ❌ 错误:缺少 identifier
scheme = "littletree_wallpaper_source_v3"
name = "壁纸源"
# 缺少 identifier 字段
# ✅ 正确:包含所有必需字段
scheme = "littletree_wallpaper_source_v3"
identifier = "com.example.source"
name = "壁纸源"
version = "1.0.0"
categories = "categories.toml"
apis = ["apis/*.toml"]错误2:图标使用本地文件
# ❌ 错误:使用本地文件路径
logo = "icon.png" # 不允许
# ✅ 正确:使用 Base64 编码
logo = "data:image/svg+xml;base64,..."
# ✅ 正确:使用外部 URL
logo = "https://example.com/icon.svg"错误3:版本格式错误
# ❌ 错误:版本格式不正确
version = "1.0" # 缺少修订号
version = "v1.0.0" # 包含前缀v
version = "1.0.0.1" # 过多部分
# ✅ 正确:语义化版本
version = "1.0.0"
version = "2.1.3"错误4:标识符格式错误
# ❌ 错误:标识符格式不正确
identifier = "my_source" # 缺少域名部分
identifier = "com.my source" # 包含空格
identifier = "COM.EXAMPLE.SOURCE" # 大写字母
# ✅ 正确:反向域名格式
identifier = "com.example.source"
identifier = "com.littletree.bing"⚙️ 配置文件 (config.toml)
配置文件定义全局请求设置,所有 API 都会继承这些配置。
请求配置
[request]
global_interval_seconds = 3600 # 全局请求间隔(秒),0=不限制
timeout_seconds = 30 # 请求超时时间(秒)
max_concurrent = 3 # 最大并发请求数
skip_ssl_verify = false # 是否跳过 SSL 验证
user_agent = "LittleTreeWallpaper/3.0" # 自定义 User-Agent请求头配置
[request.headers]
Accept = "application/json"
Accept-Language = "zh-CN,zh;q=0.9"
Accept-Encoding = "gzip, deflate"重试策略
[request.retry]
max_attempts = 3 # 最大重试次数
backoff_base = 2.0 # 退避基数(指数退避)
initial_delay_ms = 1000 # 初始延迟(毫秒)缓存配置
[request.cache]
enabled = true # 是否启用缓存
default_ttl_seconds = 300 # 默认缓存时间(秒)
max_memory_mb = 100 # 最大内存缓存大小(MB)说明
[request.cache] 用于描述客户端在进行网络请求时如何缓存响应数据(是否真正缓存、缓存介质、清理策略等最终由客户端实现决定)。
enabled:仅表示“允许/建议启用缓存”的默认开关;客户端可忽略或强制关闭(例如隐私模式/省流模式)。default_ttl_seconds:默认缓存 TTL(秒)。当某个 API 未单独配置[cache]或未提供ttl_seconds时,可使用该值。max_memory_mb:内存缓存上限(MB)。达到上限后如何淘汰(LRU/按TTL/按大小)由客户端决定。
优先级(建议)
当同一个请求同时受多处配置影响时,建议客户端按以下优先级解释:
- API 文件中的
[cache](最具体) - 全局
config.toml的[request.cache] - 客户端内置默认值(或用户设置)
内置变量
[request.variables]
timestamp = "{{timestamp_ms}}" # 当前时间戳(毫秒)
date = "{{date_iso}}" # 当前日期(ISO格式)
date_cn = "{{date_cn}}" # 中文日期
random = "{{random_string:8}}" # 8位随机字符串
random_int = "{{random_int:1:100}}" # 1-100随机整数完整示例
# config.toml
[request]
global_interval_seconds = 1800
timeout_seconds = 20
max_concurrent = 2
skip_ssl_verify = false
user_agent = "MyWallpaperClient/3.0"
[request.headers]
Accept = "application/json"
Accept-Language = "zh-CN"
[request.retry]
max_attempts = 2
backoff_base = 1.5
initial_delay_ms = 500
[request.cache]
enabled = true
default_ttl_seconds = 600
[request.variables]
timestamp = "{{timestamp_ms}}"
date = "{{date_iso}}"
random = "{{random_string:6}}"🗂️ 分类定义文件 (categories.toml)
分类定义文件组织壁纸的分类结构。
分类结构
# 分类模板(可选)
[template]
icon = "data:image/svg+xml;base64,..." # Base64 图标
category = "默认分类"
# 分类列表
[[categories]]
id = "nature" # 必填:分类唯一标识符
name = "自然风光" # 必填:分类显示名称
category = "风景" # 必填:一级分类
subcategory = "自然" # 可选:二级分类
icon = "data:image/svg+xml;base64,..." # 可选:Base64 图标
description = "自然风景壁纸" # 可选:分类描述层级图标支持(可选)
允许为每个层级(category/subcategory/subsubcategory)设置独立的图标,提供更一致的视觉体验。
# 层级图标定义(可选)
[level_icons]
# 一级分类图标(按category值匹配)
[level_icons.category]
风景 = "data:image/svg+xml;base64,..."
自然 = "data:image/svg+xml;base64,..."
二次元 = "data:image/svg+xml;base64,..."
# 二级分类图标(按subcategory值匹配)
[level_icons.subcategory]
山脉 = "data:image/svg+xml;base64,..."
湖泊 = "data:image/svg+xml;base64,..."
动漫 = "data:image/svg+xml;base64,..."
# 三级分类图标(按subsubcategory值匹配)
[level_icons.subsubcategory]
精选 = "data:image/svg+xml;base64,..."
热门 = "data:image/svg+xml;base64,..."
最新 = "data:image/svg+xml;base64,..."图标优先级规则
客户端按以下顺序确定分类显示的图标:
- 分类特定图标:
[[categories]]中的icon字段(最高优先级) - 层级图标:
[level_icons]中匹配的图标(按 subsubcategory → subcategory → category 顺序) - 模板默认图标:
[template]中的icon字段 - 系统默认图标:客户端提供的默认图标(最低优先级)
字段说明
| 字段 | 必填 | 说明 | 示例 |
|---|---|---|---|
id | ✅ | 分类唯一标识符(小写字母、数字、下划线) | "nature" |
name | ✅ | 分类显示名称 | "自然风光" |
category | ✅ | 一级分类 | "风景" |
subcategory | ❌ | 二级分类 | "自然" |
subsubcategory | ❌ | 三级分类 | "精选" |
icon | ❌ | 分类图标(Base64 或 URL) | "data:image/svg+xml;base64,..." |
description | ❌ | 分类描述 | "自然风景壁纸" |
分类分组(可选)
[[category_groups]]
name = "热门分类"
category_ids = ["nature", "anime", "abstract"]
[[category_groups]]
name = "每日更新"
category_ids = ["daily", "trending"]完整示例
# categories.toml
[template]
icon = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTIgMkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMCAxMC00LjQ4IDEwLTEwUzE3LjUyIDIgMTIgMlptMCAxOGMtNC40MSAwLTgtMy41OS04LThzMy41OS04IDgtOCA4IDMuNTkgOCA4LTMuNTkgOC04IDhaIiBmaWxsPSIjNjY2Ii8+PC9zdmc+Cg=="
category = "其他"
[[categories]]
id = "mountain"
name = "山脉"
category = "自然"
subcategory = "风景"
icon = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTIgM0w0IDIxaDE2TDEyIDNaTTEyIDcuNDQyTDkuMTAyIDE2LjVIMTQuODk2TDEyIDcuNDQyWiIgZmlsbD0iIzQyYjdkZSIvPjwvc3ZnPgo="
[[categories]]
id = "anime"
name = "动漫"
category = "二次元"
icon = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTIgMkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMCAxMC00LjQ4IDEwLTEwUzE3LjUyIDIgMTIgMlptMCAxOGMtNC40MSAwLTgtMy41OS04LThzMy41OS04IDgtOCA4IDMuNTkgOCA4LTMuNTkgOC04IDhaIiBmaWxsPSIjRkY2Njk5Ii8+PHBhdGggZD0iTTEyIDE3QzE0Ljc2MTQgMTcgMTcgMTQuNzYxNCAxNyAxMkMxNyA5LjIzODYgMTQuNzYxNCA3IDEyIDdDOS4yMzg2IDcgNyA5LjIzODYgNyAxMkM3IDE0Ljc2MTQgOS4yMzg2IDE3IDEyIDE3WiIgZmlsbD0iI0ZGNjY5OSIvPjwvc3ZnPgo="
# 分类分组
[[category_groups]]
name = "自然分类"
category_ids = ["mountain"]
[[category_groups]]
name = "动漫分类"
category_ids = ["anime"]📡 API 文件 (apis/*.toml)
每个 API 文件定义一个壁纸数据源。
基础结构
# 基本信息
name = "API 名称"
description = "API 功能描述"
logo = "data:image/svg+xml;base64,..." # Base64 图标
# 分类绑定(必填)
categories = ["category_id1", "category_id2"]
# 参数定义
[[parameters]]
key = "param_name"
type = "choice" # choice, text, boolean
label = "参数标签"
default = "默认值"
choices = ["选项1", "选项2"] # choice 类型必需
hidden = false # 是否在 UI 中隐藏
# 请求配置
[request]
url = "https://api.example.com/data?param={{param_name}}"
method = "GET" # GET 或 POST
timeout_seconds = 10 # 覆盖全局配置
interval_seconds = 3600 # 0=使用全局,-1=不限制
# 响应配置
[response]
format = "json" # json, toml, image_url, image_raw, static_list, static_dict
type = "multi" # single, multi
# 字段映射
[mapping]
# 单图模式
image = "/data/url"
title = "/data/title"
# 多图模式
items = "/data/list"
item_mapping = { image = "/url", title = "/name" }参数类型详解
1. 选择类型 (choice)
[[parameters]]
key = "resolution"
type = "choice"
label = "分辨率"
default = "1920x1080"
choices = ["1920x1080", "2560x1440", "3840x2160"]
description = "选择壁纸分辨率"2. 文本类型 (text)
[[parameters]]
key = "keyword"
type = "text"
label = "搜索关键词"
default = ""
placeholder = "输入关键词"
min_length = 1
max_length = 1003. 布尔类型 (boolean)
[[parameters]]
key = "safe_mode"
type = "boolean"
label = "安全模式"
default = true4. 隐藏参数
[[parameters]]
key = "api_key"
type = "text"
default = "ABC123"
hidden = true # 不在UI显示,但参与请求响应格式
1. JSON 格式(最常用)
[response]
format = "json"
type = "multi"
[mapping]
items = "/data/wallpapers"
item_mapping = {
image = "/image_url",
title = "/title",
width = "/width",
height = "/height"
}2. 静态字典 (static_dict)
[response]
format = "static_dict"
[static_dict]
[[items]]
image = "https://example.com/wallpaper1.jpg"
title = "壁纸标题"
description = "壁纸描述"
width = 1920
height = 1080
[[items]]
image = "https://example.com/wallpaper2.jpg"
title = "另一个壁纸"3. 静态列表 (static_list)
[response]
format = "static_list"
[static_list]
urls = [
"https://example.com/w1.jpg",
"https://example.com/w2.jpg",
"https://example.com/w3.jpg"
]4. 图片 URL (image_url)
[response]
format = "image_url"
# 响应体应为单行图片URL5. 原始图片 (image_raw)
[response]
format = "image_raw"
# 响应体应为原始图片二进制数据路径语法
JSON Pointer 语法
# 绝对路径
image = "/data/url"
# 数组索引
image = "/data/images/0/url"
# 通配符(匹配第一个)
image = "/data/images/*/url"
# 递归通配符
image = "/**/image_url"
# 多重路径(按顺序尝试)
image = ["/images/hd_url", "/images/url", "/url"]点号路径语法(用于TOML格式)
image = "data.url"
title = "data.wallpaper.title"验证配置
[validation]
# 必需字段
required_fields = ["image", "title"]
# 字段格式验证
field_patterns = [
{ path = "image", regex = "^https?://.+\\.(jpg|png|webp)$" },
{ path = "title", max_length = 100 }
]
# 数据质量验证
quality_rules = [
{ path = "width", min = 1920 },
{ path = "height", min = 1080 }
]用途
[validation] 用于定义API 响应数据在映射(mapping/post_process)之后的校验规则,帮助客户端:
- 过滤掉不完整/不合规的条目(如没有
image) - 提前发现字段映射错误(路径写错、字段类型不符合预期)
- 做最基本的数据质量门槛控制(分辨率过小、标题过长等)
注意:验证规则描述的是“规则本身”。具体失败后是报错、提示、跳过条目还是回退到备用 API,仍由客户端结合其策略决定。
字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
required_fields | 字符串数组 | 必须存在且非空的字段列表;常用于 image、title 等核心字段。 |
field_patterns | 对象数组 | 字段格式/长度等约束;每条规则以 path 指向目标字段,并附带约束条件。 |
quality_rules | 对象数组 | 字段数值质量门槛;常用于 width/height/size 等数值字段。 |
field_patterns / quality_rules 单条规则对象支持的键(本协议当前文档示例中出现的键):
path(必填):字段路径(与[mapping]使用相同的路径语法;如果最终数据是对象则按键名取值)regex(可选):正则表达式(字符串)。建议客户端使用 RE2/PCRE 等实现均可;是否区分大小写由正则本身决定。min_length/max_length(可选):字符串长度约束min/max(可选):数值范围约束
示例:常见校验
- 要求图片必须是 HTTPS 且为常见图片扩展名:
[validation]
required_fields = ["image"]
field_patterns = [
{ path = "image", regex = "^https://.+\\.(jpg|jpeg|png|webp)$" }
]- 多图模式下,对每个条目要求分辨率不低于 1080p:
[validation]
required_fields = ["image", "width", "height"]
quality_rules = [
{ path = "width", min = 1920 },
{ path = "height", min = 1080 }
]错误处理
[error_handling]
# HTTP状态码处理
http_codes = [
{ code = 429, message = "请求过于频繁", retry_after = 60 },
{ code = 404, message = "内容不存在", fallback = true }
]
# 响应处理错误
on_empty_response = "skip"
on_mapping_failed = "skip_item"用途
[error_handling] 用于描述当请求/解析/映射出现问题时,客户端应如何处理的建议策略。它不会强制客户端的最终行为,但可让同一壁纸源在不同客户端中表现更一致。
HTTP 状态码处理(http_codes)
http_codes 是规则数组,客户端在收到对应 HTTP 状态码时可参考执行:
code(必填):HTTP 状态码message(可选):面向用户或日志的提示文本retry_after(可选):建议等待秒数后再重试。若响应包含Retry-After头,建议客户端优先使用响应头。fallback(可选,布尔):建议允许回退(例如尝试备用 API、返回缓存结果或跳过该 API)
空响应与映射失败
on_empty_response = "skip":当响应体为空(或解析后无有效数据)时,建议“跳过本次结果”(不产生壁纸)。on_mapping_failed = "skip_item":当多图模式下某个条目映射失败时,建议“仅跳过该条目”,其他条目仍可保留。
备用 API(可选)
文档后续最佳实践中会用到备用 API。若你需要在协议内显式声明备用 API,可在 [error_handling] 中追加:
[error_handling]
fallback_to = "backup_api" # 指向 apis/backup_api.toml(按文件名基名匹配)建议客户端在出现以下情况时考虑使用 fallback_to(若实现支持):
- 命中
http_codes中fallback = true的规则 - 连续多次失败且超过
[request.retry]的重试上限
缓存配置
[cache]
enabled = true
ttl_seconds = 86400
key_template = "api_{{param1}}_{{date}}"用途
[cache] 用于定义某个 API 的缓存建议。它通常用于缓存“API 响应”或“解析后的结果列表”,以降低请求频率并提升列表加载速度。
重要:缓存是否启用、使用内存还是磁盘、是否加密、是否跨设备同步等均由客户端决定。即使
enabled = true,客户端也可以完全不缓存。
字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
enabled | 布尔 | 是否建议对该 API 启用缓存。 |
ttl_seconds | 整数 | 缓存 TTL(秒)。建议根据更新频率设置:每日更新用 6-24h;小时级用 5-30min。 |
key_template | 字符串 | 缓存键模板。支持使用请求参数与内置变量(如 {{date_iso}} / {{date}} / {{timestamp_ms}} 等),用于区分不同参数组合的缓存。 |
建议行为
- 若 API 文件存在
[cache],建议其优先级高于config.toml的[request.cache]。 - 对于带有动态参数(如地区、关键词)的 API,建议把关键参数写入
key_template,避免缓存互相污染。
完整 API 示例
# apis/bing_daily.toml
name = "Bing 每日壁纸"
description = "微软Bing每日更新的壁纸"
logo = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTkgMTJIMTFWN0gxOUMyMC4xMDUgNyAyMSA3Ljg5NSA3IDlWMTlDNyAxOC4xMDUgNy44OTUgMTcgOSAxN0gxN1YxMkgyMFYxOEMyMCAyMC4yMDkgMTguMjA5IDIyIDE2IDIySDhDNS43OTEgMjIgNCAyMC4yMDkgNCAxOFY2QzQgMy43OTEgNS43OTEgMiA4IDJIMTZDMTguMjA5IDIgMjAgMy43OTEgMjAgNlYxMkgxOVoiIGZpbGw9IiM0MmI3ZGUiLz48L3N2Zz4K"
categories = ["daily"]
[[parameters]]
key = "mkt"
type = "choice"
label = "地区"
default = "zh-CN"
choices = ["zh-CN", "en-US", "ja-JP"]
[[parameters]]
key = "n"
type = "choice"
label = "数量"
default = "8"
choices = ["1", "5", "8", "15"]
[request]
url = "https://www.bing.com/HPImageArchive.aspx?format=js&n={{n}}&mkt={{mkt}}&ts={{timestamp_ms}}"
method = "GET"
timeout_seconds = 15
interval_seconds = 3600
[request.headers]
Referer = "https://www.bing.com"
[response]
format = "json"
type = "multi"
[mapping]
items = "/images"
item_mapping = {
image = "/url",
title = "/copyright",
startdate = "/startdate"
}
[post_process]
image = "https://www.bing.com{{image}}"
[validation]
required_fields = ["image"]
[error_handling]
http_codes = [
{ code = 429, message = "请求过于频繁", retry_after = 300 }
]
[cache]
enabled = true
ttl_seconds = 43200
key_template = "bing_{{mkt}}_{{date}}"🔧 内置变量系统
时间变量
| 变量 | 说明 | 示例 |
|---|---|---|
{{timestamp_ms}} | 毫秒时间戳 | 1704067200000 |
{{timestamp_s}} | 秒时间戳 | 1704067200 |
{{date_iso}} | ISO 日期 | 2024-01-01 |
{{date_cn}} | 中文日期 | 2024年01月01日 |
{{year}} | 年份 | 2024 |
{{month}} | 月份 | 01 |
{{day}} | 日期 | 01 |
{{hour}} | 小时 | 12 |
{{minute}} | 分钟 | 30 |
{{second}} | 秒 | 45 |
随机变量
| 变量 | 说明 | 示例 |
|---|---|---|
{{random_string:N}} | N位随机字符串 | {{random_string:8}} → aB3dEfG7 |
{{random_int:MIN:MAX}} | MIN到MAX随机整数 | {{random_int:1:100}} → 42 |
{{random_hex:N}} | N位随机十六进制 | {{random_hex:6}} → a1b2c3 |
屏幕变量(由客户端提供)
| 变量 | 说明 | 示例 |
|---|---|---|
{{screen_width}} | 屏幕宽度 | 1920 |
{{screen_height}} | 屏幕高度 | 1080 |
{{screen_ratio}} | 屏幕宽高比 | 1.777 |
📦 打包规范
打包命令
# 基本用法
wallpaper-source-pack source_directory output_file.ltws
# 示例
wallpaper-source-pack ./my_source ./my_source.ltws打包验证
打包工具会验证以下内容:
必需文件检查
- ✅
source.toml存在且有效 - ✅
categories.toml存在且有效 - ✅
apis/目录存在且包含至少一个.toml文件
- ✅
协议版本检查
- ✅
scheme = "littletree_wallpaper_source_v3"
- ✅
资源文件检查
- ⚠️ 发现任何非
.toml文件时警告 - ❌ 不允许包含图片、字体等资源文件
- ⚠️ 发现任何非
文件处理规则
| 文件类型 | 处理方式 | 说明 |
|---|---|---|
source.toml | ✅ 包含 | 必需文件 |
categories.toml | ✅ 包含 | 必需文件 |
apis/*.toml | ✅ 包含 | 必需文件 |
config.toml | ✅ 包含 | 可选文件 |
*.png, *.jpg | ❌ 排除 | 不允许资源文件 |
*.svg, *.ico | ❌ 排除 | 不允许资源文件 |
| 其他文件 | ❌ 排除 | 仅包含配置文件 |
图标处理要求
所有图标必须使用以下方式之一:
Base64 编码
logo = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTIgMkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMCAxMC00LjQ4IDEwLTEwUzE3LjUyIDIgMTIgMlptMCAxOGMtNC40MSAwLTgtMy41OS04LThzMy41OS04IDgtOCA4IDMuNTkgOCA4LTMuNTkgOC04IDhaIiBmaWxsPSIjNDJiN2RlIi8+PC9zdmc+Cg=="外部 URL
logo = "https://example.com/icon.svg"
清单文件 (manifest.json)
打包时自动生成:
{
"format_version": "1.0",
"source_schema": "littletree_wallpaper_source_v3",
"generated_at": "2024-01-15T12:00:00Z",
"tool_version": "wallpaper-source-pack/1.0.0",
"files": [
{
"path": "source.toml",
"sha256": "abc123...",
"size": 1024
}
],
"metadata": {
"name": "自然壁纸源",
"identifier": "com.nature.wallpapers",
"version": "1.0.0"
}
}🚀 快速开始
步骤 1:创建文件结构
mkdir my_wallpaper_source
cd my_wallpaper_source
mkdir apis步骤 2:创建配置文件
source.toml:
scheme = "littletree_wallpaper_source_v3"
identifier = "com.my.first_source"
name = "我的第一个壁纸源"
version = "1.0.0"
categories = "categories.toml"
apis = ["apis/*.toml"]categories.toml:
[[categories]]
id = "simple"
name = "简单壁纸"
category = "示例"apis/simple_api.toml:
name = "简单壁纸"
categories = ["simple"]
[request]
url = "https://picsum.photos/1920/1080"
[response]
format = "image_raw"
type = "single"步骤 3:打包壁纸源
wallpaper-source-pack ./my_wallpaper_source ./my_wallpaper_source.ltws步骤 4:验证打包文件
wallpaper-source-validate ./my_wallpaper_source.ltws✅ 验证清单
必需检查项
-
scheme字段为littletree_wallpaper_source_v3 -
source.toml包含所有必需字段 -
categories.toml包含至少一个分类 -
apis/目录包含至少一个.toml文件 - 所有分类 ID 在 API 中正确引用
- 没有包含资源文件(图片、字体等)
- 所有图标使用 Base64 或外部 URL
推荐检查项
- 设置了合理的请求超时时间
- 配置了验证规则
- 配置了错误处理
- 配置了缓存策略
- 添加了有意义的描述
🔧 开发工具
1. 打包工具
# 安装
pip install wallpaper-source-tools
# 使用
wallpaper-source-pack ./source ./output.ltws
wallpaper-source-validate ./source.ltws
wallpaper-source-ls ./source.ltws2. 图标转换工具
# 将图片转换为 Base64
convert-to-base64 icon.png
# 输出: data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...3. 配置验证工具
# 验证目录结构
wallpaper-source-check ./my_source
# 输出:
# ✅ source.toml: 有效
# ✅ categories.toml: 包含 3 个分类
# ✅ apis/: 包含 5 个 API 文件
# ⚠️ 发现本地图标引用,建议转换为 Base64📊 性能指标
| 操作 | 典型时间 | 内存使用 | 说明 |
|---|---|---|---|
| 加载 .ltws 文件 | 10-50ms | 2-10MB | 不压缩 TAR 格式 |
| 解析配置 | 5-20ms | 1-5MB | TOML 解析 |
| 初始化 API | 1-10ms/API | 可变 | 每个 API 的初始化 |
| 缓存命中 | <1ms | 忽略 | 内存缓存 |
📞 支持与反馈
获取帮助
- 文档:查看完整协议文档
- 示例:参考官方示例壁纸源
- 社区:加入开发者社区讨论
- Issue:在 GitHub 提交问题报告
报告问题
遇到问题时,请提供:
- 壁纸源配置
- 错误信息
- 客户端版本
- 操作系统信息
贡献指南
- Fork 项目仓库
- 创建功能分支
- 提交更改
- 创建 Pull Request
🔀 多壁纸源分类合并(可选)
小树壁纸 Next 客户端可能支持将多个壁纸源的分类合并显示,为用户提供统一的浏览体验。
重要:是否执行“合并”由客户端决定;
source.toml中的[merge]仅用于描述当客户端选择进行合并时,各壁纸源在冲突与优先级上的建议行为。客户端可以忽略或覆盖这些建议。
声明合并行为(供客户端在合并时参考)
在 source.toml 中添加 [merge] 配置节,用于声明当分类发生合并时的行为:
# source.toml 中的合并配置
[merge]
enabled = true # 参与合并的建议开关(默认:false;客户端可忽略/覆盖)
strategy = "same_id" # 合并策略:same_id(相同ID)、same_name(相同名称)
priority = 100 # 合并优先级(0-1000,默认:100)
metadata_source = "high_priority" # 元数据来源:high_priority(高优先级源)、first_loaded(最先加载)、last_updated(最后更新)
allow_metadata_override = true # 是否允许其他源覆盖本源的分类元数据合并策略详解
1. 相同ID合并(strategy = "same_id")
- 规则:仅合并具有相同
id的分类 - 示例:两个壁纸源都有
id = "nature"的分类,合并为一个分类 - 适用场景:标准化分类ID,实现跨源内容聚合
2. 相同名称合并(strategy = "same_name")
- 规则:合并具有相同
name的分类(忽略ID差异) - 示例:一个源有
name = "自然风光",另一个源也有name = "自然风光",合并为一个分类 - 适用场景:不同源对相同主题使用不同ID但相同名称
元数据冲突解决
当多个壁纸源的分类合并时,按以下规则确定显示的元数据:
1. 优先级规则(metadata_source = "high_priority")
- 使用
priority值最高的壁纸源的元数据 priority相同时,使用版本号更高的源- 版本号相同时,使用最后加载的源
2. 加载顺序规则(metadata_source = "first_loaded")
- 使用最先加载的壁纸源的元数据
- 简单稳定,但可能不是最优选择
3. 更新时间规则(metadata_source = "last_updated")
- 使用最近更新的壁纸源的元数据
- 适合需要显示最新信息的场景
合并示例
源A(优先级:150):
# categories.toml
[[categories]]
id = "nature"
name = "自然风光"
category = "风景"
icon = "data:image/svg+xml;base64,A"
description = "源A的自然壁纸"源B(优先级:100):
# categories.toml
[[categories]]
id = "nature"
name = "自然风景"
category = "自然"
icon = "data:image/svg+xml;base64,B"
description = "源B的自然壁纸"合并结果(使用 high_priority 策略):
- 显示名称:“自然风光”(源A,优先级更高)
- 分类路径:“风景”(源A,优先级更高)
- 图标:使用源A的图标
- 描述:“源A的自然壁纸”
- 壁纸内容:包含源A和源B的所有壁纸
分类分组合并
分类分组(category_groups)也会根据合并策略进行合并:
- 相同名称的分组合并
- 合并后的分组包含所有源的相关分类
- 分组元数据使用相同的优先级规则
注意事项
- 性能影响:合并会增加客户端处理复杂度,建议合理设置优先级
- 一致性:建议相关壁纸源使用一致的分类命名规范
- 测试建议:在启用合并前,测试不同源的兼容性
- 用户控制:客户端可能允许用户手动选择合并策略或禁用特定源的合并
最佳实践
# 推荐配置
[merge]
enabled = true
strategy = "same_id" # 更精确的合并
priority = 100 # 中等优先级,允许其他源覆盖
metadata_source = "high_priority" # 公平的元数据选择
allow_metadata_override = true # 允许更好的源提供更优元数据
# 特殊场景:作为基础源(不希望被覆盖)
[merge]
enabled = true
strategy = "same_id"
priority = 1000 # 最高优先级,确保元数据不被覆盖
metadata_source = "high_priority"
allow_metadata_override = false # 禁止其他源覆盖🎯 最佳实践
1. 图标处理
# 推荐:使用 Base64 编码的小图标
logo = "data:image/svg+xml;base64,..." # SVG 格式最佳
# 可选:使用外部 CDN
logo = "https://cdn.example.com/icon.svg"
# 不推荐:大尺寸图片或本地文件
# logo = "icon.png" # ❌ 不允许2. 性能优化
# 设置合理的缓存时间
[cache]
ttl_seconds = 3600 # 根据更新频率设置
# 使用多图 API 减少请求次数
[response]
type = "multi" # 而不是多次调用单图 API3. 错误处理
# 配置降级策略
[error_handling]
fallback_to = "backup_api" # 引用备用 API
# 设置合理的重试策略
[request.retry]
max_attempts = 2 # 避免无限重试4. 安全性
# 使用 HTTPS
url = "https://api.example.com/data" # ✅ 推荐
# 隐藏敏感参数
[[parameters]]
key = "api_key"
hidden = true # 不在 UI 显示最后更新: 2025年12月13日
协议版本: v3.0
文件格式: .ltws (不压缩 TAR)
图标要求: Base64 或外部 URL
本协议文档适用于小树壁纸 Next(Little Tree Wallpaper Next)客户端 v1.0.0 及以上版本