mirror of
https://github.com/ankitects/anki.git
synced 2025-09-21 15:32:23 -04:00
split out sync, search, scheduler & config
This commit is contained in:
parent
9e0a295ab9
commit
35b059ecdb
29 changed files with 675 additions and 617 deletions
|
@ -7,7 +7,6 @@ package anki.backend;
|
|||
|
||||
import "anki/generic.proto";
|
||||
import "anki/cards.proto";
|
||||
import "anki/decks.proto";
|
||||
import "anki/collection.proto";
|
||||
import "anki/notes.proto";
|
||||
import "anki/notetypes.proto";
|
||||
|
@ -19,12 +18,12 @@ import "anki/notetypes.proto";
|
|||
/// 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_SCHEDULER = 0;
|
||||
SERVICE_INDEX_DECKS = 1;
|
||||
SERVICE_INDEX_NOTES = 2;
|
||||
SERVICE_INDEX_SYNC = 3;
|
||||
SERVICE_INDEX_NOTETYPES = 4;
|
||||
SERVICE_INDEX_CONFIG = 5;
|
||||
SERVICE_INDEX_CONFIGS = 5;
|
||||
SERVICE_INDEX_CARD_RENDERING = 6;
|
||||
SERVICE_INDEX_DECK_CONFIG = 7;
|
||||
SERVICE_INDEX_TAGS = 8;
|
||||
|
@ -36,61 +35,6 @@ enum ServiceIndex {
|
|||
SERVICE_INDEX_CARDS = 14;
|
||||
}
|
||||
|
||||
service SchedulingService {
|
||||
rpc SchedTimingToday(generic.Empty) returns (SchedTimingTodayResponse);
|
||||
rpc StudiedToday(generic.Empty) returns (generic.String);
|
||||
rpc StudiedTodayMessage(StudiedTodayMessageRequest) returns (generic.String);
|
||||
rpc UpdateStats(UpdateStatsRequest) returns (generic.Empty);
|
||||
rpc ExtendLimits(ExtendLimitsRequest) returns (generic.Empty);
|
||||
rpc CountsForDeckToday(decks.DeckId) returns (CountsForDeckTodayResponse);
|
||||
rpc CongratsInfo(generic.Empty) returns (CongratsInfoResponse);
|
||||
rpc RestoreBuriedAndSuspendedCards(cards.CardIds)
|
||||
returns (collection.OpChanges);
|
||||
rpc UnburyDeck(UnburyDeckRequest) returns (collection.OpChanges);
|
||||
rpc BuryOrSuspendCards(BuryOrSuspendCardsRequest)
|
||||
returns (collection.OpChangesWithCount);
|
||||
rpc EmptyFilteredDeck(decks.DeckId) returns (collection.OpChanges);
|
||||
rpc RebuildFilteredDeck(decks.DeckId) returns (collection.OpChangesWithCount);
|
||||
rpc ScheduleCardsAsNew(ScheduleCardsAsNewRequest)
|
||||
returns (collection.OpChanges);
|
||||
rpc SetDueDate(SetDueDateRequest) returns (collection.OpChanges);
|
||||
rpc SortCards(SortCardsRequest) returns (collection.OpChangesWithCount);
|
||||
rpc SortDeck(SortDeckRequest) returns (collection.OpChangesWithCount);
|
||||
rpc GetNextCardStates(cards.CardId) returns (NextCardStates);
|
||||
rpc DescribeNextStates(NextCardStates) returns (generic.StringList);
|
||||
rpc StateIsLeech(SchedulingState) returns (generic.Bool);
|
||||
rpc AnswerCard(CardAnswer) returns (collection.OpChanges);
|
||||
rpc UpgradeScheduler(generic.Empty) returns (generic.Empty);
|
||||
rpc GetQueuedCards(GetQueuedCardsRequest) returns (QueuedCards);
|
||||
}
|
||||
|
||||
service SyncService {
|
||||
rpc SyncMedia(SyncAuth) returns (generic.Empty);
|
||||
rpc AbortSync(generic.Empty) returns (generic.Empty);
|
||||
rpc AbortMediaSync(generic.Empty) returns (generic.Empty);
|
||||
rpc BeforeUpload(generic.Empty) returns (generic.Empty);
|
||||
rpc SyncLogin(SyncLoginRequest) returns (SyncAuth);
|
||||
rpc SyncStatus(SyncAuth) returns (SyncStatusResponse);
|
||||
rpc SyncCollection(SyncAuth) returns (SyncCollectionResponse);
|
||||
rpc FullUpload(SyncAuth) returns (generic.Empty);
|
||||
rpc FullDownload(SyncAuth) returns (generic.Empty);
|
||||
rpc SyncServerMethod(SyncServerMethodRequest) returns (generic.Json);
|
||||
}
|
||||
|
||||
service ConfigService {
|
||||
rpc GetConfigJson(generic.String) returns (generic.Json);
|
||||
rpc SetConfigJson(SetConfigJsonRequest) returns (collection.OpChanges);
|
||||
rpc SetConfigJsonNoUndo(SetConfigJsonRequest) returns (generic.Empty);
|
||||
rpc RemoveConfig(generic.String) returns (collection.OpChanges);
|
||||
rpc GetAllConfig(generic.Empty) returns (generic.Json);
|
||||
rpc GetConfigBool(Config.Bool) returns (generic.Bool);
|
||||
rpc SetConfigBool(SetConfigBoolRequest) returns (collection.OpChanges);
|
||||
rpc GetConfigString(Config.String) returns (generic.String);
|
||||
rpc SetConfigString(SetConfigStringRequest) returns (collection.OpChanges);
|
||||
rpc GetPreferences(generic.Empty) returns (Preferences);
|
||||
rpc SetPreferences(Preferences) returns (collection.OpChanges);
|
||||
}
|
||||
|
||||
service CardRenderingService {
|
||||
rpc ExtractAVTags(ExtractAVTagsRequest) returns (ExtractAVTagsResponse);
|
||||
rpc ExtractLatex(ExtractLatexRequest) returns (ExtractLatexResponse);
|
||||
|
@ -121,19 +65,6 @@ service TagsService {
|
|||
returns (collection.OpChangesWithCount);
|
||||
}
|
||||
|
||||
service SearchService {
|
||||
rpc BuildSearchString(SearchNode) returns (generic.String);
|
||||
rpc SearchCards(SearchRequest) returns (SearchResponse);
|
||||
rpc SearchNotes(SearchRequest) returns (SearchResponse);
|
||||
rpc JoinSearchNodes(JoinSearchNodesRequest) returns (generic.String);
|
||||
rpc ReplaceSearchNode(ReplaceSearchNodeRequest) returns (generic.String);
|
||||
rpc FindAndReplace(FindAndReplaceRequest)
|
||||
returns (collection.OpChangesWithCount);
|
||||
rpc AllBrowserColumns(generic.Empty) returns (BrowserColumns);
|
||||
rpc BrowserRowForId(generic.Int64) returns (BrowserRow);
|
||||
rpc SetActiveBrowserColumns(generic.StringList) returns (generic.Empty);
|
||||
}
|
||||
|
||||
service StatsService {
|
||||
rpc CardStats(cards.CardId) returns (generic.String);
|
||||
rpc Graphs(GraphsRequest) returns (GraphsResponse);
|
||||
|
@ -194,11 +125,6 @@ message BackendError {
|
|||
// Messages
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
message SchedTimingTodayResponse {
|
||||
uint32 days_elapsed = 1;
|
||||
int64 next_day_at = 2;
|
||||
}
|
||||
|
||||
message RenderExistingCardRequest {
|
||||
int64 card_id = 1;
|
||||
bool browser = 2;
|
||||
|
@ -295,118 +221,11 @@ message TrashMediaFilesRequest {
|
|||
repeated string fnames = 1;
|
||||
}
|
||||
|
||||
message StudiedTodayMessageRequest {
|
||||
uint32 cards = 1;
|
||||
double seconds = 2;
|
||||
}
|
||||
|
||||
message CongratsLearnMessageRequest {
|
||||
float next_due = 1;
|
||||
uint32 remaining = 2;
|
||||
}
|
||||
|
||||
message SearchRequest {
|
||||
string search = 1;
|
||||
SortOrder order = 2;
|
||||
}
|
||||
|
||||
message SearchResponse {
|
||||
repeated int64 ids = 1;
|
||||
}
|
||||
|
||||
message SortOrder {
|
||||
message Builtin {
|
||||
string column = 1;
|
||||
bool reverse = 2;
|
||||
}
|
||||
oneof value {
|
||||
generic.Empty none = 1;
|
||||
string custom = 2;
|
||||
Builtin builtin = 3;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
FLAG_PINK = 6;
|
||||
FLAG_TURQUOISE = 7;
|
||||
FLAG_PURPLE = 8;
|
||||
}
|
||||
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;
|
||||
uint32 introduced_in_days = 19;
|
||||
}
|
||||
}
|
||||
|
||||
message JoinSearchNodesRequest {
|
||||
SearchNode.Group.Joiner joiner = 1;
|
||||
SearchNode existing_node = 2;
|
||||
SearchNode additional_node = 3;
|
||||
}
|
||||
|
||||
message ReplaceSearchNodeRequest {
|
||||
SearchNode existing_node = 1;
|
||||
SearchNode replacement_node = 2;
|
||||
}
|
||||
|
||||
message SetTagCollapsedRequest {
|
||||
string name = 1;
|
||||
bool collapsed = 2;
|
||||
|
@ -433,12 +252,6 @@ message RenameTagsRequest {
|
|||
string new_prefix = 2;
|
||||
}
|
||||
|
||||
message SetConfigJsonRequest {
|
||||
string key = 1;
|
||||
bytes value_json = 2;
|
||||
bool undoable = 3;
|
||||
}
|
||||
|
||||
message EmptyCardsReport {
|
||||
message NoteWithEmptyCards {
|
||||
int64 note_id = 1;
|
||||
|
@ -449,59 +262,6 @@ message EmptyCardsReport {
|
|||
repeated NoteWithEmptyCards notes = 2;
|
||||
}
|
||||
|
||||
message FindAndReplaceRequest {
|
||||
repeated int64 nids = 1;
|
||||
string search = 2;
|
||||
string replacement = 3;
|
||||
bool regex = 4;
|
||||
bool match_case = 5;
|
||||
string field_name = 6;
|
||||
}
|
||||
|
||||
message BrowserColumns {
|
||||
enum Sorting {
|
||||
SORTING_NONE = 0;
|
||||
SORTING_NORMAL = 1;
|
||||
SORTING_REVERSED = 2;
|
||||
}
|
||||
enum Alignment {
|
||||
ALIGNMENT_START = 0;
|
||||
ALIGNMENT_CENTER = 1;
|
||||
}
|
||||
message Column {
|
||||
string key = 1;
|
||||
string cards_mode_label = 2;
|
||||
string notes_mode_label = 3;
|
||||
Sorting sorting = 4;
|
||||
bool uses_cell_font = 5;
|
||||
Alignment alignment = 6;
|
||||
}
|
||||
repeated Column columns = 1;
|
||||
}
|
||||
|
||||
message BrowserRow {
|
||||
message Cell {
|
||||
string text = 1;
|
||||
bool is_rtl = 2;
|
||||
}
|
||||
enum Color {
|
||||
COLOR_DEFAULT = 0;
|
||||
COLOR_MARKED = 1;
|
||||
COLOR_SUSPENDED = 2;
|
||||
COLOR_FLAG_RED = 3;
|
||||
COLOR_FLAG_ORANGE = 4;
|
||||
COLOR_FLAG_GREEN = 5;
|
||||
COLOR_FLAG_BLUE = 6;
|
||||
COLOR_FLAG_PINK = 7;
|
||||
COLOR_FLAG_TURQUOISE = 8;
|
||||
COLOR_FLAG_PURPLE = 9;
|
||||
}
|
||||
repeated Cell cells = 1;
|
||||
Color color = 2;
|
||||
string font_name = 3;
|
||||
uint32 font_size = 4;
|
||||
}
|
||||
|
||||
message NoteIdsAndTagsRequest {
|
||||
repeated int64 note_ids = 1;
|
||||
string tags = 2;
|
||||
|
@ -515,117 +275,6 @@ message FindAndReplaceTagRequest {
|
|||
bool match_case = 5;
|
||||
}
|
||||
|
||||
message Preferences {
|
||||
message Scheduling {
|
||||
enum NewReviewMix {
|
||||
DISTRIBUTE = 0;
|
||||
REVIEWS_FIRST = 1;
|
||||
NEW_FIRST = 2;
|
||||
}
|
||||
|
||||
// read only; 1-3
|
||||
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;
|
||||
string default_search_text = 4;
|
||||
}
|
||||
|
||||
Scheduling scheduling = 1;
|
||||
Reviewing reviewing = 2;
|
||||
Editing editing = 3;
|
||||
}
|
||||
|
||||
message SyncLoginRequest {
|
||||
string username = 1;
|
||||
string password = 2;
|
||||
}
|
||||
|
||||
message SyncStatusResponse {
|
||||
enum Required {
|
||||
NO_CHANGES = 0;
|
||||
NORMAL_SYNC = 1;
|
||||
FULL_SYNC = 2;
|
||||
}
|
||||
Required required = 1;
|
||||
}
|
||||
|
||||
message SyncCollectionResponse {
|
||||
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 SyncServerMethodRequest {
|
||||
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 UpdateStatsRequest {
|
||||
int64 deck_id = 1;
|
||||
int32 new_delta = 2;
|
||||
int32 review_delta = 4;
|
||||
int32 millisecond_delta = 5;
|
||||
}
|
||||
|
||||
message ExtendLimitsRequest {
|
||||
int64 deck_id = 1;
|
||||
int32 new_delta = 2;
|
||||
int32 review_delta = 3;
|
||||
}
|
||||
|
||||
message CountsForDeckTodayResponse {
|
||||
int32 new = 1;
|
||||
int32 review = 2;
|
||||
}
|
||||
|
||||
message GraphsRequest {
|
||||
string search = 1;
|
||||
uint32 days = 2;
|
||||
|
@ -673,205 +322,7 @@ message RevlogEntry {
|
|||
uint32 taken_millis = 8;
|
||||
ReviewKind review_kind = 9;
|
||||
}
|
||||
|
||||
message CongratsInfoResponse {
|
||||
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 UnburyDeckRequest {
|
||||
enum Mode {
|
||||
ALL = 0;
|
||||
SCHED_ONLY = 1;
|
||||
USER_ONLY = 2;
|
||||
}
|
||||
int64 deck_id = 1;
|
||||
Mode mode = 2;
|
||||
}
|
||||
|
||||
message BuryOrSuspendCardsRequest {
|
||||
enum Mode {
|
||||
SUSPEND = 0;
|
||||
BURY_SCHED = 1;
|
||||
BURY_USER = 2;
|
||||
}
|
||||
repeated int64 card_ids = 1;
|
||||
repeated int64 note_ids = 2;
|
||||
Mode mode = 3;
|
||||
}
|
||||
|
||||
message ScheduleCardsAsNewRequest {
|
||||
repeated int64 card_ids = 1;
|
||||
bool log = 2;
|
||||
}
|
||||
|
||||
message SetDueDateRequest {
|
||||
repeated int64 card_ids = 1;
|
||||
string days = 2;
|
||||
Config.String config_key = 3;
|
||||
}
|
||||
|
||||
message SortCardsRequest {
|
||||
repeated int64 card_ids = 1;
|
||||
uint32 starting_from = 2;
|
||||
uint32 step_size = 3;
|
||||
bool randomize = 4;
|
||||
bool shift_existing = 5;
|
||||
}
|
||||
|
||||
message SortDeckRequest {
|
||||
int64 deck_id = 1;
|
||||
bool randomize = 2;
|
||||
}
|
||||
|
||||
message Config {
|
||||
message Bool {
|
||||
enum Key {
|
||||
BROWSER_TABLE_SHOW_NOTES_MODE = 0;
|
||||
PREVIEW_BOTH_SIDES = 3;
|
||||
COLLAPSE_TAGS = 4;
|
||||
COLLAPSE_NOTETYPES = 5;
|
||||
COLLAPSE_DECKS = 6;
|
||||
COLLAPSE_SAVED_SEARCHES = 7;
|
||||
COLLAPSE_TODAY = 8;
|
||||
COLLAPSE_CARD_STATE = 9;
|
||||
COLLAPSE_FLAGS = 10;
|
||||
SCHED_2021 = 11;
|
||||
ADDING_DEFAULTS_TO_CURRENT_DECK = 12;
|
||||
HIDE_AUDIO_PLAY_BUTTONS = 13;
|
||||
INTERRUPT_AUDIO_WHEN_ANSWERING = 14;
|
||||
PASTE_IMAGES_AS_PNG = 15;
|
||||
PASTE_STRIPS_FORMATTING = 16;
|
||||
NORMALIZE_NOTE_TEXT = 17;
|
||||
}
|
||||
Key key = 1;
|
||||
}
|
||||
|
||||
message String {
|
||||
enum Key {
|
||||
SET_DUE_BROWSER = 0;
|
||||
SET_DUE_REVIEWER = 1;
|
||||
DEFAULT_SEARCH_TEXT = 2;
|
||||
CARD_STATE_CUSTOMIZER = 3;
|
||||
}
|
||||
Key key = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message SetConfigBoolRequest {
|
||||
Config.Bool.Key key = 1;
|
||||
bool value = 2;
|
||||
bool undoable = 3;
|
||||
}
|
||||
|
||||
message SetConfigStringRequest {
|
||||
Config.String.Key key = 1;
|
||||
string value = 2;
|
||||
bool undoable = 3;
|
||||
}
|
||||
|
||||
message RenderMarkdownRequest {
|
||||
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 CardAnswer {
|
||||
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 GetQueuedCardsRequest {
|
||||
uint32 fetch_limit = 1;
|
||||
bool intraday_learning_only = 2;
|
||||
}
|
||||
|
||||
message QueuedCards {
|
||||
enum Queue {
|
||||
NEW = 0;
|
||||
LEARNING = 1;
|
||||
REVIEW = 2;
|
||||
}
|
||||
message QueuedCard {
|
||||
cards.Card card = 1;
|
||||
Queue queue = 2;
|
||||
NextCardStates next_states = 3;
|
||||
}
|
||||
|
||||
repeated QueuedCard cards = 1;
|
||||
uint32 new_count = 2;
|
||||
uint32 learning_count = 3;
|
||||
uint32 review_count = 4;
|
||||
}
|
||||
|
|
113
proto/anki/configs.proto
Normal file
113
proto/anki/configs.proto
Normal file
|
@ -0,0 +1,113 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package anki.configs;
|
||||
|
||||
import "anki/generic.proto";
|
||||
import "anki/collection.proto";
|
||||
|
||||
service ConfigsService {
|
||||
rpc GetConfigJson(generic.String) returns (generic.Json);
|
||||
rpc SetConfigJson(SetConfigJsonRequest) returns (collection.OpChanges);
|
||||
rpc SetConfigJsonNoUndo(SetConfigJsonRequest) returns (generic.Empty);
|
||||
rpc RemoveConfig(generic.String) returns (collection.OpChanges);
|
||||
rpc GetAllConfig(generic.Empty) returns (generic.Json);
|
||||
rpc GetConfigBool(Config.Bool) returns (generic.Bool);
|
||||
rpc SetConfigBool(SetConfigBoolRequest) returns (collection.OpChanges);
|
||||
rpc GetConfigString(Config.String) returns (generic.String);
|
||||
rpc SetConfigString(SetConfigStringRequest) returns (collection.OpChanges);
|
||||
rpc GetPreferences(generic.Empty) returns (Preferences);
|
||||
rpc SetPreferences(Preferences) returns (collection.OpChanges);
|
||||
}
|
||||
|
||||
message Config {
|
||||
message Bool {
|
||||
enum Key {
|
||||
BROWSER_TABLE_SHOW_NOTES_MODE = 0;
|
||||
PREVIEW_BOTH_SIDES = 3;
|
||||
COLLAPSE_TAGS = 4;
|
||||
COLLAPSE_NOTETYPES = 5;
|
||||
COLLAPSE_DECKS = 6;
|
||||
COLLAPSE_SAVED_SEARCHES = 7;
|
||||
COLLAPSE_TODAY = 8;
|
||||
COLLAPSE_CARD_STATE = 9;
|
||||
COLLAPSE_FLAGS = 10;
|
||||
SCHED_2021 = 11;
|
||||
ADDING_DEFAULTS_TO_CURRENT_DECK = 12;
|
||||
HIDE_AUDIO_PLAY_BUTTONS = 13;
|
||||
INTERRUPT_AUDIO_WHEN_ANSWERING = 14;
|
||||
PASTE_IMAGES_AS_PNG = 15;
|
||||
PASTE_STRIPS_FORMATTING = 16;
|
||||
NORMALIZE_NOTE_TEXT = 17;
|
||||
}
|
||||
Key key = 1;
|
||||
}
|
||||
|
||||
message String {
|
||||
enum Key {
|
||||
SET_DUE_BROWSER = 0;
|
||||
SET_DUE_REVIEWER = 1;
|
||||
DEFAULT_SEARCH_TEXT = 2;
|
||||
CARD_STATE_CUSTOMIZER = 3;
|
||||
}
|
||||
Key key = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message SetConfigBoolRequest {
|
||||
Config.Bool.Key key = 1;
|
||||
bool value = 2;
|
||||
bool undoable = 3;
|
||||
}
|
||||
|
||||
message SetConfigStringRequest {
|
||||
Config.String.Key key = 1;
|
||||
string value = 2;
|
||||
bool undoable = 3;
|
||||
}
|
||||
|
||||
message SetConfigJsonRequest {
|
||||
string key = 1;
|
||||
bytes value_json = 2;
|
||||
bool undoable = 3;
|
||||
}
|
||||
|
||||
message Preferences {
|
||||
message Scheduling {
|
||||
enum NewReviewMix {
|
||||
DISTRIBUTE = 0;
|
||||
REVIEWS_FIRST = 1;
|
||||
NEW_FIRST = 2;
|
||||
}
|
||||
|
||||
// read only; 1-3
|
||||
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;
|
||||
string default_search_text = 4;
|
||||
}
|
||||
|
||||
Scheduling scheduling = 1;
|
||||
Reviewing reviewing = 2;
|
||||
Editing editing = 3;
|
||||
}
|
219
proto/anki/scheduler.proto
Normal file
219
proto/anki/scheduler.proto
Normal file
|
@ -0,0 +1,219 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package anki.scheduler;
|
||||
|
||||
import "anki/generic.proto";
|
||||
import "anki/cards.proto";
|
||||
import "anki/decks.proto";
|
||||
import "anki/collection.proto";
|
||||
import "anki/configs.proto";
|
||||
|
||||
service SchedulerService {
|
||||
rpc GetQueuedCards(GetQueuedCardsRequest) returns (QueuedCards);
|
||||
rpc AnswerCard(CardAnswer) returns (collection.OpChanges);
|
||||
rpc SchedTimingToday(generic.Empty) returns (SchedTimingTodayResponse);
|
||||
rpc StudiedToday(generic.Empty) returns (generic.String);
|
||||
rpc StudiedTodayMessage(StudiedTodayMessageRequest) returns (generic.String);
|
||||
rpc UpdateStats(UpdateStatsRequest) returns (generic.Empty);
|
||||
rpc ExtendLimits(ExtendLimitsRequest) returns (generic.Empty);
|
||||
rpc CountsForDeckToday(decks.DeckId) returns (CountsForDeckTodayResponse);
|
||||
rpc CongratsInfo(generic.Empty) returns (CongratsInfoResponse);
|
||||
rpc RestoreBuriedAndSuspendedCards(cards.CardIds)
|
||||
returns (collection.OpChanges);
|
||||
rpc UnburyDeck(UnburyDeckRequest) returns (collection.OpChanges);
|
||||
rpc BuryOrSuspendCards(BuryOrSuspendCardsRequest)
|
||||
returns (collection.OpChangesWithCount);
|
||||
rpc EmptyFilteredDeck(decks.DeckId) returns (collection.OpChanges);
|
||||
rpc RebuildFilteredDeck(decks.DeckId) returns (collection.OpChangesWithCount);
|
||||
rpc ScheduleCardsAsNew(ScheduleCardsAsNewRequest)
|
||||
returns (collection.OpChanges);
|
||||
rpc SetDueDate(SetDueDateRequest) returns (collection.OpChanges);
|
||||
rpc SortCards(SortCardsRequest) returns (collection.OpChangesWithCount);
|
||||
rpc SortDeck(SortDeckRequest) returns (collection.OpChangesWithCount);
|
||||
rpc GetNextCardStates(cards.CardId) returns (NextCardStates);
|
||||
rpc DescribeNextStates(NextCardStates) returns (generic.StringList);
|
||||
rpc StateIsLeech(SchedulingState) returns (generic.Bool);
|
||||
rpc UpgradeScheduler(generic.Empty) returns (generic.Empty);
|
||||
}
|
||||
|
||||
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 QueuedCards {
|
||||
enum Queue {
|
||||
NEW = 0;
|
||||
LEARNING = 1;
|
||||
REVIEW = 2;
|
||||
}
|
||||
message QueuedCard {
|
||||
cards.Card card = 1;
|
||||
Queue queue = 2;
|
||||
NextCardStates next_states = 3;
|
||||
}
|
||||
|
||||
repeated QueuedCard cards = 1;
|
||||
uint32 new_count = 2;
|
||||
uint32 learning_count = 3;
|
||||
uint32 review_count = 4;
|
||||
}
|
||||
|
||||
message GetQueuedCardsRequest {
|
||||
uint32 fetch_limit = 1;
|
||||
bool intraday_learning_only = 2;
|
||||
}
|
||||
|
||||
message SchedTimingTodayResponse {
|
||||
uint32 days_elapsed = 1;
|
||||
int64 next_day_at = 2;
|
||||
}
|
||||
|
||||
message StudiedTodayMessageRequest {
|
||||
uint32 cards = 1;
|
||||
double seconds = 2;
|
||||
}
|
||||
|
||||
message UpdateStatsRequest {
|
||||
int64 deck_id = 1;
|
||||
int32 new_delta = 2;
|
||||
int32 review_delta = 4;
|
||||
int32 millisecond_delta = 5;
|
||||
}
|
||||
|
||||
message ExtendLimitsRequest {
|
||||
int64 deck_id = 1;
|
||||
int32 new_delta = 2;
|
||||
int32 review_delta = 3;
|
||||
}
|
||||
|
||||
message CountsForDeckTodayResponse {
|
||||
int32 new = 1;
|
||||
int32 review = 2;
|
||||
}
|
||||
|
||||
message CongratsInfoResponse {
|
||||
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 UnburyDeckRequest {
|
||||
enum Mode {
|
||||
ALL = 0;
|
||||
SCHED_ONLY = 1;
|
||||
USER_ONLY = 2;
|
||||
}
|
||||
int64 deck_id = 1;
|
||||
Mode mode = 2;
|
||||
}
|
||||
|
||||
message BuryOrSuspendCardsRequest {
|
||||
enum Mode {
|
||||
SUSPEND = 0;
|
||||
BURY_SCHED = 1;
|
||||
BURY_USER = 2;
|
||||
}
|
||||
repeated int64 card_ids = 1;
|
||||
repeated int64 note_ids = 2;
|
||||
Mode mode = 3;
|
||||
}
|
||||
|
||||
message ScheduleCardsAsNewRequest {
|
||||
repeated int64 card_ids = 1;
|
||||
bool log = 2;
|
||||
}
|
||||
|
||||
message SetDueDateRequest {
|
||||
repeated int64 card_ids = 1;
|
||||
string days = 2;
|
||||
configs.Config.String config_key = 3;
|
||||
}
|
||||
|
||||
message SortCardsRequest {
|
||||
repeated int64 card_ids = 1;
|
||||
uint32 starting_from = 2;
|
||||
uint32 step_size = 3;
|
||||
bool randomize = 4;
|
||||
bool shift_existing = 5;
|
||||
}
|
||||
|
||||
message SortDeckRequest {
|
||||
int64 deck_id = 1;
|
||||
bool randomize = 2;
|
||||
}
|
||||
|
||||
message NextCardStates {
|
||||
SchedulingState current = 1;
|
||||
SchedulingState again = 2;
|
||||
SchedulingState hard = 3;
|
||||
SchedulingState good = 4;
|
||||
SchedulingState easy = 5;
|
||||
}
|
||||
|
||||
message CardAnswer {
|
||||
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;
|
||||
}
|
177
proto/anki/search.proto
Normal file
177
proto/anki/search.proto
Normal file
|
@ -0,0 +1,177 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package anki.search;
|
||||
|
||||
import "anki/generic.proto";
|
||||
import "anki/collection.proto";
|
||||
|
||||
service SearchService {
|
||||
rpc BuildSearchString(SearchNode) returns (generic.String);
|
||||
rpc SearchCards(SearchRequest) returns (SearchResponse);
|
||||
rpc SearchNotes(SearchRequest) returns (SearchResponse);
|
||||
rpc JoinSearchNodes(JoinSearchNodesRequest) returns (generic.String);
|
||||
rpc ReplaceSearchNode(ReplaceSearchNodeRequest) returns (generic.String);
|
||||
rpc FindAndReplace(FindAndReplaceRequest)
|
||||
returns (collection.OpChangesWithCount);
|
||||
rpc AllBrowserColumns(generic.Empty) returns (BrowserColumns);
|
||||
rpc BrowserRowForId(generic.Int64) returns (BrowserRow);
|
||||
rpc SetActiveBrowserColumns(generic.StringList) returns (generic.Empty);
|
||||
}
|
||||
|
||||
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;
|
||||
FLAG_PINK = 6;
|
||||
FLAG_TURQUOISE = 7;
|
||||
FLAG_PURPLE = 8;
|
||||
}
|
||||
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;
|
||||
uint32 introduced_in_days = 19;
|
||||
}
|
||||
}
|
||||
|
||||
message SearchRequest {
|
||||
string search = 1;
|
||||
SortOrder order = 2;
|
||||
}
|
||||
|
||||
message SearchResponse {
|
||||
repeated int64 ids = 1;
|
||||
}
|
||||
|
||||
message SortOrder {
|
||||
message Builtin {
|
||||
string column = 1;
|
||||
bool reverse = 2;
|
||||
}
|
||||
oneof value {
|
||||
generic.Empty none = 1;
|
||||
string custom = 2;
|
||||
Builtin builtin = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message JoinSearchNodesRequest {
|
||||
SearchNode.Group.Joiner joiner = 1;
|
||||
SearchNode existing_node = 2;
|
||||
SearchNode additional_node = 3;
|
||||
}
|
||||
|
||||
message ReplaceSearchNodeRequest {
|
||||
SearchNode existing_node = 1;
|
||||
SearchNode replacement_node = 2;
|
||||
}
|
||||
|
||||
message FindAndReplaceRequest {
|
||||
repeated int64 nids = 1;
|
||||
string search = 2;
|
||||
string replacement = 3;
|
||||
bool regex = 4;
|
||||
bool match_case = 5;
|
||||
string field_name = 6;
|
||||
}
|
||||
|
||||
message BrowserColumns {
|
||||
enum Sorting {
|
||||
SORTING_NONE = 0;
|
||||
SORTING_NORMAL = 1;
|
||||
SORTING_REVERSED = 2;
|
||||
}
|
||||
enum Alignment {
|
||||
ALIGNMENT_START = 0;
|
||||
ALIGNMENT_CENTER = 1;
|
||||
}
|
||||
message Column {
|
||||
string key = 1;
|
||||
string cards_mode_label = 2;
|
||||
string notes_mode_label = 3;
|
||||
Sorting sorting = 4;
|
||||
bool uses_cell_font = 5;
|
||||
Alignment alignment = 6;
|
||||
}
|
||||
repeated Column columns = 1;
|
||||
}
|
||||
|
||||
message BrowserRow {
|
||||
message Cell {
|
||||
string text = 1;
|
||||
bool is_rtl = 2;
|
||||
}
|
||||
enum Color {
|
||||
COLOR_DEFAULT = 0;
|
||||
COLOR_MARKED = 1;
|
||||
COLOR_SUSPENDED = 2;
|
||||
COLOR_FLAG_RED = 3;
|
||||
COLOR_FLAG_ORANGE = 4;
|
||||
COLOR_FLAG_GREEN = 5;
|
||||
COLOR_FLAG_BLUE = 6;
|
||||
COLOR_FLAG_PINK = 7;
|
||||
COLOR_FLAG_TURQUOISE = 8;
|
||||
COLOR_FLAG_PURPLE = 9;
|
||||
}
|
||||
repeated Cell cells = 1;
|
||||
Color color = 2;
|
||||
string font_name = 3;
|
||||
uint32 font_size = 4;
|
||||
}
|
76
proto/anki/sync.proto
Normal file
76
proto/anki/sync.proto
Normal file
|
@ -0,0 +1,76 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package anki.sync;
|
||||
|
||||
import "anki/generic.proto";
|
||||
|
||||
service SyncService {
|
||||
rpc SyncMedia(SyncAuth) returns (generic.Empty);
|
||||
rpc AbortSync(generic.Empty) returns (generic.Empty);
|
||||
rpc AbortMediaSync(generic.Empty) returns (generic.Empty);
|
||||
rpc BeforeUpload(generic.Empty) returns (generic.Empty);
|
||||
rpc SyncLogin(SyncLoginRequest) returns (SyncAuth);
|
||||
rpc SyncStatus(SyncAuth) returns (SyncStatusResponse);
|
||||
rpc SyncCollection(SyncAuth) returns (SyncCollectionResponse);
|
||||
rpc FullUpload(SyncAuth) returns (generic.Empty);
|
||||
rpc FullDownload(SyncAuth) returns (generic.Empty);
|
||||
rpc SyncServerMethod(SyncServerMethodRequest) returns (generic.Json);
|
||||
}
|
||||
|
||||
message SyncAuth {
|
||||
string hkey = 1;
|
||||
uint32 host_number = 2;
|
||||
}
|
||||
|
||||
message SyncLoginRequest {
|
||||
string username = 1;
|
||||
string password = 2;
|
||||
}
|
||||
|
||||
message SyncStatusResponse {
|
||||
enum Required {
|
||||
NO_CHANGES = 0;
|
||||
NORMAL_SYNC = 1;
|
||||
FULL_SYNC = 2;
|
||||
}
|
||||
Required required = 1;
|
||||
}
|
||||
|
||||
message SyncCollectionResponse {
|
||||
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 SyncServerMethodRequest {
|
||||
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;
|
||||
}
|
|
@ -16,6 +16,10 @@ import anki.decks_pb2
|
|||
import anki.deckconfig_pb2
|
||||
import anki.notes_pb2
|
||||
import anki.notetypes_pb2
|
||||
import anki.scheduler_pb2
|
||||
import anki.sync_pb2
|
||||
import anki.configs_pb2
|
||||
import anki.search_pb2
|
||||
|
||||
import stringcase
|
||||
|
||||
|
@ -179,6 +183,10 @@ service_modules = dict(
|
|||
DECKS=anki.decks_pb2,
|
||||
DECK_CONFIG=anki.deckconfig_pb2,
|
||||
NOTETYPES=anki.notetypes_pb2,
|
||||
SCHEDULER=anki.scheduler_pb2,
|
||||
SYNC=anki.sync_pb2,
|
||||
CONFIGS=anki.configs_pb2,
|
||||
SEARCH=anki.search_pb2,
|
||||
)
|
||||
|
||||
for service in anki.backend_pb2.ServiceIndex.DESCRIPTOR.values:
|
||||
|
|
|
@ -8,22 +8,22 @@ from __future__ import annotations
|
|||
from typing import Any, Generator, List, Literal, Optional, Sequence, Tuple, Union, cast
|
||||
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import collection_pb2
|
||||
from anki import collection_pb2, configs_pb2, generic_pb2, search_pb2
|
||||
from anki._legacy import DeprecatedNamesMixin, deprecated
|
||||
|
||||
# protobuf we publicly export - listed first to avoid circular imports
|
||||
SearchNode = _pb.SearchNode
|
||||
SearchNode = search_pb2.SearchNode
|
||||
Progress = collection_pb2.Progress
|
||||
EmptyCardsReport = _pb.EmptyCardsReport
|
||||
GraphPreferences = _pb.GraphPreferences
|
||||
Preferences = _pb.Preferences
|
||||
Preferences = configs_pb2.Preferences
|
||||
UndoStatus = collection_pb2.UndoStatus
|
||||
OpChanges = collection_pb2.OpChanges
|
||||
OpChangesWithCount = collection_pb2.OpChangesWithCount
|
||||
OpChangesWithId = collection_pb2.OpChangesWithId
|
||||
OpChangesAfterUndo = collection_pb2.OpChangesAfterUndo
|
||||
BrowserRow = _pb.BrowserRow
|
||||
BrowserColumns = _pb.BrowserColumns
|
||||
BrowserRow = search_pb2.BrowserRow
|
||||
BrowserColumns = search_pb2.BrowserColumns
|
||||
|
||||
import copy
|
||||
import os
|
||||
|
@ -34,7 +34,7 @@ import weakref
|
|||
from dataclasses import dataclass, field
|
||||
|
||||
import anki.latex
|
||||
from anki import generic_pb2, hooks
|
||||
from anki import hooks
|
||||
from anki._backend import RustBackend, Translations
|
||||
from anki.browser import BrowserConfig, BrowserDefaults
|
||||
from anki.cards import Card, CardId
|
||||
|
@ -486,12 +486,12 @@ class Collection(DeprecatedNamesMixin):
|
|||
order: Union[bool, str, BrowserColumns.Column],
|
||||
reverse: bool,
|
||||
finding_notes: bool,
|
||||
) -> _pb.SortOrder:
|
||||
) -> search_pb2.SortOrder:
|
||||
if isinstance(order, str):
|
||||
return _pb.SortOrder(custom=order)
|
||||
return search_pb2.SortOrder(custom=order)
|
||||
if isinstance(order, bool):
|
||||
if order is False:
|
||||
return _pb.SortOrder(none=generic_pb2.Empty())
|
||||
return search_pb2.SortOrder(none=generic_pb2.Empty())
|
||||
# order=True: set args to sort column and reverse from config
|
||||
sort_key = BrowserConfig.sort_column_key(finding_notes)
|
||||
order = self.get_browser_column(self.get_config(sort_key))
|
||||
|
@ -499,13 +499,15 @@ class Collection(DeprecatedNamesMixin):
|
|||
reverse = self.get_config(reverse_key)
|
||||
if isinstance(order, BrowserColumns.Column):
|
||||
if order.sorting != BrowserColumns.SORTING_NONE:
|
||||
return _pb.SortOrder(
|
||||
builtin=_pb.SortOrder.Builtin(column=order.key, reverse=reverse)
|
||||
return search_pb2.SortOrder(
|
||||
builtin=search_pb2.SortOrder.Builtin(
|
||||
column=order.key, reverse=reverse
|
||||
)
|
||||
)
|
||||
|
||||
# eg, user is ordering on an add-on field with the add-on not installed
|
||||
print(f"{order} is not a valid sort order.")
|
||||
return _pb.SortOrder(none=generic_pb2.Empty())
|
||||
return search_pb2.SortOrder(none=generic_pb2.Empty())
|
||||
|
||||
def find_and_replace(
|
||||
self,
|
||||
|
|
|
@ -25,12 +25,12 @@ from typing import Any
|
|||
from weakref import ref
|
||||
|
||||
import anki
|
||||
from anki import backend_pb2 as _pb
|
||||
from anki import configs_pb2
|
||||
from anki.collection import OpChanges
|
||||
from anki.errors import NotFoundError
|
||||
from anki.utils import from_json_bytes, to_json_bytes
|
||||
|
||||
Config = _pb.Config
|
||||
Config = configs_pb2.Config
|
||||
|
||||
|
||||
class ConfigManager:
|
||||
|
|
1
pylib/anki/configs_pb2.pyi
Symbolic link
1
pylib/anki/configs_pb2.pyi
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../bazel-bin/pylib/anki/configs_pb2.pyi
|
1
pylib/anki/deckconfig_pb2.pyi
Symbolic link
1
pylib/anki/deckconfig_pb2.pyi
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../bazel-bin/pylib/anki/deckconfig_pb2.pyi
|
1
pylib/anki/decks_pb2.pyi
Symbolic link
1
pylib/anki/decks_pb2.pyi
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../bazel-bin/pylib/anki/decks_pb2.pyi
|
1
pylib/anki/notes_pb2.pyi
Symbolic link
1
pylib/anki/notes_pb2.pyi
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../bazel-bin/pylib/anki/notes_pb2.pyi
|
1
pylib/anki/notetypes_pb2.pyi
Symbolic link
1
pylib/anki/notetypes_pb2.pyi
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../bazel-bin/pylib/anki/notetypes_pb2.pyi
|
|
@ -4,12 +4,15 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import anki
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import decks_pb2
|
||||
from anki import decks_pb2, scheduler_pb2
|
||||
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithId
|
||||
from anki.config import Config
|
||||
|
||||
SchedTimingToday = _pb.SchedTimingTodayResponse
|
||||
SchedTimingToday = scheduler_pb2.SchedTimingTodayResponse
|
||||
CongratsInfo = scheduler_pb2.CongratsInfoResponse
|
||||
UnburyDeck = scheduler_pb2.UnburyDeckRequest
|
||||
BuryOrSuspend = scheduler_pb2.BuryOrSuspendCardsRequest
|
||||
FilteredDeckForUpdate = decks_pb2.FilteredDeckForUpdate
|
||||
|
||||
|
||||
from typing import List, Optional, Sequence
|
||||
|
@ -20,11 +23,6 @@ from anki.decks import DeckConfigDict, DeckId, DeckTreeNode
|
|||
from anki.notes import NoteId
|
||||
from anki.utils import ids2str, intTime
|
||||
|
||||
CongratsInfo = _pb.CongratsInfoResponse
|
||||
UnburyDeck = _pb.UnburyDeckRequest
|
||||
BuryOrSuspend = _pb.BuryOrSuspendCardsRequest
|
||||
FilteredDeckForUpdate = decks_pb2.FilteredDeckForUpdate
|
||||
|
||||
|
||||
class SchedulerBase:
|
||||
"Actions shared between schedulers."
|
||||
|
|
|
@ -11,8 +11,7 @@ from heapq import *
|
|||
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
||||
|
||||
import anki # pylint: disable=unused-import
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import hooks
|
||||
from anki import hooks, scheduler_pb2
|
||||
from anki.cards import Card, CardId
|
||||
from anki.consts import *
|
||||
from anki.decks import DeckConfigDict, DeckDict, DeckId
|
||||
|
@ -20,8 +19,8 @@ from anki.lang import FormatTimeSpan
|
|||
from anki.scheduler.legacy import SchedulerBaseWithLegacy
|
||||
from anki.utils import ids2str, intTime
|
||||
|
||||
CountsForDeckToday = _pb.CountsForDeckTodayResponse
|
||||
SchedTimingToday = _pb.SchedTimingTodayResponse
|
||||
CountsForDeckToday = scheduler_pb2.CountsForDeckTodayResponse
|
||||
SchedTimingToday = scheduler_pb2.SchedTimingTodayResponse
|
||||
|
||||
# legacy type alias
|
||||
QueueConfig = Dict[str, Any]
|
||||
|
|
|
@ -14,7 +14,7 @@ from __future__ import annotations
|
|||
|
||||
from typing import List, Literal, Sequence, Tuple
|
||||
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import scheduler_pb2
|
||||
from anki.cards import Card
|
||||
from anki.collection import OpChanges
|
||||
from anki.consts import *
|
||||
|
@ -24,10 +24,10 @@ from anki.scheduler.legacy import SchedulerBaseWithLegacy
|
|||
from anki.types import assert_exhaustive
|
||||
from anki.utils import intTime
|
||||
|
||||
QueuedCards = _pb.QueuedCards
|
||||
SchedulingState = _pb.SchedulingState
|
||||
NextStates = _pb.NextCardStates
|
||||
CardAnswer = _pb.CardAnswer
|
||||
QueuedCards = scheduler_pb2.QueuedCards
|
||||
SchedulingState = scheduler_pb2.SchedulingState
|
||||
NextStates = scheduler_pb2.NextCardStates
|
||||
CardAnswer = scheduler_pb2.CardAnswer
|
||||
|
||||
|
||||
class Scheduler(SchedulerBaseWithLegacy):
|
||||
|
@ -171,7 +171,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
|||
##########################################################################
|
||||
# fixme: move these into tests_schedv2 in the future
|
||||
|
||||
def _interval_for_state(self, state: _pb.SchedulingState) -> int:
|
||||
def _interval_for_state(self, state: scheduler_pb2.SchedulingState) -> int:
|
||||
kind = state.WhichOneof("value")
|
||||
if kind == "normal":
|
||||
return self._interval_for_normal_state(state.normal)
|
||||
|
@ -181,7 +181,9 @@ class Scheduler(SchedulerBaseWithLegacy):
|
|||
assert_exhaustive(kind)
|
||||
return 0 # unreachable
|
||||
|
||||
def _interval_for_normal_state(self, normal: _pb.SchedulingState.Normal) -> int:
|
||||
def _interval_for_normal_state(
|
||||
self, normal: scheduler_pb2.SchedulingState.Normal
|
||||
) -> int:
|
||||
kind = normal.WhichOneof("value")
|
||||
if kind == "new":
|
||||
return 0
|
||||
|
@ -196,7 +198,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
|||
return 0 # unreachable
|
||||
|
||||
def _interval_for_filtered_state(
|
||||
self, filtered: _pb.SchedulingState.Filtered
|
||||
self, filtered: scheduler_pb2.SchedulingState.Filtered
|
||||
) -> int:
|
||||
kind = filtered.WhichOneof("value")
|
||||
if kind == "preview":
|
||||
|
|
1
pylib/anki/scheduler_pb2.pyi
Symbolic link
1
pylib/anki/scheduler_pb2.pyi
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../bazel-bin/pylib/anki/scheduler_pb2.pyi
|
1
pylib/anki/search_pb2.pyi
Symbolic link
1
pylib/anki/search_pb2.pyi
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../bazel-bin/pylib/anki/search_pb2.pyi
|
|
@ -1,12 +1,12 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import sync_pb2
|
||||
|
||||
# public exports
|
||||
SyncAuth = _pb.SyncAuth
|
||||
SyncOutput = _pb.SyncCollectionResponse
|
||||
SyncStatus = _pb.SyncStatusResponse
|
||||
SyncAuth = sync_pb2.SyncAuth
|
||||
SyncOutput = sync_pb2.SyncCollectionResponse
|
||||
SyncStatus = sync_pb2.SyncStatusResponse
|
||||
|
||||
|
||||
# Legacy attributes some add-ons may be using
|
||||
|
|
1
pylib/anki/sync_pb2.pyi
Symbolic link
1
pylib/anki/sync_pb2.pyi
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../bazel-bin/pylib/anki/sync_pb2.pyi
|
|
@ -27,7 +27,7 @@ except ImportError as e:
|
|||
from flask import Response
|
||||
|
||||
from anki import Collection
|
||||
from anki.backend_pb2 import SyncServerMethodRequest
|
||||
from anki.sync_pb2 import SyncServerMethodRequest
|
||||
|
||||
Method = SyncServerMethodRequest.Method # pylint: disable=no-member
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
use serde_json::Value;
|
||||
|
||||
use super::Backend;
|
||||
pub(super) use crate::backend_proto::config_service::Service as ConfigService;
|
||||
pub(super) use crate::backend_proto::configs_service::Service as ConfigsService;
|
||||
use crate::{
|
||||
backend_proto as pb,
|
||||
backend_proto::config::{bool::Key as BoolKeyProto, string::Key as StringKeyProto},
|
||||
|
@ -52,7 +52,7 @@ impl From<pb::config::String> for StringKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl ConfigService for Backend {
|
||||
impl ConfigsService for Backend {
|
||||
fn get_config_json(&self, input: pb::String) -> Result<pb::Json> {
|
||||
self.with_col(|col| {
|
||||
let val: Option<Value> = col.get_config_optional(input.val.as_str());
|
||||
|
|
|
@ -40,7 +40,7 @@ use self::{
|
|||
card::CardsService,
|
||||
cardrendering::CardRenderingService,
|
||||
collection::CollectionService,
|
||||
config::ConfigService,
|
||||
config::ConfigsService,
|
||||
deckconfig::DeckConfigService,
|
||||
decks::DecksService,
|
||||
i18n::I18nService,
|
||||
|
@ -48,7 +48,7 @@ use self::{
|
|||
notes::NotesService,
|
||||
notetypes::NotetypesService,
|
||||
progress::ProgressState,
|
||||
scheduler::SchedulingService,
|
||||
scheduler::SchedulerService,
|
||||
search::SearchService,
|
||||
stats::StatsService,
|
||||
sync::{SyncService, SyncState},
|
||||
|
@ -117,11 +117,11 @@ impl Backend {
|
|||
pb::ServiceIndex::from_i32(service as i32)
|
||||
.ok_or_else(|| AnkiError::invalid_input("invalid service"))
|
||||
.and_then(|service| match service {
|
||||
pb::ServiceIndex::Scheduling => SchedulingService::run_method(self, method, input),
|
||||
pb::ServiceIndex::Scheduler => SchedulerService::run_method(self, method, input),
|
||||
pb::ServiceIndex::Decks => DecksService::run_method(self, method, input),
|
||||
pb::ServiceIndex::Notes => NotesService::run_method(self, method, input),
|
||||
pb::ServiceIndex::Notetypes => NotetypesService::run_method(self, method, input),
|
||||
pb::ServiceIndex::Config => ConfigService::run_method(self, method, input),
|
||||
pb::ServiceIndex::Configs => ConfigsService::run_method(self, method, input),
|
||||
pb::ServiceIndex::Sync => SyncService::run_method(self, method, input),
|
||||
pb::ServiceIndex::Tags => TagsService::run_method(self, method, input),
|
||||
pb::ServiceIndex::DeckConfig => DeckConfigService::run_method(self, method, input),
|
||||
|
|
|
@ -5,7 +5,7 @@ mod answering;
|
|||
mod states;
|
||||
|
||||
use super::Backend;
|
||||
pub(super) use crate::backend_proto::scheduling_service::Service as SchedulingService;
|
||||
pub(super) use crate::backend_proto::scheduler_service::Service as SchedulerService;
|
||||
use crate::{
|
||||
backend_proto::{self as pb},
|
||||
prelude::*,
|
||||
|
@ -16,7 +16,7 @@ use crate::{
|
|||
stats::studied_today,
|
||||
};
|
||||
|
||||
impl SchedulingService for Backend {
|
||||
impl SchedulerService for Backend {
|
||||
/// This behaves like _updateCutoff() in older code - it also unburies at the start of
|
||||
/// a new day.
|
||||
fn sched_timing_today(&self, _input: pb::Empty) -> Result<pb::SchedTimingTodayResponse> {
|
||||
|
|
|
@ -14,11 +14,15 @@ macro_rules! protobuf {
|
|||
}
|
||||
|
||||
protobuf!(backend);
|
||||
protobuf!(cards);
|
||||
protobuf!(collection);
|
||||
protobuf!(configs);
|
||||
protobuf!(deckconfig);
|
||||
protobuf!(decks);
|
||||
protobuf!(generic);
|
||||
protobuf!(i18n);
|
||||
protobuf!(notes);
|
||||
protobuf!(notetypes);
|
||||
protobuf!(decks);
|
||||
protobuf!(deckconfig);
|
||||
protobuf!(i18n);
|
||||
protobuf!(cards);
|
||||
protobuf!(generic);
|
||||
protobuf!(collection);
|
||||
protobuf!(scheduler);
|
||||
protobuf!(search);
|
||||
protobuf!(sync);
|
||||
|
|
|
@ -3,11 +3,11 @@ Copyright: Ankitects Pty Ltd and contributors
|
|||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type { Backend } from "lib/proto";
|
||||
import type { Scheduler } from "lib/proto";
|
||||
import { buildNextLearnMsg } from "./lib";
|
||||
import { bridgeLink } from "lib/bridgecommand";
|
||||
|
||||
export let info: Backend.CongratsInfoResponse;
|
||||
export let info: Scheduler.CongratsInfoResponse;
|
||||
import * as tr from "lib/i18n";
|
||||
|
||||
const congrats = tr.schedulingCongratulationsFinished();
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import { Backend } from "lib/proto";
|
||||
import { Scheduler } from "lib/proto";
|
||||
import { postRequest } from "lib/postrequest";
|
||||
import { naturalUnit, unitAmount, unitName } from "lib/time";
|
||||
|
||||
import * as tr from "lib/i18n";
|
||||
|
||||
export async function getCongratsInfo(): Promise<Backend.CongratsInfoResponse> {
|
||||
return Backend.CongratsInfoResponse.decode(
|
||||
export async function getCongratsInfo(): Promise<Scheduler.CongratsInfoResponse> {
|
||||
return Scheduler.CongratsInfoResponse.decode(
|
||||
await postRequest("/_anki/congratsInfo", "")
|
||||
);
|
||||
}
|
||||
|
||||
export function buildNextLearnMsg(info: Backend.CongratsInfoResponse): string {
|
||||
export function buildNextLearnMsg(info: Scheduler.CongratsInfoResponse): string {
|
||||
const secsUntil = info.secsUntilNextLearn;
|
||||
// next learning card not due (/ until tomorrow)?
|
||||
if (secsUntil == 0 || secsUntil > 86_400) {
|
||||
|
|
|
@ -6,4 +6,5 @@ import Backend = anki.backend;
|
|||
import Cards = anki.cards;
|
||||
import DeckConfig = anki.deckconfig;
|
||||
import Notetypes = anki.notetypes;
|
||||
export { Backend, Cards, DeckConfig, Notetypes };
|
||||
import Scheduler = anki.scheduler;
|
||||
export { Backend, Cards, DeckConfig, Notetypes, Scheduler };
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import { Backend } from "lib/proto";
|
||||
import { Scheduler } from "lib/proto";
|
||||
import { postRequest } from "lib/postrequest";
|
||||
|
||||
async function getNextStates(): Promise<Backend.NextCardStates> {
|
||||
return Backend.NextCardStates.decode(
|
||||
async function getNextStates(): Promise<Scheduler.NextCardStates> {
|
||||
return Scheduler.NextCardStates.decode(
|
||||
await postRequest("/_anki/nextCardStates", "")
|
||||
);
|
||||
}
|
||||
|
||||
async function setNextStates(
|
||||
key: string,
|
||||
states: Backend.NextCardStates
|
||||
states: Scheduler.NextCardStates
|
||||
): Promise<void> {
|
||||
const data: Uint8Array = Backend.NextCardStates.encode(states).finish();
|
||||
const data: Uint8Array = Scheduler.NextCardStates.encode(states).finish();
|
||||
await postRequest("/_anki/setNextCardStates", data, { key });
|
||||
}
|
||||
|
||||
export async function mutateNextCardStates(
|
||||
key: string,
|
||||
mutator: (states: Backend.NextCardStates) => void
|
||||
mutator: (states: Scheduler.NextCardStates) => void
|
||||
): Promise<void> {
|
||||
const states = await getNextStates();
|
||||
mutator(states);
|
||||
|
|
Loading…
Reference in a new issue