# 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`
* 返回一个数组,包含给定卡片的简易度因子(按相同顺序)。
示例请求:
```json
{
"action": "getEaseFactors",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
示例结果:
```json
{
"result": [4100, 3900],
"error": null
}
```
#### `setEaseFactors`
* 通过卡片ID设置卡片的简易度因子;如果成功(所有卡片都存在)则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "setEaseFactors",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217],
"easeFactors": [4100, 3900]
}
}
```
示例结果:
```json
{
"result": [true, true],
"error": null
}
```
#### `setSpecificValueOfCard`
* 设置单个卡片的特定值。由于更改卡片的某些值可能会在数据库中造成混乱,一些键需要将参数"warning_check"设置为True。
这可用于设置卡片的标志、更改其简易度因子、更改筛选卡组中的复习顺序以及更改列"data"(目前显然未被anki使用),以及许多其他值。
可以在[AnkiDroid的wiki](https://github.com/ankidroid/Anki-Android/wiki/Database-Structure)上找到值的列表及其各自的用途解释。
示例请求:
```json
{
"action": "setSpecificValueOfCard",
"version": 6,
"params": {
"card": 1483959291685,
"keys": ["flags", "odue"],
"newValues": ["1", "-100"]
}
}
```
示例结果:
```json
{
"result": [true, true],
"error": null
}
```
#### `suspend`
* 通过卡片ID暂停卡片;如果成功(至少有一张卡片之前没有被暂停)则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "suspend",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `unsuspend`
* 通过卡片ID取消暂停卡片;如果成功(至少有一张卡片之前被暂停)则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "unsuspend",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `suspended`
* 通过ID检查卡片是否被暂停。如果被暂停则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "suspended",
"version": 6,
"params": {
"card": 1483959293217
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `areSuspended`
* 返回一个数组,表示每张给定卡片是否被暂停(按相同顺序)。如果卡片不存在,则返回`null`。
示例请求:
```json
{
"action": "areSuspended",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217, 1234567891234]
}
}
```
示例结果:
```json
{
"result": [false, true, null],
"error": null
}
```
#### `areDue`
* 返回一个数组,表示每张给定卡片是否到期(按相同顺序)。*注意*:学习队列中有大间隔(超过20分钟)的卡片被视为未到期,直到其间隔时间过去为止,这与Anki在复习时对待它们的方式相匹配。
示例请求:
```json
{
"action": "areDue",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
示例结果:
```json
{
"result": [false, true],
"error": null
}
```
#### `getIntervals`
* 返回一个数组,包含每个给定卡片ID的最近间隔,或者当`complete`为`true`时,返回每个给定卡片ID的所有间隔的二维数组。负间隔以秒为单位,正间隔以天为单位。
示例请求1:
```json
{
"action": "getIntervals",
"version": 6,
"params": {
"cards": [1502298033753, 1502298036657]
}
}
```
示例结果1:
```json
{
"result": [-14400, 3],
"error": null
}
```
示例请求2:
```json
{
"action": "getIntervals",
"version": 6,
"params": {
"cards": [1502298033753, 1502298036657],
"complete": true
}
}
```
示例结果2:
```json
{
"result": [
[-120, -180, -240, -300, -360, -14400],
[-120, -180, -240, -300, -360, -14400, 1, 3]
],
"error": null
}
```
#### `findCards`
* 返回给定查询的卡片ID数组。功能上与`guiBrowse`相同,但不使用GUI以获得更好的性能。
示例请求:
```json
{
"action": "findCards",
"version": 6,
"params": {
"query": "deck:current"
}
}
```
示例结果:
```json
{
"result": [1494723142483, 1494703460437, 1494703479525],
"error": null
}
```
#### `cardsToNotes`
* 返回给定卡片ID的笔记ID的无序数组。对于具有相同笔记的卡片,ID在数组中只给出一次。
示例请求:
```json
{
"action": "cardsToNotes",
"version": 6,
"params": {
"cards": [1502098034045, 1502098034048, 1502298033753]
}
}
```
示例结果:
```json
{
"result": [1502098029797, 1502298025183],
"error": null
}
```
#### `cardsModTime`
* 返回一个对象列表,包含每个卡片ID的修改时间。
此功能比执行`cardsInfo`快约15倍。
示例请求:
```json
{
"action": "cardsModTime",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
示例结果:
```json
{
"result": [
{
"cardId": 1498938915662,
"mod": 1629454092
}
],
"error": null
}
```
#### `cardsInfo`
* 返回一个对象列表,包含每个卡片ID的卡片字段、正反面(包括CSS)、笔记类型、卡片所属的笔记、卡组名称、最后修改时间戳以及简易度和间隔。
示例请求:
```json
{
"action": "cardsInfo",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
示例结果:
```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
}
```
#### `forgetCards`
* 忘记卡片,使卡片再次成为新卡片。
示例请求:
```json
{
"action": "forgetCards",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `relearnCards`
* 使卡片成为"重新学习"状态。
示例请求:
```json
{
"action": "relearnCards",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `answerCards`
* 回答卡片。简易度在1(重来)到4(简单)之间。将在回答前立即开始计时器。如果卡片存在则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "answerCards",
"version": 6,
"params": {
"answers": [
{
"cardId": 1498938915662,
"ease": 2
},
{
"cardId": 1502098034048,
"ease": 4
}
]
}
}
```
示例结果:
```json
{
"result": [true, true],
"error": null
}
```
#### `setDueDate`
* 设置到期日期。如果是新卡片,则将其转为复习卡片,并使其在特定日期到期。
* 0 = 今天
* 1! = 明天 + 将间隔更改为1
* 3-7 = 随机选择3-7天
示例请求:
```json
{
"action": "setDueDate",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048],
"days": "3-7"
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
---
### 卡组操作
#### `deckNames`
* 获取当前用户的完整卡组名称列表。
示例请求:
```json
{
"action": "deckNames",
"version": 6
}
```
示例结果:
```json
{
"result": ["Default"],
"error": null
}
```
#### `deckNamesAndIds`
* 获取当前用户的完整卡组名称及其对应ID的列表。
示例请求:
```json
{
"action": "deckNamesAndIds",
"version": 6
}
```
示例结果:
```json
{
"result": {"Default": 1},
"error": null
}
```
#### `getDecks`
* 接受一个卡片ID数组,并返回一个对象,其中每个卡组名称作为键,其值是属于该卡组的给定卡片数组。
示例请求:
```json
{
"action": "getDecks",
"version": 6,
"params": {
"cards": [1502298036657, 1502298033753, 1502032366472]
}
}
```
示例结果:
```json
{
"result": {
"Default": [1502032366472],
"Japanese::JLPT N3": [1502298036657, 1502298033753]
},
"error": null
}
```
#### `createDeck`
* 创建一个新的空卡组。不会覆盖同名的已存在卡组。
示例请求:
```json
{
"action": "createDeck",
"version": 6,
"params": {
"deck": "Japanese::Tokyo"
}
}
```
示例结果:
```json
{
"result": 1519323742721,
"error": null
}
```
#### `changeDeck`
* 将具有给定ID的卡片移动到不同的卡组,如果卡组尚不存在则创建它。
示例请求:
```json
{
"action": "changeDeck",
"version": 6,
"params": {
"cards": [1502098034045, 1502098034048, 1502298033753],
"deck": "Japanese::JLPT N3"
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `deleteDecks`
* 删除具有给定名称的卡组。
参数`cardsToo` *必须*被指定并设置为`true`。
示例请求:
```json
{
"action": "deleteDecks",
"version": 6,
"params": {
"decks": ["Japanese::JLPT N5", "Easy Spanish"],
"cardsToo": true
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `getDeckConfig`
* 获取给定卡组的配置组对象。
示例请求:
```json
{
"action": "getDeckConfig",
"version": 6,
"params": {
"deck": "Default"
}
}
```
示例结果:
```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
}
```
#### `saveDeckConfig`
* 保存给定的配置组,成功时返回`true`,如果配置组的ID无效(例如不存在)则返回`false`。
示例请求:
```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
}
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `setDeckConfigId`
* 将给定卡组的配置组更改为具有给定ID的配置组。成功时返回`true`,如果给定的配置组或任何给定的卡组不存在则返回`false`。
示例请求:
```json
{
"action": "setDeckConfigId",
"version": 6,
"params": {
"decks": ["Default"],
"configId": 1
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `cloneDeckConfigId`
* 使用给定的名称创建一个新的配置组,从具有给定ID的组克隆,或者如果未指定,则从默认组克隆。返回新配置组的ID,或者如果指定的要克隆的组不存在,则返回`false`。
示例请求:
```json
{
"action": "cloneDeckConfigId",
"version": 6,
"params": {
"name": "Copy of Default",
"cloneFrom": 1
}
}
```
示例结果:
```json
{
"result": 1502972374573,
"error": null
}
```
#### `removeDeckConfigId`
* 移除具有给定ID的配置组,如果成功则返回`true`,如果尝试移除默认配置组(ID = 1)或不存在的配置组则返回`false`。
示例请求:
```json
{
"action": "removeDeckConfigId",
"version": 6,
"params": {
"configId": 1502972374573
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `getDeckStats`
* 获取给定卡组的统计信息,如总卡片数和到期卡片数。
示例请求:
```json
{
"action": "getDeckStats",
"version": 6,
"params": {
"decks": ["Japanese::JLPT N5", "Easy Spanish"]
}
}
```
示例结果:
```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
}
```
---
### 图形界面操作
#### `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)中记录的)。
指定的列需要在*卡片浏览器*中可见。
示例请求:
```json
{
"action": "guiBrowse",
"version": 6,
"params": {
"query": "deck:current",
"reorderCards": {
"order": "descending",
"columnId": "noteCrt"
}
}
}
```
示例结果:
```json
{
"result": [1494723142483, 1494703460437, 1494703479525],
"error": null
}
```
#### `guiSelectCard`
* 找到*卡片浏览器*对话框的打开实例,并根据卡片标识符选择一张卡片。
如果*卡片浏览器*是打开的,返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "guiSelectCard",
"version": 6,
"params": {
"card": 1494723142483
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiSelectedNotes`
* 找到*卡片浏览器*对话框的打开实例,并返回选中笔记的标识符数组。如果浏览器未打开,则返回空列表。
示例请求:
```json
{
"action": "guiSelectedNotes",
"version": 6
}
```
示例结果:
```json
{
"result": [1494723142483, 1494703460437, 1494703479525],
"error": null
}
```
#### `guiAddCards`
* 调用*添加卡片*对话框,使用给定的卡组和模型预设笔记,带有提供的字段值和标签。
多次调用会关闭旧窗口并_重新打开窗口_,使用新提供的值。
可以通过`audio`、`video`和`picture`键将音频、视频和图片文件嵌入到字段中。
请参考`addNote`和`storeMediaFile`的文档,了解这些字段的说明。
结果是如果用户选择确认*添加卡片*对话框,将添加的笔记的ID。
示例请求:
```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"
]
}]
}
}
}
```
示例结果:
```json
{
"result": 1496198395707,
"error": null
}
```
#### `guiEditNote`
* 打开*编辑*对话框,显示对应于给定笔记ID的笔记。
该对话框类似于*编辑当前*对话框,但:
* 有一个预览按钮,用于预览笔记的卡片
* 有一个浏览按钮,用于打开浏览器并显示这些卡片
* 有上一个/后退按钮,用于导航对话框的历史
* 没有带有关闭按钮的栏
示例请求:
```json
{
"action": "guiEditNote",
"version": 6,
"params": {
"note": 1649198355435
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `guiCurrentCard`
* 返回有关当前卡片的信息,如果不在复习模式,则返回`null`。
示例请求:
```json
{
"action": "guiCurrentCard",
"version": 6
}
```
示例结果:
```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
}
```
#### `guiStartCardTimer`
* 启动或重置当前卡片的`timerStarted`值。这对于将开始时间推迟到通过API显示卡片时很有用,从而在调用`guiAnswerCard`时使记录的回答卡片所花费的时间更准确。
示例请求:
```json
{
"action": "guiStartCardTimer",
"version": 6
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiShowQuestion`
* 显示当前卡片的问题文本;如果处于复习模式则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "guiShowQuestion",
"version": 6
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiShowAnswer`
* 显示当前卡片的答案文本;如果处于复习模式则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "guiShowAnswer",
"version": 6
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiAnswerCard`
* 回答当前卡片;如果成功则返回`true`,否则返回`false`。注意,在Anki接受任何答案之前,必须先显示当前卡片的答案。
示例请求:
```json
{
"action": "guiAnswerCard",
"version": 6,
"params": {
"ease": 1
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiUndo`
* 撤销最后一个动作/卡片;如果成功则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "guiUndo",
"version": 6
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiDeckOverview`
* 为具有给定名称的卡组打开*卡组概览*对话框;如果成功则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "guiDeckOverview",
"version": 6,
"params": {
"name": "Default"
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiDeckBrowser`
* 打开*卡组浏览器*对话框。
示例请求:
```json
{
"action": "guiDeckBrowser",
"version": 6
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `guiDeckReview`
* 开始复习具有给定名称的卡组;如果成功则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "guiDeckReview",
"version": 6,
"params": {
"name": "Default"
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiImportFile`
* 调用*导入...(Ctrl+Shift+I)*对话框,并可选择提供文件路径。弹出对话框供用户审核导入。支持Anki支持的所有文件类型。如果未提供路径,则显示打开文件对话框。在Windows上的路径中必须使用正斜杠。仅支持Anki 2.1.52+。
示例请求:
```json
{
"action": "guiImportFile",
"version": 6,
"params": {
"path": "C:/Users/Desktop/cards.txt"
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `guiExitAnki`
* 安排一个请求来优雅地关闭Anki。此操作是异步的,因此它会立即返回,而不会等待Anki进程实际终止。
示例请求:
```json
{
"action": "guiExitAnki",
"version": 6
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `guiCheckDatabase`
* 请求进行数据库检查,但立即返回而不等待检查完成。因此,即使在数据库检查过程中检测到错误,此操作也将始终返回`true`。
示例请求:
```json
{
"action": "guiCheckDatabase",
"version": 6
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
---
### 媒体操作
#### `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)来防止这种情况。
示例请求(相对路径):
```json
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"data": "SGVsbG8sIHdvcmxkIQ=="
}
}
```
*`_hello.txt`的内容*:
```
Hello world!
```
示例结果(相对路径):
```json
{
"result": "_hello.txt",
"error": null
}
```
示例请求(绝对路径):
```json
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"path": "/path/to/file"
}
}
```
示例结果(绝对路径):
```json
{
"result": "_hello.txt",
"error": null
}
```
示例请求(url):
```json
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"url": "https://url.to.file"
}
}
```
示例结果(url):
```json
{
"result": "_hello.txt",
"error": null
}
```
#### `retrieveMediaFile`
* 检索指定文件的base64编码内容,如果文件不存在则返回`false`。
示例请求:
```json
{
"action": "retrieveMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt"
}
}
```
示例结果:
```json
{
"result": "SGVsbG8sIHdvcmxkIQ==",
"error": null
}
```
#### `getMediaFilesNames`
* 获取与模式匹配的媒体文件名。默认返回所有名称。
示例请求:
```json
{
"action": "getMediaFilesNames",
"version": 6,
"params": {
"pattern": "_hell*.txt"
}
}
```
示例结果:
```json
{
"result": ["_hello.txt"],
"error": null
}
```
#### `getMediaDirPath`
* 获取当前打开的配置文件的`collection.media`文件夹的完整路径。
示例请求:
```json
{
"action": "getMediaDirPath",
"version": 6
}
```
示例结果:
```json
{
"result": "/home/user/.local/share/Anki2/Main/collection.media",
"error": null
}
```
#### `deleteMediaFile`
* 删除媒体文件夹中的指定文件。
示例请求:
```json
{
"action": "deleteMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt"
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
---
### 杂项操作
#### `requestPermission`
* 请求使用此插件公开的API的权限。此方法不需要API密钥,是唯一接受来自任何来源的请求的方法;其他方法只接受来自受信任来源的请求,这些来源列在插件配置的`webCorsOriginList`下。默认情况下,`localhost`是受信任的。
从不受信任的来源调用此方法将在Anki中显示一个弹出窗口,询问用户是否允许您的来源使用API;来自受信任来源的调用将返回结果而不显示弹出窗口。
在拒绝许可时,用户还可以选择忽略来自该来源的进一步许可请求。这些来源最终会出现在`ignoreOriginList`中,可通过插件配置进行编辑。
结果始终包含`permission`字段,该字段反过来包含字符串`granted`或`denied`,对应于您的来源是否受信任。如果您的来源受信任,还将返回字段`requireApiKey`(如果需要则为`true`)和`version`。
这应该是您进行的第一个调用,以确保您的应用程序和Anki-Connect能够相互正确通信。新版本的Anki-Connect向后兼容;只要您使用在报告的Anki-Connect版本或更早版本中可用的操作,一切都应该正常工作。
示例请求:
```json
{
"action": "requestPermission",
"version": 6
}
```
示例结果:
```json
{
"result": {
"permission": "granted",
"requireApiKey": false,
"version": 6
},
"error": null
}
```
```json
{
"result": {
"permission": "denied"
},
"error": null
}
```
#### `version`
* 获取此插件公开的API的版本。目前定义了版本`1`到`6`。
示例请求:
```json
{
"action": "version",
"version": 6
}
```
示例结果:
```json
{
"result": 6,
"error": null
}
```
#### `apiReflect`
* 获取有关可用AnkiConnect API的信息。请求支持以下参数:
# 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`
* 返回一个数组,包含给定卡片的简易度因子(按相同顺序)。
示例请求:
```json
{
"action": "getEaseFactors",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
示例结果:
```json
{
"result": [4100, 3900],
"error": null
}
```
#### `setEaseFactors`
* 通过卡片ID设置卡片的简易度因子;如果成功(所有卡片都存在)则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "setEaseFactors",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217],
"easeFactors": [4100, 3900]
}
}
```
示例结果:
```json
{
"result": [true, true],
"error": null
}
```
#### `setSpecificValueOfCard`
* 设置单个卡片的特定值。由于更改卡片的某些值可能会在数据库中造成混乱,一些键需要将参数"warning_check"设置为True。
这可用于设置卡片的标志、更改其简易度因子、更改筛选卡组中的复习顺序以及更改列"data"(目前显然未被anki使用),以及许多其他值。
可以在[AnkiDroid的wiki](https://github.com/ankidroid/Anki-Android/wiki/Database-Structure)上找到值的列表及其各自的用途解释。
示例请求:
```json
{
"action": "setSpecificValueOfCard",
"version": 6,
"params": {
"card": 1483959291685,
"keys": ["flags", "odue"],
"newValues": ["1", "-100"]
}
}
```
示例结果:
```json
{
"result": [true, true],
"error": null
}
```
#### `suspend`
* 通过卡片ID暂停卡片;如果成功(至少有一张卡片之前没有被暂停)则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "suspend",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `unsuspend`
* 通过卡片ID取消暂停卡片;如果成功(至少有一张卡片之前被暂停)则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "unsuspend",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `suspended`
* 通过ID检查卡片是否被暂停。如果被暂停则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "suspended",
"version": 6,
"params": {
"card": 1483959293217
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `areSuspended`
* 返回一个数组,表示每张给定卡片是否被暂停(按相同顺序)。如果卡片不存在,则返回`null`。
示例请求:
```json
{
"action": "areSuspended",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217, 1234567891234]
}
}
```
示例结果:
```json
{
"result": [false, true, null],
"error": null
}
```
#### `areDue`
* 返回一个数组,表示每张给定卡片是否到期(按相同顺序)。*注意*:学习队列中有大间隔(超过20分钟)的卡片被视为未到期,直到其间隔时间过去为止,这与Anki在复习时对待它们的方式相匹配。
示例请求:
```json
{
"action": "areDue",
"version": 6,
"params": {
"cards": [1483959291685, 1483959293217]
}
}
```
示例结果:
```json
{
"result": [false, true],
"error": null
}
```
#### `getIntervals`
* 返回一个数组,包含每个给定卡片ID的最近间隔,或者当`complete`为`true`时,返回每个给定卡片ID的所有间隔的二维数组。负间隔以秒为单位,正间隔以天为单位。
示例请求1:
```json
{
"action": "getIntervals",
"version": 6,
"params": {
"cards": [1502298033753, 1502298036657]
}
}
```
示例结果1:
```json
{
"result": [-14400, 3],
"error": null
}
```
示例请求2:
```json
{
"action": "getIntervals",
"version": 6,
"params": {
"cards": [1502298033753, 1502298036657],
"complete": true
}
}
```
示例结果2:
```json
{
"result": [
[-120, -180, -240, -300, -360, -14400],
[-120, -180, -240, -300, -360, -14400, 1, 3]
],
"error": null
}
```
#### `findCards`
* 返回给定查询的卡片ID数组。功能上与`guiBrowse`相同,但不使用GUI以获得更好的性能。
示例请求:
```json
{
"action": "findCards",
"version": 6,
"params": {
"query": "deck:current"
}
}
```
示例结果:
```json
{
"result": [1494723142483, 1494703460437, 1494703479525],
"error": null
}
```
#### `cardsToNotes`
* 返回给定卡片ID的笔记ID的无序数组。对于具有相同笔记的卡片,ID在数组中只给出一次。
示例请求:
```json
{
"action": "cardsToNotes",
"version": 6,
"params": {
"cards": [1502098034045, 1502098034048, 1502298033753]
}
}
```
示例结果:
```json
{
"result": [1502098029797, 1502298025183],
"error": null
}
```
#### `cardsModTime`
* 返回一个对象列表,包含每个卡片ID的修改时间。
此功能比执行`cardsInfo`快约15倍。
示例请求:
```json
{
"action": "cardsModTime",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
示例结果:
```json
{
"result": [
{
"cardId": 1498938915662,
"mod": 1629454092
}
],
"error": null
}
```
#### `cardsInfo`
* 返回一个对象列表,包含每个卡片ID的卡片字段、正反面(包括CSS)、笔记类型、卡片所属的笔记、卡组名称、最后修改时间戳以及简易度和间隔。
示例请求:
```json
{
"action": "cardsInfo",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
示例结果:
```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
}
```
#### `forgetCards`
* 忘记卡片,使卡片再次成为新卡片。
示例请求:
```json
{
"action": "forgetCards",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `relearnCards`
* 使卡片成为"重新学习"状态。
示例请求:
```json
{
"action": "relearnCards",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `answerCards`
* 回答卡片。简易度在1(重来)到4(简单)之间。将在回答前立即开始计时器。如果卡片存在则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "answerCards",
"version": 6,
"params": {
"answers": [
{
"cardId": 1498938915662,
"ease": 2
},
{
"cardId": 1502098034048,
"ease": 4
}
]
}
}
```
示例结果:
```json
{
"result": [true, true],
"error": null
}
```
#### `setDueDate`
* 设置到期日期。如果是新卡片,则将其转为复习卡片,并使其在特定日期到期。
* 0 = 今天
* 1! = 明天 + 将间隔更改为1
* 3-7 = 随机选择3-7天
示例请求:
```json
{
"action": "setDueDate",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048],
"days": "3-7"
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
---
### 卡组操作
#### `deckNames`
* 获取当前用户的完整卡组名称列表。
示例请求:
```json
{
"action": "deckNames",
"version": 6
}
```
示例结果:
```json
{
"result": ["Default"],
"error": null
}
```
#### `deckNamesAndIds`
* 获取当前用户的完整卡组名称及其对应ID的列表。
示例请求:
```json
{
"action": "deckNamesAndIds",
"version": 6
}
```
示例结果:
```json
{
"result": {"Default": 1},
"error": null
}
```
#### `getDecks`
* 接受一个卡片ID数组,并返回一个对象,其中每个卡组名称作为键,其值是属于该卡组的给定卡片数组。
示例请求:
```json
{
"action": "getDecks",
"version": 6,
"params": {
"cards": [1502298036657, 1502298033753, 1502032366472]
}
}
```
示例结果:
```json
{
"result": {
"Default": [1502032366472],
"Japanese::JLPT N3": [1502298036657, 1502298033753]
},
"error": null
}
```
#### `createDeck`
* 创建一个新的空卡组。不会覆盖同名的已存在卡组。
示例请求:
```json
{
"action": "createDeck",
"version": 6,
"params": {
"deck": "Japanese::Tokyo"
}
}
```
示例结果:
```json
{
"result": 1519323742721,
"error": null
}
```
#### `changeDeck`
* 将具有给定ID的卡片移动到不同的卡组,如果卡组尚不存在则创建它。
示例请求:
```json
{
"action": "changeDeck",
"version": 6,
"params": {
"cards": [1502098034045, 1502098034048, 1502298033753],
"deck": "Japanese::JLPT N3"
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `deleteDecks`
* 删除具有给定名称的卡组。
参数`cardsToo` *必须*被指定并设置为`true`。
示例请求:
```json
{
"action": "deleteDecks",
"version": 6,
"params": {
"decks": ["Japanese::JLPT N5", "Easy Spanish"],
"cardsToo": true
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `getDeckConfig`
* 获取给定卡组的配置组对象。
示例请求:
```json
{
"action": "getDeckConfig",
"version": 6,
"params": {
"deck": "Default"
}
}
```
示例结果:
```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
}
```
#### `saveDeckConfig`
* 保存给定的配置组,成功时返回`true`,如果配置组的ID无效(例如不存在)则返回`false`。
示例请求:
```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
}
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `setDeckConfigId`
* 将给定卡组的配置组更改为具有给定ID的配置组。成功时返回`true`,如果给定的配置组或任何给定的卡组不存在则返回`false`。
示例请求:
```json
{
"action": "setDeckConfigId",
"version": 6,
"params": {
"decks": ["Default"],
"configId": 1
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `cloneDeckConfigId`
* 使用给定的名称创建一个新的配置组,从具有给定ID的组克隆,或者如果未指定,则从默认组克隆。返回新配置组的ID,或者如果指定的要克隆的组不存在,则返回`false`。
示例请求:
```json
{
"action": "cloneDeckConfigId",
"version": 6,
"params": {
"name": "Copy of Default",
"cloneFrom": 1
}
}
```
示例结果:
```json
{
"result": 1502972374573,
"error": null
}
```
#### `removeDeckConfigId`
* 移除具有给定ID的配置组,如果成功则返回`true`,如果尝试移除默认配置组(ID = 1)或不存在的配置组则返回`false`。
示例请求:
```json
{
"action": "removeDeckConfigId",
"version": 6,
"params": {
"configId": 1502972374573
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `getDeckStats`
* 获取给定卡组的统计信息,如总卡片数和到期卡片数。
示例请求:
```json
{
"action": "getDeckStats",
"version": 6,
"params": {
"decks": ["Japanese::JLPT N5", "Easy Spanish"]
}
}
```
示例结果:
```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
}
```
---
### 图形界面操作
#### `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)中记录的)。
指定的列需要在*卡片浏览器*中可见。
示例请求:
```json
{
"action": "guiBrowse",
"version": 6,
"params": {
"query": "deck:current",
"reorderCards": {
"order": "descending",
"columnId": "noteCrt"
}
}
}
```
示例结果:
```json
{
"result": [1494723142483, 1494703460437, 1494703479525],
"error": null
}
```
#### `guiSelectCard`
* 找到*卡片浏览器*对话框的打开实例,并根据卡片标识符选择一张卡片。
如果*卡片浏览器*是打开的,返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "guiSelectCard",
"version": 6,
"params": {
"card": 1494723142483
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiSelectedNotes`
* 找到*卡片浏览器*对话框的打开实例,并返回选中笔记的标识符数组。如果浏览器未打开,则返回空列表。
示例请求:
```json
{
"action": "guiSelectedNotes",
"version": 6
}
```
示例结果:
```json
{
"result": [1494723142483, 1494703460437, 1494703479525],
"error": null
}
```
#### `guiAddCards`
* 调用*添加卡片*对话框,使用给定的卡组和模型预设笔记,带有提供的字段值和标签。
多次调用会关闭旧窗口并_重新打开窗口_,使用新提供的值。
可以通过`audio`、`video`和`picture`键将音频、视频和图片文件嵌入到字段中。
请参考`addNote`和`storeMediaFile`的文档,了解这些字段的说明。
结果是如果用户选择确认*添加卡片*对话框,将添加的笔记的ID。
示例请求:
```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"
]
}]
}
}
}
```
示例结果:
```json
{
"result": 1496198395707,
"error": null
}
```
#### `guiEditNote`
* 打开*编辑*对话框,显示对应于给定笔记ID的笔记。
该对话框类似于*编辑当前*对话框,但:
* 有一个预览按钮,用于预览笔记的卡片
* 有一个浏览按钮,用于打开浏览器并显示这些卡片
* 有上一个/后退按钮,用于导航对话框的历史
* 没有带有关闭按钮的栏
示例请求:
```json
{
"action": "guiEditNote",
"version": 6,
"params": {
"note": 1649198355435
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `guiCurrentCard`
* 返回有关当前卡片的信息,如果不在复习模式,则返回`null`。
示例请求:
```json
{
"action": "guiCurrentCard",
"version": 6
}
```
示例结果:
```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
}
```
#### `guiStartCardTimer`
* 启动或重置当前卡片的`timerStarted`值。这对于将开始时间推迟到通过API显示卡片时很有用,从而在调用`guiAnswerCard`时使记录的回答卡片所花费的时间更准确。
示例请求:
```json
{
"action": "guiStartCardTimer",
"version": 6
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiShowQuestion`
* 显示当前卡片的问题文本;如果处于复习模式则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "guiShowQuestion",
"version": 6
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiShowAnswer`
* 显示当前卡片的答案文本;如果处于复习模式则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "guiShowAnswer",
"version": 6
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiAnswerCard`
* 回答当前卡片;如果成功则返回`true`,否则返回`false`。注意,在Anki接受任何答案之前,必须先显示当前卡片的答案。
示例请求:
```json
{
"action": "guiAnswerCard",
"version": 6,
"params": {
"ease": 1
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiUndo`
* 撤销最后一个动作/卡片;如果成功则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "guiUndo",
"version": 6
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiDeckOverview`
* 为具有给定名称的卡组打开*卡组概览*对话框;如果成功则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "guiDeckOverview",
"version": 6,
"params": {
"name": "Default"
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiDeckBrowser`
* 打开*卡组浏览器*对话框。
示例请求:
```json
{
"action": "guiDeckBrowser",
"version": 6
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `guiDeckReview`
* 开始复习具有给定名称的卡组;如果成功则返回`true`,否则返回`false`。
示例请求:
```json
{
"action": "guiDeckReview",
"version": 6,
"params": {
"name": "Default"
}
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
#### `guiImportFile`
* 调用*导入...(Ctrl+Shift+I)*对话框,并可选择提供文件路径。弹出对话框供用户审核导入。支持Anki支持的所有文件类型。如果未提供路径,则显示打开文件对话框。在Windows上的路径中必须使用正斜杠。仅支持Anki 2.1.52+。
示例请求:
```json
{
"action": "guiImportFile",
"version": 6,
"params": {
"path": "C:/Users/Desktop/cards.txt"
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `guiExitAnki`
* 安排一个请求来优雅地关闭Anki。此操作是异步的,因此它会立即返回,而不会等待Anki进程实际终止。
示例请求:
```json
{
"action": "guiExitAnki",
"version": 6
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
#### `guiCheckDatabase`
* 请求进行数据库检查,但立即返回而不等待检查完成。因此,即使在数据库检查过程中检测到错误,此操作也将始终返回`true`。
示例请求:
```json
{
"action": "guiCheckDatabase",
"version": 6
}
```
示例结果:
```json
{
"result": true,
"error": null
}
```
---
### 媒体操作
#### `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)来防止这种情况。
示例请求(相对路径):
```json
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"data": "SGVsbG8sIHdvcmxkIQ=="
}
}
```
*`_hello.txt`的内容*:
```
Hello world!
```
示例结果(相对路径):
```json
{
"result": "_hello.txt",
"error": null
}
```
示例请求(绝对路径):
```json
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"path": "/path/to/file"
}
}
```
示例结果(绝对路径):
```json
{
"result": "_hello.txt",
"error": null
}
```
示例请求(url):
```json
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"url": "https://url.to.file"
}
}
```
示例结果(url):
```json
{
"result": "_hello.txt",
"error": null
}
```
#### `retrieveMediaFile`
* 检索指定文件的base64编码内容,如果文件不存在则返回`false`。
示例请求:
```json
{
"action": "retrieveMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt"
}
}
```
示例结果:
```json
{
"result": "SGVsbG8sIHdvcmxkIQ==",
"error": null
}
```
#### `getMediaFilesNames`
* 获取与模式匹配的媒体文件名。默认返回所有名称。
示例请求:
```json
{
"action": "getMediaFilesNames",
"version": 6,
"params": {
"pattern": "_hell*.txt"
}
}
```
示例结果:
```json
{
"result": ["_hello.txt"],
"error": null
}
```
#### `getMediaDirPath`
* 获取当前打开的配置文件的`collection.media`文件夹的完整路径。
示例请求:
```json
{
"action": "getMediaDirPath",
"version": 6
}
```
示例结果:
```json
{
"result": "/home/user/.local/share/Anki2/Main/collection.media",
"error": null
}
```
#### `deleteMediaFile`
* 删除媒体文件夹中的指定文件。
示例请求:
```json
{
"action": "deleteMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt"
}
}
```
示例结果:
```json
{
"result": null,
"error": null
}
```
---
### 杂项操作
#### `requestPermission`
* 请求使用此插件公开的API的权限。此方法不需要API密钥,是唯一接受来自任何来源的请求的方法;其他方法只接受来自受信任来源的请求,这些来源列在插件配置的`webCorsOriginList`下。默认情况下,`localhost`是受信任的。
从不受信任的来源调用此方法将在Anki中显示一个弹出窗口,询问用户是否允许您的来源使用API;来自受信任来源的调用将返回结果而不显示弹出窗口。
在拒绝许可时,用户还可以选择忽略来自该来源的进一步许可请求。这些来源最终会出现在`ignoreOriginList`中,可通过插件配置进行编辑。
结果始终包含`permission`字段,该字段反过来包含字符串`granted`或`denied`,对应于您的来源是否受信任。如果您的来源受信任,还将返回字段`requireApiKey`(如果需要则为`true`)和`version`。
这应该是您进行的第一个调用,以确保您的应用程序和Anki-Connect能够相互正确通信。新版本的Anki-Connect向后兼容;只要您使用在报告的Anki-Connect版本或更早版本中可用的操作,一切都应该正常工作。
示例请求:
```json
{
"action": "requestPermission",
"version": 6
}
```
示例结果:
```json
{
"result": {
"permission": "granted",
"requireApiKey": false,
"version": 6
},
"error": null
}
```
```json
{
"result": {
"permission": "denied"
},
"error": null
}
```
#### `version`
* 获取此插件公开的API的版本。目前定义了版本`1`到`6`。
示例请求:
```json
{
"action": "version",
"version": 6
}
```
示例结果:
```json
{
"result": 6,
"error": null
}
```
#### `apiReflect`
* 获取有关可用 AnkiConnect API 的信息。请求支持以下参数:
* `scopes` - 要获取反射信息的作用域数组。
目前唯一支持的值是 `"actions"`。
* `actions` - 可以是 `null` 或者 API 方法名称的数组。
如果值为 `null`,结果将列出所有可用的 API 动作。
如果值是字符串数组,结果将只包含该数组中存在的动作。
结果将包含使用了哪些作用域及每个作用域的值。
例如,`"actions"` 作用域将包含一个 `"actions"` 属性,其中包含支持的动作名称列表。
请求示例:
```json
{
"action": "apiReflect",
"version": 6,
"params": {
"scopes": ["actions", "invalidType"],
"actions": ["apiReflect", "invalidMethod"]
}
}
```
结果示例:
```json
{
"result": {
"scopes": ["actions"],
"actions": ["apiReflect"]
},
"error": null
}
```
#### `sync`
* 将本地 Anki 集合与 AnkiWeb 同步。
请求示例:
```json
{
"action": "sync",
"version": 6
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `getProfiles`
* 获取个人资料列表。
请求示例:
```json
{
"action": "getProfiles",
"version": 6
}
```
结果示例:
```json
{
"result": ["User 1"],
"error": null
}
```
#### `getActiveProfile`
* 获取当前活动个人资料。
请求示例:
```json
{
"action": "getActiveProfile",
"version": 6
}
```
结果示例:
```json
{
"result": "User 1",
"error": null
}
```
#### `loadProfile`
* 选择请求中指定的个人资料。
请求示例:
```json
{
"action": "loadProfile",
"version": 6,
"params": {
"name": "user1"
}
}
```
结果示例:
```json
{
"result": true,
"error": null
}
```
#### `multi`
* 在一个请求中执行多个操作,返回一个数组,其中包含每个操作的响应(按给定顺序)。
请求示例:
```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
}
]
}
}
```
结果示例:
```json
{
"result": [
["Default"],
{"result": ["Default"], "error": null},
{"result": null, "error": "unsupported action"},
{"result": null, "error": "unsupported action"}
],
"error": null
}
```
#### `exportPackage`
* 将指定的牌组以 `.apkg` 格式导出。如果成功则返回 `true`,否则返回 `false`。可以指定可选属性
`includeSched`(默认为 `false`)以包含卡片的调度数据。
请求示例:
```json
{
"action": "exportPackage",
"version": 6,
"params": {
"deck": "Default",
"path": "/data/Deck.apkg",
"includeSched": true
}
}
```
结果示例:
```json
{
"result": true,
"error": null
}
```
#### `importPackage`
* 将 `.apkg` 格式的文件导入集合中。如果成功则返回 `true`,否则返回 `false`。
注意,文件路径是相对于 Anki 的 collection.media 文件夹,而不是相对于客户端。
请求示例:
```json
{
"action": "importPackage",
"version": 6,
"params": {
"path": "/data/Deck.apkg"
}
}
```
结果示例:
```json
{
"result": true,
"error": null
}
```
#### `reloadCollection`
* 告诉 Anki 从数据库重新加载所有数据。
请求示例:
```json
{
"action": "reloadCollection",
"version": 6
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
---
### 模型(笔记类型)操作
#### `modelNames`
* 获取当前用户的完整模型名称列表。
请求示例:
```json
{
"action": "modelNames",
"version": 6
}
```
结果示例:
```json
{
"result": ["Basic", "Basic (and reversed card)"],
"error": null
}
```
#### `modelNamesAndIds`
* 获取当前用户的完整模型名称及其对应的 ID 列表。
请求示例:
```json
{
"action": "modelNamesAndIds",
"version": 6
}
```
结果示例:
```json
{
"result": {
"Basic": 1483883011648,
"Basic (and reversed card)": 1483883011644,
"Basic (optional reversed card)": 1483883011631,
"Cloze": 1483883011630
},
"error": null
}
```
#### `findModelsById`
* 根据提供的模型 ID 从当前用户获取模型列表。
请求示例:
```json
{
"action": "findModelsById",
"version": 6,
"params": {
"modelIds": [1704387367119, 1704387398570]
}
}
```
结果示例:
```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
\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
\n\n{{Back}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": 1689886528158874152
},
{
"name": "Card 2",
"ord": 1,
"qfmt": "{{Back}}",
"afmt": "{{FrontSide}}\n\n
\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
}
```
#### `findModelsByName`
* 根据提供的模型名称从当前用户获取模型列表。
请求示例:
```json
{
"action": "findModelsByName",
"version": 6,
"params": {
"modelNames": ["Basic", "Basic (and reversed card)"]
}
}
```
结果示例:
```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
\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
\n\n{{Back}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": 1689886528158874152
},
{
"name": "Card 2",
"ord": 1,
"qfmt": "{{Back}}",
"afmt": "{{FrontSide}}\n\n
\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
}
```
#### `modelFieldNames`
* 获取提供的模型名称的完整字段名称列表。
请求示例:
```json
{
"action": "modelFieldNames",
"version": 6,
"params": {
"modelName": "Basic"
}
}
```
结果示例:
```json
{
"result": ["Front", "Back"],
"error": null
}
```
#### `modelFieldDescriptions`
* 获取提供的模型名称的完整字段描述列表(当字段为空时在 GUI 编辑器中显示的文本)。
请求示例:
```json
{
"action": "modelFieldDescriptions",
"version": 6,
"params": {
"modelName": "Basic"
}
}
```
结果示例:
```json
{
"result": ["", ""],
"error": null
}
```
#### `modelFieldFonts`
* 获取完整的字体列表及其字体大小。
请求示例:
```json
{
"action": "modelFieldFonts",
"version": 6,
"params": {
"modelName": "Basic"
}
}
```
结果示例:
```json
{
"result": {
"Front": {
"font": "Arial",
"size": 20
},
"Back": {
"font": "Arial",
"size": 20
}
},
"error": null
}
```
#### `modelFieldsOnTemplates`
* 返回一个对象,指示给定模型名称的每个卡片模板的问题侧和答案侧的字段。
问题侧在每个数组中首先给出。
请求示例:
```json
{
"action": "modelFieldsOnTemplates",
"version": 6,
"params": {
"modelName": "Basic (and reversed card)"
}
}
```
结果示例:
```json
{
"result": {
"Card 1": [["Front"], ["Back"]],
"Card 2": [["Back"], ["Front"]]
},
"error": null
}
```
#### `createModel`
* 创建一个新模型以在 Anki 中使用。用户必须提供 `modelName`、`inOrderFields` 和 `cardTemplates` 来
在模型中使用。有可选字段 `css` 和 `isCloze`。如果未指定,`css` 将使用默认的 Anki CSS,`isCloze` 将等于 `false`。如果 `isCloze` 为 `true`,则模型将创建为填空题型。
可以为 `cardTemplates` 的每个条目提供可选的 `Name` 字段。默认情况下,
卡片名称将是 `Card 1`, `Card 2` 等。
请求示例:
```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}}"
}
]
}
}
```
结果示例:
```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
}
```
#### `modelTemplates`
* 返回一个对象,指示与提供的模型名称相连接的每个卡片的模板内容。
请求示例:
```json
{
"action": "modelTemplates",
"version": 6,
"params": {
"modelName": "Basic (and reversed card)"
}
}
```
结果示例:
```json
{
"result": {
"Card 1": {
"Front": "{{Front}}",
"Back": "{{FrontSide}}\n\n
\n\n{{Back}}"
},
"Card 2": {
"Front": "{{Back}}",
"Back": "{{FrontSide}}\n\n
\n\n{{Front}}"
}
},
"error": null
}
```
#### `modelStyling`
* 获取按名称提供的模型的 CSS 样式。
请求示例:
```json
{
"action": "modelStyling",
"version": 6,
"params": {
"modelName": "Basic (and reversed card)"
}
}
```
结果示例:
```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
}
```
#### `updateModelTemplates`
* 修改现有模型的模板(通过名称指定)。只有指定的卡片和指定的侧面会被修改。
如果请求中不包括现有卡片或侧面,它将保持不变。
请求示例:
```json
{
"action": "updateModelTemplates",
"version": 6,
"params": {
"model": {
"name": "Custom",
"templates": {
"Card 1": {
"Front": "{{Question}}?",
"Back": "{{Answer}}!"
}
}
}
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `updateModelStyling`
* 修改现有模型的 CSS 样式(通过名称指定)。
请求示例:
```json
{
"action": "updateModelStyling",
"version": 6,
"params": {
"model": {
"name": "Custom",
"css": "p { color: blue; }"
}
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `findAndReplaceInModels`
* 在现有模型中查找并替换字符串(通过模型名称)。通过设置为 true/false 自定义在前面、后面或 CSS 中替换。
请求示例:
```json
{
"action": "findAndReplaceInModels",
"version": 6,
"params": {
"model": {
"modelName": "",
"findText": "text_to_replace",
"replaceText": "replace_with_text",
"front": true,
"back": true,
"css": true
}
}
}
```
结果示例:
```json
{
"result": 1,
"error": null
}
```
#### `modelTemplateRename`
* 重命名现有模型中的模板。
请求示例:
```json
{
"action": "modelTemplateRename",
"version": 6,
"params": {
"modelName": "Basic",
"oldTemplateName": "Card 1",
"newTemplateName": "Card 1 renamed"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelTemplateReposition`
* 重新定位现有模型中的模板。
`index` 的值从 0 开始。例如,索引 `0` 将模板放在第一个位置,索引 `2` 将模板放在第三个位置。
请求示例:
```json
{
"action": "modelTemplateReposition",
"version": 6,
"params": {
"modelName": "Basic",
"templateName": "Card 1",
"index": 1
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelTemplateAdd`
* 通过名称向现有模型添加模板。如果要更新现有模板,请使用 `updateModelTemplates`。
请求示例:
```json
{
"action": "modelTemplateAdd",
"version": 6,
"params": {
"modelName": "Basic",
"template": {
"Name": "Card 3",
"Front": "Front html {{Field1}}",
"Back": "Back html {{Field2}}"
}
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelTemplateRemove`
* 从现有模型中移除模板。
请求示例:
```json
{
"action": "modelTemplateRemove",
"version": 6,
"params": {
"modelName": "Basic",
"templateName": "Card 1"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldRename`
* 重命名给定模型的字段名称。
请求示例:
```json
{
"action": "modelFieldRename",
"version": 6,
"params": {
"modelName": "Basic",
"oldFieldName": "Front",
"newFieldName": "FrontRenamed"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldReposition`
* 重新定位给定模型的字段列表中的字段。
`index` 的值从 0 开始。例如,索引 `0` 将字段放在第一个位置,索引 `2` 将字段放在第三个位置。
请求示例:
```json
{
"action": "modelFieldReposition",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Back",
"index": 0
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldAdd`
* 在给定模型中创建新字段。
可以选择提供 `index` 值,其工作方式与 `modelFieldReposition` 中的索引完全相同。默认情况下,字段将添加到字段列表的末尾。
请求示例:
```json
{
"action": "modelFieldAdd",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "NewField",
"index": 0
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldRemove`
* 删除给定模型中的字段。
请求示例:
```json
{
"action": "modelFieldRemove",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldSetFont`
* 设置给定模型中字段的字体。
请求示例:
```json
{
"action": "modelFieldSetFont",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front",
"font": "Courier"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldSetFontSize`
* 设置给定模型中字段的字体大小。
请求示例:
```json
{
"action": "modelFieldSetFontSize",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front",
"fontSize": 10
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldSetDescription`
* 设置给定模型中字段的描述(当字段为空时在 GUI 编辑器中看到的文本)。
旧版本的 Anki(2.1.49 及以下)没有字段描述。在这种情况下,将返回 `false`。
请求示例:
```json
{
"action": "modelFieldSetDescription",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front",
"description": "example field description"
}
}
```
结果示例:
```json
{
"result": true,
"error": null
}
```
---
### 笔记操作
#### `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`。
请求示例:
```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"
]
}]
}
}
}
```
结果示例:
```json
{
"result": 1496198395707,
"error": null
}
```
#### `addNotes`
* 使用给定的牌组和模型创建多个笔记,包含提供的字段值和标签。返回一个数组,
包含创建的笔记的标识符。如有任何错误,将收集并返回所有错误。
* 有关 `notes` 数组中对象的解释,请参阅 `addNote` 的文档。
请求示例:
```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"
}
}
]
}
}
```
结果示例:
```json
{
"result":null,
"error":"['model was not found: non_existent_model']"
}
```
#### `canAddNotes`
* 接受一个对象数组,这些对象定义候选笔记的参数(参见 `addNote`),并返回一个布尔值数组,
指示相应索引处的参数是否可用于创建新笔记。
请求示例:
```json
{
"action": "canAddNotes",
"version": 6,
"params": {
"notes": [
{
"deckName": "Default",
"modelName": "Basic",
"fields": {
"Front": "front content",
"Back": "back content"
},
"tags": [
"yomichan"
]
}
]
}
}
```
结果示例:
```json
{
"result": [true],
"error": null
}
```
#### `canAddNotesWithErrorDetail`
* 接受一个对象数组,这些对象定义候选笔记的参数(参见 `addNote`),并返回一个对象数组,
包含 `canAdd` 和 `error` 字段。
* `canAdd` 指示相应索引处的参数是否可用于创建新笔记。
* `error` 包含无法添加笔记的原因说明。
请求示例:
```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"
]
}
]
}
}
```
结果示例:
```json
{
"result": [
{
"canAdd": false,
"error": "cannot create note because it is a duplicate"
},
{
"canAdd": true
}
],
"error": null
}
```
#### `updateNoteFields`
* 修改现有笔记的字段。您还可以包含音频、视频或图片文件,这些文件将添加到笔记中,并带有
可选的 `audio`、`video` 或 `picture` 属性。有关 `audio`、`video` 或 `picture` 数组中对象的解释,请参阅 `addNote` 的文档。
> **警告**:
> 您不能在 Anki 浏览器中查看您正在更新的笔记,否则
> 字段将不会更新。有关更多详细信息,请参阅[此问题](https://github.com/FooSoft/anki-connect/issues/82)。
请求示例:
```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"
]
}]
}
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `updateNote`
* 修改现有笔记的字段和/或标签。
换句话说,结合了 `updateNoteFields` 和 `updateNoteTags` 的功能。
请参阅它们的文档以了解所有属性。
可以省略 `fields` 或 `tags` 属性,而不影响另一个。
因此有效的 `updateNoteFields` 请求也适用于 `updateNote`。
笔记必须具有 `fields` 属性才能更新可选的音频、视频或图片对象。
如果既没有提供 `fields` 也没有提供 `tags`,则该方法将失败。
首先更新字段,如果更新标签失败,则不会回滚字段更新。
如果更新字段失败,则不会更新标签。
> **警告**
> 您不能在 Anki 浏览器中查看您正在更新的笔记,否则
> 字段将不会更新。有关更多详细信息,请参阅[此问题](https://github.com/FooSoft/anki-connect/issues/82)。
请求示例:
```json
{
"action": "updateNote",
"version": 6,
"params": {
"note": {
"id": 1514547547030,
"fields": {
"Front": "new front content",
"Back": "new back content"
},
"tags": ["new", "tags"]
}
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `updateNoteModel`
* 更新现有笔记的模型、字段和标签。
这允许您更改笔记的模型,用新内容更新其字段,并设置新标签。
请求示例:
```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"]
}
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `updateNoteTags`
* 通过笔记 ID 设置笔记的标签。旧标签将被移除。
请求示例:
```json
{
"action": "updateNoteTags",
"version": 6,
"params": {
"note": 1483959289817,
"tags": ["european-languages"]
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `getNoteTags`
* 通过笔记 ID 获取笔记的标签。
请求示例:
```json
{
"action": "getNoteTags",
"version": 6,
"params": {
"note": 1483959289817
}
}
```
结果示例:
```json
{
"result": ["european-languages"],
"error": null
}
```
#### `addTags`
* 通过笔记 ID 向笔记添加标签。
请求示例:
```json
{
"action": "addTags",
"version": 6,
"params": {
"notes": [1483959289817, 1483959291695],
"tags": "european-languages"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `removeTags`
* 通过笔记 ID 从笔记中移除标签。
请求示例:
```json
{
"action": "removeTags",
"version": 6,
"params": {
"notes": [1483959289817, 1483959291695],
"tags": "european-languages"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `getTags`
* 获取当前用户的标签完整列表。
请求示例:
```json
{
"action": "getTags",
"version": 6
}
```
结果示例:
```json
{
"result": ["european-languages", "idioms"],
"error": null
}
```
#### `clearUnusedTags`
* 清除当前用户笔记中所有未使用的标签。
请求示例:
```json
{
"action": "clearUnusedTags",
"version": 6
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `replaceTags`
* 通过笔记 ID 替换笔记中的标签。
请求示例:
```json
{
"action": "replaceTags",
"version": 6,
"params": {
"notes": [1483959289817, 1483959291695],
"tag_to_replace": "european-languages",
"replace_with_tag": "french-languages"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `replaceTagsInAllNotes`
* 替换当前用户所有笔记中的标签。
请求示例:
```json
{
"action": "replaceTagsInAllNotes",
"version": 6,
"params": {
"tag_to_replace": "european-languages",
"replace_with_tag": "french-languages"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `findNotes`
* 返回给定查询的笔记 ID 数组。查询语法[在此处有文档](https://docs.ankiweb.net/searching.html)。
请求示例:
```json
{
"action": "findNotes",
"version": 6,
"params": {
"query": "deck:current"
}
}
```
结果示例:
```json
{
"result": [1483959289817, 1483959291695],
"error": null
}
```
#### `notesInfo`
* 返回一个对象列表,每个笔记 ID 包含笔记字段、标签、笔记类型、修改时间、属于该笔记的卡片以及创建笔记的个人资料。
请求示例(笔记 id):
```json
{
"action": "notesInfo",
"version": 6,
"params": {
"notes": [1502298033753]
}
}
```
请求示例(查询):
```json
{
"action": "notesInfo",
"version": 6,
"params": {
"query": "deck:current"
}
}
```
结果示例:
```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
}
```
s
#### `notesModTime`
* 返回一个对象列表,每个笔记 ID 包含修改时间。
请求示例:
#### `apiReflect`
* 获取有关可用 AnkiConnect API 的信息。请求支持以下参数:
* `scopes` - 要获取反射信息的作用域数组。
目前唯一支持的值是 `"actions"`。
* `actions` - 可以是 `null` 或者 API 方法名称的数组。
如果值为 `null`,结果将列出所有可用的 API 动作。
如果值是字符串数组,结果将只包含该数组中存在的动作。
结果将包含使用了哪些作用域及每个作用域的值。
例如,`"actions"` 作用域将包含一个 `"actions"` 属性,其中包含支持的动作名称列表。
请求示例:
```json
{
"action": "apiReflect",
"version": 6,
"params": {
"scopes": ["actions", "invalidType"],
"actions": ["apiReflect", "invalidMethod"]
}
}
```
结果示例:
```json
{
"result": {
"scopes": ["actions"],
"actions": ["apiReflect"]
},
"error": null
}
```
#### `sync`
* 将本地 Anki 集合与 AnkiWeb 同步。
请求示例:
```json
{
"action": "sync",
"version": 6
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `getProfiles`
* 获取个人资料列表。
请求示例:
```json
{
"action": "getProfiles",
"version": 6
}
```
结果示例:
```json
{
"result": ["User 1"],
"error": null
}
```
#### `getActiveProfile`
* 获取当前活动个人资料。
请求示例:
```json
{
"action": "getActiveProfile",
"version": 6
}
```
结果示例:
```json
{
"result": "User 1",
"error": null
}
```
#### `loadProfile`
* 选择请求中指定的个人资料。
请求示例:
```json
{
"action": "loadProfile",
"version": 6,
"params": {
"name": "user1"
}
}
```
结果示例:
```json
{
"result": true,
"error": null
}
```
#### `multi`
* 在一个请求中执行多个操作,返回一个数组,其中包含每个操作的响应(按给定顺序)。
请求示例:
```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
}
]
}
}
```
结果示例:
```json
{
"result": [
["Default"],
{"result": ["Default"], "error": null},
{"result": null, "error": "unsupported action"},
{"result": null, "error": "unsupported action"}
],
"error": null
}
```
#### `exportPackage`
* 将指定的牌组以 `.apkg` 格式导出。如果成功则返回 `true`,否则返回 `false`。可以指定可选属性
`includeSched`(默认为 `false`)以包含卡片的调度数据。
请求示例:
```json
{
"action": "exportPackage",
"version": 6,
"params": {
"deck": "Default",
"path": "/data/Deck.apkg",
"includeSched": true
}
}
```
结果示例:
```json
{
"result": true,
"error": null
}
```
#### `importPackage`
* 将 `.apkg` 格式的文件导入集合中。如果成功则返回 `true`,否则返回 `false`。
注意,文件路径是相对于 Anki 的 collection.media 文件夹,而不是相对于客户端。
请求示例:
```json
{
"action": "importPackage",
"version": 6,
"params": {
"path": "/data/Deck.apkg"
}
}
```
结果示例:
```json
{
"result": true,
"error": null
}
```
#### `reloadCollection`
* 告诉 Anki 从数据库重新加载所有数据。
请求示例:
```json
{
"action": "reloadCollection",
"version": 6
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
---
### 模型(笔记类型)操作
#### `modelNames`
* 获取当前用户的完整模型名称列表。
请求示例:
```json
{
"action": "modelNames",
"version": 6
}
```
结果示例:
```json
{
"result": ["Basic", "Basic (and reversed card)"],
"error": null
}
```
#### `modelNamesAndIds`
* 获取当前用户的完整模型名称及其对应的 ID 列表。
请求示例:
```json
{
"action": "modelNamesAndIds",
"version": 6
}
```
结果示例:
```json
{
"result": {
"Basic": 1483883011648,
"Basic (and reversed card)": 1483883011644,
"Basic (optional reversed card)": 1483883011631,
"Cloze": 1483883011630
},
"error": null
}
```
#### `findModelsById`
* 根据提供的模型 ID 从当前用户获取模型列表。
请求示例:
```json
{
"action": "findModelsById",
"version": 6,
"params": {
"modelIds": [1704387367119, 1704387398570]
}
}
```
结果示例:
```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
\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
\n\n{{Back}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": 1689886528158874152
},
{
"name": "Card 2",
"ord": 1,
"qfmt": "{{Back}}",
"afmt": "{{FrontSide}}\n\n
\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
}
```
#### `findModelsByName`
* 根据提供的模型名称从当前用户获取模型列表。
请求示例:
```json
{
"action": "findModelsByName",
"version": 6,
"params": {
"modelNames": ["Basic", "Basic (and reversed card)"]
}
}
```
结果示例:
```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
\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
\n\n{{Back}}",
"bqfmt": "",
"bafmt": "",
"did": null,
"bfont": "",
"bsize": 0,
"id": 1689886528158874152
},
{
"name": "Card 2",
"ord": 1,
"qfmt": "{{Back}}",
"afmt": "{{FrontSide}}\n\n
\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
}
```
#### `modelFieldNames`
* 获取提供的模型名称的完整字段名称列表。
请求示例:
```json
{
"action": "modelFieldNames",
"version": 6,
"params": {
"modelName": "Basic"
}
}
```
结果示例:
```json
{
"result": ["Front", "Back"],
"error": null
}
```
#### `modelFieldDescriptions`
* 获取提供的模型名称的完整字段描述列表(当字段为空时在 GUI 编辑器中显示的文本)。
请求示例:
```json
{
"action": "modelFieldDescriptions",
"version": 6,
"params": {
"modelName": "Basic"
}
}
```
结果示例:
```json
{
"result": ["", ""],
"error": null
}
```
#### `modelFieldFonts`
* 获取完整的字体列表及其字体大小。
请求示例:
```json
{
"action": "modelFieldFonts",
"version": 6,
"params": {
"modelName": "Basic"
}
}
```
结果示例:
```json
{
"result": {
"Front": {
"font": "Arial",
"size": 20
},
"Back": {
"font": "Arial",
"size": 20
}
},
"error": null
}
```
#### `modelFieldsOnTemplates`
* 返回一个对象,指示给定模型名称的每个卡片模板的问题侧和答案侧的字段。
问题侧在每个数组中首先给出。
请求示例:
```json
{
"action": "modelFieldsOnTemplates",
"version": 6,
"params": {
"modelName": "Basic (and reversed card)"
}
}
```
结果示例:
```json
{
"result": {
"Card 1": [["Front"], ["Back"]],
"Card 2": [["Back"], ["Front"]]
},
"error": null
}
```
#### `createModel`
* 创建一个新模型以在 Anki 中使用。用户必须提供 `modelName`、`inOrderFields` 和 `cardTemplates` 来
在模型中使用。有可选字段 `css` 和 `isCloze`。如果未指定,`css` 将使用默认的 Anki CSS,`isCloze` 将等于 `false`。如果 `isCloze` 为 `true`,则模型将创建为填空题型。
可以为 `cardTemplates` 的每个条目提供可选的 `Name` 字段。默认情况下,
卡片名称将是 `Card 1`, `Card 2` 等。
请求示例:
```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}}"
}
]
}
}
```
结果示例:
```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
}
```
#### `modelTemplates`
* 返回一个对象,指示与提供的模型名称相连接的每个卡片的模板内容。
请求示例:
```json
{
"action": "modelTemplates",
"version": 6,
"params": {
"modelName": "Basic (and reversed card)"
}
}
```
结果示例:
```json
{
"result": {
"Card 1": {
"Front": "{{Front}}",
"Back": "{{FrontSide}}\n\n
\n\n{{Back}}"
},
"Card 2": {
"Front": "{{Back}}",
"Back": "{{FrontSide}}\n\n
\n\n{{Front}}"
}
},
"error": null
}
```
#### `modelStyling`
* 获取按名称提供的模型的 CSS 样式。
请求示例:
```json
{
"action": "modelStyling",
"version": 6,
"params": {
"modelName": "Basic (and reversed card)"
}
}
```
结果示例:
```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
}
```
#### `updateModelTemplates`
* 修改现有模型的模板(通过名称指定)。只有指定的卡片和指定的侧面会被修改。
如果请求中不包括现有卡片或侧面,它将保持不变。
请求示例:
```json
{
"action": "updateModelTemplates",
"version": 6,
"params": {
"model": {
"name": "Custom",
"templates": {
"Card 1": {
"Front": "{{Question}}?",
"Back": "{{Answer}}!"
}
}
}
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `updateModelStyling`
* 修改现有模型的 CSS 样式(通过名称指定)。
请求示例:
```json
{
"action": "updateModelStyling",
"version": 6,
"params": {
"model": {
"name": "Custom",
"css": "p { color: blue; }"
}
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `findAndReplaceInModels`
* 在现有模型中查找并替换字符串(通过模型名称)。通过设置为 true/false 自定义在前面、后面或 CSS 中替换。
请求示例:
```json
{
"action": "findAndReplaceInModels",
"version": 6,
"params": {
"model": {
"modelName": "",
"findText": "text_to_replace",
"replaceText": "replace_with_text",
"front": true,
"back": true,
"css": true
}
}
}
```
结果示例:
```json
{
"result": 1,
"error": null
}
```
#### `modelTemplateRename`
* 重命名现有模型中的模板。
请求示例:
```json
{
"action": "modelTemplateRename",
"version": 6,
"params": {
"modelName": "Basic",
"oldTemplateName": "Card 1",
"newTemplateName": "Card 1 renamed"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelTemplateReposition`
* 重新定位现有模型中的模板。
`index` 的值从 0 开始。例如,索引 `0` 将模板放在第一个位置,索引 `2` 将模板放在第三个位置。
请求示例:
```json
{
"action": "modelTemplateReposition",
"version": 6,
"params": {
"modelName": "Basic",
"templateName": "Card 1",
"index": 1
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelTemplateAdd`
* 通过名称向现有模型添加模板。如果要更新现有模板,请使用 `updateModelTemplates`。
请求示例:
```json
{
"action": "modelTemplateAdd",
"version": 6,
"params": {
"modelName": "Basic",
"template": {
"Name": "Card 3",
"Front": "Front html {{Field1}}",
"Back": "Back html {{Field2}}"
}
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelTemplateRemove`
* 从现有模型中移除模板。
请求示例:
```json
{
"action": "modelTemplateRemove",
"version": 6,
"params": {
"modelName": "Basic",
"templateName": "Card 1"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldRename`
* 重命名给定模型的字段名称。
请求示例:
```json
{
"action": "modelFieldRename",
"version": 6,
"params": {
"modelName": "Basic",
"oldFieldName": "Front",
"newFieldName": "FrontRenamed"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldReposition`
* 重新定位给定模型的字段列表中的字段。
`index` 的值从 0 开始。例如,索引 `0` 将字段放在第一个位置,索引 `2` 将字段放在第三个位置。
请求示例:
```json
{
"action": "modelFieldReposition",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Back",
"index": 0
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldAdd`
* 在给定模型中创建新字段。
可以选择提供 `index` 值,其工作方式与 `modelFieldReposition` 中的索引完全相同。默认情况下,字段将添加到字段列表的末尾。
请求示例:
```json
{
"action": "modelFieldAdd",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "NewField",
"index": 0
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldRemove`
* 删除给定模型中的字段。
请求示例:
```json
{
"action": "modelFieldRemove",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldSetFont`
* 设置给定模型中字段的字体。
请求示例:
```json
{
"action": "modelFieldSetFont",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front",
"font": "Courier"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldSetFontSize`
* 设置给定模型中字段的字体大小。
请求示例:
```json
{
"action": "modelFieldSetFontSize",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front",
"fontSize": 10
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `modelFieldSetDescription`
* 设置给定模型中字段的描述(当字段为空时在 GUI 编辑器中看到的文本)。
旧版本的 Anki(2.1.49 及以下)没有字段描述。在这种情况下,将返回 `false`。
请求示例:
```json
{
"action": "modelFieldSetDescription",
"version": 6,
"params": {
"modelName": "Basic",
"fieldName": "Front",
"description": "example field description"
}
}
```
结果示例:
```json
{
"result": true,
"error": null
}
```
---
### 笔记操作
#### `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`。
请求示例:
```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"
]
}]
}
}
}
```
结果示例:
```json
{
"result": 1496198395707,
"error": null
}
```
#### `addNotes`
* 使用给定的牌组和模型创建多个笔记,包含提供的字段值和标签。返回一个数组,
包含创建的笔记的标识符。如有任何错误,将收集并返回所有错误。
* 有关 `notes` 数组中对象的解释,请参阅 `addNote` 的文档。
请求示例:
```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"
}
}
]
}
}
```
结果示例:
```json
{
"result":null,
"error":"['model was not found: non_existent_model']"
}
```
#### `canAddNotes`
* 接受一个对象数组,这些对象定义候选笔记的参数(参见 `addNote`),并返回一个布尔值数组,
指示相应索引处的参数是否可用于创建新笔记。
请求示例:
```json
{
"action": "canAddNotes",
"version": 6,
"params": {
"notes": [
{
"deckName": "Default",
"modelName": "Basic",
"fields": {
"Front": "front content",
"Back": "back content"
},
"tags": [
"yomichan"
]
}
]
}
}
```
结果示例:
```json
{
"result": [true],
"error": null
}
```
#### `canAddNotesWithErrorDetail`
* 接受一个对象数组,这些对象定义候选笔记的参数(参见 `addNote`),并返回一个对象数组,
包含 `canAdd` 和 `error` 字段。
* `canAdd` 指示相应索引处的参数是否可用于创建新笔记。
* `error` 包含无法添加笔记的原因说明。
请求示例:
```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"
]
}
]
}
}
```
结果示例:
```json
{
"result": [
{
"canAdd": false,
"error": "cannot create note because it is a duplicate"
},
{
"canAdd": true
}
],
"error": null
}
```
#### `updateNoteFields`
* 修改现有笔记的字段。您还可以包含音频、视频或图片文件,这些文件将添加到笔记中,并带有
可选的 `audio`、`video` 或 `picture` 属性。有关 `audio`、`video` 或 `picture` 数组中对象的解释,请参阅 `addNote` 的文档。
> **警告**:
> 您不能在 Anki 浏览器中查看您正在更新的笔记,否则
> 字段将不会更新。有关更多详细信息,请参阅[此问题](https://github.com/FooSoft/anki-connect/issues/82)。
请求示例:
```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"
]
}]
}
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `updateNote`
* 修改现有笔记的字段和/或标签。
换句话说,结合了 `updateNoteFields` 和 `updateNoteTags` 的功能。
请参阅它们的文档以了解所有属性。
可以省略 `fields` 或 `tags` 属性,而不影响另一个。
因此有效的 `updateNoteFields` 请求也适用于 `updateNote`。
笔记必须具有 `fields` 属性才能更新可选的音频、视频或图片对象。
如果既没有提供 `fields` 也没有提供 `tags`,则该方法将失败。
首先更新字段,如果更新标签失败,则不会回滚字段更新。
如果更新字段失败,则不会更新标签。
> **警告**
> 您不能在 Anki 浏览器中查看您正在更新的笔记,否则
> 字段将不会更新。有关更多详细信息,请参阅[此问题](https://github.com/FooSoft/anki-connect/issues/82)。
请求示例:
```json
{
"action": "updateNote",
"version": 6,
"params": {
"note": {
"id": 1514547547030,
"fields": {
"Front": "new front content",
"Back": "new back content"
},
"tags": ["new", "tags"]
}
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `updateNoteModel`
* 更新现有笔记的模型、字段和标签。
这允许您更改笔记的模型,用新内容更新其字段,并设置新标签。
请求示例:
```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"]
}
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `updateNoteTags`
* 通过笔记 ID 设置笔记的标签。旧标签将被移除。
请求示例:
```json
{
"action": "updateNoteTags",
"version": 6,
"params": {
"note": 1483959289817,
"tags": ["european-languages"]
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `getNoteTags`
* 通过笔记 ID 获取笔记的标签。
请求示例:
```json
{
"action": "getNoteTags",
"version": 6,
"params": {
"note": 1483959289817
}
}
```
结果示例:
```json
{
"result": ["european-languages"],
"error": null
}
```
#### `addTags`
* 通过笔记 ID 向笔记添加标签。
请求示例:
```json
{
"action": "addTags",
"version": 6,
"params": {
"notes": [1483959289817, 1483959291695],
"tags": "european-languages"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `removeTags`
* 通过笔记 ID 从笔记中移除标签。
请求示例:
```json
{
"action": "removeTags",
"version": 6,
"params": {
"notes": [1483959289817, 1483959291695],
"tags": "european-languages"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `getTags`
* 获取当前用户的标签完整列表。
请求示例:
```json
{
"action": "getTags",
"version": 6
}
```
结果示例:
```json
{
"result": ["european-languages", "idioms"],
"error": null
}
```
#### `clearUnusedTags`
* 清除当前用户笔记中所有未使用的标签。
请求示例:
```json
{
"action": "clearUnusedTags",
"version": 6
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `replaceTags`
* 通过笔记 ID 替换笔记中的标签。
请求示例:
```json
{
"action": "replaceTags",
"version": 6,
"params": {
"notes": [1483959289817, 1483959291695],
"tag_to_replace": "european-languages",
"replace_with_tag": "french-languages"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `replaceTagsInAllNotes`
* 替换当前用户所有笔记中的标签。
请求示例:
```json
{
"action": "replaceTagsInAllNotes",
"version": 6,
"params": {
"tag_to_replace": "european-languages",
"replace_with_tag": "french-languages"
}
}
```
结果示例:
```json
{
"result": null,
"error": null
}
```
#### `findNotes`
* 返回给定查询的笔记 ID 数组。查询语法[在此处有文档](https://docs.ankiweb.net/searching.html)。
请求示例:
```json
{
"action": "findNotes",
"version": 6,
"params": {
"query": "deck:current"
}
}
```
结果示例:
```json
{
"result": [1483959289817, 1483959291695],
"error": null
}
```
#### `notesInfo`
* 返回一个对象列表,每个笔记 ID 包含笔记字段、标签、笔记类型、修改时间、属于该笔记的卡片以及创建笔记的个人资料。
请求示例(笔记 id):
```json
{
"action": "notesInfo",
"version": 6,
"params": {
"notes": [1502298033753]
}
}
```
请求示例(查询):
```json
{
"action": "notesInfo",
"version": 6,
"params": {
"query": "deck:current"
}
}
```
结果示例:
```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
}
```
#### `notesModTime`
* 返回一个对象列表,每个笔记 ID 包含修改时间。
请求示例: