Files
tora/proto/torrent.proto
2026-07-24 16:47:42 +02:00

192 lines
5.1 KiB
Protocol Buffer

syntax = "proto3";
package torrent;
service Torrents {
// Add a torrent from a magnet link or .torrent file and start downloading it.
rpc Add(AddRequest) returns (AddResponse);
// Get the current status of a single torrent.
rpc Status(StatusRequest) returns (TorrentStatus);
// List all torrents known to the daemon.
rpc List(ListRequest) returns (ListResponse);
// Remove a torrent from tracking.
rpc Remove(RemoveRequest) returns (RemoveResponse);
// Pause a downloading torrent.
rpc Pause(PauseRequest) returns (PauseResponse);
// Resume a paused torrent.
rpc Resume(ResumeRequest) returns (ResumeResponse);
// Subscribe to a live stream of torrent notifications. Events are delivered
// from the subscribe point onward — no history is replayed. New subscribers
// only see events that fire after they connect.
rpc Notifications(NotificationsRequest) returns (stream Notification);
// List the files inside a torrent with their download progress. Returns
// NOT_FOUND if the torrent is unknown or its metadata has not resolved yet
// (e.g. a magnet link still fetching peers).
rpc Files(FilesRequest) returns (FilesResponse);
}
message AddRequest {
string magnet = 1;
// Folder to download into. Empty = daemon default
// (<download_dir>/<torrent_name>/ for multi-file torrents).
string download_folder = 2;
// Folder to move the torrent into after completion. Empty = daemon default
// (<download_dir>/completed/<torrent_name>/).
string move_after_completion_folder = 3;
}
message AddResponse {
string id = 1;
}
message StatusRequest {
string id = 1;
}
message ListRequest {}
message ListResponse {
repeated TorrentStatus torrents = 1;
}
message RemoveRequest {
string id = 1;
bool delete_files = 2;
}
message RemoveResponse {}
message PauseRequest {
string id = 1;
}
message PauseResponse {}
message ResumeRequest {
string id = 1;
}
message ResumeResponse {}
message NotificationsRequest {
// If non-empty, only events for these torrent ids (or id prefixes, as
// accepted by `Status`/`Remove`) are delivered.
repeated string ids = 1;
// If non-empty, only these event kinds are delivered. An empty list means
// all kinds.
repeated NotificationKind kinds = 2;
}
message FilesRequest {
string id = 1;
}
enum FileState {
FILE_STATE_UNSPECIFIED = 0;
// File is partially downloaded.
IN_PROGRESS = 1;
// File's full byte range has been verified.
READY = 2;
}
message TorrentFile {
// Path relative to the torrent root, as declared in the .torrent metadata.
// May contain forward slashes for multi-file torrents.
string name = 1;
uint64 length = 2;
uint64 downloaded_bytes = 3;
FileState state = 4;
}
message FilesResponse {
repeated TorrentFile files = 1;
}
message Notification {
// Wall-clock time the daemon observed the change, in milliseconds since the
// Unix epoch.
uint64 observed_at_unix_millis = 1;
// What changed. Use this to dispatch; use the `oneof detail` for
// kind-specific payload.
NotificationKind kind = 2;
// Full snapshot of the torrent *after* the change. Always populated so
// consumers don't need to fan out to `Status` for context.
TorrentStatus torrent = 3;
oneof detail {
StateChanged state_changed = 10;
ProgressMark progress = 11;
AddedInfo added = 12;
RemovedInfo removed = 13;
}
}
enum NotificationKind {
NOTIFICATION_KIND_UNSPECIFIED = 0;
// Emitted once when a torrent is added via `Add`.
TORRENT_ADDED = 1;
// Emitted once when a torrent is removed via `Remove`.
TORRENT_REMOVED = 2;
// Emitted on any `State` transition, including PAUSED <-> DOWNLOADING,
// DOWNLOADING <-> STALE, * -> FINISHED, * -> ERROR.
STATE_CHANGED = 3;
// Emitted when the integer download percentage changes (rate-limited).
// No event is sent if the percentage did not advance since the last tick.
PROGRESS = 4;
}
message StateChanged {
State previous = 1;
State current = 2;
}
message ProgressMark {
// Current integer percentage 0..=100.
uint32 percent = 1;
// Bytes downloaded since the previous PROGRESS event for this torrent.
uint64 bytes_delta = 2;
}
message AddedInfo {
// Source string as provided to `Add` (magnet, URL, or file path).
string source = 1;
}
message RemovedInfo {
// True if `Remove` was called with `delete_files = true`.
bool files_deleted = 1;
}
enum State {
STATE_UNSPECIFIED = 0;
PENDING = 1;
DOWNLOADING = 2;
PAUSED = 3;
FINISHED = 4;
ERROR = 5;
// Live per librqbit, but the daemon has detected a stall: no byte progress
// for several ticks AND zero connected peers. The torrent is still
// considered live by the underlying engine; this state is an application-
// level overlay. Recovers to DOWNLOADING automatically when bytes advance
// or a peer connects.
STALE = 6;
}
message TorrentStatus {
string id = 1;
string info_hash = 2;
string name = 3;
string source = 4;
string output_path = 5;
uint64 total_bytes = 6;
uint64 downloaded_bytes = 7;
State state = 8;
string error_message = 9;
uint64 download_speed_bps = 10;
uint64 eta_seconds = 11;
uint64 uploaded_bytes = 12;
uint64 upload_speed_bps = 13;
uint32 peers = 14;
uint32 seeds = 15;
}