Compare commits

..

63 Commits

Author SHA1 Message Date
MadDogOwner 171aea98cf fix(conf): add default value for MultipartTTL
Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-08-29 16:27:01 +08:00
MadDogOwner 6ef934f1b5 fix(server/s3): ensure resource close safely
Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-08-29 15:54:05 +08:00
MadDogOwner 6ce5aab837 chore(deps): bump github.com/OpenListTeam/gofakes3 to v0.8.1
Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-08-29 15:51:38 +08:00
MadDogOwner 59b1dfde05 feat(server/s3): reap abandoned multipart uploads
- Track lastActivity on each multipart upload, updated on create and
  every part upload, so idle uploads can be detected
- Add a background reaper per backend instance that removes uploads
  inactive for longer than the TTL (default 24h) and cleans their temp
  directories
- Add a startup sweep that removes leftover s3-multipart-* directories
  older than the TTL, recovering part files from a previous crash
- Add a configurable s3.multipart_ttl (env S3_MULTIPART_TTL) duration,
  parsed via time.ParseDuration with a 24h default
- Add tests for TTL-based reaping and stale-directory cleanup

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-08-29 15:27:28 +08:00
MadDogOwner dd8247e578 feat(server/s3): support multipart upload
- Implement gofakes3 MultipartBackend (Create/UploadPart/Complete/Abort)
  on s3Backend so multipart parts stream to local temp files instead of
  being buffered in memory
- Track in-progress uploads via a new uploads sync.Map on s3Backend
- Refactor the PutObject body into a reusable putStream helper shared with
  the multipart Complete path
- Validate part ordering, etags and existence, reject short reads, and
  return S3-style multipart etags
