kv-anki-connect/README-zh.md
2025-06-06 15:10:15 +08:00

8415 lines
193 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Anki-Connect
Anki-Connect使外部应用程序如Yomichan能够通过简单的HTTP API与[Anki](https://apps.ankiweb.net/)进行通信。它的功能包括对用户卡片组执行查询、自动创建新卡片等。Anki-Connect与最新的稳定版(2.1.x)Anki兼容旧版本(2.0.x及以下)不再受支持。
## 安装
安装过程与其他Anki插件类似可以通过以下三个步骤完成
1. 在Anki中选择`工具` | `插件` | `获取插件...`,打开`安装插件`对话框。
2. 在标有`代码`的文本框中输入[2055492159](https://ankiweb.net/shared/info/2055492159),然后按`确定`按钮继续。
3. 当提示重启Anki时请按照要求进行操作以完成Anki-Connect的安装。
Anki必须在后台保持运行以便其他应用程序能够使用Anki-Connect。您可以随时通过在浏览器中访问`localhost:8765`来验证Anki-Connect是否在运行。如果服务器正在运行您将在浏览器窗口中看到`Anki-Connect`的消息。
### Windows用户注意事项
Windows用户可能会在Anki启动时看到防火墙提示对话框。这是因为Anki-Connect运行了本地HTTP服务器以便其他应用程序能够连接到它。主应用程序Anki必须被允许通过防火墙此插件才能正常运行。
### MacOS用户注意事项
从[Mac OS X Mavericks](https://en.wikipedia.org/wiki/OS_X_Mavericks)开始,操作系统引入了名为*App Nap*的功能。此功能会使某些已打开但不可见的应用程序进入挂起状态。由于此行为会导致Anki-Connect在前台显示其他窗口时停止工作因此应为Anki禁用App Nap
1. 启动终端应用程序。
2. 在终端窗口中执行以下命令:
```bash
defaults write net.ankiweb.dtop NSAppSleepDisabled -bool true
defaults write net.ichi2.anki NSAppSleepDisabled -bool true
defaults write org.qt-project.Qt.QtWebEngineCore NSAppSleepDisabled -bool true
```
3. 重启Anki。
## 开发者应用程序接口
Anki-Connect通过易于使用的API向外部应用程序公开Anki的内部功能。安装后只要启动Anki该插件就会在8765端口启动HTTP服务器。其他应用程序包括浏览器扩展可以通过HTTP请求与其通信。
默认情况下Anki-Connect只会将HTTP服务器绑定到`127.0.0.1`IP地址因此您只能从运行它的同一主机访问它。如果您需要通过网络访问可以在配置中更改绑定地址。进入工具->插件->AnkiConnect->配置,更改"webBindAddress"值。例如,您可以将其设置为`0.0.0.0`以将其绑定到主机上的所有网络接口。这也需要重启Anki。
### 调用示例
每个请求都由一个包含`action`、`version`、上下文`params`和用于认证的`key`值可选默认可以省略的JSON编码对象组成。Anki-Connect将返回一个包含两个字段的对象`result`和`error`。`result`字段包含执行的API的返回值而`error`字段是在API执行期间抛出的任何异常的描述如果执行成功则使用值`null`)。
*成功响应示例*
```json
{"result": ["Default", "Filtered Deck 1"], "error": null}
```
*失败响应示例*
```json
{"result": null, "error": "unsupported action"}
```
```json
{"result": null, "error": "guiBrowse() got an unexpected keyword argument 'foobar'"}
```
为了与旧版本Anki-Connect设计的客户端兼容如果请求中未提供`version`字段版本将默认为4。此外当提供的版本为4级或以下时API响应将只包含`result`的值;没有`error`字段可用于错误处理。
您可以使用任何语言或工具向Anki-Connect发出请求但下面包含了几个简单的示例作为参考。
#### Curl
```bash
curl localhost:8765 -X POST -d '{"action": "deckNames", "version": 6}'
```
#### Powershell
```powershell
(Invoke-RestMethod -Uri http://localhost:8765 -Method Post -Body '{"action": "deckNames", "version": 6}').result
```
#### Python
```python
import json
import urllib.request
def request(action, **params):
return {'action': action, 'params': params, 'version': 6}
def invoke(action, **params):
requestJson = json.dumps(request(action, **params)).encode('utf-8')
response = json.load(urllib.request.urlopen(urllib.request.Request('http://127.0.0.1:8765', requestJson)))
if len(response) != 2:
raise Exception('response has an unexpected number of fields')
if 'error' not in response:
raise Exception('response is missing required error field')
if 'result' not in response:
raise Exception('response is missing required result field')
if response['error'] is not None:
raise Exception(response['error'])
return response['result']
invoke('createDeck', deck='test1')
result = invoke('deckNames')
print('got list of decks: {}'.format(result))
```
#### JavaScript
```javascript
function invoke(action, version, params={}) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.addEventListener('error', () => reject('failed to issue request'));
xhr.addEventListener('load', () => {
try {
const response = JSON.parse(xhr.responseText);
if (Object.getOwnPropertyNames(response).length != 2) {
throw 'response has an unexpected number of fields';
}
if (!response.hasOwnProperty('error')) {
throw 'response is missing required error field';
}
if (!response.hasOwnProperty('result')) {
throw 'response is missing required result field';
}
if (response.error) {
throw response.error;
}
resolve(response.result);
} catch (e) {
reject(e);
}
});
xhr.open('POST', 'http://127.0.0.1:8765');
xhr.send(JSON.stringify({action, version, params}));
});
}
await invoke('createDeck', 6, {deck: 'test1'});
const result = await invoke('deckNames', 6);
console.log(`got list of decks: ${result}`);
```
### 认证
Anki-Connect支持要求认证以便进行API请求。
默认情况下,此支持是*禁用*的但可以通过在Anki-Config的设置工具->插件->AnkiConnect->配置)中设置`apiKey`字段为所需的字符串来启用。
如果您已经这样做,您应该会看到[`requestPermission`](#requestpermission) API请求返回`true`作为`requireApiKey`。
然后您必须在任何进一步的API请求体中包含一个名为`key`的附加参数其值必须与配置的API密钥匹配。
### 嘿你能添加一个新的action来支持$FEATURE吗
Anki-Connect的主要目标是支持来自Yomichan浏览器扩展的实时闪卡创建。当前的API提供了所有必要的动作来实现这一点。我认识到Anki-Connect的角色已经从这一最初愿景演变而且我很乐意审查新的功能请求。
话虽如此,*本项目采用自助服务模式*。如果你想要一个新功能请创建一个PR。我会审查它如果看起来不错就会合并。*没有附带拉取请求的添加新功能的请求将不会得到处理*。确保你的拉取请求满足以下标准:
* 尝试匹配周围代码的风格。
* 有附带的文档和示例。
* 有验证操作的附带测试。
* 实现在其他应用中有用的功能。
## 支持的动作
当前支持的动作的文档按类别分类并在下面引用。请注意已弃用的API将继续运行尽管未在此页面上列出只要您的请求标有对应API可用时的版本号。搜索参数传递给Anki更多信息请查看文档https://docs.ankiweb.net/searching.html
* [卡片操作](#card-actions)
* [卡组操作](#deck-actions)
* [图形界面操作](#graphical-actions)
* [媒体操作](#media-actions)
* [杂项操作](#miscellaneous-actions)
* [模型操作](#model-actions)
* [笔记操作](#note-actions)
* [统计操作](#statistic-actions)
---
### 卡片操作
#### `getEaseFactors`
* 返回一个数组,包含给定卡片的简易度因子(按相同顺序)。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "getEaseFactors",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [4100, 3900],
"error": null
}
```
</details>
#### `setEaseFactors`
* 通过卡片ID设置卡片的简易度因子如果成功所有卡片都存在则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "setEaseFactors",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217],
"easeFactors": [4100, 3900]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [true, true],
"error": null
}
```
</details>
#### `setSpecificValueOfCard`
* 设置单个卡片的特定值。由于更改卡片的某些值可能会在数据库中造成混乱,一些键需要将参数"warning_check"设置为True。
这可用于设置卡片的标志、更改其简易度因子、更改筛选卡组中的复习顺序以及更改列"data"目前显然未被anki使用以及许多其他值。
可以在[AnkiDroid的wiki](https://github.com/ankidroid/Anki-Android/wiki/Database-Structure)上找到值的列表及其各自的用途解释。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "setSpecificValueOfCard",
"version": 6,
"params": {
"card": 1483959291685,
"keys": ["flags", "odue"],
"newValues": ["1", "-100"]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [true, true],
"error": null
}
```
</details>
#### `suspend`
* 通过卡片ID暂停卡片如果成功至少有一张卡片之前没有被暂停则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "suspend",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `unsuspend`
* 通过卡片ID取消暂停卡片如果成功至少有一张卡片之前被暂停则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "unsuspend",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `suspended`
* 通过ID检查卡片是否被暂停。如果被暂停则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "suspended",
"version": 6,
"params": {
"card": 1483959293217
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `areSuspended`
* 返回一个数组,表示每张给定卡片是否被暂停(按相同顺序)。如果卡片不存在,则返回`null`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "areSuspended",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217, 1234567891234]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [false, true, null],
"error": null
}
```
</details>
#### `areDue`
* 返回一个数组,表示每张给定卡片是否到期(按相同顺序)。*注意*学习队列中有大间隔超过20分钟的卡片被视为未到期直到其间隔时间过去为止这与Anki在复习时对待它们的方式相匹配。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "areDue",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [false, true],
"error": null
}
```
</details>
#### `getIntervals`
* 返回一个数组包含每个给定卡片ID的最近间隔或者当`complete`为`true`时返回每个给定卡片ID的所有间隔的二维数组。负间隔以秒为单位正间隔以天为单位。
<details>
<summary><i>示例请求1</i></summary>
```json
{
"action": "getIntervals",
"version": 6,
"params": {
"cards": [1502298033753, 1502298036657]
}
}
```
</details>
<details>
<summary><i>示例结果1</i></summary>
```json
{
"result": [-14400, 3],
"error": null
}
```
</details>
<details>
<summary><i>示例请求2</i></summary>
```json
{
"action": "getIntervals",
"version": 6,
"params": {
"cards": [1502298033753, 1502298036657],
"complete": true
}
}
```
</details>
<details>
<summary><i>示例结果2</i></summary>
```json
{
"result": [
[-120, -180, -240, -300, -360, -14400],
[-120, -180, -240, -300, -360, -14400, 1, 3]
],
"error": null
}
```
</details>
#### `findCards`
* 返回给定查询的卡片ID数组。功能上与`guiBrowse`相同但不使用GUI以获得更好的性能。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "findCards",
"version": 6,
"params": {
"query": "deck:current"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [1494723142483, 1494703460437, 1494703479525],
"error": null
}
```
</details>
#### `cardsToNotes`
* 返回给定卡片ID的笔记ID的无序数组。对于具有相同笔记的卡片ID在数组中只给出一次。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "cardsToNotes",
"version": 6,
"params": {
"cards": [1502098034045, 1502098034048, 1502298033753]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [1502098029797, 1502298025183],
"error": null
}
```
</details>
#### `cardsModTime`
* 返回一个对象列表包含每个卡片ID的修改时间。
此功能比执行`cardsInfo`快约15倍。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "cardsModTime",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [
{
"cardId": 1498938915662,
"mod": 1629454092
}
],
"error": null
}
```
</details>
#### `cardsInfo`
* 返回一个对象列表包含每个卡片ID的卡片字段、正反面包括CSS、笔记类型、卡片所属的笔记、卡组名称、最后修改时间戳以及简易度和间隔。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "cardsInfo",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [
{
"answer": "back content",
"question": "front content",
"deckName": "Default",
"modelName": "Basic",
"fieldOrder": 1,
"fields": {
"Front": {"value": "front content", "order": 0},
"Back": {"value": "back content", "order": 1}
},
"css":"p {font-family:Arial;}",
"cardId": 1498938915662,
"interval": 16,
"note":1502298033753,
"ord": 1,
"type": 0,
"queue": 0,
"due": 1,
"reps": 1,
"lapses": 0,
"left": 6,
"mod": 1629454092
},
{
"answer": "back content",
"question": "front content",
"deckName": "Default",
"modelName": "Basic",
"fieldOrder": 0,
"fields": {
"Front": {"value": "front content", "order": 0},
"Back": {"value": "back content", "order": 1}
},
"css":"p {font-family:Arial;}",
"cardId": 1502098034048,
"interval": 23,
"note":1502298033753,
"ord": 1,
"type": 0,
"queue": 0,
"due": 1,
"reps": 1,
"lapses": 0,
"left": 6
}
],
"error": null
}
```
</details>
#### `forgetCards`
* 忘记卡片,使卡片再次成为新卡片。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "forgetCards",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `relearnCards`
* 使卡片成为"重新学习"状态。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "relearnCards",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `answerCards`
* 回答卡片。简易度在1重来到4简单之间。将在回答前立即开始计时器。如果卡片存在则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "answerCards",
"version": 6,
"params": {
"answers": [
{
"cardId": 1498938915662,
"ease": 2
},
{
"cardId": 1502098034048,
"ease": 4
}
]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [true, true],
"error": null
}
```
</details>
#### `setDueDate`
* 设置到期日期。如果是新卡片,则将其转为复习卡片,并使其在特定日期到期。
* 0 = 今天
* 1! = 明天 + 将间隔更改为1
* 3-7 = 随机选择3-7天
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "setDueDate",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048],
"days": "3-7"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
---
### 卡组操作
#### `deckNames`
* 获取当前用户的完整卡组名称列表。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "deckNames",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": ["Default"],
"error": null
}
```
</details>
#### `deckNamesAndIds`
* 获取当前用户的完整卡组名称及其对应ID的列表。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "deckNamesAndIds",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": {"Default": 1},
"error": null
}
```
</details>
#### `getDecks`
* 接受一个卡片ID数组并返回一个对象其中每个卡组名称作为键其值是属于该卡组的给定卡片数组。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "getDecks",
"version": 6,
"params": {
"cards": [1502298036657, 1502298033753, 1502032366472]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": {
"Default": [1502032366472],
"Japanese::JLPT N3": [1502298036657, 1502298033753]
},
"error": null
}
```
</details>
#### `createDeck`
* 创建一个新的空卡组。不会覆盖同名的已存在卡组。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "createDeck",
"version": 6,
"params": {
"deck": "Japanese::Tokyo"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": 1519323742721,
"error": null
}
```
</details>
#### `changeDeck`
* 将具有给定ID的卡片移动到不同的卡组如果卡组尚不存在则创建它。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "changeDeck",
"version": 6,
"params": {
"cards": [1502098034045, 1502098034048, 1502298033753],
"deck": "Japanese::JLPT N3"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `deleteDecks`
* 删除具有给定名称的卡组。
参数`cardsToo` *必须*被指定并设置为`true`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "deleteDecks",
"version": 6,
"params": {
"decks": ["Japanese::JLPT N5", "Easy Spanish"],
"cardsToo": true
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `getDeckConfig`
* 获取给定卡组的配置组对象。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "getDeckConfig",
"version": 6,
"params": {
"deck": "Default"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": {
"lapse": {
"leechFails": 8,
"delays": [10],
"minInt": 1,
"leechAction": 0,
"mult": 0
},
"dyn": false,
"autoplay": true,
"mod": 1502970872,
"id": 1,
"maxTaken": 60,
"new": {
"bury": true,
"order": 1,
"initialFactor": 2500,
"perDay": 20,
"delays": [1, 10],
"separate": true,
"ints": [1, 4, 7]
},
"name": "Default",
"rev": {
"bury": true,
"ivlFct": 1,
"ease4": 1.3,
"maxIvl": 36500,
"perDay": 100,
"minSpace": 1,
"fuzz": 0.05
},
"timer": 0,
"replayq": true,
"usn": -1
},
"error": null
}
```
</details>
#### `saveDeckConfig`
* 保存给定的配置组,成功时返回`true`如果配置组的ID无效例如不存在则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "saveDeckConfig",
"version": 6,
"params": {
"config": {
"lapse": {
"leechFails": 8,
"delays": [10],
"minInt": 1,
"leechAction": 0,
"mult": 0
},
"dyn": false,
"autoplay": true,
"mod": 1502970872,
"id": 1,
"maxTaken": 60,
"new": {
"bury": true,
"order": 1,
"initialFactor": 2500,
"perDay": 20,
"delays": [1, 10],
"separate": true,
"ints": [1, 4, 7]
},
"name": "Default",
"rev": {
"bury": true,
"ivlFct": 1,
"ease4": 1.3,
"maxIvl": 36500,
"perDay": 100,
"minSpace": 1,
"fuzz": 0.05
},
"timer": 0,
"replayq": true,
"usn": -1
}
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `setDeckConfigId`
* 将给定卡组的配置组更改为具有给定ID的配置组。成功时返回`true`,如果给定的配置组或任何给定的卡组不存在则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "setDeckConfigId",
"version": 6,
"params": {
"decks": ["Default"],
"configId": 1
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `cloneDeckConfigId`
* 使用给定的名称创建一个新的配置组从具有给定ID的组克隆或者如果未指定则从默认组克隆。返回新配置组的ID或者如果指定的要克隆的组不存在则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "cloneDeckConfigId",
"version": 6,
"params": {
"name": "Copy of Default",
"cloneFrom": 1
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": 1502972374573,
"error": null
}
```
</details>
#### `removeDeckConfigId`
* 移除具有给定ID的配置组如果成功则返回`true`如果尝试移除默认配置组ID = 1或不存在的配置组则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "removeDeckConfigId",
"version": 6,
"params": {
"configId": 1502972374573
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `getDeckStats`
* 获取给定卡组的统计信息,如总卡片数和到期卡片数。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "getDeckStats",
"version": 6,
"params": {
"decks": ["Japanese::JLPT N5", "Easy Spanish"]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": {
"1651445861967": {
"deck_id": 1651445861967,
"name": "Japanese::JLPT N5",
"new_count": 20,
"learn_count": 0,
"review_count": 0,
"total_in_deck": 1506
},
"1651445861960": {
"deck_id": 1651445861960,
"name": "Easy Spanish",
"new_count": 26,
"learn_count": 10,
"review_count": 5,
"total_in_deck": 852
}
},
"error": null
}
```
</details>
---
### 图形界面操作
#### `guiBrowse`
* 调用*卡片浏览器*对话框并搜索给定查询。返回找到的卡片标识符数组。查询语法[在此处有文档](https://docs.ankiweb.net/searching.html)。
可选地,可以提供`reorderCards`属性来重新排序*卡片浏览器*中显示的卡片。
这是一个包含`order`和`columnId`对象的数组。`order`可以是`ascending`或`descending`,而`columnId`可以是几个列标识符之一(如在[Anki源代码](https://github.com/ankitects/anki/blob/main/rslib/src/browser_table.rs)中记录的)。
指定的列需要在*卡片浏览器*中可见。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiBrowse",
"version": 6,
"params": {
"query": "deck:current",
"reorderCards": {
"order": "descending",
"columnId": "noteCrt"
}
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [1494723142483, 1494703460437, 1494703479525],
"error": null
}
```
</details>
#### `guiSelectCard`
* 找到*卡片浏览器*对话框的打开实例,并根据卡片标识符选择一张卡片。
如果*卡片浏览器*是打开的,返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiSelectCard",
"version": 6,
"params": {
"card": 1494723142483
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiSelectedNotes`
* 找到*卡片浏览器*对话框的打开实例,并返回选中笔记的标识符数组。如果浏览器未打开,则返回空列表。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiSelectedNotes",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [1494723142483, 1494703460437, 1494703479525],
"error": null
}
```
</details>
#### `guiAddCards`
* 调用*添加卡片*对话框,使用给定的卡组和模型预设笔记,带有提供的字段值和标签。
多次调用会关闭旧窗口并_重新打开窗口_使用新提供的值。
可以通过`audio`、`video`和`picture`键将音频、视频和图片文件嵌入到字段中。
请参考`addNote`和`storeMediaFile`的文档,了解这些字段的说明。
结果是如果用户选择确认*添加卡片*对话框将添加的笔记的ID。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiAddCards",
"version": 6,
"params": {
"note": {
"deckName": "Default",
"modelName": "Cloze",
"fields": {
"Text": "The capital of Romania is {{c1::Bucharest}}",
"Extra": "Romania is a country in Europe"
},
"tags": [
"countries"
],
"picture": [{
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/EU-Romania.svg/285px-EU-Romania.svg.png",
"filename": "romania.png",
"fields": [
"Extra"
]
}]
}
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": 1496198395707,
"error": null
}
```
</details>
#### `guiEditNote`
* 打开*编辑*对话框显示对应于给定笔记ID的笔记。
该对话框类似于*编辑当前*对话框,但:
* 有一个预览按钮,用于预览笔记的卡片
* 有一个浏览按钮,用于打开浏览器并显示这些卡片
* 有上一个/后退按钮,用于导航对话框的历史
* 没有带有关闭按钮的栏
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiEditNote",
"version": 6,
"params": {
"note": 1649198355435
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `guiCurrentCard`
* 返回有关当前卡片的信息,如果不在复习模式,则返回`null`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiCurrentCard",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": {
"answer": "back content",
"question": "front content",
"deckName": "Default",
"modelName": "Basic",
"fieldOrder": 0,
"fields": {
"Front": {"value": "front content", "order": 0},
"Back": {"value": "back content", "order": 1}
},
"template": "Forward",
"cardId": 1498938915662,
"buttons": [1, 2, 3],
"nextReviews": ["<1m", "<10m", "4d"]
},
"error": null
}
```
</details>
#### `guiStartCardTimer`
* 启动或重置当前卡片的`timerStarted`值。这对于将开始时间推迟到通过API显示卡片时很有用从而在调用`guiAnswerCard`时使记录的回答卡片所花费的时间更准确。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiStartCardTimer",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiShowQuestion`
* 显示当前卡片的问题文本;如果处于复习模式则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiShowQuestion",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiShowAnswer`
* 显示当前卡片的答案文本;如果处于复习模式则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiShowAnswer",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiAnswerCard`
* 回答当前卡片;如果成功则返回`true`,否则返回`false`。注意在Anki接受任何答案之前必须先显示当前卡片的答案。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiAnswerCard",
"version": 6,
"params": {
"ease": 1
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiUndo`
* 撤销最后一个动作/卡片;如果成功则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiUndo",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiDeckOverview`
* 为具有给定名称的卡组打开*卡组概览*对话框;如果成功则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiDeckOverview",
"version": 6,
"params": {
"name": "Default"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiDeckBrowser`
* 打开*卡组浏览器*对话框。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiDeckBrowser",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `guiDeckReview`
* 开始复习具有给定名称的卡组;如果成功则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiDeckReview",
"version": 6,
"params": {
"name": "Default"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiImportFile`
* 调用*导入...(Ctrl+Shift+I)*对话框并可选择提供文件路径。弹出对话框供用户审核导入。支持Anki支持的所有文件类型。如果未提供路径则显示打开文件对话框。在Windows上的路径中必须使用正斜杠。仅支持Anki 2.1.52+。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiImportFile",
"version": 6,
"params": {
"path": "C:/Users/Desktop/cards.txt"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `guiExitAnki`
* 安排一个请求来优雅地关闭Anki。此操作是异步的因此它会立即返回而不会等待Anki进程实际终止。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiExitAnki",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `guiCheckDatabase`
* 请求进行数据库检查,但立即返回而不等待检查完成。因此,即使在数据库检查过程中检测到错误,此操作也将始终返回`true`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiCheckDatabase",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
---
### 媒体操作
#### `storeMediaFile`
* 将具有指定base64编码内容的文件存储在媒体文件夹中。或者您可以指定绝对文件路径或者从中下载文件的URL。如果提供了`data`、`path`和`url`中的多个,将首先使用`data`字段,然后是`path`,最后是`url`。为了防止Anki删除不被任何卡片使用的文件例如配置文件请在文件名前加下划线。这些文件仍然会同步到AnkiWeb。
默认情况下,将删除任何同名的现有文件。设置`deleteExisting`为false可以通过[让Anki为新文件提供非冲突的名称](https://github.com/ankitects/anki/blob/aeba725d3ea9628c73300648f748140db3fdd5ed/rslib/src/media/files.rs#L194)来防止这种情况。
<details>
<summary><i>示例请求(相对路径):</i></summary>
```json
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"data": "SGVsbG8sIHdvcmxkIQ=="
}
}
```
*`_hello.txt`的内容*:
```
Hello world!
```
</details>
<details>
<summary><i>示例结果(相对路径):</i></summary>
```json
{
"result": "_hello.txt",
"error": null
}
```
</details>
<details>
<summary><i>示例请求(绝对路径):</i></summary>
```json
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"path": "/path/to/file"
}
}
```
</details>
<details>
<summary><i>示例结果(绝对路径):</i></summary>
```json
{
"result": "_hello.txt",
"error": null
}
```
</details>
<details>
<summary><i>示例请求url</i></summary>
```json
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"url": "https://url.to.file"
}
}
```
</details>
<details>
<summary><i>示例结果url</i></summary>
```json
{
"result": "_hello.txt",
"error": null
}
```
</details>
#### `retrieveMediaFile`
* 检索指定文件的base64编码内容如果文件不存在则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "retrieveMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": "SGVsbG8sIHdvcmxkIQ==",
"error": null
}
```
</details>
#### `getMediaFilesNames`
* 获取与模式匹配的媒体文件名。默认返回所有名称。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "getMediaFilesNames",
"version": 6,
"params": {
"pattern": "_hell*.txt"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": ["_hello.txt"],
"error": null
}
```
</details>
#### `getMediaDirPath`
* 获取当前打开的配置文件的`collection.media`文件夹的完整路径。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "getMediaDirPath",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": "/home/user/.local/share/Anki2/Main/collection.media",
"error": null
}
```
</details>
#### `deleteMediaFile`
* 删除媒体文件夹中的指定文件。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "deleteMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
---
### 杂项操作
#### `requestPermission`
* 请求使用此插件公开的API的权限。此方法不需要API密钥是唯一接受来自任何来源的请求的方法其他方法只接受来自受信任来源的请求这些来源列在插件配置的`webCorsOriginList`下。默认情况下,`localhost`是受信任的。
从不受信任的来源调用此方法将在Anki中显示一个弹出窗口询问用户是否允许您的来源使用API来自受信任来源的调用将返回结果而不显示弹出窗口。
在拒绝许可时,用户还可以选择忽略来自该来源的进一步许可请求。这些来源最终会出现在`ignoreOriginList`中,可通过插件配置进行编辑。
结果始终包含`permission`字段,该字段反过来包含字符串`granted`或`denied`,对应于您的来源是否受信任。如果您的来源受信任,还将返回字段`requireApiKey`(如果需要则为`true`)和`version`。
这应该是您进行的第一个调用以确保您的应用程序和Anki-Connect能够相互正确通信。新版本的Anki-Connect向后兼容只要您使用在报告的Anki-Connect版本或更早版本中可用的操作一切都应该正常工作。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "requestPermission",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": {
"permission": "granted",
"requireApiKey": false,
"version": 6
},
"error": null
}
```
```json
{
"result": {
"permission": "denied"
},
"error": null
}
```
</details>
#### `version`
* 获取此插件公开的API的版本。目前定义了版本`1`到`6`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "version",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": 6,
"error": null
}
```
</details>
#### `apiReflect`
* 获取有关可用AnkiConnect API的信息。请求支持以下参数
<!-- filepath: /Users/xion/dev2/kv-anki-connect/README-ZH.md -->
# Anki-Connect
Anki-Connect使外部应用程序如Yomichan能够通过简单的HTTP API与[Anki](https://apps.ankiweb.net/)进行通信。它的功能包括对用户卡片组执行查询、自动创建新卡片等。Anki-Connect与最新的稳定版(2.1.x)Anki兼容旧版本(2.0.x及以下)不再受支持。
## 安装
安装过程与其他Anki插件类似可以通过以下三个步骤完成
1. 在Anki中选择`工具` | `插件` | `获取插件...`,打开`安装插件`对话框。
2. 在标有`代码`的文本框中输入[2055492159](https://ankiweb.net/shared/info/2055492159),然后按`确定`按钮继续。
3. 当提示重启Anki时请按照要求进行操作以完成Anki-Connect的安装。
Anki必须在后台保持运行以便其他应用程序能够使用Anki-Connect。您可以随时通过在浏览器中访问`localhost:8765`来验证Anki-Connect是否在运行。如果服务器正在运行您将在浏览器窗口中看到`Anki-Connect`的消息。
### Windows用户注意事项
Windows用户可能会在Anki启动时看到防火墙提示对话框。这是因为Anki-Connect运行了本地HTTP服务器以便其他应用程序能够连接到它。主应用程序Anki必须被允许通过防火墙此插件才能正常运行。
### MacOS用户注意事项
从[Mac OS X Mavericks](https://en.wikipedia.org/wiki/OS_X_Mavericks)开始,操作系统引入了名为*App Nap*的功能。此功能会使某些已打开但不可见的应用程序进入挂起状态。由于此行为会导致Anki-Connect在前台显示其他窗口时停止工作因此应为Anki禁用App Nap
1. 启动终端应用程序。
2. 在终端窗口中执行以下命令:
```bash
defaults write net.ankiweb.dtop NSAppSleepDisabled -bool true
defaults write net.ichi2.anki NSAppSleepDisabled -bool true
defaults write org.qt-project.Qt.QtWebEngineCore NSAppSleepDisabled -bool true
```
3. 重启Anki。
## 开发者应用程序接口
Anki-Connect通过易于使用的API向外部应用程序公开Anki的内部功能。安装后只要启动Anki该插件就会在8765端口启动HTTP服务器。其他应用程序包括浏览器扩展可以通过HTTP请求与其通信。
默认情况下Anki-Connect只会将HTTP服务器绑定到`127.0.0.1`IP地址因此您只能从运行它的同一主机访问它。如果您需要通过网络访问可以在配置中更改绑定地址。进入工具->插件->AnkiConnect->配置,更改"webBindAddress"值。例如,您可以将其设置为`0.0.0.0`以将其绑定到主机上的所有网络接口。这也需要重启Anki。
### 调用示例
每个请求都由一个包含`action`、`version`、上下文`params`和用于认证的`key`值可选默认可以省略的JSON编码对象组成。Anki-Connect将返回一个包含两个字段的对象`result`和`error`。`result`字段包含执行的API的返回值而`error`字段是在API执行期间抛出的任何异常的描述如果执行成功则使用值`null`)。
*成功响应示例*
```json
{"result": ["Default", "Filtered Deck 1"], "error": null}
```
*失败响应示例*
```json
{"result": null, "error": "unsupported action"}
```
```json
{"result": null, "error": "guiBrowse() got an unexpected keyword argument 'foobar'"}
```
为了与旧版本Anki-Connect设计的客户端兼容如果请求中未提供`version`字段版本将默认为4。此外当提供的版本为4级或以下时API响应将只包含`result`的值;没有`error`字段可用于错误处理。
您可以使用任何语言或工具向Anki-Connect发出请求但下面包含了几个简单的示例作为参考。
#### Curl
```bash
curl localhost:8765 -X POST -d '{"action": "deckNames", "version": 6}'
```
#### Powershell
```powershell
(Invoke-RestMethod -Uri http://localhost:8765 -Method Post -Body '{"action": "deckNames", "version": 6}').result
```
#### Python
```python
import json
import urllib.request
def request(action, **params):
return {'action': action, 'params': params, 'version': 6}
def invoke(action, **params):
requestJson = json.dumps(request(action, **params)).encode('utf-8')
response = json.load(urllib.request.urlopen(urllib.request.Request('http://127.0.0.1:8765', requestJson)))
if len(response) != 2:
raise Exception('response has an unexpected number of fields')
if 'error' not in response:
raise Exception('response is missing required error field')
if 'result' not in response:
raise Exception('response is missing required result field')
if response['error'] is not None:
raise Exception(response['error'])
return response['result']
invoke('createDeck', deck='test1')
result = invoke('deckNames')
print('got list of decks: {}'.format(result))
```
#### JavaScript
```javascript
function invoke(action, version, params={}) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.addEventListener('error', () => reject('failed to issue request'));
xhr.addEventListener('load', () => {
try {
const response = JSON.parse(xhr.responseText);
if (Object.getOwnPropertyNames(response).length != 2) {
throw 'response has an unexpected number of fields';
}
if (!response.hasOwnProperty('error')) {
throw 'response is missing required error field';
}
if (!response.hasOwnProperty('result')) {
throw 'response is missing required result field';
}
if (response.error) {
throw response.error;
}
resolve(response.result);
} catch (e) {
reject(e);
}
});
xhr.open('POST', 'http://127.0.0.1:8765');
xhr.send(JSON.stringify({action, version, params}));
});
}
await invoke('createDeck', 6, {deck: 'test1'});
const result = await invoke('deckNames', 6);
console.log(`got list of decks: ${result}`);
```
### 认证
Anki-Connect支持要求认证以便进行API请求。
默认情况下,此支持是*禁用*的但可以通过在Anki-Config的设置工具->插件->AnkiConnect->配置)中设置`apiKey`字段为所需的字符串来启用。
如果您已经这样做,您应该会看到[`requestPermission`](#requestpermission) API请求返回`true`作为`requireApiKey`。
然后您必须在任何进一步的API请求体中包含一个名为`key`的附加参数其值必须与配置的API密钥匹配。
### 嘿你能添加一个新的action来支持$FEATURE吗
Anki-Connect的主要目标是支持来自Yomichan浏览器扩展的实时闪卡创建。当前的API提供了所有必要的动作来实现这一点。我认识到Anki-Connect的角色已经从这一最初愿景演变而且我很乐意审查新的功能请求。
话虽如此,*本项目采用自助服务模式*。如果你想要一个新功能请创建一个PR。我会审查它如果看起来不错就会合并。*没有附带拉取请求的添加新功能的请求将不会得到处理*。确保你的拉取请求满足以下标准:
* 尝试匹配周围代码的风格。
* 有附带的文档和示例。
* 有验证操作的附带测试。
* 实现在其他应用中有用的功能。
## 支持的动作
当前支持的动作的文档按类别分类并在下面引用。请注意已弃用的API将继续运行尽管未在此页面上列出只要您的请求标有对应API可用时的版本号。搜索参数传递给Anki更多信息请查看文档https://docs.ankiweb.net/searching.html
* [卡片操作](#card-actions)
* [卡组操作](#deck-actions)
* [图形界面操作](#graphical-actions)
* [媒体操作](#media-actions)
* [杂项操作](#miscellaneous-actions)
* [模型操作](#model-actions)
* [笔记操作](#note-actions)
* [统计操作](#statistic-actions)
---
### 卡片操作
#### `getEaseFactors`
* 返回一个数组,包含给定卡片的简易度因子(按相同顺序)。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "getEaseFactors",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [4100, 3900],
"error": null
}
```
</details>
#### `setEaseFactors`
* 通过卡片ID设置卡片的简易度因子如果成功所有卡片都存在则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "setEaseFactors",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217],
"easeFactors": [4100, 3900]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [true, true],
"error": null
}
```
</details>
#### `setSpecificValueOfCard`
* 设置单个卡片的特定值。由于更改卡片的某些值可能会在数据库中造成混乱,一些键需要将参数"warning_check"设置为True。
这可用于设置卡片的标志、更改其简易度因子、更改筛选卡组中的复习顺序以及更改列"data"目前显然未被anki使用以及许多其他值。
可以在[AnkiDroid的wiki](https://github.com/ankidroid/Anki-Android/wiki/Database-Structure)上找到值的列表及其各自的用途解释。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "setSpecificValueOfCard",
"version": 6,
"params": {
"card": 1483959291685,
"keys": ["flags", "odue"],
"newValues": ["1", "-100"]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [true, true],
"error": null
}
```
</details>
#### `suspend`
* 通过卡片ID暂停卡片如果成功至少有一张卡片之前没有被暂停则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "suspend",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `unsuspend`
* 通过卡片ID取消暂停卡片如果成功至少有一张卡片之前被暂停则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "unsuspend",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `suspended`
* 通过ID检查卡片是否被暂停。如果被暂停则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "suspended",
"version": 6,
"params": {
"card": 1483959293217
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `areSuspended`
* 返回一个数组,表示每张给定卡片是否被暂停(按相同顺序)。如果卡片不存在,则返回`null`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "areSuspended",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217, 1234567891234]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [false, true, null],
"error": null
}
```
</details>
#### `areDue`
* 返回一个数组,表示每张给定卡片是否到期(按相同顺序)。*注意*学习队列中有大间隔超过20分钟的卡片被视为未到期直到其间隔时间过去为止这与Anki在复习时对待它们的方式相匹配。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "areDue",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [false, true],
"error": null
}
```
</details>
#### `getIntervals`
* 返回一个数组包含每个给定卡片ID的最近间隔或者当`complete`为`true`时返回每个给定卡片ID的所有间隔的二维数组。负间隔以秒为单位正间隔以天为单位。
<details>
<summary><i>示例请求1</i></summary>
```json
{
"action": "getIntervals",
"version": 6,
"params": {
"cards": [1502298033753, 1502298036657]
}
}
```
</details>
<details>
<summary><i>示例结果1</i></summary>
```json
{
"result": [-14400, 3],
"error": null
}
```
</details>
<details>
<summary><i>示例请求2</i></summary>
```json
{
"action": "getIntervals",
"version": 6,
"params": {
"cards": [1502298033753, 1502298036657],
"complete": true
}
}
```
</details>
<details>
<summary><i>示例结果2</i></summary>
```json
{
"result": [
[-120, -180, -240, -300, -360, -14400],
[-120, -180, -240, -300, -360, -14400, 1, 3]
],
"error": null
}
```
</details>
#### `findCards`
* 返回给定查询的卡片ID数组。功能上与`guiBrowse`相同但不使用GUI以获得更好的性能。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "findCards",
"version": 6,
"params": {
"query": "deck:current"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [1494723142483, 1494703460437, 1494703479525],
"error": null
}
```
</details>
#### `cardsToNotes`
* 返回给定卡片ID的笔记ID的无序数组。对于具有相同笔记的卡片ID在数组中只给出一次。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "cardsToNotes",
"version": 6,
"params": {
"cards": [1502098034045, 1502098034048, 1502298033753]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [1502098029797, 1502298025183],
"error": null
}
```
</details>
#### `cardsModTime`
* 返回一个对象列表包含每个卡片ID的修改时间。
此功能比执行`cardsInfo`快约15倍。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "cardsModTime",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [
{
"cardId": 1498938915662,
"mod": 1629454092
}
],
"error": null
}
```
</details>
#### `cardsInfo`
* 返回一个对象列表包含每个卡片ID的卡片字段、正反面包括CSS、笔记类型、卡片所属的笔记、卡组名称、最后修改时间戳以及简易度和间隔。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "cardsInfo",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [
{
"answer": "back content",
"question": "front content",
"deckName": "Default",
"modelName": "Basic",
"fieldOrder": 1,
"fields": {
"Front": {"value": "front content", "order": 0},
"Back": {"value": "back content", "order": 1}
},
"css":"p {font-family:Arial;}",
"cardId": 1498938915662,
"interval": 16,
"note":1502298033753,
"ord": 1,
"type": 0,
"queue": 0,
"due": 1,
"reps": 1,
"lapses": 0,
"left": 6,
"mod": 1629454092
},
{
"answer": "back content",
"question": "front content",
"deckName": "Default",
"modelName": "Basic",
"fieldOrder": 0,
"fields": {
"Front": {"value": "front content", "order": 0},
"Back": {"value": "back content", "order": 1}
},
"css":"p {font-family:Arial;}",
"cardId": 1502098034048,
"interval": 23,
"note":1502298033753,
"ord": 1,
"type": 0,
"queue": 0,
"due": 1,
"reps": 1,
"lapses": 0,
"left": 6
}
],
"error": null
}
```
</details>
#### `forgetCards`
* 忘记卡片,使卡片再次成为新卡片。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "forgetCards",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `relearnCards`
* 使卡片成为"重新学习"状态。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "relearnCards",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `answerCards`
* 回答卡片。简易度在1重来到4简单之间。将在回答前立即开始计时器。如果卡片存在则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "answerCards",
"version": 6,
"params": {
"answers": [
{
"cardId": 1498938915662,
"ease": 2
},
{
"cardId": 1502098034048,
"ease": 4
}
]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [true, true],
"error": null
}
```
</details>
#### `setDueDate`
* 设置到期日期。如果是新卡片,则将其转为复习卡片,并使其在特定日期到期。
* 0 = 今天
* 1! = 明天 + 将间隔更改为1
* 3-7 = 随机选择3-7天
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "setDueDate",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048],
"days": "3-7"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
---
### 卡组操作
#### `deckNames`
* 获取当前用户的完整卡组名称列表。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "deckNames",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": ["Default"],
"error": null
}
```
</details>
#### `deckNamesAndIds`
* 获取当前用户的完整卡组名称及其对应ID的列表。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "deckNamesAndIds",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": {"Default": 1},
"error": null
}
```
</details>
#### `getDecks`
* 接受一个卡片ID数组并返回一个对象其中每个卡组名称作为键其值是属于该卡组的给定卡片数组。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "getDecks",
"version": 6,
"params": {
"cards": [1502298036657, 1502298033753, 1502032366472]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": {
"Default": [1502032366472],
"Japanese::JLPT N3": [1502298036657, 1502298033753]
},
"error": null
}
```
</details>
#### `createDeck`
* 创建一个新的空卡组。不会覆盖同名的已存在卡组。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "createDeck",
"version": 6,
"params": {
"deck": "Japanese::Tokyo"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": 1519323742721,
"error": null
}
```
</details>
#### `changeDeck`
* 将具有给定ID的卡片移动到不同的卡组如果卡组尚不存在则创建它。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "changeDeck",
"version": 6,
"params": {
"cards": [1502098034045, 1502098034048, 1502298033753],
"deck": "Japanese::JLPT N3"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `deleteDecks`
* 删除具有给定名称的卡组。
参数`cardsToo` *必须*被指定并设置为`true`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "deleteDecks",
"version": 6,
"params": {
"decks": ["Japanese::JLPT N5", "Easy Spanish"],
"cardsToo": true
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `getDeckConfig`
* 获取给定卡组的配置组对象。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "getDeckConfig",
"version": 6,
"params": {
"deck": "Default"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": {
"lapse": {
"leechFails": 8,
"delays": [10],
"minInt": 1,
"leechAction": 0,
"mult": 0
},
"dyn": false,
"autoplay": true,
"mod": 1502970872,
"id": 1,
"maxTaken": 60,
"new": {
"bury": true,
"order": 1,
"initialFactor": 2500,
"perDay": 20,
"delays": [1, 10],
"separate": true,
"ints": [1, 4, 7]
},
"name": "Default",
"rev": {
"bury": true,
"ivlFct": 1,
"ease4": 1.3,
"maxIvl": 36500,
"perDay": 100,
"minSpace": 1,
"fuzz": 0.05
},
"timer": 0,
"replayq": true,
"usn": -1
},
"error": null
}
```
</details>
#### `saveDeckConfig`
* 保存给定的配置组,成功时返回`true`如果配置组的ID无效例如不存在则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "saveDeckConfig",
"version": 6,
"params": {
"config": {
"lapse": {
"leechFails": 8,
"delays": [10],
"minInt": 1,
"leechAction": 0,
"mult": 0
},
"dyn": false,
"autoplay": true,
"mod": 1502970872,
"id": 1,
"maxTaken": 60,
"new": {
"bury": true,
"order": 1,
"initialFactor": 2500,
"perDay": 20,
"delays": [1, 10],
"separate": true,
"ints": [1, 4, 7]
},
"name": "Default",
"rev": {
"bury": true,
"ivlFct": 1,
"ease4": 1.3,
"maxIvl": 36500,
"perDay": 100,
"minSpace": 1,
"fuzz": 0.05
},
"timer": 0,
"replayq": true,
"usn": -1
}
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `setDeckConfigId`
* 将给定卡组的配置组更改为具有给定ID的配置组。成功时返回`true`,如果给定的配置组或任何给定的卡组不存在则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "setDeckConfigId",
"version": 6,
"params": {
"decks": ["Default"],
"configId": 1
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `cloneDeckConfigId`
* 使用给定的名称创建一个新的配置组从具有给定ID的组克隆或者如果未指定则从默认组克隆。返回新配置组的ID或者如果指定的要克隆的组不存在则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "cloneDeckConfigId",
"version": 6,
"params": {
"name": "Copy of Default",
"cloneFrom": 1
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": 1502972374573,
"error": null
}
```
</details>
#### `removeDeckConfigId`
* 移除具有给定ID的配置组如果成功则返回`true`如果尝试移除默认配置组ID = 1或不存在的配置组则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "removeDeckConfigId",
"version": 6,
"params": {
"configId": 1502972374573
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `getDeckStats`
* 获取给定卡组的统计信息,如总卡片数和到期卡片数。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "getDeckStats",
"version": 6,
"params": {
"decks": ["Japanese::JLPT N5", "Easy Spanish"]
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": {
"1651445861967": {
"deck_id": 1651445861967,
"name": "Japanese::JLPT N5",
"new_count": 20,
"learn_count": 0,
"review_count": 0,
"total_in_deck": 1506
},
"1651445861960": {
"deck_id": 1651445861960,
"name": "Easy Spanish",
"new_count": 26,
"learn_count": 10,
"review_count": 5,
"total_in_deck": 852
}
},
"error": null
}
```
</details>
---
### 图形界面操作
#### `guiBrowse`
* 调用*卡片浏览器*对话框并搜索给定查询。返回找到的卡片标识符数组。查询语法[在此处有文档](https://docs.ankiweb.net/searching.html)。
可选地,可以提供`reorderCards`属性来重新排序*卡片浏览器*中显示的卡片。
这是一个包含`order`和`columnId`对象的数组。`order`可以是`ascending`或`descending`,而`columnId`可以是几个列标识符之一(如在[Anki源代码](https://github.com/ankitects/anki/blob/main/rslib/src/browser_table.rs)中记录的)。
指定的列需要在*卡片浏览器*中可见。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiBrowse",
"version": 6,
"params": {
"query": "deck:current",
"reorderCards": {
"order": "descending",
"columnId": "noteCrt"
}
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [1494723142483, 1494703460437, 1494703479525],
"error": null
}
```
</details>
#### `guiSelectCard`
* 找到*卡片浏览器*对话框的打开实例,并根据卡片标识符选择一张卡片。
如果*卡片浏览器*是打开的,返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiSelectCard",
"version": 6,
"params": {
"card": 1494723142483
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiSelectedNotes`
* 找到*卡片浏览器*对话框的打开实例,并返回选中笔记的标识符数组。如果浏览器未打开,则返回空列表。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiSelectedNotes",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": [1494723142483, 1494703460437, 1494703479525],
"error": null
}
```
</details>
#### `guiAddCards`
* 调用*添加卡片*对话框,使用给定的卡组和模型预设笔记,带有提供的字段值和标签。
多次调用会关闭旧窗口并_重新打开窗口_使用新提供的值。
可以通过`audio`、`video`和`picture`键将音频、视频和图片文件嵌入到字段中。
请参考`addNote`和`storeMediaFile`的文档,了解这些字段的说明。
结果是如果用户选择确认*添加卡片*对话框将添加的笔记的ID。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiAddCards",
"version": 6,
"params": {
"note": {
"deckName": "Default",
"modelName": "Cloze",
"fields": {
"Text": "The capital of Romania is {{c1::Bucharest}}",
"Extra": "Romania is a country in Europe"
},
"tags": [
"countries"
],
"picture": [{
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/EU-Romania.svg/285px-EU-Romania.svg.png",
"filename": "romania.png",
"fields": [
"Extra"
]
}]
}
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": 1496198395707,
"error": null
}
```
</details>
#### `guiEditNote`
* 打开*编辑*对话框显示对应于给定笔记ID的笔记。
该对话框类似于*编辑当前*对话框,但:
* 有一个预览按钮,用于预览笔记的卡片
* 有一个浏览按钮,用于打开浏览器并显示这些卡片
* 有上一个/后退按钮,用于导航对话框的历史
* 没有带有关闭按钮的栏
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiEditNote",
"version": 6,
"params": {
"note": 1649198355435
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `guiCurrentCard`
* 返回有关当前卡片的信息,如果不在复习模式,则返回`null`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiCurrentCard",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": {
"answer": "back content",
"question": "front content",
"deckName": "Default",
"modelName": "Basic",
"fieldOrder": 0,
"fields": {
"Front": {"value": "front content", "order": 0},
"Back": {"value": "back content", "order": 1}
},
"template": "Forward",
"cardId": 1498938915662,
"buttons": [1, 2, 3],
"nextReviews": ["<1m", "<10m", "4d"]
},
"error": null
}
```
</details>
#### `guiStartCardTimer`
* 启动或重置当前卡片的`timerStarted`值。这对于将开始时间推迟到通过API显示卡片时很有用从而在调用`guiAnswerCard`时使记录的回答卡片所花费的时间更准确。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiStartCardTimer",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiShowQuestion`
* 显示当前卡片的问题文本;如果处于复习模式则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiShowQuestion",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiShowAnswer`
* 显示当前卡片的答案文本;如果处于复习模式则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiShowAnswer",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiAnswerCard`
* 回答当前卡片;如果成功则返回`true`,否则返回`false`。注意在Anki接受任何答案之前必须先显示当前卡片的答案。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiAnswerCard",
"version": 6,
"params": {
"ease": 1
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiUndo`
* 撤销最后一个动作/卡片;如果成功则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiUndo",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiDeckOverview`
* 为具有给定名称的卡组打开*卡组概览*对话框;如果成功则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiDeckOverview",
"version": 6,
"params": {
"name": "Default"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiDeckBrowser`
* 打开*卡组浏览器*对话框。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiDeckBrowser",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `guiDeckReview`
* 开始复习具有给定名称的卡组;如果成功则返回`true`,否则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiDeckReview",
"version": 6,
"params": {
"name": "Default"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `guiImportFile`
* 调用*导入...(Ctrl+Shift+I)*对话框并可选择提供文件路径。弹出对话框供用户审核导入。支持Anki支持的所有文件类型。如果未提供路径则显示打开文件对话框。在Windows上的路径中必须使用正斜杠。仅支持Anki 2.1.52+。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiImportFile",
"version": 6,
"params": {
"path": "C:/Users/Desktop/cards.txt"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `guiExitAnki`
* 安排一个请求来优雅地关闭Anki。此操作是异步的因此它会立即返回而不会等待Anki进程实际终止。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiExitAnki",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `guiCheckDatabase`
* 请求进行数据库检查,但立即返回而不等待检查完成。因此,即使在数据库检查过程中检测到错误,此操作也将始终返回`true`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "guiCheckDatabase",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
---
### 媒体操作
#### `storeMediaFile`
* 将具有指定base64编码内容的文件存储在媒体文件夹中。或者您可以指定绝对文件路径或者从中下载文件的URL。如果提供了`data`、`path`和`url`中的多个,将首先使用`data`字段,然后是`path`,最后是`url`。为了防止Anki删除不被任何卡片使用的文件例如配置文件请在文件名前加下划线。这些文件仍然会同步到AnkiWeb。
默认情况下,将删除任何同名的现有文件。设置`deleteExisting`为false可以通过[让Anki为新文件提供非冲突的名称](https://github.com/ankitects/anki/blob/aeba725d3ea9628c73300648f748140db3fdd5ed/rslib/src/media/files.rs#L194)来防止这种情况。
<details>
<summary><i>示例请求(相对路径):</i></summary>
```json
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"data": "SGVsbG8sIHdvcmxkIQ=="
}
}
```
*`_hello.txt`的内容*:
```
Hello world!
```
</details>
<details>
<summary><i>示例结果(相对路径):</i></summary>
```json
{
"result": "_hello.txt",
"error": null
}
```
</details>
<details>
<summary><i>示例请求(绝对路径):</i></summary>
```json
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"path": "/path/to/file"
}
}
```
</details>
<details>
<summary><i>示例结果(绝对路径):</i></summary>
```json
{
"result": "_hello.txt",
"error": null
}
```
</details>
<details>
<summary><i>示例请求url</i></summary>
```json
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"url": "https://url.to.file"
}
}
```
</details>
<details>
<summary><i>示例结果url</i></summary>
```json
{
"result": "_hello.txt",
"error": null
}
```
</details>
#### `retrieveMediaFile`
* 检索指定文件的base64编码内容如果文件不存在则返回`false`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "retrieveMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": "SGVsbG8sIHdvcmxkIQ==",
"error": null
}
```
</details>
#### `getMediaFilesNames`
* 获取与模式匹配的媒体文件名。默认返回所有名称。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "getMediaFilesNames",
"version": 6,
"params": {
"pattern": "_hell*.txt"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": ["_hello.txt"],
"error": null
}
```
</details>
#### `getMediaDirPath`
* 获取当前打开的配置文件的`collection.media`文件夹的完整路径。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "getMediaDirPath",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": "/home/user/.local/share/Anki2/Main/collection.media",
"error": null
}
```
</details>
#### `deleteMediaFile`
* 删除媒体文件夹中的指定文件。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "deleteMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt"
}
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
---
### 杂项操作
#### `requestPermission`
* 请求使用此插件公开的API的权限。此方法不需要API密钥是唯一接受来自任何来源的请求的方法其他方法只接受来自受信任来源的请求这些来源列在插件配置的`webCorsOriginList`下。默认情况下,`localhost`是受信任的。
从不受信任的来源调用此方法将在Anki中显示一个弹出窗口询问用户是否允许您的来源使用API来自受信任来源的调用将返回结果而不显示弹出窗口。
在拒绝许可时,用户还可以选择忽略来自该来源的进一步许可请求。这些来源最终会出现在`ignoreOriginList`中,可通过插件配置进行编辑。
结果始终包含`permission`字段,该字段反过来包含字符串`granted`或`denied`,对应于您的来源是否受信任。如果您的来源受信任,还将返回字段`requireApiKey`(如果需要则为`true`)和`version`。
这应该是您进行的第一个调用以确保您的应用程序和Anki-Connect能够相互正确通信。新版本的Anki-Connect向后兼容只要您使用在报告的Anki-Connect版本或更早版本中可用的操作一切都应该正常工作。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "requestPermission",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": {
"permission": "granted",
"requireApiKey": false,
"version": 6
},
"error": null
}
```
```json
{
"result": {
"permission": "denied"
},
"error": null
}
```
</details>
#### `version`
* 获取此插件公开的API的版本。目前定义了版本`1`到`6`。
<details>
<summary><i>示例请求:</i></summary>
```json
{
"action": "version",
"version": 6
}
```
</details>
<details>
<summary><i>示例结果:</i></summary>
```json
{
"result": 6,
"error": null
}
```
</details>
#### `apiReflect`
* 获取有关可用 AnkiConnect API 的信息。请求支持以下参数:
* `scopes` - 要获取反射信息的作用域数组。
目前唯一支持的值是 `"actions"`。
* `actions` - 可以是 `null` 或者 API 方法名称的数组。
如果值为 `null`,结果将列出所有可用的 API 动作。
如果值是字符串数组,结果将只包含该数组中存在的动作。
结果将包含使用了哪些作用域及每个作用域的值。
例如,`"actions"` 作用域将包含一个 `"actions"` 属性,其中包含支持的动作名称列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "apiReflect",
"version": 6,
"params": {
"scopes": ["actions", "invalidType"],
"actions": ["apiReflect", "invalidMethod"]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": {
"scopes": ["actions"],
"actions": ["apiReflect"]
},
"error": null
}
```
</details>
#### `sync`
* 将本地 Anki 集合与 AnkiWeb 同步。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "sync",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `getProfiles`
* 获取个人资料列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "getProfiles",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": ["User 1"],
"error": null
}
```
</details>
#### `getActiveProfile`
* 获取当前活动个人资料。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "getActiveProfile",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": "User 1",
"error": null
}
```
</details>
#### `loadProfile`
* 选择请求中指定的个人资料。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "loadProfile",
"version": 6,
"params": {
"name": "user1"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `multi`
* 在一个请求中执行多个操作,返回一个数组,其中包含每个操作的响应(按给定顺序)。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "multi",
"version": 6,
"params": {
"actions": [
{
"action": "deckNames"
},
{
"action": "deckNames",
"version": 6
},
{
"action": "invalidAction",
"params": {"useless": "param"}
},
{
"action": "invalidAction",
"params": {"useless": "param"},
"version": 6
}
]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [
["Default"],
{"result": ["Default"], "error": null},
{"result": null, "error": "unsupported action"},
{"result": null, "error": "unsupported action"}
],
"error": null
}
```
</details>
#### `exportPackage`
* 将指定的牌组以 `.apkg` 格式导出。如果成功则返回 `true`,否则返回 `false`。可以指定可选属性
`includeSched`(默认为 `false`)以包含卡片的调度数据。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "exportPackage",
"version": 6,
"params": {
"deck": "Default",
"path": "/data/Deck.apkg",
"includeSched": true
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `importPackage`
* 将 `.apkg` 格式的文件导入集合中。如果成功则返回 `true`,否则返回 `false`。
注意,文件路径是相对于 Anki 的 collection.media 文件夹,而不是相对于客户端。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "importPackage",
"version": 6,
"params": {
"path": "/data/Deck.apkg"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `reloadCollection`
* 告诉 Anki 从数据库重新加载所有数据。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "reloadCollection",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
---
### 模型(笔记类型)操作
#### `modelNames`
* 获取当前用户的完整模型名称列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelNames",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": ["Basic", "Basic (and reversed card)"],
"error": null
}
```
</details>
#### `modelNamesAndIds`
* 获取当前用户的完整模型名称及其对应的 ID 列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelNamesAndIds",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": {
"Basic": 1483883011648,
"Basic (and reversed card)": 1483883011644,
"Basic (optional reversed card)": 1483883011631,
"Cloze": 1483883011630
},
"error": null
}
```
</details>
#### `findModelsById`
* 根据提供的模型 ID 从当前用户获取模型列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "findModelsById",
"version": 6,
"params": {
"modelIds": [1704387367119, 1704387398570]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [
{
"id": 1704387367119,
"name": "Basic",
"type": 0,
"mod": 1704387367,
"usn": -1,
"sortf": 0,
"did": null,
"tmpls": [
{
"name": "Card 1",
"ord": 0,
"qfmt": "{{Front}}",
"afmt": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": 9176047152973362695
}
],
"flds": [
{
"name": "Front",
"ord": 0,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": 2453723143453745216,
"tag": null,
"preventDeletion": false
},
{
"name": "Back",
"ord": 1,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": -4853200230425436781,
"tag": null,
"preventDeletion": false
}
],
"css": ".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n",
"latexPre": "\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n",
"latexPost": "\\end{document}",
"latexsvg": false,
"req": [
[
0,
"any",
[
0
]
]
],
"originalStockKind": 1
},
{
"id": 1704387398570,
"name": "Basic (and reversed card)",
"type": 0,
"mod": 1704387398,
"usn": -1,
"sortf": 0,
"did": null,
"tmpls": [
{
"name": "Card 1",
"ord": 0,
"qfmt": "{{Front}}",
"afmt": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": 1689886528158874152
},
{
"name": "Card 2",
"ord": 1,
"qfmt": "{{Back}}",
"afmt": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Front}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": -7839609225644824587
}
],
"flds": [
{
"name": "Front",
"ord": 0,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": -7787837672455357996,
"tag": null,
"preventDeletion": false
},
{
"name": "Back",
"ord": 1,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": 6364828289839985081,
"tag": null,
"preventDeletion": false
}
],
"css": ".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n",
"latexPre": "\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n",
"latexPost": "\\end{document}",
"latexsvg": false,
"req": [
[
0,
"any",
[
0
]
],
[
1,
"any",
[
1
]
]
],
"originalStockKind": 1
}
],
"error": null
}
```
</details>
#### `findModelsByName`
* 根据提供的模型名称从当前用户获取模型列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "findModelsByName",
"version": 6,
"params": {
"modelNames": ["Basic", "Basic (and reversed card)"]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [
{
"id": 1704387367119,
"name": "Basic",
"type": 0,
"mod": 1704387367,
"usn": -1,
"sortf": 0,
"did": null,
"tmpls": [
{
"name": "Card 1",
"ord": 0,
"qfmt": "{{Front}}",
"afmt": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": 9176047152973362695
}
],
"flds": [
{
"name": "Front",
"ord": 0,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": 2453723143453745216,
"tag": null,
"preventDeletion": false
},
{
"name": "Back",
"ord": 1,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": -4853200230425436781,
"tag": null,
"preventDeletion": false
}
],
"css": ".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n",
"latexPre": "\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n",
"latexPost": "\\end{document}",
"latexsvg": false,
"req": [
[
0,
"any",
[
0
]
]
],
"originalStockKind": 1
},
{
"id": 1704387398570,
"name": "Basic (and reversed card)",
"type": 0,
"mod": 1704387398,
"usn": -1,
"sortf": 0,
"did": null,
"tmpls": [
{
"name": "Card 1",
"ord": 0,
"qfmt": "{{Front}}",
"afmt": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": 1689886528158874152
},
{
"name": "Card 2",
"ord": 1,
"qfmt": "{{Back}}",
"afmt": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Front}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": -7839609225644824587
}
],
"flds": [
{
"name": "Front",
"ord": 0,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": -7787837672455357996,
"tag": null,
"preventDeletion": false
},
{
"name": "Back",
"ord": 1,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": 6364828289839985081,
"tag": null,
"preventDeletion": false
}
],
"css": ".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n",
"latexPre": "\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n",
"latexPost": "\\end{document}",
"latexsvg": false,
"req": [
[
0,
"any",
[
0
]
],
[
1,
"any",
[
1
]
]
],
"originalStockKind": 1
}
],
"error": null
}
```
</details>
#### `modelFieldNames`
* 获取提供的模型名称的完整字段名称列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldNames",
"version": 6,
"params": {
"modelName": "Basic"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": ["Front", "Back"],
"error": null
}
```
</details>
#### `modelFieldDescriptions`
* 获取提供的模型名称的完整字段描述列表(当字段为空时在 GUI 编辑器中显示的文本)。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldDescriptions",
"version": 6,
"params": {
"modelName": "Basic"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": ["", ""],
"error": null
}
```
</details>
#### `modelFieldFonts`
* 获取完整的字体列表及其字体大小。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldFonts",
"version": 6,
"params": {
"modelName": "Basic"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": {
"Front": {
"font": "Arial",
"size": 20
},
"Back": {
"font": "Arial",
"size": 20
}
},
"error": null
}
```
</details>
#### `modelFieldsOnTemplates`
* 返回一个对象,指示给定模型名称的每个卡片模板的问题侧和答案侧的字段。
问题侧在每个数组中首先给出。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldsOnTemplates",
"version": 6,
"params": {
"modelName": "Basic (and reversed card)"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": {
"Card 1": [["Front"], ["Back"]],
"Card 2": [["Back"], ["Front"]]
},
"error": null
}
```
</details>
#### `createModel`
* 创建一个新模型以在 Anki 中使用。用户必须提供 `modelName`、`inOrderFields` 和 `cardTemplates` 来
在模型中使用。有可选字段 `css` 和 `isCloze`。如果未指定,`css` 将使用默认的 Anki CSS`isCloze` 将等于 `false`。如果 `isCloze` 为 `true`,则模型将创建为填空题型。
可以为 `cardTemplates` 的每个条目提供可选的 `Name` 字段。默认情况下,
卡片名称将是 `Card 1`, `Card 2` 等。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "createModel",
"version": 6,
"params": {
"modelName": "newModelName",
"inOrderFields": ["Field1", "Field2", "Field3"],
"css": "Optional CSS with default to builtin css",
"isCloze": false,
"cardTemplates": [
{
"Name": "My Card 1",
"Front": "Front html {{Field1}}",
"Back": "Back html {{Field2}}"
}
]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result":{
"sortf":0,
"did":1,
"latexPre":"\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n",
"latexPost":"\\end{document}",
"mod":1551462107,
"usn":-1,
"vers":[
],
"type":0,
"css":".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n",
"name":"TestApiModel",
"flds":[
{
"name":"Field1",
"ord":0,
"sticky":false,
"rtl":false,
"font":"Arial",
"size":20,
"media":[
]
},
{
"name":"Field2",
"ord":1,
"sticky":false,
"rtl":false,
"font":"Arial",
"size":20,
"media":[
]
}
],
"tmpls":[
{
"name":"My Card 1",
"ord":0,
"qfmt":"",
"afmt":"This is the back of the card {{Field2}}",
"did":null,
"bqfmt":"",
"bafmt":""
}
],
"tags":[
],
"id":1551462107104,
"req":[
[
0,
"none",
[
]
]
]
},
"error":null
}
```
</details>
#### `modelTemplates`
* 返回一个对象,指示与提供的模型名称相连接的每个卡片的模板内容。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelTemplates",
"version": 6,
"params": {
"modelName": "Basic (and reversed card)"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": {
"Card 1": {
"Front": "{{Front}}",
"Back": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}"
},
"Card 2": {
"Front": "{{Back}}",
"Back": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Front}}"
}
},
"error": null
}
```
</details>
#### `modelStyling`
* 获取按名称提供的模型的 CSS 样式。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelStyling",
"version": 6,
"params": {
"modelName": "Basic (and reversed card)"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": {
"css": ".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n"
},
"error": null
}
```
</details>
#### `updateModelTemplates`
* 修改现有模型的模板(通过名称指定)。只有指定的卡片和指定的侧面会被修改。
如果请求中不包括现有卡片或侧面,它将保持不变。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "updateModelTemplates",
"version": 6,
"params": {
"model": {
"name": "Custom",
"templates": {
"Card 1": {
"Front": "{{Question}}?",
"Back": "{{Answer}}!"
}
}
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `updateModelStyling`
* 修改现有模型的 CSS 样式(通过名称指定)。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "updateModelStyling",
"version": 6,
"params": {
"model": {
"name": "Custom",
"css": "p { color: blue; }"
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `findAndReplaceInModels`
* 在现有模型中查找并替换字符串(通过模型名称)。通过设置为 true/false 自定义在前面、后面或 CSS 中替换。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "findAndReplaceInModels",
"version": 6,
"params": {
"model": {
"modelName": "",
"findText": "text_to_replace",
"replaceText": "replace_with_text",
"front": true,
"back": true,
"css": true
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": 1,
"error": null
}
```
</details>
#### `modelTemplateRename`
* 重命名现有模型中的模板。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelTemplateRename",
"version": 6,
"params": {
"modelName": "Basic",
"oldTemplateName": "Card 1",
"newTemplateName": "Card 1 renamed"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelTemplateReposition`
* 重新定位现有模型中的模板。
`index` 的值从 0 开始。例如,索引 `0` 将模板放在第一个位置,索引 `2` 将模板放在第三个位置。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelTemplateReposition",
"version": 6,
"params": {
"modelName": "Basic",
"templateName": "Card 1",
"index": 1
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelTemplateAdd`
* 通过名称向现有模型添加模板。如果要更新现有模板,请使用 `updateModelTemplates`。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelTemplateAdd",
"version": 6,
"params": {
"modelName": "Basic",
"template": {
"Name": "Card 3",
"Front": "Front html {{Field1}}",
"Back": "Back html {{Field2}}"
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelTemplateRemove`
* 从现有模型中移除模板。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelTemplateRemove",
"version": 6,
"params": {
"modelName": "Basic",
"templateName": "Card 1"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldRename`
* 重命名给定模型的字段名称。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldRename",
"version": 6,
"params": {
"modelName": "Basic",
"oldFieldName": "Front",
"newFieldName": "FrontRenamed"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldReposition`
* 重新定位给定模型的字段列表中的字段。
`index` 的值从 0 开始。例如,索引 `0` 将字段放在第一个位置,索引 `2` 将字段放在第三个位置。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldReposition",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Back",
"index": 0
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldAdd`
* 在给定模型中创建新字段。
可以选择提供 `index` 值,其工作方式与 `modelFieldReposition` 中的索引完全相同。默认情况下,字段将添加到字段列表的末尾。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldAdd",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "NewField",
"index": 0
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldRemove`
* 删除给定模型中的字段。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldRemove",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldSetFont`
* 设置给定模型中字段的字体。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldSetFont",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front",
"font": "Courier"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldSetFontSize`
* 设置给定模型中字段的字体大小。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldSetFontSize",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front",
"fontSize": 10
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldSetDescription`
* 设置给定模型中字段的描述(当字段为空时在 GUI 编辑器中看到的文本)。
旧版本的 Anki2.1.49 及以下)没有字段描述。在这种情况下,将返回 `false`。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldSetDescription",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front",
"description": "example field description"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
---
### 笔记操作
#### `addNote`
* 使用给定的牌组和模型创建一个笔记,包含提供的字段值和标签。成功时返回创建的笔记的标识符,
失败时返回 `null`。
Anki-Connect 可以下载音频、视频和图片文件,并将它们嵌入到新创建的笔记中。相应的 `audio`、`video` 和 `picture` 笔记成员是
可选的,可以省略。如果选择包含它们中的任何一个,它们应该包含一个对象或一个对象数组,
带有必填的 `filename` 字段和 `data`、`path` 或 `url` 之一。有关这些字段的解释,请参阅 `storeMediaFile` 的文档。
可以选择提供 `skipHash` 字段,以跳过包含与提供的值匹配的 MD5 哈希的文件。
这对于避免保存错误页面和存根文件很有用。
`fields` 成员是一个字段列表,这些字段应该在卡片显示在 Anki 中时播放音频或视频,或显示图片。
`options` 组中的 `allowDuplicate` 成员可以设置为 true 以启用添加重复卡片。
通常不能添加重复卡片,会触发异常。
`options` 中的 `duplicateScope` 成员可用于指定检查重复项的范围。
值为 `"deck"` 将只检查目标牌组中的重复项;任何其他值将检查整个集合。
`duplicateScopeOptions` 对象可用于指定一些附加设置:
* `duplicateScopeOptions.deckName` 将指定用于检查重复项的牌组。如果未定义或为 `null`,将使用目标牌组。
* `duplicateScopeOptions.checkChildren` 将更改是否在子牌组中检查重复卡片。默认值为 `false`。
* `duplicateScopeOptions.checkAllModels` 指定是否在所有笔记类型中执行重复检查。默认值为 `false`。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "addNote",
"version": 6,
"params": {
"note": {
"deckName": "Default",
"modelName": "Basic",
"fields": {
"Front": "front content",
"Back": "back content"
},
"options": {
"allowDuplicate": false,
"duplicateScope": "deck",
"duplicateScopeOptions": {
"deckName": "Default",
"checkChildren": false,
"checkAllModels": false
}
},
"tags": [
"yomichan"
],
"audio": [{
"url": "https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?kanji=猫&kana=ねこ",
"filename": "yomichan_ねこ_猫.mp3",
"skipHash": "7e2c2f954ef6051373ba916f000168dc",
"fields": [
"Front"
]
}],
"video": [{
"url": "https://cdn.videvo.net/videvo_files/video/free/2015-06/small_watermarked/Contador_Glam_preview.mp4",
"filename": "countdown.mp4",
"skipHash": "4117e8aab0d37534d9c8eac362388bbe",
"fields": [
"Back"
]
}],
"picture": [{
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/A_black_cat_named_Tilly.jpg/220px-A_black_cat_named_Tilly.jpg",
"filename": "black_cat.jpg",
"skipHash": "8d6e4646dfae812bf39651b59d7429ce",
"fields": [
"Back"
]
}]
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": 1496198395707,
"error": null
}
```
</details>
#### `addNotes`
* 使用给定的牌组和模型创建多个笔记,包含提供的字段值和标签。返回一个数组,
包含创建的笔记的标识符。如有任何错误,将收集并返回所有错误。
* 有关 `notes` 数组中对象的解释,请参阅 `addNote` 的文档。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action":"addNotes",
"version":6,
"params":{
"notes":[
{
"deckName":"College::PluginDev",
"modelName":"non_existent_model",
"fields":{
"Front":"front",
"Back":"bak"
}
},
{
"deckName":"College::PluginDev",
"modelName":"Basic",
"fields":{
"Front":"front",
"Back":"bak"
}
}
]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result":null,
"error":"['model was not found: non_existent_model']"
}
```
</details>
#### `canAddNotes`
* 接受一个对象数组,这些对象定义候选笔记的参数(参见 `addNote`),并返回一个布尔值数组,
指示相应索引处的参数是否可用于创建新笔记。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "canAddNotes",
"version": 6,
"params": {
"notes": [
{
"deckName": "Default",
"modelName": "Basic",
"fields": {
"Front": "front content",
"Back": "back content"
},
"tags": [
"yomichan"
]
}
]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [true],
"error": null
}
```
</details>
#### `canAddNotesWithErrorDetail`
* 接受一个对象数组,这些对象定义候选笔记的参数(参见 `addNote`),并返回一个对象数组,
包含 `canAdd` 和 `error` 字段。
* `canAdd` 指示相应索引处的参数是否可用于创建新笔记。
* `error` 包含无法添加笔记的原因说明。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "canAddNotesWithErrorDetail",
"version": 6,
"params": {
"notes": [
{
"deckName": "Default",
"modelName": "Basic",
"fields": {
"Front": "front content",
"Back": "back content"
},
"tags": [
"yomichan"
]
},
{
"deckName": "Default",
"modelName": "Basic",
"fields": {
"Front": "front content 2",
"Back": "back content 2"
},
"tags": [
"yomichan"
]
}
]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [
{
"canAdd": false,
"error": "cannot create note because it is a duplicate"
},
{
"canAdd": true
}
],
"error": null
}
```
</details>
#### `updateNoteFields`
* 修改现有笔记的字段。您还可以包含音频、视频或图片文件,这些文件将添加到笔记中,并带有
可选的 `audio`、`video` 或 `picture` 属性。有关 `audio`、`video` 或 `picture` 数组中对象的解释,请参阅 `addNote` 的文档。
> **警告**
> 您不能在 Anki 浏览器中查看您正在更新的笔记,否则
> 字段将不会更新。有关更多详细信息,请参阅[此问题](https://github.com/FooSoft/anki-connect/issues/82)。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "updateNoteFields",
"version": 6,
"params": {
"note": {
"id": 1514547547030,
"fields": {
"Front": "new front content",
"Back": "new back content"
},
"audio": [{
"url": "https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?kanji=猫&kana=ねこ",
"filename": "yomichan_ねこ_猫.mp3",
"skipHash": "7e2c2f954ef6051373ba916f000168dc",
"fields": [
"Front"
]
}]
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `updateNote`
* 修改现有笔记的字段和/或标签。
换句话说,结合了 `updateNoteFields` 和 `updateNoteTags` 的功能。
请参阅它们的文档以了解所有属性。
可以省略 `fields` 或 `tags` 属性,而不影响另一个。
因此有效的 `updateNoteFields` 请求也适用于 `updateNote`。
笔记必须具有 `fields` 属性才能更新可选的音频、视频或图片对象。
如果既没有提供 `fields` 也没有提供 `tags`,则该方法将失败。
首先更新字段,如果更新标签失败,则不会回滚字段更新。
如果更新字段失败,则不会更新标签。
> **警告**
> 您不能在 Anki 浏览器中查看您正在更新的笔记,否则
> 字段将不会更新。有关更多详细信息,请参阅[此问题](https://github.com/FooSoft/anki-connect/issues/82)。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "updateNote",
"version": 6,
"params": {
"note": {
"id": 1514547547030,
"fields": {
"Front": "new front content",
"Back": "new back content"
},
"tags": ["new", "tags"]
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `updateNoteModel`
* 更新现有笔记的模型、字段和标签。
这允许您更改笔记的模型,用新内容更新其字段,并设置新标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "updateNoteModel",
"version": 6,
"params": {
"note": {
"id": 1514547547030,
"modelName": "NewModel",
"fields": {
"NewField1": "new field 1",
"NewField2": "new field 2",
"NewField3": "new field 3"
},
"tags": ["new", "updated", "tags"]
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `updateNoteTags`
* 通过笔记 ID 设置笔记的标签。旧标签将被移除。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "updateNoteTags",
"version": 6,
"params": {
"note": 1483959289817,
"tags": ["european-languages"]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `getNoteTags`
* 通过笔记 ID 获取笔记的标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "getNoteTags",
"version": 6,
"params": {
"note": 1483959289817
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": ["european-languages"],
"error": null
}
```
</details>
#### `addTags`
* 通过笔记 ID 向笔记添加标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "addTags",
"version": 6,
"params": {
"notes": [1483959289817, 1483959291695],
"tags": "european-languages"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `removeTags`
* 通过笔记 ID 从笔记中移除标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "removeTags",
"version": 6,
"params": {
"notes": [1483959289817, 1483959291695],
"tags": "european-languages"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `getTags`
* 获取当前用户的标签完整列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "getTags",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": ["european-languages", "idioms"],
"error": null
}
```
</details>
#### `clearUnusedTags`
* 清除当前用户笔记中所有未使用的标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "clearUnusedTags",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `replaceTags`
* 通过笔记 ID 替换笔记中的标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "replaceTags",
"version": 6,
"params": {
"notes": [1483959289817, 1483959291695],
"tag_to_replace": "european-languages",
"replace_with_tag": "french-languages"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `replaceTagsInAllNotes`
* 替换当前用户所有笔记中的标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "replaceTagsInAllNotes",
"version": 6,
"params": {
"tag_to_replace": "european-languages",
"replace_with_tag": "french-languages"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `findNotes`
* 返回给定查询的笔记 ID 数组。查询语法[在此处有文档](https://docs.ankiweb.net/searching.html)。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "findNotes",
"version": 6,
"params": {
"query": "deck:current"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [1483959289817, 1483959291695],
"error": null
}
```
</details>
#### `notesInfo`
* 返回一个对象列表,每个笔记 ID 包含笔记字段、标签、笔记类型、修改时间、属于该笔记的卡片以及创建笔记的个人资料。
<details>
<summary><i>请求示例(笔记 id</i></summary>
```json
{
"action": "notesInfo",
"version": 6,
"params": {
"notes": [1502298033753]
}
}
```
</details>
<details>
<summary><i>请求示例(查询):</i></summary>
```json
{
"action": "notesInfo",
"version": 6,
"params": {
"query": "deck:current"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [
{
"noteId":1502298033753,
"profile": "User_1",
"modelName": "Basic",
"tags":["tag","another_tag"],
"fields": {
"Front": {"value": "front content", "order": 0},
"Back": {"value": "back content", "order": 1}
},
"mod": 1718377864,
"cards": [1498938915662]
}
],
"error": null
}
```
</details>
s
#### `notesModTime`
* 返回一个对象列表,每个笔记 ID 包含修改时间。
<details>
<summary><i>请求示例:</i><!-- filepath: /Users/xion/dev2/kv-anki-connect/README-ZH.md -->
#### `apiReflect`
* 获取有关可用 AnkiConnect API 的信息。请求支持以下参数:
* `scopes` - 要获取反射信息的作用域数组。
目前唯一支持的值是 `"actions"`。
* `actions` - 可以是 `null` 或者 API 方法名称的数组。
如果值为 `null`,结果将列出所有可用的 API 动作。
如果值是字符串数组,结果将只包含该数组中存在的动作。
结果将包含使用了哪些作用域及每个作用域的值。
例如,`"actions"` 作用域将包含一个 `"actions"` 属性,其中包含支持的动作名称列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "apiReflect",
"version": 6,
"params": {
"scopes": ["actions", "invalidType"],
"actions": ["apiReflect", "invalidMethod"]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": {
"scopes": ["actions"],
"actions": ["apiReflect"]
},
"error": null
}
```
</details>
#### `sync`
* 将本地 Anki 集合与 AnkiWeb 同步。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "sync",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `getProfiles`
* 获取个人资料列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "getProfiles",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": ["User 1"],
"error": null
}
```
</details>
#### `getActiveProfile`
* 获取当前活动个人资料。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "getActiveProfile",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": "User 1",
"error": null
}
```
</details>
#### `loadProfile`
* 选择请求中指定的个人资料。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "loadProfile",
"version": 6,
"params": {
"name": "user1"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `multi`
* 在一个请求中执行多个操作,返回一个数组,其中包含每个操作的响应(按给定顺序)。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "multi",
"version": 6,
"params": {
"actions": [
{
"action": "deckNames"
},
{
"action": "deckNames",
"version": 6
},
{
"action": "invalidAction",
"params": {"useless": "param"}
},
{
"action": "invalidAction",
"params": {"useless": "param"},
"version": 6
}
]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [
["Default"],
{"result": ["Default"], "error": null},
{"result": null, "error": "unsupported action"},
{"result": null, "error": "unsupported action"}
],
"error": null
}
```
</details>
#### `exportPackage`
* 将指定的牌组以 `.apkg` 格式导出。如果成功则返回 `true`,否则返回 `false`。可以指定可选属性
`includeSched`(默认为 `false`)以包含卡片的调度数据。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "exportPackage",
"version": 6,
"params": {
"deck": "Default",
"path": "/data/Deck.apkg",
"includeSched": true
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `importPackage`
* 将 `.apkg` 格式的文件导入集合中。如果成功则返回 `true`,否则返回 `false`。
注意,文件路径是相对于 Anki 的 collection.media 文件夹,而不是相对于客户端。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "importPackage",
"version": 6,
"params": {
"path": "/data/Deck.apkg"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
#### `reloadCollection`
* 告诉 Anki 从数据库重新加载所有数据。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "reloadCollection",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
---
### 模型(笔记类型)操作
#### `modelNames`
* 获取当前用户的完整模型名称列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelNames",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": ["Basic", "Basic (and reversed card)"],
"error": null
}
```
</details>
#### `modelNamesAndIds`
* 获取当前用户的完整模型名称及其对应的 ID 列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelNamesAndIds",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": {
"Basic": 1483883011648,
"Basic (and reversed card)": 1483883011644,
"Basic (optional reversed card)": 1483883011631,
"Cloze": 1483883011630
},
"error": null
}
```
</details>
#### `findModelsById`
* 根据提供的模型 ID 从当前用户获取模型列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "findModelsById",
"version": 6,
"params": {
"modelIds": [1704387367119, 1704387398570]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [
{
"id": 1704387367119,
"name": "Basic",
"type": 0,
"mod": 1704387367,
"usn": -1,
"sortf": 0,
"did": null,
"tmpls": [
{
"name": "Card 1",
"ord": 0,
"qfmt": "{{Front}}",
"afmt": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": 9176047152973362695
}
],
"flds": [
{
"name": "Front",
"ord": 0,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": 2453723143453745216,
"tag": null,
"preventDeletion": false
},
{
"name": "Back",
"ord": 1,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": -4853200230425436781,
"tag": null,
"preventDeletion": false
}
],
"css": ".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n",
"latexPre": "\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n",
"latexPost": "\\end{document}",
"latexsvg": false,
"req": [
[
0,
"any",
[
0
]
]
],
"originalStockKind": 1
},
{
"id": 1704387398570,
"name": "Basic (and reversed card)",
"type": 0,
"mod": 1704387398,
"usn": -1,
"sortf": 0,
"did": null,
"tmpls": [
{
"name": "Card 1",
"ord": 0,
"qfmt": "{{Front}}",
"afmt": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": 1689886528158874152
},
{
"name": "Card 2",
"ord": 1,
"qfmt": "{{Back}}",
"afmt": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Front}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": -7839609225644824587
}
],
"flds": [
{
"name": "Front",
"ord": 0,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": -7787837672455357996,
"tag": null,
"preventDeletion": false
},
{
"name": "Back",
"ord": 1,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": 6364828289839985081,
"tag": null,
"preventDeletion": false
}
],
"css": ".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n",
"latexPre": "\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n",
"latexPost": "\\end{document}",
"latexsvg": false,
"req": [
[
0,
"any",
[
0
]
],
[
1,
"any",
[
1
]
]
],
"originalStockKind": 1
}
],
"error": null
}
```
</details>
#### `findModelsByName`
* 根据提供的模型名称从当前用户获取模型列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "findModelsByName",
"version": 6,
"params": {
"modelNames": ["Basic", "Basic (and reversed card)"]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [
{
"id": 1704387367119,
"name": "Basic",
"type": 0,
"mod": 1704387367,
"usn": -1,
"sortf": 0,
"did": null,
"tmpls": [
{
"name": "Card 1",
"ord": 0,
"qfmt": "{{Front}}",
"afmt": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": 9176047152973362695
}
],
"flds": [
{
"name": "Front",
"ord": 0,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": 2453723143453745216,
"tag": null,
"preventDeletion": false
},
{
"name": "Back",
"ord": 1,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": -4853200230425436781,
"tag": null,
"preventDeletion": false
}
],
"css": ".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n",
"latexPre": "\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n",
"latexPost": "\\end{document}",
"latexsvg": false,
"req": [
[
0,
"any",
[
0
]
]
],
"originalStockKind": 1
},
{
"id": 1704387398570,
"name": "Basic (and reversed card)",
"type": 0,
"mod": 1704387398,
"usn": -1,
"sortf": 0,
"did": null,
"tmpls": [
{
"name": "Card 1",
"ord": 0,
"qfmt": "{{Front}}",
"afmt": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": 1689886528158874152
},
{
"name": "Card 2",
"ord": 1,
"qfmt": "{{Back}}",
"afmt": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Front}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": -7839609225644824587
}
],
"flds": [
{
"name": "Front",
"ord": 0,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": -7787837672455357996,
"tag": null,
"preventDeletion": false
},
{
"name": "Back",
"ord": 1,
"sticky": false,
"rtl": false,
"font": "Arial",
"size": 20,
"description": "",
"plainText": false,
"collapsed": false,
"excludeFromSearch": false,
"id": 6364828289839985081,
"tag": null,
"preventDeletion": false
}
],
"css": ".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n",
"latexPre": "\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n",
"latexPost": "\\end{document}",
"latexsvg": false,
"req": [
[
0,
"any",
[
0
]
],
[
1,
"any",
[
1
]
]
],
"originalStockKind": 1
}
],
"error": null
}
```
</details>
#### `modelFieldNames`
* 获取提供的模型名称的完整字段名称列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldNames",
"version": 6,
"params": {
"modelName": "Basic"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": ["Front", "Back"],
"error": null
}
```
</details>
#### `modelFieldDescriptions`
* 获取提供的模型名称的完整字段描述列表(当字段为空时在 GUI 编辑器中显示的文本)。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldDescriptions",
"version": 6,
"params": {
"modelName": "Basic"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": ["", ""],
"error": null
}
```
</details>
#### `modelFieldFonts`
* 获取完整的字体列表及其字体大小。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldFonts",
"version": 6,
"params": {
"modelName": "Basic"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": {
"Front": {
"font": "Arial",
"size": 20
},
"Back": {
"font": "Arial",
"size": 20
}
},
"error": null
}
```
</details>
#### `modelFieldsOnTemplates`
* 返回一个对象,指示给定模型名称的每个卡片模板的问题侧和答案侧的字段。
问题侧在每个数组中首先给出。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldsOnTemplates",
"version": 6,
"params": {
"modelName": "Basic (and reversed card)"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": {
"Card 1": [["Front"], ["Back"]],
"Card 2": [["Back"], ["Front"]]
},
"error": null
}
```
</details>
#### `createModel`
* 创建一个新模型以在 Anki 中使用。用户必须提供 `modelName`、`inOrderFields` 和 `cardTemplates` 来
在模型中使用。有可选字段 `css` 和 `isCloze`。如果未指定,`css` 将使用默认的 Anki CSS`isCloze` 将等于 `false`。如果 `isCloze` 为 `true`,则模型将创建为填空题型。
可以为 `cardTemplates` 的每个条目提供可选的 `Name` 字段。默认情况下,
卡片名称将是 `Card 1`, `Card 2` 等。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "createModel",
"version": 6,
"params": {
"modelName": "newModelName",
"inOrderFields": ["Field1", "Field2", "Field3"],
"css": "Optional CSS with default to builtin css",
"isCloze": false,
"cardTemplates": [
{
"Name": "My Card 1",
"Front": "Front html {{Field1}}",
"Back": "Back html {{Field2}}"
}
]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result":{
"sortf":0,
"did":1,
"latexPre":"\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n",
"latexPost":"\\end{document}",
"mod":1551462107,
"usn":-1,
"vers":[
],
"type":0,
"css":".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n",
"name":"TestApiModel",
"flds":[
{
"name":"Field1",
"ord":0,
"sticky":false,
"rtl":false,
"font":"Arial",
"size":20,
"media":[
]
},
{
"name":"Field2",
"ord":1,
"sticky":false,
"rtl":false,
"font":"Arial",
"size":20,
"media":[
]
}
],
"tmpls":[
{
"name":"My Card 1",
"ord":0,
"qfmt":"",
"afmt":"This is the back of the card {{Field2}}",
"did":null,
"bqfmt":"",
"bafmt":""
}
],
"tags":[
],
"id":1551462107104,
"req":[
[
0,
"none",
[
]
]
]
},
"error":null
}
```
</details>
#### `modelTemplates`
* 返回一个对象,指示与提供的模型名称相连接的每个卡片的模板内容。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelTemplates",
"version": 6,
"params": {
"modelName": "Basic (and reversed card)"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": {
"Card 1": {
"Front": "{{Front}}",
"Back": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}"
},
"Card 2": {
"Front": "{{Back}}",
"Back": "{{FrontSide}}\n\n<hr id=answer>\n\n{{Front}}"
}
},
"error": null
}
```
</details>
#### `modelStyling`
* 获取按名称提供的模型的 CSS 样式。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelStyling",
"version": 6,
"params": {
"modelName": "Basic (and reversed card)"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": {
"css": ".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n"
},
"error": null
}
```
</details>
#### `updateModelTemplates`
* 修改现有模型的模板(通过名称指定)。只有指定的卡片和指定的侧面会被修改。
如果请求中不包括现有卡片或侧面,它将保持不变。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "updateModelTemplates",
"version": 6,
"params": {
"model": {
"name": "Custom",
"templates": {
"Card 1": {
"Front": "{{Question}}?",
"Back": "{{Answer}}!"
}
}
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `updateModelStyling`
* 修改现有模型的 CSS 样式(通过名称指定)。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "updateModelStyling",
"version": 6,
"params": {
"model": {
"name": "Custom",
"css": "p { color: blue; }"
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `findAndReplaceInModels`
* 在现有模型中查找并替换字符串(通过模型名称)。通过设置为 true/false 自定义在前面、后面或 CSS 中替换。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "findAndReplaceInModels",
"version": 6,
"params": {
"model": {
"modelName": "",
"findText": "text_to_replace",
"replaceText": "replace_with_text",
"front": true,
"back": true,
"css": true
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": 1,
"error": null
}
```
</details>
#### `modelTemplateRename`
* 重命名现有模型中的模板。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelTemplateRename",
"version": 6,
"params": {
"modelName": "Basic",
"oldTemplateName": "Card 1",
"newTemplateName": "Card 1 renamed"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelTemplateReposition`
* 重新定位现有模型中的模板。
`index` 的值从 0 开始。例如,索引 `0` 将模板放在第一个位置,索引 `2` 将模板放在第三个位置。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelTemplateReposition",
"version": 6,
"params": {
"modelName": "Basic",
"templateName": "Card 1",
"index": 1
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelTemplateAdd`
* 通过名称向现有模型添加模板。如果要更新现有模板,请使用 `updateModelTemplates`。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelTemplateAdd",
"version": 6,
"params": {
"modelName": "Basic",
"template": {
"Name": "Card 3",
"Front": "Front html {{Field1}}",
"Back": "Back html {{Field2}}"
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelTemplateRemove`
* 从现有模型中移除模板。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelTemplateRemove",
"version": 6,
"params": {
"modelName": "Basic",
"templateName": "Card 1"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldRename`
* 重命名给定模型的字段名称。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldRename",
"version": 6,
"params": {
"modelName": "Basic",
"oldFieldName": "Front",
"newFieldName": "FrontRenamed"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldReposition`
* 重新定位给定模型的字段列表中的字段。
`index` 的值从 0 开始。例如,索引 `0` 将字段放在第一个位置,索引 `2` 将字段放在第三个位置。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldReposition",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Back",
"index": 0
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldAdd`
* 在给定模型中创建新字段。
可以选择提供 `index` 值,其工作方式与 `modelFieldReposition` 中的索引完全相同。默认情况下,字段将添加到字段列表的末尾。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldAdd",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "NewField",
"index": 0
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldRemove`
* 删除给定模型中的字段。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldRemove",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldSetFont`
* 设置给定模型中字段的字体。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldSetFont",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front",
"font": "Courier"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldSetFontSize`
* 设置给定模型中字段的字体大小。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldSetFontSize",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front",
"fontSize": 10
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `modelFieldSetDescription`
* 设置给定模型中字段的描述(当字段为空时在 GUI 编辑器中看到的文本)。
旧版本的 Anki2.1.49 及以下)没有字段描述。在这种情况下,将返回 `false`。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "modelFieldSetDescription",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front",
"description": "example field description"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": true,
"error": null
}
```
</details>
---
### 笔记操作
#### `addNote`
* 使用给定的牌组和模型创建一个笔记,包含提供的字段值和标签。成功时返回创建的笔记的标识符,
失败时返回 `null`。
Anki-Connect 可以下载音频、视频和图片文件,并将它们嵌入到新创建的笔记中。相应的 `audio`、`video` 和 `picture` 笔记成员是
可选的,可以省略。如果选择包含它们中的任何一个,它们应该包含一个对象或一个对象数组,
带有必填的 `filename` 字段和 `data`、`path` 或 `url` 之一。有关这些字段的解释,请参阅 `storeMediaFile` 的文档。
可以选择提供 `skipHash` 字段,以跳过包含与提供的值匹配的 MD5 哈希的文件。
这对于避免保存错误页面和存根文件很有用。
`fields` 成员是一个字段列表,这些字段应该在卡片显示在 Anki 中时播放音频或视频,或显示图片。
`options` 组中的 `allowDuplicate` 成员可以设置为 true 以启用添加重复卡片。
通常不能添加重复卡片,会触发异常。
`options` 中的 `duplicateScope` 成员可用于指定检查重复项的范围。
值为 `"deck"` 将只检查目标牌组中的重复项;任何其他值将检查整个集合。
`duplicateScopeOptions` 对象可用于指定一些附加设置:
* `duplicateScopeOptions.deckName` 将指定用于检查重复项的牌组。如果未定义或为 `null`,将使用目标牌组。
* `duplicateScopeOptions.checkChildren` 将更改是否在子牌组中检查重复卡片。默认值为 `false`。
* `duplicateScopeOptions.checkAllModels` 指定是否在所有笔记类型中执行重复检查。默认值为 `false`。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "addNote",
"version": 6,
"params": {
"note": {
"deckName": "Default",
"modelName": "Basic",
"fields": {
"Front": "front content",
"Back": "back content"
},
"options": {
"allowDuplicate": false,
"duplicateScope": "deck",
"duplicateScopeOptions": {
"deckName": "Default",
"checkChildren": false,
"checkAllModels": false
}
},
"tags": [
"yomichan"
],
"audio": [{
"url": "https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?kanji=猫&kana=ねこ",
"filename": "yomichan_ねこ_猫.mp3",
"skipHash": "7e2c2f954ef6051373ba916f000168dc",
"fields": [
"Front"
]
}],
"video": [{
"url": "https://cdn.videvo.net/videvo_files/video/free/2015-06/small_watermarked/Contador_Glam_preview.mp4",
"filename": "countdown.mp4",
"skipHash": "4117e8aab0d37534d9c8eac362388bbe",
"fields": [
"Back"
]
}],
"picture": [{
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/A_black_cat_named_Tilly.jpg/220px-A_black_cat_named_Tilly.jpg",
"filename": "black_cat.jpg",
"skipHash": "8d6e4646dfae812bf39651b59d7429ce",
"fields": [
"Back"
]
}]
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": 1496198395707,
"error": null
}
```
</details>
#### `addNotes`
* 使用给定的牌组和模型创建多个笔记,包含提供的字段值和标签。返回一个数组,
包含创建的笔记的标识符。如有任何错误,将收集并返回所有错误。
* 有关 `notes` 数组中对象的解释,请参阅 `addNote` 的文档。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action":"addNotes",
"version":6,
"params":{
"notes":[
{
"deckName":"College::PluginDev",
"modelName":"non_existent_model",
"fields":{
"Front":"front",
"Back":"bak"
}
},
{
"deckName":"College::PluginDev",
"modelName":"Basic",
"fields":{
"Front":"front",
"Back":"bak"
}
}
]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result":null,
"error":"['model was not found: non_existent_model']"
}
```
</details>
#### `canAddNotes`
* 接受一个对象数组,这些对象定义候选笔记的参数(参见 `addNote`),并返回一个布尔值数组,
指示相应索引处的参数是否可用于创建新笔记。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "canAddNotes",
"version": 6,
"params": {
"notes": [
{
"deckName": "Default",
"modelName": "Basic",
"fields": {
"Front": "front content",
"Back": "back content"
},
"tags": [
"yomichan"
]
}
]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [true],
"error": null
}
```
</details>
#### `canAddNotesWithErrorDetail`
* 接受一个对象数组,这些对象定义候选笔记的参数(参见 `addNote`),并返回一个对象数组,
包含 `canAdd` 和 `error` 字段。
* `canAdd` 指示相应索引处的参数是否可用于创建新笔记。
* `error` 包含无法添加笔记的原因说明。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "canAddNotesWithErrorDetail",
"version": 6,
"params": {
"notes": [
{
"deckName": "Default",
"modelName": "Basic",
"fields": {
"Front": "front content",
"Back": "back content"
},
"tags": [
"yomichan"
]
},
{
"deckName": "Default",
"modelName": "Basic",
"fields": {
"Front": "front content 2",
"Back": "back content 2"
},
"tags": [
"yomichan"
]
}
]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [
{
"canAdd": false,
"error": "cannot create note because it is a duplicate"
},
{
"canAdd": true
}
],
"error": null
}
```
</details>
#### `updateNoteFields`
* 修改现有笔记的字段。您还可以包含音频、视频或图片文件,这些文件将添加到笔记中,并带有
可选的 `audio`、`video` 或 `picture` 属性。有关 `audio`、`video` 或 `picture` 数组中对象的解释,请参阅 `addNote` 的文档。
> **警告**
> 您不能在 Anki 浏览器中查看您正在更新的笔记,否则
> 字段将不会更新。有关更多详细信息,请参阅[此问题](https://github.com/FooSoft/anki-connect/issues/82)。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "updateNoteFields",
"version": 6,
"params": {
"note": {
"id": 1514547547030,
"fields": {
"Front": "new front content",
"Back": "new back content"
},
"audio": [{
"url": "https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?kanji=猫&kana=ねこ",
"filename": "yomichan_ねこ_猫.mp3",
"skipHash": "7e2c2f954ef6051373ba916f000168dc",
"fields": [
"Front"
]
}]
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `updateNote`
* 修改现有笔记的字段和/或标签。
换句话说,结合了 `updateNoteFields` 和 `updateNoteTags` 的功能。
请参阅它们的文档以了解所有属性。
可以省略 `fields` 或 `tags` 属性,而不影响另一个。
因此有效的 `updateNoteFields` 请求也适用于 `updateNote`。
笔记必须具有 `fields` 属性才能更新可选的音频、视频或图片对象。
如果既没有提供 `fields` 也没有提供 `tags`,则该方法将失败。
首先更新字段,如果更新标签失败,则不会回滚字段更新。
如果更新字段失败,则不会更新标签。
> **警告**
> 您不能在 Anki 浏览器中查看您正在更新的笔记,否则
> 字段将不会更新。有关更多详细信息,请参阅[此问题](https://github.com/FooSoft/anki-connect/issues/82)。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "updateNote",
"version": 6,
"params": {
"note": {
"id": 1514547547030,
"fields": {
"Front": "new front content",
"Back": "new back content"
},
"tags": ["new", "tags"]
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `updateNoteModel`
* 更新现有笔记的模型、字段和标签。
这允许您更改笔记的模型,用新内容更新其字段,并设置新标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "updateNoteModel",
"version": 6,
"params": {
"note": {
"id": 1514547547030,
"modelName": "NewModel",
"fields": {
"NewField1": "new field 1",
"NewField2": "new field 2",
"NewField3": "new field 3"
},
"tags": ["new", "updated", "tags"]
}
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `updateNoteTags`
* 通过笔记 ID 设置笔记的标签。旧标签将被移除。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "updateNoteTags",
"version": 6,
"params": {
"note": 1483959289817,
"tags": ["european-languages"]
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `getNoteTags`
* 通过笔记 ID 获取笔记的标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "getNoteTags",
"version": 6,
"params": {
"note": 1483959289817
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": ["european-languages"],
"error": null
}
```
</details>
#### `addTags`
* 通过笔记 ID 向笔记添加标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "addTags",
"version": 6,
"params": {
"notes": [1483959289817, 1483959291695],
"tags": "european-languages"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `removeTags`
* 通过笔记 ID 从笔记中移除标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "removeTags",
"version": 6,
"params": {
"notes": [1483959289817, 1483959291695],
"tags": "european-languages"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `getTags`
* 获取当前用户的标签完整列表。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "getTags",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": ["european-languages", "idioms"],
"error": null
}
```
</details>
#### `clearUnusedTags`
* 清除当前用户笔记中所有未使用的标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "clearUnusedTags",
"version": 6
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `replaceTags`
* 通过笔记 ID 替换笔记中的标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "replaceTags",
"version": 6,
"params": {
"notes": [1483959289817, 1483959291695],
"tag_to_replace": "european-languages",
"replace_with_tag": "french-languages"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `replaceTagsInAllNotes`
* 替换当前用户所有笔记中的标签。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "replaceTagsInAllNotes",
"version": 6,
"params": {
"tag_to_replace": "european-languages",
"replace_with_tag": "french-languages"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": null,
"error": null
}
```
</details>
#### `findNotes`
* 返回给定查询的笔记 ID 数组。查询语法[在此处有文档](https://docs.ankiweb.net/searching.html)。
<details>
<summary><i>请求示例:</i></summary>
```json
{
"action": "findNotes",
"version": 6,
"params": {
"query": "deck:current"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [1483959289817, 1483959291695],
"error": null
}
```
</details>
#### `notesInfo`
* 返回一个对象列表,每个笔记 ID 包含笔记字段、标签、笔记类型、修改时间、属于该笔记的卡片以及创建笔记的个人资料。
<details>
<summary><i>请求示例(笔记 id</i></summary>
```json
{
"action": "notesInfo",
"version": 6,
"params": {
"notes": [1502298033753]
}
}
```
</details>
<details>
<summary><i>请求示例(查询):</i></summary>
```json
{
"action": "notesInfo",
"version": 6,
"params": {
"query": "deck:current"
}
}
```
</details>
<details>
<summary><i>结果示例:</i></summary>
```json
{
"result": [
{
"noteId":1502298033753,
"profile": "User_1",
"modelName": "Basic",
"tags":["tag","another_tag"],
"fields": {
"Front": {"value": "front content", "order": 0},
"Back": {"value": "back content", "order": 1}
},
"mod": 1718377864,
"cards": [1498938915662]
}
],
"error": null
}
```
</details>
#### `notesModTime`
* 返回一个对象列表,每个笔记 ID 包含修改时间。
<details>
<summary><i>请求示例:</i>