syntax = "proto3"; package archive_control.v1; import "google/protobuf/timestamp.proto"; // ResourceId models BitTorrent v1, v2, and hybrid torrent identity. Hex values // are lowercase and have exact SHA-1/SHA-256 lengths. At least one is required. message ResourceId { string info_hash_v1_hex = 1; string info_hash_v2_hex = 2; } // FileIndexRange is inclusive at both ends. Ranges in a SelectionSet must be // sorted, non-overlapping, and coalesced. message FileIndexRange { uint32 first = 1; uint32 last = 2; } message SelectionSet { repeated FileIndexRange ranges = 1; } enum TorrentRuntimeState { TORRENT_RUNTIME_STATE_UNSPECIFIED = 0; TORRENT_RUNTIME_STATE_STOPPED = 1; TORRENT_RUNTIME_STATE_QUEUED = 2; TORRENT_RUNTIME_STATE_CHECKING = 3; TORRENT_RUNTIME_STATE_DOWNLOADING = 4; TORRENT_RUNTIME_STATE_SEEDING = 5; TORRENT_RUNTIME_STATE_STALLED = 6; TORRENT_RUNTIME_STATE_ERROR = 7; TORRENT_RUNTIME_STATE_MISSING = 8; } enum ContentEntryType { CONTENT_ENTRY_TYPE_UNSPECIFIED = 0; CONTENT_ENTRY_TYPE_FILE = 1; CONTENT_ENTRY_TYPE_DIRECTORY = 2; CONTENT_ENTRY_TYPE_PADDING_FILE = 3; } message TorrentFile { uint32 file_index = 1; string canonical_path = 2; uint64 logical_bytes = 3; uint64 allocated_bytes = 4; uint64 completed_bytes = 5; bool selected = 6; bool sparse = 7; bool padding = 8; } // ContentTreeEntry is a flat tree record. Directory selections are expanded by // the source into available_file_indices before a job is created. message ContentTreeEntry { string canonical_path = 1; string parent_path = 2; string display_name = 3; ContentEntryType type = 4; optional uint32 file_index = 5; SelectionSet available_file_indices = 6; uint64 available_logical_bytes = 7; uint32 available_file_count = 8; // Present for FILE and PADDING_FILE entries. The duplicated canonical_path // must match this tree entry; receivers reject inconsistent records. TorrentFile file = 9; } message ResourceSummary { ResourceId resource_id = 1; // qb_torrent_id is meaningful only to the reporting qBittorrent instance. string qb_torrent_id = 2; string display_name = 3; TorrentRuntimeState runtime_state = 4; SelectionSet selected_files = 5; SelectionSet selected_complete_files = 6; uint64 selected_logical_bytes = 7; uint64 selected_complete_bytes = 8; uint64 total_logical_bytes = 9; uint32 total_file_count = 10; string content_revision = 11; bool canonical_paths = 12; google.protobuf.Timestamp observed_at = 13; } // ResourceStateFingerprint is an optimistic concurrency token for active jobs. message ResourceStateFingerprint { ResourceId resource_id = 1; string client_id = 2; string qb_torrent_id = 3; string content_revision = 4; SelectionSet selected_files = 5; SelectionSet selected_complete_files = 6; TorrentRuntimeState runtime_state = 7; string save_path_fingerprint = 8; google.protobuf.Timestamp observed_at = 9; } enum PlacementState { PLACEMENT_STATE_UNSPECIFIED = 0; PLACEMENT_STATE_PRESENT = 1; PLACEMENT_STATE_MERGING = 2; PLACEMENT_STATE_EVICTING = 3; PLACEMENT_STATE_ABSENT = 4; PLACEMENT_STATE_ERROR = 5; PLACEMENT_STATE_UNKNOWN = 6; } message Placement { ResourceId resource_id = 1; string client_id = 2; PlacementState state = 3; SelectionSet verified_files = 4; uint64 verified_logical_bytes = 5; uint64 generation = 6; ResourceStateFingerprint fingerprint = 7; google.protobuf.Timestamp verified_at = 8; string created_by_job_id = 9; }