- Add end-to-end multipart tests against a real Local driver

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-08-29 15:27:28 +08:00
MadDogOwner 7d91598f17 refactor(server/s3): use OpenListTeam/gofakes3
Replace itsHenry35/gofakes3 with OpenListTeam/gofakes3

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-08-29 15:26:11 +08:00
无知的错 819fdbd518 fix(drivers/189pc,drivers/189tv): fix extra requests when viewing files (#2791)
* fix(drivers/189pc,drivers/189tv): fix extra requests when viewing files

* fix(drivers/189pc,drivers/189tv): fix extra requests when viewing files
2026-08-29 01:33:16 +08:00
qbisicwate d220b8b005 fix(drivers/189pc)!: normalize escaped apostrophes in names (#2792)
fix(189pc): normalize escaped apostrophes in names

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-08-29 01:32:57 +08:00
jiwangyihao d12bd4c71e feat(drivers/github): add optional accurate modified time (#2388)
* feat(drivers/github): add optional accurate modified time

* refactor(github): 简化准确修改时间查询

- 将最多 200 个路径合并到一次 GraphQL history 查询,并用 ^{commit} 统一解析 ref

- 删除分批和冗余响应解析,保留失败降级、tree fallback 与缓存行为

- 使用 JSON 字符串字面量支持控制字符路径,并收敛行为测试

---------

Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-08-29 01:31:11 +08:00
renovate[bot] 4c611ef8de fix(deps): update github.com/cloudsoda/go-smb2 digest to 0b399b9 (#2976)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 01:28:32 +08:00
beardthelion eea8fee7f1 fix(drivers): stop the upload retry loop when the context is canceled (#2892)
The 115 and pikpak multipart uploaders checked for cancellation with a
`case <-ctx.Done()` inside a select, and a break there only leaves the
select, not the enclosing `for retry := 0; retry < 3; retry++` loop.
Cancelling an upload therefore ran all three attempts for every
remaining chunk, each allocating a chunk-sized buffer and reading it
off disk before firing a request that could not succeed, and reported
a transport error instead of the cancellation.

Move the check ahead of the select and use utils.IsCanceled, matching
the pattern the other drivers already use. Assigning ctx.Err() to err
is load-bearing: without it a cancelled chunk takes the success branch,
counts toward progress, and appends a zero-value UploadPart.

Found with staticcheck (SA4011).

Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-08-29 01:27:00 +08:00
AmPlace c06656958c fix(offline): expose native 115 tools for ED2K downloads (#2920)
* fix(offline): allow ED2K downloads through 115 tools

- Treat 115 Cloud and 115 Open as ED2K-capable tools.
- Keep automatic fallback limited to Thunder tools.
- Add regression coverage for supported and unsupported tools.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(offline): route ED2K to native 115 tools

- Allow ED2K requests initially using SimpleHttp to enter tool routing.
- Prefer the matching 115 tool for 115 Cloud and 115 Open destinations.
- Add regression coverage for native storage tool selection.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(offline): expose native tools for destination storage

- Include the native destination tool in the path-aware tool list.
- Keep existing ready-tool filtering for external destinations.
- Add coverage for native storage to tool mapping.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

---------

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-08-29 01:22:29 +08:00
Strom 0d277b8550 fix(drivers/strm): respect deployment umask for local directories (#2931)
* feat(strm): add local save permission mode

- add private and shared permission modes for local STRM files
- repair shared-mode directory and file permissions during generation
- add permission handling tests

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(strm): respect deployment umask for local directories

- remove application-level permission modes and chmod operations
- create local STRM directories with umask-controlled permissions
- preserve existing permissions and test the behavior

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

---------

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-08-29 01:20:44 +08:00
Nostalgia e0e4de5e82 fix(server/s3): paginate recursive object listings (#2968)
fix(s3): paginate recursive object listings

- stop recursive traversal after filling the requested S3 page
- preserve lexicographic marker ordering and request cancellation
- cover bounded traversal, continuation, prefixes, and cache safety

Co-authored-by: nostalume <nostalucent@gmail.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-08-29 01:18:42 +08:00
Lythen 39fcaf488b feat(ilanzou): modernize console API session and copy (#2962)
* feat(ilanzou): modernize console API session and copy

Use an isolated cookie-backed API session and preserve raw appToken syntax required by current iLanzou endpoints.

Resolve CDN download responses more robustly, align upload metadata with the console protocol, and delegate copies to OpenList background tasks instead of blocking requests.

* fix(ilanzou): escape appToken query values

Escape opaque appToken values while preserving the literal colon required by iLanzou endpoints. Ignore CDN HEAD response lengths unless the response status is successful.

* fix(ilanzou): address driver review feedback

Use the ilanzou package name consistently, document upload result polling, and bound CDN size probes. Keep the appToken and CDN challenge handling covered by focused tests and comments.

* fix(ilanzou): use context timeout for HEAD probe
2026-08-29 01:17:04 +08:00
ShenLin 31ae0f5bc9 fix(drivers/onedrive_sharelink): reuse shared HTTP clients (#2961)
fix(onedrive_sharelink): reuse shared HTTP clients

- Reuse shared client settings for redirect and GraphQL requests
- Propagate request contexts through password and pagination requests
- Close OneDrive response bodies that were missing cleanup
- Add tests for shared client settings and redirect handling

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-08-29 01:10:01 +08:00
renovate[bot] 3943180898 fix(deps): update module github.com/antchfx/xpath to v1.3.8 (#2977)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 01:04:56 +08:00
renovate[bot] b1cc7c6a93 fix(deps): update module github.com/jlaffaye/ftp to v0.2.4 (#2979)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 01:04:00 +08:00
renovate[bot] f6557f3d62 chore(deps): update docker/setup-buildx-action digest to 37fe631 (#2975)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 01:03:14 +08:00
renovate[bot] 9dc6cb29d9 chore(deps): update docker/login-action digest to dbcb813 (#2974)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 01:02:56 +08:00
renovate[bot] b86e4cb8dc fix(deps): update module github.com/pkg/sftp to v1.13.11 (#2980)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 01:00:46 +08:00
renovate[bot] fd7fb04ed1 fix(deps): update module github.com/rclone/rclone to v1.75.0 (#2900)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 00:59:42 +08:00
renovate[bot] 80795b8ec3 fix(deps): update module github.com/sirupsen/logrus to v1.10.2 (#2982)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 00:52:48 +08:00
renovate[bot] c2b3666818 fix(deps): update module gorm.io/driver/postgres to v1.6.2 (#2981)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 00:52:36 +08:00
renovate[bot] edbf42898b fix(deps): update module github.com/blevesearch/bleve/v2 to v2.6.1 (#2978)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 00:50:49 +08:00
renovate[bot] ab51cd6eae fix(deps): update module github.com/quic-go/quic-go to v0.61.0 (#2899)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-28 22:09:24 +08:00
renovate[bot] 4619aa2bc5 fix(deps): update module github.com/nwaples/rardecode/v2 to v2.4.1 (#2973)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-28 22:07:52 +08:00
UcnacDx2 376cada3d4 fix(drivers/139): optimize login flow with cookie reuse and robust fallback (#2067)
* fix(drivers/139): optimize login flow with robust tests

* fix(drivers/139): preserve configured HTTP client settings
2026-08-28 20:29:09 +08:00
没空的人 1a6cabf45a fix(drivers/lanzou): fix file download (#2960) 2026-08-24 21:39:39 +08:00
renovate[bot] 0b1e9d0943 fix(deps): update module github.com/blevesearch/bleve/v2 to v2.6.0 (#2704)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-19 20:38:12 +08:00
quan-ge 18823a23d5 fix(drivers/emby): allow username‑only login (#2949)
fix(drivers/emby): Emby允许仅用户名登录

Signed-off-by: quan-ge <quan13177379368@qq.com>
2026-08-19 20:11:08 +08:00
kanoshiou 150a90f2ac feat(strm): add file size filtering for STRM generation (#2911)
* feat(strm): add file size filtering for STRM generation

- add ParseSize helper function in pkg/utils to parse human-readable byte sizes
- add minFileSize setting field to STRM driver Addition struct
- filter out files below minFileSize threshold during STRM generation

* refactor(strm): use MB as default unit for minFileSize instead of ParseSize

Replace string-based ParseSize auto-conversion with a simple int64 number
field defaulting to MB, consistent with other drivers (Google Drive,
Teldrive). Remove the now-unused ParseSize function and its tests.
2026-08-14 15:34:58 +08:00
Shelken e80ee006ad fix(drivers/189): support updated 189 time format (#2919)
fix(drivers/189): support updated 189 time format with comma, timezone and unicode spaces

189 API 变更了时间返回格式,现有 Time.Unmarshal 无法解析,导致 189pc/189_tv
驱动所有写操作失败(Put → 500)。

新格式有三种形态,现有两个模板均无法覆盖:
1. "Aug 11, 2026, 10:37:18 PM +08" — 年份后多逗号,且自带时区
2. "Aug 12, 2026, 12:35:41\u202fAM +08" — AM/PM 前为 U+202F 窄不换行空格
3. "Aug 12, 2026, 12:35:41\u00a0AM +08" — AM/PM 前为 U+00A0 不换行空格

修复(189pc/help.go、189_tv/help.go 的 Time.Unmarshal):
- 解析前将 U+202F 和 U+00A0 统一替换为普通空格
- 新增模板 "Jan 2, 2006, 3:04:05 PM -07"(带逗号,3 为 12 小时制配 PM)
- 对可能不带时区的串,先试原串再试追加 " +08"(向后兼容)

新增 help_test.go 覆盖:数字日期、旧月份格式、新格式带/不带时区、
U+202F/U+00A0 空格、非法输入。

Fixes #2917



Generated-By: pi 0.84.1

Co-authored-by: Advanced <noreply@pi.dev>
2026-08-14 11:49:51 +08:00
UVJkiNTQ 89077c35a7 feat(setting): add move transfer threads option (#2907) 2026-08-08 19:05:49 +08:00
renovate[bot] cc87e88f03 fix(deps): update module gorm.io/driver/mysql to v1.6.0 (#819)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-08-07 23:20:41 +08:00
Ovear 7e9082f90e fix(stream): allow seeking beyond file size per Go convention (#2667)
Remove `offset > size` guard from RangeReadReadAtSeeker.Seek and
DynamicReadAtSeeker.Seek. Go's io.Seeker convention allows seeking
past EOF.

Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-08-07 22:53:49 +08:00
renovate[bot] 6d4ad58678 fix(deps): update module golang.org/x/net to v0.57.0 (#2748)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-08-07 22:50:11 +08:00
renovate[bot] d8ad28f5b7 fix(deps): update module github.com/ipfs/go-cid to v0.6.2 (#2738)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-07 22:44:19 +08:00
renovate[bot] 2e27852952 fix(deps): update azure-sdk-for-go monorepo (#2700)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-07 22:43:31 +08:00
renovate[bot] 194f941f15 fix(deps): update module golang.org/x/sys to v0.47.0 (#2751)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-07 22:42:26 +08:00
renovate[bot] ec1f968de1 fix(deps): update module github.com/shirou/gopsutil/v4 to v4.26.7 (#2896)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-07 22:41:10 +08:00
renovate[bot] c97173286c fix(deps): update module github.com/nwaples/rardecode/v2 to v2.3.0 (#2898)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-08-07 22:40:45 +08:00
ThetaPilla. cca773f07b feat(fs): add pipelined multipart upload (#2723)
* feat(multipart): add chunk reassembly window

- Reassemble concurrently uploaded chunks into a sequential stream through a ring file, bounding disk usage to slots*chunkSize per session
- Park writers up to a deadline when their slot is busy instead of rejecting instantly, so flow control does not surface as connection errors in browsers
- Record a per-chunk CRC32 table for re-fill verification and keep it readable after close
- Propagate cancellation to blocked readers via CloseWithError so drivers treat aborts like canceled requests
- Cover ordering, backpressure, idempotent resends and close/abort wake-ups with race-enabled tests

* feat(multipart): add pipelined upload session manager

- Start the driver upload at session init over a sequential stream backed by the window, so client-to-server and server-to-storage transfers run concurrently
- Attach client-provided hashes to the stream so drivers can attempt rapid upload before any chunk arrives, and absorb chunks racing pipeline completion idempotently
- Keep only metadata and chunk CRCs after a failed attempt: re-sending chunk 0 re-fills a fresh window, and content changes between attempts are rejected
- Resume receiving sessions only when client hashes prove the same file; failed_retriable sessions resume unconditionally
- Reclaim sessions with a sliding-TTL GC and sweep orphaned ring files at startup
- Cover the state machine with race-enabled tests over a stubbed storage layer

* feat(setting): add multipart upload settings

- Add multipart_enabled and multipart_chunk_size (MB) as public traffic settings
- Validate the chunk size on save (integer within 1-90) via the setting item hook

* feat(server): add multipart upload API

- Add /api/fs/multipart init/chunk/complete/status/abort endpoints with headers aligned with /fs/put
- Gate init behind the FsUp permission checks and reuse the client upload rate limiter for chunk uploads
- Drain the request body before answering chunk requests on every path, so browsers do not see early responses as network errors
- Start the multipart session GC when the router is initialized to reclaim ring files orphaned by a previous run

* refactor(multipart): remove unused overwrite session field

- The overwrite flag was stored on the session but never read: the handler
  performs the pre-check and op.Put owns the overwrite semantics

* feat(setting): allow any positive multipart chunk size

- Validate the setting as a positive integer only; self-hosted admins decide
  the ceiling themselves instead of an arbitrary 90MB cap
- Keep clamping the client-suggested X-Chunk-Size to the admin value: the
  server buffers a window of 8 chunks per session, so an unbounded client
  suggestion would translate directly into server-side disk usage

* refactor(server): simplify multipart chunk size clamp

- Fold the two-step clamp into one branch: the ceiling is already floored,
  so a client suggestion just lowers the size with a 1MB floor
2026-08-06 14:14:35 +08:00
renovate[bot] a4ae2acb65 fix(deps): update module github.com/sheltonzhu/115driver to v1.3.5 (#2895)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-04 12:03:42 +08:00
MadDogOwner f68f3e9f4a fix(drivers/guangyapan): remove default value (#2894)
* fix(drivers/guangyapan): remove default value for ClientID

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(drivers/guangyapan): remove unused configuration options from driver settings

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-08-04 11:53:45 +08:00
Pikachu Ren 6f80df2827 feat(drivers): add GuangYaPan driver with offline download support (#2882)
* feat(drivers): add GuangYaPan driver with offline download support

* fix(drivers): GuangYaPan driver multipartUploadToOSS
2026-08-04 11:34:56 +08:00
没空的人 940b69fe38 fix(drivers/lanzou): handle acw_sc__v2 challenge in Login function (#2876)
The Login endpoint may return an acw_sc__v2 validation page when accessed,
which previously caused login failures. This change adds the same retry
logic and cookie handling already used in request() to automatically solve
the challenge, ensuring login success even when the anti-bot mechanism is
triggered.
2026-07-31 18:13:47 +08:00
Yinan Qin f2f7ee4107 fix(ci): change missed pull_request to pull_request_target (#2873) 2026-07-30 00:45:01 +08:00
ILoveScratch cf931d4760 chore: fix typos (#2859) 2026-07-28 13:18:34 +08:00
ILoveScratch be708292eb chore: fix up .gitignore (#2857) 2026-07-28 07:37:07 +08:00
Liangbin Lian 78f2f0b25d chore(deps): remove unimplemented FUSE mount functionality and dependencies (#2854)
FUSE was introduced years ago but never implemented,
let's remove it to reduce dependencies.

Signed-off-by: Liangbin Lian <jjm2473@gmail.com>
2026-07-28 01:50:22 +08:00
Yinan Qin 6b92cbd21f fix(ci): allow pr check to run by default (#2856) 2026-07-27 23:52:20 +08:00
ShenLin 84ecda35aa fix(search): apply access filtering before paginating results
* fix: replace strings.HasPrefix with utils.IsSubPath for path validation

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix: re-validate shared paths to ensure they remain within the creator's base path

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(search): apply access filtering before paginating results

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-07-23 20:15:21 +08:00
renovate[bot] 2deb16b26e fix(deps): update github.com/t3rm1n4l/go-mega digest to c6acd6a (#2829)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-23 19:44:46 +08:00
ShenLin 8495470e63 fix(search): serialize index updates by parent (#2827)
- Prevent concurrent updates from inserting duplicate index entries
- Preserve parallel indexing across different parent paths
- Add serialization, concurrency, and lock cleanup tests

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-07-23 19:33:25 +08:00
ShenLin fe56ca483d fix(drivers/s3): support multipart object copy (#2826)
fix(s3): support multipart object copy

- Route objects larger than 5 GB through multipart copy
- Preserve source metadata and abort incomplete multipart copies
- Cover size routing, byte ranges, metadata, and failure cleanup

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-07-23 19:33:16 +08:00
ShenLin e83835dd80 fix(buffer): wait for active I/O before closing (#2825)
* fix(buffer): wait for active I/O before closing

- Track in-flight PipeBuffer read and write operations
- Wait for active I/O before releasing backing storage
- Add concurrent close regression coverage for reads and writes

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>

* ensure waitgroup handling

---------

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-07-23 19:33:14 +08:00
Firmant Xu 791a27e2ac feat(drivers): add Bunny Storage driver (#2472)
* feat(driver/bunny_storage): add Bunny Storage driver

Add Bunny Storage API support with optional CDN links and token signing.

Cover CDN mount path handling, token signing, and proxy/cache behavior with unit tests.

* replace RootFolderPath with driver.RootPath in Addition struct

* fix(driver/bunny_storage): parse fractional Bunny timestamps

* fix(bunny_storage): correct CDN token signing

- Decode URL paths without treating literal plus signs as spaces.
- Reject duplicate query parameters and cover both cases with regression tests.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

---------

Co-authored-by: j2rong4cn <j2rong@qq.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-07-23 19:29:53 +08:00
ShenLin 28cea1fb2b fix(proxy): preserve proxied download filenames (#2824)
- Override transparent proxy Content-Disposition with the OpenList object name
- Add regression coverage for incorrect upstream download headers

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-07-23 16:10:45 +08:00
So 0a9e71ae67 feat(drivers/139): merge multiple share roots (#2783)
* feat(drivers/139): merge multiple share roots

* fix(drivers/139): fallback to share preview without account

* chore(drivers/139): address share review comments

* refactor(drivers/139): reuse crypto

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* docs(drivers/139): add share support

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: syscc <syscc@users.noreply.github.com>
Co-authored-by: MadDogOwner <xiaoran@xrgzs.top>
2026-07-23 10:49:54 +08:00
So a21bc8bd0f fix(115_open): clean parent path before lookup (#2820) 2026-07-22 22:21:00 +08:00
MadDogOwner bacd087096 refactor(drivers/139): update path handling, put for family/group (#2719)
* fix(drivers/139): update path handling for family

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* perf(drivers/139): add retry go for family upload

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* feat(drivers/139): add FamilyCloudHost and GroupCloudHost handling

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* perf(drivers/139): add retry go for personalnew upload

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(drivers/139): use new batchpartinfos for remaining parts

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(driver/139): do not use path in id

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(driver/139): refactor RootPath handling

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(driver/139): remove root path stripping in Init method

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* chore(drivers/139): reduce upload retry attempts to 3

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(drivers/139): add rate limiting for MetaPersonalNew upload

- Wrap stream with LimitedUploadStream before creating StreamSectionReader
- Aligns with the same pattern used in the MetaPersonal/MetaGroup/MetaFamily path

Co-authored-by: GitHub Copilot <copilot@github.com>

* fix(drivers/139): fix section reader leak and seek check in retry block

- Check rd.Seek() return value and free the section reader on error
- Call ss.FreeSectionReader(rd) on all error paths within retry.Do closure
- Prevents buffer.Block leak when retrying failed upload chunks

Co-authored-by: GitHub Copilot <copilot@github.com>
Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(drivers/139): move GetSectionReader outside retry loop

- Move ss.GetSectionReader() before retry.Do() so the sequential
  stream section reader is only called once per chunk
- Remove redundant ss.FreeSectionReader() calls from inside the
  retry closure since the reader is now owned by the outer scope
- Fixes 'stream not cached' errors when retrying failed chunk
  uploads during cross-storage WebDAV COPY operations

Co-authored-by: GitHub Copilot <copilot@github.com>

* feat(drivers/139): add UseOldStreamUpload option

- Add UseOldStreamUpload option
- Implement newRequest, newPost
- Support rapid upload for PersonalNew and Group/Family

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(drivers/139): add more param for group/family put

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(drivers/139): correct group params for new put

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(drivers/139): update personalPost to use getPersonalCloudHost

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* chore(drivers/139): correct typo

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(drivers/139): pass full partInfos slice for batched upload

- Pass the global partInfos slice instead of the batch subset to
  uploadPersonalParts, so that PartNumber-1 indexing does not go
  out of bounds when a file has more than 100 parts.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(drivers/139): avoid double-counting progress on upload retries

- Save p.Done before each part and reset it inside the retry function
  so that bytes from failed attempts are not counted toward progress.
- Each part is counted exactly once, on the successful attempt.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(drivers/139): gate route-host checks by cloud type

- Only validate GroupCloudHost and FamilyCloudHost for MetaGroup
  and MetaFamily storage types, so that personal-only accounts do
  not fail initialization when the route policy omits group/family.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(drivers/139): add ProviderRoot back for groupgetfiles

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(drivers/139): set path to 0 when group old upload

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(drivers/139): improve error handling for family root path retrieval

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* refactor(drivers/139): update condition checks for CloudHost initialization

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
Co-authored-by: GitHub Copilot <copilot@github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-07-22 15:14:38 +08:00
Suyunjing e1ded83d5f fix(drivers/115_open): recover transient path metadata (#2816)
Recover temporarily missing or incomplete 115 Open path metadata from parent
and ancestor directory listings. Use 115-sdk-go v0.2.6 to normalize missing
object errors, while preserving valid zero-byte files and ensuring recursive
parent resolution progresses correctly.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-22 12:59:41 +08:00
126 changed files with 10741 additions and 1372 deletions
+2 -2
View File
@@ -3,7 +3,7 @@ name: Issue or PR Auto Reply
on:
issues:
types: [opened]
pull_request:
pull_request_target:
types: [opened]
permissions:
@@ -78,7 +78,7 @@ jobs:
pr-title-check:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
if: github.event_name == 'pull_request_target'
steps:
- name: Check PR title for required prefix and comment
uses: actions/github-script@v9
+6 -6
View File
@@ -156,11 +156,11 @@ jobs:
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4
- name: Login to GitHub Container Registry
if: env.IMAGE_PUSH == 'true'
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -168,7 +168,7 @@ jobs:
- name: Login to DockerHub Container Registry
if: env.IMAGE_PUSH == 'true'
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
username: ${{ vars.DOCKERHUB_ORG_NAME_BACKUP || env.DOCKERHUB_ORG_NAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -240,11 +240,11 @@ jobs:
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4
- name: Login to GitHub Container Registry
if: env.IMAGE_PUSH == 'true'
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -252,7 +252,7 @@ jobs:
- name: Login to DockerHub Container Registry
if: env.IMAGE_PUSH == 'true'
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
username: ${{ vars.DOCKERHUB_ORG_NAME_BACKUP || env.DOCKERHUB_ORG_NAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
+3 -3
View File
@@ -107,11 +107,11 @@ jobs:
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4
- name: Login to GitHub Container Registry
if: env.IMAGE_PUSH == 'true'
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -119,7 +119,7 @@ jobs:
- name: Login to DockerHub Container Registry
if: env.IMAGE_PUSH == 'true'
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
username: ${{ vars.DOCKERHUB_ORG_NAME_BACKUP || env.DOCKERHUB_ORG_NAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
+4 -2
View File
@@ -22,6 +22,7 @@ output/
# vendor/
/bin/*
*.json
!renovate.json
/build
/data/
/tmp/
@@ -29,6 +30,7 @@ output/
/lang/
/daemon/
/public/dist/*
/!public/dist/README.md
!/public/dist/README.md
.VSCodeCounter
.VSCodeCounter
*.syso
+1 -1
View File
@@ -67,7 +67,7 @@ Thank you for your support and understanding of the OpenList project.
- [x] [MediaFire](https://www.mediafire.com)
- [x] [Mediatrack](https://www.mediatrack.cn)
- [x] [ProtonDrive](https://proton.me/drive)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
+1 -1
View File
@@ -50,7 +50,7 @@ OpenList has no official association with third-party derivative projects that u
- [x] [MediaFire](https://www.mediafire.com)
- [x] [Mediatrack](https://www.mediatrack.cn)
- [x] [ProtonDrive](https://proton.me/drive)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
+1 -1
View File
@@ -67,7 +67,7 @@ OpenList 是一个由 OpenList 团队独立维护的开源项目,遵循 AGPL-3
- [x] [MediaFire](https://www.mediafire.com)
- [x] [分秒帧](https://www.mediatrack.cn)
- [x] [ProtonDrive](https://proton.me/drive)
- [x] [和彩云](https://yun.139.com)(个人、家庭、群组)
- [x] [和彩云](https://yun.139.com)(个人、家庭、群组、分享)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [百度网盘](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
+1 -1
View File
@@ -50,7 +50,7 @@ OpenList has no official association with third-party derivative projects that u
- [x] [MediaFire](https://www.mediafire.com)
- [x] [Mediatrack](https://www.mediatrack.cn)
- [x] [ProtonDrive](https://proton.me/drive)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
+1 -1
View File
@@ -50,7 +50,7 @@ OpenList has no official association with third-party derivative projects that u
- [x] [MediaFire](https://www.mediafire.com)
- [x] [Mediatrack](https://www.mediatrack.cn)
- [x] [ProtonDrive](https://proton.me/drive)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
+1 -1
View File
@@ -50,7 +50,7 @@ OpenList has no official association with third-party derivative projects that u
- [x] [MediaFire](https://www.mediafire.com)
- [x] [Mediatrack](https://www.mediatrack.cn)
- [x] [ProtonDrive](https://proton.me/drive)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
+1 -1
View File
@@ -66,7 +66,7 @@ OpenListプロジェクトへのご支援とご理解をありがとうござい
- [x] Teambition([中国](https://www.teambition.com), [国際](https://us.teambition.com))
- [x] [Mediatrack](https://www.mediatrack.cn)
- [x] [ProtonDrive](https://proton.me/drive)
- [x] [139yun](https://yun.139.com)(個人、家族、グループ)
- [x] [139yun](https://yun.139.com)(個人、家族、グループ、共有)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
+1 -1
View File
@@ -50,7 +50,7 @@ OpenList has no official association with third-party derivative projects that u
- [x] [MediaFire](https://www.mediafire.com)
- [x] [Mediatrack](https://www.mediatrack.cn)
- [x] [ProtonDrive](https://proton.me/drive)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
+1 -1
View File
@@ -67,7 +67,7 @@ Dank u voor uw ondersteuning en begrip
- [x] [MediaFire](https://www.mediafire.com)
- [x] [Mediatrack](https://www.mediatrack.cn)
- [x] [ProtonDrive](https://proton.me/drive)
- [x] [139yun](https://yun.139.com) (Persoonlijk, Familie, Groep)
- [x] [139yun](https://yun.139.com) (Persoonlijk, Familie, Groep, Delen)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
+1 -1
View File
@@ -50,7 +50,7 @@ OpenList has no official association with third-party derivative projects that u
- [x] [MediaFire](https://www.mediafire.com)
- [x] [Mediatrack](https://www.mediatrack.cn)
- [x] [ProtonDrive](https://proton.me/drive)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group)
- [x] [139yun](https://yun.139.com) (Personal, Family, Group, Share)
- [x] [YandexDisk](https://disk.yandex.com)
- [x] [BaiduNetdisk](http://pan.baidu.com)
- [x] [Terabox](https://www.terabox.com/main)
+1 -1
View File
@@ -23,7 +23,7 @@ type options struct {
pwd string //de/encrypt password
salt string
filenameEncryption string //reference drivers\crypt\meta.go Addtion
filenameEncryption string //reference drivers\crypt\meta.go Addition
dirnameEncryption string
filenameEncode string
suffix string
+4 -2
View File
@@ -337,9 +337,11 @@ func (d *Pan115) UploadByMultipart(ctx context.Context, params *driver115.Upload
for chunk := range chunksCh {
var part oss.UploadPart // 出现错误就继续尝试,共尝试3次
for retry := 0; retry < 3; retry++ {
select {
case <-ctx.Done():
if utils.IsCanceled(ctx) {
err = ctx.Err()
break
}
select {
case <-ticker.C:
if ossToken, err = d.client.GetOSSToken(); err != nil { // 到时重新获取ossToken
errCh <- errors.Wrap(err, "刷新token时出现错误")
+44 -3
View File
@@ -172,18 +172,59 @@ func (d *Open115) Get(ctx context.Context, path string) (model.Obj, error) {
resp, err := d.client.GetFolderInfoByPath(ctx, path)
if err != nil {
if errors.Is(err, sdk.ErrObjectNotFound) {
return nil, errs.ObjectNotFound
return d.getFromParent(ctx, path, "")
}
return nil, err
}
return &Obj{
obj := &Obj{
Fid: resp.FileID,
Fn: resp.FileName,
Fc: resp.FileCategory,
Sha1: resp.Sha1,
Pc: resp.PickCode,
FS: resp.SizeByte,
}, nil
Upt: parseTime(resp.UTime),
UpPt: parseTime(resp.PTime),
}
if !obj.IsDir() && obj.ModTime().Unix() <= 0 {
return d.getFromParent(ctx, path, obj.GetID())
}
return obj, nil
}
func (d *Open115) getFromParent(ctx context.Context, path, id string) (model.Obj, error) {
path = stdpath.Clean(path)
parent, name := stdpath.Split(path)
parent = stdpath.Clean(parent)
parentID := d.GetRootId()
if stdpath.Clean(parent) != stdpath.Clean(d.parentPath) {
if err := d.WaitLimit(ctx); err != nil {
return nil, err
}
parentInfo, err := d.client.GetFolderInfoByPath(ctx, parent)
if err != nil {
if !errors.Is(err, sdk.ErrObjectNotFound) {
return nil, err
}
parentObj, err := d.getFromParent(ctx, parent, "")
if err != nil {
return nil, err
}
parentID = parentObj.GetID()
} else {
parentID = parentInfo.FileID
}
}
files, err := d.List(ctx, &Obj{Fid: parentID, Fc: "0"}, model.ListArgs{})
if err != nil {
return nil, err
}
for _, file := range files {
if (id != "" && file.GetID() == id) || (id == "" && file.GetName() == name) {
return file, nil
}
}
return nil, errs.ObjectNotFound
}
func (d *Open115) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) (model.Obj, error) {
+9 -1
View File
@@ -1,6 +1,9 @@
package _115_open
import "encoding/json"
import (
"encoding/json"
"strconv"
)
func ParseInt64(v json.Number) (int64, error) {
i, err := v.Int64()
@@ -13,3 +16,8 @@ func ParseInt64(v json.Number) (int64, error) {
}
return int64(0), err
}
func parseTime(value string) int64 {
timestamp, _ := strconv.ParseInt(value, 10, 64)
return timestamp
}
+21 -14
View File
@@ -18,10 +18,10 @@ import (
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/internal/stream"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/go-resty/resty/v2"
log "github.com/sirupsen/logrus"
)
@@ -212,22 +212,29 @@ func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, file model.FileStrea
err = d.newUpload(ctx, &resp, file, up)
return err
} else {
s3Client := s3.NewFromConfig(aws.Config{
Credentials: credentials.NewStaticCredentialsProvider(resp.Data.AccessKeyId, resp.Data.SecretAccessKey, resp.Data.SessionToken),
Region: "123pan",
}, func(o *s3.Options) {
o.BaseEndpoint = aws.String(resp.Data.EndPoint)
o.UsePathStyle = true
})
tmClient := transfermanager.New(s3Client)
_, err = tmClient.UploadObject(ctx, &transfermanager.UploadObjectInput{
cfg := &aws.Config{
Credentials: credentials.NewStaticCredentials(resp.Data.AccessKeyId, resp.Data.SecretAccessKey, resp.Data.SessionToken),
Region: aws.String("123pan"),
Endpoint: aws.String(resp.Data.EndPoint),
S3ForcePathStyle: aws.Bool(true),
}
s, err := session.NewSession(cfg)
if err != nil {
return err
}
uploader := s3manager.NewUploader(s)
if file.GetSize() > s3manager.MaxUploadParts*s3manager.DefaultUploadPartSize {
uploader.PartSize = file.GetSize() / (s3manager.MaxUploadParts - 1)
}
input := &s3manager.UploadInput{
Bucket: &resp.Data.Bucket,
Key: &resp.Data.Key,
Body: driver.NewLimitedUploadStream(ctx, &driver.ReaderUpdatingProgress{
Reader: file,
UpdateProgress: up,
}),
})
}
_, err = uploader.UploadWithContext(ctx, input)
if err != nil {
return err
}
+250 -107
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More