Add getNoteTags, updateNoteTags and updateNote
getNoteTags returns [str ...] of tags for a given note (note: int) updateNoteTags removes the existing tags and sets new tags updateNote combines the old updateNoteFields and the new updateNoteTags Closes #369
This commit is contained in:
parent
7234914d44
commit
2f50c747fb
94
README.md
94
README.md
@ -2533,7 +2533,7 @@ corresponding to when the API was available for use.
|
|||||||
|
|
||||||
* **updateNoteFields**
|
* **updateNoteFields**
|
||||||
|
|
||||||
Modify the fields of an exist note. You can also include audio, video, or picture files which will be added to the note with an
|
Modify the fields of an existing note. You can also include audio, video, or picture files which will be added to the note with an
|
||||||
optional `audio`, `video`, or `picture` property. Please see the documentation for `addNote` for an explanation of objects in the `audio`, `video`, or `picture` array.
|
optional `audio`, `video`, or `picture` property. Please see the documentation for `addNote` for an explanation of objects in the `audio`, `video`, or `picture` array.
|
||||||
|
|
||||||
> **Warning**
|
> **Warning**
|
||||||
@ -2574,6 +2574,98 @@ corresponding to when the API was available for use.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
* **updateNote**
|
||||||
|
|
||||||
|
Modify the fields and/or tags of an existing note.
|
||||||
|
In other words, combines `updateNoteFields` and `updateNoteTags`.
|
||||||
|
Please see their documentation for an explanation of all properties.
|
||||||
|
|
||||||
|
Either `fields` or `tags` property can be omitted without affecting the other.
|
||||||
|
Thus valid requests to `updateNoteFields` also work with `updateNote`.
|
||||||
|
The note must have the `fields` property in order to update the optional audio, video, or picture objects.
|
||||||
|
|
||||||
|
If neither `fields` nor `tags` are provided, the method will fail.
|
||||||
|
Fields are updated first and are not rolled back if updating tags fails.
|
||||||
|
Tags are not updated if updating fields fails.
|
||||||
|
|
||||||
|
> **Warning**
|
||||||
|
> You must not be viewing the note that you are updating on your Anki browser, otherwise
|
||||||
|
> the fields will not update. See [this issue](https://github.com/FooSoft/anki-connect/issues/82)
|
||||||
|
> for further details.
|
||||||
|
|
||||||
|
*Sample request*:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "updateNote",
|
||||||
|
"version": 6,
|
||||||
|
"params": {
|
||||||
|
"note": {
|
||||||
|
"id": 1514547547030,
|
||||||
|
"fields": {
|
||||||
|
"Front": "new front content",
|
||||||
|
"Back": "new back content"
|
||||||
|
},
|
||||||
|
"tags": ["new", "tags"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Sample result*:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"result": null,
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* **updateNoteTags**
|
||||||
|
|
||||||
|
Set a note's tags by note ID. Old tags will be removed.
|
||||||
|
|
||||||
|
*Sample request*:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "updateNoteTags",
|
||||||
|
"version": 6,
|
||||||
|
"params": {
|
||||||
|
"note": 1483959289817,
|
||||||
|
"tags": ["european-languages"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Sample result*:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"result": null,
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* **getNoteTags**
|
||||||
|
|
||||||
|
Get a note's tags by note ID.
|
||||||
|
|
||||||
|
*Sample request*:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "getNoteTags",
|
||||||
|
"version": 6,
|
||||||
|
"params": {
|
||||||
|
"note": 1483959289817,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Sample result*:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"result": ["european-languages"],
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
* **addTags**
|
* **addTags**
|
||||||
|
|
||||||
Adds tags to notes by note ID.
|
Adds tags to notes by note ID.
|
||||||
|
@ -811,6 +811,37 @@ class AnkiConnect:
|
|||||||
self.stopEditing()
|
self.stopEditing()
|
||||||
|
|
||||||
|
|
||||||
|
@util.api()
|
||||||
|
def updateNote(self, note):
|
||||||
|
updated = False
|
||||||
|
if 'fields' in note.keys():
|
||||||
|
self.updateNoteFields(note)
|
||||||
|
updated = True
|
||||||
|
if 'tags' in note.keys():
|
||||||
|
self.updateNoteTags(note['id'], note['tags'])
|
||||||
|
updated = True
|
||||||
|
if not updated:
|
||||||
|
raise Exception('Must provide a "fields" or "tags" property.')
|
||||||
|
|
||||||
|
|
||||||
|
@util.api()
|
||||||
|
def updateNoteTags(self, note, tags):
|
||||||
|
if type(tags) == str:
|
||||||
|
tags = [tags]
|
||||||
|
if type(tags) != list or not all([type(t) == str for t in tags]):
|
||||||
|
raise Exception('Must provide tags as a list of strings')
|
||||||
|
|
||||||
|
for old_tag in self.getNoteTags(note):
|
||||||
|
self.removeTags([note], old_tag)
|
||||||
|
for new_tag in tags:
|
||||||
|
self.addTags([note], new_tag)
|
||||||
|
|
||||||
|
|
||||||
|
@util.api()
|
||||||
|
def getNoteTags(self, note):
|
||||||
|
return self.getNote(note).tags
|
||||||
|
|
||||||
|
|
||||||
@util.api()
|
@util.api()
|
||||||
def addTags(self, notes, tags, add=True):
|
def addTags(self, notes, tags, add=True):
|
||||||
self.startEditing()
|
self.startEditing()
|
||||||
|
@ -98,6 +98,12 @@ class TestTags:
|
|||||||
ac.clearUnusedTags()
|
ac.clearUnusedTags()
|
||||||
assert ac.getTags() == ["tag1"]
|
assert ac.getTags() == ["tag1"]
|
||||||
|
|
||||||
|
def test_updateNoteTags_and_getNoteTags(self, setup):
|
||||||
|
ac.updateNoteTags(note=setup.note1_id, tags="footag")
|
||||||
|
assert ac.getNoteTags(note=setup.note1_id) == ["footag"]
|
||||||
|
ac.updateNoteTags(note=setup.note1_id, tags=["foo", "bar", "baz"])
|
||||||
|
assert len(ac.getNoteTags(note=setup.note1_id)) == 3
|
||||||
|
|
||||||
|
|
||||||
class TestUpdateNoteFields:
|
class TestUpdateNoteFields:
|
||||||
def test_updateNoteFields(self, setup):
|
def test_updateNoteFields(self, setup):
|
||||||
@ -107,12 +113,27 @@ class TestUpdateNoteFields:
|
|||||||
notes_info = ac.notesInfo(notes=[setup.note1_id])
|
notes_info = ac.notesInfo(notes=[setup.note1_id])
|
||||||
assert notes_info[0]["fields"]["field2"]["value"] == "bar"
|
assert notes_info[0]["fields"]["field2"]["value"] == "bar"
|
||||||
|
|
||||||
def test_updateNoteFields_will_note_update_invalid_notes(self, setup):
|
def test_updateNoteFields_will_not_update_invalid_notes(self, setup):
|
||||||
bad_note = {"id": 123, "fields": make_note()["fields"]}
|
bad_note = {"id": 123, "fields": make_note()["fields"]}
|
||||||
with pytest.raises(NotFoundError):
|
with pytest.raises(NotFoundError):
|
||||||
ac.updateNoteFields(note=bad_note)
|
ac.updateNoteFields(note=bad_note)
|
||||||
|
|
||||||
|
|
||||||
|
class TestUpdateNote:
|
||||||
|
def test_updateNote(self, setup):
|
||||||
|
new_fields = {"field1": "frontbar", "field2": "backbar"}
|
||||||
|
new_tags = ["foobar"]
|
||||||
|
good_note = {"id": setup.note1_id, "fields": new_fields, "tags": new_tags}
|
||||||
|
ac.updateNote(note=good_note)
|
||||||
|
notes_info = ac.notesInfo(notes=[setup.note1_id])
|
||||||
|
assert notes_info[0]["fields"]["field2"]["value"] == "backbar"
|
||||||
|
assert notes_info[0]["tags"] == ["foobar"]
|
||||||
|
|
||||||
|
def test_updateNote_requires_either_fields_or_tags(self, setup):
|
||||||
|
with pytest.raises(Exception, match="ust provide"):
|
||||||
|
ac.updateNote(note={"id": setup.note1_id})
|
||||||
|
|
||||||
|
|
||||||
class TestCanAddNotes:
|
class TestCanAddNotes:
|
||||||
foo_bar_notes = [make_note(front="foo"), make_note(front="bar")]
|
foo_bar_notes = [make_note(front="foo"), make_note(front="bar")]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user