Skip to content

feat(drivers): add Teldrive V2 driver - #3000

Open
totza2010 wants to merge 1 commit into
OpenListTeam:mainfrom
totza2010:feat/teldrive-v2
Open

feat(drivers): add Teldrive V2 driver#3000
totza2010 wants to merge 1 commit into
OpenListTeam:mainfrom
totza2010:feat/teldrive-v2

Conversation

@totza2010

@totza2010 totza2010 commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Summary / 摘要

Adds a driver for TelDrive v2.

TelDrive v2 is a full rewrite of the server's HTTP API, not a version bump. It is
not backward compatible with the v1 API that the existing drivers/teldrive
speaks, so the two cannot be served by one client:

v1 (drivers/teldrive) v2 (this PR)
Auth access_token cookie X-Api-Key header
Addressing path strings UUIDs (parentId)
Listing offset + meta.totalPages opaque cursor (nextCursor)
Mutations plain requests Idempotency-Key header required
Upload per-chunk POST durable session: create → PUT parts → complete
Overwrite client-side check server-side conflictPolicy
Integrity none BLAKE3 tree hash, 16 MiB blocks

Because listing, addressing, auth and upload all differ, a shared client would be
two implementations behind one set of if v2 {} branches. This PR adds a
separate package instead and does not touch drivers/teldrive — existing v1
storages keep working untouched.

User-visible behaviour

  • New storage driver Teldrive V2 in the driver dropdown.
  • Uploads are resumable: an interrupted upload re-attaches to its existing server
    session and only sends the parts that are missing.
  • Optional per-part BLAKE3 checksum so the server rejects corruption in transit.
  • Optional direct 302 download links via TelDrive share tokens, cached and
    auto-renewed before expiry.

Implementation notes

  • pkg/utils/hash/tdhash.go registers TelDrive's BLAKE3 tree hash
    (blake3_tree) with the existing hash registry, following the gcid
    precedent. Verified byte-for-byte against a live TelDrive server and against
    rclone's backend/teldrive/tdhash.
  • Part uploads use a dedicated resty client. base.RestyClient has a 30s
    timeout and 3 built-in retries, both wrong for a part upload — the server only
    responds once the part has been relayed to Telegram, and an automatic retry
    would replay a body behind the driver's own retry policy.
  • Progress is reported per completed part. Byte-level progress is not achievable
    here: instrumentation showed the request body drains in ~0.3s of a ~26s
    request, so the remaining time is the server relaying to Telegram.
  • PreferProxy: true — without a share token the download URL is authenticated
    by a header, which a browser following a 302 cannot send.

Dependencies

go.mod changes by one line. github.com/zeebo/blake3 v0.2.4 was already in
the tree, pulled in by rclone/rclone v1.75.0, and is only moving out of the
// indirect block because pkg/utils/hash/tdhash.go now imports it directly —
this is what go mod tidy produces. go.sum is unchanged, which is the
proof that no new module enters the build.

  • This PR has breaking changes.
  • This PR changes public API, config, storage format, or migration behavior.
  • This PR requires corresponding changes in related repositories.

Related repository PRs / 关联仓库 PR:

Related Issues / 关联 Issue

Relates to #2034 (the v1 driver).

Testing / 测试

Tested against a real TelDrive v2 server (ghcr.io/tgdrive/teldrive:v2, commit
e3142b5) backed by a real Telegram account, driven through the OpenList web UI.

Exercised end to end: list, mkdir, rename, move, copy, remove (trash and hard
delete), download through the proxy, download via 302 share link, multi-part
upload, upload resume after an interrupted transfer, and conflict handling.

Hash agreement checked three ways — this driver, the TelDrive server, and
rclone 1.75.1's teldrive hash — on the same 36 MiB file, whole-file and
per-part. The vectors are pinned in pkg/utils/hash/tdhash_test.go.

  • go test ./...
  • Manual test / 手动测试: Windows 11, Docker Desktop, TelDrive v2 + Telegram
go build ./...
go vet ./drivers/teldrive_v2/
go test ./drivers/teldrive_v2/ ./pkg/utils/hash/

One note on go test ./...: it is currently red on main as well, before this
change. Go 1.27's vet runs a stricter printf check, and ten pre-existing
packages (drivers/123, drivers/189, drivers/189pc, drivers/chaoxing,
drivers/google_drive, drivers/google_photo, drivers/lanzou, and three
under internal/offline_download/) fail it with "non-constant format string".
I reproduced this on a clean upstream/main checkout — it is unrelated to this
PR, and none of the packages this PR adds or touches are affected. Happy to open
a separate PR for those if that would be useful.

Unit tests cover the pure logic that does not need a server: path normalisation,
chunk-size rounding, share-expiry parsing, retry classification, idempotency-key
stability, error formatting, and the BLAKE3 tree hash vectors.

Checklist / 检查清单

  • I have read CONTRIBUTING.
  • I confirm this contribution follows the repository license, contribution policy, and code of conduct.
  • I have formatted the changed code with gofmt, go fmt, or prettier where applicable.
  • I have requested review from relevant maintainers or code owners where applicable.

AI Disclosure / AI 使用声明

  • This PR includes AI-assisted content.

Tools used / 使用工具:

  • Claude

Usage scope / 使用范围:

  • Code generation / 代码生成

  • Refactoring / 重构

  • Documentation / 文档

  • Tests / 测试

  • Translation / 翻译

  • Review assistance / 审查辅助

  • I have reviewed and validated all AI-assisted content included in this PR.

  • I have ensured that all AI-assisted commits include Co-Authored-By attribution.

  • I can reproduce all AI-assisted content included in this PR without any AI tools.

I used Claude Code as an assistant while writing this driver: mapping the v2
OpenAPI surface onto OpenList's driver interfaces, drafting and refactoring the
implementation, and writing the tests. Every design decision - separate package
over a version flag, part-level progress, the share-token cache, which optional
interfaces to implement - was mine, and I validated the result against a live
TelDrive v2 server and a real Telegram account rather than against the spec
alone. The commit carries a Co-Authored-By trailer accordingly.

TelDrive v2 rewrites its HTTP API: every path moves under /api/v1, the
listing is cursor-paginated instead of page-numbered, objects are addressed
by UUID rather than path, uploads go through durable server-side sessions,
and every mutating endpoint requires an Idempotency-Key. None of it is
reachable from the existing Teldrive driver, so this adds a separate one
and leaves the v1 driver untouched.

Notable differences from the v1 driver:

- Copy is a single request; the server copies a whole subtree
  transactionally, so no client-side recursion is needed.
- Uploads create a session, PUT each part, then complete. Parts are
  idempotent on (uploadId, partNo), and an interrupted upload resumes by
  reusing its session and skipping parts the server already stored.
- The client mtime is preserved, which the v1 driver could not do.
- Files carry a BLAKE3 tree hash. It is registered as blake3_tree in
  pkg/utils/hash and reported on every object; when hash_enabled is set,
  each part is also sent with a checksum for the server to verify.

Part uploads use a dedicated resty client: the shared one caps requests at
30s, which a part cannot meet because the server only responds once it has
relayed the part to Telegram, and it would buffer the whole part in memory
to compute Content-Length.

Requires a TelDrive v2 server at e3142b5 or newer, where the move endpoint
began accepting a conflictPolicy other than "fail".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant