// Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html syntax = "proto3"; option java_multiple_files = true; package anki.decks; import "anki/generic.proto"; import "anki/collection.proto"; service DecksService { rpc NewDeck(generic.Empty) returns (Deck); rpc AddDeck(Deck) returns (collection.OpChangesWithId); rpc AddDeckLegacy(generic.Json) returns (collection.OpChangesWithId); rpc AddOrUpdateDeckLegacy(AddOrUpdateDeckLegacyRequest) returns (DeckId); rpc DeckTree(DeckTreeRequest) returns (DeckTreeNode); rpc DeckTreeLegacy(generic.Empty) returns (generic.Json); rpc GetAllDecksLegacy(generic.Empty) returns (generic.Json); rpc GetDeckIdByName(generic.String) returns (DeckId); rpc GetDeck(DeckId) returns (Deck); rpc UpdateDeck(Deck) returns (collection.OpChanges); rpc UpdateDeckLegacy(generic.Json) returns (collection.OpChanges); rpc SetDeckCollapsed(SetDeckCollapsedRequest) returns (collection.OpChanges); rpc GetDeckLegacy(DeckId) returns (generic.Json); rpc GetDeckNames(GetDeckNamesRequest) returns (DeckNames); rpc GetDeckAndChildNames(DeckId) returns (DeckNames); rpc NewDeckLegacy(generic.Bool) returns (generic.Json); rpc RemoveDecks(DeckIds) returns (collection.OpChangesWithCount); rpc ReparentDecks(ReparentDecksRequest) returns (collection.OpChangesWithCount); rpc RenameDeck(RenameDeckRequest) returns (collection.OpChanges); rpc GetOrCreateFilteredDeck(DeckId) returns (FilteredDeckForUpdate); rpc AddOrUpdateFilteredDeck(FilteredDeckForUpdate) returns (collection.OpChangesWithId); rpc FilteredDeckOrderLabels(generic.Empty) returns (generic.StringList); rpc SetCurrentDeck(DeckId) returns (collection.OpChanges); rpc GetCurrentDeck(generic.Empty) returns (Deck); } // Implicitly includes any of the above methods that are not listed in the // backend service. service BackendDecksService {} message DeckId { int64 did = 1; } message DeckIds { repeated int64 dids = 1; } message Deck { message Common { bool study_collapsed = 1; bool browser_collapsed = 2; uint32 last_day_studied = 3; int32 new_studied = 4; int32 review_studied = 5; int32 milliseconds_studied = 7; // previously set in the v1 scheduler, // but not currently used for anything int32 learning_studied = 6; reserved 8 to 13; bytes other = 255; } message Normal { message DayLimit { uint32 limit = 1; uint32 today = 2; } int64 config_id = 1; uint32 extend_new = 2; uint32 extend_review = 3; string description = 4; bool markdown_description = 5; optional uint32 review_limit = 6; optional uint32 new_limit = 7; DayLimit review_limit_today = 8; DayLimit new_limit_today = 9; // Deck-specific desired retention override optional float desired_retention = 10; reserved 12 to 15; } message Filtered { message SearchTerm { enum Order { OLDEST_REVIEWED_FIRST = 0; RANDOM = 1; INTERVALS_ASCENDING = 2; INTERVALS_DESCENDING = 3; LAPSES = 4; ADDED = 5; DUE = 6; REVERSE_ADDED = 7; RETRIEVABILITY_ASCENDING = 8; RETRIEVABILITY_DESCENDING = 9; } string search = 1; uint32 limit = 2; Order order = 3; } bool reschedule = 1; repeated SearchTerm search_terms = 2; // v1 scheduler only repeated float delays = 3; // v2 and old v3 scheduler only uint32 preview_delay = 4; // recent v3 scheduler only; 0 means card will be returned uint32 preview_again_secs = 7; // recent v3 scheduler only; 0 means card will be returned uint32 preview_hard_secs = 5; // recent v3 scheduler only; 0 means card will be returned uint32 preview_good_secs = 6; } // a container to store the deck specifics in the DB // as a tagged enum message KindContainer { oneof kind { Normal normal = 1; Filtered filtered = 2; } } int64 id = 1; string name = 2; int64 mtime_secs = 3; int32 usn = 4; Common common = 5; // the specifics are inlined here when sending data to clients, // as otherwise an extra level of indirection would be required oneof kind { Normal normal = 6; Filtered filtered = 7; } } message AddOrUpdateDeckLegacyRequest { bytes deck = 1; bool preserve_usn_and_mtime = 2; } message DeckTreeRequest { // if non-zero, counts for the provided timestamp will be included int64 now = 1; } message DeckTreeNode { int64 deck_id = 1; string name = 2; uint32 level = 4; bool collapsed = 5; // counts after adding children+applying limits uint32 review_count = 6; uint32 learn_count = 7; uint32 new_count = 8; // card counts without children or limits applied uint32 intraday_learning = 9; uint32 interday_learning_uncapped = 10; uint32 new_uncapped = 11; uint32 review_uncapped = 12; uint32 total_in_deck = 13; // with children, without any limits uint32 total_including_children = 14; bool filtered = 16; // low index so key can be packed into a byte, but at bottom // to make debug output easier to read repeated DeckTreeNode children = 3; } message SetDeckCollapsedRequest { enum Scope { REVIEWER = 0; BROWSER = 1; } int64 deck_id = 1; bool collapsed = 2; Scope scope = 3; } message GetDeckNamesRequest { bool skip_empty_default = 1; // if unset, implies skip_empty_default bool include_filtered = 2; } message DeckNames { repeated DeckNameId entries = 1; } message DeckNameId { int64 id = 1; string name = 2; } message ReparentDecksRequest { repeated int64 deck_ids = 1; int64 new_parent = 2; } message RenameDeckRequest { int64 deck_id = 1; string new_name = 2; } message FilteredDeckForUpdate { int64 id = 1; string name = 2; Deck.Filtered config = 3; bool allow_empty = 4; }