// Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html syntax = "proto3"; package BackendProto; // Generic containers /////////////////////////////////////////////////////////// message Empty {} message OptionalInt32 { sint32 val = 1; } message OptionalUInt32 { uint32 val = 1; } message Int32 { sint32 val = 1; } message UInt32 { uint32 val = 1; } message Int64 { int64 val = 1; } message String { string val = 1; } message Json { bytes json = 1; } message Bool { bool val = 1; } message StringList { repeated string vals = 1; } message OpChangesWithCount { uint32 count = 1; OpChanges changes = 2; } // IDs used in RPC calls /////////////////////////////////////////////////////////// message NoteTypeID { int64 ntid = 1; } message NoteID { int64 nid = 1; } message CardID { int64 cid = 1; } message CardIDs { repeated int64 cids = 1; } message DeckID { int64 did = 1; } message DeckIDs { repeated int64 dids = 1; } message DeckConfigID { int64 dcid = 1; } // Backend methods /////////////////////////////////////////////////////////// /// while the protobuf descriptors expose the order services are defined in, /// that information is not available in prost, so we define an enum to make /// sure all clients agree on the service index enum ServiceIndex { SERVICE_INDEX_SCHEDULING = 0; SERVICE_INDEX_DECKS = 1; SERVICE_INDEX_NOTES = 2; SERVICE_INDEX_SYNC = 3; SERVICE_INDEX_NOTE_TYPES = 4; SERVICE_INDEX_CONFIG = 5; SERVICE_INDEX_CARD_RENDERING = 6; SERVICE_INDEX_DECK_CONFIG = 7; SERVICE_INDEX_TAGS = 8; SERVICE_INDEX_SEARCH = 9; SERVICE_INDEX_STATS = 10; SERVICE_INDEX_MEDIA = 11; SERVICE_INDEX_I18N = 12; SERVICE_INDEX_COLLECTION = 13; SERVICE_INDEX_CARDS = 14; } service SchedulingService { rpc SchedTimingToday(Empty) returns (SchedTimingTodayOut); rpc StudiedToday(Empty) returns (String); rpc StudiedTodayMessage(StudiedTodayMessageIn) returns (String); rpc UpdateStats(UpdateStatsIn) returns (Empty); rpc ExtendLimits(ExtendLimitsIn) returns (Empty); rpc CountsForDeckToday(DeckID) returns (CountsForDeckTodayOut); rpc CongratsInfo(Empty) returns (CongratsInfoOut); rpc RestoreBuriedAndSuspendedCards(CardIDs) returns (OpChanges); rpc UnburyCardsInCurrentDeck(UnburyCardsInCurrentDeckIn) returns (Empty); rpc BuryOrSuspendCards(BuryOrSuspendCardsIn) returns (OpChanges); rpc EmptyFilteredDeck(DeckID) returns (Empty); rpc RebuildFilteredDeck(DeckID) returns (UInt32); rpc ScheduleCardsAsNew(ScheduleCardsAsNewIn) returns (OpChanges); rpc SetDueDate(SetDueDateIn) returns (OpChanges); rpc SortCards(SortCardsIn) returns (OpChangesWithCount); rpc SortDeck(SortDeckIn) returns (OpChangesWithCount); rpc GetNextCardStates(CardID) returns (NextCardStates); rpc DescribeNextStates(NextCardStates) returns (StringList); rpc StateIsLeech(SchedulingState) returns (Bool); rpc AnswerCard(AnswerCardIn) returns (OpChanges); rpc UpgradeScheduler(Empty) returns (Empty); rpc GetQueuedCards(GetQueuedCardsIn) returns (GetQueuedCardsOut); } service DecksService { rpc AddOrUpdateDeckLegacy(AddOrUpdateDeckLegacyIn) returns (DeckID); rpc DeckTree(DeckTreeIn) returns (DeckTreeNode); rpc DeckTreeLegacy(Empty) returns (Json); rpc GetAllDecksLegacy(Empty) returns (Json); rpc GetDeckIDByName(String) returns (DeckID); rpc GetDeckLegacy(DeckID) returns (Json); rpc GetDeckNames(GetDeckNamesIn) returns (DeckNames); rpc NewDeckLegacy(Bool) returns (Json); rpc RemoveDecks(DeckIDs) returns (OpChangesWithCount); rpc DragDropDecks(DragDropDecksIn) returns (OpChanges); rpc RenameDeck(RenameDeckIn) returns (OpChanges); } service NotesService { rpc NewNote(NoteTypeID) returns (Note); rpc AddNote(AddNoteIn) returns (AddNoteOut); rpc DefaultsForAdding(DefaultsForAddingIn) returns (DeckAndNotetype); rpc DefaultDeckForNotetype(NoteTypeID) returns (DeckID); rpc UpdateNote(UpdateNoteIn) returns (OpChanges); rpc GetNote(NoteID) returns (Note); rpc RemoveNotes(RemoveNotesIn) returns (OpChanges); rpc ClozeNumbersInNote(Note) returns (ClozeNumbersInNoteOut); rpc AfterNoteUpdates(AfterNoteUpdatesIn) returns (OpChanges); rpc FieldNamesForNotes(FieldNamesForNotesIn) returns (FieldNamesForNotesOut); rpc NoteIsDuplicateOrEmpty(Note) returns (NoteIsDuplicateOrEmptyOut); rpc CardsOfNote(NoteID) returns (CardIDs); } service SyncService { rpc SyncMedia(SyncAuth) returns (Empty); rpc AbortSync(Empty) returns (Empty); rpc AbortMediaSync(Empty) returns (Empty); rpc BeforeUpload(Empty) returns (Empty); rpc SyncLogin(SyncLoginIn) returns (SyncAuth); rpc SyncStatus(SyncAuth) returns (SyncStatusOut); rpc SyncCollection(SyncAuth) returns (SyncCollectionOut); rpc FullUpload(SyncAuth) returns (Empty); rpc FullDownload(SyncAuth) returns (Empty); rpc SyncServerMethod(SyncServerMethodIn) returns (Json); } service ConfigService { rpc GetConfigJson(String) returns (Json); rpc SetConfigJson(SetConfigJsonIn) returns (Empty); rpc RemoveConfig(String) returns (Empty); rpc GetAllConfig(Empty) returns (Json); rpc GetConfigBool(Config.Bool) returns (Bool); rpc SetConfigBool(SetConfigBoolIn) returns (Empty); rpc GetConfigString(Config.String) returns (String); rpc SetConfigString(SetConfigStringIn) returns (Empty); rpc GetPreferences(Empty) returns (Preferences); rpc SetPreferences(Preferences) returns (OpChanges); } service NoteTypesService { rpc AddOrUpdateNotetype(AddOrUpdateNotetypeIn) returns (NoteTypeID); rpc GetStockNotetypeLegacy(StockNoteType) returns (Json); rpc GetNotetypeLegacy(NoteTypeID) returns (Json); rpc GetNotetypeNames(Empty) returns (NoteTypeNames); rpc GetNotetypeNamesAndCounts(Empty) returns (NoteTypeUseCounts); rpc GetNotetypeIDByName(String) returns (NoteTypeID); rpc RemoveNotetype(NoteTypeID) returns (Empty); } service CardRenderingService { rpc ExtractAVTags(ExtractAVTagsIn) returns (ExtractAVTagsOut); rpc ExtractLatex(ExtractLatexIn) returns (ExtractLatexOut); rpc GetEmptyCards(Empty) returns (EmptyCardsReport); rpc RenderExistingCard(RenderExistingCardIn) returns (RenderCardOut); rpc RenderUncommittedCard(RenderUncommittedCardIn) returns (RenderCardOut); rpc StripAVTags(String) returns (String); rpc RenderMarkdown(RenderMarkdownIn) returns (String); } service DeckConfigService { rpc AddOrUpdateDeckConfigLegacy(AddOrUpdateDeckConfigLegacyIn) returns (DeckConfigID); rpc AllDeckConfigLegacy(Empty) returns (Json); rpc GetDeckConfigLegacy(DeckConfigID) returns (Json); rpc NewDeckConfigLegacy(Empty) returns (Json); rpc RemoveDeckConfig(DeckConfigID) returns (Empty); } service TagsService { rpc ClearUnusedTags(Empty) returns (OpChangesWithCount); rpc AllTags(Empty) returns (StringList); rpc RemoveTags(String) returns (OpChangesWithCount); rpc SetTagExpanded(SetTagExpandedIn) returns (Empty); rpc TagTree(Empty) returns (TagTreeNode); rpc ReparentTags(ReparentTagsIn) returns (OpChangesWithCount); rpc RenameTags(RenameTagsIn) returns (OpChangesWithCount); rpc AddNoteTags(NoteIDsAndTagsIn) returns (OpChangesWithCount); rpc RemoveNoteTags(NoteIDsAndTagsIn) returns (OpChangesWithCount); rpc FindAndReplaceTag(FindAndReplaceTagIn) returns (OpChangesWithCount); } service SearchService { rpc BuildSearchString(SearchNode) returns (String); rpc SearchCards(SearchCardsIn) returns (SearchCardsOut); rpc SearchNotes(SearchNotesIn) returns (SearchNotesOut); rpc JoinSearchNodes(JoinSearchNodesIn) returns (String); rpc ReplaceSearchNode(ReplaceSearchNodeIn) returns (String); rpc FindAndReplace(FindAndReplaceIn) returns (OpChangesWithCount); } service StatsService { rpc CardStats(CardID) returns (String); rpc Graphs(GraphsIn) returns (GraphsOut); rpc GetGraphPreferences(Empty) returns (GraphPreferences); rpc SetGraphPreferences(GraphPreferences) returns (Empty); } service MediaService { rpc CheckMedia(Empty) returns (CheckMediaOut); rpc TrashMediaFiles(TrashMediaFilesIn) returns (Empty); rpc AddMediaFile(AddMediaFileIn) returns (String); rpc EmptyTrash(Empty) returns (Empty); rpc RestoreTrash(Empty) returns (Empty); } service I18nService { rpc TranslateString(TranslateStringIn) returns (String); rpc FormatTimespan(FormatTimespanIn) returns (String); rpc I18nResources(Empty) returns (Json); } service CollectionService { rpc OpenCollection(OpenCollectionIn) returns (Empty); rpc CloseCollection(CloseCollectionIn) returns (Empty); rpc CheckDatabase(Empty) returns (CheckDatabaseOut); rpc GetUndoStatus(Empty) returns (UndoStatus); rpc Undo(Empty) returns (UndoStatus); rpc Redo(Empty) returns (UndoStatus); rpc LatestProgress(Empty) returns (Progress); rpc SetWantsAbort(Empty) returns (Empty); } service CardsService { rpc GetCard(CardID) returns (Card); rpc UpdateCard(UpdateCardIn) returns (OpChanges); rpc RemoveCards(RemoveCardsIn) returns (Empty); rpc SetDeck(SetDeckIn) returns (OpChanges); rpc SetFlag(SetFlagIn) returns (OpChanges); } // Protobuf stored in .anki2 files // These should be moved to a separate file in the future /////////////////////////////////////////////////////////// message DeckConfigInner { enum NewCardOrder { NEW_CARD_ORDER_DUE = 0; NEW_CARD_ORDER_RANDOM = 1; } enum ReviewCardOrder { REVIEW_CARD_ORDER_SHUFFLED_BY_DAY = 0; REVIEW_CARD_ORDER_SHUFFLED = 1; REVIEW_CARD_ORDER_INTERVALS_ASCENDING = 2; REVIEW_CARD_ORDER_INTERVALS_DESCENDING = 3; } enum ReviewMix { REVIEW_MIX_MIX_WITH_REVIEWS = 0; REVIEW_MIX_AFTER_REVIEWS = 1; REVIEW_MIX_BEFORE_REVIEWS = 2; } enum LeechAction { LEECH_ACTION_SUSPEND = 0; LEECH_ACTION_TAG_ONLY = 1; } repeated float learn_steps = 1; repeated float relearn_steps = 2; reserved 3 to 8; uint32 new_per_day = 9; uint32 reviews_per_day = 10; uint32 new_per_day_minimum = 29; float initial_ease = 11; float easy_multiplier = 12; float hard_multiplier = 13; float lapse_multiplier = 14; float interval_multiplier = 15; uint32 maximum_review_interval = 16; uint32 minimum_lapse_interval = 17; uint32 graduating_interval_good = 18; uint32 graduating_interval_easy = 19; NewCardOrder new_card_order = 20; ReviewCardOrder review_order = 32; ReviewMix new_mix = 30; ReviewMix interday_learning_mix = 31; LeechAction leech_action = 21; uint32 leech_threshold = 22; bool disable_autoplay = 23; uint32 cap_answer_time_to_secs = 24; uint32 visible_timer_secs = 25; bool skip_question_when_replaying_answer = 26; bool bury_new = 27; bool bury_reviews = 28; bytes other = 255; } message DeckCommon { 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 DeckKind { oneof kind { NormalDeck normal = 1; FilteredDeck filtered = 2; } } message NormalDeck { int64 config_id = 1; uint32 extend_new = 2; uint32 extend_review = 3; string description = 4; bool markdown_description = 5; reserved 6 to 11; } message FilteredDeck { bool reschedule = 1; repeated FilteredSearchTerm search_terms = 2; // v1 scheduler only repeated float delays = 3; // v2 scheduler only uint32 preview_delay = 4; } message FilteredSearchTerm { enum FilteredSearchOrder { FILTERED_SEARCH_ORDER_OLDEST_FIRST = 0; FILTERED_SEARCH_ORDER_RANDOM = 1; FILTERED_SEARCH_ORDER_INTERVALS_ASCENDING = 2; FILTERED_SEARCH_ORDER_INTERVALS_DESCENDING = 3; FILTERED_SEARCH_ORDER_LAPSES = 4; FILTERED_SEARCH_ORDER_ADDED = 5; FILTERED_SEARCH_ORDER_DUE = 6; FILTERED_SEARCH_ORDER_REVERSE_ADDED = 7; FILTERED_SEARCH_ORDER_DUE_PRIORITY = 8; } string search = 1; uint32 limit = 2; FilteredSearchOrder order = 3; } message NoteFieldConfig { bool sticky = 1; bool rtl = 2; string font_name = 3; uint32 font_size = 4; bytes other = 255; } message CardTemplateConfig { string q_format = 1; string a_format = 2; string q_format_browser = 3; string a_format_browser = 4; int64 target_deck_id = 5; string browser_font_name = 6; uint32 browser_font_size = 7; bytes other = 255; } message NoteTypeConfig { enum Kind { KIND_NORMAL = 0; KIND_CLOZE = 1; } Kind kind = 1; uint32 sort_field_idx = 2; string css = 3; int64 target_deck_id = 4; // moved into config var string latex_pre = 5; string latex_post = 6; bool latex_svg = 7; repeated CardRequirement reqs = 8; bytes other = 255; } message CardRequirement { enum Kind { KIND_NONE = 0; KIND_ANY = 1; KIND_ALL = 2; } uint32 card_ord = 1; Kind kind = 2; repeated uint32 field_ords = 3; } // Containers for passing around database objects /////////////////////////////////////////////////////////// message Deck { int64 id = 1; string name = 2; uint32 mtime_secs = 3; int32 usn = 4; DeckCommon common = 5; oneof kind { NormalDeck normal = 6; FilteredDeck filtered = 7; } } message NoteType { int64 id = 1; string name = 2; uint32 mtime_secs = 3; sint32 usn = 4; NoteTypeConfig config = 7; repeated NoteField fields = 8; repeated CardTemplate templates = 9; } message NoteField { OptionalUInt32 ord = 1; string name = 2; NoteFieldConfig config = 5; } message CardTemplate { OptionalUInt32 ord = 1; string name = 2; uint32 mtime_secs = 3; sint32 usn = 4; CardTemplateConfig config = 5; } message Note { int64 id = 1; string guid = 2; int64 notetype_id = 3; uint32 mtime_secs = 4; int32 usn = 5; repeated string tags = 6; repeated string fields = 7; } message Card { int64 id = 1; int64 note_id = 2; int64 deck_id = 3; uint32 template_idx = 4; int64 mtime_secs = 5; sint32 usn = 6; uint32 ctype = 7; sint32 queue = 8; sint32 due = 9; uint32 interval = 10; uint32 ease_factor = 11; uint32 reps = 12; uint32 lapses = 13; uint32 remaining_steps = 14; sint32 original_due = 15; int64 original_deck_id = 16; uint32 flags = 17; string data = 18; } // Backend /////////////////////////////////////////////////////////// message BackendInit { repeated string preferred_langs = 1; string locale_folder_path = 2; bool server = 3; } message I18nBackendInit { repeated string preferred_langs = 4; string locale_folder_path = 5; } // Errors /////////////////////////////////////////////////////////// message BackendError { // localized error description suitable for displaying to the user string localized = 1; // error specifics oneof value { Empty invalid_input = 2; Empty template_parse = 3; Empty io_error = 4; Empty db_error = 5; NetworkError network_error = 6; SyncError sync_error = 7; // user interrupted operation Empty interrupted = 8; string json_error = 9; string proto_error = 10; Empty not_found_error = 11; Empty exists = 12; Empty deck_is_filtered = 13; } } message NetworkError { enum NetworkErrorKind { OTHER = 0; OFFLINE = 1; TIMEOUT = 2; PROXY_AUTH = 3; } NetworkErrorKind kind = 1; } message SyncError { enum SyncErrorKind { OTHER = 0; CONFLICT = 1; SERVER_ERROR = 2; CLIENT_TOO_OLD = 3; AUTH_FAILED = 4; SERVER_MESSAGE = 5; MEDIA_CHECK_REQUIRED = 6; RESYNC_REQUIRED = 7; CLOCK_INCORRECT = 8; DATABASE_CHECK_REQUIRED = 9; SYNC_NOT_STARTED = 10; } SyncErrorKind kind = 1; } // Progress /////////////////////////////////////////////////////////// message Progress { message MediaSync { string checked = 1; string added = 2; string removed = 3; } message FullSync { uint32 transferred = 1; uint32 total = 2; } message NormalSync { string stage = 1; string added = 2; string removed = 3; } message DatabaseCheck { string stage = 1; uint32 stage_total = 2; uint32 stage_current = 3; } oneof value { Empty none = 1; MediaSync media_sync = 2; string media_check = 3; FullSync full_sync = 4; NormalSync normal_sync = 5; DatabaseCheck database_check = 6; } } // Messages /////////////////////////////////////////////////////////// message SchedTimingTodayOut { uint32 days_elapsed = 1; int64 next_day_at = 2; } message DeckTreeIn { // if non-zero, counts for the provided timestamp will be included int64 now = 1; int64 top_deck_id = 2; } message DeckTreeNode { int64 deck_id = 1; string name = 2; repeated DeckTreeNode children = 3; uint32 level = 4; bool collapsed = 5; uint32 review_count = 6; uint32 learn_count = 7; uint32 new_count = 8; bool filtered = 16; } message RenderExistingCardIn { int64 card_id = 1; bool browser = 2; } message RenderUncommittedCardIn { Note note = 1; uint32 card_ord = 2; bytes template = 3; bool fill_empty = 4; } message RenderCardOut { repeated RenderedTemplateNode question_nodes = 1; repeated RenderedTemplateNode answer_nodes = 2; } message RenderedTemplateNode { oneof value { string text = 1; RenderedTemplateReplacement replacement = 2; } } message RenderedTemplateReplacement { string field_name = 1; string current_text = 2; repeated string filters = 3; } message ExtractAVTagsIn { string text = 1; bool question_side = 2; } message ExtractAVTagsOut { string text = 1; repeated AVTag av_tags = 2; } message AVTag { oneof value { string sound_or_video = 1; TTSTag tts = 2; } } message TTSTag { string field_text = 1; string lang = 2; repeated string voices = 3; float speed = 4; repeated string other_args = 5; } message ExtractLatexIn { string text = 1; bool svg = 2; bool expand_clozes = 3; } message ExtractLatexOut { string text = 1; repeated ExtractedLatex latex = 2; } message ExtractedLatex { string filename = 1; string latex_body = 2; } message AddMediaFileIn { string desired_name = 1; bytes data = 2; } message CheckMediaOut { repeated string unused = 1; repeated string missing = 2; string report = 3; bool have_trash = 4; } message TrashMediaFilesIn { repeated string fnames = 1; } message TranslateStringIn { int32 key = 2; map args = 3; } message TranslateArgValue { oneof value { string str = 1; double number = 2; } } message FormatTimespanIn { enum Context { PRECISE = 0; ANSWER_BUTTONS = 1; INTERVALS = 2; } float seconds = 1; Context context = 2; } message StudiedTodayMessageIn { uint32 cards = 1; double seconds = 2; } message CongratsLearnMessageIn { float next_due = 1; uint32 remaining = 2; } message OpenCollectionIn { string collection_path = 1; string media_folder_path = 2; string media_db_path = 3; string log_path = 4; } message SearchCardsIn { string search = 1; SortOrder order = 2; } message SearchCardsOut { repeated int64 card_ids = 1; } message SortOrder { message Builtin { enum Kind { NOTE_CREATION = 0; NOTE_MOD = 1; NOTE_FIELD = 2; NOTE_TAGS = 3; NOTE_TYPE = 4; CARD_MOD = 5; CARD_REPS = 6; CARD_DUE = 7; CARD_EASE = 8; CARD_LAPSES = 9; CARD_INTERVAL = 10; CARD_DECK = 11; CARD_TEMPLATE = 12; } Kind kind = 1; bool reverse = 2; } oneof value { Empty from_config = 1; Empty none = 2; string custom = 3; Builtin builtin = 4; } } message SearchNotesIn { string search = 1; } message SearchNotesOut { repeated int64 note_ids = 2; } message SearchNode { message Dupe { int64 notetype_id = 1; string first_field = 2; } enum Flag { FLAG_NONE = 0; FLAG_ANY = 1; FLAG_RED = 2; FLAG_ORANGE = 3; FLAG_GREEN = 4; FLAG_BLUE = 5; } enum Rating { RATING_ANY = 0; RATING_AGAIN = 1; RATING_HARD = 2; RATING_GOOD = 3; RATING_EASY = 4; RATING_BY_RESCHEDULE = 5; } message Rated { uint32 days = 1; Rating rating = 2; } enum CardState { CARD_STATE_NEW = 0; CARD_STATE_LEARN = 1; CARD_STATE_REVIEW = 2; CARD_STATE_DUE = 3; CARD_STATE_SUSPENDED = 4; CARD_STATE_BURIED = 5; } message IdList { repeated int64 ids = 1; } message Group { enum Joiner { AND = 0; OR = 1; } repeated SearchNode nodes = 1; Joiner joiner = 2; } oneof filter { Group group = 1; SearchNode negated = 2; string parsable_text = 3; uint32 template = 4; int64 nid = 5; Dupe dupe = 6; string field_name = 7; Rated rated = 8; uint32 added_in_days = 9; int32 due_in_days = 10; Flag flag = 11; CardState card_state = 12; IdList nids = 13; uint32 edited_in_days = 14; string deck = 15; int32 due_on_day = 16; string tag = 17; string note = 18; } } message JoinSearchNodesIn { SearchNode.Group.Joiner joiner = 1; SearchNode existing_node = 2; SearchNode additional_node = 3; } message ReplaceSearchNodeIn { SearchNode existing_node = 1; SearchNode replacement_node = 2; } message CloseCollectionIn { bool downgrade_to_schema11 = 1; } message AddOrUpdateDeckConfigLegacyIn { bytes config = 1; bool preserve_usn_and_mtime = 2; } message SetTagExpandedIn { string name = 1; bool expanded = 2; } message GetChangedTagsOut { repeated string tags = 1; } message TagTreeNode { string name = 1; repeated TagTreeNode children = 2; uint32 level = 3; bool expanded = 4; } message ReparentTagsIn { repeated string tags = 1; string new_parent = 2; } message RenameTagsIn { string current_prefix = 1; string new_prefix = 2; } message SetConfigJsonIn { string key = 1; bytes value_json = 2; } message StockNoteType { enum Kind { BASIC = 0; BASIC_AND_REVERSED = 1; BASIC_OPTIONAL_REVERSED = 2; BASIC_TYPING = 3; CLOZE = 4; } Kind kind = 1; } message NoteTypeNames { repeated NoteTypeNameID entries = 1; } message NoteTypeUseCounts { repeated NoteTypeNameIDUseCount entries = 1; } message NoteTypeNameID { int64 id = 1; string name = 2; } message NoteTypeNameIDUseCount { int64 id = 1; string name = 2; uint32 use_count = 3; } message AddOrUpdateNotetypeIn { bytes json = 1; bool preserve_usn_and_mtime = 2; } message AddNoteIn { Note note = 1; int64 deck_id = 2; } message AddNoteOut { int64 note_id = 1; OpChanges changes = 2; } message UpdateNoteIn { Note note = 1; bool skip_undo_entry = 2; } message UpdateCardIn { Card card = 1; bool skip_undo_entry = 2; } message EmptyCardsReport { message NoteWithEmptyCards { int64 note_id = 1; repeated int64 card_ids = 2; bool will_delete_note = 3; } string report = 1; repeated NoteWithEmptyCards notes = 2; } message DeckNames { repeated DeckNameID entries = 1; } message DeckNameID { int64 id = 1; string name = 2; } message AddOrUpdateDeckLegacyIn { bytes deck = 1; bool preserve_usn_and_mtime = 2; } message FieldNamesForNotesIn { repeated int64 nids = 1; } message FieldNamesForNotesOut { repeated string fields = 1; } message FindAndReplaceIn { repeated int64 nids = 1; string search = 2; string replacement = 3; bool regex = 4; bool match_case = 5; string field_name = 6; } message AfterNoteUpdatesIn { repeated int64 nids = 1; bool mark_notes_modified = 2; bool generate_cards = 3; } message NoteIDsAndTagsIn { repeated int64 note_ids = 1; string tags = 2; } message FindAndReplaceTagIn { repeated int64 note_ids = 1; string search = 2; string replacement = 3; bool regex = 4; bool match_case = 5; } message CheckDatabaseOut { repeated string problems = 1; } message Preferences { message Scheduling { enum NewReviewMix { DISTRIBUTE = 0; REVIEWS_FIRST = 1; NEW_FIRST = 2; } // read only uint32 scheduler_version = 1; uint32 rollover = 2; uint32 learn_ahead_secs = 3; NewReviewMix new_review_mix = 4; // v2 only bool new_timezone = 5; bool day_learn_first = 6; } message Reviewing { bool hide_audio_play_buttons = 1; bool interrupt_audio_when_answering = 2; bool show_remaining_due_counts = 3; bool show_intervals_on_buttons = 4; uint32 time_limit_secs = 5; } message Editing { bool adding_defaults_to_current_deck = 1; bool paste_images_as_png = 2; bool paste_strips_formatting = 3; } Scheduling scheduling = 1; Reviewing reviewing = 2; Editing editing = 3; } message ClozeNumbersInNoteOut { repeated uint32 numbers = 1; } message GetDeckNamesIn { bool skip_empty_default = 1; // if unset, implies skip_empty_default bool include_filtered = 2; } message DragDropDecksIn { repeated int64 source_deck_ids = 1; int64 target_deck_id = 2; } message NoteIsDuplicateOrEmptyOut { enum State { NORMAL = 0; EMPTY = 1; DUPLICATE = 2; } State state = 1; } message SyncLoginIn { string username = 1; string password = 2; } message SyncStatusOut { enum Required { NO_CHANGES = 0; NORMAL_SYNC = 1; FULL_SYNC = 2; } Required required = 1; } message SyncCollectionOut { enum ChangesRequired { NO_CHANGES = 0; NORMAL_SYNC = 1; FULL_SYNC = 2; // local collection has no cards; upload not an option FULL_DOWNLOAD = 3; // remote collection has no cards; download not an option FULL_UPLOAD = 4; } uint32 host_number = 1; string server_message = 2; ChangesRequired required = 3; } message SyncAuth { string hkey = 1; uint32 host_number = 2; } message SyncServerMethodIn { enum Method { HOST_KEY = 0; META = 1; START = 2; APPLY_GRAVES = 3; APPLY_CHANGES = 4; CHUNK = 5; APPLY_CHUNK = 6; SANITY_CHECK = 7; FINISH = 8; ABORT = 9; // caller must reopen after these two are called FULL_UPLOAD = 10; FULL_DOWNLOAD = 11; } Method method = 1; bytes data = 2; } message RemoveNotesIn { repeated int64 note_ids = 1; repeated int64 card_ids = 2; } message RemoveCardsIn { repeated int64 card_ids = 1; } message UpdateStatsIn { int64 deck_id = 1; int32 new_delta = 2; int32 review_delta = 4; int32 millisecond_delta = 5; } message ExtendLimitsIn { int64 deck_id = 1; int32 new_delta = 2; int32 review_delta = 3; } message CountsForDeckTodayOut { int32 new = 1; int32 review = 2; } message GraphsIn { string search = 1; uint32 days = 2; } message GraphsOut { repeated Card cards = 1; repeated RevlogEntry revlog = 2; uint32 days_elapsed = 3; // Based on rollover hour uint32 next_day_at_secs = 4; uint32 scheduler_version = 5; /// Seconds to add to UTC timestamps to get local time. int32 local_offset_secs = 7; } message GraphPreferences { enum Weekday { SUNDAY = 0; MONDAY = 1; FRIDAY = 5; SATURDAY = 6; } Weekday calendar_first_day_of_week = 1; bool card_counts_separate_inactive = 2; bool browser_links_supported = 3; bool future_due_show_backlog = 4; } message RevlogEntry { enum ReviewKind { LEARNING = 0; REVIEW = 1; RELEARNING = 2; EARLY_REVIEW = 3; MANUAL = 4; } int64 id = 1; int64 cid = 2; int32 usn = 3; uint32 button_chosen = 4; int32 interval = 5; int32 last_interval = 6; uint32 ease_factor = 7; uint32 taken_millis = 8; ReviewKind review_kind = 9; } message CongratsInfoOut { uint32 learn_remaining = 1; uint32 secs_until_next_learn = 2; bool review_remaining = 3; bool new_remaining = 4; bool have_sched_buried = 5; bool have_user_buried = 6; bool is_filtered_deck = 7; bool bridge_commands_supported = 8; string deck_description = 9; } message UnburyCardsInCurrentDeckIn { enum Mode { ALL = 0; SCHED_ONLY = 1; USER_ONLY = 2; } Mode mode = 1; } message BuryOrSuspendCardsIn { enum Mode { SUSPEND = 0; BURY_SCHED = 1; BURY_USER = 2; } repeated int64 card_ids = 1; Mode mode = 2; } message ScheduleCardsAsNewIn { repeated int64 card_ids = 1; bool log = 2; } message SetDueDateIn { repeated int64 card_ids = 1; string days = 2; Config.String config_key = 3; } message SortCardsIn { repeated int64 card_ids = 1; uint32 starting_from = 2; uint32 step_size = 3; bool randomize = 4; bool shift_existing = 5; } message SortDeckIn { int64 deck_id = 1; bool randomize = 2; } message SetDeckIn { repeated int64 card_ids = 1; int64 deck_id = 2; } message Config { message Bool { enum Key { BROWSER_SORT_BACKWARDS = 0; PREVIEW_BOTH_SIDES = 1; COLLAPSE_TAGS = 2; COLLAPSE_NOTETYPES = 3; COLLAPSE_DECKS = 4; COLLAPSE_SAVED_SEARCHES = 5; COLLAPSE_TODAY = 6; COLLAPSE_CARD_STATE = 7; COLLAPSE_FLAGS = 8; SCHED_2021 = 9; ADDING_DEFAULTS_TO_CURRENT_DECK = 10; HIDE_AUDIO_PLAY_BUTTONS = 11; INTERRUPT_AUDIO_WHEN_ANSWERING = 12; PASTE_IMAGES_AS_PNG = 13; PASTE_STRIPS_FORMATTING = 14; } Key key = 1; } message String { enum Key { SET_DUE_BROWSER = 0; SET_DUE_REVIEWER = 1; } Key key = 1; } } message SetConfigBoolIn { Config.Bool.Key key = 1; bool value = 2; } message SetConfigStringIn { Config.String.Key key = 1; string value = 2; } message RenderMarkdownIn { string markdown = 1; bool sanitize = 2; } message SchedulingState { message New { uint32 position = 1; } message Learning { uint32 remaining_steps = 1; uint32 scheduled_secs = 2; } message Review { uint32 scheduled_days = 1; uint32 elapsed_days = 2; float ease_factor = 3; uint32 lapses = 4; bool leeched = 5; } message Relearning { Review review = 1; Learning learning = 2; } message Normal { oneof value { New new = 1; Learning learning = 2; Review review = 3; Relearning relearning = 4; } } message Preview { uint32 scheduled_secs = 1; bool finished = 2; } message ReschedulingFilter { Normal original_state = 1; } message Filtered { oneof value { Preview preview = 1; ReschedulingFilter rescheduling = 2; } } oneof value { Normal normal = 1; Filtered filtered = 2; } } message NextCardStates { SchedulingState current = 1; SchedulingState again = 2; SchedulingState hard = 3; SchedulingState good = 4; SchedulingState easy = 5; } message AnswerCardIn { enum Rating { AGAIN = 0; HARD = 1; GOOD = 2; EASY = 3; } int64 card_id = 1; SchedulingState current_state = 2; SchedulingState new_state = 3; Rating rating = 4; int64 answered_at_millis = 5; uint32 milliseconds_taken = 6; } message GetQueuedCardsIn { uint32 fetch_limit = 1; bool intraday_learning_only = 2; } message GetQueuedCardsOut { enum Queue { New = 0; Learning = 1; Review = 2; } message QueuedCard { Card card = 1; Queue queue = 2; NextCardStates next_states = 3; } message QueuedCards { repeated QueuedCard cards = 1; uint32 new_count = 2; uint32 learning_count = 3; uint32 review_count = 4; } oneof value { QueuedCards queued_cards = 1; CongratsInfoOut congrats_info = 2; } } message OpChanges { // this is not an exhaustive list; we can add more cases as we need them enum Kind { OTHER = 0; UPDATE_NOTE_TAGS = 1; SET_CARD_FLAG = 2; UPDATE_NOTE = 3; } Kind kind = 1; bool card = 2; bool note = 3; bool deck = 4; bool tag = 5; bool notetype = 6; bool preference = 7; } message UndoStatus { string undo = 1; string redo = 2; } message DefaultsForAddingIn { int64 home_deck_of_current_review_card = 1; } message DeckAndNotetype { int64 deck_id = 1; int64 notetype_id = 2; } message RenameDeckIn { int64 deck_id = 1; string new_name = 2; } message SetFlagIn { repeated int64 card_ids = 1; uint32 flag = 2; }